commit 2650d1cdf0915aedeab710f362a0627775ce6caa Author: k kfluous Date: Wed Mar 11 22:18:23 2026 +0800 Initial commit: OneOS frontend based on yudao-ui-admin-vben diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..dc3bc09 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,4 @@ +> 1% +last 2 versions +not dead +not ie 11 diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..5654e89 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,5 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works with multi-package repos, or single-package repos to help you version and publish your code. You can find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..f954fb4 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", + "changelog": [ + "@changesets/changelog-github", + { "repo": "vbenjs/vue-vben-admin" } + ], + "commit": false, + "fixed": [["@vben-core/*", "@vben/*"]], + "snapshot": { + "prereleaseTemplate": "{tag}-{datetime}" + }, + "privatePackages": { "version": true, "tag": true }, + "linked": [], + "access": "public", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.commitlintrc.js b/.commitlintrc.js new file mode 100644 index 0000000..02e33fa --- /dev/null +++ b/.commitlintrc.js @@ -0,0 +1 @@ +export { default } from '@vben/commitlint-config'; diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..52b833a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +node_modules +.git +.gitignore +*.md +dist +.turbo +dist.zip diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..179aec6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset=utf-8 +end_of_line=lf +insert_final_newline=true +indent_style=space +indent_size=2 +max_line_length = 100 +trim_trailing_whitespace = true +quote_type = single + +[*.{yml,yaml,json}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d4e5bd3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# https://docs.github.com/cn/get-started/getting-started-with-git/configuring-git-to-handle-line-endings + +# Automatically normalize line endings (to LF) for all text-based files. +* text=auto eol=lf + +# Declare files that will always have CRLF line endings on checkout. +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf + +# Denote all files that are truly binary and should not be modified. +*.{ico,png,jpg,jpeg,gif,webp,svg,woff,woff2} binary \ No newline at end of file diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..4b28a69 --- /dev/null +++ b/.gitconfig @@ -0,0 +1,2 @@ +[core] + ignorecase = false diff --git a/.gitee/ISSUE_TEMPLATE/bug.yml b/.gitee/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..dd12519 --- /dev/null +++ b/.gitee/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,65 @@ +name: Bug 反馈 +description: 当你在代码中发现了一个 Bug,导致应用崩溃或抛出异常,或者有一个组件存在问题,或者某些地方看起来不对劲。 +title: '[Bug]: ' +labels: [bug] +body: + - type: markdown + attributes: + value: | + 感谢对项目的支持与关注。在提出问题之前,请确保你已查看相关开发或使用文档: + - https://doc.iocoder.cn/ + - type: dropdown + id: version + attributes: + label: 分支 + description: 你当前正在使用我们软件的哪个分支? + options: + - master (默认) + - dev (开发分支) + validations: + required: true + - type: dropdown + id: version + attributes: + label: 版本 + description: 你当前正在使用我们软件的哪个版本? + options: + - antd-design-vue + - element-plus + - naiveui + validations: + required: true + - type: checkboxes + attributes: + label: 这个问题是否已经存在? + options: + - label: 我已经搜索过现有的问题 (https://gitee.com/yudaocode/yudao-ui-admin-vben/issues) + required: true + - type: textarea + attributes: + label: 如何复现 + description: 请详细告诉我们如何复现你遇到的问题,如涉及代码,可提供一个最小代码示例,并使用反引号```附上它 + placeholder: | + 1. ... + 2. ... + 3. ... + validations: + required: true + - type: textarea + attributes: + label: 预期结果 + description: 请告诉我们你预期会发生什么。 + validations: + required: true + - type: textarea + attributes: + label: 实际结果 + description: 请告诉我们实际发生了什么。 + validations: + required: true + - type: textarea + attributes: + label: 截图或视频 + description: 如果可以的话,上传任何关于 bug 的截图。 + value: | + [在这里上传图片] diff --git a/.gitee/ISSUE_TEMPLATE/config.yml b/.gitee/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..43d9671 --- /dev/null +++ b/.gitee/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: 项目开发文档 + url: https://doc.iocoder.cn/ + about: 提供项目启动、开发的相关文档 diff --git a/.gitee/ISSUE_TEMPLATE/feature.yml b/.gitee/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 0000000..9017190 --- /dev/null +++ b/.gitee/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,43 @@ +name: 功能建议 +description: 对本项目提出一个功能建议 +title: '[功能建议]: ' +labels: [enhancement] +body: + - type: markdown + attributes: + value: | + 感谢提出功能建议,我们将仔细考虑! + - type: textarea + id: related-problem + attributes: + label: 你的功能建议是否和某个问题相关? + description: 清晰并简洁地描述问题是什么,例如,当我...时,我总是感到困扰。 + validations: + required: false + - type: textarea + id: desired-solution + attributes: + label: 你希望看到什么解决方案? + description: 清晰并简洁地描述你希望发生的事情。 + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: 你考虑过哪些替代方案? + description: 清晰并简洁地描述你考虑过的任何替代解决方案或功能。 + validations: + required: false + - type: textarea + id: additional-context + attributes: + label: 你有其他上下文或截图吗? + description: 在此处添加有关功能请求的任何其他上下文或截图。 + validations: + required: false + - type: checkboxes + attributes: + label: 意向参与贡献 + options: + - label: 我有意向参与具体功能的开发实现并将代码贡献回到上游社区 + required: false diff --git a/.gitee/image/common/ai-feature.png b/.gitee/image/common/ai-feature.png new file mode 100644 index 0000000..1c22dbe Binary files /dev/null and b/.gitee/image/common/ai-feature.png differ diff --git a/.gitee/image/common/ai-preview.gif b/.gitee/image/common/ai-preview.gif new file mode 100644 index 0000000..5f13ac4 Binary files /dev/null and b/.gitee/image/common/ai-preview.gif differ diff --git a/.gitee/image/common/bpm-feature.png b/.gitee/image/common/bpm-feature.png new file mode 100644 index 0000000..23787fb Binary files /dev/null and b/.gitee/image/common/bpm-feature.png differ diff --git a/.gitee/image/common/crm-feature.png b/.gitee/image/common/crm-feature.png new file mode 100644 index 0000000..e1c9670 Binary files /dev/null and b/.gitee/image/common/crm-feature.png differ diff --git a/.gitee/image/common/erp-feature.png b/.gitee/image/common/erp-feature.png new file mode 100644 index 0000000..d30b30e Binary files /dev/null and b/.gitee/image/common/erp-feature.png differ diff --git a/.gitee/image/common/infra-feature.png b/.gitee/image/common/infra-feature.png new file mode 100644 index 0000000..f5cef50 Binary files /dev/null and b/.gitee/image/common/infra-feature.png differ diff --git a/.gitee/image/common/mall-feature.png b/.gitee/image/common/mall-feature.png new file mode 100644 index 0000000..cca05c0 Binary files /dev/null and b/.gitee/image/common/mall-feature.png differ diff --git a/.gitee/image/common/mall-preview.png b/.gitee/image/common/mall-preview.png new file mode 100644 index 0000000..f939214 Binary files /dev/null and b/.gitee/image/common/mall-preview.png differ diff --git a/.gitee/image/common/project-vs.png b/.gitee/image/common/project-vs.png new file mode 100644 index 0000000..561e092 Binary files /dev/null and b/.gitee/image/common/project-vs.png differ diff --git a/.gitee/image/common/ruoyi-vue-pro-architecture.png b/.gitee/image/common/ruoyi-vue-pro-architecture.png new file mode 100644 index 0000000..7bd7d59 Binary files /dev/null and b/.gitee/image/common/ruoyi-vue-pro-architecture.png differ diff --git a/.gitee/image/common/ruoyi-vue-pro-biz.png b/.gitee/image/common/ruoyi-vue-pro-biz.png new file mode 100644 index 0000000..24a385a Binary files /dev/null and b/.gitee/image/common/ruoyi-vue-pro-biz.png differ diff --git a/.gitee/image/common/system-feature.png b/.gitee/image/common/system-feature.png new file mode 100644 index 0000000..366087c Binary files /dev/null and b/.gitee/image/common/system-feature.png differ diff --git a/.gitee/image/common/yudao-cloud-architecture.png b/.gitee/image/common/yudao-cloud-architecture.png new file mode 100644 index 0000000..59416d8 Binary files /dev/null and b/.gitee/image/common/yudao-cloud-architecture.png differ diff --git a/.gitee/image/common/yudao-roadmap.png b/.gitee/image/common/yudao-roadmap.png new file mode 100644 index 0000000..f4becc9 Binary files /dev/null and b/.gitee/image/common/yudao-roadmap.png differ diff --git a/.gitee/image/demo/vben.png b/.gitee/image/demo/vben.png new file mode 100644 index 0000000..989187d Binary files /dev/null and b/.gitee/image/demo/vben.png differ diff --git a/.gitee/image/wx-xingyu.png b/.gitee/image/wx-xingyu.png new file mode 100644 index 0000000..da2e45a Binary files /dev/null and b/.gitee/image/wx-xingyu.png differ diff --git a/.gitee/image/工作流设计器-bpmn.jpg b/.gitee/image/工作流设计器-bpmn.jpg new file mode 100644 index 0000000..2a61f60 Binary files /dev/null and b/.gitee/image/工作流设计器-bpmn.jpg differ diff --git a/.gitee/image/工作流设计器-simple.jpg b/.gitee/image/工作流设计器-simple.jpg new file mode 100644 index 0000000..9ef2c9e Binary files /dev/null and b/.gitee/image/工作流设计器-simple.jpg differ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..b95ff94 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,14 @@ +# default onwer +* anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com + +# vben core onwer +/.github/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com +/.vscode/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com +/packages/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com +/packages/@core/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com +/internal/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com +/scripts/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com + +# vben team onwer +apps/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com @vbenjs/team-v5 jinmao88@qq.com +docs/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com @vbenjs/team-v5 jinmao88@qq.com diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000..ae92780 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,74 @@ +name: 🐞 Bug Report +description: Report an issue with Vben Admin to help us make it better. +title: 'Bug: ' +labels: ['bug: pending triage'] + +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: dropdown + id: version + attributes: + label: Version + description: What version of our software are you running? + options: + - Vben Admin V5 + - Vben Admin V2 + default: 0 + validations: + required: true + + - type: textarea + id: bug-desc + attributes: + label: Describe the bug? + description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks! + placeholder: Bug Description + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Reproduction + description: Please provide a link to [StackBlitz](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/basic?initialPath=__vitest__/) (you can also use [examples](https://github.com/vitest-dev/vitest/tree/main/examples)) or a github repo that can reproduce the problem you ran into. A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is required unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "needs reproduction" label. If no reproduction is provided after 3 days, it will be auto-closed. + placeholder: Reproduction + validations: + required: true + + - type: textarea + id: system-info + attributes: + label: System Info + description: Output of `npx envinfo --system --npmPackages '{vue}' --binaries --browsers` + render: shell + placeholder: System, Binaries, Browsers + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell + + - type: checkboxes + id: terms + attributes: + label: Validations + description: Before submitting the issue, please make sure you do the following + # description: By submitting this issue, you agree to follow our [Code of Conduct](https://example.com). + options: + - label: Read the [docs](https://doc.vben.pro/) + required: true + - label: Ensure the code is up to date. (Some issues have been fixed in the latest version) + required: true + - label: I have searched the [existing issues](https://github.com/vbenjs/vue-vben-admin/issues) and checked that my issue does not duplicate any existing issues. + required: true + - label: Check that this is a concrete bug. For Q&A open a [GitHub Discussion](https://github.com/vbenjs/vue-vben-admin/discussions) or join our [Discord Chat Server](https://discord.gg/8GuAdwDhj6). + required: true + - label: The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug. + required: true diff --git a/.github/ISSUE_TEMPLATE/docs.yml b/.github/ISSUE_TEMPLATE/docs.yml new file mode 100644 index 0000000..d2bf16e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/docs.yml @@ -0,0 +1,38 @@ +name: 📚 Documentation +description: Report an issue with Vben Admin Website to help us make it better. +title: 'Docs: ' +labels: [documentation] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this issue! + - type: checkboxes + id: documentation_is + attributes: + label: Documentation is + options: + - label: Missing + - label: Outdated + - label: Confusing + - label: Not sure? + - type: textarea + id: description + attributes: + label: Explain in Detail + description: A clear and concise description of your suggestion. If you intend to submit a PR for this issue, tell us in the description. Thanks! + placeholder: The description of ... page is not clear. I thought it meant ... but it wasn't. + validations: + required: true + - type: textarea + id: suggestion + attributes: + label: Your Suggestion for Changes + validations: + required: true + - type: textarea + id: reproduction-steps + attributes: + label: Steps to reproduce + description: Please provide any reproduction steps that may need to be described. E.g. if it happens only when running the dev or build script make sure it's clear which one to use. + placeholder: Run `pnpm install` followed by `pnpm run docs:dev` diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 0000000..393334e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,70 @@ +name: ✨ New Feature Proposal +description: Propose a new feature to be added to Vben Admin +title: 'FEATURE: ' +labels: ['enhancement: pending triage'] +body: + - type: markdown + attributes: + value: | + Thank you for suggesting a feature for our project! Please fill out the information below to help us understand and implement your request! + - type: dropdown + id: version + attributes: + label: Version + description: What version of our software are you running? + options: + - Vben Admin V5 + - Vben Admin V2 + default: 0 + validations: + required: true + + - type: textarea + id: description + attributes: + label: Description + description: A detailed description of the feature request. + placeholder: Please describe the feature you would like to see, and why it would be useful. + validations: + required: true + + - type: textarea + id: proposed-solution + attributes: + label: Proposed Solution + description: A clear and concise description of what you want to happen. + placeholder: Describe the solution you'd like to see + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: | + A clear and concise description of any alternative solutions or features you've considered. + placeholder: Describe any alternative solutions or features you've considered + validations: + required: false + + - type: input + id: additional-context + attributes: + label: Additional Context + description: Add any other context or screenshots about the feature request here. + placeholder: Any additional information + validations: + required: false + + - type: checkboxes + id: checkboxes + attributes: + label: Validations + description: Before submitting the issue, please make sure you do the following + options: + - label: Read the [docs](https://doc.vben.pro/) + required: true + - label: Ensure the code is up to date. (Some issues have been fixed in the latest version) + required: true + - label: I have searched the [existing issues](https://github.com/vbenjs/vue-vben-admin/issues) and checked that my issue does not duplicate any existing issues. + required: true diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml new file mode 100644 index 0000000..d208b00 --- /dev/null +++ b/.github/actions/setup-node/action.yml @@ -0,0 +1,40 @@ +name: 'Setup Node' + +description: 'Setup node and pnpm' + +runs: + using: 'composite' + steps: + - name: Install pnpm + uses: pnpm/action-setup@v4 + + - name: Install Node.js + uses: actions/setup-node@v6 + with: + node-version-file: .node-version + cache: 'pnpm' + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - uses: actions/cache@v4 + name: Setup pnpm cache + if: ${{ github.ref_name == 'main' }} + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - uses: actions/cache/restore@v4 + if: ${{ github.ref_name != 'main' }} + with: + path: ${{ env.STORE_PATH }} + key: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + shell: bash + run: pnpm install --frozen-lockfile diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 0000000..5245484 --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,39 @@ +# Prevent issues being created without using the template +blank_issues_enabled: false +checkIssueTemplate: true +checkPullRequestTemplate: true + +contact_links: + - name: 💬 Discord Chat + url: https://discord.gg/8GuAdwDhj6 + about: Ask questions and discuss with other Vben users in real time. + + - name: ❓ Questions & Discussions + url: https://github.com/@vbenjs/vue-vben-admin/discussions + about: Use GitHub discussions for message-board style questions and discussions. + +# Comment to be posted to on PRs from first time contributors in your repository +newPRWelcomeComment: | + 💖 Thanks for opening this pull request! 💖 + Please be patient and we will get back to you as soon as we can. + +# Comment to be posted to on pull requests merged by a first time user +firstPRMergeComment: > + Thanks for your contribution! 🎉🎉🎉 + + +# Comment to be posted to on first time issues +newIssueWelcomeComment: > + Thanks for opening your first issue! Be sure to follow the issue template and provide every bit of information to help the developers! + + +# *OPTIONAL* default titles to check against for lack of descriptiveness +# MUST BE ALL LOWERCASE +requestInfoDefaultTitles: + - update readme.md + - updates + +# *Required* Comment to reply with +requestInfoReplyComment: > + Thanks for filing this issue/PR! It would be much appreciated if you could provide us with more information so we can effectively analyze the situation in context. + diff --git a/.github/contributing.md b/.github/contributing.md new file mode 100644 index 0000000..304c519 --- /dev/null +++ b/.github/contributing.md @@ -0,0 +1,40 @@ +# Vben Admin Contributing Guide + +Hi! We're really excited that you are interested in contributing to Vben Admin. Before submitting your contribution, please make sure to take a moment and read through the following guidelines: + +- [Pull Request Guidelines](#pull-request-guidelines) + +## Contributor Code of Conduct + +As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of the level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion. + +Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. + +## Pull Request Guidelines + +- Checkout a topic branch from the relevant branch, e.g. main, and merge back against that branch. + +- If adding a new feature: + - Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it. + +- If fixing bug: + - Provide a detailed description of the bug in the PR. Live demo preferred. + +- It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging. + +## Development Setup + +You will need [pnpm](https://pnpm.io/) + +After cloning the repo, run: + +```bash +# install the dependencies of the project +$ pnpm install +# start the project +$ pnpm run dev +``` diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d1b6d3b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 +updates: + - package-ecosystem: npm + directory: '/' + schedule: + interval: daily + groups: + non-breaking-changes: + update-types: [minor, patch] + + - package-ecosystem: github-actions + directory: '/' + schedule: + interval: weekly + groups: + non-breaking-changes: + update-types: [minor, patch] diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..8d7da67 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,33 @@ +## Description + + + + + +## Type of change + +Please delete options that are not relevant. + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update +- [ ] Please, don't make changes to `pnpm-lock.yaml` unless you introduce a new test example. + +## Checklist + +> ℹ️ Check all checkboxes - this will indicate that you have done everything in accordance with the rules in [CONTRIBUTING](contributing.md). + +- [ ] If you introduce new functionality, document it. You can run documentation with `pnpm run docs:dev` command. +- [ ] Run the tests with `pnpm test`. +- [ ] Changes in changelog are generated from PR name. Please, make sure that it explains your changes in an understandable manner. Please, prefix changeset messages with `feat:`, `fix:`, `perf:`, `docs:`, or `chore:`. +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] Any dependent changes have been merged and published in downstream modules diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..8861909 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,61 @@ +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' +version-template: $MAJOR.$MINOR.$PATCH +change-template: '* $TITLE (#$NUMBER) @$AUTHOR' +template: | + # What's Changed + + $CHANGES + + **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION + +categories: + - title: '🚀 Features' + labels: + - 'feature' + - title: '🐞 Bug Fixes' + labels: + - 'bug' + - title: '📈 Performance & Enhancement' + labels: + - 'perf' + - 'enhancement' + - title: 📝 Documentation + labels: + - 'documentation' + - title: 👻 Maintenance + labels: + - 'chore' + - 'dependencies' + # collapse-after: 12 + - title: 🚦 Tests + labels: + - 'tests' + - title: 'Breaking' + label: 'breaking' + +version-resolver: + major: + labels: + - 'major' + - 'breaking' + minor: + labels: + - 'minor' + patch: + labels: + - 'feature' + - 'patch' + - 'bug' + - 'maintenance' + - 'docs' + - 'dependencies' + - 'security' + +exclude-labels: + - 'skip-changelog' + - 'no-changelog' + - 'changelog' + - 'bump versions' + - 'reverted' + - 'invalid' diff --git a/.github/semantic.yml b/.github/semantic.yml new file mode 100644 index 0000000..8d8ffd9 --- /dev/null +++ b/.github/semantic.yml @@ -0,0 +1,13 @@ +titleAndCommits: true +types: + - feat + - fix + - docs + - chore + - style + - refactor + - perf + - test + - build + - ci + - revert diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..f60b047 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,48 @@ +# name: Dependabot post-update +name: Build detection +on: + pull_request_target: + types: [opened, synchronize, reopened] + branches: + - main + +env: + HUSKY: '0' + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write + +jobs: + post-update: + if: github.repository == 'vbenjs/vue-vben-admin' + # if: ${{ github.actor == 'dependabot[bot]' }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - ubuntu-latest + # - macos-latest + - windows-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Checkout out pull request + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh pr checkout ${{ github.event.pull_request.number }} + + - name: Setup Node + uses: ./.github/actions/setup-node + + - name: Build + run: | + pnpm run build diff --git a/.github/workflows/changeset-version.yml b/.github/workflows/changeset-version.yml new file mode 100644 index 0000000..cdccceb --- /dev/null +++ b/.github/workflows/changeset-version.yml @@ -0,0 +1,42 @@ +# https://github.com/changesets/action +name: Changeset version + +on: + workflow_dispatch: + pull_request: + types: + - closed + branches: + - main + +permissions: + pull-requests: write + contents: write + +env: + CI: true + +jobs: + version: + if: (github.event.pull_request.merged || github.event_name == 'workflow_dispatch') && github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' + # if: github.repository == 'vbenjs/vue-vben-admin' + timeout-minutes: 15 + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Setup Node + uses: ./.github/actions/setup-node + + - name: Create Release Pull Request + uses: changesets/action@v1 + with: + version: pnpm run version + commit: 'chore: bump versions' + title: 'chore: bump versions' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..339e5fd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,125 @@ +name: CI + +on: + pull_request: + push: + branches: + - main + - 'releases/*' + +permissions: + contents: read + +env: + CI: true + TZ: Asia/Shanghai + +jobs: + test: + name: Test + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - ubuntu-latest + # - macos-latest + - windows-latest + timeout-minutes: 20 + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + run_install: false + + - name: Setup Node + uses: ./.github/actions/setup-node + + # - name: Check Git version + # run: git --version + + # - name: Setup mock Git user + # run: git config --global user.email "you@example.com" && git config --global user.name "Your Name" + + - name: Vitest tests + run: pnpm run test:unit + + # - name: Upload coverage + # uses: codecov/codecov-action@v4 + # with: + # token: ${{ secrets.CODECOV_TOKEN }} + + lint: + name: Lint + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - ubuntu-latest + # - macos-latest + - windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Setup Node + uses: ./.github/actions/setup-node + + - name: Lint + run: pnpm run lint + + check: + name: Check + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ${{ matrix.os }} + timeout-minutes: 20 + strategy: + matrix: + os: + - ubuntu-latest + # - macos-latest + - windows-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Setup Node + uses: ./.github/actions/setup-node + + - name: Typecheck + run: pnpm check:type + + # From https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions + - name: Check workflow files + if: runner.os == 'Linux' + run: | + bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) + ./actionlint -color -shellcheck="" + + ci-ok: + name: CI OK + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + needs: [test, check, lint] + env: + FAILURE: ${{ contains(join(needs.*.result, ','), 'failure') }} + steps: + - name: Check for failure + run: | + echo $FAILURE + if [ "$FAILURE" = "false" ]; then + exit 0 + else + exit 1 + fi diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..61137ad --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,94 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: 'CodeQL' + +on: + push: + branches: ['main'] + pull_request: + branches: ['main'] + schedule: + - cron: '35 0 * * 0' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + if: github.repository == 'vbenjs/vue-vben-admin' + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: javascript-typescript + build-mode: none + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: '/language:${{matrix.language}}' diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..2207ace --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,172 @@ +name: Deploy Website on push + +on: + push: + branches: + - main + +jobs: + deploy-playground-ftp: + name: Deploy Push Playground Ftp + if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Sed Config Base + shell: bash + run: | + sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./playground/.env.production + sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./playground/.env.production + cat ./playground/.env.production + + - name: Setup Node + uses: ./.github/actions/setup-node + + - name: Build + run: pnpm build:play + + - name: Sync Playground files + uses: SamKirkland/FTP-Deploy-Action@v4.3.6 + with: + server: ${{ secrets.PRO_FTP_HOST }} + username: ${{ secrets.WEB_PLAYGROUND_FTP_ACCOUNT }} + password: ${{ secrets.WEB_PLAYGROUND_FTP_PWSSWORD }} + local-dir: ./playground/dist/ + + deploy-docs-ftp: + name: Deploy Push Docs Ftp + if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Setup Node + uses: ./.github/actions/setup-node + + - name: Build + run: pnpm build:docs + + - name: Sync Docs files + uses: SamKirkland/FTP-Deploy-Action@v4.3.6 + with: + server: ${{ secrets.PRO_FTP_HOST }} + username: ${{ secrets.WEBSITE_FTP_ACCOUNT }} + password: ${{ secrets.WEBSITE_FTP_PASSWORD }} + local-dir: ./docs/.vitepress/dist/ + + deploy-antd-ftp: + name: Deploy Push Antd Ftp + if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Sed Config Base + shell: bash + run: | + sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-antd/.env.production + sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-antd/.env.production + cat ./apps/web-antd/.env.production + + - name: Setup Node + uses: ./.github/actions/setup-node + + - name: Build + run: pnpm run build:antd + + - name: Sync files + uses: SamKirkland/FTP-Deploy-Action@v4.3.6 + with: + server: ${{ secrets.PRO_FTP_HOST }} + username: ${{ secrets.WEB_ANTD_FTP_ACCOUNT }} + password: ${{ secrets.WEB_ANTD_FTP_PASSWORD }} + local-dir: ./apps/web-antd/dist/ + + deploy-ele-ftp: + name: Deploy Push Element Ftp + if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Sed Config Base + shell: bash + run: | + sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-ele/.env.production + sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-ele/.env.production + cat ./apps/web-ele/.env.production + + - name: Setup Node + uses: ./.github/actions/setup-node + + - name: Build + run: pnpm run build:ele + + - name: Sync files + uses: SamKirkland/FTP-Deploy-Action@v4.3.6 + with: + server: ${{ secrets.PRO_FTP_HOST }} + username: ${{ secrets.WEB_ELE_FTP_ACCOUNT }} + password: ${{ secrets.WEB_ELE_FTP_PASSWORD }} + local-dir: ./apps/web-ele/dist/ + + deploy-naive-ftp: + name: Deploy Push Naive Ftp + if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Sed Config Base + shell: bash + run: | + sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-naive/.env.production + sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-naive/.env.production + cat ./apps/web-naive/.env.production + + - name: Setup Node + uses: ./.github/actions/setup-node + + - name: Build + run: pnpm run build:naive + + - name: Sync files + uses: SamKirkland/FTP-Deploy-Action@v4.3.6 + with: + server: ${{ secrets.PRO_FTP_HOST }} + username: ${{ secrets.WEB_NAIVE_FTP_ACCOUNT }} + password: ${{ secrets.WEB_NAIVE_FTP_PASSWORD }} + local-dir: ./apps/web-naive/dist/ + + rerun-on-failure: + name: Rerun on failure + needs: + - deploy-playground-ftp + - deploy-docs-ftp + - deploy-antd-ftp + - deploy-ele-ftp + - deploy-naive-ftp + if: failure() && fromJSON(github.run_attempt) < 10 + runs-on: ubuntu-latest + steps: + - name: Retry ${{ fromJSON(github.run_attempt) }} of 10 + env: + GH_REPO: ${{ github.repository }} + GH_TOKEN: ${{ github.token }} + run: gh workflow run rerun.yml -F run_id=${{ github.run_id }} diff --git a/.github/workflows/draft.yml b/.github/workflows/draft.yml new file mode 100644 index 0000000..20b4148 --- /dev/null +++ b/.github/workflows/draft.yml @@ -0,0 +1,25 @@ +name: Release Drafter + +on: + push: + branches: + - main + +permissions: + contents: read + pull-requests: write + +jobs: + update_release_draft: + permissions: + # write permission is required to create a github release + contents: write + # write permission is required for autolabeler + # otherwise, read permission is required at least + pull-requests: write + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v6 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/issue-close-require.yml b/.github/workflows/issue-close-require.yml new file mode 100644 index 0000000..18c007b --- /dev/null +++ b/.github/workflows/issue-close-require.yml @@ -0,0 +1,31 @@ +# 每天零点运行一次,它会检查所有带有 "need reproduction" 标签的 Issues。如果这些 Issues 在过去的 3 天内没有任何活动,它们将会被自动关闭。这有助于保持 Issue 列表的整洁,并且提醒用户在必要时提供更多的信息。 +name: Issue Close Require + +# 触发条件:每天零点 +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * *' + +permissions: + pull-requests: write + contents: write + issues: write + +jobs: + close-issues: + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + # 关闭未活动的 Issues + - name: Close Inactive Issues + uses: actions/stale@v9 + with: + days-before-stale: -1 # Issues and PR will never be flagged stale automatically. + stale-issue-label: needs-reproduction # Label that flags an issue as stale. + only-labels: needs-reproduction # Only process these issues + days-before-issue-close: 3 + ignore-updates: true + remove-stale-when-updated: false + close-issue-message: This issue was closed because it was open for 3 days without a valid reproduction. + close-issue-label: closed-by-action diff --git a/.github/workflows/issue-labeled.yml b/.github/workflows/issue-labeled.yml new file mode 100644 index 0000000..2feda4e --- /dev/null +++ b/.github/workflows/issue-labeled.yml @@ -0,0 +1,46 @@ +name: Label Based Actions + +on: + issues: + types: [labeled] + # pull_request: + # types: [labeled] + +permissions: + issues: write + pull-requests: write + contents: write + +jobs: + reply-labeled: + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + - name: remove enhancement pending + if: github.event.label.name == 'enhancement' + uses: actions-cool/issues-helper@v3 + with: + actions: 'remove-labels' + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + labels: 'enhancement: pending triage' + + - name: remove bug pending + if: github.event.label.name == 'bug' + uses: actions-cool/issues-helper@v3 + with: + actions: 'remove-labels' + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + labels: 'bug: pending triage' + + - name: needs reproduction + if: github.event.label.name == 'needs reproduction' + uses: actions-cool/issues-helper@v3 + with: + actions: 'create-comment, remove-labels' + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + body: | + Hello @${{ github.event.issue.user.login }}. Please provide the complete reproduction steps and code. Issues labeled by `needs reproduction` will be closed if no activities in 3 days. + labels: 'bug: pending triage' diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml new file mode 100644 index 0000000..bd73d53 --- /dev/null +++ b/.github/workflows/lock.yml @@ -0,0 +1,24 @@ +name: Lock Threads + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + action: + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v5 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + issue-inactive-days: '14' + issue-lock-reason: '' + pr-inactive-days: '30' + pr-lock-reason: '' + process-only: 'issues, prs' diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml new file mode 100644 index 0000000..5684990 --- /dev/null +++ b/.github/workflows/release-tag.yml @@ -0,0 +1,80 @@ +name: Create Release Tag + +on: + push: + tags: + - 'v*.*.*' # Push events to matching v*, i.e. v1.0, v20.15.10 + +env: + HUSKY: '0' + +permissions: + pull-requests: write + contents: write + +jobs: + build: + name: Create Release + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [22] + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + # - name: Checkout code + # uses: actions/checkout@v6 + # with: + # fetch-depth: 0 + + # - name: Install pnpm + # uses: pnpm/action-setup@v4 + + # - name: Use Node.js ${{ matrix.node-version }} + # uses: actions/setup-node@v4 + # with: + # node-version: ${{ matrix.node-version }} + # cache: "pnpm" + + # - name: Install dependencies + # run: pnpm install --frozen-lockfile + + # - name: Test and Build + # run: | + # pnpm run test + # pnpm run build + + - name: version + id: version + run: | + tag=${GITHUB_REF/refs\/tags\//} + version=${tag#v} + major=${version%%.*} + echo "tag=${tag}" >> $GITHUB_OUTPUT + echo "version=${version}" >> $GITHUB_OUTPUT + echo "major=${major}" >> $GITHUB_OUTPUT + + - uses: release-drafter/release-drafter@v6 + with: + version: ${{ steps.version.outputs.version }} + publish: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # - name: force update major tag + # run: | + # git tag v${{ steps.version.outputs.major }} ${{ steps.version.outputs.tag }} -f + # git push origin refs/tags/v${{ steps.version.outputs.major }} -f + + # - name: Create Release for Tag + # id: release_tag + # uses: ncipollo/release-action@v1 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # generateReleaseNotes: "true" + # body: | + # > Please refer to [CHANGELOG.md](https://github.com/vbenjs/vue-vben-admin/blob/main/CHANGELOG.md) for details. diff --git a/.github/workflows/rerun.yml b/.github/workflows/rerun.yml new file mode 100644 index 0000000..2b46255 --- /dev/null +++ b/.github/workflows/rerun.yml @@ -0,0 +1,19 @@ +name: Rerun workflow + +on: + workflow_dispatch: + inputs: + run_id: + description: The workflow id to relanch + required: true +jobs: + rerun: + runs-on: ubuntu-latest + steps: + - name: rerun ${{ inputs.run_id }} + env: + GH_REPO: ${{ github.repository }} + GH_TOKEN: ${{ github.token }} + run: | + gh run watch ${{ inputs.run_id }} > /dev/null 2>&1 + gh run rerun ${{ inputs.run_id }} --failed diff --git a/.github/workflows/semantic-pull-request.yml b/.github/workflows/semantic-pull-request.yml new file mode 100644 index 0000000..db8e9e0 --- /dev/null +++ b/.github/workflows/semantic-pull-request.yml @@ -0,0 +1,41 @@ +name: Semantic Pull Request + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + +jobs: + main: + name: Semantic Pull Request + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + - name: Validate PR title + uses: amannn/action-semantic-pull-request@v5 + with: + wip: true + subjectPattern: ^(?![A-Z]).+$ + subjectPatternError: | + The subject "{subject}" found in the pull request title "{title}" + didn't match the configured pattern. Please ensure that the subject + doesn't start with an uppercase character. + requireScope: false + types: | + fix + feat + docs + style + refactor + perf + test + build + ci + chore + revert + types + release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..991e133 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,19 @@ +name: 'Close stale issues' + +on: + schedule: + - cron: '0 1 * * *' + +jobs: + stale: + if: github.repository == 'vbenjs/vue-vben-admin' + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' + stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' + exempt-issue-labels: 'bug,enhancement' + days-before-stale: 60 + days-before-close: 7 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3399f39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,52 @@ +node_modules +.DS_Store +dist +dist-ssr +dist.zip +dist.tar +dist.war +.nitro +.output +*-dist.zip +*-dist.tar +*-dist.war +coverage +*.local +**/.vitepress/cache +.cache +.turbo +.temp +dev-dist +.stylelintcache +yarn.lock +package-lock.json +.VSCodeCounter +**/backend-mock/data + +# local env files +.env.local +.env.*.local +.eslintcache + +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* +vite.config.mts.* +vite.config.mjs.* +vite.config.js.* +vite.config.ts.* + +# Editor directories and files +.idea +# .vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.history +.cursor diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..5fda2cf --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,6 @@ +ports: + - port: 5555 + onOpen: open-preview +tasks: + - init: npm i -g corepack && pnpm install + command: pnpm run dev:play diff --git a/.node-version b/.node-version new file mode 100644 index 0000000..85e5027 --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +22.22.0 diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..aeac1ae --- /dev/null +++ b/.npmrc @@ -0,0 +1,13 @@ +registry=https://registry.npmmirror.com +public-hoist-pattern[]=lefthook +public-hoist-pattern[]=eslint +public-hoist-pattern[]=prettier +public-hoist-pattern[]=prettier-plugin-tailwindcss +public-hoist-pattern[]=stylelint +public-hoist-pattern[]=*postcss* +public-hoist-pattern[]=@commitlint/* +public-hoist-pattern[]=czg + +strict-peer-dependencies=false +auto-install-peers=true +dedupe-peer-dependents=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..d0b0ca1 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,18 @@ +dist +dev-dist +.local +.output.js +node_modules +.nvmrc +coverage +CODEOWNERS +.nitro +.output + + +**/*.svg +**/*.sh + +public +.npmrc +*-lock.yaml diff --git a/.prettierrc.mjs b/.prettierrc.mjs new file mode 100644 index 0000000..3e25d2c --- /dev/null +++ b/.prettierrc.mjs @@ -0,0 +1 @@ +export { default } from '@vben/prettier-config'; diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..f4b2db2 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,4 @@ +dist +public +__tests__ +coverage diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..e8dc9ed --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,30 @@ +{ + "recommendations": [ + // Vue 3 的语言支持 + "Vue.volar", + // 将 ESLint JavaScript 集成到 VS Code 中。 + "dbaeumer.vscode-eslint", + // Visual Studio Code 的官方 Stylelint 扩展 + "stylelint.vscode-stylelint", + // 使用 Prettier 的代码格式化程序 + "esbenp.prettier-vscode", + // 支持 dotenv 文件语法 + "mikestead.dotenv", + // 源代码的拼写检查器 + "streetsidesoftware.code-spell-checker", + // Tailwind CSS 的官方 VS Code 插件 + "bradlc.vscode-tailwindcss", + // iconify 图标插件 + "antfu.iconify", + // i18n 插件 + "Lokalise.i18n-ally", + // CSS 变量提示 + "vunguyentuan.vscode-css-variables", + // 在 package.json 中显示 PNPM catalog 的版本 + "antfu.pnpm-catalog-lens" + ], + "unwantedRecommendations": [ + // 和 volar 冲突 + "octref.vetur" + ] +} diff --git a/.vscode/global.code-snippets b/.vscode/global.code-snippets new file mode 100644 index 0000000..7604b01 --- /dev/null +++ b/.vscode/global.code-snippets @@ -0,0 +1,37 @@ +{ + "import": { + "scope": "javascript,typescript", + "prefix": "im", + "body": ["import { $2 } from '$1';"], + "description": "Import a module", + }, + "export-all": { + "scope": "javascript,typescript", + "prefix": "ex", + "body": ["export * from '$1';"], + "description": "Export a module", + }, + "vue-script-setup": { + "scope": "vue", + "prefix": "", + "const props = defineProps<{", + " modelValue?: boolean,", + "}>()", + "$1", + "", + "", + "", + ], + }, + "vue-computed": { + "scope": "javascript,typescript,vue", + "prefix": "com", + "body": ["computed(() => { $1 })"], + }, +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..0278f83 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "name": "vben admin antd dev", + "request": "launch", + "url": "http://localhost:5666", + "env": { "NODE_ENV": "development" }, + "sourceMaps": true, + "webRoot": "${workspaceFolder}/apps/web-antd" + }, + { + "type": "chrome", + "name": "vben admin ele dev", + "request": "launch", + "url": "http://localhost:5777", + "env": { "NODE_ENV": "development" }, + "sourceMaps": true, + "webRoot": "${workspaceFolder}/apps/web-ele" + }, + { + "type": "chrome", + "name": "vben admin naive dev", + "request": "launch", + "url": "http://localhost:5888", + "env": { "NODE_ENV": "development" }, + "sourceMaps": true, + "webRoot": "${workspaceFolder}/apps/web-naive" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..588357b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,229 @@ +{ + "tailwindCSS.experimental.configFile": "internal/tailwind-config/src/index.ts", + // workbench + "workbench.list.smoothScrolling": true, + "workbench.startupEditor": "newUntitledFile", + "workbench.tree.indent": 10, + "workbench.editor.highlightModifiedTabs": true, + "workbench.editor.closeOnFileDelete": true, + "workbench.editor.limit.enabled": true, + "workbench.editor.limit.perEditorGroup": true, + "workbench.editor.limit.value": 5, + + // editor + "editor.tabSize": 2, + "editor.detectIndentation": false, + "editor.cursorBlinking": "expand", + "editor.largeFileOptimizations": true, + "editor.accessibilitySupport": "off", + "editor.cursorSmoothCaretAnimation": "on", + "editor.guides.bracketPairs": "active", + "editor.inlineSuggest.enabled": true, + "editor.suggestSelection": "recentlyUsedByPrefix", + "editor.acceptSuggestionOnEnter": "smart", + "editor.suggest.snippetsPreventQuickSuggestions": false, + "editor.stickyScroll.enabled": true, + "editor.hover.sticky": true, + "editor.suggest.insertMode": "replace", + "editor.bracketPairColorization.enabled": true, + "editor.autoClosingBrackets": "beforeWhitespace", + "editor.autoClosingDelete": "always", + "editor.autoClosingOvertype": "always", + "editor.autoClosingQuotes": "beforeWhitespace", + "editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit", + "source.fixAll.stylelint": "explicit", + "source.organizeImports": "never" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[html]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[css]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[scss]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[markdown]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[vue]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + // extensions + "extensions.ignoreRecommendations": true, + + // terminal + "terminal.integrated.cursorBlinking": true, + "terminal.integrated.persistentSessionReviveProcess": "never", + "terminal.integrated.tabs.enabled": true, + "terminal.integrated.scrollback": 10000, + "terminal.integrated.stickyScroll.enabled": true, + + // files + "files.eol": "\n", + "files.insertFinalNewline": true, + "files.simpleDialog.enable": true, + "files.associations": { + "*.ejs": "html", + "*.art": "html", + "**/tsconfig.json": "jsonc", + "*.json": "jsonc", + "package.json": "json" + }, + + "files.exclude": { + "**/.eslintcache": true, + "**/bower_components": true, + "**/.turbo": true, + "**/.idea": true, + "**/.vitepress": true, + "**/tmp": true, + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.stylelintcache": true, + "**/.DS_Store": true, + "**/vite.config.mts.*": true, + "**/tea.yaml": true + }, + "files.watcherExclude": { + "**/.git/objects/**": true, + "**/.git/subtree-cache/**": true, + "**/.vscode/**": true, + "**/node_modules/**": true, + "**/tmp/**": true, + "**/bower_components/**": true, + "**/dist/**": true, + "**/yarn.lock": true + }, + + "typescript.tsserver.exclude": ["**/node_modules", "**/dist", "**/.turbo"], + + // search + "search.searchEditor.singleClickBehaviour": "peekDefinition", + "search.followSymlinks": false, + // 在使用搜索功能时,将这些文件夹/文件排除在外 + "search.exclude": { + "**/node_modules": true, + "**/*.log": true, + "**/*.log*": true, + "**/bower_components": true, + "**/dist": true, + "**/elehukouben": true, + "**/.git": true, + "**/.github": true, + "**/.gitignore": true, + "**/.svn": true, + "**/.DS_Store": true, + "**/.vitepress/cache": true, + "**/.idea": true, + "**/.vscode": false, + "**/.yarn": true, + "**/tmp": true, + "*.xml": true, + "out": true, + "dist": true, + "node_modules": true, + "CHANGELOG.md": true, + "**/pnpm-lock.yaml": true, + "**/yarn.lock": true, + "**/public/**": true + }, + + "debug.onTaskErrors": "debugAnyway", + "diffEditor.ignoreTrimWhitespace": false, + "npm.packageManager": "pnpm", + + "css.validate": false, + "less.validate": false, + "scss.validate": false, + + // extension + "emmet.showSuggestionsAsSnippets": true, + "emmet.triggerExpansionOnTab": false, + + "errorLens.enabledDiagnosticLevels": ["warning", "error"], + "errorLens.excludeBySource": ["cSpell", "Grammarly", "eslint"], + + "stylelint.enable": true, + "stylelint.packageManager": "pnpm", + "stylelint.validate": ["css", "less", "postcss", "scss", "vue"], + "stylelint.customSyntax": "postcss-html", + "stylelint.snippet": ["css", "less", "postcss", "scss", "vue"], + + "typescript.inlayHints.enumMemberValues.enabled": true, + "typescript.preferences.preferTypeOnlyAutoImports": true, + "typescript.preferences.includePackageJsonAutoImports": "on", + + "eslint.validate": [ + "javascript", + "typescript", + "javascriptreact", + "typescriptreact", + "vue", + "html", + "markdown", + "json", + "jsonc", + "json5", + "yaml" + ], + + "tailwindCSS.experimental.classRegex": [ + ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"] + ], + + "github.copilot.enable": { + "*": false + }, + + "cssVariables.lookupFiles": ["packages/core/base/design/src/**/*.css"], + + "i18n-ally.localesPaths": [ + "packages/locales/src/langs", + "playground/src/locales/langs", + "apps/*/src/locales/langs" + ], + "i18n-ally.pathMatcher": "{locale}/{namespace}.{ext}", + "i18n-ally.enabledParsers": ["json"], + "i18n-ally.sourceLanguage": "en", + "i18n-ally.displayLanguage": "zh-CN", + "i18n-ally.enabledFrameworks": ["vue", "react"], + "i18n-ally.keystyle": "nested", + "i18n-ally.sortKeys": true, + "i18n-ally.namespace": true, + + // 控制相关文件嵌套展示 + "explorer.fileNesting.enabled": true, + "explorer.fileNesting.expand": false, + "explorer.fileNesting.patterns": { + "*.ts": "$(capture).test.ts, $(capture).test.tsx, $(capture).spec.ts, $(capture).spec.tsx, $(capture).d.ts", + "*.tsx": "$(capture).test.ts, $(capture).test.tsx, $(capture).spec.ts, $(capture).spec.tsx,$(capture).d.ts", + "*.env": "$(capture).env.*", + "README.md": "README*,CHANGELOG*,LICENSE,CNAME", + "package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json", + "eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml", + "tailwind.config.mjs": "postcss.*" + }, + "commentTranslate.hover.enabled": false, + "commentTranslate.multiLineMerge": true, + "vue.server.hybridMode": true, + "typescript.tsdk": "node_modules/typescript/lib", + "oxc.enable": false +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cec5b42 --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2024-present, Vben + +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/README.md b/README.md new file mode 100644 index 0000000..0b16aa1 --- /dev/null +++ b/README.md @@ -0,0 +1,240 @@ +# 严肃声明:现在、未来都不会有商业版本,所有代码全部开源 + +**「我喜欢写代码,乐此不疲」** +**「我喜欢做开源,以此为乐」** + +我 🐶 在上海艰苦奋斗,早中晚在 top3 大厂认真搬砖,夜里为开源做贡献。 + +如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。 + +## 🐶 新手必读 + +- nodejs > v20.19.0 | v22 | v24 && pnpm > 10.20.0 (强制使用pnpm) +- 演示地址【Vue3 + element-plus】: +- 演示地址【Vue3 + vben5(ant-design-vue)】: +- 演示地址【Vue2 + element-ui】: +- 启动文档: +- 视频教程: + +## 🐯 平台简介 + +**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。 + +- 采用最新 [vue-vben-admin](https://github.com/vbenjs/vue-vben-admin) v5 实现 +- 支持 [Ant Design Vue](https://www.antdv.com/) | [Element Plus](https://element-plus.org/zh-CN/) | [Naive UI](https://www.naiveui.com/) | [TDesign](https://tdesign.tencent.com/) 多种免费开源的中后台模版,具备如下特性: + +![首页](.gitee/image/demo/vben.png) + +- **最新技术栈**:使用 Vue3、Vite7 等前端前沿技术开发 +- **TypeScript**: 应用程序级 JavaScript 的语言 +- **主题**: 提供多套主题色彩,可配置自定义主题 +- **国际化**:内置完善的国际化方案 +- **权限**:内置完善的动态路由权限生成方案 +- **组件**:二次封装了多个常用的组件 +- **示例**:内置丰富的示例 + +## [外包项目请联系【非项目需求请勿扫码,非客服,不解答项目问题】](https://www.shuduokeji.com?yudao) + +![alt 软件定制开发 数舵科技](.gitee/image/wx-xingyu.png) + +## 技术栈 + +| 框架 | 说明 | 版本 | +| --- | --- | --- | +| [Vue](https://staging-cn.vuejs.org/) | vue框架 | 3.5.27 | +| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 7.3.1 | +| [Ant Design Vue](https://www.antdv.com/) | Ant Design Vue | 4.2.6 | +| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.13.1 | +| [Naive UI](https://www.naiveui.com/) | Naive UI | 2.43.2 | +| [TDesign](https://tdesign.tencent.com/) | TDesign | 1.18.0 | +| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 超集 | 5.9.3 | +| [pinia](https://pinia.vuejs.org/) | Vue 存储库替代 vuex5 | 3.0.4 | +| [vueuse](https://vueuse.org/) | 常用工具集 | 14.1.0 | +| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 11.2.8 | +| [vue-router](https://router.vuejs.org/) | Vue 路由 | 4.6.4 | +| [Tailwind CSS](https://tailwindcss.com/) | 原子 CSS | 3.4.19 | +| [Iconify](https://iconify.design/) | 图标组件 | 5.0.0 | +| [Iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.431 | +| [TinyMCE](https://www.tiny.cloud/) | 富文本编辑器 | 7.3.0 | +| [Echarts](https://echarts.apache.org/) | 图表库 | 6.0.0 | +| [axios](https://axios-http.com/) | http客户端 | 1.13.2 | +| [dayjs](https://day.js.org/) | 日期处理库 | 1.11.19 | +| [vee-validate](https://vee-validate.logaretm.com/) | 表单验证 | 4.15.1 | +| [zod](https://zod.dev/) | 数据验证 | 3.25.76 | + +## 🔥 后端架构 + +支持 Spring Boot、Spring Cloud 两种架构: + +① Spring Boot 单体架构: + +![架构图](/.gitee/image/common/ruoyi-vue-pro-architecture.png) + +② Spring Cloud 微服务架构: + +![架构图](/.gitee/image/common/yudao-cloud-architecture.png) + +## 内置功能 + +系统内置多种多种业务功能,可以用于快速你的业务系统: + +系统内置多种多种业务功能,可以用于快速你的业务系统: + +![功能分层](/.gitee/image/common/ruoyi-vue-pro-biz.png) + +- 通用模块(必选):系统功能、基础设施 +- 通用模块(可选):工作流程、支付系统、数据报表、会员中心 +- 业务系统(按需):ERP 系统、CRM 系统、商城系统、微信公众号、AI 大模型 + +### 系统功能 + +| | 功能 | 描述 | +| --- | --- | --- | +| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 | +| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 | +| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 | +| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 | +| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 | +| | 岗位管理 | 配置系统用户所属担任职务 | +| 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 | +| 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 | +| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | +| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 | +| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 | +| 🚀 | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 | +| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 | +| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 | +| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 | +| | 通知公告 | 系统通知公告信息发布维护 | +| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 | +| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 | +| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 | + +![功能图](/.gitee/image/common/system-feature.png) + +### 工作流程 + +![功能图](/.gitee/image/common/bpm-feature.png) + +基于 Flowable 构建,可支持信创(国产)数据库,满足中国特色流程操作: + +| BPMN 设计器 | 钉钉/飞书设计器 | +| --- | --- | +| ![工作流设计器](.gitee/image/工作流设计器-bpmn.jpg) | ![工作流设计器](.gitee/image/工作流设计器-simple.jpg) | + +> 历经头部企业生产验证,工作流引擎须标配仿钉钉/飞书 + BPMN 双设计器!!! +> +> 前者支持轻量配置简单流程,后者实现复杂场景深度编排 + +| 功能列表 | 功能描述 | 是否完成 | +| --- | --- | --- | +| SIMPLE 设计器 | 仿钉钉/飞书设计器,支持拖拽搭建表单流程,10 分钟快速完成审批流程配置 | ✅ | +| BPMN 设计器 | 基于 BPMN 标准开发,适配复杂业务场景,满足多层级审批及流程自动化需求 | ✅ | +| 会签 | 同一个审批节点设置多个人(如 A、B、C 三人,三人会同时收到待办任务),需全部同意之后,审批才可到下一审批节点 | ✅ | +| 或签 | 同一个审批节点设置多个人,任意一个人处理后,就能进入下一个节点 | ✅ | +| 依次审批 | (顺序会签)同一个审批节点设置多个人(如 A、B、C 三人),三人按顺序依次收到待办,即 A 先审批,A 提交后 B 才能审批,需全部同意之后,审批才可到下一审批节点 | ✅ | +| 抄送 | 将审批结果通知给抄送人,同一个审批默认排重,不重复抄送给同一人 | ✅ | +| 驳回 | (退回)将审批重置发送给某节点,重新审批。可驳回至发起人、上一节点、任意节点 | ✅ | +| 转办 | A 转给其 B 审批,B 审批后,进入下一节点 | ✅ | +| 委派 | A 转给其 B 审批,B 审批后,转给 A,A 继续审批后进入下一节点 | ✅ | +| 加签 | 允许当前审批人根据需要,自行增加当前节点的审批人,支持向前、向后加签 | ✅ | +| 减签 | (取消加签)在当前审批人操作之前,减少审批人 | ✅ | +| 撤销 | (取消流程)流程发起人,可以对流程进行撤销处理 | ✅ | +| 终止 | 系统管理员,在任意节点终止流程实例 | ✅ | +| 表单权限 | 支持拖拉拽配置表单,每个审批节点可配置只读、编辑、隐藏权限 | ✅ | +| 超时审批 | 配置超时审批时间,超时后自动触发审批通过、不通过、驳回等操作 | ✅ | +| 自动提醒 | 配置提醒时间,到达时间后自动触发短信、邮箱、站内信等通知提醒,支持自定义重复提醒频次 | ✅ | +| 父子流程 | 主流程设置子流程节点,子流程节点会自动触发子流程。子流程结束后,主流程才会执行(继续往下下执行),支持同步子流程、异步子流程 | ✅ | +| 条件分支 | (排它分支)用于在流程中实现决策,即根据条件选择一个分支执行 | ✅ | +| 并行分支 | 允许将流程分成多条分支,不进行条件判断,所有分支都会执行 | ✅ | +| 包容分支 | (条件分支 + 并行分支的结合体)允许基于条件选择多条分支执行,但如果没有任何一个分支满足条件,则可以选择默认分支 | ✅ | +| 路由分支 | 根据条件选择一个分支执行(重定向到指定配置节点),也可以选择默认分支执行(继续往下执行) | ✅ | +| 触发节点 | 执行到该节点,触发 HTTP 请求、HTTP 回调、更新数据、删除数据等 | ✅ | +| 延迟节点 | 执行到该节点,审批等待一段时间再执行,支持固定时长、固定日期等 | ✅ | +| 拓展设置 | 流程前置/后置通知,节点(任务)前置、后置通知,流程报表,自动审批去重,自定流程编号、标题、摘要,流程报表等 | ✅ | + +### 支付系统 + +| | 功能 | 描述 | +| --- | -------- | -------------------------------------------------- | +| 🚀 | 应用信息 | 配置商户的应用信息,对接支付宝、微信等多个支付渠道 | +| 🚀 | 支付订单 | 查看用户发起的支付宝、微信等的【支付】订单 | +| 🚀 | 退款订单 | 查看用户发起的支付宝、微信等的【退款】订单 | +| 🚀 | 回调通知 | 查看支付回调业务的【支付】【退款】的通知结果 | +| 🚀 | 接入示例 | 提供接入支付系统的【支付】【退款】的功能实战 | + +### 基础设施 + +| | 功能 | 描述 | +| --- | --- | --- | +| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 | +| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 | +| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 | +| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 | +| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 | +| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 | +| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 | +| 🚀 | WebSocket | 提供 WebSocket 接入示例,支持一对一、一对多发送方式 | +| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 | +| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 | +| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 | +| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 | +| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 | +| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 | +| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 | +| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 | +| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 | +| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 | + +![功能图](/.gitee/image/common/infra-feature.png) + +### 数据报表 + +| | 功能 | 描述 | +| --- | ---------- | ------------------------------------ | +| 🚀 | 报表设计器 | 支持数据报表、图形报表、打印设计等 | +| 🚀 | 大屏设计器 | 拖拽生成数据大屏,内置几十种图表组件 | + +### 微信公众号 + +| | 功能 | 描述 | +| --- | --- | --- | +| 🚀 | 账号管理 | 配置接入的微信公众号,可支持多个公众号 | +| 🚀 | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 | +| 🚀 | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 | +| 🚀 | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 | +| 🚀 | 模版消息 | 配置和发送模版消息,用于向粉丝推送通知类消息 | +| 🚀 | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 | +| 🚀 | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 | +| 🚀 | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 | +| 🚀 | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 | +| 🚀 | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 | +| 🚀 | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 | + +### 商城系统 + +演示地址: + +![功能图](/.gitee/image/common/mall-feature.png) + +![功能图](/.gitee/image/common/mall-preview.png) + +### ERP 系统 + +演示地址: + +![功能图](/.gitee/image/common/erp-feature.png) + +### CRM 系统 + +演示地址: + +![功能图](/.gitee/image/common/crm-feature.png) + +### AI 大模型 + +演示地址: + +![功能图](/.gitee/image/common/ai-feature.png) + +![功能图](/.gitee/image/common/ai-preview.gif) diff --git a/apps/web-antd/.env b/apps/web-antd/.env new file mode 100644 index 0000000..a0bfde1 --- /dev/null +++ b/apps/web-antd/.env @@ -0,0 +1,38 @@ +# 应用标题 +VITE_APP_TITLE=芋道管理系统 + +# 应用命名空间,用于缓存、store等功能的前缀,确保隔离 +VITE_APP_NAMESPACE=yudao-vben-antd + +# 对store进行加密的密钥,在将store持久化到localStorage时会使用该密钥进行加密 +VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key + +# 是否开启模拟数据 +VITE_NITRO_MOCK=false + +# 租户开关 +VITE_APP_TENANT_ENABLE=true + +# 验证码的开关 +VITE_APP_CAPTCHA_ENABLE=false + +# 文档地址的开关 +VITE_APP_DOCALERT_ENABLE=true + +# 百度统计 +VITE_APP_BAIDU_CODE = e98f2eab6ceb8688bc6d8fc5332ff093 + +# GoView域名 +VITE_GOVIEW_URL='http://127.0.0.1:3000' + +# API 加解密 +VITE_APP_API_ENCRYPT_ENABLE = true +VITE_APP_API_ENCRYPT_HEADER = X-Api-Encrypt +VITE_APP_API_ENCRYPT_ALGORITHM = AES +VITE_APP_API_ENCRYPT_REQUEST_KEY = 52549111389893486934626385991395 +VITE_APP_API_ENCRYPT_RESPONSE_KEY = 96103715984234343991809655248883 +# VITE_APP_API_ENCRYPT_REQUEST_KEY = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCls2rIpnGdYnLFgz1XU13GbNQ5DloyPpvW00FPGjqn5Z6JpK+kDtVlnkhwR87iRrE5Vf2WNqRX6vzbLSgveIQY8e8oqGCb829myjf1MuI+ZzN4ghf/7tEYhZJGPI9AbfxFqBUzm+kR3/HByAI22GLT96WM26QiMK8n3tIP/yiLswIDAQAB +# VITE_APP_API_ENCRYPT_RESPONSE_KEY = MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOH8IfIFxL/MR9XIg1UDv5z1fGXQI93E8wrU4iPFovL/sEt9uSgSkjyidC2O7N+m7EKtoN6b1u7cEwXSkwf3kfK0jdWLSQaNpX5YshqXCBzbDfugDaxuyYrNA4/tIMs7mzZAk0APuRXB35Dmupou7Yw7TFW/7QhQmGfzeEKULQvnAgMBAAECgYAw8LqlQGyQoPv5p3gRxEMOCfgL0JzD3XBJKztiRd35RDh40Nx1ejgjW4dPioFwGiVWd2W8cAGHLzALdcQT2KDJh+T/tsd4SPmI6uSBBK6Ff2DkO+kFFcuYvfclQQKqxma5CaZOSqhgenacmgTMFeg2eKlY3symV6JlFNu/IKU42QJBAOhxAK/Eq3e61aYQV2JSguhMR3b8NXJJRroRs/QHEanksJtl+M+2qhkC9nQVXBmBkndnkU/l2tYcHfSBlAyFySMCQQD445tgm/J2b6qMQmuUGQAYDN8FIkHjeKmha+l/fv0igWm8NDlBAem91lNDIPBUzHL1X1+pcts5bjmq99YdOnhtAkAg2J8dN3B3idpZDiQbC8fd5bGPmdI/pSUudAP27uzLEjr2qrE/QPPGdwm2m7IZFJtK7kK1hKio6u48t/bg0iL7AkEAuUUs94h+v702Fnym+jJ2CHEkXvz2US8UDs52nWrZYiM1o1y4tfSHm8H8bv8JCAa9GHyriEawfBraILOmllFdLQJAQSRZy4wmlaG48MhVXodB85X+VZ9krGXZ2TLhz7kz9iuToy53l9jTkESt6L5BfBDCVdIwcXLYgK+8KFdHN5W7HQ== + +# 百度地图 +VITE_BAIDU_MAP_KEY=Y2aJXiswwPxy6mwFs1z9c7U5gwX9WfUN \ No newline at end of file diff --git a/apps/web-antd/.env.analyze b/apps/web-antd/.env.analyze new file mode 100644 index 0000000..ffafa8d --- /dev/null +++ b/apps/web-antd/.env.analyze @@ -0,0 +1,7 @@ +# public path +VITE_BASE=/ + +# Basic interface address SPA +VITE_GLOB_API_URL=/api + +VITE_VISUALIZER=true diff --git a/apps/web-antd/.env.development b/apps/web-antd/.env.development new file mode 100644 index 0000000..cff2557 --- /dev/null +++ b/apps/web-antd/.env.development @@ -0,0 +1,21 @@ +# 端口号 +VITE_PORT=5666 + +VITE_BASE=/ + +# 请求路径 +VITE_BASE_URL=http://127.0.0.1:48080 +# 接口地址 +VITE_GLOB_API_URL=/admin-api +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务 +VITE_UPLOAD_TYPE=server +# 是否打开 devtools,true 为打开,false 为关闭 +VITE_DEVTOOLS=false + +# 是否注入全局loading +VITE_INJECT_APP_LOADING=true + +# 默认登录用户名 +VITE_APP_DEFAULT_USERNAME=admin +# 默认登录密码 +VITE_APP_DEFAULT_PASSWORD=admin123 diff --git a/apps/web-antd/.env.production b/apps/web-antd/.env.production new file mode 100644 index 0000000..a8f3d29 --- /dev/null +++ b/apps/web-antd/.env.production @@ -0,0 +1,26 @@ +VITE_BASE=/ + +# 请求路径 +VITE_BASE_URL=http://127.0.0.1:48080 +# 接口地址 +VITE_GLOB_API_URL=http://127.0.0.1:48080/admin-api +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务 +VITE_UPLOAD_TYPE=server + +# 是否开启压缩,可以设置为 none, brotli, gzip +VITE_COMPRESS=none + +# 是否开启 PWA +VITE_PWA=false + +# vue-router 的模式 +VITE_ROUTER_HISTORY=hash + +# 是否注入全局loading +VITE_INJECT_APP_LOADING=true + +# 打包后是否生成dist.zip +VITE_ARCHIVER=true + +# 验证码的开关 +VITE_APP_CAPTCHA_ENABLE=true \ No newline at end of file diff --git a/apps/web-antd/index.html b/apps/web-antd/index.html new file mode 100644 index 0000000..34c6f14 --- /dev/null +++ b/apps/web-antd/index.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + <%= VITE_APP_TITLE %> + + + + +
+ + + diff --git a/apps/web-antd/package.json b/apps/web-antd/package.json new file mode 100644 index 0000000..75506ad --- /dev/null +++ b/apps/web-antd/package.json @@ -0,0 +1,71 @@ +{ + "name": "@vben/web-antd", + "version": "5.6.0", + "homepage": "https://vben.pro", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "apps/web-antd" + }, + "license": "MIT", + "author": { + "name": "vben", + "email": "ann.vben@gmail.com", + "url": "https://github.com/anncwb" + }, + "type": "module", + "scripts": { + "build": "pnpm vite build --mode production", + "build:analyze": "pnpm vite build --mode analyze", + "dev": "pnpm vite --mode development", + "preview": "vite preview", + "typecheck": "vue-tsc --noEmit --skipLibCheck" + }, + "imports": { + "#/*": "./src/*" + }, + "dependencies": { + "@form-create/ant-design-vue": "catalog:", + "@form-create/antd-designer": "catalog:", + "@tinymce/tinymce-vue": "catalog:", + "@vben/access": "workspace:*", + "@vben/common-ui": "workspace:*", + "@vben/constants": "workspace:*", + "@vben/hooks": "workspace:*", + "@vben/icons": "workspace:*", + "@vben/layouts": "workspace:*", + "@vben/locales": "workspace:*", + "@vben/plugins": "workspace:*", + "@vben/preferences": "workspace:*", + "@vben/request": "workspace:*", + "@vben/stores": "workspace:*", + "@vben/styles": "workspace:*", + "@vben/types": "workspace:*", + "@vben/utils": "workspace:*", + "@videojs-player/vue": "catalog:", + "@vueuse/core": "catalog:", + "@vueuse/integrations": "catalog:", + "ant-design-vue": "catalog:", + "benz-amr-recorder": "catalog:", + "bpmn-js": "catalog:", + "bpmn-js-properties-panel": "catalog:", + "bpmn-js-token-simulation": "catalog:", + "camunda-bpmn-moddle": "catalog:", + "cropperjs": "catalog:", + "dayjs": "catalog:", + "diagram-js": "catalog:", + "fast-xml-parser": "catalog:", + "highlight.js": "catalog:", + "pinia": "catalog:", + "steady-xml": "catalog:", + "tinymce": "catalog:", + "video.js": "catalog:", + "vue": "catalog:", + "vue-dompurify-html": "catalog:", + "vue-router": "catalog:", + "vue3-print-nb": "catalog:", + "vue3-signature": "catalog:", + "vuedraggable": "catalog:" + } +} diff --git a/apps/web-antd/postcss.config.mjs b/apps/web-antd/postcss.config.mjs new file mode 100644 index 0000000..3d80704 --- /dev/null +++ b/apps/web-antd/postcss.config.mjs @@ -0,0 +1 @@ +export { default } from '@vben/tailwind-config/postcss'; diff --git a/apps/web-antd/public/favicon.ico b/apps/web-antd/public/favicon.ico new file mode 100644 index 0000000..fcf9818 Binary files /dev/null and b/apps/web-antd/public/favicon.ico differ diff --git a/apps/web-antd/public/static/imgs/ai/dall2.jpg b/apps/web-antd/public/static/imgs/ai/dall2.jpg new file mode 100644 index 0000000..c07374d Binary files /dev/null and b/apps/web-antd/public/static/imgs/ai/dall2.jpg differ diff --git a/apps/web-antd/public/static/imgs/ai/dall3.jpg b/apps/web-antd/public/static/imgs/ai/dall3.jpg new file mode 100644 index 0000000..7f45803 Binary files /dev/null and b/apps/web-antd/public/static/imgs/ai/dall3.jpg differ diff --git a/apps/web-antd/public/static/imgs/ai/qingxi.jpg b/apps/web-antd/public/static/imgs/ai/qingxi.jpg new file mode 100644 index 0000000..d76b815 Binary files /dev/null and b/apps/web-antd/public/static/imgs/ai/qingxi.jpg differ diff --git a/apps/web-antd/public/static/imgs/ai/ziran.jpg b/apps/web-antd/public/static/imgs/ai/ziran.jpg new file mode 100644 index 0000000..6290724 Binary files /dev/null and b/apps/web-antd/public/static/imgs/ai/ziran.jpg differ diff --git a/apps/web-antd/public/tinymce/icons/default/icons.min.js b/apps/web-antd/public/tinymce/icons/default/icons.min.js new file mode 100644 index 0000000..620f554 --- /dev/null +++ b/apps/web-antd/public/tinymce/icons/default/icons.min.js @@ -0,0 +1 @@ +tinymce.IconManager.add("default",{icons:{"accessibility-check":'',"accordion-toggle":'',accordion:'',"action-next":'',"action-prev":'',addtag:'',"ai-prompt":'',ai:'',"align-center":'',"align-justify":'',"align-left":'',"align-none":'',"align-right":'',"arrow-left":'',"arrow-right":'',bold:'',bookmark:'',"border-style":'',"border-width":'',brightness:'',browse:'',cancel:'',"cell-background-color":'',"cell-border-color":'',"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":'',footnote:'',"format-code":'',"format-painter":'',format:'',fullscreen:'',gallery:'',gamma:'',help:'',"highlight-bg-color":'',home:'',"horizontal-rule":'',"image-options":'',image:'',indent:'',info:'',"insert-character":'',"insert-time":'',invert:'',italic:'',language:'',"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:'',"math-equation":'',mentions:'',minus:'',"more-drawer":'',"new-document":'',"new-tab":'',"non-breaking":'',notice:'',"ordered-list-rtl":'',"ordered-list":'',orientation:'',outdent:'',"export-pdf":'',"export-word":'',"import-word":'',"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":'',"revision-history":'',"rotate-left":'',"rotate-right":'',rtl:'',save:'',search:'',"select-all":'',selected:'',send:'',settings:'',sharpen:'',sourcecode:'',"spell-check":'',"strike-through":'',subscript:'',superscript:'',"table-caption":'',"table-cell-classes":'',"table-cell-properties":'',"table-cell-select-all":'',"table-cell-select-inner":'',"table-classes":'',"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-numbering-rtl":'',"table-row-numbering":'',"table-row-properties":'',"table-split-cells":'',"table-top-header":'',table:'',"template-add":'',template:'',"temporary-placeholder":'',"text-color":'',"text-size-decrease":'',"text-size-increase":'',toc:'',translate:'',typography:'',underline:'',undo:'',unlink:'',unlock:'',"unordered-list":'',unselected:'',upload:'',"add-file":'',adjustments:'',"alt-text":'',"auto-image-enhancement":'',blur:'',box:'',camera:'',caption:'',dropbox:'',evernote:'',exposure:'',fb:'',flickr:'',folder:'',"google-drive":'',"google-photos":'',grayscale:'',huddle:'',"image-decorative":'',"image-enhancements":'',instagram:'',onedrive:'',"photo-filter":'',"revert-changes":'',saturation:'',"transform-image":'',vibrance:'',vk:'',warmth:'',user:'',"vertical-align":'',visualblocks:'',visualchars:'',warning:'',"zoom-in":'',"zoom-out":''}}); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/langs/README.md b/apps/web-antd/public/tinymce/langs/README.md new file mode 100644 index 0000000..cd93d8c --- /dev/null +++ b/apps/web-antd/public/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 instead: https://crowdin.com/project/tinymce diff --git a/apps/web-antd/public/tinymce/langs/zh_CN.js b/apps/web-antd/public/tinymce/langs/zh_CN.js new file mode 100644 index 0000000..58ed188 --- /dev/null +++ b/apps/web-antd/public/tinymce/langs/zh_CN.js @@ -0,0 +1 @@ +tinymce.addI18n("zh_CN",{"#":"#","Accessibility":"\u8f85\u52a9\u529f\u80fd","Accordion":"\u6298\u53e0\u9762\u677f","Accordion body...":"\u6298\u53e0\u9762\u677f\u6b63\u6587...","Accordion summary...":"\u6298\u53e0\u9762\u677f\u6458\u8981...","Action":"\u52a8\u4f5c","Activity":"\u6d3b\u52a8","Address":"\u5730\u5740","Advanced":"\u9ad8\u7ea7","Align":"\u5bf9\u9f50","Align center":"\u5c45\u4e2d\u5bf9\u9f50","Align left":"\u5de6\u5bf9\u9f50","Align right":"\u53f3\u5bf9\u9f50","Alignment":"\u5bf9\u9f50","Alignment {0}":"\u5bf9\u9f50{0}","All":"\u5168\u90e8","Alternative description":"\u66ff\u4ee3\u63cf\u8ff0","Alternative source":"\u955c\u50cf","Alternative source URL":"\u66ff\u4ee3\u6765\u6e90\u7f51\u5740","Anchor":"\u951a\u70b9","Anchor...":"\u951a\u70b9...","Anchors":"\u951a\u70b9","Animals and Nature":"\u52a8\u7269\u548c\u81ea\u7136","Arrows":"\u7bad\u5934","B":"B","Background color":"\u80cc\u666f\u989c\u8272","Background color {0}":"\u80cc\u666f\u989c\u8272 {0}","Black":"\u9ed1\u8272","Block":"\u5757","Block {0}":"\u6587\u672c\u5757{0}","Blockquote":"Blockquote","Blocks":"\u6837\u5f0f","Blue":"\u84dd\u8272","Blue component":"\u767d\u8272\u90e8\u5206","Body":"\u8868\u4f53","Bold":"\u7c97\u4f53","Border":"\u6846\u7ebf","Border color":"\u6846\u7ebf\u989c\u8272","Border style":"\u8fb9\u6846\u6837\u5f0f","Border width":"\u8fb9\u6846\u5bbd\u5ea6","Bottom":"\u4e0b\u65b9\u5bf9\u9f50","Browse files":"\u6d4f\u89c8\u6587\u4ef6","Browse for an image":"\u6d4f\u89c8\u56fe\u7247","Browse links":"\u6d4f\u89c8\u94fe\u63a5","Bullet list":"\u65e0\u5e8f\u5217\u8868","Cancel":"\u53d6\u6d88","Caption":"\u6807\u9898","Cell":"\u5355\u5143\u683c","Cell padding":"\u5355\u5143\u683c\u5185\u8fb9\u8ddd","Cell properties":"\u5355\u5143\u683c\u5c5e\u6027","Cell spacing":"\u5355\u5143\u683c\u5916\u95f4\u8ddd","Cell styles":"\u5355\u5143\u683c\u6837\u5f0f","Cell type":"\u50a8\u5b58\u683c\u522b","Center":"\u5c45\u4e2d","Characters":"\u5b57\u7b26","Characters (no spaces)":"\u5b57\u7b26(\u65e0\u7a7a\u683c)","Circle":"\u7a7a\u5fc3\u5706","Class":"\u7c7b\u578b","Clear formatting":"\u6e05\u9664\u683c\u5f0f","Close":"\u5173\u95ed","Code":"\u4ee3\u7801","Code sample...":"\u793a\u4f8b\u4ee3\u7801...","Code view":"\u4ee3\u7801\u89c6\u56fe","Color Picker":"\u9009\u8272\u5668","Color swatch":"\u989c\u8272\u6837\u672c","Cols":"\u5217","Column":"\u5217","Column clipboard actions":"\u5217\u526a\u8d34\u677f\u64cd\u4f5c","Column group":"\u5217\u7ec4","Column header":"\u5217\u6807\u9898","Constrain proportions":"\u4fdd\u6301\u6bd4\u4f8b","Copy":"\u590d\u5236","Copy column":"\u590d\u5236\u5217","Copy row":"\u590d\u5236\u884c","Could not find the specified string.":"\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9\u3002","Could not load emojis":"\u65e0\u6cd5\u52a0\u8f7dEmojis","Count":"\u8ba1\u6570","Currency":"\u8d27\u5e01","Current window":"\u5f53\u524d\u7a97\u53e3","Custom color":"\u81ea\u5b9a\u4e49\u989c\u8272","Custom...":"\u81ea\u5b9a\u4e49......","Cut":"\u526a\u5207","Cut column":"\u526a\u5207\u5217","Cut row":"\u526a\u5207\u884c","Dark Blue":"\u6df1\u84dd\u8272","Dark Gray":"\u6df1\u7070\u8272","Dark Green":"\u6df1\u7eff\u8272","Dark Orange":"\u6df1\u6a59\u8272","Dark Purple":"\u6df1\u7d2b\u8272","Dark Red":"\u6df1\u7ea2\u8272","Dark Turquoise":"\u6df1\u84dd\u7eff\u8272","Dark Yellow":"\u6697\u9ec4\u8272","Dashed":"\u865a\u7ebf","Date/time":"\u65e5\u671f/\u65f6\u95f4","Decrease indent":"\u51cf\u5c11\u7f29\u8fdb","Default":"\u9884\u8bbe","Delete accordion":"\u5220\u9664\u6298\u53e0\u9762\u677f","Delete column":"\u5220\u9664\u5217","Delete row":"\u5220\u9664\u884c","Delete table":"\u5220\u9664\u8868\u683c","Dimensions":"\u5c3a\u5bf8","Disc":"\u5b9e\u5fc3\u5706","Div":"Div","Document":"\u6587\u6863","Dotted":"\u865a\u7ebf","Double":"\u53cc\u7cbe\u5ea6","Drop an image here":"\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64","Dropped file type is not supported":"\u6b64\u6587\u4ef6\u7c7b\u578b\u4e0d\u652f\u6301\u62d6\u653e","Edit":"\u7f16\u8f91","Embed":"\u5185\u5d4c","Emojis":"Emojis","Emojis...":"Emojis...","Error":"\u9519\u8bef","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","Extended Latin":"\u62c9\u4e01\u8bed\u6269\u5145","Failed to initialize plugin: {0}":"\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}","Failed to load plugin url: {0}":"\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}","Failed to load plugin: {0} from url {1}":"\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}","Failed to upload image: {0}":"\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}","File":"\u6587\u4ef6","Find":"\u5bfb\u627e","Find (if searchreplace plugin activated)":"\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)","Find and Replace":"\u67e5\u627e\u548c\u66ff\u6362","Find and replace...":"\u67e5\u627e\u5e76\u66ff\u6362...","Find in selection":"\u5728\u9009\u533a\u4e2d\u67e5\u627e","Find whole words only":"\u5168\u5b57\u5339\u914d","Flags":"\u65d7\u5e1c","Focus to contextual toolbar":"\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355","Focus to element path":"\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84","Focus to menubar":"\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f","Focus to toolbar":"\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f","Font":"\u5b57\u4f53","Font size {0}":"\u5b57\u4f53\u5927\u5c0f{0}","Font sizes":"\u5b57\u4f53\u5927\u5c0f","Font {0}":"\u5b57\u4f53{0}","Fonts":"\u5b57\u4f53","Food and Drink":"\u98df\u7269\u548c\u996e\u54c1","Footer":"\u8868\u5c3e","Format":"\u683c\u5f0f","Format {0}":"\u683c\u5f0f{0}","Formats":"\u683c\u5f0f","Fullscreen":"\u5168\u5c4f","G":"G","General":"\u4e00\u822c","Gray":"\u7070\u8272","Green":"\u7eff\u8272","Green component":"\u7eff\u8272\u90e8\u5206","Groove":"\u51f9\u69fd","Handy Shortcuts":"\u5feb\u6377\u952e","Header":"\u8868\u5934","Header cell":"\u8868\u5934\u5355\u5143\u683c","Heading 1":"\u4e00\u7ea7\u6807\u9898","Heading 2":"\u4e8c\u7ea7\u6807\u9898","Heading 3":"\u4e09\u7ea7\u6807\u9898","Heading 4":"\u56db\u7ea7\u6807\u9898","Heading 5":"\u4e94\u7ea7\u6807\u9898","Heading 6":"\u516d\u7ea7\u6807\u9898","Headings":"\u6807\u9898","Height":"\u9ad8\u5ea6","Help":"\u5e2e\u52a9","Hex color code":"\u5341\u516d\u8fdb\u5236\u989c\u8272\u4ee3\u7801","Hidden":"\u9690\u85cf","Horizontal align":"\u6c34\u5e73\u5bf9\u9f50","Horizontal line":"\u6c34\u5e73\u5206\u5272\u7ebf","Horizontal space":"\u6c34\u5e73\u95f4\u8ddd","ID":"ID","ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.":"ID\u5e94\u8be5\u4ee5\u82f1\u6587\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u9762\u53ea\u80fd\u6709\u82f1\u6587\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002","Image is decorative":"\u56fe\u50cf\u662f\u88c5\u9970\u6027\u7684","Image list":"\u56fe\u7247\u6e05\u5355","Image title":"\u56fe\u7247\u6807\u9898","Image...":"\u56fe\u7247...","ImageProxy HTTP error: Could not find Image Proxy":"\u56fe\u7247\u4ee3\u7406\u8bf7\u6c42\u9519\u8bef\uff1a\u65e0\u6cd5\u627e\u5230\u56fe\u7247\u4ee3\u7406","ImageProxy HTTP error: Incorrect Image Proxy URL":"\u56fe\u7247\u4ee3\u7406\u8bf7\u6c42\u9519\u8bef\uff1a\u56fe\u7247\u4ee3\u7406\u5730\u5740\u9519\u8bef","ImageProxy HTTP error: Rejected request":"\u56fe\u7247\u4ee3\u7406\u8bf7\u6c42\u9519\u8bef\uff1a\u8bf7\u6c42\u88ab\u62d2\u7edd","ImageProxy HTTP error: Unknown ImageProxy error":"\u56fe\u7247\u4ee3\u7406\u8bf7\u6c42\u9519\u8bef\uff1a\u672a\u77e5\u7684\u56fe\u7247\u4ee3\u7406\u9519\u8bef","Increase indent":"\u589e\u52a0\u7f29\u8fdb","Inline":"\u6587\u672c","Insert":"\u63d2\u5165","Insert Template":"\u63d2\u5165\u6a21\u677f","Insert accordion":"\u63d2\u5165\u6298\u53e0\u9762\u677f","Insert column after":"\u5728\u53f3\u4fa7\u63d2\u5165\u5217","Insert column before":"\u5728\u5de6\u4fa7\u63d2\u5165\u5217","Insert date/time":"\u63d2\u5165\u65e5\u671f/\u65f6\u95f4","Insert image":"\u63d2\u5165\u56fe\u7247","Insert link (if link plugin activated)":"\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)","Insert row after":"\u5728\u4e0b\u65b9\u63d2\u5165\u884c","Insert row before":"\u5728\u4e0a\u65b9\u63d2\u5165\u884c","Insert table":"\u63d2\u5165\u8868\u683c","Insert template...":"\u63d2\u5165\u6a21\u677f...","Insert video":"\u63d2\u5165\u89c6\u9891","Insert/Edit code sample":"\u63d2\u5165/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b","Insert/edit image":"\u63d2\u5165/\u7f16\u8f91\u56fe\u7247","Insert/edit link":"\u63d2\u5165/\u7f16\u8f91\u94fe\u63a5","Insert/edit media":"\u63d2\u5165/\u7f16\u8f91\u5a92\u4f53","Insert/edit video":"\u63d2\u5165/\u7f16\u8f91\u89c6\u9891","Inset":"\u5d4c\u5165","Invalid hex color code: {0}":"\u5341\u516d\u8fdb\u5236\u989c\u8272\u4ee3\u7801\u65e0\u6548\uff1a {0}","Invalid input":"\u65e0\u6548\u8f93\u5165","Italic":"\u659c\u4f53","Justify":"\u4e24\u7aef\u5bf9\u9f50","Keyboard Navigation":"\u952e\u76d8\u6307\u5f15","Language":"\u8bed\u8a00","Learn more...":"\u4e86\u89e3\u66f4\u591a...","Left":"\u5de6","Left to right":"\u7531\u5de6\u5230\u53f3","Light Blue":"\u6d45\u84dd\u8272","Light Gray":"\u6d45\u7070\u8272","Light Green":"\u6d45\u7eff\u8272","Light Purple":"\u6d45\u7d2b\u8272","Light Red":"\u6d45\u7ea2\u8272","Light Yellow":"\u6d45\u9ec4\u8272","Line height":"Line height","Link list":"\u94fe\u63a5\u6e05\u5355","Link...":"\u94fe\u63a5...","List Properties":"\u5217\u8868\u5c5e\u6027","List properties...":"\u6807\u9898\u5b57\u4f53\u5c5e\u6027","Loading emojis...":"\u6b63\u5728\u52a0\u8f7dEmojis...","Loading...":"\u52a0\u8f7d\u4e2d...","Lower Alpha":"\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd","Lower Greek":"\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd","Lower Roman":"\u5c0f\u5199\u7f57\u9a6c\u6570\u5b57","Match case":"\u5927\u5c0f\u5199\u5339\u914d","Mathematical":"\u6570\u5b66","Media poster (Image URL)":"\u5c01\u9762(\u56fe\u7247\u5730\u5740)","Media...":"\u591a\u5a92\u4f53...","Medium Blue":"\u4e2d\u84dd\u8272","Medium Gray":"\u4e2d\u7070\u8272","Medium Purple":"\u4e2d\u7d2b\u8272","Merge cells":"\u5408\u5e76\u5355\u5143\u683c","Middle":"\u5c45\u4e2d\u5bf9\u9f50","Midnight Blue":"\u6df1\u84dd\u8272","More...":"\u66f4\u591a...","Name":"\u540d\u79f0","Navy Blue":"\u6d77\u519b\u84dd","New document":"\u65b0\u5efa\u6587\u6863","New window":"\u65b0\u7a97\u53e3","Next":"\u4e0b\u4e00\u4e2a","No":"\u5426","No alignment":"\u672a\u5bf9\u9f50","No color":"\u65e0","Nonbreaking space":"\u4e0d\u95f4\u65ad\u7a7a\u683c","None":"\u65e0","Numbered list":"\u6709\u5e8f\u5217\u8868","OR":"\u6216","Objects":"\u7269\u4ef6","Ok":"\u786e\u5b9a","Open help dialog":"\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846","Open link":"\u6253\u5f00\u94fe\u63a5","Open link in...":"\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...","Open popup menu for split buttons":"\u6253\u5f00\u5f39\u51fa\u5f0f\u83dc\u5355\uff0c\u7528\u4e8e\u62c6\u5206\u6309\u94ae","Orange":"\u6a59\u8272","Outset":"\u5916\u7f6e","Page break":"\u5206\u9875\u7b26","Paragraph":"\u6bb5\u843d","Paste":"\u7c98\u8d34","Paste as text":"\u7c98\u8d34\u4e3a\u6587\u672c","Paste column after":"\u7c98\u8d34\u540e\u9762\u7684\u5217","Paste column before":"\u7c98\u8d34\u6b64\u5217\u524d","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","Paste or type a link":"\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5","Paste row after":"\u7c98\u8d34\u884c\u5230\u4e0b\u65b9","Paste row before":"\u7c98\u8d34\u884c\u5230\u4e0a\u65b9","Paste your embed code below:":"\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:","People":"\u4eba\u7c7b","Plugins":"\u63d2\u4ef6","Plugins installed ({0}):":"\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):","Powered by {0}":"\u7531{0}\u9a71\u52a8","Pre":"\u524d\u8a00","Preferences":"\u9996\u9009\u9879","Preformatted":"\u9884\u5148\u683c\u5f0f\u5316\u7684","Premium plugins:":"\u4f18\u79c0\u63d2\u4ef6\uff1a","Press the Up and Down arrow keys to resize the editor.":"\u6309\u4e0a\u4e0b\u7bad\u5934\u952e\u4ee5\u8c03\u6574\u7f16\u8f91\u5668\u5927\u5c0f\u3002","Press the arrow keys to resize the editor.":"\u6309\u7bad\u5934\u952e\u4ee5\u8c03\u6574\u7f16\u8f91\u5668\u5927\u5c0f\u3002","Press {0} for help":"\u6309 {0} \u83b7\u5f97\u5e2e\u52a9","Preview":"\u9884\u89c8","Previous":"\u4e0a\u4e00\u4e2a","Print":"\u6253\u5370","Print...":"\u6253\u5370...","Purple":"\u7d2b\u8272","Quotations":"\u5f15\u7528","R":"R","Range 0 to 255":"\u8303\u56f40\u81f3255","Red":"\u7ea2\u8272","Red component":"\u7ea2\u8272\u90e8\u5206","Redo":"\u91cd\u505a","Remove":"\u79fb\u9664","Remove color":"\u79fb\u9664\u989c\u8272","Remove link":"\u79fb\u9664\u94fe\u63a5","Replace":"\u66ff\u6362","Replace all":"\u66ff\u6362\u5168\u90e8","Replace with":"\u66ff\u6362\u4e3a","Resize":"\u8c03\u6574\u5927\u5c0f","Restore last draft":"\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f","Reveal or hide additional toolbar items":"\u663e\u793a\u6216\u9690\u85cf\u5176\u4ed6\u5de5\u5177\u680f\u9879","Rich Text Area":"\u5bcc\u6587\u672c\u533a\u57df","Rich Text Area. Press ALT-0 for help.":"\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002","Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help":"\u7f16\u8f91\u533a\u3002\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9","Ridge":"\u6d77\u810a\u5ea7","Right":"\u53f3","Right to left":"\u7531\u53f3\u5230\u5de6","Row":"\u884c","Row clipboard actions":"\u884c\u526a\u8d34\u677f\u64cd\u4f5c","Row group":"\u884c\u7ec4","Row header":"\u884c\u5934","Row properties":"\u884c\u5c5e\u6027","Row type":"\u884c\u7c7b\u578b","Rows":"\u884c\u6570","Save":"\u4fdd\u5b58","Save (if save plugin activated)":"\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)","Scope":"\u8303\u56f4","Search":"\u641c\u7d22","Select all":"\u5168\u9009","Select...":"\u9009\u62e9...","Selection":"\u9009\u62e9","Shortcut":"\u5feb\u6377\u65b9\u5f0f","Show blocks":"\u663e\u793a\u533a\u5757\u8fb9\u6846","Show caption":"\u663e\u793a\u6807\u9898","Show invisible characters":"\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26","Size":"\u5b57\u53f7","Solid":"\u5b9e\u7ebf","Source":"\u5730\u5740","Source code":"\u6e90\u4ee3\u7801","Special Character":"\u7279\u6b8a\u5b57\u7b26","Special character...":"\u7279\u6b8a\u5b57\u7b26...","Split cell":"\u62c6\u5206\u5355\u5143\u683c","Square":"\u5b9e\u5fc3\u65b9\u5757","Start list at number":"\u4ee5\u6570\u5b57\u5f00\u59cb\u5217\u8868","Strikethrough":"\u5220\u9664\u7ebf","Style":"\u6837\u5f0f","Subscript":"\u4e0b\u6807","Superscript":"\u4e0a\u6807","Switch to or from fullscreen mode":"\u5207\u6362\u5168\u5c4f\u6a21\u5f0f","Symbols":"\u7b26\u53f7","System Font":"\u7cfb\u7edf\u5b57\u4f53","Table":"\u8868\u683c","Table caption":"\u8868\u683c\u6807\u9898","Table properties":"\u8868\u683c\u5c5e\u6027","Table styles":"\u8868\u683c\u6837\u5f0f","Template":"\u6a21\u677f","Templates":"\u6a21\u677f","Text":"\u6587\u5b57","Text color":"\u5b57\u4f53\u989c\u8272","Text color {0}":"\u5b57\u4f53\u989c\u8272 {0}","Text to display":"\u8981\u663e\u793a\u7684\u6587\u672c","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","The URL you entered seems to be an external link. Do you want to add the required https:// prefix?":"\u60a8\u8f93\u5165\u7684 URL \u4f3c\u4e4e\u662f\u4e00\u4e2a\u5916\u90e8\u94fe\u63a5\u3002\u60a8\u60f3\u6dfb\u52a0\u6240\u9700\u7684 https:// \u524d\u7f00\u5417\uff1f","Title":"\u6807\u9898","To open the popup, press Shift+Enter":"\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846","Toggle accordion":"\u5207\u6362\u6298\u53e0\u9762\u677f","Tools":"\u5de5\u5177","Top":"\u4e0a\u65b9\u5bf9\u9f50","Travel and Places":"\u65c5\u6e38\u548c\u5730\u70b9","Turquoise":"\u9752\u7eff\u8272","Underline":"\u4e0b\u5212\u7ebf","Undo":"\u64a4\u9500","Upload":"\u4e0a\u4f20","Uploading image":"\u4e0a\u4f20\u56fe\u7247","Upper Alpha":"\u5927\u5199\u82f1\u6587\u5b57\u6bcd","Upper Roman":"\u5927\u5199\u7f57\u9a6c\u6570\u5b57","Url":"\u5730\u5740","User Defined":"\u81ea\u5b9a\u4e49","Valid":"\u6709\u6548","Version":"\u7248\u672c","Vertical align":"\u5782\u76f4\u5bf9\u9f50","Vertical space":"\u5782\u76f4\u95f4\u8ddd","View":"\u67e5\u770b","Visual aids":"\u7f51\u683c\u7ebf","Warn":"\u8b66\u544a","White":"\u767d\u8272","Width":"\u5bbd\u5ea6","Word count":"\u5b57\u6570","Words":"\u5355\u8bcd","Words: {0}":"\u5b57\u6570\uff1a{0}","Yellow":"\u9ec4\u8272","Yes":"\u662f","You are using {0}":"\u4f60\u6b63\u5728\u4f7f\u7528 {0}","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","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","alignment":"\u5bf9\u9f50","austral sign":"\u6fb3\u5143\u7b26\u53f7","cedi sign":"\u585e\u5730\u7b26\u53f7","colon sign":"\u5192\u53f7","cruzeiro sign":"\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7","currency sign":"\u8d27\u5e01\u7b26\u53f7","dollar sign":"\u7f8e\u5143\u7b26\u53f7","dong sign":"\u8d8a\u5357\u76fe\u7b26\u53f7","drachma sign":"\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7","euro-currency sign":"\u6b27\u5143\u7b26\u53f7","example":"\u793a\u4f8b","formatting":"\u683c\u5f0f\u5316","french franc sign":"\u6cd5\u90ce\u7b26\u53f7","german penny symbol":"\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7","guarani sign":"\u74dc\u62c9\u5c3c\u7b26\u53f7","history":"\u5386\u53f2","hryvnia sign":"\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7","indentation":"\u7f29\u8fdb","indian rupee sign":"\u5370\u5ea6\u5362\u6bd4","kip sign":"\u8001\u631d\u57fa\u666e\u7b26\u53f7","lira sign":"\u91cc\u62c9\u7b26\u53f7","livre tournois sign":"\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7","manat sign":"\u9a6c\u7eb3\u7279\u7b26\u53f7","mill sign":"\u5bc6\u5c14\u7b26\u53f7","naira sign":"\u5948\u62c9\u7b26\u53f7","new sheqel sign":"\u65b0\u8c22\u514b\u5c14\u7b26\u53f7","nordic mark sign":"\u5317\u6b27\u9a6c\u514b","peseta sign":"\u6bd4\u585e\u5854\u7b26\u53f7","peso sign":"\u6bd4\u7d22\u7b26\u53f7","ruble sign":"\u5362\u5e03\u7b26\u53f7","rupee sign":"\u5362\u6bd4\u7b26\u53f7","spesmilo sign":"spesmilo\u7b26\u53f7","styles":"\u6837\u5f0f","tenge sign":"\u575a\u6208\u7b26\u53f7","tugrik sign":"\u56fe\u683c\u91cc\u514b\u7b26\u53f7","turkish lira sign":"\u571f\u8033\u5176\u91cc\u62c9","won sign":"\u97e9\u5143\u7b26\u53f7","yen character":"\u65e5\u5143\u5b57\u6837","yen/yuan character variant one":"\u5143\u5b57\u6837\uff08\u5927\u5199\uff09","yuan character":"\u4eba\u6c11\u5e01\u5143\u5b57\u6837","yuan character, in hong kong and taiwan":"\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09","{0} characters":"{0} \u4e2a\u5b57\u7b26","{0} columns, {1} rows":"{0} \u5217\uff0c{1} \u884c","{0} words":"{0} \u5b57"}); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/license.md b/apps/web-antd/public/tinymce/license.md new file mode 100644 index 0000000..70454a6 --- /dev/null +++ b/apps/web-antd/public/tinymce/license.md @@ -0,0 +1,6 @@ +# Software License Agreement + +**TinyMCE** – [](https://github.com/tinymce/tinymce) +Copyright (c) 2024, Ephox Corporation DBA Tiny Technologies, Inc. + +Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html). diff --git a/apps/web-antd/public/tinymce/models/dom/model.min.js b/apps/web-antd/public/tinymce/models/dom/model.min.js new file mode 100644 index 0000000..bce8e62 --- /dev/null +++ b/apps/web-antd/public/tinymce/models/dom/model.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.ModelManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(o=n=e,(r=String).prototype.isPrototypeOf(o)||(null===(s=n.constructor)||void 0===s?void 0:s.name)===r.name)?"string":t;var o,n,r,s})(t)===e,o=e=>t=>typeof t===e,n=e=>t=>e===t,r=t("string"),s=t("object"),l=t("array"),a=n(null),c=o("boolean"),i=n(void 0),m=e=>!(e=>null==e)(e),d=o("function"),u=o("number"),f=()=>{},g=e=>()=>e,h=e=>e,p=(e,t)=>e===t;function b(e,...t){return(...o)=>{const n=t.concat(o);return e.apply(null,n)}}const w=e=>t=>!e(t),v=e=>e(),y=g(!1),x=g(!0);class C{constructor(e,t){this.tag=e,this.value=t}static some(e){return new C(!0,e)}static none(){return C.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?C.some(e(this.value)):C.none()}bind(e){return this.tag?e(this.value):C.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:C.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return m(e)?C.some(e):C.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}C.singletonNone=new C(!1);const S=Array.prototype.slice,T=Array.prototype.indexOf,R=Array.prototype.push,D=(e,t)=>{return o=e,n=t,T.call(o,n)>-1;var o,n},O=(e,t)=>{for(let o=0,n=e.length;o{const o=[];for(let n=0;n{const o=e.length,n=new Array(o);for(let r=0;r{for(let o=0,n=e.length;o{const o=[],n=[];for(let r=0,s=e.length;r{const o=[];for(let n=0,r=e.length;n(((e,t)=>{for(let o=e.length-1;o>=0;o--)t(e[o],o)})(e,((e,n)=>{o=t(o,e,n)})),o),A=(e,t,o)=>(N(e,((e,n)=>{o=t(o,e,n)})),o),L=(e,t)=>((e,t,o)=>{for(let n=0,r=e.length;n{for(let o=0,n=e.length;o{const t=[];for(let o=0,n=e.length;oM(E(e,t)),P=(e,t)=>{for(let o=0,n=e.length;o{const o={};for(let n=0,r=e.length;nt>=0&&tF(e,0),$=e=>F(e,e.length-1),V=(e,t)=>{for(let o=0;o{const o=q(e);for(let n=0,r=o.length;nY(e,((e,o)=>({k:o,v:t(e,o)}))),Y=(e,t)=>{const o={};return G(e,((e,n)=>{const r=t(e,n);o[r.k]=r.v})),o},J=(e,t)=>{const o=[];return G(e,((e,n)=>{o.push(t(e,n))})),o},Q=e=>J(e,h),X=(e,t)=>U.call(e,t),Z="undefined"!=typeof window?window:Function("return this;")(),ee=(e,t)=>((e,t)=>{let o=null!=t?t:Z;for(let t=0;t{const t=ee("ownerDocument.defaultView",e);return s(e)&&((e=>((e,t)=>{const o=((e,t)=>ee(e,t))(e,t);if(null==o)throw new Error(e+" not available on this browser");return o})("HTMLElement",e))(t).prototype.isPrototypeOf(e)||/^HTML\w*Element$/.test(te(e).constructor.name))},ne=e=>e.dom.nodeName.toLowerCase(),re=e=>e.dom.nodeType,se=e=>t=>re(t)===e,le=e=>8===re(e)||"#comment"===ne(e),ae=e=>ce(e)&&oe(e.dom),ce=se(1),ie=se(3),me=se(9),de=se(11),ue=e=>t=>ce(t)&&ne(t)===e,fe=(e,t,o)=>{if(!(r(o)||c(o)||u(o)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",o,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,o+"")},ge=(e,t,o)=>{fe(e.dom,t,o)},he=(e,t)=>{const o=e.dom;G(t,((e,t)=>{fe(o,t,e)}))},pe=(e,t)=>{const o=e.dom.getAttribute(t);return null===o?void 0:o},be=(e,t)=>C.from(pe(e,t)),we=(e,t)=>{e.dom.removeAttribute(t)},ve=e=>A(e.dom.attributes,((e,t)=>(e[t.name]=t.value,e)),{}),ye=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},xe={fromHtml:(e,t)=>{const o=(t||document).createElement("div");if(o.innerHTML=e,!o.hasChildNodes()||o.childNodes.length>1){const t="HTML does not have a single root node";throw console.error(t,e),new Error(t)}return ye(o.childNodes[0])},fromTag:(e,t)=>{const o=(t||document).createElement(e);return ye(o)},fromText:(e,t)=>{const o=(t||document).createTextNode(e);return ye(o)},fromDom:ye,fromPoint:(e,t,o)=>C.from(e.dom.elementFromPoint(t,o)).map(ye)},Ce=(e,t)=>{const o=e.dom;if(1!==o.nodeType)return!1;{const e=o;if(void 0!==e.matches)return e.matches(t);if(void 0!==e.msMatchesSelector)return e.msMatchesSelector(t);if(void 0!==e.webkitMatchesSelector)return e.webkitMatchesSelector(t);if(void 0!==e.mozMatchesSelector)return e.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}},Se=e=>1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType||0===e.childElementCount,Te=(e,t)=>{const o=void 0===t?document:t.dom;return Se(o)?C.none():C.from(o.querySelector(e)).map(xe.fromDom)},Re=(e,t)=>e.dom===t.dom,De=(e,t)=>{const o=e.dom,n=t.dom;return o!==n&&o.contains(n)},Oe=Ce,ke=e=>xe.fromDom(e.dom.ownerDocument),Ee=e=>me(e)?e:ke(e),Ne=e=>C.from(e.dom.parentNode).map(xe.fromDom),_e=e=>C.from(e.dom.parentElement).map(xe.fromDom),Be=(e,t)=>{const o=d(t)?t:y;let n=e.dom;const r=[];for(;null!==n.parentNode&&void 0!==n.parentNode;){const e=n.parentNode,t=xe.fromDom(e);if(r.push(t),!0===o(t))break;n=e}return r},ze=e=>C.from(e.dom.previousSibling).map(xe.fromDom),Ae=e=>C.from(e.dom.nextSibling).map(xe.fromDom),Le=e=>E(e.dom.childNodes,xe.fromDom),We=(e,t)=>{const o=e.dom.childNodes;return C.from(o[t]).map(xe.fromDom)},Me=(e,t)=>{Ne(e).each((o=>{o.dom.insertBefore(t.dom,e.dom)}))},je=(e,t)=>{Ae(e).fold((()=>{Ne(e).each((e=>{Ie(e,t)}))}),(e=>{Me(e,t)}))},Pe=(e,t)=>{const o=(e=>We(e,0))(e);o.fold((()=>{Ie(e,t)}),(o=>{e.dom.insertBefore(t.dom,o.dom)}))},Ie=(e,t)=>{e.dom.appendChild(t.dom)},Fe=(e,t)=>{Me(e,t),Ie(t,e)},He=(e,t)=>{N(t,((o,n)=>{const r=0===n?e:t[n-1];je(r,o)}))},$e=(e,t)=>{N(t,(t=>{Ie(e,t)}))},Ve=e=>{e.dom.textContent="",N(Le(e),(e=>{qe(e)}))},qe=e=>{const t=e.dom;null!==t.parentNode&&t.parentNode.removeChild(t)},Ue=e=>{const t=Le(e);t.length>0&&He(e,t),qe(e)},Ge=(e,t)=>xe.fromDom(e.dom.cloneNode(t)),Ke=e=>Ge(e,!1),Ye=e=>Ge(e,!0),Je=(e,t)=>{const o=xe.fromTag(t),n=ve(e);return he(o,n),o},Qe=["tfoot","thead","tbody","colgroup"],Xe=(e,t,o)=>({element:e,rowspan:t,colspan:o}),Ze=(e,t,o)=>({element:e,cells:t,section:o}),et=(e,t,o)=>({element:e,isNew:t,isLocked:o}),tt=(e,t,o,n)=>({element:e,cells:t,section:o,isNew:n}),ot=e=>de(e)&&m(e.dom.host),nt=e=>xe.fromDom(e.dom.getRootNode()),rt=e=>xe.fromDom(e.dom.host),st=e=>{const t=ie(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;const o=t.ownerDocument;return(e=>{const t=nt(e);return ot(t)?C.some(t):C.none()})(xe.fromDom(t)).fold((()=>o.body.contains(t)),(n=st,r=rt,e=>n(r(e))));var n,r},lt=()=>at(xe.fromDom(document)),at=e=>{const t=e.dom.body;if(null==t)throw new Error("Body is not available yet");return xe.fromDom(t)},ct=(e,t)=>{let o=[];return N(Le(e),(e=>{t(e)&&(o=o.concat([e])),o=o.concat(ct(e,t))})),o},it=(e,t,o)=>((e,o,n)=>B(Be(e,n),(e=>Ce(e,t))))(e,0,o),mt=(e,t)=>(e=>B(Le(e),(e=>Ce(e,t))))(e),dt=(e,t)=>((e,t)=>{const o=void 0===t?document:t.dom;return Se(o)?[]:E(o.querySelectorAll(e),xe.fromDom)})(t,e);var ut=(e,t,o,n,r)=>e(o,n)?C.some(o):d(r)&&r(o)?C.none():t(o,n,r);const ft=(e,t,o)=>{let n=e.dom;const r=d(o)?o:y;for(;n.parentNode;){n=n.parentNode;const e=xe.fromDom(n);if(t(e))return C.some(e);if(r(e))break}return C.none()},gt=(e,t,o)=>ut(((e,t)=>t(e)),ft,e,t,o),ht=(e,t,o)=>ft(e,(e=>Ce(e,t)),o),pt=(e,t)=>(e=>L(e.dom.childNodes,(e=>{return o=xe.fromDom(e),Ce(o,t);var o})).map(xe.fromDom))(e),bt=(e,t)=>Te(t,e),wt=(e,t,o)=>ut(((e,t)=>Ce(e,t)),ht,e,t,o),vt=(e,t,o=p)=>e.exists((e=>o(e,t))),yt=e=>{const t=[],o=e=>{t.push(e)};for(let t=0;te?C.some(t):C.none(),Ct=(e,t,o)=>""===t||e.length>=t.length&&e.substr(o,o+t.length)===t,St=(e,t,o=0,n)=>{const r=e.indexOf(t,o);return-1!==r&&(!!i(n)||r+t.length<=n)},Tt=(e,t)=>Ct(e,t,0),Rt=(e,t)=>Ct(e,t,e.length-t.length),Dt=(e=>t=>t.replace(e,""))(/^\s+|\s+$/g),Ot=e=>e.length>0,kt=e=>void 0!==e.style&&d(e.style.getPropertyValue),Et=(e,t,o)=>{if(!r(o))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",o,":: Element ",e),new Error("CSS value must be a string: "+o);kt(e)&&e.style.setProperty(t,o)},Nt=(e,t,o)=>{const n=e.dom;Et(n,t,o)},_t=(e,t)=>{const o=e.dom;G(t,((e,t)=>{Et(o,t,e)}))},Bt=(e,t)=>{const o=e.dom,n=window.getComputedStyle(o).getPropertyValue(t);return""!==n||st(e)?n:zt(o,t)},zt=(e,t)=>kt(e)?e.style.getPropertyValue(t):"",At=(e,t)=>{const o=e.dom,n=zt(o,t);return C.from(n).filter((e=>e.length>0))},Lt=(e,t)=>{((e,t)=>{kt(e)&&e.style.removeProperty(t)})(e.dom,t),vt(be(e,"style").map(Dt),"")&&we(e,"style")},Wt=(e,t,o=0)=>be(e,t).map((e=>parseInt(e,10))).getOr(o),Mt=(e,t)=>Wt(e,t,1),jt=e=>ue("col")(e)?Wt(e,"span",1)>1:Mt(e,"colspan")>1,Pt=(e,t)=>parseInt(Bt(e,t),10),It=g(10),Ft=g(10),Ht=(e,t)=>$t(e,t,x),$t=(e,t,o)=>j(Le(e),(e=>Ce(e,t)?o(e)?[e]:[]:$t(e,t,o))),Vt=(e,t)=>((e,t,o=y)=>o(t)?C.none():D(e,ne(t))?C.some(t):ht(t,e.join(","),(e=>Ce(e,"table")||o(e))))(["td","th"],e,t),qt=e=>Ht(e,"th,td"),Ut=e=>Ce(e,"colgroup")?mt(e,"col"):j(Yt(e),(e=>mt(e,"col"))),Gt=(e,t)=>wt(e,"table",t),Kt=e=>Ht(e,"tr"),Yt=e=>Gt(e).fold(g([]),(e=>mt(e,"colgroup"))),Jt=(e,t)=>E(e,(e=>{if("colgroup"===ne(e)){const t=E(Ut(e),(e=>{const t=Wt(e,"span",1);return Xe(e,1,t)}));return Ze(e,t,"colgroup")}{const o=E(qt(e),(e=>{const t=Wt(e,"rowspan",1),o=Wt(e,"colspan",1);return Xe(e,t,o)}));return Ze(e,o,t(e))}})),Qt=e=>Ne(e).map((e=>{const t=ne(e);return(e=>D(Qe,e))(t)?t:"tbody"})).getOr("tbody"),Xt=e=>{const t=Kt(e),o=[...Yt(e),...t];return Jt(o,Qt)},Zt=e=>{let t,o=!1;return(...n)=>(o||(o=!0,t=e.apply(null,n)),t)},eo=()=>to(0,0),to=(e,t)=>({major:e,minor:t}),oo={nu:to,detect:(e,t)=>{const o=String(t).toLowerCase();return 0===e.length?eo():((e,t)=>{const o=((e,t)=>{for(let o=0;oNumber(t.replace(o,"$"+e));return to(n(1),n(2))})(e,o)},unknown:eo},no=(e,t)=>{const o=String(t).toLowerCase();return L(e,(e=>e.search(o)))},ro=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,so=e=>t=>St(t,e),lo=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:e=>St(e,"edge/")&&St(e,"chrome")&&St(e,"safari")&&St(e,"applewebkit")},{name:"Chromium",brand:"Chromium",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,ro],search:e=>St(e,"chrome")&&!St(e,"chromeframe")},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:e=>St(e,"msie")||St(e,"trident")},{name:"Opera",versionRegexes:[ro,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:so("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:so("firefox")},{name:"Safari",versionRegexes:[ro,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:e=>(St(e,"safari")||St(e,"mobile/"))&&St(e,"applewebkit")}],ao=[{name:"Windows",search:so("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:e=>St(e,"iphone")||St(e,"ipad"),versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:so("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"macOS",search:so("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:so("linux"),versionRegexes:[]},{name:"Solaris",search:so("sunos"),versionRegexes:[]},{name:"FreeBSD",search:so("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:so("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}],co={browsers:g(lo),oses:g(ao)},io="Edge",mo="Chromium",uo="Opera",fo="Firefox",go="Safari",ho=e=>{const t=e.current,o=e.version,n=e=>()=>t===e;return{current:t,version:o,isEdge:n(io),isChromium:n(mo),isIE:n("IE"),isOpera:n(uo),isFirefox:n(fo),isSafari:n(go)}},po=()=>ho({current:void 0,version:oo.unknown()}),bo=ho,wo=(g(io),g(mo),g("IE"),g(uo),g(fo),g(go),"Windows"),vo="Android",yo="Linux",xo="macOS",Co="Solaris",So="FreeBSD",To="ChromeOS",Ro=e=>{const t=e.current,o=e.version,n=e=>()=>t===e;return{current:t,version:o,isWindows:n(wo),isiOS:n("iOS"),isAndroid:n(vo),isMacOS:n(xo),isLinux:n(yo),isSolaris:n(Co),isFreeBSD:n(So),isChromeOS:n(To)}},Do=()=>Ro({current:void 0,version:oo.unknown()}),Oo=Ro,ko=(g(wo),g("iOS"),g(vo),g(yo),g(xo),g(Co),g(So),g(To),e=>window.matchMedia(e).matches);let Eo=Zt((()=>((e,t,o)=>{const n=co.browsers(),r=co.oses(),s=t.bind((e=>((e,t)=>V(t.brands,(t=>{const o=t.brand.toLowerCase();return L(e,(e=>{var t;return o===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())})).map((e=>({current:e.name,version:oo.nu(parseInt(t.version,10),0)})))})))(n,e))).orThunk((()=>((e,t)=>no(e,t).map((e=>{const o=oo.detect(e.versionRegexes,t);return{current:e.name,version:o}})))(n,e))).fold(po,bo),l=((e,t)=>no(e,t).map((e=>{const o=oo.detect(e.versionRegexes,t);return{current:e.name,version:o}})))(r,e).fold(Do,Oo),a=((e,t,o,n)=>{const r=e.isiOS()&&!0===/ipad/i.test(o),s=e.isiOS()&&!r,l=e.isiOS()||e.isAndroid(),a=l||n("(pointer:coarse)"),c=r||!s&&l&&n("(min-device-width:768px)"),i=s||l&&!c,m=t.isSafari()&&e.isiOS()&&!1===/safari/i.test(o),d=!i&&!c&&!m;return{isiPad:g(r),isiPhone:g(s),isTablet:g(c),isPhone:g(i),isTouch:g(a),isAndroid:e.isAndroid,isiOS:e.isiOS,isWebView:g(m),isDesktop:g(d)}})(l,s,e,o);return{browser:s,os:l,deviceType:a}})(window.navigator.userAgent,C.from(window.navigator.userAgentData),ko)));const No=()=>Eo(),_o=(e,t)=>{const o=o=>{const n=t(o);if(n<=0||null===n){const t=Bt(o,e);return parseFloat(t)||0}return n},n=(e,t)=>A(t,((t,o)=>{const n=Bt(e,o),r=void 0===n?0:parseInt(n,10);return isNaN(r)?t:t+r}),0);return{set:(t,o)=>{if(!u(o)&&!o.match(/^[0-9]+$/))throw new Error(e+".set accepts only positive integer values. Value was "+o);const n=t.dom;kt(n)&&(n.style[e]=o+"px")},get:o,getOuter:o,aggregate:n,max:(e,t,o)=>{const r=n(e,o);return t>r?t-r:0}}},Bo=(e,t,o)=>((e,t)=>(e=>{const t=parseFloat(e);return isNaN(t)?C.none():C.some(t)})(e).getOr(t))(Bt(e,t),o),zo=_o("width",(e=>e.dom.offsetWidth)),Ao=e=>zo.get(e),Lo=e=>zo.getOuter(e),Wo=e=>((e,t)=>{const o=e.dom,n=o.getBoundingClientRect().width||o.offsetWidth;return"border-box"===t?n:((e,t,o,n)=>t-Bo(e,`padding-${o}`,0)-Bo(e,`padding-${n}`,0)-Bo(e,`border-${o}-width`,0)-Bo(e,`border-${n}-width`,0))(e,n,"left","right")})(e,"content-box"),Mo=(e,t,o)=>{const n=e.cells,r=n.slice(0,t),s=n.slice(t),l=r.concat(o).concat(s);return Io(e,l)},jo=(e,t,o)=>Mo(e,t,[o]),Po=(e,t,o)=>{e.cells[t]=o},Io=(e,t)=>tt(e.element,t,e.section,e.isNew),Fo=(e,t)=>e.cells[t],Ho=(e,t)=>Fo(e,t).element,$o=e=>e.cells.length,Vo=e=>{const t=_(e,(e=>"colgroup"===e.section));return{rows:t.fail,cols:t.pass}},qo=(e,t,o)=>{const n=E(e.cells,o);return tt(t(e.element),n,e.section,!0)},Uo="data-snooker-locked-cols",Go=e=>be(e,Uo).bind((e=>C.from(e.match(/\d+/g)))).map((e=>I(e,x))),Ko=e=>{const t=A(Vo(e).rows,((e,t)=>(N(t.cells,((t,o)=>{t.isLocked&&(e[o]=!0)})),e)),{}),o=J(t,((e,t)=>parseInt(t,10)));return(e=>{const t=S.call(e,0);return t.sort(void 0),t})(o)},Yo=(e,t)=>e+","+t,Jo=(e,t)=>{const o=j(e.all,(e=>e.cells));return B(o,t)},Qo=e=>{const t={},o=[],n=H(e).map((e=>e.element)).bind(Gt).bind(Go).getOr({});let r=0,s=0,l=0;const{pass:a,fail:c}=_(e,(e=>"colgroup"===e.section));N(c,(e=>{const a=[];N(e.cells,(e=>{let o=0;for(;void 0!==t[Yo(l,o)];)o++;const r=((e,t)=>X(e,t)&&void 0!==e[t]&&null!==e[t])(n,o.toString()),c=((e,t,o,n,r,s)=>({element:e,rowspan:t,colspan:o,row:n,column:r,isLocked:s}))(e.element,e.rowspan,e.colspan,l,o,r);for(let n=0;n{const t=(e=>{const t={};let o=0;return N(e.cells,(e=>{const n=e.colspan;k(n,(r=>{const s=o+r;t[s]=((e,t,o)=>({element:e,colspan:t,column:o}))(e.element,n,s)})),o+=n})),t})(e),o=((e,t)=>({element:e,columns:t}))(e.element,Q(t));return{colgroups:[o],columns:t}})).getOrThunk((()=>({colgroups:[],columns:{}}))),d=((e,t)=>({rows:e,columns:t}))(r,s);return{grid:d,access:t,all:o,columns:i,colgroups:m}},Xo=e=>{const t=Xt(e);return Qo(t)},Zo=Qo,en=(e,t,o)=>C.from(e.access[Yo(t,o)]),tn=(e,t,o)=>{const n=Jo(e,(e=>o(t,e.element)));return n.length>0?C.some(n[0]):C.none()},on=Jo,nn=e=>j(e.all,(e=>e.cells)),rn=e=>Q(e.columns),sn=e=>q(e.columns).length>0,ln=(e,t)=>C.from(e.columns[t]),an=(e,t=x)=>{const o=e.grid,n=k(o.columns,h),r=k(o.rows,h);return E(n,(o=>cn((()=>j(r,(t=>en(e,t,o).filter((e=>e.column===o)).toArray()))),(e=>1===e.colspan&&t(e.element)),(()=>en(e,0,o)))))},cn=(e,t,o)=>{const n=e();return L(n,t).orThunk((()=>C.from(n[0]).orThunk(o))).map((e=>e.element))},mn=e=>{const t=e.grid,o=k(t.rows,h),n=k(t.columns,h);return E(o,(t=>cn((()=>j(n,(o=>en(e,t,o).filter((e=>e.row===t)).fold(g([]),(e=>[e]))))),(e=>1===e.rowspan),(()=>en(e,t,0)))))},dn=(e,t)=>o=>"rtl"===un(o)?t:e,un=e=>"rtl"===Bt(e,"direction")?"rtl":"ltr",fn=_o("height",(e=>{const t=e.dom;return st(e)?t.getBoundingClientRect().height:t.offsetHeight})),gn=e=>fn.get(e),hn=e=>fn.getOuter(e),pn=(e,t)=>({left:e,top:t,translate:(o,n)=>pn(e+o,t+n)}),bn=pn,wn=(e,t)=>void 0!==e?e:void 0!==t?t:0,vn=e=>{const t=e.dom.ownerDocument,o=t.body,n=t.defaultView,r=t.documentElement;if(o===e.dom)return bn(o.offsetLeft,o.offsetTop);const s=wn(null==n?void 0:n.pageYOffset,r.scrollTop),l=wn(null==n?void 0:n.pageXOffset,r.scrollLeft),a=wn(r.clientTop,o.clientTop),c=wn(r.clientLeft,o.clientLeft);return yn(e).translate(l-c,s-a)},yn=e=>{const t=e.dom,o=t.ownerDocument.body;return o===t?bn(o.offsetLeft,o.offsetTop):st(e)?(e=>{const t=e.getBoundingClientRect();return bn(t.left,t.top)})(t):bn(0,0)},xn=(e,t)=>({row:e,y:t}),Cn=(e,t)=>({col:e,x:t}),Sn=e=>vn(e).left+Lo(e),Tn=e=>vn(e).left,Rn=(e,t)=>Cn(e,Tn(t)),Dn=(e,t)=>Cn(e,Sn(t)),On=e=>vn(e).top,kn=(e,t)=>xn(e,On(t)),En=(e,t)=>xn(e,On(t)+hn(t)),Nn=(e,t,o)=>{if(0===o.length)return[];const n=E(o.slice(1),((t,o)=>t.map((t=>e(o,t))))),r=o[o.length-1].map((e=>t(o.length-1,e)));return n.concat([r])},_n={delta:h,positions:e=>Nn(kn,En,e),edge:On},Bn=dn({delta:h,edge:Tn,positions:e=>Nn(Rn,Dn,e)},{delta:e=>-e,edge:Sn,positions:e=>Nn(Dn,Rn,e)}),zn={delta:(e,t)=>Bn(t).delta(e,t),positions:(e,t)=>Bn(t).positions(e,t),edge:e=>Bn(e).edge(e)},An={unsupportedLength:["em","ex","cap","ch","ic","rem","lh","rlh","vw","vh","vi","vb","vmin","vmax","cm","mm","Q","in","pc","pt","px"],fixed:["px","pt"],relative:["%"],empty:[""]},Ln=(()=>{const e="[0-9]+",t="[eE][+-]?"+e,o=e=>`(?:${e})?`,n=["Infinity",e+"\\."+o(e)+o(t),"\\."+e+o(t),e+o(t)].join("|");return new RegExp(`^([+-]?(?:${n}))(.*)$`)})(),Wn=/(\d+(\.\d+)?)%/,Mn=/(\d+(\.\d+)?)px|em/,jn=ue("col"),Pn=ue("tr"),In=(e,t,o)=>{const n=_e(e).getOrThunk((()=>at(ke(e))));return t(e)/o(n)*100},Fn=(e,t)=>{Nt(e,"width",t+"px")},Hn=(e,t)=>{Nt(e,"width",t+"%")},$n=(e,t)=>{Nt(e,"height",t+"px")},Vn=e=>{const t=(e=>{return Bo(t=e,"height",t.dom.offsetHeight)+"px";var t})(e);return t?((e,t,o,n)=>{const r=parseFloat(e);return Rt(e,"%")&&"table"!==ne(t)?((e,t,o,n)=>{const r=Gt(e).map((e=>{const n=o(e);return Math.floor(t/100*n)})).getOr(t);return n(e,r),r})(t,r,o,n):r})(t,e,gn,$n):gn(e)},qn=(e,t)=>At(e,t).orThunk((()=>be(e,t).map((e=>e+"px")))),Un=e=>qn(e,"width"),Gn=e=>In(e,Ao,Wo),Kn=e=>{return jn(e)?Ao(e):Bo(t=e,"width",t.dom.offsetWidth);var t},Yn=e=>Pn(e)?gn(e):((e,t,o)=>o(e)/Mt(e,"rowspan"))(e,0,Vn),Jn=(e,t,o)=>{Nt(e,"width",t+o)},Qn=e=>In(e,Ao,Wo)+"%",Xn=g(Wn),Zn=ue("col"),er=e=>Un(e).getOrThunk((()=>Kn(e)+"px")),tr=e=>{return(t=e,qn(t,"height")).getOrThunk((()=>Yn(e)+"px"));var t},or=(e,t,o,n,r,s)=>e.filter(n).fold((()=>s(((e,t)=>{if(t<0||t>=e.length-1)return C.none();const o=e[t].fold((()=>{const o=(e=>{const t=S.call(e,0);return t.reverse(),t})(e.slice(0,t));return V(o,((e,t)=>e.map((e=>({value:e,delta:t+1})))))}),(e=>C.some({value:e,delta:0}))),n=e[t+1].fold((()=>{const o=e.slice(t+1);return V(o,((e,t)=>e.map((e=>({value:e,delta:t+1})))))}),(e=>C.some({value:e,delta:1})));return o.bind((e=>n.map((t=>{const o=t.delta+e.delta;return Math.abs(t.value-e.value)/o}))))})(o,t))),(e=>r(e))),nr=(e,t,o,n)=>{const r=an(e),s=sn(e)?(e=>E(rn(e),(e=>C.from(e.element))))(e):r,l=[C.some(zn.edge(t))].concat(E(zn.positions(r,t),(e=>e.map((e=>e.x))))),a=w(jt);return E(s,((e,t)=>or(e,t,l,a,(e=>{if((e=>{const t=No().browser,o=t.isChromium()||t.isFirefox();return!Zn(e)||o})(e))return o(e);{const e=null!=(s=r[t])?h(s):C.none();return or(e,t,l,a,(e=>n(C.some(Ao(e)))),n)}var s}),n)))},rr=e=>e.map((e=>e+"px")).getOr(""),sr=(e,t,o)=>nr(e,t,Kn,(e=>e.getOrThunk(o.minCellWidth))),lr=(e,t,o,n)=>{const r=mn(e),s=E(e.all,(e=>C.some(e.element))),l=[C.some(_n.edge(t))].concat(E(_n.positions(r,t),(e=>e.map((e=>e.y)))));return E(s,((e,t)=>or(e,t,l,x,o,n)))},ar=(e,t)=>()=>st(e)?t(e):parseFloat(At(e,"width").getOr("0")),cr=e=>{const t=ar(e,(e=>parseFloat(Qn(e)))),o=ar(e,Ao);return{width:t,pixelWidth:o,getWidths:(t,o)=>((e,t,o)=>nr(e,t,Gn,(e=>e.fold((()=>o.minCellWidth()),(e=>e/o.pixelWidth()*100)))))(t,e,o),getCellDelta:e=>e/o()*100,singleColumnWidth:(e,t)=>[100-e],minCellWidth:()=>It()/o()*100,setElementWidth:Hn,adjustTableWidth:o=>{const n=t();Hn(e,n+o/100*n)},isRelative:!0,label:"percent"}},ir=e=>{const t=ar(e,Ao);return{width:t,pixelWidth:t,getWidths:(t,o)=>sr(t,e,o),getCellDelta:h,singleColumnWidth:(e,t)=>[Math.max(It(),e+t)-e],minCellWidth:It,setElementWidth:Fn,adjustTableWidth:o=>{const n=t()+o;Fn(e,n)},isRelative:!1,label:"pixel"}},mr=e=>Un(e).fold((()=>(e=>{const t=ar(e,Ao),o=g(0);return{width:t,pixelWidth:t,getWidths:(t,o)=>sr(t,e,o),getCellDelta:o,singleColumnWidth:g([0]),minCellWidth:o,setElementWidth:f,adjustTableWidth:f,isRelative:!0,label:"none"}})(e)),(t=>((e,t)=>null!==Xn().exec(t)?cr(e):ir(e))(e,t))),dr=ir,ur=cr,fr=(e,t,o)=>{const n=e[o].element,r=xe.fromTag("td");Ie(r,xe.fromTag("br")),(t?Ie:Pe)(n,r)},gr=(e=>{const t=t=>e(t)?C.from(t.dom.nodeValue):C.none();return{get:o=>{if(!e(o))throw new Error("Can only get text value of a text node");return t(o).getOr("")},getOption:t,set:(t,o)=>{if(!e(t))throw new Error("Can only set raw text value of a text node");t.dom.nodeValue=o}}})(ie),hr=e=>gr.get(e),pr=e=>gr.getOption(e),br=(e,t)=>gr.set(e,t),wr=e=>"img"===ne(e)?1:pr(e).fold((()=>Le(e).length),(e=>e.length)),vr=["img","br"],yr=e=>pr(e).filter((e=>0!==e.trim().length||e.indexOf("\xa0")>-1)).isSome()||D(vr,ne(e))||(e=>ae(e)&&"false"===pe(e,"contenteditable"))(e),xr=e=>((e,t)=>{const o=e=>{for(let n=0;nSr(e,yr),Sr=(e,t)=>{const o=e=>{const n=Le(e);for(let e=n.length-1;e>=0;e--){const r=n[e];if(t(r))return C.some(r);const s=o(r);if(s.isSome())return s}return C.none()};return o(e)},Tr={scope:["row","col"]},Rr=e=>()=>{const t=xe.fromTag("td",e.dom);return Ie(t,xe.fromTag("br",e.dom)),t},Dr=e=>()=>xe.fromTag("col",e.dom),Or=e=>()=>xe.fromTag("colgroup",e.dom),kr=e=>()=>xe.fromTag("tr",e.dom),Er=(e,t,o)=>{const n=((e,t)=>{const o=Je(e,t),n=Le(Ye(e));return $e(o,n),o})(e,t);return G(o,((e,t)=>{null===e?we(n,t):ge(n,t,e)})),n},Nr=e=>e,_r=(e,t,o)=>{const n=(e,t)=>{((e,t)=>{const o=e.dom,n=t.dom;kt(o)&&kt(n)&&(n.style.cssText=o.style.cssText)})(e.element,t),Lt(t,"height"),1!==e.colspan&&Lt(t,"width")};return{col:o=>{const r=xe.fromTag(ne(o.element),t.dom);return n(o,r),e(o.element,r),r},colgroup:Or(t),row:kr(t),cell:r=>{const s=xe.fromTag(ne(r.element),t.dom),l=o.getOr(["strong","em","b","i","span","font","h1","h2","h3","h4","h5","h6","p","div"]),a=l.length>0?((e,t,o)=>xr(e).map((n=>{const r=o.join(","),s=it(n,r,(t=>Re(t,e)));return z(s,((e,t)=>{const o=Ke(t);return Ie(e,o),o}),t)})).getOr(t))(r.element,s,l):s;return Ie(a,xe.fromTag("br")),n(r,s),((e,t)=>{G(Tr,((o,n)=>be(e,n).filter((e=>D(o,e))).each((e=>ge(t,n,e)))))})(r.element,s),e(r.element,s),s},replace:Er,colGap:Dr(t),gap:Rr(t)}},Br=e=>({col:Dr(e),colgroup:Or(e),row:kr(e),cell:Rr(e),replace:Nr,colGap:Dr(e),gap:Rr(e)}),zr=e=>t=>t.options.get(e),Ar="100%",Lr=e=>{var t;const o=e.dom,n=null!==(t=o.getParent(e.selection.getStart(),o.isBlock))&&void 0!==t?t:e.getBody();return Wo(xe.fromDom(n))+"px"},Wr=e=>C.from(e.options.get("table_clone_elements")),Mr=zr("table_header_type"),jr=zr("table_column_resizing"),Pr=e=>"preservetable"===jr(e),Ir=e=>"resizetable"===jr(e),Fr=zr("table_sizing_mode"),Hr=e=>"relative"===Fr(e),$r=e=>"fixed"===Fr(e),Vr=e=>"responsive"===Fr(e),qr=zr("table_resize_bars"),Ur=zr("table_style_by_css"),Gr=zr("table_merge_content_on_paste"),Kr=e=>{const t=e.options,o=t.get("table_default_attributes");return t.isSet("table_default_attributes")?o:((e,t)=>Vr(e)||Ur(e)?t:$r(e)?{...t,width:Lr(e)}:{...t,width:Ar})(e,o)},Yr=zr("table_use_colgroups"),Jr=zr("fixed_toolbar_container"),Qr=zr("fixed_toolbar_container_target"),Xr=zr("ui_mode"),Zr=e=>wt(e,"[contenteditable]"),es=(e,t=!1)=>st(e)?e.dom.isContentEditable:Zr(e).fold(g(t),(e=>"true"===ts(e))),ts=e=>e.dom.contentEditable,os=e=>xe.fromDom(e.getBody()),ns=e=>t=>Re(t,os(e)),rs=e=>{we(e,"data-mce-style");const t=e=>we(e,"data-mce-style");N(qt(e),t),N(Ut(e),t),N(Kt(e),t)},ss=e=>xe.fromDom(e.selection.getStart()),ls=e=>e.getBoundingClientRect().width,as=e=>e.getBoundingClientRect().height,cs=e=>(t,o)=>{const n=t.dom.getStyle(o,e)||t.dom.getAttrib(o,e);return C.from(n).filter(Ot)},is=cs("width"),ms=cs("height"),ds=e=>gt(e,ue("table")).exists(es),us=(e,t)=>{const o=t.column,n=t.column+t.colspan-1,r=t.row,s=t.row+t.rowspan-1;return o<=e.finishCol&&n>=e.startCol&&r<=e.finishRow&&s>=e.startRow},fs=(e,t)=>t.column>=e.startCol&&t.column+t.colspan-1<=e.finishCol&&t.row>=e.startRow&&t.row+t.rowspan-1<=e.finishRow,gs=(e,t,o)=>{const n=tn(e,t,Re),r=tn(e,o,Re);return n.bind((e=>r.map((t=>{return o=e,n=t,{startRow:Math.min(o.row,n.row),startCol:Math.min(o.column,n.column),finishRow:Math.max(o.row+o.rowspan-1,n.row+n.rowspan-1),finishCol:Math.max(o.column+o.colspan-1,n.column+n.colspan-1)};var o,n}))))},hs=(e,t,o)=>gs(e,t,o).map((t=>{const o=on(e,b(us,t));return E(o,(e=>e.element))})),ps=(e,t)=>tn(e,t,((e,t)=>De(t,e))).map((e=>e.element)),bs=(e,t,o)=>{const n=vs(e);return hs(n,t,o)},ws=(e,t,o,n,r)=>{const s=vs(e),l=Re(e,o)?C.some(t):ps(s,t),a=Re(e,r)?C.some(n):ps(s,n);return l.bind((e=>a.bind((t=>hs(s,e,t)))))},vs=Xo;var ys=["body","p","div","article","aside","figcaption","figure","footer","header","nav","section","ol","ul","li","table","thead","tbody","tfoot","caption","tr","td","th","h1","h2","h3","h4","h5","h6","blockquote","pre","address"],xs=()=>({up:g({selector:ht,closest:wt,predicate:ft,all:Be}),down:g({selector:dt,predicate:ct}),styles:g({get:Bt,getRaw:At,set:Nt,remove:Lt}),attrs:g({get:pe,set:ge,remove:we,copyTo:(e,t)=>{const o=ve(e);he(t,o)}}),insert:g({before:Me,after:je,afterAll:He,append:Ie,appendAll:$e,prepend:Pe,wrap:Fe}),remove:g({unwrap:Ue,remove:qe}),create:g({nu:xe.fromTag,clone:e=>xe.fromDom(e.dom.cloneNode(!1)),text:xe.fromText}),query:g({comparePosition:(e,t)=>e.dom.compareDocumentPosition(t.dom),prevSibling:ze,nextSibling:Ae}),property:g({children:Le,name:ne,parent:Ne,document:e=>Ee(e).dom,isText:ie,isComment:le,isElement:ce,isSpecial:e=>{const t=ne(e);return D(["script","noscript","iframe","noframes","noembed","title","style","textarea","xmp"],t)},getLanguage:e=>ce(e)?be(e,"lang"):C.none(),getText:hr,setText:br,isBoundary:e=>!!ce(e)&&("body"===ne(e)||D(ys,ne(e))),isEmptyTag:e=>!!ce(e)&&D(["br","img","hr","input"],ne(e)),isNonEditable:e=>ce(e)&&"false"===pe(e,"contenteditable")}),eq:Re,is:Oe});const Cs=(e,t,o,n)=>{const r=t(e,o);return z(n,((o,n)=>{const r=t(e,n);return Ss(e,o,r)}),r)},Ss=(e,t,o)=>t.bind((t=>o.filter(b(e.eq,t)))),Ts=xs(),Rs=(e,t)=>((e,t,o)=>o.length>0?((e,t,o,n)=>n(e,t,o[0],o.slice(1)))(e,t,o,Cs):C.none())(Ts,((t,o)=>e(o)),t),Ds=e=>ht(e,"table"),Os=(e,t,o)=>{const n=e=>t=>void 0!==o&&o(t)||Re(t,e);return Re(e,t)?C.some({boxes:C.some([e]),start:e,finish:t}):Ds(e).bind((r=>Ds(t).bind((s=>{if(Re(r,s))return C.some({boxes:bs(r,e,t),start:e,finish:t});if(De(r,s)){const o=it(t,"td,th",n(r)),l=o.length>0?o[o.length-1]:t;return C.some({boxes:ws(r,e,r,t,s),start:e,finish:l})}if(De(s,r)){const o=it(e,"td,th",n(s)),l=o.length>0?o[o.length-1]:e;return C.some({boxes:ws(s,e,r,t,s),start:e,finish:l})}return((e,t)=>((e,t,o,n=y)=>{const r=[t].concat(e.up().all(t)),s=[o].concat(e.up().all(o)),l=e=>W(e,n).fold((()=>e),(t=>e.slice(0,t+1))),a=l(r),c=l(s),i=L(a,(t=>O(c,((e,t)=>b(e.eq,t))(e,t))));return{firstpath:a,secondpath:c,shared:i}})(Ts,e,t,void 0))(e,t).shared.bind((l=>wt(l,"table",o).bind((o=>{const l=it(t,"td,th",n(o)),a=l.length>0?l[l.length-1]:t,c=it(e,"td,th",n(o)),i=c.length>0?c[c.length-1]:e;return C.some({boxes:ws(o,e,r,t,s),start:i,finish:a})}))))}))))},ks=(e,t)=>{const o=dt(e,t);return o.length>0?C.some(o):C.none()},Es=(e,t,o)=>bt(e,t).bind((t=>bt(e,o).bind((e=>Rs(Ds,[t,e]).map((o=>({first:t,last:e,table:o}))))))),Ns=(e,t,o,n,r)=>((e,t)=>L(e,(e=>Ce(e,t))))(e,r).bind((e=>((e,t,o)=>Gt(e).bind((n=>((e,t,o,n)=>tn(e,t,Re).bind((t=>{const r=o>0?t.row+t.rowspan-1:t.row,s=n>0?t.column+t.colspan-1:t.column;return en(e,r+o,s+n).map((e=>e.element))})))(vs(n),e,t,o))))(e,t,o).bind((e=>((e,t)=>ht(e,"table").bind((o=>bt(o,t).bind((t=>Os(t,e).bind((e=>e.boxes.map((t=>({boxes:t,start:e.start,finish:e.finish}))))))))))(e,n))))),_s=(e,t)=>ks(e,t),Bs=(e,t,o)=>Es(e,t,o).bind((t=>{const o=t=>Re(e,t),n="thead,tfoot,tbody,table",r=ht(t.first,n,o),s=ht(t.last,n,o);return r.bind((e=>s.bind((o=>Re(e,o)?((e,t,o)=>((e,t,o)=>gs(e,t,o).bind((t=>((e,t)=>{let o=!0;const n=b(fs,t);for(let r=t.startRow;r<=t.finishRow;r++)for(let s=t.startCol;s<=t.finishCol;s++)o=o&&en(e,r,s).exists(n);return o?C.some(t):C.none()})(e,t))))(vs(e),t,o))(t.table,t.first,t.last):C.none()))))})),zs=h,As=e=>{const t=(e,t)=>be(e,t).exists((e=>parseInt(e,10)>1));return e.length>0&&P(e,(e=>t(e,"rowspan")||t(e,"colspan")))?C.some(e):C.none()},Ls=(e,t,o)=>t.length<=1?C.none():Bs(e,o.firstSelectedSelector,o.lastSelectedSelector).map((e=>({bounds:e,cells:t}))),Ws="data-mce-selected",Ms="data-mce-first-selected",js="data-mce-last-selected",Ps="["+Ws+"]",Is={selected:Ws,selectedSelector:"td["+Ws+"],th["+Ws+"]",firstSelected:Ms,firstSelectedSelector:"td["+Ms+"],th["+Ms+"]",lastSelected:js,lastSelectedSelector:"td["+js+"],th["+js+"]"},Fs=(e,t,o)=>({element:o,mergable:Ls(t,e,Is),unmergable:As(e),selection:zs(e)}),Hs=e=>(t,o)=>{const n=ne(t),r="col"===n||"colgroup"===n?Gt(s=t).bind((e=>_s(e,Is.firstSelectedSelector))).fold(g(s),(e=>e[0])):t;var s;return wt(r,e,o)},$s=Hs("th,td,caption"),Vs=Hs("th,td"),qs=e=>{return t=e.model.table.getSelectedCells(),E(t,xe.fromDom);var t},Us=(e,t)=>{e.on("BeforeGetContent",(t=>{const o=o=>{t.preventDefault(),(e=>Gt(e[0]).map((e=>{const t=((e,t)=>{const o=e=>Ce(e.element,t),n=Ye(e),r=Xt(n),s=mr(e),l=Zo(r),a=((e,t)=>{const o=e.grid.columns;let n=e.grid.rows,r=o,s=0,l=0;const a=[],c=[];return G(e.access,(e=>{if(a.push(e),t(e)){c.push(e);const t=e.row,o=t+e.rowspan-1,a=e.column,i=a+e.colspan-1;ts&&(s=o),al&&(l=i)}})),((e,t,o,n,r,s)=>({minRow:e,minCol:t,maxRow:o,maxCol:n,allCells:r,selectedCells:s}))(n,r,s,l,a,c)})(l,o),c="th:not("+t+"),td:not("+t+")",i=$t(n,"th,td",(e=>Ce(e,c)));N(i,qe),((e,t,o,n)=>{const r=B(e,(e=>"colgroup"!==e.section)),s=t.grid.columns,l=t.grid.rows;for(let e=0;eo.maxRow||ao.maxCol||(en(t,e,a).filter(n).isNone()?fr(r,l,e):l=!0)}})(r,l,a,o);const m=((e,t,o,n)=>{if(0===n.minCol&&t.grid.columns===n.maxCol+1)return 0;const r=sr(t,e,o),s=A(r,((e,t)=>e+t),0),l=A(r.slice(n.minCol,n.maxCol+1),((e,t)=>e+t),0),a=l/s*o.pixelWidth()-o.pixelWidth();return o.getCellDelta(a)})(e,Xo(e),s,a);return((e,t,o,n)=>{G(o.columns,(e=>{(e.columnt.maxCol)&&qe(e.element)}));const r=B(Ht(e,"tr"),(e=>0===e.dom.childElementCount));N(r,qe),t.minCol!==t.maxCol&&t.minRow!==t.maxRow||N(Ht(e,"th,td"),(e=>{we(e,"rowspan"),we(e,"colspan")})),we(e,Uo),we(e,"data-snooker-col-series"),mr(e).adjustTableWidth(n)})(n,a,l,m),n})(e,Ps);return rs(t),[t]})))(o).each((o=>{const n="text"===t.format?((e,t)=>{const o=e.getDoc(),n=nt(xe.fromDom(e.getBody())),r=xe.fromTag("div",o);ge(r,"data-mce-bogus","all"),_t(r,{position:"fixed",left:"-9999999px",top:"0",overflow:"hidden",opacity:"0"});const s=(e=>ot(e)?e:xe.fromDom(Ee(e).dom.body))(n);$e(r,t),Ie(s,r);const l=r.dom.innerText;return qe(r),l})(e,o):((e,t)=>E(t,(t=>e.selection.serializer.serialize(t.dom,{}))).join(""))(e,o);t.content=n}))};if(!0===t.selection){const t=(e=>B(qs(e),(e=>Ce(e,Is.selectedSelector))))(e);t.length>=1&&o(t)}})),e.on("BeforeSetContent",(o=>{if(!0===o.selection&&!0===o.paste){const n=qs(e);H(n).each((n=>{Gt(n).each((r=>{const s=B((e=>{const t=document.createElement("div");return t.innerHTML=e,Le(xe.fromDom(t))})(o.content),(e=>"meta"!==ne(e))),l=ue("table");if(Gr(e)&&1===s.length&&l(s[0])){o.preventDefault();const l=xe.fromDom(e.getDoc()),a=Br(l),c=((e,t,o)=>({element:e,clipboard:t,generators:o}))(n,s[0],a);t.pasteCells(r,c).each((()=>{e.focus()}))}}))}))}}))},Gs=(e,t)=>({element:e,offset:t}),Ks=(e,t,o)=>e.property().isText(t)&&0===e.property().getText(t).trim().length||e.property().isComment(t)?o(t).bind((t=>Ks(e,t,o).orThunk((()=>C.some(t))))):C.none(),Ys=(e,t)=>e.property().isText(t)?e.property().getText(t).length:e.property().children(t).length,Js=(e,t)=>{const o=Ks(e,t,e.query().prevSibling).getOr(t);if(e.property().isText(o))return Gs(o,Ys(e,o));const n=e.property().children(o);return n.length>0?Js(e,n[n.length-1]):Gs(o,Ys(e,o))},Qs=Js,Xs=xs(),Zs=(e,t)=>{if(!jt(e)){const o=(e=>Un(e).bind((e=>{return t=e,o=["fixed","relative","empty"],C.from(Ln.exec(t)).bind((e=>{const t=Number(e[1]),n=e[2];return((e,t)=>O(t,(t=>O(An[t],(t=>e===t)))))(n,o)?C.some({value:t,unit:n}):C.none()}));var t,o})))(e);o.each((o=>{const n=o.value/2;Jn(e,n,o.unit),Jn(t,n,o.unit)}))}},el=e=>E(e,g(0)),tl=(e,t,o,n,r)=>r(e.slice(0,t)).concat(n).concat(r(e.slice(o))),ol=e=>(t,o,n,r)=>{if(e(n)){const e=Math.max(r,t[o]-Math.abs(n)),s=Math.abs(e-t[o]);return n>=0?s:-s}return n},nl=ol((e=>e<0)),rl=ol(x),sl=()=>{const e=(e,t,o,n)=>{const r=(100+o)/100,s=Math.max(n,(e[t]+o)/r);return E(e,((e,o)=>(o===t?s:e/r)-e))},t=(t,o,n,r,s,l)=>l?e(t,o,r,s):((e,t,o,n,r)=>{const s=nl(e,t,n,r);return tl(e,t,o+1,[s,0],el)})(t,o,n,r,s);return{resizeTable:(e,t)=>e(t),clampTableDelta:nl,calcLeftEdgeDeltas:t,calcMiddleDeltas:(e,o,n,r,s,l,a)=>t(e,n,r,s,l,a),calcRightEdgeDeltas:(t,o,n,r,s,l)=>{if(l)return e(t,n,r,s);{const e=nl(t,n,r,s);return el(t.slice(0,n)).concat([e])}},calcRedestributedWidths:(e,t,o,n)=>{if(n){const n=(t+o)/t,r=E(e,(e=>e/n));return{delta:100*n-100,newSizes:r}}return{delta:o,newSizes:e}}}},ll=()=>{const e=(e,t,o,n,r)=>{const s=rl(e,n>=0?o:t,n,r);return tl(e,t,o+1,[s,-s],el)};return{resizeTable:(e,t,o)=>{o&&e(t)},clampTableDelta:(e,t,o,n,r)=>{if(r){if(o>=0)return o;{const t=A(e,((e,t)=>e+t-n),0);return Math.max(-t,o)}}return nl(e,t,o,n)},calcLeftEdgeDeltas:e,calcMiddleDeltas:(t,o,n,r,s,l)=>e(t,n,r,s,l),calcRightEdgeDeltas:(e,t,o,n,r,s)=>{if(s)return el(e);{const t=n/e.length;return E(e,g(t))}},calcRedestributedWidths:(e,t,o,n)=>({delta:0,newSizes:e})}},al=e=>Xo(e).grid,cl=ue("th"),il=e=>P(e,(e=>cl(e.element))),ml=(e,t)=>e&&t?"sectionCells":e?"section":"cells",dl=e=>{const t="thead"===e.section,o=vt(ul(e.cells),"th");return"tfoot"===e.section?{type:"footer"}:t||o?{type:"header",subType:ml(t,o)}:{type:"body"}},ul=e=>{const t=B(e,(e=>cl(e.element)));return 0===t.length?C.some("td"):t.length===e.length?C.some("th"):C.none()},fl=(e,t,o)=>et(o(e.element,t),!0,e.isLocked),gl=(e,t)=>e.section!==t?tt(e.element,e.cells,t,e.isNew):e,hl=()=>({transformRow:gl,transformCell:(e,t,o)=>{const n=o(e.element,t),r="td"!==ne(n)?(e=>{const t=Je(e,"td");je(e,t);const o=Le(e);return $e(t,o),qe(e),t})(n):n;return et(r,e.isNew,e.isLocked)}}),pl=()=>({transformRow:gl,transformCell:fl}),bl=()=>({transformRow:(e,t)=>gl(e,"thead"===t?"tbody":t),transformCell:fl}),wl=hl,vl=pl,yl=bl,xl=()=>({transformRow:h,transformCell:fl}),Cl=(e,t,o,n)=>{o===n?we(e,t):ge(e,t,o)},Sl=(e,t,o)=>{$(mt(e,t)).fold((()=>Pe(e,o)),(e=>je(e,o)))},Tl=(e,t)=>{const o=[],n=[],r=e=>E(e,(e=>{e.isNew&&o.push(e.element);const t=e.element;return Ve(t),N(e.cells,(e=>{e.isNew&&n.push(e.element),Cl(e.element,"colspan",e.colspan,1),Cl(e.element,"rowspan",e.rowspan,1),Ie(t,e.element)})),t})),s=e=>j(e,(e=>E(e.cells,(e=>(Cl(e.element,"span",e.colspan,1),e.element))))),l=(t,o)=>{const n=((e,t)=>{const o=pt(e,t).getOrThunk((()=>{const o=xe.fromTag(t,ke(e).dom);return"thead"===t?Sl(e,"caption,colgroup",o):"colgroup"===t?Sl(e,"caption",o):Ie(e,o),o}));return Ve(o),o})(e,o),l=("colgroup"===o?s:r)(t);$e(n,l)},a=(t,o)=>{t.length>0?l(t,o):(t=>{pt(e,t).each(qe)})(o)},c=[],i=[],m=[],d=[];return N(t,(e=>{switch(e.section){case"thead":c.push(e);break;case"tbody":i.push(e);break;case"tfoot":m.push(e);break;case"colgroup":d.push(e)}})),a(d,"colgroup"),a(c,"thead"),a(i,"tbody"),a(m,"tfoot"),{newRows:o,newCells:n}},Rl=(e,t)=>{if(0===e.length)return 0;const o=e[0];return W(e,(e=>!t(o.element,e.element))).getOr(e.length)},Dl=(e,t)=>{const o=E(e,(e=>E(e.cells,y)));return E(e,((n,r)=>{const s=j(n.cells,((n,s)=>{if(!1===o[r][s]){const m=((e,t,o,n)=>{const r=((e,t)=>e[t])(e,t),s="colgroup"===r.section,l=Rl(r.cells.slice(o),n),a=s?1:Rl(((e,t)=>E(e,(e=>Fo(e,t))))(e.slice(t),o),n);return{colspan:l,rowspan:a}})(e,r,s,t);return((e,t,n,r)=>{for(let s=e;s({element:e,cells:t,section:o,isNew:n}))(n.element,s,n.section,n.isNew)}))},Ol=(e,t,o)=>{const n=[];N(e.colgroups,(r=>{const s=[];for(let n=0;net(e.element,o,!1))).getOrThunk((()=>et(t.colGap(),!0,!1)));s.push(r)}n.push(tt(r.element,s,"colgroup",o))}));for(let r=0;ret(e.element,o,e.isLocked))).getOrThunk((()=>et(t.gap(),!0,!1)));s.push(l)}const l=e.all[r],a=tt(l.element,s,l.section,o);n.push(a)}return n},kl=e=>Dl(e,Re),El=(e,t)=>V(e.all,(e=>L(e.cells,(e=>Re(t,e.element))))),Nl=(e,t,o)=>{const n=E(t.selection,(t=>Vt(t).bind((t=>El(e,t))).filter(o))),r=yt(n);return xt(r.length>0,r)},_l=(e,t,o,n,r)=>(s,l,a,c)=>{const i=Xo(s),m=C.from(null==c?void 0:c.section).getOrThunk(xl);return t(i,l).map((t=>{const o=((e,t)=>Ol(e,t,!1))(i,a),n=e(o,t,Re,r(a),m),s=Ko(n.grid);return{info:t,grid:kl(n.grid),cursor:n.cursor,lockedColumns:s}})).bind((e=>{const t=Tl(s,e.grid),r=C.from(null==c?void 0:c.sizing).getOrThunk((()=>mr(s))),l=C.from(null==c?void 0:c.resize).getOrThunk(ll);return o(s,e.grid,e.info,{sizing:r,resize:l,section:m}),n(s),we(s,Uo),e.lockedColumns.length>0&&ge(s,Uo,e.lockedColumns.join(",")),C.some({cursor:e.cursor,newRows:t.newRows,newCells:t.newCells})}))},Bl=(e,t)=>Nl(e,t,x).map((e=>({cells:e,generators:t.generators,clipboard:t.clipboard}))),zl=(e,t)=>Nl(e,t,x),Al=(e,t)=>Nl(e,t,(e=>!e.isLocked)),Ll=(e,t)=>P(t,(t=>((e,t)=>El(e,t).exists((e=>!e.isLocked)))(e,t))),Wl=(e,t,o,n)=>{const r=Vo(e).rows;let s=!0;for(let e=0;e{const t=t=>t(e),o=g(e),n=()=>r,r={tag:!0,inner:e,fold:(t,o)=>o(e),isValue:x,isError:y,map:t=>Pl.value(t(e)),mapError:n,bind:t,exists:t,forall:t,getOr:o,or:n,getOrThunk:o,orThunk:n,getOrDie:o,each:t=>{t(e)},toOptional:()=>C.some(e)};return r},jl=e=>{const t=()=>o,o={tag:!1,inner:e,fold:(t,o)=>t(e),isValue:y,isError:x,map:t,mapError:t=>Pl.error(t(e)),bind:t,exists:y,forall:x,getOr:h,or:h,getOrThunk:v,orThunk:v,getOrDie:(n=String(e),()=>{throw new Error(n)}),each:f,toOptional:C.none};var n;return o},Pl={value:Ml,error:jl,fromOption:(e,t)=>e.fold((()=>jl(t)),Ml)},Il=(e,t)=>({rowDelta:0,colDelta:$o(e[0])-$o(t[0])}),Fl=(e,t)=>({rowDelta:e.length-t.length,colDelta:0}),Hl=(e,t,o,n)=>{const r="colgroup"===t.section?o.col:o.cell;return k(e,(e=>et(r(),!0,n(e))))},$l=(e,t,o,n)=>{const r=e[e.length-1];return e.concat(k(t,(()=>{const e="colgroup"===r.section?o.colgroup:o.row,t=qo(r,e,h),s=Hl(t.cells.length,t,o,(e=>X(n,e.toString())));return Io(t,s)})))},Vl=(e,t,o,n)=>E(e,(e=>{const r=Hl(t,e,o,y);return Mo(e,n,r)})),ql=(e,t,o)=>{const n=t.colDelta<0?Vl:h,r=t.rowDelta<0?$l:h,s=Ko(e),l=$o(e[0]),a=O(s,(e=>e===l-1)),c=n(e,Math.abs(t.colDelta),o,a?l-1:l),i=Ko(c);return r(c,Math.abs(t.rowDelta),o,I(i,x))},Ul=(e,t,o,n)=>{const r=b(n,Fo(e[t],o).element),s=e[t];return e.length>1&&$o(s)>1&&(o>0&&r(Ho(s,o-1))||o0&&r(Ho(e[t-1],o))||tB(o,(o=>o>=e.column&&o<=$o(t[0])+e.column)),Kl=(e,t,o,n,r)=>{((e,t,o,n)=>{t>0&&t{const r=e.cells[t-1];let s=0;const l=n();for(;e.cells.length>t+s&&o(r.element,e.cells[t+s].element);)Po(e,t+s,et(l,!0,e.cells[t+s].isLocked)),s++}))})(t,e,r,n.cell);const s=Fl(o,t),l=ql(o,s,n),a=Fl(t,l),c=ql(t,a,n);return E(c,((t,o)=>Mo(t,e,l[o].cells)))},Yl=(e,t,o,n,r)=>{((e,t,o,n)=>{const r=Vo(e).rows;if(t>0&&tA(e,((e,o)=>O(e,(e=>t(e.element,o.element)))?e:e.concat([o])),[]))(r[t-1].cells,o);N(e,(e=>{let s=C.none();for(let l=t;l{Po(a,t,et(e,!0,c.isLocked))})))}}))}})(t,e,r,n.cell);const s=Ko(t),l=Il(t,o),a={...l,colDelta:l.colDelta-s.length},c=ql(t,a,n),{cols:i,rows:m}=Vo(c),d=Ko(c),u=Il(o,t),f={...u,colDelta:u.colDelta+d.length},g=(p=n,b=d,E(o,(e=>A(b,((t,o)=>{const n=Hl(1,e,p,x)[0];return jo(t,o,n)}),e)))),h=ql(g,f,n);var p,b;return[...i,...m.slice(0,e),...h,...m.slice(e,m.length)]},Jl=(e,t,o,n,r)=>{const{rows:s,cols:l}=Vo(e),a=s.slice(0,t),c=s.slice(t);return[...l,...a,((e,t,o,n)=>qo(e,(e=>n(e,o)),t))(s[o],((e,o)=>t>0&&tE(e,(e=>{const s=t>0&&t<$o(e)&&n(Ho(e,t-1),Ho(e,t)),l=((e,t,o,n,r,s,l)=>{if("colgroup"!==o&&n)return Fo(e,t);{const t=Fo(e,r);return et(l(t.element,s),!0,!1)}})(e,t,e.section,s,o,n,r);return jo(e,t,l)})),Xl=(e,t,o,n)=>((e,t,o,n)=>void 0!==Ho(e[t],o)&&t>0&&n(Ho(e[t-1],o),Ho(e[t],o)))(e,t,o,n)||((e,t,o)=>t>0&&o(Ho(e,t-1),Ho(e,t)))(e[t],o,n),Zl=(e,t,o,n)=>{const r=e=>(e=>"row"===e?(e=>Mt(e,"rowspan")>1)(t):jt(t))(e)?`${e}group`:e;return e?cl(t)?r(o):null:n&&cl(t)?r("row"===o?"col":"row"):null},ea=(e,t,o)=>et(o(e.element,t),!0,e.isLocked),ta=(e,t,o,n,r,s,l)=>E(e,((e,a)=>(e=>{const c=e.cells,i=E(c,((e,c)=>{if((e=>O(t,(t=>o(e.element,t.element))))(e)){const t=l(e,a,c)?r(e,o,n):e;return s(t,a,c).each((e=>{var o,n;o=t.element,n={scope:C.from(e)},G(n,((e,t)=>{e.fold((()=>{we(o,t)}),(e=>{fe(o.dom,t,e)}))}))})),t}return e}));return tt(e.element,i,e.section,e.isNew)})(e))),oa=(e,t,o)=>j(e,((n,r)=>Xl(e,r,t,o)?[]:[Fo(n,t)])),na=(e,t,o,n,r)=>{const s=Vo(e).rows,l=j(t,(e=>oa(s,e,n))),a=E(s,(e=>il(e.cells))),c=((e,t)=>P(t,h)&&il(e)?x:(e,o,n)=>!("th"===ne(e.element)&&t[o]))(l,a),i=((e,t)=>(o,n)=>C.some(Zl(e,o.element,"row",t[n])))(o,a);return ta(e,l,n,r,ea,i,c)},ra=(e,t,o,n)=>{const r=Vo(e).rows,s=E(t,(e=>Fo(r[e.row],e.column)));return ta(e,s,o,n,ea,C.none,x)},sa=e=>{if(!l(e))throw new Error("cases must be an array");if(0===e.length)throw new Error("there must be at least one case");const t=[],o={};return N(e,((n,r)=>{const s=q(n);if(1!==s.length)throw new Error("one and only one name per case");const a=s[0],c=n[a];if(void 0!==o[a])throw new Error("duplicate key detected:"+a);if("cata"===a)throw new Error("cannot have a case named cata (sorry)");if(!l(c))throw new Error("case arguments must be an array");t.push(a),o[a]=(...o)=>{const n=o.length;if(n!==c.length)throw new Error("Wrong number of arguments to case "+a+". Expected "+c.length+" ("+c+"), got "+n);return{fold:(...t)=>{if(t.length!==e.length)throw new Error("Wrong number of arguments to fold. Expected "+e.length+", got "+t.length);return t[r].apply(null,o)},match:e=>{const n=q(e);if(t.length!==n.length)throw new Error("Wrong number of arguments to match. Expected: "+t.join(",")+"\nActual: "+n.join(","));if(!P(t,(e=>D(n,e))))throw new Error("Not all branches were specified when using match. Specified: "+n.join(", ")+"\nRequired: "+t.join(", "));return e[a].apply(null,o)},log:e=>{console.log(e,{constructors:t,constructor:a,params:o})}}}})),o},la={...sa([{none:[]},{only:["index"]},{left:["index","next"]},{middle:["prev","index","next"]},{right:["prev","index"]}])},aa=(e,t,o)=>{const n=((e,t)=>sn(e)?((e,t)=>{const o=rn(e);return E(o,((e,o)=>({element:e.element,width:t[o],colspan:e.colspan})))})(e,t):((e,t)=>{const o=nn(e);return E(o,(e=>{const o=((e,t,o)=>{let n=0;for(let r=e;r{o.setElementWidth(e.element,e.width)}))},ca=(e,t,o,n,r)=>{const s=Xo(e),l=r.getCellDelta(t),a=r.getWidths(s,r),c=o===s.grid.columns-1,i=n.clampTableDelta(a,o,l,r.minCellWidth(),c),m=((e,t,o,n,r)=>{const s=e.slice(0),l=((e,t)=>0===e.length?la.none():1===e.length?la.only(0):0===t?la.left(0,1):t===e.length-1?la.right(t-1,t):t>0&&tn.singleColumnWidth(s[e],o)),((e,t)=>r.calcLeftEdgeDeltas(s,e,t,o,n.minCellWidth(),n.isRelative)),((e,t,l)=>r.calcMiddleDeltas(s,e,t,l,o,n.minCellWidth(),n.isRelative)),((e,t)=>r.calcRightEdgeDeltas(s,e,t,o,n.minCellWidth(),n.isRelative)))})(a,o,i,r,n),d=E(m,((e,t)=>e+a[t]));aa(s,d,r),n.resizeTable(r.adjustTableWidth,i,c)},ia=(e,t,o)=>{const n=Xo(e),r=((e,t)=>lr(e,t,Yn,(e=>e.getOrThunk(Ft))))(n,e),s=E(r,((e,n)=>o===n?Math.max(t+e,Ft()):e)),l=((e,t)=>E(e.all,((e,o)=>({element:e.element,height:t[o]}))))(n,s);N(l,(e=>{$n(e.element,e.height)})),N(nn(n),(e=>{(e=>{Lt(e,"height")})(e.element)}));const a=z(s,((e,t)=>e+t),0);$n(e,a)},ma=e=>A(e,((e,t)=>O(e,(e=>e.column===t.column))?e:e.concat([t])),[]).sort(((e,t)=>e.column-t.column)),da=ue("col"),ua=ue("colgroup"),fa=e=>"tr"===ne(e)||ua(e),ga=e=>({element:e,colspan:Wt(e,"colspan",1),rowspan:Wt(e,"rowspan",1)}),ha=e=>be(e,"scope").map((e=>e.substr(0,3))),pa=(e,t=ga)=>{const o=o=>{if(fa(o))return ua((r={element:o}).element)?e.colgroup(r):e.row(r);{const r=o,s=(t=>da(t.element)?e.col(t):e.cell(t))(t(r));return n=C.some({item:r,replacement:s}),s}var r};let n=C.none();return{getOrInit:(e,t)=>n.fold((()=>o(e)),(n=>t(e,n.item)?n.replacement:o(e)))}},ba=e=>t=>{const o=[],n=n=>{const r="td"===e?{scope:null}:{},s=t.replace(n,e,r);return o.push({item:n,sub:s}),s};return{replaceOrInit:(e,t)=>{if(fa(e)||da(e))return e;{const r=e;return((e,t)=>L(o,(o=>t(o.item,e))))(r,t).fold((()=>n(r)),(o=>t(e,o.item)?o.sub:n(r)))}}}},wa=e=>({unmerge:t=>{const o=ha(t);return o.each((e=>ge(t,"scope",e))),()=>{const n=e.cell({element:t,colspan:1,rowspan:1});return Lt(n,"width"),Lt(t,"width"),o.each((e=>ge(n,"scope",e))),n}},merge:e=>(Lt(e[0],"width"),(()=>{const t=yt(E(e,ha));if(0===t.length)return C.none();{const e=t[0],o=["row","col"];return O(t,(t=>t!==e&&D(o,t)))?C.none():C.from(e)}})().fold((()=>we(e[0],"scope")),(t=>ge(e[0],"scope",t+"group"))),g(e[0]))}),va=["body","p","div","article","aside","figcaption","figure","footer","header","nav","section","ol","ul","table","thead","tfoot","tbody","caption","tr","td","th","h1","h2","h3","h4","h5","h6","blockquote","pre","address"],ya=xs(),xa=e=>((e,t)=>{const o=e.property().name(t);return D(va,o)})(ya,e),Ca=e=>((e,t)=>{const o=e.property().name(t);return D(["ol","ul"],o)})(ya,e),Sa=e=>{const t=ue("br"),o=e=>Cr(e).bind((o=>{const n=Ae(o).map((e=>!!xa(e)||!!((e,t)=>D(["br","img","hr","input"],e.property().name(t)))(ya,e)&&"img"!==ne(e))).getOr(!1);return Ne(o).map((r=>{return!0===n||("li"===ne(s=r)||ft(s,Ca).isSome())||t(o)||xa(r)&&!Re(e,r)?[]:[xe.fromTag("br")];var s}))})).getOr([]),n=(()=>{const n=j(e,(e=>{const n=Le(e);return(e=>P(e,(e=>t(e)||ie(e)&&0===hr(e).trim().length)))(n)?[]:n.concat(o(e))}));return 0===n.length?[xe.fromTag("br")]:n})();Ve(e[0]),$e(e[0],n)},Ta=e=>es(e,!0),Ra=e=>{0===qt(e).length&&qe(e)},Da=(e,t)=>({grid:e,cursor:t}),Oa=(e,t,o)=>{const n=((e,t,o)=>{var n,r;const s=Vo(e).rows;return C.from(null===(r=null===(n=s[t])||void 0===n?void 0:n.cells[o])||void 0===r?void 0:r.element).filter(Ta).orThunk((()=>(e=>V(e,(e=>V(e.cells,(e=>{const t=e.element;return xt(Ta(t),t)})))))(s)))})(e,t,o);return Da(e,n)},ka=e=>A(e,((e,t)=>O(e,(e=>e.row===t.row))?e:e.concat([t])),[]).sort(((e,t)=>e.row-t.row)),Ea=(e,t)=>(o,n,r,s,l)=>{const a=ka(n),c=E(a,(e=>e.row)),i=((e,t,o,n,r,s,l)=>{const{cols:a,rows:c}=Vo(e),i=c[t[0]],m=j(t,(e=>((e,t,o)=>{const n=e[t];return j(n.cells,((n,r)=>Xl(e,t,r,o)?[]:[n]))})(c,e,r))),d=E(i.cells,((e,t)=>il(oa(c,t,r)))),u=[...c];N(t,(e=>{u[e]=l.transformRow(c[e],o)}));const f=[...a,...u],g=((e,t)=>P(t,h)&&il(e.cells)?x:(e,o,n)=>!("th"===ne(e.element)&&t[n]))(i,d),p=((e,t)=>(o,n,r)=>C.some(Zl(e,o.element,"col",t[r])))(n,d);return ta(f,m,r,s,l.transformCell,p,g)})(o,c,e,t,r,s.replaceOrInit,l);return Oa(i,n[0].row,n[0].column)},Na=Ea("thead",!0),_a=Ea("tbody",!1),Ba=Ea("tfoot",!1),za=(e,t,o)=>{const n=((e,t)=>Jt(e,(()=>t)))(e,o.section),r=Zo(n);return Ol(r,t,!0)},Aa=(e,t,o,n)=>((e,t,o,n)=>{const r=Zo(t),s=n.getWidths(r,n);aa(r,s,n)})(0,t,0,n.sizing),La=(e,t,o,n)=>((e,t,o,n,r)=>{const s=Zo(t),l=n.getWidths(s,n),a=n.pixelWidth(),{newSizes:c,delta:i}=r.calcRedestributedWidths(l,a,o.pixelDelta,n.isRelative);aa(s,c,n),n.adjustTableWidth(i)})(0,t,o,n.sizing,n.resize),Wa=(e,t)=>O(t,(e=>0===e.column&&e.isLocked)),Ma=(e,t)=>O(t,(t=>t.column+t.colspan>=e.grid.columns&&t.isLocked)),ja=(e,t)=>{const o=an(e),n=ma(t);return A(n,((e,t)=>e+o[t.column].map(Lo).getOr(0)),0)},Pa=e=>(t,o)=>zl(t,o).filter((o=>!(e?Wa:Ma)(t,o))).map((e=>({details:e,pixelDelta:ja(t,e)}))),Ia=e=>(t,o)=>Bl(t,o).filter((o=>!(e?Wa:Ma)(t,o.cells))),Fa=ba("th"),Ha=ba("td"),$a=_l(((e,t,o,n)=>{const r=t[0].row,s=ka(t),l=z(s,((e,t)=>({grid:Jl(e.grid,r,t.row+e.delta,o,n.getOrInit),delta:e.delta+1})),{grid:e,delta:0}).grid;return Oa(l,r,t[0].column)}),zl,f,f,pa),Va=_l(((e,t,o,n)=>{const r=ka(t),s=r[r.length-1],l=s.row+s.rowspan,a=z(r,((e,t)=>Jl(e,l,t.row,o,n.getOrInit)),e);return Oa(a,l,t[0].column)}),zl,f,f,pa),qa=_l(((e,t,o,n)=>{const r=t.details,s=ma(r),l=s[0].column,a=z(s,((e,t)=>({grid:Ql(e.grid,l,t.column+e.delta,o,n.getOrInit),delta:e.delta+1})),{grid:e,delta:0}).grid;return Oa(a,r[0].row,l)}),Pa(!0),La,f,pa),Ua=_l(((e,t,o,n)=>{const r=t.details,s=r[r.length-1],l=s.column+s.colspan,a=ma(r),c=z(a,((e,t)=>Ql(e,l,t.column,o,n.getOrInit)),e);return Oa(c,r[0].row,l)}),Pa(!1),La,f,pa),Ga=_l(((e,t,o,n)=>{const r=ma(t.details),s=((e,t)=>j(e,(e=>{const o=e.cells,n=z(t,((e,t)=>t>=0&&t0?[tt(e.element,n,e.section,e.isNew)]:[]})))(e,E(r,(e=>e.column))),l=s.length>0?s[0].cells.length-1:0;return Oa(s,r[0].row,Math.min(r[0].column,l))}),((e,t)=>Al(e,t).map((t=>({details:t,pixelDelta:-ja(e,t)})))),La,Ra,pa),Ka=_l(((e,t,o,n)=>{const r=ka(t),s=((e,t,o)=>{const{rows:n,cols:r}=Vo(e);return[...r,...n.slice(0,t),...n.slice(o+1)]})(e,r[0].row,r[r.length-1].row),l=Math.max(Vo(s).rows.length-1,0);return Oa(s,Math.min(t[0].row,l),t[0].column)}),zl,f,Ra,pa),Ya=_l(((e,t,o,n)=>{const r=ma(t),s=E(r,(e=>e.column)),l=na(e,s,!0,o,n.replaceOrInit);return Oa(l,t[0].row,t[0].column)}),Al,f,f,Fa),Ja=_l(((e,t,o,n)=>{const r=ma(t),s=E(r,(e=>e.column)),l=na(e,s,!1,o,n.replaceOrInit);return Oa(l,t[0].row,t[0].column)}),Al,f,f,Ha),Qa=_l(Na,zl,f,f,Fa),Xa=_l(_a,zl,f,f,Ha),Za=_l(Ba,zl,f,f,Ha),ec=_l(((e,t,o,n)=>{const r=ra(e,t,o,n.replaceOrInit);return Oa(r,t[0].row,t[0].column)}),Al,f,f,Fa),tc=_l(((e,t,o,n)=>{const r=ra(e,t,o,n.replaceOrInit);return Oa(r,t[0].row,t[0].column)}),Al,f,f,Ha),oc=_l(((e,t,o,n)=>{const r=t.cells;Sa(r);const s=((e,t,o,n)=>{const r=Vo(e).rows;if(0===r.length)return e;for(let e=t.startRow;e<=t.finishRow;e++)for(let o=t.startCol;o<=t.finishCol;o++){const t=r[e],s=Fo(t,o).isLocked;Po(t,o,et(n(),!1,s))}return e})(e,t.bounds,0,n.merge(r));return Da(s,C.from(r[0]))}),((e,t)=>((e,t)=>t.mergable)(0,t).filter((t=>Ll(e,t.cells)))),Aa,f,wa),nc=_l(((e,t,o,n)=>{const r=z(t,((e,t)=>Wl(e,t,o,n.unmerge(t))),e);return Da(r,C.from(t[0]))}),((e,t)=>((e,t)=>t.unmergable)(0,t).filter((t=>Ll(e,t)))),Aa,f,wa),rc=_l(((e,t,o,n)=>{const r=((e,t)=>{const o=Xo(e);return Ol(o,t,!0)})(t.clipboard,t.generators);var s,l;return((e,t,o,n,r)=>{const s=Ko(t),l=((e,t,o)=>{const n=$o(t[0]),r=Vo(t).cols.length+e.row,s=k(n-e.column,(t=>t+e.column));return{row:r,column:L(s,(e=>P(o,(t=>t!==e)))).getOr(n-1)}})(e,t,s),a=Vo(o).rows,c=Gl(l,a,s),i=((e,t,o)=>{if(e.row>=t.length||e.column>$o(t[0]))return Pl.error("invalid start address out of table bounds, row: "+e.row+", column: "+e.column);const n=t.slice(e.row),r=n[0].cells.slice(e.column),s=$o(o[0]),l=o.length;return Pl.value({rowDelta:n.length-l,colDelta:r.length-s})})(l,t,a);return i.map((e=>{const o={...e,colDelta:e.colDelta-c.length},s=ql(t,o,n),i=Ko(s),m=Gl(l,a,i);return((e,t,o,n,r,s)=>{const l=e.row,a=e.column,c=l+o.length,i=a+$o(o[0])+s.length,m=I(s,x);for(let e=l;eDa(e,C.some(t.element))),(e=>Oa(e,t.row,t.column)))}),((e,t)=>Vt(t.element).bind((o=>El(e,o).map((e=>({...e,generators:t.generators,clipboard:t.clipboard})))))),Aa,f,pa),sc=_l(((e,t,o,n)=>{const r=Vo(e).rows,s=t.cells[0].column,l=r[t.cells[0].row],a=za(t.clipboard,t.generators,l),c=Kl(s,e,a,t.generators,o);return Oa(c,t.cells[0].row,t.cells[0].column)}),Ia(!0),f,f,pa),lc=_l(((e,t,o,n)=>{const r=Vo(e).rows,s=t.cells[t.cells.length-1].column+t.cells[t.cells.length-1].colspan,l=r[t.cells[0].row],a=za(t.clipboard,t.generators,l),c=Kl(s,e,a,t.generators,o);return Oa(c,t.cells[0].row,s)}),Ia(!1),f,f,pa),ac=_l(((e,t,o,n)=>{const r=Vo(e).rows,s=t.cells[0].row,l=r[s],a=za(t.clipboard,t.generators,l),c=Yl(s,e,a,t.generators,o);return Oa(c,t.cells[0].row,t.cells[0].column)}),Bl,f,f,pa),cc=_l(((e,t,o,n)=>{const r=Vo(e).rows,s=t.cells[t.cells.length-1].row+t.cells[t.cells.length-1].rowspan,l=r[t.cells[0].row],a=za(t.clipboard,t.generators,l),c=Yl(s,e,a,t.generators,o);return Oa(c,s,t.cells[0].column)}),Bl,f,f,pa),ic=(e,t)=>{const o=Xo(e);return zl(o,t).bind((e=>{const t=e[e.length-1],n=e[0].column,r=t.column+t.colspan,s=M(E(o.all,(e=>B(e.cells,(e=>e.column>=n&&e.column{const o=Xo(e);return zl(o,t).bind(ul).getOr("")},dc=(e,t)=>{const o=Xo(e);return zl(o,t).bind((e=>{const t=e[e.length-1],n=e[0].row,r=t.row+t.rowspan;return(e=>{const t=E(e,(e=>dl(e).type)),o=D(t,"header"),n=D(t,"footer");if(o||n){const e=D(t,"body");return!o||e||n?o||e||!n?C.none():C.some("footer"):C.some("header")}return C.some("body")})(o.all.slice(n,r))})).getOr("")},uc=(e,t)=>e.dispatch("NewRow",{node:t}),fc=(e,t)=>e.dispatch("NewCell",{node:t}),gc=(e,t,o)=>{e.dispatch("TableModified",{...o,table:t})},hc={structure:!1,style:!0},pc={structure:!0,style:!1},bc={structure:!0,style:!0},wc=(e,t)=>Hr(e)?ur(t):$r(e)?dr(t):mr(t),vc=(e,t,o)=>{const n=e=>"table"===ne(os(e)),r=Wr(e),s=Ir(e)?f:Zs,l=t=>{switch(Mr(e)){case"section":return wl();case"sectionCells":return vl();case"cells":return yl();default:return((e,t)=>{var o;switch((o=Xo(e),V(o.all,(e=>{const t=dl(e);return"header"===t.type?C.from(t.subType):C.none()}))).getOr(t)){case"section":return hl();case"sectionCells":return pl();case"cells":return bl()}})(t,"section")}},a=(n,s,a,c)=>(i,m,d=!1)=>{rs(i);const u=xe.fromDom(e.getDoc()),f=_r(a,u,r),g={sizing:wc(e,i),resize:Ir(e)?sl():ll(),section:l(i)};return s(i)?n(i,m,f,g).bind((n=>{t.refresh(i.dom),N(n.newRows,(t=>{uc(e,t.dom)})),N(n.newCells,(t=>{fc(e,t.dom)}));const r=((t,n)=>n.cursor.fold((()=>{const n=qt(t);return H(n).filter(st).map((n=>{o.clearSelectedCells(t.dom);const r=e.dom.createRng();return r.selectNode(n.dom),e.selection.setRng(r),ge(n,"data-mce-selected","1"),r}))}),(n=>{const r=Qs(Xs,n),s=e.dom.createRng();return s.setStart(r.element.dom,r.offset),s.setEnd(r.element.dom,r.offset),e.selection.setRng(s),o.clearSelectedCells(t.dom),C.some(s)})))(i,n);return st(i)&&(rs(i),d||gc(e,i.dom,c)),r.map((e=>({rng:e,effect:c})))})):C.none()},c=a(Ka,(t=>!n(e)||al(t).rows>1),f,pc),i=a(Ga,(t=>!n(e)||al(t).columns>1),f,pc);return{deleteRow:c,deleteColumn:i,insertRowsBefore:a($a,x,f,pc),insertRowsAfter:a(Va,x,f,pc),insertColumnsBefore:a(qa,x,s,pc),insertColumnsAfter:a(Ua,x,s,pc),mergeCells:a(oc,x,f,pc),unmergeCells:a(nc,x,f,pc),pasteColsBefore:a(sc,x,f,pc),pasteColsAfter:a(lc,x,f,pc),pasteRowsBefore:a(ac,x,f,pc),pasteRowsAfter:a(cc,x,f,pc),pasteCells:a(rc,x,f,bc),makeCellsHeader:a(ec,x,f,pc),unmakeCellsHeader:a(tc,x,f,pc),makeColumnsHeader:a(Ya,x,f,pc),unmakeColumnsHeader:a(Ja,x,f,pc),makeRowsHeader:a(Qa,x,f,pc),makeRowsBody:a(Xa,x,f,pc),makeRowsFooter:a(Za,x,f,pc),getTableRowType:dc,getTableCellType:mc,getTableColType:ic}},yc=(e,t,o)=>{const n=Wt(e,t,1);1===o||n<=1?we(e,t):ge(e,t,Math.min(o,n))},xc=(e,t)=>o=>{const n=o.column+o.colspan-1,r=o.column;return n>=e&&r{const n=o.substring(0,o.length-e.length),r=parseFloat(n);return n===r.toString()?t(r):Cc.invalid(o)},Tc={...Cc,from:e=>Rt(e,"%")?Sc("%",Cc.percent,e):Rt(e,"px")?Sc("px",Cc.pixels,e):Cc.invalid(e)},Rc=(e,t,o)=>{const n=Tc.from(o),r=P(e,(e=>"0px"===e))?((e,t)=>{const o=e.fold((()=>g("")),(e=>g(e/t+"px")),(()=>g(100/t+"%")));return k(t,o)})(n,e.length):((e,t,o)=>e.fold((()=>t),(e=>((e,t,o)=>{const n=o/t;return E(e,(e=>Tc.from(e).fold((()=>e),(e=>e*n+"px"),(e=>e/100*o+"px"))))})(t,o,e)),(e=>((e,t)=>E(e,(e=>Tc.from(e).fold((()=>e),(e=>e/t*100+"%"),(e=>e+"%")))))(t,o))))(n,e,t);return kc(r)},Dc=(e,t)=>0===e.length?t:z(e,((e,t)=>Tc.from(t).fold(g(0),h,h)+e),0),Oc=(e,t)=>Tc.from(e).fold(g(e),(e=>e+t+"px"),(e=>e+t+"%")),kc=e=>{if(0===e.length)return e;const t=z(e,((e,t)=>{const o=Tc.from(t).fold((()=>({value:t,remainder:0})),(e=>(e=>{const t=Math.floor(e);return{value:t+"px",remainder:e-t}})(e)),(e=>({value:e+"%",remainder:0})));return{output:[o.value].concat(e.output),remainder:e.remainder+o.remainder}}),{output:[],remainder:0}),o=t.output;return o.slice(0,o.length-1).concat([Oc(o[o.length-1],Math.round(t.remainder))])},Ec=Tc.from,Nc=(e,t,o)=>{const n=Xo(e),r=n.all,s=nn(n),l=rn(n);t.each((t=>{const o=Ec(t).fold(g("px"),g("px"),g("%")),r=Ao(e),a=((e,t)=>nr(e,t,er,rr))(n,e),c=Rc(a,r,t);sn(n)?((e,t,o)=>{N(t,((t,n)=>{const r=Dc([e[n]],It());Nt(t.element,"width",r+o)}))})(c,l,o):((e,t,o)=>{N(t,(t=>{const n=e.slice(t.column,t.colspan+t.column),r=Dc(n,It());Nt(t.element,"width",r+o)}))})(c,s,o),Nt(e,"width",t)})),o.each((t=>{const o=gn(e),l=((e,t)=>lr(e,t,tr,rr))(n,e);((e,t,o)=>{N(o,(e=>{Lt(e.element,"height")})),N(t,((t,o)=>{Nt(t.element,"height",e[o])}))})(Rc(l,o,t),r,s),Nt(e,"height",t)}))},_c=e=>Un(e).exists((e=>Wn.test(e))),Bc=e=>Un(e).exists((e=>Mn.test(e))),zc=e=>Un(e).isNone(),Ac=e=>{we(e,"width"),we(e,"height")},Lc=e=>{const t=Qn(e);Nc(e,C.some(t),C.none()),Ac(e)},Wc=e=>{const t=(e=>Ao(e)+"px")(e);Nc(e,C.some(t),C.none()),Ac(e)},Mc=e=>{Lt(e,"width");const t=Ut(e),o=t.length>0?t:qt(e);N(o,(e=>{Lt(e,"width"),Ac(e)})),Ac(e)},jc={styles:{"border-collapse":"collapse",width:"100%"},attributes:{border:"1"},colGroups:!1},Pc=(e,t,o,n)=>k(e,(e=>((e,t,o,n)=>{const r=xe.fromTag("tr");for(let s=0;s{e.selection.select(t.dom,!0),e.selection.collapse(!0)},Fc=(e,t,o,n,s)=>{const l=(e=>{const t=e.options,o=t.get("table_default_styles");return t.isSet("table_default_styles")?o:((e,t)=>Vr(e)||!Ur(e)?t:$r(e)?{...t,width:Lr(e)}:{...t,width:Ar})(e,o)})(e),a={styles:l,attributes:Kr(e),colGroups:Yr(e)};return e.undoManager.ignore((()=>{const r=((e,t,o,n,r,s=jc)=>{const l=xe.fromTag("table"),a="cells"!==r;_t(l,s.styles),he(l,s.attributes),s.colGroups&&Ie(l,(e=>{const t=xe.fromTag("colgroup");return k(e,(()=>Ie(t,xe.fromTag("col")))),t})(t));const c=Math.min(e,o);if(a&&o>0){const e=xe.fromTag("thead");Ie(l,e);const s=Pc(o,t,"sectionCells"===r?c:0,n);$e(e,s)}const i=xe.fromTag("tbody");Ie(l,i);const m=Pc(a?e-c:e,t,a?0:o,n);return $e(i,m),l})(o,t,s,n,Mr(e),a);ge(r,"data-mce-id","__mce");const l=(e=>{const t=xe.fromTag("div"),o=xe.fromDom(e.dom.cloneNode(!0));return Ie(t,o),(e=>e.dom.innerHTML)(t)})(r);e.insertContent(l),e.addVisual()})),bt(os(e),'table[data-mce-id="__mce"]').map((t=>($r(e)?Wc(t):Vr(e)?Mc(t):(Hr(e)||(e=>r(e)&&-1!==e.indexOf("%"))(l.width))&&Lc(t),rs(t),we(t,"data-mce-id"),((e,t)=>{N(dt(t,"tr"),(t=>{uc(e,t.dom),N(dt(t,"th,td"),(t=>{fc(e,t.dom)}))}))})(e,t),((e,t)=>{bt(t,"td,th").each(b(Ic,e))})(e,t),t.dom))).getOrNull()};var Hc=tinymce.util.Tools.resolve("tinymce.FakeClipboard");const $c="x-tinymce/dom-table-",Vc=$c+"rows",qc=$c+"columns",Uc=e=>{const t=Hc.FakeClipboardItem(e);Hc.write([t])},Gc=e=>{var t;const o=null!==(t=Hc.read())&&void 0!==t?t:[];return V(o,(t=>C.from(t.getType(e))))},Kc=e=>{Gc(e).isSome()&&Hc.clear()},Yc=e=>{e.fold(Qc,(e=>Uc({[Vc]:e})))},Jc=()=>Gc(Vc),Qc=()=>Kc(Vc),Xc=e=>{e.fold(ei,(e=>Uc({[qc]:e})))},Zc=()=>Gc(qc),ei=()=>Kc(qc),ti=e=>$s(ss(e),ns(e)).filter(ds),oi=(e,t)=>{const o=ns(e),n=e=>Gt(e,o),l=t=>(e=>Vs(ss(e),ns(e)).filter(ds))(e).bind((e=>n(e).map((o=>t(o,e))))),a=t=>{e.focus()},c=(t,o=!1)=>l(((n,r)=>{const s=Fs(qs(e),n,r);t(n,s,o).each(a)})),i=()=>l(((t,o)=>((e,t,o)=>{const n=Xo(e);return zl(n,t).bind((e=>{const t=Ol(n,o,!1),r=Vo(t).rows.slice(e[0].row,e[e.length-1].row+e[e.length-1].rowspan),s=j(r,(e=>{const t=B(e.cells,(e=>!e.isLocked));return t.length>0?[{...e,cells:t}]:[]})),l=kl(s);return xt(l.length>0,l)})).map((e=>E(e,(e=>{const t=Ke(e.element);return N(e.cells,(e=>{const o=Ye(e.element);Cl(o,"colspan",e.colspan,1),Cl(o,"rowspan",e.rowspan,1),Ie(t,o)})),t}))))})(t,Fs(qs(e),t,o),_r(f,xe.fromDom(e.getDoc()),C.none())))),m=()=>l(((t,o)=>((e,t)=>{const o=Xo(e);return Al(o,t).map((e=>{const t=e[e.length-1],n=e[0].column,r=t.column+t.colspan,s=((e,t,o)=>{if(sn(e)){const n=B(rn(e),xc(t,o)),r=E(n,(e=>{const n=Ye(e.element);return yc(n,"span",o-t),n})),s=xe.fromTag("colgroup");return $e(s,r),[s]}return[]})(o,n,r),l=((e,t,o)=>E(e.all,(e=>{const n=B(e.cells,xc(t,o)),r=E(n,(e=>{const n=Ye(e.element);return yc(n,"colspan",o-t),n})),s=xe.fromTag("tr");return $e(s,r),s})))(o,n,r);return[...s,...l]}))})(t,Fs(qs(e),t,o)))),d=(t,o)=>o().each((o=>{const n=E(o,(e=>Ye(e)));l(((o,r)=>{const s=Br(xe.fromDom(e.getDoc())),l=((e,t,o,n)=>({selection:zs(e),clipboard:o,generators:n}))(qs(e),0,n,s);t(o,l).each(a)}))})),g=e=>(t,o)=>((e,t)=>X(e,t)?C.from(e[t]):C.none())(o,"type").each((t=>{c(e(t),o.no_events)}));G({mceTableSplitCells:()=>c(t.unmergeCells),mceTableMergeCells:()=>c(t.mergeCells),mceTableInsertRowBefore:()=>c(t.insertRowsBefore),mceTableInsertRowAfter:()=>c(t.insertRowsAfter),mceTableInsertColBefore:()=>c(t.insertColumnsBefore),mceTableInsertColAfter:()=>c(t.insertColumnsAfter),mceTableDeleteCol:()=>c(t.deleteColumn),mceTableDeleteRow:()=>c(t.deleteRow),mceTableCutCol:()=>m().each((e=>{Xc(e),c(t.deleteColumn)})),mceTableCutRow:()=>i().each((e=>{Yc(e),c(t.deleteRow)})),mceTableCopyCol:()=>m().each((e=>Xc(e))),mceTableCopyRow:()=>i().each((e=>Yc(e))),mceTablePasteColBefore:()=>d(t.pasteColsBefore,Zc),mceTablePasteColAfter:()=>d(t.pasteColsAfter,Zc),mceTablePasteRowBefore:()=>d(t.pasteRowsBefore,Jc),mceTablePasteRowAfter:()=>d(t.pasteRowsAfter,Jc),mceTableDelete:()=>ti(e).each((t=>{Gt(t,o).filter(w(o)).each((t=>{const o=xe.fromText("");if(je(t,o),qe(t),e.dom.isEmpty(e.getBody()))e.setContent(""),e.selection.setCursorLocation();else{const t=e.dom.createRng();t.setStart(o.dom,0),t.setEnd(o.dom,0),e.selection.setRng(t),e.nodeChanged()}}))})),mceTableCellToggleClass:(t,o)=>{l((t=>{const n=qs(e),r=P(n,(t=>e.formatter.match("tablecellclass",{value:o},t.dom))),s=r?e.formatter.remove:e.formatter.apply;N(n,(e=>s("tablecellclass",{value:o},e.dom))),gc(e,t.dom,hc)}))},mceTableToggleClass:(t,o)=>{l((t=>{e.formatter.toggle("tableclass",{value:o},t.dom),gc(e,t.dom,hc)}))},mceTableToggleCaption:()=>{ti(e).each((t=>{Gt(t,o).each((o=>{pt(o,"caption").fold((()=>{const t=xe.fromTag("caption");Ie(t,xe.fromText("Caption")),((e,t)=>{We(e,0).fold((()=>{Ie(e,t)}),(e=>{Me(e,t)}))})(o,t),e.selection.setCursorLocation(t.dom,0)}),(n=>{ue("caption")(t)&&Te("td",o).each((t=>e.selection.setCursorLocation(t.dom,0))),qe(n)})),gc(e,o.dom,pc)}))}))},mceTableSizingMode:(t,n)=>(t=>ti(e).each((n=>{Vr(e)||$r(e)||Hr(e)||Gt(n,o).each((o=>{"relative"!==t||_c(o)?"fixed"!==t||Bc(o)?"responsive"!==t||zc(o)||Mc(o):Wc(o):Lc(o),rs(o),gc(e,o.dom,pc)}))})))(n),mceTableCellType:g((e=>"th"===e?t.makeCellsHeader:t.unmakeCellsHeader)),mceTableColType:g((e=>"th"===e?t.makeColumnsHeader:t.unmakeColumnsHeader)),mceTableRowType:g((e=>{switch(e){case"header":return t.makeRowsHeader;case"footer":return t.makeRowsFooter;default:return t.makeRowsBody}}))},((t,o)=>e.addCommand(o,t))),e.addCommand("mceInsertTable",((t,o)=>{((e,t,o,n={})=>{const r=e=>u(e)&&e>0;if(r(t)&&r(o)){const r=n.headerRows||0,s=n.headerColumns||0;return Fc(e,o,t,s,r)}console.error("Invalid values for mceInsertTable - rows and columns values are required to insert a table.")})(e,o.rows,o.columns,o.options)})),e.addCommand("mceTableApplyCellStyle",((t,o)=>{const l=e=>"tablecell"+e.toLowerCase().replace("-","");if(!s(o))return;const a=B(qs(e),ds);if(0===a.length)return;const c=((e,t)=>{const o={};return((e,t,o,n)=>{G(e,((e,r)=>{(t(e,r)?o:n)(e,r)}))})(e,t,(e=>(t,o)=>{e[o]=t})(o),f),o})(o,((t,o)=>e.formatter.has(l(o))&&r(t)));(e=>{for(const t in e)if(U.call(e,t))return!1;return!0})(c)||(G(c,((t,o)=>{const n=l(o);N(a,(o=>{""===t?e.formatter.remove(n,{value:null},o.dom,!0):e.formatter.apply(n,{value:t},o.dom)}))})),n(a[0]).each((t=>gc(e,t.dom,hc))))}))},ni=sa([{before:["element"]},{on:["element","offset"]},{after:["element"]}]),ri={before:ni.before,on:ni.on,after:ni.after,cata:(e,t,o,n)=>e.fold(t,o,n),getStart:e=>e.fold(h,h,h)},si=(e,t)=>({selection:e,kill:t}),li=(e,t)=>{const o=e.document.createRange();return o.selectNode(t.dom),o},ai=(e,t)=>{const o=e.document.createRange();return ci(o,t),o},ci=(e,t)=>e.selectNodeContents(t.dom),ii=(e,t,o)=>{const n=e.document.createRange();var r;return r=n,t.fold((e=>{r.setStartBefore(e.dom)}),((e,t)=>{r.setStart(e.dom,t)}),(e=>{r.setStartAfter(e.dom)})),((e,t)=>{t.fold((t=>{e.setEndBefore(t.dom)}),((t,o)=>{e.setEnd(t.dom,o)}),(t=>{e.setEndAfter(t.dom)}))})(n,o),n},mi=(e,t,o,n,r)=>{const s=e.document.createRange();return s.setStart(t.dom,o),s.setEnd(n.dom,r),s},di=e=>({left:e.left,top:e.top,right:e.right,bottom:e.bottom,width:e.width,height:e.height}),ui=sa([{ltr:["start","soffset","finish","foffset"]},{rtl:["start","soffset","finish","foffset"]}]),fi=(e,t,o)=>t(xe.fromDom(o.startContainer),o.startOffset,xe.fromDom(o.endContainer),o.endOffset),gi=(e,t)=>{const o=((e,t)=>t.match({domRange:e=>({ltr:g(e),rtl:C.none}),relative:(t,o)=>({ltr:Zt((()=>ii(e,t,o))),rtl:Zt((()=>C.some(ii(e,o,t))))}),exact:(t,o,n,r)=>({ltr:Zt((()=>mi(e,t,o,n,r))),rtl:Zt((()=>C.some(mi(e,n,r,t,o))))})}))(e,t);return((e,t)=>{const o=t.ltr();return o.collapsed?t.rtl().filter((e=>!1===e.collapsed)).map((e=>ui.rtl(xe.fromDom(e.endContainer),e.endOffset,xe.fromDom(e.startContainer),e.startOffset))).getOrThunk((()=>fi(0,ui.ltr,o))):fi(0,ui.ltr,o)})(0,o)},hi=(e,t)=>gi(e,t).match({ltr:(t,o,n,r)=>{const s=e.document.createRange();return s.setStart(t.dom,o),s.setEnd(n.dom,r),s},rtl:(t,o,n,r)=>{const s=e.document.createRange();return s.setStart(n.dom,r),s.setEnd(t.dom,o),s}});ui.ltr,ui.rtl;const pi=(e,t,o,n)=>({start:e,soffset:t,finish:o,foffset:n}),bi=(e,t,o,n)=>({start:ri.on(e,t),finish:ri.on(o,n)}),wi=(e,t)=>{const o=hi(e,t);return pi(xe.fromDom(o.startContainer),o.startOffset,xe.fromDom(o.endContainer),o.endOffset)},vi=bi,yi=(e,t,o,n,r)=>Re(o,n)?C.none():Os(o,n,t).bind((t=>{const n=t.boxes.getOr([]);return n.length>1?(r(e,n,t.start,t.finish),C.some(si(C.some(vi(o,0,o,wr(o))),!0))):C.none()})),xi=(e,t)=>({item:e,mode:t}),Ci=(e,t,o,n=Si)=>e.property().parent(t).map((e=>xi(e,n))),Si=(e,t,o,n=Ti)=>o.sibling(e,t).map((e=>xi(e,n))),Ti=(e,t,o,n=Ti)=>{const r=e.property().children(t);return o.first(r).map((e=>xi(e,n)))},Ri=[{current:Ci,next:Si,fallback:C.none()},{current:Si,next:Ti,fallback:C.some(Ci)},{current:Ti,next:Ti,fallback:C.some(Si)}],Di=(e,t,o,n,r=Ri)=>L(r,(e=>e.current===o)).bind((o=>o.current(e,t,n,o.next).orThunk((()=>o.fallback.bind((o=>Di(e,t,o,n))))))),Oi=(e,t,o,n,r,s)=>Di(e,t,n,r).bind((t=>s(t.item)?C.none():o(t.item)?C.some(t.item):Oi(e,t.item,o,t.mode,r,s))),ki=e=>t=>0===e.property().children(t).length,Ei=(e,t,o,n)=>Oi(e,t,o,Si,{sibling:(e,t)=>e.query().prevSibling(t),first:e=>e.length>0?C.some(e[e.length-1]):C.none()},n),Ni=(e,t,o,n)=>Oi(e,t,o,Si,{sibling:(e,t)=>e.query().nextSibling(t),first:e=>e.length>0?C.some(e[0]):C.none()},n),_i=xs(),Bi=(e,t)=>((e,t,o)=>Ei(e,t,ki(e),o))(_i,e,t),zi=(e,t)=>((e,t,o)=>Ni(e,t,ki(e),o))(_i,e,t),Ai=sa([{none:["message"]},{success:[]},{failedUp:["cell"]},{failedDown:["cell"]}]),Li=e=>wt(e,"tr"),Wi={...Ai,verify:(e,t,o,n,r,s,l)=>wt(n,"td,th",l).bind((o=>wt(t,"td,th",l).map((t=>Re(o,t)?Re(n,o)&&wr(o)===r?s(t):Ai.none("in same cell"):Rs(Li,[o,t]).fold((()=>((e,t,o)=>{const n=e.getRect(t),r=e.getRect(o);return r.right>n.left&&r.lefts(t))))))).getOr(Ai.none("default")),cata:(e,t,o,n,r)=>e.fold(t,o,n,r)},Mi=ue("br"),ji=(e,t,o)=>t(e,o).bind((e=>ie(e)&&0===hr(e).trim().length?ji(e,t,o):C.some(e))),Pi=(e,t,o,n)=>((e,t)=>We(e,t).filter(Mi).orThunk((()=>We(e,t-1).filter(Mi))))(t,o).bind((t=>n.traverse(t).fold((()=>ji(t,n.gather,e).map(n.relative)),(e=>(e=>Ne(e).bind((t=>{const o=Le(t);return((e,t)=>W(e,b(Re,t)))(o,e).map((n=>((e,t,o,n)=>({parent:e,children:t,element:o,index:n}))(t,o,e,n)))})))(e).map((e=>ri.on(e.parent,e.index))))))),Ii=(e,t)=>({left:e.left,top:e.top+t,right:e.right,bottom:e.bottom+t}),Fi=(e,t)=>({left:e.left,top:e.top-t,right:e.right,bottom:e.bottom-t}),Hi=(e,t,o)=>({left:e.left+t,top:e.top+o,right:e.right+t,bottom:e.bottom+o}),$i=e=>({left:e.left,top:e.top,right:e.right,bottom:e.bottom}),Vi=(e,t)=>C.some(e.getRect(t)),qi=(e,t,o)=>ce(t)?Vi(e,t).map($i):ie(t)?((e,t,o)=>o>=0&&o0?e.getRangedRect(t,o-1,t,o):C.none())(e,t,o).map($i):C.none(),Ui=(e,t)=>ce(t)?Vi(e,t).map($i):ie(t)?e.getRangedRect(t,0,t,wr(t)).map($i):C.none(),Gi=sa([{none:[]},{retry:["caret"]}]),Ki=(e,t,o)=>gt(t,xa).fold(y,(t=>Ui(e,t).exists((e=>((e,t)=>e.leftt.right)(o,e))))),Yi={point:e=>e.bottom,adjuster:(e,t,o,n,r)=>{const s=Ii(r,5);return Math.abs(o.bottom-n.bottom)<1||o.top>r.bottom?Gi.retry(s):o.top===r.bottom?Gi.retry(Ii(r,1)):Ki(e,t,r)?Gi.retry(Hi(s,5,0)):Gi.none()},move:Ii,gather:zi},Ji=(e,t,o,n,r)=>0===r?C.some(n):((e,t,o)=>e.elementFromPoint(t,o).filter((e=>"table"===ne(e))).isSome())(e,n.left,t.point(n))?((e,t,o,n,r)=>Ji(e,t,o,t.move(n,5),r))(e,t,o,n,r-1):e.situsFromPoint(n.left,t.point(n)).bind((s=>s.start.fold(C.none,(s=>Ui(e,s).bind((l=>t.adjuster(e,s,l,o,n).fold(C.none,(n=>Ji(e,t,o,n,r-1))))).orThunk((()=>C.some(n)))),C.none))),Qi=(e,t,o)=>{const n=e.move(o,5),r=Ji(t,e,o,n,100).getOr(n);return((e,t,o)=>e.point(t)>o.getInnerHeight()?C.some(e.point(t)-o.getInnerHeight()):e.point(t)<0?C.some(-e.point(t)):C.none())(e,r,t).fold((()=>t.situsFromPoint(r.left,e.point(r))),(o=>(t.scrollBy(0,o),t.situsFromPoint(r.left,e.point(r)-o))))},Xi={tryUp:b(Qi,{point:e=>e.top,adjuster:(e,t,o,n,r)=>{const s=Fi(r,5);return Math.abs(o.top-n.top)<1||o.bottome.getSelection().bind((n=>((e,t,o,n)=>{const r=Mi(t)?((e,t,o)=>o.traverse(t).orThunk((()=>ji(t,o.gather,e))).map(o.relative))(e,t,n):Pi(e,t,o,n);return r.map((e=>({start:e,finish:e})))})(t,n.finish,n.foffset,o).fold((()=>C.some(Gs(n.finish,n.foffset))),(r=>{const s=e.fromSitus(r);return l=Wi.verify(e,n.finish,n.foffset,s.finish,s.foffset,o.failure,t),Wi.cata(l,(e=>C.none()),(()=>C.none()),(e=>C.some(Gs(e,0))),(e=>C.some(Gs(e,wr(e)))));var l})))),em=(e,t,o,n,r,s)=>0===s?C.none():nm(e,t,o,n,r).bind((l=>{const a=e.fromSitus(l),c=Wi.verify(e,o,n,a.finish,a.foffset,r.failure,t);return Wi.cata(c,(()=>C.none()),(()=>C.some(l)),(l=>Re(o,l)&&0===n?tm(e,o,n,Fi,r):em(e,t,l,0,r,s-1)),(l=>Re(o,l)&&n===wr(l)?tm(e,o,n,Ii,r):em(e,t,l,wr(l),r,s-1)))})),tm=(e,t,o,n,r)=>qi(e,t,o).bind((t=>om(e,r,n(t,Xi.getJumpSize())))),om=(e,t,o)=>{const n=No().browser;return n.isChromium()||n.isSafari()||n.isFirefox()?t.retry(e,o):C.none()},nm=(e,t,o,n,r)=>qi(e,o,n).bind((t=>om(e,r,t))),rm=(e,t,o,n,r)=>wt(n,"td,th",t).bind((n=>wt(n,"table",t).bind((s=>((e,t)=>ft(e,(e=>Ne(e).exists((e=>Re(e,t)))),void 0).isSome())(r,s)?((e,t,o)=>Zi(e,t,o).bind((n=>em(e,t,n.element,n.offset,o,20).map(e.fromSitus))))(e,t,o).bind((e=>wt(e.finish,"td,th",t).map((t=>({start:n,finish:t,range:e}))))):C.none())))),sm=(e,t,o,n,r,s)=>s(n,t).orThunk((()=>rm(e,t,o,n,r).map((e=>{const t=e.range;return si(C.some(vi(t.start,t.soffset,t.finish,t.foffset)),!0)})))),lm=(e,t)=>wt(e,"tr",t).bind((e=>wt(e,"table",t).bind((o=>{const n=dt(o,"tr");return Re(e,n[0])?((e,t,o)=>Ei(_i,e,(e=>Cr(e).isSome()),o))(o,0,t).map((e=>{const t=wr(e);return si(C.some(vi(e,t,e,t)),!0)})):C.none()})))),am=(e,t)=>wt(e,"tr",t).bind((e=>wt(e,"table",t).bind((o=>{const n=dt(o,"tr");return Re(e,n[n.length-1])?((e,t,o)=>Ni(_i,e,(e=>xr(e).isSome()),o))(o,0,t).map((e=>si(C.some(vi(e,0,e,0)),!0))):C.none()})))),cm=(e,t,o,n,r,s,l)=>rm(e,o,n,r,s).bind((e=>yi(t,o,e.start,e.finish,l))),im=e=>{let t=e;return{get:()=>t,set:e=>{t=e}}},mm=()=>{const e=(e=>{const t=im(C.none()),o=()=>t.get().each(e);return{clear:()=>{o(),t.set(C.none())},isSet:()=>t.get().isSome(),get:()=>t.get(),set:e=>{o(),t.set(C.some(e))}}})(f);return{...e,on:t=>e.get().each(t)}},dm=(e,t)=>wt(e,"td,th",t),um=e=>_e(e).exists(es),fm={traverse:Ae,gather:zi,relative:ri.before,retry:Xi.tryDown,failure:Wi.failedDown},gm={traverse:ze,gather:Bi,relative:ri.before,retry:Xi.tryUp,failure:Wi.failedUp},hm=e=>t=>t===e,pm=hm(38),bm=hm(40),wm=e=>e>=37&&e<=40,vm={isBackward:hm(37),isForward:hm(39)},ym={isBackward:hm(39),isForward:hm(37)},xm=sa([{domRange:["rng"]},{relative:["startSitu","finishSitu"]},{exact:["start","soffset","finish","foffset"]}]),Cm={domRange:xm.domRange,relative:xm.relative,exact:xm.exact,exactFromRange:e=>xm.exact(e.start,e.soffset,e.finish,e.foffset),getWin:e=>{const t=(e=>e.match({domRange:e=>xe.fromDom(e.startContainer),relative:(e,t)=>ri.getStart(e),exact:(e,t,o,n)=>e}))(e);return xe.fromDom(Ee(t).dom.defaultView)},range:pi},Sm=(e,t)=>{const o=ne(e);return"input"===o?ri.after(e):D(["br","img"],o)?0===t?ri.before(e):ri.after(e):ri.on(e,t)},Tm=e=>C.from(e.getSelection()),Rm=(e,t)=>{Tm(e).each((e=>{e.removeAllRanges(),e.addRange(t)}))},Dm=(e,t,o,n,r)=>{const s=mi(e,t,o,n,r);Rm(e,s)},Om=(e,t)=>gi(e,t).match({ltr:(t,o,n,r)=>{Dm(e,t,o,n,r)},rtl:(t,o,n,r)=>{Tm(e).each((s=>{if(s.setBaseAndExtent)s.setBaseAndExtent(t.dom,o,n.dom,r);else if(s.extend)try{((e,t,o,n,r,s)=>{t.collapse(o.dom,n),t.extend(r.dom,s)})(0,s,t,o,n,r)}catch(s){Dm(e,n,r,t,o)}else Dm(e,n,r,t,o)}))}}),km=(e,t,o,n,r)=>{const s=((e,t,o,n)=>{const r=Sm(e,t),s=Sm(o,n);return Cm.relative(r,s)})(t,o,n,r);Om(e,s)},Em=(e,t,o)=>{const n=((e,t)=>{const o=e.fold(ri.before,Sm,ri.after),n=t.fold(ri.before,Sm,ri.after);return Cm.relative(o,n)})(t,o);Om(e,n)},Nm=e=>{if(e.rangeCount>0){const t=e.getRangeAt(0),o=e.getRangeAt(e.rangeCount-1);return C.some(pi(xe.fromDom(t.startContainer),t.startOffset,xe.fromDom(o.endContainer),o.endOffset))}return C.none()},_m=e=>{if(null===e.anchorNode||null===e.focusNode)return Nm(e);{const t=xe.fromDom(e.anchorNode),o=xe.fromDom(e.focusNode);return((e,t,o,n)=>{const r=((e,t,o,n)=>{const r=ke(e).dom.createRange();return r.setStart(e.dom,t),r.setEnd(o.dom,n),r})(e,t,o,n),s=Re(e,o)&&t===n;return r.collapsed&&!s})(t,e.anchorOffset,o,e.focusOffset)?C.some(pi(t,e.anchorOffset,o,e.focusOffset)):Nm(e)}},Bm=(e,t,o=!0)=>{const n=(o?ai:li)(e,t);Rm(e,n)},zm=e=>(e=>Tm(e).filter((e=>e.rangeCount>0)).bind(_m))(e).map((e=>Cm.exact(e.start,e.soffset,e.finish,e.foffset))),Am=(e,t,o)=>((e,t,o)=>((e,t,o)=>e.caretPositionFromPoint?((e,t,o)=>{var n;return C.from(null===(n=e.caretPositionFromPoint)||void 0===n?void 0:n.call(e,t,o)).bind((t=>{if(null===t.offsetNode)return C.none();const o=e.createRange();return o.setStart(t.offsetNode,t.offset),o.collapse(),C.some(o)}))})(e,t,o):e.caretRangeFromPoint?((e,t,o)=>{var n;return C.from(null===(n=e.caretRangeFromPoint)||void 0===n?void 0:n.call(e,t,o))})(e,t,o):C.none())(e.document,t,o).map((e=>pi(xe.fromDom(e.startContainer),e.startOffset,xe.fromDom(e.endContainer),e.endOffset))))(e,t,o),Lm=e=>({elementFromPoint:(t,o)=>xe.fromPoint(xe.fromDom(e.document),t,o),getRect:e=>e.dom.getBoundingClientRect(),getRangedRect:(t,o,n,r)=>{const s=Cm.exact(t,o,n,r);return((e,t)=>(e=>{const t=e.getClientRects(),o=t.length>0?t[0]:e.getBoundingClientRect();return o.width>0||o.height>0?C.some(o).map(di):C.none()})(hi(e,t)))(e,s)},getSelection:()=>zm(e).map((t=>wi(e,t))),fromSitus:t=>{const o=Cm.relative(t.start,t.finish);return wi(e,o)},situsFromPoint:(t,o)=>Am(e,t,o).map((e=>bi(e.start,e.soffset,e.finish,e.foffset))),clearSelection:()=>{(e=>{Tm(e).each((e=>e.removeAllRanges()))})(e)},collapseSelection:(t=!1)=>{zm(e).each((o=>o.fold((e=>e.collapse(t)),((o,n)=>{const r=t?o:n;Em(e,r,r)}),((o,n,r,s)=>{const l=t?o:r,a=t?n:s;km(e,l,a,l,a)}))))},setSelection:t=>{km(e,t.start,t.soffset,t.finish,t.foffset)},setRelativeSelection:(t,o)=>{Em(e,t,o)},selectNode:t=>{Bm(e,t,!1)},selectContents:t=>{Bm(e,t)},getInnerHeight:()=>e.innerHeight,getScrollY:()=>(e=>{const t=void 0!==e?e.dom:document,o=t.body.scrollLeft||t.documentElement.scrollLeft,n=t.body.scrollTop||t.documentElement.scrollTop;return bn(o,n)})(xe.fromDom(e.document)).top,scrollBy:(t,o)=>{((e,t,o)=>{const n=(void 0!==o?o.dom:document).defaultView;n&&n.scrollBy(e,t)})(t,o,xe.fromDom(e.document))}}),Wm=(e,t)=>({rows:e,cols:t}),Mm=e=>gt(e,ae).exists(es),jm=(e,t)=>Mm(e)||Mm(t),Pm=e=>void 0!==e.dom.classList,Im=(e,t)=>((e,t,o)=>{const n=((e,t)=>{const o=pe(e,t);return void 0===o||""===o?[]:o.split(" ")})(e,t).concat([o]);return ge(e,t,n.join(" ")),!0})(e,"class",t),Fm=(e,t)=>{Pm(e)?e.dom.classList.add(t):Im(e,t)},Hm=(e,t)=>Pm(e)&&e.dom.classList.contains(t),$m=()=>({tag:"none"}),Vm=e=>({tag:"multiple",elements:e}),qm=e=>({tag:"single",element:e}),Um=e=>{const t=xe.fromDom((e=>{if(m(e.target)){const t=xe.fromDom(e.target);if(ce(t)&&m(t.dom.shadowRoot)&&e.composed&&e.composedPath){const t=e.composedPath();if(t)return H(t)}}return C.from(e.target)})(e).getOr(e.target)),o=()=>e.stopPropagation(),n=()=>e.preventDefault(),r=(s=n,l=o,(...e)=>s(l.apply(null,e)));var s,l;return((e,t,o,n,r,s,l)=>({target:e,x:t,y:o,stop:n,prevent:r,kill:s,raw:l}))(t,e.clientX,e.clientY,o,n,r,e)},Gm=(e,t,o,n)=>{e.dom.removeEventListener(t,o,n)},Km=x,Ym=(e,t,o)=>((e,t,o,n)=>((e,t,o,n,r)=>{const s=((e,t)=>o=>{e(o)&&t(Um(o))})(o,n);return e.dom.addEventListener(t,s,r),{unbind:b(Gm,e,t,s,r)}})(e,t,o,n,!1))(e,t,Km,o),Jm=Um,Qm=e=>!Hm(xe.fromDom(e.target),"ephox-snooker-resizer-bar"),Xm=(e,t)=>{const o=(r=Is.selectedSelector,{get:()=>_s(xe.fromDom(e.getBody()),r).fold((()=>Vs(ss(e),ns(e)).fold($m,qm)),Vm)}),n=((e,t,o)=>{const n=t=>{we(t,e.selected),we(t,e.firstSelected),we(t,e.lastSelected)},r=t=>{ge(t,e.selected,"1")},s=e=>{l(e),o()},l=t=>{const o=dt(t,`${e.selectedSelector},${e.firstSelectedSelector},${e.lastSelectedSelector}`);N(o,n)};return{clearBeforeUpdate:l,clear:s,selectRange:(o,n,l,a)=>{s(o),N(n,r),ge(l,e.firstSelected,"1"),ge(a,e.lastSelected,"1"),t(n,l,a)},selectedSelector:e.selectedSelector,firstSelectedSelector:e.firstSelectedSelector,lastSelectedSelector:e.lastSelectedSelector}})(Is,((t,o,n)=>{Gt(o).each((r=>{const s=E(t,(e=>e.dom)),l=Wr(e),a=_r(f,xe.fromDom(e.getDoc()),l),c=((e,t,o)=>{const n=Xo(e);return zl(n,t).map((e=>{const t=Ol(n,o,!1),{rows:r}=Vo(t),s=((e,t)=>{const o=e.slice(0,t[t.length-1].row+1),n=kl(o);return j(n,(e=>{const o=e.cells.slice(0,t[t.length-1].column+1);return E(o,(e=>e.element))}))})(r,e),l=((e,t)=>{const o=e.slice(t[0].row+t[0].rowspan-1,e.length),n=kl(o);return j(n,(e=>{const o=e.cells.slice(t[0].column+t[0].colspan-1,e.cells.length);return E(o,(e=>e.element))}))})(r,e);return{upOrLeftCells:s,downOrRightCells:l}}))})(r,{selection:qs(e)},a).map((e=>K(e,(e=>E(e,(e=>e.dom)))))).getOrUndefined();((e,t,o,n,r)=>{e.dispatch("TableSelectionChange",{cells:t,start:o,finish:n,otherCells:r})})(e,s,o.dom,n.dom,c)}))}),(()=>(e=>{e.dispatch("TableSelectionClear")})(e)));var r;return e.on("init",(o=>{const r=e.getWin(),s=os(e),l=ns(e),a=((e,t,o,n)=>{const r=((e,t,o,n)=>{const r=mm(),s=r.clear,l=s=>{r.on((r=>{n.clearBeforeUpdate(t),dm(s.target,o).each((l=>{Os(r,l,o).each((o=>{const r=o.boxes.getOr([]);if(1===r.length){const e=r[0],o="false"===ts(e),l=vt(Zr(s.target),e,Re);o&&l&&n.selectRange(t,r,e,e)}else r.length>1&&(n.selectRange(t,r,o.start,o.finish),e.selectContents(l))}))}))}))};return{clearstate:s,mousedown:e=>{n.clear(t),dm(e.target,o).filter(um).each(r.set)},mouseover:e=>{l(e)},mouseup:e=>{l(e),s()}}})(Lm(e),t,o,n);return{clearstate:r.clearstate,mousedown:r.mousedown,mouseover:r.mouseover,mouseup:r.mouseup}})(r,s,l,n),c=((e,t,o,n)=>{const r=Lm(e),s=()=>(n.clear(t),C.none());return{keydown:(e,l,a,c,i,m)=>{const d=e.raw,u=d.which,f=!0===d.shiftKey,g=ks(t,n.selectedSelector).fold((()=>(wm(u)&&!f&&n.clearBeforeUpdate(t),wm(u)&&f&&!jm(l,c)?C.none:bm(u)&&f?b(cm,r,t,o,fm,c,l,n.selectRange):pm(u)&&f?b(cm,r,t,o,gm,c,l,n.selectRange):bm(u)?b(sm,r,o,fm,c,l,am):pm(u)?b(sm,r,o,gm,c,l,lm):C.none)),(e=>{const o=o=>()=>{const s=V(o,(o=>((e,t,o,n,r)=>Ns(n,e,t,r.firstSelectedSelector,r.lastSelectedSelector).map((e=>(r.clearBeforeUpdate(o),r.selectRange(o,e.boxes,e.start,e.finish),e.boxes))))(o.rows,o.cols,t,e,n)));return s.fold((()=>Es(t,n.firstSelectedSelector,n.lastSelectedSelector).map((e=>{const o=bm(u)||m.isForward(u)?ri.after:ri.before;return r.setRelativeSelection(ri.on(e.first,0),o(e.table)),n.clear(t),si(C.none(),!0)}))),(e=>C.some(si(C.none(),!0))))};return wm(u)&&f&&!jm(l,c)?C.none:bm(u)&&f?o([Wm(1,0)]):pm(u)&&f?o([Wm(-1,0)]):m.isBackward(u)&&f?o([Wm(0,-1),Wm(-1,0)]):m.isForward(u)&&f?o([Wm(0,1),Wm(1,0)]):wm(u)&&!f?s:C.none}));return g()},keyup:(e,r,s,l,a)=>ks(t,n.selectedSelector).fold((()=>{const c=e.raw,i=c.which;return!0===c.shiftKey&&wm(i)&&jm(r,l)?((e,t,o,n,r,s,l)=>Re(o,r)&&n===s?C.none():wt(o,"td,th",t).bind((o=>wt(r,"td,th",t).bind((n=>yi(e,t,o,n,l))))))(t,o,r,s,l,a,n.selectRange):C.none()}),C.none)}})(r,s,l,n),i=((e,t,o,n)=>{const r=Lm(e);return(e,s)=>{n.clearBeforeUpdate(t),Os(e,s,o).each((e=>{const o=e.boxes.getOr([]);n.selectRange(t,o,e.start,e.finish),r.selectContents(s),r.collapseSelection()}))}})(r,s,l,n);e.on("TableSelectorChange",(e=>i(e.start,e.finish)));const m=(t,o)=>{(e=>!0===e.raw.shiftKey)(t)&&(o.kill&&t.kill(),o.selection.each((t=>{const o=Cm.relative(t.start,t.finish),n=hi(r,o);e.selection.setRng(n)})))},d=e=>0===e.button,u=(()=>{const e=im(xe.fromDom(s)),t=im(0);return{touchEnd:o=>{const n=xe.fromDom(o.target);if(ue("td")(n)||ue("th")(n)){const r=e.get(),s=t.get();Re(r,n)&&o.timeStamp-s<300&&(o.preventDefault(),i(n,n))}e.set(n),t.set(o.timeStamp)}}})();e.on("dragstart",(e=>{a.clearstate()})),e.on("mousedown",(e=>{d(e)&&Qm(e)&&a.mousedown(Jm(e))})),e.on("mouseover",(e=>{var t;(void 0===(t=e).buttons||1&t.buttons)&&Qm(e)&&a.mouseover(Jm(e))})),e.on("mouseup",(e=>{d(e)&&Qm(e)&&a.mouseup(Jm(e))})),e.on("touchend",u.touchEnd),e.on("keyup",(t=>{const o=Jm(t);if(o.raw.shiftKey&&wm(o.raw.which)){const t=e.selection.getRng(),n=xe.fromDom(t.startContainer),r=xe.fromDom(t.endContainer);c.keyup(o,n,t.startOffset,r,t.endOffset).each((e=>{m(o,e)}))}})),e.on("keydown",(o=>{const n=Jm(o);t.hide();const r=e.selection.getRng(),s=xe.fromDom(r.startContainer),l=xe.fromDom(r.endContainer),a=dn(vm,ym)(xe.fromDom(e.selection.getStart()));c.keydown(n,s,r.startOffset,l,r.endOffset,a).each((e=>{m(n,e)})),t.show()})),e.on("NodeChange",(()=>{const t=e.selection,o=xe.fromDom(t.getStart()),r=xe.fromDom(t.getEnd());Rs(Gt,[o,r]).fold((()=>n.clear(s)),f)}))})),e.on("PreInit",(()=>{e.serializer.addTempAttr(Is.firstSelected),e.serializer.addTempAttr(Is.lastSelected)})),{getSelectedCells:()=>((e,t)=>{switch(e.tag){case"none":return t();case"single":return(e=>[e.dom])(e.element);case"multiple":return(e=>E(e,(e=>e.dom)))(e.elements)}})(o.get(),g([])),clearSelectedCells:e=>n.clear(xe.fromDom(e))}},Zm=e=>{let t=[];return{bind:e=>{if(void 0===e)throw new Error("Event bind error: undefined handler");t.push(e)},unbind:e=>{t=B(t,(t=>t!==e))},trigger:(...o)=>{const n={};N(e,((e,t)=>{n[e]=o[t]})),N(t,(e=>{e(n)}))}}},ed=e=>({registry:K(e,(e=>({bind:e.bind,unbind:e.unbind}))),trigger:K(e,(e=>e.trigger))}),td=e=>e.slice(0).sort(),od=(e,t)=>{const o=B(t,(t=>!D(e,t)));o.length>0&&(e=>{throw new Error("Unsupported keys for object: "+td(e).join(", "))})(o)},nd=e=>((e,t)=>((e,t,o)=>{if(0===t.length)throw new Error("You must specify at least one required field.");return((e,t)=>{if(!l(t))throw new Error("The "+e+" fields must be an array. Was: "+t+".");N(t,(t=>{if(!r(t))throw new Error("The value "+t+" in the "+e+" fields was not a string.")}))})("required",t),(e=>{const t=td(e);L(t,((e,o)=>o{throw new Error("The field: "+e+" occurs more than once in the combined fields: ["+t.join(", ")+"].")}))})(t),n=>{const r=q(n);P(t,(e=>D(r,e)))||((e,t)=>{throw new Error("All required keys ("+td(e).join(", ")+") were not specified. Specified keys were: "+td(t).join(", ")+".")})(t,r),e(t,r);const s=B(t,(e=>!o.validate(n[e],e)));return s.length>0&&((e,t)=>{throw new Error("All values need to be of type: "+t+". Keys ("+td(e).join(", ")+") were not.")})(s,o.label),n}})(e,t,{validate:d,label:"function"}))(od,e),rd=nd(["compare","extract","mutate","sink"]),sd=nd(["element","start","stop","destroy"]),ld=nd(["forceDrop","drop","move","delayDrop"]),ad=()=>{const e=(()=>{const e=ed({move:Zm(["info"])});return{onEvent:f,reset:f,events:e.registry}})(),t=(()=>{let e=C.none();const t=ed({move:Zm(["info"])});return{onEvent:(o,n)=>{n.extract(o).each((o=>{const r=((t,o)=>{const n=e.map((e=>t.compare(e,o)));return e=C.some(o),n})(n,o);r.each((e=>{t.trigger.move(e)}))}))},reset:()=>{e=C.none()},events:t.registry}})();let o=e;return{on:()=>{o.reset(),o=t},off:()=>{o.reset(),o=e},isOn:()=>o===t,onEvent:(e,t)=>{o.onEvent(e,t)},events:t.events}},cd=e=>{const t=e.replace(/\./g,"-");return{resolve:e=>t+"-"+e}},id=cd("ephox-dragster").resolve;var md=rd({compare:(e,t)=>bn(t.left-e.left,t.top-e.top),extract:e=>C.some(bn(e.x,e.y)),sink:(e,t)=>{const o=(e=>{const t={layerClass:id("blocker"),...e},o=xe.fromTag("div");return ge(o,"role","presentation"),_t(o,{position:"fixed",left:"0px",top:"0px",width:"100%",height:"100%"}),Fm(o,id("blocker")),Fm(o,t.layerClass),{element:g(o),destroy:()=>{qe(o)}}})(t),n=Ym(o.element(),"mousedown",e.forceDrop),r=Ym(o.element(),"mouseup",e.drop),s=Ym(o.element(),"mousemove",e.move),l=Ym(o.element(),"mouseout",e.delayDrop);return sd({element:o.element,start:e=>{Ie(e,o.element())},stop:()=>{qe(o.element())},destroy:()=>{o.destroy(),r.unbind(),s.unbind(),l.unbind(),n.unbind()}})},mutate:(e,t)=>{e.mutate(t.left,t.top)}});const dd=cd("ephox-snooker").resolve,ud=dd("resizer-bar"),fd=dd("resizer-rows"),gd=dd("resizer-cols"),hd=e=>{const t=dt(e.parent(),"."+ud);N(t,qe)},pd=(e,t,o)=>{const n=e.origin();N(t,(t=>{t.each((t=>{const r=o(n,t);Fm(r,ud),Ie(e.parent(),r)}))}))},bd=(e,t,o,n,r)=>{const s=vn(o),l=t.isResizable,a=n.length>0?_n.positions(n,o):[],c=a.length>0?((e,t)=>j(e.all,((e,o)=>t(e.element)?[o]:[])))(e,l):[];((e,t,o,n)=>{pd(e,t,((e,t)=>{const r=((e,t,o,n)=>{const r=xe.fromTag("div");return _t(r,{position:"absolute",left:t+"px",top:o-3.5+"px",height:"7px",width:n+"px"}),he(r,{"data-row":e,role:"presentation"}),r})(t.row,o.left-e.left,t.y-e.top,n);return Fm(r,fd),r}))})(t,B(a,((e,t)=>O(c,(e=>t===e)))),s,Lo(o));const i=r.length>0?zn.positions(r,o):[],m=i.length>0?((e,t)=>{const o=[];return k(e.grid.columns,(n=>{ln(e,n).map((e=>e.element)).forall(t)&&o.push(n)})),B(o,(o=>{const n=on(e,(e=>e.column===o));return P(n,(e=>t(e.element)))}))})(e,l):[];((e,t,o,n)=>{pd(e,t,((e,t)=>{const r=((e,t,o,n,r)=>{const s=xe.fromTag("div");return _t(s,{position:"absolute",left:t-3.5+"px",top:o+"px",height:r+"px",width:"7px"}),he(s,{"data-column":e,role:"presentation"}),s})(t.col,t.x-e.left,o.top-e.top,0,n);return Fm(r,gd),r}))})(t,B(i,((e,t)=>O(m,(e=>t===e)))),s,hn(o))},wd=(e,t)=>{if(hd(e),e.isResizable(t)){const o=Xo(t),n=mn(o),r=an(o);bd(o,e,t,n,r)}},vd=(e,t)=>{const o=dt(e.parent(),"."+ud);N(o,t)},yd=e=>{vd(e,(e=>{Nt(e,"display","none")}))},xd=e=>{vd(e,(e=>{Nt(e,"display","block")}))},Cd=dd("resizer-bar-dragging"),Sd=e=>{const t=(()=>{const e=ed({drag:Zm(["xDelta","yDelta","target"])});let t=C.none();const o=(()=>{const e=ed({drag:Zm(["xDelta","yDelta"])});return{mutate:(t,o)=>{e.trigger.drag(t,o)},events:e.registry}})();return o.events.drag.bind((o=>{t.each((t=>{e.trigger.drag(o.xDelta,o.yDelta,t)}))})),{assign:e=>{t=C.some(e)},get:()=>t,mutate:o.mutate,events:e.registry}})(),o=((e,t={})=>{var o;return((e,t,o)=>{let n=!1;const r=ed({start:Zm([]),stop:Zm([])}),s=ad(),l=()=>{m.stop(),s.isOn()&&(s.off(),r.trigger.stop())},c=(e=>{let t=null;const o=()=>{a(t)||(clearTimeout(t),t=null)};return{cancel:o,throttle:(...n)=>{o(),t=setTimeout((()=>{t=null,e.apply(null,n)}),200)}}})(l);s.events.move.bind((o=>{t.mutate(e,o.info)}));const i=e=>(...t)=>{n&&e.apply(null,t)},m=t.sink(ld({forceDrop:l,drop:i(l),move:i((e=>{c.cancel(),s.onEvent(e,t)})),delayDrop:i(c.throttle)}),o);return{element:m.element,go:e=>{m.start(e),s.on(),r.trigger.start()},on:()=>{n=!0},off:()=>{n=!1},isActive:()=>n,destroy:()=>{m.destroy()},events:r.registry}})(e,null!==(o=t.mode)&&void 0!==o?o:md,t)})(t,{});let n=C.none();const r=(e,t)=>C.from(pe(e,t));t.events.drag.bind((e=>{r(e.target,"data-row").each((t=>{const o=Pt(e.target,"top");Nt(e.target,"top",o+e.yDelta+"px")})),r(e.target,"data-column").each((t=>{const o=Pt(e.target,"left");Nt(e.target,"left",o+e.xDelta+"px")}))}));const s=(e,t)=>Pt(e,t)-Wt(e,"data-initial-"+t,0);o.events.stop.bind((()=>{t.get().each((t=>{n.each((o=>{r(t,"data-row").each((e=>{const n=s(t,"top");we(t,"data-initial-top"),d.trigger.adjustHeight(o,n,parseInt(e,10))})),r(t,"data-column").each((e=>{const n=s(t,"left");we(t,"data-initial-left"),d.trigger.adjustWidth(o,n,parseInt(e,10))})),wd(e,o)}))}))}));const l=(n,r)=>{d.trigger.startAdjust(),t.assign(n),ge(n,"data-initial-"+r,Pt(n,r)),Fm(n,Cd),Nt(n,"opacity","0.2"),o.go(e.dragContainer())},c=Ym(e.parent(),"mousedown",(e=>{var t;t=e.target,Hm(t,fd)&&l(e.target,"top"),(e=>Hm(e,gd))(e.target)&&l(e.target,"left")})),i=t=>Re(t,e.view()),m=Ym(e.view(),"mouseover",(t=>{var r;(r=t.target,wt(r,"table",i).filter(es)).fold((()=>{st(t.target)&&hd(e)}),(t=>{o.isActive()&&(n=C.some(t),wd(e,t))}))})),d=ed({adjustHeight:Zm(["table","delta","row"]),adjustWidth:Zm(["table","delta","column"]),startAdjust:Zm([])});return{destroy:()=>{c.unbind(),m.unbind(),o.destroy(),hd(e)},refresh:t=>{wd(e,t)},on:o.on,off:o.off,hideBars:b(yd,e),showBars:b(xd,e),events:d.registry}};let Td=0;const Rd=(e,t)=>{const o=(e=>!(e=>e.inline&&(e=>{var t;if(!e.inline)return C.none();const o=null!==(t=Jr(e))&&void 0!==t?t:"";if(o.length>0)return bt(lt(),o);const n=Qr(e);return m(n)?C.some(xe.fromDom(n)):C.none()})(e).isSome())(e)&&"split"===Xr(e))(e),n=xe.fromDom(e.getBody()),r=(e=>{const t=(e=>{const t=(new Date).getTime(),o=Math.floor(window.crypto.getRandomValues(new Uint32Array(1))[0]/4294967295*1e9);return Td++,e+"_"+o+Td+String(t)})("resizer-container"),o=xe.fromTag("div");return ge(o,"id",t),_t(o,{position:e,height:"0",width:"0",padding:"0",margin:"0",border:"0"}),o})(o?"relative":"static"),s=lt();return o?(je(n,r),((e,t,o,n)=>({parent:g(t),view:g(e),dragContainer:g(o),origin:()=>vn(t),isResizable:n}))(n,r,s,t)):(Ie(s,r),((e,t,o)=>({parent:g(t),view:g(e),dragContainer:g(t),origin:g(bn(0,0)),isResizable:o}))(n,r,t))},Dd=e=>m(e)&&"TABLE"===e.nodeName,Od="bar-",kd=e=>"false"!==pe(e,"data-mce-resize"),Ed=e=>{const t=mm(),o=mm(),n=mm();let r,s,l,a;const c=t=>wc(e,t),i=()=>Pr(e)?ll():sl(),m=(t,o,n,m)=>{const d=(e=>{return Tt(t=e,"corner-")?(e=>e.substring(7))(t):t;var t})(o),u=Rt(d,"e"),f=Tt(d,"n");if(""===s&&Lc(t),""===a&&(e=>{const t=(e=>gn(e)+"px")(e);Nc(e,C.none(),C.some(t)),Ac(e)})(t),n!==r&&""!==s){Nt(t,"width",s);const o=i(),l=c(t),a=Pr(e)||u?(e=>al(e).columns)(t)-1:0;ca(t,n-r,a,o,l)}else if((e=>/^(\d+(\.\d+)?)%$/.test(e))(s)){const e=parseFloat(s.replace("%",""));Nt(t,"width",n*e/r+"%")}if((e=>/^(\d+(\.\d+)?)px$/.test(e))(s)&&(e=>{const t=Xo(e);sn(t)||N(qt(e),(e=>{const t=Bt(e,"width");Nt(e,"width",t),we(e,"width")}))})(t),m!==l&&""!==a){Nt(t,"height",a);const e=f?0:(e=>al(e).rows)(t)-1;ia(t,m-l,e)}};e.on("init",(()=>{const r=((e,t)=>e.inline?Rd(e,t):((e,t)=>{const o=me(e)?(e=>xe.fromDom(Ee(e).dom.documentElement))(e):e;return{parent:g(o),view:g(e),dragContainer:g(o),origin:g(bn(0,0)),isResizable:t}})(xe.fromDom(e.getDoc()),t))(e,kd);if(n.set(r),(e=>{const t=e.options.get("object_resizing");return D(t.split(","),"table")})(e)&&qr(e)){const n=((e,t,o)=>{const n=_n,r=zn,s=Sd(e),l=ed({beforeResize:Zm(["table","type"]),afterResize:Zm(["table","type"]),startDrag:Zm([])});return s.events.adjustHeight.bind((e=>{const t=e.table;l.trigger.beforeResize(t,"row");const o=n.delta(e.delta,t);ia(t,o,e.row),l.trigger.afterResize(t,"row")})),s.events.startAdjust.bind((e=>{l.trigger.startDrag()})),s.events.adjustWidth.bind((e=>{const n=e.table;l.trigger.beforeResize(n,"col");const s=r.delta(e.delta,n),a=o(n);ca(n,s,e.column,t,a),l.trigger.afterResize(n,"col")})),{on:s.on,off:s.off,refreshBars:s.refresh,hideBars:s.hideBars,showBars:s.showBars,destroy:s.destroy,events:l.registry}})(r,i(),c);e.mode.isReadOnly()||n.on(),n.events.startDrag.bind((o=>{t.set(e.selection.getRng())})),n.events.beforeResize.bind((t=>{const o=t.table.dom;((e,t,o,n,r)=>{e.dispatch("ObjectResizeStart",{target:t,width:o,height:n,origin:r})})(e,o,ls(o),as(o),Od+t.type)})),n.events.afterResize.bind((o=>{const n=o.table,r=n.dom;rs(n),t.on((t=>{e.selection.setRng(t),e.focus()})),((e,t,o,n,r)=>{e.dispatch("ObjectResized",{target:t,width:o,height:n,origin:r})})(e,r,ls(r),as(r),Od+o.type),e.undoManager.add()})),o.set(n)}})),e.on("ObjectResizeStart",(t=>{const o=t.target;if(Dd(o)&&!e.mode.isReadOnly()){const n=xe.fromDom(o);N(e.dom.select(".mce-clonedresizable"),(t=>{e.dom.addClass(t,"mce-"+jr(e)+"-columns")})),!Bc(n)&&$r(e)?Wc(n):!_c(n)&&Hr(e)&&Lc(n),zc(n)&&Tt(t.origin,Od)&&Lc(n),r=t.width,s=Vr(e)?"":is(e,o).getOr(""),l=t.height,a=ms(e,o).getOr("")}})),e.on("ObjectResized",(t=>{const o=t.target;if(Dd(o)){const n=xe.fromDom(o),r=t.origin;(e=>Tt(e,"corner-"))(r)&&m(n,r,t.width,t.height),rs(n),gc(e,n.dom,hc)}}));const d=()=>{o.on((e=>{e.on(),e.showBars()}))},u=()=>{o.on((e=>{e.off(),e.hideBars()}))};return e.on("DisabledStateChange",(e=>{e.state?u():d()})),e.on("SwitchMode",(()=>{e.mode.isReadOnly()?u():d()})),e.on("dragstart dragend",(e=>{"dragstart"===e.type?u():d()})),e.on("remove",(()=>{o.on((e=>{e.destroy()})),n.on((t=>{((e,t)=>{e.inline&&qe(t.parent())})(e,t)}))})),{refresh:e=>{o.on((t=>t.refreshBars(xe.fromDom(e))))},hide:()=>{o.on((e=>e.hideBars()))},show:()=>{o.on((e=>e.showBars()))}}},Nd=e=>{(e=>{const t=e.options.register;t("table_clone_elements",{processor:"string[]"}),t("table_use_colgroups",{processor:"boolean",default:!0}),t("table_header_type",{processor:e=>{const t=D(["section","cells","sectionCells","auto"],e);return t?{value:e,valid:t}:{valid:!1,message:"Must be one of: section, cells, sectionCells or auto."}},default:"section"}),t("table_sizing_mode",{processor:"string",default:"auto"}),t("table_default_attributes",{processor:"object",default:{border:"1"}}),t("table_default_styles",{processor:"object",default:{"border-collapse":"collapse"}}),t("table_column_resizing",{processor:e=>{const t=D(["preservetable","resizetable"],e);return t?{value:e,valid:t}:{valid:!1,message:"Must be preservetable, or resizetable."}},default:"preservetable"}),t("table_resize_bars",{processor:"boolean",default:!0}),t("table_style_by_css",{processor:"boolean",default:!0}),t("table_merge_content_on_paste",{processor:"boolean",default:!0})})(e);const t=Ed(e),o=Xm(e,t),n=vc(e,t,o);return oi(e,n),((e,t)=>{const o=ns(e),n=t=>Vs(ss(e)).bind((n=>Gt(n,o).map((o=>{const r=Fs(qs(e),o,n);return t(o,r)})))).getOr("");G({mceTableRowType:()=>n(t.getTableRowType),mceTableCellType:()=>n(t.getTableCellType),mceTableColType:()=>n(t.getTableColType)},((t,o)=>e.addQueryValueHandler(o,t)))})(e,n),Us(e,n),{getSelectedCells:o.getSelectedCells,clearSelectedCells:o.clearSelectedCells}};e.add("dom",(e=>({table:Nd(e)})))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/accordion/plugin.min.js b/apps/web-antd/public/tinymce/plugins/accordion/plugin.min.js new file mode 100644 index 0000000..3c88604 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/accordion/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");let t=0;const o=e=>t=>typeof t===e,n=e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(o=n=e,(r=String).prototype.isPrototypeOf(o)||(null===(s=n.constructor)||void 0===s?void 0:s.name)===r.name)?"string":t;var o,n,r,s})(e),r=o("boolean"),s=e=>null==e,i=e=>!s(e),a=o("function"),d=o("number"),l=e=>()=>e,c=(e,t)=>e===t,m=l(!1);class u{constructor(e,t){this.tag=e,this.value=t}static some(e){return new u(!0,e)}static none(){return u.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?u.some(e(this.value)):u.none()}bind(e){return this.tag?e(this.value):u.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:u.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return i(e)?u.some(e):u.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}u.singletonNone=new u(!1);const g=Array.prototype.indexOf,p=(e,t)=>{return o=e,n=t,g.call(o,n)>-1;var o,n},h=(e,t)=>{const o=e.length,n=new Array(o);for(let r=0;r{for(let o=0,n=e.length;oe.dom.nodeName.toLowerCase(),w=e=>e.dom.nodeType,b=e=>t=>w(t)===e,N=b(1),T=b(3),A=b(9),C=b(11),S=(e,t,o)=>{if(!(n(o)||r(o)||d(o)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",o,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,o+"")},x=(e,t)=>{const o=e.dom.getAttribute(t);return null===o?void 0:o},D=(e,t)=>u.from(x(e,t)),E=(e,t)=>{e.dom.removeAttribute(t)},O=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},M={fromHtml:(e,t)=>{const o=(t||document).createElement("div");if(o.innerHTML=e,!o.hasChildNodes()||o.childNodes.length>1){const t="HTML does not have a single root node";throw console.error(t,e),new Error(t)}return O(o.childNodes[0])},fromTag:(e,t)=>{const o=(t||document).createElement(e);return O(o)},fromText:(e,t)=>{const o=(t||document).createTextNode(e);return O(o)},fromDom:O,fromPoint:(e,t,o)=>u.from(e.dom.elementFromPoint(t,o)).map(O)},P=(e,t)=>{const o=e.dom;if(1!==o.nodeType)return!1;{const e=o;if(void 0!==e.matches)return e.matches(t);if(void 0!==e.msMatchesSelector)return e.msMatchesSelector(t);if(void 0!==e.webkitMatchesSelector)return e.webkitMatchesSelector(t);if(void 0!==e.mozMatchesSelector)return e.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}},R=e=>1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType||0===e.childElementCount,k=P,B=(L=/^\s+|\s+$/g,e=>e.replace(L,""));var L;const $=e=>void 0!==e.style&&a(e.style.getPropertyValue),V=e=>u.from(e.dom.parentNode).map(M.fromDom),I=e=>u.from(e.dom.nextSibling).map(M.fromDom),j=e=>h(e.dom.childNodes,M.fromDom),q=e=>M.fromDom(e.dom.host),F=e=>{const t=T(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;const o=t.ownerDocument;return(e=>{const t=(e=>M.fromDom(e.dom.getRootNode()))(e);return C(o=t)&&i(o.dom.host)?u.some(t):u.none();var o})(M.fromDom(t)).fold((()=>o.body.contains(t)),(n=F,r=q,e=>n(r(e))));var n,r},H=(e,t)=>$(e)?e.style.getPropertyValue(t):"",z=(e,t)=>{V(e).each((o=>{o.dom.insertBefore(t.dom,e.dom)}))},K=(e,t)=>{I(e).fold((()=>{V(e).each((e=>{U(e,t)}))}),(e=>{z(e,t)}))},U=(e,t)=>{e.dom.appendChild(t.dom)},Y=(e,t)=>{f(t,((o,n)=>{const r=0===n?e:t[n-1];K(r,o)}))},_=(e,t)=>{let o=[];return f(j(e),(e=>{t(e)&&(o=o.concat([e])),o=o.concat(_(e,t))})),o},G=(e,t,o)=>{let n=e.dom;const r=a(o)?o:m;for(;n.parentNode;){n=n.parentNode;const e=M.fromDom(n);if(t(e))return u.some(e);if(r(e))break}return u.none()},J=e=>{const t=e.dom;null!==t.parentNode&&t.parentNode.removeChild(t)},Q=(e,t,o)=>G(e,(e=>P(e,t)),o),W=(e,t)=>((e,t)=>{const o=void 0===t?document:t.dom;return R(o)?u.none():u.from(o.querySelector(e)).map(M.fromDom)})(t,e),X=(e=>{const t=t=>e(t)?u.from(t.dom.nodeValue):u.none();return{get:o=>{if(!e(o))throw new Error("Can only get text value of a text node");return t(o).getOr("")},getOption:t,set:(t,o)=>{if(!e(t))throw new Error("Can only set raw text value of a text node");t.dom.nodeValue=o}}})(T);var Z=["body","p","div","article","aside","figcaption","figure","footer","header","nav","section","ol","ul","li","table","thead","tbody","tfoot","caption","tr","td","th","h1","h2","h3","h4","h5","h6","blockquote","pre","address"];const ee=(e,t)=>({element:e,offset:t}),te=(e,t,o)=>e.property().isText(t)&&0===e.property().getText(t).trim().length||e.property().isComment(t)?o(t).bind((t=>te(e,t,o).orThunk((()=>u.some(t))))):u.none(),oe=(e,t)=>e.property().isText(t)?e.property().getText(t).length:e.property().children(t).length,ne=(e,t)=>{const o=te(e,t,e.query().prevSibling).getOr(t);if(e.property().isText(o))return ee(o,oe(e,o));const n=e.property().children(o);return n.length>0?ne(e,n[n.length-1]):ee(o,oe(e,o))},re=ne,se={up:l({selector:Q,closest:(e,t,o)=>((e,t,o,n,r)=>((e,t)=>P(e,t))(o,n)?u.some(o):a(r)&&r(o)?u.none():t(o,n,r))(0,Q,e,t,o),predicate:G,all:(e,t)=>{const o=a(t)?t:m;let n=e.dom;const r=[];for(;null!==n.parentNode&&void 0!==n.parentNode;){const e=n.parentNode,t=M.fromDom(e);if(r.push(t),!0===o(t))break;n=e}return r}}),down:l({selector:(e,t)=>((e,t)=>{const o=void 0===t?document:t.dom;return R(o)?[]:h(o.querySelectorAll(e),M.fromDom)})(t,e),predicate:_}),styles:l({get:(e,t)=>{const o=e.dom,n=window.getComputedStyle(o).getPropertyValue(t);return""!==n||F(e)?n:H(o,t)},getRaw:(e,t)=>{const o=e.dom,n=H(o,t);return u.from(n).filter((e=>e.length>0))},set:(e,t,o)=>{((e,t,o)=>{if(!n(o))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",o,":: Element ",e),new Error("CSS value must be a string: "+o);$(e)&&e.style.setProperty(t,o)})(e.dom,t,o)},remove:(e,t)=>{((e,t)=>{$(e)&&e.style.removeProperty(t)})(e.dom,t),((e,t,o=c)=>e.exists((e=>o(e,t))))(D(e,"style").map(B),"")&&E(e,"style")}}),attrs:l({get:x,set:(e,t,o)=>{S(e.dom,t,o)},remove:E,copyTo:(e,t)=>{const o=(n=e.dom.attributes,r=(e,t)=>(e[t.name]=t.value,e),s={},f(n,((e,t)=>{s=r(s,e)})),s);var n,r,s;((e,t)=>{const o=e.dom;((e,t)=>{const o=y(e);for(let n=0,r=o.length;n{S(o,t,e)}))})(t,o)}}),insert:l({before:z,after:K,afterAll:Y,append:U,appendAll:(e,t)=>{f(t,(t=>{U(e,t)}))},prepend:(e,t)=>{(e=>(e=>{const t=e.dom.childNodes;return u.from(t[0]).map(M.fromDom)})(e))(e).fold((()=>{U(e,t)}),(o=>{e.dom.insertBefore(t.dom,o.dom)}))},wrap:(e,t)=>{z(e,t),U(t,e)}}),remove:l({unwrap:e=>{const t=j(e);t.length>0&&Y(e,t),J(e)},remove:J}),create:l({nu:M.fromTag,clone:e=>M.fromDom(e.dom.cloneNode(!1)),text:M.fromText}),query:l({comparePosition:(e,t)=>e.dom.compareDocumentPosition(t.dom),prevSibling:e=>u.from(e.dom.previousSibling).map(M.fromDom),nextSibling:I}),property:l({children:j,name:v,parent:V,document:e=>{return(t=e,A(t)?t:M.fromDom(t.dom.ownerDocument)).dom;var t},isText:T,isComment:e=>8===w(e)||"#comment"===v(e),isElement:N,isSpecial:e=>{const t=v(e);return p(["script","noscript","iframe","noframes","noembed","title","style","textarea","xmp"],t)},getLanguage:e=>N(e)?D(e,"lang"):u.none(),getText:e=>X.get(e),setText:(e,t)=>X.set(e,t),isBoundary:e=>!!N(e)&&("body"===v(e)||p(Z,v(e))),isEmptyTag:e=>!!N(e)&&p(["br","img","hr","input"],v(e)),isNonEditable:e=>N(e)&&"false"===x(e,"contenteditable")}),eq:(e,t)=>e.dom===t.dom,is:k},ie="details",ae="mce-accordion",de="mce-accordion-summary",le="mce-accordion-body",ce="div";var me=tinymce.util.Tools.resolve("tinymce.util.Tools");const ue=e=>"SUMMARY"===(null==e?void 0:e.nodeName),ge=e=>"DETAILS"===(null==e?void 0:e.nodeName),pe=e=>e.hasAttribute("open"),he=e=>{const t=e.selection.getNode();return ue(t)||Boolean(e.dom.getParent(t,ue))},fe=e=>!he(e)&&e.dom.isEditable(e.selection.getNode())&&!e.mode.isReadOnly(),ye=e=>u.from(e.dom.getParent(e.selection.getNode(),ge)),ve=e=>(e.innerHTML='
',e),we=e=>ve(e.dom.create("p")),be=e=>t=>{((e,t)=>{if(ue(null==t?void 0:t.lastChild)){const o=we(e);t.appendChild(o),e.selection.setCursorLocation(o,0)}})(e,t),((e,t)=>{if(!ue(null==t?void 0:t.firstChild)){const o=(e=>ve(e.dom.create("summary")))(e);t.prepend(o),e.selection.setCursorLocation(o,0)}})(e,t)},Ne=e=>{if(!fe(e))return;const o=M.fromDom(e.getBody()),n=(e=>{const o=(new Date).getTime(),n=Math.floor(window.crypto.getRandomValues(new Uint32Array(1))[0]/4294967295*1e9);return t++,e+"_"+n+t+String(o)})("acc"),r=e.dom.encode(e.selection.getRng().toString()||e.translate("Accordion summary...")),s=e.dom.encode(e.translate("Accordion body...")),i=`${r}`,a=`<${ce} class="${le}">

${s}

`;e.undoManager.transact((()=>{e.insertContent([`
`,i,a,"
"].join("")),W(o,`[data-mce-id="${n}"]`).each((t=>{E(t,"data-mce-id"),W(t,"summary").each((t=>{const o=e.dom.createRng(),n=re(se,t);o.setStart(n.element.dom,n.offset),o.setEnd(n.element.dom,n.offset),e.selection.setRng(o)}))}))}))},Te=(e,t)=>{const o=null!=t?t:!pe(e);return o?e.setAttribute("open","open"):e.removeAttribute("open"),o},Ae=e=>{e.addCommand("InsertAccordion",(()=>Ne(e))),e.addCommand("ToggleAccordion",((t,o)=>((e,t)=>{ye(e).each((o=>{((e,t,o)=>{e.dispatch("ToggledAccordion",{element:t,state:o})})(e,o,Te(o,t))}))})(e,o))),e.addCommand("ToggleAllAccordions",((t,o)=>((e,t)=>{const o=Array.from(e.getBody().querySelectorAll("details"));0!==o.length&&(f(o,(e=>Te(e,null!=t?t:!pe(e)))),((e,t,o)=>{e.dispatch("ToggledAllAccordions",{elements:t,state:o})})(e,o,t))})(e,o))),e.addCommand("RemoveAccordion",(()=>(e=>{e.mode.isReadOnly()||ye(e).each((t=>{const{nextSibling:o}=t;o?(e.selection.select(o,!0),e.selection.collapse(!0)):((e,t)=>{const o=we(e);t.insertAdjacentElement("afterend",o),e.selection.setCursorLocation(o,0)})(e,t),t.remove()}))})(e)))};var Ce=tinymce.util.Tools.resolve("tinymce.html.Node");const Se=e=>{var t,o;return null!==(o=null===(t=e.attr("class"))||void 0===t?void 0:t.split(" "))&&void 0!==o?o:[]},xe=(e,t)=>{const o=new Set([...Se(e),...t]),n=Array.from(o);n.length>0&&e.attr("class",n.join(" "))},De=(e,t)=>{const o=(e=>{const o=[];for(let r=0,s=e.length;r0?o.join(" "):null)},Ee=e=>e.name===ie&&p(Se(e),ae),Oe=e=>{const t=e.children();let o,n;const r=[];for(let e=0;e{const t=new Ce("br",1);t.attr("data-mce-bogus","1"),e.empty(),e.append(t)};var Pe=tinymce.util.Tools.resolve("tinymce.util.VK");const Re=e=>{(e=>{e.on("keydown",(t=>{(!t.shiftKey&&t.keyCode===Pe.ENTER&&he(e)||(e=>{const t=e.selection.getRng();return ge(t.startContainer)&&t.collapsed&&0===t.startOffset})(e))&&(t.preventDefault(),e.execCommand("ToggleAccordion"))}))})(e),e.on("ExecCommand",(t=>{const o=t.command.toLowerCase();"delete"!==o&&"forwarddelete"!==o||!(e=>ye(e).isSome())(e)||(e=>{me.each(me.grep(e.dom.select("details",e.getBody())),be(e))})(e)}))};var ke=tinymce.util.Tools.resolve("tinymce.Env");const Be=e=>t=>{const o=()=>t.setEnabled(fe(e));return e.on("NodeChange",o),()=>e.off("NodeChange",o)};e.add("accordion",(e=>{(e=>{const t=()=>e.execCommand("InsertAccordion");e.ui.registry.addButton("accordion",{icon:"accordion",tooltip:"Insert accordion",onSetup:Be(e),onAction:t}),e.ui.registry.addMenuItem("accordion",{icon:"accordion",text:"Accordion",onSetup:Be(e),onAction:t}),e.ui.registry.addToggleButton("accordiontoggle",{icon:"accordion-toggle",tooltip:"Toggle accordion",onAction:()=>e.execCommand("ToggleAccordion")}),e.ui.registry.addToggleButton("accordionremove",{icon:"remove",tooltip:"Delete accordion",onAction:()=>e.execCommand("RemoveAccordion")}),e.ui.registry.addContextToolbar("accordion",{predicate:t=>e.dom.is(t,"details")&&e.getBody().contains(t)&&e.dom.isEditable(t.parentNode),items:"accordiontoggle accordionremove",scope:"node",position:"node"})})(e),Ae(e),Re(e),(e=>{e.on("PreInit",(()=>{const{serializer:t,parser:o}=e;o.addNodeFilter(ie,(e=>{for(let t=0;t0)for(let e=0;e{const t=new Set([de]);for(let o=0;o{ke.browser.isSafari()&&e.on("click",(t=>{if(ue(t.target)){const o=t.target,n=e.selection.getRng();n.collapsed&&n.startContainer===o.parentNode&&0===n.startOffset&&e.selection.setCursorLocation(o,0)}}))})(e)}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/advlist/plugin.min.js b/apps/web-antd/public/tinymce/plugins/advlist/plugin.min.js new file mode 100644 index 0000000..781711d --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/advlist/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=(t,e,s)=>{const r="UL"===e?"InsertUnorderedList":"InsertOrderedList";t.execCommand(r,!1,!1===s?null:{"list-style-type":s})},s=t=>e=>e.options.get(t),r=s("advlist_number_styles"),n=s("advlist_bullet_styles"),l=t=>null==t,i=t=>!l(t);class o{constructor(t,e){this.tag=t,this.value=e}static some(t){return new o(!0,t)}static none(){return o.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?o.some(t(this.value)):o.none()}bind(t){return this.tag?t(this.value):o.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:o.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return i(t)?o.some(t):o.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}o.singletonNone=new o(!1);const a=Array.prototype.indexOf,u=Object.keys;var d=tinymce.util.Tools.resolve("tinymce.util.Tools");const c=t=>e=>i(e)&&t.test(e.nodeName),h=c(/^(OL|UL|DL)$/),g=c(/^(TH|TD)$/),p=t=>l(t)||"default"===t?"":t,m=(t,e)=>s=>((t,e)=>{const s=t.selection.getNode();return e({parents:t.dom.getParents(s),element:s}),t.on("NodeChange",e),()=>t.off("NodeChange",e)})(t,(r=>((t,r)=>{const n=t.selection.getStart(!0);s.setActive(((t,e,s)=>((t,e,s)=>{for(let e=0,n=t.length;ee.nodeName===s&&((t,e)=>t.dom.isChildOf(e,t.getBody()))(t,e))))(t,r,e)),s.setEnabled(!((t,e)=>{const s=t.dom.getParent(e,"ol,ul,dl");return((t,e)=>null!==e&&!t.dom.isEditable(e))(t,s)||!t.selection.isEditable()})(t,n))})(t,r.parents))),v=(t,s,r,n,l,i)=>{const c={"lower-latin":"lower-alpha","upper-latin":"upper-alpha","lower-alpha":"lower-latin","upper-alpha":"upper-latin"},h=(g=t=>{return e=i,s=t,a.call(e,s)>-1;var e,s},((t,e)=>{const s={};return((t,e)=>{const s=u(t);for(let r=0,n=s.length;r{const n=e(t,r);s[n.k]=n.v})),s})(c,((t,e)=>({k:e,v:g(t)}))));var g;t.ui.registry.addSplitButton(s,{tooltip:r,icon:"OL"===l?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:t=>{t(d.map(i,(t=>{const e="OL"===l?"num":"bull",s="disc"===t||"decimal"===t?"default":t,r=p(t),n=(t=>t.replace(/\-/g," ").replace(/\b\w/g,(t=>t.toUpperCase())))(t);return{type:"choiceitem",value:r,icon:"list-"+e+"-"+s,text:n}})))},onAction:()=>t.execCommand(n),onItemAction:(s,r)=>{e(t,l,r)},select:e=>{const s=(t=>{const e=t.dom.getParent(t.selection.getNode(),"ol,ul"),s=t.dom.getStyle(e,"listStyleType");return o.from(s)})(t);return s.exists((t=>e===t||c[t]===e&&!h[e]))},onSetup:m(t,l)})},y=(t,s,r,n,l,i)=>{i.length>1?v(t,s,r,n,l,i):((t,s,r,n,l,i)=>{t.ui.registry.addToggleButton(s,{active:!1,tooltip:r,icon:"OL"===l?"ordered-list":"unordered-list",onSetup:m(t,l),onAction:()=>t.queryCommandState(n)||""===i?t.execCommand(n):e(t,l,i)})})(t,s,r,n,l,p(i[0]))};t.add("advlist",(t=>{t.hasPlugin("lists")?((t=>{const e=t.options.register;e("advlist_number_styles",{processor:"string[]",default:"default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman".split(",")}),e("advlist_bullet_styles",{processor:"string[]",default:"default,circle,square".split(",")})})(t),(t=>{y(t,"numlist","Numbered list","InsertOrderedList","OL",r(t)),y(t,"bullist","Bullet list","InsertUnorderedList","UL",n(t))})(t),(t=>{t.addCommand("ApplyUnorderedListStyle",((s,r)=>{e(t,"UL",r["list-style-type"])})),t.addCommand("ApplyOrderedListStyle",((s,r)=>{e(t,"OL",r["list-style-type"])}))})(t)):console.error("Please use the Lists plugin together with the List Styles plugin.")}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/anchor/plugin.min.js b/apps/web-antd/public/tinymce/plugins/anchor/plugin.min.js new file mode 100644 index 0000000..3c944ed --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/anchor/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=e=>e.options.get("allow_html_in_named_anchor");const a="a:not([href])",r=e=>!e,i=e=>e.getAttribute("id")||e.getAttribute("name")||"",l=e=>(e=>"a"===e.nodeName.toLowerCase())(e)&&!e.getAttribute("href")&&""!==i(e),s=e=>e.dom.getParent(e.selection.getStart(),a),d=(e,a)=>{const r=s(e);r?((e,t,o)=>{o.removeAttribute("name"),o.id=t,e.addVisual(),e.undoManager.add()})(e,a,r):((e,a)=>{e.undoManager.transact((()=>{n(e)||e.selection.collapse(!0),e.selection.isCollapsed()?e.insertContent(e.dom.createHTML("a",{id:a})):((e=>{const n=e.dom;t(n).walk(e.selection.getRng(),(e=>{o.each(e,(e=>{var t;l(t=e)&&!t.firstChild&&n.remove(e,!1)}))}))})(e),e.formatter.remove("namedAnchor",void 0,void 0,!0),e.formatter.apply("namedAnchor",{value:a}),e.addVisual())}))})(e,a),e.focus()},c=e=>(e=>r(e.attr("href"))&&!r(e.attr("id")||e.attr("name")))(e)&&!e.firstChild,m=e=>t=>{for(let o=0;ot=>{const o=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",o),o(),()=>{e.off("NodeChange",o)}};e.add("anchor",(e=>{(e=>{(0,e.options.register)("allow_html_in_named_anchor",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreInit",(()=>{e.parser.addNodeFilter("a",m("false")),e.serializer.addNodeFilter("a",m(null))}))})(e),(e=>{e.addCommand("mceAnchor",(()=>{(e=>{const t=(e=>{const t=s(e);return t?i(t):""})(e);e.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:t},onSubmit:t=>{((e,t)=>/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(t)?(d(e,t),!0):(e.windowManager.alert("ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),!1))(e,t.getData().id)&&t.close()}})})(e)}))})(e),(e=>{const t=()=>e.execCommand("mceAnchor");e.ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:t,onSetup:t=>{const o=e.selection.selectorChangedWithUnbind("a:not([href])",t.setActive).unbind,n=u(e)(t);return()=>{o(),n()}}}),e.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:t,onSetup:u(e)})})(e),e.on("PreInit",(()=>{(e=>{e.formatter.register("namedAnchor",{inline:"a",selector:a,remove:"all",split:!0,deep:!0,attributes:{id:"%value"},onmatch:(e,t,o)=>l(e)})})(e)}))}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/autolink/plugin.min.js b/apps/web-antd/public/tinymce/plugins/autolink/plugin.min.js new file mode 100644 index 0000000..ba87c86 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/autolink/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),n=t("autolink_pattern"),o=t("link_default_target"),r=t("link_default_protocol"),a=t("allow_unsafe_link_target"),s=e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=o=e,(r=String).prototype.isPrototypeOf(n)||(null===(a=o.constructor)||void 0===a?void 0:a.name)===r.name)?"string":t;var n,o,r,a})(e);const l=e=>undefined===e;const i=e=>!(e=>null==e)(e),c=Object.hasOwnProperty,d=e=>"\ufeff"===e;var u=tinymce.util.Tools.resolve("tinymce.dom.TextSeeker");const f=e=>/^[(\[{ \u00a0]$/.test(e),g=(e,t,n)=>{for(let o=t-1;o>=0;o--){const t=e.charAt(o);if(!d(t)&&n(t))return o}return-1},m=(e,t)=>{var o;const a=e.schema.getVoidElements(),s=n(e),{dom:i,selection:d}=e;if(null!==i.getParent(d.getNode(),"a[href]")||e.mode.isReadOnly())return null;const m=d.getRng(),k=u(i,(e=>{return i.isBlock(e)||(t=a,n=e.nodeName.toLowerCase(),c.call(t,n))||"false"===i.getContentEditable(e);var t,n})),{container:p,offset:y}=((e,t)=>{let n=e,o=t;for(;1===n.nodeType&&n.childNodes[o];)n=n.childNodes[o],o=3===n.nodeType?n.data.length:n.childNodes.length;return{container:n,offset:o}})(m.endContainer,m.endOffset),w=null!==(o=i.getParent(p,i.isBlock))&&void 0!==o?o:i.getRoot(),h=k.backwards(p,y+t,((e,t)=>{const n=e.data,o=g(n,t,(r=f,e=>!r(e)));var r,a;return-1===o||(a=n[o],/[?!,.;:]/.test(a))?o:o+1}),w);if(!h)return null;let v=h.container;const _=k.backwards(h.container,h.offset,((e,t)=>{v=e;const n=g(e.data,t,f);return-1===n?n:n+1}),w),A=i.createRng();_?A.setStart(_.container,_.offset):A.setStart(v,0),A.setEnd(h.container,h.offset);const C=A.toString().replace(/\uFEFF/g,"").match(s);if(C){let t=C[0];return $="www.",(b=t).length>=4&&b.substr(0,4)===$?t=r(e)+"://"+t:((e,t,n=0,o)=>{const r=e.indexOf(t,n);return-1!==r&&(!!l(o)||r+t.length<=o)})(t,"@")&&!(e=>/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(e))(t)&&(t="mailto:"+t),{rng:A,url:t}}var b,$;return null},k=(e,t)=>{const{dom:n,selection:r}=e,{rng:l,url:i}=t,c=r.getBookmark();r.setRng(l);const d="createlink",u={command:d,ui:!1,value:i};if(!e.dispatch("BeforeExecCommand",u).isDefaultPrevented()){e.getDoc().execCommand(d,!1,i),e.dispatch("ExecCommand",u);const t=o(e);if(s(t)){const o=r.getNode();n.setAttrib(o,"target",t),"_blank"!==t||a(e)||n.setAttrib(o,"rel","noopener")}}r.moveToBookmark(c),e.nodeChanged()},p=e=>{const t=m(e,-1);i(t)&&k(e,t)},y=p;e.add("autolink",(e=>{(e=>{const t=e.options.register;t("autolink_pattern",{processor:"regexp",default:new RegExp("^"+/(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)[A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?/g.source+"$","i")}),t("link_default_target",{processor:"string"}),t("link_default_protocol",{processor:"string",default:"https"})})(e),(e=>{e.on("keydown",(t=>{13!==t.keyCode||t.isDefaultPrevented()||(e=>{const t=m(e,0);i(t)&&k(e,t)})(e)})),e.on("keyup",(t=>{32===t.keyCode?p(e):(48===t.keyCode&&t.shiftKey||221===t.keyCode)&&y(e)}))})(e)}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/autoresize/plugin.min.js b/apps/web-antd/public/tinymce/plugins/autoresize/plugin.min.js new file mode 100644 index 0000000..1f5e37f --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/autoresize/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.Env");const o=e=>t=>t.options.get(e),n=o("min_height"),s=o("max_height"),i=o("autoresize_overflow_padding"),r=o("autoresize_bottom_margin"),g=(e,t)=>{const o=e.getBody();o&&(o.style.overflowY=t?"":"hidden",t||(o.scrollTop=0))},l=(e,t,o,n)=>{var s;const i=parseInt(null!==(s=e.getStyle(t,o,n))&&void 0!==s?s:"",10);return isNaN(i)?0:i},a=(e,o,r,c)=>{var d;const u=e.dom,h=e.getDoc();if(!h)return;if((e=>e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen())(e))return void g(e,!0);const m=h.documentElement,f=c?c():i(e),p=null!==(d=n(e))&&void 0!==d?d:e.getElement().offsetHeight;let y=p;const S=l(u,m,"margin-top",!0),v=l(u,m,"margin-bottom",!0);let C=m.offsetHeight+S+v+f;C<0&&(C=0);const H=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;C+H>p&&(y=C+H);const b=s(e);b&&y>b?(y=b,g(e,!0)):g(e,!1);const w=o.get();if(w.set&&(e.dom.setStyles(e.getDoc().documentElement,{"min-height":0}),e.dom.setStyles(e.getBody(),{"min-height":"inherit"})),y!==w.totalHeight&&(C-f!==w.contentHeight||!w.set)){const n=y-w.totalHeight;if(u.setStyle(e.getContainer(),"height",y+"px"),o.set({totalHeight:y,contentHeight:C,set:!0}),(e=>{e.dispatch("ResizeEditor")})(e),t.browser.isSafari()&&(t.os.isMacOS()||t.os.isiOS())){const t=e.getWin();t.scrollTo(t.pageXOffset,t.pageYOffset)}e.hasFocus()&&(e=>{if("setcontent"===(null==e?void 0:e.type.toLowerCase())){const t=e;return!0===t.selection||!0===t.paste}return!1})(r)&&e.selection.scrollIntoView(),(t.browser.isSafari()||t.browser.isChromium())&&n<0&&a(e,o,r,c)}};e.add("autoresize",(e=>{if((e=>{const t=e.options.register;t("autoresize_overflow_padding",{processor:"number",default:1}),t("autoresize_bottom_margin",{processor:"number",default:50})})(e),e.options.isSet("resize")||e.options.set("resize",!1),!e.inline){const o=(()=>{let e={totalHeight:0,contentHeight:0,set:!1};return{get:()=>e,set:t=>{e=t}}})();((e,t)=>{e.addCommand("mceAutoResize",(()=>{a(e,t)}))})(e,o),((e,o)=>{const n=()=>r(e);e.on("init",(s=>{const r=i(e),g=e.dom;g.setStyles(e.getDoc().documentElement,{height:"auto"}),t.browser.isEdge()||t.browser.isIE()?g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r,"min-height":0}):g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r}),a(e,o,s,n)})),e.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",(t=>{a(e,o,t,n)}))})(e,o)}}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/autosave/plugin.min.js b/apps/web-antd/public/tinymce/plugins/autosave/plugin.min.js new file mode 100644 index 0000000..354d42e --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/autosave/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(r=o=t,(a=String).prototype.isPrototypeOf(r)||(null===(s=o.constructor)||void 0===s?void 0:s.name)===a.name)?"string":e;var r,o,a,s})(t);const r=t=>undefined===t;var o=tinymce.util.Tools.resolve("tinymce.util.Delay"),a=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),s=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=t=>{const e=/^(\d+)([ms]?)$/.exec(t);return(e&&e[2]?{s:1e3,m:6e4}[e[2]]:1)*parseInt(t,10)},i=t=>e=>e.options.get(t),u=i("autosave_ask_before_unload"),l=i("autosave_restore_when_empty"),c=i("autosave_interval"),d=i("autosave_retention"),m=t=>{const e=document.location;return t.options.get("autosave_prefix").replace(/{path}/g,e.pathname).replace(/{query}/g,e.search).replace(/{hash}/g,e.hash).replace(/{id}/g,t.id)},v=(t,e)=>{if(r(e))return t.dom.isEmpty(t.getBody());{const r=s.trim(e);if(""===r)return!0;{const e=(new DOMParser).parseFromString(r,"text/html");return t.dom.isEmpty(e)}}},f=t=>{var e;const r=parseInt(null!==(e=a.getItem(m(t)+"time"))&&void 0!==e?e:"0",10)||0;return!((new Date).getTime()-r>d(t)&&(p(t,!1),1))},p=(t,e)=>{const r=m(t);a.removeItem(r+"draft"),a.removeItem(r+"time"),!1!==e&&(t=>{t.dispatch("RemoveDraft")})(t)},y=t=>{const e=m(t);!v(t)&&t.isDirty()&&(a.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),a.setItem(e+"time",(new Date).getTime().toString()),(t=>{t.dispatch("StoreDraft")})(t))},g=t=>{var e;const r=m(t);f(t)&&(t.setContent(null!==(e=a.getItem(r+"draft"))&&void 0!==e?e:"",{format:"raw"}),(t=>{t.dispatch("RestoreDraft")})(t))};var D=tinymce.util.Tools.resolve("tinymce.EditorManager");const h=t=>e=>{const r=()=>f(t)&&!t.mode.isReadOnly();e.setEnabled(r());const o=()=>e.setEnabled(r());return t.on("StoreDraft RestoreDraft RemoveDraft",o),()=>t.off("StoreDraft RestoreDraft RemoveDraft",o)};t.add("autosave",(t=>((t=>{const r=t.options.register,o=t=>{const r=e(t);return r?{value:n(t),valid:r}:{valid:!1,message:"Must be a string."}};r("autosave_ask_before_unload",{processor:"boolean",default:!0}),r("autosave_prefix",{processor:"string",default:"tinymce-autosave-{path}{query}{hash}-{id}-"}),r("autosave_restore_when_empty",{processor:"boolean",default:!1}),r("autosave_interval",{processor:o,default:"30s"}),r("autosave_retention",{processor:o,default:"20m"})})(t),(t=>{t.editorManager.on("BeforeUnload",(t=>{let e;s.each(D.get(),(t=>{t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&u(t)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))})),e&&(t.preventDefault(),t.returnValue=e)}))})(t),(t=>{(t=>{const e=c(t);o.setEditorInterval(t,(()=>{y(t)}),e)})(t);const e=()=>{(t=>{t.undoManager.transact((()=>{g(t),p(t)})),t.focus()})(t)};t.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)}),t.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)})})(t),t.on("init",(()=>{l(t)&&t.dom.isEmpty(t.getBody())&&g(t)})),(t=>({hasDraft:()=>f(t),storeDraft:()=>y(t),restoreDraft:()=>g(t),removeDraft:e=>p(t,e),isEmpty:e=>v(t,e)}))(t))))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/charmap/plugin.min.js b/apps/web-antd/public/tinymce/plugins/charmap/plugin.min.js new file mode 100644 index 0000000..cd905e6 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/charmap/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=(e,t)=>{const r=((e,t)=>e.dispatch("insertCustomChar",{chr:t}))(e,t).chr;e.execCommand("mceInsertContent",!1,r)},r=e=>t=>e===t,a=e=>"array"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(r=a=e,(n=String).prototype.isPrototypeOf(r)||(null===(i=a.constructor)||void 0===i?void 0:i.name)===n.name)?"string":t;var r,a,n,i})(e);const n=r(null),i=r(void 0),o=e=>"function"==typeof e,s=()=>false;class l{constructor(e,t){this.tag=e,this.value=t}static some(e){return new l(!0,e)}static none(){return l.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?l.some(e(this.value)):l.none()}bind(e){return this.tag?e(this.value):l.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:l.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return null==e?l.none():l.some(e)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}l.singletonNone=new l(!1);const c=Array.prototype.push,u=(e,t)=>{const r=e.length,a=new Array(r);for(let n=0;nt=>t.options.get(e),m=h("charmap"),p=h("charmap_append"),d=g.isArray,f="User Defined",y=e=>{return d(e)?(t=e,g.grep(t,(e=>d(e)&&2===e.length))):"function"==typeof e?e():[];var t},b=e=>{const t=((e,t)=>{const r=m(e);r&&(t=[{name:f,characters:y(r)}]);const a=p(e);if(a){const e=g.grep(t,(e=>e.name===f));return e.length?(e[0].characters=[...e[0].characters,...y(a)],t):t.concat({name:f,characters:y(a)})}return t})(e,[{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"]]}]);return t.length>1?[{name:"All",characters:(r=t,n=e=>e.characters,(e=>{const t=[];for(let r=0,n=e.length;r{let t=e;return{get:()=>t,set:e=>{t=e}}},v=(e,t,r=0,a)=>{const n=e.indexOf(t,r);return-1!==n&&(!!i(a)||n+t.length<=a)},k=String.fromCodePoint,C=(e,t)=>{const r=[],a=t.toLowerCase();return(e=>{for(let n=0,i=e.length;n!!v(k(e).toLowerCase(),r)||v(t.toLowerCase(),r)||v(t.toLowerCase().replace(/\s+/g,""),r))((t=e[n])[0],t[1],a)&&r.push(t);var t})(e.characters),u(r,(e=>({text:e[1],value:k(e[0]),icon:k(e[0])})))},x="pattern",A=(e,r)=>{const a=()=>[{label:"Search",type:"input",name:x},{type:"collection",name:"results"}],i=1===r.length?w(f):w("All"),o=(e=>{let t=null;const r=()=>{n(t)||(clearTimeout(t),t=null)};return{cancel:r,throttle:(...a)=>{r(),t=setTimeout((()=>{t=null,e.apply(null,a)}),40)}}})((e=>{const t=e.getData().pattern;((e,t)=>{var a,n;(a=r,n=e=>e.name===i.get(),((e,t,r)=>{for(let a=0,n=e.length;a{const a=C(r,t);e.setData({results:a})}))})(e,t)})),c={title:"Special Character",size:"normal",body:1===r.length?{type:"panel",items:a()}:{type:"tabpanel",tabs:u(r,(e=>({title:e.name,name:e.name,items:a()})))},buttons:[{type:"cancel",name:"close",text:"Close",primary:!0}],initialData:{pattern:"",results:C(r[0],"")},onAction:(r,a)=>{"results"===a.name&&(t(e,a.value),r.close())},onTabChange:(e,t)=>{i.set(t.newTabName),o.throttle(e)},onChange:(e,t)=>{t.name===x&&o.throttle(e)}};e.windowManager.open(c).focus(x)},q=e=>t=>{const r=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",r),r(),()=>{e.off("NodeChange",r)}};e.add("charmap",(e=>{(e=>{const t=e.options.register,r=e=>o(e)||a(e);t("charmap",{processor:r}),t("charmap_append",{processor:r})})(e);const r=b(e);return((e,t)=>{e.addCommand("mceShowCharmap",(()=>{A(e,t)}))})(e,r),(e=>{const t=()=>e.execCommand("mceShowCharmap");e.ui.registry.addButton("charmap",{icon:"insert-character",tooltip:"Special character",onAction:t,onSetup:q(e)}),e.ui.registry.addMenuItem("charmap",{icon:"insert-character",text:"Special character...",onAction:t,onSetup:q(e)})})(e),((e,t)=>{e.ui.registry.addAutocompleter("charmap",{trigger:":",columns:"auto",minChars:2,fetch:(e,r)=>new Promise(((r,a)=>{r(C(t,e))})),onAction:(t,r,a)=>{e.selection.setRng(r),e.insertContent(a),t.hide()}})})(e,r[0]),(e=>({getCharMap:()=>b(e),insertChar:r=>{t(e,r)}}))(e)}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/code/plugin.min.js b/apps/web-antd/public/tinymce/plugins/code/plugin.min.js new file mode 100644 index 0000000..54a780c --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/code/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("code",(e=>((e=>{e.addCommand("mceCodeEditor",(()=>{(e=>{const o=(e=>e.getContent({source_view:!0}))(e);e.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:o},onSubmit:o=>{((e,o)=>{e.focus(),e.undoManager.transact((()=>{e.setContent(o)})),e.selection.setCursorLocation(),e.nodeChanged()})(e,o.getData().code),o.close()}})})(e)}))})(e),(e=>{const o=()=>e.execCommand("mceCodeEditor");e.ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:o}),e.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:o})})(e),{})))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/codesample/plugin.min.js b/apps/web-antd/public/tinymce/plugins/codesample/plugin.min.js new file mode 100644 index 0000000..2283bb9 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/codesample/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>!(e=>null==e)(e),n=()=>{};class a{constructor(e,t){this.tag=e,this.value=t}static some(e){return new a(!0,e)}static none(){return a.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?a.some(e(this.value)):a.none()}bind(e){return this.tag?e(this.value):a.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:a.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return t(e)?a.some(e):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);var s=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils");const r="undefined"!=typeof window?window:Function("return this;")(),i=function(){const e=window.Prism;window.Prism={manual:!0};var t=function(e){var t=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,n=0,a={},s={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(t){return t instanceof r?new r(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=d.reach);x+=_.value.length,_=_.next){var F=_.value;if(t.length>e.length)return;if(!(F instanceof r)){var A,S=1;if(y){if(!(A=i(v,x,e,m))||A.index>=e.length)break;var $=A.index,z=A.index+A[0].length,E=x;for(E+=_.value.length;$>=E;)E+=(_=_.next).value.length;if(x=E-=_.value.length,_.value instanceof r)continue;for(var C=_;C!==t.tail&&(Ed.reach&&(d.reach=O);var P=_.prev;if(B&&(P=u(t,P,B),x+=B.length),c(t,P,S),_=u(t,P,new r(g,f?s.tokenize(j,f):j,w,j)),T&&u(t,_,T),S>1){var N={cause:g+","+b,reach:O};o(e,t,n,_.prev,x,N),d&&N.reach>d.reach&&(d.reach=N.reach)}}}}}}function l(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function u(e,t,n){var a=t.next,s={value:n,prev:t,next:a};return t.next=s,a.prev=s,e.length++,s}function c(e,t,n){for(var a=t.next,s=0;s"+r.content+""},!e.document)return e.addEventListener?(s.disableWorkerMessageHandler||e.addEventListener("message",(function(t){var n=JSON.parse(t.data),a=n.language,r=n.code,i=n.immediateClose;e.postMessage(s.highlight(r,s.languages[a],a)),i&&e.close()}),!1),s):s;var d=s.util.currentScript();function g(){s.manual||s.highlightAll()}if(d&&(s.filename=d.src,d.hasAttribute("data-manual")&&(s.manual=!0)),!s.manual){var p=document.readyState;"loading"===p||"interactive"===p&&d&&d.defer?document.addEventListener("DOMContentLoaded",g):window.requestAnimationFrame?window.requestAnimationFrame(g):window.setTimeout(g,16)}return s}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});return t.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,a,s,r){if(n.language===a){var i=n.tokenStack=[];n.code=n.code.replace(s,(function(e){if("function"==typeof r&&!r(e))return e;for(var s,o=i.length;-1!==n.code.indexOf(s=t(a,o));)++o;return i[o]=e,s})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,a){if(n.language===a&&n.tokenStack){n.grammar=e.languages[a];var s=0,r=Object.keys(n.tokenStack);!function i(o){for(var l=0;l=r.length);l++){var u=o[l];if("string"==typeof u||u.content&&"string"==typeof u.content){var c=r[s],d=n.tokenStack[c],g="string"==typeof u?u:u.content,p=t(a,c),b=g.indexOf(p);if(b>-1){++s;var h=g.substring(0,b),f=new e.Token(a,e.tokenize(d,n.grammar),"language-"+a,d),m=g.substring(b+p.length),y=[];h&&y.push.apply(y,i([h])),y.push(f),m&&y.push.apply(y,i([m])),"string"==typeof u?o.splice.apply(o,[l,1].concat(y)):u.content=y}}else u.content&&i(u.content)}return o}(n.tokens)}}}})}(t),t.languages.c=t.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),t.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),t.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},t.languages.c.string],char:t.languages.c.char,comment:t.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:t.languages.c}}}}),t.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete t.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|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|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(t),function(e){function t(e,t){return e.replace(/<<(\d+)>>/g,(function(e,n){return"(?:"+t[+n]+")"}))}function n(e,n,a){return RegExp(t(e,n),a||"")}function a(e,t){for(var n=0;n>/g,(function(){return"(?:"+e+")"}));return e.replace(/<>/g,"[^\\s\\S]")}var s="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",r="class enum interface record struct",i="add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",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(r),c=RegExp(l(s+" "+r+" "+i+" "+o)),d=l(r+" "+i+" "+o),g=l(s+" "+r+" "+o),p=a(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source,2),b=a(/\((?:[^()]|<>)*\)/.source,2),h=/@?\b[A-Za-z_]\w*\b/.source,f=t(/<<0>>(?:\s*<<1>>)?/.source,[h,p]),m=t(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source,[d,f]),y=/\[\s*(?:,\s*)*\]/.source,w=t(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,[m,y]),k=t(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,[p,b,y]),v=t(/\(<<0>>+(?:,<<0>>+)+\)/.source,[k]),_=t(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,[v,m,y]),x={keyword:c,punctuation:/[<>()?,.:[\]]/},F=/'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source,A=/"(?:\\.|[^\\"\r\n])*"/.source,S=/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source;e.languages.csharp=e.languages.extend("clike",{string:[{pattern:n(/(^|[^$\\])<<0>>/.source,[S]),lookbehind:!0,greedy:!0},{pattern:n(/(^|[^@$\\])<<0>>/.source,[A]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:n(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source,[m]),lookbehind:!0,inside:x},{pattern:n(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source,[h,_]),lookbehind:!0,inside:x},{pattern:n(/(\busing\s+)<<0>>(?=\s*=)/.source,[h]),lookbehind:!0},{pattern:n(/(\b<<0>>\s+)<<1>>/.source,[u,f]),lookbehind:!0,inside:x},{pattern:n(/(\bcatch\s*\(\s*)<<0>>/.source,[m]),lookbehind:!0,inside:x},{pattern:n(/(\bwhere\s+)<<0>>/.source,[h]),lookbehind:!0},{pattern:n(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source,[w]),lookbehind:!0,inside:x},{pattern:n(/\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source,[_,g,h]),inside:x}],keyword:c,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),e.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),e.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:n(/([(,]\s*)<<0>>(?=\s*:)/.source,[h]),lookbehind:!0,alias:"punctuation"}}),e.languages.insertBefore("csharp","class-name",{namespace:{pattern:n(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,[h]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:n(/(\b(?:default|sizeof|typeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/.source,[b]),lookbehind:!0,alias:"class-name",inside:x},"return-type":{pattern:n(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,[_,m]),inside:x,alias:"class-name"},"constructor-invocation":{pattern:n(/(\bnew\s+)<<0>>(?=\s*[[({])/.source,[_]),lookbehind:!0,inside:x,alias:"class-name"},"generic-method":{pattern:n(/<<0>>\s*<<1>>(?=\s*\()/.source,[h,p]),inside:{function:n(/^<<0>>/.source,[h]),generic:{pattern:RegExp(p),alias:"class-name",inside:x}}},"type-list":{pattern:n(/\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/.source,[u,f,h,_,c.source,b,/\bnew\s*\(\s*\)/.source]),lookbehind:!0,inside:{"record-arguments":{pattern:n(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source,[f,b]),lookbehind:!0,greedy:!0,inside:e.languages.csharp},keyword:c,"class-name":{pattern:RegExp(_),greedy:!0,inside:x},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var $=A+"|"+F,z=t(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,[$]),E=a(t(/[^"'/()]|<<0>>|\(<>*\)/.source,[z]),2),C=/\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source,j=t(/<<0>>(?:\s*\(<<1>>*\))?/.source,[m,E]);e.languages.insertBefore("csharp","class-name",{attribute:{pattern:n(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source,[C,j]),lookbehind:!0,greedy:!0,inside:{target:{pattern:n(/^<<0>>(?=\s*:)/.source,[C]),alias:"keyword"},"attribute-arguments":{pattern:n(/\(<<0>>*\)/.source,[E]),inside:e.languages.csharp},"class-name":{pattern:RegExp(m),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var B=/:[^}\r\n]+/.source,T=a(t(/[^"'/()]|<<0>>|\(<>*\)/.source,[z]),2),O=t(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[T,B]),P=a(t(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source,[$]),2),N=t(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[P,B]);function R(t,a){return{interpolation:{pattern:n(/((?:^|[^{])(?:\{\{)*)<<0>>/.source,[t]),lookbehind:!0,inside:{"format-string":{pattern:n(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source,[a,B]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:e.languages.csharp}}},string:/[\s\S]+/}}e.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:n(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,[O]),lookbehind:!0,greedy:!0,inside:R(O,T)},{pattern:n(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source,[N]),lookbehind:!0,greedy:!0,inside:R(N,P)}],char:{pattern:RegExp(F),greedy:!0}}),e.languages.dotnet=e.languages.cs=e.languages.csharp}(t),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+t.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(t),function(e){var t=/\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|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,a={pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[a,{pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:a.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+n+/[A-Z]\w*\b/.source),lookbehind:!0,inside:a.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+n+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:a.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+n+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:a.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],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 t.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(t),t.languages.javascript=t.languages.extend("clike",{"class-name":[t.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|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}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),t.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,t.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:t.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:t.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:t.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:t.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]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:t.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),t.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"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:t.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),t.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),t.languages.markup&&(t.languages.markup.tag.addInlined("script","javascript"),t.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),t.languages.js=t.languages.javascript,t.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},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/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},t.languages.markup.tag.inside["attr-value"].inside.entity=t.languages.markup.entity,t.languages.markup.doctype.inside["internal-subset"].inside=t.languages.markup,t.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(t.languages.markup.tag,"addInlined",{value:function(e,n){var a={};a["language-"+n]={pattern:/(^$)/i,lookbehind:!0,inside:t.languages[n]},a.cdata=/^$/i;var s={"included-cdata":{pattern://i,inside:a}};s["language-"+n]={pattern:/[\s\S]+/,inside:t.languages[n]};var r={};r[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:s},t.languages.insertBefore("markup","cdata",r)}}),Object.defineProperty(t.languages.markup.tag,"addAttribute",{value:function(e,n){t.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[n,"language-"+n],inside:t.languages[n]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),t.languages.html=t.languages.markup,t.languages.mathml=t.languages.markup,t.languages.svg=t.languages.markup,t.languages.xml=t.languages.extend("markup",{}),t.languages.ssml=t.languages.xml,t.languages.atom=t.languages.xml,t.languages.rss=t.languages.xml,function(e){var t=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,n=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],a=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,s=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,r=/[{}\[\](),:;]/;e.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:t,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:a,operator:s,punctuation:r};var i={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:e.languages.php},o=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:i}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:i}}];e.languages.insertBefore("php","variable",{string:o,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:t,string:o,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,number:a,operator:s,punctuation:r}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),e.hooks.add("before-tokenize",(function(t){/<\?/.test(t.code)&&e.languages["markup-templating"].buildPlaceholders(t,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"php")}))}(t),t.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\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]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\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:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|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(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},t.languages.python["string-interpolation"].inside.interpolation.inside.rest=t.languages.python,t.languages.py=t.languages.python,function(e){e.languages.ruby=e.languages.extend("clike",{comment:{pattern:/#.*|^=begin\s[\s\S]*?^=end/m,greedy:!0},"class-name":{pattern:/(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/,operator:/\.{2,3}|&\.|===||[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),e.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var t={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:e.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete e.languages.ruby.function;var n="(?:"+[/([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,/\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,/<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source].join("|")+")",a=/(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;e.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp(/%r/.source+n+/[egimnosux]{0,6}/.source),greedy:!0,inside:{interpolation:t,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:t,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp(/(^|[^:]):/.source+a),lookbehind:!0,greedy:!0},{pattern:RegExp(/([\r\n{(,][ \t]*)/.source+a+/(?=:(?!:))/.source),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),e.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp(/%[qQiIwWs]?/.source+n),greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:t,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp(/%x/.source+n),greedy:!0,inside:{interpolation:t,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:t,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete e.languages.ruby.string,e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),e.languages.rb=e.languages.ruby}(t),window.Prism=e,t}(),o=e=>t=>t.options.get(e),l=o("codesample_languages"),u=o("codesample_global_prismjs"),c=e=>r.Prism&&u(e)?r.Prism:i,d=e=>t(e)&&"PRE"===e.nodeName&&-1!==e.className.indexOf("language-"),g=e=>{const t=e.selection?e.selection.getNode():null;return d(t)?a.some(t):a.none()},p=e=>{const t=(e=>l(e)||[{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"}])(e),n=(r=t,(e=>0""),(e=>e.value));var r;const i=((e,t)=>g(e).fold((()=>t),(e=>{const n=e.className.match(/language-(\w+)/);return n?n[1]:t})))(e,n),o=(e=>g(e).bind((e=>a.from(e.textContent))).getOr(""))(e);e.windowManager.open({title:"Insert/Edit Code Sample",size:"large",body:{type:"panel",items:[{type:"listbox",name:"language",label:"Language",items:t},{type:"textarea",name:"code",label:"Code view"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{language:i,code:o},onSubmit:t=>{const n=t.getData();((e,t,n)=>{const a=e.dom;e.undoManager.transact((()=>{const r=g(e);return n=s.DOM.encode(n),r.fold((()=>{e.insertContent('
'+n+"
");const s=a.select("#__new")[0];a.setAttrib(s,"id",null),e.selection.select(s)}),(s=>{a.setAttrib(s,"class","language-"+t),s.innerHTML=n,c(e).highlightElement(s),e.selection.select(s)}))}))})(e,n.language,n.code),t.close()}})},b=(h=/^\s+|\s+$/g,e=>e.replace(h,""));var h,f=tinymce.util.Tools.resolve("tinymce.util.Tools");const m=(e,t=n)=>n=>{const a=()=>{n.setEnabled(e.selection.isEditable()),t(n)};return e.on("NodeChange",a),a(),()=>{e.off("NodeChange",a)}};e.add("codesample",(e=>{(e=>{const t=e.options.register;t("codesample_languages",{processor:"object[]"}),t("codesample_global_prismjs",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreProcess",(t=>{const n=e.dom,a=n.select("pre[contenteditable=false]",t.node);f.each(f.grep(a,d),(e=>{const t=e.textContent;let a;for(n.setAttrib(e,"class",b(n.getAttrib(e,"class"))),n.setAttrib(e,"contentEditable",null),n.setAttrib(e,"data-mce-highlighted",null);a=e.firstChild;)e.removeChild(a);n.add(e,"code").textContent=t}))})),e.on("SetContent",(()=>{const t=e.dom,n=f.grep(t.select("pre"),(e=>d(e)&&"true"!==t.getAttrib(e,"data-mce-highlighted")));n.length&&e.undoManager.transact((()=>{f.each(n,(n=>{var a;f.each(t.select("br",n),(n=>{t.replace(e.getDoc().createTextNode("\n"),n)})),n.innerHTML=t.encode(null!==(a=n.textContent)&&void 0!==a?a:""),c(e).highlightElement(n),t.setAttrib(n,"data-mce-highlighted",!0),n.className=b(n.className)}))}))})),e.on("PreInit",(()=>{e.parser.addNodeFilter("pre",(e=>{var t;for(let n=0,a=e.length;n{const t=()=>e.execCommand("codesample");e.ui.registry.addToggleButton("codesample",{icon:"code-sample",tooltip:"Insert/edit code sample",onAction:t,onSetup:m(e,(t=>{t.setActive((e=>{const t=e.selection.getStart();return e.dom.is(t,'pre[class*="language-"]')})(e))}))}),e.ui.registry.addMenuItem("codesample",{text:"Code sample...",icon:"code-sample",onAction:t,onSetup:m(e)})})(e),(e=>{e.addCommand("codesample",(()=>{const t=e.selection.getNode();e.selection.isCollapsed()||d(t)?p(e):e.formatter.toggle("code")}))})(e),e.on("dblclick",(t=>{d(t.target)&&p(e)}))}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/directionality/plugin.min.js b/apps/web-antd/public/tinymce/plugins/directionality/plugin.min.js new file mode 100644 index 0000000..a4f3780 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/directionality/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>e=>typeof e===t,o=t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(o=r=t,(n=String).prototype.isPrototypeOf(o)||(null===(i=r.constructor)||void 0===i?void 0:i.name)===n.name)?"string":e;var o,r,n,i})(t),r=e("boolean"),n=t=>!(t=>null==t)(t),i=e("function"),s=e("number"),l=()=>false;class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return n(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=(t,e)=>{for(let o=0,r=t.length;o{if(null==t)throw new Error("Node cannot be null or undefined");return{dom:t}},d=c,h=(t,e)=>{const o=t.dom;if(1!==o.nodeType)return!1;{const t=o;if(void 0!==t.matches)return t.matches(e);if(void 0!==t.msMatchesSelector)return t.msMatchesSelector(e);if(void 0!==t.webkitMatchesSelector)return t.webkitMatchesSelector(e);if(void 0!==t.mozMatchesSelector)return t.mozMatchesSelector(e);throw new Error("Browser lacks native selectors")}};"undefined"!=typeof window?window:Function("return this;")();const m=t=>e=>(t=>t.dom.nodeType)(e)===t,g=m(1),f=m(3),v=m(11),y=(t,e)=>{t.dom.removeAttribute(e)},p=t=>d(t.dom.host),w=t=>{const e=f(t)?t.dom.parentNode:t.dom;if(null==e||null===e.ownerDocument)return!1;const o=e.ownerDocument;return(t=>{const e=(t=>d(t.dom.getRootNode()))(t);return v(o=e)&&n(o.dom.host)?a.some(e):a.none();var o})(d(e)).fold((()=>o.body.contains(e)),(r=w,i=p,t=>r(i(t))));var r,i},b=t=>"rtl"===((t,e)=>{const o=t.dom,r=window.getComputedStyle(o).getPropertyValue(e);return""!==r||w(t)?r:((t,e)=>(t=>void 0!==t.style&&i(t.style.getPropertyValue))(t)?t.style.getPropertyValue(e):"")(o,e)})(t,"direction")?"rtl":"ltr",S=(t,e)=>(t=>((t,e)=>{const o=[];for(let r=0,n=t.length;r{const o=t.length,r=new Array(o);for(let n=0;nh(t,e))))(t),N=t=>g(t)&&"li"===t.dom.nodeName.toLowerCase();const A=(t,e,n)=>{u(e,(e=>{const c=d(e),m=N(c),f=((t,e)=>{return(e?(o=t,r="ol,ul",((t,e,o)=>{let n=t.dom;const s=i(o)?o:l;for(;n.parentNode;){n=n.parentNode;const t=d(n);if(h(t,r))return a.some(t);if(s(t))break}return a.none()})(o,0,n)):a.some(t)).getOr(t);var o,r,n})(c,m);var v;(v=f,(t=>a.from(t.dom.parentNode).map(d))(v).filter(g)).each((e=>{if(t.setStyle(f.dom,"direction",null),b(e)===n?y(f,"dir"):((t,e,n)=>{((t,e,n)=>{if(!(o(n)||r(n)||s(n)))throw console.error("Invalid call to Attribute.set. Key ",e,":: Value ",n,":: Element ",t),new Error("Attribute value was not simple");t.setAttribute(e,n+"")})(t.dom,e,n)})(f,"dir",n),b(f)!==n&&t.setStyle(f.dom,"direction",n),m){const e=S(f,"li[dir],li[style]");u(e,(e=>{y(e,"dir"),t.setStyle(e.dom,"direction",null)}))}}))}))},T=(t,e)=>{t.selection.isEditable()&&(A(t.dom,t.selection.getSelectedBlocks(),e),t.nodeChanged())},C=(t,e)=>o=>{const r=r=>{const n=d(r.element);o.setActive(b(n)===e),o.setEnabled(t.selection.isEditable())};return t.on("NodeChange",r),o.setEnabled(t.selection.isEditable()),()=>t.off("NodeChange",r)};t.add("directionality",(t=>{(t=>{t.addCommand("mceDirectionLTR",(()=>{T(t,"ltr")})),t.addCommand("mceDirectionRTL",(()=>{T(t,"rtl")}))})(t),(t=>{t.ui.registry.addToggleButton("ltr",{tooltip:"Left to right",icon:"ltr",onAction:()=>t.execCommand("mceDirectionLTR"),onSetup:C(t,"ltr")}),t.ui.registry.addToggleButton("rtl",{tooltip:"Right to left",icon:"rtl",onAction:()=>t.execCommand("mceDirectionRTL"),onSetup:C(t,"rtl")})})(t)}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/emoticons/js/emojiimages.js b/apps/web-antd/public/tinymce/plugins/emoticons/js/emojiimages.js new file mode 100644 index 0000000..6fcec71 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/emoticons/js/emojiimages.js @@ -0,0 +1 @@ +window.tinymce.Resource.add("tinymce.plugins.emoticons",{100:{keywords:["score","perfect","numbers","century","exam","quiz","test","pass","hundred"],char:'💯',fitzpatrick_scale:false,category:"symbols"},1234:{keywords:["numbers","blue-square"],char:'🔢',fitzpatrick_scale:false,category:"symbols"},grinning:{keywords:["face","smile","happy","joy",":D","grin"],char:'😀',fitzpatrick_scale:false,category:"people"},grimacing:{keywords:["face","grimace","teeth"],char:'😬',fitzpatrick_scale:false,category:"people"},grin:{keywords:["face","happy","smile","joy","kawaii"],char:'😁',fitzpatrick_scale:false,category:"people"},joy:{keywords:["face","cry","tears","weep","happy","happytears","haha"],char:'😂',fitzpatrick_scale:false,category:"people"},rofl:{keywords:["face","rolling","floor","laughing","lol","haha"],char:'🤣',fitzpatrick_scale:false,category:"people"},partying:{keywords:["face","celebration","woohoo"],char:'🥳',fitzpatrick_scale:false,category:"people"},smiley:{keywords:["face","happy","joy","haha",":D",":)","smile","funny"],char:'😃',fitzpatrick_scale:false,category:"people"},smile:{keywords:["face","happy","joy","funny","haha","laugh","like",":D",":)"],char:'😄',fitzpatrick_scale:false,category:"people"},sweat_smile:{keywords:["face","hot","happy","laugh","sweat","smile","relief"],char:'😅',fitzpatrick_scale:false,category:"people"},laughing:{keywords:["happy","joy","lol","satisfied","haha","face","glad","XD","laugh"],char:'😆',fitzpatrick_scale:false,category:"people"},innocent:{keywords:["face","angel","heaven","halo"],char:'😇',fitzpatrick_scale:false,category:"people"},wink:{keywords:["face","happy","mischievous","secret",";)","smile","eye"],char:'😉',fitzpatrick_scale:false,category:"people"},blush:{keywords:["face","smile","happy","flushed","crush","embarrassed","shy","joy"],char:'😊',fitzpatrick_scale:false,category:"people"},slightly_smiling_face:{keywords:["face","smile"],char:'🙂',fitzpatrick_scale:false,category:"people"},upside_down_face:{keywords:["face","flipped","silly","smile"],char:'🙃',fitzpatrick_scale:false,category:"people"},relaxed:{keywords:["face","blush","massage","happiness"],char:'☺️',fitzpatrick_scale:false,category:"people"},yum:{keywords:["happy","joy","tongue","smile","face","silly","yummy","nom","delicious","savouring"],char:'😋',fitzpatrick_scale:false,category:"people"},relieved:{keywords:["face","relaxed","phew","massage","happiness"],char:'😌',fitzpatrick_scale:false,category:"people"},heart_eyes:{keywords:["face","love","like","affection","valentines","infatuation","crush","heart"],char:'😍',fitzpatrick_scale:false,category:"people"},smiling_face_with_three_hearts:{keywords:["face","love","like","affection","valentines","infatuation","crush","hearts","adore"],char:'🥰',fitzpatrick_scale:false,category:"people"},kissing_heart:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:'😘',fitzpatrick_scale:false,category:"people"},kissing:{keywords:["love","like","face","3","valentines","infatuation","kiss"],char:'😗',fitzpatrick_scale:false,category:"people"},kissing_smiling_eyes:{keywords:["face","affection","valentines","infatuation","kiss"],char:'😙',fitzpatrick_scale:false,category:"people"},kissing_closed_eyes:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:'😚',fitzpatrick_scale:false,category:"people"},stuck_out_tongue_winking_eye:{keywords:["face","prank","childish","playful","mischievous","smile","wink","tongue"],char:'😜',fitzpatrick_scale:false,category:"people"},zany:{keywords:["face","goofy","crazy"],char:'🤪',fitzpatrick_scale:false,category:"people"},raised_eyebrow:{keywords:["face","distrust","scepticism","disapproval","disbelief","surprise"],char:'🤨',fitzpatrick_scale:false,category:"people"},monocle:{keywords:["face","stuffy","wealthy"],char:'🧐',fitzpatrick_scale:false,category:"people"},stuck_out_tongue_closed_eyes:{keywords:["face","prank","playful","mischievous","smile","tongue"],char:'😝',fitzpatrick_scale:false,category:"people"},stuck_out_tongue:{keywords:["face","prank","childish","playful","mischievous","smile","tongue"],char:'😛',fitzpatrick_scale:false,category:"people"},money_mouth_face:{keywords:["face","rich","dollar","money"],char:'🤑',fitzpatrick_scale:false,category:"people"},nerd_face:{keywords:["face","nerdy","geek","dork"],char:'🤓',fitzpatrick_scale:false,category:"people"},sunglasses:{keywords:["face","cool","smile","summer","beach","sunglass"],char:'😎',fitzpatrick_scale:false,category:"people"},star_struck:{keywords:["face","smile","starry","eyes","grinning"],char:'🤩',fitzpatrick_scale:false,category:"people"},clown_face:{keywords:["face"],char:'🤡',fitzpatrick_scale:false,category:"people"},cowboy_hat_face:{keywords:["face","cowgirl","hat"],char:'🤠',fitzpatrick_scale:false,category:"people"},hugs:{keywords:["face","smile","hug"],char:'🤗',fitzpatrick_scale:false,category:"people"},smirk:{keywords:["face","smile","mean","prank","smug","sarcasm"],char:'😏',fitzpatrick_scale:false,category:"people"},no_mouth:{keywords:["face","hellokitty"],char:'😶',fitzpatrick_scale:false,category:"people"},neutral_face:{keywords:["indifference","meh",":|","neutral"],char:'😐',fitzpatrick_scale:false,category:"people"},expressionless:{keywords:["face","indifferent","-_-","meh","deadpan"],char:'😑',fitzpatrick_scale:false,category:"people"},unamused:{keywords:["indifference","bored","straight face","serious","sarcasm","unimpressed","skeptical","dubious","side_eye"],char:'😒',fitzpatrick_scale:false,category:"people"},roll_eyes:{keywords:["face","eyeroll","frustrated"],char:'🙄',fitzpatrick_scale:false,category:"people"},thinking:{keywords:["face","hmmm","think","consider"],char:'🤔',fitzpatrick_scale:false,category:"people"},lying_face:{keywords:["face","lie","pinocchio"],char:'🤥',fitzpatrick_scale:false,category:"people"},hand_over_mouth:{keywords:["face","whoops","shock","surprise"],char:'🤭',fitzpatrick_scale:false,category:"people"},shushing:{keywords:["face","quiet","shhh"],char:'🤫',fitzpatrick_scale:false,category:"people"},symbols_over_mouth:{keywords:["face","swearing","cursing","cussing","profanity","expletive"],char:'🤬',fitzpatrick_scale:false,category:"people"},exploding_head:{keywords:["face","shocked","mind","blown"],char:'🤯',fitzpatrick_scale:false,category:"people"},flushed:{keywords:["face","blush","shy","flattered"],char:'😳',fitzpatrick_scale:false,category:"people"},disappointed:{keywords:["face","sad","upset","depressed",":("],char:'😞',fitzpatrick_scale:false,category:"people"},worried:{keywords:["face","concern","nervous",":("],char:'😟',fitzpatrick_scale:false,category:"people"},angry:{keywords:["mad","face","annoyed","frustrated"],char:'😠',fitzpatrick_scale:false,category:"people"},rage:{keywords:["angry","mad","hate","despise"],char:'😡',fitzpatrick_scale:false,category:"people"},pensive:{keywords:["face","sad","depressed","upset"],char:'😔',fitzpatrick_scale:false,category:"people"},confused:{keywords:["face","indifference","huh","weird","hmmm",":/"],char:'😕',fitzpatrick_scale:false,category:"people"},slightly_frowning_face:{keywords:["face","frowning","disappointed","sad","upset"],char:'🙁',fitzpatrick_scale:false,category:"people"},frowning_face:{keywords:["face","sad","upset","frown"],char:'☹',fitzpatrick_scale:false,category:"people"},persevere:{keywords:["face","sick","no","upset","oops"],char:'😣',fitzpatrick_scale:false,category:"people"},confounded:{keywords:["face","confused","sick","unwell","oops",":S"],char:'😖',fitzpatrick_scale:false,category:"people"},tired_face:{keywords:["sick","whine","upset","frustrated"],char:'😫',fitzpatrick_scale:false,category:"people"},weary:{keywords:["face","tired","sleepy","sad","frustrated","upset"],char:'😩',fitzpatrick_scale:false,category:"people"},pleading:{keywords:["face","begging","mercy"],char:'🥺',fitzpatrick_scale:false,category:"people"},triumph:{keywords:["face","gas","phew","proud","pride"],char:'😤',fitzpatrick_scale:false,category:"people"},open_mouth:{keywords:["face","surprise","impressed","wow","whoa",":O"],char:'😮',fitzpatrick_scale:false,category:"people"},scream:{keywords:["face","munch","scared","omg"],char:'😱',fitzpatrick_scale:false,category:"people"},fearful:{keywords:["face","scared","terrified","nervous","oops","huh"],char:'😨',fitzpatrick_scale:false,category:"people"},cold_sweat:{keywords:["face","nervous","sweat"],char:'😰',fitzpatrick_scale:false,category:"people"},hushed:{keywords:["face","woo","shh"],char:'😯',fitzpatrick_scale:false,category:"people"},frowning:{keywords:["face","aw","what"],char:'😦',fitzpatrick_scale:false,category:"people"},anguished:{keywords:["face","stunned","nervous"],char:'😧',fitzpatrick_scale:false,category:"people"},cry:{keywords:["face","tears","sad","depressed","upset",":'("],char:'😢',fitzpatrick_scale:false,category:"people"},disappointed_relieved:{keywords:["face","phew","sweat","nervous"],char:'😥',fitzpatrick_scale:false,category:"people"},drooling_face:{keywords:["face"],char:'🤤',fitzpatrick_scale:false,category:"people"},sleepy:{keywords:["face","tired","rest","nap"],char:'😪',fitzpatrick_scale:false,category:"people"},sweat:{keywords:["face","hot","sad","tired","exercise"],char:'😓',fitzpatrick_scale:false,category:"people"},hot:{keywords:["face","feverish","heat","red","sweating"],char:'🥵',fitzpatrick_scale:false,category:"people"},cold:{keywords:["face","blue","freezing","frozen","frostbite","icicles"],char:'🥶',fitzpatrick_scale:false,category:"people"},sob:{keywords:["face","cry","tears","sad","upset","depressed"],char:'😭',fitzpatrick_scale:false,category:"people"},dizzy_face:{keywords:["spent","unconscious","xox","dizzy"],char:'😵',fitzpatrick_scale:false,category:"people"},astonished:{keywords:["face","xox","surprised","poisoned"],char:'😲',fitzpatrick_scale:false,category:"people"},zipper_mouth_face:{keywords:["face","sealed","zipper","secret"],char:'🤐',fitzpatrick_scale:false,category:"people"},nauseated_face:{keywords:["face","vomit","gross","green","sick","throw up","ill"],char:'🤢',fitzpatrick_scale:false,category:"people"},sneezing_face:{keywords:["face","gesundheit","sneeze","sick","allergy"],char:'🤧',fitzpatrick_scale:false,category:"people"},vomiting:{keywords:["face","sick"],char:'🤮',fitzpatrick_scale:false,category:"people"},mask:{keywords:["face","sick","ill","disease"],char:'😷',fitzpatrick_scale:false,category:"people"},face_with_thermometer:{keywords:["sick","temperature","thermometer","cold","fever"],char:'🤒',fitzpatrick_scale:false,category:"people"},face_with_head_bandage:{keywords:["injured","clumsy","bandage","hurt"],char:'🤕',fitzpatrick_scale:false,category:"people"},woozy:{keywords:["face","dizzy","intoxicated","tipsy","wavy"],char:'🥴',fitzpatrick_scale:false,category:"people"},sleeping:{keywords:["face","tired","sleepy","night","zzz"],char:'😴',fitzpatrick_scale:false,category:"people"},zzz:{keywords:["sleepy","tired","dream"],char:'💤',fitzpatrick_scale:false,category:"people"},poop:{keywords:["hankey","shitface","fail","turd","shit"],char:'💩',fitzpatrick_scale:false,category:"people"},smiling_imp:{keywords:["devil","horns"],char:'😈',fitzpatrick_scale:false,category:"people"},imp:{keywords:["devil","angry","horns"],char:'👿',fitzpatrick_scale:false,category:"people"},japanese_ogre:{keywords:["monster","red","mask","halloween","scary","creepy","devil","demon","japanese","ogre"],char:'👹',fitzpatrick_scale:false,category:"people"},japanese_goblin:{keywords:["red","evil","mask","monster","scary","creepy","japanese","goblin"],char:'👺',fitzpatrick_scale:false,category:"people"},skull:{keywords:["dead","skeleton","creepy","death"],char:'💀',fitzpatrick_scale:false,category:"people"},ghost:{keywords:["halloween","spooky","scary"],char:'👻',fitzpatrick_scale:false,category:"people"},alien:{keywords:["UFO","paul","weird","outer_space"],char:'👽',fitzpatrick_scale:false,category:"people"},robot:{keywords:["computer","machine","bot"],char:'🤖',fitzpatrick_scale:false,category:"people"},smiley_cat:{keywords:["animal","cats","happy","smile"],char:'😺',fitzpatrick_scale:false,category:"people"},smile_cat:{keywords:["animal","cats","smile"],char:'😸',fitzpatrick_scale:false,category:"people"},joy_cat:{keywords:["animal","cats","haha","happy","tears"],char:'😹',fitzpatrick_scale:false,category:"people"},heart_eyes_cat:{keywords:["animal","love","like","affection","cats","valentines","heart"],char:'😻',fitzpatrick_scale:false,category:"people"},smirk_cat:{keywords:["animal","cats","smirk"],char:'😼',fitzpatrick_scale:false,category:"people"},kissing_cat:{keywords:["animal","cats","kiss"],char:'😽',fitzpatrick_scale:false,category:"people"},scream_cat:{keywords:["animal","cats","munch","scared","scream"],char:'🙀',fitzpatrick_scale:false,category:"people"},crying_cat_face:{keywords:["animal","tears","weep","sad","cats","upset","cry"],char:'😿',fitzpatrick_scale:false,category:"people"},pouting_cat:{keywords:["animal","cats"],char:'😾',fitzpatrick_scale:false,category:"people"},palms_up:{keywords:["hands","gesture","cupped","prayer"],char:'🤲',fitzpatrick_scale:true,category:"people"},raised_hands:{keywords:["gesture","hooray","yea","celebration","hands"],char:'🙌',fitzpatrick_scale:true,category:"people"},clap:{keywords:["hands","praise","applause","congrats","yay"],char:'👏',fitzpatrick_scale:true,category:"people"},wave:{keywords:["hands","gesture","goodbye","solong","farewell","hello","hi","palm"],char:'👋',fitzpatrick_scale:true,category:"people"},call_me_hand:{keywords:["hands","gesture"],char:'🤙',fitzpatrick_scale:true,category:"people"},"+1":{keywords:["thumbsup","yes","awesome","good","agree","accept","cool","hand","like"],char:'👍',fitzpatrick_scale:true,category:"people"},"-1":{keywords:["thumbsdown","no","dislike","hand"],char:'👎',fitzpatrick_scale:true,category:"people"},facepunch:{keywords:["angry","violence","fist","hit","attack","hand"],char:'👊',fitzpatrick_scale:true,category:"people"},fist:{keywords:["fingers","hand","grasp"],char:'✊',fitzpatrick_scale:true,category:"people"},fist_left:{keywords:["hand","fistbump"],char:'🤛',fitzpatrick_scale:true,category:"people"},fist_right:{keywords:["hand","fistbump"],char:'🤜',fitzpatrick_scale:true,category:"people"},v:{keywords:["fingers","ohyeah","hand","peace","victory","two"],char:'✌',fitzpatrick_scale:true,category:"people"},ok_hand:{keywords:["fingers","limbs","perfect","ok","okay"],char:'👌',fitzpatrick_scale:true,category:"people"},raised_hand:{keywords:["fingers","stop","highfive","palm","ban"],char:'✋',fitzpatrick_scale:true,category:"people"},raised_back_of_hand:{keywords:["fingers","raised","backhand"],char:'🤚',fitzpatrick_scale:true,category:"people"},open_hands:{keywords:["fingers","butterfly","hands","open"],char:'👐',fitzpatrick_scale:true,category:"people"},muscle:{keywords:["arm","flex","hand","summer","strong","biceps"],char:'💪',fitzpatrick_scale:true,category:"people"},pray:{keywords:["please","hope","wish","namaste","highfive"],char:'🙏',fitzpatrick_scale:true,category:"people"},foot:{keywords:["kick","stomp"],char:'🦶',fitzpatrick_scale:true,category:"people"},leg:{keywords:["kick","limb"],char:'🦵',fitzpatrick_scale:true,category:"people"},handshake:{keywords:["agreement","shake"],char:'🤝',fitzpatrick_scale:false,category:"people"},point_up:{keywords:["hand","fingers","direction","up"],char:'☝',fitzpatrick_scale:true,category:"people"},point_up_2:{keywords:["fingers","hand","direction","up"],char:'👆',fitzpatrick_scale:true,category:"people"},point_down:{keywords:["fingers","hand","direction","down"],char:'👇',fitzpatrick_scale:true,category:"people"},point_left:{keywords:["direction","fingers","hand","left"],char:'👈',fitzpatrick_scale:true,category:"people"},point_right:{keywords:["fingers","hand","direction","right"],char:'👉',fitzpatrick_scale:true,category:"people"},fu:{keywords:["hand","fingers","rude","middle","flipping"],char:'🖕',fitzpatrick_scale:true,category:"people"},raised_hand_with_fingers_splayed:{keywords:["hand","fingers","palm"],char:'🖐',fitzpatrick_scale:true,category:"people"},love_you:{keywords:["hand","fingers","gesture"],char:'🤟',fitzpatrick_scale:true,category:"people"},metal:{keywords:["hand","fingers","evil_eye","sign_of_horns","rock_on"],char:'🤘',fitzpatrick_scale:true,category:"people"},crossed_fingers:{keywords:["good","lucky"],char:'🤞',fitzpatrick_scale:true,category:"people"},vulcan_salute:{keywords:["hand","fingers","spock","star trek"],char:'🖖',fitzpatrick_scale:true,category:"people"},writing_hand:{keywords:["lower_left_ballpoint_pen","stationery","write","compose"],char:'✍',fitzpatrick_scale:true,category:"people"},selfie:{keywords:["camera","phone"],char:'🤳',fitzpatrick_scale:true,category:"people"},nail_care:{keywords:["beauty","manicure","finger","fashion","nail"],char:'💅',fitzpatrick_scale:true,category:"people"},lips:{keywords:["mouth","kiss"],char:'👄',fitzpatrick_scale:false,category:"people"},tooth:{keywords:["teeth","dentist"],char:'🦷',fitzpatrick_scale:false,category:"people"},tongue:{keywords:["mouth","playful"],char:'👅',fitzpatrick_scale:false,category:"people"},ear:{keywords:["face","hear","sound","listen"],char:'👂',fitzpatrick_scale:true,category:"people"},nose:{keywords:["smell","sniff"],char:'👃',fitzpatrick_scale:true,category:"people"},eye:{keywords:["face","look","see","watch","stare"],char:'👁',fitzpatrick_scale:false,category:"people"},eyes:{keywords:["look","watch","stalk","peek","see"],char:'👀',fitzpatrick_scale:false,category:"people"},brain:{keywords:["smart","intelligent"],char:'🧠',fitzpatrick_scale:false,category:"people"},bust_in_silhouette:{keywords:["user","person","human"],char:'👤',fitzpatrick_scale:false,category:"people"},busts_in_silhouette:{keywords:["user","person","human","group","team"],char:'👥',fitzpatrick_scale:false,category:"people"},speaking_head:{keywords:["user","person","human","sing","say","talk"],char:'🗣',fitzpatrick_scale:false,category:"people"},baby:{keywords:["child","boy","girl","toddler"],char:'👶',fitzpatrick_scale:true,category:"people"},child:{keywords:["gender-neutral","young"],char:'🧒',fitzpatrick_scale:true,category:"people"},boy:{keywords:["man","male","guy","teenager"],char:'👦',fitzpatrick_scale:true,category:"people"},girl:{keywords:["female","woman","teenager"],char:'👧',fitzpatrick_scale:true,category:"people"},adult:{keywords:["gender-neutral","person"],char:'🧑',fitzpatrick_scale:true,category:"people"},man:{keywords:["mustache","father","dad","guy","classy","sir","moustache"],char:'👨',fitzpatrick_scale:true,category:"people"},woman:{keywords:["female","girls","lady"],char:'👩',fitzpatrick_scale:true,category:"people"},blonde_woman:{keywords:["woman","female","girl","blonde","person"],char:'👱‍♀️',fitzpatrick_scale:true,category:"people"},blonde_man:{keywords:["man","male","boy","blonde","guy","person"],char:'👱',fitzpatrick_scale:true,category:"people"},bearded_person:{keywords:["person","bewhiskered"],char:'🧔',fitzpatrick_scale:true,category:"people"},older_adult:{keywords:["human","elder","senior","gender-neutral"],char:'🧓',fitzpatrick_scale:true,category:"people"},older_man:{keywords:["human","male","men","old","elder","senior"],char:'👴',fitzpatrick_scale:true,category:"people"},older_woman:{keywords:["human","female","women","lady","old","elder","senior"],char:'👵',fitzpatrick_scale:true,category:"people"},man_with_gua_pi_mao:{keywords:["male","boy","chinese"],char:'👲',fitzpatrick_scale:true,category:"people"},woman_with_headscarf:{keywords:["female","hijab","mantilla","tichel"],char:'🧕',fitzpatrick_scale:true,category:"people"},woman_with_turban:{keywords:["female","indian","hinduism","arabs","woman"],char:'👳‍♀️',fitzpatrick_scale:true,category:"people"},man_with_turban:{keywords:["male","indian","hinduism","arabs"],char:'👳',fitzpatrick_scale:true,category:"people"},policewoman:{keywords:["woman","police","law","legal","enforcement","arrest","911","female"],char:'👮‍♀️',fitzpatrick_scale:true,category:"people"},policeman:{keywords:["man","police","law","legal","enforcement","arrest","911"],char:'👮',fitzpatrick_scale:true,category:"people"},construction_worker_woman:{keywords:["female","human","wip","build","construction","worker","labor","woman"],char:'👷‍♀️',fitzpatrick_scale:true,category:"people"},construction_worker_man:{keywords:["male","human","wip","guy","build","construction","worker","labor"],char:'👷',fitzpatrick_scale:true,category:"people"},guardswoman:{keywords:["uk","gb","british","female","royal","woman"],char:'💂‍♀️',fitzpatrick_scale:true,category:"people"},guardsman:{keywords:["uk","gb","british","male","guy","royal"],char:'💂',fitzpatrick_scale:true,category:"people"},female_detective:{keywords:["human","spy","detective","female","woman"],char:'🕵️‍♀️',fitzpatrick_scale:true,category:"people"},male_detective:{keywords:["human","spy","detective"],char:'🕵',fitzpatrick_scale:true,category:"people"},woman_health_worker:{keywords:["doctor","nurse","therapist","healthcare","woman","human"],char:'👩‍⚕️',fitzpatrick_scale:true,category:"people"},man_health_worker:{keywords:["doctor","nurse","therapist","healthcare","man","human"],char:'👨‍⚕️',fitzpatrick_scale:true,category:"people"},woman_farmer:{keywords:["rancher","gardener","woman","human"],char:'👩‍🌾',fitzpatrick_scale:true,category:"people"},man_farmer:{keywords:["rancher","gardener","man","human"],char:'👨‍🌾',fitzpatrick_scale:true,category:"people"},woman_cook:{keywords:["chef","woman","human"],char:'👩‍🍳',fitzpatrick_scale:true,category:"people"},man_cook:{keywords:["chef","man","human"],char:'👨‍🍳',fitzpatrick_scale:true,category:"people"},woman_student:{keywords:["graduate","woman","human"],char:'👩‍🎓',fitzpatrick_scale:true,category:"people"},man_student:{keywords:["graduate","man","human"],char:'👨‍🎓',fitzpatrick_scale:true,category:"people"},woman_singer:{keywords:["rockstar","entertainer","woman","human"],char:'👩‍🎤',fitzpatrick_scale:true,category:"people"},man_singer:{keywords:["rockstar","entertainer","man","human"],char:'👨‍🎤',fitzpatrick_scale:true,category:"people"},woman_teacher:{keywords:["instructor","professor","woman","human"],char:'👩‍🏫',fitzpatrick_scale:true,category:"people"},man_teacher:{keywords:["instructor","professor","man","human"],char:'👨‍🏫',fitzpatrick_scale:true,category:"people"},woman_factory_worker:{keywords:["assembly","industrial","woman","human"],char:'👩‍🏭',fitzpatrick_scale:true,category:"people"},man_factory_worker:{keywords:["assembly","industrial","man","human"],char:'👨‍🏭',fitzpatrick_scale:true,category:"people"},woman_technologist:{keywords:["coder","developer","engineer","programmer","software","woman","human","laptop","computer"],char:'👩‍💻',fitzpatrick_scale:true,category:"people"},man_technologist:{keywords:["coder","developer","engineer","programmer","software","man","human","laptop","computer"],char:'👨‍💻',fitzpatrick_scale:true,category:"people"},woman_office_worker:{keywords:["business","manager","woman","human"],char:'👩‍💼',fitzpatrick_scale:true,category:"people"},man_office_worker:{keywords:["business","manager","man","human"],char:'👨‍💼',fitzpatrick_scale:true,category:"people"},woman_mechanic:{keywords:["plumber","woman","human","wrench"],char:'👩‍🔧',fitzpatrick_scale:true,category:"people"},man_mechanic:{keywords:["plumber","man","human","wrench"],char:'👨‍🔧',fitzpatrick_scale:true,category:"people"},woman_scientist:{keywords:["biologist","chemist","engineer","physicist","woman","human"],char:'👩‍🔬',fitzpatrick_scale:true,category:"people"},man_scientist:{keywords:["biologist","chemist","engineer","physicist","man","human"],char:'👨‍🔬',fitzpatrick_scale:true,category:"people"},woman_artist:{keywords:["painter","woman","human"],char:'👩‍🎨',fitzpatrick_scale:true,category:"people"},man_artist:{keywords:["painter","man","human"],char:'👨‍🎨',fitzpatrick_scale:true,category:"people"},woman_firefighter:{keywords:["fireman","woman","human"],char:'👩‍🚒',fitzpatrick_scale:true,category:"people"},man_firefighter:{keywords:["fireman","man","human"],char:'👨‍🚒',fitzpatrick_scale:true,category:"people"},woman_pilot:{keywords:["aviator","plane","woman","human"],char:'👩‍✈️',fitzpatrick_scale:true,category:"people"},man_pilot:{keywords:["aviator","plane","man","human"],char:'👨‍✈️',fitzpatrick_scale:true,category:"people"},woman_astronaut:{keywords:["space","rocket","woman","human"],char:'👩‍🚀',fitzpatrick_scale:true,category:"people"},man_astronaut:{keywords:["space","rocket","man","human"],char:'👨‍🚀',fitzpatrick_scale:true,category:"people"},woman_judge:{keywords:["justice","court","woman","human"],char:'👩‍⚖️',fitzpatrick_scale:true,category:"people"},man_judge:{keywords:["justice","court","man","human"],char:'👨‍⚖️',fitzpatrick_scale:true,category:"people"},woman_superhero:{keywords:["woman","female","good","heroine","superpowers"],char:'🦸‍♀️',fitzpatrick_scale:true,category:"people"},man_superhero:{keywords:["man","male","good","hero","superpowers"],char:'🦸‍♂️',fitzpatrick_scale:true,category:"people"},woman_supervillain:{keywords:["woman","female","evil","bad","criminal","heroine","superpowers"],char:'🦹‍♀️',fitzpatrick_scale:true,category:"people"},man_supervillain:{keywords:["man","male","evil","bad","criminal","hero","superpowers"],char:'🦹‍♂️',fitzpatrick_scale:true,category:"people"},mrs_claus:{keywords:["woman","female","xmas","mother christmas"],char:'🤶',fitzpatrick_scale:true,category:"people"},santa:{keywords:["festival","man","male","xmas","father christmas"],char:'🎅',fitzpatrick_scale:true,category:"people"},sorceress:{keywords:["woman","female","mage","witch"],char:'🧙‍♀️',fitzpatrick_scale:true,category:"people"},wizard:{keywords:["man","male","mage","sorcerer"],char:'🧙‍♂️',fitzpatrick_scale:true,category:"people"},woman_elf:{keywords:["woman","female"],char:'🧝‍♀️',fitzpatrick_scale:true,category:"people"},man_elf:{keywords:["man","male"],char:'🧝‍♂️',fitzpatrick_scale:true,category:"people"},woman_vampire:{keywords:["woman","female"],char:'🧛‍♀️',fitzpatrick_scale:true,category:"people"},man_vampire:{keywords:["man","male","dracula"],char:'🧛‍♂️',fitzpatrick_scale:true,category:"people"},woman_zombie:{keywords:["woman","female","undead","walking dead"],char:'🧟‍♀️',fitzpatrick_scale:false,category:"people"},man_zombie:{keywords:["man","male","dracula","undead","walking dead"],char:'🧟‍♂️',fitzpatrick_scale:false,category:"people"},woman_genie:{keywords:["woman","female"],char:'🧞‍♀️',fitzpatrick_scale:false,category:"people"},man_genie:{keywords:["man","male"],char:'🧞‍♂️',fitzpatrick_scale:false,category:"people"},mermaid:{keywords:["woman","female","merwoman","ariel"],char:'🧜‍♀️',fitzpatrick_scale:true,category:"people"},merman:{keywords:["man","male","triton"],char:'🧜‍♂️',fitzpatrick_scale:true,category:"people"},woman_fairy:{keywords:["woman","female"],char:'🧚‍♀️',fitzpatrick_scale:true,category:"people"},man_fairy:{keywords:["man","male"],char:'🧚‍♂️',fitzpatrick_scale:true,category:"people"},angel:{keywords:["heaven","wings","halo"],char:'👼',fitzpatrick_scale:true,category:"people"},pregnant_woman:{keywords:["baby"],char:'🤰',fitzpatrick_scale:true,category:"people"},breastfeeding:{keywords:["nursing","baby"],char:'🤱',fitzpatrick_scale:true,category:"people"},princess:{keywords:["girl","woman","female","blond","crown","royal","queen"],char:'👸',fitzpatrick_scale:true,category:"people"},prince:{keywords:["boy","man","male","crown","royal","king"],char:'🤴',fitzpatrick_scale:true,category:"people"},bride_with_veil:{keywords:["couple","marriage","wedding","woman","bride"],char:'👰',fitzpatrick_scale:true,category:"people"},man_in_tuxedo:{keywords:["couple","marriage","wedding","groom"],char:'🤵',fitzpatrick_scale:true,category:"people"},running_woman:{keywords:["woman","walking","exercise","race","running","female"],char:'🏃‍♀️',fitzpatrick_scale:true,category:"people"},running_man:{keywords:["man","walking","exercise","race","running"],char:'🏃',fitzpatrick_scale:true,category:"people"},walking_woman:{keywords:["human","feet","steps","woman","female"],char:'🚶‍♀️',fitzpatrick_scale:true,category:"people"},walking_man:{keywords:["human","feet","steps"],char:'🚶',fitzpatrick_scale:true,category:"people"},dancer:{keywords:["female","girl","woman","fun"],char:'💃',fitzpatrick_scale:true,category:"people"},man_dancing:{keywords:["male","boy","fun","dancer"],char:'🕺',fitzpatrick_scale:true,category:"people"},dancing_women:{keywords:["female","bunny","women","girls"],char:'👯',fitzpatrick_scale:false,category:"people"},dancing_men:{keywords:["male","bunny","men","boys"],char:'👯‍♂️',fitzpatrick_scale:false,category:"people"},couple:{keywords:["pair","people","human","love","date","dating","like","affection","valentines","marriage"],char:'👫',fitzpatrick_scale:false,category:"people"},two_men_holding_hands:{keywords:["pair","couple","love","like","bromance","friendship","people","human"],char:'👬',fitzpatrick_scale:false,category:"people"},two_women_holding_hands:{keywords:["pair","friendship","couple","love","like","female","people","human"],char:'👭',fitzpatrick_scale:false,category:"people"},bowing_woman:{keywords:["woman","female","girl"],char:'🙇‍♀️',fitzpatrick_scale:true,category:"people"},bowing_man:{keywords:["man","male","boy"],char:'🙇',fitzpatrick_scale:true,category:"people"},man_facepalming:{keywords:["man","male","boy","disbelief"],char:'🤦‍♂️',fitzpatrick_scale:true,category:"people"},woman_facepalming:{keywords:["woman","female","girl","disbelief"],char:'🤦‍♀️',fitzpatrick_scale:true,category:"people"},woman_shrugging:{keywords:["woman","female","girl","confused","indifferent","doubt"],char:'🤷',fitzpatrick_scale:true,category:"people"},man_shrugging:{keywords:["man","male","boy","confused","indifferent","doubt"],char:'🤷‍♂️',fitzpatrick_scale:true,category:"people"},tipping_hand_woman:{keywords:["female","girl","woman","human","information"],char:'💁',fitzpatrick_scale:true,category:"people"},tipping_hand_man:{keywords:["male","boy","man","human","information"],char:'💁‍♂️',fitzpatrick_scale:true,category:"people"},no_good_woman:{keywords:["female","girl","woman","nope"],char:'🙅',fitzpatrick_scale:true,category:"people"},no_good_man:{keywords:["male","boy","man","nope"],char:'🙅‍♂️',fitzpatrick_scale:true,category:"people"},ok_woman:{keywords:["women","girl","female","pink","human","woman"],char:'🙆',fitzpatrick_scale:true,category:"people"},ok_man:{keywords:["men","boy","male","blue","human","man"],char:'🙆‍♂️',fitzpatrick_scale:true,category:"people"},raising_hand_woman:{keywords:["female","girl","woman"],char:'🙋',fitzpatrick_scale:true,category:"people"},raising_hand_man:{keywords:["male","boy","man"],char:'🙋‍♂️',fitzpatrick_scale:true,category:"people"},pouting_woman:{keywords:["female","girl","woman"],char:'🙎',fitzpatrick_scale:true,category:"people"},pouting_man:{keywords:["male","boy","man"],char:'🙎‍♂️',fitzpatrick_scale:true,category:"people"},frowning_woman:{keywords:["female","girl","woman","sad","depressed","discouraged","unhappy"],char:'🙍',fitzpatrick_scale:true,category:"people"},frowning_man:{keywords:["male","boy","man","sad","depressed","discouraged","unhappy"],char:'🙍‍♂️',fitzpatrick_scale:true,category:"people"},haircut_woman:{keywords:["female","girl","woman"],char:'💇',fitzpatrick_scale:true,category:"people"},haircut_man:{keywords:["male","boy","man"],char:'💇‍♂️',fitzpatrick_scale:true,category:"people"},massage_woman:{keywords:["female","girl","woman","head"],char:'💆',fitzpatrick_scale:true,category:"people"},massage_man:{keywords:["male","boy","man","head"],char:'💆‍♂️',fitzpatrick_scale:true,category:"people"},woman_in_steamy_room:{keywords:["female","woman","spa","steamroom","sauna"],char:'🧖‍♀️',fitzpatrick_scale:true,category:"people"},man_in_steamy_room:{keywords:["male","man","spa","steamroom","sauna"],char:'🧖‍♂️',fitzpatrick_scale:true,category:"people"},couple_with_heart_woman_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'💑',fitzpatrick_scale:false,category:"people"},couple_with_heart_woman_woman:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'👩‍❤️‍👩',fitzpatrick_scale:false,category:"people"},couple_with_heart_man_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'👨‍❤️‍👨',fitzpatrick_scale:false,category:"people"},couplekiss_man_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:'💏',fitzpatrick_scale:false,category:"people"},couplekiss_woman_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:'👩‍❤️‍💋‍👩',fitzpatrick_scale:false,category:"people"},couplekiss_man_man:{keywords:["pair","valentines","love","like","dating","marriage"],char:'👨‍❤️‍💋‍👨',fitzpatrick_scale:false,category:"people"},family_man_woman_boy:{keywords:["home","parents","child","mom","dad","father","mother","people","human"],char:'👪',fitzpatrick_scale:false,category:"people"},family_man_woman_girl:{keywords:["home","parents","people","human","child"],char:'👨‍👩‍👧',fitzpatrick_scale:false,category:"people"},family_man_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:'👨‍👩‍👧‍👦',fitzpatrick_scale:false,category:"people"},family_man_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:'👨‍👩‍👦‍👦',fitzpatrick_scale:false,category:"people"},family_man_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:'👨‍👩‍👧‍👧',fitzpatrick_scale:false,category:"people"},family_woman_woman_boy:{keywords:["home","parents","people","human","children"],char:'👩‍👩‍👦',fitzpatrick_scale:false,category:"people"},family_woman_woman_girl:{keywords:["home","parents","people","human","children"],char:'👩‍👩‍👧',fitzpatrick_scale:false,category:"people"},family_woman_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:'👩‍👩‍👧‍👦',fitzpatrick_scale:false,category:"people"},family_woman_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:'👩‍👩‍👦‍👦',fitzpatrick_scale:false,category:"people"},family_woman_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:'👩‍👩‍👧‍👧',fitzpatrick_scale:false,category:"people"},family_man_man_boy:{keywords:["home","parents","people","human","children"],char:'👨‍👨‍👦',fitzpatrick_scale:false,category:"people"},family_man_man_girl:{keywords:["home","parents","people","human","children"],char:'👨‍👨‍👧',fitzpatrick_scale:false,category:"people"},family_man_man_girl_boy:{keywords:["home","parents","people","human","children"],char:'👨‍👨‍👧‍👦',fitzpatrick_scale:false,category:"people"},family_man_man_boy_boy:{keywords:["home","parents","people","human","children"],char:'👨‍👨‍👦‍👦',fitzpatrick_scale:false,category:"people"},family_man_man_girl_girl:{keywords:["home","parents","people","human","children"],char:'👨‍👨‍👧‍👧',fitzpatrick_scale:false,category:"people"},family_woman_boy:{keywords:["home","parent","people","human","child"],char:'👩‍👦',fitzpatrick_scale:false,category:"people"},family_woman_girl:{keywords:["home","parent","people","human","child"],char:'👩‍👧',fitzpatrick_scale:false,category:"people"},family_woman_girl_boy:{keywords:["home","parent","people","human","children"],char:'👩‍👧‍👦',fitzpatrick_scale:false,category:"people"},family_woman_boy_boy:{keywords:["home","parent","people","human","children"],char:'👩‍👦‍👦',fitzpatrick_scale:false,category:"people"},family_woman_girl_girl:{keywords:["home","parent","people","human","children"],char:'👩‍👧‍👧',fitzpatrick_scale:false,category:"people"},family_man_boy:{keywords:["home","parent","people","human","child"],char:'👨‍👦',fitzpatrick_scale:false,category:"people"},family_man_girl:{keywords:["home","parent","people","human","child"],char:'👨‍👧',fitzpatrick_scale:false,category:"people"},family_man_girl_boy:{keywords:["home","parent","people","human","children"],char:'👨‍👧‍👦',fitzpatrick_scale:false,category:"people"},family_man_boy_boy:{keywords:["home","parent","people","human","children"],char:'👨‍👦‍👦',fitzpatrick_scale:false,category:"people"},family_man_girl_girl:{keywords:["home","parent","people","human","children"],char:'👨‍👧‍👧',fitzpatrick_scale:false,category:"people"},yarn:{keywords:["ball","crochet","knit"],char:'🧶',fitzpatrick_scale:false,category:"people"},thread:{keywords:["needle","sewing","spool","string"],char:'🧵',fitzpatrick_scale:false,category:"people"},coat:{keywords:["jacket"],char:'🧥',fitzpatrick_scale:false,category:"people"},labcoat:{keywords:["doctor","experiment","scientist","chemist"],char:'🥼',fitzpatrick_scale:false,category:"people"},womans_clothes:{keywords:["fashion","shopping_bags","female"],char:'👚',fitzpatrick_scale:false,category:"people"},tshirt:{keywords:["fashion","cloth","casual","shirt","tee"],char:'👕',fitzpatrick_scale:false,category:"people"},jeans:{keywords:["fashion","shopping"],char:'👖',fitzpatrick_scale:false,category:"people"},necktie:{keywords:["shirt","suitup","formal","fashion","cloth","business"],char:'👔',fitzpatrick_scale:false,category:"people"},dress:{keywords:["clothes","fashion","shopping"],char:'👗',fitzpatrick_scale:false,category:"people"},bikini:{keywords:["swimming","female","woman","girl","fashion","beach","summer"],char:'👙',fitzpatrick_scale:false,category:"people"},kimono:{keywords:["dress","fashion","women","female","japanese"],char:'👘',fitzpatrick_scale:false,category:"people"},lipstick:{keywords:["female","girl","fashion","woman"],char:'💄',fitzpatrick_scale:false,category:"people"},kiss:{keywords:["face","lips","love","like","affection","valentines"],char:'💋',fitzpatrick_scale:false,category:"people"},footprints:{keywords:["feet","tracking","walking","beach"],char:'👣',fitzpatrick_scale:false,category:"people"},flat_shoe:{keywords:["ballet","slip-on","slipper"],char:'🥿',fitzpatrick_scale:false,category:"people"},high_heel:{keywords:["fashion","shoes","female","pumps","stiletto"],char:'👠',fitzpatrick_scale:false,category:"people"},sandal:{keywords:["shoes","fashion","flip flops"],char:'👡',fitzpatrick_scale:false,category:"people"},boot:{keywords:["shoes","fashion"],char:'👢',fitzpatrick_scale:false,category:"people"},mans_shoe:{keywords:["fashion","male"],char:'👞',fitzpatrick_scale:false,category:"people"},athletic_shoe:{keywords:["shoes","sports","sneakers"],char:'👟',fitzpatrick_scale:false,category:"people"},hiking_boot:{keywords:["backpacking","camping","hiking"],char:'🥾',fitzpatrick_scale:false,category:"people"},socks:{keywords:["stockings","clothes"],char:'🧦',fitzpatrick_scale:false,category:"people"},gloves:{keywords:["hands","winter","clothes"],char:'🧤',fitzpatrick_scale:false,category:"people"},scarf:{keywords:["neck","winter","clothes"],char:'🧣',fitzpatrick_scale:false,category:"people"},womans_hat:{keywords:["fashion","accessories","female","lady","spring"],char:'👒',fitzpatrick_scale:false,category:"people"},tophat:{keywords:["magic","gentleman","classy","circus"],char:'🎩',fitzpatrick_scale:false,category:"people"},billed_hat:{keywords:["cap","baseball"],char:'🧢',fitzpatrick_scale:false,category:"people"},rescue_worker_helmet:{keywords:["construction","build"],char:'⛑',fitzpatrick_scale:false,category:"people"},mortar_board:{keywords:["school","college","degree","university","graduation","cap","hat","legal","learn","education"],char:'🎓',fitzpatrick_scale:false,category:"people"},crown:{keywords:["king","kod","leader","royalty","lord"],char:'👑',fitzpatrick_scale:false,category:"people"},school_satchel:{keywords:["student","education","bag","backpack"],char:'🎒',fitzpatrick_scale:false,category:"people"},luggage:{keywords:["packing","travel"],char:'🧳',fitzpatrick_scale:false,category:"people"},pouch:{keywords:["bag","accessories","shopping"],char:'👝',fitzpatrick_scale:false,category:"people"},purse:{keywords:["fashion","accessories","money","sales","shopping"],char:'👛',fitzpatrick_scale:false,category:"people"},handbag:{keywords:["fashion","accessory","accessories","shopping"],char:'👜',fitzpatrick_scale:false,category:"people"},briefcase:{keywords:["business","documents","work","law","legal","job","career"],char:'💼',fitzpatrick_scale:false,category:"people"},eyeglasses:{keywords:["fashion","accessories","eyesight","nerdy","dork","geek"],char:'👓',fitzpatrick_scale:false,category:"people"},dark_sunglasses:{keywords:["face","cool","accessories"],char:'🕶',fitzpatrick_scale:false,category:"people"},goggles:{keywords:["eyes","protection","safety"],char:'🥽',fitzpatrick_scale:false,category:"people"},ring:{keywords:["wedding","propose","marriage","valentines","diamond","fashion","jewelry","gem","engagement"],char:'💍',fitzpatrick_scale:false,category:"people"},closed_umbrella:{keywords:["weather","rain","drizzle"],char:'🌂',fitzpatrick_scale:false,category:"people"},dog:{keywords:["animal","friend","nature","woof","puppy","pet","faithful"],char:'🐶',fitzpatrick_scale:false,category:"animals_and_nature"},cat:{keywords:["animal","meow","nature","pet","kitten"],char:'🐱',fitzpatrick_scale:false,category:"animals_and_nature"},mouse:{keywords:["animal","nature","cheese_wedge","rodent"],char:'🐭',fitzpatrick_scale:false,category:"animals_and_nature"},hamster:{keywords:["animal","nature"],char:'🐹',fitzpatrick_scale:false,category:"animals_and_nature"},rabbit:{keywords:["animal","nature","pet","spring","magic","bunny"],char:'🐰',fitzpatrick_scale:false,category:"animals_and_nature"},fox_face:{keywords:["animal","nature","face"],char:'🦊',fitzpatrick_scale:false,category:"animals_and_nature"},bear:{keywords:["animal","nature","wild"],char:'🐻',fitzpatrick_scale:false,category:"animals_and_nature"},panda_face:{keywords:["animal","nature","panda"],char:'🐼',fitzpatrick_scale:false,category:"animals_and_nature"},koala:{keywords:["animal","nature"],char:'🐨',fitzpatrick_scale:false,category:"animals_and_nature"},tiger:{keywords:["animal","cat","danger","wild","nature","roar"],char:'🐯',fitzpatrick_scale:false,category:"animals_and_nature"},lion:{keywords:["animal","nature"],char:'🦁',fitzpatrick_scale:false,category:"animals_and_nature"},cow:{keywords:["beef","ox","animal","nature","moo","milk"],char:'🐮',fitzpatrick_scale:false,category:"animals_and_nature"},pig:{keywords:["animal","oink","nature"],char:'🐷',fitzpatrick_scale:false,category:"animals_and_nature"},pig_nose:{keywords:["animal","oink"],char:'🐽',fitzpatrick_scale:false,category:"animals_and_nature"},frog:{keywords:["animal","nature","croak","toad"],char:'🐸',fitzpatrick_scale:false,category:"animals_and_nature"},squid:{keywords:["animal","nature","ocean","sea"],char:'🦑',fitzpatrick_scale:false,category:"animals_and_nature"},octopus:{keywords:["animal","creature","ocean","sea","nature","beach"],char:'🐙',fitzpatrick_scale:false,category:"animals_and_nature"},shrimp:{keywords:["animal","ocean","nature","seafood"],char:'🦐',fitzpatrick_scale:false,category:"animals_and_nature"},monkey_face:{keywords:["animal","nature","circus"],char:'🐵',fitzpatrick_scale:false,category:"animals_and_nature"},gorilla:{keywords:["animal","nature","circus"],char:'🦍',fitzpatrick_scale:false,category:"animals_and_nature"},see_no_evil:{keywords:["monkey","animal","nature","haha"],char:'🙈',fitzpatrick_scale:false,category:"animals_and_nature"},hear_no_evil:{keywords:["animal","monkey","nature"],char:'🙉',fitzpatrick_scale:false,category:"animals_and_nature"},speak_no_evil:{keywords:["monkey","animal","nature","omg"],char:'🙊',fitzpatrick_scale:false,category:"animals_and_nature"},monkey:{keywords:["animal","nature","banana","circus"],char:'🐒',fitzpatrick_scale:false,category:"animals_and_nature"},chicken:{keywords:["animal","cluck","nature","bird"],char:'🐔',fitzpatrick_scale:false,category:"animals_and_nature"},penguin:{keywords:["animal","nature"],char:'🐧',fitzpatrick_scale:false,category:"animals_and_nature"},bird:{keywords:["animal","nature","fly","tweet","spring"],char:'🐦',fitzpatrick_scale:false,category:"animals_and_nature"},baby_chick:{keywords:["animal","chicken","bird"],char:'🐤',fitzpatrick_scale:false,category:"animals_and_nature"},hatching_chick:{keywords:["animal","chicken","egg","born","baby","bird"],char:'🐣',fitzpatrick_scale:false,category:"animals_and_nature"},hatched_chick:{keywords:["animal","chicken","baby","bird"],char:'🐥',fitzpatrick_scale:false,category:"animals_and_nature"},duck:{keywords:["animal","nature","bird","mallard"],char:'🦆',fitzpatrick_scale:false,category:"animals_and_nature"},eagle:{keywords:["animal","nature","bird"],char:'🦅',fitzpatrick_scale:false,category:"animals_and_nature"},owl:{keywords:["animal","nature","bird","hoot"],char:'🦉',fitzpatrick_scale:false,category:"animals_and_nature"},bat:{keywords:["animal","nature","blind","vampire"],char:'🦇',fitzpatrick_scale:false,category:"animals_and_nature"},wolf:{keywords:["animal","nature","wild"],char:'🐺',fitzpatrick_scale:false,category:"animals_and_nature"},boar:{keywords:["animal","nature"],char:'🐗',fitzpatrick_scale:false,category:"animals_and_nature"},horse:{keywords:["animal","brown","nature"],char:'🐴',fitzpatrick_scale:false,category:"animals_and_nature"},unicorn:{keywords:["animal","nature","mystical"],char:'🦄',fitzpatrick_scale:false,category:"animals_and_nature"},honeybee:{keywords:["animal","insect","nature","bug","spring","honey"],char:'🐝',fitzpatrick_scale:false,category:"animals_and_nature"},bug:{keywords:["animal","insect","nature","worm"],char:'🐛',fitzpatrick_scale:false,category:"animals_and_nature"},butterfly:{keywords:["animal","insect","nature","caterpillar"],char:'🦋',fitzpatrick_scale:false,category:"animals_and_nature"},snail:{keywords:["slow","animal","shell"],char:'🐌',fitzpatrick_scale:false,category:"animals_and_nature"},beetle:{keywords:["animal","insect","nature","ladybug"],char:'🐞',fitzpatrick_scale:false,category:"animals_and_nature"},ant:{keywords:["animal","insect","nature","bug"],char:'🐜',fitzpatrick_scale:false,category:"animals_and_nature"},grasshopper:{keywords:["animal","cricket","chirp"],char:'🦗',fitzpatrick_scale:false,category:"animals_and_nature"},spider:{keywords:["animal","arachnid"],char:'🕷',fitzpatrick_scale:false,category:"animals_and_nature"},scorpion:{keywords:["animal","arachnid"],char:'🦂',fitzpatrick_scale:false,category:"animals_and_nature"},crab:{keywords:["animal","crustacean"],char:'🦀',fitzpatrick_scale:false,category:"animals_and_nature"},snake:{keywords:["animal","evil","nature","hiss","python"],char:'🐍',fitzpatrick_scale:false,category:"animals_and_nature"},lizard:{keywords:["animal","nature","reptile"],char:'🦎',fitzpatrick_scale:false,category:"animals_and_nature"},"t-rex":{keywords:["animal","nature","dinosaur","tyrannosaurus","extinct"],char:'🦖',fitzpatrick_scale:false,category:"animals_and_nature"},sauropod:{keywords:["animal","nature","dinosaur","brachiosaurus","brontosaurus","diplodocus","extinct"],char:'🦕',fitzpatrick_scale:false,category:"animals_and_nature"},turtle:{keywords:["animal","slow","nature","tortoise"],char:'🐢',fitzpatrick_scale:false,category:"animals_and_nature"},tropical_fish:{keywords:["animal","swim","ocean","beach","nemo"],char:'🐠',fitzpatrick_scale:false,category:"animals_and_nature"},fish:{keywords:["animal","food","nature"],char:'🐟',fitzpatrick_scale:false,category:"animals_and_nature"},blowfish:{keywords:["animal","nature","food","sea","ocean"],char:'🐡',fitzpatrick_scale:false,category:"animals_and_nature"},dolphin:{keywords:["animal","nature","fish","sea","ocean","flipper","fins","beach"],char:'🐬',fitzpatrick_scale:false,category:"animals_and_nature"},shark:{keywords:["animal","nature","fish","sea","ocean","jaws","fins","beach"],char:'🦈',fitzpatrick_scale:false,category:"animals_and_nature"},whale:{keywords:["animal","nature","sea","ocean"],char:'🐳',fitzpatrick_scale:false,category:"animals_and_nature"},whale2:{keywords:["animal","nature","sea","ocean"],char:'🐋',fitzpatrick_scale:false,category:"animals_and_nature"},crocodile:{keywords:["animal","nature","reptile","lizard","alligator"],char:'🐊',fitzpatrick_scale:false,category:"animals_and_nature"},leopard:{keywords:["animal","nature"],char:'🐆',fitzpatrick_scale:false,category:"animals_and_nature"},zebra:{keywords:["animal","nature","stripes","safari"],char:'🦓',fitzpatrick_scale:false,category:"animals_and_nature"},tiger2:{keywords:["animal","nature","roar"],char:'🐅',fitzpatrick_scale:false,category:"animals_and_nature"},water_buffalo:{keywords:["animal","nature","ox","cow"],char:'🐃',fitzpatrick_scale:false,category:"animals_and_nature"},ox:{keywords:["animal","cow","beef"],char:'🐂',fitzpatrick_scale:false,category:"animals_and_nature"},cow2:{keywords:["beef","ox","animal","nature","moo","milk"],char:'🐄',fitzpatrick_scale:false,category:"animals_and_nature"},deer:{keywords:["animal","nature","horns","venison"],char:'🦌',fitzpatrick_scale:false,category:"animals_and_nature"},dromedary_camel:{keywords:["animal","hot","desert","hump"],char:'🐪',fitzpatrick_scale:false,category:"animals_and_nature"},camel:{keywords:["animal","nature","hot","desert","hump"],char:'🐫',fitzpatrick_scale:false,category:"animals_and_nature"},giraffe:{keywords:["animal","nature","spots","safari"],char:'🦒',fitzpatrick_scale:false,category:"animals_and_nature"},elephant:{keywords:["animal","nature","nose","th","circus"],char:'🐘',fitzpatrick_scale:false,category:"animals_and_nature"},rhinoceros:{keywords:["animal","nature","horn"],char:'🦏',fitzpatrick_scale:false,category:"animals_and_nature"},goat:{keywords:["animal","nature"],char:'🐐',fitzpatrick_scale:false,category:"animals_and_nature"},ram:{keywords:["animal","sheep","nature"],char:'🐏',fitzpatrick_scale:false,category:"animals_and_nature"},sheep:{keywords:["animal","nature","wool","shipit"],char:'🐑',fitzpatrick_scale:false,category:"animals_and_nature"},racehorse:{keywords:["animal","gamble","luck"],char:'🐎',fitzpatrick_scale:false,category:"animals_and_nature"},pig2:{keywords:["animal","nature"],char:'🐖',fitzpatrick_scale:false,category:"animals_and_nature"},rat:{keywords:["animal","mouse","rodent"],char:'🐀',fitzpatrick_scale:false,category:"animals_and_nature"},mouse2:{keywords:["animal","nature","rodent"],char:'🐁',fitzpatrick_scale:false,category:"animals_and_nature"},rooster:{keywords:["animal","nature","chicken"],char:'🐓',fitzpatrick_scale:false,category:"animals_and_nature"},turkey:{keywords:["animal","bird"],char:'🦃',fitzpatrick_scale:false,category:"animals_and_nature"},dove:{keywords:["animal","bird"],char:'🕊',fitzpatrick_scale:false,category:"animals_and_nature"},dog2:{keywords:["animal","nature","friend","doge","pet","faithful"],char:'🐕',fitzpatrick_scale:false,category:"animals_and_nature"},poodle:{keywords:["dog","animal","101","nature","pet"],char:'🐩',fitzpatrick_scale:false,category:"animals_and_nature"},cat2:{keywords:["animal","meow","pet","cats"],char:'🐈',fitzpatrick_scale:false,category:"animals_and_nature"},rabbit2:{keywords:["animal","nature","pet","magic","spring"],char:'🐇',fitzpatrick_scale:false,category:"animals_and_nature"},chipmunk:{keywords:["animal","nature","rodent","squirrel"],char:'🐿',fitzpatrick_scale:false,category:"animals_and_nature"},hedgehog:{keywords:["animal","nature","spiny"],char:'🦔',fitzpatrick_scale:false,category:"animals_and_nature"},raccoon:{keywords:["animal","nature"],char:'🦝',fitzpatrick_scale:false,category:"animals_and_nature"},llama:{keywords:["animal","nature","alpaca"],char:'🦙',fitzpatrick_scale:false,category:"animals_and_nature"},hippopotamus:{keywords:["animal","nature"],char:'🦛',fitzpatrick_scale:false,category:"animals_and_nature"},kangaroo:{keywords:["animal","nature","australia","joey","hop","marsupial"],char:'🦘',fitzpatrick_scale:false,category:"animals_and_nature"},badger:{keywords:["animal","nature","honey"],char:'🦡',fitzpatrick_scale:false,category:"animals_and_nature"},swan:{keywords:["animal","nature","bird"],char:'🦢',fitzpatrick_scale:false,category:"animals_and_nature"},peacock:{keywords:["animal","nature","peahen","bird"],char:'🦚',fitzpatrick_scale:false,category:"animals_and_nature"},parrot:{keywords:["animal","nature","bird","pirate","talk"],char:'🦜',fitzpatrick_scale:false,category:"animals_and_nature"},lobster:{keywords:["animal","nature","bisque","claws","seafood"],char:'🦞',fitzpatrick_scale:false,category:"animals_and_nature"},mosquito:{keywords:["animal","nature","insect","malaria"],char:'🦟',fitzpatrick_scale:false,category:"animals_and_nature"},paw_prints:{keywords:["animal","tracking","footprints","dog","cat","pet","feet"],char:'🐾',fitzpatrick_scale:false,category:"animals_and_nature"},dragon:{keywords:["animal","myth","nature","chinese","green"],char:'🐉',fitzpatrick_scale:false,category:"animals_and_nature"},dragon_face:{keywords:["animal","myth","nature","chinese","green"],char:'🐲',fitzpatrick_scale:false,category:"animals_and_nature"},cactus:{keywords:["vegetable","plant","nature"],char:'🌵',fitzpatrick_scale:false,category:"animals_and_nature"},christmas_tree:{keywords:["festival","vacation","december","xmas","celebration"],char:'🎄',fitzpatrick_scale:false,category:"animals_and_nature"},evergreen_tree:{keywords:["plant","nature"],char:'🌲',fitzpatrick_scale:false,category:"animals_and_nature"},deciduous_tree:{keywords:["plant","nature"],char:'🌳',fitzpatrick_scale:false,category:"animals_and_nature"},palm_tree:{keywords:["plant","vegetable","nature","summer","beach","mojito","tropical"],char:'🌴',fitzpatrick_scale:false,category:"animals_and_nature"},seedling:{keywords:["plant","nature","grass","lawn","spring"],char:'🌱',fitzpatrick_scale:false,category:"animals_and_nature"},herb:{keywords:["vegetable","plant","medicine","weed","grass","lawn"],char:'🌿',fitzpatrick_scale:false,category:"animals_and_nature"},shamrock:{keywords:["vegetable","plant","nature","irish","clover"],char:'☘',fitzpatrick_scale:false,category:"animals_and_nature"},four_leaf_clover:{keywords:["vegetable","plant","nature","lucky","irish"],char:'🍀',fitzpatrick_scale:false,category:"animals_and_nature"},bamboo:{keywords:["plant","nature","vegetable","panda","pine_decoration"],char:'🎍',fitzpatrick_scale:false,category:"animals_and_nature"},tanabata_tree:{keywords:["plant","nature","branch","summer"],char:'🎋',fitzpatrick_scale:false,category:"animals_and_nature"},leaves:{keywords:["nature","plant","tree","vegetable","grass","lawn","spring"],char:'🍃',fitzpatrick_scale:false,category:"animals_and_nature"},fallen_leaf:{keywords:["nature","plant","vegetable","leaves"],char:'🍂',fitzpatrick_scale:false,category:"animals_and_nature"},maple_leaf:{keywords:["nature","plant","vegetable","ca","fall"],char:'🍁',fitzpatrick_scale:false,category:"animals_and_nature"},ear_of_rice:{keywords:["nature","plant"],char:'🌾',fitzpatrick_scale:false,category:"animals_and_nature"},hibiscus:{keywords:["plant","vegetable","flowers","beach"],char:'🌺',fitzpatrick_scale:false,category:"animals_and_nature"},sunflower:{keywords:["nature","plant","fall"],char:'🌻',fitzpatrick_scale:false,category:"animals_and_nature"},rose:{keywords:["flowers","valentines","love","spring"],char:'🌹',fitzpatrick_scale:false,category:"animals_and_nature"},wilted_flower:{keywords:["plant","nature","flower"],char:'🥀',fitzpatrick_scale:false,category:"animals_and_nature"},tulip:{keywords:["flowers","plant","nature","summer","spring"],char:'🌷',fitzpatrick_scale:false,category:"animals_and_nature"},blossom:{keywords:["nature","flowers","yellow"],char:'🌼',fitzpatrick_scale:false,category:"animals_and_nature"},cherry_blossom:{keywords:["nature","plant","spring","flower"],char:'🌸',fitzpatrick_scale:false,category:"animals_and_nature"},bouquet:{keywords:["flowers","nature","spring"],char:'💐',fitzpatrick_scale:false,category:"animals_and_nature"},mushroom:{keywords:["plant","vegetable"],char:'🍄',fitzpatrick_scale:false,category:"animals_and_nature"},chestnut:{keywords:["food","squirrel"],char:'🌰',fitzpatrick_scale:false,category:"animals_and_nature"},jack_o_lantern:{keywords:["halloween","light","pumpkin","creepy","fall"],char:'🎃',fitzpatrick_scale:false,category:"animals_and_nature"},shell:{keywords:["nature","sea","beach"],char:'🐚',fitzpatrick_scale:false,category:"animals_and_nature"},spider_web:{keywords:["animal","insect","arachnid","silk"],char:'🕸',fitzpatrick_scale:false,category:"animals_and_nature"},earth_americas:{keywords:["globe","world","USA","international"],char:'🌎',fitzpatrick_scale:false,category:"animals_and_nature"},earth_africa:{keywords:["globe","world","international"],char:'🌍',fitzpatrick_scale:false,category:"animals_and_nature"},earth_asia:{keywords:["globe","world","east","international"],char:'🌏',fitzpatrick_scale:false,category:"animals_and_nature"},full_moon:{keywords:["nature","yellow","twilight","planet","space","night","evening","sleep"],char:'🌕',fitzpatrick_scale:false,category:"animals_and_nature"},waning_gibbous_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep","waxing_gibbous_moon"],char:'🌖',fitzpatrick_scale:false,category:"animals_and_nature"},last_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌗',fitzpatrick_scale:false,category:"animals_and_nature"},waning_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌘',fitzpatrick_scale:false,category:"animals_and_nature"},new_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌑',fitzpatrick_scale:false,category:"animals_and_nature"},waxing_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌒',fitzpatrick_scale:false,category:"animals_and_nature"},first_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌓',fitzpatrick_scale:false,category:"animals_and_nature"},waxing_gibbous_moon:{keywords:["nature","night","sky","gray","twilight","planet","space","evening","sleep"],char:'🌔',fitzpatrick_scale:false,category:"animals_and_nature"},new_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌚',fitzpatrick_scale:false,category:"animals_and_nature"},full_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌝',fitzpatrick_scale:false,category:"animals_and_nature"},first_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌛',fitzpatrick_scale:false,category:"animals_and_nature"},last_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌜',fitzpatrick_scale:false,category:"animals_and_nature"},sun_with_face:{keywords:["nature","morning","sky"],char:'🌞',fitzpatrick_scale:false,category:"animals_and_nature"},crescent_moon:{keywords:["night","sleep","sky","evening","magic"],char:'🌙',fitzpatrick_scale:false,category:"animals_and_nature"},star:{keywords:["night","yellow"],char:'⭐',fitzpatrick_scale:false,category:"animals_and_nature"},star2:{keywords:["night","sparkle","awesome","good","magic"],char:'🌟',fitzpatrick_scale:false,category:"animals_and_nature"},dizzy:{keywords:["star","sparkle","shoot","magic"],char:'💫',fitzpatrick_scale:false,category:"animals_and_nature"},sparkles:{keywords:["stars","shine","shiny","cool","awesome","good","magic"],char:'✨',fitzpatrick_scale:false,category:"animals_and_nature"},comet:{keywords:["space"],char:'☄',fitzpatrick_scale:false,category:"animals_and_nature"},sunny:{keywords:["weather","nature","brightness","summer","beach","spring"],char:'☀️',fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_small_cloud:{keywords:["weather"],char:'🌤',fitzpatrick_scale:false,category:"animals_and_nature"},partly_sunny:{keywords:["weather","nature","cloudy","morning","fall","spring"],char:'⛅',fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_large_cloud:{keywords:["weather"],char:'🌥',fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_rain_cloud:{keywords:["weather"],char:'🌦',fitzpatrick_scale:false,category:"animals_and_nature"},cloud:{keywords:["weather","sky"],char:'☁️',fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_rain:{keywords:["weather"],char:'🌧',fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_lightning_and_rain:{keywords:["weather","lightning"],char:'⛈',fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_lightning:{keywords:["weather","thunder"],char:'🌩',fitzpatrick_scale:false,category:"animals_and_nature"},zap:{keywords:["thunder","weather","lightning bolt","fast"],char:'⚡',fitzpatrick_scale:false,category:"animals_and_nature"},fire:{keywords:["hot","cook","flame"],char:'🔥',fitzpatrick_scale:false,category:"animals_and_nature"},boom:{keywords:["bomb","explode","explosion","collision","blown"],char:'💥',fitzpatrick_scale:false,category:"animals_and_nature"},snowflake:{keywords:["winter","season","cold","weather","christmas","xmas"],char:'❄️',fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_snow:{keywords:["weather"],char:'🌨',fitzpatrick_scale:false,category:"animals_and_nature"},snowman:{keywords:["winter","season","cold","weather","christmas","xmas","frozen","without_snow"],char:'⛄',fitzpatrick_scale:false,category:"animals_and_nature"},snowman_with_snow:{keywords:["winter","season","cold","weather","christmas","xmas","frozen"],char:'☃',fitzpatrick_scale:false,category:"animals_and_nature"},wind_face:{keywords:["gust","air"],char:'🌬',fitzpatrick_scale:false,category:"animals_and_nature"},dash:{keywords:["wind","air","fast","shoo","fart","smoke","puff"],char:'💨',fitzpatrick_scale:false,category:"animals_and_nature"},tornado:{keywords:["weather","cyclone","twister"],char:'🌪',fitzpatrick_scale:false,category:"animals_and_nature"},fog:{keywords:["weather"],char:'🌫',fitzpatrick_scale:false,category:"animals_and_nature"},open_umbrella:{keywords:["weather","spring"],char:'☂',fitzpatrick_scale:false,category:"animals_and_nature"},umbrella:{keywords:["rainy","weather","spring"],char:'☔',fitzpatrick_scale:false,category:"animals_and_nature"},droplet:{keywords:["water","drip","faucet","spring"],char:'💧',fitzpatrick_scale:false,category:"animals_and_nature"},sweat_drops:{keywords:["water","drip","oops"],char:'💦',fitzpatrick_scale:false,category:"animals_and_nature"},ocean:{keywords:["sea","water","wave","nature","tsunami","disaster"],char:'🌊',fitzpatrick_scale:false,category:"animals_and_nature"},green_apple:{keywords:["fruit","nature"],char:'🍏',fitzpatrick_scale:false,category:"food_and_drink"},apple:{keywords:["fruit","mac","school"],char:'🍎',fitzpatrick_scale:false,category:"food_and_drink"},pear:{keywords:["fruit","nature","food"],char:'🍐',fitzpatrick_scale:false,category:"food_and_drink"},tangerine:{keywords:["food","fruit","nature","orange"],char:'🍊',fitzpatrick_scale:false,category:"food_and_drink"},lemon:{keywords:["fruit","nature"],char:'🍋',fitzpatrick_scale:false,category:"food_and_drink"},banana:{keywords:["fruit","food","monkey"],char:'🍌',fitzpatrick_scale:false,category:"food_and_drink"},watermelon:{keywords:["fruit","food","picnic","summer"],char:'🍉',fitzpatrick_scale:false,category:"food_and_drink"},grapes:{keywords:["fruit","food","wine"],char:'🍇',fitzpatrick_scale:false,category:"food_and_drink"},strawberry:{keywords:["fruit","food","nature"],char:'🍓',fitzpatrick_scale:false,category:"food_and_drink"},melon:{keywords:["fruit","nature","food"],char:'🍈',fitzpatrick_scale:false,category:"food_and_drink"},cherries:{keywords:["food","fruit"],char:'🍒',fitzpatrick_scale:false,category:"food_and_drink"},peach:{keywords:["fruit","nature","food"],char:'🍑',fitzpatrick_scale:false,category:"food_and_drink"},pineapple:{keywords:["fruit","nature","food"],char:'🍍',fitzpatrick_scale:false,category:"food_and_drink"},coconut:{keywords:["fruit","nature","food","palm"],char:'🥥',fitzpatrick_scale:false,category:"food_and_drink"},kiwi_fruit:{keywords:["fruit","food"],char:'🥝',fitzpatrick_scale:false,category:"food_and_drink"},mango:{keywords:["fruit","food","tropical"],char:'🥭',fitzpatrick_scale:false,category:"food_and_drink"},avocado:{keywords:["fruit","food"],char:'🥑',fitzpatrick_scale:false,category:"food_and_drink"},broccoli:{keywords:["fruit","food","vegetable"],char:'🥦',fitzpatrick_scale:false,category:"food_and_drink"},tomato:{keywords:["fruit","vegetable","nature","food"],char:'🍅',fitzpatrick_scale:false,category:"food_and_drink"},eggplant:{keywords:["vegetable","nature","food","aubergine"],char:'🍆',fitzpatrick_scale:false,category:"food_and_drink"},cucumber:{keywords:["fruit","food","pickle"],char:'🥒',fitzpatrick_scale:false,category:"food_and_drink"},carrot:{keywords:["vegetable","food","orange"],char:'🥕',fitzpatrick_scale:false,category:"food_and_drink"},hot_pepper:{keywords:["food","spicy","chilli","chili"],char:'🌶',fitzpatrick_scale:false,category:"food_and_drink"},potato:{keywords:["food","tuber","vegatable","starch"],char:'🥔',fitzpatrick_scale:false,category:"food_and_drink"},corn:{keywords:["food","vegetable","plant"],char:'🌽',fitzpatrick_scale:false,category:"food_and_drink"},leafy_greens:{keywords:["food","vegetable","plant","bok choy","cabbage","kale","lettuce"],char:'🥬',fitzpatrick_scale:false,category:"food_and_drink"},sweet_potato:{keywords:["food","nature"],char:'🍠',fitzpatrick_scale:false,category:"food_and_drink"},peanuts:{keywords:["food","nut"],char:'🥜',fitzpatrick_scale:false,category:"food_and_drink"},honey_pot:{keywords:["bees","sweet","kitchen"],char:'🍯',fitzpatrick_scale:false,category:"food_and_drink"},croissant:{keywords:["food","bread","french"],char:'🥐',fitzpatrick_scale:false,category:"food_and_drink"},bread:{keywords:["food","wheat","breakfast","toast"],char:'🍞',fitzpatrick_scale:false,category:"food_and_drink"},baguette_bread:{keywords:["food","bread","french"],char:'🥖',fitzpatrick_scale:false,category:"food_and_drink"},bagel:{keywords:["food","bread","bakery","schmear"],char:'🥯',fitzpatrick_scale:false,category:"food_and_drink"},pretzel:{keywords:["food","bread","twisted"],char:'🥨',fitzpatrick_scale:false,category:"food_and_drink"},cheese:{keywords:["food","chadder"],char:'🧀',fitzpatrick_scale:false,category:"food_and_drink"},egg:{keywords:["food","chicken","breakfast"],char:'🥚',fitzpatrick_scale:false,category:"food_and_drink"},bacon:{keywords:["food","breakfast","pork","pig","meat"],char:'🥓',fitzpatrick_scale:false,category:"food_and_drink"},steak:{keywords:["food","cow","meat","cut","chop","lambchop","porkchop"],char:'🥩',fitzpatrick_scale:false,category:"food_and_drink"},pancakes:{keywords:["food","breakfast","flapjacks","hotcakes"],char:'🥞',fitzpatrick_scale:false,category:"food_and_drink"},poultry_leg:{keywords:["food","meat","drumstick","bird","chicken","turkey"],char:'🍗',fitzpatrick_scale:false,category:"food_and_drink"},meat_on_bone:{keywords:["good","food","drumstick"],char:'🍖',fitzpatrick_scale:false,category:"food_and_drink"},bone:{keywords:["skeleton"],char:'🦴',fitzpatrick_scale:false,category:"food_and_drink"},fried_shrimp:{keywords:["food","animal","appetizer","summer"],char:'🍤',fitzpatrick_scale:false,category:"food_and_drink"},fried_egg:{keywords:["food","breakfast","kitchen","egg"],char:'🍳',fitzpatrick_scale:false,category:"food_and_drink"},hamburger:{keywords:["meat","fast food","beef","cheeseburger","mcdonalds","burger king"],char:'🍔',fitzpatrick_scale:false,category:"food_and_drink"},fries:{keywords:["chips","snack","fast food"],char:'🍟',fitzpatrick_scale:false,category:"food_and_drink"},stuffed_flatbread:{keywords:["food","flatbread","stuffed","gyro"],char:'🥙',fitzpatrick_scale:false,category:"food_and_drink"},hotdog:{keywords:["food","frankfurter"],char:'🌭',fitzpatrick_scale:false,category:"food_and_drink"},pizza:{keywords:["food","party"],char:'🍕',fitzpatrick_scale:false,category:"food_and_drink"},sandwich:{keywords:["food","lunch","bread"],char:'🥪',fitzpatrick_scale:false,category:"food_and_drink"},canned_food:{keywords:["food","soup"],char:'🥫',fitzpatrick_scale:false,category:"food_and_drink"},spaghetti:{keywords:["food","italian","noodle"],char:'🍝',fitzpatrick_scale:false,category:"food_and_drink"},taco:{keywords:["food","mexican"],char:'🌮',fitzpatrick_scale:false,category:"food_and_drink"},burrito:{keywords:["food","mexican"],char:'🌯',fitzpatrick_scale:false,category:"food_and_drink"},green_salad:{keywords:["food","healthy","lettuce"],char:'🥗',fitzpatrick_scale:false,category:"food_and_drink"},shallow_pan_of_food:{keywords:["food","cooking","casserole","paella"],char:'🥘',fitzpatrick_scale:false,category:"food_and_drink"},ramen:{keywords:["food","japanese","noodle","chopsticks"],char:'🍜',fitzpatrick_scale:false,category:"food_and_drink"},stew:{keywords:["food","meat","soup"],char:'🍲',fitzpatrick_scale:false,category:"food_and_drink"},fish_cake:{keywords:["food","japan","sea","beach","narutomaki","pink","swirl","kamaboko","surimi","ramen"],char:'🍥',fitzpatrick_scale:false,category:"food_and_drink"},fortune_cookie:{keywords:["food","prophecy"],char:'🥠',fitzpatrick_scale:false,category:"food_and_drink"},sushi:{keywords:["food","fish","japanese","rice"],char:'🍣',fitzpatrick_scale:false,category:"food_and_drink"},bento:{keywords:["food","japanese","box"],char:'🍱',fitzpatrick_scale:false,category:"food_and_drink"},curry:{keywords:["food","spicy","hot","indian"],char:'🍛',fitzpatrick_scale:false,category:"food_and_drink"},rice_ball:{keywords:["food","japanese"],char:'🍙',fitzpatrick_scale:false,category:"food_and_drink"},rice:{keywords:["food","china","asian"],char:'🍚',fitzpatrick_scale:false,category:"food_and_drink"},rice_cracker:{keywords:["food","japanese"],char:'🍘',fitzpatrick_scale:false,category:"food_and_drink"},oden:{keywords:["food","japanese"],char:'🍢',fitzpatrick_scale:false,category:"food_and_drink"},dango:{keywords:["food","dessert","sweet","japanese","barbecue","meat"],char:'🍡',fitzpatrick_scale:false,category:"food_and_drink"},shaved_ice:{keywords:["hot","dessert","summer"],char:'🍧',fitzpatrick_scale:false,category:"food_and_drink"},ice_cream:{keywords:["food","hot","dessert"],char:'🍨',fitzpatrick_scale:false,category:"food_and_drink"},icecream:{keywords:["food","hot","dessert","summer"],char:'🍦',fitzpatrick_scale:false,category:"food_and_drink"},pie:{keywords:["food","dessert","pastry"],char:'🥧',fitzpatrick_scale:false,category:"food_and_drink"},cake:{keywords:["food","dessert"],char:'🍰',fitzpatrick_scale:false,category:"food_and_drink"},cupcake:{keywords:["food","dessert","bakery","sweet"],char:'🧁',fitzpatrick_scale:false,category:"food_and_drink"},moon_cake:{keywords:["food","autumn"],char:'🥮',fitzpatrick_scale:false,category:"food_and_drink"},birthday:{keywords:["food","dessert","cake"],char:'🎂',fitzpatrick_scale:false,category:"food_and_drink"},custard:{keywords:["dessert","food"],char:'🍮',fitzpatrick_scale:false,category:"food_and_drink"},candy:{keywords:["snack","dessert","sweet","lolly"],char:'🍬',fitzpatrick_scale:false,category:"food_and_drink"},lollipop:{keywords:["food","snack","candy","sweet"],char:'🍭',fitzpatrick_scale:false,category:"food_and_drink"},chocolate_bar:{keywords:["food","snack","dessert","sweet"],char:'🍫',fitzpatrick_scale:false,category:"food_and_drink"},popcorn:{keywords:["food","movie theater","films","snack"],char:'🍿',fitzpatrick_scale:false,category:"food_and_drink"},dumpling:{keywords:["food","empanada","pierogi","potsticker"],char:'🥟',fitzpatrick_scale:false,category:"food_and_drink"},doughnut:{keywords:["food","dessert","snack","sweet","donut"],char:'🍩',fitzpatrick_scale:false,category:"food_and_drink"},cookie:{keywords:["food","snack","oreo","chocolate","sweet","dessert"],char:'🍪',fitzpatrick_scale:false,category:"food_and_drink"},milk_glass:{keywords:["beverage","drink","cow"],char:'🥛',fitzpatrick_scale:false,category:"food_and_drink"},beer:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:'🍺',fitzpatrick_scale:false,category:"food_and_drink"},beers:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:'🍻',fitzpatrick_scale:false,category:"food_and_drink"},clinking_glasses:{keywords:["beverage","drink","party","alcohol","celebrate","cheers","wine","champagne","toast"],char:'🥂',fitzpatrick_scale:false,category:"food_and_drink"},wine_glass:{keywords:["drink","beverage","drunk","alcohol","booze"],char:'🍷',fitzpatrick_scale:false,category:"food_and_drink"},tumbler_glass:{keywords:["drink","beverage","drunk","alcohol","liquor","booze","bourbon","scotch","whisky","glass","shot"],char:'🥃',fitzpatrick_scale:false,category:"food_and_drink"},cocktail:{keywords:["drink","drunk","alcohol","beverage","booze","mojito"],char:'🍸',fitzpatrick_scale:false,category:"food_and_drink"},tropical_drink:{keywords:["beverage","cocktail","summer","beach","alcohol","booze","mojito"],char:'🍹',fitzpatrick_scale:false,category:"food_and_drink"},champagne:{keywords:["drink","wine","bottle","celebration"],char:'🍾',fitzpatrick_scale:false,category:"food_and_drink"},sake:{keywords:["wine","drink","drunk","beverage","japanese","alcohol","booze"],char:'🍶',fitzpatrick_scale:false,category:"food_and_drink"},tea:{keywords:["drink","bowl","breakfast","green","british"],char:'🍵',fitzpatrick_scale:false,category:"food_and_drink"},cup_with_straw:{keywords:["drink","soda"],char:'🥤',fitzpatrick_scale:false,category:"food_and_drink"},coffee:{keywords:["beverage","caffeine","latte","espresso"],char:'☕',fitzpatrick_scale:false,category:"food_and_drink"},baby_bottle:{keywords:["food","container","milk"],char:'🍼',fitzpatrick_scale:false,category:"food_and_drink"},salt:{keywords:["condiment","shaker"],char:'🧂',fitzpatrick_scale:false,category:"food_and_drink"},spoon:{keywords:["cutlery","kitchen","tableware"],char:'🥄',fitzpatrick_scale:false,category:"food_and_drink"},fork_and_knife:{keywords:["cutlery","kitchen"],char:'🍴',fitzpatrick_scale:false,category:"food_and_drink"},plate_with_cutlery:{keywords:["food","eat","meal","lunch","dinner","restaurant"],char:'🍽',fitzpatrick_scale:false,category:"food_and_drink"},bowl_with_spoon:{keywords:["food","breakfast","cereal","oatmeal","porridge"],char:'🥣',fitzpatrick_scale:false,category:"food_and_drink"},takeout_box:{keywords:["food","leftovers"],char:'🥡',fitzpatrick_scale:false,category:"food_and_drink"},chopsticks:{keywords:["food"],char:'🥢',fitzpatrick_scale:false,category:"food_and_drink"},soccer:{keywords:["sports","football"],char:'⚽',fitzpatrick_scale:false,category:"activity"},basketball:{keywords:["sports","balls","NBA"],char:'🏀',fitzpatrick_scale:false,category:"activity"},football:{keywords:["sports","balls","NFL"],char:'🏈',fitzpatrick_scale:false,category:"activity"},baseball:{keywords:["sports","balls"],char:'⚾',fitzpatrick_scale:false,category:"activity"},softball:{keywords:["sports","balls"],char:'🥎',fitzpatrick_scale:false,category:"activity"},tennis:{keywords:["sports","balls","green"],char:'🎾',fitzpatrick_scale:false,category:"activity"},volleyball:{keywords:["sports","balls"],char:'🏐',fitzpatrick_scale:false,category:"activity"},rugby_football:{keywords:["sports","team"],char:'🏉',fitzpatrick_scale:false,category:"activity"},flying_disc:{keywords:["sports","frisbee","ultimate"],char:'🥏',fitzpatrick_scale:false,category:"activity"},"8ball":{keywords:["pool","hobby","game","luck","magic"],char:'🎱',fitzpatrick_scale:false,category:"activity"},golf:{keywords:["sports","business","flag","hole","summer"],char:'⛳',fitzpatrick_scale:false,category:"activity"},golfing_woman:{keywords:["sports","business","woman","female"],char:'🏌️‍♀️',fitzpatrick_scale:false,category:"activity"},golfing_man:{keywords:["sports","business"],char:'🏌',fitzpatrick_scale:true,category:"activity"},ping_pong:{keywords:["sports","pingpong"],char:'🏓',fitzpatrick_scale:false,category:"activity"},badminton:{keywords:["sports"],char:'🏸',fitzpatrick_scale:false,category:"activity"},goal_net:{keywords:["sports"],char:'🥅',fitzpatrick_scale:false,category:"activity"},ice_hockey:{keywords:["sports"],char:'🏒',fitzpatrick_scale:false,category:"activity"},field_hockey:{keywords:["sports"],char:'🏑',fitzpatrick_scale:false,category:"activity"},lacrosse:{keywords:["sports","ball","stick"],char:'🥍',fitzpatrick_scale:false,category:"activity"},cricket:{keywords:["sports"],char:'🏏',fitzpatrick_scale:false,category:"activity"},ski:{keywords:["sports","winter","cold","snow"],char:'🎿',fitzpatrick_scale:false,category:"activity"},skier:{keywords:["sports","winter","snow"],char:'⛷',fitzpatrick_scale:false,category:"activity"},snowboarder:{keywords:["sports","winter"],char:'🏂',fitzpatrick_scale:true,category:"activity"},person_fencing:{keywords:["sports","fencing","sword"],char:'🤺',fitzpatrick_scale:false,category:"activity"},women_wrestling:{keywords:["sports","wrestlers"],char:'🤼‍♀️',fitzpatrick_scale:false,category:"activity"},men_wrestling:{keywords:["sports","wrestlers"],char:'🤼‍♂️',fitzpatrick_scale:false,category:"activity"},woman_cartwheeling:{keywords:["gymnastics"],char:'🤸‍♀️',fitzpatrick_scale:true,category:"activity"},man_cartwheeling:{keywords:["gymnastics"],char:'🤸‍♂️',fitzpatrick_scale:true,category:"activity"},woman_playing_handball:{keywords:["sports"],char:'🤾‍♀️',fitzpatrick_scale:true,category:"activity"},man_playing_handball:{keywords:["sports"],char:'🤾‍♂️',fitzpatrick_scale:true,category:"activity"},ice_skate:{keywords:["sports"],char:'⛸',fitzpatrick_scale:false,category:"activity"},curling_stone:{keywords:["sports"],char:'🥌',fitzpatrick_scale:false,category:"activity"},skateboard:{keywords:["board"],char:'🛹',fitzpatrick_scale:false,category:"activity"},sled:{keywords:["sleigh","luge","toboggan"],char:'🛷',fitzpatrick_scale:false,category:"activity"},bow_and_arrow:{keywords:["sports"],char:'🏹',fitzpatrick_scale:false,category:"activity"},fishing_pole_and_fish:{keywords:["food","hobby","summer"],char:'🎣',fitzpatrick_scale:false,category:"activity"},boxing_glove:{keywords:["sports","fighting"],char:'🥊',fitzpatrick_scale:false,category:"activity"},martial_arts_uniform:{keywords:["judo","karate","taekwondo"],char:'🥋',fitzpatrick_scale:false,category:"activity"},rowing_woman:{keywords:["sports","hobby","water","ship","woman","female"],char:'🚣‍♀️',fitzpatrick_scale:true,category:"activity"},rowing_man:{keywords:["sports","hobby","water","ship"],char:'🚣',fitzpatrick_scale:true,category:"activity"},climbing_woman:{keywords:["sports","hobby","woman","female","rock"],char:'🧗‍♀️',fitzpatrick_scale:true,category:"activity"},climbing_man:{keywords:["sports","hobby","man","male","rock"],char:'🧗‍♂️',fitzpatrick_scale:true,category:"activity"},swimming_woman:{keywords:["sports","exercise","human","athlete","water","summer","woman","female"],char:'🏊‍♀️',fitzpatrick_scale:true,category:"activity"},swimming_man:{keywords:["sports","exercise","human","athlete","water","summer"],char:'🏊',fitzpatrick_scale:true,category:"activity"},woman_playing_water_polo:{keywords:["sports","pool"],char:'🤽‍♀️',fitzpatrick_scale:true,category:"activity"},man_playing_water_polo:{keywords:["sports","pool"],char:'🤽‍♂️',fitzpatrick_scale:true,category:"activity"},woman_in_lotus_position:{keywords:["woman","female","meditation","yoga","serenity","zen","mindfulness"],char:'🧘‍♀️',fitzpatrick_scale:true,category:"activity"},man_in_lotus_position:{keywords:["man","male","meditation","yoga","serenity","zen","mindfulness"],char:'🧘‍♂️',fitzpatrick_scale:true,category:"activity"},surfing_woman:{keywords:["sports","ocean","sea","summer","beach","woman","female"],char:'🏄‍♀️',fitzpatrick_scale:true,category:"activity"},surfing_man:{keywords:["sports","ocean","sea","summer","beach"],char:'🏄',fitzpatrick_scale:true,category:"activity"},bath:{keywords:["clean","shower","bathroom"],char:'🛀',fitzpatrick_scale:true,category:"activity"},basketball_woman:{keywords:["sports","human","woman","female"],char:'⛹️‍♀️',fitzpatrick_scale:true,category:"activity"},basketball_man:{keywords:["sports","human"],char:'⛹',fitzpatrick_scale:true,category:"activity"},weight_lifting_woman:{keywords:["sports","training","exercise","woman","female"],char:'🏋️‍♀️',fitzpatrick_scale:true,category:"activity"},weight_lifting_man:{keywords:["sports","training","exercise"],char:'🏋',fitzpatrick_scale:true,category:"activity"},biking_woman:{keywords:["sports","bike","exercise","hipster","woman","female"],char:'🚴‍♀️',fitzpatrick_scale:true,category:"activity"},biking_man:{keywords:["sports","bike","exercise","hipster"],char:'🚴',fitzpatrick_scale:true,category:"activity"},mountain_biking_woman:{keywords:["transportation","sports","human","race","bike","woman","female"],char:'🚵‍♀️',fitzpatrick_scale:true,category:"activity"},mountain_biking_man:{keywords:["transportation","sports","human","race","bike"],char:'🚵',fitzpatrick_scale:true,category:"activity"},horse_racing:{keywords:["animal","betting","competition","gambling","luck"],char:'🏇',fitzpatrick_scale:true,category:"activity"},business_suit_levitating:{keywords:["suit","business","levitate","hover","jump"],char:'🕴',fitzpatrick_scale:true,category:"activity"},trophy:{keywords:["win","award","contest","place","ftw","ceremony"],char:'🏆',fitzpatrick_scale:false,category:"activity"},running_shirt_with_sash:{keywords:["play","pageant"],char:'🎽',fitzpatrick_scale:false,category:"activity"},medal_sports:{keywords:["award","winning"],char:'🏅',fitzpatrick_scale:false,category:"activity"},medal_military:{keywords:["award","winning","army"],char:'🎖',fitzpatrick_scale:false,category:"activity"},"1st_place_medal":{keywords:["award","winning","first"],char:'🥇',fitzpatrick_scale:false,category:"activity"},"2nd_place_medal":{keywords:["award","second"],char:'🥈',fitzpatrick_scale:false,category:"activity"},"3rd_place_medal":{keywords:["award","third"],char:'🥉',fitzpatrick_scale:false,category:"activity"},reminder_ribbon:{keywords:["sports","cause","support","awareness"],char:'🎗',fitzpatrick_scale:false,category:"activity"},rosette:{keywords:["flower","decoration","military"],char:'🏵',fitzpatrick_scale:false,category:"activity"},ticket:{keywords:["event","concert","pass"],char:'🎫',fitzpatrick_scale:false,category:"activity"},tickets:{keywords:["sports","concert","entrance"],char:'🎟',fitzpatrick_scale:false,category:"activity"},performing_arts:{keywords:["acting","theater","drama"],char:'🎭',fitzpatrick_scale:false,category:"activity"},art:{keywords:["design","paint","draw","colors"],char:'🎨',fitzpatrick_scale:false,category:"activity"},circus_tent:{keywords:["festival","carnival","party"],char:'🎪',fitzpatrick_scale:false,category:"activity"},woman_juggling:{keywords:["juggle","balance","skill","multitask"],char:'🤹‍♀️',fitzpatrick_scale:true,category:"activity"},man_juggling:{keywords:["juggle","balance","skill","multitask"],char:'🤹‍♂️',fitzpatrick_scale:true,category:"activity"},microphone:{keywords:["sound","music","PA","sing","talkshow"],char:'🎤',fitzpatrick_scale:false,category:"activity"},headphones:{keywords:["music","score","gadgets"],char:'🎧',fitzpatrick_scale:false,category:"activity"},musical_score:{keywords:["treble","clef","compose"],char:'🎼',fitzpatrick_scale:false,category:"activity"},musical_keyboard:{keywords:["piano","instrument","compose"],char:'🎹',fitzpatrick_scale:false,category:"activity"},drum:{keywords:["music","instrument","drumsticks","snare"],char:'🥁',fitzpatrick_scale:false,category:"activity"},saxophone:{keywords:["music","instrument","jazz","blues"],char:'🎷',fitzpatrick_scale:false,category:"activity"},trumpet:{keywords:["music","brass"],char:'🎺',fitzpatrick_scale:false,category:"activity"},guitar:{keywords:["music","instrument"],char:'🎸',fitzpatrick_scale:false,category:"activity"},violin:{keywords:["music","instrument","orchestra","symphony"],char:'🎻',fitzpatrick_scale:false,category:"activity"},clapper:{keywords:["movie","film","record"],char:'🎬',fitzpatrick_scale:false,category:"activity"},video_game:{keywords:["play","console","PS4","controller"],char:'🎮',fitzpatrick_scale:false,category:"activity"},space_invader:{keywords:["game","arcade","play"],char:'👾',fitzpatrick_scale:false,category:"activity"},dart:{keywords:["game","play","bar","target","bullseye"],char:'🎯',fitzpatrick_scale:false,category:"activity"},game_die:{keywords:["dice","random","tabletop","play","luck"],char:'🎲',fitzpatrick_scale:false,category:"activity"},chess_pawn:{keywords:["expendable"],char:"♟",fitzpatrick_scale:false,category:"activity"},slot_machine:{keywords:["bet","gamble","vegas","fruit machine","luck","casino"],char:'🎰',fitzpatrick_scale:false,category:"activity"},jigsaw:{keywords:["interlocking","puzzle","piece"],char:'🧩',fitzpatrick_scale:false,category:"activity"},bowling:{keywords:["sports","fun","play"],char:'🎳',fitzpatrick_scale:false,category:"activity"},red_car:{keywords:["red","transportation","vehicle"],char:'🚗',fitzpatrick_scale:false,category:"travel_and_places"},taxi:{keywords:["uber","vehicle","cars","transportation"],char:'🚕',fitzpatrick_scale:false,category:"travel_and_places"},blue_car:{keywords:["transportation","vehicle"],char:'🚙',fitzpatrick_scale:false,category:"travel_and_places"},bus:{keywords:["car","vehicle","transportation"],char:'🚌',fitzpatrick_scale:false,category:"travel_and_places"},trolleybus:{keywords:["bart","transportation","vehicle"],char:'🚎',fitzpatrick_scale:false,category:"travel_and_places"},racing_car:{keywords:["sports","race","fast","formula","f1"],char:'🏎',fitzpatrick_scale:false,category:"travel_and_places"},police_car:{keywords:["vehicle","cars","transportation","law","legal","enforcement"],char:'🚓',fitzpatrick_scale:false,category:"travel_and_places"},ambulance:{keywords:["health","911","hospital"],char:'🚑',fitzpatrick_scale:false,category:"travel_and_places"},fire_engine:{keywords:["transportation","cars","vehicle"],char:'🚒',fitzpatrick_scale:false,category:"travel_and_places"},minibus:{keywords:["vehicle","car","transportation"],char:'🚐',fitzpatrick_scale:false,category:"travel_and_places"},truck:{keywords:["cars","transportation"],char:'🚚',fitzpatrick_scale:false,category:"travel_and_places"},articulated_lorry:{keywords:["vehicle","cars","transportation","express"],char:'🚛',fitzpatrick_scale:false,category:"travel_and_places"},tractor:{keywords:["vehicle","car","farming","agriculture"],char:'🚜',fitzpatrick_scale:false,category:"travel_and_places"},kick_scooter:{keywords:["vehicle","kick","razor"],char:'🛴',fitzpatrick_scale:false,category:"travel_and_places"},motorcycle:{keywords:["race","sports","fast"],char:'🏍',fitzpatrick_scale:false,category:"travel_and_places"},bike:{keywords:["sports","bicycle","exercise","hipster"],char:'🚲',fitzpatrick_scale:false,category:"travel_and_places"},motor_scooter:{keywords:["vehicle","vespa","sasha"],char:'🛵',fitzpatrick_scale:false,category:"travel_and_places"},rotating_light:{keywords:["police","ambulance","911","emergency","alert","error","pinged","law","legal"],char:'🚨',fitzpatrick_scale:false,category:"travel_and_places"},oncoming_police_car:{keywords:["vehicle","law","legal","enforcement","911"],char:'🚔',fitzpatrick_scale:false,category:"travel_and_places"},oncoming_bus:{keywords:["vehicle","transportation"],char:'🚍',fitzpatrick_scale:false,category:"travel_and_places"},oncoming_automobile:{keywords:["car","vehicle","transportation"],char:'🚘',fitzpatrick_scale:false,category:"travel_and_places"},oncoming_taxi:{keywords:["vehicle","cars","uber"],char:'🚖',fitzpatrick_scale:false,category:"travel_and_places"},aerial_tramway:{keywords:["transportation","vehicle","ski"],char:'🚡',fitzpatrick_scale:false,category:"travel_and_places"},mountain_cableway:{keywords:["transportation","vehicle","ski"],char:'🚠',fitzpatrick_scale:false,category:"travel_and_places"},suspension_railway:{keywords:["vehicle","transportation"],char:'🚟',fitzpatrick_scale:false,category:"travel_and_places"},railway_car:{keywords:["transportation","vehicle"],char:'🚃',fitzpatrick_scale:false,category:"travel_and_places"},train:{keywords:["transportation","vehicle","carriage","public","travel"],char:'🚋',fitzpatrick_scale:false,category:"travel_and_places"},monorail:{keywords:["transportation","vehicle"],char:'🚝',fitzpatrick_scale:false,category:"travel_and_places"},bullettrain_side:{keywords:["transportation","vehicle"],char:'🚄',fitzpatrick_scale:false,category:"travel_and_places"},bullettrain_front:{keywords:["transportation","vehicle","speed","fast","public","travel"],char:'🚅',fitzpatrick_scale:false,category:"travel_and_places"},light_rail:{keywords:["transportation","vehicle"],char:'🚈',fitzpatrick_scale:false,category:"travel_and_places"},mountain_railway:{keywords:["transportation","vehicle"],char:'🚞',fitzpatrick_scale:false,category:"travel_and_places"},steam_locomotive:{keywords:["transportation","vehicle","train"],char:'🚂',fitzpatrick_scale:false,category:"travel_and_places"},train2:{keywords:["transportation","vehicle"],char:'🚆',fitzpatrick_scale:false,category:"travel_and_places"},metro:{keywords:["transportation","blue-square","mrt","underground","tube"],char:'🚇',fitzpatrick_scale:false,category:"travel_and_places"},tram:{keywords:["transportation","vehicle"],char:'🚊',fitzpatrick_scale:false,category:"travel_and_places"},station:{keywords:["transportation","vehicle","public"],char:'🚉',fitzpatrick_scale:false,category:"travel_and_places"},flying_saucer:{keywords:["transportation","vehicle","ufo"],char:'🛸',fitzpatrick_scale:false,category:"travel_and_places"},helicopter:{keywords:["transportation","vehicle","fly"],char:'🚁',fitzpatrick_scale:false,category:"travel_and_places"},small_airplane:{keywords:["flight","transportation","fly","vehicle"],char:'🛩',fitzpatrick_scale:false,category:"travel_and_places"},airplane:{keywords:["vehicle","transportation","flight","fly"],char:'✈️',fitzpatrick_scale:false,category:"travel_and_places"},flight_departure:{keywords:["airport","flight","landing"],char:'🛫',fitzpatrick_scale:false,category:"travel_and_places"},flight_arrival:{keywords:["airport","flight","boarding"],char:'🛬',fitzpatrick_scale:false,category:"travel_and_places"},sailboat:{keywords:["ship","summer","transportation","water","sailing"],char:'⛵',fitzpatrick_scale:false,category:"travel_and_places"},motor_boat:{keywords:["ship"],char:'🛥',fitzpatrick_scale:false,category:"travel_and_places"},speedboat:{keywords:["ship","transportation","vehicle","summer"],char:'🚤',fitzpatrick_scale:false,category:"travel_and_places"},ferry:{keywords:["boat","ship","yacht"],char:'⛴',fitzpatrick_scale:false,category:"travel_and_places"},passenger_ship:{keywords:["yacht","cruise","ferry"],char:'🛳',fitzpatrick_scale:false,category:"travel_and_places"},rocket:{keywords:["launch","ship","staffmode","NASA","outer space","outer_space","fly"],char:'🚀',fitzpatrick_scale:false,category:"travel_and_places"},artificial_satellite:{keywords:["communication","gps","orbit","spaceflight","NASA","ISS"],char:'🛰',fitzpatrick_scale:false,category:"travel_and_places"},seat:{keywords:["sit","airplane","transport","bus","flight","fly"],char:'💺',fitzpatrick_scale:false,category:"travel_and_places"},canoe:{keywords:["boat","paddle","water","ship"],char:'🛶',fitzpatrick_scale:false,category:"travel_and_places"},anchor:{keywords:["ship","ferry","sea","boat"],char:'⚓',fitzpatrick_scale:false,category:"travel_and_places"},construction:{keywords:["wip","progress","caution","warning"],char:'🚧',fitzpatrick_scale:false,category:"travel_and_places"},fuelpump:{keywords:["gas station","petroleum"],char:'⛽',fitzpatrick_scale:false,category:"travel_and_places"},busstop:{keywords:["transportation","wait"],char:'🚏',fitzpatrick_scale:false,category:"travel_and_places"},vertical_traffic_light:{keywords:["transportation","driving"],char:'🚦',fitzpatrick_scale:false,category:"travel_and_places"},traffic_light:{keywords:["transportation","signal"],char:'🚥',fitzpatrick_scale:false,category:"travel_and_places"},checkered_flag:{keywords:["contest","finishline","race","gokart"],char:'🏁',fitzpatrick_scale:false,category:"travel_and_places"},ship:{keywords:["transportation","titanic","deploy"],char:'🚢',fitzpatrick_scale:false,category:"travel_and_places"},ferris_wheel:{keywords:["photo","carnival","londoneye"],char:'🎡',fitzpatrick_scale:false,category:"travel_and_places"},roller_coaster:{keywords:["carnival","playground","photo","fun"],char:'🎢',fitzpatrick_scale:false,category:"travel_and_places"},carousel_horse:{keywords:["photo","carnival"],char:'🎠',fitzpatrick_scale:false,category:"travel_and_places"},building_construction:{keywords:["wip","working","progress"],char:'🏗',fitzpatrick_scale:false,category:"travel_and_places"},foggy:{keywords:["photo","mountain"],char:'🌁',fitzpatrick_scale:false,category:"travel_and_places"},tokyo_tower:{keywords:["photo","japanese"],char:'🗼',fitzpatrick_scale:false,category:"travel_and_places"},factory:{keywords:["building","industry","pollution","smoke"],char:'🏭',fitzpatrick_scale:false,category:"travel_and_places"},fountain:{keywords:["photo","summer","water","fresh"],char:'⛲',fitzpatrick_scale:false,category:"travel_and_places"},rice_scene:{keywords:["photo","japan","asia","tsukimi"],char:'🎑',fitzpatrick_scale:false,category:"travel_and_places"},mountain:{keywords:["photo","nature","environment"],char:'⛰',fitzpatrick_scale:false,category:"travel_and_places"},mountain_snow:{keywords:["photo","nature","environment","winter","cold"],char:'🏔',fitzpatrick_scale:false,category:"travel_and_places"},mount_fuji:{keywords:["photo","mountain","nature","japanese"],char:'🗻',fitzpatrick_scale:false,category:"travel_and_places"},volcano:{keywords:["photo","nature","disaster"],char:'🌋',fitzpatrick_scale:false,category:"travel_and_places"},japan:{keywords:["nation","country","japanese","asia"],char:'🗾',fitzpatrick_scale:false,category:"travel_and_places"},camping:{keywords:["photo","outdoors","tent"],char:'🏕',fitzpatrick_scale:false,category:"travel_and_places"},tent:{keywords:["photo","camping","outdoors"],char:'⛺',fitzpatrick_scale:false,category:"travel_and_places"},national_park:{keywords:["photo","environment","nature"],char:'🏞',fitzpatrick_scale:false,category:"travel_and_places"},motorway:{keywords:["road","cupertino","interstate","highway"],char:'🛣',fitzpatrick_scale:false,category:"travel_and_places"},railway_track:{keywords:["train","transportation"],char:'🛤',fitzpatrick_scale:false,category:"travel_and_places"},sunrise:{keywords:["morning","view","vacation","photo"],char:'🌅',fitzpatrick_scale:false,category:"travel_and_places"},sunrise_over_mountains:{keywords:["view","vacation","photo"],char:'🌄',fitzpatrick_scale:false,category:"travel_and_places"},desert:{keywords:["photo","warm","saharah"],char:'🏜',fitzpatrick_scale:false,category:"travel_and_places"},beach_umbrella:{keywords:["weather","summer","sunny","sand","mojito"],char:'🏖',fitzpatrick_scale:false,category:"travel_and_places"},desert_island:{keywords:["photo","tropical","mojito"],char:'🏝',fitzpatrick_scale:false,category:"travel_and_places"},city_sunrise:{keywords:["photo","good morning","dawn"],char:'🌇',fitzpatrick_scale:false,category:"travel_and_places"},city_sunset:{keywords:["photo","evening","sky","buildings"],char:'🌆',fitzpatrick_scale:false,category:"travel_and_places"},cityscape:{keywords:["photo","night life","urban"],char:'🏙',fitzpatrick_scale:false,category:"travel_and_places"},night_with_stars:{keywords:["evening","city","downtown"],char:'🌃',fitzpatrick_scale:false,category:"travel_and_places"},bridge_at_night:{keywords:["photo","sanfrancisco"],char:'🌉',fitzpatrick_scale:false,category:"travel_and_places"},milky_way:{keywords:["photo","space","stars"],char:'🌌',fitzpatrick_scale:false,category:"travel_and_places"},stars:{keywords:["night","photo"],char:'🌠',fitzpatrick_scale:false,category:"travel_and_places"},sparkler:{keywords:["stars","night","shine"],char:'🎇',fitzpatrick_scale:false,category:"travel_and_places"},fireworks:{keywords:["photo","festival","carnival","congratulations"],char:'🎆',fitzpatrick_scale:false,category:"travel_and_places"},rainbow:{keywords:["nature","happy","unicorn_face","photo","sky","spring"],char:'🌈',fitzpatrick_scale:false,category:"travel_and_places"},houses:{keywords:["buildings","photo"],char:'🏘',fitzpatrick_scale:false,category:"travel_and_places"},european_castle:{keywords:["building","royalty","history"],char:'🏰',fitzpatrick_scale:false,category:"travel_and_places"},japanese_castle:{keywords:["photo","building"],char:'🏯',fitzpatrick_scale:false,category:"travel_and_places"},stadium:{keywords:["photo","place","sports","concert","venue"],char:'🏟',fitzpatrick_scale:false,category:"travel_and_places"},statue_of_liberty:{keywords:["american","newyork"],char:'🗽',fitzpatrick_scale:false,category:"travel_and_places"},house:{keywords:["building","home"],char:'🏠',fitzpatrick_scale:false,category:"travel_and_places"},house_with_garden:{keywords:["home","plant","nature"],char:'🏡',fitzpatrick_scale:false,category:"travel_and_places"},derelict_house:{keywords:["abandon","evict","broken","building"],char:'🏚',fitzpatrick_scale:false,category:"travel_and_places"},office:{keywords:["building","bureau","work"],char:'🏢',fitzpatrick_scale:false,category:"travel_and_places"},department_store:{keywords:["building","shopping","mall"],char:'🏬',fitzpatrick_scale:false,category:"travel_and_places"},post_office:{keywords:["building","envelope","communication"],char:'🏣',fitzpatrick_scale:false,category:"travel_and_places"},european_post_office:{keywords:["building","email"],char:'🏤',fitzpatrick_scale:false,category:"travel_and_places"},hospital:{keywords:["building","health","surgery","doctor"],char:'🏥',fitzpatrick_scale:false,category:"travel_and_places"},bank:{keywords:["building","money","sales","cash","business","enterprise"],char:'🏦',fitzpatrick_scale:false,category:"travel_and_places"},hotel:{keywords:["building","accomodation","checkin"],char:'🏨',fitzpatrick_scale:false,category:"travel_and_places"},convenience_store:{keywords:["building","shopping","groceries"],char:'🏪',fitzpatrick_scale:false,category:"travel_and_places"},school:{keywords:["building","student","education","learn","teach"],char:'🏫',fitzpatrick_scale:false,category:"travel_and_places"},love_hotel:{keywords:["like","affection","dating"],char:'🏩',fitzpatrick_scale:false,category:"travel_and_places"},wedding:{keywords:["love","like","affection","couple","marriage","bride","groom"],char:'💒',fitzpatrick_scale:false,category:"travel_and_places"},classical_building:{keywords:["art","culture","history"],char:'🏛',fitzpatrick_scale:false,category:"travel_and_places"},church:{keywords:["building","religion","christ"],char:'⛪',fitzpatrick_scale:false,category:"travel_and_places"},mosque:{keywords:["islam","worship","minaret"],char:'🕌',fitzpatrick_scale:false,category:"travel_and_places"},synagogue:{keywords:["judaism","worship","temple","jewish"],char:'🕍',fitzpatrick_scale:false,category:"travel_and_places"},kaaba:{keywords:["mecca","mosque","islam"],char:'🕋',fitzpatrick_scale:false,category:"travel_and_places"},shinto_shrine:{keywords:["temple","japan","kyoto"],char:'⛩',fitzpatrick_scale:false,category:"travel_and_places"},watch:{keywords:["time","accessories"],char:'⌚',fitzpatrick_scale:false,category:"objects"},iphone:{keywords:["technology","apple","gadgets","dial"],char:'📱',fitzpatrick_scale:false,category:"objects"},calling:{keywords:["iphone","incoming"],char:'📲',fitzpatrick_scale:false,category:"objects"},computer:{keywords:["technology","laptop","screen","display","monitor"],char:'💻',fitzpatrick_scale:false,category:"objects"},keyboard:{keywords:["technology","computer","type","input","text"],char:'⌨',fitzpatrick_scale:false,category:"objects"},desktop_computer:{keywords:["technology","computing","screen"],char:'🖥',fitzpatrick_scale:false,category:"objects"},printer:{keywords:["paper","ink"],char:'🖨',fitzpatrick_scale:false,category:"objects"},computer_mouse:{keywords:["click"],char:'🖱',fitzpatrick_scale:false,category:"objects"},trackball:{keywords:["technology","trackpad"],char:'🖲',fitzpatrick_scale:false,category:"objects"},joystick:{keywords:["game","play"],char:'🕹',fitzpatrick_scale:false,category:"objects"},clamp:{keywords:["tool"],char:'🗜',fitzpatrick_scale:false,category:"objects"},minidisc:{keywords:["technology","record","data","disk","90s"],char:'💽',fitzpatrick_scale:false,category:"objects"},floppy_disk:{keywords:["oldschool","technology","save","90s","80s"],char:'💾',fitzpatrick_scale:false,category:"objects"},cd:{keywords:["technology","dvd","disk","disc","90s"],char:'💿',fitzpatrick_scale:false,category:"objects"},dvd:{keywords:["cd","disk","disc"],char:'📀',fitzpatrick_scale:false,category:"objects"},vhs:{keywords:["record","video","oldschool","90s","80s"],char:'📼',fitzpatrick_scale:false,category:"objects"},camera:{keywords:["gadgets","photography"],char:'📷',fitzpatrick_scale:false,category:"objects"},camera_flash:{keywords:["photography","gadgets"],char:'📸',fitzpatrick_scale:false,category:"objects"},video_camera:{keywords:["film","record"],char:'📹',fitzpatrick_scale:false,category:"objects"},movie_camera:{keywords:["film","record"],char:'🎥',fitzpatrick_scale:false,category:"objects"},film_projector:{keywords:["video","tape","record","movie"],char:'📽',fitzpatrick_scale:false,category:"objects"},film_strip:{keywords:["movie"],char:'🎞',fitzpatrick_scale:false,category:"objects"},telephone_receiver:{keywords:["technology","communication","dial"],char:'📞',fitzpatrick_scale:false,category:"objects"},phone:{keywords:["technology","communication","dial","telephone"],char:'☎️',fitzpatrick_scale:false,category:"objects"},pager:{keywords:["bbcall","oldschool","90s"],char:'📟',fitzpatrick_scale:false,category:"objects"},fax:{keywords:["communication","technology"],char:'📠',fitzpatrick_scale:false,category:"objects"},tv:{keywords:["technology","program","oldschool","show","television"],char:'📺',fitzpatrick_scale:false,category:"objects"},radio:{keywords:["communication","music","podcast","program"],char:'📻',fitzpatrick_scale:false,category:"objects"},studio_microphone:{keywords:["sing","recording","artist","talkshow"],char:'🎙',fitzpatrick_scale:false,category:"objects"},level_slider:{keywords:["scale"],char:'🎚',fitzpatrick_scale:false,category:"objects"},control_knobs:{keywords:["dial"],char:'🎛',fitzpatrick_scale:false,category:"objects"},compass:{keywords:["magnetic","navigation","orienteering"],char:'🧭',fitzpatrick_scale:false,category:"objects"},stopwatch:{keywords:["time","deadline"],char:'⏱',fitzpatrick_scale:false,category:"objects"},timer_clock:{keywords:["alarm"],char:'⏲',fitzpatrick_scale:false,category:"objects"},alarm_clock:{keywords:["time","wake"],char:'⏰',fitzpatrick_scale:false,category:"objects"},mantelpiece_clock:{keywords:["time"],char:'🕰',fitzpatrick_scale:false,category:"objects"},hourglass_flowing_sand:{keywords:["oldschool","time","countdown"],char:'⏳',fitzpatrick_scale:false,category:"objects"},hourglass:{keywords:["time","clock","oldschool","limit","exam","quiz","test"],char:'⌛',fitzpatrick_scale:false,category:"objects"},satellite:{keywords:["communication","future","radio","space"],char:'📡',fitzpatrick_scale:false,category:"objects"},battery:{keywords:["power","energy","sustain"],char:'🔋',fitzpatrick_scale:false,category:"objects"},electric_plug:{keywords:["charger","power"],char:'🔌',fitzpatrick_scale:false,category:"objects"},bulb:{keywords:["light","electricity","idea"],char:'💡',fitzpatrick_scale:false,category:"objects"},flashlight:{keywords:["dark","camping","sight","night"],char:'🔦',fitzpatrick_scale:false,category:"objects"},candle:{keywords:["fire","wax"],char:'🕯',fitzpatrick_scale:false,category:"objects"},fire_extinguisher:{keywords:["quench"],char:'🧯',fitzpatrick_scale:false,category:"objects"},wastebasket:{keywords:["bin","trash","rubbish","garbage","toss"],char:'🗑',fitzpatrick_scale:false,category:"objects"},oil_drum:{keywords:["barrell"],char:'🛢',fitzpatrick_scale:false,category:"objects"},money_with_wings:{keywords:["dollar","bills","payment","sale"],char:'💸',fitzpatrick_scale:false,category:"objects"},dollar:{keywords:["money","sales","bill","currency"],char:'💵',fitzpatrick_scale:false,category:"objects"},yen:{keywords:["money","sales","japanese","dollar","currency"],char:'💴',fitzpatrick_scale:false,category:"objects"},euro:{keywords:["money","sales","dollar","currency"],char:'💶',fitzpatrick_scale:false,category:"objects"},pound:{keywords:["british","sterling","money","sales","bills","uk","england","currency"],char:'💷',fitzpatrick_scale:false,category:"objects"},moneybag:{keywords:["dollar","payment","coins","sale"],char:'💰',fitzpatrick_scale:false,category:"objects"},credit_card:{keywords:["money","sales","dollar","bill","payment","shopping"],char:'💳',fitzpatrick_scale:false,category:"objects"},gem:{keywords:["blue","ruby","diamond","jewelry"],char:'💎',fitzpatrick_scale:false,category:"objects"},balance_scale:{keywords:["law","fairness","weight"],char:'⚖',fitzpatrick_scale:false,category:"objects"},toolbox:{keywords:["tools","diy","fix","maintainer","mechanic"],char:'🧰',fitzpatrick_scale:false,category:"objects"},wrench:{keywords:["tools","diy","ikea","fix","maintainer"],char:'🔧',fitzpatrick_scale:false,category:"objects"},hammer:{keywords:["tools","build","create"],char:'🔨',fitzpatrick_scale:false,category:"objects"},hammer_and_pick:{keywords:["tools","build","create"],char:'⚒',fitzpatrick_scale:false,category:"objects"},hammer_and_wrench:{keywords:["tools","build","create"],char:'🛠',fitzpatrick_scale:false,category:"objects"},pick:{keywords:["tools","dig"],char:'⛏',fitzpatrick_scale:false,category:"objects"},nut_and_bolt:{keywords:["handy","tools","fix"],char:'🔩',fitzpatrick_scale:false,category:"objects"},gear:{keywords:["cog"],char:'⚙',fitzpatrick_scale:false,category:"objects"},brick:{keywords:["bricks"],char:'🧱',fitzpatrick_scale:false,category:"objects"},chains:{keywords:["lock","arrest"],char:'⛓',fitzpatrick_scale:false,category:"objects"},magnet:{keywords:["attraction","magnetic"],char:'🧲',fitzpatrick_scale:false,category:"objects"},gun:{keywords:["violence","weapon","pistol","revolver"],char:'🔫',fitzpatrick_scale:false,category:"objects"},bomb:{keywords:["boom","explode","explosion","terrorism"],char:'💣',fitzpatrick_scale:false,category:"objects"},firecracker:{keywords:["dynamite","boom","explode","explosion","explosive"],char:'🧨',fitzpatrick_scale:false,category:"objects"},hocho:{keywords:["knife","blade","cutlery","kitchen","weapon"],char:'🔪',fitzpatrick_scale:false,category:"objects"},dagger:{keywords:["weapon"],char:'🗡',fitzpatrick_scale:false,category:"objects"},crossed_swords:{keywords:["weapon"],char:'⚔',fitzpatrick_scale:false,category:"objects"},shield:{keywords:["protection","security"],char:'🛡',fitzpatrick_scale:false,category:"objects"},smoking:{keywords:["kills","tobacco","cigarette","joint","smoke"],char:'🚬',fitzpatrick_scale:false,category:"objects"},skull_and_crossbones:{keywords:["poison","danger","deadly","scary","death","pirate","evil"],char:'☠',fitzpatrick_scale:false,category:"objects"},coffin:{keywords:["vampire","dead","die","death","rip","graveyard","cemetery","casket","funeral","box"],char:'⚰',fitzpatrick_scale:false,category:"objects"},funeral_urn:{keywords:["dead","die","death","rip","ashes"],char:'⚱',fitzpatrick_scale:false,category:"objects"},amphora:{keywords:["vase","jar"],char:'🏺',fitzpatrick_scale:false,category:"objects"},crystal_ball:{keywords:["disco","party","magic","circus","fortune_teller"],char:'🔮',fitzpatrick_scale:false,category:"objects"},prayer_beads:{keywords:["dhikr","religious"],char:'📿',fitzpatrick_scale:false,category:"objects"},nazar_amulet:{keywords:["bead","charm"],char:'🧿',fitzpatrick_scale:false,category:"objects"},barber:{keywords:["hair","salon","style"],char:'💈',fitzpatrick_scale:false,category:"objects"},alembic:{keywords:["distilling","science","experiment","chemistry"],char:'⚗',fitzpatrick_scale:false,category:"objects"},telescope:{keywords:["stars","space","zoom","science","astronomy"],char:'🔭',fitzpatrick_scale:false,category:"objects"},microscope:{keywords:["laboratory","experiment","zoomin","science","study"],char:'🔬',fitzpatrick_scale:false,category:"objects"},hole:{keywords:["embarrassing"],char:'🕳',fitzpatrick_scale:false,category:"objects"},pill:{keywords:["health","medicine","doctor","pharmacy","drug"],char:'💊',fitzpatrick_scale:false,category:"objects"},syringe:{keywords:["health","hospital","drugs","blood","medicine","needle","doctor","nurse"],char:'💉',fitzpatrick_scale:false,category:"objects"},dna:{keywords:["biologist","genetics","life"],char:'🧬',fitzpatrick_scale:false,category:"objects"},microbe:{keywords:["amoeba","bacteria","germs"],char:'🦠',fitzpatrick_scale:false,category:"objects"},petri_dish:{keywords:["bacteria","biology","culture","lab"],char:'🧫',fitzpatrick_scale:false,category:"objects"},test_tube:{keywords:["chemistry","experiment","lab","science"],char:'🧪',fitzpatrick_scale:false,category:"objects"},thermometer:{keywords:["weather","temperature","hot","cold"],char:'🌡',fitzpatrick_scale:false,category:"objects"},broom:{keywords:["cleaning","sweeping","witch"],char:'🧹',fitzpatrick_scale:false,category:"objects"},basket:{keywords:["laundry"],char:'🧺',fitzpatrick_scale:false,category:"objects"},toilet_paper:{keywords:["roll"],char:'🧻',fitzpatrick_scale:false,category:"objects"},label:{keywords:["sale","tag"],char:'🏷',fitzpatrick_scale:false,category:"objects"},bookmark:{keywords:["favorite","label","save"],char:'🔖',fitzpatrick_scale:false,category:"objects"},toilet:{keywords:["restroom","wc","washroom","bathroom","potty"],char:'🚽',fitzpatrick_scale:false,category:"objects"},shower:{keywords:["clean","water","bathroom"],char:'🚿',fitzpatrick_scale:false,category:"objects"},bathtub:{keywords:["clean","shower","bathroom"],char:'🛁',fitzpatrick_scale:false,category:"objects"},soap:{keywords:["bar","bathing","cleaning","lather"],char:'🧼',fitzpatrick_scale:false,category:"objects"},sponge:{keywords:["absorbing","cleaning","porous"],char:'🧽',fitzpatrick_scale:false,category:"objects"},lotion_bottle:{keywords:["moisturizer","sunscreen"],char:'🧴',fitzpatrick_scale:false,category:"objects"},key:{keywords:["lock","door","password"],char:'🔑',fitzpatrick_scale:false,category:"objects"},old_key:{keywords:["lock","door","password"],char:'🗝',fitzpatrick_scale:false,category:"objects"},couch_and_lamp:{keywords:["read","chill"],char:'🛋',fitzpatrick_scale:false,category:"objects"},sleeping_bed:{keywords:["bed","rest"],char:'🛌',fitzpatrick_scale:true,category:"objects"},bed:{keywords:["sleep","rest"],char:'🛏',fitzpatrick_scale:false,category:"objects"},door:{keywords:["house","entry","exit"],char:'🚪',fitzpatrick_scale:false,category:"objects"},bellhop_bell:{keywords:["service"],char:'🛎',fitzpatrick_scale:false,category:"objects"},teddy_bear:{keywords:["plush","stuffed"],char:'🧸',fitzpatrick_scale:false,category:"objects"},framed_picture:{keywords:["photography"],char:'🖼',fitzpatrick_scale:false,category:"objects"},world_map:{keywords:["location","direction"],char:'🗺',fitzpatrick_scale:false,category:"objects"},parasol_on_ground:{keywords:["weather","summer"],char:'⛱',fitzpatrick_scale:false,category:"objects"},moyai:{keywords:["rock","easter island","moai"],char:'🗿',fitzpatrick_scale:false,category:"objects"},shopping:{keywords:["mall","buy","purchase"],char:'🛍',fitzpatrick_scale:false,category:"objects"},shopping_cart:{keywords:["trolley"],char:'🛒',fitzpatrick_scale:false,category:"objects"},balloon:{keywords:["party","celebration","birthday","circus"],char:'🎈',fitzpatrick_scale:false,category:"objects"},flags:{keywords:["fish","japanese","koinobori","carp","banner"],char:'🎏',fitzpatrick_scale:false,category:"objects"},ribbon:{keywords:["decoration","pink","girl","bowtie"],char:'🎀',fitzpatrick_scale:false,category:"objects"},gift:{keywords:["present","birthday","christmas","xmas"],char:'🎁',fitzpatrick_scale:false,category:"objects"},confetti_ball:{keywords:["festival","party","birthday","circus"],char:'🎊',fitzpatrick_scale:false,category:"objects"},tada:{keywords:["party","congratulations","birthday","magic","circus","celebration"],char:'🎉',fitzpatrick_scale:false,category:"objects"},dolls:{keywords:["japanese","toy","kimono"],char:'🎎',fitzpatrick_scale:false,category:"objects"},wind_chime:{keywords:["nature","ding","spring","bell"],char:'🎐',fitzpatrick_scale:false,category:"objects"},crossed_flags:{keywords:["japanese","nation","country","border"],char:'🎌',fitzpatrick_scale:false,category:"objects"},izakaya_lantern:{keywords:["light","paper","halloween","spooky"],char:'🏮',fitzpatrick_scale:false,category:"objects"},red_envelope:{keywords:["gift"],char:'🧧',fitzpatrick_scale:false,category:"objects"},email:{keywords:["letter","postal","inbox","communication"],char:'✉️',fitzpatrick_scale:false,category:"objects"},envelope_with_arrow:{keywords:["email","communication"],char:'📩',fitzpatrick_scale:false,category:"objects"},incoming_envelope:{keywords:["email","inbox"],char:'📨',fitzpatrick_scale:false,category:"objects"},"e-mail":{keywords:["communication","inbox"],char:'📧',fitzpatrick_scale:false,category:"objects"},love_letter:{keywords:["email","like","affection","envelope","valentines"],char:'💌',fitzpatrick_scale:false,category:"objects"},postbox:{keywords:["email","letter","envelope"],char:'📮',fitzpatrick_scale:false,category:"objects"},mailbox_closed:{keywords:["email","communication","inbox"],char:'📪',fitzpatrick_scale:false,category:"objects"},mailbox:{keywords:["email","inbox","communication"],char:'📫',fitzpatrick_scale:false,category:"objects"},mailbox_with_mail:{keywords:["email","inbox","communication"],char:'📬',fitzpatrick_scale:false,category:"objects"},mailbox_with_no_mail:{keywords:["email","inbox"],char:'📭',fitzpatrick_scale:false,category:"objects"},package:{keywords:["mail","gift","cardboard","box","moving"],char:'📦',fitzpatrick_scale:false,category:"objects"},postal_horn:{keywords:["instrument","music"],char:'📯',fitzpatrick_scale:false,category:"objects"},inbox_tray:{keywords:["email","documents"],char:'📥',fitzpatrick_scale:false,category:"objects"},outbox_tray:{keywords:["inbox","email"],char:'📤',fitzpatrick_scale:false,category:"objects"},scroll:{keywords:["documents","ancient","history","paper"],char:'📜',fitzpatrick_scale:false,category:"objects"},page_with_curl:{keywords:["documents","office","paper"],char:'📃',fitzpatrick_scale:false,category:"objects"},bookmark_tabs:{keywords:["favorite","save","order","tidy"],char:'📑',fitzpatrick_scale:false,category:"objects"},receipt:{keywords:["accounting","expenses"],char:'🧾',fitzpatrick_scale:false,category:"objects"},bar_chart:{keywords:["graph","presentation","stats"],char:'📊',fitzpatrick_scale:false,category:"objects"},chart_with_upwards_trend:{keywords:["graph","presentation","stats","recovery","business","economics","money","sales","good","success"],char:'📈',fitzpatrick_scale:false,category:"objects"},chart_with_downwards_trend:{keywords:["graph","presentation","stats","recession","business","economics","money","sales","bad","failure"],char:'📉',fitzpatrick_scale:false,category:"objects"},page_facing_up:{keywords:["documents","office","paper","information"],char:'📄',fitzpatrick_scale:false,category:"objects"},date:{keywords:["calendar","schedule"],char:'📅',fitzpatrick_scale:false,category:"objects"},calendar:{keywords:["schedule","date","planning"],char:'📆',fitzpatrick_scale:false,category:"objects"},spiral_calendar:{keywords:["date","schedule","planning"],char:'🗓',fitzpatrick_scale:false,category:"objects"},card_index:{keywords:["business","stationery"],char:'📇',fitzpatrick_scale:false,category:"objects"},card_file_box:{keywords:["business","stationery"],char:'🗃',fitzpatrick_scale:false,category:"objects"},ballot_box:{keywords:["election","vote"],char:'🗳',fitzpatrick_scale:false,category:"objects"},file_cabinet:{keywords:["filing","organizing"],char:'🗄',fitzpatrick_scale:false,category:"objects"},clipboard:{keywords:["stationery","documents"],char:'📋',fitzpatrick_scale:false,category:"objects"},spiral_notepad:{keywords:["memo","stationery"],char:'🗒',fitzpatrick_scale:false,category:"objects"},file_folder:{keywords:["documents","business","office"],char:'📁',fitzpatrick_scale:false,category:"objects"},open_file_folder:{keywords:["documents","load"],char:'📂',fitzpatrick_scale:false,category:"objects"},card_index_dividers:{keywords:["organizing","business","stationery"],char:'🗂',fitzpatrick_scale:false,category:"objects"},newspaper_roll:{keywords:["press","headline"],char:'🗞',fitzpatrick_scale:false,category:"objects"},newspaper:{keywords:["press","headline"],char:'📰',fitzpatrick_scale:false,category:"objects"},notebook:{keywords:["stationery","record","notes","paper","study"],char:'📓',fitzpatrick_scale:false,category:"objects"},closed_book:{keywords:["read","library","knowledge","textbook","learn"],char:'📕',fitzpatrick_scale:false,category:"objects"},green_book:{keywords:["read","library","knowledge","study"],char:'📗',fitzpatrick_scale:false,category:"objects"},blue_book:{keywords:["read","library","knowledge","learn","study"],char:'📘',fitzpatrick_scale:false,category:"objects"},orange_book:{keywords:["read","library","knowledge","textbook","study"],char:'📙',fitzpatrick_scale:false,category:"objects"},notebook_with_decorative_cover:{keywords:["classroom","notes","record","paper","study"],char:'📔',fitzpatrick_scale:false,category:"objects"},ledger:{keywords:["notes","paper"],char:'📒',fitzpatrick_scale:false,category:"objects"},books:{keywords:["literature","library","study"],char:'📚',fitzpatrick_scale:false,category:"objects"},open_book:{keywords:["book","read","library","knowledge","literature","learn","study"],char:'📖',fitzpatrick_scale:false,category:"objects"},safety_pin:{keywords:["diaper"],char:'🧷',fitzpatrick_scale:false,category:"objects"},link:{keywords:["rings","url"],char:'🔗',fitzpatrick_scale:false,category:"objects"},paperclip:{keywords:["documents","stationery"],char:'📎',fitzpatrick_scale:false,category:"objects"},paperclips:{keywords:["documents","stationery"],char:'🖇',fitzpatrick_scale:false,category:"objects"},scissors:{keywords:["stationery","cut"],char:'✂️',fitzpatrick_scale:false,category:"objects"},triangular_ruler:{keywords:["stationery","math","architect","sketch"],char:'📐',fitzpatrick_scale:false,category:"objects"},straight_ruler:{keywords:["stationery","calculate","length","math","school","drawing","architect","sketch"],char:'📏',fitzpatrick_scale:false,category:"objects"},abacus:{keywords:["calculation"],char:'🧮',fitzpatrick_scale:false,category:"objects"},pushpin:{keywords:["stationery","mark","here"],char:'📌',fitzpatrick_scale:false,category:"objects"},round_pushpin:{keywords:["stationery","location","map","here"],char:'📍',fitzpatrick_scale:false,category:"objects"},triangular_flag_on_post:{keywords:["mark","milestone","place"],char:'🚩',fitzpatrick_scale:false,category:"objects"},white_flag:{keywords:["losing","loser","lost","surrender","give up","fail"],char:'🏳',fitzpatrick_scale:false,category:"objects"},black_flag:{keywords:["pirate"],char:'🏴',fitzpatrick_scale:false,category:"objects"},rainbow_flag:{keywords:["flag","rainbow","pride","gay","lgbt","glbt","queer","homosexual","lesbian","bisexual","transgender"],char:'🏳️‍🌈',fitzpatrick_scale:false,category:"objects"},closed_lock_with_key:{keywords:["security","privacy"],char:'🔐',fitzpatrick_scale:false,category:"objects"},lock:{keywords:["security","password","padlock"],char:'🔒',fitzpatrick_scale:false,category:"objects"},unlock:{keywords:["privacy","security"],char:'🔓',fitzpatrick_scale:false,category:"objects"},lock_with_ink_pen:{keywords:["security","secret"],char:'🔏',fitzpatrick_scale:false,category:"objects"},pen:{keywords:["stationery","writing","write"],char:'🖊',fitzpatrick_scale:false,category:"objects"},fountain_pen:{keywords:["stationery","writing","write"],char:'🖋',fitzpatrick_scale:false,category:"objects"},black_nib:{keywords:["pen","stationery","writing","write"],char:'✒️',fitzpatrick_scale:false,category:"objects"},memo:{keywords:["write","documents","stationery","pencil","paper","writing","legal","exam","quiz","test","study","compose"],char:'📝',fitzpatrick_scale:false,category:"objects"},pencil2:{keywords:["stationery","write","paper","writing","school","study"],char:'✏️',fitzpatrick_scale:false,category:"objects"},crayon:{keywords:["drawing","creativity"],char:'🖍',fitzpatrick_scale:false,category:"objects"},paintbrush:{keywords:["drawing","creativity","art"],char:'🖌',fitzpatrick_scale:false,category:"objects"},mag:{keywords:["search","zoom","find","detective"],char:'🔍',fitzpatrick_scale:false,category:"objects"},mag_right:{keywords:["search","zoom","find","detective"],char:'🔎',fitzpatrick_scale:false,category:"objects"},heart:{keywords:["love","like","valentines"],char:'❤️',fitzpatrick_scale:false,category:"symbols"},orange_heart:{keywords:["love","like","affection","valentines"],char:'🧡',fitzpatrick_scale:false,category:"symbols"},yellow_heart:{keywords:["love","like","affection","valentines"],char:'💛',fitzpatrick_scale:false,category:"symbols"},green_heart:{keywords:["love","like","affection","valentines"],char:'💚',fitzpatrick_scale:false,category:"symbols"},blue_heart:{keywords:["love","like","affection","valentines"],char:'💙',fitzpatrick_scale:false,category:"symbols"},purple_heart:{keywords:["love","like","affection","valentines"],char:'💜',fitzpatrick_scale:false,category:"symbols"},black_heart:{keywords:["evil"],char:'🖤',fitzpatrick_scale:false,category:"symbols"},broken_heart:{keywords:["sad","sorry","break","heart","heartbreak"],char:'💔',fitzpatrick_scale:false,category:"symbols"},heavy_heart_exclamation:{keywords:["decoration","love"],char:'❣',fitzpatrick_scale:false,category:"symbols"},two_hearts:{keywords:["love","like","affection","valentines","heart"],char:'💕',fitzpatrick_scale:false,category:"symbols"},revolving_hearts:{keywords:["love","like","affection","valentines"],char:'💞',fitzpatrick_scale:false,category:"symbols"},heartbeat:{keywords:["love","like","affection","valentines","pink","heart"],char:'💓',fitzpatrick_scale:false,category:"symbols"},heartpulse:{keywords:["like","love","affection","valentines","pink"],char:'💗',fitzpatrick_scale:false,category:"symbols"},sparkling_heart:{keywords:["love","like","affection","valentines"],char:'💖',fitzpatrick_scale:false,category:"symbols"},cupid:{keywords:["love","like","heart","affection","valentines"],char:'💘',fitzpatrick_scale:false,category:"symbols"},gift_heart:{keywords:["love","valentines"],char:'💝',fitzpatrick_scale:false,category:"symbols"},heart_decoration:{keywords:["purple-square","love","like"],char:'💟',fitzpatrick_scale:false,category:"symbols"},peace_symbol:{keywords:["hippie"],char:'☮',fitzpatrick_scale:false,category:"symbols"},latin_cross:{keywords:["christianity"],char:'✝',fitzpatrick_scale:false,category:"symbols"},star_and_crescent:{keywords:["islam"],char:'☪',fitzpatrick_scale:false,category:"symbols"},om:{keywords:["hinduism","buddhism","sikhism","jainism"],char:'🕉',fitzpatrick_scale:false,category:"symbols"},wheel_of_dharma:{keywords:["hinduism","buddhism","sikhism","jainism"],char:'☸',fitzpatrick_scale:false,category:"symbols"},star_of_david:{keywords:["judaism"],char:'✡',fitzpatrick_scale:false,category:"symbols"},six_pointed_star:{keywords:["purple-square","religion","jewish","hexagram"],char:'🔯',fitzpatrick_scale:false,category:"symbols"},menorah:{keywords:["hanukkah","candles","jewish"],char:'🕎',fitzpatrick_scale:false,category:"symbols"},yin_yang:{keywords:["balance"],char:'☯',fitzpatrick_scale:false,category:"symbols"},orthodox_cross:{keywords:["suppedaneum","religion"],char:'☦',fitzpatrick_scale:false,category:"symbols"},place_of_worship:{keywords:["religion","church","temple","prayer"],char:'🛐',fitzpatrick_scale:false,category:"symbols"},ophiuchus:{keywords:["sign","purple-square","constellation","astrology"],char:'⛎',fitzpatrick_scale:false,category:"symbols"},aries:{keywords:["sign","purple-square","zodiac","astrology"],char:'♈',fitzpatrick_scale:false,category:"symbols"},taurus:{keywords:["purple-square","sign","zodiac","astrology"],char:'♉',fitzpatrick_scale:false,category:"symbols"},gemini:{keywords:["sign","zodiac","purple-square","astrology"],char:'♊',fitzpatrick_scale:false,category:"symbols"},cancer:{keywords:["sign","zodiac","purple-square","astrology"],char:'♋',fitzpatrick_scale:false,category:"symbols"},leo:{keywords:["sign","purple-square","zodiac","astrology"],char:'♌',fitzpatrick_scale:false,category:"symbols"},virgo:{keywords:["sign","zodiac","purple-square","astrology"],char:'♍',fitzpatrick_scale:false,category:"symbols"},libra:{keywords:["sign","purple-square","zodiac","astrology"],char:'♎',fitzpatrick_scale:false,category:"symbols"},scorpius:{keywords:["sign","zodiac","purple-square","astrology","scorpio"],char:'♏',fitzpatrick_scale:false,category:"symbols"},sagittarius:{keywords:["sign","zodiac","purple-square","astrology"],char:'♐',fitzpatrick_scale:false,category:"symbols"},capricorn:{keywords:["sign","zodiac","purple-square","astrology"],char:'♑',fitzpatrick_scale:false,category:"symbols"},aquarius:{keywords:["sign","purple-square","zodiac","astrology"],char:'♒',fitzpatrick_scale:false,category:"symbols"},pisces:{keywords:["purple-square","sign","zodiac","astrology"],char:'♓',fitzpatrick_scale:false,category:"symbols"},id:{keywords:["purple-square","words"],char:'🆔',fitzpatrick_scale:false,category:"symbols"},atom_symbol:{keywords:["science","physics","chemistry"],char:'⚛',fitzpatrick_scale:false,category:"symbols"},u7a7a:{keywords:["kanji","japanese","chinese","empty","sky","blue-square"],char:'🈳',fitzpatrick_scale:false,category:"symbols"},u5272:{keywords:["cut","divide","chinese","kanji","pink-square"],char:'🈹',fitzpatrick_scale:false,category:"symbols"},radioactive:{keywords:["nuclear","danger"],char:'☢',fitzpatrick_scale:false,category:"symbols"},biohazard:{keywords:["danger"],char:'☣',fitzpatrick_scale:false,category:"symbols"},mobile_phone_off:{keywords:["mute","orange-square","silence","quiet"],char:'📴',fitzpatrick_scale:false,category:"symbols"},vibration_mode:{keywords:["orange-square","phone"],char:'📳',fitzpatrick_scale:false,category:"symbols"},u6709:{keywords:["orange-square","chinese","have","kanji"],char:'🈶',fitzpatrick_scale:false,category:"symbols"},u7121:{keywords:["nothing","chinese","kanji","japanese","orange-square"],char:'🈚',fitzpatrick_scale:false,category:"symbols"},u7533:{keywords:["chinese","japanese","kanji","orange-square"],char:'🈸',fitzpatrick_scale:false,category:"symbols"},u55b6:{keywords:["japanese","opening hours","orange-square"],char:'🈺',fitzpatrick_scale:false,category:"symbols"},u6708:{keywords:["chinese","month","moon","japanese","orange-square","kanji"],char:'🈷️',fitzpatrick_scale:false,category:"symbols"},eight_pointed_black_star:{keywords:["orange-square","shape","polygon"],char:'✴️',fitzpatrick_scale:false,category:"symbols"},vs:{keywords:["words","orange-square"],char:'🆚',fitzpatrick_scale:false,category:"symbols"},accept:{keywords:["ok","good","chinese","kanji","agree","yes","orange-circle"],char:'🉑',fitzpatrick_scale:false,category:"symbols"},white_flower:{keywords:["japanese","spring"],char:'💮',fitzpatrick_scale:false,category:"symbols"},ideograph_advantage:{keywords:["chinese","kanji","obtain","get","circle"],char:'🉐',fitzpatrick_scale:false,category:"symbols"},secret:{keywords:["privacy","chinese","sshh","kanji","red-circle"],char:'㊙️',fitzpatrick_scale:false,category:"symbols"},congratulations:{keywords:["chinese","kanji","japanese","red-circle"],char:'㊗️',fitzpatrick_scale:false,category:"symbols"},u5408:{keywords:["japanese","chinese","join","kanji","red-square"],char:'🈴',fitzpatrick_scale:false,category:"symbols"},u6e80:{keywords:["full","chinese","japanese","red-square","kanji"],char:'🈵',fitzpatrick_scale:false,category:"symbols"},u7981:{keywords:["kanji","japanese","chinese","forbidden","limit","restricted","red-square"],char:'🈲',fitzpatrick_scale:false,category:"symbols"},a:{keywords:["red-square","alphabet","letter"],char:'🅰️',fitzpatrick_scale:false,category:"symbols"},b:{keywords:["red-square","alphabet","letter"],char:'🅱️',fitzpatrick_scale:false,category:"symbols"},ab:{keywords:["red-square","alphabet"],char:'🆎',fitzpatrick_scale:false,category:"symbols"},cl:{keywords:["alphabet","words","red-square"],char:'🆑',fitzpatrick_scale:false,category:"symbols"},o2:{keywords:["alphabet","red-square","letter"],char:'🅾️',fitzpatrick_scale:false,category:"symbols"},sos:{keywords:["help","red-square","words","emergency","911"],char:'🆘',fitzpatrick_scale:false,category:"symbols"},no_entry:{keywords:["limit","security","privacy","bad","denied","stop","circle"],char:'⛔',fitzpatrick_scale:false,category:"symbols"},name_badge:{keywords:["fire","forbid"],char:'📛',fitzpatrick_scale:false,category:"symbols"},no_entry_sign:{keywords:["forbid","stop","limit","denied","disallow","circle"],char:'🚫',fitzpatrick_scale:false,category:"symbols"},x:{keywords:["no","delete","remove","cancel","red"],char:'❌',fitzpatrick_scale:false,category:"symbols"},o:{keywords:["circle","round"],char:'⭕',fitzpatrick_scale:false,category:"symbols"},stop_sign:{keywords:["stop"],char:'🛑',fitzpatrick_scale:false,category:"symbols"},anger:{keywords:["angry","mad"],char:'💢',fitzpatrick_scale:false,category:"symbols"},hotsprings:{keywords:["bath","warm","relax"],char:'♨️',fitzpatrick_scale:false,category:"symbols"},no_pedestrians:{keywords:["rules","crossing","walking","circle"],char:'🚷',fitzpatrick_scale:false,category:"symbols"},do_not_litter:{keywords:["trash","bin","garbage","circle"],char:'🚯',fitzpatrick_scale:false,category:"symbols"},no_bicycles:{keywords:["cyclist","prohibited","circle"],char:'🚳',fitzpatrick_scale:false,category:"symbols"},"non-potable_water":{keywords:["drink","faucet","tap","circle"],char:'🚱',fitzpatrick_scale:false,category:"symbols"},underage:{keywords:["18","drink","pub","night","minor","circle"],char:'🔞',fitzpatrick_scale:false,category:"symbols"},no_mobile_phones:{keywords:["iphone","mute","circle"],char:'📵',fitzpatrick_scale:false,category:"symbols"},exclamation:{keywords:["heavy_exclamation_mark","danger","surprise","punctuation","wow","warning"],char:'❗',fitzpatrick_scale:false,category:"symbols"},grey_exclamation:{keywords:["surprise","punctuation","gray","wow","warning"],char:'❕',fitzpatrick_scale:false,category:"symbols"},question:{keywords:["doubt","confused"],char:'❓',fitzpatrick_scale:false,category:"symbols"},grey_question:{keywords:["doubts","gray","huh","confused"],char:'❔',fitzpatrick_scale:false,category:"symbols"},bangbang:{keywords:["exclamation","surprise"],char:'‼️',fitzpatrick_scale:false,category:"symbols"},interrobang:{keywords:["wat","punctuation","surprise"],char:'⁉️',fitzpatrick_scale:false,category:"symbols"},low_brightness:{keywords:["sun","afternoon","warm","summer"],char:'🔅',fitzpatrick_scale:false,category:"symbols"},high_brightness:{keywords:["sun","light"],char:'🔆',fitzpatrick_scale:false,category:"symbols"},trident:{keywords:["weapon","spear"],char:'🔱',fitzpatrick_scale:false,category:"symbols"},fleur_de_lis:{keywords:["decorative","scout"],char:'⚜',fitzpatrick_scale:false,category:"symbols"},part_alternation_mark:{keywords:["graph","presentation","stats","business","economics","bad"],char:'〽️',fitzpatrick_scale:false,category:"symbols"},warning:{keywords:["exclamation","wip","alert","error","problem","issue"],char:'⚠️',fitzpatrick_scale:false,category:"symbols"},children_crossing:{keywords:["school","warning","danger","sign","driving","yellow-diamond"],char:'🚸',fitzpatrick_scale:false,category:"symbols"},beginner:{keywords:["badge","shield"],char:'🔰',fitzpatrick_scale:false,category:"symbols"},recycle:{keywords:["arrow","environment","garbage","trash"],char:'♻️',fitzpatrick_scale:false,category:"symbols"},u6307:{keywords:["chinese","point","green-square","kanji"],char:'🈯',fitzpatrick_scale:false,category:"symbols"},chart:{keywords:["green-square","graph","presentation","stats"],char:'💹',fitzpatrick_scale:false,category:"symbols"},sparkle:{keywords:["stars","green-square","awesome","good","fireworks"],char:'❇️',fitzpatrick_scale:false,category:"symbols"},eight_spoked_asterisk:{keywords:["star","sparkle","green-square"],char:'✳️',fitzpatrick_scale:false,category:"symbols"},negative_squared_cross_mark:{keywords:["x","green-square","no","deny"],char:'❎',fitzpatrick_scale:false,category:"symbols"},white_check_mark:{keywords:["green-square","ok","agree","vote","election","answer","tick"],char:'✅',fitzpatrick_scale:false,category:"symbols"},diamond_shape_with_a_dot_inside:{keywords:["jewel","blue","gem","crystal","fancy"],char:'💠',fitzpatrick_scale:false,category:"symbols"},cyclone:{keywords:["weather","swirl","blue","cloud","vortex","spiral","whirlpool","spin","tornado","hurricane","typhoon"],char:'🌀',fitzpatrick_scale:false,category:"symbols"},loop:{keywords:["tape","cassette"],char:'➿',fitzpatrick_scale:false,category:"symbols"},globe_with_meridians:{keywords:["earth","international","world","internet","interweb","i18n"],char:'🌐',fitzpatrick_scale:false,category:"symbols"},m:{keywords:["alphabet","blue-circle","letter"],char:'Ⓜ️',fitzpatrick_scale:false,category:"symbols"},atm:{keywords:["money","sales","cash","blue-square","payment","bank"],char:'🏧',fitzpatrick_scale:false,category:"symbols"},sa:{keywords:["japanese","blue-square","katakana"],char:'🈂️',fitzpatrick_scale:false,category:"symbols"},passport_control:{keywords:["custom","blue-square"],char:'🛂',fitzpatrick_scale:false,category:"symbols"},customs:{keywords:["passport","border","blue-square"],char:'🛃',fitzpatrick_scale:false,category:"symbols"},baggage_claim:{keywords:["blue-square","airport","transport"],char:'🛄',fitzpatrick_scale:false,category:"symbols"},left_luggage:{keywords:["blue-square","travel"],char:'🛅',fitzpatrick_scale:false,category:"symbols"},wheelchair:{keywords:["blue-square","disabled","a11y","accessibility"],char:'♿',fitzpatrick_scale:false,category:"symbols"},no_smoking:{keywords:["cigarette","blue-square","smell","smoke"],char:'🚭',fitzpatrick_scale:false,category:"symbols"},wc:{keywords:["toilet","restroom","blue-square"],char:'🚾',fitzpatrick_scale:false,category:"symbols"},parking:{keywords:["cars","blue-square","alphabet","letter"],char:'🅿️',fitzpatrick_scale:false,category:"symbols"},potable_water:{keywords:["blue-square","liquid","restroom","cleaning","faucet"],char:'🚰',fitzpatrick_scale:false,category:"symbols"},mens:{keywords:["toilet","restroom","wc","blue-square","gender","male"],char:'🚹',fitzpatrick_scale:false,category:"symbols"},womens:{keywords:["purple-square","woman","female","toilet","loo","restroom","gender"],char:'🚺',fitzpatrick_scale:false,category:"symbols"},baby_symbol:{keywords:["orange-square","child"],char:'🚼',fitzpatrick_scale:false,category:"symbols"},restroom:{keywords:["blue-square","toilet","refresh","wc","gender"],char:'🚻',fitzpatrick_scale:false,category:"symbols"},put_litter_in_its_place:{keywords:["blue-square","sign","human","info"],char:'🚮',fitzpatrick_scale:false,category:"symbols"},cinema:{keywords:["blue-square","record","film","movie","curtain","stage","theater"],char:'🎦',fitzpatrick_scale:false,category:"symbols"},signal_strength:{keywords:["blue-square","reception","phone","internet","connection","wifi","bluetooth","bars"],char:'📶',fitzpatrick_scale:false,category:"symbols"},koko:{keywords:["blue-square","here","katakana","japanese","destination"],char:'🈁',fitzpatrick_scale:false,category:"symbols"},ng:{keywords:["blue-square","words","shape","icon"],char:'🆖',fitzpatrick_scale:false,category:"symbols"},ok:{keywords:["good","agree","yes","blue-square"],char:'🆗',fitzpatrick_scale:false,category:"symbols"},up:{keywords:["blue-square","above","high"],char:'🆙',fitzpatrick_scale:false,category:"symbols"},cool:{keywords:["words","blue-square"],char:'🆒',fitzpatrick_scale:false,category:"symbols"},new:{keywords:["blue-square","words","start"],char:'🆕',fitzpatrick_scale:false,category:"symbols"},free:{keywords:["blue-square","words"],char:'🆓',fitzpatrick_scale:false,category:"symbols"},zero:{keywords:["0","numbers","blue-square","null"],char:'0️⃣',fitzpatrick_scale:false,category:"symbols"},one:{keywords:["blue-square","numbers","1"],char:'1️⃣',fitzpatrick_scale:false,category:"symbols"},two:{keywords:["numbers","2","prime","blue-square"],char:'2️⃣',fitzpatrick_scale:false,category:"symbols"},three:{keywords:["3","numbers","prime","blue-square"],char:'3️⃣',fitzpatrick_scale:false,category:"symbols"},four:{keywords:["4","numbers","blue-square"],char:'4️⃣',fitzpatrick_scale:false,category:"symbols"},five:{keywords:["5","numbers","blue-square","prime"],char:'5️⃣',fitzpatrick_scale:false,category:"symbols"},six:{keywords:["6","numbers","blue-square"],char:'6️⃣',fitzpatrick_scale:false,category:"symbols"},seven:{keywords:["7","numbers","blue-square","prime"],char:'7️⃣',fitzpatrick_scale:false,category:"symbols"},eight:{keywords:["8","blue-square","numbers"],char:'8️⃣',fitzpatrick_scale:false,category:"symbols"},nine:{keywords:["blue-square","numbers","9"],char:'9️⃣',fitzpatrick_scale:false,category:"symbols"},keycap_ten:{keywords:["numbers","10","blue-square"],char:'🔟',fitzpatrick_scale:false,category:"symbols"},asterisk:{keywords:["star","keycap"],char:'*⃣',fitzpatrick_scale:false,category:"symbols"},eject_button:{keywords:["blue-square"],char:'⏏️',fitzpatrick_scale:false,category:"symbols"},arrow_forward:{keywords:["blue-square","right","direction","play"],char:'▶️',fitzpatrick_scale:false,category:"symbols"},pause_button:{keywords:["pause","blue-square"],char:'⏸',fitzpatrick_scale:false,category:"symbols"},next_track_button:{keywords:["forward","next","blue-square"],char:'⏭',fitzpatrick_scale:false,category:"symbols"},stop_button:{keywords:["blue-square"],char:'⏹',fitzpatrick_scale:false,category:"symbols"},record_button:{keywords:["blue-square"],char:'⏺',fitzpatrick_scale:false,category:"symbols"},play_or_pause_button:{keywords:["blue-square","play","pause"],char:'⏯',fitzpatrick_scale:false,category:"symbols"},previous_track_button:{keywords:["backward"],char:'⏮',fitzpatrick_scale:false,category:"symbols"},fast_forward:{keywords:["blue-square","play","speed","continue"],char:'⏩',fitzpatrick_scale:false,category:"symbols"},rewind:{keywords:["play","blue-square"],char:'⏪',fitzpatrick_scale:false,category:"symbols"},twisted_rightwards_arrows:{keywords:["blue-square","shuffle","music","random"],char:'🔀',fitzpatrick_scale:false,category:"symbols"},repeat:{keywords:["loop","record"],char:'🔁',fitzpatrick_scale:false,category:"symbols"},repeat_one:{keywords:["blue-square","loop"],char:'🔂',fitzpatrick_scale:false,category:"symbols"},arrow_backward:{keywords:["blue-square","left","direction"],char:'◀️',fitzpatrick_scale:false,category:"symbols"},arrow_up_small:{keywords:["blue-square","triangle","direction","point","forward","top"],char:'🔼',fitzpatrick_scale:false,category:"symbols"},arrow_down_small:{keywords:["blue-square","direction","bottom"],char:'🔽',fitzpatrick_scale:false,category:"symbols"},arrow_double_up:{keywords:["blue-square","direction","top"],char:'⏫',fitzpatrick_scale:false,category:"symbols"},arrow_double_down:{keywords:["blue-square","direction","bottom"],char:'⏬',fitzpatrick_scale:false,category:"symbols"},arrow_right:{keywords:["blue-square","next"],char:'➡️',fitzpatrick_scale:false,category:"symbols"},arrow_left:{keywords:["blue-square","previous","back"],char:'⬅️',fitzpatrick_scale:false,category:"symbols"},arrow_up:{keywords:["blue-square","continue","top","direction"],char:'⬆️',fitzpatrick_scale:false,category:"symbols"},arrow_down:{keywords:["blue-square","direction","bottom"],char:'⬇️',fitzpatrick_scale:false,category:"symbols"},arrow_upper_right:{keywords:["blue-square","point","direction","diagonal","northeast"],char:'↗️',fitzpatrick_scale:false,category:"symbols"},arrow_lower_right:{keywords:["blue-square","direction","diagonal","southeast"],char:'↘️',fitzpatrick_scale:false,category:"symbols"},arrow_lower_left:{keywords:["blue-square","direction","diagonal","southwest"],char:'↙️',fitzpatrick_scale:false,category:"symbols"},arrow_upper_left:{keywords:["blue-square","point","direction","diagonal","northwest"],char:'↖️',fitzpatrick_scale:false,category:"symbols"},arrow_up_down:{keywords:["blue-square","direction","way","vertical"],char:'↕️',fitzpatrick_scale:false,category:"symbols"},left_right_arrow:{keywords:["shape","direction","horizontal","sideways"],char:'↔️',fitzpatrick_scale:false,category:"symbols"},arrows_counterclockwise:{keywords:["blue-square","sync","cycle"],char:'🔄',fitzpatrick_scale:false,category:"symbols"},arrow_right_hook:{keywords:["blue-square","return","rotate","direction"],char:'↪️',fitzpatrick_scale:false,category:"symbols"},leftwards_arrow_with_hook:{keywords:["back","return","blue-square","undo","enter"],char:'↩️',fitzpatrick_scale:false,category:"symbols"},arrow_heading_up:{keywords:["blue-square","direction","top"],char:'⤴️',fitzpatrick_scale:false,category:"symbols"},arrow_heading_down:{keywords:["blue-square","direction","bottom"],char:'⤵️',fitzpatrick_scale:false,category:"symbols"},hash:{keywords:["symbol","blue-square","twitter"],char:'#️⃣',fitzpatrick_scale:false,category:"symbols"},information_source:{keywords:["blue-square","alphabet","letter"],char:'ℹ️',fitzpatrick_scale:false,category:"symbols"},abc:{keywords:["blue-square","alphabet"],char:'🔤',fitzpatrick_scale:false,category:"symbols"},abcd:{keywords:["blue-square","alphabet"],char:'🔡',fitzpatrick_scale:false,category:"symbols"},capital_abcd:{keywords:["alphabet","words","blue-square"],char:'🔠',fitzpatrick_scale:false,category:"symbols"},symbols:{keywords:["blue-square","music","note","ampersand","percent","glyphs","characters"],char:'🔣',fitzpatrick_scale:false,category:"symbols"},musical_note:{keywords:["score","tone","sound"],char:'🎵',fitzpatrick_scale:false,category:"symbols"},notes:{keywords:["music","score"],char:'🎶',fitzpatrick_scale:false,category:"symbols"},wavy_dash:{keywords:["draw","line","moustache","mustache","squiggle","scribble"],char:'〰️',fitzpatrick_scale:false,category:"symbols"},curly_loop:{keywords:["scribble","draw","shape","squiggle"],char:'➰',fitzpatrick_scale:false,category:"symbols"},heavy_check_mark:{keywords:["ok","nike","answer","yes","tick"],char:'✔️',fitzpatrick_scale:false,category:"symbols"},arrows_clockwise:{keywords:["sync","cycle","round","repeat"],char:'🔃',fitzpatrick_scale:false,category:"symbols"},heavy_plus_sign:{keywords:["math","calculation","addition","more","increase"],char:'➕',fitzpatrick_scale:false,category:"symbols"},heavy_minus_sign:{keywords:["math","calculation","subtract","less"],char:'➖',fitzpatrick_scale:false,category:"symbols"},heavy_division_sign:{keywords:["divide","math","calculation"],char:'➗',fitzpatrick_scale:false,category:"symbols"},heavy_multiplication_x:{keywords:["math","calculation"],char:'✖️',fitzpatrick_scale:false,category:"symbols"},infinity:{keywords:["forever"],char:'♾',fitzpatrick_scale:false,category:"symbols"},heavy_dollar_sign:{keywords:["money","sales","payment","currency","buck"],char:'💲',fitzpatrick_scale:false,category:"symbols"},currency_exchange:{keywords:["money","sales","dollar","travel"],char:'💱',fitzpatrick_scale:false,category:"symbols"},copyright:{keywords:["ip","license","circle","law","legal"],char:'©️',fitzpatrick_scale:false,category:"symbols"},registered:{keywords:["alphabet","circle"],char:'®️',fitzpatrick_scale:false,category:"symbols"},tm:{keywords:["trademark","brand","law","legal"],char:'™️',fitzpatrick_scale:false,category:"symbols"},end:{keywords:["words","arrow"],char:'🔚',fitzpatrick_scale:false,category:"symbols"},back:{keywords:["arrow","words","return"],char:'🔙',fitzpatrick_scale:false,category:"symbols"},on:{keywords:["arrow","words"],char:'🔛',fitzpatrick_scale:false,category:"symbols"},top:{keywords:["words","blue-square"],char:'🔝',fitzpatrick_scale:false,category:"symbols"},soon:{keywords:["arrow","words"],char:'🔜',fitzpatrick_scale:false,category:"symbols"},ballot_box_with_check:{keywords:["ok","agree","confirm","black-square","vote","election","yes","tick"],char:'☑️',fitzpatrick_scale:false,category:"symbols"},radio_button:{keywords:["input","old","music","circle"],char:'🔘',fitzpatrick_scale:false,category:"symbols"},white_circle:{keywords:["shape","round"],char:'⚪',fitzpatrick_scale:false,category:"symbols"},black_circle:{keywords:["shape","button","round"],char:'⚫',fitzpatrick_scale:false,category:"symbols"},red_circle:{keywords:["shape","error","danger"],char:'🔴',fitzpatrick_scale:false,category:"symbols"},large_blue_circle:{keywords:["shape","icon","button"],char:'🔵',fitzpatrick_scale:false,category:"symbols"},small_orange_diamond:{keywords:["shape","jewel","gem"],char:'🔸',fitzpatrick_scale:false,category:"symbols"},small_blue_diamond:{keywords:["shape","jewel","gem"],char:'🔹',fitzpatrick_scale:false,category:"symbols"},large_orange_diamond:{keywords:["shape","jewel","gem"],char:'🔶',fitzpatrick_scale:false,category:"symbols"},large_blue_diamond:{keywords:["shape","jewel","gem"],char:'🔷',fitzpatrick_scale:false,category:"symbols"},small_red_triangle:{keywords:["shape","direction","up","top"],char:'🔺',fitzpatrick_scale:false,category:"symbols"},black_small_square:{keywords:["shape","icon"],char:'▪️',fitzpatrick_scale:false,category:"symbols"},white_small_square:{keywords:["shape","icon"],char:'▫️',fitzpatrick_scale:false,category:"symbols"},black_large_square:{keywords:["shape","icon","button"],char:'⬛',fitzpatrick_scale:false,category:"symbols"},white_large_square:{keywords:["shape","icon","stone","button"],char:'⬜',fitzpatrick_scale:false,category:"symbols"},small_red_triangle_down:{keywords:["shape","direction","bottom"],char:'🔻',fitzpatrick_scale:false,category:"symbols"},black_medium_square:{keywords:["shape","button","icon"],char:'◼️',fitzpatrick_scale:false,category:"symbols"},white_medium_square:{keywords:["shape","stone","icon"],char:'◻️',fitzpatrick_scale:false,category:"symbols"},black_medium_small_square:{keywords:["icon","shape","button"],char:'◾',fitzpatrick_scale:false,category:"symbols"},white_medium_small_square:{keywords:["shape","stone","icon","button"],char:'◽',fitzpatrick_scale:false,category:"symbols"},black_square_button:{keywords:["shape","input","frame"],char:'🔲',fitzpatrick_scale:false,category:"symbols"},white_square_button:{keywords:["shape","input"],char:'🔳',fitzpatrick_scale:false,category:"symbols"},speaker:{keywords:["sound","volume","silence","broadcast"],char:'🔈',fitzpatrick_scale:false,category:"symbols"},sound:{keywords:["volume","speaker","broadcast"],char:'🔉',fitzpatrick_scale:false,category:"symbols"},loud_sound:{keywords:["volume","noise","noisy","speaker","broadcast"],char:'🔊',fitzpatrick_scale:false,category:"symbols"},mute:{keywords:["sound","volume","silence","quiet"],char:'🔇',fitzpatrick_scale:false,category:"symbols"},mega:{keywords:["sound","speaker","volume"],char:'📣',fitzpatrick_scale:false,category:"symbols"},loudspeaker:{keywords:["volume","sound"],char:'📢',fitzpatrick_scale:false,category:"symbols"},bell:{keywords:["sound","notification","christmas","xmas","chime"],char:'🔔',fitzpatrick_scale:false,category:"symbols"},no_bell:{keywords:["sound","volume","mute","quiet","silent"],char:'🔕',fitzpatrick_scale:false,category:"symbols"},black_joker:{keywords:["poker","cards","game","play","magic"],char:'🃏',fitzpatrick_scale:false,category:"symbols"},mahjong:{keywords:["game","play","chinese","kanji"],char:'🀄',fitzpatrick_scale:false,category:"symbols"},spades:{keywords:["poker","cards","suits","magic"],char:'♠️',fitzpatrick_scale:false,category:"symbols"},clubs:{keywords:["poker","cards","magic","suits"],char:'♣️',fitzpatrick_scale:false,category:"symbols"},hearts:{keywords:["poker","cards","magic","suits"],char:'♥️',fitzpatrick_scale:false,category:"symbols"},diamonds:{keywords:["poker","cards","magic","suits"],char:'♦️',fitzpatrick_scale:false,category:"symbols"},flower_playing_cards:{keywords:["game","sunset","red"],char:'🎴',fitzpatrick_scale:false,category:"symbols"},thought_balloon:{keywords:["bubble","cloud","speech","thinking","dream"],char:'💭',fitzpatrick_scale:false,category:"symbols"},right_anger_bubble:{keywords:["caption","speech","thinking","mad"],char:'🗯',fitzpatrick_scale:false,category:"symbols"},speech_balloon:{keywords:["bubble","words","message","talk","chatting"],char:'💬',fitzpatrick_scale:false,category:"symbols"},left_speech_bubble:{keywords:["words","message","talk","chatting"],char:'🗨',fitzpatrick_scale:false,category:"symbols"},clock1:{keywords:["time","late","early","schedule"],char:'🕐',fitzpatrick_scale:false,category:"symbols"},clock2:{keywords:["time","late","early","schedule"],char:'🕑',fitzpatrick_scale:false,category:"symbols"},clock3:{keywords:["time","late","early","schedule"],char:'🕒',fitzpatrick_scale:false,category:"symbols"},clock4:{keywords:["time","late","early","schedule"],char:'🕓',fitzpatrick_scale:false,category:"symbols"},clock5:{keywords:["time","late","early","schedule"],char:'🕔',fitzpatrick_scale:false,category:"symbols"},clock6:{keywords:["time","late","early","schedule","dawn","dusk"],char:'🕕',fitzpatrick_scale:false,category:"symbols"},clock7:{keywords:["time","late","early","schedule"],char:'🕖',fitzpatrick_scale:false,category:"symbols"},clock8:{keywords:["time","late","early","schedule"],char:'🕗',fitzpatrick_scale:false,category:"symbols"},clock9:{keywords:["time","late","early","schedule"],char:'🕘',fitzpatrick_scale:false,category:"symbols"},clock10:{keywords:["time","late","early","schedule"],char:'🕙',fitzpatrick_scale:false,category:"symbols"},clock11:{keywords:["time","late","early","schedule"],char:'🕚',fitzpatrick_scale:false,category:"symbols"},clock12:{keywords:["time","noon","midnight","midday","late","early","schedule"],char:'🕛',fitzpatrick_scale:false,category:"symbols"},clock130:{keywords:["time","late","early","schedule"],char:'🕜',fitzpatrick_scale:false,category:"symbols"},clock230:{keywords:["time","late","early","schedule"],char:'🕝',fitzpatrick_scale:false,category:"symbols"},clock330:{keywords:["time","late","early","schedule"],char:'🕞',fitzpatrick_scale:false,category:"symbols"},clock430:{keywords:["time","late","early","schedule"],char:'🕟',fitzpatrick_scale:false,category:"symbols"},clock530:{keywords:["time","late","early","schedule"],char:'🕠',fitzpatrick_scale:false,category:"symbols"},clock630:{keywords:["time","late","early","schedule"],char:'🕡',fitzpatrick_scale:false,category:"symbols"},clock730:{keywords:["time","late","early","schedule"],char:'🕢',fitzpatrick_scale:false,category:"symbols"},clock830:{keywords:["time","late","early","schedule"],char:'🕣',fitzpatrick_scale:false,category:"symbols"},clock930:{keywords:["time","late","early","schedule"],char:'🕤',fitzpatrick_scale:false,category:"symbols"},clock1030:{keywords:["time","late","early","schedule"],char:'🕥',fitzpatrick_scale:false,category:"symbols"},clock1130:{keywords:["time","late","early","schedule"],char:'🕦',fitzpatrick_scale:false,category:"symbols"},clock1230:{keywords:["time","late","early","schedule"],char:'🕧',fitzpatrick_scale:false,category:"symbols"},afghanistan:{keywords:["af","flag","nation","country","banner"],char:'🇦🇫',fitzpatrick_scale:false,category:"flags"},aland_islands:{keywords:["Åland","islands","flag","nation","country","banner"],char:'🇦🇽',fitzpatrick_scale:false,category:"flags"},albania:{keywords:["al","flag","nation","country","banner"],char:'🇦🇱',fitzpatrick_scale:false,category:"flags"},algeria:{keywords:["dz","flag","nation","country","banner"],char:'🇩🇿',fitzpatrick_scale:false,category:"flags"},american_samoa:{keywords:["american","ws","flag","nation","country","banner"],char:'🇦🇸',fitzpatrick_scale:false,category:"flags"},andorra:{keywords:["ad","flag","nation","country","banner"],char:'🇦🇩',fitzpatrick_scale:false,category:"flags"},angola:{keywords:["ao","flag","nation","country","banner"],char:'🇦🇴',fitzpatrick_scale:false,category:"flags"},anguilla:{keywords:["ai","flag","nation","country","banner"],char:'🇦🇮',fitzpatrick_scale:false,category:"flags"},antarctica:{keywords:["aq","flag","nation","country","banner"],char:'🇦🇶',fitzpatrick_scale:false,category:"flags"},antigua_barbuda:{keywords:["antigua","barbuda","flag","nation","country","banner"],char:'🇦🇬',fitzpatrick_scale:false,category:"flags"},argentina:{keywords:["ar","flag","nation","country","banner"],char:'🇦🇷',fitzpatrick_scale:false,category:"flags"},armenia:{keywords:["am","flag","nation","country","banner"],char:'🇦🇲',fitzpatrick_scale:false,category:"flags"},aruba:{keywords:["aw","flag","nation","country","banner"],char:'🇦🇼',fitzpatrick_scale:false,category:"flags"},australia:{keywords:["au","flag","nation","country","banner"],char:'🇦🇺',fitzpatrick_scale:false,category:"flags"},austria:{keywords:["at","flag","nation","country","banner"],char:'🇦🇹',fitzpatrick_scale:false,category:"flags"},azerbaijan:{keywords:["az","flag","nation","country","banner"],char:'🇦🇿',fitzpatrick_scale:false,category:"flags"},bahamas:{keywords:["bs","flag","nation","country","banner"],char:'🇧🇸',fitzpatrick_scale:false,category:"flags"},bahrain:{keywords:["bh","flag","nation","country","banner"],char:'🇧🇭',fitzpatrick_scale:false,category:"flags"},bangladesh:{keywords:["bd","flag","nation","country","banner"],char:'🇧🇩',fitzpatrick_scale:false,category:"flags"},barbados:{keywords:["bb","flag","nation","country","banner"],char:'🇧🇧',fitzpatrick_scale:false,category:"flags"},belarus:{keywords:["by","flag","nation","country","banner"],char:'🇧🇾',fitzpatrick_scale:false,category:"flags"},belgium:{keywords:["be","flag","nation","country","banner"],char:'🇧🇪',fitzpatrick_scale:false,category:"flags"},belize:{keywords:["bz","flag","nation","country","banner"],char:'🇧🇿',fitzpatrick_scale:false,category:"flags"},benin:{keywords:["bj","flag","nation","country","banner"],char:'🇧🇯',fitzpatrick_scale:false,category:"flags"},bermuda:{keywords:["bm","flag","nation","country","banner"],char:'🇧🇲',fitzpatrick_scale:false,category:"flags"},bhutan:{keywords:["bt","flag","nation","country","banner"],char:'🇧🇹',fitzpatrick_scale:false,category:"flags"},bolivia:{keywords:["bo","flag","nation","country","banner"],char:'🇧🇴',fitzpatrick_scale:false,category:"flags"},caribbean_netherlands:{keywords:["bonaire","flag","nation","country","banner"],char:'🇧🇶',fitzpatrick_scale:false,category:"flags"},bosnia_herzegovina:{keywords:["bosnia","herzegovina","flag","nation","country","banner"],char:'🇧🇦',fitzpatrick_scale:false,category:"flags"},botswana:{keywords:["bw","flag","nation","country","banner"],char:'🇧🇼',fitzpatrick_scale:false,category:"flags"},brazil:{keywords:["br","flag","nation","country","banner"],char:'🇧🇷',fitzpatrick_scale:false,category:"flags"},british_indian_ocean_territory:{keywords:["british","indian","ocean","territory","flag","nation","country","banner"],char:'🇮🇴',fitzpatrick_scale:false,category:"flags"},british_virgin_islands:{keywords:["british","virgin","islands","bvi","flag","nation","country","banner"],char:'🇻🇬',fitzpatrick_scale:false,category:"flags"},brunei:{keywords:["bn","darussalam","flag","nation","country","banner"],char:'🇧🇳',fitzpatrick_scale:false,category:"flags"},bulgaria:{keywords:["bg","flag","nation","country","banner"],char:'🇧🇬',fitzpatrick_scale:false,category:"flags"},burkina_faso:{keywords:["burkina","faso","flag","nation","country","banner"],char:'🇧🇫',fitzpatrick_scale:false,category:"flags"},burundi:{keywords:["bi","flag","nation","country","banner"],char:'🇧🇮',fitzpatrick_scale:false,category:"flags"},cape_verde:{keywords:["cabo","verde","flag","nation","country","banner"],char:'🇨🇻',fitzpatrick_scale:false,category:"flags"},cambodia:{keywords:["kh","flag","nation","country","banner"],char:'🇰🇭',fitzpatrick_scale:false,category:"flags"},cameroon:{keywords:["cm","flag","nation","country","banner"],char:'🇨🇲',fitzpatrick_scale:false,category:"flags"},canada:{keywords:["ca","flag","nation","country","banner"],char:'🇨🇦',fitzpatrick_scale:false,category:"flags"},canary_islands:{keywords:["canary","islands","flag","nation","country","banner"],char:'🇮🇨',fitzpatrick_scale:false,category:"flags"},cayman_islands:{keywords:["cayman","islands","flag","nation","country","banner"],char:'🇰🇾',fitzpatrick_scale:false,category:"flags"},central_african_republic:{keywords:["central","african","republic","flag","nation","country","banner"],char:'🇨🇫',fitzpatrick_scale:false,category:"flags"},chad:{keywords:["td","flag","nation","country","banner"],char:'🇹🇩',fitzpatrick_scale:false,category:"flags"},chile:{keywords:["flag","nation","country","banner"],char:'🇨🇱',fitzpatrick_scale:false,category:"flags"},cn:{keywords:["china","chinese","prc","flag","country","nation","banner"],char:'🇨🇳',fitzpatrick_scale:false,category:"flags"},christmas_island:{keywords:["christmas","island","flag","nation","country","banner"],char:'🇨🇽',fitzpatrick_scale:false,category:"flags"},cocos_islands:{keywords:["cocos","keeling","islands","flag","nation","country","banner"],char:'🇨🇨',fitzpatrick_scale:false,category:"flags"},colombia:{keywords:["co","flag","nation","country","banner"],char:'🇨🇴',fitzpatrick_scale:false,category:"flags"},comoros:{keywords:["km","flag","nation","country","banner"],char:'🇰🇲',fitzpatrick_scale:false,category:"flags"},congo_brazzaville:{keywords:["congo","flag","nation","country","banner"],char:'🇨🇬',fitzpatrick_scale:false,category:"flags"},congo_kinshasa:{keywords:["congo","democratic","republic","flag","nation","country","banner"],char:'🇨🇩',fitzpatrick_scale:false,category:"flags"},cook_islands:{keywords:["cook","islands","flag","nation","country","banner"],char:'🇨🇰',fitzpatrick_scale:false,category:"flags"},costa_rica:{keywords:["costa","rica","flag","nation","country","banner"],char:'🇨🇷',fitzpatrick_scale:false,category:"flags"},croatia:{keywords:["hr","flag","nation","country","banner"],char:'🇭🇷',fitzpatrick_scale:false,category:"flags"},cuba:{keywords:["cu","flag","nation","country","banner"],char:'🇨🇺',fitzpatrick_scale:false,category:"flags"},curacao:{keywords:["curaçao","flag","nation","country","banner"],char:'🇨🇼',fitzpatrick_scale:false,category:"flags"},cyprus:{keywords:["cy","flag","nation","country","banner"],char:'🇨🇾',fitzpatrick_scale:false,category:"flags"},czech_republic:{keywords:["cz","flag","nation","country","banner"],char:'🇨🇿',fitzpatrick_scale:false,category:"flags"},denmark:{keywords:["dk","flag","nation","country","banner"],char:'🇩🇰',fitzpatrick_scale:false,category:"flags"},djibouti:{keywords:["dj","flag","nation","country","banner"],char:'🇩🇯',fitzpatrick_scale:false,category:"flags"},dominica:{keywords:["dm","flag","nation","country","banner"],char:'🇩🇲',fitzpatrick_scale:false,category:"flags"},dominican_republic:{keywords:["dominican","republic","flag","nation","country","banner"],char:'🇩🇴',fitzpatrick_scale:false,category:"flags"},ecuador:{keywords:["ec","flag","nation","country","banner"],char:'🇪🇨',fitzpatrick_scale:false,category:"flags"},egypt:{keywords:["eg","flag","nation","country","banner"],char:'🇪🇬',fitzpatrick_scale:false,category:"flags"},el_salvador:{keywords:["el","salvador","flag","nation","country","banner"],char:'🇸🇻',fitzpatrick_scale:false,category:"flags"},equatorial_guinea:{keywords:["equatorial","gn","flag","nation","country","banner"],char:'🇬🇶',fitzpatrick_scale:false,category:"flags"},eritrea:{keywords:["er","flag","nation","country","banner"],char:'🇪🇷',fitzpatrick_scale:false,category:"flags"},estonia:{keywords:["ee","flag","nation","country","banner"],char:'🇪🇪',fitzpatrick_scale:false,category:"flags"},ethiopia:{keywords:["et","flag","nation","country","banner"],char:'🇪🇹',fitzpatrick_scale:false,category:"flags"},eu:{keywords:["european","union","flag","banner"],char:'🇪🇺',fitzpatrick_scale:false,category:"flags"},falkland_islands:{keywords:["falkland","islands","malvinas","flag","nation","country","banner"],char:'🇫🇰',fitzpatrick_scale:false,category:"flags"},faroe_islands:{keywords:["faroe","islands","flag","nation","country","banner"],char:'🇫🇴',fitzpatrick_scale:false,category:"flags"},fiji:{keywords:["fj","flag","nation","country","banner"],char:'🇫🇯',fitzpatrick_scale:false,category:"flags"},finland:{keywords:["fi","flag","nation","country","banner"],char:'🇫🇮',fitzpatrick_scale:false,category:"flags"},fr:{keywords:["banner","flag","nation","france","french","country"],char:'🇫🇷',fitzpatrick_scale:false,category:"flags"},french_guiana:{keywords:["french","guiana","flag","nation","country","banner"],char:'🇬🇫',fitzpatrick_scale:false,category:"flags"},french_polynesia:{keywords:["french","polynesia","flag","nation","country","banner"],char:'🇵🇫',fitzpatrick_scale:false,category:"flags"},french_southern_territories:{keywords:["french","southern","territories","flag","nation","country","banner"],char:'🇹🇫',fitzpatrick_scale:false,category:"flags"},gabon:{keywords:["ga","flag","nation","country","banner"],char:'🇬🇦',fitzpatrick_scale:false,category:"flags"},gambia:{keywords:["gm","flag","nation","country","banner"],char:'🇬🇲',fitzpatrick_scale:false,category:"flags"},georgia:{keywords:["ge","flag","nation","country","banner"],char:'🇬🇪',fitzpatrick_scale:false,category:"flags"},de:{keywords:["german","nation","flag","country","banner"],char:'🇩🇪',fitzpatrick_scale:false,category:"flags"},ghana:{keywords:["gh","flag","nation","country","banner"],char:'🇬🇭',fitzpatrick_scale:false,category:"flags"},gibraltar:{keywords:["gi","flag","nation","country","banner"],char:'🇬🇮',fitzpatrick_scale:false,category:"flags"},greece:{keywords:["gr","flag","nation","country","banner"],char:'🇬🇷',fitzpatrick_scale:false,category:"flags"},greenland:{keywords:["gl","flag","nation","country","banner"],char:'🇬🇱',fitzpatrick_scale:false,category:"flags"},grenada:{keywords:["gd","flag","nation","country","banner"],char:'🇬🇩',fitzpatrick_scale:false,category:"flags"},guadeloupe:{keywords:["gp","flag","nation","country","banner"],char:'🇬🇵',fitzpatrick_scale:false,category:"flags"},guam:{keywords:["gu","flag","nation","country","banner"],char:'🇬🇺',fitzpatrick_scale:false,category:"flags"},guatemala:{keywords:["gt","flag","nation","country","banner"],char:'🇬🇹',fitzpatrick_scale:false,category:"flags"},guernsey:{keywords:["gg","flag","nation","country","banner"],char:'🇬🇬',fitzpatrick_scale:false,category:"flags"},guinea:{keywords:["gn","flag","nation","country","banner"],char:'🇬🇳',fitzpatrick_scale:false,category:"flags"},guinea_bissau:{keywords:["gw","bissau","flag","nation","country","banner"],char:'🇬🇼',fitzpatrick_scale:false,category:"flags"},guyana:{keywords:["gy","flag","nation","country","banner"],char:'🇬🇾',fitzpatrick_scale:false,category:"flags"},haiti:{keywords:["ht","flag","nation","country","banner"],char:'🇭🇹',fitzpatrick_scale:false,category:"flags"},honduras:{keywords:["hn","flag","nation","country","banner"],char:'🇭🇳',fitzpatrick_scale:false,category:"flags"},hong_kong:{keywords:["hong","kong","flag","nation","country","banner"],char:'🇭🇰',fitzpatrick_scale:false,category:"flags"},hungary:{keywords:["hu","flag","nation","country","banner"],char:'🇭🇺',fitzpatrick_scale:false,category:"flags"},iceland:{keywords:["is","flag","nation","country","banner"],char:'🇮🇸',fitzpatrick_scale:false,category:"flags"},india:{keywords:["in","flag","nation","country","banner"],char:'🇮🇳',fitzpatrick_scale:false,category:"flags"},indonesia:{keywords:["flag","nation","country","banner"],char:'🇮🇩',fitzpatrick_scale:false,category:"flags"},iran:{keywords:["iran,","islamic","republic","flag","nation","country","banner"],char:'🇮🇷',fitzpatrick_scale:false,category:"flags"},iraq:{keywords:["iq","flag","nation","country","banner"],char:'🇮🇶',fitzpatrick_scale:false,category:"flags"},ireland:{keywords:["ie","flag","nation","country","banner"],char:'🇮🇪',fitzpatrick_scale:false,category:"flags"},isle_of_man:{keywords:["isle","man","flag","nation","country","banner"],char:'🇮🇲',fitzpatrick_scale:false,category:"flags"},israel:{keywords:["il","flag","nation","country","banner"],char:'🇮🇱',fitzpatrick_scale:false,category:"flags"},it:{keywords:["italy","flag","nation","country","banner"],char:'🇮🇹',fitzpatrick_scale:false,category:"flags"},cote_divoire:{keywords:["ivory","coast","flag","nation","country","banner"],char:'🇨🇮',fitzpatrick_scale:false,category:"flags"},jamaica:{keywords:["jm","flag","nation","country","banner"],char:'🇯🇲',fitzpatrick_scale:false,category:"flags"},jp:{keywords:["japanese","nation","flag","country","banner"],char:'🇯🇵',fitzpatrick_scale:false,category:"flags"},jersey:{keywords:["je","flag","nation","country","banner"],char:'🇯🇪',fitzpatrick_scale:false,category:"flags"},jordan:{keywords:["jo","flag","nation","country","banner"],char:'🇯🇴',fitzpatrick_scale:false,category:"flags"},kazakhstan:{keywords:["kz","flag","nation","country","banner"],char:'🇰🇿',fitzpatrick_scale:false,category:"flags"},kenya:{keywords:["ke","flag","nation","country","banner"],char:'🇰🇪',fitzpatrick_scale:false,category:"flags"},kiribati:{keywords:["ki","flag","nation","country","banner"],char:'🇰🇮',fitzpatrick_scale:false,category:"flags"},kosovo:{keywords:["xk","flag","nation","country","banner"],char:'🇽🇰',fitzpatrick_scale:false,category:"flags"},kuwait:{keywords:["kw","flag","nation","country","banner"],char:'🇰🇼',fitzpatrick_scale:false,category:"flags"},kyrgyzstan:{keywords:["kg","flag","nation","country","banner"],char:'🇰🇬',fitzpatrick_scale:false,category:"flags"},laos:{keywords:["lao","democratic","republic","flag","nation","country","banner"],char:'🇱🇦',fitzpatrick_scale:false,category:"flags"},latvia:{keywords:["lv","flag","nation","country","banner"],char:'🇱🇻',fitzpatrick_scale:false,category:"flags"},lebanon:{keywords:["lb","flag","nation","country","banner"],char:'🇱🇧',fitzpatrick_scale:false,category:"flags"},lesotho:{keywords:["ls","flag","nation","country","banner"],char:'🇱🇸',fitzpatrick_scale:false,category:"flags"},liberia:{keywords:["lr","flag","nation","country","banner"],char:'🇱🇷',fitzpatrick_scale:false,category:"flags"},libya:{keywords:["ly","flag","nation","country","banner"],char:'🇱🇾',fitzpatrick_scale:false,category:"flags"},liechtenstein:{keywords:["li","flag","nation","country","banner"],char:'🇱🇮',fitzpatrick_scale:false,category:"flags"},lithuania:{keywords:["lt","flag","nation","country","banner"],char:'🇱🇹',fitzpatrick_scale:false,category:"flags"},luxembourg:{keywords:["lu","flag","nation","country","banner"],char:'🇱🇺',fitzpatrick_scale:false,category:"flags"},macau:{keywords:["macao","flag","nation","country","banner"],char:'🇲🇴',fitzpatrick_scale:false,category:"flags"},macedonia:{keywords:["macedonia,","flag","nation","country","banner"],char:'🇲🇰',fitzpatrick_scale:false,category:"flags"},madagascar:{keywords:["mg","flag","nation","country","banner"],char:'🇲🇬',fitzpatrick_scale:false,category:"flags"},malawi:{keywords:["mw","flag","nation","country","banner"],char:'🇲🇼',fitzpatrick_scale:false,category:"flags"},malaysia:{keywords:["my","flag","nation","country","banner"],char:'🇲🇾',fitzpatrick_scale:false,category:"flags"},maldives:{keywords:["mv","flag","nation","country","banner"],char:'🇲🇻',fitzpatrick_scale:false,category:"flags"},mali:{keywords:["ml","flag","nation","country","banner"],char:'🇲🇱',fitzpatrick_scale:false,category:"flags"},malta:{keywords:["mt","flag","nation","country","banner"],char:'🇲🇹',fitzpatrick_scale:false,category:"flags"},marshall_islands:{keywords:["marshall","islands","flag","nation","country","banner"],char:'🇲🇭',fitzpatrick_scale:false,category:"flags"},martinique:{keywords:["mq","flag","nation","country","banner"],char:'🇲🇶',fitzpatrick_scale:false,category:"flags"},mauritania:{keywords:["mr","flag","nation","country","banner"],char:'🇲🇷',fitzpatrick_scale:false,category:"flags"},mauritius:{keywords:["mu","flag","nation","country","banner"],char:'🇲🇺',fitzpatrick_scale:false,category:"flags"},mayotte:{keywords:["yt","flag","nation","country","banner"],char:'🇾🇹',fitzpatrick_scale:false,category:"flags"},mexico:{keywords:["mx","flag","nation","country","banner"],char:'🇲🇽',fitzpatrick_scale:false,category:"flags"},micronesia:{keywords:["micronesia,","federated","states","flag","nation","country","banner"],char:'🇫🇲',fitzpatrick_scale:false,category:"flags"},moldova:{keywords:["moldova,","republic","flag","nation","country","banner"],char:'🇲🇩',fitzpatrick_scale:false,category:"flags"},monaco:{keywords:["mc","flag","nation","country","banner"],char:'🇲🇨',fitzpatrick_scale:false,category:"flags"},mongolia:{keywords:["mn","flag","nation","country","banner"],char:'🇲🇳',fitzpatrick_scale:false,category:"flags"},montenegro:{keywords:["me","flag","nation","country","banner"],char:'🇲🇪',fitzpatrick_scale:false,category:"flags"},montserrat:{keywords:["ms","flag","nation","country","banner"],char:'🇲🇸',fitzpatrick_scale:false,category:"flags"},morocco:{keywords:["ma","flag","nation","country","banner"],char:'🇲🇦',fitzpatrick_scale:false,category:"flags"},mozambique:{keywords:["mz","flag","nation","country","banner"],char:'🇲🇿',fitzpatrick_scale:false,category:"flags"},myanmar:{keywords:["mm","flag","nation","country","banner"],char:'🇲🇲',fitzpatrick_scale:false,category:"flags"},namibia:{keywords:["na","flag","nation","country","banner"],char:'🇳🇦',fitzpatrick_scale:false,category:"flags"},nauru:{keywords:["nr","flag","nation","country","banner"],char:'🇳🇷',fitzpatrick_scale:false,category:"flags"},nepal:{keywords:["np","flag","nation","country","banner"],char:'🇳🇵',fitzpatrick_scale:false,category:"flags"},netherlands:{keywords:["nl","flag","nation","country","banner"],char:'🇳🇱',fitzpatrick_scale:false,category:"flags"},new_caledonia:{keywords:["new","caledonia","flag","nation","country","banner"],char:'🇳🇨',fitzpatrick_scale:false,category:"flags"},new_zealand:{keywords:["new","zealand","flag","nation","country","banner"],char:'🇳🇿',fitzpatrick_scale:false,category:"flags"},nicaragua:{keywords:["ni","flag","nation","country","banner"],char:'🇳🇮',fitzpatrick_scale:false,category:"flags"},niger:{keywords:["ne","flag","nation","country","banner"],char:'🇳🇪',fitzpatrick_scale:false,category:"flags"},nigeria:{keywords:["flag","nation","country","banner"],char:'🇳🇬',fitzpatrick_scale:false,category:"flags"},niue:{keywords:["nu","flag","nation","country","banner"],char:'🇳🇺',fitzpatrick_scale:false,category:"flags"},norfolk_island:{keywords:["norfolk","island","flag","nation","country","banner"],char:'🇳🇫',fitzpatrick_scale:false,category:"flags"},northern_mariana_islands:{keywords:["northern","mariana","islands","flag","nation","country","banner"],char:'🇲🇵',fitzpatrick_scale:false,category:"flags"},north_korea:{keywords:["north","korea","nation","flag","country","banner"],char:'🇰🇵',fitzpatrick_scale:false,category:"flags"},norway:{keywords:["no","flag","nation","country","banner"],char:'🇳🇴',fitzpatrick_scale:false,category:"flags"},oman:{keywords:["om_symbol","flag","nation","country","banner"],char:'🇴🇲',fitzpatrick_scale:false,category:"flags"},pakistan:{keywords:["pk","flag","nation","country","banner"],char:'🇵🇰',fitzpatrick_scale:false,category:"flags"},palau:{keywords:["pw","flag","nation","country","banner"],char:'🇵🇼',fitzpatrick_scale:false,category:"flags"},palestinian_territories:{keywords:["palestine","palestinian","territories","flag","nation","country","banner"],char:'🇵🇸',fitzpatrick_scale:false,category:"flags"},panama:{keywords:["pa","flag","nation","country","banner"],char:'🇵🇦',fitzpatrick_scale:false,category:"flags"},papua_new_guinea:{keywords:["papua","new","guinea","flag","nation","country","banner"],char:'🇵🇬',fitzpatrick_scale:false,category:"flags"},paraguay:{keywords:["py","flag","nation","country","banner"],char:'🇵🇾',fitzpatrick_scale:false,category:"flags"},peru:{keywords:["pe","flag","nation","country","banner"],char:'🇵🇪',fitzpatrick_scale:false,category:"flags"},philippines:{keywords:["ph","flag","nation","country","banner"],char:'🇵🇭',fitzpatrick_scale:false,category:"flags"},pitcairn_islands:{keywords:["pitcairn","flag","nation","country","banner"],char:'🇵🇳',fitzpatrick_scale:false,category:"flags"},poland:{keywords:["pl","flag","nation","country","banner"],char:'🇵🇱',fitzpatrick_scale:false,category:"flags"},portugal:{keywords:["pt","flag","nation","country","banner"],char:'🇵🇹',fitzpatrick_scale:false,category:"flags"},puerto_rico:{keywords:["puerto","rico","flag","nation","country","banner"],char:'🇵🇷',fitzpatrick_scale:false,category:"flags"},qatar:{keywords:["qa","flag","nation","country","banner"],char:'🇶🇦',fitzpatrick_scale:false,category:"flags"},reunion:{keywords:["réunion","flag","nation","country","banner"],char:'🇷🇪',fitzpatrick_scale:false,category:"flags"},romania:{keywords:["ro","flag","nation","country","banner"],char:'🇷🇴',fitzpatrick_scale:false,category:"flags"},ru:{keywords:["russian","federation","flag","nation","country","banner"],char:'🇷🇺',fitzpatrick_scale:false,category:"flags"},rwanda:{keywords:["rw","flag","nation","country","banner"],char:'🇷🇼',fitzpatrick_scale:false,category:"flags"},st_barthelemy:{keywords:["saint","barthélemy","flag","nation","country","banner"],char:'🇧🇱',fitzpatrick_scale:false,category:"flags"},st_helena:{keywords:["saint","helena","ascension","tristan","cunha","flag","nation","country","banner"],char:'🇸🇭',fitzpatrick_scale:false,category:"flags"},st_kitts_nevis:{keywords:["saint","kitts","nevis","flag","nation","country","banner"],char:'🇰🇳',fitzpatrick_scale:false,category:"flags"},st_lucia:{keywords:["saint","lucia","flag","nation","country","banner"],char:'🇱🇨',fitzpatrick_scale:false,category:"flags"},st_pierre_miquelon:{keywords:["saint","pierre","miquelon","flag","nation","country","banner"],char:'🇵🇲',fitzpatrick_scale:false,category:"flags"},st_vincent_grenadines:{keywords:["saint","vincent","grenadines","flag","nation","country","banner"],char:'🇻🇨',fitzpatrick_scale:false,category:"flags"},samoa:{keywords:["ws","flag","nation","country","banner"],char:'🇼🇸',fitzpatrick_scale:false,category:"flags"},san_marino:{keywords:["san","marino","flag","nation","country","banner"],char:'🇸🇲',fitzpatrick_scale:false,category:"flags"},sao_tome_principe:{keywords:["sao","tome","principe","flag","nation","country","banner"],char:'🇸🇹',fitzpatrick_scale:false,category:"flags"},saudi_arabia:{keywords:["flag","nation","country","banner"],char:'🇸🇦',fitzpatrick_scale:false,category:"flags"},senegal:{keywords:["sn","flag","nation","country","banner"],char:'🇸🇳',fitzpatrick_scale:false,category:"flags"},serbia:{keywords:["rs","flag","nation","country","banner"],char:'🇷🇸',fitzpatrick_scale:false,category:"flags"},seychelles:{keywords:["sc","flag","nation","country","banner"],char:'🇸🇨',fitzpatrick_scale:false,category:"flags"},sierra_leone:{keywords:["sierra","leone","flag","nation","country","banner"],char:'🇸🇱',fitzpatrick_scale:false,category:"flags"},singapore:{keywords:["sg","flag","nation","country","banner"],char:'🇸🇬',fitzpatrick_scale:false,category:"flags"},sint_maarten:{keywords:["sint","maarten","dutch","flag","nation","country","banner"],char:'🇸🇽',fitzpatrick_scale:false,category:"flags"},slovakia:{keywords:["sk","flag","nation","country","banner"],char:'🇸🇰',fitzpatrick_scale:false,category:"flags"},slovenia:{keywords:["si","flag","nation","country","banner"],char:'🇸🇮',fitzpatrick_scale:false,category:"flags"},solomon_islands:{keywords:["solomon","islands","flag","nation","country","banner"],char:'🇸🇧',fitzpatrick_scale:false,category:"flags"},somalia:{keywords:["so","flag","nation","country","banner"],char:'🇸🇴',fitzpatrick_scale:false,category:"flags"},south_africa:{keywords:["south","africa","flag","nation","country","banner"],char:'🇿🇦',fitzpatrick_scale:false,category:"flags"},south_georgia_south_sandwich_islands:{keywords:["south","georgia","sandwich","islands","flag","nation","country","banner"],char:'🇬🇸',fitzpatrick_scale:false,category:"flags"},kr:{keywords:["south","korea","nation","flag","country","banner"],char:'🇰🇷',fitzpatrick_scale:false,category:"flags"},south_sudan:{keywords:["south","sd","flag","nation","country","banner"],char:'🇸🇸',fitzpatrick_scale:false,category:"flags"},es:{keywords:["spain","flag","nation","country","banner"],char:'🇪🇸',fitzpatrick_scale:false,category:"flags"},sri_lanka:{keywords:["sri","lanka","flag","nation","country","banner"],char:'🇱🇰',fitzpatrick_scale:false,category:"flags"},sudan:{keywords:["sd","flag","nation","country","banner"],char:'🇸🇩',fitzpatrick_scale:false,category:"flags"},suriname:{keywords:["sr","flag","nation","country","banner"],char:'🇸🇷',fitzpatrick_scale:false,category:"flags"},swaziland:{keywords:["sz","flag","nation","country","banner"],char:'🇸🇿',fitzpatrick_scale:false,category:"flags"},sweden:{keywords:["se","flag","nation","country","banner"],char:'🇸🇪',fitzpatrick_scale:false,category:"flags"},switzerland:{keywords:["ch","flag","nation","country","banner"],char:'🇨🇭',fitzpatrick_scale:false,category:"flags"},syria:{keywords:["syrian","arab","republic","flag","nation","country","banner"],char:'🇸🇾',fitzpatrick_scale:false,category:"flags"},taiwan:{keywords:["tw","flag","nation","country","banner"],char:'🇹🇼',fitzpatrick_scale:false,category:"flags"},tajikistan:{keywords:["tj","flag","nation","country","banner"],char:'🇹🇯',fitzpatrick_scale:false,category:"flags"},tanzania:{keywords:["tanzania,","united","republic","flag","nation","country","banner"],char:'🇹🇿',fitzpatrick_scale:false,category:"flags"},thailand:{keywords:["th","flag","nation","country","banner"],char:'🇹🇭',fitzpatrick_scale:false,category:"flags"},timor_leste:{keywords:["timor","leste","flag","nation","country","banner"],char:'🇹🇱',fitzpatrick_scale:false,category:"flags"},togo:{keywords:["tg","flag","nation","country","banner"],char:'🇹🇬',fitzpatrick_scale:false,category:"flags"},tokelau:{keywords:["tk","flag","nation","country","banner"],char:'🇹🇰',fitzpatrick_scale:false,category:"flags"},tonga:{keywords:["to","flag","nation","country","banner"],char:'🇹🇴',fitzpatrick_scale:false,category:"flags"},trinidad_tobago:{keywords:["trinidad","tobago","flag","nation","country","banner"],char:'🇹🇹',fitzpatrick_scale:false,category:"flags"},tunisia:{keywords:["tn","flag","nation","country","banner"],char:'🇹🇳',fitzpatrick_scale:false,category:"flags"},tr:{keywords:["turkey","flag","nation","country","banner"],char:'🇹🇷',fitzpatrick_scale:false,category:"flags"},turkmenistan:{keywords:["flag","nation","country","banner"],char:'🇹🇲',fitzpatrick_scale:false,category:"flags"},turks_caicos_islands:{keywords:["turks","caicos","islands","flag","nation","country","banner"],char:'🇹🇨',fitzpatrick_scale:false,category:"flags"},tuvalu:{keywords:["flag","nation","country","banner"],char:'🇹🇻',fitzpatrick_scale:false,category:"flags"},uganda:{keywords:["ug","flag","nation","country","banner"],char:'🇺🇬',fitzpatrick_scale:false,category:"flags"},ukraine:{keywords:["ua","flag","nation","country","banner"],char:'🇺🇦',fitzpatrick_scale:false,category:"flags"},united_arab_emirates:{keywords:["united","arab","emirates","flag","nation","country","banner"],char:'🇦🇪',fitzpatrick_scale:false,category:"flags"},uk:{keywords:["united","kingdom","great","britain","northern","ireland","flag","nation","country","banner","british","UK","english","england","union jack"],char:'🇬🇧',fitzpatrick_scale:false,category:"flags"},england:{keywords:["flag","english"],char:'🏴󠁧󠁢󠁥󠁮󠁧󠁿',fitzpatrick_scale:false,category:"flags"},scotland:{keywords:["flag","scottish"],char:'🏴󠁧󠁢󠁳󠁣󠁴󠁿',fitzpatrick_scale:false,category:"flags"},wales:{keywords:["flag","welsh"],char:'🏴󠁧󠁢󠁷󠁬󠁳󠁿',fitzpatrick_scale:false,category:"flags"},us:{keywords:["united","states","america","flag","nation","country","banner"],char:'🇺🇸',fitzpatrick_scale:false,category:"flags"},us_virgin_islands:{keywords:["virgin","islands","us","flag","nation","country","banner"],char:'🇻🇮',fitzpatrick_scale:false,category:"flags"},uruguay:{keywords:["uy","flag","nation","country","banner"],char:'🇺🇾',fitzpatrick_scale:false,category:"flags"},uzbekistan:{keywords:["uz","flag","nation","country","banner"],char:'🇺🇿',fitzpatrick_scale:false,category:"flags"},vanuatu:{keywords:["vu","flag","nation","country","banner"],char:'🇻🇺',fitzpatrick_scale:false,category:"flags"},vatican_city:{keywords:["vatican","city","flag","nation","country","banner"],char:'🇻🇦',fitzpatrick_scale:false,category:"flags"},venezuela:{keywords:["ve","bolivarian","republic","flag","nation","country","banner"],char:'🇻🇪',fitzpatrick_scale:false,category:"flags"},vietnam:{keywords:["viet","nam","flag","nation","country","banner"],char:'🇻🇳',fitzpatrick_scale:false,category:"flags"},wallis_futuna:{keywords:["wallis","futuna","flag","nation","country","banner"],char:'🇼🇫',fitzpatrick_scale:false,category:"flags"},western_sahara:{keywords:["western","sahara","flag","nation","country","banner"],char:'🇪🇭',fitzpatrick_scale:false,category:"flags"},yemen:{keywords:["ye","flag","nation","country","banner"],char:'🇾🇪',fitzpatrick_scale:false,category:"flags"},zambia:{keywords:["zm","flag","nation","country","banner"],char:'🇿🇲',fitzpatrick_scale:false,category:"flags"},zimbabwe:{keywords:["zw","flag","nation","country","banner"],char:'🇿🇼',fitzpatrick_scale:false,category:"flags"},united_nations:{keywords:["un","flag","banner"],char:'🇺🇳',fitzpatrick_scale:false,category:"flags"},pirate_flag:{keywords:["skull","crossbones","flag","banner"],char:'🏴‍☠️',fitzpatrick_scale:false,category:"flags"}}); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/emoticons/js/emojiimages.min.js b/apps/web-antd/public/tinymce/plugins/emoticons/js/emojiimages.min.js new file mode 100644 index 0000000..37f3bcf --- /dev/null +++ b/apps/web-antd/public/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:'\u{1f4af}',fitzpatrick_scale:!1,category:"symbols"},1234:{keywords:["numbers","blue-square"],char:'\u{1f522}',fitzpatrick_scale:!1,category:"symbols"},grinning:{keywords:["face","smile","happy","joy",":D","grin"],char:'\u{1f600}',fitzpatrick_scale:!1,category:"people"},grimacing:{keywords:["face","grimace","teeth"],char:'\u{1f62c}',fitzpatrick_scale:!1,category:"people"},grin:{keywords:["face","happy","smile","joy","kawaii"],char:'\u{1f601}',fitzpatrick_scale:!1,category:"people"},joy:{keywords:["face","cry","tears","weep","happy","happytears","haha"],char:'\u{1f602}',fitzpatrick_scale:!1,category:"people"},rofl:{keywords:["face","rolling","floor","laughing","lol","haha"],char:'\u{1f923}',fitzpatrick_scale:!1,category:"people"},partying:{keywords:["face","celebration","woohoo"],char:'\u{1f973}',fitzpatrick_scale:!1,category:"people"},smiley:{keywords:["face","happy","joy","haha",":D",":)","smile","funny"],char:'\u{1f603}',fitzpatrick_scale:!1,category:"people"},smile:{keywords:["face","happy","joy","funny","haha","laugh","like",":D",":)"],char:'\u{1f604}',fitzpatrick_scale:!1,category:"people"},sweat_smile:{keywords:["face","hot","happy","laugh","sweat","smile","relief"],char:'\u{1f605}',fitzpatrick_scale:!1,category:"people"},laughing:{keywords:["happy","joy","lol","satisfied","haha","face","glad","XD","laugh"],char:'\u{1f606}',fitzpatrick_scale:!1,category:"people"},innocent:{keywords:["face","angel","heaven","halo"],char:'\u{1f607}',fitzpatrick_scale:!1,category:"people"},wink:{keywords:["face","happy","mischievous","secret",";)","smile","eye"],char:'\u{1f609}',fitzpatrick_scale:!1,category:"people"},blush:{keywords:["face","smile","happy","flushed","crush","embarrassed","shy","joy"],char:'\u{1f60a}',fitzpatrick_scale:!1,category:"people"},slightly_smiling_face:{keywords:["face","smile"],char:'\u{1f642}',fitzpatrick_scale:!1,category:"people"},upside_down_face:{keywords:["face","flipped","silly","smile"],char:'\u{1f643}',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:'\u{1f60b}',fitzpatrick_scale:!1,category:"people"},relieved:{keywords:["face","relaxed","phew","massage","happiness"],char:'\u{1f60c}',fitzpatrick_scale:!1,category:"people"},heart_eyes:{keywords:["face","love","like","affection","valentines","infatuation","crush","heart"],char:'\u{1f60d}',fitzpatrick_scale:!1,category:"people"},smiling_face_with_three_hearts:{keywords:["face","love","like","affection","valentines","infatuation","crush","hearts","adore"],char:'\u{1f970}',fitzpatrick_scale:!1,category:"people"},kissing_heart:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:'\u{1f618}',fitzpatrick_scale:!1,category:"people"},kissing:{keywords:["love","like","face","3","valentines","infatuation","kiss"],char:'\u{1f617}',fitzpatrick_scale:!1,category:"people"},kissing_smiling_eyes:{keywords:["face","affection","valentines","infatuation","kiss"],char:'\u{1f619}',fitzpatrick_scale:!1,category:"people"},kissing_closed_eyes:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:'\u{1f61a}',fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_winking_eye:{keywords:["face","prank","childish","playful","mischievous","smile","wink","tongue"],char:'\u{1f61c}',fitzpatrick_scale:!1,category:"people"},zany:{keywords:["face","goofy","crazy"],char:'\u{1f92a}',fitzpatrick_scale:!1,category:"people"},raised_eyebrow:{keywords:["face","distrust","scepticism","disapproval","disbelief","surprise"],char:'\u{1f928}',fitzpatrick_scale:!1,category:"people"},monocle:{keywords:["face","stuffy","wealthy"],char:'\u{1f9d0}',fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_closed_eyes:{keywords:["face","prank","playful","mischievous","smile","tongue"],char:'\u{1f61d}',fitzpatrick_scale:!1,category:"people"},stuck_out_tongue:{keywords:["face","prank","childish","playful","mischievous","smile","tongue"],char:'\u{1f61b}',fitzpatrick_scale:!1,category:"people"},money_mouth_face:{keywords:["face","rich","dollar","money"],char:'\u{1f911}',fitzpatrick_scale:!1,category:"people"},nerd_face:{keywords:["face","nerdy","geek","dork"],char:'\u{1f913}',fitzpatrick_scale:!1,category:"people"},sunglasses:{keywords:["face","cool","smile","summer","beach","sunglass"],char:'\u{1f60e}',fitzpatrick_scale:!1,category:"people"},star_struck:{keywords:["face","smile","starry","eyes","grinning"],char:'\u{1f929}',fitzpatrick_scale:!1,category:"people"},clown_face:{keywords:["face"],char:'\u{1f921}',fitzpatrick_scale:!1,category:"people"},cowboy_hat_face:{keywords:["face","cowgirl","hat"],char:'\u{1f920}',fitzpatrick_scale:!1,category:"people"},hugs:{keywords:["face","smile","hug"],char:'\u{1f917}',fitzpatrick_scale:!1,category:"people"},smirk:{keywords:["face","smile","mean","prank","smug","sarcasm"],char:'\u{1f60f}',fitzpatrick_scale:!1,category:"people"},no_mouth:{keywords:["face","hellokitty"],char:'\u{1f636}',fitzpatrick_scale:!1,category:"people"},neutral_face:{keywords:["indifference","meh",":|","neutral"],char:'\u{1f610}',fitzpatrick_scale:!1,category:"people"},expressionless:{keywords:["face","indifferent","-_-","meh","deadpan"],char:'\u{1f611}',fitzpatrick_scale:!1,category:"people"},unamused:{keywords:["indifference","bored","straight face","serious","sarcasm","unimpressed","skeptical","dubious","side_eye"],char:'\u{1f612}',fitzpatrick_scale:!1,category:"people"},roll_eyes:{keywords:["face","eyeroll","frustrated"],char:'\u{1f644}',fitzpatrick_scale:!1,category:"people"},thinking:{keywords:["face","hmmm","think","consider"],char:'\u{1f914}',fitzpatrick_scale:!1,category:"people"},lying_face:{keywords:["face","lie","pinocchio"],char:'\u{1f925}',fitzpatrick_scale:!1,category:"people"},hand_over_mouth:{keywords:["face","whoops","shock","surprise"],char:'\u{1f92d}',fitzpatrick_scale:!1,category:"people"},shushing:{keywords:["face","quiet","shhh"],char:'\u{1f92b}',fitzpatrick_scale:!1,category:"people"},symbols_over_mouth:{keywords:["face","swearing","cursing","cussing","profanity","expletive"],char:'\u{1f92c}',fitzpatrick_scale:!1,category:"people"},exploding_head:{keywords:["face","shocked","mind","blown"],char:'\u{1f92f}',fitzpatrick_scale:!1,category:"people"},flushed:{keywords:["face","blush","shy","flattered"],char:'\u{1f633}',fitzpatrick_scale:!1,category:"people"},disappointed:{keywords:["face","sad","upset","depressed",":("],char:'\u{1f61e}',fitzpatrick_scale:!1,category:"people"},worried:{keywords:["face","concern","nervous",":("],char:'\u{1f61f}',fitzpatrick_scale:!1,category:"people"},angry:{keywords:["mad","face","annoyed","frustrated"],char:'\u{1f620}',fitzpatrick_scale:!1,category:"people"},rage:{keywords:["angry","mad","hate","despise"],char:'\u{1f621}',fitzpatrick_scale:!1,category:"people"},pensive:{keywords:["face","sad","depressed","upset"],char:'\u{1f614}',fitzpatrick_scale:!1,category:"people"},confused:{keywords:["face","indifference","huh","weird","hmmm",":/"],char:'\u{1f615}',fitzpatrick_scale:!1,category:"people"},slightly_frowning_face:{keywords:["face","frowning","disappointed","sad","upset"],char:'\u{1f641}',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:'\u{1f623}',fitzpatrick_scale:!1,category:"people"},confounded:{keywords:["face","confused","sick","unwell","oops",":S"],char:'\u{1f616}',fitzpatrick_scale:!1,category:"people"},tired_face:{keywords:["sick","whine","upset","frustrated"],char:'\u{1f62b}',fitzpatrick_scale:!1,category:"people"},weary:{keywords:["face","tired","sleepy","sad","frustrated","upset"],char:'\u{1f629}',fitzpatrick_scale:!1,category:"people"},pleading:{keywords:["face","begging","mercy"],char:'\u{1f97a}',fitzpatrick_scale:!1,category:"people"},triumph:{keywords:["face","gas","phew","proud","pride"],char:'\u{1f624}',fitzpatrick_scale:!1,category:"people"},open_mouth:{keywords:["face","surprise","impressed","wow","whoa",":O"],char:'\u{1f62e}',fitzpatrick_scale:!1,category:"people"},scream:{keywords:["face","munch","scared","omg"],char:'\u{1f631}',fitzpatrick_scale:!1,category:"people"},fearful:{keywords:["face","scared","terrified","nervous","oops","huh"],char:'\u{1f628}',fitzpatrick_scale:!1,category:"people"},cold_sweat:{keywords:["face","nervous","sweat"],char:'\u{1f630}',fitzpatrick_scale:!1,category:"people"},hushed:{keywords:["face","woo","shh"],char:'\u{1f62f}',fitzpatrick_scale:!1,category:"people"},frowning:{keywords:["face","aw","what"],char:'\u{1f626}',fitzpatrick_scale:!1,category:"people"},anguished:{keywords:["face","stunned","nervous"],char:'\u{1f627}',fitzpatrick_scale:!1,category:"people"},cry:{keywords:["face","tears","sad","depressed","upset",":'("],char:'\u{1f622}',fitzpatrick_scale:!1,category:"people"},disappointed_relieved:{keywords:["face","phew","sweat","nervous"],char:'\u{1f625}',fitzpatrick_scale:!1,category:"people"},drooling_face:{keywords:["face"],char:'\u{1f924}',fitzpatrick_scale:!1,category:"people"},sleepy:{keywords:["face","tired","rest","nap"],char:'\u{1f62a}',fitzpatrick_scale:!1,category:"people"},sweat:{keywords:["face","hot","sad","tired","exercise"],char:'\u{1f613}',fitzpatrick_scale:!1,category:"people"},hot:{keywords:["face","feverish","heat","red","sweating"],char:'\u{1f975}',fitzpatrick_scale:!1,category:"people"},cold:{keywords:["face","blue","freezing","frozen","frostbite","icicles"],char:'\u{1f976}',fitzpatrick_scale:!1,category:"people"},sob:{keywords:["face","cry","tears","sad","upset","depressed"],char:'\u{1f62d}',fitzpatrick_scale:!1,category:"people"},dizzy_face:{keywords:["spent","unconscious","xox","dizzy"],char:'\u{1f635}',fitzpatrick_scale:!1,category:"people"},astonished:{keywords:["face","xox","surprised","poisoned"],char:'\u{1f632}',fitzpatrick_scale:!1,category:"people"},zipper_mouth_face:{keywords:["face","sealed","zipper","secret"],char:'\u{1f910}',fitzpatrick_scale:!1,category:"people"},nauseated_face:{keywords:["face","vomit","gross","green","sick","throw up","ill"],char:'\u{1f922}',fitzpatrick_scale:!1,category:"people"},sneezing_face:{keywords:["face","gesundheit","sneeze","sick","allergy"],char:'\u{1f927}',fitzpatrick_scale:!1,category:"people"},vomiting:{keywords:["face","sick"],char:'\u{1f92e}',fitzpatrick_scale:!1,category:"people"},mask:{keywords:["face","sick","ill","disease"],char:'\u{1f637}',fitzpatrick_scale:!1,category:"people"},face_with_thermometer:{keywords:["sick","temperature","thermometer","cold","fever"],char:'\u{1f912}',fitzpatrick_scale:!1,category:"people"},face_with_head_bandage:{keywords:["injured","clumsy","bandage","hurt"],char:'\u{1f915}',fitzpatrick_scale:!1,category:"people"},woozy:{keywords:["face","dizzy","intoxicated","tipsy","wavy"],char:'\u{1f974}',fitzpatrick_scale:!1,category:"people"},sleeping:{keywords:["face","tired","sleepy","night","zzz"],char:'\u{1f634}',fitzpatrick_scale:!1,category:"people"},zzz:{keywords:["sleepy","tired","dream"],char:'\u{1f4a4}',fitzpatrick_scale:!1,category:"people"},poop:{keywords:["hankey","shitface","fail","turd","shit"],char:'\u{1f4a9}',fitzpatrick_scale:!1,category:"people"},smiling_imp:{keywords:["devil","horns"],char:'\u{1f608}',fitzpatrick_scale:!1,category:"people"},imp:{keywords:["devil","angry","horns"],char:'\u{1f47f}',fitzpatrick_scale:!1,category:"people"},japanese_ogre:{keywords:["monster","red","mask","halloween","scary","creepy","devil","demon","japanese","ogre"],char:'\u{1f479}',fitzpatrick_scale:!1,category:"people"},japanese_goblin:{keywords:["red","evil","mask","monster","scary","creepy","japanese","goblin"],char:'\u{1f47a}',fitzpatrick_scale:!1,category:"people"},skull:{keywords:["dead","skeleton","creepy","death"],char:'\u{1f480}',fitzpatrick_scale:!1,category:"people"},ghost:{keywords:["halloween","spooky","scary"],char:'\u{1f47b}',fitzpatrick_scale:!1,category:"people"},alien:{keywords:["UFO","paul","weird","outer_space"],char:'\u{1f47d}',fitzpatrick_scale:!1,category:"people"},robot:{keywords:["computer","machine","bot"],char:'\u{1f916}',fitzpatrick_scale:!1,category:"people"},smiley_cat:{keywords:["animal","cats","happy","smile"],char:'\u{1f63a}',fitzpatrick_scale:!1,category:"people"},smile_cat:{keywords:["animal","cats","smile"],char:'\u{1f638}',fitzpatrick_scale:!1,category:"people"},joy_cat:{keywords:["animal","cats","haha","happy","tears"],char:'\u{1f639}',fitzpatrick_scale:!1,category:"people"},heart_eyes_cat:{keywords:["animal","love","like","affection","cats","valentines","heart"],char:'\u{1f63b}',fitzpatrick_scale:!1,category:"people"},smirk_cat:{keywords:["animal","cats","smirk"],char:'\u{1f63c}',fitzpatrick_scale:!1,category:"people"},kissing_cat:{keywords:["animal","cats","kiss"],char:'\u{1f63d}',fitzpatrick_scale:!1,category:"people"},scream_cat:{keywords:["animal","cats","munch","scared","scream"],char:'\u{1f640}',fitzpatrick_scale:!1,category:"people"},crying_cat_face:{keywords:["animal","tears","weep","sad","cats","upset","cry"],char:'\u{1f63f}',fitzpatrick_scale:!1,category:"people"},pouting_cat:{keywords:["animal","cats"],char:'\u{1f63e}',fitzpatrick_scale:!1,category:"people"},palms_up:{keywords:["hands","gesture","cupped","prayer"],char:'\u{1f932}',fitzpatrick_scale:!0,category:"people"},raised_hands:{keywords:["gesture","hooray","yea","celebration","hands"],char:'\u{1f64c}',fitzpatrick_scale:!0,category:"people"},clap:{keywords:["hands","praise","applause","congrats","yay"],char:'\u{1f44f}',fitzpatrick_scale:!0,category:"people"},wave:{keywords:["hands","gesture","goodbye","solong","farewell","hello","hi","palm"],char:'\u{1f44b}',fitzpatrick_scale:!0,category:"people"},call_me_hand:{keywords:["hands","gesture"],char:'\u{1f919}',fitzpatrick_scale:!0,category:"people"},"+1":{keywords:["thumbsup","yes","awesome","good","agree","accept","cool","hand","like"],char:'\u{1f44d}',fitzpatrick_scale:!0,category:"people"},"-1":{keywords:["thumbsdown","no","dislike","hand"],char:'\u{1f44e}',fitzpatrick_scale:!0,category:"people"},facepunch:{keywords:["angry","violence","fist","hit","attack","hand"],char:'\u{1f44a}',fitzpatrick_scale:!0,category:"people"},fist:{keywords:["fingers","hand","grasp"],char:'\u270a',fitzpatrick_scale:!0,category:"people"},fist_left:{keywords:["hand","fistbump"],char:'\u{1f91b}',fitzpatrick_scale:!0,category:"people"},fist_right:{keywords:["hand","fistbump"],char:'\u{1f91c}',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:'\u{1f44c}',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:'\u{1f91a}',fitzpatrick_scale:!0,category:"people"},open_hands:{keywords:["fingers","butterfly","hands","open"],char:'\u{1f450}',fitzpatrick_scale:!0,category:"people"},muscle:{keywords:["arm","flex","hand","summer","strong","biceps"],char:'\u{1f4aa}',fitzpatrick_scale:!0,category:"people"},pray:{keywords:["please","hope","wish","namaste","highfive"],char:'\u{1f64f}',fitzpatrick_scale:!0,category:"people"},foot:{keywords:["kick","stomp"],char:'\u{1f9b6}',fitzpatrick_scale:!0,category:"people"},leg:{keywords:["kick","limb"],char:'\u{1f9b5}',fitzpatrick_scale:!0,category:"people"},handshake:{keywords:["agreement","shake"],char:'\u{1f91d}',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:'\u{1f446}',fitzpatrick_scale:!0,category:"people"},point_down:{keywords:["fingers","hand","direction","down"],char:'\u{1f447}',fitzpatrick_scale:!0,category:"people"},point_left:{keywords:["direction","fingers","hand","left"],char:'\u{1f448}',fitzpatrick_scale:!0,category:"people"},point_right:{keywords:["fingers","hand","direction","right"],char:'\u{1f449}',fitzpatrick_scale:!0,category:"people"},fu:{keywords:["hand","fingers","rude","middle","flipping"],char:'\u{1f595}',fitzpatrick_scale:!0,category:"people"},raised_hand_with_fingers_splayed:{keywords:["hand","fingers","palm"],char:'\u{1f590}',fitzpatrick_scale:!0,category:"people"},love_you:{keywords:["hand","fingers","gesture"],char:'\u{1f91f}',fitzpatrick_scale:!0,category:"people"},metal:{keywords:["hand","fingers","evil_eye","sign_of_horns","rock_on"],char:'\u{1f918}',fitzpatrick_scale:!0,category:"people"},crossed_fingers:{keywords:["good","lucky"],char:'\u{1f91e}',fitzpatrick_scale:!0,category:"people"},vulcan_salute:{keywords:["hand","fingers","spock","star trek"],char:'\u{1f596}',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:'\u{1f933}',fitzpatrick_scale:!0,category:"people"},nail_care:{keywords:["beauty","manicure","finger","fashion","nail"],char:'\u{1f485}',fitzpatrick_scale:!0,category:"people"},lips:{keywords:["mouth","kiss"],char:'\u{1f444}',fitzpatrick_scale:!1,category:"people"},tooth:{keywords:["teeth","dentist"],char:'\u{1f9b7}',fitzpatrick_scale:!1,category:"people"},tongue:{keywords:["mouth","playful"],char:'\u{1f445}',fitzpatrick_scale:!1,category:"people"},ear:{keywords:["face","hear","sound","listen"],char:'\u{1f442}',fitzpatrick_scale:!0,category:"people"},nose:{keywords:["smell","sniff"],char:'\u{1f443}',fitzpatrick_scale:!0,category:"people"},eye:{keywords:["face","look","see","watch","stare"],char:'\u{1f441}',fitzpatrick_scale:!1,category:"people"},eyes:{keywords:["look","watch","stalk","peek","see"],char:'\u{1f440}',fitzpatrick_scale:!1,category:"people"},brain:{keywords:["smart","intelligent"],char:'\u{1f9e0}',fitzpatrick_scale:!1,category:"people"},bust_in_silhouette:{keywords:["user","person","human"],char:'\u{1f464}',fitzpatrick_scale:!1,category:"people"},busts_in_silhouette:{keywords:["user","person","human","group","team"],char:'\u{1f465}',fitzpatrick_scale:!1,category:"people"},speaking_head:{keywords:["user","person","human","sing","say","talk"],char:'\u{1f5e3}',fitzpatrick_scale:!1,category:"people"},baby:{keywords:["child","boy","girl","toddler"],char:'\u{1f476}',fitzpatrick_scale:!0,category:"people"},child:{keywords:["gender-neutral","young"],char:'\u{1f9d2}',fitzpatrick_scale:!0,category:"people"},boy:{keywords:["man","male","guy","teenager"],char:'\u{1f466}',fitzpatrick_scale:!0,category:"people"},girl:{keywords:["female","woman","teenager"],char:'\u{1f467}',fitzpatrick_scale:!0,category:"people"},adult:{keywords:["gender-neutral","person"],char:'\u{1f9d1}',fitzpatrick_scale:!0,category:"people"},man:{keywords:["mustache","father","dad","guy","classy","sir","moustache"],char:'\u{1f468}',fitzpatrick_scale:!0,category:"people"},woman:{keywords:["female","girls","lady"],char:'\u{1f469}',fitzpatrick_scale:!0,category:"people"},blonde_woman:{keywords:["woman","female","girl","blonde","person"],char:'\u{1f471}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},blonde_man:{keywords:["man","male","boy","blonde","guy","person"],char:'\u{1f471}',fitzpatrick_scale:!0,category:"people"},bearded_person:{keywords:["person","bewhiskered"],char:'\u{1f9d4}',fitzpatrick_scale:!0,category:"people"},older_adult:{keywords:["human","elder","senior","gender-neutral"],char:'\u{1f9d3}',fitzpatrick_scale:!0,category:"people"},older_man:{keywords:["human","male","men","old","elder","senior"],char:'\u{1f474}',fitzpatrick_scale:!0,category:"people"},older_woman:{keywords:["human","female","women","lady","old","elder","senior"],char:'\u{1f475}',fitzpatrick_scale:!0,category:"people"},man_with_gua_pi_mao:{keywords:["male","boy","chinese"],char:'\u{1f472}',fitzpatrick_scale:!0,category:"people"},woman_with_headscarf:{keywords:["female","hijab","mantilla","tichel"],char:'\u{1f9d5}',fitzpatrick_scale:!0,category:"people"},woman_with_turban:{keywords:["female","indian","hinduism","arabs","woman"],char:'\u{1f473}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_with_turban:{keywords:["male","indian","hinduism","arabs"],char:'\u{1f473}',fitzpatrick_scale:!0,category:"people"},policewoman:{keywords:["woman","police","law","legal","enforcement","arrest","911","female"],char:'\u{1f46e}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},policeman:{keywords:["man","police","law","legal","enforcement","arrest","911"],char:'\u{1f46e}',fitzpatrick_scale:!0,category:"people"},construction_worker_woman:{keywords:["female","human","wip","build","construction","worker","labor","woman"],char:'\u{1f477}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},construction_worker_man:{keywords:["male","human","wip","guy","build","construction","worker","labor"],char:'\u{1f477}',fitzpatrick_scale:!0,category:"people"},guardswoman:{keywords:["uk","gb","british","female","royal","woman"],char:'\u{1f482}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},guardsman:{keywords:["uk","gb","british","male","guy","royal"],char:'\u{1f482}',fitzpatrick_scale:!0,category:"people"},female_detective:{keywords:["human","spy","detective","female","woman"],char:'\u{1f575}\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},male_detective:{keywords:["human","spy","detective"],char:'\u{1f575}',fitzpatrick_scale:!0,category:"people"},woman_health_worker:{keywords:["doctor","nurse","therapist","healthcare","woman","human"],char:'\u{1f469}\u200d\u2695\ufe0f',fitzpatrick_scale:!0,category:"people"},man_health_worker:{keywords:["doctor","nurse","therapist","healthcare","man","human"],char:'\u{1f468}\u200d\u2695\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_farmer:{keywords:["rancher","gardener","woman","human"],char:'\u{1f469}\u200d\u{1f33e}',fitzpatrick_scale:!0,category:"people"},man_farmer:{keywords:["rancher","gardener","man","human"],char:'\u{1f468}\u200d\u{1f33e}',fitzpatrick_scale:!0,category:"people"},woman_cook:{keywords:["chef","woman","human"],char:'\u{1f469}\u200d\u{1f373}',fitzpatrick_scale:!0,category:"people"},man_cook:{keywords:["chef","man","human"],char:'\u{1f468}\u200d\u{1f373}',fitzpatrick_scale:!0,category:"people"},woman_student:{keywords:["graduate","woman","human"],char:'\u{1f469}\u200d\u{1f393}',fitzpatrick_scale:!0,category:"people"},man_student:{keywords:["graduate","man","human"],char:'\u{1f468}\u200d\u{1f393}',fitzpatrick_scale:!0,category:"people"},woman_singer:{keywords:["rockstar","entertainer","woman","human"],char:'\u{1f469}\u200d\u{1f3a4}',fitzpatrick_scale:!0,category:"people"},man_singer:{keywords:["rockstar","entertainer","man","human"],char:'\u{1f468}\u200d\u{1f3a4}',fitzpatrick_scale:!0,category:"people"},woman_teacher:{keywords:["instructor","professor","woman","human"],char:'\u{1f469}\u200d\u{1f3eb}',fitzpatrick_scale:!0,category:"people"},man_teacher:{keywords:["instructor","professor","man","human"],char:'\u{1f468}\u200d\u{1f3eb}',fitzpatrick_scale:!0,category:"people"},woman_factory_worker:{keywords:["assembly","industrial","woman","human"],char:'\u{1f469}\u200d\u{1f3ed}',fitzpatrick_scale:!0,category:"people"},man_factory_worker:{keywords:["assembly","industrial","man","human"],char:'\u{1f468}\u200d\u{1f3ed}',fitzpatrick_scale:!0,category:"people"},woman_technologist:{keywords:["coder","developer","engineer","programmer","software","woman","human","laptop","computer"],char:'\u{1f469}\u200d\u{1f4bb}',fitzpatrick_scale:!0,category:"people"},man_technologist:{keywords:["coder","developer","engineer","programmer","software","man","human","laptop","computer"],char:'\u{1f468}\u200d\u{1f4bb}',fitzpatrick_scale:!0,category:"people"},woman_office_worker:{keywords:["business","manager","woman","human"],char:'\u{1f469}\u200d\u{1f4bc}',fitzpatrick_scale:!0,category:"people"},man_office_worker:{keywords:["business","manager","man","human"],char:'\u{1f468}\u200d\u{1f4bc}',fitzpatrick_scale:!0,category:"people"},woman_mechanic:{keywords:["plumber","woman","human","wrench"],char:'\u{1f469}\u200d\u{1f527}',fitzpatrick_scale:!0,category:"people"},man_mechanic:{keywords:["plumber","man","human","wrench"],char:'\u{1f468}\u200d\u{1f527}',fitzpatrick_scale:!0,category:"people"},woman_scientist:{keywords:["biologist","chemist","engineer","physicist","woman","human"],char:'\u{1f469}\u200d\u{1f52c}',fitzpatrick_scale:!0,category:"people"},man_scientist:{keywords:["biologist","chemist","engineer","physicist","man","human"],char:'\u{1f468}\u200d\u{1f52c}',fitzpatrick_scale:!0,category:"people"},woman_artist:{keywords:["painter","woman","human"],char:'\u{1f469}\u200d\u{1f3a8}',fitzpatrick_scale:!0,category:"people"},man_artist:{keywords:["painter","man","human"],char:'\u{1f468}\u200d\u{1f3a8}',fitzpatrick_scale:!0,category:"people"},woman_firefighter:{keywords:["fireman","woman","human"],char:'\u{1f469}\u200d\u{1f692}',fitzpatrick_scale:!0,category:"people"},man_firefighter:{keywords:["fireman","man","human"],char:'\u{1f468}\u200d\u{1f692}',fitzpatrick_scale:!0,category:"people"},woman_pilot:{keywords:["aviator","plane","woman","human"],char:'\u{1f469}\u200d\u2708\ufe0f',fitzpatrick_scale:!0,category:"people"},man_pilot:{keywords:["aviator","plane","man","human"],char:'\u{1f468}\u200d\u2708\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_astronaut:{keywords:["space","rocket","woman","human"],char:'\u{1f469}\u200d\u{1f680}',fitzpatrick_scale:!0,category:"people"},man_astronaut:{keywords:["space","rocket","man","human"],char:'\u{1f468}\u200d\u{1f680}',fitzpatrick_scale:!0,category:"people"},woman_judge:{keywords:["justice","court","woman","human"],char:'\u{1f469}\u200d\u2696\ufe0f',fitzpatrick_scale:!0,category:"people"},man_judge:{keywords:["justice","court","man","human"],char:'\u{1f468}\u200d\u2696\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_superhero:{keywords:["woman","female","good","heroine","superpowers"],char:'\u{1f9b8}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_superhero:{keywords:["man","male","good","hero","superpowers"],char:'\u{1f9b8}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_supervillain:{keywords:["woman","female","evil","bad","criminal","heroine","superpowers"],char:'\u{1f9b9}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_supervillain:{keywords:["man","male","evil","bad","criminal","hero","superpowers"],char:'\u{1f9b9}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},mrs_claus:{keywords:["woman","female","xmas","mother christmas"],char:'\u{1f936}',fitzpatrick_scale:!0,category:"people"},santa:{keywords:["festival","man","male","xmas","father christmas"],char:'\u{1f385}',fitzpatrick_scale:!0,category:"people"},sorceress:{keywords:["woman","female","mage","witch"],char:'\u{1f9d9}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},wizard:{keywords:["man","male","mage","sorcerer"],char:'\u{1f9d9}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_elf:{keywords:["woman","female"],char:'\u{1f9dd}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_elf:{keywords:["man","male"],char:'\u{1f9dd}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_vampire:{keywords:["woman","female"],char:'\u{1f9db}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_vampire:{keywords:["man","male","dracula"],char:'\u{1f9db}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_zombie:{keywords:["woman","female","undead","walking dead"],char:'\u{1f9df}\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"people"},man_zombie:{keywords:["man","male","dracula","undead","walking dead"],char:'\u{1f9df}\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"people"},woman_genie:{keywords:["woman","female"],char:'\u{1f9de}\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"people"},man_genie:{keywords:["man","male"],char:'\u{1f9de}\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"people"},mermaid:{keywords:["woman","female","merwoman","ariel"],char:'\u{1f9dc}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},merman:{keywords:["man","male","triton"],char:'\u{1f9dc}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_fairy:{keywords:["woman","female"],char:'\u{1f9da}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_fairy:{keywords:["man","male"],char:'\u{1f9da}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},angel:{keywords:["heaven","wings","halo"],char:'\u{1f47c}',fitzpatrick_scale:!0,category:"people"},pregnant_woman:{keywords:["baby"],char:'\u{1f930}',fitzpatrick_scale:!0,category:"people"},breastfeeding:{keywords:["nursing","baby"],char:'\u{1f931}',fitzpatrick_scale:!0,category:"people"},princess:{keywords:["girl","woman","female","blond","crown","royal","queen"],char:'\u{1f478}',fitzpatrick_scale:!0,category:"people"},prince:{keywords:["boy","man","male","crown","royal","king"],char:'\u{1f934}',fitzpatrick_scale:!0,category:"people"},bride_with_veil:{keywords:["couple","marriage","wedding","woman","bride"],char:'\u{1f470}',fitzpatrick_scale:!0,category:"people"},man_in_tuxedo:{keywords:["couple","marriage","wedding","groom"],char:'\u{1f935}',fitzpatrick_scale:!0,category:"people"},running_woman:{keywords:["woman","walking","exercise","race","running","female"],char:'\u{1f3c3}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},running_man:{keywords:["man","walking","exercise","race","running"],char:'\u{1f3c3}',fitzpatrick_scale:!0,category:"people"},walking_woman:{keywords:["human","feet","steps","woman","female"],char:'\u{1f6b6}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},walking_man:{keywords:["human","feet","steps"],char:'\u{1f6b6}',fitzpatrick_scale:!0,category:"people"},dancer:{keywords:["female","girl","woman","fun"],char:'\u{1f483}',fitzpatrick_scale:!0,category:"people"},man_dancing:{keywords:["male","boy","fun","dancer"],char:'\u{1f57a}',fitzpatrick_scale:!0,category:"people"},dancing_women:{keywords:["female","bunny","women","girls"],char:'\u{1f46f}',fitzpatrick_scale:!1,category:"people"},dancing_men:{keywords:["male","bunny","men","boys"],char:'\u{1f46f}\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"people"},couple:{keywords:["pair","people","human","love","date","dating","like","affection","valentines","marriage"],char:'\u{1f46b}',fitzpatrick_scale:!1,category:"people"},two_men_holding_hands:{keywords:["pair","couple","love","like","bromance","friendship","people","human"],char:'\u{1f46c}',fitzpatrick_scale:!1,category:"people"},two_women_holding_hands:{keywords:["pair","friendship","couple","love","like","female","people","human"],char:'\u{1f46d}',fitzpatrick_scale:!1,category:"people"},bowing_woman:{keywords:["woman","female","girl"],char:'\u{1f647}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},bowing_man:{keywords:["man","male","boy"],char:'\u{1f647}',fitzpatrick_scale:!0,category:"people"},man_facepalming:{keywords:["man","male","boy","disbelief"],char:'\u{1f926}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_facepalming:{keywords:["woman","female","girl","disbelief"],char:'\u{1f926}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_shrugging:{keywords:["woman","female","girl","confused","indifferent","doubt"],char:'\u{1f937}',fitzpatrick_scale:!0,category:"people"},man_shrugging:{keywords:["man","male","boy","confused","indifferent","doubt"],char:'\u{1f937}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},tipping_hand_woman:{keywords:["female","girl","woman","human","information"],char:'\u{1f481}',fitzpatrick_scale:!0,category:"people"},tipping_hand_man:{keywords:["male","boy","man","human","information"],char:'\u{1f481}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},no_good_woman:{keywords:["female","girl","woman","nope"],char:'\u{1f645}',fitzpatrick_scale:!0,category:"people"},no_good_man:{keywords:["male","boy","man","nope"],char:'\u{1f645}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},ok_woman:{keywords:["women","girl","female","pink","human","woman"],char:'\u{1f646}',fitzpatrick_scale:!0,category:"people"},ok_man:{keywords:["men","boy","male","blue","human","man"],char:'\u{1f646}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},raising_hand_woman:{keywords:["female","girl","woman"],char:'\u{1f64b}',fitzpatrick_scale:!0,category:"people"},raising_hand_man:{keywords:["male","boy","man"],char:'\u{1f64b}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},pouting_woman:{keywords:["female","girl","woman"],char:'\u{1f64e}',fitzpatrick_scale:!0,category:"people"},pouting_man:{keywords:["male","boy","man"],char:'\u{1f64e}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},frowning_woman:{keywords:["female","girl","woman","sad","depressed","discouraged","unhappy"],char:'\u{1f64d}',fitzpatrick_scale:!0,category:"people"},frowning_man:{keywords:["male","boy","man","sad","depressed","discouraged","unhappy"],char:'\u{1f64d}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},haircut_woman:{keywords:["female","girl","woman"],char:'\u{1f487}',fitzpatrick_scale:!0,category:"people"},haircut_man:{keywords:["male","boy","man"],char:'\u{1f487}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},massage_woman:{keywords:["female","girl","woman","head"],char:'\u{1f486}',fitzpatrick_scale:!0,category:"people"},massage_man:{keywords:["male","boy","man","head"],char:'\u{1f486}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_in_steamy_room:{keywords:["female","woman","spa","steamroom","sauna"],char:'\u{1f9d6}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_in_steamy_room:{keywords:["male","man","spa","steamroom","sauna"],char:'\u{1f9d6}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},couple_with_heart_woman_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'\u{1f491}',fitzpatrick_scale:!1,category:"people"},couple_with_heart_woman_woman:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'\u{1f469}\u200d\u2764\ufe0f\u200d\u{1f469}',fitzpatrick_scale:!1,category:"people"},couple_with_heart_man_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'\u{1f468}\u200d\u2764\ufe0f\u200d\u{1f468}',fitzpatrick_scale:!1,category:"people"},couplekiss_man_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:'\u{1f48f}',fitzpatrick_scale:!1,category:"people"},couplekiss_woman_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:'\u{1f469}\u200d\u2764\ufe0f\u200d\u{1f48b}\u200d\u{1f469}',fitzpatrick_scale:!1,category:"people"},couplekiss_man_man:{keywords:["pair","valentines","love","like","dating","marriage"],char:'\u{1f468}\u200d\u2764\ufe0f\u200d\u{1f48b}\u200d\u{1f468}',fitzpatrick_scale:!1,category:"people"},family_man_woman_boy:{keywords:["home","parents","child","mom","dad","father","mother","people","human"],char:'\u{1f46a}',fitzpatrick_scale:!1,category:"people"},family_man_woman_girl:{keywords:["home","parents","people","human","child"],char:'\u{1f468}\u200d\u{1f469}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f469}\u200d\u{1f466}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f469}\u200d\u{1f469}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl:{keywords:["home","parents","people","human","children"],char:'\u{1f469}\u200d\u{1f469}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f469}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f469}\u200d\u{1f469}\u200d\u{1f466}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:'\u{1f469}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_man_man_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f468}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_man_girl:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f468}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_man_man_girl_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f468}\u200d\u{1f467}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_man_boy_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f468}\u200d\u{1f466}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_man_girl_girl:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f468}\u200d\u{1f467}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_woman_boy:{keywords:["home","parent","people","human","child"],char:'\u{1f469}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_girl:{keywords:["home","parent","people","human","child"],char:'\u{1f469}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_woman_girl_boy:{keywords:["home","parent","people","human","children"],char:'\u{1f469}\u200d\u{1f467}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_boy_boy:{keywords:["home","parent","people","human","children"],char:'\u{1f469}\u200d\u{1f466}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_girl_girl:{keywords:["home","parent","people","human","children"],char:'\u{1f469}\u200d\u{1f467}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_man_boy:{keywords:["home","parent","people","human","child"],char:'\u{1f468}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_girl:{keywords:["home","parent","people","human","child"],char:'\u{1f468}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_man_girl_boy:{keywords:["home","parent","people","human","children"],char:'\u{1f468}\u200d\u{1f467}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_boy_boy:{keywords:["home","parent","people","human","children"],char:'\u{1f468}\u200d\u{1f466}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_girl_girl:{keywords:["home","parent","people","human","children"],char:'\u{1f468}\u200d\u{1f467}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},yarn:{keywords:["ball","crochet","knit"],char:'\u{1f9f6}',fitzpatrick_scale:!1,category:"people"},thread:{keywords:["needle","sewing","spool","string"],char:'\u{1f9f5}',fitzpatrick_scale:!1,category:"people"},coat:{keywords:["jacket"],char:'\u{1f9e5}',fitzpatrick_scale:!1,category:"people"},labcoat:{keywords:["doctor","experiment","scientist","chemist"],char:'\u{1f97c}',fitzpatrick_scale:!1,category:"people"},womans_clothes:{keywords:["fashion","shopping_bags","female"],char:'\u{1f45a}',fitzpatrick_scale:!1,category:"people"},tshirt:{keywords:["fashion","cloth","casual","shirt","tee"],char:'\u{1f455}',fitzpatrick_scale:!1,category:"people"},jeans:{keywords:["fashion","shopping"],char:'\u{1f456}',fitzpatrick_scale:!1,category:"people"},necktie:{keywords:["shirt","suitup","formal","fashion","cloth","business"],char:'\u{1f454}',fitzpatrick_scale:!1,category:"people"},dress:{keywords:["clothes","fashion","shopping"],char:'\u{1f457}',fitzpatrick_scale:!1,category:"people"},bikini:{keywords:["swimming","female","woman","girl","fashion","beach","summer"],char:'\u{1f459}',fitzpatrick_scale:!1,category:"people"},kimono:{keywords:["dress","fashion","women","female","japanese"],char:'\u{1f458}',fitzpatrick_scale:!1,category:"people"},lipstick:{keywords:["female","girl","fashion","woman"],char:'\u{1f484}',fitzpatrick_scale:!1,category:"people"},kiss:{keywords:["face","lips","love","like","affection","valentines"],char:'\u{1f48b}',fitzpatrick_scale:!1,category:"people"},footprints:{keywords:["feet","tracking","walking","beach"],char:'\u{1f463}',fitzpatrick_scale:!1,category:"people"},flat_shoe:{keywords:["ballet","slip-on","slipper"],char:'\u{1f97f}',fitzpatrick_scale:!1,category:"people"},high_heel:{keywords:["fashion","shoes","female","pumps","stiletto"],char:'\u{1f460}',fitzpatrick_scale:!1,category:"people"},sandal:{keywords:["shoes","fashion","flip flops"],char:'\u{1f461}',fitzpatrick_scale:!1,category:"people"},boot:{keywords:["shoes","fashion"],char:'\u{1f462}',fitzpatrick_scale:!1,category:"people"},mans_shoe:{keywords:["fashion","male"],char:'\u{1f45e}',fitzpatrick_scale:!1,category:"people"},athletic_shoe:{keywords:["shoes","sports","sneakers"],char:'\u{1f45f}',fitzpatrick_scale:!1,category:"people"},hiking_boot:{keywords:["backpacking","camping","hiking"],char:'\u{1f97e}',fitzpatrick_scale:!1,category:"people"},socks:{keywords:["stockings","clothes"],char:'\u{1f9e6}',fitzpatrick_scale:!1,category:"people"},gloves:{keywords:["hands","winter","clothes"],char:'\u{1f9e4}',fitzpatrick_scale:!1,category:"people"},scarf:{keywords:["neck","winter","clothes"],char:'\u{1f9e3}',fitzpatrick_scale:!1,category:"people"},womans_hat:{keywords:["fashion","accessories","female","lady","spring"],char:'\u{1f452}',fitzpatrick_scale:!1,category:"people"},tophat:{keywords:["magic","gentleman","classy","circus"],char:'\u{1f3a9}',fitzpatrick_scale:!1,category:"people"},billed_hat:{keywords:["cap","baseball"],char:'\u{1f9e2}',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:'\u{1f393}',fitzpatrick_scale:!1,category:"people"},crown:{keywords:["king","kod","leader","royalty","lord"],char:'\u{1f451}',fitzpatrick_scale:!1,category:"people"},school_satchel:{keywords:["student","education","bag","backpack"],char:'\u{1f392}',fitzpatrick_scale:!1,category:"people"},luggage:{keywords:["packing","travel"],char:'\u{1f9f3}',fitzpatrick_scale:!1,category:"people"},pouch:{keywords:["bag","accessories","shopping"],char:'\u{1f45d}',fitzpatrick_scale:!1,category:"people"},purse:{keywords:["fashion","accessories","money","sales","shopping"],char:'\u{1f45b}',fitzpatrick_scale:!1,category:"people"},handbag:{keywords:["fashion","accessory","accessories","shopping"],char:'\u{1f45c}',fitzpatrick_scale:!1,category:"people"},briefcase:{keywords:["business","documents","work","law","legal","job","career"],char:'\u{1f4bc}',fitzpatrick_scale:!1,category:"people"},eyeglasses:{keywords:["fashion","accessories","eyesight","nerdy","dork","geek"],char:'\u{1f453}',fitzpatrick_scale:!1,category:"people"},dark_sunglasses:{keywords:["face","cool","accessories"],char:'\u{1f576}',fitzpatrick_scale:!1,category:"people"},goggles:{keywords:["eyes","protection","safety"],char:'\u{1f97d}',fitzpatrick_scale:!1,category:"people"},ring:{keywords:["wedding","propose","marriage","valentines","diamond","fashion","jewelry","gem","engagement"],char:'\u{1f48d}',fitzpatrick_scale:!1,category:"people"},closed_umbrella:{keywords:["weather","rain","drizzle"],char:'\u{1f302}',fitzpatrick_scale:!1,category:"people"},dog:{keywords:["animal","friend","nature","woof","puppy","pet","faithful"],char:'\u{1f436}',fitzpatrick_scale:!1,category:"animals_and_nature"},cat:{keywords:["animal","meow","nature","pet","kitten"],char:'\u{1f431}',fitzpatrick_scale:!1,category:"animals_and_nature"},mouse:{keywords:["animal","nature","cheese_wedge","rodent"],char:'\u{1f42d}',fitzpatrick_scale:!1,category:"animals_and_nature"},hamster:{keywords:["animal","nature"],char:'\u{1f439}',fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit:{keywords:["animal","nature","pet","spring","magic","bunny"],char:'\u{1f430}',fitzpatrick_scale:!1,category:"animals_and_nature"},fox_face:{keywords:["animal","nature","face"],char:'\u{1f98a}',fitzpatrick_scale:!1,category:"animals_and_nature"},bear:{keywords:["animal","nature","wild"],char:'\u{1f43b}',fitzpatrick_scale:!1,category:"animals_and_nature"},panda_face:{keywords:["animal","nature","panda"],char:'\u{1f43c}',fitzpatrick_scale:!1,category:"animals_and_nature"},koala:{keywords:["animal","nature"],char:'\u{1f428}',fitzpatrick_scale:!1,category:"animals_and_nature"},tiger:{keywords:["animal","cat","danger","wild","nature","roar"],char:'\u{1f42f}',fitzpatrick_scale:!1,category:"animals_and_nature"},lion:{keywords:["animal","nature"],char:'\u{1f981}',fitzpatrick_scale:!1,category:"animals_and_nature"},cow:{keywords:["beef","ox","animal","nature","moo","milk"],char:'\u{1f42e}',fitzpatrick_scale:!1,category:"animals_and_nature"},pig:{keywords:["animal","oink","nature"],char:'\u{1f437}',fitzpatrick_scale:!1,category:"animals_and_nature"},pig_nose:{keywords:["animal","oink"],char:'\u{1f43d}',fitzpatrick_scale:!1,category:"animals_and_nature"},frog:{keywords:["animal","nature","croak","toad"],char:'\u{1f438}',fitzpatrick_scale:!1,category:"animals_and_nature"},squid:{keywords:["animal","nature","ocean","sea"],char:'\u{1f991}',fitzpatrick_scale:!1,category:"animals_and_nature"},octopus:{keywords:["animal","creature","ocean","sea","nature","beach"],char:'\u{1f419}',fitzpatrick_scale:!1,category:"animals_and_nature"},shrimp:{keywords:["animal","ocean","nature","seafood"],char:'\u{1f990}',fitzpatrick_scale:!1,category:"animals_and_nature"},monkey_face:{keywords:["animal","nature","circus"],char:'\u{1f435}',fitzpatrick_scale:!1,category:"animals_and_nature"},gorilla:{keywords:["animal","nature","circus"],char:'\u{1f98d}',fitzpatrick_scale:!1,category:"animals_and_nature"},see_no_evil:{keywords:["monkey","animal","nature","haha"],char:'\u{1f648}',fitzpatrick_scale:!1,category:"animals_and_nature"},hear_no_evil:{keywords:["animal","monkey","nature"],char:'\u{1f649}',fitzpatrick_scale:!1,category:"animals_and_nature"},speak_no_evil:{keywords:["monkey","animal","nature","omg"],char:'\u{1f64a}',fitzpatrick_scale:!1,category:"animals_and_nature"},monkey:{keywords:["animal","nature","banana","circus"],char:'\u{1f412}',fitzpatrick_scale:!1,category:"animals_and_nature"},chicken:{keywords:["animal","cluck","nature","bird"],char:'\u{1f414}',fitzpatrick_scale:!1,category:"animals_and_nature"},penguin:{keywords:["animal","nature"],char:'\u{1f427}',fitzpatrick_scale:!1,category:"animals_and_nature"},bird:{keywords:["animal","nature","fly","tweet","spring"],char:'\u{1f426}',fitzpatrick_scale:!1,category:"animals_and_nature"},baby_chick:{keywords:["animal","chicken","bird"],char:'\u{1f424}',fitzpatrick_scale:!1,category:"animals_and_nature"},hatching_chick:{keywords:["animal","chicken","egg","born","baby","bird"],char:'\u{1f423}',fitzpatrick_scale:!1,category:"animals_and_nature"},hatched_chick:{keywords:["animal","chicken","baby","bird"],char:'\u{1f425}',fitzpatrick_scale:!1,category:"animals_and_nature"},duck:{keywords:["animal","nature","bird","mallard"],char:'\u{1f986}',fitzpatrick_scale:!1,category:"animals_and_nature"},eagle:{keywords:["animal","nature","bird"],char:'\u{1f985}',fitzpatrick_scale:!1,category:"animals_and_nature"},owl:{keywords:["animal","nature","bird","hoot"],char:'\u{1f989}',fitzpatrick_scale:!1,category:"animals_and_nature"},bat:{keywords:["animal","nature","blind","vampire"],char:'\u{1f987}',fitzpatrick_scale:!1,category:"animals_and_nature"},wolf:{keywords:["animal","nature","wild"],char:'\u{1f43a}',fitzpatrick_scale:!1,category:"animals_and_nature"},boar:{keywords:["animal","nature"],char:'\u{1f417}',fitzpatrick_scale:!1,category:"animals_and_nature"},horse:{keywords:["animal","brown","nature"],char:'\u{1f434}',fitzpatrick_scale:!1,category:"animals_and_nature"},unicorn:{keywords:["animal","nature","mystical"],char:'\u{1f984}',fitzpatrick_scale:!1,category:"animals_and_nature"},honeybee:{keywords:["animal","insect","nature","bug","spring","honey"],char:'\u{1f41d}',fitzpatrick_scale:!1,category:"animals_and_nature"},bug:{keywords:["animal","insect","nature","worm"],char:'\u{1f41b}',fitzpatrick_scale:!1,category:"animals_and_nature"},butterfly:{keywords:["animal","insect","nature","caterpillar"],char:'\u{1f98b}',fitzpatrick_scale:!1,category:"animals_and_nature"},snail:{keywords:["slow","animal","shell"],char:'\u{1f40c}',fitzpatrick_scale:!1,category:"animals_and_nature"},beetle:{keywords:["animal","insect","nature","ladybug"],char:'\u{1f41e}',fitzpatrick_scale:!1,category:"animals_and_nature"},ant:{keywords:["animal","insect","nature","bug"],char:'\u{1f41c}',fitzpatrick_scale:!1,category:"animals_and_nature"},grasshopper:{keywords:["animal","cricket","chirp"],char:'\u{1f997}',fitzpatrick_scale:!1,category:"animals_and_nature"},spider:{keywords:["animal","arachnid"],char:'\u{1f577}',fitzpatrick_scale:!1,category:"animals_and_nature"},scorpion:{keywords:["animal","arachnid"],char:'\u{1f982}',fitzpatrick_scale:!1,category:"animals_and_nature"},crab:{keywords:["animal","crustacean"],char:'\u{1f980}',fitzpatrick_scale:!1,category:"animals_and_nature"},snake:{keywords:["animal","evil","nature","hiss","python"],char:'\u{1f40d}',fitzpatrick_scale:!1,category:"animals_and_nature"},lizard:{keywords:["animal","nature","reptile"],char:'\u{1f98e}',fitzpatrick_scale:!1,category:"animals_and_nature"},"t-rex":{keywords:["animal","nature","dinosaur","tyrannosaurus","extinct"],char:'\u{1f996}',fitzpatrick_scale:!1,category:"animals_and_nature"},sauropod:{keywords:["animal","nature","dinosaur","brachiosaurus","brontosaurus","diplodocus","extinct"],char:'\u{1f995}',fitzpatrick_scale:!1,category:"animals_and_nature"},turtle:{keywords:["animal","slow","nature","tortoise"],char:'\u{1f422}',fitzpatrick_scale:!1,category:"animals_and_nature"},tropical_fish:{keywords:["animal","swim","ocean","beach","nemo"],char:'\u{1f420}',fitzpatrick_scale:!1,category:"animals_and_nature"},fish:{keywords:["animal","food","nature"],char:'\u{1f41f}',fitzpatrick_scale:!1,category:"animals_and_nature"},blowfish:{keywords:["animal","nature","food","sea","ocean"],char:'\u{1f421}',fitzpatrick_scale:!1,category:"animals_and_nature"},dolphin:{keywords:["animal","nature","fish","sea","ocean","flipper","fins","beach"],char:'\u{1f42c}',fitzpatrick_scale:!1,category:"animals_and_nature"},shark:{keywords:["animal","nature","fish","sea","ocean","jaws","fins","beach"],char:'\u{1f988}',fitzpatrick_scale:!1,category:"animals_and_nature"},whale:{keywords:["animal","nature","sea","ocean"],char:'\u{1f433}',fitzpatrick_scale:!1,category:"animals_and_nature"},whale2:{keywords:["animal","nature","sea","ocean"],char:'\u{1f40b}',fitzpatrick_scale:!1,category:"animals_and_nature"},crocodile:{keywords:["animal","nature","reptile","lizard","alligator"],char:'\u{1f40a}',fitzpatrick_scale:!1,category:"animals_and_nature"},leopard:{keywords:["animal","nature"],char:'\u{1f406}',fitzpatrick_scale:!1,category:"animals_and_nature"},zebra:{keywords:["animal","nature","stripes","safari"],char:'\u{1f993}',fitzpatrick_scale:!1,category:"animals_and_nature"},tiger2:{keywords:["animal","nature","roar"],char:'\u{1f405}',fitzpatrick_scale:!1,category:"animals_and_nature"},water_buffalo:{keywords:["animal","nature","ox","cow"],char:'\u{1f403}',fitzpatrick_scale:!1,category:"animals_and_nature"},ox:{keywords:["animal","cow","beef"],char:'\u{1f402}',fitzpatrick_scale:!1,category:"animals_and_nature"},cow2:{keywords:["beef","ox","animal","nature","moo","milk"],char:'\u{1f404}',fitzpatrick_scale:!1,category:"animals_and_nature"},deer:{keywords:["animal","nature","horns","venison"],char:'\u{1f98c}',fitzpatrick_scale:!1,category:"animals_and_nature"},dromedary_camel:{keywords:["animal","hot","desert","hump"],char:'\u{1f42a}',fitzpatrick_scale:!1,category:"animals_and_nature"},camel:{keywords:["animal","nature","hot","desert","hump"],char:'\u{1f42b}',fitzpatrick_scale:!1,category:"animals_and_nature"},giraffe:{keywords:["animal","nature","spots","safari"],char:'\u{1f992}',fitzpatrick_scale:!1,category:"animals_and_nature"},elephant:{keywords:["animal","nature","nose","th","circus"],char:'\u{1f418}',fitzpatrick_scale:!1,category:"animals_and_nature"},rhinoceros:{keywords:["animal","nature","horn"],char:'\u{1f98f}',fitzpatrick_scale:!1,category:"animals_and_nature"},goat:{keywords:["animal","nature"],char:'\u{1f410}',fitzpatrick_scale:!1,category:"animals_and_nature"},ram:{keywords:["animal","sheep","nature"],char:'\u{1f40f}',fitzpatrick_scale:!1,category:"animals_and_nature"},sheep:{keywords:["animal","nature","wool","shipit"],char:'\u{1f411}',fitzpatrick_scale:!1,category:"animals_and_nature"},racehorse:{keywords:["animal","gamble","luck"],char:'\u{1f40e}',fitzpatrick_scale:!1,category:"animals_and_nature"},pig2:{keywords:["animal","nature"],char:'\u{1f416}',fitzpatrick_scale:!1,category:"animals_and_nature"},rat:{keywords:["animal","mouse","rodent"],char:'\u{1f400}',fitzpatrick_scale:!1,category:"animals_and_nature"},mouse2:{keywords:["animal","nature","rodent"],char:'\u{1f401}',fitzpatrick_scale:!1,category:"animals_and_nature"},rooster:{keywords:["animal","nature","chicken"],char:'\u{1f413}',fitzpatrick_scale:!1,category:"animals_and_nature"},turkey:{keywords:["animal","bird"],char:'\u{1f983}',fitzpatrick_scale:!1,category:"animals_and_nature"},dove:{keywords:["animal","bird"],char:'\u{1f54a}',fitzpatrick_scale:!1,category:"animals_and_nature"},dog2:{keywords:["animal","nature","friend","doge","pet","faithful"],char:'\u{1f415}',fitzpatrick_scale:!1,category:"animals_and_nature"},poodle:{keywords:["dog","animal","101","nature","pet"],char:'\u{1f429}',fitzpatrick_scale:!1,category:"animals_and_nature"},cat2:{keywords:["animal","meow","pet","cats"],char:'\u{1f408}',fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit2:{keywords:["animal","nature","pet","magic","spring"],char:'\u{1f407}',fitzpatrick_scale:!1,category:"animals_and_nature"},chipmunk:{keywords:["animal","nature","rodent","squirrel"],char:'\u{1f43f}',fitzpatrick_scale:!1,category:"animals_and_nature"},hedgehog:{keywords:["animal","nature","spiny"],char:'\u{1f994}',fitzpatrick_scale:!1,category:"animals_and_nature"},raccoon:{keywords:["animal","nature"],char:'\u{1f99d}',fitzpatrick_scale:!1,category:"animals_and_nature"},llama:{keywords:["animal","nature","alpaca"],char:'\u{1f999}',fitzpatrick_scale:!1,category:"animals_and_nature"},hippopotamus:{keywords:["animal","nature"],char:'\u{1f99b}',fitzpatrick_scale:!1,category:"animals_and_nature"},kangaroo:{keywords:["animal","nature","australia","joey","hop","marsupial"],char:'\u{1f998}',fitzpatrick_scale:!1,category:"animals_and_nature"},badger:{keywords:["animal","nature","honey"],char:'\u{1f9a1}',fitzpatrick_scale:!1,category:"animals_and_nature"},swan:{keywords:["animal","nature","bird"],char:'\u{1f9a2}',fitzpatrick_scale:!1,category:"animals_and_nature"},peacock:{keywords:["animal","nature","peahen","bird"],char:'\u{1f99a}',fitzpatrick_scale:!1,category:"animals_and_nature"},parrot:{keywords:["animal","nature","bird","pirate","talk"],char:'\u{1f99c}',fitzpatrick_scale:!1,category:"animals_and_nature"},lobster:{keywords:["animal","nature","bisque","claws","seafood"],char:'\u{1f99e}',fitzpatrick_scale:!1,category:"animals_and_nature"},mosquito:{keywords:["animal","nature","insect","malaria"],char:'\u{1f99f}',fitzpatrick_scale:!1,category:"animals_and_nature"},paw_prints:{keywords:["animal","tracking","footprints","dog","cat","pet","feet"],char:'\u{1f43e}',fitzpatrick_scale:!1,category:"animals_and_nature"},dragon:{keywords:["animal","myth","nature","chinese","green"],char:'\u{1f409}',fitzpatrick_scale:!1,category:"animals_and_nature"},dragon_face:{keywords:["animal","myth","nature","chinese","green"],char:'\u{1f432}',fitzpatrick_scale:!1,category:"animals_and_nature"},cactus:{keywords:["vegetable","plant","nature"],char:'\u{1f335}',fitzpatrick_scale:!1,category:"animals_and_nature"},christmas_tree:{keywords:["festival","vacation","december","xmas","celebration"],char:'\u{1f384}',fitzpatrick_scale:!1,category:"animals_and_nature"},evergreen_tree:{keywords:["plant","nature"],char:'\u{1f332}',fitzpatrick_scale:!1,category:"animals_and_nature"},deciduous_tree:{keywords:["plant","nature"],char:'\u{1f333}',fitzpatrick_scale:!1,category:"animals_and_nature"},palm_tree:{keywords:["plant","vegetable","nature","summer","beach","mojito","tropical"],char:'\u{1f334}',fitzpatrick_scale:!1,category:"animals_and_nature"},seedling:{keywords:["plant","nature","grass","lawn","spring"],char:'\u{1f331}',fitzpatrick_scale:!1,category:"animals_and_nature"},herb:{keywords:["vegetable","plant","medicine","weed","grass","lawn"],char:'\u{1f33f}',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:'\u{1f340}',fitzpatrick_scale:!1,category:"animals_and_nature"},bamboo:{keywords:["plant","nature","vegetable","panda","pine_decoration"],char:'\u{1f38d}',fitzpatrick_scale:!1,category:"animals_and_nature"},tanabata_tree:{keywords:["plant","nature","branch","summer"],char:'\u{1f38b}',fitzpatrick_scale:!1,category:"animals_and_nature"},leaves:{keywords:["nature","plant","tree","vegetable","grass","lawn","spring"],char:'\u{1f343}',fitzpatrick_scale:!1,category:"animals_and_nature"},fallen_leaf:{keywords:["nature","plant","vegetable","leaves"],char:'\u{1f342}',fitzpatrick_scale:!1,category:"animals_and_nature"},maple_leaf:{keywords:["nature","plant","vegetable","ca","fall"],char:'\u{1f341}',fitzpatrick_scale:!1,category:"animals_and_nature"},ear_of_rice:{keywords:["nature","plant"],char:'\u{1f33e}',fitzpatrick_scale:!1,category:"animals_and_nature"},hibiscus:{keywords:["plant","vegetable","flowers","beach"],char:'\u{1f33a}',fitzpatrick_scale:!1,category:"animals_and_nature"},sunflower:{keywords:["nature","plant","fall"],char:'\u{1f33b}',fitzpatrick_scale:!1,category:"animals_and_nature"},rose:{keywords:["flowers","valentines","love","spring"],char:'\u{1f339}',fitzpatrick_scale:!1,category:"animals_and_nature"},wilted_flower:{keywords:["plant","nature","flower"],char:'\u{1f940}',fitzpatrick_scale:!1,category:"animals_and_nature"},tulip:{keywords:["flowers","plant","nature","summer","spring"],char:'\u{1f337}',fitzpatrick_scale:!1,category:"animals_and_nature"},blossom:{keywords:["nature","flowers","yellow"],char:'\u{1f33c}',fitzpatrick_scale:!1,category:"animals_and_nature"},cherry_blossom:{keywords:["nature","plant","spring","flower"],char:'\u{1f338}',fitzpatrick_scale:!1,category:"animals_and_nature"},bouquet:{keywords:["flowers","nature","spring"],char:'\u{1f490}',fitzpatrick_scale:!1,category:"animals_and_nature"},mushroom:{keywords:["plant","vegetable"],char:'\u{1f344}',fitzpatrick_scale:!1,category:"animals_and_nature"},chestnut:{keywords:["food","squirrel"],char:'\u{1f330}',fitzpatrick_scale:!1,category:"animals_and_nature"},jack_o_lantern:{keywords:["halloween","light","pumpkin","creepy","fall"],char:'\u{1f383}',fitzpatrick_scale:!1,category:"animals_and_nature"},shell:{keywords:["nature","sea","beach"],char:'\u{1f41a}',fitzpatrick_scale:!1,category:"animals_and_nature"},spider_web:{keywords:["animal","insect","arachnid","silk"],char:'\u{1f578}',fitzpatrick_scale:!1,category:"animals_and_nature"},earth_americas:{keywords:["globe","world","USA","international"],char:'\u{1f30e}',fitzpatrick_scale:!1,category:"animals_and_nature"},earth_africa:{keywords:["globe","world","international"],char:'\u{1f30d}',fitzpatrick_scale:!1,category:"animals_and_nature"},earth_asia:{keywords:["globe","world","east","international"],char:'\u{1f30f}',fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon:{keywords:["nature","yellow","twilight","planet","space","night","evening","sleep"],char:'\u{1f315}',fitzpatrick_scale:!1,category:"animals_and_nature"},waning_gibbous_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep","waxing_gibbous_moon"],char:'\u{1f316}',fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f317}',fitzpatrick_scale:!1,category:"animals_and_nature"},waning_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f318}',fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f311}',fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f312}',fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f313}',fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_gibbous_moon:{keywords:["nature","night","sky","gray","twilight","planet","space","evening","sleep"],char:'\u{1f314}',fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f31a}',fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f31d}',fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f31b}',fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f31c}',fitzpatrick_scale:!1,category:"animals_and_nature"},sun_with_face:{keywords:["nature","morning","sky"],char:'\u{1f31e}',fitzpatrick_scale:!1,category:"animals_and_nature"},crescent_moon:{keywords:["night","sleep","sky","evening","magic"],char:'\u{1f319}',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:'\u{1f31f}',fitzpatrick_scale:!1,category:"animals_and_nature"},dizzy:{keywords:["star","sparkle","shoot","magic"],char:'\u{1f4ab}',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:'\u{1f324}',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:'\u{1f325}',fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_rain_cloud:{keywords:["weather"],char:'\u{1f326}',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:'\u{1f327}',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:'\u{1f329}',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:'\u{1f525}',fitzpatrick_scale:!1,category:"animals_and_nature"},boom:{keywords:["bomb","explode","explosion","collision","blown"],char:'\u{1f4a5}',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:'\u{1f328}',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:'\u{1f32c}',fitzpatrick_scale:!1,category:"animals_and_nature"},dash:{keywords:["wind","air","fast","shoo","fart","smoke","puff"],char:'\u{1f4a8}',fitzpatrick_scale:!1,category:"animals_and_nature"},tornado:{keywords:["weather","cyclone","twister"],char:'\u{1f32a}',fitzpatrick_scale:!1,category:"animals_and_nature"},fog:{keywords:["weather"],char:'\u{1f32b}',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:'\u{1f4a7}',fitzpatrick_scale:!1,category:"animals_and_nature"},sweat_drops:{keywords:["water","drip","oops"],char:'\u{1f4a6}',fitzpatrick_scale:!1,category:"animals_and_nature"},ocean:{keywords:["sea","water","wave","nature","tsunami","disaster"],char:'\u{1f30a}',fitzpatrick_scale:!1,category:"animals_and_nature"},green_apple:{keywords:["fruit","nature"],char:'\u{1f34f}',fitzpatrick_scale:!1,category:"food_and_drink"},apple:{keywords:["fruit","mac","school"],char:'\u{1f34e}',fitzpatrick_scale:!1,category:"food_and_drink"},pear:{keywords:["fruit","nature","food"],char:'\u{1f350}',fitzpatrick_scale:!1,category:"food_and_drink"},tangerine:{keywords:["food","fruit","nature","orange"],char:'\u{1f34a}',fitzpatrick_scale:!1,category:"food_and_drink"},lemon:{keywords:["fruit","nature"],char:'\u{1f34b}',fitzpatrick_scale:!1,category:"food_and_drink"},banana:{keywords:["fruit","food","monkey"],char:'\u{1f34c}',fitzpatrick_scale:!1,category:"food_and_drink"},watermelon:{keywords:["fruit","food","picnic","summer"],char:'\u{1f349}',fitzpatrick_scale:!1,category:"food_and_drink"},grapes:{keywords:["fruit","food","wine"],char:'\u{1f347}',fitzpatrick_scale:!1,category:"food_and_drink"},strawberry:{keywords:["fruit","food","nature"],char:'\u{1f353}',fitzpatrick_scale:!1,category:"food_and_drink"},melon:{keywords:["fruit","nature","food"],char:'\u{1f348}',fitzpatrick_scale:!1,category:"food_and_drink"},cherries:{keywords:["food","fruit"],char:'\u{1f352}',fitzpatrick_scale:!1,category:"food_and_drink"},peach:{keywords:["fruit","nature","food"],char:'\u{1f351}',fitzpatrick_scale:!1,category:"food_and_drink"},pineapple:{keywords:["fruit","nature","food"],char:'\u{1f34d}',fitzpatrick_scale:!1,category:"food_and_drink"},coconut:{keywords:["fruit","nature","food","palm"],char:'\u{1f965}',fitzpatrick_scale:!1,category:"food_and_drink"},kiwi_fruit:{keywords:["fruit","food"],char:'\u{1f95d}',fitzpatrick_scale:!1,category:"food_and_drink"},mango:{keywords:["fruit","food","tropical"],char:'\u{1f96d}',fitzpatrick_scale:!1,category:"food_and_drink"},avocado:{keywords:["fruit","food"],char:'\u{1f951}',fitzpatrick_scale:!1,category:"food_and_drink"},broccoli:{keywords:["fruit","food","vegetable"],char:'\u{1f966}',fitzpatrick_scale:!1,category:"food_and_drink"},tomato:{keywords:["fruit","vegetable","nature","food"],char:'\u{1f345}',fitzpatrick_scale:!1,category:"food_and_drink"},eggplant:{keywords:["vegetable","nature","food","aubergine"],char:'\u{1f346}',fitzpatrick_scale:!1,category:"food_and_drink"},cucumber:{keywords:["fruit","food","pickle"],char:'\u{1f952}',fitzpatrick_scale:!1,category:"food_and_drink"},carrot:{keywords:["vegetable","food","orange"],char:'\u{1f955}',fitzpatrick_scale:!1,category:"food_and_drink"},hot_pepper:{keywords:["food","spicy","chilli","chili"],char:'\u{1f336}',fitzpatrick_scale:!1,category:"food_and_drink"},potato:{keywords:["food","tuber","vegatable","starch"],char:'\u{1f954}',fitzpatrick_scale:!1,category:"food_and_drink"},corn:{keywords:["food","vegetable","plant"],char:'\u{1f33d}',fitzpatrick_scale:!1,category:"food_and_drink"},leafy_greens:{keywords:["food","vegetable","plant","bok choy","cabbage","kale","lettuce"],char:'\u{1f96c}',fitzpatrick_scale:!1,category:"food_and_drink"},sweet_potato:{keywords:["food","nature"],char:'\u{1f360}',fitzpatrick_scale:!1,category:"food_and_drink"},peanuts:{keywords:["food","nut"],char:'\u{1f95c}',fitzpatrick_scale:!1,category:"food_and_drink"},honey_pot:{keywords:["bees","sweet","kitchen"],char:'\u{1f36f}',fitzpatrick_scale:!1,category:"food_and_drink"},croissant:{keywords:["food","bread","french"],char:'\u{1f950}',fitzpatrick_scale:!1,category:"food_and_drink"},bread:{keywords:["food","wheat","breakfast","toast"],char:'\u{1f35e}',fitzpatrick_scale:!1,category:"food_and_drink"},baguette_bread:{keywords:["food","bread","french"],char:'\u{1f956}',fitzpatrick_scale:!1,category:"food_and_drink"},bagel:{keywords:["food","bread","bakery","schmear"],char:'\u{1f96f}',fitzpatrick_scale:!1,category:"food_and_drink"},pretzel:{keywords:["food","bread","twisted"],char:'\u{1f968}',fitzpatrick_scale:!1,category:"food_and_drink"},cheese:{keywords:["food","chadder"],char:'\u{1f9c0}',fitzpatrick_scale:!1,category:"food_and_drink"},egg:{keywords:["food","chicken","breakfast"],char:'\u{1f95a}',fitzpatrick_scale:!1,category:"food_and_drink"},bacon:{keywords:["food","breakfast","pork","pig","meat"],char:'\u{1f953}',fitzpatrick_scale:!1,category:"food_and_drink"},steak:{keywords:["food","cow","meat","cut","chop","lambchop","porkchop"],char:'\u{1f969}',fitzpatrick_scale:!1,category:"food_and_drink"},pancakes:{keywords:["food","breakfast","flapjacks","hotcakes"],char:'\u{1f95e}',fitzpatrick_scale:!1,category:"food_and_drink"},poultry_leg:{keywords:["food","meat","drumstick","bird","chicken","turkey"],char:'\u{1f357}',fitzpatrick_scale:!1,category:"food_and_drink"},meat_on_bone:{keywords:["good","food","drumstick"],char:'\u{1f356}',fitzpatrick_scale:!1,category:"food_and_drink"},bone:{keywords:["skeleton"],char:'\u{1f9b4}',fitzpatrick_scale:!1,category:"food_and_drink"},fried_shrimp:{keywords:["food","animal","appetizer","summer"],char:'\u{1f364}',fitzpatrick_scale:!1,category:"food_and_drink"},fried_egg:{keywords:["food","breakfast","kitchen","egg"],char:'\u{1f373}',fitzpatrick_scale:!1,category:"food_and_drink"},hamburger:{keywords:["meat","fast food","beef","cheeseburger","mcdonalds","burger king"],char:'\u{1f354}',fitzpatrick_scale:!1,category:"food_and_drink"},fries:{keywords:["chips","snack","fast food"],char:'\u{1f35f}',fitzpatrick_scale:!1,category:"food_and_drink"},stuffed_flatbread:{keywords:["food","flatbread","stuffed","gyro"],char:'\u{1f959}',fitzpatrick_scale:!1,category:"food_and_drink"},hotdog:{keywords:["food","frankfurter"],char:'\u{1f32d}',fitzpatrick_scale:!1,category:"food_and_drink"},pizza:{keywords:["food","party"],char:'\u{1f355}',fitzpatrick_scale:!1,category:"food_and_drink"},sandwich:{keywords:["food","lunch","bread"],char:'\u{1f96a}',fitzpatrick_scale:!1,category:"food_and_drink"},canned_food:{keywords:["food","soup"],char:'\u{1f96b}',fitzpatrick_scale:!1,category:"food_and_drink"},spaghetti:{keywords:["food","italian","noodle"],char:'\u{1f35d}',fitzpatrick_scale:!1,category:"food_and_drink"},taco:{keywords:["food","mexican"],char:'\u{1f32e}',fitzpatrick_scale:!1,category:"food_and_drink"},burrito:{keywords:["food","mexican"],char:'\u{1f32f}',fitzpatrick_scale:!1,category:"food_and_drink"},green_salad:{keywords:["food","healthy","lettuce"],char:'\u{1f957}',fitzpatrick_scale:!1,category:"food_and_drink"},shallow_pan_of_food:{keywords:["food","cooking","casserole","paella"],char:'\u{1f958}',fitzpatrick_scale:!1,category:"food_and_drink"},ramen:{keywords:["food","japanese","noodle","chopsticks"],char:'\u{1f35c}',fitzpatrick_scale:!1,category:"food_and_drink"},stew:{keywords:["food","meat","soup"],char:'\u{1f372}',fitzpatrick_scale:!1,category:"food_and_drink"},fish_cake:{keywords:["food","japan","sea","beach","narutomaki","pink","swirl","kamaboko","surimi","ramen"],char:'\u{1f365}',fitzpatrick_scale:!1,category:"food_and_drink"},fortune_cookie:{keywords:["food","prophecy"],char:'\u{1f960}',fitzpatrick_scale:!1,category:"food_and_drink"},sushi:{keywords:["food","fish","japanese","rice"],char:'\u{1f363}',fitzpatrick_scale:!1,category:"food_and_drink"},bento:{keywords:["food","japanese","box"],char:'\u{1f371}',fitzpatrick_scale:!1,category:"food_and_drink"},curry:{keywords:["food","spicy","hot","indian"],char:'\u{1f35b}',fitzpatrick_scale:!1,category:"food_and_drink"},rice_ball:{keywords:["food","japanese"],char:'\u{1f359}',fitzpatrick_scale:!1,category:"food_and_drink"},rice:{keywords:["food","china","asian"],char:'\u{1f35a}',fitzpatrick_scale:!1,category:"food_and_drink"},rice_cracker:{keywords:["food","japanese"],char:'\u{1f358}',fitzpatrick_scale:!1,category:"food_and_drink"},oden:{keywords:["food","japanese"],char:'\u{1f362}',fitzpatrick_scale:!1,category:"food_and_drink"},dango:{keywords:["food","dessert","sweet","japanese","barbecue","meat"],char:'\u{1f361}',fitzpatrick_scale:!1,category:"food_and_drink"},shaved_ice:{keywords:["hot","dessert","summer"],char:'\u{1f367}',fitzpatrick_scale:!1,category:"food_and_drink"},ice_cream:{keywords:["food","hot","dessert"],char:'\u{1f368}',fitzpatrick_scale:!1,category:"food_and_drink"},icecream:{keywords:["food","hot","dessert","summer"],char:'\u{1f366}',fitzpatrick_scale:!1,category:"food_and_drink"},pie:{keywords:["food","dessert","pastry"],char:'\u{1f967}',fitzpatrick_scale:!1,category:"food_and_drink"},cake:{keywords:["food","dessert"],char:'\u{1f370}',fitzpatrick_scale:!1,category:"food_and_drink"},cupcake:{keywords:["food","dessert","bakery","sweet"],char:'\u{1f9c1}',fitzpatrick_scale:!1,category:"food_and_drink"},moon_cake:{keywords:["food","autumn"],char:'\u{1f96e}',fitzpatrick_scale:!1,category:"food_and_drink"},birthday:{keywords:["food","dessert","cake"],char:'\u{1f382}',fitzpatrick_scale:!1,category:"food_and_drink"},custard:{keywords:["dessert","food"],char:'\u{1f36e}',fitzpatrick_scale:!1,category:"food_and_drink"},candy:{keywords:["snack","dessert","sweet","lolly"],char:'\u{1f36c}',fitzpatrick_scale:!1,category:"food_and_drink"},lollipop:{keywords:["food","snack","candy","sweet"],char:'\u{1f36d}',fitzpatrick_scale:!1,category:"food_and_drink"},chocolate_bar:{keywords:["food","snack","dessert","sweet"],char:'\u{1f36b}',fitzpatrick_scale:!1,category:"food_and_drink"},popcorn:{keywords:["food","movie theater","films","snack"],char:'\u{1f37f}',fitzpatrick_scale:!1,category:"food_and_drink"},dumpling:{keywords:["food","empanada","pierogi","potsticker"],char:'\u{1f95f}',fitzpatrick_scale:!1,category:"food_and_drink"},doughnut:{keywords:["food","dessert","snack","sweet","donut"],char:'\u{1f369}',fitzpatrick_scale:!1,category:"food_and_drink"},cookie:{keywords:["food","snack","oreo","chocolate","sweet","dessert"],char:'\u{1f36a}',fitzpatrick_scale:!1,category:"food_and_drink"},milk_glass:{keywords:["beverage","drink","cow"],char:'\u{1f95b}',fitzpatrick_scale:!1,category:"food_and_drink"},beer:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:'\u{1f37a}',fitzpatrick_scale:!1,category:"food_and_drink"},beers:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:'\u{1f37b}',fitzpatrick_scale:!1,category:"food_and_drink"},clinking_glasses:{keywords:["beverage","drink","party","alcohol","celebrate","cheers","wine","champagne","toast"],char:'\u{1f942}',fitzpatrick_scale:!1,category:"food_and_drink"},wine_glass:{keywords:["drink","beverage","drunk","alcohol","booze"],char:'\u{1f377}',fitzpatrick_scale:!1,category:"food_and_drink"},tumbler_glass:{keywords:["drink","beverage","drunk","alcohol","liquor","booze","bourbon","scotch","whisky","glass","shot"],char:'\u{1f943}',fitzpatrick_scale:!1,category:"food_and_drink"},cocktail:{keywords:["drink","drunk","alcohol","beverage","booze","mojito"],char:'\u{1f378}',fitzpatrick_scale:!1,category:"food_and_drink"},tropical_drink:{keywords:["beverage","cocktail","summer","beach","alcohol","booze","mojito"],char:'\u{1f379}',fitzpatrick_scale:!1,category:"food_and_drink"},champagne:{keywords:["drink","wine","bottle","celebration"],char:'\u{1f37e}',fitzpatrick_scale:!1,category:"food_and_drink"},sake:{keywords:["wine","drink","drunk","beverage","japanese","alcohol","booze"],char:'\u{1f376}',fitzpatrick_scale:!1,category:"food_and_drink"},tea:{keywords:["drink","bowl","breakfast","green","british"],char:'\u{1f375}',fitzpatrick_scale:!1,category:"food_and_drink"},cup_with_straw:{keywords:["drink","soda"],char:'\u{1f964}',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:'\u{1f37c}',fitzpatrick_scale:!1,category:"food_and_drink"},salt:{keywords:["condiment","shaker"],char:'\u{1f9c2}',fitzpatrick_scale:!1,category:"food_and_drink"},spoon:{keywords:["cutlery","kitchen","tableware"],char:'\u{1f944}',fitzpatrick_scale:!1,category:"food_and_drink"},fork_and_knife:{keywords:["cutlery","kitchen"],char:'\u{1f374}',fitzpatrick_scale:!1,category:"food_and_drink"},plate_with_cutlery:{keywords:["food","eat","meal","lunch","dinner","restaurant"],char:'\u{1f37d}',fitzpatrick_scale:!1,category:"food_and_drink"},bowl_with_spoon:{keywords:["food","breakfast","cereal","oatmeal","porridge"],char:'\u{1f963}',fitzpatrick_scale:!1,category:"food_and_drink"},takeout_box:{keywords:["food","leftovers"],char:'\u{1f961}',fitzpatrick_scale:!1,category:"food_and_drink"},chopsticks:{keywords:["food"],char:'\u{1f962}',fitzpatrick_scale:!1,category:"food_and_drink"},soccer:{keywords:["sports","football"],char:'\u26bd',fitzpatrick_scale:!1,category:"activity"},basketball:{keywords:["sports","balls","NBA"],char:'\u{1f3c0}',fitzpatrick_scale:!1,category:"activity"},football:{keywords:["sports","balls","NFL"],char:'\u{1f3c8}',fitzpatrick_scale:!1,category:"activity"},baseball:{keywords:["sports","balls"],char:'\u26be',fitzpatrick_scale:!1,category:"activity"},softball:{keywords:["sports","balls"],char:'\u{1f94e}',fitzpatrick_scale:!1,category:"activity"},tennis:{keywords:["sports","balls","green"],char:'\u{1f3be}',fitzpatrick_scale:!1,category:"activity"},volleyball:{keywords:["sports","balls"],char:'\u{1f3d0}',fitzpatrick_scale:!1,category:"activity"},rugby_football:{keywords:["sports","team"],char:'\u{1f3c9}',fitzpatrick_scale:!1,category:"activity"},flying_disc:{keywords:["sports","frisbee","ultimate"],char:'\u{1f94f}',fitzpatrick_scale:!1,category:"activity"},"8ball":{keywords:["pool","hobby","game","luck","magic"],char:'\u{1f3b1}',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:'\u{1f3cc}\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"activity"},golfing_man:{keywords:["sports","business"],char:'\u{1f3cc}',fitzpatrick_scale:!0,category:"activity"},ping_pong:{keywords:["sports","pingpong"],char:'\u{1f3d3}',fitzpatrick_scale:!1,category:"activity"},badminton:{keywords:["sports"],char:'\u{1f3f8}',fitzpatrick_scale:!1,category:"activity"},goal_net:{keywords:["sports"],char:'\u{1f945}',fitzpatrick_scale:!1,category:"activity"},ice_hockey:{keywords:["sports"],char:'\u{1f3d2}',fitzpatrick_scale:!1,category:"activity"},field_hockey:{keywords:["sports"],char:'\u{1f3d1}',fitzpatrick_scale:!1,category:"activity"},lacrosse:{keywords:["sports","ball","stick"],char:'\u{1f94d}',fitzpatrick_scale:!1,category:"activity"},cricket:{keywords:["sports"],char:'\u{1f3cf}',fitzpatrick_scale:!1,category:"activity"},ski:{keywords:["sports","winter","cold","snow"],char:'\u{1f3bf}',fitzpatrick_scale:!1,category:"activity"},skier:{keywords:["sports","winter","snow"],char:'\u26f7',fitzpatrick_scale:!1,category:"activity"},snowboarder:{keywords:["sports","winter"],char:'\u{1f3c2}',fitzpatrick_scale:!0,category:"activity"},person_fencing:{keywords:["sports","fencing","sword"],char:'\u{1f93a}',fitzpatrick_scale:!1,category:"activity"},women_wrestling:{keywords:["sports","wrestlers"],char:'\u{1f93c}\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"activity"},men_wrestling:{keywords:["sports","wrestlers"],char:'\u{1f93c}\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"activity"},woman_cartwheeling:{keywords:["gymnastics"],char:'\u{1f938}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_cartwheeling:{keywords:["gymnastics"],char:'\u{1f938}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},woman_playing_handball:{keywords:["sports"],char:'\u{1f93e}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_playing_handball:{keywords:["sports"],char:'\u{1f93e}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},ice_skate:{keywords:["sports"],char:'\u26f8',fitzpatrick_scale:!1,category:"activity"},curling_stone:{keywords:["sports"],char:'\u{1f94c}',fitzpatrick_scale:!1,category:"activity"},skateboard:{keywords:["board"],char:'\u{1f6f9}',fitzpatrick_scale:!1,category:"activity"},sled:{keywords:["sleigh","luge","toboggan"],char:'\u{1f6f7}',fitzpatrick_scale:!1,category:"activity"},bow_and_arrow:{keywords:["sports"],char:'\u{1f3f9}',fitzpatrick_scale:!1,category:"activity"},fishing_pole_and_fish:{keywords:["food","hobby","summer"],char:'\u{1f3a3}',fitzpatrick_scale:!1,category:"activity"},boxing_glove:{keywords:["sports","fighting"],char:'\u{1f94a}',fitzpatrick_scale:!1,category:"activity"},martial_arts_uniform:{keywords:["judo","karate","taekwondo"],char:'\u{1f94b}',fitzpatrick_scale:!1,category:"activity"},rowing_woman:{keywords:["sports","hobby","water","ship","woman","female"],char:'\u{1f6a3}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},rowing_man:{keywords:["sports","hobby","water","ship"],char:'\u{1f6a3}',fitzpatrick_scale:!0,category:"activity"},climbing_woman:{keywords:["sports","hobby","woman","female","rock"],char:'\u{1f9d7}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},climbing_man:{keywords:["sports","hobby","man","male","rock"],char:'\u{1f9d7}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},swimming_woman:{keywords:["sports","exercise","human","athlete","water","summer","woman","female"],char:'\u{1f3ca}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},swimming_man:{keywords:["sports","exercise","human","athlete","water","summer"],char:'\u{1f3ca}',fitzpatrick_scale:!0,category:"activity"},woman_playing_water_polo:{keywords:["sports","pool"],char:'\u{1f93d}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_playing_water_polo:{keywords:["sports","pool"],char:'\u{1f93d}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},woman_in_lotus_position:{keywords:["woman","female","meditation","yoga","serenity","zen","mindfulness"],char:'\u{1f9d8}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_in_lotus_position:{keywords:["man","male","meditation","yoga","serenity","zen","mindfulness"],char:'\u{1f9d8}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},surfing_woman:{keywords:["sports","ocean","sea","summer","beach","woman","female"],char:'\u{1f3c4}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},surfing_man:{keywords:["sports","ocean","sea","summer","beach"],char:'\u{1f3c4}',fitzpatrick_scale:!0,category:"activity"},bath:{keywords:["clean","shower","bathroom"],char:'\u{1f6c0}',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:'\u{1f3cb}\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},weight_lifting_man:{keywords:["sports","training","exercise"],char:'\u{1f3cb}',fitzpatrick_scale:!0,category:"activity"},biking_woman:{keywords:["sports","bike","exercise","hipster","woman","female"],char:'\u{1f6b4}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},biking_man:{keywords:["sports","bike","exercise","hipster"],char:'\u{1f6b4}',fitzpatrick_scale:!0,category:"activity"},mountain_biking_woman:{keywords:["transportation","sports","human","race","bike","woman","female"],char:'\u{1f6b5}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},mountain_biking_man:{keywords:["transportation","sports","human","race","bike"],char:'\u{1f6b5}',fitzpatrick_scale:!0,category:"activity"},horse_racing:{keywords:["animal","betting","competition","gambling","luck"],char:'\u{1f3c7}',fitzpatrick_scale:!0,category:"activity"},business_suit_levitating:{keywords:["suit","business","levitate","hover","jump"],char:'\u{1f574}',fitzpatrick_scale:!0,category:"activity"},trophy:{keywords:["win","award","contest","place","ftw","ceremony"],char:'\u{1f3c6}',fitzpatrick_scale:!1,category:"activity"},running_shirt_with_sash:{keywords:["play","pageant"],char:'\u{1f3bd}',fitzpatrick_scale:!1,category:"activity"},medal_sports:{keywords:["award","winning"],char:'\u{1f3c5}',fitzpatrick_scale:!1,category:"activity"},medal_military:{keywords:["award","winning","army"],char:'\u{1f396}',fitzpatrick_scale:!1,category:"activity"},"1st_place_medal":{keywords:["award","winning","first"],char:'\u{1f947}',fitzpatrick_scale:!1,category:"activity"},"2nd_place_medal":{keywords:["award","second"],char:'\u{1f948}',fitzpatrick_scale:!1,category:"activity"},"3rd_place_medal":{keywords:["award","third"],char:'\u{1f949}',fitzpatrick_scale:!1,category:"activity"},reminder_ribbon:{keywords:["sports","cause","support","awareness"],char:'\u{1f397}',fitzpatrick_scale:!1,category:"activity"},rosette:{keywords:["flower","decoration","military"],char:'\u{1f3f5}',fitzpatrick_scale:!1,category:"activity"},ticket:{keywords:["event","concert","pass"],char:'\u{1f3ab}',fitzpatrick_scale:!1,category:"activity"},tickets:{keywords:["sports","concert","entrance"],char:'\u{1f39f}',fitzpatrick_scale:!1,category:"activity"},performing_arts:{keywords:["acting","theater","drama"],char:'\u{1f3ad}',fitzpatrick_scale:!1,category:"activity"},art:{keywords:["design","paint","draw","colors"],char:'\u{1f3a8}',fitzpatrick_scale:!1,category:"activity"},circus_tent:{keywords:["festival","carnival","party"],char:'\u{1f3aa}',fitzpatrick_scale:!1,category:"activity"},woman_juggling:{keywords:["juggle","balance","skill","multitask"],char:'\u{1f939}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_juggling:{keywords:["juggle","balance","skill","multitask"],char:'\u{1f939}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},microphone:{keywords:["sound","music","PA","sing","talkshow"],char:'\u{1f3a4}',fitzpatrick_scale:!1,category:"activity"},headphones:{keywords:["music","score","gadgets"],char:'\u{1f3a7}',fitzpatrick_scale:!1,category:"activity"},musical_score:{keywords:["treble","clef","compose"],char:'\u{1f3bc}',fitzpatrick_scale:!1,category:"activity"},musical_keyboard:{keywords:["piano","instrument","compose"],char:'\u{1f3b9}',fitzpatrick_scale:!1,category:"activity"},drum:{keywords:["music","instrument","drumsticks","snare"],char:'\u{1f941}',fitzpatrick_scale:!1,category:"activity"},saxophone:{keywords:["music","instrument","jazz","blues"],char:'\u{1f3b7}',fitzpatrick_scale:!1,category:"activity"},trumpet:{keywords:["music","brass"],char:'\u{1f3ba}',fitzpatrick_scale:!1,category:"activity"},guitar:{keywords:["music","instrument"],char:'\u{1f3b8}',fitzpatrick_scale:!1,category:"activity"},violin:{keywords:["music","instrument","orchestra","symphony"],char:'\u{1f3bb}',fitzpatrick_scale:!1,category:"activity"},clapper:{keywords:["movie","film","record"],char:'\u{1f3ac}',fitzpatrick_scale:!1,category:"activity"},video_game:{keywords:["play","console","PS4","controller"],char:'\u{1f3ae}',fitzpatrick_scale:!1,category:"activity"},space_invader:{keywords:["game","arcade","play"],char:'\u{1f47e}',fitzpatrick_scale:!1,category:"activity"},dart:{keywords:["game","play","bar","target","bullseye"],char:'\u{1f3af}',fitzpatrick_scale:!1,category:"activity"},game_die:{keywords:["dice","random","tabletop","play","luck"],char:'\u{1f3b2}',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:'\u{1f3b0}',fitzpatrick_scale:!1,category:"activity"},jigsaw:{keywords:["interlocking","puzzle","piece"],char:'\u{1f9e9}',fitzpatrick_scale:!1,category:"activity"},bowling:{keywords:["sports","fun","play"],char:'\u{1f3b3}',fitzpatrick_scale:!1,category:"activity"},red_car:{keywords:["red","transportation","vehicle"],char:'\u{1f697}',fitzpatrick_scale:!1,category:"travel_and_places"},taxi:{keywords:["uber","vehicle","cars","transportation"],char:'\u{1f695}',fitzpatrick_scale:!1,category:"travel_and_places"},blue_car:{keywords:["transportation","vehicle"],char:'\u{1f699}',fitzpatrick_scale:!1,category:"travel_and_places"},bus:{keywords:["car","vehicle","transportation"],char:'\u{1f68c}',fitzpatrick_scale:!1,category:"travel_and_places"},trolleybus:{keywords:["bart","transportation","vehicle"],char:'\u{1f68e}',fitzpatrick_scale:!1,category:"travel_and_places"},racing_car:{keywords:["sports","race","fast","formula","f1"],char:'\u{1f3ce}',fitzpatrick_scale:!1,category:"travel_and_places"},police_car:{keywords:["vehicle","cars","transportation","law","legal","enforcement"],char:'\u{1f693}',fitzpatrick_scale:!1,category:"travel_and_places"},ambulance:{keywords:["health","911","hospital"],char:'\u{1f691}',fitzpatrick_scale:!1,category:"travel_and_places"},fire_engine:{keywords:["transportation","cars","vehicle"],char:'\u{1f692}',fitzpatrick_scale:!1,category:"travel_and_places"},minibus:{keywords:["vehicle","car","transportation"],char:'\u{1f690}',fitzpatrick_scale:!1,category:"travel_and_places"},truck:{keywords:["cars","transportation"],char:'\u{1f69a}',fitzpatrick_scale:!1,category:"travel_and_places"},articulated_lorry:{keywords:["vehicle","cars","transportation","express"],char:'\u{1f69b}',fitzpatrick_scale:!1,category:"travel_and_places"},tractor:{keywords:["vehicle","car","farming","agriculture"],char:'\u{1f69c}',fitzpatrick_scale:!1,category:"travel_and_places"},kick_scooter:{keywords:["vehicle","kick","razor"],char:'\u{1f6f4}',fitzpatrick_scale:!1,category:"travel_and_places"},motorcycle:{keywords:["race","sports","fast"],char:'\u{1f3cd}',fitzpatrick_scale:!1,category:"travel_and_places"},bike:{keywords:["sports","bicycle","exercise","hipster"],char:'\u{1f6b2}',fitzpatrick_scale:!1,category:"travel_and_places"},motor_scooter:{keywords:["vehicle","vespa","sasha"],char:'\u{1f6f5}',fitzpatrick_scale:!1,category:"travel_and_places"},rotating_light:{keywords:["police","ambulance","911","emergency","alert","error","pinged","law","legal"],char:'\u{1f6a8}',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_police_car:{keywords:["vehicle","law","legal","enforcement","911"],char:'\u{1f694}',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_bus:{keywords:["vehicle","transportation"],char:'\u{1f68d}',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_automobile:{keywords:["car","vehicle","transportation"],char:'\u{1f698}',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_taxi:{keywords:["vehicle","cars","uber"],char:'\u{1f696}',fitzpatrick_scale:!1,category:"travel_and_places"},aerial_tramway:{keywords:["transportation","vehicle","ski"],char:'\u{1f6a1}',fitzpatrick_scale:!1,category:"travel_and_places"},mountain_cableway:{keywords:["transportation","vehicle","ski"],char:'\u{1f6a0}',fitzpatrick_scale:!1,category:"travel_and_places"},suspension_railway:{keywords:["vehicle","transportation"],char:'\u{1f69f}',fitzpatrick_scale:!1,category:"travel_and_places"},railway_car:{keywords:["transportation","vehicle"],char:'\u{1f683}',fitzpatrick_scale:!1,category:"travel_and_places"},train:{keywords:["transportation","vehicle","carriage","public","travel"],char:'\u{1f68b}',fitzpatrick_scale:!1,category:"travel_and_places"},monorail:{keywords:["transportation","vehicle"],char:'\u{1f69d}',fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_side:{keywords:["transportation","vehicle"],char:'\u{1f684}',fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_front:{keywords:["transportation","vehicle","speed","fast","public","travel"],char:'\u{1f685}',fitzpatrick_scale:!1,category:"travel_and_places"},light_rail:{keywords:["transportation","vehicle"],char:'\u{1f688}',fitzpatrick_scale:!1,category:"travel_and_places"},mountain_railway:{keywords:["transportation","vehicle"],char:'\u{1f69e}',fitzpatrick_scale:!1,category:"travel_and_places"},steam_locomotive:{keywords:["transportation","vehicle","train"],char:'\u{1f682}',fitzpatrick_scale:!1,category:"travel_and_places"},train2:{keywords:["transportation","vehicle"],char:'\u{1f686}',fitzpatrick_scale:!1,category:"travel_and_places"},metro:{keywords:["transportation","blue-square","mrt","underground","tube"],char:'\u{1f687}',fitzpatrick_scale:!1,category:"travel_and_places"},tram:{keywords:["transportation","vehicle"],char:'\u{1f68a}',fitzpatrick_scale:!1,category:"travel_and_places"},station:{keywords:["transportation","vehicle","public"],char:'\u{1f689}',fitzpatrick_scale:!1,category:"travel_and_places"},flying_saucer:{keywords:["transportation","vehicle","ufo"],char:'\u{1f6f8}',fitzpatrick_scale:!1,category:"travel_and_places"},helicopter:{keywords:["transportation","vehicle","fly"],char:'\u{1f681}',fitzpatrick_scale:!1,category:"travel_and_places"},small_airplane:{keywords:["flight","transportation","fly","vehicle"],char:'\u{1f6e9}',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:'\u{1f6eb}',fitzpatrick_scale:!1,category:"travel_and_places"},flight_arrival:{keywords:["airport","flight","boarding"],char:'\u{1f6ec}',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:'\u{1f6e5}',fitzpatrick_scale:!1,category:"travel_and_places"},speedboat:{keywords:["ship","transportation","vehicle","summer"],char:'\u{1f6a4}',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:'\u{1f6f3}',fitzpatrick_scale:!1,category:"travel_and_places"},rocket:{keywords:["launch","ship","staffmode","NASA","outer space","outer_space","fly"],char:'\u{1f680}',fitzpatrick_scale:!1,category:"travel_and_places"},artificial_satellite:{keywords:["communication","gps","orbit","spaceflight","NASA","ISS"],char:'\u{1f6f0}',fitzpatrick_scale:!1,category:"travel_and_places"},seat:{keywords:["sit","airplane","transport","bus","flight","fly"],char:'\u{1f4ba}',fitzpatrick_scale:!1,category:"travel_and_places"},canoe:{keywords:["boat","paddle","water","ship"],char:'\u{1f6f6}',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:'\u{1f6a7}',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:'\u{1f68f}',fitzpatrick_scale:!1,category:"travel_and_places"},vertical_traffic_light:{keywords:["transportation","driving"],char:'\u{1f6a6}',fitzpatrick_scale:!1,category:"travel_and_places"},traffic_light:{keywords:["transportation","signal"],char:'\u{1f6a5}',fitzpatrick_scale:!1,category:"travel_and_places"},checkered_flag:{keywords:["contest","finishline","race","gokart"],char:'\u{1f3c1}',fitzpatrick_scale:!1,category:"travel_and_places"},ship:{keywords:["transportation","titanic","deploy"],char:'\u{1f6a2}',fitzpatrick_scale:!1,category:"travel_and_places"},ferris_wheel:{keywords:["photo","carnival","londoneye"],char:'\u{1f3a1}',fitzpatrick_scale:!1,category:"travel_and_places"},roller_coaster:{keywords:["carnival","playground","photo","fun"],char:'\u{1f3a2}',fitzpatrick_scale:!1,category:"travel_and_places"},carousel_horse:{keywords:["photo","carnival"],char:'\u{1f3a0}',fitzpatrick_scale:!1,category:"travel_and_places"},building_construction:{keywords:["wip","working","progress"],char:'\u{1f3d7}',fitzpatrick_scale:!1,category:"travel_and_places"},foggy:{keywords:["photo","mountain"],char:'\u{1f301}',fitzpatrick_scale:!1,category:"travel_and_places"},tokyo_tower:{keywords:["photo","japanese"],char:'\u{1f5fc}',fitzpatrick_scale:!1,category:"travel_and_places"},factory:{keywords:["building","industry","pollution","smoke"],char:'\u{1f3ed}',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:'\u{1f391}',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:'\u{1f3d4}',fitzpatrick_scale:!1,category:"travel_and_places"},mount_fuji:{keywords:["photo","mountain","nature","japanese"],char:'\u{1f5fb}',fitzpatrick_scale:!1,category:"travel_and_places"},volcano:{keywords:["photo","nature","disaster"],char:'\u{1f30b}',fitzpatrick_scale:!1,category:"travel_and_places"},japan:{keywords:["nation","country","japanese","asia"],char:'\u{1f5fe}',fitzpatrick_scale:!1,category:"travel_and_places"},camping:{keywords:["photo","outdoors","tent"],char:'\u{1f3d5}',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:'\u{1f3de}',fitzpatrick_scale:!1,category:"travel_and_places"},motorway:{keywords:["road","cupertino","interstate","highway"],char:'\u{1f6e3}',fitzpatrick_scale:!1,category:"travel_and_places"},railway_track:{keywords:["train","transportation"],char:'\u{1f6e4}',fitzpatrick_scale:!1,category:"travel_and_places"},sunrise:{keywords:["morning","view","vacation","photo"],char:'\u{1f305}',fitzpatrick_scale:!1,category:"travel_and_places"},sunrise_over_mountains:{keywords:["view","vacation","photo"],char:'\u{1f304}',fitzpatrick_scale:!1,category:"travel_and_places"},desert:{keywords:["photo","warm","saharah"],char:'\u{1f3dc}',fitzpatrick_scale:!1,category:"travel_and_places"},beach_umbrella:{keywords:["weather","summer","sunny","sand","mojito"],char:'\u{1f3d6}',fitzpatrick_scale:!1,category:"travel_and_places"},desert_island:{keywords:["photo","tropical","mojito"],char:'\u{1f3dd}',fitzpatrick_scale:!1,category:"travel_and_places"},city_sunrise:{keywords:["photo","good morning","dawn"],char:'\u{1f307}',fitzpatrick_scale:!1,category:"travel_and_places"},city_sunset:{keywords:["photo","evening","sky","buildings"],char:'\u{1f306}',fitzpatrick_scale:!1,category:"travel_and_places"},cityscape:{keywords:["photo","night life","urban"],char:'\u{1f3d9}',fitzpatrick_scale:!1,category:"travel_and_places"},night_with_stars:{keywords:["evening","city","downtown"],char:'\u{1f303}',fitzpatrick_scale:!1,category:"travel_and_places"},bridge_at_night:{keywords:["photo","sanfrancisco"],char:'\u{1f309}',fitzpatrick_scale:!1,category:"travel_and_places"},milky_way:{keywords:["photo","space","stars"],char:'\u{1f30c}',fitzpatrick_scale:!1,category:"travel_and_places"},stars:{keywords:["night","photo"],char:'\u{1f320}',fitzpatrick_scale:!1,category:"travel_and_places"},sparkler:{keywords:["stars","night","shine"],char:'\u{1f387}',fitzpatrick_scale:!1,category:"travel_and_places"},fireworks:{keywords:["photo","festival","carnival","congratulations"],char:'\u{1f386}',fitzpatrick_scale:!1,category:"travel_and_places"},rainbow:{keywords:["nature","happy","unicorn_face","photo","sky","spring"],char:'\u{1f308}',fitzpatrick_scale:!1,category:"travel_and_places"},houses:{keywords:["buildings","photo"],char:'\u{1f3d8}',fitzpatrick_scale:!1,category:"travel_and_places"},european_castle:{keywords:["building","royalty","history"],char:'\u{1f3f0}',fitzpatrick_scale:!1,category:"travel_and_places"},japanese_castle:{keywords:["photo","building"],char:'\u{1f3ef}',fitzpatrick_scale:!1,category:"travel_and_places"},stadium:{keywords:["photo","place","sports","concert","venue"],char:'\u{1f3df}',fitzpatrick_scale:!1,category:"travel_and_places"},statue_of_liberty:{keywords:["american","newyork"],char:'\u{1f5fd}',fitzpatrick_scale:!1,category:"travel_and_places"},house:{keywords:["building","home"],char:'\u{1f3e0}',fitzpatrick_scale:!1,category:"travel_and_places"},house_with_garden:{keywords:["home","plant","nature"],char:'\u{1f3e1}',fitzpatrick_scale:!1,category:"travel_and_places"},derelict_house:{keywords:["abandon","evict","broken","building"],char:'\u{1f3da}',fitzpatrick_scale:!1,category:"travel_and_places"},office:{keywords:["building","bureau","work"],char:'\u{1f3e2}',fitzpatrick_scale:!1,category:"travel_and_places"},department_store:{keywords:["building","shopping","mall"],char:'\u{1f3ec}',fitzpatrick_scale:!1,category:"travel_and_places"},post_office:{keywords:["building","envelope","communication"],char:'\u{1f3e3}',fitzpatrick_scale:!1,category:"travel_and_places"},european_post_office:{keywords:["building","email"],char:'\u{1f3e4}',fitzpatrick_scale:!1,category:"travel_and_places"},hospital:{keywords:["building","health","surgery","doctor"],char:'\u{1f3e5}',fitzpatrick_scale:!1,category:"travel_and_places"},bank:{keywords:["building","money","sales","cash","business","enterprise"],char:'\u{1f3e6}',fitzpatrick_scale:!1,category:"travel_and_places"},hotel:{keywords:["building","accomodation","checkin"],char:'\u{1f3e8}',fitzpatrick_scale:!1,category:"travel_and_places"},convenience_store:{keywords:["building","shopping","groceries"],char:'\u{1f3ea}',fitzpatrick_scale:!1,category:"travel_and_places"},school:{keywords:["building","student","education","learn","teach"],char:'\u{1f3eb}',fitzpatrick_scale:!1,category:"travel_and_places"},love_hotel:{keywords:["like","affection","dating"],char:'\u{1f3e9}',fitzpatrick_scale:!1,category:"travel_and_places"},wedding:{keywords:["love","like","affection","couple","marriage","bride","groom"],char:'\u{1f492}',fitzpatrick_scale:!1,category:"travel_and_places"},classical_building:{keywords:["art","culture","history"],char:'\u{1f3db}',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:'\u{1f54c}',fitzpatrick_scale:!1,category:"travel_and_places"},synagogue:{keywords:["judaism","worship","temple","jewish"],char:'\u{1f54d}',fitzpatrick_scale:!1,category:"travel_and_places"},kaaba:{keywords:["mecca","mosque","islam"],char:'\u{1f54b}',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:'\u{1f4f1}',fitzpatrick_scale:!1,category:"objects"},calling:{keywords:["iphone","incoming"],char:'\u{1f4f2}',fitzpatrick_scale:!1,category:"objects"},computer:{keywords:["technology","laptop","screen","display","monitor"],char:'\u{1f4bb}',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:'\u{1f5a5}',fitzpatrick_scale:!1,category:"objects"},printer:{keywords:["paper","ink"],char:'\u{1f5a8}',fitzpatrick_scale:!1,category:"objects"},computer_mouse:{keywords:["click"],char:'\u{1f5b1}',fitzpatrick_scale:!1,category:"objects"},trackball:{keywords:["technology","trackpad"],char:'\u{1f5b2}',fitzpatrick_scale:!1,category:"objects"},joystick:{keywords:["game","play"],char:'\u{1f579}',fitzpatrick_scale:!1,category:"objects"},clamp:{keywords:["tool"],char:'\u{1f5dc}',fitzpatrick_scale:!1,category:"objects"},minidisc:{keywords:["technology","record","data","disk","90s"],char:'\u{1f4bd}',fitzpatrick_scale:!1,category:"objects"},floppy_disk:{keywords:["oldschool","technology","save","90s","80s"],char:'\u{1f4be}',fitzpatrick_scale:!1,category:"objects"},cd:{keywords:["technology","dvd","disk","disc","90s"],char:'\u{1f4bf}',fitzpatrick_scale:!1,category:"objects"},dvd:{keywords:["cd","disk","disc"],char:'\u{1f4c0}',fitzpatrick_scale:!1,category:"objects"},vhs:{keywords:["record","video","oldschool","90s","80s"],char:'\u{1f4fc}',fitzpatrick_scale:!1,category:"objects"},camera:{keywords:["gadgets","photography"],char:'\u{1f4f7}',fitzpatrick_scale:!1,category:"objects"},camera_flash:{keywords:["photography","gadgets"],char:'\u{1f4f8}',fitzpatrick_scale:!1,category:"objects"},video_camera:{keywords:["film","record"],char:'\u{1f4f9}',fitzpatrick_scale:!1,category:"objects"},movie_camera:{keywords:["film","record"],char:'\u{1f3a5}',fitzpatrick_scale:!1,category:"objects"},film_projector:{keywords:["video","tape","record","movie"],char:'\u{1f4fd}',fitzpatrick_scale:!1,category:"objects"},film_strip:{keywords:["movie"],char:'\u{1f39e}',fitzpatrick_scale:!1,category:"objects"},telephone_receiver:{keywords:["technology","communication","dial"],char:'\u{1f4de}',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:'\u{1f4df}',fitzpatrick_scale:!1,category:"objects"},fax:{keywords:["communication","technology"],char:'\u{1f4e0}',fitzpatrick_scale:!1,category:"objects"},tv:{keywords:["technology","program","oldschool","show","television"],char:'\u{1f4fa}',fitzpatrick_scale:!1,category:"objects"},radio:{keywords:["communication","music","podcast","program"],char:'\u{1f4fb}',fitzpatrick_scale:!1,category:"objects"},studio_microphone:{keywords:["sing","recording","artist","talkshow"],char:'\u{1f399}',fitzpatrick_scale:!1,category:"objects"},level_slider:{keywords:["scale"],char:'\u{1f39a}',fitzpatrick_scale:!1,category:"objects"},control_knobs:{keywords:["dial"],char:'\u{1f39b}',fitzpatrick_scale:!1,category:"objects"},compass:{keywords:["magnetic","navigation","orienteering"],char:'\u{1f9ed}',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:'\u{1f570}',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:'\u{1f4e1}',fitzpatrick_scale:!1,category:"objects"},battery:{keywords:["power","energy","sustain"],char:'\u{1f50b}',fitzpatrick_scale:!1,category:"objects"},electric_plug:{keywords:["charger","power"],char:'\u{1f50c}',fitzpatrick_scale:!1,category:"objects"},bulb:{keywords:["light","electricity","idea"],char:'\u{1f4a1}',fitzpatrick_scale:!1,category:"objects"},flashlight:{keywords:["dark","camping","sight","night"],char:'\u{1f526}',fitzpatrick_scale:!1,category:"objects"},candle:{keywords:["fire","wax"],char:'\u{1f56f}',fitzpatrick_scale:!1,category:"objects"},fire_extinguisher:{keywords:["quench"],char:'\u{1f9ef}',fitzpatrick_scale:!1,category:"objects"},wastebasket:{keywords:["bin","trash","rubbish","garbage","toss"],char:'\u{1f5d1}',fitzpatrick_scale:!1,category:"objects"},oil_drum:{keywords:["barrell"],char:'\u{1f6e2}',fitzpatrick_scale:!1,category:"objects"},money_with_wings:{keywords:["dollar","bills","payment","sale"],char:'\u{1f4b8}',fitzpatrick_scale:!1,category:"objects"},dollar:{keywords:["money","sales","bill","currency"],char:'\u{1f4b5}',fitzpatrick_scale:!1,category:"objects"},yen:{keywords:["money","sales","japanese","dollar","currency"],char:'\u{1f4b4}',fitzpatrick_scale:!1,category:"objects"},euro:{keywords:["money","sales","dollar","currency"],char:'\u{1f4b6}',fitzpatrick_scale:!1,category:"objects"},pound:{keywords:["british","sterling","money","sales","bills","uk","england","currency"],char:'\u{1f4b7}',fitzpatrick_scale:!1,category:"objects"},moneybag:{keywords:["dollar","payment","coins","sale"],char:'\u{1f4b0}',fitzpatrick_scale:!1,category:"objects"},credit_card:{keywords:["money","sales","dollar","bill","payment","shopping"],char:'\u{1f4b3}',fitzpatrick_scale:!1,category:"objects"},gem:{keywords:["blue","ruby","diamond","jewelry"],char:'\u{1f48e}',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:'\u{1f9f0}',fitzpatrick_scale:!1,category:"objects"},wrench:{keywords:["tools","diy","ikea","fix","maintainer"],char:'\u{1f527}',fitzpatrick_scale:!1,category:"objects"},hammer:{keywords:["tools","build","create"],char:'\u{1f528}',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:'\u{1f6e0}',fitzpatrick_scale:!1,category:"objects"},pick:{keywords:["tools","dig"],char:'\u26cf',fitzpatrick_scale:!1,category:"objects"},nut_and_bolt:{keywords:["handy","tools","fix"],char:'\u{1f529}',fitzpatrick_scale:!1,category:"objects"},gear:{keywords:["cog"],char:'\u2699',fitzpatrick_scale:!1,category:"objects"},brick:{keywords:["bricks"],char:'\u{1f9f1}',fitzpatrick_scale:!1,category:"objects"},chains:{keywords:["lock","arrest"],char:'\u26d3',fitzpatrick_scale:!1,category:"objects"},magnet:{keywords:["attraction","magnetic"],char:'\u{1f9f2}',fitzpatrick_scale:!1,category:"objects"},gun:{keywords:["violence","weapon","pistol","revolver"],char:'\u{1f52b}',fitzpatrick_scale:!1,category:"objects"},bomb:{keywords:["boom","explode","explosion","terrorism"],char:'\u{1f4a3}',fitzpatrick_scale:!1,category:"objects"},firecracker:{keywords:["dynamite","boom","explode","explosion","explosive"],char:'\u{1f9e8}',fitzpatrick_scale:!1,category:"objects"},hocho:{keywords:["knife","blade","cutlery","kitchen","weapon"],char:'\u{1f52a}',fitzpatrick_scale:!1,category:"objects"},dagger:{keywords:["weapon"],char:'\u{1f5e1}',fitzpatrick_scale:!1,category:"objects"},crossed_swords:{keywords:["weapon"],char:'\u2694',fitzpatrick_scale:!1,category:"objects"},shield:{keywords:["protection","security"],char:'\u{1f6e1}',fitzpatrick_scale:!1,category:"objects"},smoking:{keywords:["kills","tobacco","cigarette","joint","smoke"],char:'\u{1f6ac}',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:'\u{1f3fa}',fitzpatrick_scale:!1,category:"objects"},crystal_ball:{keywords:["disco","party","magic","circus","fortune_teller"],char:'\u{1f52e}',fitzpatrick_scale:!1,category:"objects"},prayer_beads:{keywords:["dhikr","religious"],char:'\u{1f4ff}',fitzpatrick_scale:!1,category:"objects"},nazar_amulet:{keywords:["bead","charm"],char:'\u{1f9ff}',fitzpatrick_scale:!1,category:"objects"},barber:{keywords:["hair","salon","style"],char:'\u{1f488}',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:'\u{1f52d}',fitzpatrick_scale:!1,category:"objects"},microscope:{keywords:["laboratory","experiment","zoomin","science","study"],char:'\u{1f52c}',fitzpatrick_scale:!1,category:"objects"},hole:{keywords:["embarrassing"],char:'\u{1f573}',fitzpatrick_scale:!1,category:"objects"},pill:{keywords:["health","medicine","doctor","pharmacy","drug"],char:'\u{1f48a}',fitzpatrick_scale:!1,category:"objects"},syringe:{keywords:["health","hospital","drugs","blood","medicine","needle","doctor","nurse"],char:'\u{1f489}',fitzpatrick_scale:!1,category:"objects"},dna:{keywords:["biologist","genetics","life"],char:'\u{1f9ec}',fitzpatrick_scale:!1,category:"objects"},microbe:{keywords:["amoeba","bacteria","germs"],char:'\u{1f9a0}',fitzpatrick_scale:!1,category:"objects"},petri_dish:{keywords:["bacteria","biology","culture","lab"],char:'\u{1f9eb}',fitzpatrick_scale:!1,category:"objects"},test_tube:{keywords:["chemistry","experiment","lab","science"],char:'\u{1f9ea}',fitzpatrick_scale:!1,category:"objects"},thermometer:{keywords:["weather","temperature","hot","cold"],char:'\u{1f321}',fitzpatrick_scale:!1,category:"objects"},broom:{keywords:["cleaning","sweeping","witch"],char:'\u{1f9f9}',fitzpatrick_scale:!1,category:"objects"},basket:{keywords:["laundry"],char:'\u{1f9fa}',fitzpatrick_scale:!1,category:"objects"},toilet_paper:{keywords:["roll"],char:'\u{1f9fb}',fitzpatrick_scale:!1,category:"objects"},label:{keywords:["sale","tag"],char:'\u{1f3f7}',fitzpatrick_scale:!1,category:"objects"},bookmark:{keywords:["favorite","label","save"],char:'\u{1f516}',fitzpatrick_scale:!1,category:"objects"},toilet:{keywords:["restroom","wc","washroom","bathroom","potty"],char:'\u{1f6bd}',fitzpatrick_scale:!1,category:"objects"},shower:{keywords:["clean","water","bathroom"],char:'\u{1f6bf}',fitzpatrick_scale:!1,category:"objects"},bathtub:{keywords:["clean","shower","bathroom"],char:'\u{1f6c1}',fitzpatrick_scale:!1,category:"objects"},soap:{keywords:["bar","bathing","cleaning","lather"],char:'\u{1f9fc}',fitzpatrick_scale:!1,category:"objects"},sponge:{keywords:["absorbing","cleaning","porous"],char:'\u{1f9fd}',fitzpatrick_scale:!1,category:"objects"},lotion_bottle:{keywords:["moisturizer","sunscreen"],char:'\u{1f9f4}',fitzpatrick_scale:!1,category:"objects"},key:{keywords:["lock","door","password"],char:'\u{1f511}',fitzpatrick_scale:!1,category:"objects"},old_key:{keywords:["lock","door","password"],char:'\u{1f5dd}',fitzpatrick_scale:!1,category:"objects"},couch_and_lamp:{keywords:["read","chill"],char:'\u{1f6cb}',fitzpatrick_scale:!1,category:"objects"},sleeping_bed:{keywords:["bed","rest"],char:'\u{1f6cc}',fitzpatrick_scale:!0,category:"objects"},bed:{keywords:["sleep","rest"],char:'\u{1f6cf}',fitzpatrick_scale:!1,category:"objects"},door:{keywords:["house","entry","exit"],char:'\u{1f6aa}',fitzpatrick_scale:!1,category:"objects"},bellhop_bell:{keywords:["service"],char:'\u{1f6ce}',fitzpatrick_scale:!1,category:"objects"},teddy_bear:{keywords:["plush","stuffed"],char:'\u{1f9f8}',fitzpatrick_scale:!1,category:"objects"},framed_picture:{keywords:["photography"],char:'\u{1f5bc}',fitzpatrick_scale:!1,category:"objects"},world_map:{keywords:["location","direction"],char:'\u{1f5fa}',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:'\u{1f5ff}',fitzpatrick_scale:!1,category:"objects"},shopping:{keywords:["mall","buy","purchase"],char:'\u{1f6cd}',fitzpatrick_scale:!1,category:"objects"},shopping_cart:{keywords:["trolley"],char:'\u{1f6d2}',fitzpatrick_scale:!1,category:"objects"},balloon:{keywords:["party","celebration","birthday","circus"],char:'\u{1f388}',fitzpatrick_scale:!1,category:"objects"},flags:{keywords:["fish","japanese","koinobori","carp","banner"],char:'\u{1f38f}',fitzpatrick_scale:!1,category:"objects"},ribbon:{keywords:["decoration","pink","girl","bowtie"],char:'\u{1f380}',fitzpatrick_scale:!1,category:"objects"},gift:{keywords:["present","birthday","christmas","xmas"],char:'\u{1f381}',fitzpatrick_scale:!1,category:"objects"},confetti_ball:{keywords:["festival","party","birthday","circus"],char:'\u{1f38a}',fitzpatrick_scale:!1,category:"objects"},tada:{keywords:["party","congratulations","birthday","magic","circus","celebration"],char:'\u{1f389}',fitzpatrick_scale:!1,category:"objects"},dolls:{keywords:["japanese","toy","kimono"],char:'\u{1f38e}',fitzpatrick_scale:!1,category:"objects"},wind_chime:{keywords:["nature","ding","spring","bell"],char:'\u{1f390}',fitzpatrick_scale:!1,category:"objects"},crossed_flags:{keywords:["japanese","nation","country","border"],char:'\u{1f38c}',fitzpatrick_scale:!1,category:"objects"},izakaya_lantern:{keywords:["light","paper","halloween","spooky"],char:'\u{1f3ee}',fitzpatrick_scale:!1,category:"objects"},red_envelope:{keywords:["gift"],char:'\u{1f9e7}',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:'\u{1f4e9}',fitzpatrick_scale:!1,category:"objects"},incoming_envelope:{keywords:["email","inbox"],char:'\u{1f4e8}',fitzpatrick_scale:!1,category:"objects"},"e-mail":{keywords:["communication","inbox"],char:'\u{1f4e7}',fitzpatrick_scale:!1,category:"objects"},love_letter:{keywords:["email","like","affection","envelope","valentines"],char:'\u{1f48c}',fitzpatrick_scale:!1,category:"objects"},postbox:{keywords:["email","letter","envelope"],char:'\u{1f4ee}',fitzpatrick_scale:!1,category:"objects"},mailbox_closed:{keywords:["email","communication","inbox"],char:'\u{1f4ea}',fitzpatrick_scale:!1,category:"objects"},mailbox:{keywords:["email","inbox","communication"],char:'\u{1f4eb}',fitzpatrick_scale:!1,category:"objects"},mailbox_with_mail:{keywords:["email","inbox","communication"],char:'\u{1f4ec}',fitzpatrick_scale:!1,category:"objects"},mailbox_with_no_mail:{keywords:["email","inbox"],char:'\u{1f4ed}',fitzpatrick_scale:!1,category:"objects"},package:{keywords:["mail","gift","cardboard","box","moving"],char:'\u{1f4e6}',fitzpatrick_scale:!1,category:"objects"},postal_horn:{keywords:["instrument","music"],char:'\u{1f4ef}',fitzpatrick_scale:!1,category:"objects"},inbox_tray:{keywords:["email","documents"],char:'\u{1f4e5}',fitzpatrick_scale:!1,category:"objects"},outbox_tray:{keywords:["inbox","email"],char:'\u{1f4e4}',fitzpatrick_scale:!1,category:"objects"},scroll:{keywords:["documents","ancient","history","paper"],char:'\u{1f4dc}',fitzpatrick_scale:!1,category:"objects"},page_with_curl:{keywords:["documents","office","paper"],char:'\u{1f4c3}',fitzpatrick_scale:!1,category:"objects"},bookmark_tabs:{keywords:["favorite","save","order","tidy"],char:'\u{1f4d1}',fitzpatrick_scale:!1,category:"objects"},receipt:{keywords:["accounting","expenses"],char:'\u{1f9fe}',fitzpatrick_scale:!1,category:"objects"},bar_chart:{keywords:["graph","presentation","stats"],char:'\u{1f4ca}',fitzpatrick_scale:!1,category:"objects"},chart_with_upwards_trend:{keywords:["graph","presentation","stats","recovery","business","economics","money","sales","good","success"],char:'\u{1f4c8}',fitzpatrick_scale:!1,category:"objects"},chart_with_downwards_trend:{keywords:["graph","presentation","stats","recession","business","economics","money","sales","bad","failure"],char:'\u{1f4c9}',fitzpatrick_scale:!1,category:"objects"},page_facing_up:{keywords:["documents","office","paper","information"],char:'\u{1f4c4}',fitzpatrick_scale:!1,category:"objects"},date:{keywords:["calendar","schedule"],char:'\u{1f4c5}',fitzpatrick_scale:!1,category:"objects"},calendar:{keywords:["schedule","date","planning"],char:'\u{1f4c6}',fitzpatrick_scale:!1,category:"objects"},spiral_calendar:{keywords:["date","schedule","planning"],char:'\u{1f5d3}',fitzpatrick_scale:!1,category:"objects"},card_index:{keywords:["business","stationery"],char:'\u{1f4c7}',fitzpatrick_scale:!1,category:"objects"},card_file_box:{keywords:["business","stationery"],char:'\u{1f5c3}',fitzpatrick_scale:!1,category:"objects"},ballot_box:{keywords:["election","vote"],char:'\u{1f5f3}',fitzpatrick_scale:!1,category:"objects"},file_cabinet:{keywords:["filing","organizing"],char:'\u{1f5c4}',fitzpatrick_scale:!1,category:"objects"},clipboard:{keywords:["stationery","documents"],char:'\u{1f4cb}',fitzpatrick_scale:!1,category:"objects"},spiral_notepad:{keywords:["memo","stationery"],char:'\u{1f5d2}',fitzpatrick_scale:!1,category:"objects"},file_folder:{keywords:["documents","business","office"],char:'\u{1f4c1}',fitzpatrick_scale:!1,category:"objects"},open_file_folder:{keywords:["documents","load"],char:'\u{1f4c2}',fitzpatrick_scale:!1,category:"objects"},card_index_dividers:{keywords:["organizing","business","stationery"],char:'\u{1f5c2}',fitzpatrick_scale:!1,category:"objects"},newspaper_roll:{keywords:["press","headline"],char:'\u{1f5de}',fitzpatrick_scale:!1,category:"objects"},newspaper:{keywords:["press","headline"],char:'\u{1f4f0}',fitzpatrick_scale:!1,category:"objects"},notebook:{keywords:["stationery","record","notes","paper","study"],char:'\u{1f4d3}',fitzpatrick_scale:!1,category:"objects"},closed_book:{keywords:["read","library","knowledge","textbook","learn"],char:'\u{1f4d5}',fitzpatrick_scale:!1,category:"objects"},green_book:{keywords:["read","library","knowledge","study"],char:'\u{1f4d7}',fitzpatrick_scale:!1,category:"objects"},blue_book:{keywords:["read","library","knowledge","learn","study"],char:'\u{1f4d8}',fitzpatrick_scale:!1,category:"objects"},orange_book:{keywords:["read","library","knowledge","textbook","study"],char:'\u{1f4d9}',fitzpatrick_scale:!1,category:"objects"},notebook_with_decorative_cover:{keywords:["classroom","notes","record","paper","study"],char:'\u{1f4d4}',fitzpatrick_scale:!1,category:"objects"},ledger:{keywords:["notes","paper"],char:'\u{1f4d2}',fitzpatrick_scale:!1,category:"objects"},books:{keywords:["literature","library","study"],char:'\u{1f4da}',fitzpatrick_scale:!1,category:"objects"},open_book:{keywords:["book","read","library","knowledge","literature","learn","study"],char:'\u{1f4d6}',fitzpatrick_scale:!1,category:"objects"},safety_pin:{keywords:["diaper"],char:'\u{1f9f7}',fitzpatrick_scale:!1,category:"objects"},link:{keywords:["rings","url"],char:'\u{1f517}',fitzpatrick_scale:!1,category:"objects"},paperclip:{keywords:["documents","stationery"],char:'\u{1f4ce}',fitzpatrick_scale:!1,category:"objects"},paperclips:{keywords:["documents","stationery"],char:'\u{1f587}',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:'\u{1f4d0}',fitzpatrick_scale:!1,category:"objects"},straight_ruler:{keywords:["stationery","calculate","length","math","school","drawing","architect","sketch"],char:'\u{1f4cf}',fitzpatrick_scale:!1,category:"objects"},abacus:{keywords:["calculation"],char:'\u{1f9ee}',fitzpatrick_scale:!1,category:"objects"},pushpin:{keywords:["stationery","mark","here"],char:'\u{1f4cc}',fitzpatrick_scale:!1,category:"objects"},round_pushpin:{keywords:["stationery","location","map","here"],char:'\u{1f4cd}',fitzpatrick_scale:!1,category:"objects"},triangular_flag_on_post:{keywords:["mark","milestone","place"],char:'\u{1f6a9}',fitzpatrick_scale:!1,category:"objects"},white_flag:{keywords:["losing","loser","lost","surrender","give up","fail"],char:'\u{1f3f3}',fitzpatrick_scale:!1,category:"objects"},black_flag:{keywords:["pirate"],char:'\u{1f3f4}',fitzpatrick_scale:!1,category:"objects"},rainbow_flag:{keywords:["flag","rainbow","pride","gay","lgbt","glbt","queer","homosexual","lesbian","bisexual","transgender"],char:'\u{1f3f3}\ufe0f\u200d\u{1f308}',fitzpatrick_scale:!1,category:"objects"},closed_lock_with_key:{keywords:["security","privacy"],char:'\u{1f510}',fitzpatrick_scale:!1,category:"objects"},lock:{keywords:["security","password","padlock"],char:'\u{1f512}',fitzpatrick_scale:!1,category:"objects"},unlock:{keywords:["privacy","security"],char:'\u{1f513}',fitzpatrick_scale:!1,category:"objects"},lock_with_ink_pen:{keywords:["security","secret"],char:'\u{1f50f}',fitzpatrick_scale:!1,category:"objects"},pen:{keywords:["stationery","writing","write"],char:'\u{1f58a}',fitzpatrick_scale:!1,category:"objects"},fountain_pen:{keywords:["stationery","writing","write"],char:'\u{1f58b}',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:'\u{1f4dd}',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:'\u{1f58d}',fitzpatrick_scale:!1,category:"objects"},paintbrush:{keywords:["drawing","creativity","art"],char:'\u{1f58c}',fitzpatrick_scale:!1,category:"objects"},mag:{keywords:["search","zoom","find","detective"],char:'\u{1f50d}',fitzpatrick_scale:!1,category:"objects"},mag_right:{keywords:["search","zoom","find","detective"],char:'\u{1f50e}',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:'\u{1f9e1}',fitzpatrick_scale:!1,category:"symbols"},yellow_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f49b}',fitzpatrick_scale:!1,category:"symbols"},green_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f49a}',fitzpatrick_scale:!1,category:"symbols"},blue_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f499}',fitzpatrick_scale:!1,category:"symbols"},purple_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f49c}',fitzpatrick_scale:!1,category:"symbols"},black_heart:{keywords:["evil"],char:'\u{1f5a4}',fitzpatrick_scale:!1,category:"symbols"},broken_heart:{keywords:["sad","sorry","break","heart","heartbreak"],char:'\u{1f494}',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:'\u{1f495}',fitzpatrick_scale:!1,category:"symbols"},revolving_hearts:{keywords:["love","like","affection","valentines"],char:'\u{1f49e}',fitzpatrick_scale:!1,category:"symbols"},heartbeat:{keywords:["love","like","affection","valentines","pink","heart"],char:'\u{1f493}',fitzpatrick_scale:!1,category:"symbols"},heartpulse:{keywords:["like","love","affection","valentines","pink"],char:'\u{1f497}',fitzpatrick_scale:!1,category:"symbols"},sparkling_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f496}',fitzpatrick_scale:!1,category:"symbols"},cupid:{keywords:["love","like","heart","affection","valentines"],char:'\u{1f498}',fitzpatrick_scale:!1,category:"symbols"},gift_heart:{keywords:["love","valentines"],char:'\u{1f49d}',fitzpatrick_scale:!1,category:"symbols"},heart_decoration:{keywords:["purple-square","love","like"],char:'\u{1f49f}',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:'\u{1f549}',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:'\u{1f52f}',fitzpatrick_scale:!1,category:"symbols"},menorah:{keywords:["hanukkah","candles","jewish"],char:'\u{1f54e}',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:'\u{1f6d0}',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:'\u{1f194}',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:'\u{1f233}',fitzpatrick_scale:!1,category:"symbols"},u5272:{keywords:["cut","divide","chinese","kanji","pink-square"],char:'\u{1f239}',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:'\u{1f4f4}',fitzpatrick_scale:!1,category:"symbols"},vibration_mode:{keywords:["orange-square","phone"],char:'\u{1f4f3}',fitzpatrick_scale:!1,category:"symbols"},u6709:{keywords:["orange-square","chinese","have","kanji"],char:'\u{1f236}',fitzpatrick_scale:!1,category:"symbols"},u7121:{keywords:["nothing","chinese","kanji","japanese","orange-square"],char:'\u{1f21a}',fitzpatrick_scale:!1,category:"symbols"},u7533:{keywords:["chinese","japanese","kanji","orange-square"],char:'\u{1f238}',fitzpatrick_scale:!1,category:"symbols"},u55b6:{keywords:["japanese","opening hours","orange-square"],char:'\u{1f23a}',fitzpatrick_scale:!1,category:"symbols"},u6708:{keywords:["chinese","month","moon","japanese","orange-square","kanji"],char:'\u{1f237}\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:'\u{1f19a}',fitzpatrick_scale:!1,category:"symbols"},accept:{keywords:["ok","good","chinese","kanji","agree","yes","orange-circle"],char:'\u{1f251}',fitzpatrick_scale:!1,category:"symbols"},white_flower:{keywords:["japanese","spring"],char:'\u{1f4ae}',fitzpatrick_scale:!1,category:"symbols"},ideograph_advantage:{keywords:["chinese","kanji","obtain","get","circle"],char:'\u{1f250}',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:'\u{1f234}',fitzpatrick_scale:!1,category:"symbols"},u6e80:{keywords:["full","chinese","japanese","red-square","kanji"],char:'\u{1f235}',fitzpatrick_scale:!1,category:"symbols"},u7981:{keywords:["kanji","japanese","chinese","forbidden","limit","restricted","red-square"],char:'\u{1f232}',fitzpatrick_scale:!1,category:"symbols"},a:{keywords:["red-square","alphabet","letter"],char:'\u{1f170}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},b:{keywords:["red-square","alphabet","letter"],char:'\u{1f171}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},ab:{keywords:["red-square","alphabet"],char:'\u{1f18e}',fitzpatrick_scale:!1,category:"symbols"},cl:{keywords:["alphabet","words","red-square"],char:'\u{1f191}',fitzpatrick_scale:!1,category:"symbols"},o2:{keywords:["alphabet","red-square","letter"],char:'\u{1f17e}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},sos:{keywords:["help","red-square","words","emergency","911"],char:'\u{1f198}',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:'\u{1f4db}',fitzpatrick_scale:!1,category:"symbols"},no_entry_sign:{keywords:["forbid","stop","limit","denied","disallow","circle"],char:'\u{1f6ab}',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:'\u{1f6d1}',fitzpatrick_scale:!1,category:"symbols"},anger:{keywords:["angry","mad"],char:'\u{1f4a2}',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:'\u{1f6b7}',fitzpatrick_scale:!1,category:"symbols"},do_not_litter:{keywords:["trash","bin","garbage","circle"],char:'\u{1f6af}',fitzpatrick_scale:!1,category:"symbols"},no_bicycles:{keywords:["cyclist","prohibited","circle"],char:'\u{1f6b3}',fitzpatrick_scale:!1,category:"symbols"},"non-potable_water":{keywords:["drink","faucet","tap","circle"],char:'\u{1f6b1}',fitzpatrick_scale:!1,category:"symbols"},underage:{keywords:["18","drink","pub","night","minor","circle"],char:'\u{1f51e}',fitzpatrick_scale:!1,category:"symbols"},no_mobile_phones:{keywords:["iphone","mute","circle"],char:'\u{1f4f5}',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:'\u{1f505}',fitzpatrick_scale:!1,category:"symbols"},high_brightness:{keywords:["sun","light"],char:'\u{1f506}',fitzpatrick_scale:!1,category:"symbols"},trident:{keywords:["weapon","spear"],char:'\u{1f531}',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:'\u{1f6b8}',fitzpatrick_scale:!1,category:"symbols"},beginner:{keywords:["badge","shield"],char:'\u{1f530}',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:'\u{1f22f}',fitzpatrick_scale:!1,category:"symbols"},chart:{keywords:["green-square","graph","presentation","stats"],char:'\u{1f4b9}',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:'\u{1f4a0}',fitzpatrick_scale:!1,category:"symbols"},cyclone:{keywords:["weather","swirl","blue","cloud","vortex","spiral","whirlpool","spin","tornado","hurricane","typhoon"],char:'\u{1f300}',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:'\u{1f310}',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:'\u{1f3e7}',fitzpatrick_scale:!1,category:"symbols"},sa:{keywords:["japanese","blue-square","katakana"],char:'\u{1f202}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},passport_control:{keywords:["custom","blue-square"],char:'\u{1f6c2}',fitzpatrick_scale:!1,category:"symbols"},customs:{keywords:["passport","border","blue-square"],char:'\u{1f6c3}',fitzpatrick_scale:!1,category:"symbols"},baggage_claim:{keywords:["blue-square","airport","transport"],char:'\u{1f6c4}',fitzpatrick_scale:!1,category:"symbols"},left_luggage:{keywords:["blue-square","travel"],char:'\u{1f6c5}',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:'\u{1f6ad}',fitzpatrick_scale:!1,category:"symbols"},wc:{keywords:["toilet","restroom","blue-square"],char:'\u{1f6be}',fitzpatrick_scale:!1,category:"symbols"},parking:{keywords:["cars","blue-square","alphabet","letter"],char:'\u{1f17f}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},potable_water:{keywords:["blue-square","liquid","restroom","cleaning","faucet"],char:'\u{1f6b0}',fitzpatrick_scale:!1,category:"symbols"},mens:{keywords:["toilet","restroom","wc","blue-square","gender","male"],char:'\u{1f6b9}',fitzpatrick_scale:!1,category:"symbols"},womens:{keywords:["purple-square","woman","female","toilet","loo","restroom","gender"],char:'\u{1f6ba}',fitzpatrick_scale:!1,category:"symbols"},baby_symbol:{keywords:["orange-square","child"],char:'\u{1f6bc}',fitzpatrick_scale:!1,category:"symbols"},restroom:{keywords:["blue-square","toilet","refresh","wc","gender"],char:'\u{1f6bb}',fitzpatrick_scale:!1,category:"symbols"},put_litter_in_its_place:{keywords:["blue-square","sign","human","info"],char:'\u{1f6ae}',fitzpatrick_scale:!1,category:"symbols"},cinema:{keywords:["blue-square","record","film","movie","curtain","stage","theater"],char:'\u{1f3a6}',fitzpatrick_scale:!1,category:"symbols"},signal_strength:{keywords:["blue-square","reception","phone","internet","connection","wifi","bluetooth","bars"],char:'\u{1f4f6}',fitzpatrick_scale:!1,category:"symbols"},koko:{keywords:["blue-square","here","katakana","japanese","destination"],char:'\u{1f201}',fitzpatrick_scale:!1,category:"symbols"},ng:{keywords:["blue-square","words","shape","icon"],char:'\u{1f196}',fitzpatrick_scale:!1,category:"symbols"},ok:{keywords:["good","agree","yes","blue-square"],char:'\u{1f197}',fitzpatrick_scale:!1,category:"symbols"},up:{keywords:["blue-square","above","high"],char:'\u{1f199}',fitzpatrick_scale:!1,category:"symbols"},cool:{keywords:["words","blue-square"],char:'\u{1f192}',fitzpatrick_scale:!1,category:"symbols"},new:{keywords:["blue-square","words","start"],char:'\u{1f195}',fitzpatrick_scale:!1,category:"symbols"},free:{keywords:["blue-square","words"],char:'\u{1f193}',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:'\u{1f51f}',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:'\u{1f500}',fitzpatrick_scale:!1,category:"symbols"},repeat:{keywords:["loop","record"],char:'\u{1f501}',fitzpatrick_scale:!1,category:"symbols"},repeat_one:{keywords:["blue-square","loop"],char:'\u{1f502}',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:'\u{1f53c}',fitzpatrick_scale:!1,category:"symbols"},arrow_down_small:{keywords:["blue-square","direction","bottom"],char:'\u{1f53d}',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:'\u{1f504}',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:'\u{1f524}',fitzpatrick_scale:!1,category:"symbols"},abcd:{keywords:["blue-square","alphabet"],char:'\u{1f521}',fitzpatrick_scale:!1,category:"symbols"},capital_abcd:{keywords:["alphabet","words","blue-square"],char:'\u{1f520}',fitzpatrick_scale:!1,category:"symbols"},symbols:{keywords:["blue-square","music","note","ampersand","percent","glyphs","characters"],char:'\u{1f523}',fitzpatrick_scale:!1,category:"symbols"},musical_note:{keywords:["score","tone","sound"],char:'\u{1f3b5}',fitzpatrick_scale:!1,category:"symbols"},notes:{keywords:["music","score"],char:'\u{1f3b6}',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:'\u{1f503}',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:'\u{1f4b2}',fitzpatrick_scale:!1,category:"symbols"},currency_exchange:{keywords:["money","sales","dollar","travel"],char:'\u{1f4b1}',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:'\u{1f51a}',fitzpatrick_scale:!1,category:"symbols"},back:{keywords:["arrow","words","return"],char:'\u{1f519}',fitzpatrick_scale:!1,category:"symbols"},on:{keywords:["arrow","words"],char:'\u{1f51b}',fitzpatrick_scale:!1,category:"symbols"},top:{keywords:["words","blue-square"],char:'\u{1f51d}',fitzpatrick_scale:!1,category:"symbols"},soon:{keywords:["arrow","words"],char:'\u{1f51c}',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:'\u{1f518}',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:'\u{1f534}',fitzpatrick_scale:!1,category:"symbols"},large_blue_circle:{keywords:["shape","icon","button"],char:'\u{1f535}',fitzpatrick_scale:!1,category:"symbols"},small_orange_diamond:{keywords:["shape","jewel","gem"],char:'\u{1f538}',fitzpatrick_scale:!1,category:"symbols"},small_blue_diamond:{keywords:["shape","jewel","gem"],char:'\u{1f539}',fitzpatrick_scale:!1,category:"symbols"},large_orange_diamond:{keywords:["shape","jewel","gem"],char:'\u{1f536}',fitzpatrick_scale:!1,category:"symbols"},large_blue_diamond:{keywords:["shape","jewel","gem"],char:'\u{1f537}',fitzpatrick_scale:!1,category:"symbols"},small_red_triangle:{keywords:["shape","direction","up","top"],char:'\u{1f53a}',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:'\u{1f53b}',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:'\u{1f532}',fitzpatrick_scale:!1,category:"symbols"},white_square_button:{keywords:["shape","input"],char:'\u{1f533}',fitzpatrick_scale:!1,category:"symbols"},speaker:{keywords:["sound","volume","silence","broadcast"],char:'\u{1f508}',fitzpatrick_scale:!1,category:"symbols"},sound:{keywords:["volume","speaker","broadcast"],char:'\u{1f509}',fitzpatrick_scale:!1,category:"symbols"},loud_sound:{keywords:["volume","noise","noisy","speaker","broadcast"],char:'\u{1f50a}',fitzpatrick_scale:!1,category:"symbols"},mute:{keywords:["sound","volume","silence","quiet"],char:'\u{1f507}',fitzpatrick_scale:!1,category:"symbols"},mega:{keywords:["sound","speaker","volume"],char:'\u{1f4e3}',fitzpatrick_scale:!1,category:"symbols"},loudspeaker:{keywords:["volume","sound"],char:'\u{1f4e2}',fitzpatrick_scale:!1,category:"symbols"},bell:{keywords:["sound","notification","christmas","xmas","chime"],char:'\u{1f514}',fitzpatrick_scale:!1,category:"symbols"},no_bell:{keywords:["sound","volume","mute","quiet","silent"],char:'\u{1f515}',fitzpatrick_scale:!1,category:"symbols"},black_joker:{keywords:["poker","cards","game","play","magic"],char:'\u{1f0cf}',fitzpatrick_scale:!1,category:"symbols"},mahjong:{keywords:["game","play","chinese","kanji"],char:'\u{1f004}',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:'\u{1f3b4}',fitzpatrick_scale:!1,category:"symbols"},thought_balloon:{keywords:["bubble","cloud","speech","thinking","dream"],char:'\u{1f4ad}',fitzpatrick_scale:!1,category:"symbols"},right_anger_bubble:{keywords:["caption","speech","thinking","mad"],char:'\u{1f5ef}',fitzpatrick_scale:!1,category:"symbols"},speech_balloon:{keywords:["bubble","words","message","talk","chatting"],char:'\u{1f4ac}',fitzpatrick_scale:!1,category:"symbols"},left_speech_bubble:{keywords:["words","message","talk","chatting"],char:'\u{1f5e8}',fitzpatrick_scale:!1,category:"symbols"},clock1:{keywords:["time","late","early","schedule"],char:'\u{1f550}',fitzpatrick_scale:!1,category:"symbols"},clock2:{keywords:["time","late","early","schedule"],char:'\u{1f551}',fitzpatrick_scale:!1,category:"symbols"},clock3:{keywords:["time","late","early","schedule"],char:'\u{1f552}',fitzpatrick_scale:!1,category:"symbols"},clock4:{keywords:["time","late","early","schedule"],char:'\u{1f553}',fitzpatrick_scale:!1,category:"symbols"},clock5:{keywords:["time","late","early","schedule"],char:'\u{1f554}',fitzpatrick_scale:!1,category:"symbols"},clock6:{keywords:["time","late","early","schedule","dawn","dusk"],char:'\u{1f555}',fitzpatrick_scale:!1,category:"symbols"},clock7:{keywords:["time","late","early","schedule"],char:'\u{1f556}',fitzpatrick_scale:!1,category:"symbols"},clock8:{keywords:["time","late","early","schedule"],char:'\u{1f557}',fitzpatrick_scale:!1,category:"symbols"},clock9:{keywords:["time","late","early","schedule"],char:'\u{1f558}',fitzpatrick_scale:!1,category:"symbols"},clock10:{keywords:["time","late","early","schedule"],char:'\u{1f559}',fitzpatrick_scale:!1,category:"symbols"},clock11:{keywords:["time","late","early","schedule"],char:'\u{1f55a}',fitzpatrick_scale:!1,category:"symbols"},clock12:{keywords:["time","noon","midnight","midday","late","early","schedule"],char:'\u{1f55b}',fitzpatrick_scale:!1,category:"symbols"},clock130:{keywords:["time","late","early","schedule"],char:'\u{1f55c}',fitzpatrick_scale:!1,category:"symbols"},clock230:{keywords:["time","late","early","schedule"],char:'\u{1f55d}',fitzpatrick_scale:!1,category:"symbols"},clock330:{keywords:["time","late","early","schedule"],char:'\u{1f55e}',fitzpatrick_scale:!1,category:"symbols"},clock430:{keywords:["time","late","early","schedule"],char:'\u{1f55f}',fitzpatrick_scale:!1,category:"symbols"},clock530:{keywords:["time","late","early","schedule"],char:'\u{1f560}',fitzpatrick_scale:!1,category:"symbols"},clock630:{keywords:["time","late","early","schedule"],char:'\u{1f561}',fitzpatrick_scale:!1,category:"symbols"},clock730:{keywords:["time","late","early","schedule"],char:'\u{1f562}',fitzpatrick_scale:!1,category:"symbols"},clock830:{keywords:["time","late","early","schedule"],char:'\u{1f563}',fitzpatrick_scale:!1,category:"symbols"},clock930:{keywords:["time","late","early","schedule"],char:'\u{1f564}',fitzpatrick_scale:!1,category:"symbols"},clock1030:{keywords:["time","late","early","schedule"],char:'\u{1f565}',fitzpatrick_scale:!1,category:"symbols"},clock1130:{keywords:["time","late","early","schedule"],char:'\u{1f566}',fitzpatrick_scale:!1,category:"symbols"},clock1230:{keywords:["time","late","early","schedule"],char:'\u{1f567}',fitzpatrick_scale:!1,category:"symbols"},afghanistan:{keywords:["af","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},aland_islands:{keywords:["\xc5land","islands","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1fd}',fitzpatrick_scale:!1,category:"flags"},albania:{keywords:["al","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},algeria:{keywords:["dz","flag","nation","country","banner"],char:'\u{1f1e9}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},american_samoa:{keywords:["american","ws","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},andorra:{keywords:["ad","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},angola:{keywords:["ao","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},anguilla:{keywords:["ai","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},antarctica:{keywords:["aq","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f6}',fitzpatrick_scale:!1,category:"flags"},antigua_barbuda:{keywords:["antigua","barbuda","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},argentina:{keywords:["ar","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},armenia:{keywords:["am","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},aruba:{keywords:["aw","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},australia:{keywords:["au","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},austria:{keywords:["at","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},azerbaijan:{keywords:["az","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},bahamas:{keywords:["bs","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},bahrain:{keywords:["bh","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},bangladesh:{keywords:["bd","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},barbados:{keywords:["bb","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1e7}',fitzpatrick_scale:!1,category:"flags"},belarus:{keywords:["by","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},belgium:{keywords:["be","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},belize:{keywords:["bz","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},benin:{keywords:["bj","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ef}',fitzpatrick_scale:!1,category:"flags"},bermuda:{keywords:["bm","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},bhutan:{keywords:["bt","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},bolivia:{keywords:["bo","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},caribbean_netherlands:{keywords:["bonaire","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f6}',fitzpatrick_scale:!1,category:"flags"},bosnia_herzegovina:{keywords:["bosnia","herzegovina","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},botswana:{keywords:["bw","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},brazil:{keywords:["br","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},british_indian_ocean_territory:{keywords:["british","indian","ocean","territory","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},british_virgin_islands:{keywords:["british","virgin","islands","bvi","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},brunei:{keywords:["bn","darussalam","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},bulgaria:{keywords:["bg","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},burkina_faso:{keywords:["burkina","faso","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},burundi:{keywords:["bi","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},cape_verde:{keywords:["cabo","verde","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1fb}',fitzpatrick_scale:!1,category:"flags"},cambodia:{keywords:["kh","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},cameroon:{keywords:["cm","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},canada:{keywords:["ca","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},canary_islands:{keywords:["canary","islands","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},cayman_islands:{keywords:["cayman","islands","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},central_african_republic:{keywords:["central","african","republic","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},chad:{keywords:["td","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},chile:{keywords:["flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},cn:{keywords:["china","chinese","prc","flag","country","nation","banner"],char:'\u{1f1e8}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},christmas_island:{keywords:["christmas","island","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1fd}',fitzpatrick_scale:!1,category:"flags"},cocos_islands:{keywords:["cocos","keeling","islands","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},colombia:{keywords:["co","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},comoros:{keywords:["km","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},congo_brazzaville:{keywords:["congo","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},congo_kinshasa:{keywords:["congo","democratic","republic","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},cook_islands:{keywords:["cook","islands","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},costa_rica:{keywords:["costa","rica","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},croatia:{keywords:["hr","flag","nation","country","banner"],char:'\u{1f1ed}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},cuba:{keywords:["cu","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},curacao:{keywords:["cura\xe7ao","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},cyprus:{keywords:["cy","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},czech_republic:{keywords:["cz","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},denmark:{keywords:["dk","flag","nation","country","banner"],char:'\u{1f1e9}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},djibouti:{keywords:["dj","flag","nation","country","banner"],char:'\u{1f1e9}\u{1f1ef}',fitzpatrick_scale:!1,category:"flags"},dominica:{keywords:["dm","flag","nation","country","banner"],char:'\u{1f1e9}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},dominican_republic:{keywords:["dominican","republic","flag","nation","country","banner"],char:'\u{1f1e9}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},ecuador:{keywords:["ec","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},egypt:{keywords:["eg","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},el_salvador:{keywords:["el","salvador","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1fb}',fitzpatrick_scale:!1,category:"flags"},equatorial_guinea:{keywords:["equatorial","gn","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f6}',fitzpatrick_scale:!1,category:"flags"},eritrea:{keywords:["er","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},estonia:{keywords:["ee","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},ethiopia:{keywords:["et","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},eu:{keywords:["european","union","flag","banner"],char:'\u{1f1ea}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},falkland_islands:{keywords:["falkland","islands","malvinas","flag","nation","country","banner"],char:'\u{1f1eb}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},faroe_islands:{keywords:["faroe","islands","flag","nation","country","banner"],char:'\u{1f1eb}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},fiji:{keywords:["fj","flag","nation","country","banner"],char:'\u{1f1eb}\u{1f1ef}',fitzpatrick_scale:!1,category:"flags"},finland:{keywords:["fi","flag","nation","country","banner"],char:'\u{1f1eb}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},fr:{keywords:["banner","flag","nation","france","french","country"],char:'\u{1f1eb}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},french_guiana:{keywords:["french","guiana","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},french_polynesia:{keywords:["french","polynesia","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},french_southern_territories:{keywords:["french","southern","territories","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},gabon:{keywords:["ga","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},gambia:{keywords:["gm","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},georgia:{keywords:["ge","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},de:{keywords:["german","nation","flag","country","banner"],char:'\u{1f1e9}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},ghana:{keywords:["gh","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},gibraltar:{keywords:["gi","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},greece:{keywords:["gr","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},greenland:{keywords:["gl","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},grenada:{keywords:["gd","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},guadeloupe:{keywords:["gp","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f5}',fitzpatrick_scale:!1,category:"flags"},guam:{keywords:["gu","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},guatemala:{keywords:["gt","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},guernsey:{keywords:["gg","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},guinea:{keywords:["gn","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},guinea_bissau:{keywords:["gw","bissau","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},guyana:{keywords:["gy","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},haiti:{keywords:["ht","flag","nation","country","banner"],char:'\u{1f1ed}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},honduras:{keywords:["hn","flag","nation","country","banner"],char:'\u{1f1ed}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},hong_kong:{keywords:["hong","kong","flag","nation","country","banner"],char:'\u{1f1ed}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},hungary:{keywords:["hu","flag","nation","country","banner"],char:'\u{1f1ed}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},iceland:{keywords:["is","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},india:{keywords:["in","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},indonesia:{keywords:["flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},iran:{keywords:["iran,","islamic","republic","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},iraq:{keywords:["iq","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f6}',fitzpatrick_scale:!1,category:"flags"},ireland:{keywords:["ie","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},isle_of_man:{keywords:["isle","man","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},israel:{keywords:["il","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},it:{keywords:["italy","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},cote_divoire:{keywords:["ivory","coast","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},jamaica:{keywords:["jm","flag","nation","country","banner"],char:'\u{1f1ef}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},jp:{keywords:["japanese","nation","flag","country","banner"],char:'\u{1f1ef}\u{1f1f5}',fitzpatrick_scale:!1,category:"flags"},jersey:{keywords:["je","flag","nation","country","banner"],char:'\u{1f1ef}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},jordan:{keywords:["jo","flag","nation","country","banner"],char:'\u{1f1ef}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},kazakhstan:{keywords:["kz","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},kenya:{keywords:["ke","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},kiribati:{keywords:["ki","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},kosovo:{keywords:["xk","flag","nation","country","banner"],char:'\u{1f1fd}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},kuwait:{keywords:["kw","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},kyrgyzstan:{keywords:["kg","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},laos:{keywords:["lao","democratic","republic","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},latvia:{keywords:["lv","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1fb}',fitzpatrick_scale:!1,category:"flags"},lebanon:{keywords:["lb","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1e7}',fitzpatrick_scale:!1,category:"flags"},lesotho:{keywords:["ls","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},liberia:{keywords:["lr","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},libya:{keywords:["ly","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},liechtenstein:{keywords:["li","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},lithuania:{keywords:["lt","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},luxembourg:{keywords:["lu","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},macau:{keywords:["macao","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},macedonia:{keywords:["macedonia,","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},madagascar:{keywords:["mg","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},malawi:{keywords:["mw","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},malaysia:{keywords:["my","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},maldives:{keywords:["mv","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1fb}',fitzpatrick_scale:!1,category:"flags"},mali:{keywords:["ml","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},malta:{keywords:["mt","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},marshall_islands:{keywords:["marshall","islands","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},martinique:{keywords:["mq","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f6}',fitzpatrick_scale:!1,category:"flags"},mauritania:{keywords:["mr","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},mauritius:{keywords:["mu","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},mayotte:{keywords:["yt","flag","nation","country","banner"],char:'\u{1f1fe}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},mexico:{keywords:["mx","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1fd}',fitzpatrick_scale:!1,category:"flags"},micronesia:{keywords:["micronesia,","federated","states","flag","nation","country","banner"],char:'\u{1f1eb}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},moldova:{keywords:["moldova,","republic","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},monaco:{keywords:["mc","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},mongolia:{keywords:["mn","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},montenegro:{keywords:["me","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},montserrat:{keywords:["ms","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},morocco:{keywords:["ma","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},mozambique:{keywords:["mz","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},myanmar:{keywords:["mm","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},namibia:{keywords:["na","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},nauru:{keywords:["nr","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},nepal:{keywords:["np","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1f5}',fitzpatrick_scale:!1,category:"flags"},netherlands:{keywords:["nl","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},new_caledonia:{keywords:["new","caledonia","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},new_zealand:{keywords:["new","zealand","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},nicaragua:{keywords:["ni","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},niger:{keywords:["ne","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},nigeria:{keywords:["flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},niue:{keywords:["nu","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},norfolk_island:{keywords:["norfolk","island","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},northern_mariana_islands:{keywords:["northern","mariana","islands","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f5}',fitzpatrick_scale:!1,category:"flags"},north_korea:{keywords:["north","korea","nation","flag","country","banner"],char:'\u{1f1f0}\u{1f1f5}',fitzpatrick_scale:!1,category:"flags"},norway:{keywords:["no","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},oman:{keywords:["om_symbol","flag","nation","country","banner"],char:'\u{1f1f4}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},pakistan:{keywords:["pk","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},palau:{keywords:["pw","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},palestinian_territories:{keywords:["palestine","palestinian","territories","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},panama:{keywords:["pa","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},papua_new_guinea:{keywords:["papua","new","guinea","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},paraguay:{keywords:["py","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},peru:{keywords:["pe","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},philippines:{keywords:["ph","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},pitcairn_islands:{keywords:["pitcairn","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},poland:{keywords:["pl","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},portugal:{keywords:["pt","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},puerto_rico:{keywords:["puerto","rico","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},qatar:{keywords:["qa","flag","nation","country","banner"],char:'\u{1f1f6}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},reunion:{keywords:["r\xe9union","flag","nation","country","banner"],char:'\u{1f1f7}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},romania:{keywords:["ro","flag","nation","country","banner"],char:'\u{1f1f7}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},ru:{keywords:["russian","federation","flag","nation","country","banner"],char:'\u{1f1f7}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},rwanda:{keywords:["rw","flag","nation","country","banner"],char:'\u{1f1f7}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},st_barthelemy:{keywords:["saint","barth\xe9lemy","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},st_helena:{keywords:["saint","helena","ascension","tristan","cunha","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},st_kitts_nevis:{keywords:["saint","kitts","nevis","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},st_lucia:{keywords:["saint","lucia","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},st_pierre_miquelon:{keywords:["saint","pierre","miquelon","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},st_vincent_grenadines:{keywords:["saint","vincent","grenadines","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},samoa:{keywords:["ws","flag","nation","country","banner"],char:'\u{1f1fc}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},san_marino:{keywords:["san","marino","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},sao_tome_principe:{keywords:["sao","tome","principe","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},saudi_arabia:{keywords:["flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},senegal:{keywords:["sn","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},serbia:{keywords:["rs","flag","nation","country","banner"],char:'\u{1f1f7}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},seychelles:{keywords:["sc","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},sierra_leone:{keywords:["sierra","leone","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},singapore:{keywords:["sg","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},sint_maarten:{keywords:["sint","maarten","dutch","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1fd}',fitzpatrick_scale:!1,category:"flags"},slovakia:{keywords:["sk","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},slovenia:{keywords:["si","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},solomon_islands:{keywords:["solomon","islands","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1e7}',fitzpatrick_scale:!1,category:"flags"},somalia:{keywords:["so","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},south_africa:{keywords:["south","africa","flag","nation","country","banner"],char:'\u{1f1ff}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},south_georgia_south_sandwich_islands:{keywords:["south","georgia","sandwich","islands","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},kr:{keywords:["south","korea","nation","flag","country","banner"],char:'\u{1f1f0}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},south_sudan:{keywords:["south","sd","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},es:{keywords:["spain","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},sri_lanka:{keywords:["sri","lanka","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},sudan:{keywords:["sd","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},suriname:{keywords:["sr","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},swaziland:{keywords:["sz","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},sweden:{keywords:["se","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},switzerland:{keywords:["ch","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},syria:{keywords:["syrian","arab","republic","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},taiwan:{keywords:["tw","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},tajikistan:{keywords:["tj","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1ef}',fitzpatrick_scale:!1,category:"flags"},tanzania:{keywords:["tanzania,","united","republic","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},thailand:{keywords:["th","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},timor_leste:{keywords:["timor","leste","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},togo:{keywords:["tg","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},tokelau:{keywords:["tk","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},tonga:{keywords:["to","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},trinidad_tobago:{keywords:["trinidad","tobago","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},tunisia:{keywords:["tn","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},tr:{keywords:["turkey","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},turkmenistan:{keywords:["flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},turks_caicos_islands:{keywords:["turks","caicos","islands","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},tuvalu:{keywords:["flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1fb}',fitzpatrick_scale:!1,category:"flags"},uganda:{keywords:["ug","flag","nation","country","banner"],char:'\u{1f1fa}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},ukraine:{keywords:["ua","flag","nation","country","banner"],char:'\u{1f1fa}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},united_arab_emirates:{keywords:["united","arab","emirates","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},uk:{keywords:["united","kingdom","great","britain","northern","ireland","flag","nation","country","banner","british","UK","english","england","union jack"],char:'\u{1f1ec}\u{1f1e7}',fitzpatrick_scale:!1,category:"flags"},england:{keywords:["flag","english"],char:'\u{1f3f4}\u{e0067}\u{e0062}\u{e0065}\u{e006e}\u{e0067}\u{e007f}',fitzpatrick_scale:!1,category:"flags"},scotland:{keywords:["flag","scottish"],char:'\u{1f3f4}\u{e0067}\u{e0062}\u{e0073}\u{e0063}\u{e0074}\u{e007f}',fitzpatrick_scale:!1,category:"flags"},wales:{keywords:["flag","welsh"],char:'\u{1f3f4}\u{e0067}\u{e0062}\u{e0077}\u{e006c}\u{e0073}\u{e007f}',fitzpatrick_scale:!1,category:"flags"},us:{keywords:["united","states","america","flag","nation","country","banner"],char:'\u{1f1fa}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},us_virgin_islands:{keywords:["virgin","islands","us","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},uruguay:{keywords:["uy","flag","nation","country","banner"],char:'\u{1f1fa}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},uzbekistan:{keywords:["uz","flag","nation","country","banner"],char:'\u{1f1fa}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},vanuatu:{keywords:["vu","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},vatican_city:{keywords:["vatican","city","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},venezuela:{keywords:["ve","bolivarian","republic","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},vietnam:{keywords:["viet","nam","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},wallis_futuna:{keywords:["wallis","futuna","flag","nation","country","banner"],char:'\u{1f1fc}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},western_sahara:{keywords:["western","sahara","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},yemen:{keywords:["ye","flag","nation","country","banner"],char:'\u{1f1fe}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},zambia:{keywords:["zm","flag","nation","country","banner"],char:'\u{1f1ff}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},zimbabwe:{keywords:["zw","flag","nation","country","banner"],char:'\u{1f1ff}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},united_nations:{keywords:["un","flag","banner"],char:'\u{1f1fa}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},pirate_flag:{keywords:["skull","crossbones","flag","banner"],char:'\u{1f3f4}\u200d\u2620\ufe0f',fitzpatrick_scale:!1,category:"flags"}}); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/emoticons/js/emojis.js b/apps/web-antd/public/tinymce/plugins/emoticons/js/emojis.js new file mode 100644 index 0000000..88455e9 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/emoticons/js/emojis.js @@ -0,0 +1 @@ +window.tinymce.Resource.add("tinymce.plugins.emoticons",{grinning:{keywords:["face","smile","happy","joy",":D","grin"],char:"😀",fitzpatrick_scale:false,category:"people"},grimacing:{keywords:["face","grimace","teeth"],char:"😬",fitzpatrick_scale:false,category:"people"},grin:{keywords:["face","happy","smile","joy","kawaii"],char:"😁",fitzpatrick_scale:false,category:"people"},joy:{keywords:["face","cry","tears","weep","happy","happytears","haha"],char:"😂",fitzpatrick_scale:false,category:"people"},rofl:{keywords:["face","rolling","floor","laughing","lol","haha"],char:"🤣",fitzpatrick_scale:false,category:"people"},partying:{keywords:["face","celebration","woohoo"],char:"🥳",fitzpatrick_scale:false,category:"people"},smiley:{keywords:["face","happy","joy","haha",":D",":)","smile","funny"],char:"😃",fitzpatrick_scale:false,category:"people"},smile:{keywords:["face","happy","joy","funny","haha","laugh","like",":D",":)"],char:"😄",fitzpatrick_scale:false,category:"people"},sweat_smile:{keywords:["face","hot","happy","laugh","sweat","smile","relief"],char:"😅",fitzpatrick_scale:false,category:"people"},laughing:{keywords:["happy","joy","lol","satisfied","haha","face","glad","XD","laugh"],char:"😆",fitzpatrick_scale:false,category:"people"},innocent:{keywords:["face","angel","heaven","halo"],char:"😇",fitzpatrick_scale:false,category:"people"},wink:{keywords:["face","happy","mischievous","secret",";)","smile","eye"],char:"😉",fitzpatrick_scale:false,category:"people"},blush:{keywords:["face","smile","happy","flushed","crush","embarrassed","shy","joy"],char:"😊",fitzpatrick_scale:false,category:"people"},slightly_smiling_face:{keywords:["face","smile"],char:"🙂",fitzpatrick_scale:false,category:"people"},upside_down_face:{keywords:["face","flipped","silly","smile"],char:"🙃",fitzpatrick_scale:false,category:"people"},relaxed:{keywords:["face","blush","massage","happiness"],char:"☺️",fitzpatrick_scale:false,category:"people"},yum:{keywords:["happy","joy","tongue","smile","face","silly","yummy","nom","delicious","savouring"],char:"😋",fitzpatrick_scale:false,category:"people"},relieved:{keywords:["face","relaxed","phew","massage","happiness"],char:"😌",fitzpatrick_scale:false,category:"people"},heart_eyes:{keywords:["face","love","like","affection","valentines","infatuation","crush","heart"],char:"😍",fitzpatrick_scale:false,category:"people"},smiling_face_with_three_hearts:{keywords:["face","love","like","affection","valentines","infatuation","crush","hearts","adore"],char:"🥰",fitzpatrick_scale:false,category:"people"},kissing_heart:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:"😘",fitzpatrick_scale:false,category:"people"},kissing:{keywords:["love","like","face","3","valentines","infatuation","kiss"],char:"😗",fitzpatrick_scale:false,category:"people"},kissing_smiling_eyes:{keywords:["face","affection","valentines","infatuation","kiss"],char:"😙",fitzpatrick_scale:false,category:"people"},kissing_closed_eyes:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:"😚",fitzpatrick_scale:false,category:"people"},stuck_out_tongue_winking_eye:{keywords:["face","prank","childish","playful","mischievous","smile","wink","tongue"],char:"😜",fitzpatrick_scale:false,category:"people"},zany:{keywords:["face","goofy","crazy"],char:"🤪",fitzpatrick_scale:false,category:"people"},raised_eyebrow:{keywords:["face","distrust","scepticism","disapproval","disbelief","surprise"],char:"🤨",fitzpatrick_scale:false,category:"people"},monocle:{keywords:["face","stuffy","wealthy"],char:"🧐",fitzpatrick_scale:false,category:"people"},stuck_out_tongue_closed_eyes:{keywords:["face","prank","playful","mischievous","smile","tongue"],char:"😝",fitzpatrick_scale:false,category:"people"},stuck_out_tongue:{keywords:["face","prank","childish","playful","mischievous","smile","tongue"],char:"😛",fitzpatrick_scale:false,category:"people"},money_mouth_face:{keywords:["face","rich","dollar","money"],char:"🤑",fitzpatrick_scale:false,category:"people"},nerd_face:{keywords:["face","nerdy","geek","dork"],char:"🤓",fitzpatrick_scale:false,category:"people"},sunglasses:{keywords:["face","cool","smile","summer","beach","sunglass"],char:"😎",fitzpatrick_scale:false,category:"people"},star_struck:{keywords:["face","smile","starry","eyes","grinning"],char:"🤩",fitzpatrick_scale:false,category:"people"},clown_face:{keywords:["face"],char:"🤡",fitzpatrick_scale:false,category:"people"},cowboy_hat_face:{keywords:["face","cowgirl","hat"],char:"🤠",fitzpatrick_scale:false,category:"people"},hugs:{keywords:["face","smile","hug"],char:"🤗",fitzpatrick_scale:false,category:"people"},smirk:{keywords:["face","smile","mean","prank","smug","sarcasm"],char:"😏",fitzpatrick_scale:false,category:"people"},no_mouth:{keywords:["face","hellokitty"],char:"😶",fitzpatrick_scale:false,category:"people"},neutral_face:{keywords:["indifference","meh",":|","neutral"],char:"😐",fitzpatrick_scale:false,category:"people"},expressionless:{keywords:["face","indifferent","-_-","meh","deadpan"],char:"😑",fitzpatrick_scale:false,category:"people"},unamused:{keywords:["indifference","bored","straight face","serious","sarcasm","unimpressed","skeptical","dubious","side_eye"],char:"😒",fitzpatrick_scale:false,category:"people"},roll_eyes:{keywords:["face","eyeroll","frustrated"],char:"🙄",fitzpatrick_scale:false,category:"people"},thinking:{keywords:["face","hmmm","think","consider"],char:"🤔",fitzpatrick_scale:false,category:"people"},lying_face:{keywords:["face","lie","pinocchio"],char:"🤥",fitzpatrick_scale:false,category:"people"},hand_over_mouth:{keywords:["face","whoops","shock","surprise"],char:"🤭",fitzpatrick_scale:false,category:"people"},shushing:{keywords:["face","quiet","shhh"],char:"🤫",fitzpatrick_scale:false,category:"people"},symbols_over_mouth:{keywords:["face","swearing","cursing","cussing","profanity","expletive"],char:"🤬",fitzpatrick_scale:false,category:"people"},exploding_head:{keywords:["face","shocked","mind","blown"],char:"🤯",fitzpatrick_scale:false,category:"people"},flushed:{keywords:["face","blush","shy","flattered"],char:"😳",fitzpatrick_scale:false,category:"people"},disappointed:{keywords:["face","sad","upset","depressed",":("],char:"😞",fitzpatrick_scale:false,category:"people"},worried:{keywords:["face","concern","nervous",":("],char:"😟",fitzpatrick_scale:false,category:"people"},angry:{keywords:["mad","face","annoyed","frustrated"],char:"😠",fitzpatrick_scale:false,category:"people"},rage:{keywords:["angry","mad","hate","despise"],char:"😡",fitzpatrick_scale:false,category:"people"},pensive:{keywords:["face","sad","depressed","upset"],char:"😔",fitzpatrick_scale:false,category:"people"},confused:{keywords:["face","indifference","huh","weird","hmmm",":/"],char:"😕",fitzpatrick_scale:false,category:"people"},slightly_frowning_face:{keywords:["face","frowning","disappointed","sad","upset"],char:"🙁",fitzpatrick_scale:false,category:"people"},frowning_face:{keywords:["face","sad","upset","frown"],char:"☹",fitzpatrick_scale:false,category:"people"},persevere:{keywords:["face","sick","no","upset","oops"],char:"😣",fitzpatrick_scale:false,category:"people"},confounded:{keywords:["face","confused","sick","unwell","oops",":S"],char:"😖",fitzpatrick_scale:false,category:"people"},tired_face:{keywords:["sick","whine","upset","frustrated"],char:"😫",fitzpatrick_scale:false,category:"people"},weary:{keywords:["face","tired","sleepy","sad","frustrated","upset"],char:"😩",fitzpatrick_scale:false,category:"people"},pleading:{keywords:["face","begging","mercy"],char:"🥺",fitzpatrick_scale:false,category:"people"},triumph:{keywords:["face","gas","phew","proud","pride"],char:"😤",fitzpatrick_scale:false,category:"people"},open_mouth:{keywords:["face","surprise","impressed","wow","whoa",":O"],char:"😮",fitzpatrick_scale:false,category:"people"},scream:{keywords:["face","munch","scared","omg"],char:"😱",fitzpatrick_scale:false,category:"people"},fearful:{keywords:["face","scared","terrified","nervous","oops","huh"],char:"😨",fitzpatrick_scale:false,category:"people"},cold_sweat:{keywords:["face","nervous","sweat"],char:"😰",fitzpatrick_scale:false,category:"people"},hushed:{keywords:["face","woo","shh"],char:"😯",fitzpatrick_scale:false,category:"people"},frowning:{keywords:["face","aw","what"],char:"😦",fitzpatrick_scale:false,category:"people"},anguished:{keywords:["face","stunned","nervous"],char:"😧",fitzpatrick_scale:false,category:"people"},cry:{keywords:["face","tears","sad","depressed","upset",":'("],char:"😢",fitzpatrick_scale:false,category:"people"},disappointed_relieved:{keywords:["face","phew","sweat","nervous"],char:"😥",fitzpatrick_scale:false,category:"people"},drooling_face:{keywords:["face"],char:"🤤",fitzpatrick_scale:false,category:"people"},sleepy:{keywords:["face","tired","rest","nap"],char:"😪",fitzpatrick_scale:false,category:"people"},sweat:{keywords:["face","hot","sad","tired","exercise"],char:"😓",fitzpatrick_scale:false,category:"people"},hot:{keywords:["face","feverish","heat","red","sweating"],char:"🥵",fitzpatrick_scale:false,category:"people"},cold:{keywords:["face","blue","freezing","frozen","frostbite","icicles"],char:"🥶",fitzpatrick_scale:false,category:"people"},sob:{keywords:["face","cry","tears","sad","upset","depressed"],char:"😭",fitzpatrick_scale:false,category:"people"},dizzy_face:{keywords:["spent","unconscious","xox","dizzy"],char:"😵",fitzpatrick_scale:false,category:"people"},astonished:{keywords:["face","xox","surprised","poisoned"],char:"😲",fitzpatrick_scale:false,category:"people"},zipper_mouth_face:{keywords:["face","sealed","zipper","secret"],char:"🤐",fitzpatrick_scale:false,category:"people"},nauseated_face:{keywords:["face","vomit","gross","green","sick","throw up","ill"],char:"🤢",fitzpatrick_scale:false,category:"people"},sneezing_face:{keywords:["face","gesundheit","sneeze","sick","allergy"],char:"🤧",fitzpatrick_scale:false,category:"people"},vomiting:{keywords:["face","sick"],char:"🤮",fitzpatrick_scale:false,category:"people"},mask:{keywords:["face","sick","ill","disease"],char:"😷",fitzpatrick_scale:false,category:"people"},face_with_thermometer:{keywords:["sick","temperature","thermometer","cold","fever"],char:"🤒",fitzpatrick_scale:false,category:"people"},face_with_head_bandage:{keywords:["injured","clumsy","bandage","hurt"],char:"🤕",fitzpatrick_scale:false,category:"people"},woozy:{keywords:["face","dizzy","intoxicated","tipsy","wavy"],char:"🥴",fitzpatrick_scale:false,category:"people"},sleeping:{keywords:["face","tired","sleepy","night","zzz"],char:"😴",fitzpatrick_scale:false,category:"people"},zzz:{keywords:["sleepy","tired","dream"],char:"💤",fitzpatrick_scale:false,category:"people"},poop:{keywords:["hankey","shitface","fail","turd","shit"],char:"💩",fitzpatrick_scale:false,category:"people"},smiling_imp:{keywords:["devil","horns"],char:"😈",fitzpatrick_scale:false,category:"people"},imp:{keywords:["devil","angry","horns"],char:"👿",fitzpatrick_scale:false,category:"people"},japanese_ogre:{keywords:["monster","red","mask","halloween","scary","creepy","devil","demon","japanese","ogre"],char:"👹",fitzpatrick_scale:false,category:"people"},japanese_goblin:{keywords:["red","evil","mask","monster","scary","creepy","japanese","goblin"],char:"👺",fitzpatrick_scale:false,category:"people"},skull:{keywords:["dead","skeleton","creepy","death"],char:"💀",fitzpatrick_scale:false,category:"people"},ghost:{keywords:["halloween","spooky","scary"],char:"👻",fitzpatrick_scale:false,category:"people"},alien:{keywords:["UFO","paul","weird","outer_space"],char:"👽",fitzpatrick_scale:false,category:"people"},robot:{keywords:["computer","machine","bot"],char:"🤖",fitzpatrick_scale:false,category:"people"},smiley_cat:{keywords:["animal","cats","happy","smile"],char:"😺",fitzpatrick_scale:false,category:"people"},smile_cat:{keywords:["animal","cats","smile"],char:"😸",fitzpatrick_scale:false,category:"people"},joy_cat:{keywords:["animal","cats","haha","happy","tears"],char:"😹",fitzpatrick_scale:false,category:"people"},heart_eyes_cat:{keywords:["animal","love","like","affection","cats","valentines","heart"],char:"😻",fitzpatrick_scale:false,category:"people"},smirk_cat:{keywords:["animal","cats","smirk"],char:"😼",fitzpatrick_scale:false,category:"people"},kissing_cat:{keywords:["animal","cats","kiss"],char:"😽",fitzpatrick_scale:false,category:"people"},scream_cat:{keywords:["animal","cats","munch","scared","scream"],char:"🙀",fitzpatrick_scale:false,category:"people"},crying_cat_face:{keywords:["animal","tears","weep","sad","cats","upset","cry"],char:"😿",fitzpatrick_scale:false,category:"people"},pouting_cat:{keywords:["animal","cats"],char:"😾",fitzpatrick_scale:false,category:"people"},palms_up:{keywords:["hands","gesture","cupped","prayer"],char:"🤲",fitzpatrick_scale:true,category:"people"},raised_hands:{keywords:["gesture","hooray","yea","celebration","hands"],char:"🙌",fitzpatrick_scale:true,category:"people"},clap:{keywords:["hands","praise","applause","congrats","yay"],char:"👏",fitzpatrick_scale:true,category:"people"},wave:{keywords:["hands","gesture","goodbye","solong","farewell","hello","hi","palm"],char:"👋",fitzpatrick_scale:true,category:"people"},call_me_hand:{keywords:["hands","gesture"],char:"🤙",fitzpatrick_scale:true,category:"people"},"+1":{keywords:["thumbsup","yes","awesome","good","agree","accept","cool","hand","like"],char:"👍",fitzpatrick_scale:true,category:"people"},"-1":{keywords:["thumbsdown","no","dislike","hand"],char:"👎",fitzpatrick_scale:true,category:"people"},facepunch:{keywords:["angry","violence","fist","hit","attack","hand"],char:"👊",fitzpatrick_scale:true,category:"people"},fist:{keywords:["fingers","hand","grasp"],char:"✊",fitzpatrick_scale:true,category:"people"},fist_left:{keywords:["hand","fistbump"],char:"🤛",fitzpatrick_scale:true,category:"people"},fist_right:{keywords:["hand","fistbump"],char:"🤜",fitzpatrick_scale:true,category:"people"},v:{keywords:["fingers","ohyeah","hand","peace","victory","two"],char:"✌",fitzpatrick_scale:true,category:"people"},ok_hand:{keywords:["fingers","limbs","perfect","ok","okay"],char:"👌",fitzpatrick_scale:true,category:"people"},raised_hand:{keywords:["fingers","stop","highfive","palm","ban"],char:"✋",fitzpatrick_scale:true,category:"people"},raised_back_of_hand:{keywords:["fingers","raised","backhand"],char:"🤚",fitzpatrick_scale:true,category:"people"},open_hands:{keywords:["fingers","butterfly","hands","open"],char:"👐",fitzpatrick_scale:true,category:"people"},muscle:{keywords:["arm","flex","hand","summer","strong","biceps"],char:"💪",fitzpatrick_scale:true,category:"people"},pray:{keywords:["please","hope","wish","namaste","highfive"],char:"🙏",fitzpatrick_scale:true,category:"people"},foot:{keywords:["kick","stomp"],char:"🦶",fitzpatrick_scale:true,category:"people"},leg:{keywords:["kick","limb"],char:"🦵",fitzpatrick_scale:true,category:"people"},handshake:{keywords:["agreement","shake"],char:"🤝",fitzpatrick_scale:false,category:"people"},point_up:{keywords:["hand","fingers","direction","up"],char:"☝",fitzpatrick_scale:true,category:"people"},point_up_2:{keywords:["fingers","hand","direction","up"],char:"👆",fitzpatrick_scale:true,category:"people"},point_down:{keywords:["fingers","hand","direction","down"],char:"👇",fitzpatrick_scale:true,category:"people"},point_left:{keywords:["direction","fingers","hand","left"],char:"👈",fitzpatrick_scale:true,category:"people"},point_right:{keywords:["fingers","hand","direction","right"],char:"👉",fitzpatrick_scale:true,category:"people"},fu:{keywords:["hand","fingers","rude","middle","flipping"],char:"🖕",fitzpatrick_scale:true,category:"people"},raised_hand_with_fingers_splayed:{keywords:["hand","fingers","palm"],char:"🖐",fitzpatrick_scale:true,category:"people"},love_you:{keywords:["hand","fingers","gesture"],char:"🤟",fitzpatrick_scale:true,category:"people"},metal:{keywords:["hand","fingers","evil_eye","sign_of_horns","rock_on"],char:"🤘",fitzpatrick_scale:true,category:"people"},crossed_fingers:{keywords:["good","lucky"],char:"🤞",fitzpatrick_scale:true,category:"people"},vulcan_salute:{keywords:["hand","fingers","spock","star trek"],char:"🖖",fitzpatrick_scale:true,category:"people"},writing_hand:{keywords:["lower_left_ballpoint_pen","stationery","write","compose"],char:"✍",fitzpatrick_scale:true,category:"people"},selfie:{keywords:["camera","phone"],char:"🤳",fitzpatrick_scale:true,category:"people"},nail_care:{keywords:["beauty","manicure","finger","fashion","nail"],char:"💅",fitzpatrick_scale:true,category:"people"},lips:{keywords:["mouth","kiss"],char:"👄",fitzpatrick_scale:false,category:"people"},tooth:{keywords:["teeth","dentist"],char:"🦷",fitzpatrick_scale:false,category:"people"},tongue:{keywords:["mouth","playful"],char:"👅",fitzpatrick_scale:false,category:"people"},ear:{keywords:["face","hear","sound","listen"],char:"👂",fitzpatrick_scale:true,category:"people"},nose:{keywords:["smell","sniff"],char:"👃",fitzpatrick_scale:true,category:"people"},eye:{keywords:["face","look","see","watch","stare"],char:"👁",fitzpatrick_scale:false,category:"people"},eyes:{keywords:["look","watch","stalk","peek","see"],char:"👀",fitzpatrick_scale:false,category:"people"},brain:{keywords:["smart","intelligent"],char:"🧠",fitzpatrick_scale:false,category:"people"},bust_in_silhouette:{keywords:["user","person","human"],char:"👤",fitzpatrick_scale:false,category:"people"},busts_in_silhouette:{keywords:["user","person","human","group","team"],char:"👥",fitzpatrick_scale:false,category:"people"},speaking_head:{keywords:["user","person","human","sing","say","talk"],char:"🗣",fitzpatrick_scale:false,category:"people"},baby:{keywords:["child","boy","girl","toddler"],char:"👶",fitzpatrick_scale:true,category:"people"},child:{keywords:["gender-neutral","young"],char:"🧒",fitzpatrick_scale:true,category:"people"},boy:{keywords:["man","male","guy","teenager"],char:"👦",fitzpatrick_scale:true,category:"people"},girl:{keywords:["female","woman","teenager"],char:"👧",fitzpatrick_scale:true,category:"people"},adult:{keywords:["gender-neutral","person"],char:"🧑",fitzpatrick_scale:true,category:"people"},man:{keywords:["mustache","father","dad","guy","classy","sir","moustache"],char:"👨",fitzpatrick_scale:true,category:"people"},woman:{keywords:["female","girls","lady"],char:"👩",fitzpatrick_scale:true,category:"people"},blonde_woman:{keywords:["woman","female","girl","blonde","person"],char:"👱‍♀️",fitzpatrick_scale:true,category:"people"},blonde_man:{keywords:["man","male","boy","blonde","guy","person"],char:"👱",fitzpatrick_scale:true,category:"people"},bearded_person:{keywords:["person","bewhiskered"],char:"🧔",fitzpatrick_scale:true,category:"people"},older_adult:{keywords:["human","elder","senior","gender-neutral"],char:"🧓",fitzpatrick_scale:true,category:"people"},older_man:{keywords:["human","male","men","old","elder","senior"],char:"👴",fitzpatrick_scale:true,category:"people"},older_woman:{keywords:["human","female","women","lady","old","elder","senior"],char:"👵",fitzpatrick_scale:true,category:"people"},man_with_gua_pi_mao:{keywords:["male","boy","chinese"],char:"👲",fitzpatrick_scale:true,category:"people"},woman_with_headscarf:{keywords:["female","hijab","mantilla","tichel"],char:"🧕",fitzpatrick_scale:true,category:"people"},woman_with_turban:{keywords:["female","indian","hinduism","arabs","woman"],char:"👳‍♀️",fitzpatrick_scale:true,category:"people"},man_with_turban:{keywords:["male","indian","hinduism","arabs"],char:"👳",fitzpatrick_scale:true,category:"people"},policewoman:{keywords:["woman","police","law","legal","enforcement","arrest","911","female"],char:"👮‍♀️",fitzpatrick_scale:true,category:"people"},policeman:{keywords:["man","police","law","legal","enforcement","arrest","911"],char:"👮",fitzpatrick_scale:true,category:"people"},construction_worker_woman:{keywords:["female","human","wip","build","construction","worker","labor","woman"],char:"👷‍♀️",fitzpatrick_scale:true,category:"people"},construction_worker_man:{keywords:["male","human","wip","guy","build","construction","worker","labor"],char:"👷",fitzpatrick_scale:true,category:"people"},guardswoman:{keywords:["uk","gb","british","female","royal","woman"],char:"💂‍♀️",fitzpatrick_scale:true,category:"people"},guardsman:{keywords:["uk","gb","british","male","guy","royal"],char:"💂",fitzpatrick_scale:true,category:"people"},female_detective:{keywords:["human","spy","detective","female","woman"],char:"🕵️‍♀️",fitzpatrick_scale:true,category:"people"},male_detective:{keywords:["human","spy","detective"],char:"🕵",fitzpatrick_scale:true,category:"people"},woman_health_worker:{keywords:["doctor","nurse","therapist","healthcare","woman","human"],char:"👩‍⚕️",fitzpatrick_scale:true,category:"people"},man_health_worker:{keywords:["doctor","nurse","therapist","healthcare","man","human"],char:"👨‍⚕️",fitzpatrick_scale:true,category:"people"},woman_farmer:{keywords:["rancher","gardener","woman","human"],char:"👩‍🌾",fitzpatrick_scale:true,category:"people"},man_farmer:{keywords:["rancher","gardener","man","human"],char:"👨‍🌾",fitzpatrick_scale:true,category:"people"},woman_cook:{keywords:["chef","woman","human"],char:"👩‍🍳",fitzpatrick_scale:true,category:"people"},man_cook:{keywords:["chef","man","human"],char:"👨‍🍳",fitzpatrick_scale:true,category:"people"},woman_student:{keywords:["graduate","woman","human"],char:"👩‍🎓",fitzpatrick_scale:true,category:"people"},man_student:{keywords:["graduate","man","human"],char:"👨‍🎓",fitzpatrick_scale:true,category:"people"},woman_singer:{keywords:["rockstar","entertainer","woman","human"],char:"👩‍🎤",fitzpatrick_scale:true,category:"people"},man_singer:{keywords:["rockstar","entertainer","man","human"],char:"👨‍🎤",fitzpatrick_scale:true,category:"people"},woman_teacher:{keywords:["instructor","professor","woman","human"],char:"👩‍🏫",fitzpatrick_scale:true,category:"people"},man_teacher:{keywords:["instructor","professor","man","human"],char:"👨‍🏫",fitzpatrick_scale:true,category:"people"},woman_factory_worker:{keywords:["assembly","industrial","woman","human"],char:"👩‍🏭",fitzpatrick_scale:true,category:"people"},man_factory_worker:{keywords:["assembly","industrial","man","human"],char:"👨‍🏭",fitzpatrick_scale:true,category:"people"},woman_technologist:{keywords:["coder","developer","engineer","programmer","software","woman","human","laptop","computer"],char:"👩‍💻",fitzpatrick_scale:true,category:"people"},man_technologist:{keywords:["coder","developer","engineer","programmer","software","man","human","laptop","computer"],char:"👨‍💻",fitzpatrick_scale:true,category:"people"},woman_office_worker:{keywords:["business","manager","woman","human"],char:"👩‍💼",fitzpatrick_scale:true,category:"people"},man_office_worker:{keywords:["business","manager","man","human"],char:"👨‍💼",fitzpatrick_scale:true,category:"people"},woman_mechanic:{keywords:["plumber","woman","human","wrench"],char:"👩‍🔧",fitzpatrick_scale:true,category:"people"},man_mechanic:{keywords:["plumber","man","human","wrench"],char:"👨‍🔧",fitzpatrick_scale:true,category:"people"},woman_scientist:{keywords:["biologist","chemist","engineer","physicist","woman","human"],char:"👩‍🔬",fitzpatrick_scale:true,category:"people"},man_scientist:{keywords:["biologist","chemist","engineer","physicist","man","human"],char:"👨‍🔬",fitzpatrick_scale:true,category:"people"},woman_artist:{keywords:["painter","woman","human"],char:"👩‍🎨",fitzpatrick_scale:true,category:"people"},man_artist:{keywords:["painter","man","human"],char:"👨‍🎨",fitzpatrick_scale:true,category:"people"},woman_firefighter:{keywords:["fireman","woman","human"],char:"👩‍🚒",fitzpatrick_scale:true,category:"people"},man_firefighter:{keywords:["fireman","man","human"],char:"👨‍🚒",fitzpatrick_scale:true,category:"people"},woman_pilot:{keywords:["aviator","plane","woman","human"],char:"👩‍✈️",fitzpatrick_scale:true,category:"people"},man_pilot:{keywords:["aviator","plane","man","human"],char:"👨‍✈️",fitzpatrick_scale:true,category:"people"},woman_astronaut:{keywords:["space","rocket","woman","human"],char:"👩‍🚀",fitzpatrick_scale:true,category:"people"},man_astronaut:{keywords:["space","rocket","man","human"],char:"👨‍🚀",fitzpatrick_scale:true,category:"people"},woman_judge:{keywords:["justice","court","woman","human"],char:"👩‍⚖️",fitzpatrick_scale:true,category:"people"},man_judge:{keywords:["justice","court","man","human"],char:"👨‍⚖️",fitzpatrick_scale:true,category:"people"},woman_superhero:{keywords:["woman","female","good","heroine","superpowers"],char:"🦸‍♀️",fitzpatrick_scale:true,category:"people"},man_superhero:{keywords:["man","male","good","hero","superpowers"],char:"🦸‍♂️",fitzpatrick_scale:true,category:"people"},woman_supervillain:{keywords:["woman","female","evil","bad","criminal","heroine","superpowers"],char:"🦹‍♀️",fitzpatrick_scale:true,category:"people"},man_supervillain:{keywords:["man","male","evil","bad","criminal","hero","superpowers"],char:"🦹‍♂️",fitzpatrick_scale:true,category:"people"},mrs_claus:{keywords:["woman","female","xmas","mother christmas"],char:"🤶",fitzpatrick_scale:true,category:"people"},santa:{keywords:["festival","man","male","xmas","father christmas"],char:"🎅",fitzpatrick_scale:true,category:"people"},sorceress:{keywords:["woman","female","mage","witch"],char:"🧙‍♀️",fitzpatrick_scale:true,category:"people"},wizard:{keywords:["man","male","mage","sorcerer"],char:"🧙‍♂️",fitzpatrick_scale:true,category:"people"},woman_elf:{keywords:["woman","female"],char:"🧝‍♀️",fitzpatrick_scale:true,category:"people"},man_elf:{keywords:["man","male"],char:"🧝‍♂️",fitzpatrick_scale:true,category:"people"},woman_vampire:{keywords:["woman","female"],char:"🧛‍♀️",fitzpatrick_scale:true,category:"people"},man_vampire:{keywords:["man","male","dracula"],char:"🧛‍♂️",fitzpatrick_scale:true,category:"people"},woman_zombie:{keywords:["woman","female","undead","walking dead"],char:"🧟‍♀️",fitzpatrick_scale:false,category:"people"},man_zombie:{keywords:["man","male","dracula","undead","walking dead"],char:"🧟‍♂️",fitzpatrick_scale:false,category:"people"},woman_genie:{keywords:["woman","female"],char:"🧞‍♀️",fitzpatrick_scale:false,category:"people"},man_genie:{keywords:["man","male"],char:"🧞‍♂️",fitzpatrick_scale:false,category:"people"},mermaid:{keywords:["woman","female","merwoman","ariel"],char:"🧜‍♀️",fitzpatrick_scale:true,category:"people"},merman:{keywords:["man","male","triton"],char:"🧜‍♂️",fitzpatrick_scale:true,category:"people"},woman_fairy:{keywords:["woman","female"],char:"🧚‍♀️",fitzpatrick_scale:true,category:"people"},man_fairy:{keywords:["man","male"],char:"🧚‍♂️",fitzpatrick_scale:true,category:"people"},angel:{keywords:["heaven","wings","halo"],char:"👼",fitzpatrick_scale:true,category:"people"},pregnant_woman:{keywords:["baby"],char:"🤰",fitzpatrick_scale:true,category:"people"},breastfeeding:{keywords:["nursing","baby"],char:"🤱",fitzpatrick_scale:true,category:"people"},princess:{keywords:["girl","woman","female","blond","crown","royal","queen"],char:"👸",fitzpatrick_scale:true,category:"people"},prince:{keywords:["boy","man","male","crown","royal","king"],char:"🤴",fitzpatrick_scale:true,category:"people"},bride_with_veil:{keywords:["couple","marriage","wedding","woman","bride"],char:"👰",fitzpatrick_scale:true,category:"people"},man_in_tuxedo:{keywords:["couple","marriage","wedding","groom"],char:"🤵",fitzpatrick_scale:true,category:"people"},running_woman:{keywords:["woman","walking","exercise","race","running","female"],char:"🏃‍♀️",fitzpatrick_scale:true,category:"people"},running_man:{keywords:["man","walking","exercise","race","running"],char:"🏃",fitzpatrick_scale:true,category:"people"},walking_woman:{keywords:["human","feet","steps","woman","female"],char:"🚶‍♀️",fitzpatrick_scale:true,category:"people"},walking_man:{keywords:["human","feet","steps"],char:"🚶",fitzpatrick_scale:true,category:"people"},dancer:{keywords:["female","girl","woman","fun"],char:"💃",fitzpatrick_scale:true,category:"people"},man_dancing:{keywords:["male","boy","fun","dancer"],char:"🕺",fitzpatrick_scale:true,category:"people"},dancing_women:{keywords:["female","bunny","women","girls"],char:"👯",fitzpatrick_scale:false,category:"people"},dancing_men:{keywords:["male","bunny","men","boys"],char:"👯‍♂️",fitzpatrick_scale:false,category:"people"},couple:{keywords:["pair","people","human","love","date","dating","like","affection","valentines","marriage"],char:"👫",fitzpatrick_scale:false,category:"people"},two_men_holding_hands:{keywords:["pair","couple","love","like","bromance","friendship","people","human"],char:"👬",fitzpatrick_scale:false,category:"people"},two_women_holding_hands:{keywords:["pair","friendship","couple","love","like","female","people","human"],char:"👭",fitzpatrick_scale:false,category:"people"},bowing_woman:{keywords:["woman","female","girl"],char:"🙇‍♀️",fitzpatrick_scale:true,category:"people"},bowing_man:{keywords:["man","male","boy"],char:"🙇",fitzpatrick_scale:true,category:"people"},man_facepalming:{keywords:["man","male","boy","disbelief"],char:"🤦‍♂️",fitzpatrick_scale:true,category:"people"},woman_facepalming:{keywords:["woman","female","girl","disbelief"],char:"🤦‍♀️",fitzpatrick_scale:true,category:"people"},woman_shrugging:{keywords:["woman","female","girl","confused","indifferent","doubt"],char:"🤷",fitzpatrick_scale:true,category:"people"},man_shrugging:{keywords:["man","male","boy","confused","indifferent","doubt"],char:"🤷‍♂️",fitzpatrick_scale:true,category:"people"},tipping_hand_woman:{keywords:["female","girl","woman","human","information"],char:"💁",fitzpatrick_scale:true,category:"people"},tipping_hand_man:{keywords:["male","boy","man","human","information"],char:"💁‍♂️",fitzpatrick_scale:true,category:"people"},no_good_woman:{keywords:["female","girl","woman","nope"],char:"🙅",fitzpatrick_scale:true,category:"people"},no_good_man:{keywords:["male","boy","man","nope"],char:"🙅‍♂️",fitzpatrick_scale:true,category:"people"},ok_woman:{keywords:["women","girl","female","pink","human","woman"],char:"🙆",fitzpatrick_scale:true,category:"people"},ok_man:{keywords:["men","boy","male","blue","human","man"],char:"🙆‍♂️",fitzpatrick_scale:true,category:"people"},raising_hand_woman:{keywords:["female","girl","woman"],char:"🙋",fitzpatrick_scale:true,category:"people"},raising_hand_man:{keywords:["male","boy","man"],char:"🙋‍♂️",fitzpatrick_scale:true,category:"people"},pouting_woman:{keywords:["female","girl","woman"],char:"🙎",fitzpatrick_scale:true,category:"people"},pouting_man:{keywords:["male","boy","man"],char:"🙎‍♂️",fitzpatrick_scale:true,category:"people"},frowning_woman:{keywords:["female","girl","woman","sad","depressed","discouraged","unhappy"],char:"🙍",fitzpatrick_scale:true,category:"people"},frowning_man:{keywords:["male","boy","man","sad","depressed","discouraged","unhappy"],char:"🙍‍♂️",fitzpatrick_scale:true,category:"people"},haircut_woman:{keywords:["female","girl","woman"],char:"💇",fitzpatrick_scale:true,category:"people"},haircut_man:{keywords:["male","boy","man"],char:"💇‍♂️",fitzpatrick_scale:true,category:"people"},massage_woman:{keywords:["female","girl","woman","head"],char:"💆",fitzpatrick_scale:true,category:"people"},massage_man:{keywords:["male","boy","man","head"],char:"💆‍♂️",fitzpatrick_scale:true,category:"people"},woman_in_steamy_room:{keywords:["female","woman","spa","steamroom","sauna"],char:"🧖‍♀️",fitzpatrick_scale:true,category:"people"},man_in_steamy_room:{keywords:["male","man","spa","steamroom","sauna"],char:"🧖‍♂️",fitzpatrick_scale:true,category:"people"},couple_with_heart_woman_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"💑",fitzpatrick_scale:false,category:"people"},couple_with_heart_woman_woman:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"👩‍❤️‍👩",fitzpatrick_scale:false,category:"people"},couple_with_heart_man_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"👨‍❤️‍👨",fitzpatrick_scale:false,category:"people"},couplekiss_man_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:"💏",fitzpatrick_scale:false,category:"people"},couplekiss_woman_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:"👩‍❤️‍💋‍👩",fitzpatrick_scale:false,category:"people"},couplekiss_man_man:{keywords:["pair","valentines","love","like","dating","marriage"],char:"👨‍❤️‍💋‍👨",fitzpatrick_scale:false,category:"people"},family_man_woman_boy:{keywords:["home","parents","child","mom","dad","father","mother","people","human"],char:"👪",fitzpatrick_scale:false,category:"people"},family_man_woman_girl:{keywords:["home","parents","people","human","child"],char:"👨‍👩‍👧",fitzpatrick_scale:false,category:"people"},family_man_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:"👨‍👩‍👧‍👦",fitzpatrick_scale:false,category:"people"},family_man_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:"👨‍👩‍👦‍👦",fitzpatrick_scale:false,category:"people"},family_man_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:"👨‍👩‍👧‍👧",fitzpatrick_scale:false,category:"people"},family_woman_woman_boy:{keywords:["home","parents","people","human","children"],char:"👩‍👩‍👦",fitzpatrick_scale:false,category:"people"},family_woman_woman_girl:{keywords:["home","parents","people","human","children"],char:"👩‍👩‍👧",fitzpatrick_scale:false,category:"people"},family_woman_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:"👩‍👩‍👧‍👦",fitzpatrick_scale:false,category:"people"},family_woman_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:"👩‍👩‍👦‍👦",fitzpatrick_scale:false,category:"people"},family_woman_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:"👩‍👩‍👧‍👧",fitzpatrick_scale:false,category:"people"},family_man_man_boy:{keywords:["home","parents","people","human","children"],char:"👨‍👨‍👦",fitzpatrick_scale:false,category:"people"},family_man_man_girl:{keywords:["home","parents","people","human","children"],char:"👨‍👨‍👧",fitzpatrick_scale:false,category:"people"},family_man_man_girl_boy:{keywords:["home","parents","people","human","children"],char:"👨‍👨‍👧‍👦",fitzpatrick_scale:false,category:"people"},family_man_man_boy_boy:{keywords:["home","parents","people","human","children"],char:"👨‍👨‍👦‍👦",fitzpatrick_scale:false,category:"people"},family_man_man_girl_girl:{keywords:["home","parents","people","human","children"],char:"👨‍👨‍👧‍👧",fitzpatrick_scale:false,category:"people"},family_woman_boy:{keywords:["home","parent","people","human","child"],char:"👩‍👦",fitzpatrick_scale:false,category:"people"},family_woman_girl:{keywords:["home","parent","people","human","child"],char:"👩‍👧",fitzpatrick_scale:false,category:"people"},family_woman_girl_boy:{keywords:["home","parent","people","human","children"],char:"👩‍👧‍👦",fitzpatrick_scale:false,category:"people"},family_woman_boy_boy:{keywords:["home","parent","people","human","children"],char:"👩‍👦‍👦",fitzpatrick_scale:false,category:"people"},family_woman_girl_girl:{keywords:["home","parent","people","human","children"],char:"👩‍👧‍👧",fitzpatrick_scale:false,category:"people"},family_man_boy:{keywords:["home","parent","people","human","child"],char:"👨‍👦",fitzpatrick_scale:false,category:"people"},family_man_girl:{keywords:["home","parent","people","human","child"],char:"👨‍👧",fitzpatrick_scale:false,category:"people"},family_man_girl_boy:{keywords:["home","parent","people","human","children"],char:"👨‍👧‍👦",fitzpatrick_scale:false,category:"people"},family_man_boy_boy:{keywords:["home","parent","people","human","children"],char:"👨‍👦‍👦",fitzpatrick_scale:false,category:"people"},family_man_girl_girl:{keywords:["home","parent","people","human","children"],char:"👨‍👧‍👧",fitzpatrick_scale:false,category:"people"},yarn:{keywords:["ball","crochet","knit"],char:"🧶",fitzpatrick_scale:false,category:"people"},thread:{keywords:["needle","sewing","spool","string"],char:"🧵",fitzpatrick_scale:false,category:"people"},coat:{keywords:["jacket"],char:"🧥",fitzpatrick_scale:false,category:"people"},labcoat:{keywords:["doctor","experiment","scientist","chemist"],char:"🥼",fitzpatrick_scale:false,category:"people"},womans_clothes:{keywords:["fashion","shopping_bags","female"],char:"👚",fitzpatrick_scale:false,category:"people"},tshirt:{keywords:["fashion","cloth","casual","shirt","tee"],char:"👕",fitzpatrick_scale:false,category:"people"},jeans:{keywords:["fashion","shopping"],char:"👖",fitzpatrick_scale:false,category:"people"},necktie:{keywords:["shirt","suitup","formal","fashion","cloth","business"],char:"👔",fitzpatrick_scale:false,category:"people"},dress:{keywords:["clothes","fashion","shopping"],char:"👗",fitzpatrick_scale:false,category:"people"},bikini:{keywords:["swimming","female","woman","girl","fashion","beach","summer"],char:"👙",fitzpatrick_scale:false,category:"people"},kimono:{keywords:["dress","fashion","women","female","japanese"],char:"👘",fitzpatrick_scale:false,category:"people"},lipstick:{keywords:["female","girl","fashion","woman"],char:"💄",fitzpatrick_scale:false,category:"people"},kiss:{keywords:["face","lips","love","like","affection","valentines"],char:"💋",fitzpatrick_scale:false,category:"people"},footprints:{keywords:["feet","tracking","walking","beach"],char:"👣",fitzpatrick_scale:false,category:"people"},flat_shoe:{keywords:["ballet","slip-on","slipper"],char:"🥿",fitzpatrick_scale:false,category:"people"},high_heel:{keywords:["fashion","shoes","female","pumps","stiletto"],char:"👠",fitzpatrick_scale:false,category:"people"},sandal:{keywords:["shoes","fashion","flip flops"],char:"👡",fitzpatrick_scale:false,category:"people"},boot:{keywords:["shoes","fashion"],char:"👢",fitzpatrick_scale:false,category:"people"},mans_shoe:{keywords:["fashion","male"],char:"👞",fitzpatrick_scale:false,category:"people"},athletic_shoe:{keywords:["shoes","sports","sneakers"],char:"👟",fitzpatrick_scale:false,category:"people"},hiking_boot:{keywords:["backpacking","camping","hiking"],char:"🥾",fitzpatrick_scale:false,category:"people"},socks:{keywords:["stockings","clothes"],char:"🧦",fitzpatrick_scale:false,category:"people"},gloves:{keywords:["hands","winter","clothes"],char:"🧤",fitzpatrick_scale:false,category:"people"},scarf:{keywords:["neck","winter","clothes"],char:"🧣",fitzpatrick_scale:false,category:"people"},womans_hat:{keywords:["fashion","accessories","female","lady","spring"],char:"👒",fitzpatrick_scale:false,category:"people"},tophat:{keywords:["magic","gentleman","classy","circus"],char:"🎩",fitzpatrick_scale:false,category:"people"},billed_hat:{keywords:["cap","baseball"],char:"🧢",fitzpatrick_scale:false,category:"people"},rescue_worker_helmet:{keywords:["construction","build"],char:"⛑",fitzpatrick_scale:false,category:"people"},mortar_board:{keywords:["school","college","degree","university","graduation","cap","hat","legal","learn","education"],char:"🎓",fitzpatrick_scale:false,category:"people"},crown:{keywords:["king","kod","leader","royalty","lord"],char:"👑",fitzpatrick_scale:false,category:"people"},school_satchel:{keywords:["student","education","bag","backpack"],char:"🎒",fitzpatrick_scale:false,category:"people"},luggage:{keywords:["packing","travel"],char:"🧳",fitzpatrick_scale:false,category:"people"},pouch:{keywords:["bag","accessories","shopping"],char:"👝",fitzpatrick_scale:false,category:"people"},purse:{keywords:["fashion","accessories","money","sales","shopping"],char:"👛",fitzpatrick_scale:false,category:"people"},handbag:{keywords:["fashion","accessory","accessories","shopping"],char:"👜",fitzpatrick_scale:false,category:"people"},briefcase:{keywords:["business","documents","work","law","legal","job","career"],char:"💼",fitzpatrick_scale:false,category:"people"},eyeglasses:{keywords:["fashion","accessories","eyesight","nerdy","dork","geek"],char:"👓",fitzpatrick_scale:false,category:"people"},dark_sunglasses:{keywords:["face","cool","accessories"],char:"🕶",fitzpatrick_scale:false,category:"people"},goggles:{keywords:["eyes","protection","safety"],char:"🥽",fitzpatrick_scale:false,category:"people"},ring:{keywords:["wedding","propose","marriage","valentines","diamond","fashion","jewelry","gem","engagement"],char:"💍",fitzpatrick_scale:false,category:"people"},closed_umbrella:{keywords:["weather","rain","drizzle"],char:"🌂",fitzpatrick_scale:false,category:"people"},dog:{keywords:["animal","friend","nature","woof","puppy","pet","faithful"],char:"🐶",fitzpatrick_scale:false,category:"animals_and_nature"},cat:{keywords:["animal","meow","nature","pet","kitten"],char:"🐱",fitzpatrick_scale:false,category:"animals_and_nature"},mouse:{keywords:["animal","nature","cheese_wedge","rodent"],char:"🐭",fitzpatrick_scale:false,category:"animals_and_nature"},hamster:{keywords:["animal","nature"],char:"🐹",fitzpatrick_scale:false,category:"animals_and_nature"},rabbit:{keywords:["animal","nature","pet","spring","magic","bunny"],char:"🐰",fitzpatrick_scale:false,category:"animals_and_nature"},fox_face:{keywords:["animal","nature","face"],char:"🦊",fitzpatrick_scale:false,category:"animals_and_nature"},bear:{keywords:["animal","nature","wild"],char:"🐻",fitzpatrick_scale:false,category:"animals_and_nature"},panda_face:{keywords:["animal","nature","panda"],char:"🐼",fitzpatrick_scale:false,category:"animals_and_nature"},koala:{keywords:["animal","nature"],char:"🐨",fitzpatrick_scale:false,category:"animals_and_nature"},tiger:{keywords:["animal","cat","danger","wild","nature","roar"],char:"🐯",fitzpatrick_scale:false,category:"animals_and_nature"},lion:{keywords:["animal","nature"],char:"🦁",fitzpatrick_scale:false,category:"animals_and_nature"},cow:{keywords:["beef","ox","animal","nature","moo","milk"],char:"🐮",fitzpatrick_scale:false,category:"animals_and_nature"},pig:{keywords:["animal","oink","nature"],char:"🐷",fitzpatrick_scale:false,category:"animals_and_nature"},pig_nose:{keywords:["animal","oink"],char:"🐽",fitzpatrick_scale:false,category:"animals_and_nature"},frog:{keywords:["animal","nature","croak","toad"],char:"🐸",fitzpatrick_scale:false,category:"animals_and_nature"},squid:{keywords:["animal","nature","ocean","sea"],char:"🦑",fitzpatrick_scale:false,category:"animals_and_nature"},octopus:{keywords:["animal","creature","ocean","sea","nature","beach"],char:"🐙",fitzpatrick_scale:false,category:"animals_and_nature"},shrimp:{keywords:["animal","ocean","nature","seafood"],char:"🦐",fitzpatrick_scale:false,category:"animals_and_nature"},monkey_face:{keywords:["animal","nature","circus"],char:"🐵",fitzpatrick_scale:false,category:"animals_and_nature"},gorilla:{keywords:["animal","nature","circus"],char:"🦍",fitzpatrick_scale:false,category:"animals_and_nature"},see_no_evil:{keywords:["monkey","animal","nature","haha"],char:"🙈",fitzpatrick_scale:false,category:"animals_and_nature"},hear_no_evil:{keywords:["animal","monkey","nature"],char:"🙉",fitzpatrick_scale:false,category:"animals_and_nature"},speak_no_evil:{keywords:["monkey","animal","nature","omg"],char:"🙊",fitzpatrick_scale:false,category:"animals_and_nature"},monkey:{keywords:["animal","nature","banana","circus"],char:"🐒",fitzpatrick_scale:false,category:"animals_and_nature"},chicken:{keywords:["animal","cluck","nature","bird"],char:"🐔",fitzpatrick_scale:false,category:"animals_and_nature"},penguin:{keywords:["animal","nature"],char:"🐧",fitzpatrick_scale:false,category:"animals_and_nature"},bird:{keywords:["animal","nature","fly","tweet","spring"],char:"🐦",fitzpatrick_scale:false,category:"animals_and_nature"},baby_chick:{keywords:["animal","chicken","bird"],char:"🐤",fitzpatrick_scale:false,category:"animals_and_nature"},hatching_chick:{keywords:["animal","chicken","egg","born","baby","bird"],char:"🐣",fitzpatrick_scale:false,category:"animals_and_nature"},hatched_chick:{keywords:["animal","chicken","baby","bird"],char:"🐥",fitzpatrick_scale:false,category:"animals_and_nature"},duck:{keywords:["animal","nature","bird","mallard"],char:"🦆",fitzpatrick_scale:false,category:"animals_and_nature"},eagle:{keywords:["animal","nature","bird"],char:"🦅",fitzpatrick_scale:false,category:"animals_and_nature"},owl:{keywords:["animal","nature","bird","hoot"],char:"🦉",fitzpatrick_scale:false,category:"animals_and_nature"},bat:{keywords:["animal","nature","blind","vampire"],char:"🦇",fitzpatrick_scale:false,category:"animals_and_nature"},wolf:{keywords:["animal","nature","wild"],char:"🐺",fitzpatrick_scale:false,category:"animals_and_nature"},boar:{keywords:["animal","nature"],char:"🐗",fitzpatrick_scale:false,category:"animals_and_nature"},horse:{keywords:["animal","brown","nature"],char:"🐴",fitzpatrick_scale:false,category:"animals_and_nature"},unicorn:{keywords:["animal","nature","mystical"],char:"🦄",fitzpatrick_scale:false,category:"animals_and_nature"},honeybee:{keywords:["animal","insect","nature","bug","spring","honey"],char:"🐝",fitzpatrick_scale:false,category:"animals_and_nature"},bug:{keywords:["animal","insect","nature","worm"],char:"🐛",fitzpatrick_scale:false,category:"animals_and_nature"},butterfly:{keywords:["animal","insect","nature","caterpillar"],char:"🦋",fitzpatrick_scale:false,category:"animals_and_nature"},snail:{keywords:["slow","animal","shell"],char:"🐌",fitzpatrick_scale:false,category:"animals_and_nature"},beetle:{keywords:["animal","insect","nature","ladybug"],char:"🐞",fitzpatrick_scale:false,category:"animals_and_nature"},ant:{keywords:["animal","insect","nature","bug"],char:"🐜",fitzpatrick_scale:false,category:"animals_and_nature"},grasshopper:{keywords:["animal","cricket","chirp"],char:"🦗",fitzpatrick_scale:false,category:"animals_and_nature"},spider:{keywords:["animal","arachnid"],char:"🕷",fitzpatrick_scale:false,category:"animals_and_nature"},scorpion:{keywords:["animal","arachnid"],char:"🦂",fitzpatrick_scale:false,category:"animals_and_nature"},crab:{keywords:["animal","crustacean"],char:"🦀",fitzpatrick_scale:false,category:"animals_and_nature"},snake:{keywords:["animal","evil","nature","hiss","python"],char:"🐍",fitzpatrick_scale:false,category:"animals_and_nature"},lizard:{keywords:["animal","nature","reptile"],char:"🦎",fitzpatrick_scale:false,category:"animals_and_nature"},"t-rex":{keywords:["animal","nature","dinosaur","tyrannosaurus","extinct"],char:"🦖",fitzpatrick_scale:false,category:"animals_and_nature"},sauropod:{keywords:["animal","nature","dinosaur","brachiosaurus","brontosaurus","diplodocus","extinct"],char:"🦕",fitzpatrick_scale:false,category:"animals_and_nature"},turtle:{keywords:["animal","slow","nature","tortoise"],char:"🐢",fitzpatrick_scale:false,category:"animals_and_nature"},tropical_fish:{keywords:["animal","swim","ocean","beach","nemo"],char:"🐠",fitzpatrick_scale:false,category:"animals_and_nature"},fish:{keywords:["animal","food","nature"],char:"🐟",fitzpatrick_scale:false,category:"animals_and_nature"},blowfish:{keywords:["animal","nature","food","sea","ocean"],char:"🐡",fitzpatrick_scale:false,category:"animals_and_nature"},dolphin:{keywords:["animal","nature","fish","sea","ocean","flipper","fins","beach"],char:"🐬",fitzpatrick_scale:false,category:"animals_and_nature"},shark:{keywords:["animal","nature","fish","sea","ocean","jaws","fins","beach"],char:"🦈",fitzpatrick_scale:false,category:"animals_and_nature"},whale:{keywords:["animal","nature","sea","ocean"],char:"🐳",fitzpatrick_scale:false,category:"animals_and_nature"},whale2:{keywords:["animal","nature","sea","ocean"],char:"🐋",fitzpatrick_scale:false,category:"animals_and_nature"},crocodile:{keywords:["animal","nature","reptile","lizard","alligator"],char:"🐊",fitzpatrick_scale:false,category:"animals_and_nature"},leopard:{keywords:["animal","nature"],char:"🐆",fitzpatrick_scale:false,category:"animals_and_nature"},zebra:{keywords:["animal","nature","stripes","safari"],char:"🦓",fitzpatrick_scale:false,category:"animals_and_nature"},tiger2:{keywords:["animal","nature","roar"],char:"🐅",fitzpatrick_scale:false,category:"animals_and_nature"},water_buffalo:{keywords:["animal","nature","ox","cow"],char:"🐃",fitzpatrick_scale:false,category:"animals_and_nature"},ox:{keywords:["animal","cow","beef"],char:"🐂",fitzpatrick_scale:false,category:"animals_and_nature"},cow2:{keywords:["beef","ox","animal","nature","moo","milk"],char:"🐄",fitzpatrick_scale:false,category:"animals_and_nature"},deer:{keywords:["animal","nature","horns","venison"],char:"🦌",fitzpatrick_scale:false,category:"animals_and_nature"},dromedary_camel:{keywords:["animal","hot","desert","hump"],char:"🐪",fitzpatrick_scale:false,category:"animals_and_nature"},camel:{keywords:["animal","nature","hot","desert","hump"],char:"🐫",fitzpatrick_scale:false,category:"animals_and_nature"},giraffe:{keywords:["animal","nature","spots","safari"],char:"🦒",fitzpatrick_scale:false,category:"animals_and_nature"},elephant:{keywords:["animal","nature","nose","th","circus"],char:"🐘",fitzpatrick_scale:false,category:"animals_and_nature"},rhinoceros:{keywords:["animal","nature","horn"],char:"🦏",fitzpatrick_scale:false,category:"animals_and_nature"},goat:{keywords:["animal","nature"],char:"🐐",fitzpatrick_scale:false,category:"animals_and_nature"},ram:{keywords:["animal","sheep","nature"],char:"🐏",fitzpatrick_scale:false,category:"animals_and_nature"},sheep:{keywords:["animal","nature","wool","shipit"],char:"🐑",fitzpatrick_scale:false,category:"animals_and_nature"},racehorse:{keywords:["animal","gamble","luck"],char:"🐎",fitzpatrick_scale:false,category:"animals_and_nature"},pig2:{keywords:["animal","nature"],char:"🐖",fitzpatrick_scale:false,category:"animals_and_nature"},rat:{keywords:["animal","mouse","rodent"],char:"🐀",fitzpatrick_scale:false,category:"animals_and_nature"},mouse2:{keywords:["animal","nature","rodent"],char:"🐁",fitzpatrick_scale:false,category:"animals_and_nature"},rooster:{keywords:["animal","nature","chicken"],char:"🐓",fitzpatrick_scale:false,category:"animals_and_nature"},turkey:{keywords:["animal","bird"],char:"🦃",fitzpatrick_scale:false,category:"animals_and_nature"},dove:{keywords:["animal","bird"],char:"🕊",fitzpatrick_scale:false,category:"animals_and_nature"},dog2:{keywords:["animal","nature","friend","doge","pet","faithful"],char:"🐕",fitzpatrick_scale:false,category:"animals_and_nature"},poodle:{keywords:["dog","animal","101","nature","pet"],char:"🐩",fitzpatrick_scale:false,category:"animals_and_nature"},cat2:{keywords:["animal","meow","pet","cats"],char:"🐈",fitzpatrick_scale:false,category:"animals_and_nature"},rabbit2:{keywords:["animal","nature","pet","magic","spring"],char:"🐇",fitzpatrick_scale:false,category:"animals_and_nature"},chipmunk:{keywords:["animal","nature","rodent","squirrel"],char:"🐿",fitzpatrick_scale:false,category:"animals_and_nature"},hedgehog:{keywords:["animal","nature","spiny"],char:"🦔",fitzpatrick_scale:false,category:"animals_and_nature"},raccoon:{keywords:["animal","nature"],char:"🦝",fitzpatrick_scale:false,category:"animals_and_nature"},llama:{keywords:["animal","nature","alpaca"],char:"🦙",fitzpatrick_scale:false,category:"animals_and_nature"},hippopotamus:{keywords:["animal","nature"],char:"🦛",fitzpatrick_scale:false,category:"animals_and_nature"},kangaroo:{keywords:["animal","nature","australia","joey","hop","marsupial"],char:"🦘",fitzpatrick_scale:false,category:"animals_and_nature"},badger:{keywords:["animal","nature","honey"],char:"🦡",fitzpatrick_scale:false,category:"animals_and_nature"},swan:{keywords:["animal","nature","bird"],char:"🦢",fitzpatrick_scale:false,category:"animals_and_nature"},peacock:{keywords:["animal","nature","peahen","bird"],char:"🦚",fitzpatrick_scale:false,category:"animals_and_nature"},parrot:{keywords:["animal","nature","bird","pirate","talk"],char:"🦜",fitzpatrick_scale:false,category:"animals_and_nature"},lobster:{keywords:["animal","nature","bisque","claws","seafood"],char:"🦞",fitzpatrick_scale:false,category:"animals_and_nature"},mosquito:{keywords:["animal","nature","insect","malaria"],char:"🦟",fitzpatrick_scale:false,category:"animals_and_nature"},paw_prints:{keywords:["animal","tracking","footprints","dog","cat","pet","feet"],char:"🐾",fitzpatrick_scale:false,category:"animals_and_nature"},dragon:{keywords:["animal","myth","nature","chinese","green"],char:"🐉",fitzpatrick_scale:false,category:"animals_and_nature"},dragon_face:{keywords:["animal","myth","nature","chinese","green"],char:"🐲",fitzpatrick_scale:false,category:"animals_and_nature"},cactus:{keywords:["vegetable","plant","nature"],char:"🌵",fitzpatrick_scale:false,category:"animals_and_nature"},christmas_tree:{keywords:["festival","vacation","december","xmas","celebration"],char:"🎄",fitzpatrick_scale:false,category:"animals_and_nature"},evergreen_tree:{keywords:["plant","nature"],char:"🌲",fitzpatrick_scale:false,category:"animals_and_nature"},deciduous_tree:{keywords:["plant","nature"],char:"🌳",fitzpatrick_scale:false,category:"animals_and_nature"},palm_tree:{keywords:["plant","vegetable","nature","summer","beach","mojito","tropical"],char:"🌴",fitzpatrick_scale:false,category:"animals_and_nature"},seedling:{keywords:["plant","nature","grass","lawn","spring"],char:"🌱",fitzpatrick_scale:false,category:"animals_and_nature"},herb:{keywords:["vegetable","plant","medicine","weed","grass","lawn"],char:"🌿",fitzpatrick_scale:false,category:"animals_and_nature"},shamrock:{keywords:["vegetable","plant","nature","irish","clover"],char:"☘",fitzpatrick_scale:false,category:"animals_and_nature"},four_leaf_clover:{keywords:["vegetable","plant","nature","lucky","irish"],char:"🍀",fitzpatrick_scale:false,category:"animals_and_nature"},bamboo:{keywords:["plant","nature","vegetable","panda","pine_decoration"],char:"🎍",fitzpatrick_scale:false,category:"animals_and_nature"},tanabata_tree:{keywords:["plant","nature","branch","summer"],char:"🎋",fitzpatrick_scale:false,category:"animals_and_nature"},leaves:{keywords:["nature","plant","tree","vegetable","grass","lawn","spring"],char:"🍃",fitzpatrick_scale:false,category:"animals_and_nature"},fallen_leaf:{keywords:["nature","plant","vegetable","leaves"],char:"🍂",fitzpatrick_scale:false,category:"animals_and_nature"},maple_leaf:{keywords:["nature","plant","vegetable","ca","fall"],char:"🍁",fitzpatrick_scale:false,category:"animals_and_nature"},ear_of_rice:{keywords:["nature","plant"],char:"🌾",fitzpatrick_scale:false,category:"animals_and_nature"},hibiscus:{keywords:["plant","vegetable","flowers","beach"],char:"🌺",fitzpatrick_scale:false,category:"animals_and_nature"},sunflower:{keywords:["nature","plant","fall"],char:"🌻",fitzpatrick_scale:false,category:"animals_and_nature"},rose:{keywords:["flowers","valentines","love","spring"],char:"🌹",fitzpatrick_scale:false,category:"animals_and_nature"},wilted_flower:{keywords:["plant","nature","flower"],char:"🥀",fitzpatrick_scale:false,category:"animals_and_nature"},tulip:{keywords:["flowers","plant","nature","summer","spring"],char:"🌷",fitzpatrick_scale:false,category:"animals_and_nature"},blossom:{keywords:["nature","flowers","yellow"],char:"🌼",fitzpatrick_scale:false,category:"animals_and_nature"},cherry_blossom:{keywords:["nature","plant","spring","flower"],char:"🌸",fitzpatrick_scale:false,category:"animals_and_nature"},bouquet:{keywords:["flowers","nature","spring"],char:"💐",fitzpatrick_scale:false,category:"animals_and_nature"},mushroom:{keywords:["plant","vegetable"],char:"🍄",fitzpatrick_scale:false,category:"animals_and_nature"},chestnut:{keywords:["food","squirrel"],char:"🌰",fitzpatrick_scale:false,category:"animals_and_nature"},jack_o_lantern:{keywords:["halloween","light","pumpkin","creepy","fall"],char:"🎃",fitzpatrick_scale:false,category:"animals_and_nature"},shell:{keywords:["nature","sea","beach"],char:"🐚",fitzpatrick_scale:false,category:"animals_and_nature"},spider_web:{keywords:["animal","insect","arachnid","silk"],char:"🕸",fitzpatrick_scale:false,category:"animals_and_nature"},earth_americas:{keywords:["globe","world","USA","international"],char:"🌎",fitzpatrick_scale:false,category:"animals_and_nature"},earth_africa:{keywords:["globe","world","international"],char:"🌍",fitzpatrick_scale:false,category:"animals_and_nature"},earth_asia:{keywords:["globe","world","east","international"],char:"🌏",fitzpatrick_scale:false,category:"animals_and_nature"},full_moon:{keywords:["nature","yellow","twilight","planet","space","night","evening","sleep"],char:"🌕",fitzpatrick_scale:false,category:"animals_and_nature"},waning_gibbous_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep","waxing_gibbous_moon"],char:"🌖",fitzpatrick_scale:false,category:"animals_and_nature"},last_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌗",fitzpatrick_scale:false,category:"animals_and_nature"},waning_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌘",fitzpatrick_scale:false,category:"animals_and_nature"},new_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌑",fitzpatrick_scale:false,category:"animals_and_nature"},waxing_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌒",fitzpatrick_scale:false,category:"animals_and_nature"},first_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌓",fitzpatrick_scale:false,category:"animals_and_nature"},waxing_gibbous_moon:{keywords:["nature","night","sky","gray","twilight","planet","space","evening","sleep"],char:"🌔",fitzpatrick_scale:false,category:"animals_and_nature"},new_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌚",fitzpatrick_scale:false,category:"animals_and_nature"},full_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌝",fitzpatrick_scale:false,category:"animals_and_nature"},first_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌛",fitzpatrick_scale:false,category:"animals_and_nature"},last_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌜",fitzpatrick_scale:false,category:"animals_and_nature"},sun_with_face:{keywords:["nature","morning","sky"],char:"🌞",fitzpatrick_scale:false,category:"animals_and_nature"},crescent_moon:{keywords:["night","sleep","sky","evening","magic"],char:"🌙",fitzpatrick_scale:false,category:"animals_and_nature"},star:{keywords:["night","yellow"],char:"⭐",fitzpatrick_scale:false,category:"animals_and_nature"},star2:{keywords:["night","sparkle","awesome","good","magic"],char:"🌟",fitzpatrick_scale:false,category:"animals_and_nature"},dizzy:{keywords:["star","sparkle","shoot","magic"],char:"💫",fitzpatrick_scale:false,category:"animals_and_nature"},sparkles:{keywords:["stars","shine","shiny","cool","awesome","good","magic"],char:"✨",fitzpatrick_scale:false,category:"animals_and_nature"},comet:{keywords:["space"],char:"☄",fitzpatrick_scale:false,category:"animals_and_nature"},sunny:{keywords:["weather","nature","brightness","summer","beach","spring"],char:"☀️",fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_small_cloud:{keywords:["weather"],char:"🌤",fitzpatrick_scale:false,category:"animals_and_nature"},partly_sunny:{keywords:["weather","nature","cloudy","morning","fall","spring"],char:"⛅",fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_large_cloud:{keywords:["weather"],char:"🌥",fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_rain_cloud:{keywords:["weather"],char:"🌦",fitzpatrick_scale:false,category:"animals_and_nature"},cloud:{keywords:["weather","sky"],char:"☁️",fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_rain:{keywords:["weather"],char:"🌧",fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_lightning_and_rain:{keywords:["weather","lightning"],char:"⛈",fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_lightning:{keywords:["weather","thunder"],char:"🌩",fitzpatrick_scale:false,category:"animals_and_nature"},zap:{keywords:["thunder","weather","lightning bolt","fast"],char:"⚡",fitzpatrick_scale:false,category:"animals_and_nature"},fire:{keywords:["hot","cook","flame"],char:"🔥",fitzpatrick_scale:false,category:"animals_and_nature"},boom:{keywords:["bomb","explode","explosion","collision","blown"],char:"💥",fitzpatrick_scale:false,category:"animals_and_nature"},snowflake:{keywords:["winter","season","cold","weather","christmas","xmas"],char:"❄️",fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_snow:{keywords:["weather"],char:"🌨",fitzpatrick_scale:false,category:"animals_and_nature"},snowman:{keywords:["winter","season","cold","weather","christmas","xmas","frozen","without_snow"],char:"⛄",fitzpatrick_scale:false,category:"animals_and_nature"},snowman_with_snow:{keywords:["winter","season","cold","weather","christmas","xmas","frozen"],char:"☃",fitzpatrick_scale:false,category:"animals_and_nature"},wind_face:{keywords:["gust","air"],char:"🌬",fitzpatrick_scale:false,category:"animals_and_nature"},dash:{keywords:["wind","air","fast","shoo","fart","smoke","puff"],char:"💨",fitzpatrick_scale:false,category:"animals_and_nature"},tornado:{keywords:["weather","cyclone","twister"],char:"🌪",fitzpatrick_scale:false,category:"animals_and_nature"},fog:{keywords:["weather"],char:"🌫",fitzpatrick_scale:false,category:"animals_and_nature"},open_umbrella:{keywords:["weather","spring"],char:"☂",fitzpatrick_scale:false,category:"animals_and_nature"},umbrella:{keywords:["rainy","weather","spring"],char:"☔",fitzpatrick_scale:false,category:"animals_and_nature"},droplet:{keywords:["water","drip","faucet","spring"],char:"💧",fitzpatrick_scale:false,category:"animals_and_nature"},sweat_drops:{keywords:["water","drip","oops"],char:"💦",fitzpatrick_scale:false,category:"animals_and_nature"},ocean:{keywords:["sea","water","wave","nature","tsunami","disaster"],char:"🌊",fitzpatrick_scale:false,category:"animals_and_nature"},green_apple:{keywords:["fruit","nature"],char:"🍏",fitzpatrick_scale:false,category:"food_and_drink"},apple:{keywords:["fruit","mac","school"],char:"🍎",fitzpatrick_scale:false,category:"food_and_drink"},pear:{keywords:["fruit","nature","food"],char:"🍐",fitzpatrick_scale:false,category:"food_and_drink"},tangerine:{keywords:["food","fruit","nature","orange"],char:"🍊",fitzpatrick_scale:false,category:"food_and_drink"},lemon:{keywords:["fruit","nature"],char:"🍋",fitzpatrick_scale:false,category:"food_and_drink"},banana:{keywords:["fruit","food","monkey"],char:"🍌",fitzpatrick_scale:false,category:"food_and_drink"},watermelon:{keywords:["fruit","food","picnic","summer"],char:"🍉",fitzpatrick_scale:false,category:"food_and_drink"},grapes:{keywords:["fruit","food","wine"],char:"🍇",fitzpatrick_scale:false,category:"food_and_drink"},strawberry:{keywords:["fruit","food","nature"],char:"🍓",fitzpatrick_scale:false,category:"food_and_drink"},melon:{keywords:["fruit","nature","food"],char:"🍈",fitzpatrick_scale:false,category:"food_and_drink"},cherries:{keywords:["food","fruit"],char:"🍒",fitzpatrick_scale:false,category:"food_and_drink"},peach:{keywords:["fruit","nature","food"],char:"🍑",fitzpatrick_scale:false,category:"food_and_drink"},pineapple:{keywords:["fruit","nature","food"],char:"🍍",fitzpatrick_scale:false,category:"food_and_drink"},coconut:{keywords:["fruit","nature","food","palm"],char:"🥥",fitzpatrick_scale:false,category:"food_and_drink"},kiwi_fruit:{keywords:["fruit","food"],char:"🥝",fitzpatrick_scale:false,category:"food_and_drink"},mango:{keywords:["fruit","food","tropical"],char:"🥭",fitzpatrick_scale:false,category:"food_and_drink"},avocado:{keywords:["fruit","food"],char:"🥑",fitzpatrick_scale:false,category:"food_and_drink"},broccoli:{keywords:["fruit","food","vegetable"],char:"🥦",fitzpatrick_scale:false,category:"food_and_drink"},tomato:{keywords:["fruit","vegetable","nature","food"],char:"🍅",fitzpatrick_scale:false,category:"food_and_drink"},eggplant:{keywords:["vegetable","nature","food","aubergine"],char:"🍆",fitzpatrick_scale:false,category:"food_and_drink"},cucumber:{keywords:["fruit","food","pickle"],char:"🥒",fitzpatrick_scale:false,category:"food_and_drink"},carrot:{keywords:["vegetable","food","orange"],char:"🥕",fitzpatrick_scale:false,category:"food_and_drink"},hot_pepper:{keywords:["food","spicy","chilli","chili"],char:"🌶",fitzpatrick_scale:false,category:"food_and_drink"},potato:{keywords:["food","tuber","vegatable","starch"],char:"🥔",fitzpatrick_scale:false,category:"food_and_drink"},corn:{keywords:["food","vegetable","plant"],char:"🌽",fitzpatrick_scale:false,category:"food_and_drink"},leafy_greens:{keywords:["food","vegetable","plant","bok choy","cabbage","kale","lettuce"],char:"🥬",fitzpatrick_scale:false,category:"food_and_drink"},sweet_potato:{keywords:["food","nature"],char:"🍠",fitzpatrick_scale:false,category:"food_and_drink"},peanuts:{keywords:["food","nut"],char:"🥜",fitzpatrick_scale:false,category:"food_and_drink"},honey_pot:{keywords:["bees","sweet","kitchen"],char:"🍯",fitzpatrick_scale:false,category:"food_and_drink"},croissant:{keywords:["food","bread","french"],char:"🥐",fitzpatrick_scale:false,category:"food_and_drink"},bread:{keywords:["food","wheat","breakfast","toast"],char:"🍞",fitzpatrick_scale:false,category:"food_and_drink"},baguette_bread:{keywords:["food","bread","french"],char:"🥖",fitzpatrick_scale:false,category:"food_and_drink"},bagel:{keywords:["food","bread","bakery","schmear"],char:"🥯",fitzpatrick_scale:false,category:"food_and_drink"},pretzel:{keywords:["food","bread","twisted"],char:"🥨",fitzpatrick_scale:false,category:"food_and_drink"},cheese:{keywords:["food","chadder"],char:"🧀",fitzpatrick_scale:false,category:"food_and_drink"},egg:{keywords:["food","chicken","breakfast"],char:"🥚",fitzpatrick_scale:false,category:"food_and_drink"},bacon:{keywords:["food","breakfast","pork","pig","meat"],char:"🥓",fitzpatrick_scale:false,category:"food_and_drink"},steak:{keywords:["food","cow","meat","cut","chop","lambchop","porkchop"],char:"🥩",fitzpatrick_scale:false,category:"food_and_drink"},pancakes:{keywords:["food","breakfast","flapjacks","hotcakes"],char:"🥞",fitzpatrick_scale:false,category:"food_and_drink"},poultry_leg:{keywords:["food","meat","drumstick","bird","chicken","turkey"],char:"🍗",fitzpatrick_scale:false,category:"food_and_drink"},meat_on_bone:{keywords:["good","food","drumstick"],char:"🍖",fitzpatrick_scale:false,category:"food_and_drink"},bone:{keywords:["skeleton"],char:"🦴",fitzpatrick_scale:false,category:"food_and_drink"},fried_shrimp:{keywords:["food","animal","appetizer","summer"],char:"🍤",fitzpatrick_scale:false,category:"food_and_drink"},fried_egg:{keywords:["food","breakfast","kitchen","egg"],char:"🍳",fitzpatrick_scale:false,category:"food_and_drink"},hamburger:{keywords:["meat","fast food","beef","cheeseburger","mcdonalds","burger king"],char:"🍔",fitzpatrick_scale:false,category:"food_and_drink"},fries:{keywords:["chips","snack","fast food"],char:"🍟",fitzpatrick_scale:false,category:"food_and_drink"},stuffed_flatbread:{keywords:["food","flatbread","stuffed","gyro"],char:"🥙",fitzpatrick_scale:false,category:"food_and_drink"},hotdog:{keywords:["food","frankfurter"],char:"🌭",fitzpatrick_scale:false,category:"food_and_drink"},pizza:{keywords:["food","party"],char:"🍕",fitzpatrick_scale:false,category:"food_and_drink"},sandwich:{keywords:["food","lunch","bread"],char:"🥪",fitzpatrick_scale:false,category:"food_and_drink"},canned_food:{keywords:["food","soup"],char:"🥫",fitzpatrick_scale:false,category:"food_and_drink"},spaghetti:{keywords:["food","italian","noodle"],char:"🍝",fitzpatrick_scale:false,category:"food_and_drink"},taco:{keywords:["food","mexican"],char:"🌮",fitzpatrick_scale:false,category:"food_and_drink"},burrito:{keywords:["food","mexican"],char:"🌯",fitzpatrick_scale:false,category:"food_and_drink"},green_salad:{keywords:["food","healthy","lettuce"],char:"🥗",fitzpatrick_scale:false,category:"food_and_drink"},shallow_pan_of_food:{keywords:["food","cooking","casserole","paella"],char:"🥘",fitzpatrick_scale:false,category:"food_and_drink"},ramen:{keywords:["food","japanese","noodle","chopsticks"],char:"🍜",fitzpatrick_scale:false,category:"food_and_drink"},stew:{keywords:["food","meat","soup"],char:"🍲",fitzpatrick_scale:false,category:"food_and_drink"},fish_cake:{keywords:["food","japan","sea","beach","narutomaki","pink","swirl","kamaboko","surimi","ramen"],char:"🍥",fitzpatrick_scale:false,category:"food_and_drink"},fortune_cookie:{keywords:["food","prophecy"],char:"🥠",fitzpatrick_scale:false,category:"food_and_drink"},sushi:{keywords:["food","fish","japanese","rice"],char:"🍣",fitzpatrick_scale:false,category:"food_and_drink"},bento:{keywords:["food","japanese","box"],char:"🍱",fitzpatrick_scale:false,category:"food_and_drink"},curry:{keywords:["food","spicy","hot","indian"],char:"🍛",fitzpatrick_scale:false,category:"food_and_drink"},rice_ball:{keywords:["food","japanese"],char:"🍙",fitzpatrick_scale:false,category:"food_and_drink"},rice:{keywords:["food","china","asian"],char:"🍚",fitzpatrick_scale:false,category:"food_and_drink"},rice_cracker:{keywords:["food","japanese"],char:"🍘",fitzpatrick_scale:false,category:"food_and_drink"},oden:{keywords:["food","japanese"],char:"🍢",fitzpatrick_scale:false,category:"food_and_drink"},dango:{keywords:["food","dessert","sweet","japanese","barbecue","meat"],char:"🍡",fitzpatrick_scale:false,category:"food_and_drink"},shaved_ice:{keywords:["hot","dessert","summer"],char:"🍧",fitzpatrick_scale:false,category:"food_and_drink"},ice_cream:{keywords:["food","hot","dessert"],char:"🍨",fitzpatrick_scale:false,category:"food_and_drink"},icecream:{keywords:["food","hot","dessert","summer"],char:"🍦",fitzpatrick_scale:false,category:"food_and_drink"},pie:{keywords:["food","dessert","pastry"],char:"🥧",fitzpatrick_scale:false,category:"food_and_drink"},cake:{keywords:["food","dessert"],char:"🍰",fitzpatrick_scale:false,category:"food_and_drink"},cupcake:{keywords:["food","dessert","bakery","sweet"],char:"🧁",fitzpatrick_scale:false,category:"food_and_drink"},moon_cake:{keywords:["food","autumn"],char:"🥮",fitzpatrick_scale:false,category:"food_and_drink"},birthday:{keywords:["food","dessert","cake"],char:"🎂",fitzpatrick_scale:false,category:"food_and_drink"},custard:{keywords:["dessert","food"],char:"🍮",fitzpatrick_scale:false,category:"food_and_drink"},candy:{keywords:["snack","dessert","sweet","lolly"],char:"🍬",fitzpatrick_scale:false,category:"food_and_drink"},lollipop:{keywords:["food","snack","candy","sweet"],char:"🍭",fitzpatrick_scale:false,category:"food_and_drink"},chocolate_bar:{keywords:["food","snack","dessert","sweet"],char:"🍫",fitzpatrick_scale:false,category:"food_and_drink"},popcorn:{keywords:["food","movie theater","films","snack"],char:"🍿",fitzpatrick_scale:false,category:"food_and_drink"},dumpling:{keywords:["food","empanada","pierogi","potsticker"],char:"🥟",fitzpatrick_scale:false,category:"food_and_drink"},doughnut:{keywords:["food","dessert","snack","sweet","donut"],char:"🍩",fitzpatrick_scale:false,category:"food_and_drink"},cookie:{keywords:["food","snack","oreo","chocolate","sweet","dessert"],char:"🍪",fitzpatrick_scale:false,category:"food_and_drink"},milk_glass:{keywords:["beverage","drink","cow"],char:"🥛",fitzpatrick_scale:false,category:"food_and_drink"},beer:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:"🍺",fitzpatrick_scale:false,category:"food_and_drink"},beers:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:"🍻",fitzpatrick_scale:false,category:"food_and_drink"},clinking_glasses:{keywords:["beverage","drink","party","alcohol","celebrate","cheers","wine","champagne","toast"],char:"🥂",fitzpatrick_scale:false,category:"food_and_drink"},wine_glass:{keywords:["drink","beverage","drunk","alcohol","booze"],char:"🍷",fitzpatrick_scale:false,category:"food_and_drink"},tumbler_glass:{keywords:["drink","beverage","drunk","alcohol","liquor","booze","bourbon","scotch","whisky","glass","shot"],char:"🥃",fitzpatrick_scale:false,category:"food_and_drink"},cocktail:{keywords:["drink","drunk","alcohol","beverage","booze","mojito"],char:"🍸",fitzpatrick_scale:false,category:"food_and_drink"},tropical_drink:{keywords:["beverage","cocktail","summer","beach","alcohol","booze","mojito"],char:"🍹",fitzpatrick_scale:false,category:"food_and_drink"},champagne:{keywords:["drink","wine","bottle","celebration"],char:"🍾",fitzpatrick_scale:false,category:"food_and_drink"},sake:{keywords:["wine","drink","drunk","beverage","japanese","alcohol","booze"],char:"🍶",fitzpatrick_scale:false,category:"food_and_drink"},tea:{keywords:["drink","bowl","breakfast","green","british"],char:"🍵",fitzpatrick_scale:false,category:"food_and_drink"},cup_with_straw:{keywords:["drink","soda"],char:"🥤",fitzpatrick_scale:false,category:"food_and_drink"},coffee:{keywords:["beverage","caffeine","latte","espresso"],char:"☕",fitzpatrick_scale:false,category:"food_and_drink"},baby_bottle:{keywords:["food","container","milk"],char:"🍼",fitzpatrick_scale:false,category:"food_and_drink"},salt:{keywords:["condiment","shaker"],char:"🧂",fitzpatrick_scale:false,category:"food_and_drink"},spoon:{keywords:["cutlery","kitchen","tableware"],char:"🥄",fitzpatrick_scale:false,category:"food_and_drink"},fork_and_knife:{keywords:["cutlery","kitchen"],char:"🍴",fitzpatrick_scale:false,category:"food_and_drink"},plate_with_cutlery:{keywords:["food","eat","meal","lunch","dinner","restaurant"],char:"🍽",fitzpatrick_scale:false,category:"food_and_drink"},bowl_with_spoon:{keywords:["food","breakfast","cereal","oatmeal","porridge"],char:"🥣",fitzpatrick_scale:false,category:"food_and_drink"},takeout_box:{keywords:["food","leftovers"],char:"🥡",fitzpatrick_scale:false,category:"food_and_drink"},chopsticks:{keywords:["food"],char:"🥢",fitzpatrick_scale:false,category:"food_and_drink"},soccer:{keywords:["sports","football"],char:"⚽",fitzpatrick_scale:false,category:"activity"},basketball:{keywords:["sports","balls","NBA"],char:"🏀",fitzpatrick_scale:false,category:"activity"},football:{keywords:["sports","balls","NFL"],char:"🏈",fitzpatrick_scale:false,category:"activity"},baseball:{keywords:["sports","balls"],char:"⚾",fitzpatrick_scale:false,category:"activity"},softball:{keywords:["sports","balls"],char:"🥎",fitzpatrick_scale:false,category:"activity"},tennis:{keywords:["sports","balls","green"],char:"🎾",fitzpatrick_scale:false,category:"activity"},volleyball:{keywords:["sports","balls"],char:"🏐",fitzpatrick_scale:false,category:"activity"},rugby_football:{keywords:["sports","team"],char:"🏉",fitzpatrick_scale:false,category:"activity"},flying_disc:{keywords:["sports","frisbee","ultimate"],char:"🥏",fitzpatrick_scale:false,category:"activity"},"8ball":{keywords:["pool","hobby","game","luck","magic"],char:"🎱",fitzpatrick_scale:false,category:"activity"},golf:{keywords:["sports","business","flag","hole","summer"],char:"⛳",fitzpatrick_scale:false,category:"activity"},golfing_woman:{keywords:["sports","business","woman","female"],char:"🏌️‍♀️",fitzpatrick_scale:false,category:"activity"},golfing_man:{keywords:["sports","business"],char:"🏌",fitzpatrick_scale:true,category:"activity"},ping_pong:{keywords:["sports","pingpong"],char:"🏓",fitzpatrick_scale:false,category:"activity"},badminton:{keywords:["sports"],char:"🏸",fitzpatrick_scale:false,category:"activity"},goal_net:{keywords:["sports"],char:"🥅",fitzpatrick_scale:false,category:"activity"},ice_hockey:{keywords:["sports"],char:"🏒",fitzpatrick_scale:false,category:"activity"},field_hockey:{keywords:["sports"],char:"🏑",fitzpatrick_scale:false,category:"activity"},lacrosse:{keywords:["sports","ball","stick"],char:"🥍",fitzpatrick_scale:false,category:"activity"},cricket:{keywords:["sports"],char:"🏏",fitzpatrick_scale:false,category:"activity"},ski:{keywords:["sports","winter","cold","snow"],char:"🎿",fitzpatrick_scale:false,category:"activity"},skier:{keywords:["sports","winter","snow"],char:"⛷",fitzpatrick_scale:false,category:"activity"},snowboarder:{keywords:["sports","winter"],char:"🏂",fitzpatrick_scale:true,category:"activity"},person_fencing:{keywords:["sports","fencing","sword"],char:"🤺",fitzpatrick_scale:false,category:"activity"},women_wrestling:{keywords:["sports","wrestlers"],char:"🤼‍♀️",fitzpatrick_scale:false,category:"activity"},men_wrestling:{keywords:["sports","wrestlers"],char:"🤼‍♂️",fitzpatrick_scale:false,category:"activity"},woman_cartwheeling:{keywords:["gymnastics"],char:"🤸‍♀️",fitzpatrick_scale:true,category:"activity"},man_cartwheeling:{keywords:["gymnastics"],char:"🤸‍♂️",fitzpatrick_scale:true,category:"activity"},woman_playing_handball:{keywords:["sports"],char:"🤾‍♀️",fitzpatrick_scale:true,category:"activity"},man_playing_handball:{keywords:["sports"],char:"🤾‍♂️",fitzpatrick_scale:true,category:"activity"},ice_skate:{keywords:["sports"],char:"⛸",fitzpatrick_scale:false,category:"activity"},curling_stone:{keywords:["sports"],char:"🥌",fitzpatrick_scale:false,category:"activity"},skateboard:{keywords:["board"],char:"🛹",fitzpatrick_scale:false,category:"activity"},sled:{keywords:["sleigh","luge","toboggan"],char:"🛷",fitzpatrick_scale:false,category:"activity"},bow_and_arrow:{keywords:["sports"],char:"🏹",fitzpatrick_scale:false,category:"activity"},fishing_pole_and_fish:{keywords:["food","hobby","summer"],char:"🎣",fitzpatrick_scale:false,category:"activity"},boxing_glove:{keywords:["sports","fighting"],char:"🥊",fitzpatrick_scale:false,category:"activity"},martial_arts_uniform:{keywords:["judo","karate","taekwondo"],char:"🥋",fitzpatrick_scale:false,category:"activity"},rowing_woman:{keywords:["sports","hobby","water","ship","woman","female"],char:"🚣‍♀️",fitzpatrick_scale:true,category:"activity"},rowing_man:{keywords:["sports","hobby","water","ship"],char:"🚣",fitzpatrick_scale:true,category:"activity"},climbing_woman:{keywords:["sports","hobby","woman","female","rock"],char:"🧗‍♀️",fitzpatrick_scale:true,category:"activity"},climbing_man:{keywords:["sports","hobby","man","male","rock"],char:"🧗‍♂️",fitzpatrick_scale:true,category:"activity"},swimming_woman:{keywords:["sports","exercise","human","athlete","water","summer","woman","female"],char:"🏊‍♀️",fitzpatrick_scale:true,category:"activity"},swimming_man:{keywords:["sports","exercise","human","athlete","water","summer"],char:"🏊",fitzpatrick_scale:true,category:"activity"},woman_playing_water_polo:{keywords:["sports","pool"],char:"🤽‍♀️",fitzpatrick_scale:true,category:"activity"},man_playing_water_polo:{keywords:["sports","pool"],char:"🤽‍♂️",fitzpatrick_scale:true,category:"activity"},woman_in_lotus_position:{keywords:["woman","female","meditation","yoga","serenity","zen","mindfulness"],char:"🧘‍♀️",fitzpatrick_scale:true,category:"activity"},man_in_lotus_position:{keywords:["man","male","meditation","yoga","serenity","zen","mindfulness"],char:"🧘‍♂️",fitzpatrick_scale:true,category:"activity"},surfing_woman:{keywords:["sports","ocean","sea","summer","beach","woman","female"],char:"🏄‍♀️",fitzpatrick_scale:true,category:"activity"},surfing_man:{keywords:["sports","ocean","sea","summer","beach"],char:"🏄",fitzpatrick_scale:true,category:"activity"},bath:{keywords:["clean","shower","bathroom"],char:"🛀",fitzpatrick_scale:true,category:"activity"},basketball_woman:{keywords:["sports","human","woman","female"],char:"⛹️‍♀️",fitzpatrick_scale:true,category:"activity"},basketball_man:{keywords:["sports","human"],char:"⛹",fitzpatrick_scale:true,category:"activity"},weight_lifting_woman:{keywords:["sports","training","exercise","woman","female"],char:"🏋️‍♀️",fitzpatrick_scale:true,category:"activity"},weight_lifting_man:{keywords:["sports","training","exercise"],char:"🏋",fitzpatrick_scale:true,category:"activity"},biking_woman:{keywords:["sports","bike","exercise","hipster","woman","female"],char:"🚴‍♀️",fitzpatrick_scale:true,category:"activity"},biking_man:{keywords:["sports","bike","exercise","hipster"],char:"🚴",fitzpatrick_scale:true,category:"activity"},mountain_biking_woman:{keywords:["transportation","sports","human","race","bike","woman","female"],char:"🚵‍♀️",fitzpatrick_scale:true,category:"activity"},mountain_biking_man:{keywords:["transportation","sports","human","race","bike"],char:"🚵",fitzpatrick_scale:true,category:"activity"},horse_racing:{keywords:["animal","betting","competition","gambling","luck"],char:"🏇",fitzpatrick_scale:true,category:"activity"},business_suit_levitating:{keywords:["suit","business","levitate","hover","jump"],char:"🕴",fitzpatrick_scale:true,category:"activity"},trophy:{keywords:["win","award","contest","place","ftw","ceremony"],char:"🏆",fitzpatrick_scale:false,category:"activity"},running_shirt_with_sash:{keywords:["play","pageant"],char:"🎽",fitzpatrick_scale:false,category:"activity"},medal_sports:{keywords:["award","winning"],char:"🏅",fitzpatrick_scale:false,category:"activity"},medal_military:{keywords:["award","winning","army"],char:"🎖",fitzpatrick_scale:false,category:"activity"},"1st_place_medal":{keywords:["award","winning","first"],char:"🥇",fitzpatrick_scale:false,category:"activity"},"2nd_place_medal":{keywords:["award","second"],char:"🥈",fitzpatrick_scale:false,category:"activity"},"3rd_place_medal":{keywords:["award","third"],char:"🥉",fitzpatrick_scale:false,category:"activity"},reminder_ribbon:{keywords:["sports","cause","support","awareness"],char:"🎗",fitzpatrick_scale:false,category:"activity"},rosette:{keywords:["flower","decoration","military"],char:"🏵",fitzpatrick_scale:false,category:"activity"},ticket:{keywords:["event","concert","pass"],char:"🎫",fitzpatrick_scale:false,category:"activity"},tickets:{keywords:["sports","concert","entrance"],char:"🎟",fitzpatrick_scale:false,category:"activity"},performing_arts:{keywords:["acting","theater","drama"],char:"🎭",fitzpatrick_scale:false,category:"activity"},art:{keywords:["design","paint","draw","colors"],char:"🎨",fitzpatrick_scale:false,category:"activity"},circus_tent:{keywords:["festival","carnival","party"],char:"🎪",fitzpatrick_scale:false,category:"activity"},woman_juggling:{keywords:["juggle","balance","skill","multitask"],char:"🤹‍♀️",fitzpatrick_scale:true,category:"activity"},man_juggling:{keywords:["juggle","balance","skill","multitask"],char:"🤹‍♂️",fitzpatrick_scale:true,category:"activity"},microphone:{keywords:["sound","music","PA","sing","talkshow"],char:"🎤",fitzpatrick_scale:false,category:"activity"},headphones:{keywords:["music","score","gadgets"],char:"🎧",fitzpatrick_scale:false,category:"activity"},musical_score:{keywords:["treble","clef","compose"],char:"🎼",fitzpatrick_scale:false,category:"activity"},musical_keyboard:{keywords:["piano","instrument","compose"],char:"🎹",fitzpatrick_scale:false,category:"activity"},drum:{keywords:["music","instrument","drumsticks","snare"],char:"🥁",fitzpatrick_scale:false,category:"activity"},saxophone:{keywords:["music","instrument","jazz","blues"],char:"🎷",fitzpatrick_scale:false,category:"activity"},trumpet:{keywords:["music","brass"],char:"🎺",fitzpatrick_scale:false,category:"activity"},guitar:{keywords:["music","instrument"],char:"🎸",fitzpatrick_scale:false,category:"activity"},violin:{keywords:["music","instrument","orchestra","symphony"],char:"🎻",fitzpatrick_scale:false,category:"activity"},clapper:{keywords:["movie","film","record"],char:"🎬",fitzpatrick_scale:false,category:"activity"},video_game:{keywords:["play","console","PS4","controller"],char:"🎮",fitzpatrick_scale:false,category:"activity"},space_invader:{keywords:["game","arcade","play"],char:"👾",fitzpatrick_scale:false,category:"activity"},dart:{keywords:["game","play","bar","target","bullseye"],char:"🎯",fitzpatrick_scale:false,category:"activity"},game_die:{keywords:["dice","random","tabletop","play","luck"],char:"🎲",fitzpatrick_scale:false,category:"activity"},chess_pawn:{keywords:["expendable"],char:"♟",fitzpatrick_scale:false,category:"activity"},slot_machine:{keywords:["bet","gamble","vegas","fruit machine","luck","casino"],char:"🎰",fitzpatrick_scale:false,category:"activity"},jigsaw:{keywords:["interlocking","puzzle","piece"],char:"🧩",fitzpatrick_scale:false,category:"activity"},bowling:{keywords:["sports","fun","play"],char:"🎳",fitzpatrick_scale:false,category:"activity"},red_car:{keywords:["red","transportation","vehicle"],char:"🚗",fitzpatrick_scale:false,category:"travel_and_places"},taxi:{keywords:["uber","vehicle","cars","transportation"],char:"🚕",fitzpatrick_scale:false,category:"travel_and_places"},blue_car:{keywords:["transportation","vehicle"],char:"🚙",fitzpatrick_scale:false,category:"travel_and_places"},bus:{keywords:["car","vehicle","transportation"],char:"🚌",fitzpatrick_scale:false,category:"travel_and_places"},trolleybus:{keywords:["bart","transportation","vehicle"],char:"🚎",fitzpatrick_scale:false,category:"travel_and_places"},racing_car:{keywords:["sports","race","fast","formula","f1"],char:"🏎",fitzpatrick_scale:false,category:"travel_and_places"},police_car:{keywords:["vehicle","cars","transportation","law","legal","enforcement"],char:"🚓",fitzpatrick_scale:false,category:"travel_and_places"},ambulance:{keywords:["health","911","hospital"],char:"🚑",fitzpatrick_scale:false,category:"travel_and_places"},fire_engine:{keywords:["transportation","cars","vehicle"],char:"🚒",fitzpatrick_scale:false,category:"travel_and_places"},minibus:{keywords:["vehicle","car","transportation"],char:"🚐",fitzpatrick_scale:false,category:"travel_and_places"},truck:{keywords:["cars","transportation"],char:"🚚",fitzpatrick_scale:false,category:"travel_and_places"},articulated_lorry:{keywords:["vehicle","cars","transportation","express"],char:"🚛",fitzpatrick_scale:false,category:"travel_and_places"},tractor:{keywords:["vehicle","car","farming","agriculture"],char:"🚜",fitzpatrick_scale:false,category:"travel_and_places"},kick_scooter:{keywords:["vehicle","kick","razor"],char:"🛴",fitzpatrick_scale:false,category:"travel_and_places"},motorcycle:{keywords:["race","sports","fast"],char:"🏍",fitzpatrick_scale:false,category:"travel_and_places"},bike:{keywords:["sports","bicycle","exercise","hipster"],char:"🚲",fitzpatrick_scale:false,category:"travel_and_places"},motor_scooter:{keywords:["vehicle","vespa","sasha"],char:"🛵",fitzpatrick_scale:false,category:"travel_and_places"},rotating_light:{keywords:["police","ambulance","911","emergency","alert","error","pinged","law","legal"],char:"🚨",fitzpatrick_scale:false,category:"travel_and_places"},oncoming_police_car:{keywords:["vehicle","law","legal","enforcement","911"],char:"🚔",fitzpatrick_scale:false,category:"travel_and_places"},oncoming_bus:{keywords:["vehicle","transportation"],char:"🚍",fitzpatrick_scale:false,category:"travel_and_places"},oncoming_automobile:{keywords:["car","vehicle","transportation"],char:"🚘",fitzpatrick_scale:false,category:"travel_and_places"},oncoming_taxi:{keywords:["vehicle","cars","uber"],char:"🚖",fitzpatrick_scale:false,category:"travel_and_places"},aerial_tramway:{keywords:["transportation","vehicle","ski"],char:"🚡",fitzpatrick_scale:false,category:"travel_and_places"},mountain_cableway:{keywords:["transportation","vehicle","ski"],char:"🚠",fitzpatrick_scale:false,category:"travel_and_places"},suspension_railway:{keywords:["vehicle","transportation"],char:"🚟",fitzpatrick_scale:false,category:"travel_and_places"},railway_car:{keywords:["transportation","vehicle"],char:"🚃",fitzpatrick_scale:false,category:"travel_and_places"},train:{keywords:["transportation","vehicle","carriage","public","travel"],char:"🚋",fitzpatrick_scale:false,category:"travel_and_places"},monorail:{keywords:["transportation","vehicle"],char:"🚝",fitzpatrick_scale:false,category:"travel_and_places"},bullettrain_side:{keywords:["transportation","vehicle"],char:"🚄",fitzpatrick_scale:false,category:"travel_and_places"},bullettrain_front:{keywords:["transportation","vehicle","speed","fast","public","travel"],char:"🚅",fitzpatrick_scale:false,category:"travel_and_places"},light_rail:{keywords:["transportation","vehicle"],char:"🚈",fitzpatrick_scale:false,category:"travel_and_places"},mountain_railway:{keywords:["transportation","vehicle"],char:"🚞",fitzpatrick_scale:false,category:"travel_and_places"},steam_locomotive:{keywords:["transportation","vehicle","train"],char:"🚂",fitzpatrick_scale:false,category:"travel_and_places"},train2:{keywords:["transportation","vehicle"],char:"🚆",fitzpatrick_scale:false,category:"travel_and_places"},metro:{keywords:["transportation","blue-square","mrt","underground","tube"],char:"🚇",fitzpatrick_scale:false,category:"travel_and_places"},tram:{keywords:["transportation","vehicle"],char:"🚊",fitzpatrick_scale:false,category:"travel_and_places"},station:{keywords:["transportation","vehicle","public"],char:"🚉",fitzpatrick_scale:false,category:"travel_and_places"},flying_saucer:{keywords:["transportation","vehicle","ufo"],char:"🛸",fitzpatrick_scale:false,category:"travel_and_places"},helicopter:{keywords:["transportation","vehicle","fly"],char:"🚁",fitzpatrick_scale:false,category:"travel_and_places"},small_airplane:{keywords:["flight","transportation","fly","vehicle"],char:"🛩",fitzpatrick_scale:false,category:"travel_and_places"},airplane:{keywords:["vehicle","transportation","flight","fly"],char:"✈️",fitzpatrick_scale:false,category:"travel_and_places"},flight_departure:{keywords:["airport","flight","landing"],char:"🛫",fitzpatrick_scale:false,category:"travel_and_places"},flight_arrival:{keywords:["airport","flight","boarding"],char:"🛬",fitzpatrick_scale:false,category:"travel_and_places"},sailboat:{keywords:["ship","summer","transportation","water","sailing"],char:"⛵",fitzpatrick_scale:false,category:"travel_and_places"},motor_boat:{keywords:["ship"],char:"🛥",fitzpatrick_scale:false,category:"travel_and_places"},speedboat:{keywords:["ship","transportation","vehicle","summer"],char:"🚤",fitzpatrick_scale:false,category:"travel_and_places"},ferry:{keywords:["boat","ship","yacht"],char:"⛴",fitzpatrick_scale:false,category:"travel_and_places"},passenger_ship:{keywords:["yacht","cruise","ferry"],char:"🛳",fitzpatrick_scale:false,category:"travel_and_places"},rocket:{keywords:["launch","ship","staffmode","NASA","outer space","outer_space","fly"],char:"🚀",fitzpatrick_scale:false,category:"travel_and_places"},artificial_satellite:{keywords:["communication","gps","orbit","spaceflight","NASA","ISS"],char:"🛰",fitzpatrick_scale:false,category:"travel_and_places"},seat:{keywords:["sit","airplane","transport","bus","flight","fly"],char:"💺",fitzpatrick_scale:false,category:"travel_and_places"},canoe:{keywords:["boat","paddle","water","ship"],char:"🛶",fitzpatrick_scale:false,category:"travel_and_places"},anchor:{keywords:["ship","ferry","sea","boat"],char:"⚓",fitzpatrick_scale:false,category:"travel_and_places"},construction:{keywords:["wip","progress","caution","warning"],char:"🚧",fitzpatrick_scale:false,category:"travel_and_places"},fuelpump:{keywords:["gas station","petroleum"],char:"⛽",fitzpatrick_scale:false,category:"travel_and_places"},busstop:{keywords:["transportation","wait"],char:"🚏",fitzpatrick_scale:false,category:"travel_and_places"},vertical_traffic_light:{keywords:["transportation","driving"],char:"🚦",fitzpatrick_scale:false,category:"travel_and_places"},traffic_light:{keywords:["transportation","signal"],char:"🚥",fitzpatrick_scale:false,category:"travel_and_places"},checkered_flag:{keywords:["contest","finishline","race","gokart"],char:"🏁",fitzpatrick_scale:false,category:"travel_and_places"},ship:{keywords:["transportation","titanic","deploy"],char:"🚢",fitzpatrick_scale:false,category:"travel_and_places"},ferris_wheel:{keywords:["photo","carnival","londoneye"],char:"🎡",fitzpatrick_scale:false,category:"travel_and_places"},roller_coaster:{keywords:["carnival","playground","photo","fun"],char:"🎢",fitzpatrick_scale:false,category:"travel_and_places"},carousel_horse:{keywords:["photo","carnival"],char:"🎠",fitzpatrick_scale:false,category:"travel_and_places"},building_construction:{keywords:["wip","working","progress"],char:"🏗",fitzpatrick_scale:false,category:"travel_and_places"},foggy:{keywords:["photo","mountain"],char:"🌁",fitzpatrick_scale:false,category:"travel_and_places"},tokyo_tower:{keywords:["photo","japanese"],char:"🗼",fitzpatrick_scale:false,category:"travel_and_places"},factory:{keywords:["building","industry","pollution","smoke"],char:"🏭",fitzpatrick_scale:false,category:"travel_and_places"},fountain:{keywords:["photo","summer","water","fresh"],char:"⛲",fitzpatrick_scale:false,category:"travel_and_places"},rice_scene:{keywords:["photo","japan","asia","tsukimi"],char:"🎑",fitzpatrick_scale:false,category:"travel_and_places"},mountain:{keywords:["photo","nature","environment"],char:"⛰",fitzpatrick_scale:false,category:"travel_and_places"},mountain_snow:{keywords:["photo","nature","environment","winter","cold"],char:"🏔",fitzpatrick_scale:false,category:"travel_and_places"},mount_fuji:{keywords:["photo","mountain","nature","japanese"],char:"🗻",fitzpatrick_scale:false,category:"travel_and_places"},volcano:{keywords:["photo","nature","disaster"],char:"🌋",fitzpatrick_scale:false,category:"travel_and_places"},japan:{keywords:["nation","country","japanese","asia"],char:"🗾",fitzpatrick_scale:false,category:"travel_and_places"},camping:{keywords:["photo","outdoors","tent"],char:"🏕",fitzpatrick_scale:false,category:"travel_and_places"},tent:{keywords:["photo","camping","outdoors"],char:"⛺",fitzpatrick_scale:false,category:"travel_and_places"},national_park:{keywords:["photo","environment","nature"],char:"🏞",fitzpatrick_scale:false,category:"travel_and_places"},motorway:{keywords:["road","cupertino","interstate","highway"],char:"🛣",fitzpatrick_scale:false,category:"travel_and_places"},railway_track:{keywords:["train","transportation"],char:"🛤",fitzpatrick_scale:false,category:"travel_and_places"},sunrise:{keywords:["morning","view","vacation","photo"],char:"🌅",fitzpatrick_scale:false,category:"travel_and_places"},sunrise_over_mountains:{keywords:["view","vacation","photo"],char:"🌄",fitzpatrick_scale:false,category:"travel_and_places"},desert:{keywords:["photo","warm","saharah"],char:"🏜",fitzpatrick_scale:false,category:"travel_and_places"},beach_umbrella:{keywords:["weather","summer","sunny","sand","mojito"],char:"🏖",fitzpatrick_scale:false,category:"travel_and_places"},desert_island:{keywords:["photo","tropical","mojito"],char:"🏝",fitzpatrick_scale:false,category:"travel_and_places"},city_sunrise:{keywords:["photo","good morning","dawn"],char:"🌇",fitzpatrick_scale:false,category:"travel_and_places"},city_sunset:{keywords:["photo","evening","sky","buildings"],char:"🌆",fitzpatrick_scale:false,category:"travel_and_places"},cityscape:{keywords:["photo","night life","urban"],char:"🏙",fitzpatrick_scale:false,category:"travel_and_places"},night_with_stars:{keywords:["evening","city","downtown"],char:"🌃",fitzpatrick_scale:false,category:"travel_and_places"},bridge_at_night:{keywords:["photo","sanfrancisco"],char:"🌉",fitzpatrick_scale:false,category:"travel_and_places"},milky_way:{keywords:["photo","space","stars"],char:"🌌",fitzpatrick_scale:false,category:"travel_and_places"},stars:{keywords:["night","photo"],char:"🌠",fitzpatrick_scale:false,category:"travel_and_places"},sparkler:{keywords:["stars","night","shine"],char:"🎇",fitzpatrick_scale:false,category:"travel_and_places"},fireworks:{keywords:["photo","festival","carnival","congratulations"],char:"🎆",fitzpatrick_scale:false,category:"travel_and_places"},rainbow:{keywords:["nature","happy","unicorn_face","photo","sky","spring"],char:"🌈",fitzpatrick_scale:false,category:"travel_and_places"},houses:{keywords:["buildings","photo"],char:"🏘",fitzpatrick_scale:false,category:"travel_and_places"},european_castle:{keywords:["building","royalty","history"],char:"🏰",fitzpatrick_scale:false,category:"travel_and_places"},japanese_castle:{keywords:["photo","building"],char:"🏯",fitzpatrick_scale:false,category:"travel_and_places"},stadium:{keywords:["photo","place","sports","concert","venue"],char:"🏟",fitzpatrick_scale:false,category:"travel_and_places"},statue_of_liberty:{keywords:["american","newyork"],char:"🗽",fitzpatrick_scale:false,category:"travel_and_places"},house:{keywords:["building","home"],char:"🏠",fitzpatrick_scale:false,category:"travel_and_places"},house_with_garden:{keywords:["home","plant","nature"],char:"🏡",fitzpatrick_scale:false,category:"travel_and_places"},derelict_house:{keywords:["abandon","evict","broken","building"],char:"🏚",fitzpatrick_scale:false,category:"travel_and_places"},office:{keywords:["building","bureau","work"],char:"🏢",fitzpatrick_scale:false,category:"travel_and_places"},department_store:{keywords:["building","shopping","mall"],char:"🏬",fitzpatrick_scale:false,category:"travel_and_places"},post_office:{keywords:["building","envelope","communication"],char:"🏣",fitzpatrick_scale:false,category:"travel_and_places"},european_post_office:{keywords:["building","email"],char:"🏤",fitzpatrick_scale:false,category:"travel_and_places"},hospital:{keywords:["building","health","surgery","doctor"],char:"🏥",fitzpatrick_scale:false,category:"travel_and_places"},bank:{keywords:["building","money","sales","cash","business","enterprise"],char:"🏦",fitzpatrick_scale:false,category:"travel_and_places"},hotel:{keywords:["building","accomodation","checkin"],char:"🏨",fitzpatrick_scale:false,category:"travel_and_places"},convenience_store:{keywords:["building","shopping","groceries"],char:"🏪",fitzpatrick_scale:false,category:"travel_and_places"},school:{keywords:["building","student","education","learn","teach"],char:"🏫",fitzpatrick_scale:false,category:"travel_and_places"},love_hotel:{keywords:["like","affection","dating"],char:"🏩",fitzpatrick_scale:false,category:"travel_and_places"},wedding:{keywords:["love","like","affection","couple","marriage","bride","groom"],char:"💒",fitzpatrick_scale:false,category:"travel_and_places"},classical_building:{keywords:["art","culture","history"],char:"🏛",fitzpatrick_scale:false,category:"travel_and_places"},church:{keywords:["building","religion","christ"],char:"⛪",fitzpatrick_scale:false,category:"travel_and_places"},mosque:{keywords:["islam","worship","minaret"],char:"🕌",fitzpatrick_scale:false,category:"travel_and_places"},synagogue:{keywords:["judaism","worship","temple","jewish"],char:"🕍",fitzpatrick_scale:false,category:"travel_and_places"},kaaba:{keywords:["mecca","mosque","islam"],char:"🕋",fitzpatrick_scale:false,category:"travel_and_places"},shinto_shrine:{keywords:["temple","japan","kyoto"],char:"⛩",fitzpatrick_scale:false,category:"travel_and_places"},watch:{keywords:["time","accessories"],char:"⌚",fitzpatrick_scale:false,category:"objects"},iphone:{keywords:["technology","apple","gadgets","dial"],char:"📱",fitzpatrick_scale:false,category:"objects"},calling:{keywords:["iphone","incoming"],char:"📲",fitzpatrick_scale:false,category:"objects"},computer:{keywords:["technology","laptop","screen","display","monitor"],char:"💻",fitzpatrick_scale:false,category:"objects"},keyboard:{keywords:["technology","computer","type","input","text"],char:"⌨",fitzpatrick_scale:false,category:"objects"},desktop_computer:{keywords:["technology","computing","screen"],char:"🖥",fitzpatrick_scale:false,category:"objects"},printer:{keywords:["paper","ink"],char:"🖨",fitzpatrick_scale:false,category:"objects"},computer_mouse:{keywords:["click"],char:"🖱",fitzpatrick_scale:false,category:"objects"},trackball:{keywords:["technology","trackpad"],char:"🖲",fitzpatrick_scale:false,category:"objects"},joystick:{keywords:["game","play"],char:"🕹",fitzpatrick_scale:false,category:"objects"},clamp:{keywords:["tool"],char:"🗜",fitzpatrick_scale:false,category:"objects"},minidisc:{keywords:["technology","record","data","disk","90s"],char:"💽",fitzpatrick_scale:false,category:"objects"},floppy_disk:{keywords:["oldschool","technology","save","90s","80s"],char:"💾",fitzpatrick_scale:false,category:"objects"},cd:{keywords:["technology","dvd","disk","disc","90s"],char:"💿",fitzpatrick_scale:false,category:"objects"},dvd:{keywords:["cd","disk","disc"],char:"📀",fitzpatrick_scale:false,category:"objects"},vhs:{keywords:["record","video","oldschool","90s","80s"],char:"📼",fitzpatrick_scale:false,category:"objects"},camera:{keywords:["gadgets","photography"],char:"📷",fitzpatrick_scale:false,category:"objects"},camera_flash:{keywords:["photography","gadgets"],char:"📸",fitzpatrick_scale:false,category:"objects"},video_camera:{keywords:["film","record"],char:"📹",fitzpatrick_scale:false,category:"objects"},movie_camera:{keywords:["film","record"],char:"🎥",fitzpatrick_scale:false,category:"objects"},film_projector:{keywords:["video","tape","record","movie"],char:"📽",fitzpatrick_scale:false,category:"objects"},film_strip:{keywords:["movie"],char:"🎞",fitzpatrick_scale:false,category:"objects"},telephone_receiver:{keywords:["technology","communication","dial"],char:"📞",fitzpatrick_scale:false,category:"objects"},phone:{keywords:["technology","communication","dial","telephone"],char:"☎️",fitzpatrick_scale:false,category:"objects"},pager:{keywords:["bbcall","oldschool","90s"],char:"📟",fitzpatrick_scale:false,category:"objects"},fax:{keywords:["communication","technology"],char:"📠",fitzpatrick_scale:false,category:"objects"},tv:{keywords:["technology","program","oldschool","show","television"],char:"📺",fitzpatrick_scale:false,category:"objects"},radio:{keywords:["communication","music","podcast","program"],char:"📻",fitzpatrick_scale:false,category:"objects"},studio_microphone:{keywords:["sing","recording","artist","talkshow"],char:"🎙",fitzpatrick_scale:false,category:"objects"},level_slider:{keywords:["scale"],char:"🎚",fitzpatrick_scale:false,category:"objects"},control_knobs:{keywords:["dial"],char:"🎛",fitzpatrick_scale:false,category:"objects"},compass:{keywords:["magnetic","navigation","orienteering"],char:"🧭",fitzpatrick_scale:false,category:"objects"},stopwatch:{keywords:["time","deadline"],char:"⏱",fitzpatrick_scale:false,category:"objects"},timer_clock:{keywords:["alarm"],char:"⏲",fitzpatrick_scale:false,category:"objects"},alarm_clock:{keywords:["time","wake"],char:"⏰",fitzpatrick_scale:false,category:"objects"},mantelpiece_clock:{keywords:["time"],char:"🕰",fitzpatrick_scale:false,category:"objects"},hourglass_flowing_sand:{keywords:["oldschool","time","countdown"],char:"⏳",fitzpatrick_scale:false,category:"objects"},hourglass:{keywords:["time","clock","oldschool","limit","exam","quiz","test"],char:"⌛",fitzpatrick_scale:false,category:"objects"},satellite:{keywords:["communication","future","radio","space"],char:"📡",fitzpatrick_scale:false,category:"objects"},battery:{keywords:["power","energy","sustain"],char:"🔋",fitzpatrick_scale:false,category:"objects"},electric_plug:{keywords:["charger","power"],char:"🔌",fitzpatrick_scale:false,category:"objects"},bulb:{keywords:["light","electricity","idea"],char:"💡",fitzpatrick_scale:false,category:"objects"},flashlight:{keywords:["dark","camping","sight","night"],char:"🔦",fitzpatrick_scale:false,category:"objects"},candle:{keywords:["fire","wax"],char:"🕯",fitzpatrick_scale:false,category:"objects"},fire_extinguisher:{keywords:["quench"],char:"🧯",fitzpatrick_scale:false,category:"objects"},wastebasket:{keywords:["bin","trash","rubbish","garbage","toss"],char:"🗑",fitzpatrick_scale:false,category:"objects"},oil_drum:{keywords:["barrell"],char:"🛢",fitzpatrick_scale:false,category:"objects"},money_with_wings:{keywords:["dollar","bills","payment","sale"],char:"💸",fitzpatrick_scale:false,category:"objects"},dollar:{keywords:["money","sales","bill","currency"],char:"💵",fitzpatrick_scale:false,category:"objects"},yen:{keywords:["money","sales","japanese","dollar","currency"],char:"💴",fitzpatrick_scale:false,category:"objects"},euro:{keywords:["money","sales","dollar","currency"],char:"💶",fitzpatrick_scale:false,category:"objects"},pound:{keywords:["british","sterling","money","sales","bills","uk","england","currency"],char:"💷",fitzpatrick_scale:false,category:"objects"},moneybag:{keywords:["dollar","payment","coins","sale"],char:"💰",fitzpatrick_scale:false,category:"objects"},credit_card:{keywords:["money","sales","dollar","bill","payment","shopping"],char:"💳",fitzpatrick_scale:false,category:"objects"},gem:{keywords:["blue","ruby","diamond","jewelry"],char:"💎",fitzpatrick_scale:false,category:"objects"},balance_scale:{keywords:["law","fairness","weight"],char:"⚖",fitzpatrick_scale:false,category:"objects"},toolbox:{keywords:["tools","diy","fix","maintainer","mechanic"],char:"🧰",fitzpatrick_scale:false,category:"objects"},wrench:{keywords:["tools","diy","ikea","fix","maintainer"],char:"🔧",fitzpatrick_scale:false,category:"objects"},hammer:{keywords:["tools","build","create"],char:"🔨",fitzpatrick_scale:false,category:"objects"},hammer_and_pick:{keywords:["tools","build","create"],char:"⚒",fitzpatrick_scale:false,category:"objects"},hammer_and_wrench:{keywords:["tools","build","create"],char:"🛠",fitzpatrick_scale:false,category:"objects"},pick:{keywords:["tools","dig"],char:"⛏",fitzpatrick_scale:false,category:"objects"},nut_and_bolt:{keywords:["handy","tools","fix"],char:"🔩",fitzpatrick_scale:false,category:"objects"},gear:{keywords:["cog"],char:"⚙",fitzpatrick_scale:false,category:"objects"},brick:{keywords:["bricks"],char:"🧱",fitzpatrick_scale:false,category:"objects"},chains:{keywords:["lock","arrest"],char:"⛓",fitzpatrick_scale:false,category:"objects"},magnet:{keywords:["attraction","magnetic"],char:"🧲",fitzpatrick_scale:false,category:"objects"},gun:{keywords:["violence","weapon","pistol","revolver"],char:"🔫",fitzpatrick_scale:false,category:"objects"},bomb:{keywords:["boom","explode","explosion","terrorism"],char:"💣",fitzpatrick_scale:false,category:"objects"},firecracker:{keywords:["dynamite","boom","explode","explosion","explosive"],char:"🧨",fitzpatrick_scale:false,category:"objects"},hocho:{keywords:["knife","blade","cutlery","kitchen","weapon"],char:"🔪",fitzpatrick_scale:false,category:"objects"},dagger:{keywords:["weapon"],char:"🗡",fitzpatrick_scale:false,category:"objects"},crossed_swords:{keywords:["weapon"],char:"⚔",fitzpatrick_scale:false,category:"objects"},shield:{keywords:["protection","security"],char:"🛡",fitzpatrick_scale:false,category:"objects"},smoking:{keywords:["kills","tobacco","cigarette","joint","smoke"],char:"🚬",fitzpatrick_scale:false,category:"objects"},skull_and_crossbones:{keywords:["poison","danger","deadly","scary","death","pirate","evil"],char:"☠",fitzpatrick_scale:false,category:"objects"},coffin:{keywords:["vampire","dead","die","death","rip","graveyard","cemetery","casket","funeral","box"],char:"⚰",fitzpatrick_scale:false,category:"objects"},funeral_urn:{keywords:["dead","die","death","rip","ashes"],char:"⚱",fitzpatrick_scale:false,category:"objects"},amphora:{keywords:["vase","jar"],char:"🏺",fitzpatrick_scale:false,category:"objects"},crystal_ball:{keywords:["disco","party","magic","circus","fortune_teller"],char:"🔮",fitzpatrick_scale:false,category:"objects"},prayer_beads:{keywords:["dhikr","religious"],char:"📿",fitzpatrick_scale:false,category:"objects"},nazar_amulet:{keywords:["bead","charm"],char:"🧿",fitzpatrick_scale:false,category:"objects"},barber:{keywords:["hair","salon","style"],char:"💈",fitzpatrick_scale:false,category:"objects"},alembic:{keywords:["distilling","science","experiment","chemistry"],char:"⚗",fitzpatrick_scale:false,category:"objects"},telescope:{keywords:["stars","space","zoom","science","astronomy"],char:"🔭",fitzpatrick_scale:false,category:"objects"},microscope:{keywords:["laboratory","experiment","zoomin","science","study"],char:"🔬",fitzpatrick_scale:false,category:"objects"},hole:{keywords:["embarrassing"],char:"🕳",fitzpatrick_scale:false,category:"objects"},pill:{keywords:["health","medicine","doctor","pharmacy","drug"],char:"💊",fitzpatrick_scale:false,category:"objects"},syringe:{keywords:["health","hospital","drugs","blood","medicine","needle","doctor","nurse"],char:"💉",fitzpatrick_scale:false,category:"objects"},dna:{keywords:["biologist","genetics","life"],char:"🧬",fitzpatrick_scale:false,category:"objects"},microbe:{keywords:["amoeba","bacteria","germs"],char:"🦠",fitzpatrick_scale:false,category:"objects"},petri_dish:{keywords:["bacteria","biology","culture","lab"],char:"🧫",fitzpatrick_scale:false,category:"objects"},test_tube:{keywords:["chemistry","experiment","lab","science"],char:"🧪",fitzpatrick_scale:false,category:"objects"},thermometer:{keywords:["weather","temperature","hot","cold"],char:"🌡",fitzpatrick_scale:false,category:"objects"},broom:{keywords:["cleaning","sweeping","witch"],char:"🧹",fitzpatrick_scale:false,category:"objects"},basket:{keywords:["laundry"],char:"🧺",fitzpatrick_scale:false,category:"objects"},toilet_paper:{keywords:["roll"],char:"🧻",fitzpatrick_scale:false,category:"objects"},label:{keywords:["sale","tag"],char:"🏷",fitzpatrick_scale:false,category:"objects"},bookmark:{keywords:["favorite","label","save"],char:"🔖",fitzpatrick_scale:false,category:"objects"},toilet:{keywords:["restroom","wc","washroom","bathroom","potty"],char:"🚽",fitzpatrick_scale:false,category:"objects"},shower:{keywords:["clean","water","bathroom"],char:"🚿",fitzpatrick_scale:false,category:"objects"},bathtub:{keywords:["clean","shower","bathroom"],char:"🛁",fitzpatrick_scale:false,category:"objects"},soap:{keywords:["bar","bathing","cleaning","lather"],char:"🧼",fitzpatrick_scale:false,category:"objects"},sponge:{keywords:["absorbing","cleaning","porous"],char:"🧽",fitzpatrick_scale:false,category:"objects"},lotion_bottle:{keywords:["moisturizer","sunscreen"],char:"🧴",fitzpatrick_scale:false,category:"objects"},key:{keywords:["lock","door","password"],char:"🔑",fitzpatrick_scale:false,category:"objects"},old_key:{keywords:["lock","door","password"],char:"🗝",fitzpatrick_scale:false,category:"objects"},couch_and_lamp:{keywords:["read","chill"],char:"🛋",fitzpatrick_scale:false,category:"objects"},sleeping_bed:{keywords:["bed","rest"],char:"🛌",fitzpatrick_scale:true,category:"objects"},bed:{keywords:["sleep","rest"],char:"🛏",fitzpatrick_scale:false,category:"objects"},door:{keywords:["house","entry","exit"],char:"🚪",fitzpatrick_scale:false,category:"objects"},bellhop_bell:{keywords:["service"],char:"🛎",fitzpatrick_scale:false,category:"objects"},teddy_bear:{keywords:["plush","stuffed"],char:"🧸",fitzpatrick_scale:false,category:"objects"},framed_picture:{keywords:["photography"],char:"🖼",fitzpatrick_scale:false,category:"objects"},world_map:{keywords:["location","direction"],char:"🗺",fitzpatrick_scale:false,category:"objects"},parasol_on_ground:{keywords:["weather","summer"],char:"⛱",fitzpatrick_scale:false,category:"objects"},moyai:{keywords:["rock","easter island","moai"],char:"🗿",fitzpatrick_scale:false,category:"objects"},shopping:{keywords:["mall","buy","purchase"],char:"🛍",fitzpatrick_scale:false,category:"objects"},shopping_cart:{keywords:["trolley"],char:"🛒",fitzpatrick_scale:false,category:"objects"},balloon:{keywords:["party","celebration","birthday","circus"],char:"🎈",fitzpatrick_scale:false,category:"objects"},flags:{keywords:["fish","japanese","koinobori","carp","banner"],char:"🎏",fitzpatrick_scale:false,category:"objects"},ribbon:{keywords:["decoration","pink","girl","bowtie"],char:"🎀",fitzpatrick_scale:false,category:"objects"},gift:{keywords:["present","birthday","christmas","xmas"],char:"🎁",fitzpatrick_scale:false,category:"objects"},confetti_ball:{keywords:["festival","party","birthday","circus"],char:"🎊",fitzpatrick_scale:false,category:"objects"},tada:{keywords:["party","congratulations","birthday","magic","circus","celebration"],char:"🎉",fitzpatrick_scale:false,category:"objects"},dolls:{keywords:["japanese","toy","kimono"],char:"🎎",fitzpatrick_scale:false,category:"objects"},wind_chime:{keywords:["nature","ding","spring","bell"],char:"🎐",fitzpatrick_scale:false,category:"objects"},crossed_flags:{keywords:["japanese","nation","country","border"],char:"🎌",fitzpatrick_scale:false,category:"objects"},izakaya_lantern:{keywords:["light","paper","halloween","spooky"],char:"🏮",fitzpatrick_scale:false,category:"objects"},red_envelope:{keywords:["gift"],char:"🧧",fitzpatrick_scale:false,category:"objects"},email:{keywords:["letter","postal","inbox","communication"],char:"✉️",fitzpatrick_scale:false,category:"objects"},envelope_with_arrow:{keywords:["email","communication"],char:"📩",fitzpatrick_scale:false,category:"objects"},incoming_envelope:{keywords:["email","inbox"],char:"📨",fitzpatrick_scale:false,category:"objects"},"e-mail":{keywords:["communication","inbox"],char:"📧",fitzpatrick_scale:false,category:"objects"},love_letter:{keywords:["email","like","affection","envelope","valentines"],char:"💌",fitzpatrick_scale:false,category:"objects"},postbox:{keywords:["email","letter","envelope"],char:"📮",fitzpatrick_scale:false,category:"objects"},mailbox_closed:{keywords:["email","communication","inbox"],char:"📪",fitzpatrick_scale:false,category:"objects"},mailbox:{keywords:["email","inbox","communication"],char:"📫",fitzpatrick_scale:false,category:"objects"},mailbox_with_mail:{keywords:["email","inbox","communication"],char:"📬",fitzpatrick_scale:false,category:"objects"},mailbox_with_no_mail:{keywords:["email","inbox"],char:"📭",fitzpatrick_scale:false,category:"objects"},package:{keywords:["mail","gift","cardboard","box","moving"],char:"📦",fitzpatrick_scale:false,category:"objects"},postal_horn:{keywords:["instrument","music"],char:"📯",fitzpatrick_scale:false,category:"objects"},inbox_tray:{keywords:["email","documents"],char:"📥",fitzpatrick_scale:false,category:"objects"},outbox_tray:{keywords:["inbox","email"],char:"📤",fitzpatrick_scale:false,category:"objects"},scroll:{keywords:["documents","ancient","history","paper"],char:"📜",fitzpatrick_scale:false,category:"objects"},page_with_curl:{keywords:["documents","office","paper"],char:"📃",fitzpatrick_scale:false,category:"objects"},bookmark_tabs:{keywords:["favorite","save","order","tidy"],char:"📑",fitzpatrick_scale:false,category:"objects"},receipt:{keywords:["accounting","expenses"],char:"🧾",fitzpatrick_scale:false,category:"objects"},bar_chart:{keywords:["graph","presentation","stats"],char:"📊",fitzpatrick_scale:false,category:"objects"},chart_with_upwards_trend:{keywords:["graph","presentation","stats","recovery","business","economics","money","sales","good","success"],char:"📈",fitzpatrick_scale:false,category:"objects"},chart_with_downwards_trend:{keywords:["graph","presentation","stats","recession","business","economics","money","sales","bad","failure"],char:"📉",fitzpatrick_scale:false,category:"objects"},page_facing_up:{keywords:["documents","office","paper","information"],char:"📄",fitzpatrick_scale:false,category:"objects"},date:{keywords:["calendar","schedule"],char:"📅",fitzpatrick_scale:false,category:"objects"},calendar:{keywords:["schedule","date","planning"],char:"📆",fitzpatrick_scale:false,category:"objects"},spiral_calendar:{keywords:["date","schedule","planning"],char:"🗓",fitzpatrick_scale:false,category:"objects"},card_index:{keywords:["business","stationery"],char:"📇",fitzpatrick_scale:false,category:"objects"},card_file_box:{keywords:["business","stationery"],char:"🗃",fitzpatrick_scale:false,category:"objects"},ballot_box:{keywords:["election","vote"],char:"🗳",fitzpatrick_scale:false,category:"objects"},file_cabinet:{keywords:["filing","organizing"],char:"🗄",fitzpatrick_scale:false,category:"objects"},clipboard:{keywords:["stationery","documents"],char:"📋",fitzpatrick_scale:false,category:"objects"},spiral_notepad:{keywords:["memo","stationery"],char:"🗒",fitzpatrick_scale:false,category:"objects"},file_folder:{keywords:["documents","business","office"],char:"📁",fitzpatrick_scale:false,category:"objects"},open_file_folder:{keywords:["documents","load"],char:"📂",fitzpatrick_scale:false,category:"objects"},card_index_dividers:{keywords:["organizing","business","stationery"],char:"🗂",fitzpatrick_scale:false,category:"objects"},newspaper_roll:{keywords:["press","headline"],char:"🗞",fitzpatrick_scale:false,category:"objects"},newspaper:{keywords:["press","headline"],char:"📰",fitzpatrick_scale:false,category:"objects"},notebook:{keywords:["stationery","record","notes","paper","study"],char:"📓",fitzpatrick_scale:false,category:"objects"},closed_book:{keywords:["read","library","knowledge","textbook","learn"],char:"📕",fitzpatrick_scale:false,category:"objects"},green_book:{keywords:["read","library","knowledge","study"],char:"📗",fitzpatrick_scale:false,category:"objects"},blue_book:{keywords:["read","library","knowledge","learn","study"],char:"📘",fitzpatrick_scale:false,category:"objects"},orange_book:{keywords:["read","library","knowledge","textbook","study"],char:"📙",fitzpatrick_scale:false,category:"objects"},notebook_with_decorative_cover:{keywords:["classroom","notes","record","paper","study"],char:"📔",fitzpatrick_scale:false,category:"objects"},ledger:{keywords:["notes","paper"],char:"📒",fitzpatrick_scale:false,category:"objects"},books:{keywords:["literature","library","study"],char:"📚",fitzpatrick_scale:false,category:"objects"},open_book:{keywords:["book","read","library","knowledge","literature","learn","study"],char:"📖",fitzpatrick_scale:false,category:"objects"},safety_pin:{keywords:["diaper"],char:"🧷",fitzpatrick_scale:false,category:"objects"},link:{keywords:["rings","url"],char:"🔗",fitzpatrick_scale:false,category:"objects"},paperclip:{keywords:["documents","stationery"],char:"📎",fitzpatrick_scale:false,category:"objects"},paperclips:{keywords:["documents","stationery"],char:"🖇",fitzpatrick_scale:false,category:"objects"},scissors:{keywords:["stationery","cut"],char:"✂️",fitzpatrick_scale:false,category:"objects"},triangular_ruler:{keywords:["stationery","math","architect","sketch"],char:"📐",fitzpatrick_scale:false,category:"objects"},straight_ruler:{keywords:["stationery","calculate","length","math","school","drawing","architect","sketch"],char:"📏",fitzpatrick_scale:false,category:"objects"},abacus:{keywords:["calculation"],char:"🧮",fitzpatrick_scale:false,category:"objects"},pushpin:{keywords:["stationery","mark","here"],char:"📌",fitzpatrick_scale:false,category:"objects"},round_pushpin:{keywords:["stationery","location","map","here"],char:"📍",fitzpatrick_scale:false,category:"objects"},triangular_flag_on_post:{keywords:["mark","milestone","place"],char:"🚩",fitzpatrick_scale:false,category:"objects"},white_flag:{keywords:["losing","loser","lost","surrender","give up","fail"],char:"🏳",fitzpatrick_scale:false,category:"objects"},black_flag:{keywords:["pirate"],char:"🏴",fitzpatrick_scale:false,category:"objects"},rainbow_flag:{keywords:["flag","rainbow","pride","gay","lgbt","glbt","queer","homosexual","lesbian","bisexual","transgender"],char:"🏳️‍🌈",fitzpatrick_scale:false,category:"objects"},closed_lock_with_key:{keywords:["security","privacy"],char:"🔐",fitzpatrick_scale:false,category:"objects"},lock:{keywords:["security","password","padlock"],char:"🔒",fitzpatrick_scale:false,category:"objects"},unlock:{keywords:["privacy","security"],char:"🔓",fitzpatrick_scale:false,category:"objects"},lock_with_ink_pen:{keywords:["security","secret"],char:"🔏",fitzpatrick_scale:false,category:"objects"},pen:{keywords:["stationery","writing","write"],char:"🖊",fitzpatrick_scale:false,category:"objects"},fountain_pen:{keywords:["stationery","writing","write"],char:"🖋",fitzpatrick_scale:false,category:"objects"},black_nib:{keywords:["pen","stationery","writing","write"],char:"✒️",fitzpatrick_scale:false,category:"objects"},memo:{keywords:["write","documents","stationery","pencil","paper","writing","legal","exam","quiz","test","study","compose"],char:"📝",fitzpatrick_scale:false,category:"objects"},pencil2:{keywords:["stationery","write","paper","writing","school","study"],char:"✏️",fitzpatrick_scale:false,category:"objects"},crayon:{keywords:["drawing","creativity"],char:"🖍",fitzpatrick_scale:false,category:"objects"},paintbrush:{keywords:["drawing","creativity","art"],char:"🖌",fitzpatrick_scale:false,category:"objects"},mag:{keywords:["search","zoom","find","detective"],char:"🔍",fitzpatrick_scale:false,category:"objects"},mag_right:{keywords:["search","zoom","find","detective"],char:"🔎",fitzpatrick_scale:false,category:"objects"},heart:{keywords:["love","like","valentines"],char:"❤️",fitzpatrick_scale:false,category:"symbols"},orange_heart:{keywords:["love","like","affection","valentines"],char:"🧡",fitzpatrick_scale:false,category:"symbols"},yellow_heart:{keywords:["love","like","affection","valentines"],char:"💛",fitzpatrick_scale:false,category:"symbols"},green_heart:{keywords:["love","like","affection","valentines"],char:"💚",fitzpatrick_scale:false,category:"symbols"},blue_heart:{keywords:["love","like","affection","valentines"],char:"💙",fitzpatrick_scale:false,category:"symbols"},purple_heart:{keywords:["love","like","affection","valentines"],char:"💜",fitzpatrick_scale:false,category:"symbols"},black_heart:{keywords:["evil"],char:"🖤",fitzpatrick_scale:false,category:"symbols"},broken_heart:{keywords:["sad","sorry","break","heart","heartbreak"],char:"💔",fitzpatrick_scale:false,category:"symbols"},heavy_heart_exclamation:{keywords:["decoration","love"],char:"❣",fitzpatrick_scale:false,category:"symbols"},two_hearts:{keywords:["love","like","affection","valentines","heart"],char:"💕",fitzpatrick_scale:false,category:"symbols"},revolving_hearts:{keywords:["love","like","affection","valentines"],char:"💞",fitzpatrick_scale:false,category:"symbols"},heartbeat:{keywords:["love","like","affection","valentines","pink","heart"],char:"💓",fitzpatrick_scale:false,category:"symbols"},heartpulse:{keywords:["like","love","affection","valentines","pink"],char:"💗",fitzpatrick_scale:false,category:"symbols"},sparkling_heart:{keywords:["love","like","affection","valentines"],char:"💖",fitzpatrick_scale:false,category:"symbols"},cupid:{keywords:["love","like","heart","affection","valentines"],char:"💘",fitzpatrick_scale:false,category:"symbols"},gift_heart:{keywords:["love","valentines"],char:"💝",fitzpatrick_scale:false,category:"symbols"},heart_decoration:{keywords:["purple-square","love","like"],char:"💟",fitzpatrick_scale:false,category:"symbols"},peace_symbol:{keywords:["hippie"],char:"☮",fitzpatrick_scale:false,category:"symbols"},latin_cross:{keywords:["christianity"],char:"✝",fitzpatrick_scale:false,category:"symbols"},star_and_crescent:{keywords:["islam"],char:"☪",fitzpatrick_scale:false,category:"symbols"},om:{keywords:["hinduism","buddhism","sikhism","jainism"],char:"🕉",fitzpatrick_scale:false,category:"symbols"},wheel_of_dharma:{keywords:["hinduism","buddhism","sikhism","jainism"],char:"☸",fitzpatrick_scale:false,category:"symbols"},star_of_david:{keywords:["judaism"],char:"✡",fitzpatrick_scale:false,category:"symbols"},six_pointed_star:{keywords:["purple-square","religion","jewish","hexagram"],char:"🔯",fitzpatrick_scale:false,category:"symbols"},menorah:{keywords:["hanukkah","candles","jewish"],char:"🕎",fitzpatrick_scale:false,category:"symbols"},yin_yang:{keywords:["balance"],char:"☯",fitzpatrick_scale:false,category:"symbols"},orthodox_cross:{keywords:["suppedaneum","religion"],char:"☦",fitzpatrick_scale:false,category:"symbols"},place_of_worship:{keywords:["religion","church","temple","prayer"],char:"🛐",fitzpatrick_scale:false,category:"symbols"},ophiuchus:{keywords:["sign","purple-square","constellation","astrology"],char:"⛎",fitzpatrick_scale:false,category:"symbols"},aries:{keywords:["sign","purple-square","zodiac","astrology"],char:"♈",fitzpatrick_scale:false,category:"symbols"},taurus:{keywords:["purple-square","sign","zodiac","astrology"],char:"♉",fitzpatrick_scale:false,category:"symbols"},gemini:{keywords:["sign","zodiac","purple-square","astrology"],char:"♊",fitzpatrick_scale:false,category:"symbols"},cancer:{keywords:["sign","zodiac","purple-square","astrology"],char:"♋",fitzpatrick_scale:false,category:"symbols"},leo:{keywords:["sign","purple-square","zodiac","astrology"],char:"♌",fitzpatrick_scale:false,category:"symbols"},virgo:{keywords:["sign","zodiac","purple-square","astrology"],char:"♍",fitzpatrick_scale:false,category:"symbols"},libra:{keywords:["sign","purple-square","zodiac","astrology"],char:"♎",fitzpatrick_scale:false,category:"symbols"},scorpius:{keywords:["sign","zodiac","purple-square","astrology","scorpio"],char:"♏",fitzpatrick_scale:false,category:"symbols"},sagittarius:{keywords:["sign","zodiac","purple-square","astrology"],char:"♐",fitzpatrick_scale:false,category:"symbols"},capricorn:{keywords:["sign","zodiac","purple-square","astrology"],char:"♑",fitzpatrick_scale:false,category:"symbols"},aquarius:{keywords:["sign","purple-square","zodiac","astrology"],char:"♒",fitzpatrick_scale:false,category:"symbols"},pisces:{keywords:["purple-square","sign","zodiac","astrology"],char:"♓",fitzpatrick_scale:false,category:"symbols"},id:{keywords:["purple-square","words"],char:"🆔",fitzpatrick_scale:false,category:"symbols"},atom_symbol:{keywords:["science","physics","chemistry"],char:"⚛",fitzpatrick_scale:false,category:"symbols"},u7a7a:{keywords:["kanji","japanese","chinese","empty","sky","blue-square"],char:"🈳",fitzpatrick_scale:false,category:"symbols"},u5272:{keywords:["cut","divide","chinese","kanji","pink-square"],char:"🈹",fitzpatrick_scale:false,category:"symbols"},radioactive:{keywords:["nuclear","danger"],char:"☢",fitzpatrick_scale:false,category:"symbols"},biohazard:{keywords:["danger"],char:"☣",fitzpatrick_scale:false,category:"symbols"},mobile_phone_off:{keywords:["mute","orange-square","silence","quiet"],char:"📴",fitzpatrick_scale:false,category:"symbols"},vibration_mode:{keywords:["orange-square","phone"],char:"📳",fitzpatrick_scale:false,category:"symbols"},u6709:{keywords:["orange-square","chinese","have","kanji"],char:"🈶",fitzpatrick_scale:false,category:"symbols"},u7121:{keywords:["nothing","chinese","kanji","japanese","orange-square"],char:"🈚",fitzpatrick_scale:false,category:"symbols"},u7533:{keywords:["chinese","japanese","kanji","orange-square"],char:"🈸",fitzpatrick_scale:false,category:"symbols"},u55b6:{keywords:["japanese","opening hours","orange-square"],char:"🈺",fitzpatrick_scale:false,category:"symbols"},u6708:{keywords:["chinese","month","moon","japanese","orange-square","kanji"],char:"🈷️",fitzpatrick_scale:false,category:"symbols"},eight_pointed_black_star:{keywords:["orange-square","shape","polygon"],char:"✴️",fitzpatrick_scale:false,category:"symbols"},vs:{keywords:["words","orange-square"],char:"🆚",fitzpatrick_scale:false,category:"symbols"},accept:{keywords:["ok","good","chinese","kanji","agree","yes","orange-circle"],char:"🉑",fitzpatrick_scale:false,category:"symbols"},white_flower:{keywords:["japanese","spring"],char:"💮",fitzpatrick_scale:false,category:"symbols"},ideograph_advantage:{keywords:["chinese","kanji","obtain","get","circle"],char:"🉐",fitzpatrick_scale:false,category:"symbols"},secret:{keywords:["privacy","chinese","sshh","kanji","red-circle"],char:"㊙️",fitzpatrick_scale:false,category:"symbols"},congratulations:{keywords:["chinese","kanji","japanese","red-circle"],char:"㊗️",fitzpatrick_scale:false,category:"symbols"},u5408:{keywords:["japanese","chinese","join","kanji","red-square"],char:"🈴",fitzpatrick_scale:false,category:"symbols"},u6e80:{keywords:["full","chinese","japanese","red-square","kanji"],char:"🈵",fitzpatrick_scale:false,category:"symbols"},u7981:{keywords:["kanji","japanese","chinese","forbidden","limit","restricted","red-square"],char:"🈲",fitzpatrick_scale:false,category:"symbols"},a:{keywords:["red-square","alphabet","letter"],char:"🅰️",fitzpatrick_scale:false,category:"symbols"},b:{keywords:["red-square","alphabet","letter"],char:"🅱️",fitzpatrick_scale:false,category:"symbols"},ab:{keywords:["red-square","alphabet"],char:"🆎",fitzpatrick_scale:false,category:"symbols"},cl:{keywords:["alphabet","words","red-square"],char:"🆑",fitzpatrick_scale:false,category:"symbols"},o2:{keywords:["alphabet","red-square","letter"],char:"🅾️",fitzpatrick_scale:false,category:"symbols"},sos:{keywords:["help","red-square","words","emergency","911"],char:"🆘",fitzpatrick_scale:false,category:"symbols"},no_entry:{keywords:["limit","security","privacy","bad","denied","stop","circle"],char:"⛔",fitzpatrick_scale:false,category:"symbols"},name_badge:{keywords:["fire","forbid"],char:"📛",fitzpatrick_scale:false,category:"symbols"},no_entry_sign:{keywords:["forbid","stop","limit","denied","disallow","circle"],char:"🚫",fitzpatrick_scale:false,category:"symbols"},x:{keywords:["no","delete","remove","cancel","red"],char:"❌",fitzpatrick_scale:false,category:"symbols"},o:{keywords:["circle","round"],char:"⭕",fitzpatrick_scale:false,category:"symbols"},stop_sign:{keywords:["stop"],char:"🛑",fitzpatrick_scale:false,category:"symbols"},anger:{keywords:["angry","mad"],char:"💢",fitzpatrick_scale:false,category:"symbols"},hotsprings:{keywords:["bath","warm","relax"],char:"♨️",fitzpatrick_scale:false,category:"symbols"},no_pedestrians:{keywords:["rules","crossing","walking","circle"],char:"🚷",fitzpatrick_scale:false,category:"symbols"},do_not_litter:{keywords:["trash","bin","garbage","circle"],char:"🚯",fitzpatrick_scale:false,category:"symbols"},no_bicycles:{keywords:["cyclist","prohibited","circle"],char:"🚳",fitzpatrick_scale:false,category:"symbols"},"non-potable_water":{keywords:["drink","faucet","tap","circle"],char:"🚱",fitzpatrick_scale:false,category:"symbols"},underage:{keywords:["18","drink","pub","night","minor","circle"],char:"🔞",fitzpatrick_scale:false,category:"symbols"},no_mobile_phones:{keywords:["iphone","mute","circle"],char:"📵",fitzpatrick_scale:false,category:"symbols"},exclamation:{keywords:["heavy_exclamation_mark","danger","surprise","punctuation","wow","warning"],char:"❗",fitzpatrick_scale:false,category:"symbols"},grey_exclamation:{keywords:["surprise","punctuation","gray","wow","warning"],char:"❕",fitzpatrick_scale:false,category:"symbols"},question:{keywords:["doubt","confused"],char:"❓",fitzpatrick_scale:false,category:"symbols"},grey_question:{keywords:["doubts","gray","huh","confused"],char:"❔",fitzpatrick_scale:false,category:"symbols"},bangbang:{keywords:["exclamation","surprise"],char:"‼️",fitzpatrick_scale:false,category:"symbols"},interrobang:{keywords:["wat","punctuation","surprise"],char:"⁉️",fitzpatrick_scale:false,category:"symbols"},100:{keywords:["score","perfect","numbers","century","exam","quiz","test","pass","hundred"],char:"💯",fitzpatrick_scale:false,category:"symbols"},low_brightness:{keywords:["sun","afternoon","warm","summer"],char:"🔅",fitzpatrick_scale:false,category:"symbols"},high_brightness:{keywords:["sun","light"],char:"🔆",fitzpatrick_scale:false,category:"symbols"},trident:{keywords:["weapon","spear"],char:"🔱",fitzpatrick_scale:false,category:"symbols"},fleur_de_lis:{keywords:["decorative","scout"],char:"⚜",fitzpatrick_scale:false,category:"symbols"},part_alternation_mark:{keywords:["graph","presentation","stats","business","economics","bad"],char:"〽️",fitzpatrick_scale:false,category:"symbols"},warning:{keywords:["exclamation","wip","alert","error","problem","issue"],char:"⚠️",fitzpatrick_scale:false,category:"symbols"},children_crossing:{keywords:["school","warning","danger","sign","driving","yellow-diamond"],char:"🚸",fitzpatrick_scale:false,category:"symbols"},beginner:{keywords:["badge","shield"],char:"🔰",fitzpatrick_scale:false,category:"symbols"},recycle:{keywords:["arrow","environment","garbage","trash"],char:"♻️",fitzpatrick_scale:false,category:"symbols"},u6307:{keywords:["chinese","point","green-square","kanji"],char:"🈯",fitzpatrick_scale:false,category:"symbols"},chart:{keywords:["green-square","graph","presentation","stats"],char:"💹",fitzpatrick_scale:false,category:"symbols"},sparkle:{keywords:["stars","green-square","awesome","good","fireworks"],char:"❇️",fitzpatrick_scale:false,category:"symbols"},eight_spoked_asterisk:{keywords:["star","sparkle","green-square"],char:"✳️",fitzpatrick_scale:false,category:"symbols"},negative_squared_cross_mark:{keywords:["x","green-square","no","deny"],char:"❎",fitzpatrick_scale:false,category:"symbols"},white_check_mark:{keywords:["green-square","ok","agree","vote","election","answer","tick"],char:"✅",fitzpatrick_scale:false,category:"symbols"},diamond_shape_with_a_dot_inside:{keywords:["jewel","blue","gem","crystal","fancy"],char:"💠",fitzpatrick_scale:false,category:"symbols"},cyclone:{keywords:["weather","swirl","blue","cloud","vortex","spiral","whirlpool","spin","tornado","hurricane","typhoon"],char:"🌀",fitzpatrick_scale:false,category:"symbols"},loop:{keywords:["tape","cassette"],char:"➿",fitzpatrick_scale:false,category:"symbols"},globe_with_meridians:{keywords:["earth","international","world","internet","interweb","i18n"],char:"🌐",fitzpatrick_scale:false,category:"symbols"},m:{keywords:["alphabet","blue-circle","letter"],char:"Ⓜ️",fitzpatrick_scale:false,category:"symbols"},atm:{keywords:["money","sales","cash","blue-square","payment","bank"],char:"🏧",fitzpatrick_scale:false,category:"symbols"},sa:{keywords:["japanese","blue-square","katakana"],char:"🈂️",fitzpatrick_scale:false,category:"symbols"},passport_control:{keywords:["custom","blue-square"],char:"🛂",fitzpatrick_scale:false,category:"symbols"},customs:{keywords:["passport","border","blue-square"],char:"🛃",fitzpatrick_scale:false,category:"symbols"},baggage_claim:{keywords:["blue-square","airport","transport"],char:"🛄",fitzpatrick_scale:false,category:"symbols"},left_luggage:{keywords:["blue-square","travel"],char:"🛅",fitzpatrick_scale:false,category:"symbols"},wheelchair:{keywords:["blue-square","disabled","a11y","accessibility"],char:"♿",fitzpatrick_scale:false,category:"symbols"},no_smoking:{keywords:["cigarette","blue-square","smell","smoke"],char:"🚭",fitzpatrick_scale:false,category:"symbols"},wc:{keywords:["toilet","restroom","blue-square"],char:"🚾",fitzpatrick_scale:false,category:"symbols"},parking:{keywords:["cars","blue-square","alphabet","letter"],char:"🅿️",fitzpatrick_scale:false,category:"symbols"},potable_water:{keywords:["blue-square","liquid","restroom","cleaning","faucet"],char:"🚰",fitzpatrick_scale:false,category:"symbols"},mens:{keywords:["toilet","restroom","wc","blue-square","gender","male"],char:"🚹",fitzpatrick_scale:false,category:"symbols"},womens:{keywords:["purple-square","woman","female","toilet","loo","restroom","gender"],char:"🚺",fitzpatrick_scale:false,category:"symbols"},baby_symbol:{keywords:["orange-square","child"],char:"🚼",fitzpatrick_scale:false,category:"symbols"},restroom:{keywords:["blue-square","toilet","refresh","wc","gender"],char:"🚻",fitzpatrick_scale:false,category:"symbols"},put_litter_in_its_place:{keywords:["blue-square","sign","human","info"],char:"🚮",fitzpatrick_scale:false,category:"symbols"},cinema:{keywords:["blue-square","record","film","movie","curtain","stage","theater"],char:"🎦",fitzpatrick_scale:false,category:"symbols"},signal_strength:{keywords:["blue-square","reception","phone","internet","connection","wifi","bluetooth","bars"],char:"📶",fitzpatrick_scale:false,category:"symbols"},koko:{keywords:["blue-square","here","katakana","japanese","destination"],char:"🈁",fitzpatrick_scale:false,category:"symbols"},ng:{keywords:["blue-square","words","shape","icon"],char:"🆖",fitzpatrick_scale:false,category:"symbols"},ok:{keywords:["good","agree","yes","blue-square"],char:"🆗",fitzpatrick_scale:false,category:"symbols"},up:{keywords:["blue-square","above","high"],char:"🆙",fitzpatrick_scale:false,category:"symbols"},cool:{keywords:["words","blue-square"],char:"🆒",fitzpatrick_scale:false,category:"symbols"},new:{keywords:["blue-square","words","start"],char:"🆕",fitzpatrick_scale:false,category:"symbols"},free:{keywords:["blue-square","words"],char:"🆓",fitzpatrick_scale:false,category:"symbols"},zero:{keywords:["0","numbers","blue-square","null"],char:"0️⃣",fitzpatrick_scale:false,category:"symbols"},one:{keywords:["blue-square","numbers","1"],char:"1️⃣",fitzpatrick_scale:false,category:"symbols"},two:{keywords:["numbers","2","prime","blue-square"],char:"2️⃣",fitzpatrick_scale:false,category:"symbols"},three:{keywords:["3","numbers","prime","blue-square"],char:"3️⃣",fitzpatrick_scale:false,category:"symbols"},four:{keywords:["4","numbers","blue-square"],char:"4️⃣",fitzpatrick_scale:false,category:"symbols"},five:{keywords:["5","numbers","blue-square","prime"],char:"5️⃣",fitzpatrick_scale:false,category:"symbols"},six:{keywords:["6","numbers","blue-square"],char:"6️⃣",fitzpatrick_scale:false,category:"symbols"},seven:{keywords:["7","numbers","blue-square","prime"],char:"7️⃣",fitzpatrick_scale:false,category:"symbols"},eight:{keywords:["8","blue-square","numbers"],char:"8️⃣",fitzpatrick_scale:false,category:"symbols"},nine:{keywords:["blue-square","numbers","9"],char:"9️⃣",fitzpatrick_scale:false,category:"symbols"},keycap_ten:{keywords:["numbers","10","blue-square"],char:"🔟",fitzpatrick_scale:false,category:"symbols"},asterisk:{keywords:["star","keycap"],char:"*⃣",fitzpatrick_scale:false,category:"symbols"},1234:{keywords:["numbers","blue-square"],char:"🔢",fitzpatrick_scale:false,category:"symbols"},eject_button:{keywords:["blue-square"],char:"⏏️",fitzpatrick_scale:false,category:"symbols"},arrow_forward:{keywords:["blue-square","right","direction","play"],char:"▶️",fitzpatrick_scale:false,category:"symbols"},pause_button:{keywords:["pause","blue-square"],char:"⏸",fitzpatrick_scale:false,category:"symbols"},next_track_button:{keywords:["forward","next","blue-square"],char:"⏭",fitzpatrick_scale:false,category:"symbols"},stop_button:{keywords:["blue-square"],char:"⏹",fitzpatrick_scale:false,category:"symbols"},record_button:{keywords:["blue-square"],char:"⏺",fitzpatrick_scale:false,category:"symbols"},play_or_pause_button:{keywords:["blue-square","play","pause"],char:"⏯",fitzpatrick_scale:false,category:"symbols"},previous_track_button:{keywords:["backward"],char:"⏮",fitzpatrick_scale:false,category:"symbols"},fast_forward:{keywords:["blue-square","play","speed","continue"],char:"⏩",fitzpatrick_scale:false,category:"symbols"},rewind:{keywords:["play","blue-square"],char:"⏪",fitzpatrick_scale:false,category:"symbols"},twisted_rightwards_arrows:{keywords:["blue-square","shuffle","music","random"],char:"🔀",fitzpatrick_scale:false,category:"symbols"},repeat:{keywords:["loop","record"],char:"🔁",fitzpatrick_scale:false,category:"symbols"},repeat_one:{keywords:["blue-square","loop"],char:"🔂",fitzpatrick_scale:false,category:"symbols"},arrow_backward:{keywords:["blue-square","left","direction"],char:"◀️",fitzpatrick_scale:false,category:"symbols"},arrow_up_small:{keywords:["blue-square","triangle","direction","point","forward","top"],char:"🔼",fitzpatrick_scale:false,category:"symbols"},arrow_down_small:{keywords:["blue-square","direction","bottom"],char:"🔽",fitzpatrick_scale:false,category:"symbols"},arrow_double_up:{keywords:["blue-square","direction","top"],char:"⏫",fitzpatrick_scale:false,category:"symbols"},arrow_double_down:{keywords:["blue-square","direction","bottom"],char:"⏬",fitzpatrick_scale:false,category:"symbols"},arrow_right:{keywords:["blue-square","next"],char:"➡️",fitzpatrick_scale:false,category:"symbols"},arrow_left:{keywords:["blue-square","previous","back"],char:"⬅️",fitzpatrick_scale:false,category:"symbols"},arrow_up:{keywords:["blue-square","continue","top","direction"],char:"⬆️",fitzpatrick_scale:false,category:"symbols"},arrow_down:{keywords:["blue-square","direction","bottom"],char:"⬇️",fitzpatrick_scale:false,category:"symbols"},arrow_upper_right:{keywords:["blue-square","point","direction","diagonal","northeast"],char:"↗️",fitzpatrick_scale:false,category:"symbols"},arrow_lower_right:{keywords:["blue-square","direction","diagonal","southeast"],char:"↘️",fitzpatrick_scale:false,category:"symbols"},arrow_lower_left:{keywords:["blue-square","direction","diagonal","southwest"],char:"↙️",fitzpatrick_scale:false,category:"symbols"},arrow_upper_left:{keywords:["blue-square","point","direction","diagonal","northwest"],char:"↖️",fitzpatrick_scale:false,category:"symbols"},arrow_up_down:{keywords:["blue-square","direction","way","vertical"],char:"↕️",fitzpatrick_scale:false,category:"symbols"},left_right_arrow:{keywords:["shape","direction","horizontal","sideways"],char:"↔️",fitzpatrick_scale:false,category:"symbols"},arrows_counterclockwise:{keywords:["blue-square","sync","cycle"],char:"🔄",fitzpatrick_scale:false,category:"symbols"},arrow_right_hook:{keywords:["blue-square","return","rotate","direction"],char:"↪️",fitzpatrick_scale:false,category:"symbols"},leftwards_arrow_with_hook:{keywords:["back","return","blue-square","undo","enter"],char:"↩️",fitzpatrick_scale:false,category:"symbols"},arrow_heading_up:{keywords:["blue-square","direction","top"],char:"⤴️",fitzpatrick_scale:false,category:"symbols"},arrow_heading_down:{keywords:["blue-square","direction","bottom"],char:"⤵️",fitzpatrick_scale:false,category:"symbols"},hash:{keywords:["symbol","blue-square","twitter"],char:"#️⃣",fitzpatrick_scale:false,category:"symbols"},information_source:{keywords:["blue-square","alphabet","letter"],char:"ℹ️",fitzpatrick_scale:false,category:"symbols"},abc:{keywords:["blue-square","alphabet"],char:"🔤",fitzpatrick_scale:false,category:"symbols"},abcd:{keywords:["blue-square","alphabet"],char:"🔡",fitzpatrick_scale:false,category:"symbols"},capital_abcd:{keywords:["alphabet","words","blue-square"],char:"🔠",fitzpatrick_scale:false,category:"symbols"},symbols:{keywords:["blue-square","music","note","ampersand","percent","glyphs","characters"],char:"🔣",fitzpatrick_scale:false,category:"symbols"},musical_note:{keywords:["score","tone","sound"],char:"🎵",fitzpatrick_scale:false,category:"symbols"},notes:{keywords:["music","score"],char:"🎶",fitzpatrick_scale:false,category:"symbols"},wavy_dash:{keywords:["draw","line","moustache","mustache","squiggle","scribble"],char:"〰️",fitzpatrick_scale:false,category:"symbols"},curly_loop:{keywords:["scribble","draw","shape","squiggle"],char:"➰",fitzpatrick_scale:false,category:"symbols"},heavy_check_mark:{keywords:["ok","nike","answer","yes","tick"],char:"✔️",fitzpatrick_scale:false,category:"symbols"},arrows_clockwise:{keywords:["sync","cycle","round","repeat"],char:"🔃",fitzpatrick_scale:false,category:"symbols"},heavy_plus_sign:{keywords:["math","calculation","addition","more","increase"],char:"➕",fitzpatrick_scale:false,category:"symbols"},heavy_minus_sign:{keywords:["math","calculation","subtract","less"],char:"➖",fitzpatrick_scale:false,category:"symbols"},heavy_division_sign:{keywords:["divide","math","calculation"],char:"➗",fitzpatrick_scale:false,category:"symbols"},heavy_multiplication_x:{keywords:["math","calculation"],char:"✖️",fitzpatrick_scale:false,category:"symbols"},infinity:{keywords:["forever"],char:"♾",fitzpatrick_scale:false,category:"symbols"},heavy_dollar_sign:{keywords:["money","sales","payment","currency","buck"],char:"💲",fitzpatrick_scale:false,category:"symbols"},currency_exchange:{keywords:["money","sales","dollar","travel"],char:"💱",fitzpatrick_scale:false,category:"symbols"},copyright:{keywords:["ip","license","circle","law","legal"],char:"©️",fitzpatrick_scale:false,category:"symbols"},registered:{keywords:["alphabet","circle"],char:"®️",fitzpatrick_scale:false,category:"symbols"},tm:{keywords:["trademark","brand","law","legal"],char:"™️",fitzpatrick_scale:false,category:"symbols"},end:{keywords:["words","arrow"],char:"🔚",fitzpatrick_scale:false,category:"symbols"},back:{keywords:["arrow","words","return"],char:"🔙",fitzpatrick_scale:false,category:"symbols"},on:{keywords:["arrow","words"],char:"🔛",fitzpatrick_scale:false,category:"symbols"},top:{keywords:["words","blue-square"],char:"🔝",fitzpatrick_scale:false,category:"symbols"},soon:{keywords:["arrow","words"],char:"🔜",fitzpatrick_scale:false,category:"symbols"},ballot_box_with_check:{keywords:["ok","agree","confirm","black-square","vote","election","yes","tick"],char:"☑️",fitzpatrick_scale:false,category:"symbols"},radio_button:{keywords:["input","old","music","circle"],char:"🔘",fitzpatrick_scale:false,category:"symbols"},white_circle:{keywords:["shape","round"],char:"⚪",fitzpatrick_scale:false,category:"symbols"},black_circle:{keywords:["shape","button","round"],char:"⚫",fitzpatrick_scale:false,category:"symbols"},red_circle:{keywords:["shape","error","danger"],char:"🔴",fitzpatrick_scale:false,category:"symbols"},large_blue_circle:{keywords:["shape","icon","button"],char:"🔵",fitzpatrick_scale:false,category:"symbols"},small_orange_diamond:{keywords:["shape","jewel","gem"],char:"🔸",fitzpatrick_scale:false,category:"symbols"},small_blue_diamond:{keywords:["shape","jewel","gem"],char:"🔹",fitzpatrick_scale:false,category:"symbols"},large_orange_diamond:{keywords:["shape","jewel","gem"],char:"🔶",fitzpatrick_scale:false,category:"symbols"},large_blue_diamond:{keywords:["shape","jewel","gem"],char:"🔷",fitzpatrick_scale:false,category:"symbols"},small_red_triangle:{keywords:["shape","direction","up","top"],char:"🔺",fitzpatrick_scale:false,category:"symbols"},black_small_square:{keywords:["shape","icon"],char:"▪️",fitzpatrick_scale:false,category:"symbols"},white_small_square:{keywords:["shape","icon"],char:"▫️",fitzpatrick_scale:false,category:"symbols"},black_large_square:{keywords:["shape","icon","button"],char:"⬛",fitzpatrick_scale:false,category:"symbols"},white_large_square:{keywords:["shape","icon","stone","button"],char:"⬜",fitzpatrick_scale:false,category:"symbols"},small_red_triangle_down:{keywords:["shape","direction","bottom"],char:"🔻",fitzpatrick_scale:false,category:"symbols"},black_medium_square:{keywords:["shape","button","icon"],char:"◼️",fitzpatrick_scale:false,category:"symbols"},white_medium_square:{keywords:["shape","stone","icon"],char:"◻️",fitzpatrick_scale:false,category:"symbols"},black_medium_small_square:{keywords:["icon","shape","button"],char:"◾",fitzpatrick_scale:false,category:"symbols"},white_medium_small_square:{keywords:["shape","stone","icon","button"],char:"◽",fitzpatrick_scale:false,category:"symbols"},black_square_button:{keywords:["shape","input","frame"],char:"🔲",fitzpatrick_scale:false,category:"symbols"},white_square_button:{keywords:["shape","input"],char:"🔳",fitzpatrick_scale:false,category:"symbols"},speaker:{keywords:["sound","volume","silence","broadcast"],char:"🔈",fitzpatrick_scale:false,category:"symbols"},sound:{keywords:["volume","speaker","broadcast"],char:"🔉",fitzpatrick_scale:false,category:"symbols"},loud_sound:{keywords:["volume","noise","noisy","speaker","broadcast"],char:"🔊",fitzpatrick_scale:false,category:"symbols"},mute:{keywords:["sound","volume","silence","quiet"],char:"🔇",fitzpatrick_scale:false,category:"symbols"},mega:{keywords:["sound","speaker","volume"],char:"📣",fitzpatrick_scale:false,category:"symbols"},loudspeaker:{keywords:["volume","sound"],char:"📢",fitzpatrick_scale:false,category:"symbols"},bell:{keywords:["sound","notification","christmas","xmas","chime"],char:"🔔",fitzpatrick_scale:false,category:"symbols"},no_bell:{keywords:["sound","volume","mute","quiet","silent"],char:"🔕",fitzpatrick_scale:false,category:"symbols"},black_joker:{keywords:["poker","cards","game","play","magic"],char:"🃏",fitzpatrick_scale:false,category:"symbols"},mahjong:{keywords:["game","play","chinese","kanji"],char:"🀄",fitzpatrick_scale:false,category:"symbols"},spades:{keywords:["poker","cards","suits","magic"],char:"♠️",fitzpatrick_scale:false,category:"symbols"},clubs:{keywords:["poker","cards","magic","suits"],char:"♣️",fitzpatrick_scale:false,category:"symbols"},hearts:{keywords:["poker","cards","magic","suits"],char:"♥️",fitzpatrick_scale:false,category:"symbols"},diamonds:{keywords:["poker","cards","magic","suits"],char:"♦️",fitzpatrick_scale:false,category:"symbols"},flower_playing_cards:{keywords:["game","sunset","red"],char:"🎴",fitzpatrick_scale:false,category:"symbols"},thought_balloon:{keywords:["bubble","cloud","speech","thinking","dream"],char:"💭",fitzpatrick_scale:false,category:"symbols"},right_anger_bubble:{keywords:["caption","speech","thinking","mad"],char:"🗯",fitzpatrick_scale:false,category:"symbols"},speech_balloon:{keywords:["bubble","words","message","talk","chatting"],char:"💬",fitzpatrick_scale:false,category:"symbols"},left_speech_bubble:{keywords:["words","message","talk","chatting"],char:"🗨",fitzpatrick_scale:false,category:"symbols"},clock1:{keywords:["time","late","early","schedule"],char:"🕐",fitzpatrick_scale:false,category:"symbols"},clock2:{keywords:["time","late","early","schedule"],char:"🕑",fitzpatrick_scale:false,category:"symbols"},clock3:{keywords:["time","late","early","schedule"],char:"🕒",fitzpatrick_scale:false,category:"symbols"},clock4:{keywords:["time","late","early","schedule"],char:"🕓",fitzpatrick_scale:false,category:"symbols"},clock5:{keywords:["time","late","early","schedule"],char:"🕔",fitzpatrick_scale:false,category:"symbols"},clock6:{keywords:["time","late","early","schedule","dawn","dusk"],char:"🕕",fitzpatrick_scale:false,category:"symbols"},clock7:{keywords:["time","late","early","schedule"],char:"🕖",fitzpatrick_scale:false,category:"symbols"},clock8:{keywords:["time","late","early","schedule"],char:"🕗",fitzpatrick_scale:false,category:"symbols"},clock9:{keywords:["time","late","early","schedule"],char:"🕘",fitzpatrick_scale:false,category:"symbols"},clock10:{keywords:["time","late","early","schedule"],char:"🕙",fitzpatrick_scale:false,category:"symbols"},clock11:{keywords:["time","late","early","schedule"],char:"🕚",fitzpatrick_scale:false,category:"symbols"},clock12:{keywords:["time","noon","midnight","midday","late","early","schedule"],char:"🕛",fitzpatrick_scale:false,category:"symbols"},clock130:{keywords:["time","late","early","schedule"],char:"🕜",fitzpatrick_scale:false,category:"symbols"},clock230:{keywords:["time","late","early","schedule"],char:"🕝",fitzpatrick_scale:false,category:"symbols"},clock330:{keywords:["time","late","early","schedule"],char:"🕞",fitzpatrick_scale:false,category:"symbols"},clock430:{keywords:["time","late","early","schedule"],char:"🕟",fitzpatrick_scale:false,category:"symbols"},clock530:{keywords:["time","late","early","schedule"],char:"🕠",fitzpatrick_scale:false,category:"symbols"},clock630:{keywords:["time","late","early","schedule"],char:"🕡",fitzpatrick_scale:false,category:"symbols"},clock730:{keywords:["time","late","early","schedule"],char:"🕢",fitzpatrick_scale:false,category:"symbols"},clock830:{keywords:["time","late","early","schedule"],char:"🕣",fitzpatrick_scale:false,category:"symbols"},clock930:{keywords:["time","late","early","schedule"],char:"🕤",fitzpatrick_scale:false,category:"symbols"},clock1030:{keywords:["time","late","early","schedule"],char:"🕥",fitzpatrick_scale:false,category:"symbols"},clock1130:{keywords:["time","late","early","schedule"],char:"🕦",fitzpatrick_scale:false,category:"symbols"},clock1230:{keywords:["time","late","early","schedule"],char:"🕧",fitzpatrick_scale:false,category:"symbols"},afghanistan:{keywords:["af","flag","nation","country","banner"],char:"🇦🇫",fitzpatrick_scale:false,category:"flags"},aland_islands:{keywords:["Åland","islands","flag","nation","country","banner"],char:"🇦🇽",fitzpatrick_scale:false,category:"flags"},albania:{keywords:["al","flag","nation","country","banner"],char:"🇦🇱",fitzpatrick_scale:false,category:"flags"},algeria:{keywords:["dz","flag","nation","country","banner"],char:"🇩🇿",fitzpatrick_scale:false,category:"flags"},american_samoa:{keywords:["american","ws","flag","nation","country","banner"],char:"🇦🇸",fitzpatrick_scale:false,category:"flags"},andorra:{keywords:["ad","flag","nation","country","banner"],char:"🇦🇩",fitzpatrick_scale:false,category:"flags"},angola:{keywords:["ao","flag","nation","country","banner"],char:"🇦🇴",fitzpatrick_scale:false,category:"flags"},anguilla:{keywords:["ai","flag","nation","country","banner"],char:"🇦🇮",fitzpatrick_scale:false,category:"flags"},antarctica:{keywords:["aq","flag","nation","country","banner"],char:"🇦🇶",fitzpatrick_scale:false,category:"flags"},antigua_barbuda:{keywords:["antigua","barbuda","flag","nation","country","banner"],char:"🇦🇬",fitzpatrick_scale:false,category:"flags"},argentina:{keywords:["ar","flag","nation","country","banner"],char:"🇦🇷",fitzpatrick_scale:false,category:"flags"},armenia:{keywords:["am","flag","nation","country","banner"],char:"🇦🇲",fitzpatrick_scale:false,category:"flags"},aruba:{keywords:["aw","flag","nation","country","banner"],char:"🇦🇼",fitzpatrick_scale:false,category:"flags"},australia:{keywords:["au","flag","nation","country","banner"],char:"🇦🇺",fitzpatrick_scale:false,category:"flags"},austria:{keywords:["at","flag","nation","country","banner"],char:"🇦🇹",fitzpatrick_scale:false,category:"flags"},azerbaijan:{keywords:["az","flag","nation","country","banner"],char:"🇦🇿",fitzpatrick_scale:false,category:"flags"},bahamas:{keywords:["bs","flag","nation","country","banner"],char:"🇧🇸",fitzpatrick_scale:false,category:"flags"},bahrain:{keywords:["bh","flag","nation","country","banner"],char:"🇧🇭",fitzpatrick_scale:false,category:"flags"},bangladesh:{keywords:["bd","flag","nation","country","banner"],char:"🇧🇩",fitzpatrick_scale:false,category:"flags"},barbados:{keywords:["bb","flag","nation","country","banner"],char:"🇧🇧",fitzpatrick_scale:false,category:"flags"},belarus:{keywords:["by","flag","nation","country","banner"],char:"🇧🇾",fitzpatrick_scale:false,category:"flags"},belgium:{keywords:["be","flag","nation","country","banner"],char:"🇧🇪",fitzpatrick_scale:false,category:"flags"},belize:{keywords:["bz","flag","nation","country","banner"],char:"🇧🇿",fitzpatrick_scale:false,category:"flags"},benin:{keywords:["bj","flag","nation","country","banner"],char:"🇧🇯",fitzpatrick_scale:false,category:"flags"},bermuda:{keywords:["bm","flag","nation","country","banner"],char:"🇧🇲",fitzpatrick_scale:false,category:"flags"},bhutan:{keywords:["bt","flag","nation","country","banner"],char:"🇧🇹",fitzpatrick_scale:false,category:"flags"},bolivia:{keywords:["bo","flag","nation","country","banner"],char:"🇧🇴",fitzpatrick_scale:false,category:"flags"},caribbean_netherlands:{keywords:["bonaire","flag","nation","country","banner"],char:"🇧🇶",fitzpatrick_scale:false,category:"flags"},bosnia_herzegovina:{keywords:["bosnia","herzegovina","flag","nation","country","banner"],char:"🇧🇦",fitzpatrick_scale:false,category:"flags"},botswana:{keywords:["bw","flag","nation","country","banner"],char:"🇧🇼",fitzpatrick_scale:false,category:"flags"},brazil:{keywords:["br","flag","nation","country","banner"],char:"🇧🇷",fitzpatrick_scale:false,category:"flags"},british_indian_ocean_territory:{keywords:["british","indian","ocean","territory","flag","nation","country","banner"],char:"🇮🇴",fitzpatrick_scale:false,category:"flags"},british_virgin_islands:{keywords:["british","virgin","islands","bvi","flag","nation","country","banner"],char:"🇻🇬",fitzpatrick_scale:false,category:"flags"},brunei:{keywords:["bn","darussalam","flag","nation","country","banner"],char:"🇧🇳",fitzpatrick_scale:false,category:"flags"},bulgaria:{keywords:["bg","flag","nation","country","banner"],char:"🇧🇬",fitzpatrick_scale:false,category:"flags"},burkina_faso:{keywords:["burkina","faso","flag","nation","country","banner"],char:"🇧🇫",fitzpatrick_scale:false,category:"flags"},burundi:{keywords:["bi","flag","nation","country","banner"],char:"🇧🇮",fitzpatrick_scale:false,category:"flags"},cape_verde:{keywords:["cabo","verde","flag","nation","country","banner"],char:"🇨🇻",fitzpatrick_scale:false,category:"flags"},cambodia:{keywords:["kh","flag","nation","country","banner"],char:"🇰🇭",fitzpatrick_scale:false,category:"flags"},cameroon:{keywords:["cm","flag","nation","country","banner"],char:"🇨🇲",fitzpatrick_scale:false,category:"flags"},canada:{keywords:["ca","flag","nation","country","banner"],char:"🇨🇦",fitzpatrick_scale:false,category:"flags"},canary_islands:{keywords:["canary","islands","flag","nation","country","banner"],char:"🇮🇨",fitzpatrick_scale:false,category:"flags"},cayman_islands:{keywords:["cayman","islands","flag","nation","country","banner"],char:"🇰🇾",fitzpatrick_scale:false,category:"flags"},central_african_republic:{keywords:["central","african","republic","flag","nation","country","banner"],char:"🇨🇫",fitzpatrick_scale:false,category:"flags"},chad:{keywords:["td","flag","nation","country","banner"],char:"🇹🇩",fitzpatrick_scale:false,category:"flags"},chile:{keywords:["flag","nation","country","banner"],char:"🇨🇱",fitzpatrick_scale:false,category:"flags"},cn:{keywords:["china","chinese","prc","flag","country","nation","banner"],char:"🇨🇳",fitzpatrick_scale:false,category:"flags"},christmas_island:{keywords:["christmas","island","flag","nation","country","banner"],char:"🇨🇽",fitzpatrick_scale:false,category:"flags"},cocos_islands:{keywords:["cocos","keeling","islands","flag","nation","country","banner"],char:"🇨🇨",fitzpatrick_scale:false,category:"flags"},colombia:{keywords:["co","flag","nation","country","banner"],char:"🇨🇴",fitzpatrick_scale:false,category:"flags"},comoros:{keywords:["km","flag","nation","country","banner"],char:"🇰🇲",fitzpatrick_scale:false,category:"flags"},congo_brazzaville:{keywords:["congo","flag","nation","country","banner"],char:"🇨🇬",fitzpatrick_scale:false,category:"flags"},congo_kinshasa:{keywords:["congo","democratic","republic","flag","nation","country","banner"],char:"🇨🇩",fitzpatrick_scale:false,category:"flags"},cook_islands:{keywords:["cook","islands","flag","nation","country","banner"],char:"🇨🇰",fitzpatrick_scale:false,category:"flags"},costa_rica:{keywords:["costa","rica","flag","nation","country","banner"],char:"🇨🇷",fitzpatrick_scale:false,category:"flags"},croatia:{keywords:["hr","flag","nation","country","banner"],char:"🇭🇷",fitzpatrick_scale:false,category:"flags"},cuba:{keywords:["cu","flag","nation","country","banner"],char:"🇨🇺",fitzpatrick_scale:false,category:"flags"},curacao:{keywords:["curaçao","flag","nation","country","banner"],char:"🇨🇼",fitzpatrick_scale:false,category:"flags"},cyprus:{keywords:["cy","flag","nation","country","banner"],char:"🇨🇾",fitzpatrick_scale:false,category:"flags"},czech_republic:{keywords:["cz","flag","nation","country","banner"],char:"🇨🇿",fitzpatrick_scale:false,category:"flags"},denmark:{keywords:["dk","flag","nation","country","banner"],char:"🇩🇰",fitzpatrick_scale:false,category:"flags"},djibouti:{keywords:["dj","flag","nation","country","banner"],char:"🇩🇯",fitzpatrick_scale:false,category:"flags"},dominica:{keywords:["dm","flag","nation","country","banner"],char:"🇩🇲",fitzpatrick_scale:false,category:"flags"},dominican_republic:{keywords:["dominican","republic","flag","nation","country","banner"],char:"🇩🇴",fitzpatrick_scale:false,category:"flags"},ecuador:{keywords:["ec","flag","nation","country","banner"],char:"🇪🇨",fitzpatrick_scale:false,category:"flags"},egypt:{keywords:["eg","flag","nation","country","banner"],char:"🇪🇬",fitzpatrick_scale:false,category:"flags"},el_salvador:{keywords:["el","salvador","flag","nation","country","banner"],char:"🇸🇻",fitzpatrick_scale:false,category:"flags"},equatorial_guinea:{keywords:["equatorial","gn","flag","nation","country","banner"],char:"🇬🇶",fitzpatrick_scale:false,category:"flags"},eritrea:{keywords:["er","flag","nation","country","banner"],char:"🇪🇷",fitzpatrick_scale:false,category:"flags"},estonia:{keywords:["ee","flag","nation","country","banner"],char:"🇪🇪",fitzpatrick_scale:false,category:"flags"},ethiopia:{keywords:["et","flag","nation","country","banner"],char:"🇪🇹",fitzpatrick_scale:false,category:"flags"},eu:{keywords:["european","union","flag","banner"],char:"🇪🇺",fitzpatrick_scale:false,category:"flags"},falkland_islands:{keywords:["falkland","islands","malvinas","flag","nation","country","banner"],char:"🇫🇰",fitzpatrick_scale:false,category:"flags"},faroe_islands:{keywords:["faroe","islands","flag","nation","country","banner"],char:"🇫🇴",fitzpatrick_scale:false,category:"flags"},fiji:{keywords:["fj","flag","nation","country","banner"],char:"🇫🇯",fitzpatrick_scale:false,category:"flags"},finland:{keywords:["fi","flag","nation","country","banner"],char:"🇫🇮",fitzpatrick_scale:false,category:"flags"},fr:{keywords:["banner","flag","nation","france","french","country"],char:"🇫🇷",fitzpatrick_scale:false,category:"flags"},french_guiana:{keywords:["french","guiana","flag","nation","country","banner"],char:"🇬🇫",fitzpatrick_scale:false,category:"flags"},french_polynesia:{keywords:["french","polynesia","flag","nation","country","banner"],char:"🇵🇫",fitzpatrick_scale:false,category:"flags"},french_southern_territories:{keywords:["french","southern","territories","flag","nation","country","banner"],char:"🇹🇫",fitzpatrick_scale:false,category:"flags"},gabon:{keywords:["ga","flag","nation","country","banner"],char:"🇬🇦",fitzpatrick_scale:false,category:"flags"},gambia:{keywords:["gm","flag","nation","country","banner"],char:"🇬🇲",fitzpatrick_scale:false,category:"flags"},georgia:{keywords:["ge","flag","nation","country","banner"],char:"🇬🇪",fitzpatrick_scale:false,category:"flags"},de:{keywords:["german","nation","flag","country","banner"],char:"🇩🇪",fitzpatrick_scale:false,category:"flags"},ghana:{keywords:["gh","flag","nation","country","banner"],char:"🇬🇭",fitzpatrick_scale:false,category:"flags"},gibraltar:{keywords:["gi","flag","nation","country","banner"],char:"🇬🇮",fitzpatrick_scale:false,category:"flags"},greece:{keywords:["gr","flag","nation","country","banner"],char:"🇬🇷",fitzpatrick_scale:false,category:"flags"},greenland:{keywords:["gl","flag","nation","country","banner"],char:"🇬🇱",fitzpatrick_scale:false,category:"flags"},grenada:{keywords:["gd","flag","nation","country","banner"],char:"🇬🇩",fitzpatrick_scale:false,category:"flags"},guadeloupe:{keywords:["gp","flag","nation","country","banner"],char:"🇬🇵",fitzpatrick_scale:false,category:"flags"},guam:{keywords:["gu","flag","nation","country","banner"],char:"🇬🇺",fitzpatrick_scale:false,category:"flags"},guatemala:{keywords:["gt","flag","nation","country","banner"],char:"🇬🇹",fitzpatrick_scale:false,category:"flags"},guernsey:{keywords:["gg","flag","nation","country","banner"],char:"🇬🇬",fitzpatrick_scale:false,category:"flags"},guinea:{keywords:["gn","flag","nation","country","banner"],char:"🇬🇳",fitzpatrick_scale:false,category:"flags"},guinea_bissau:{keywords:["gw","bissau","flag","nation","country","banner"],char:"🇬🇼",fitzpatrick_scale:false,category:"flags"},guyana:{keywords:["gy","flag","nation","country","banner"],char:"🇬🇾",fitzpatrick_scale:false,category:"flags"},haiti:{keywords:["ht","flag","nation","country","banner"],char:"🇭🇹",fitzpatrick_scale:false,category:"flags"},honduras:{keywords:["hn","flag","nation","country","banner"],char:"🇭🇳",fitzpatrick_scale:false,category:"flags"},hong_kong:{keywords:["hong","kong","flag","nation","country","banner"],char:"🇭🇰",fitzpatrick_scale:false,category:"flags"},hungary:{keywords:["hu","flag","nation","country","banner"],char:"🇭🇺",fitzpatrick_scale:false,category:"flags"},iceland:{keywords:["is","flag","nation","country","banner"],char:"🇮🇸",fitzpatrick_scale:false,category:"flags"},india:{keywords:["in","flag","nation","country","banner"],char:"🇮🇳",fitzpatrick_scale:false,category:"flags"},indonesia:{keywords:["flag","nation","country","banner"],char:"🇮🇩",fitzpatrick_scale:false,category:"flags"},iran:{keywords:["iran,","islamic","republic","flag","nation","country","banner"],char:"🇮🇷",fitzpatrick_scale:false,category:"flags"},iraq:{keywords:["iq","flag","nation","country","banner"],char:"🇮🇶",fitzpatrick_scale:false,category:"flags"},ireland:{keywords:["ie","flag","nation","country","banner"],char:"🇮🇪",fitzpatrick_scale:false,category:"flags"},isle_of_man:{keywords:["isle","man","flag","nation","country","banner"],char:"🇮🇲",fitzpatrick_scale:false,category:"flags"},israel:{keywords:["il","flag","nation","country","banner"],char:"🇮🇱",fitzpatrick_scale:false,category:"flags"},it:{keywords:["italy","flag","nation","country","banner"],char:"🇮🇹",fitzpatrick_scale:false,category:"flags"},cote_divoire:{keywords:["ivory","coast","flag","nation","country","banner"],char:"🇨🇮",fitzpatrick_scale:false,category:"flags"},jamaica:{keywords:["jm","flag","nation","country","banner"],char:"🇯🇲",fitzpatrick_scale:false,category:"flags"},jp:{keywords:["japanese","nation","flag","country","banner"],char:"🇯🇵",fitzpatrick_scale:false,category:"flags"},jersey:{keywords:["je","flag","nation","country","banner"],char:"🇯🇪",fitzpatrick_scale:false,category:"flags"},jordan:{keywords:["jo","flag","nation","country","banner"],char:"🇯🇴",fitzpatrick_scale:false,category:"flags"},kazakhstan:{keywords:["kz","flag","nation","country","banner"],char:"🇰🇿",fitzpatrick_scale:false,category:"flags"},kenya:{keywords:["ke","flag","nation","country","banner"],char:"🇰🇪",fitzpatrick_scale:false,category:"flags"},kiribati:{keywords:["ki","flag","nation","country","banner"],char:"🇰🇮",fitzpatrick_scale:false,category:"flags"},kosovo:{keywords:["xk","flag","nation","country","banner"],char:"🇽🇰",fitzpatrick_scale:false,category:"flags"},kuwait:{keywords:["kw","flag","nation","country","banner"],char:"🇰🇼",fitzpatrick_scale:false,category:"flags"},kyrgyzstan:{keywords:["kg","flag","nation","country","banner"],char:"🇰🇬",fitzpatrick_scale:false,category:"flags"},laos:{keywords:["lao","democratic","republic","flag","nation","country","banner"],char:"🇱🇦",fitzpatrick_scale:false,category:"flags"},latvia:{keywords:["lv","flag","nation","country","banner"],char:"🇱🇻",fitzpatrick_scale:false,category:"flags"},lebanon:{keywords:["lb","flag","nation","country","banner"],char:"🇱🇧",fitzpatrick_scale:false,category:"flags"},lesotho:{keywords:["ls","flag","nation","country","banner"],char:"🇱🇸",fitzpatrick_scale:false,category:"flags"},liberia:{keywords:["lr","flag","nation","country","banner"],char:"🇱🇷",fitzpatrick_scale:false,category:"flags"},libya:{keywords:["ly","flag","nation","country","banner"],char:"🇱🇾",fitzpatrick_scale:false,category:"flags"},liechtenstein:{keywords:["li","flag","nation","country","banner"],char:"🇱🇮",fitzpatrick_scale:false,category:"flags"},lithuania:{keywords:["lt","flag","nation","country","banner"],char:"🇱🇹",fitzpatrick_scale:false,category:"flags"},luxembourg:{keywords:["lu","flag","nation","country","banner"],char:"🇱🇺",fitzpatrick_scale:false,category:"flags"},macau:{keywords:["macao","flag","nation","country","banner"],char:"🇲🇴",fitzpatrick_scale:false,category:"flags"},macedonia:{keywords:["macedonia,","flag","nation","country","banner"],char:"🇲🇰",fitzpatrick_scale:false,category:"flags"},madagascar:{keywords:["mg","flag","nation","country","banner"],char:"🇲🇬",fitzpatrick_scale:false,category:"flags"},malawi:{keywords:["mw","flag","nation","country","banner"],char:"🇲🇼",fitzpatrick_scale:false,category:"flags"},malaysia:{keywords:["my","flag","nation","country","banner"],char:"🇲🇾",fitzpatrick_scale:false,category:"flags"},maldives:{keywords:["mv","flag","nation","country","banner"],char:"🇲🇻",fitzpatrick_scale:false,category:"flags"},mali:{keywords:["ml","flag","nation","country","banner"],char:"🇲🇱",fitzpatrick_scale:false,category:"flags"},malta:{keywords:["mt","flag","nation","country","banner"],char:"🇲🇹",fitzpatrick_scale:false,category:"flags"},marshall_islands:{keywords:["marshall","islands","flag","nation","country","banner"],char:"🇲🇭",fitzpatrick_scale:false,category:"flags"},martinique:{keywords:["mq","flag","nation","country","banner"],char:"🇲🇶",fitzpatrick_scale:false,category:"flags"},mauritania:{keywords:["mr","flag","nation","country","banner"],char:"🇲🇷",fitzpatrick_scale:false,category:"flags"},mauritius:{keywords:["mu","flag","nation","country","banner"],char:"🇲🇺",fitzpatrick_scale:false,category:"flags"},mayotte:{keywords:["yt","flag","nation","country","banner"],char:"🇾🇹",fitzpatrick_scale:false,category:"flags"},mexico:{keywords:["mx","flag","nation","country","banner"],char:"🇲🇽",fitzpatrick_scale:false,category:"flags"},micronesia:{keywords:["micronesia,","federated","states","flag","nation","country","banner"],char:"🇫🇲",fitzpatrick_scale:false,category:"flags"},moldova:{keywords:["moldova,","republic","flag","nation","country","banner"],char:"🇲🇩",fitzpatrick_scale:false,category:"flags"},monaco:{keywords:["mc","flag","nation","country","banner"],char:"🇲🇨",fitzpatrick_scale:false,category:"flags"},mongolia:{keywords:["mn","flag","nation","country","banner"],char:"🇲🇳",fitzpatrick_scale:false,category:"flags"},montenegro:{keywords:["me","flag","nation","country","banner"],char:"🇲🇪",fitzpatrick_scale:false,category:"flags"},montserrat:{keywords:["ms","flag","nation","country","banner"],char:"🇲🇸",fitzpatrick_scale:false,category:"flags"},morocco:{keywords:["ma","flag","nation","country","banner"],char:"🇲🇦",fitzpatrick_scale:false,category:"flags"},mozambique:{keywords:["mz","flag","nation","country","banner"],char:"🇲🇿",fitzpatrick_scale:false,category:"flags"},myanmar:{keywords:["mm","flag","nation","country","banner"],char:"🇲🇲",fitzpatrick_scale:false,category:"flags"},namibia:{keywords:["na","flag","nation","country","banner"],char:"🇳🇦",fitzpatrick_scale:false,category:"flags"},nauru:{keywords:["nr","flag","nation","country","banner"],char:"🇳🇷",fitzpatrick_scale:false,category:"flags"},nepal:{keywords:["np","flag","nation","country","banner"],char:"🇳🇵",fitzpatrick_scale:false,category:"flags"},netherlands:{keywords:["nl","flag","nation","country","banner"],char:"🇳🇱",fitzpatrick_scale:false,category:"flags"},new_caledonia:{keywords:["new","caledonia","flag","nation","country","banner"],char:"🇳🇨",fitzpatrick_scale:false,category:"flags"},new_zealand:{keywords:["new","zealand","flag","nation","country","banner"],char:"🇳🇿",fitzpatrick_scale:false,category:"flags"},nicaragua:{keywords:["ni","flag","nation","country","banner"],char:"🇳🇮",fitzpatrick_scale:false,category:"flags"},niger:{keywords:["ne","flag","nation","country","banner"],char:"🇳🇪",fitzpatrick_scale:false,category:"flags"},nigeria:{keywords:["flag","nation","country","banner"],char:"🇳🇬",fitzpatrick_scale:false,category:"flags"},niue:{keywords:["nu","flag","nation","country","banner"],char:"🇳🇺",fitzpatrick_scale:false,category:"flags"},norfolk_island:{keywords:["norfolk","island","flag","nation","country","banner"],char:"🇳🇫",fitzpatrick_scale:false,category:"flags"},northern_mariana_islands:{keywords:["northern","mariana","islands","flag","nation","country","banner"],char:"🇲🇵",fitzpatrick_scale:false,category:"flags"},north_korea:{keywords:["north","korea","nation","flag","country","banner"],char:"🇰🇵",fitzpatrick_scale:false,category:"flags"},norway:{keywords:["no","flag","nation","country","banner"],char:"🇳🇴",fitzpatrick_scale:false,category:"flags"},oman:{keywords:["om_symbol","flag","nation","country","banner"],char:"🇴🇲",fitzpatrick_scale:false,category:"flags"},pakistan:{keywords:["pk","flag","nation","country","banner"],char:"🇵🇰",fitzpatrick_scale:false,category:"flags"},palau:{keywords:["pw","flag","nation","country","banner"],char:"🇵🇼",fitzpatrick_scale:false,category:"flags"},palestinian_territories:{keywords:["palestine","palestinian","territories","flag","nation","country","banner"],char:"🇵🇸",fitzpatrick_scale:false,category:"flags"},panama:{keywords:["pa","flag","nation","country","banner"],char:"🇵🇦",fitzpatrick_scale:false,category:"flags"},papua_new_guinea:{keywords:["papua","new","guinea","flag","nation","country","banner"],char:"🇵🇬",fitzpatrick_scale:false,category:"flags"},paraguay:{keywords:["py","flag","nation","country","banner"],char:"🇵🇾",fitzpatrick_scale:false,category:"flags"},peru:{keywords:["pe","flag","nation","country","banner"],char:"🇵🇪",fitzpatrick_scale:false,category:"flags"},philippines:{keywords:["ph","flag","nation","country","banner"],char:"🇵🇭",fitzpatrick_scale:false,category:"flags"},pitcairn_islands:{keywords:["pitcairn","flag","nation","country","banner"],char:"🇵🇳",fitzpatrick_scale:false,category:"flags"},poland:{keywords:["pl","flag","nation","country","banner"],char:"🇵🇱",fitzpatrick_scale:false,category:"flags"},portugal:{keywords:["pt","flag","nation","country","banner"],char:"🇵🇹",fitzpatrick_scale:false,category:"flags"},puerto_rico:{keywords:["puerto","rico","flag","nation","country","banner"],char:"🇵🇷",fitzpatrick_scale:false,category:"flags"},qatar:{keywords:["qa","flag","nation","country","banner"],char:"🇶🇦",fitzpatrick_scale:false,category:"flags"},reunion:{keywords:["réunion","flag","nation","country","banner"],char:"🇷🇪",fitzpatrick_scale:false,category:"flags"},romania:{keywords:["ro","flag","nation","country","banner"],char:"🇷🇴",fitzpatrick_scale:false,category:"flags"},ru:{keywords:["russian","federation","flag","nation","country","banner"],char:"🇷🇺",fitzpatrick_scale:false,category:"flags"},rwanda:{keywords:["rw","flag","nation","country","banner"],char:"🇷🇼",fitzpatrick_scale:false,category:"flags"},st_barthelemy:{keywords:["saint","barthélemy","flag","nation","country","banner"],char:"🇧🇱",fitzpatrick_scale:false,category:"flags"},st_helena:{keywords:["saint","helena","ascension","tristan","cunha","flag","nation","country","banner"],char:"🇸🇭",fitzpatrick_scale:false,category:"flags"},st_kitts_nevis:{keywords:["saint","kitts","nevis","flag","nation","country","banner"],char:"🇰🇳",fitzpatrick_scale:false,category:"flags"},st_lucia:{keywords:["saint","lucia","flag","nation","country","banner"],char:"🇱🇨",fitzpatrick_scale:false,category:"flags"},st_pierre_miquelon:{keywords:["saint","pierre","miquelon","flag","nation","country","banner"],char:"🇵🇲",fitzpatrick_scale:false,category:"flags"},st_vincent_grenadines:{keywords:["saint","vincent","grenadines","flag","nation","country","banner"],char:"🇻🇨",fitzpatrick_scale:false,category:"flags"},samoa:{keywords:["ws","flag","nation","country","banner"],char:"🇼🇸",fitzpatrick_scale:false,category:"flags"},san_marino:{keywords:["san","marino","flag","nation","country","banner"],char:"🇸🇲",fitzpatrick_scale:false,category:"flags"},sao_tome_principe:{keywords:["sao","tome","principe","flag","nation","country","banner"],char:"🇸🇹",fitzpatrick_scale:false,category:"flags"},saudi_arabia:{keywords:["flag","nation","country","banner"],char:"🇸🇦",fitzpatrick_scale:false,category:"flags"},senegal:{keywords:["sn","flag","nation","country","banner"],char:"🇸🇳",fitzpatrick_scale:false,category:"flags"},serbia:{keywords:["rs","flag","nation","country","banner"],char:"🇷🇸",fitzpatrick_scale:false,category:"flags"},seychelles:{keywords:["sc","flag","nation","country","banner"],char:"🇸🇨",fitzpatrick_scale:false,category:"flags"},sierra_leone:{keywords:["sierra","leone","flag","nation","country","banner"],char:"🇸🇱",fitzpatrick_scale:false,category:"flags"},singapore:{keywords:["sg","flag","nation","country","banner"],char:"🇸🇬",fitzpatrick_scale:false,category:"flags"},sint_maarten:{keywords:["sint","maarten","dutch","flag","nation","country","banner"],char:"🇸🇽",fitzpatrick_scale:false,category:"flags"},slovakia:{keywords:["sk","flag","nation","country","banner"],char:"🇸🇰",fitzpatrick_scale:false,category:"flags"},slovenia:{keywords:["si","flag","nation","country","banner"],char:"🇸🇮",fitzpatrick_scale:false,category:"flags"},solomon_islands:{keywords:["solomon","islands","flag","nation","country","banner"],char:"🇸🇧",fitzpatrick_scale:false,category:"flags"},somalia:{keywords:["so","flag","nation","country","banner"],char:"🇸🇴",fitzpatrick_scale:false,category:"flags"},south_africa:{keywords:["south","africa","flag","nation","country","banner"],char:"🇿🇦",fitzpatrick_scale:false,category:"flags"},south_georgia_south_sandwich_islands:{keywords:["south","georgia","sandwich","islands","flag","nation","country","banner"],char:"🇬🇸",fitzpatrick_scale:false,category:"flags"},kr:{keywords:["south","korea","nation","flag","country","banner"],char:"🇰🇷",fitzpatrick_scale:false,category:"flags"},south_sudan:{keywords:["south","sd","flag","nation","country","banner"],char:"🇸🇸",fitzpatrick_scale:false,category:"flags"},es:{keywords:["spain","flag","nation","country","banner"],char:"🇪🇸",fitzpatrick_scale:false,category:"flags"},sri_lanka:{keywords:["sri","lanka","flag","nation","country","banner"],char:"🇱🇰",fitzpatrick_scale:false,category:"flags"},sudan:{keywords:["sd","flag","nation","country","banner"],char:"🇸🇩",fitzpatrick_scale:false,category:"flags"},suriname:{keywords:["sr","flag","nation","country","banner"],char:"🇸🇷",fitzpatrick_scale:false,category:"flags"},swaziland:{keywords:["sz","flag","nation","country","banner"],char:"🇸🇿",fitzpatrick_scale:false,category:"flags"},sweden:{keywords:["se","flag","nation","country","banner"],char:"🇸🇪",fitzpatrick_scale:false,category:"flags"},switzerland:{keywords:["ch","flag","nation","country","banner"],char:"🇨🇭",fitzpatrick_scale:false,category:"flags"},syria:{keywords:["syrian","arab","republic","flag","nation","country","banner"],char:"🇸🇾",fitzpatrick_scale:false,category:"flags"},taiwan:{keywords:["tw","flag","nation","country","banner"],char:"🇹🇼",fitzpatrick_scale:false,category:"flags"},tajikistan:{keywords:["tj","flag","nation","country","banner"],char:"🇹🇯",fitzpatrick_scale:false,category:"flags"},tanzania:{keywords:["tanzania,","united","republic","flag","nation","country","banner"],char:"🇹🇿",fitzpatrick_scale:false,category:"flags"},thailand:{keywords:["th","flag","nation","country","banner"],char:"🇹🇭",fitzpatrick_scale:false,category:"flags"},timor_leste:{keywords:["timor","leste","flag","nation","country","banner"],char:"🇹🇱",fitzpatrick_scale:false,category:"flags"},togo:{keywords:["tg","flag","nation","country","banner"],char:"🇹🇬",fitzpatrick_scale:false,category:"flags"},tokelau:{keywords:["tk","flag","nation","country","banner"],char:"🇹🇰",fitzpatrick_scale:false,category:"flags"},tonga:{keywords:["to","flag","nation","country","banner"],char:"🇹🇴",fitzpatrick_scale:false,category:"flags"},trinidad_tobago:{keywords:["trinidad","tobago","flag","nation","country","banner"],char:"🇹🇹",fitzpatrick_scale:false,category:"flags"},tunisia:{keywords:["tn","flag","nation","country","banner"],char:"🇹🇳",fitzpatrick_scale:false,category:"flags"},tr:{keywords:["turkey","flag","nation","country","banner"],char:"🇹🇷",fitzpatrick_scale:false,category:"flags"},turkmenistan:{keywords:["flag","nation","country","banner"],char:"🇹🇲",fitzpatrick_scale:false,category:"flags"},turks_caicos_islands:{keywords:["turks","caicos","islands","flag","nation","country","banner"],char:"🇹🇨",fitzpatrick_scale:false,category:"flags"},tuvalu:{keywords:["flag","nation","country","banner"],char:"🇹🇻",fitzpatrick_scale:false,category:"flags"},uganda:{keywords:["ug","flag","nation","country","banner"],char:"🇺🇬",fitzpatrick_scale:false,category:"flags"},ukraine:{keywords:["ua","flag","nation","country","banner"],char:"🇺🇦",fitzpatrick_scale:false,category:"flags"},united_arab_emirates:{keywords:["united","arab","emirates","flag","nation","country","banner"],char:"🇦🇪",fitzpatrick_scale:false,category:"flags"},uk:{keywords:["united","kingdom","great","britain","northern","ireland","flag","nation","country","banner","british","UK","english","england","union jack"],char:"🇬🇧",fitzpatrick_scale:false,category:"flags"},england:{keywords:["flag","english"],char:"🏴󠁧󠁢󠁥󠁮󠁧󠁿",fitzpatrick_scale:false,category:"flags"},scotland:{keywords:["flag","scottish"],char:"🏴󠁧󠁢󠁳󠁣󠁴󠁿",fitzpatrick_scale:false,category:"flags"},wales:{keywords:["flag","welsh"],char:"🏴󠁧󠁢󠁷󠁬󠁳󠁿",fitzpatrick_scale:false,category:"flags"},us:{keywords:["united","states","america","flag","nation","country","banner"],char:"🇺🇸",fitzpatrick_scale:false,category:"flags"},us_virgin_islands:{keywords:["virgin","islands","us","flag","nation","country","banner"],char:"🇻🇮",fitzpatrick_scale:false,category:"flags"},uruguay:{keywords:["uy","flag","nation","country","banner"],char:"🇺🇾",fitzpatrick_scale:false,category:"flags"},uzbekistan:{keywords:["uz","flag","nation","country","banner"],char:"🇺🇿",fitzpatrick_scale:false,category:"flags"},vanuatu:{keywords:["vu","flag","nation","country","banner"],char:"🇻🇺",fitzpatrick_scale:false,category:"flags"},vatican_city:{keywords:["vatican","city","flag","nation","country","banner"],char:"🇻🇦",fitzpatrick_scale:false,category:"flags"},venezuela:{keywords:["ve","bolivarian","republic","flag","nation","country","banner"],char:"🇻🇪",fitzpatrick_scale:false,category:"flags"},vietnam:{keywords:["viet","nam","flag","nation","country","banner"],char:"🇻🇳",fitzpatrick_scale:false,category:"flags"},wallis_futuna:{keywords:["wallis","futuna","flag","nation","country","banner"],char:"🇼🇫",fitzpatrick_scale:false,category:"flags"},western_sahara:{keywords:["western","sahara","flag","nation","country","banner"],char:"🇪🇭",fitzpatrick_scale:false,category:"flags"},yemen:{keywords:["ye","flag","nation","country","banner"],char:"🇾🇪",fitzpatrick_scale:false,category:"flags"},zambia:{keywords:["zm","flag","nation","country","banner"],char:"🇿🇲",fitzpatrick_scale:false,category:"flags"},zimbabwe:{keywords:["zw","flag","nation","country","banner"],char:"🇿🇼",fitzpatrick_scale:false,category:"flags"},united_nations:{keywords:["un","flag","banner"],char:"🇺🇳",fitzpatrick_scale:false,category:"flags"},pirate_flag:{keywords:["skull","crossbones","flag","banner"],char:"🏴‍☠️",fitzpatrick_scale:false,category:"flags"}}); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/emoticons/js/emojis.min.js b/apps/web-antd/public/tinymce/plugins/emoticons/js/emojis.min.js new file mode 100644 index 0000000..5a1c491 --- /dev/null +++ b/apps/web-antd/public/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:"\u{1f600}",fitzpatrick_scale:!1,category:"people"},grimacing:{keywords:["face","grimace","teeth"],char:"\u{1f62c}",fitzpatrick_scale:!1,category:"people"},grin:{keywords:["face","happy","smile","joy","kawaii"],char:"\u{1f601}",fitzpatrick_scale:!1,category:"people"},joy:{keywords:["face","cry","tears","weep","happy","happytears","haha"],char:"\u{1f602}",fitzpatrick_scale:!1,category:"people"},rofl:{keywords:["face","rolling","floor","laughing","lol","haha"],char:"\u{1f923}",fitzpatrick_scale:!1,category:"people"},partying:{keywords:["face","celebration","woohoo"],char:"\u{1f973}",fitzpatrick_scale:!1,category:"people"},smiley:{keywords:["face","happy","joy","haha",":D",":)","smile","funny"],char:"\u{1f603}",fitzpatrick_scale:!1,category:"people"},smile:{keywords:["face","happy","joy","funny","haha","laugh","like",":D",":)"],char:"\u{1f604}",fitzpatrick_scale:!1,category:"people"},sweat_smile:{keywords:["face","hot","happy","laugh","sweat","smile","relief"],char:"\u{1f605}",fitzpatrick_scale:!1,category:"people"},laughing:{keywords:["happy","joy","lol","satisfied","haha","face","glad","XD","laugh"],char:"\u{1f606}",fitzpatrick_scale:!1,category:"people"},innocent:{keywords:["face","angel","heaven","halo"],char:"\u{1f607}",fitzpatrick_scale:!1,category:"people"},wink:{keywords:["face","happy","mischievous","secret",";)","smile","eye"],char:"\u{1f609}",fitzpatrick_scale:!1,category:"people"},blush:{keywords:["face","smile","happy","flushed","crush","embarrassed","shy","joy"],char:"\u{1f60a}",fitzpatrick_scale:!1,category:"people"},slightly_smiling_face:{keywords:["face","smile"],char:"\u{1f642}",fitzpatrick_scale:!1,category:"people"},upside_down_face:{keywords:["face","flipped","silly","smile"],char:"\u{1f643}",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:"\u{1f60b}",fitzpatrick_scale:!1,category:"people"},relieved:{keywords:["face","relaxed","phew","massage","happiness"],char:"\u{1f60c}",fitzpatrick_scale:!1,category:"people"},heart_eyes:{keywords:["face","love","like","affection","valentines","infatuation","crush","heart"],char:"\u{1f60d}",fitzpatrick_scale:!1,category:"people"},smiling_face_with_three_hearts:{keywords:["face","love","like","affection","valentines","infatuation","crush","hearts","adore"],char:"\u{1f970}",fitzpatrick_scale:!1,category:"people"},kissing_heart:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:"\u{1f618}",fitzpatrick_scale:!1,category:"people"},kissing:{keywords:["love","like","face","3","valentines","infatuation","kiss"],char:"\u{1f617}",fitzpatrick_scale:!1,category:"people"},kissing_smiling_eyes:{keywords:["face","affection","valentines","infatuation","kiss"],char:"\u{1f619}",fitzpatrick_scale:!1,category:"people"},kissing_closed_eyes:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:"\u{1f61a}",fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_winking_eye:{keywords:["face","prank","childish","playful","mischievous","smile","wink","tongue"],char:"\u{1f61c}",fitzpatrick_scale:!1,category:"people"},zany:{keywords:["face","goofy","crazy"],char:"\u{1f92a}",fitzpatrick_scale:!1,category:"people"},raised_eyebrow:{keywords:["face","distrust","scepticism","disapproval","disbelief","surprise"],char:"\u{1f928}",fitzpatrick_scale:!1,category:"people"},monocle:{keywords:["face","stuffy","wealthy"],char:"\u{1f9d0}",fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_closed_eyes:{keywords:["face","prank","playful","mischievous","smile","tongue"],char:"\u{1f61d}",fitzpatrick_scale:!1,category:"people"},stuck_out_tongue:{keywords:["face","prank","childish","playful","mischievous","smile","tongue"],char:"\u{1f61b}",fitzpatrick_scale:!1,category:"people"},money_mouth_face:{keywords:["face","rich","dollar","money"],char:"\u{1f911}",fitzpatrick_scale:!1,category:"people"},nerd_face:{keywords:["face","nerdy","geek","dork"],char:"\u{1f913}",fitzpatrick_scale:!1,category:"people"},sunglasses:{keywords:["face","cool","smile","summer","beach","sunglass"],char:"\u{1f60e}",fitzpatrick_scale:!1,category:"people"},star_struck:{keywords:["face","smile","starry","eyes","grinning"],char:"\u{1f929}",fitzpatrick_scale:!1,category:"people"},clown_face:{keywords:["face"],char:"\u{1f921}",fitzpatrick_scale:!1,category:"people"},cowboy_hat_face:{keywords:["face","cowgirl","hat"],char:"\u{1f920}",fitzpatrick_scale:!1,category:"people"},hugs:{keywords:["face","smile","hug"],char:"\u{1f917}",fitzpatrick_scale:!1,category:"people"},smirk:{keywords:["face","smile","mean","prank","smug","sarcasm"],char:"\u{1f60f}",fitzpatrick_scale:!1,category:"people"},no_mouth:{keywords:["face","hellokitty"],char:"\u{1f636}",fitzpatrick_scale:!1,category:"people"},neutral_face:{keywords:["indifference","meh",":|","neutral"],char:"\u{1f610}",fitzpatrick_scale:!1,category:"people"},expressionless:{keywords:["face","indifferent","-_-","meh","deadpan"],char:"\u{1f611}",fitzpatrick_scale:!1,category:"people"},unamused:{keywords:["indifference","bored","straight face","serious","sarcasm","unimpressed","skeptical","dubious","side_eye"],char:"\u{1f612}",fitzpatrick_scale:!1,category:"people"},roll_eyes:{keywords:["face","eyeroll","frustrated"],char:"\u{1f644}",fitzpatrick_scale:!1,category:"people"},thinking:{keywords:["face","hmmm","think","consider"],char:"\u{1f914}",fitzpatrick_scale:!1,category:"people"},lying_face:{keywords:["face","lie","pinocchio"],char:"\u{1f925}",fitzpatrick_scale:!1,category:"people"},hand_over_mouth:{keywords:["face","whoops","shock","surprise"],char:"\u{1f92d}",fitzpatrick_scale:!1,category:"people"},shushing:{keywords:["face","quiet","shhh"],char:"\u{1f92b}",fitzpatrick_scale:!1,category:"people"},symbols_over_mouth:{keywords:["face","swearing","cursing","cussing","profanity","expletive"],char:"\u{1f92c}",fitzpatrick_scale:!1,category:"people"},exploding_head:{keywords:["face","shocked","mind","blown"],char:"\u{1f92f}",fitzpatrick_scale:!1,category:"people"},flushed:{keywords:["face","blush","shy","flattered"],char:"\u{1f633}",fitzpatrick_scale:!1,category:"people"},disappointed:{keywords:["face","sad","upset","depressed",":("],char:"\u{1f61e}",fitzpatrick_scale:!1,category:"people"},worried:{keywords:["face","concern","nervous",":("],char:"\u{1f61f}",fitzpatrick_scale:!1,category:"people"},angry:{keywords:["mad","face","annoyed","frustrated"],char:"\u{1f620}",fitzpatrick_scale:!1,category:"people"},rage:{keywords:["angry","mad","hate","despise"],char:"\u{1f621}",fitzpatrick_scale:!1,category:"people"},pensive:{keywords:["face","sad","depressed","upset"],char:"\u{1f614}",fitzpatrick_scale:!1,category:"people"},confused:{keywords:["face","indifference","huh","weird","hmmm",":/"],char:"\u{1f615}",fitzpatrick_scale:!1,category:"people"},slightly_frowning_face:{keywords:["face","frowning","disappointed","sad","upset"],char:"\u{1f641}",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:"\u{1f623}",fitzpatrick_scale:!1,category:"people"},confounded:{keywords:["face","confused","sick","unwell","oops",":S"],char:"\u{1f616}",fitzpatrick_scale:!1,category:"people"},tired_face:{keywords:["sick","whine","upset","frustrated"],char:"\u{1f62b}",fitzpatrick_scale:!1,category:"people"},weary:{keywords:["face","tired","sleepy","sad","frustrated","upset"],char:"\u{1f629}",fitzpatrick_scale:!1,category:"people"},pleading:{keywords:["face","begging","mercy"],char:"\u{1f97a}",fitzpatrick_scale:!1,category:"people"},triumph:{keywords:["face","gas","phew","proud","pride"],char:"\u{1f624}",fitzpatrick_scale:!1,category:"people"},open_mouth:{keywords:["face","surprise","impressed","wow","whoa",":O"],char:"\u{1f62e}",fitzpatrick_scale:!1,category:"people"},scream:{keywords:["face","munch","scared","omg"],char:"\u{1f631}",fitzpatrick_scale:!1,category:"people"},fearful:{keywords:["face","scared","terrified","nervous","oops","huh"],char:"\u{1f628}",fitzpatrick_scale:!1,category:"people"},cold_sweat:{keywords:["face","nervous","sweat"],char:"\u{1f630}",fitzpatrick_scale:!1,category:"people"},hushed:{keywords:["face","woo","shh"],char:"\u{1f62f}",fitzpatrick_scale:!1,category:"people"},frowning:{keywords:["face","aw","what"],char:"\u{1f626}",fitzpatrick_scale:!1,category:"people"},anguished:{keywords:["face","stunned","nervous"],char:"\u{1f627}",fitzpatrick_scale:!1,category:"people"},cry:{keywords:["face","tears","sad","depressed","upset",":'("],char:"\u{1f622}",fitzpatrick_scale:!1,category:"people"},disappointed_relieved:{keywords:["face","phew","sweat","nervous"],char:"\u{1f625}",fitzpatrick_scale:!1,category:"people"},drooling_face:{keywords:["face"],char:"\u{1f924}",fitzpatrick_scale:!1,category:"people"},sleepy:{keywords:["face","tired","rest","nap"],char:"\u{1f62a}",fitzpatrick_scale:!1,category:"people"},sweat:{keywords:["face","hot","sad","tired","exercise"],char:"\u{1f613}",fitzpatrick_scale:!1,category:"people"},hot:{keywords:["face","feverish","heat","red","sweating"],char:"\u{1f975}",fitzpatrick_scale:!1,category:"people"},cold:{keywords:["face","blue","freezing","frozen","frostbite","icicles"],char:"\u{1f976}",fitzpatrick_scale:!1,category:"people"},sob:{keywords:["face","cry","tears","sad","upset","depressed"],char:"\u{1f62d}",fitzpatrick_scale:!1,category:"people"},dizzy_face:{keywords:["spent","unconscious","xox","dizzy"],char:"\u{1f635}",fitzpatrick_scale:!1,category:"people"},astonished:{keywords:["face","xox","surprised","poisoned"],char:"\u{1f632}",fitzpatrick_scale:!1,category:"people"},zipper_mouth_face:{keywords:["face","sealed","zipper","secret"],char:"\u{1f910}",fitzpatrick_scale:!1,category:"people"},nauseated_face:{keywords:["face","vomit","gross","green","sick","throw up","ill"],char:"\u{1f922}",fitzpatrick_scale:!1,category:"people"},sneezing_face:{keywords:["face","gesundheit","sneeze","sick","allergy"],char:"\u{1f927}",fitzpatrick_scale:!1,category:"people"},vomiting:{keywords:["face","sick"],char:"\u{1f92e}",fitzpatrick_scale:!1,category:"people"},mask:{keywords:["face","sick","ill","disease"],char:"\u{1f637}",fitzpatrick_scale:!1,category:"people"},face_with_thermometer:{keywords:["sick","temperature","thermometer","cold","fever"],char:"\u{1f912}",fitzpatrick_scale:!1,category:"people"},face_with_head_bandage:{keywords:["injured","clumsy","bandage","hurt"],char:"\u{1f915}",fitzpatrick_scale:!1,category:"people"},woozy:{keywords:["face","dizzy","intoxicated","tipsy","wavy"],char:"\u{1f974}",fitzpatrick_scale:!1,category:"people"},sleeping:{keywords:["face","tired","sleepy","night","zzz"],char:"\u{1f634}",fitzpatrick_scale:!1,category:"people"},zzz:{keywords:["sleepy","tired","dream"],char:"\u{1f4a4}",fitzpatrick_scale:!1,category:"people"},poop:{keywords:["hankey","shitface","fail","turd","shit"],char:"\u{1f4a9}",fitzpatrick_scale:!1,category:"people"},smiling_imp:{keywords:["devil","horns"],char:"\u{1f608}",fitzpatrick_scale:!1,category:"people"},imp:{keywords:["devil","angry","horns"],char:"\u{1f47f}",fitzpatrick_scale:!1,category:"people"},japanese_ogre:{keywords:["monster","red","mask","halloween","scary","creepy","devil","demon","japanese","ogre"],char:"\u{1f479}",fitzpatrick_scale:!1,category:"people"},japanese_goblin:{keywords:["red","evil","mask","monster","scary","creepy","japanese","goblin"],char:"\u{1f47a}",fitzpatrick_scale:!1,category:"people"},skull:{keywords:["dead","skeleton","creepy","death"],char:"\u{1f480}",fitzpatrick_scale:!1,category:"people"},ghost:{keywords:["halloween","spooky","scary"],char:"\u{1f47b}",fitzpatrick_scale:!1,category:"people"},alien:{keywords:["UFO","paul","weird","outer_space"],char:"\u{1f47d}",fitzpatrick_scale:!1,category:"people"},robot:{keywords:["computer","machine","bot"],char:"\u{1f916}",fitzpatrick_scale:!1,category:"people"},smiley_cat:{keywords:["animal","cats","happy","smile"],char:"\u{1f63a}",fitzpatrick_scale:!1,category:"people"},smile_cat:{keywords:["animal","cats","smile"],char:"\u{1f638}",fitzpatrick_scale:!1,category:"people"},joy_cat:{keywords:["animal","cats","haha","happy","tears"],char:"\u{1f639}",fitzpatrick_scale:!1,category:"people"},heart_eyes_cat:{keywords:["animal","love","like","affection","cats","valentines","heart"],char:"\u{1f63b}",fitzpatrick_scale:!1,category:"people"},smirk_cat:{keywords:["animal","cats","smirk"],char:"\u{1f63c}",fitzpatrick_scale:!1,category:"people"},kissing_cat:{keywords:["animal","cats","kiss"],char:"\u{1f63d}",fitzpatrick_scale:!1,category:"people"},scream_cat:{keywords:["animal","cats","munch","scared","scream"],char:"\u{1f640}",fitzpatrick_scale:!1,category:"people"},crying_cat_face:{keywords:["animal","tears","weep","sad","cats","upset","cry"],char:"\u{1f63f}",fitzpatrick_scale:!1,category:"people"},pouting_cat:{keywords:["animal","cats"],char:"\u{1f63e}",fitzpatrick_scale:!1,category:"people"},palms_up:{keywords:["hands","gesture","cupped","prayer"],char:"\u{1f932}",fitzpatrick_scale:!0,category:"people"},raised_hands:{keywords:["gesture","hooray","yea","celebration","hands"],char:"\u{1f64c}",fitzpatrick_scale:!0,category:"people"},clap:{keywords:["hands","praise","applause","congrats","yay"],char:"\u{1f44f}",fitzpatrick_scale:!0,category:"people"},wave:{keywords:["hands","gesture","goodbye","solong","farewell","hello","hi","palm"],char:"\u{1f44b}",fitzpatrick_scale:!0,category:"people"},call_me_hand:{keywords:["hands","gesture"],char:"\u{1f919}",fitzpatrick_scale:!0,category:"people"},"+1":{keywords:["thumbsup","yes","awesome","good","agree","accept","cool","hand","like"],char:"\u{1f44d}",fitzpatrick_scale:!0,category:"people"},"-1":{keywords:["thumbsdown","no","dislike","hand"],char:"\u{1f44e}",fitzpatrick_scale:!0,category:"people"},facepunch:{keywords:["angry","violence","fist","hit","attack","hand"],char:"\u{1f44a}",fitzpatrick_scale:!0,category:"people"},fist:{keywords:["fingers","hand","grasp"],char:"\u270a",fitzpatrick_scale:!0,category:"people"},fist_left:{keywords:["hand","fistbump"],char:"\u{1f91b}",fitzpatrick_scale:!0,category:"people"},fist_right:{keywords:["hand","fistbump"],char:"\u{1f91c}",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:"\u{1f44c}",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:"\u{1f91a}",fitzpatrick_scale:!0,category:"people"},open_hands:{keywords:["fingers","butterfly","hands","open"],char:"\u{1f450}",fitzpatrick_scale:!0,category:"people"},muscle:{keywords:["arm","flex","hand","summer","strong","biceps"],char:"\u{1f4aa}",fitzpatrick_scale:!0,category:"people"},pray:{keywords:["please","hope","wish","namaste","highfive"],char:"\u{1f64f}",fitzpatrick_scale:!0,category:"people"},foot:{keywords:["kick","stomp"],char:"\u{1f9b6}",fitzpatrick_scale:!0,category:"people"},leg:{keywords:["kick","limb"],char:"\u{1f9b5}",fitzpatrick_scale:!0,category:"people"},handshake:{keywords:["agreement","shake"],char:"\u{1f91d}",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:"\u{1f446}",fitzpatrick_scale:!0,category:"people"},point_down:{keywords:["fingers","hand","direction","down"],char:"\u{1f447}",fitzpatrick_scale:!0,category:"people"},point_left:{keywords:["direction","fingers","hand","left"],char:"\u{1f448}",fitzpatrick_scale:!0,category:"people"},point_right:{keywords:["fingers","hand","direction","right"],char:"\u{1f449}",fitzpatrick_scale:!0,category:"people"},fu:{keywords:["hand","fingers","rude","middle","flipping"],char:"\u{1f595}",fitzpatrick_scale:!0,category:"people"},raised_hand_with_fingers_splayed:{keywords:["hand","fingers","palm"],char:"\u{1f590}",fitzpatrick_scale:!0,category:"people"},love_you:{keywords:["hand","fingers","gesture"],char:"\u{1f91f}",fitzpatrick_scale:!0,category:"people"},metal:{keywords:["hand","fingers","evil_eye","sign_of_horns","rock_on"],char:"\u{1f918}",fitzpatrick_scale:!0,category:"people"},crossed_fingers:{keywords:["good","lucky"],char:"\u{1f91e}",fitzpatrick_scale:!0,category:"people"},vulcan_salute:{keywords:["hand","fingers","spock","star trek"],char:"\u{1f596}",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:"\u{1f933}",fitzpatrick_scale:!0,category:"people"},nail_care:{keywords:["beauty","manicure","finger","fashion","nail"],char:"\u{1f485}",fitzpatrick_scale:!0,category:"people"},lips:{keywords:["mouth","kiss"],char:"\u{1f444}",fitzpatrick_scale:!1,category:"people"},tooth:{keywords:["teeth","dentist"],char:"\u{1f9b7}",fitzpatrick_scale:!1,category:"people"},tongue:{keywords:["mouth","playful"],char:"\u{1f445}",fitzpatrick_scale:!1,category:"people"},ear:{keywords:["face","hear","sound","listen"],char:"\u{1f442}",fitzpatrick_scale:!0,category:"people"},nose:{keywords:["smell","sniff"],char:"\u{1f443}",fitzpatrick_scale:!0,category:"people"},eye:{keywords:["face","look","see","watch","stare"],char:"\u{1f441}",fitzpatrick_scale:!1,category:"people"},eyes:{keywords:["look","watch","stalk","peek","see"],char:"\u{1f440}",fitzpatrick_scale:!1,category:"people"},brain:{keywords:["smart","intelligent"],char:"\u{1f9e0}",fitzpatrick_scale:!1,category:"people"},bust_in_silhouette:{keywords:["user","person","human"],char:"\u{1f464}",fitzpatrick_scale:!1,category:"people"},busts_in_silhouette:{keywords:["user","person","human","group","team"],char:"\u{1f465}",fitzpatrick_scale:!1,category:"people"},speaking_head:{keywords:["user","person","human","sing","say","talk"],char:"\u{1f5e3}",fitzpatrick_scale:!1,category:"people"},baby:{keywords:["child","boy","girl","toddler"],char:"\u{1f476}",fitzpatrick_scale:!0,category:"people"},child:{keywords:["gender-neutral","young"],char:"\u{1f9d2}",fitzpatrick_scale:!0,category:"people"},boy:{keywords:["man","male","guy","teenager"],char:"\u{1f466}",fitzpatrick_scale:!0,category:"people"},girl:{keywords:["female","woman","teenager"],char:"\u{1f467}",fitzpatrick_scale:!0,category:"people"},adult:{keywords:["gender-neutral","person"],char:"\u{1f9d1}",fitzpatrick_scale:!0,category:"people"},man:{keywords:["mustache","father","dad","guy","classy","sir","moustache"],char:"\u{1f468}",fitzpatrick_scale:!0,category:"people"},woman:{keywords:["female","girls","lady"],char:"\u{1f469}",fitzpatrick_scale:!0,category:"people"},blonde_woman:{keywords:["woman","female","girl","blonde","person"],char:"\u{1f471}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},blonde_man:{keywords:["man","male","boy","blonde","guy","person"],char:"\u{1f471}",fitzpatrick_scale:!0,category:"people"},bearded_person:{keywords:["person","bewhiskered"],char:"\u{1f9d4}",fitzpatrick_scale:!0,category:"people"},older_adult:{keywords:["human","elder","senior","gender-neutral"],char:"\u{1f9d3}",fitzpatrick_scale:!0,category:"people"},older_man:{keywords:["human","male","men","old","elder","senior"],char:"\u{1f474}",fitzpatrick_scale:!0,category:"people"},older_woman:{keywords:["human","female","women","lady","old","elder","senior"],char:"\u{1f475}",fitzpatrick_scale:!0,category:"people"},man_with_gua_pi_mao:{keywords:["male","boy","chinese"],char:"\u{1f472}",fitzpatrick_scale:!0,category:"people"},woman_with_headscarf:{keywords:["female","hijab","mantilla","tichel"],char:"\u{1f9d5}",fitzpatrick_scale:!0,category:"people"},woman_with_turban:{keywords:["female","indian","hinduism","arabs","woman"],char:"\u{1f473}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_with_turban:{keywords:["male","indian","hinduism","arabs"],char:"\u{1f473}",fitzpatrick_scale:!0,category:"people"},policewoman:{keywords:["woman","police","law","legal","enforcement","arrest","911","female"],char:"\u{1f46e}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},policeman:{keywords:["man","police","law","legal","enforcement","arrest","911"],char:"\u{1f46e}",fitzpatrick_scale:!0,category:"people"},construction_worker_woman:{keywords:["female","human","wip","build","construction","worker","labor","woman"],char:"\u{1f477}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},construction_worker_man:{keywords:["male","human","wip","guy","build","construction","worker","labor"],char:"\u{1f477}",fitzpatrick_scale:!0,category:"people"},guardswoman:{keywords:["uk","gb","british","female","royal","woman"],char:"\u{1f482}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},guardsman:{keywords:["uk","gb","british","male","guy","royal"],char:"\u{1f482}",fitzpatrick_scale:!0,category:"people"},female_detective:{keywords:["human","spy","detective","female","woman"],char:"\u{1f575}\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},male_detective:{keywords:["human","spy","detective"],char:"\u{1f575}",fitzpatrick_scale:!0,category:"people"},woman_health_worker:{keywords:["doctor","nurse","therapist","healthcare","woman","human"],char:"\u{1f469}\u200d\u2695\ufe0f",fitzpatrick_scale:!0,category:"people"},man_health_worker:{keywords:["doctor","nurse","therapist","healthcare","man","human"],char:"\u{1f468}\u200d\u2695\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_farmer:{keywords:["rancher","gardener","woman","human"],char:"\u{1f469}\u200d\u{1f33e}",fitzpatrick_scale:!0,category:"people"},man_farmer:{keywords:["rancher","gardener","man","human"],char:"\u{1f468}\u200d\u{1f33e}",fitzpatrick_scale:!0,category:"people"},woman_cook:{keywords:["chef","woman","human"],char:"\u{1f469}\u200d\u{1f373}",fitzpatrick_scale:!0,category:"people"},man_cook:{keywords:["chef","man","human"],char:"\u{1f468}\u200d\u{1f373}",fitzpatrick_scale:!0,category:"people"},woman_student:{keywords:["graduate","woman","human"],char:"\u{1f469}\u200d\u{1f393}",fitzpatrick_scale:!0,category:"people"},man_student:{keywords:["graduate","man","human"],char:"\u{1f468}\u200d\u{1f393}",fitzpatrick_scale:!0,category:"people"},woman_singer:{keywords:["rockstar","entertainer","woman","human"],char:"\u{1f469}\u200d\u{1f3a4}",fitzpatrick_scale:!0,category:"people"},man_singer:{keywords:["rockstar","entertainer","man","human"],char:"\u{1f468}\u200d\u{1f3a4}",fitzpatrick_scale:!0,category:"people"},woman_teacher:{keywords:["instructor","professor","woman","human"],char:"\u{1f469}\u200d\u{1f3eb}",fitzpatrick_scale:!0,category:"people"},man_teacher:{keywords:["instructor","professor","man","human"],char:"\u{1f468}\u200d\u{1f3eb}",fitzpatrick_scale:!0,category:"people"},woman_factory_worker:{keywords:["assembly","industrial","woman","human"],char:"\u{1f469}\u200d\u{1f3ed}",fitzpatrick_scale:!0,category:"people"},man_factory_worker:{keywords:["assembly","industrial","man","human"],char:"\u{1f468}\u200d\u{1f3ed}",fitzpatrick_scale:!0,category:"people"},woman_technologist:{keywords:["coder","developer","engineer","programmer","software","woman","human","laptop","computer"],char:"\u{1f469}\u200d\u{1f4bb}",fitzpatrick_scale:!0,category:"people"},man_technologist:{keywords:["coder","developer","engineer","programmer","software","man","human","laptop","computer"],char:"\u{1f468}\u200d\u{1f4bb}",fitzpatrick_scale:!0,category:"people"},woman_office_worker:{keywords:["business","manager","woman","human"],char:"\u{1f469}\u200d\u{1f4bc}",fitzpatrick_scale:!0,category:"people"},man_office_worker:{keywords:["business","manager","man","human"],char:"\u{1f468}\u200d\u{1f4bc}",fitzpatrick_scale:!0,category:"people"},woman_mechanic:{keywords:["plumber","woman","human","wrench"],char:"\u{1f469}\u200d\u{1f527}",fitzpatrick_scale:!0,category:"people"},man_mechanic:{keywords:["plumber","man","human","wrench"],char:"\u{1f468}\u200d\u{1f527}",fitzpatrick_scale:!0,category:"people"},woman_scientist:{keywords:["biologist","chemist","engineer","physicist","woman","human"],char:"\u{1f469}\u200d\u{1f52c}",fitzpatrick_scale:!0,category:"people"},man_scientist:{keywords:["biologist","chemist","engineer","physicist","man","human"],char:"\u{1f468}\u200d\u{1f52c}",fitzpatrick_scale:!0,category:"people"},woman_artist:{keywords:["painter","woman","human"],char:"\u{1f469}\u200d\u{1f3a8}",fitzpatrick_scale:!0,category:"people"},man_artist:{keywords:["painter","man","human"],char:"\u{1f468}\u200d\u{1f3a8}",fitzpatrick_scale:!0,category:"people"},woman_firefighter:{keywords:["fireman","woman","human"],char:"\u{1f469}\u200d\u{1f692}",fitzpatrick_scale:!0,category:"people"},man_firefighter:{keywords:["fireman","man","human"],char:"\u{1f468}\u200d\u{1f692}",fitzpatrick_scale:!0,category:"people"},woman_pilot:{keywords:["aviator","plane","woman","human"],char:"\u{1f469}\u200d\u2708\ufe0f",fitzpatrick_scale:!0,category:"people"},man_pilot:{keywords:["aviator","plane","man","human"],char:"\u{1f468}\u200d\u2708\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_astronaut:{keywords:["space","rocket","woman","human"],char:"\u{1f469}\u200d\u{1f680}",fitzpatrick_scale:!0,category:"people"},man_astronaut:{keywords:["space","rocket","man","human"],char:"\u{1f468}\u200d\u{1f680}",fitzpatrick_scale:!0,category:"people"},woman_judge:{keywords:["justice","court","woman","human"],char:"\u{1f469}\u200d\u2696\ufe0f",fitzpatrick_scale:!0,category:"people"},man_judge:{keywords:["justice","court","man","human"],char:"\u{1f468}\u200d\u2696\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_superhero:{keywords:["woman","female","good","heroine","superpowers"],char:"\u{1f9b8}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_superhero:{keywords:["man","male","good","hero","superpowers"],char:"\u{1f9b8}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_supervillain:{keywords:["woman","female","evil","bad","criminal","heroine","superpowers"],char:"\u{1f9b9}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_supervillain:{keywords:["man","male","evil","bad","criminal","hero","superpowers"],char:"\u{1f9b9}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},mrs_claus:{keywords:["woman","female","xmas","mother christmas"],char:"\u{1f936}",fitzpatrick_scale:!0,category:"people"},santa:{keywords:["festival","man","male","xmas","father christmas"],char:"\u{1f385}",fitzpatrick_scale:!0,category:"people"},sorceress:{keywords:["woman","female","mage","witch"],char:"\u{1f9d9}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},wizard:{keywords:["man","male","mage","sorcerer"],char:"\u{1f9d9}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_elf:{keywords:["woman","female"],char:"\u{1f9dd}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_elf:{keywords:["man","male"],char:"\u{1f9dd}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_vampire:{keywords:["woman","female"],char:"\u{1f9db}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_vampire:{keywords:["man","male","dracula"],char:"\u{1f9db}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_zombie:{keywords:["woman","female","undead","walking dead"],char:"\u{1f9df}\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"people"},man_zombie:{keywords:["man","male","dracula","undead","walking dead"],char:"\u{1f9df}\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"people"},woman_genie:{keywords:["woman","female"],char:"\u{1f9de}\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"people"},man_genie:{keywords:["man","male"],char:"\u{1f9de}\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"people"},mermaid:{keywords:["woman","female","merwoman","ariel"],char:"\u{1f9dc}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},merman:{keywords:["man","male","triton"],char:"\u{1f9dc}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_fairy:{keywords:["woman","female"],char:"\u{1f9da}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_fairy:{keywords:["man","male"],char:"\u{1f9da}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},angel:{keywords:["heaven","wings","halo"],char:"\u{1f47c}",fitzpatrick_scale:!0,category:"people"},pregnant_woman:{keywords:["baby"],char:"\u{1f930}",fitzpatrick_scale:!0,category:"people"},breastfeeding:{keywords:["nursing","baby"],char:"\u{1f931}",fitzpatrick_scale:!0,category:"people"},princess:{keywords:["girl","woman","female","blond","crown","royal","queen"],char:"\u{1f478}",fitzpatrick_scale:!0,category:"people"},prince:{keywords:["boy","man","male","crown","royal","king"],char:"\u{1f934}",fitzpatrick_scale:!0,category:"people"},bride_with_veil:{keywords:["couple","marriage","wedding","woman","bride"],char:"\u{1f470}",fitzpatrick_scale:!0,category:"people"},man_in_tuxedo:{keywords:["couple","marriage","wedding","groom"],char:"\u{1f935}",fitzpatrick_scale:!0,category:"people"},running_woman:{keywords:["woman","walking","exercise","race","running","female"],char:"\u{1f3c3}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},running_man:{keywords:["man","walking","exercise","race","running"],char:"\u{1f3c3}",fitzpatrick_scale:!0,category:"people"},walking_woman:{keywords:["human","feet","steps","woman","female"],char:"\u{1f6b6}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},walking_man:{keywords:["human","feet","steps"],char:"\u{1f6b6}",fitzpatrick_scale:!0,category:"people"},dancer:{keywords:["female","girl","woman","fun"],char:"\u{1f483}",fitzpatrick_scale:!0,category:"people"},man_dancing:{keywords:["male","boy","fun","dancer"],char:"\u{1f57a}",fitzpatrick_scale:!0,category:"people"},dancing_women:{keywords:["female","bunny","women","girls"],char:"\u{1f46f}",fitzpatrick_scale:!1,category:"people"},dancing_men:{keywords:["male","bunny","men","boys"],char:"\u{1f46f}\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"people"},couple:{keywords:["pair","people","human","love","date","dating","like","affection","valentines","marriage"],char:"\u{1f46b}",fitzpatrick_scale:!1,category:"people"},two_men_holding_hands:{keywords:["pair","couple","love","like","bromance","friendship","people","human"],char:"\u{1f46c}",fitzpatrick_scale:!1,category:"people"},two_women_holding_hands:{keywords:["pair","friendship","couple","love","like","female","people","human"],char:"\u{1f46d}",fitzpatrick_scale:!1,category:"people"},bowing_woman:{keywords:["woman","female","girl"],char:"\u{1f647}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},bowing_man:{keywords:["man","male","boy"],char:"\u{1f647}",fitzpatrick_scale:!0,category:"people"},man_facepalming:{keywords:["man","male","boy","disbelief"],char:"\u{1f926}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_facepalming:{keywords:["woman","female","girl","disbelief"],char:"\u{1f926}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_shrugging:{keywords:["woman","female","girl","confused","indifferent","doubt"],char:"\u{1f937}",fitzpatrick_scale:!0,category:"people"},man_shrugging:{keywords:["man","male","boy","confused","indifferent","doubt"],char:"\u{1f937}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},tipping_hand_woman:{keywords:["female","girl","woman","human","information"],char:"\u{1f481}",fitzpatrick_scale:!0,category:"people"},tipping_hand_man:{keywords:["male","boy","man","human","information"],char:"\u{1f481}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},no_good_woman:{keywords:["female","girl","woman","nope"],char:"\u{1f645}",fitzpatrick_scale:!0,category:"people"},no_good_man:{keywords:["male","boy","man","nope"],char:"\u{1f645}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},ok_woman:{keywords:["women","girl","female","pink","human","woman"],char:"\u{1f646}",fitzpatrick_scale:!0,category:"people"},ok_man:{keywords:["men","boy","male","blue","human","man"],char:"\u{1f646}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},raising_hand_woman:{keywords:["female","girl","woman"],char:"\u{1f64b}",fitzpatrick_scale:!0,category:"people"},raising_hand_man:{keywords:["male","boy","man"],char:"\u{1f64b}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},pouting_woman:{keywords:["female","girl","woman"],char:"\u{1f64e}",fitzpatrick_scale:!0,category:"people"},pouting_man:{keywords:["male","boy","man"],char:"\u{1f64e}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},frowning_woman:{keywords:["female","girl","woman","sad","depressed","discouraged","unhappy"],char:"\u{1f64d}",fitzpatrick_scale:!0,category:"people"},frowning_man:{keywords:["male","boy","man","sad","depressed","discouraged","unhappy"],char:"\u{1f64d}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},haircut_woman:{keywords:["female","girl","woman"],char:"\u{1f487}",fitzpatrick_scale:!0,category:"people"},haircut_man:{keywords:["male","boy","man"],char:"\u{1f487}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},massage_woman:{keywords:["female","girl","woman","head"],char:"\u{1f486}",fitzpatrick_scale:!0,category:"people"},massage_man:{keywords:["male","boy","man","head"],char:"\u{1f486}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_in_steamy_room:{keywords:["female","woman","spa","steamroom","sauna"],char:"\u{1f9d6}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_in_steamy_room:{keywords:["male","man","spa","steamroom","sauna"],char:"\u{1f9d6}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},couple_with_heart_woman_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"\u{1f491}",fitzpatrick_scale:!1,category:"people"},couple_with_heart_woman_woman:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"\u{1f469}\u200d\u2764\ufe0f\u200d\u{1f469}",fitzpatrick_scale:!1,category:"people"},couple_with_heart_man_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"\u{1f468}\u200d\u2764\ufe0f\u200d\u{1f468}",fitzpatrick_scale:!1,category:"people"},couplekiss_man_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:"\u{1f48f}",fitzpatrick_scale:!1,category:"people"},couplekiss_woman_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:"\u{1f469}\u200d\u2764\ufe0f\u200d\u{1f48b}\u200d\u{1f469}",fitzpatrick_scale:!1,category:"people"},couplekiss_man_man:{keywords:["pair","valentines","love","like","dating","marriage"],char:"\u{1f468}\u200d\u2764\ufe0f\u200d\u{1f48b}\u200d\u{1f468}",fitzpatrick_scale:!1,category:"people"},family_man_woman_boy:{keywords:["home","parents","child","mom","dad","father","mother","people","human"],char:"\u{1f46a}",fitzpatrick_scale:!1,category:"people"},family_man_woman_girl:{keywords:["home","parents","people","human","child"],char:"\u{1f468}\u200d\u{1f469}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f469}\u200d\u{1f466}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f469}\u200d\u{1f469}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl:{keywords:["home","parents","people","human","children"],char:"\u{1f469}\u200d\u{1f469}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f469}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f469}\u200d\u{1f469}\u200d\u{1f466}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:"\u{1f469}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_man_man_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f468}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_man_girl:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f468}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_man_man_girl_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f468}\u200d\u{1f467}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_man_boy_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f468}\u200d\u{1f466}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_man_girl_girl:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f468}\u200d\u{1f467}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_woman_boy:{keywords:["home","parent","people","human","child"],char:"\u{1f469}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_girl:{keywords:["home","parent","people","human","child"],char:"\u{1f469}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_woman_girl_boy:{keywords:["home","parent","people","human","children"],char:"\u{1f469}\u200d\u{1f467}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_boy_boy:{keywords:["home","parent","people","human","children"],char:"\u{1f469}\u200d\u{1f466}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_girl_girl:{keywords:["home","parent","people","human","children"],char:"\u{1f469}\u200d\u{1f467}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_man_boy:{keywords:["home","parent","people","human","child"],char:"\u{1f468}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_girl:{keywords:["home","parent","people","human","child"],char:"\u{1f468}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_man_girl_boy:{keywords:["home","parent","people","human","children"],char:"\u{1f468}\u200d\u{1f467}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_boy_boy:{keywords:["home","parent","people","human","children"],char:"\u{1f468}\u200d\u{1f466}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_girl_girl:{keywords:["home","parent","people","human","children"],char:"\u{1f468}\u200d\u{1f467}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},yarn:{keywords:["ball","crochet","knit"],char:"\u{1f9f6}",fitzpatrick_scale:!1,category:"people"},thread:{keywords:["needle","sewing","spool","string"],char:"\u{1f9f5}",fitzpatrick_scale:!1,category:"people"},coat:{keywords:["jacket"],char:"\u{1f9e5}",fitzpatrick_scale:!1,category:"people"},labcoat:{keywords:["doctor","experiment","scientist","chemist"],char:"\u{1f97c}",fitzpatrick_scale:!1,category:"people"},womans_clothes:{keywords:["fashion","shopping_bags","female"],char:"\u{1f45a}",fitzpatrick_scale:!1,category:"people"},tshirt:{keywords:["fashion","cloth","casual","shirt","tee"],char:"\u{1f455}",fitzpatrick_scale:!1,category:"people"},jeans:{keywords:["fashion","shopping"],char:"\u{1f456}",fitzpatrick_scale:!1,category:"people"},necktie:{keywords:["shirt","suitup","formal","fashion","cloth","business"],char:"\u{1f454}",fitzpatrick_scale:!1,category:"people"},dress:{keywords:["clothes","fashion","shopping"],char:"\u{1f457}",fitzpatrick_scale:!1,category:"people"},bikini:{keywords:["swimming","female","woman","girl","fashion","beach","summer"],char:"\u{1f459}",fitzpatrick_scale:!1,category:"people"},kimono:{keywords:["dress","fashion","women","female","japanese"],char:"\u{1f458}",fitzpatrick_scale:!1,category:"people"},lipstick:{keywords:["female","girl","fashion","woman"],char:"\u{1f484}",fitzpatrick_scale:!1,category:"people"},kiss:{keywords:["face","lips","love","like","affection","valentines"],char:"\u{1f48b}",fitzpatrick_scale:!1,category:"people"},footprints:{keywords:["feet","tracking","walking","beach"],char:"\u{1f463}",fitzpatrick_scale:!1,category:"people"},flat_shoe:{keywords:["ballet","slip-on","slipper"],char:"\u{1f97f}",fitzpatrick_scale:!1,category:"people"},high_heel:{keywords:["fashion","shoes","female","pumps","stiletto"],char:"\u{1f460}",fitzpatrick_scale:!1,category:"people"},sandal:{keywords:["shoes","fashion","flip flops"],char:"\u{1f461}",fitzpatrick_scale:!1,category:"people"},boot:{keywords:["shoes","fashion"],char:"\u{1f462}",fitzpatrick_scale:!1,category:"people"},mans_shoe:{keywords:["fashion","male"],char:"\u{1f45e}",fitzpatrick_scale:!1,category:"people"},athletic_shoe:{keywords:["shoes","sports","sneakers"],char:"\u{1f45f}",fitzpatrick_scale:!1,category:"people"},hiking_boot:{keywords:["backpacking","camping","hiking"],char:"\u{1f97e}",fitzpatrick_scale:!1,category:"people"},socks:{keywords:["stockings","clothes"],char:"\u{1f9e6}",fitzpatrick_scale:!1,category:"people"},gloves:{keywords:["hands","winter","clothes"],char:"\u{1f9e4}",fitzpatrick_scale:!1,category:"people"},scarf:{keywords:["neck","winter","clothes"],char:"\u{1f9e3}",fitzpatrick_scale:!1,category:"people"},womans_hat:{keywords:["fashion","accessories","female","lady","spring"],char:"\u{1f452}",fitzpatrick_scale:!1,category:"people"},tophat:{keywords:["magic","gentleman","classy","circus"],char:"\u{1f3a9}",fitzpatrick_scale:!1,category:"people"},billed_hat:{keywords:["cap","baseball"],char:"\u{1f9e2}",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:"\u{1f393}",fitzpatrick_scale:!1,category:"people"},crown:{keywords:["king","kod","leader","royalty","lord"],char:"\u{1f451}",fitzpatrick_scale:!1,category:"people"},school_satchel:{keywords:["student","education","bag","backpack"],char:"\u{1f392}",fitzpatrick_scale:!1,category:"people"},luggage:{keywords:["packing","travel"],char:"\u{1f9f3}",fitzpatrick_scale:!1,category:"people"},pouch:{keywords:["bag","accessories","shopping"],char:"\u{1f45d}",fitzpatrick_scale:!1,category:"people"},purse:{keywords:["fashion","accessories","money","sales","shopping"],char:"\u{1f45b}",fitzpatrick_scale:!1,category:"people"},handbag:{keywords:["fashion","accessory","accessories","shopping"],char:"\u{1f45c}",fitzpatrick_scale:!1,category:"people"},briefcase:{keywords:["business","documents","work","law","legal","job","career"],char:"\u{1f4bc}",fitzpatrick_scale:!1,category:"people"},eyeglasses:{keywords:["fashion","accessories","eyesight","nerdy","dork","geek"],char:"\u{1f453}",fitzpatrick_scale:!1,category:"people"},dark_sunglasses:{keywords:["face","cool","accessories"],char:"\u{1f576}",fitzpatrick_scale:!1,category:"people"},goggles:{keywords:["eyes","protection","safety"],char:"\u{1f97d}",fitzpatrick_scale:!1,category:"people"},ring:{keywords:["wedding","propose","marriage","valentines","diamond","fashion","jewelry","gem","engagement"],char:"\u{1f48d}",fitzpatrick_scale:!1,category:"people"},closed_umbrella:{keywords:["weather","rain","drizzle"],char:"\u{1f302}",fitzpatrick_scale:!1,category:"people"},dog:{keywords:["animal","friend","nature","woof","puppy","pet","faithful"],char:"\u{1f436}",fitzpatrick_scale:!1,category:"animals_and_nature"},cat:{keywords:["animal","meow","nature","pet","kitten"],char:"\u{1f431}",fitzpatrick_scale:!1,category:"animals_and_nature"},mouse:{keywords:["animal","nature","cheese_wedge","rodent"],char:"\u{1f42d}",fitzpatrick_scale:!1,category:"animals_and_nature"},hamster:{keywords:["animal","nature"],char:"\u{1f439}",fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit:{keywords:["animal","nature","pet","spring","magic","bunny"],char:"\u{1f430}",fitzpatrick_scale:!1,category:"animals_and_nature"},fox_face:{keywords:["animal","nature","face"],char:"\u{1f98a}",fitzpatrick_scale:!1,category:"animals_and_nature"},bear:{keywords:["animal","nature","wild"],char:"\u{1f43b}",fitzpatrick_scale:!1,category:"animals_and_nature"},panda_face:{keywords:["animal","nature","panda"],char:"\u{1f43c}",fitzpatrick_scale:!1,category:"animals_and_nature"},koala:{keywords:["animal","nature"],char:"\u{1f428}",fitzpatrick_scale:!1,category:"animals_and_nature"},tiger:{keywords:["animal","cat","danger","wild","nature","roar"],char:"\u{1f42f}",fitzpatrick_scale:!1,category:"animals_and_nature"},lion:{keywords:["animal","nature"],char:"\u{1f981}",fitzpatrick_scale:!1,category:"animals_and_nature"},cow:{keywords:["beef","ox","animal","nature","moo","milk"],char:"\u{1f42e}",fitzpatrick_scale:!1,category:"animals_and_nature"},pig:{keywords:["animal","oink","nature"],char:"\u{1f437}",fitzpatrick_scale:!1,category:"animals_and_nature"},pig_nose:{keywords:["animal","oink"],char:"\u{1f43d}",fitzpatrick_scale:!1,category:"animals_and_nature"},frog:{keywords:["animal","nature","croak","toad"],char:"\u{1f438}",fitzpatrick_scale:!1,category:"animals_and_nature"},squid:{keywords:["animal","nature","ocean","sea"],char:"\u{1f991}",fitzpatrick_scale:!1,category:"animals_and_nature"},octopus:{keywords:["animal","creature","ocean","sea","nature","beach"],char:"\u{1f419}",fitzpatrick_scale:!1,category:"animals_and_nature"},shrimp:{keywords:["animal","ocean","nature","seafood"],char:"\u{1f990}",fitzpatrick_scale:!1,category:"animals_and_nature"},monkey_face:{keywords:["animal","nature","circus"],char:"\u{1f435}",fitzpatrick_scale:!1,category:"animals_and_nature"},gorilla:{keywords:["animal","nature","circus"],char:"\u{1f98d}",fitzpatrick_scale:!1,category:"animals_and_nature"},see_no_evil:{keywords:["monkey","animal","nature","haha"],char:"\u{1f648}",fitzpatrick_scale:!1,category:"animals_and_nature"},hear_no_evil:{keywords:["animal","monkey","nature"],char:"\u{1f649}",fitzpatrick_scale:!1,category:"animals_and_nature"},speak_no_evil:{keywords:["monkey","animal","nature","omg"],char:"\u{1f64a}",fitzpatrick_scale:!1,category:"animals_and_nature"},monkey:{keywords:["animal","nature","banana","circus"],char:"\u{1f412}",fitzpatrick_scale:!1,category:"animals_and_nature"},chicken:{keywords:["animal","cluck","nature","bird"],char:"\u{1f414}",fitzpatrick_scale:!1,category:"animals_and_nature"},penguin:{keywords:["animal","nature"],char:"\u{1f427}",fitzpatrick_scale:!1,category:"animals_and_nature"},bird:{keywords:["animal","nature","fly","tweet","spring"],char:"\u{1f426}",fitzpatrick_scale:!1,category:"animals_and_nature"},baby_chick:{keywords:["animal","chicken","bird"],char:"\u{1f424}",fitzpatrick_scale:!1,category:"animals_and_nature"},hatching_chick:{keywords:["animal","chicken","egg","born","baby","bird"],char:"\u{1f423}",fitzpatrick_scale:!1,category:"animals_and_nature"},hatched_chick:{keywords:["animal","chicken","baby","bird"],char:"\u{1f425}",fitzpatrick_scale:!1,category:"animals_and_nature"},duck:{keywords:["animal","nature","bird","mallard"],char:"\u{1f986}",fitzpatrick_scale:!1,category:"animals_and_nature"},eagle:{keywords:["animal","nature","bird"],char:"\u{1f985}",fitzpatrick_scale:!1,category:"animals_and_nature"},owl:{keywords:["animal","nature","bird","hoot"],char:"\u{1f989}",fitzpatrick_scale:!1,category:"animals_and_nature"},bat:{keywords:["animal","nature","blind","vampire"],char:"\u{1f987}",fitzpatrick_scale:!1,category:"animals_and_nature"},wolf:{keywords:["animal","nature","wild"],char:"\u{1f43a}",fitzpatrick_scale:!1,category:"animals_and_nature"},boar:{keywords:["animal","nature"],char:"\u{1f417}",fitzpatrick_scale:!1,category:"animals_and_nature"},horse:{keywords:["animal","brown","nature"],char:"\u{1f434}",fitzpatrick_scale:!1,category:"animals_and_nature"},unicorn:{keywords:["animal","nature","mystical"],char:"\u{1f984}",fitzpatrick_scale:!1,category:"animals_and_nature"},honeybee:{keywords:["animal","insect","nature","bug","spring","honey"],char:"\u{1f41d}",fitzpatrick_scale:!1,category:"animals_and_nature"},bug:{keywords:["animal","insect","nature","worm"],char:"\u{1f41b}",fitzpatrick_scale:!1,category:"animals_and_nature"},butterfly:{keywords:["animal","insect","nature","caterpillar"],char:"\u{1f98b}",fitzpatrick_scale:!1,category:"animals_and_nature"},snail:{keywords:["slow","animal","shell"],char:"\u{1f40c}",fitzpatrick_scale:!1,category:"animals_and_nature"},beetle:{keywords:["animal","insect","nature","ladybug"],char:"\u{1f41e}",fitzpatrick_scale:!1,category:"animals_and_nature"},ant:{keywords:["animal","insect","nature","bug"],char:"\u{1f41c}",fitzpatrick_scale:!1,category:"animals_and_nature"},grasshopper:{keywords:["animal","cricket","chirp"],char:"\u{1f997}",fitzpatrick_scale:!1,category:"animals_and_nature"},spider:{keywords:["animal","arachnid"],char:"\u{1f577}",fitzpatrick_scale:!1,category:"animals_and_nature"},scorpion:{keywords:["animal","arachnid"],char:"\u{1f982}",fitzpatrick_scale:!1,category:"animals_and_nature"},crab:{keywords:["animal","crustacean"],char:"\u{1f980}",fitzpatrick_scale:!1,category:"animals_and_nature"},snake:{keywords:["animal","evil","nature","hiss","python"],char:"\u{1f40d}",fitzpatrick_scale:!1,category:"animals_and_nature"},lizard:{keywords:["animal","nature","reptile"],char:"\u{1f98e}",fitzpatrick_scale:!1,category:"animals_and_nature"},"t-rex":{keywords:["animal","nature","dinosaur","tyrannosaurus","extinct"],char:"\u{1f996}",fitzpatrick_scale:!1,category:"animals_and_nature"},sauropod:{keywords:["animal","nature","dinosaur","brachiosaurus","brontosaurus","diplodocus","extinct"],char:"\u{1f995}",fitzpatrick_scale:!1,category:"animals_and_nature"},turtle:{keywords:["animal","slow","nature","tortoise"],char:"\u{1f422}",fitzpatrick_scale:!1,category:"animals_and_nature"},tropical_fish:{keywords:["animal","swim","ocean","beach","nemo"],char:"\u{1f420}",fitzpatrick_scale:!1,category:"animals_and_nature"},fish:{keywords:["animal","food","nature"],char:"\u{1f41f}",fitzpatrick_scale:!1,category:"animals_and_nature"},blowfish:{keywords:["animal","nature","food","sea","ocean"],char:"\u{1f421}",fitzpatrick_scale:!1,category:"animals_and_nature"},dolphin:{keywords:["animal","nature","fish","sea","ocean","flipper","fins","beach"],char:"\u{1f42c}",fitzpatrick_scale:!1,category:"animals_and_nature"},shark:{keywords:["animal","nature","fish","sea","ocean","jaws","fins","beach"],char:"\u{1f988}",fitzpatrick_scale:!1,category:"animals_and_nature"},whale:{keywords:["animal","nature","sea","ocean"],char:"\u{1f433}",fitzpatrick_scale:!1,category:"animals_and_nature"},whale2:{keywords:["animal","nature","sea","ocean"],char:"\u{1f40b}",fitzpatrick_scale:!1,category:"animals_and_nature"},crocodile:{keywords:["animal","nature","reptile","lizard","alligator"],char:"\u{1f40a}",fitzpatrick_scale:!1,category:"animals_and_nature"},leopard:{keywords:["animal","nature"],char:"\u{1f406}",fitzpatrick_scale:!1,category:"animals_and_nature"},zebra:{keywords:["animal","nature","stripes","safari"],char:"\u{1f993}",fitzpatrick_scale:!1,category:"animals_and_nature"},tiger2:{keywords:["animal","nature","roar"],char:"\u{1f405}",fitzpatrick_scale:!1,category:"animals_and_nature"},water_buffalo:{keywords:["animal","nature","ox","cow"],char:"\u{1f403}",fitzpatrick_scale:!1,category:"animals_and_nature"},ox:{keywords:["animal","cow","beef"],char:"\u{1f402}",fitzpatrick_scale:!1,category:"animals_and_nature"},cow2:{keywords:["beef","ox","animal","nature","moo","milk"],char:"\u{1f404}",fitzpatrick_scale:!1,category:"animals_and_nature"},deer:{keywords:["animal","nature","horns","venison"],char:"\u{1f98c}",fitzpatrick_scale:!1,category:"animals_and_nature"},dromedary_camel:{keywords:["animal","hot","desert","hump"],char:"\u{1f42a}",fitzpatrick_scale:!1,category:"animals_and_nature"},camel:{keywords:["animal","nature","hot","desert","hump"],char:"\u{1f42b}",fitzpatrick_scale:!1,category:"animals_and_nature"},giraffe:{keywords:["animal","nature","spots","safari"],char:"\u{1f992}",fitzpatrick_scale:!1,category:"animals_and_nature"},elephant:{keywords:["animal","nature","nose","th","circus"],char:"\u{1f418}",fitzpatrick_scale:!1,category:"animals_and_nature"},rhinoceros:{keywords:["animal","nature","horn"],char:"\u{1f98f}",fitzpatrick_scale:!1,category:"animals_and_nature"},goat:{keywords:["animal","nature"],char:"\u{1f410}",fitzpatrick_scale:!1,category:"animals_and_nature"},ram:{keywords:["animal","sheep","nature"],char:"\u{1f40f}",fitzpatrick_scale:!1,category:"animals_and_nature"},sheep:{keywords:["animal","nature","wool","shipit"],char:"\u{1f411}",fitzpatrick_scale:!1,category:"animals_and_nature"},racehorse:{keywords:["animal","gamble","luck"],char:"\u{1f40e}",fitzpatrick_scale:!1,category:"animals_and_nature"},pig2:{keywords:["animal","nature"],char:"\u{1f416}",fitzpatrick_scale:!1,category:"animals_and_nature"},rat:{keywords:["animal","mouse","rodent"],char:"\u{1f400}",fitzpatrick_scale:!1,category:"animals_and_nature"},mouse2:{keywords:["animal","nature","rodent"],char:"\u{1f401}",fitzpatrick_scale:!1,category:"animals_and_nature"},rooster:{keywords:["animal","nature","chicken"],char:"\u{1f413}",fitzpatrick_scale:!1,category:"animals_and_nature"},turkey:{keywords:["animal","bird"],char:"\u{1f983}",fitzpatrick_scale:!1,category:"animals_and_nature"},dove:{keywords:["animal","bird"],char:"\u{1f54a}",fitzpatrick_scale:!1,category:"animals_and_nature"},dog2:{keywords:["animal","nature","friend","doge","pet","faithful"],char:"\u{1f415}",fitzpatrick_scale:!1,category:"animals_and_nature"},poodle:{keywords:["dog","animal","101","nature","pet"],char:"\u{1f429}",fitzpatrick_scale:!1,category:"animals_and_nature"},cat2:{keywords:["animal","meow","pet","cats"],char:"\u{1f408}",fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit2:{keywords:["animal","nature","pet","magic","spring"],char:"\u{1f407}",fitzpatrick_scale:!1,category:"animals_and_nature"},chipmunk:{keywords:["animal","nature","rodent","squirrel"],char:"\u{1f43f}",fitzpatrick_scale:!1,category:"animals_and_nature"},hedgehog:{keywords:["animal","nature","spiny"],char:"\u{1f994}",fitzpatrick_scale:!1,category:"animals_and_nature"},raccoon:{keywords:["animal","nature"],char:"\u{1f99d}",fitzpatrick_scale:!1,category:"animals_and_nature"},llama:{keywords:["animal","nature","alpaca"],char:"\u{1f999}",fitzpatrick_scale:!1,category:"animals_and_nature"},hippopotamus:{keywords:["animal","nature"],char:"\u{1f99b}",fitzpatrick_scale:!1,category:"animals_and_nature"},kangaroo:{keywords:["animal","nature","australia","joey","hop","marsupial"],char:"\u{1f998}",fitzpatrick_scale:!1,category:"animals_and_nature"},badger:{keywords:["animal","nature","honey"],char:"\u{1f9a1}",fitzpatrick_scale:!1,category:"animals_and_nature"},swan:{keywords:["animal","nature","bird"],char:"\u{1f9a2}",fitzpatrick_scale:!1,category:"animals_and_nature"},peacock:{keywords:["animal","nature","peahen","bird"],char:"\u{1f99a}",fitzpatrick_scale:!1,category:"animals_and_nature"},parrot:{keywords:["animal","nature","bird","pirate","talk"],char:"\u{1f99c}",fitzpatrick_scale:!1,category:"animals_and_nature"},lobster:{keywords:["animal","nature","bisque","claws","seafood"],char:"\u{1f99e}",fitzpatrick_scale:!1,category:"animals_and_nature"},mosquito:{keywords:["animal","nature","insect","malaria"],char:"\u{1f99f}",fitzpatrick_scale:!1,category:"animals_and_nature"},paw_prints:{keywords:["animal","tracking","footprints","dog","cat","pet","feet"],char:"\u{1f43e}",fitzpatrick_scale:!1,category:"animals_and_nature"},dragon:{keywords:["animal","myth","nature","chinese","green"],char:"\u{1f409}",fitzpatrick_scale:!1,category:"animals_and_nature"},dragon_face:{keywords:["animal","myth","nature","chinese","green"],char:"\u{1f432}",fitzpatrick_scale:!1,category:"animals_and_nature"},cactus:{keywords:["vegetable","plant","nature"],char:"\u{1f335}",fitzpatrick_scale:!1,category:"animals_and_nature"},christmas_tree:{keywords:["festival","vacation","december","xmas","celebration"],char:"\u{1f384}",fitzpatrick_scale:!1,category:"animals_and_nature"},evergreen_tree:{keywords:["plant","nature"],char:"\u{1f332}",fitzpatrick_scale:!1,category:"animals_and_nature"},deciduous_tree:{keywords:["plant","nature"],char:"\u{1f333}",fitzpatrick_scale:!1,category:"animals_and_nature"},palm_tree:{keywords:["plant","vegetable","nature","summer","beach","mojito","tropical"],char:"\u{1f334}",fitzpatrick_scale:!1,category:"animals_and_nature"},seedling:{keywords:["plant","nature","grass","lawn","spring"],char:"\u{1f331}",fitzpatrick_scale:!1,category:"animals_and_nature"},herb:{keywords:["vegetable","plant","medicine","weed","grass","lawn"],char:"\u{1f33f}",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:"\u{1f340}",fitzpatrick_scale:!1,category:"animals_and_nature"},bamboo:{keywords:["plant","nature","vegetable","panda","pine_decoration"],char:"\u{1f38d}",fitzpatrick_scale:!1,category:"animals_and_nature"},tanabata_tree:{keywords:["plant","nature","branch","summer"],char:"\u{1f38b}",fitzpatrick_scale:!1,category:"animals_and_nature"},leaves:{keywords:["nature","plant","tree","vegetable","grass","lawn","spring"],char:"\u{1f343}",fitzpatrick_scale:!1,category:"animals_and_nature"},fallen_leaf:{keywords:["nature","plant","vegetable","leaves"],char:"\u{1f342}",fitzpatrick_scale:!1,category:"animals_and_nature"},maple_leaf:{keywords:["nature","plant","vegetable","ca","fall"],char:"\u{1f341}",fitzpatrick_scale:!1,category:"animals_and_nature"},ear_of_rice:{keywords:["nature","plant"],char:"\u{1f33e}",fitzpatrick_scale:!1,category:"animals_and_nature"},hibiscus:{keywords:["plant","vegetable","flowers","beach"],char:"\u{1f33a}",fitzpatrick_scale:!1,category:"animals_and_nature"},sunflower:{keywords:["nature","plant","fall"],char:"\u{1f33b}",fitzpatrick_scale:!1,category:"animals_and_nature"},rose:{keywords:["flowers","valentines","love","spring"],char:"\u{1f339}",fitzpatrick_scale:!1,category:"animals_and_nature"},wilted_flower:{keywords:["plant","nature","flower"],char:"\u{1f940}",fitzpatrick_scale:!1,category:"animals_and_nature"},tulip:{keywords:["flowers","plant","nature","summer","spring"],char:"\u{1f337}",fitzpatrick_scale:!1,category:"animals_and_nature"},blossom:{keywords:["nature","flowers","yellow"],char:"\u{1f33c}",fitzpatrick_scale:!1,category:"animals_and_nature"},cherry_blossom:{keywords:["nature","plant","spring","flower"],char:"\u{1f338}",fitzpatrick_scale:!1,category:"animals_and_nature"},bouquet:{keywords:["flowers","nature","spring"],char:"\u{1f490}",fitzpatrick_scale:!1,category:"animals_and_nature"},mushroom:{keywords:["plant","vegetable"],char:"\u{1f344}",fitzpatrick_scale:!1,category:"animals_and_nature"},chestnut:{keywords:["food","squirrel"],char:"\u{1f330}",fitzpatrick_scale:!1,category:"animals_and_nature"},jack_o_lantern:{keywords:["halloween","light","pumpkin","creepy","fall"],char:"\u{1f383}",fitzpatrick_scale:!1,category:"animals_and_nature"},shell:{keywords:["nature","sea","beach"],char:"\u{1f41a}",fitzpatrick_scale:!1,category:"animals_and_nature"},spider_web:{keywords:["animal","insect","arachnid","silk"],char:"\u{1f578}",fitzpatrick_scale:!1,category:"animals_and_nature"},earth_americas:{keywords:["globe","world","USA","international"],char:"\u{1f30e}",fitzpatrick_scale:!1,category:"animals_and_nature"},earth_africa:{keywords:["globe","world","international"],char:"\u{1f30d}",fitzpatrick_scale:!1,category:"animals_and_nature"},earth_asia:{keywords:["globe","world","east","international"],char:"\u{1f30f}",fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon:{keywords:["nature","yellow","twilight","planet","space","night","evening","sleep"],char:"\u{1f315}",fitzpatrick_scale:!1,category:"animals_and_nature"},waning_gibbous_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep","waxing_gibbous_moon"],char:"\u{1f316}",fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f317}",fitzpatrick_scale:!1,category:"animals_and_nature"},waning_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f318}",fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f311}",fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f312}",fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f313}",fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_gibbous_moon:{keywords:["nature","night","sky","gray","twilight","planet","space","evening","sleep"],char:"\u{1f314}",fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f31a}",fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f31d}",fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f31b}",fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f31c}",fitzpatrick_scale:!1,category:"animals_and_nature"},sun_with_face:{keywords:["nature","morning","sky"],char:"\u{1f31e}",fitzpatrick_scale:!1,category:"animals_and_nature"},crescent_moon:{keywords:["night","sleep","sky","evening","magic"],char:"\u{1f319}",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:"\u{1f31f}",fitzpatrick_scale:!1,category:"animals_and_nature"},dizzy:{keywords:["star","sparkle","shoot","magic"],char:"\u{1f4ab}",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:"\u{1f324}",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:"\u{1f325}",fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_rain_cloud:{keywords:["weather"],char:"\u{1f326}",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:"\u{1f327}",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:"\u{1f329}",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:"\u{1f525}",fitzpatrick_scale:!1,category:"animals_and_nature"},boom:{keywords:["bomb","explode","explosion","collision","blown"],char:"\u{1f4a5}",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:"\u{1f328}",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:"\u{1f32c}",fitzpatrick_scale:!1,category:"animals_and_nature"},dash:{keywords:["wind","air","fast","shoo","fart","smoke","puff"],char:"\u{1f4a8}",fitzpatrick_scale:!1,category:"animals_and_nature"},tornado:{keywords:["weather","cyclone","twister"],char:"\u{1f32a}",fitzpatrick_scale:!1,category:"animals_and_nature"},fog:{keywords:["weather"],char:"\u{1f32b}",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:"\u{1f4a7}",fitzpatrick_scale:!1,category:"animals_and_nature"},sweat_drops:{keywords:["water","drip","oops"],char:"\u{1f4a6}",fitzpatrick_scale:!1,category:"animals_and_nature"},ocean:{keywords:["sea","water","wave","nature","tsunami","disaster"],char:"\u{1f30a}",fitzpatrick_scale:!1,category:"animals_and_nature"},green_apple:{keywords:["fruit","nature"],char:"\u{1f34f}",fitzpatrick_scale:!1,category:"food_and_drink"},apple:{keywords:["fruit","mac","school"],char:"\u{1f34e}",fitzpatrick_scale:!1,category:"food_and_drink"},pear:{keywords:["fruit","nature","food"],char:"\u{1f350}",fitzpatrick_scale:!1,category:"food_and_drink"},tangerine:{keywords:["food","fruit","nature","orange"],char:"\u{1f34a}",fitzpatrick_scale:!1,category:"food_and_drink"},lemon:{keywords:["fruit","nature"],char:"\u{1f34b}",fitzpatrick_scale:!1,category:"food_and_drink"},banana:{keywords:["fruit","food","monkey"],char:"\u{1f34c}",fitzpatrick_scale:!1,category:"food_and_drink"},watermelon:{keywords:["fruit","food","picnic","summer"],char:"\u{1f349}",fitzpatrick_scale:!1,category:"food_and_drink"},grapes:{keywords:["fruit","food","wine"],char:"\u{1f347}",fitzpatrick_scale:!1,category:"food_and_drink"},strawberry:{keywords:["fruit","food","nature"],char:"\u{1f353}",fitzpatrick_scale:!1,category:"food_and_drink"},melon:{keywords:["fruit","nature","food"],char:"\u{1f348}",fitzpatrick_scale:!1,category:"food_and_drink"},cherries:{keywords:["food","fruit"],char:"\u{1f352}",fitzpatrick_scale:!1,category:"food_and_drink"},peach:{keywords:["fruit","nature","food"],char:"\u{1f351}",fitzpatrick_scale:!1,category:"food_and_drink"},pineapple:{keywords:["fruit","nature","food"],char:"\u{1f34d}",fitzpatrick_scale:!1,category:"food_and_drink"},coconut:{keywords:["fruit","nature","food","palm"],char:"\u{1f965}",fitzpatrick_scale:!1,category:"food_and_drink"},kiwi_fruit:{keywords:["fruit","food"],char:"\u{1f95d}",fitzpatrick_scale:!1,category:"food_and_drink"},mango:{keywords:["fruit","food","tropical"],char:"\u{1f96d}",fitzpatrick_scale:!1,category:"food_and_drink"},avocado:{keywords:["fruit","food"],char:"\u{1f951}",fitzpatrick_scale:!1,category:"food_and_drink"},broccoli:{keywords:["fruit","food","vegetable"],char:"\u{1f966}",fitzpatrick_scale:!1,category:"food_and_drink"},tomato:{keywords:["fruit","vegetable","nature","food"],char:"\u{1f345}",fitzpatrick_scale:!1,category:"food_and_drink"},eggplant:{keywords:["vegetable","nature","food","aubergine"],char:"\u{1f346}",fitzpatrick_scale:!1,category:"food_and_drink"},cucumber:{keywords:["fruit","food","pickle"],char:"\u{1f952}",fitzpatrick_scale:!1,category:"food_and_drink"},carrot:{keywords:["vegetable","food","orange"],char:"\u{1f955}",fitzpatrick_scale:!1,category:"food_and_drink"},hot_pepper:{keywords:["food","spicy","chilli","chili"],char:"\u{1f336}",fitzpatrick_scale:!1,category:"food_and_drink"},potato:{keywords:["food","tuber","vegatable","starch"],char:"\u{1f954}",fitzpatrick_scale:!1,category:"food_and_drink"},corn:{keywords:["food","vegetable","plant"],char:"\u{1f33d}",fitzpatrick_scale:!1,category:"food_and_drink"},leafy_greens:{keywords:["food","vegetable","plant","bok choy","cabbage","kale","lettuce"],char:"\u{1f96c}",fitzpatrick_scale:!1,category:"food_and_drink"},sweet_potato:{keywords:["food","nature"],char:"\u{1f360}",fitzpatrick_scale:!1,category:"food_and_drink"},peanuts:{keywords:["food","nut"],char:"\u{1f95c}",fitzpatrick_scale:!1,category:"food_and_drink"},honey_pot:{keywords:["bees","sweet","kitchen"],char:"\u{1f36f}",fitzpatrick_scale:!1,category:"food_and_drink"},croissant:{keywords:["food","bread","french"],char:"\u{1f950}",fitzpatrick_scale:!1,category:"food_and_drink"},bread:{keywords:["food","wheat","breakfast","toast"],char:"\u{1f35e}",fitzpatrick_scale:!1,category:"food_and_drink"},baguette_bread:{keywords:["food","bread","french"],char:"\u{1f956}",fitzpatrick_scale:!1,category:"food_and_drink"},bagel:{keywords:["food","bread","bakery","schmear"],char:"\u{1f96f}",fitzpatrick_scale:!1,category:"food_and_drink"},pretzel:{keywords:["food","bread","twisted"],char:"\u{1f968}",fitzpatrick_scale:!1,category:"food_and_drink"},cheese:{keywords:["food","chadder"],char:"\u{1f9c0}",fitzpatrick_scale:!1,category:"food_and_drink"},egg:{keywords:["food","chicken","breakfast"],char:"\u{1f95a}",fitzpatrick_scale:!1,category:"food_and_drink"},bacon:{keywords:["food","breakfast","pork","pig","meat"],char:"\u{1f953}",fitzpatrick_scale:!1,category:"food_and_drink"},steak:{keywords:["food","cow","meat","cut","chop","lambchop","porkchop"],char:"\u{1f969}",fitzpatrick_scale:!1,category:"food_and_drink"},pancakes:{keywords:["food","breakfast","flapjacks","hotcakes"],char:"\u{1f95e}",fitzpatrick_scale:!1,category:"food_and_drink"},poultry_leg:{keywords:["food","meat","drumstick","bird","chicken","turkey"],char:"\u{1f357}",fitzpatrick_scale:!1,category:"food_and_drink"},meat_on_bone:{keywords:["good","food","drumstick"],char:"\u{1f356}",fitzpatrick_scale:!1,category:"food_and_drink"},bone:{keywords:["skeleton"],char:"\u{1f9b4}",fitzpatrick_scale:!1,category:"food_and_drink"},fried_shrimp:{keywords:["food","animal","appetizer","summer"],char:"\u{1f364}",fitzpatrick_scale:!1,category:"food_and_drink"},fried_egg:{keywords:["food","breakfast","kitchen","egg"],char:"\u{1f373}",fitzpatrick_scale:!1,category:"food_and_drink"},hamburger:{keywords:["meat","fast food","beef","cheeseburger","mcdonalds","burger king"],char:"\u{1f354}",fitzpatrick_scale:!1,category:"food_and_drink"},fries:{keywords:["chips","snack","fast food"],char:"\u{1f35f}",fitzpatrick_scale:!1,category:"food_and_drink"},stuffed_flatbread:{keywords:["food","flatbread","stuffed","gyro"],char:"\u{1f959}",fitzpatrick_scale:!1,category:"food_and_drink"},hotdog:{keywords:["food","frankfurter"],char:"\u{1f32d}",fitzpatrick_scale:!1,category:"food_and_drink"},pizza:{keywords:["food","party"],char:"\u{1f355}",fitzpatrick_scale:!1,category:"food_and_drink"},sandwich:{keywords:["food","lunch","bread"],char:"\u{1f96a}",fitzpatrick_scale:!1,category:"food_and_drink"},canned_food:{keywords:["food","soup"],char:"\u{1f96b}",fitzpatrick_scale:!1,category:"food_and_drink"},spaghetti:{keywords:["food","italian","noodle"],char:"\u{1f35d}",fitzpatrick_scale:!1,category:"food_and_drink"},taco:{keywords:["food","mexican"],char:"\u{1f32e}",fitzpatrick_scale:!1,category:"food_and_drink"},burrito:{keywords:["food","mexican"],char:"\u{1f32f}",fitzpatrick_scale:!1,category:"food_and_drink"},green_salad:{keywords:["food","healthy","lettuce"],char:"\u{1f957}",fitzpatrick_scale:!1,category:"food_and_drink"},shallow_pan_of_food:{keywords:["food","cooking","casserole","paella"],char:"\u{1f958}",fitzpatrick_scale:!1,category:"food_and_drink"},ramen:{keywords:["food","japanese","noodle","chopsticks"],char:"\u{1f35c}",fitzpatrick_scale:!1,category:"food_and_drink"},stew:{keywords:["food","meat","soup"],char:"\u{1f372}",fitzpatrick_scale:!1,category:"food_and_drink"},fish_cake:{keywords:["food","japan","sea","beach","narutomaki","pink","swirl","kamaboko","surimi","ramen"],char:"\u{1f365}",fitzpatrick_scale:!1,category:"food_and_drink"},fortune_cookie:{keywords:["food","prophecy"],char:"\u{1f960}",fitzpatrick_scale:!1,category:"food_and_drink"},sushi:{keywords:["food","fish","japanese","rice"],char:"\u{1f363}",fitzpatrick_scale:!1,category:"food_and_drink"},bento:{keywords:["food","japanese","box"],char:"\u{1f371}",fitzpatrick_scale:!1,category:"food_and_drink"},curry:{keywords:["food","spicy","hot","indian"],char:"\u{1f35b}",fitzpatrick_scale:!1,category:"food_and_drink"},rice_ball:{keywords:["food","japanese"],char:"\u{1f359}",fitzpatrick_scale:!1,category:"food_and_drink"},rice:{keywords:["food","china","asian"],char:"\u{1f35a}",fitzpatrick_scale:!1,category:"food_and_drink"},rice_cracker:{keywords:["food","japanese"],char:"\u{1f358}",fitzpatrick_scale:!1,category:"food_and_drink"},oden:{keywords:["food","japanese"],char:"\u{1f362}",fitzpatrick_scale:!1,category:"food_and_drink"},dango:{keywords:["food","dessert","sweet","japanese","barbecue","meat"],char:"\u{1f361}",fitzpatrick_scale:!1,category:"food_and_drink"},shaved_ice:{keywords:["hot","dessert","summer"],char:"\u{1f367}",fitzpatrick_scale:!1,category:"food_and_drink"},ice_cream:{keywords:["food","hot","dessert"],char:"\u{1f368}",fitzpatrick_scale:!1,category:"food_and_drink"},icecream:{keywords:["food","hot","dessert","summer"],char:"\u{1f366}",fitzpatrick_scale:!1,category:"food_and_drink"},pie:{keywords:["food","dessert","pastry"],char:"\u{1f967}",fitzpatrick_scale:!1,category:"food_and_drink"},cake:{keywords:["food","dessert"],char:"\u{1f370}",fitzpatrick_scale:!1,category:"food_and_drink"},cupcake:{keywords:["food","dessert","bakery","sweet"],char:"\u{1f9c1}",fitzpatrick_scale:!1,category:"food_and_drink"},moon_cake:{keywords:["food","autumn"],char:"\u{1f96e}",fitzpatrick_scale:!1,category:"food_and_drink"},birthday:{keywords:["food","dessert","cake"],char:"\u{1f382}",fitzpatrick_scale:!1,category:"food_and_drink"},custard:{keywords:["dessert","food"],char:"\u{1f36e}",fitzpatrick_scale:!1,category:"food_and_drink"},candy:{keywords:["snack","dessert","sweet","lolly"],char:"\u{1f36c}",fitzpatrick_scale:!1,category:"food_and_drink"},lollipop:{keywords:["food","snack","candy","sweet"],char:"\u{1f36d}",fitzpatrick_scale:!1,category:"food_and_drink"},chocolate_bar:{keywords:["food","snack","dessert","sweet"],char:"\u{1f36b}",fitzpatrick_scale:!1,category:"food_and_drink"},popcorn:{keywords:["food","movie theater","films","snack"],char:"\u{1f37f}",fitzpatrick_scale:!1,category:"food_and_drink"},dumpling:{keywords:["food","empanada","pierogi","potsticker"],char:"\u{1f95f}",fitzpatrick_scale:!1,category:"food_and_drink"},doughnut:{keywords:["food","dessert","snack","sweet","donut"],char:"\u{1f369}",fitzpatrick_scale:!1,category:"food_and_drink"},cookie:{keywords:["food","snack","oreo","chocolate","sweet","dessert"],char:"\u{1f36a}",fitzpatrick_scale:!1,category:"food_and_drink"},milk_glass:{keywords:["beverage","drink","cow"],char:"\u{1f95b}",fitzpatrick_scale:!1,category:"food_and_drink"},beer:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:"\u{1f37a}",fitzpatrick_scale:!1,category:"food_and_drink"},beers:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:"\u{1f37b}",fitzpatrick_scale:!1,category:"food_and_drink"},clinking_glasses:{keywords:["beverage","drink","party","alcohol","celebrate","cheers","wine","champagne","toast"],char:"\u{1f942}",fitzpatrick_scale:!1,category:"food_and_drink"},wine_glass:{keywords:["drink","beverage","drunk","alcohol","booze"],char:"\u{1f377}",fitzpatrick_scale:!1,category:"food_and_drink"},tumbler_glass:{keywords:["drink","beverage","drunk","alcohol","liquor","booze","bourbon","scotch","whisky","glass","shot"],char:"\u{1f943}",fitzpatrick_scale:!1,category:"food_and_drink"},cocktail:{keywords:["drink","drunk","alcohol","beverage","booze","mojito"],char:"\u{1f378}",fitzpatrick_scale:!1,category:"food_and_drink"},tropical_drink:{keywords:["beverage","cocktail","summer","beach","alcohol","booze","mojito"],char:"\u{1f379}",fitzpatrick_scale:!1,category:"food_and_drink"},champagne:{keywords:["drink","wine","bottle","celebration"],char:"\u{1f37e}",fitzpatrick_scale:!1,category:"food_and_drink"},sake:{keywords:["wine","drink","drunk","beverage","japanese","alcohol","booze"],char:"\u{1f376}",fitzpatrick_scale:!1,category:"food_and_drink"},tea:{keywords:["drink","bowl","breakfast","green","british"],char:"\u{1f375}",fitzpatrick_scale:!1,category:"food_and_drink"},cup_with_straw:{keywords:["drink","soda"],char:"\u{1f964}",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:"\u{1f37c}",fitzpatrick_scale:!1,category:"food_and_drink"},salt:{keywords:["condiment","shaker"],char:"\u{1f9c2}",fitzpatrick_scale:!1,category:"food_and_drink"},spoon:{keywords:["cutlery","kitchen","tableware"],char:"\u{1f944}",fitzpatrick_scale:!1,category:"food_and_drink"},fork_and_knife:{keywords:["cutlery","kitchen"],char:"\u{1f374}",fitzpatrick_scale:!1,category:"food_and_drink"},plate_with_cutlery:{keywords:["food","eat","meal","lunch","dinner","restaurant"],char:"\u{1f37d}",fitzpatrick_scale:!1,category:"food_and_drink"},bowl_with_spoon:{keywords:["food","breakfast","cereal","oatmeal","porridge"],char:"\u{1f963}",fitzpatrick_scale:!1,category:"food_and_drink"},takeout_box:{keywords:["food","leftovers"],char:"\u{1f961}",fitzpatrick_scale:!1,category:"food_and_drink"},chopsticks:{keywords:["food"],char:"\u{1f962}",fitzpatrick_scale:!1,category:"food_and_drink"},soccer:{keywords:["sports","football"],char:"\u26bd",fitzpatrick_scale:!1,category:"activity"},basketball:{keywords:["sports","balls","NBA"],char:"\u{1f3c0}",fitzpatrick_scale:!1,category:"activity"},football:{keywords:["sports","balls","NFL"],char:"\u{1f3c8}",fitzpatrick_scale:!1,category:"activity"},baseball:{keywords:["sports","balls"],char:"\u26be",fitzpatrick_scale:!1,category:"activity"},softball:{keywords:["sports","balls"],char:"\u{1f94e}",fitzpatrick_scale:!1,category:"activity"},tennis:{keywords:["sports","balls","green"],char:"\u{1f3be}",fitzpatrick_scale:!1,category:"activity"},volleyball:{keywords:["sports","balls"],char:"\u{1f3d0}",fitzpatrick_scale:!1,category:"activity"},rugby_football:{keywords:["sports","team"],char:"\u{1f3c9}",fitzpatrick_scale:!1,category:"activity"},flying_disc:{keywords:["sports","frisbee","ultimate"],char:"\u{1f94f}",fitzpatrick_scale:!1,category:"activity"},"8ball":{keywords:["pool","hobby","game","luck","magic"],char:"\u{1f3b1}",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:"\u{1f3cc}\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"activity"},golfing_man:{keywords:["sports","business"],char:"\u{1f3cc}",fitzpatrick_scale:!0,category:"activity"},ping_pong:{keywords:["sports","pingpong"],char:"\u{1f3d3}",fitzpatrick_scale:!1,category:"activity"},badminton:{keywords:["sports"],char:"\u{1f3f8}",fitzpatrick_scale:!1,category:"activity"},goal_net:{keywords:["sports"],char:"\u{1f945}",fitzpatrick_scale:!1,category:"activity"},ice_hockey:{keywords:["sports"],char:"\u{1f3d2}",fitzpatrick_scale:!1,category:"activity"},field_hockey:{keywords:["sports"],char:"\u{1f3d1}",fitzpatrick_scale:!1,category:"activity"},lacrosse:{keywords:["sports","ball","stick"],char:"\u{1f94d}",fitzpatrick_scale:!1,category:"activity"},cricket:{keywords:["sports"],char:"\u{1f3cf}",fitzpatrick_scale:!1,category:"activity"},ski:{keywords:["sports","winter","cold","snow"],char:"\u{1f3bf}",fitzpatrick_scale:!1,category:"activity"},skier:{keywords:["sports","winter","snow"],char:"\u26f7",fitzpatrick_scale:!1,category:"activity"},snowboarder:{keywords:["sports","winter"],char:"\u{1f3c2}",fitzpatrick_scale:!0,category:"activity"},person_fencing:{keywords:["sports","fencing","sword"],char:"\u{1f93a}",fitzpatrick_scale:!1,category:"activity"},women_wrestling:{keywords:["sports","wrestlers"],char:"\u{1f93c}\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"activity"},men_wrestling:{keywords:["sports","wrestlers"],char:"\u{1f93c}\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"activity"},woman_cartwheeling:{keywords:["gymnastics"],char:"\u{1f938}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_cartwheeling:{keywords:["gymnastics"],char:"\u{1f938}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},woman_playing_handball:{keywords:["sports"],char:"\u{1f93e}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_playing_handball:{keywords:["sports"],char:"\u{1f93e}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},ice_skate:{keywords:["sports"],char:"\u26f8",fitzpatrick_scale:!1,category:"activity"},curling_stone:{keywords:["sports"],char:"\u{1f94c}",fitzpatrick_scale:!1,category:"activity"},skateboard:{keywords:["board"],char:"\u{1f6f9}",fitzpatrick_scale:!1,category:"activity"},sled:{keywords:["sleigh","luge","toboggan"],char:"\u{1f6f7}",fitzpatrick_scale:!1,category:"activity"},bow_and_arrow:{keywords:["sports"],char:"\u{1f3f9}",fitzpatrick_scale:!1,category:"activity"},fishing_pole_and_fish:{keywords:["food","hobby","summer"],char:"\u{1f3a3}",fitzpatrick_scale:!1,category:"activity"},boxing_glove:{keywords:["sports","fighting"],char:"\u{1f94a}",fitzpatrick_scale:!1,category:"activity"},martial_arts_uniform:{keywords:["judo","karate","taekwondo"],char:"\u{1f94b}",fitzpatrick_scale:!1,category:"activity"},rowing_woman:{keywords:["sports","hobby","water","ship","woman","female"],char:"\u{1f6a3}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},rowing_man:{keywords:["sports","hobby","water","ship"],char:"\u{1f6a3}",fitzpatrick_scale:!0,category:"activity"},climbing_woman:{keywords:["sports","hobby","woman","female","rock"],char:"\u{1f9d7}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},climbing_man:{keywords:["sports","hobby","man","male","rock"],char:"\u{1f9d7}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},swimming_woman:{keywords:["sports","exercise","human","athlete","water","summer","woman","female"],char:"\u{1f3ca}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},swimming_man:{keywords:["sports","exercise","human","athlete","water","summer"],char:"\u{1f3ca}",fitzpatrick_scale:!0,category:"activity"},woman_playing_water_polo:{keywords:["sports","pool"],char:"\u{1f93d}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_playing_water_polo:{keywords:["sports","pool"],char:"\u{1f93d}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},woman_in_lotus_position:{keywords:["woman","female","meditation","yoga","serenity","zen","mindfulness"],char:"\u{1f9d8}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_in_lotus_position:{keywords:["man","male","meditation","yoga","serenity","zen","mindfulness"],char:"\u{1f9d8}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},surfing_woman:{keywords:["sports","ocean","sea","summer","beach","woman","female"],char:"\u{1f3c4}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},surfing_man:{keywords:["sports","ocean","sea","summer","beach"],char:"\u{1f3c4}",fitzpatrick_scale:!0,category:"activity"},bath:{keywords:["clean","shower","bathroom"],char:"\u{1f6c0}",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:"\u{1f3cb}\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},weight_lifting_man:{keywords:["sports","training","exercise"],char:"\u{1f3cb}",fitzpatrick_scale:!0,category:"activity"},biking_woman:{keywords:["sports","bike","exercise","hipster","woman","female"],char:"\u{1f6b4}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},biking_man:{keywords:["sports","bike","exercise","hipster"],char:"\u{1f6b4}",fitzpatrick_scale:!0,category:"activity"},mountain_biking_woman:{keywords:["transportation","sports","human","race","bike","woman","female"],char:"\u{1f6b5}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},mountain_biking_man:{keywords:["transportation","sports","human","race","bike"],char:"\u{1f6b5}",fitzpatrick_scale:!0,category:"activity"},horse_racing:{keywords:["animal","betting","competition","gambling","luck"],char:"\u{1f3c7}",fitzpatrick_scale:!0,category:"activity"},business_suit_levitating:{keywords:["suit","business","levitate","hover","jump"],char:"\u{1f574}",fitzpatrick_scale:!0,category:"activity"},trophy:{keywords:["win","award","contest","place","ftw","ceremony"],char:"\u{1f3c6}",fitzpatrick_scale:!1,category:"activity"},running_shirt_with_sash:{keywords:["play","pageant"],char:"\u{1f3bd}",fitzpatrick_scale:!1,category:"activity"},medal_sports:{keywords:["award","winning"],char:"\u{1f3c5}",fitzpatrick_scale:!1,category:"activity"},medal_military:{keywords:["award","winning","army"],char:"\u{1f396}",fitzpatrick_scale:!1,category:"activity"},"1st_place_medal":{keywords:["award","winning","first"],char:"\u{1f947}",fitzpatrick_scale:!1,category:"activity"},"2nd_place_medal":{keywords:["award","second"],char:"\u{1f948}",fitzpatrick_scale:!1,category:"activity"},"3rd_place_medal":{keywords:["award","third"],char:"\u{1f949}",fitzpatrick_scale:!1,category:"activity"},reminder_ribbon:{keywords:["sports","cause","support","awareness"],char:"\u{1f397}",fitzpatrick_scale:!1,category:"activity"},rosette:{keywords:["flower","decoration","military"],char:"\u{1f3f5}",fitzpatrick_scale:!1,category:"activity"},ticket:{keywords:["event","concert","pass"],char:"\u{1f3ab}",fitzpatrick_scale:!1,category:"activity"},tickets:{keywords:["sports","concert","entrance"],char:"\u{1f39f}",fitzpatrick_scale:!1,category:"activity"},performing_arts:{keywords:["acting","theater","drama"],char:"\u{1f3ad}",fitzpatrick_scale:!1,category:"activity"},art:{keywords:["design","paint","draw","colors"],char:"\u{1f3a8}",fitzpatrick_scale:!1,category:"activity"},circus_tent:{keywords:["festival","carnival","party"],char:"\u{1f3aa}",fitzpatrick_scale:!1,category:"activity"},woman_juggling:{keywords:["juggle","balance","skill","multitask"],char:"\u{1f939}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_juggling:{keywords:["juggle","balance","skill","multitask"],char:"\u{1f939}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},microphone:{keywords:["sound","music","PA","sing","talkshow"],char:"\u{1f3a4}",fitzpatrick_scale:!1,category:"activity"},headphones:{keywords:["music","score","gadgets"],char:"\u{1f3a7}",fitzpatrick_scale:!1,category:"activity"},musical_score:{keywords:["treble","clef","compose"],char:"\u{1f3bc}",fitzpatrick_scale:!1,category:"activity"},musical_keyboard:{keywords:["piano","instrument","compose"],char:"\u{1f3b9}",fitzpatrick_scale:!1,category:"activity"},drum:{keywords:["music","instrument","drumsticks","snare"],char:"\u{1f941}",fitzpatrick_scale:!1,category:"activity"},saxophone:{keywords:["music","instrument","jazz","blues"],char:"\u{1f3b7}",fitzpatrick_scale:!1,category:"activity"},trumpet:{keywords:["music","brass"],char:"\u{1f3ba}",fitzpatrick_scale:!1,category:"activity"},guitar:{keywords:["music","instrument"],char:"\u{1f3b8}",fitzpatrick_scale:!1,category:"activity"},violin:{keywords:["music","instrument","orchestra","symphony"],char:"\u{1f3bb}",fitzpatrick_scale:!1,category:"activity"},clapper:{keywords:["movie","film","record"],char:"\u{1f3ac}",fitzpatrick_scale:!1,category:"activity"},video_game:{keywords:["play","console","PS4","controller"],char:"\u{1f3ae}",fitzpatrick_scale:!1,category:"activity"},space_invader:{keywords:["game","arcade","play"],char:"\u{1f47e}",fitzpatrick_scale:!1,category:"activity"},dart:{keywords:["game","play","bar","target","bullseye"],char:"\u{1f3af}",fitzpatrick_scale:!1,category:"activity"},game_die:{keywords:["dice","random","tabletop","play","luck"],char:"\u{1f3b2}",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:"\u{1f3b0}",fitzpatrick_scale:!1,category:"activity"},jigsaw:{keywords:["interlocking","puzzle","piece"],char:"\u{1f9e9}",fitzpatrick_scale:!1,category:"activity"},bowling:{keywords:["sports","fun","play"],char:"\u{1f3b3}",fitzpatrick_scale:!1,category:"activity"},red_car:{keywords:["red","transportation","vehicle"],char:"\u{1f697}",fitzpatrick_scale:!1,category:"travel_and_places"},taxi:{keywords:["uber","vehicle","cars","transportation"],char:"\u{1f695}",fitzpatrick_scale:!1,category:"travel_and_places"},blue_car:{keywords:["transportation","vehicle"],char:"\u{1f699}",fitzpatrick_scale:!1,category:"travel_and_places"},bus:{keywords:["car","vehicle","transportation"],char:"\u{1f68c}",fitzpatrick_scale:!1,category:"travel_and_places"},trolleybus:{keywords:["bart","transportation","vehicle"],char:"\u{1f68e}",fitzpatrick_scale:!1,category:"travel_and_places"},racing_car:{keywords:["sports","race","fast","formula","f1"],char:"\u{1f3ce}",fitzpatrick_scale:!1,category:"travel_and_places"},police_car:{keywords:["vehicle","cars","transportation","law","legal","enforcement"],char:"\u{1f693}",fitzpatrick_scale:!1,category:"travel_and_places"},ambulance:{keywords:["health","911","hospital"],char:"\u{1f691}",fitzpatrick_scale:!1,category:"travel_and_places"},fire_engine:{keywords:["transportation","cars","vehicle"],char:"\u{1f692}",fitzpatrick_scale:!1,category:"travel_and_places"},minibus:{keywords:["vehicle","car","transportation"],char:"\u{1f690}",fitzpatrick_scale:!1,category:"travel_and_places"},truck:{keywords:["cars","transportation"],char:"\u{1f69a}",fitzpatrick_scale:!1,category:"travel_and_places"},articulated_lorry:{keywords:["vehicle","cars","transportation","express"],char:"\u{1f69b}",fitzpatrick_scale:!1,category:"travel_and_places"},tractor:{keywords:["vehicle","car","farming","agriculture"],char:"\u{1f69c}",fitzpatrick_scale:!1,category:"travel_and_places"},kick_scooter:{keywords:["vehicle","kick","razor"],char:"\u{1f6f4}",fitzpatrick_scale:!1,category:"travel_and_places"},motorcycle:{keywords:["race","sports","fast"],char:"\u{1f3cd}",fitzpatrick_scale:!1,category:"travel_and_places"},bike:{keywords:["sports","bicycle","exercise","hipster"],char:"\u{1f6b2}",fitzpatrick_scale:!1,category:"travel_and_places"},motor_scooter:{keywords:["vehicle","vespa","sasha"],char:"\u{1f6f5}",fitzpatrick_scale:!1,category:"travel_and_places"},rotating_light:{keywords:["police","ambulance","911","emergency","alert","error","pinged","law","legal"],char:"\u{1f6a8}",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_police_car:{keywords:["vehicle","law","legal","enforcement","911"],char:"\u{1f694}",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_bus:{keywords:["vehicle","transportation"],char:"\u{1f68d}",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_automobile:{keywords:["car","vehicle","transportation"],char:"\u{1f698}",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_taxi:{keywords:["vehicle","cars","uber"],char:"\u{1f696}",fitzpatrick_scale:!1,category:"travel_and_places"},aerial_tramway:{keywords:["transportation","vehicle","ski"],char:"\u{1f6a1}",fitzpatrick_scale:!1,category:"travel_and_places"},mountain_cableway:{keywords:["transportation","vehicle","ski"],char:"\u{1f6a0}",fitzpatrick_scale:!1,category:"travel_and_places"},suspension_railway:{keywords:["vehicle","transportation"],char:"\u{1f69f}",fitzpatrick_scale:!1,category:"travel_and_places"},railway_car:{keywords:["transportation","vehicle"],char:"\u{1f683}",fitzpatrick_scale:!1,category:"travel_and_places"},train:{keywords:["transportation","vehicle","carriage","public","travel"],char:"\u{1f68b}",fitzpatrick_scale:!1,category:"travel_and_places"},monorail:{keywords:["transportation","vehicle"],char:"\u{1f69d}",fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_side:{keywords:["transportation","vehicle"],char:"\u{1f684}",fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_front:{keywords:["transportation","vehicle","speed","fast","public","travel"],char:"\u{1f685}",fitzpatrick_scale:!1,category:"travel_and_places"},light_rail:{keywords:["transportation","vehicle"],char:"\u{1f688}",fitzpatrick_scale:!1,category:"travel_and_places"},mountain_railway:{keywords:["transportation","vehicle"],char:"\u{1f69e}",fitzpatrick_scale:!1,category:"travel_and_places"},steam_locomotive:{keywords:["transportation","vehicle","train"],char:"\u{1f682}",fitzpatrick_scale:!1,category:"travel_and_places"},train2:{keywords:["transportation","vehicle"],char:"\u{1f686}",fitzpatrick_scale:!1,category:"travel_and_places"},metro:{keywords:["transportation","blue-square","mrt","underground","tube"],char:"\u{1f687}",fitzpatrick_scale:!1,category:"travel_and_places"},tram:{keywords:["transportation","vehicle"],char:"\u{1f68a}",fitzpatrick_scale:!1,category:"travel_and_places"},station:{keywords:["transportation","vehicle","public"],char:"\u{1f689}",fitzpatrick_scale:!1,category:"travel_and_places"},flying_saucer:{keywords:["transportation","vehicle","ufo"],char:"\u{1f6f8}",fitzpatrick_scale:!1,category:"travel_and_places"},helicopter:{keywords:["transportation","vehicle","fly"],char:"\u{1f681}",fitzpatrick_scale:!1,category:"travel_and_places"},small_airplane:{keywords:["flight","transportation","fly","vehicle"],char:"\u{1f6e9}",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:"\u{1f6eb}",fitzpatrick_scale:!1,category:"travel_and_places"},flight_arrival:{keywords:["airport","flight","boarding"],char:"\u{1f6ec}",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:"\u{1f6e5}",fitzpatrick_scale:!1,category:"travel_and_places"},speedboat:{keywords:["ship","transportation","vehicle","summer"],char:"\u{1f6a4}",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:"\u{1f6f3}",fitzpatrick_scale:!1,category:"travel_and_places"},rocket:{keywords:["launch","ship","staffmode","NASA","outer space","outer_space","fly"],char:"\u{1f680}",fitzpatrick_scale:!1,category:"travel_and_places"},artificial_satellite:{keywords:["communication","gps","orbit","spaceflight","NASA","ISS"],char:"\u{1f6f0}",fitzpatrick_scale:!1,category:"travel_and_places"},seat:{keywords:["sit","airplane","transport","bus","flight","fly"],char:"\u{1f4ba}",fitzpatrick_scale:!1,category:"travel_and_places"},canoe:{keywords:["boat","paddle","water","ship"],char:"\u{1f6f6}",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:"\u{1f6a7}",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:"\u{1f68f}",fitzpatrick_scale:!1,category:"travel_and_places"},vertical_traffic_light:{keywords:["transportation","driving"],char:"\u{1f6a6}",fitzpatrick_scale:!1,category:"travel_and_places"},traffic_light:{keywords:["transportation","signal"],char:"\u{1f6a5}",fitzpatrick_scale:!1,category:"travel_and_places"},checkered_flag:{keywords:["contest","finishline","race","gokart"],char:"\u{1f3c1}",fitzpatrick_scale:!1,category:"travel_and_places"},ship:{keywords:["transportation","titanic","deploy"],char:"\u{1f6a2}",fitzpatrick_scale:!1,category:"travel_and_places"},ferris_wheel:{keywords:["photo","carnival","londoneye"],char:"\u{1f3a1}",fitzpatrick_scale:!1,category:"travel_and_places"},roller_coaster:{keywords:["carnival","playground","photo","fun"],char:"\u{1f3a2}",fitzpatrick_scale:!1,category:"travel_and_places"},carousel_horse:{keywords:["photo","carnival"],char:"\u{1f3a0}",fitzpatrick_scale:!1,category:"travel_and_places"},building_construction:{keywords:["wip","working","progress"],char:"\u{1f3d7}",fitzpatrick_scale:!1,category:"travel_and_places"},foggy:{keywords:["photo","mountain"],char:"\u{1f301}",fitzpatrick_scale:!1,category:"travel_and_places"},tokyo_tower:{keywords:["photo","japanese"],char:"\u{1f5fc}",fitzpatrick_scale:!1,category:"travel_and_places"},factory:{keywords:["building","industry","pollution","smoke"],char:"\u{1f3ed}",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:"\u{1f391}",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:"\u{1f3d4}",fitzpatrick_scale:!1,category:"travel_and_places"},mount_fuji:{keywords:["photo","mountain","nature","japanese"],char:"\u{1f5fb}",fitzpatrick_scale:!1,category:"travel_and_places"},volcano:{keywords:["photo","nature","disaster"],char:"\u{1f30b}",fitzpatrick_scale:!1,category:"travel_and_places"},japan:{keywords:["nation","country","japanese","asia"],char:"\u{1f5fe}",fitzpatrick_scale:!1,category:"travel_and_places"},camping:{keywords:["photo","outdoors","tent"],char:"\u{1f3d5}",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:"\u{1f3de}",fitzpatrick_scale:!1,category:"travel_and_places"},motorway:{keywords:["road","cupertino","interstate","highway"],char:"\u{1f6e3}",fitzpatrick_scale:!1,category:"travel_and_places"},railway_track:{keywords:["train","transportation"],char:"\u{1f6e4}",fitzpatrick_scale:!1,category:"travel_and_places"},sunrise:{keywords:["morning","view","vacation","photo"],char:"\u{1f305}",fitzpatrick_scale:!1,category:"travel_and_places"},sunrise_over_mountains:{keywords:["view","vacation","photo"],char:"\u{1f304}",fitzpatrick_scale:!1,category:"travel_and_places"},desert:{keywords:["photo","warm","saharah"],char:"\u{1f3dc}",fitzpatrick_scale:!1,category:"travel_and_places"},beach_umbrella:{keywords:["weather","summer","sunny","sand","mojito"],char:"\u{1f3d6}",fitzpatrick_scale:!1,category:"travel_and_places"},desert_island:{keywords:["photo","tropical","mojito"],char:"\u{1f3dd}",fitzpatrick_scale:!1,category:"travel_and_places"},city_sunrise:{keywords:["photo","good morning","dawn"],char:"\u{1f307}",fitzpatrick_scale:!1,category:"travel_and_places"},city_sunset:{keywords:["photo","evening","sky","buildings"],char:"\u{1f306}",fitzpatrick_scale:!1,category:"travel_and_places"},cityscape:{keywords:["photo","night life","urban"],char:"\u{1f3d9}",fitzpatrick_scale:!1,category:"travel_and_places"},night_with_stars:{keywords:["evening","city","downtown"],char:"\u{1f303}",fitzpatrick_scale:!1,category:"travel_and_places"},bridge_at_night:{keywords:["photo","sanfrancisco"],char:"\u{1f309}",fitzpatrick_scale:!1,category:"travel_and_places"},milky_way:{keywords:["photo","space","stars"],char:"\u{1f30c}",fitzpatrick_scale:!1,category:"travel_and_places"},stars:{keywords:["night","photo"],char:"\u{1f320}",fitzpatrick_scale:!1,category:"travel_and_places"},sparkler:{keywords:["stars","night","shine"],char:"\u{1f387}",fitzpatrick_scale:!1,category:"travel_and_places"},fireworks:{keywords:["photo","festival","carnival","congratulations"],char:"\u{1f386}",fitzpatrick_scale:!1,category:"travel_and_places"},rainbow:{keywords:["nature","happy","unicorn_face","photo","sky","spring"],char:"\u{1f308}",fitzpatrick_scale:!1,category:"travel_and_places"},houses:{keywords:["buildings","photo"],char:"\u{1f3d8}",fitzpatrick_scale:!1,category:"travel_and_places"},european_castle:{keywords:["building","royalty","history"],char:"\u{1f3f0}",fitzpatrick_scale:!1,category:"travel_and_places"},japanese_castle:{keywords:["photo","building"],char:"\u{1f3ef}",fitzpatrick_scale:!1,category:"travel_and_places"},stadium:{keywords:["photo","place","sports","concert","venue"],char:"\u{1f3df}",fitzpatrick_scale:!1,category:"travel_and_places"},statue_of_liberty:{keywords:["american","newyork"],char:"\u{1f5fd}",fitzpatrick_scale:!1,category:"travel_and_places"},house:{keywords:["building","home"],char:"\u{1f3e0}",fitzpatrick_scale:!1,category:"travel_and_places"},house_with_garden:{keywords:["home","plant","nature"],char:"\u{1f3e1}",fitzpatrick_scale:!1,category:"travel_and_places"},derelict_house:{keywords:["abandon","evict","broken","building"],char:"\u{1f3da}",fitzpatrick_scale:!1,category:"travel_and_places"},office:{keywords:["building","bureau","work"],char:"\u{1f3e2}",fitzpatrick_scale:!1,category:"travel_and_places"},department_store:{keywords:["building","shopping","mall"],char:"\u{1f3ec}",fitzpatrick_scale:!1,category:"travel_and_places"},post_office:{keywords:["building","envelope","communication"],char:"\u{1f3e3}",fitzpatrick_scale:!1,category:"travel_and_places"},european_post_office:{keywords:["building","email"],char:"\u{1f3e4}",fitzpatrick_scale:!1,category:"travel_and_places"},hospital:{keywords:["building","health","surgery","doctor"],char:"\u{1f3e5}",fitzpatrick_scale:!1,category:"travel_and_places"},bank:{keywords:["building","money","sales","cash","business","enterprise"],char:"\u{1f3e6}",fitzpatrick_scale:!1,category:"travel_and_places"},hotel:{keywords:["building","accomodation","checkin"],char:"\u{1f3e8}",fitzpatrick_scale:!1,category:"travel_and_places"},convenience_store:{keywords:["building","shopping","groceries"],char:"\u{1f3ea}",fitzpatrick_scale:!1,category:"travel_and_places"},school:{keywords:["building","student","education","learn","teach"],char:"\u{1f3eb}",fitzpatrick_scale:!1,category:"travel_and_places"},love_hotel:{keywords:["like","affection","dating"],char:"\u{1f3e9}",fitzpatrick_scale:!1,category:"travel_and_places"},wedding:{keywords:["love","like","affection","couple","marriage","bride","groom"],char:"\u{1f492}",fitzpatrick_scale:!1,category:"travel_and_places"},classical_building:{keywords:["art","culture","history"],char:"\u{1f3db}",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:"\u{1f54c}",fitzpatrick_scale:!1,category:"travel_and_places"},synagogue:{keywords:["judaism","worship","temple","jewish"],char:"\u{1f54d}",fitzpatrick_scale:!1,category:"travel_and_places"},kaaba:{keywords:["mecca","mosque","islam"],char:"\u{1f54b}",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:"\u{1f4f1}",fitzpatrick_scale:!1,category:"objects"},calling:{keywords:["iphone","incoming"],char:"\u{1f4f2}",fitzpatrick_scale:!1,category:"objects"},computer:{keywords:["technology","laptop","screen","display","monitor"],char:"\u{1f4bb}",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:"\u{1f5a5}",fitzpatrick_scale:!1,category:"objects"},printer:{keywords:["paper","ink"],char:"\u{1f5a8}",fitzpatrick_scale:!1,category:"objects"},computer_mouse:{keywords:["click"],char:"\u{1f5b1}",fitzpatrick_scale:!1,category:"objects"},trackball:{keywords:["technology","trackpad"],char:"\u{1f5b2}",fitzpatrick_scale:!1,category:"objects"},joystick:{keywords:["game","play"],char:"\u{1f579}",fitzpatrick_scale:!1,category:"objects"},clamp:{keywords:["tool"],char:"\u{1f5dc}",fitzpatrick_scale:!1,category:"objects"},minidisc:{keywords:["technology","record","data","disk","90s"],char:"\u{1f4bd}",fitzpatrick_scale:!1,category:"objects"},floppy_disk:{keywords:["oldschool","technology","save","90s","80s"],char:"\u{1f4be}",fitzpatrick_scale:!1,category:"objects"},cd:{keywords:["technology","dvd","disk","disc","90s"],char:"\u{1f4bf}",fitzpatrick_scale:!1,category:"objects"},dvd:{keywords:["cd","disk","disc"],char:"\u{1f4c0}",fitzpatrick_scale:!1,category:"objects"},vhs:{keywords:["record","video","oldschool","90s","80s"],char:"\u{1f4fc}",fitzpatrick_scale:!1,category:"objects"},camera:{keywords:["gadgets","photography"],char:"\u{1f4f7}",fitzpatrick_scale:!1,category:"objects"},camera_flash:{keywords:["photography","gadgets"],char:"\u{1f4f8}",fitzpatrick_scale:!1,category:"objects"},video_camera:{keywords:["film","record"],char:"\u{1f4f9}",fitzpatrick_scale:!1,category:"objects"},movie_camera:{keywords:["film","record"],char:"\u{1f3a5}",fitzpatrick_scale:!1,category:"objects"},film_projector:{keywords:["video","tape","record","movie"],char:"\u{1f4fd}",fitzpatrick_scale:!1,category:"objects"},film_strip:{keywords:["movie"],char:"\u{1f39e}",fitzpatrick_scale:!1,category:"objects"},telephone_receiver:{keywords:["technology","communication","dial"],char:"\u{1f4de}",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:"\u{1f4df}",fitzpatrick_scale:!1,category:"objects"},fax:{keywords:["communication","technology"],char:"\u{1f4e0}",fitzpatrick_scale:!1,category:"objects"},tv:{keywords:["technology","program","oldschool","show","television"],char:"\u{1f4fa}",fitzpatrick_scale:!1,category:"objects"},radio:{keywords:["communication","music","podcast","program"],char:"\u{1f4fb}",fitzpatrick_scale:!1,category:"objects"},studio_microphone:{keywords:["sing","recording","artist","talkshow"],char:"\u{1f399}",fitzpatrick_scale:!1,category:"objects"},level_slider:{keywords:["scale"],char:"\u{1f39a}",fitzpatrick_scale:!1,category:"objects"},control_knobs:{keywords:["dial"],char:"\u{1f39b}",fitzpatrick_scale:!1,category:"objects"},compass:{keywords:["magnetic","navigation","orienteering"],char:"\u{1f9ed}",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:"\u{1f570}",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:"\u{1f4e1}",fitzpatrick_scale:!1,category:"objects"},battery:{keywords:["power","energy","sustain"],char:"\u{1f50b}",fitzpatrick_scale:!1,category:"objects"},electric_plug:{keywords:["charger","power"],char:"\u{1f50c}",fitzpatrick_scale:!1,category:"objects"},bulb:{keywords:["light","electricity","idea"],char:"\u{1f4a1}",fitzpatrick_scale:!1,category:"objects"},flashlight:{keywords:["dark","camping","sight","night"],char:"\u{1f526}",fitzpatrick_scale:!1,category:"objects"},candle:{keywords:["fire","wax"],char:"\u{1f56f}",fitzpatrick_scale:!1,category:"objects"},fire_extinguisher:{keywords:["quench"],char:"\u{1f9ef}",fitzpatrick_scale:!1,category:"objects"},wastebasket:{keywords:["bin","trash","rubbish","garbage","toss"],char:"\u{1f5d1}",fitzpatrick_scale:!1,category:"objects"},oil_drum:{keywords:["barrell"],char:"\u{1f6e2}",fitzpatrick_scale:!1,category:"objects"},money_with_wings:{keywords:["dollar","bills","payment","sale"],char:"\u{1f4b8}",fitzpatrick_scale:!1,category:"objects"},dollar:{keywords:["money","sales","bill","currency"],char:"\u{1f4b5}",fitzpatrick_scale:!1,category:"objects"},yen:{keywords:["money","sales","japanese","dollar","currency"],char:"\u{1f4b4}",fitzpatrick_scale:!1,category:"objects"},euro:{keywords:["money","sales","dollar","currency"],char:"\u{1f4b6}",fitzpatrick_scale:!1,category:"objects"},pound:{keywords:["british","sterling","money","sales","bills","uk","england","currency"],char:"\u{1f4b7}",fitzpatrick_scale:!1,category:"objects"},moneybag:{keywords:["dollar","payment","coins","sale"],char:"\u{1f4b0}",fitzpatrick_scale:!1,category:"objects"},credit_card:{keywords:["money","sales","dollar","bill","payment","shopping"],char:"\u{1f4b3}",fitzpatrick_scale:!1,category:"objects"},gem:{keywords:["blue","ruby","diamond","jewelry"],char:"\u{1f48e}",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:"\u{1f9f0}",fitzpatrick_scale:!1,category:"objects"},wrench:{keywords:["tools","diy","ikea","fix","maintainer"],char:"\u{1f527}",fitzpatrick_scale:!1,category:"objects"},hammer:{keywords:["tools","build","create"],char:"\u{1f528}",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:"\u{1f6e0}",fitzpatrick_scale:!1,category:"objects"},pick:{keywords:["tools","dig"],char:"\u26cf",fitzpatrick_scale:!1,category:"objects"},nut_and_bolt:{keywords:["handy","tools","fix"],char:"\u{1f529}",fitzpatrick_scale:!1,category:"objects"},gear:{keywords:["cog"],char:"\u2699",fitzpatrick_scale:!1,category:"objects"},brick:{keywords:["bricks"],char:"\u{1f9f1}",fitzpatrick_scale:!1,category:"objects"},chains:{keywords:["lock","arrest"],char:"\u26d3",fitzpatrick_scale:!1,category:"objects"},magnet:{keywords:["attraction","magnetic"],char:"\u{1f9f2}",fitzpatrick_scale:!1,category:"objects"},gun:{keywords:["violence","weapon","pistol","revolver"],char:"\u{1f52b}",fitzpatrick_scale:!1,category:"objects"},bomb:{keywords:["boom","explode","explosion","terrorism"],char:"\u{1f4a3}",fitzpatrick_scale:!1,category:"objects"},firecracker:{keywords:["dynamite","boom","explode","explosion","explosive"],char:"\u{1f9e8}",fitzpatrick_scale:!1,category:"objects"},hocho:{keywords:["knife","blade","cutlery","kitchen","weapon"],char:"\u{1f52a}",fitzpatrick_scale:!1,category:"objects"},dagger:{keywords:["weapon"],char:"\u{1f5e1}",fitzpatrick_scale:!1,category:"objects"},crossed_swords:{keywords:["weapon"],char:"\u2694",fitzpatrick_scale:!1,category:"objects"},shield:{keywords:["protection","security"],char:"\u{1f6e1}",fitzpatrick_scale:!1,category:"objects"},smoking:{keywords:["kills","tobacco","cigarette","joint","smoke"],char:"\u{1f6ac}",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:"\u{1f3fa}",fitzpatrick_scale:!1,category:"objects"},crystal_ball:{keywords:["disco","party","magic","circus","fortune_teller"],char:"\u{1f52e}",fitzpatrick_scale:!1,category:"objects"},prayer_beads:{keywords:["dhikr","religious"],char:"\u{1f4ff}",fitzpatrick_scale:!1,category:"objects"},nazar_amulet:{keywords:["bead","charm"],char:"\u{1f9ff}",fitzpatrick_scale:!1,category:"objects"},barber:{keywords:["hair","salon","style"],char:"\u{1f488}",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:"\u{1f52d}",fitzpatrick_scale:!1,category:"objects"},microscope:{keywords:["laboratory","experiment","zoomin","science","study"],char:"\u{1f52c}",fitzpatrick_scale:!1,category:"objects"},hole:{keywords:["embarrassing"],char:"\u{1f573}",fitzpatrick_scale:!1,category:"objects"},pill:{keywords:["health","medicine","doctor","pharmacy","drug"],char:"\u{1f48a}",fitzpatrick_scale:!1,category:"objects"},syringe:{keywords:["health","hospital","drugs","blood","medicine","needle","doctor","nurse"],char:"\u{1f489}",fitzpatrick_scale:!1,category:"objects"},dna:{keywords:["biologist","genetics","life"],char:"\u{1f9ec}",fitzpatrick_scale:!1,category:"objects"},microbe:{keywords:["amoeba","bacteria","germs"],char:"\u{1f9a0}",fitzpatrick_scale:!1,category:"objects"},petri_dish:{keywords:["bacteria","biology","culture","lab"],char:"\u{1f9eb}",fitzpatrick_scale:!1,category:"objects"},test_tube:{keywords:["chemistry","experiment","lab","science"],char:"\u{1f9ea}",fitzpatrick_scale:!1,category:"objects"},thermometer:{keywords:["weather","temperature","hot","cold"],char:"\u{1f321}",fitzpatrick_scale:!1,category:"objects"},broom:{keywords:["cleaning","sweeping","witch"],char:"\u{1f9f9}",fitzpatrick_scale:!1,category:"objects"},basket:{keywords:["laundry"],char:"\u{1f9fa}",fitzpatrick_scale:!1,category:"objects"},toilet_paper:{keywords:["roll"],char:"\u{1f9fb}",fitzpatrick_scale:!1,category:"objects"},label:{keywords:["sale","tag"],char:"\u{1f3f7}",fitzpatrick_scale:!1,category:"objects"},bookmark:{keywords:["favorite","label","save"],char:"\u{1f516}",fitzpatrick_scale:!1,category:"objects"},toilet:{keywords:["restroom","wc","washroom","bathroom","potty"],char:"\u{1f6bd}",fitzpatrick_scale:!1,category:"objects"},shower:{keywords:["clean","water","bathroom"],char:"\u{1f6bf}",fitzpatrick_scale:!1,category:"objects"},bathtub:{keywords:["clean","shower","bathroom"],char:"\u{1f6c1}",fitzpatrick_scale:!1,category:"objects"},soap:{keywords:["bar","bathing","cleaning","lather"],char:"\u{1f9fc}",fitzpatrick_scale:!1,category:"objects"},sponge:{keywords:["absorbing","cleaning","porous"],char:"\u{1f9fd}",fitzpatrick_scale:!1,category:"objects"},lotion_bottle:{keywords:["moisturizer","sunscreen"],char:"\u{1f9f4}",fitzpatrick_scale:!1,category:"objects"},key:{keywords:["lock","door","password"],char:"\u{1f511}",fitzpatrick_scale:!1,category:"objects"},old_key:{keywords:["lock","door","password"],char:"\u{1f5dd}",fitzpatrick_scale:!1,category:"objects"},couch_and_lamp:{keywords:["read","chill"],char:"\u{1f6cb}",fitzpatrick_scale:!1,category:"objects"},sleeping_bed:{keywords:["bed","rest"],char:"\u{1f6cc}",fitzpatrick_scale:!0,category:"objects"},bed:{keywords:["sleep","rest"],char:"\u{1f6cf}",fitzpatrick_scale:!1,category:"objects"},door:{keywords:["house","entry","exit"],char:"\u{1f6aa}",fitzpatrick_scale:!1,category:"objects"},bellhop_bell:{keywords:["service"],char:"\u{1f6ce}",fitzpatrick_scale:!1,category:"objects"},teddy_bear:{keywords:["plush","stuffed"],char:"\u{1f9f8}",fitzpatrick_scale:!1,category:"objects"},framed_picture:{keywords:["photography"],char:"\u{1f5bc}",fitzpatrick_scale:!1,category:"objects"},world_map:{keywords:["location","direction"],char:"\u{1f5fa}",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:"\u{1f5ff}",fitzpatrick_scale:!1,category:"objects"},shopping:{keywords:["mall","buy","purchase"],char:"\u{1f6cd}",fitzpatrick_scale:!1,category:"objects"},shopping_cart:{keywords:["trolley"],char:"\u{1f6d2}",fitzpatrick_scale:!1,category:"objects"},balloon:{keywords:["party","celebration","birthday","circus"],char:"\u{1f388}",fitzpatrick_scale:!1,category:"objects"},flags:{keywords:["fish","japanese","koinobori","carp","banner"],char:"\u{1f38f}",fitzpatrick_scale:!1,category:"objects"},ribbon:{keywords:["decoration","pink","girl","bowtie"],char:"\u{1f380}",fitzpatrick_scale:!1,category:"objects"},gift:{keywords:["present","birthday","christmas","xmas"],char:"\u{1f381}",fitzpatrick_scale:!1,category:"objects"},confetti_ball:{keywords:["festival","party","birthday","circus"],char:"\u{1f38a}",fitzpatrick_scale:!1,category:"objects"},tada:{keywords:["party","congratulations","birthday","magic","circus","celebration"],char:"\u{1f389}",fitzpatrick_scale:!1,category:"objects"},dolls:{keywords:["japanese","toy","kimono"],char:"\u{1f38e}",fitzpatrick_scale:!1,category:"objects"},wind_chime:{keywords:["nature","ding","spring","bell"],char:"\u{1f390}",fitzpatrick_scale:!1,category:"objects"},crossed_flags:{keywords:["japanese","nation","country","border"],char:"\u{1f38c}",fitzpatrick_scale:!1,category:"objects"},izakaya_lantern:{keywords:["light","paper","halloween","spooky"],char:"\u{1f3ee}",fitzpatrick_scale:!1,category:"objects"},red_envelope:{keywords:["gift"],char:"\u{1f9e7}",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:"\u{1f4e9}",fitzpatrick_scale:!1,category:"objects"},incoming_envelope:{keywords:["email","inbox"],char:"\u{1f4e8}",fitzpatrick_scale:!1,category:"objects"},"e-mail":{keywords:["communication","inbox"],char:"\u{1f4e7}",fitzpatrick_scale:!1,category:"objects"},love_letter:{keywords:["email","like","affection","envelope","valentines"],char:"\u{1f48c}",fitzpatrick_scale:!1,category:"objects"},postbox:{keywords:["email","letter","envelope"],char:"\u{1f4ee}",fitzpatrick_scale:!1,category:"objects"},mailbox_closed:{keywords:["email","communication","inbox"],char:"\u{1f4ea}",fitzpatrick_scale:!1,category:"objects"},mailbox:{keywords:["email","inbox","communication"],char:"\u{1f4eb}",fitzpatrick_scale:!1,category:"objects"},mailbox_with_mail:{keywords:["email","inbox","communication"],char:"\u{1f4ec}",fitzpatrick_scale:!1,category:"objects"},mailbox_with_no_mail:{keywords:["email","inbox"],char:"\u{1f4ed}",fitzpatrick_scale:!1,category:"objects"},package:{keywords:["mail","gift","cardboard","box","moving"],char:"\u{1f4e6}",fitzpatrick_scale:!1,category:"objects"},postal_horn:{keywords:["instrument","music"],char:"\u{1f4ef}",fitzpatrick_scale:!1,category:"objects"},inbox_tray:{keywords:["email","documents"],char:"\u{1f4e5}",fitzpatrick_scale:!1,category:"objects"},outbox_tray:{keywords:["inbox","email"],char:"\u{1f4e4}",fitzpatrick_scale:!1,category:"objects"},scroll:{keywords:["documents","ancient","history","paper"],char:"\u{1f4dc}",fitzpatrick_scale:!1,category:"objects"},page_with_curl:{keywords:["documents","office","paper"],char:"\u{1f4c3}",fitzpatrick_scale:!1,category:"objects"},bookmark_tabs:{keywords:["favorite","save","order","tidy"],char:"\u{1f4d1}",fitzpatrick_scale:!1,category:"objects"},receipt:{keywords:["accounting","expenses"],char:"\u{1f9fe}",fitzpatrick_scale:!1,category:"objects"},bar_chart:{keywords:["graph","presentation","stats"],char:"\u{1f4ca}",fitzpatrick_scale:!1,category:"objects"},chart_with_upwards_trend:{keywords:["graph","presentation","stats","recovery","business","economics","money","sales","good","success"],char:"\u{1f4c8}",fitzpatrick_scale:!1,category:"objects"},chart_with_downwards_trend:{keywords:["graph","presentation","stats","recession","business","economics","money","sales","bad","failure"],char:"\u{1f4c9}",fitzpatrick_scale:!1,category:"objects"},page_facing_up:{keywords:["documents","office","paper","information"],char:"\u{1f4c4}",fitzpatrick_scale:!1,category:"objects"},date:{keywords:["calendar","schedule"],char:"\u{1f4c5}",fitzpatrick_scale:!1,category:"objects"},calendar:{keywords:["schedule","date","planning"],char:"\u{1f4c6}",fitzpatrick_scale:!1,category:"objects"},spiral_calendar:{keywords:["date","schedule","planning"],char:"\u{1f5d3}",fitzpatrick_scale:!1,category:"objects"},card_index:{keywords:["business","stationery"],char:"\u{1f4c7}",fitzpatrick_scale:!1,category:"objects"},card_file_box:{keywords:["business","stationery"],char:"\u{1f5c3}",fitzpatrick_scale:!1,category:"objects"},ballot_box:{keywords:["election","vote"],char:"\u{1f5f3}",fitzpatrick_scale:!1,category:"objects"},file_cabinet:{keywords:["filing","organizing"],char:"\u{1f5c4}",fitzpatrick_scale:!1,category:"objects"},clipboard:{keywords:["stationery","documents"],char:"\u{1f4cb}",fitzpatrick_scale:!1,category:"objects"},spiral_notepad:{keywords:["memo","stationery"],char:"\u{1f5d2}",fitzpatrick_scale:!1,category:"objects"},file_folder:{keywords:["documents","business","office"],char:"\u{1f4c1}",fitzpatrick_scale:!1,category:"objects"},open_file_folder:{keywords:["documents","load"],char:"\u{1f4c2}",fitzpatrick_scale:!1,category:"objects"},card_index_dividers:{keywords:["organizing","business","stationery"],char:"\u{1f5c2}",fitzpatrick_scale:!1,category:"objects"},newspaper_roll:{keywords:["press","headline"],char:"\u{1f5de}",fitzpatrick_scale:!1,category:"objects"},newspaper:{keywords:["press","headline"],char:"\u{1f4f0}",fitzpatrick_scale:!1,category:"objects"},notebook:{keywords:["stationery","record","notes","paper","study"],char:"\u{1f4d3}",fitzpatrick_scale:!1,category:"objects"},closed_book:{keywords:["read","library","knowledge","textbook","learn"],char:"\u{1f4d5}",fitzpatrick_scale:!1,category:"objects"},green_book:{keywords:["read","library","knowledge","study"],char:"\u{1f4d7}",fitzpatrick_scale:!1,category:"objects"},blue_book:{keywords:["read","library","knowledge","learn","study"],char:"\u{1f4d8}",fitzpatrick_scale:!1,category:"objects"},orange_book:{keywords:["read","library","knowledge","textbook","study"],char:"\u{1f4d9}",fitzpatrick_scale:!1,category:"objects"},notebook_with_decorative_cover:{keywords:["classroom","notes","record","paper","study"],char:"\u{1f4d4}",fitzpatrick_scale:!1,category:"objects"},ledger:{keywords:["notes","paper"],char:"\u{1f4d2}",fitzpatrick_scale:!1,category:"objects"},books:{keywords:["literature","library","study"],char:"\u{1f4da}",fitzpatrick_scale:!1,category:"objects"},open_book:{keywords:["book","read","library","knowledge","literature","learn","study"],char:"\u{1f4d6}",fitzpatrick_scale:!1,category:"objects"},safety_pin:{keywords:["diaper"],char:"\u{1f9f7}",fitzpatrick_scale:!1,category:"objects"},link:{keywords:["rings","url"],char:"\u{1f517}",fitzpatrick_scale:!1,category:"objects"},paperclip:{keywords:["documents","stationery"],char:"\u{1f4ce}",fitzpatrick_scale:!1,category:"objects"},paperclips:{keywords:["documents","stationery"],char:"\u{1f587}",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:"\u{1f4d0}",fitzpatrick_scale:!1,category:"objects"},straight_ruler:{keywords:["stationery","calculate","length","math","school","drawing","architect","sketch"],char:"\u{1f4cf}",fitzpatrick_scale:!1,category:"objects"},abacus:{keywords:["calculation"],char:"\u{1f9ee}",fitzpatrick_scale:!1,category:"objects"},pushpin:{keywords:["stationery","mark","here"],char:"\u{1f4cc}",fitzpatrick_scale:!1,category:"objects"},round_pushpin:{keywords:["stationery","location","map","here"],char:"\u{1f4cd}",fitzpatrick_scale:!1,category:"objects"},triangular_flag_on_post:{keywords:["mark","milestone","place"],char:"\u{1f6a9}",fitzpatrick_scale:!1,category:"objects"},white_flag:{keywords:["losing","loser","lost","surrender","give up","fail"],char:"\u{1f3f3}",fitzpatrick_scale:!1,category:"objects"},black_flag:{keywords:["pirate"],char:"\u{1f3f4}",fitzpatrick_scale:!1,category:"objects"},rainbow_flag:{keywords:["flag","rainbow","pride","gay","lgbt","glbt","queer","homosexual","lesbian","bisexual","transgender"],char:"\u{1f3f3}\ufe0f\u200d\u{1f308}",fitzpatrick_scale:!1,category:"objects"},closed_lock_with_key:{keywords:["security","privacy"],char:"\u{1f510}",fitzpatrick_scale:!1,category:"objects"},lock:{keywords:["security","password","padlock"],char:"\u{1f512}",fitzpatrick_scale:!1,category:"objects"},unlock:{keywords:["privacy","security"],char:"\u{1f513}",fitzpatrick_scale:!1,category:"objects"},lock_with_ink_pen:{keywords:["security","secret"],char:"\u{1f50f}",fitzpatrick_scale:!1,category:"objects"},pen:{keywords:["stationery","writing","write"],char:"\u{1f58a}",fitzpatrick_scale:!1,category:"objects"},fountain_pen:{keywords:["stationery","writing","write"],char:"\u{1f58b}",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:"\u{1f4dd}",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:"\u{1f58d}",fitzpatrick_scale:!1,category:"objects"},paintbrush:{keywords:["drawing","creativity","art"],char:"\u{1f58c}",fitzpatrick_scale:!1,category:"objects"},mag:{keywords:["search","zoom","find","detective"],char:"\u{1f50d}",fitzpatrick_scale:!1,category:"objects"},mag_right:{keywords:["search","zoom","find","detective"],char:"\u{1f50e}",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:"\u{1f9e1}",fitzpatrick_scale:!1,category:"symbols"},yellow_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f49b}",fitzpatrick_scale:!1,category:"symbols"},green_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f49a}",fitzpatrick_scale:!1,category:"symbols"},blue_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f499}",fitzpatrick_scale:!1,category:"symbols"},purple_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f49c}",fitzpatrick_scale:!1,category:"symbols"},black_heart:{keywords:["evil"],char:"\u{1f5a4}",fitzpatrick_scale:!1,category:"symbols"},broken_heart:{keywords:["sad","sorry","break","heart","heartbreak"],char:"\u{1f494}",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:"\u{1f495}",fitzpatrick_scale:!1,category:"symbols"},revolving_hearts:{keywords:["love","like","affection","valentines"],char:"\u{1f49e}",fitzpatrick_scale:!1,category:"symbols"},heartbeat:{keywords:["love","like","affection","valentines","pink","heart"],char:"\u{1f493}",fitzpatrick_scale:!1,category:"symbols"},heartpulse:{keywords:["like","love","affection","valentines","pink"],char:"\u{1f497}",fitzpatrick_scale:!1,category:"symbols"},sparkling_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f496}",fitzpatrick_scale:!1,category:"symbols"},cupid:{keywords:["love","like","heart","affection","valentines"],char:"\u{1f498}",fitzpatrick_scale:!1,category:"symbols"},gift_heart:{keywords:["love","valentines"],char:"\u{1f49d}",fitzpatrick_scale:!1,category:"symbols"},heart_decoration:{keywords:["purple-square","love","like"],char:"\u{1f49f}",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:"\u{1f549}",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:"\u{1f52f}",fitzpatrick_scale:!1,category:"symbols"},menorah:{keywords:["hanukkah","candles","jewish"],char:"\u{1f54e}",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:"\u{1f6d0}",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:"\u{1f194}",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:"\u{1f233}",fitzpatrick_scale:!1,category:"symbols"},u5272:{keywords:["cut","divide","chinese","kanji","pink-square"],char:"\u{1f239}",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:"\u{1f4f4}",fitzpatrick_scale:!1,category:"symbols"},vibration_mode:{keywords:["orange-square","phone"],char:"\u{1f4f3}",fitzpatrick_scale:!1,category:"symbols"},u6709:{keywords:["orange-square","chinese","have","kanji"],char:"\u{1f236}",fitzpatrick_scale:!1,category:"symbols"},u7121:{keywords:["nothing","chinese","kanji","japanese","orange-square"],char:"\u{1f21a}",fitzpatrick_scale:!1,category:"symbols"},u7533:{keywords:["chinese","japanese","kanji","orange-square"],char:"\u{1f238}",fitzpatrick_scale:!1,category:"symbols"},u55b6:{keywords:["japanese","opening hours","orange-square"],char:"\u{1f23a}",fitzpatrick_scale:!1,category:"symbols"},u6708:{keywords:["chinese","month","moon","japanese","orange-square","kanji"],char:"\u{1f237}\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:"\u{1f19a}",fitzpatrick_scale:!1,category:"symbols"},accept:{keywords:["ok","good","chinese","kanji","agree","yes","orange-circle"],char:"\u{1f251}",fitzpatrick_scale:!1,category:"symbols"},white_flower:{keywords:["japanese","spring"],char:"\u{1f4ae}",fitzpatrick_scale:!1,category:"symbols"},ideograph_advantage:{keywords:["chinese","kanji","obtain","get","circle"],char:"\u{1f250}",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:"\u{1f234}",fitzpatrick_scale:!1,category:"symbols"},u6e80:{keywords:["full","chinese","japanese","red-square","kanji"],char:"\u{1f235}",fitzpatrick_scale:!1,category:"symbols"},u7981:{keywords:["kanji","japanese","chinese","forbidden","limit","restricted","red-square"],char:"\u{1f232}",fitzpatrick_scale:!1,category:"symbols"},a:{keywords:["red-square","alphabet","letter"],char:"\u{1f170}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},b:{keywords:["red-square","alphabet","letter"],char:"\u{1f171}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},ab:{keywords:["red-square","alphabet"],char:"\u{1f18e}",fitzpatrick_scale:!1,category:"symbols"},cl:{keywords:["alphabet","words","red-square"],char:"\u{1f191}",fitzpatrick_scale:!1,category:"symbols"},o2:{keywords:["alphabet","red-square","letter"],char:"\u{1f17e}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},sos:{keywords:["help","red-square","words","emergency","911"],char:"\u{1f198}",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:"\u{1f4db}",fitzpatrick_scale:!1,category:"symbols"},no_entry_sign:{keywords:["forbid","stop","limit","denied","disallow","circle"],char:"\u{1f6ab}",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:"\u{1f6d1}",fitzpatrick_scale:!1,category:"symbols"},anger:{keywords:["angry","mad"],char:"\u{1f4a2}",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:"\u{1f6b7}",fitzpatrick_scale:!1,category:"symbols"},do_not_litter:{keywords:["trash","bin","garbage","circle"],char:"\u{1f6af}",fitzpatrick_scale:!1,category:"symbols"},no_bicycles:{keywords:["cyclist","prohibited","circle"],char:"\u{1f6b3}",fitzpatrick_scale:!1,category:"symbols"},"non-potable_water":{keywords:["drink","faucet","tap","circle"],char:"\u{1f6b1}",fitzpatrick_scale:!1,category:"symbols"},underage:{keywords:["18","drink","pub","night","minor","circle"],char:"\u{1f51e}",fitzpatrick_scale:!1,category:"symbols"},no_mobile_phones:{keywords:["iphone","mute","circle"],char:"\u{1f4f5}",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:"\u{1f4af}",fitzpatrick_scale:!1,category:"symbols"},low_brightness:{keywords:["sun","afternoon","warm","summer"],char:"\u{1f505}",fitzpatrick_scale:!1,category:"symbols"},high_brightness:{keywords:["sun","light"],char:"\u{1f506}",fitzpatrick_scale:!1,category:"symbols"},trident:{keywords:["weapon","spear"],char:"\u{1f531}",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:"\u{1f6b8}",fitzpatrick_scale:!1,category:"symbols"},beginner:{keywords:["badge","shield"],char:"\u{1f530}",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:"\u{1f22f}",fitzpatrick_scale:!1,category:"symbols"},chart:{keywords:["green-square","graph","presentation","stats"],char:"\u{1f4b9}",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:"\u{1f4a0}",fitzpatrick_scale:!1,category:"symbols"},cyclone:{keywords:["weather","swirl","blue","cloud","vortex","spiral","whirlpool","spin","tornado","hurricane","typhoon"],char:"\u{1f300}",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:"\u{1f310}",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:"\u{1f3e7}",fitzpatrick_scale:!1,category:"symbols"},sa:{keywords:["japanese","blue-square","katakana"],char:"\u{1f202}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},passport_control:{keywords:["custom","blue-square"],char:"\u{1f6c2}",fitzpatrick_scale:!1,category:"symbols"},customs:{keywords:["passport","border","blue-square"],char:"\u{1f6c3}",fitzpatrick_scale:!1,category:"symbols"},baggage_claim:{keywords:["blue-square","airport","transport"],char:"\u{1f6c4}",fitzpatrick_scale:!1,category:"symbols"},left_luggage:{keywords:["blue-square","travel"],char:"\u{1f6c5}",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:"\u{1f6ad}",fitzpatrick_scale:!1,category:"symbols"},wc:{keywords:["toilet","restroom","blue-square"],char:"\u{1f6be}",fitzpatrick_scale:!1,category:"symbols"},parking:{keywords:["cars","blue-square","alphabet","letter"],char:"\u{1f17f}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},potable_water:{keywords:["blue-square","liquid","restroom","cleaning","faucet"],char:"\u{1f6b0}",fitzpatrick_scale:!1,category:"symbols"},mens:{keywords:["toilet","restroom","wc","blue-square","gender","male"],char:"\u{1f6b9}",fitzpatrick_scale:!1,category:"symbols"},womens:{keywords:["purple-square","woman","female","toilet","loo","restroom","gender"],char:"\u{1f6ba}",fitzpatrick_scale:!1,category:"symbols"},baby_symbol:{keywords:["orange-square","child"],char:"\u{1f6bc}",fitzpatrick_scale:!1,category:"symbols"},restroom:{keywords:["blue-square","toilet","refresh","wc","gender"],char:"\u{1f6bb}",fitzpatrick_scale:!1,category:"symbols"},put_litter_in_its_place:{keywords:["blue-square","sign","human","info"],char:"\u{1f6ae}",fitzpatrick_scale:!1,category:"symbols"},cinema:{keywords:["blue-square","record","film","movie","curtain","stage","theater"],char:"\u{1f3a6}",fitzpatrick_scale:!1,category:"symbols"},signal_strength:{keywords:["blue-square","reception","phone","internet","connection","wifi","bluetooth","bars"],char:"\u{1f4f6}",fitzpatrick_scale:!1,category:"symbols"},koko:{keywords:["blue-square","here","katakana","japanese","destination"],char:"\u{1f201}",fitzpatrick_scale:!1,category:"symbols"},ng:{keywords:["blue-square","words","shape","icon"],char:"\u{1f196}",fitzpatrick_scale:!1,category:"symbols"},ok:{keywords:["good","agree","yes","blue-square"],char:"\u{1f197}",fitzpatrick_scale:!1,category:"symbols"},up:{keywords:["blue-square","above","high"],char:"\u{1f199}",fitzpatrick_scale:!1,category:"symbols"},cool:{keywords:["words","blue-square"],char:"\u{1f192}",fitzpatrick_scale:!1,category:"symbols"},new:{keywords:["blue-square","words","start"],char:"\u{1f195}",fitzpatrick_scale:!1,category:"symbols"},free:{keywords:["blue-square","words"],char:"\u{1f193}",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:"\u{1f51f}",fitzpatrick_scale:!1,category:"symbols"},asterisk:{keywords:["star","keycap"],char:"*\u20e3",fitzpatrick_scale:!1,category:"symbols"},1234:{keywords:["numbers","blue-square"],char:"\u{1f522}",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:"\u{1f500}",fitzpatrick_scale:!1,category:"symbols"},repeat:{keywords:["loop","record"],char:"\u{1f501}",fitzpatrick_scale:!1,category:"symbols"},repeat_one:{keywords:["blue-square","loop"],char:"\u{1f502}",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:"\u{1f53c}",fitzpatrick_scale:!1,category:"symbols"},arrow_down_small:{keywords:["blue-square","direction","bottom"],char:"\u{1f53d}",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:"\u{1f504}",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:"\u{1f524}",fitzpatrick_scale:!1,category:"symbols"},abcd:{keywords:["blue-square","alphabet"],char:"\u{1f521}",fitzpatrick_scale:!1,category:"symbols"},capital_abcd:{keywords:["alphabet","words","blue-square"],char:"\u{1f520}",fitzpatrick_scale:!1,category:"symbols"},symbols:{keywords:["blue-square","music","note","ampersand","percent","glyphs","characters"],char:"\u{1f523}",fitzpatrick_scale:!1,category:"symbols"},musical_note:{keywords:["score","tone","sound"],char:"\u{1f3b5}",fitzpatrick_scale:!1,category:"symbols"},notes:{keywords:["music","score"],char:"\u{1f3b6}",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:"\u{1f503}",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:"\u{1f4b2}",fitzpatrick_scale:!1,category:"symbols"},currency_exchange:{keywords:["money","sales","dollar","travel"],char:"\u{1f4b1}",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:"\u{1f51a}",fitzpatrick_scale:!1,category:"symbols"},back:{keywords:["arrow","words","return"],char:"\u{1f519}",fitzpatrick_scale:!1,category:"symbols"},on:{keywords:["arrow","words"],char:"\u{1f51b}",fitzpatrick_scale:!1,category:"symbols"},top:{keywords:["words","blue-square"],char:"\u{1f51d}",fitzpatrick_scale:!1,category:"symbols"},soon:{keywords:["arrow","words"],char:"\u{1f51c}",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:"\u{1f518}",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:"\u{1f534}",fitzpatrick_scale:!1,category:"symbols"},large_blue_circle:{keywords:["shape","icon","button"],char:"\u{1f535}",fitzpatrick_scale:!1,category:"symbols"},small_orange_diamond:{keywords:["shape","jewel","gem"],char:"\u{1f538}",fitzpatrick_scale:!1,category:"symbols"},small_blue_diamond:{keywords:["shape","jewel","gem"],char:"\u{1f539}",fitzpatrick_scale:!1,category:"symbols"},large_orange_diamond:{keywords:["shape","jewel","gem"],char:"\u{1f536}",fitzpatrick_scale:!1,category:"symbols"},large_blue_diamond:{keywords:["shape","jewel","gem"],char:"\u{1f537}",fitzpatrick_scale:!1,category:"symbols"},small_red_triangle:{keywords:["shape","direction","up","top"],char:"\u{1f53a}",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:"\u{1f53b}",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:"\u{1f532}",fitzpatrick_scale:!1,category:"symbols"},white_square_button:{keywords:["shape","input"],char:"\u{1f533}",fitzpatrick_scale:!1,category:"symbols"},speaker:{keywords:["sound","volume","silence","broadcast"],char:"\u{1f508}",fitzpatrick_scale:!1,category:"symbols"},sound:{keywords:["volume","speaker","broadcast"],char:"\u{1f509}",fitzpatrick_scale:!1,category:"symbols"},loud_sound:{keywords:["volume","noise","noisy","speaker","broadcast"],char:"\u{1f50a}",fitzpatrick_scale:!1,category:"symbols"},mute:{keywords:["sound","volume","silence","quiet"],char:"\u{1f507}",fitzpatrick_scale:!1,category:"symbols"},mega:{keywords:["sound","speaker","volume"],char:"\u{1f4e3}",fitzpatrick_scale:!1,category:"symbols"},loudspeaker:{keywords:["volume","sound"],char:"\u{1f4e2}",fitzpatrick_scale:!1,category:"symbols"},bell:{keywords:["sound","notification","christmas","xmas","chime"],char:"\u{1f514}",fitzpatrick_scale:!1,category:"symbols"},no_bell:{keywords:["sound","volume","mute","quiet","silent"],char:"\u{1f515}",fitzpatrick_scale:!1,category:"symbols"},black_joker:{keywords:["poker","cards","game","play","magic"],char:"\u{1f0cf}",fitzpatrick_scale:!1,category:"symbols"},mahjong:{keywords:["game","play","chinese","kanji"],char:"\u{1f004}",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:"\u{1f3b4}",fitzpatrick_scale:!1,category:"symbols"},thought_balloon:{keywords:["bubble","cloud","speech","thinking","dream"],char:"\u{1f4ad}",fitzpatrick_scale:!1,category:"symbols"},right_anger_bubble:{keywords:["caption","speech","thinking","mad"],char:"\u{1f5ef}",fitzpatrick_scale:!1,category:"symbols"},speech_balloon:{keywords:["bubble","words","message","talk","chatting"],char:"\u{1f4ac}",fitzpatrick_scale:!1,category:"symbols"},left_speech_bubble:{keywords:["words","message","talk","chatting"],char:"\u{1f5e8}",fitzpatrick_scale:!1,category:"symbols"},clock1:{keywords:["time","late","early","schedule"],char:"\u{1f550}",fitzpatrick_scale:!1,category:"symbols"},clock2:{keywords:["time","late","early","schedule"],char:"\u{1f551}",fitzpatrick_scale:!1,category:"symbols"},clock3:{keywords:["time","late","early","schedule"],char:"\u{1f552}",fitzpatrick_scale:!1,category:"symbols"},clock4:{keywords:["time","late","early","schedule"],char:"\u{1f553}",fitzpatrick_scale:!1,category:"symbols"},clock5:{keywords:["time","late","early","schedule"],char:"\u{1f554}",fitzpatrick_scale:!1,category:"symbols"},clock6:{keywords:["time","late","early","schedule","dawn","dusk"],char:"\u{1f555}",fitzpatrick_scale:!1,category:"symbols"},clock7:{keywords:["time","late","early","schedule"],char:"\u{1f556}",fitzpatrick_scale:!1,category:"symbols"},clock8:{keywords:["time","late","early","schedule"],char:"\u{1f557}",fitzpatrick_scale:!1,category:"symbols"},clock9:{keywords:["time","late","early","schedule"],char:"\u{1f558}",fitzpatrick_scale:!1,category:"symbols"},clock10:{keywords:["time","late","early","schedule"],char:"\u{1f559}",fitzpatrick_scale:!1,category:"symbols"},clock11:{keywords:["time","late","early","schedule"],char:"\u{1f55a}",fitzpatrick_scale:!1,category:"symbols"},clock12:{keywords:["time","noon","midnight","midday","late","early","schedule"],char:"\u{1f55b}",fitzpatrick_scale:!1,category:"symbols"},clock130:{keywords:["time","late","early","schedule"],char:"\u{1f55c}",fitzpatrick_scale:!1,category:"symbols"},clock230:{keywords:["time","late","early","schedule"],char:"\u{1f55d}",fitzpatrick_scale:!1,category:"symbols"},clock330:{keywords:["time","late","early","schedule"],char:"\u{1f55e}",fitzpatrick_scale:!1,category:"symbols"},clock430:{keywords:["time","late","early","schedule"],char:"\u{1f55f}",fitzpatrick_scale:!1,category:"symbols"},clock530:{keywords:["time","late","early","schedule"],char:"\u{1f560}",fitzpatrick_scale:!1,category:"symbols"},clock630:{keywords:["time","late","early","schedule"],char:"\u{1f561}",fitzpatrick_scale:!1,category:"symbols"},clock730:{keywords:["time","late","early","schedule"],char:"\u{1f562}",fitzpatrick_scale:!1,category:"symbols"},clock830:{keywords:["time","late","early","schedule"],char:"\u{1f563}",fitzpatrick_scale:!1,category:"symbols"},clock930:{keywords:["time","late","early","schedule"],char:"\u{1f564}",fitzpatrick_scale:!1,category:"symbols"},clock1030:{keywords:["time","late","early","schedule"],char:"\u{1f565}",fitzpatrick_scale:!1,category:"symbols"},clock1130:{keywords:["time","late","early","schedule"],char:"\u{1f566}",fitzpatrick_scale:!1,category:"symbols"},clock1230:{keywords:["time","late","early","schedule"],char:"\u{1f567}",fitzpatrick_scale:!1,category:"symbols"},afghanistan:{keywords:["af","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},aland_islands:{keywords:["\xc5land","islands","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1fd}",fitzpatrick_scale:!1,category:"flags"},albania:{keywords:["al","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},algeria:{keywords:["dz","flag","nation","country","banner"],char:"\u{1f1e9}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},american_samoa:{keywords:["american","ws","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},andorra:{keywords:["ad","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},angola:{keywords:["ao","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},anguilla:{keywords:["ai","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},antarctica:{keywords:["aq","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f6}",fitzpatrick_scale:!1,category:"flags"},antigua_barbuda:{keywords:["antigua","barbuda","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},argentina:{keywords:["ar","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},armenia:{keywords:["am","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},aruba:{keywords:["aw","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},australia:{keywords:["au","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},austria:{keywords:["at","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},azerbaijan:{keywords:["az","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},bahamas:{keywords:["bs","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},bahrain:{keywords:["bh","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},bangladesh:{keywords:["bd","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},barbados:{keywords:["bb","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1e7}",fitzpatrick_scale:!1,category:"flags"},belarus:{keywords:["by","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},belgium:{keywords:["be","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},belize:{keywords:["bz","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},benin:{keywords:["bj","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ef}",fitzpatrick_scale:!1,category:"flags"},bermuda:{keywords:["bm","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},bhutan:{keywords:["bt","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},bolivia:{keywords:["bo","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},caribbean_netherlands:{keywords:["bonaire","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f6}",fitzpatrick_scale:!1,category:"flags"},bosnia_herzegovina:{keywords:["bosnia","herzegovina","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},botswana:{keywords:["bw","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},brazil:{keywords:["br","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},british_indian_ocean_territory:{keywords:["british","indian","ocean","territory","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},british_virgin_islands:{keywords:["british","virgin","islands","bvi","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},brunei:{keywords:["bn","darussalam","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},bulgaria:{keywords:["bg","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},burkina_faso:{keywords:["burkina","faso","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},burundi:{keywords:["bi","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},cape_verde:{keywords:["cabo","verde","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1fb}",fitzpatrick_scale:!1,category:"flags"},cambodia:{keywords:["kh","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},cameroon:{keywords:["cm","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},canada:{keywords:["ca","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},canary_islands:{keywords:["canary","islands","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},cayman_islands:{keywords:["cayman","islands","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},central_african_republic:{keywords:["central","african","republic","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},chad:{keywords:["td","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},chile:{keywords:["flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},cn:{keywords:["china","chinese","prc","flag","country","nation","banner"],char:"\u{1f1e8}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},christmas_island:{keywords:["christmas","island","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1fd}",fitzpatrick_scale:!1,category:"flags"},cocos_islands:{keywords:["cocos","keeling","islands","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},colombia:{keywords:["co","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},comoros:{keywords:["km","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},congo_brazzaville:{keywords:["congo","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},congo_kinshasa:{keywords:["congo","democratic","republic","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},cook_islands:{keywords:["cook","islands","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},costa_rica:{keywords:["costa","rica","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},croatia:{keywords:["hr","flag","nation","country","banner"],char:"\u{1f1ed}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},cuba:{keywords:["cu","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},curacao:{keywords:["cura\xe7ao","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},cyprus:{keywords:["cy","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},czech_republic:{keywords:["cz","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},denmark:{keywords:["dk","flag","nation","country","banner"],char:"\u{1f1e9}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},djibouti:{keywords:["dj","flag","nation","country","banner"],char:"\u{1f1e9}\u{1f1ef}",fitzpatrick_scale:!1,category:"flags"},dominica:{keywords:["dm","flag","nation","country","banner"],char:"\u{1f1e9}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},dominican_republic:{keywords:["dominican","republic","flag","nation","country","banner"],char:"\u{1f1e9}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},ecuador:{keywords:["ec","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},egypt:{keywords:["eg","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},el_salvador:{keywords:["el","salvador","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1fb}",fitzpatrick_scale:!1,category:"flags"},equatorial_guinea:{keywords:["equatorial","gn","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f6}",fitzpatrick_scale:!1,category:"flags"},eritrea:{keywords:["er","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},estonia:{keywords:["ee","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},ethiopia:{keywords:["et","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},eu:{keywords:["european","union","flag","banner"],char:"\u{1f1ea}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},falkland_islands:{keywords:["falkland","islands","malvinas","flag","nation","country","banner"],char:"\u{1f1eb}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},faroe_islands:{keywords:["faroe","islands","flag","nation","country","banner"],char:"\u{1f1eb}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},fiji:{keywords:["fj","flag","nation","country","banner"],char:"\u{1f1eb}\u{1f1ef}",fitzpatrick_scale:!1,category:"flags"},finland:{keywords:["fi","flag","nation","country","banner"],char:"\u{1f1eb}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},fr:{keywords:["banner","flag","nation","france","french","country"],char:"\u{1f1eb}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},french_guiana:{keywords:["french","guiana","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},french_polynesia:{keywords:["french","polynesia","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},french_southern_territories:{keywords:["french","southern","territories","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},gabon:{keywords:["ga","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},gambia:{keywords:["gm","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},georgia:{keywords:["ge","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},de:{keywords:["german","nation","flag","country","banner"],char:"\u{1f1e9}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},ghana:{keywords:["gh","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},gibraltar:{keywords:["gi","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},greece:{keywords:["gr","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},greenland:{keywords:["gl","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},grenada:{keywords:["gd","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},guadeloupe:{keywords:["gp","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f5}",fitzpatrick_scale:!1,category:"flags"},guam:{keywords:["gu","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},guatemala:{keywords:["gt","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},guernsey:{keywords:["gg","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},guinea:{keywords:["gn","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},guinea_bissau:{keywords:["gw","bissau","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},guyana:{keywords:["gy","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},haiti:{keywords:["ht","flag","nation","country","banner"],char:"\u{1f1ed}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},honduras:{keywords:["hn","flag","nation","country","banner"],char:"\u{1f1ed}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},hong_kong:{keywords:["hong","kong","flag","nation","country","banner"],char:"\u{1f1ed}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},hungary:{keywords:["hu","flag","nation","country","banner"],char:"\u{1f1ed}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},iceland:{keywords:["is","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},india:{keywords:["in","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},indonesia:{keywords:["flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},iran:{keywords:["iran,","islamic","republic","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},iraq:{keywords:["iq","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f6}",fitzpatrick_scale:!1,category:"flags"},ireland:{keywords:["ie","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},isle_of_man:{keywords:["isle","man","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},israel:{keywords:["il","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},it:{keywords:["italy","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},cote_divoire:{keywords:["ivory","coast","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},jamaica:{keywords:["jm","flag","nation","country","banner"],char:"\u{1f1ef}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},jp:{keywords:["japanese","nation","flag","country","banner"],char:"\u{1f1ef}\u{1f1f5}",fitzpatrick_scale:!1,category:"flags"},jersey:{keywords:["je","flag","nation","country","banner"],char:"\u{1f1ef}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},jordan:{keywords:["jo","flag","nation","country","banner"],char:"\u{1f1ef}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},kazakhstan:{keywords:["kz","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},kenya:{keywords:["ke","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},kiribati:{keywords:["ki","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},kosovo:{keywords:["xk","flag","nation","country","banner"],char:"\u{1f1fd}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},kuwait:{keywords:["kw","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},kyrgyzstan:{keywords:["kg","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},laos:{keywords:["lao","democratic","republic","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},latvia:{keywords:["lv","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1fb}",fitzpatrick_scale:!1,category:"flags"},lebanon:{keywords:["lb","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1e7}",fitzpatrick_scale:!1,category:"flags"},lesotho:{keywords:["ls","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},liberia:{keywords:["lr","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},libya:{keywords:["ly","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},liechtenstein:{keywords:["li","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},lithuania:{keywords:["lt","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},luxembourg:{keywords:["lu","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},macau:{keywords:["macao","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},macedonia:{keywords:["macedonia,","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},madagascar:{keywords:["mg","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},malawi:{keywords:["mw","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},malaysia:{keywords:["my","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},maldives:{keywords:["mv","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1fb}",fitzpatrick_scale:!1,category:"flags"},mali:{keywords:["ml","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},malta:{keywords:["mt","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},marshall_islands:{keywords:["marshall","islands","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},martinique:{keywords:["mq","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f6}",fitzpatrick_scale:!1,category:"flags"},mauritania:{keywords:["mr","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},mauritius:{keywords:["mu","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},mayotte:{keywords:["yt","flag","nation","country","banner"],char:"\u{1f1fe}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},mexico:{keywords:["mx","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1fd}",fitzpatrick_scale:!1,category:"flags"},micronesia:{keywords:["micronesia,","federated","states","flag","nation","country","banner"],char:"\u{1f1eb}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},moldova:{keywords:["moldova,","republic","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},monaco:{keywords:["mc","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},mongolia:{keywords:["mn","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},montenegro:{keywords:["me","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},montserrat:{keywords:["ms","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},morocco:{keywords:["ma","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},mozambique:{keywords:["mz","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},myanmar:{keywords:["mm","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},namibia:{keywords:["na","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},nauru:{keywords:["nr","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},nepal:{keywords:["np","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1f5}",fitzpatrick_scale:!1,category:"flags"},netherlands:{keywords:["nl","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},new_caledonia:{keywords:["new","caledonia","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},new_zealand:{keywords:["new","zealand","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},nicaragua:{keywords:["ni","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},niger:{keywords:["ne","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},nigeria:{keywords:["flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},niue:{keywords:["nu","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},norfolk_island:{keywords:["norfolk","island","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},northern_mariana_islands:{keywords:["northern","mariana","islands","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f5}",fitzpatrick_scale:!1,category:"flags"},north_korea:{keywords:["north","korea","nation","flag","country","banner"],char:"\u{1f1f0}\u{1f1f5}",fitzpatrick_scale:!1,category:"flags"},norway:{keywords:["no","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},oman:{keywords:["om_symbol","flag","nation","country","banner"],char:"\u{1f1f4}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},pakistan:{keywords:["pk","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},palau:{keywords:["pw","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},palestinian_territories:{keywords:["palestine","palestinian","territories","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},panama:{keywords:["pa","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},papua_new_guinea:{keywords:["papua","new","guinea","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},paraguay:{keywords:["py","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},peru:{keywords:["pe","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},philippines:{keywords:["ph","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},pitcairn_islands:{keywords:["pitcairn","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},poland:{keywords:["pl","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},portugal:{keywords:["pt","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},puerto_rico:{keywords:["puerto","rico","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},qatar:{keywords:["qa","flag","nation","country","banner"],char:"\u{1f1f6}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},reunion:{keywords:["r\xe9union","flag","nation","country","banner"],char:"\u{1f1f7}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},romania:{keywords:["ro","flag","nation","country","banner"],char:"\u{1f1f7}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},ru:{keywords:["russian","federation","flag","nation","country","banner"],char:"\u{1f1f7}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},rwanda:{keywords:["rw","flag","nation","country","banner"],char:"\u{1f1f7}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},st_barthelemy:{keywords:["saint","barth\xe9lemy","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},st_helena:{keywords:["saint","helena","ascension","tristan","cunha","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},st_kitts_nevis:{keywords:["saint","kitts","nevis","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},st_lucia:{keywords:["saint","lucia","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},st_pierre_miquelon:{keywords:["saint","pierre","miquelon","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},st_vincent_grenadines:{keywords:["saint","vincent","grenadines","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},samoa:{keywords:["ws","flag","nation","country","banner"],char:"\u{1f1fc}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},san_marino:{keywords:["san","marino","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},sao_tome_principe:{keywords:["sao","tome","principe","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},saudi_arabia:{keywords:["flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},senegal:{keywords:["sn","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},serbia:{keywords:["rs","flag","nation","country","banner"],char:"\u{1f1f7}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},seychelles:{keywords:["sc","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},sierra_leone:{keywords:["sierra","leone","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},singapore:{keywords:["sg","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},sint_maarten:{keywords:["sint","maarten","dutch","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1fd}",fitzpatrick_scale:!1,category:"flags"},slovakia:{keywords:["sk","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},slovenia:{keywords:["si","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},solomon_islands:{keywords:["solomon","islands","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1e7}",fitzpatrick_scale:!1,category:"flags"},somalia:{keywords:["so","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},south_africa:{keywords:["south","africa","flag","nation","country","banner"],char:"\u{1f1ff}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},south_georgia_south_sandwich_islands:{keywords:["south","georgia","sandwich","islands","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},kr:{keywords:["south","korea","nation","flag","country","banner"],char:"\u{1f1f0}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},south_sudan:{keywords:["south","sd","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},es:{keywords:["spain","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},sri_lanka:{keywords:["sri","lanka","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},sudan:{keywords:["sd","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},suriname:{keywords:["sr","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},swaziland:{keywords:["sz","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},sweden:{keywords:["se","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},switzerland:{keywords:["ch","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},syria:{keywords:["syrian","arab","republic","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},taiwan:{keywords:["tw","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},tajikistan:{keywords:["tj","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1ef}",fitzpatrick_scale:!1,category:"flags"},tanzania:{keywords:["tanzania,","united","republic","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},thailand:{keywords:["th","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},timor_leste:{keywords:["timor","leste","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},togo:{keywords:["tg","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},tokelau:{keywords:["tk","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},tonga:{keywords:["to","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},trinidad_tobago:{keywords:["trinidad","tobago","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},tunisia:{keywords:["tn","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},tr:{keywords:["turkey","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},turkmenistan:{keywords:["flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},turks_caicos_islands:{keywords:["turks","caicos","islands","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},tuvalu:{keywords:["flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1fb}",fitzpatrick_scale:!1,category:"flags"},uganda:{keywords:["ug","flag","nation","country","banner"],char:"\u{1f1fa}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},ukraine:{keywords:["ua","flag","nation","country","banner"],char:"\u{1f1fa}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},united_arab_emirates:{keywords:["united","arab","emirates","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},uk:{keywords:["united","kingdom","great","britain","northern","ireland","flag","nation","country","banner","british","UK","english","england","union jack"],char:"\u{1f1ec}\u{1f1e7}",fitzpatrick_scale:!1,category:"flags"},england:{keywords:["flag","english"],char:"\u{1f3f4}\u{e0067}\u{e0062}\u{e0065}\u{e006e}\u{e0067}\u{e007f}",fitzpatrick_scale:!1,category:"flags"},scotland:{keywords:["flag","scottish"],char:"\u{1f3f4}\u{e0067}\u{e0062}\u{e0073}\u{e0063}\u{e0074}\u{e007f}",fitzpatrick_scale:!1,category:"flags"},wales:{keywords:["flag","welsh"],char:"\u{1f3f4}\u{e0067}\u{e0062}\u{e0077}\u{e006c}\u{e0073}\u{e007f}",fitzpatrick_scale:!1,category:"flags"},us:{keywords:["united","states","america","flag","nation","country","banner"],char:"\u{1f1fa}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},us_virgin_islands:{keywords:["virgin","islands","us","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},uruguay:{keywords:["uy","flag","nation","country","banner"],char:"\u{1f1fa}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},uzbekistan:{keywords:["uz","flag","nation","country","banner"],char:"\u{1f1fa}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},vanuatu:{keywords:["vu","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},vatican_city:{keywords:["vatican","city","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},venezuela:{keywords:["ve","bolivarian","republic","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},vietnam:{keywords:["viet","nam","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},wallis_futuna:{keywords:["wallis","futuna","flag","nation","country","banner"],char:"\u{1f1fc}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},western_sahara:{keywords:["western","sahara","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},yemen:{keywords:["ye","flag","nation","country","banner"],char:"\u{1f1fe}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},zambia:{keywords:["zm","flag","nation","country","banner"],char:"\u{1f1ff}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},zimbabwe:{keywords:["zw","flag","nation","country","banner"],char:"\u{1f1ff}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},united_nations:{keywords:["un","flag","banner"],char:"\u{1f1fa}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},pirate_flag:{keywords:["skull","crossbones","flag","banner"],char:"\u{1f3f4}\u200d\u2620\ufe0f",fitzpatrick_scale:!1,category:"flags"}}); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/emoticons/plugin.min.js b/apps/web-antd/public/tinymce/plugins/emoticons/plugin.min.js new file mode 100644 index 0000000..23fa192 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/emoticons/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>e=>t===e,o=e(null),n=e(void 0),s=()=>{},r=()=>!1;class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return null==t?a.none():a.some(t)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const i=(t,e)=>{const o=t.length,n=new Array(o);for(let s=0;s{let e=t;return{get:()=>e,set:t=>{e=t}}},c=Object.keys,u=Object.hasOwnProperty,g=(t,e)=>{const o=c(t);for(let n=0,s=o.length;nu.call(t,e),m=(h=(t,e)=>e,(...t)=>{if(0===t.length)throw new Error("Can't merge zero objects");const e={};for(let o=0;o{const t=(t=>{const e=l(a.none()),o=()=>e.get().each(t);return{clear:()=>{o(),e.set(a.none())},isSet:()=>e.get().isSome(),get:()=>e.get(),set:t=>{o(),e.set(a.some(t))}}})(s);return{...t,on:e=>t.get().each(e)}},y=(t,e,o=0,s)=>{const r=t.indexOf(e,o);return-1!==r&&(!!n(s)||r+e.length<=s)};var v=tinymce.util.Tools.resolve("tinymce.Resource");const f=t=>e=>e.options.get(t),b=f("emoticons_database"),w=f("emoticons_database_url"),j=f("emoticons_database_id"),C=f("emoticons_append"),_=f("emoticons_images_url"),A="All",k={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"},O=(t,e)=>d(t,e)?t[e]:e,x=t=>{const e=C(t);return o=t=>({keywords:[],category:"user",...t}),((t,e)=>{const o={};return g(t,((t,n)=>{const s=e(t,n);o[s.k]=s.v})),o})(e,((t,e)=>({k:e,v:o(t)})));var o},E=(t,e)=>y(t.title.toLowerCase(),e)||(t=>{for(let n=0,s=t.length;n{const n=[],s=e.toLowerCase(),a=o.fold((()=>r),(t=>e=>e>=t));for(let o=0;o{const n={pattern:"",results:L(e.listAll(),"",a.some(300))},s=l(A),r=(t=>{let e=null;const n=()=>{o(e)||(clearTimeout(e),e=null)};return{cancel:n,throttle:(...o)=>{n(),e=setTimeout((()=>{e=null,t.apply(null,o)}),200)}}})((t=>{(t=>{const o=t.getData(),n=s.get(),r=e.listCategory(n),i=L(r,o[S],n===A?a.some(300):a.none());t.setData({results:i})})(t)})),c={label:"Search",type:"input",name:S},u={type:"collection",name:"results"},g=()=>({title:"Emojis",size:"normal",body:{type:"tabpanel",tabs:i(e.listCategories(),(t=>({title:t,name:t,items:[c,u]})))},initialData:n,onTabChange:(t,e)=>{s.set(e.newTabName),r.throttle(t)},onChange:r.throttle,onAction:(e,o)=>{"results"===o.name&&(((t,e)=>{t.insertContent(e)})(t,o.value),e.close())},buttons:[{type:"cancel",text:"Close",primary:!0}]}),d=t.windowManager.open(g());d.focus(S),e.hasLoaded()||(d.block("Loading emojis..."),e.waitForLoad().then((()=>{d.redial(g()),r.throttle(d),d.focus(S),d.unblock()})).catch((t=>{d.redial({title:"Emojis",body:{type:"panel",items:[{type:"alertbanner",level:"error",icon:"warning",text:"Could not load emojis"}]},buttons:[{type:"cancel",text:"Close",primary:!0}],initialData:{pattern:"",results:[]}}),d.focus(S),d.unblock()})))},T=t=>e=>{const o=()=>{e.setEnabled(t.selection.isEditable())};return t.on("NodeChange",o),o(),()=>{t.off("NodeChange",o)}};t.add("emoticons",((t,e)=>{((t,e)=>{const o=t.options.register;o("emoticons_database",{processor:"string",default:"emojis"}),o("emoticons_database_url",{processor:"string",default:`${e}/js/${b(t)}${t.suffix}.js`}),o("emoticons_database_id",{processor:"string",default:"tinymce.plugins.emoticons"}),o("emoticons_append",{processor:"object",default:{}}),o("emoticons_images_url",{processor:"string",default:"https://cdnjs.cloudflare.com/ajax/libs/twemoji/15.1.0/72x72/"})})(t,e);const o=((t,e,o)=>{const n=p(),s=p(),r=_(t),i=t=>{return o="=4&&e.substr(0,4)===o?t.char.replace(/src="([^"]+)"/,((t,e)=>`src="${r}${e}"`)):t.char;var e,o};t.on("init",(()=>{v.load(o,e).then((e=>{const o=x(t);(t=>{const e={},o=[];g(t,((t,n)=>{const s={title:n,keywords:t.keywords,char:i(t),category:O(k,t.category)},r=void 0!==e[s.category]?e[s.category]:[];e[s.category]=r.concat([s]),o.push(s)})),n.set(e),s.set(o)})(m(e,o))}),(t=>{console.log(`Failed to load emojis: ${t}`),n.set({}),s.set([])}))}));const l=()=>s.get().getOr([]),u=()=>n.isSet()&&s.isSet();return{listCategories:()=>[A].concat(c(n.get().getOr({}))),hasLoaded:u,waitForLoad:()=>u()?Promise.resolve(!0):new Promise(((t,o)=>{let n=15;const s=setInterval((()=>{u()?(clearInterval(s),t(!0)):(n--,n<0&&(console.log("Could not load emojis from url: "+e),clearInterval(s),o(!1)))}),100)})),listAll:l,listCategory:t=>t===A?l():n.get().bind((e=>a.from(e[t]))).getOr([])}})(t,w(t),j(t));return((t,e)=>{t.addCommand("mceEmoticons",(()=>N(t,e)))})(t,o),(t=>{const e=()=>t.execCommand("mceEmoticons");t.ui.registry.addButton("emoticons",{tooltip:"Emojis",icon:"emoji",onAction:e,onSetup:T(t)}),t.ui.registry.addMenuItem("emoticons",{text:"Emojis...",icon:"emoji",onAction:e,onSetup:T(t)})})(t),((t,e)=>{t.ui.registry.addAutocompleter("emoticons",{trigger:":",columns:"auto",minChars:2,fetch:(t,o)=>e.waitForLoad().then((()=>{const n=e.listAll();return L(n,t,a.some(o))})),onAction:(e,o,n)=>{t.selection.setRng(o),t.insertContent(n),e.hide()}})})(t,o),(t=>{t.on("PreInit",(()=>{t.parser.addAttributeFilter("data-emoticon",(t=>{(t=>{for(let o=0,n=t.length;oo.waitForLoad().then((()=>o.listAll()))}}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/fullscreen/plugin.min.js b/apps/web-antd/public/tinymce/plugins/fullscreen/plugin.min.js new file mode 100644 index 0000000..37f4522 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/fullscreen/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";const e=e=>{let t=e;return{get:()=>t,set:e=>{t=e}}};var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const n=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=r=e,(o=String).prototype.isPrototypeOf(n)||(null===(s=r.constructor)||void 0===s?void 0:s.name)===o.name)?"string":t;var n,r,o,s})(t)===e,r=e=>t=>typeof t===e,o=e=>t=>e===t,s=n("string"),i=n("object"),l=n("array"),a=o(null),c=r("boolean"),u=o(void 0),d=e=>!(e=>null==e)(e),m=r("function"),h=r("number"),g=()=>{},p=e=>()=>e;function f(e,...t){return(...n)=>{const r=t.concat(n);return e.apply(null,r)}}const v=p(!1),w=p(!0);class y{constructor(e,t){this.tag=e,this.value=t}static some(e){return new y(!0,e)}static none(){return y.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?y.some(e(this.value)):y.none()}bind(e){return this.tag?e(this.value):y.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:y.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return d(e)?y.some(e):y.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}y.singletonNone=new y(!1);const b=Array.prototype.push,S=(e,t)=>{const n=e.length,r=new Array(n);for(let o=0;o{for(let n=0,r=e.length;n{const n=[];for(let r=0,o=e.length;r((e,t,n)=>{for(let r=0,o=e.length;r{const n=e(y.none()),r=()=>n.get().each(t);return{clear:()=>{r(),n.set(y.none())},isSet:()=>n.get().isSome(),get:()=>n.get(),set:e=>{r(),n.set(y.some(e))}}},k=()=>O((e=>e.unbind())),T=Object.keys,C="undefined"!=typeof window?window:Function("return this;")(),A=(e,t)=>((e,t)=>{let n=null!=t?t:C;for(let t=0;t{const t=A("ownerDocument.defaultView",e);return i(e)&&((e=>((e,t)=>{const n=((e,t)=>A(e,t))(e,t);if(null==n)throw new Error(e+" not available on this browser");return n})("HTMLElement",e))(t).prototype.isPrototypeOf(e)||/^HTML\w*Element$/.test(R(e).constructor.name))},M=e=>t=>(e=>e.dom.nodeType)(t)===e,P=M(1),D=M(3),N=M(11),H=(e,t)=>{const n=e.dom.getAttribute(t);return null===n?void 0:n},V=(e,t)=>{e.dom.removeAttribute(t)},W=(e,t,n=0,r)=>{const o=e.indexOf(t,n);return-1!==o&&(!!u(r)||o+t.length<=r)},q=e=>void 0!==e.style&&m(e.style.getPropertyValue),B=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},I=B,j=(e,t)=>{const n=e.dom;if(1!==n.nodeType)return!1;{const e=n;if(void 0!==e.matches)return e.matches(t);if(void 0!==e.msMatchesSelector)return e.msMatchesSelector(t);if(void 0!==e.webkitMatchesSelector)return e.webkitMatchesSelector(t);if(void 0!==e.mozMatchesSelector)return e.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}},_=e=>I(e.dom.ownerDocument),z=e=>S(e.dom.childNodes,I),K=e=>{const t=(e=>I(e.dom.getRootNode()))(e);return N(n=t)&&d(n.dom.host)?y.some(t):y.none();var n},$=e=>I(e.dom.host),U=e=>{const t=D(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;const n=t.ownerDocument;return K(I(t)).fold((()=>n.body.contains(t)),(r=U,o=$,e=>r(o(e))));var r,o},X=(e,t,n)=>{if(!s(n))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",n,":: Element ",e),new Error("CSS value must be a string: "+n);q(e)&&e.style.setProperty(t,n)},Y=(e,t,n)=>{const r=e.dom;X(r,t,n)},G=(e,t)=>{const n=e.dom;((e,t)=>{const n=T(e);for(let r=0,o=n.length;r{X(n,t,e)}))},J=(e,t)=>{const n=e.dom,r=window.getComputedStyle(n).getPropertyValue(t);return""!==r||U(e)?r:Q(n,t)},Q=(e,t)=>q(e)?e.style.getPropertyValue(t):"",Z=e=>{const t=I((e=>{if(d(e.target)){const t=I(e.target);if(P(t)&&d(t.dom.shadowRoot)&&e.composed&&e.composedPath){const t=e.composedPath();if(t)return(e=>0e.stopPropagation(),r=()=>e.preventDefault(),o=(s=r,i=n,(...e)=>s(i.apply(null,e)));var s,i;return((e,t,n,r,o,s,i)=>({target:e,x:t,y:n,stop:r,prevent:o,kill:s,raw:i}))(t,e.clientX,e.clientY,n,r,o,e)},ee=(e,t,n,r)=>{e.dom.removeEventListener(t,n,r)},te=w,ne=(e,t,n)=>((e,t,n,r)=>((e,t,n,r,o)=>{const s=((e,t)=>n=>{e(n)&&t(Z(n))})(n,r);return e.dom.addEventListener(t,s,o),{unbind:f(ee,e,t,s,o)}})(e,t,n,r,!1))(e,t,te,n),re=()=>oe(0,0),oe=(e,t)=>({major:e,minor:t}),se={nu:oe,detect:(e,t)=>{const n=String(t).toLowerCase();return 0===e.length?re():((e,t)=>{const n=((e,t)=>{for(let n=0;nNumber(t.replace(n,"$"+e));return oe(r(1),r(2))})(e,n)},unknown:re},ie=(e,t)=>{const n=String(t).toLowerCase();return F(e,(e=>e.search(n)))},le=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,ae=e=>t=>W(t,e),ce=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:e=>W(e,"edge/")&&W(e,"chrome")&&W(e,"safari")&&W(e,"applewebkit")},{name:"Chromium",brand:"Chromium",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,le],search:e=>W(e,"chrome")&&!W(e,"chromeframe")},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:e=>W(e,"msie")||W(e,"trident")},{name:"Opera",versionRegexes:[le,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:ae("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:ae("firefox")},{name:"Safari",versionRegexes:[le,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:e=>(W(e,"safari")||W(e,"mobile/"))&&W(e,"applewebkit")}],ue=[{name:"Windows",search:ae("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:e=>W(e,"iphone")||W(e,"ipad"),versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:ae("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"macOS",search:ae("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:ae("linux"),versionRegexes:[]},{name:"Solaris",search:ae("sunos"),versionRegexes:[]},{name:"FreeBSD",search:ae("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:ae("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}],de={browsers:p(ce),oses:p(ue)},me="Edge",he="Chromium",ge="Opera",pe="Firefox",fe="Safari",ve=e=>{const t=e.current,n=e.version,r=e=>()=>t===e;return{current:t,version:n,isEdge:r(me),isChromium:r(he),isIE:r("IE"),isOpera:r(ge),isFirefox:r(pe),isSafari:r(fe)}},we=()=>ve({current:void 0,version:se.unknown()}),ye=ve,be=(p(me),p(he),p("IE"),p(ge),p(pe),p(fe),"Windows"),Se="Android",xe="Linux",Ee="macOS",Fe="Solaris",Oe="FreeBSD",ke="ChromeOS",Te=e=>{const t=e.current,n=e.version,r=e=>()=>t===e;return{current:t,version:n,isWindows:r(be),isiOS:r("iOS"),isAndroid:r(Se),isMacOS:r(Ee),isLinux:r(xe),isSolaris:r(Fe),isFreeBSD:r(Oe),isChromeOS:r(ke)}},Ce=()=>Te({current:void 0,version:se.unknown()}),Ae=Te,Re=(p(be),p("iOS"),p(Se),p(xe),p(Ee),p(Fe),p(Oe),p(ke),(e,t,n)=>{const r=de.browsers(),o=de.oses(),s=t.bind((e=>((e,t)=>((e,t)=>{for(let n=0;n{const n=t.brand.toLowerCase();return F(e,(e=>{var t;return n===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())})).map((e=>({current:e.name,version:se.nu(parseInt(t.version,10),0)})))})))(r,e))).orThunk((()=>((e,t)=>ie(e,t).map((e=>{const n=se.detect(e.versionRegexes,t);return{current:e.name,version:n}})))(r,e))).fold(we,ye),i=((e,t)=>ie(e,t).map((e=>{const n=se.detect(e.versionRegexes,t);return{current:e.name,version:n}})))(o,e).fold(Ce,Ae),l=((e,t,n,r)=>{const o=e.isiOS()&&!0===/ipad/i.test(n),s=e.isiOS()&&!o,i=e.isiOS()||e.isAndroid(),l=i||r("(pointer:coarse)"),a=o||!s&&i&&r("(min-device-width:768px)"),c=s||i&&!a,u=t.isSafari()&&e.isiOS()&&!1===/safari/i.test(n),d=!c&&!a&&!u;return{isiPad:p(o),isiPhone:p(s),isTablet:p(a),isPhone:p(c),isTouch:p(l),isAndroid:e.isAndroid,isiOS:e.isiOS,isWebView:p(u),isDesktop:p(d)}})(i,s,e,n);return{browser:s,os:i,deviceType:l}}),Le=e=>window.matchMedia(e).matches;let Me=(e=>{let t,n=!1;return(...r)=>(n||(n=!0,t=e.apply(null,r)),t)})((()=>Re(window.navigator.userAgent,y.from(window.navigator.userAgentData),Le)));const Pe=(e,t)=>({left:e,top:t,translate:(n,r)=>Pe(e+n,t+r)}),De=Pe,Ne=e=>{const t=void 0===e?window:e;return Me().browser.isFirefox()?y.none():y.from(t.visualViewport)},He=(e,t,n,r)=>({x:e,y:t,width:n,height:r,right:e+n,bottom:t+r}),Ve=e=>{const t=void 0===e?window:e,n=t.document,r=(e=>{const t=void 0!==e?e.dom:document,n=t.body.scrollLeft||t.documentElement.scrollLeft,r=t.body.scrollTop||t.documentElement.scrollTop;return De(n,r)})(I(n));return Ne(t).fold((()=>{const e=t.document.documentElement,n=e.clientWidth,o=e.clientHeight;return He(r.left,r.top,n,o)}),(e=>He(Math.max(e.pageLeft,r.left),Math.max(e.pageTop,r.top),e.width,e.height)))},We=(e,t,n)=>Ne(n).map((n=>{const r=e=>t(Z(e));return n.addEventListener(e,r),{unbind:()=>n.removeEventListener(e,r)}})).getOrThunk((()=>({unbind:g})));var qe=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),Be=tinymce.util.Tools.resolve("tinymce.Env");const Ie=(e,t)=>{e.dispatch("FullscreenStateChanged",{state:t}),e.dispatch("ResizeEditor")},je=e=>e.options.get("fullscreen_native");const _e=e=>{return e.dom===(void 0!==(t=_(e).dom).fullscreenElement?t.fullscreenElement:void 0!==t.msFullscreenElement?t.msFullscreenElement:void 0!==t.webkitFullscreenElement?t.webkitFullscreenElement:null);var t},ze=(e,t,n)=>((e,t,n)=>E(((e,t)=>{const n=m(t)?t:v;let r=e.dom;const o=[];for(;null!==r.parentNode&&void 0!==r.parentNode;){const e=r.parentNode,t=I(e);if(o.push(t),!0===n(t))break;r=e}return o})(e,n),t))(e,(e=>j(e,t)),n),Ke=(e,t)=>(e=>{return E((e=>y.from(e.dom.parentNode).map(I))(n=e).map(z).map((e=>E(e,(e=>{return t=e,!(n.dom===t.dom);var t})))).getOr([]),(e=>j(e,t)));var n})(e),$e="data-ephox-mobile-fullscreen-style",Ue="position:absolute!important;",Xe="top:0!important;left:0!important;margin:0!important;padding:0!important;width:100%!important;height:100%!important;overflow:visible!important;",Ye=Be.os.isAndroid(),Ge=(e,t,n)=>{const r=t=>n=>{const r=H(n,"style"),o=void 0===r?"no-styles":r.trim();o!==t&&(((e,t,n)=>{((e,t,n)=>{if(!(s(n)||c(n)||h(n)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",n,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,n+"")})(e.dom,t,n)})(n,$e,o),G(n,e.parseStyle(t)))},o=ze(t,"*"),i=(e=>{const t=[];for(let n=0,r=e.length;nKe(e,"*:not(.tox-silver-sink)")))),a=(e=>{const t=J(e,"background-color");return void 0!==t&&""!==t?"background-color:"+t+"!important":"background-color:rgb(255,255,255)!important;"})(n);x(i,r("display:none!important;")),x(o,r(Ue+Xe+a)),r((!0===Ye?"":Ue)+Xe+a)(t)},Je=qe.DOM,Qe=Ne().fold((()=>({bind:g,unbind:g})),(e=>{const t=(()=>{const e=O(g);return{...e,on:t=>e.get().each(t)}})(),n=k(),r=k(),o=(e=>{let t=null;return{cancel:()=>{a(t)||(clearTimeout(t),t=null)},throttle:(...n)=>{a(t)&&(t=setTimeout((()=>{t=null,e.apply(null,n)}),50))}}})((()=>{document.body.scrollTop=0,document.documentElement.scrollTop=0,window.requestAnimationFrame((()=>{t.on((t=>G(t,{top:e.offsetTop+"px",left:e.offsetLeft+"px",height:e.height+"px",width:e.width+"px"})))}))}));return{bind:e=>{t.set(e),o.throttle(),n.set(We("resize",o.throttle)),r.set(We("scroll",o.throttle))},unbind:()=>{t.on((()=>{n.clear(),r.clear()})),t.clear()}}})),Ze=(e,t)=>{const n=document.body,r=document.documentElement,o=e.getContainer(),s=I(o),i=(l=s,y.from(l.dom.nextSibling).map(I)).filter((e=>(e=>P(e)&&L(e.dom))(e)&&(e=>(e=>void 0!==e.dom.classList)(e)&&e.dom.classList.contains("tox-silver-sink"))(e)));var l;const a=(e=>{const t=I(e.getElement());return K(t).map($).getOrThunk((()=>(e=>{const t=e.dom.body;if(null==t)throw new Error("Body is not available yet");return I(t)})(_(t))))})(e),c=t.get(),u=I(e.getBody()),d=Be.deviceType.isTouch(),m=o.style,h=e.iframeElement,g=null==h?void 0:h.style,p=e=>{e(n,"tox-fullscreen"),e(r,"tox-fullscreen"),e(o,"tox-fullscreen"),K(s).map((e=>$(e).dom)).each((t=>{e(t,"tox-fullscreen"),e(t,"tox-shadowhost")}))},f=()=>{d&&(e=>{const t=(e=>{const t=document;return 1!==(n=t).nodeType&&9!==n.nodeType&&11!==n.nodeType||0===n.childElementCount?[]:S(t.querySelectorAll(e),I);var n})("["+$e+"]");x(t,(t=>{const n=H(t,$e);n&&"no-styles"!==n?G(t,e.parseStyle(n)):V(t,"style"),V(t,$e)}))})(e.dom),p(Je.removeClass),Qe.unbind(),y.from(t.get()).each((e=>e.fullscreenChangeHandler.unbind()))};if(c)c.fullscreenChangeHandler.unbind(),je(e)&&_e(a)&&(e=>{const t=e.dom;t.exitFullscreen?t.exitFullscreen():t.msExitFullscreen?t.msExitFullscreen():t.webkitCancelFullScreen&&t.webkitCancelFullScreen()})(_(a)),g.width=c.iframeWidth,g.height=c.iframeHeight,m.width=c.containerWidth,m.height=c.containerHeight,m.top=c.containerTop,m.left=c.containerLeft,w=i,b=c.sinkCssPosition,E=(e,t)=>{Y(e,"position",t)},w.isSome()&&b.isSome()?y.some(E(w.getOrDie(),b.getOrDie())):y.none(),f(),v=c.scrollPos,window.scrollTo(v.x,v.y),t.set(null),Ie(e,!1),e.off("remove",f);else{const n=ne(_(a),void 0!==document.fullscreenElement?"fullscreenchange":void 0!==document.msFullscreenElement?"MSFullscreenChange":void 0!==document.webkitFullscreenElement?"webkitfullscreenchange":"fullscreenchange",(n=>{je(e)&&(_e(a)||null===t.get()||Ze(e,t))})),r={scrollPos:Ve(window),containerWidth:m.width,containerHeight:m.height,containerTop:m.top,containerLeft:m.left,iframeWidth:g.width,iframeHeight:g.height,fullscreenChangeHandler:n,sinkCssPosition:i.map((e=>J(e,"position")))};d&&Ge(e.dom,s,u),g.width=g.height="100%",m.width=m.height="",p(Je.addClass),i.each((e=>{Y(e,"position","fixed")})),Qe.bind(s),e.on("remove",f),t.set(r),je(e)&&(e=>{const t=e.dom;t.requestFullscreen?t.requestFullscreen():t.msRequestFullscreen?t.msRequestFullscreen():t.webkitRequestFullScreen&&t.webkitRequestFullScreen()})(a),Ie(e,!0)}var v,w,b,E};var et=tinymce.util.Tools.resolve("tinymce.util.VK");const tt=(e,t)=>n=>{n.setActive(null!==t.get());const r=e=>n.setActive(e.state);return e.on("FullscreenStateChanged",r),()=>e.off("FullscreenStateChanged",r)};t.add("fullscreen",(t=>{const n=e(null);return t.inline||((e=>{(0,e.options.register)("fullscreen_native",{processor:"boolean",default:!1})})(t),((e,t)=>{e.addCommand("mceFullScreen",(()=>{Ze(e,t)}))})(t,n),((e,t)=>{const n=()=>e.execCommand("mceFullScreen");e.ui.registry.addToggleMenuItem("fullscreen",{text:"Fullscreen",icon:"fullscreen",shortcut:"Meta+Shift+F",onAction:n,onSetup:tt(e,t),context:"any"}),e.ui.registry.addToggleButton("fullscreen",{tooltip:"Fullscreen",icon:"fullscreen",onAction:n,onSetup:tt(e,t),shortcut:"Meta+Shift+F",context:"any"})})(t,n),((e,t)=>{e.on("init",(()=>{e.on("keydown",(e=>{e.keyCode!==et.TAB||e.metaKey||e.ctrlKey||!t.get()||e.preventDefault()}))}))})(t,n),t.addShortcut("Meta+Shift+F","","mceFullScreen")),(e=>({isFullscreen:()=>null!==e.get()}))(n)}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ar.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ar.js new file mode 100644 index 0000000..e2cf02f --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ar.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.ar', +'

بدء التنقل بواسطة لوحة المفاتيح

\n' + + '\n' + + '
\n' + + '
التركيز على شريط القوائم
\n' + + '
نظاما التشغيل Windows أو Linux: Alt + F9
\n' + + '
نظام التشغيل macOS: ⌥F9
\n' + + '
التركيز على شريط الأدوات
\n' + + '
نظاما التشغيل Windows أو Linux: Alt + F10
\n' + + '
نظام التشغيل macOS: ⌥F10
\n' + + '
التركيز على التذييل
\n' + + '
نظاما التشغيل Windows أو Linux: Alt + F11
\n' + + '
نظام التشغيل macOS: ⌥F11
\n' + + '
تركيز الإشعارات
\n' + + '
نظاما التشغيل Windows أو Linux: Alt + F12
\n' + + '
نظام التشغيل macOS: ⌥F12
\n' + + '
التركيز على شريط أدوات السياق
\n' + + '
أنظمة التشغيل Windows أو Linux أو macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

سيبدأ التنقل عند عنصر واجهة المستخدم الأول، والذي سيتم تمييزه أو تسطيره في حالة العنصر الأول في\n' + + ' مسار عنصر التذييل.

\n' + + '\n' + + '

التنقل بين أقسام واجهة المستخدم

\n' + + '\n' + + '

للانتقال من أحد أقسام واجهة المستخدم إلى القسم التالي، اضغط على Tab.

\n' + + '\n' + + '

للانتقال من أحد أقسام واجهة المستخدم إلى القسم السابق، اضغط على Shift+Tab.

\n' + + '\n' + + '

ترتيب علامات Tab لأقسام واجهة المستخدم هذه هو:

\n' + + '\n' + + '
    \n' + + '
  1. شريط القوائم
  2. \n' + + '
  3. كل مجموعة شريط الأدوات
  4. \n' + + '
  5. الشريط الجانبي
  6. \n' + + '
  7. مسار العنصر في التذييل
  8. \n' + + '
  9. زر تبديل عدد الكلمات في التذييل
  10. \n' + + '
  11. رابط إدراج العلامة التجارية في التذييل
  12. \n' + + '
  13. مؤشر تغيير حجم المحرر في التذييل
  14. \n' + + '
\n' + + '\n' + + '

إذا لم يكن قسم واجهة المستخدم موجودًا، فسيتم تخطيه.

\n' + + '\n' + + '

إذا كان التذييل يحتوي على التركيز على ‏‫التنقل بواسطة لوحة المفاتيح، ولا يوجد شريط جانبي مرئي، فإن الضغط على Shift+Tab\n' + + ' ينقل التركيز إلى مجموعة شريط الأدوات الأولى، وليس الأخيرة.

\n' + + '\n' + + '

التنقل بين أقسام واجهة المستخدم

\n' + + '\n' + + '

للانتقال من أحد عناصر واجهة المستخدم إلى العنصر التالي، اضغط على مفتاح السهم المناسب.

\n' + + '\n' + + '

مفتاحا السهمين اليسار‎ واليمين‎

\n' + + '\n' + + '
    \n' + + '
  • التنقل بين القوائم في شريط القوائم.
  • \n' + + '
  • فتح قائمة فرعية في القائمة.
  • \n' + + '
  • التنقل بين الأزرار في مجموعة شريط الأدوات.
  • \n' + + '
  • التنقل بين العناصر في مسار عنصر التذييل.
  • \n' + + '
\n' + + '\n' + + '

مفتاحا السهمين لأسفل‎ ولأعلى‎

\n' + + '\n' + + '
    \n' + + '
  • التنقل بين عناصر القائمة في القائمة.
  • \n' + + '
  • التنقل بين العناصر في قائمة شريط الأدوات المنبثقة.
  • \n' + + '
\n' + + '\n' + + '

دورة مفاتيح الأسهم‎ داخل قسم واجهة المستخدم التي تم التركيز عليها.

\n' + + '\n' + + '

لإغلاق قائمة مفتوحة أو قائمة فرعية مفتوحة أو قائمة منبثقة مفتوحة، اضغط على مفتاح Esc.

\n' + + '\n' + + '

إذا كان التركيز الحالي على "الجزء العلوي" من قسم معين لواجهة المستخدم، فإن الضغط على مفتاح Esc يؤدي أيضًا إلى الخروج\n' + + ' من التنقل بواسطة لوحة المفاتيح بالكامل.

\n' + + '\n' + + '

تنفيذ عنصر قائمة أو زر شريط أدوات

\n' + + '\n' + + '

عندما يتم تمييز عنصر القائمة المطلوب أو زر شريط الأدوات، اضغط على زر Return، أو Enter،\n' + + ' أو مفتاح المسافة لتنفيذ العنصر.

\n' + + '\n' + + '

التنقل في مربعات الحوار غير المبوبة

\n' + + '\n' + + '

في مربعات الحوار غير المبوبة، يتم التركيز على المكون التفاعلي الأول عند فتح مربع الحوار.

\n' + + '\n' + + '

التنقل بين مكونات الحوار التفاعلي بالضغط على زر Tab أو Shift+Tab.

\n' + + '\n' + + '

التنقل في مربعات الحوار المبوبة

\n' + + '\n' + + '

في مربعات الحوار المبوبة، يتم التركيز على الزر الأول في قائمة علامات التبويب عند فتح مربع الحوار.

\n' + + '\n' + + '

التنقل بين المكونات التفاعلية لعلامة التبويب لمربع الحوار هذه بالضغط على زر Tab أو\n' + + ' Shift+Tab.

\n' + + '\n' + + '

التبديل إلى علامة تبويب أخرى لمربع الحوار من خلال التركيز على قائمة علامة التبويب ثم الضغط على زر السهم المناسب\n' + + ' مفتاح للتنقل بين علامات التبويب المتاحة.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/bg_BG.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/bg_BG.js new file mode 100644 index 0000000..09eacf3 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/bg_BG.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.bg_BG', +'

Начало на навигацията с клавиатурата

\n' + + '\n' + + '
\n' + + '
Фокусиране върху лентата с менюта
\n' + + '
Windows или Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Фокусиране върху лентата с инструменти
\n' + + '
Windows или Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Фокусиране върху долния колонтитул
\n' + + '
Windows или Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Фокусиране на известието
\n' + + '
Windows или Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Фокусиране върху контекстуалната лента с инструменти
\n' + + '
Windows, Linux или macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Навигацията ще започне с първия елемент на ПИ, който ще бъде маркиран или подчертан в случая на първия елемент в\n' + + ' пътя до елемента в долния колонтитул.

\n' + + '\n' + + '

Навигиране между раздели на ПИ

\n' + + '\n' + + '

За да преминете от един раздел на ПИ към следващия, натиснете Tab.

\n' + + '\n' + + '

За да преминете от един раздел на ПИ към предишния, натиснете Shift+Tab.

\n' + + '\n' + + '

Редът за обхождане с табулация на тези раздели на ПИ е:

\n' + + '\n' + + '
    \n' + + '
  1. Лентата с менюта
  2. \n' + + '
  3. Всяка група на лентата с инструменти
  4. \n' + + '
  5. Страничната лента
  6. \n' + + '
  7. Пътят до елемента в долния колонтитул
  8. \n' + + '
  9. Бутонът за превключване на броя на думите в долния колонтитул
  10. \n' + + '
  11. Връзката за търговска марка в долния колонтитул
  12. \n' + + '
  13. Манипулаторът за преоразмеряване на редактора в долния колонтитул
  14. \n' + + '
\n' + + '\n' + + '

Ако някой раздел на ПИ липсва, той се пропуска.

\n' + + '\n' + + '

Ако долният колонтитул има фокус за навигация с клавиатурата и няма странична лента, натискането на Shift+Tab\n' + + ' премества фокуса към първата група на лентата с инструменти, а не към последната.

\n' + + '\n' + + '

Навигиране в разделите на ПИ

\n' + + '\n' + + '

За да преминете от един елемент на ПИ към следващия, натиснете съответния клавиш със стрелка.

\n' + + '\n' + + '

С клавишите със стрелка наляво и надясно

\n' + + '\n' + + '
    \n' + + '
  • се придвижвате между менютата в лентата с менюто;
  • \n' + + '
  • отваряте подменю в меню;
  • \n' + + '
  • се придвижвате между бутоните в група на лентата с инструменти;
  • \n' + + '
  • се придвижвате между елементи в пътя до елемент в долния колонтитул.
  • \n' + + '
\n' + + '\n' + + '

С клавишите със стрелка надолу и нагоре

\n' + + '\n' + + '
    \n' + + '
  • се придвижвате между елементите от менюто в дадено меню;
  • \n' + + '
  • се придвижвате между елементите в изскачащо меню на лентата с инструменти.
  • \n' + + '
\n' + + '\n' + + '

Клавишите със стрелки се придвижват в рамките на фокусирания раздел на ПИ.

\n' + + '\n' + + '

За да затворите отворено меню, подменю или изскачащо меню, натиснете клавиша Esc.

\n' + + '\n' + + '

Ако текущият фокус е върху „горната част“ на конкретен раздел на ПИ, натискането на клавиша Esc също излиза\n' + + ' напълно от навигацията с клавиатурата.

\n' + + '\n' + + '

Изпълнение на елемент от менюто или бутон от лентата с инструменти

\n' + + '\n' + + '

Когато желаният елемент от менюто или бутон от лентата с инструменти е маркиран, натиснете Return, Enter\n' + + ' или клавиша за интервал, за да изпълните елемента.

\n' + + '\n' + + '

Навигиране в диалогови прозорци без раздели

\n' + + '\n' + + '

В диалоговите прозорци без раздели първият интерактивен компонент се фокусира, когато се отвори диалоговият прозорец.

\n' + + '\n' + + '

Навигирайте между интерактивните компоненти на диалоговия прозорец, като натиснете Tab или Shift+Tab.

\n' + + '\n' + + '

Навигиране в диалогови прозорци с раздели

\n' + + '\n' + + '

В диалоговите прозорци с раздели първият бутон в менюто с раздели се фокусира, когато се отвори диалоговият прозорец.

\n' + + '\n' + + '

Навигирайте между интерактивните компоненти на този диалогов раздел, като натиснете Tab или\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Превключете към друг диалогов раздел, като фокусирате върху менюто с раздели и след това натиснете съответния клавиш със стрелка,\n' + + ' за да преминете през наличните раздели.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ca.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ca.js new file mode 100644 index 0000000..996e29c --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ca.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.ca', +'

Inici de la navegació amb el teclat

\n' + + '\n' + + '
\n' + + '
Enfocar la barra de menús
\n' + + '
Windows o Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + "
Enfocar la barra d'eines
\n" + + '
Windows o Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Enfocar el peu de pàgina
\n' + + '
Windows o Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Enfocar la notificació
\n' + + '
Windows o Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + "
Enfocar una barra d'eines contextual
\n" + + '
Windows, Linux o macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + "

La navegació començarà en el primer element de la interfície d'usuari, que es ressaltarà o subratllarà per al primer element a\n" + + " la ruta de l'element de peu de pàgina.

\n" + + '\n' + + "

Navegació entre seccions de la interfície d'usuari

\n" + + '\n' + + "

Per desplaçar-vos des d'una secció de la interfície d'usuari a la següent, premeu la tecla Tab.

\n" + + '\n' + + "

Per desplaçar-vos des d'una secció de la interfície d'usuari a l'anterior, premeu les tecles Maj+Tab.

\n" + + '\n' + + "

L'ordre en prémer la tecla Tab d'aquestes secciones de la interfície d'usuari és:

\n" + + '\n' + + '
    \n' + + '
  1. Barra de menús
  2. \n' + + "
  3. Cada grup de la barra d'eines
  4. \n" + + '
  5. Barra lateral
  6. \n' + + "
  7. Ruta de l'element del peu de pàgina
  8. \n" + + '
  9. Botó de commutació de recompte de paraules al peu de pàgina
  10. \n' + + '
  11. Enllaç de marca del peu de pàgina
  12. \n' + + "
  13. Control de canvi de mida de l'editor al peu de pàgina
  14. \n" + + '
\n' + + '\n' + + "

Si no hi ha una secció de la interfície d'usuari, s'ometrà.

\n" + + '\n' + + '

Si el peu de pàgina té el focus de navegació del teclat i no hi ha cap barra lateral visible, en prémer Maj+Tab\n' + + " el focus es mou al primer grup de la barra d'eines, no l'últim.

\n" + + '\n' + + "

Navegació dins de les seccions de la interfície d'usuari

\n" + + '\n' + + "

Per desplaçar-vos des d'un element de la interfície d'usuari al següent, premeu la tecla de Fletxa adequada.

\n" + + '\n' + + '

Les tecles de fletxa Esquerra i Dreta

\n' + + '\n' + + '
    \n' + + '
  • us permeten desplaçar-vos entre menús de la barra de menús.
  • \n' + + '
  • obren un submenú en un menú.
  • \n' + + "
  • us permeten desplaçar-vos entre botons d'un grup de la barra d'eines.
  • \n" + + "
  • us permeten desplaçar-vos entre elements de la ruta d'elements del peu de pàgina.
  • \n" + + '
\n' + + '\n' + + '

Les tecles de fletxa Avall i Amunt

\n' + + '\n' + + '
    \n' + + "
  • us permeten desplaçar-vos entre elements de menú d'un menú.
  • \n" + + "
  • us permeten desplaçar-vos entre elements d'un menú emergent de la barra d'eines.
  • \n" + + '
\n' + + '\n' + + "

Les tecles de Fletxa us permeten desplaçar-vos dins de la secció de la interfície d'usuari que té el focus.

\n" + + '\n' + + '

Per tancar un menú, un submenú o un menú emergent oberts, premeu la tecla Esc.

\n' + + '\n' + + "

Si el focus actual es troba a la ‘part superior’ d'una secció específica de la interfície d'usuari, en prémer la tecla Esc també es tanca\n" + + ' completament la navegació amb el teclat.

\n' + + '\n' + + "

Execució d'un element de menú o d'un botó de la barra d'eines

\n" + + '\n' + + "

Quan l'element del menú o el botó de la barra d'eines que desitgeu estigui ressaltat, premeu Retorn, Intro\n" + + " o la barra d'espai per executar l'element.

\n" + + '\n' + + '

Navegació per quadres de diàleg sense pestanyes

\n' + + '\n' + + "

En els quadres de diàleg sense pestanyes, el primer component interactiu pren el focus quan s'obre el quadre diàleg.

\n" + + '\n' + + '

Premeu la tecla Tab o les tecles Maj+Tab per desplaçar-vos entre components interactius del quadre de diàleg.

\n' + + '\n' + + '

Navegació per quadres de diàleg amb pestanyes

\n' + + '\n' + + "

En els quadres de diàleg amb pestanyes, el primer botó del menú de la pestanya pren el focus quan s'obre el quadre diàleg.

\n" + + '\n' + + "

Per desplaçar-vos entre components interactius d'aquest quadre de diàleg, premeu la tecla Tab o\n" + + ' les tecles Maj+Tab.

\n' + + '\n' + + "

Canvieu a la pestanya d'un altre quadre de diàleg, tot enfocant el menú de la pestanya, i després premeu la tecla Fletxa adequada\n" + + ' per canviar entre les pestanyes disponibles.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/cs.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/cs.js new file mode 100644 index 0000000..4a5a902 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/cs.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.cs', +'

Začínáme navigovat pomocí klávesnice

\n' + + '\n' + + '
\n' + + '
Přejít na řádek nabídek
\n' + + '
Windows nebo Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Přejít na panel nástrojů
\n' + + '
Windows nebo Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Přejít na zápatí
\n' + + '
Windows nebo Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Přejít na oznámení
\n' + + '
Windows nebo Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Přejít na kontextový panel nástrojů
\n' + + '
Windows, Linux nebo macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Navigace začne u první položky uživatelského rozhraní, která bude zvýrazněna nebo v případě první položky\n' + + ' cesty k prvku zápatí podtržena.

\n' + + '\n' + + '

Navigace mezi oddíly uživatelského rozhraní

\n' + + '\n' + + '

Stisknutím klávesy Tab se posunete z jednoho oddílu uživatelského rozhraní na další.

\n' + + '\n' + + '

Stisknutím kláves Shift+Tab se posunete z jednoho oddílu uživatelského rozhraní na předchozí.

\n' + + '\n' + + '

Pořadí přepínání mezi oddíly uživatelského rozhraní pomocí klávesy Tab:

\n' + + '\n' + + '
    \n' + + '
  1. Řádek nabídek
  2. \n' + + '
  3. Každá skupina panelu nástrojů
  4. \n' + + '
  5. Boční panel
  6. \n' + + '
  7. Cesta k prvku v zápatí.
  8. \n' + + '
  9. Tlačítko přepínače počtu slov v zápatí
  10. \n' + + '
  11. Odkaz na informace o značce v zápatí
  12. \n' + + '
  13. Úchyt pro změnu velikosti editoru v zápatí
  14. \n' + + '
\n' + + '\n' + + '

Pokud nějaký oddíl uživatelského rozhraní není přítomen, je přeskočen.

\n' + + '\n' + + '

Pokud je zápatí vybrané pro navigaci pomocí klávesnice a není zobrazen žádný boční panel, stisknutím kláves Shift+Tab\n' + + ' přejdete na první skupinu panelu nástrojů, nikoli na poslední.

\n' + + '\n' + + '

Navigace v rámci oddílů uživatelského rozhraní

\n' + + '\n' + + '

Chcete-li se přesunout z jednoho prvku uživatelského rozhraní na další, stiskněte příslušnou klávesu s šipkou.

\n' + + '\n' + + '

Klávesy s šipkou vlevovpravo

\n' + + '\n' + + '
    \n' + + '
  • umožňují přesun mezi nabídkami na řádku nabídek;
  • \n' + + '
  • otevírají podnabídku nabídky;
  • \n' + + '
  • umožňují přesun mezi tlačítky ve skupině panelu nástrojů;
  • \n' + + '
  • umožňují přesun mezi položkami cesty prvku v zápatí.
  • \n' + + '
\n' + + '\n' + + '

Klávesy se šipkou dolůnahoru

\n' + + '\n' + + '
    \n' + + '
  • umožňují přesun mezi položkami nabídky;
  • \n' + + '
  • umožňují přesun mezi položkami místní nabídky panelu nástrojů.
  • \n' + + '
\n' + + '\n' + + '

Šipky provádí přepínání v rámci vybraného oddílu uživatelského rozhraní.

\n' + + '\n' + + '

Chcete-li zavřít otevřenou nabídku, podnabídku nebo místní nabídku, stiskněte klávesu Esc.

\n' + + '\n' + + '

Pokud je aktuálně vybrána horní část oddílu uživatelského rozhraní, stisknutím klávesy Esc zcela ukončíte také\n' + + ' navigaci pomocí klávesnice.

\n' + + '\n' + + '

Provedení příkazu položky nabídky nebo tlačítka panelu nástrojů

\n' + + '\n' + + '

Pokud je zvýrazněna požadovaná položka nabídky nebo tlačítko panelu nástrojů, stisknutím klávesy Return, Enter\n' + + ' nebo mezerníku provedete příslušný příkaz.

\n' + + '\n' + + '

Navigace v dialogových oknech bez záložek

\n' + + '\n' + + '

Při otevření dialogových oken bez záložek přejdete na první interaktivní komponentu.

\n' + + '\n' + + '

Přecházet mezi interaktivními komponentami dialogového okna můžete stisknutím klávesy Tab nebo kombinace Shift+Tab.

\n' + + '\n' + + '

Navigace v dialogových oknech se záložkami

\n' + + '\n' + + '

Při otevření dialogových oken se záložkami přejdete na první tlačítko v nabídce záložek.

\n' + + '\n' + + '

Přecházet mezi interaktivními komponentami této záložky dialogového okna můžete stisknutím klávesy Tab nebo\n' + + ' kombinace Shift+Tab.

\n' + + '\n' + + '

Chcete-li přepnout na další záložku dialogového okna, přejděte na nabídku záložek a poté můžete stisknutím požadované šipky\n' + + ' přepínat mezi dostupnými záložkami.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/da.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/da.js new file mode 100644 index 0000000..4d1e1d4 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/da.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.da', +'

Start tastaturnavigation

\n' + + '\n' + + '
\n' + + '
Fokuser på menulinjen
\n' + + '
Windows eller Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Fokuser på værktøjslinjen
\n' + + '
Windows eller Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Fokuser på sidefoden
\n' + + '
Windows eller Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Fokuser på meddelelsen
\n' + + '
Windows eller Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Fokuser på kontekstuel værktøjslinje
\n' + + '
Windows, Linux eller macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Navigationen starter ved det første UI-element, som fremhæves eller understreges hvad angår det første element i\n' + + ' sidefodens sti til elementet.

\n' + + '\n' + + '

Naviger mellem UI-sektioner

\n' + + '\n' + + '

Gå fra én UI-sektion til den næste ved at trykke på Tab.

\n' + + '\n' + + '

Gå fra én UI-sektion til den forrige ved at trykke på Shift+Tab.

\n' + + '\n' + + '

Tab-rækkefølgen af disse UI-sektioner er:

\n' + + '\n' + + '
    \n' + + '
  1. Menulinje
  2. \n' + + '
  3. Hver værktøjsgruppe
  4. \n' + + '
  5. Sidepanel
  6. \n' + + '
  7. Sti til elementet i sidefoden
  8. \n' + + '
  9. Til/fra-knap for ordoptælling i sidefoden
  10. \n' + + '
  11. Brandinglink i sidefoden
  12. \n' + + '
  13. Tilpasningshåndtag for editor i sidefoden
  14. \n' + + '
\n' + + '\n' + + '

Hvis en UI-sektion ikke er til stede, springes den over.

\n' + + '\n' + + '

Hvis sidefoden har fokus til tastaturnavigation, og der ikke er noget synligt sidepanel, kan der trykkes på Shift+Tab\n' + + ' for at flytte fokus til den første værktøjsgruppe, ikke den sidste.

\n' + + '\n' + + '

Naviger inden for UI-sektioner

\n' + + '\n' + + '

Gå fra ét UI-element til det næste ved at trykke på den relevante piletast.

\n' + + '\n' + + '

Venstre og højre piletast

\n' + + '\n' + + '
    \n' + + '
  • flytter mellem menuerne i menulinjen.
  • \n' + + '
  • åbner en undermenu i en menu.
  • \n' + + '
  • flytter mellem knapperne i en værktøjsgruppe.
  • \n' + + '
  • flytter mellem elementer i sidefodens sti til elementet.
  • \n' + + '
\n' + + '\n' + + '

Pil ned og op

\n' + + '\n' + + '
    \n' + + '
  • flytter mellem menupunkterne i en menu.
  • \n' + + '
  • flytter mellem punkterne i en genvejsmenu i værktøjslinjen.
  • \n' + + '
\n' + + '\n' + + '

Piletasterne kører rundt inden for UI-sektionen, der fokuseres på.

\n' + + '\n' + + '

For at lukke en åben menu, en åben undermenu eller en åben genvejsmenu trykkes der på Esc-tasten.

\n' + + '\n' + + "

Hvis det aktuelle fokus er i 'toppen' af en bestemt UI-sektion, vil tryk på Esc-tasten også afslutte\n" + + ' tastaturnavigationen helt.

\n' + + '\n' + + '

Udfør et menupunkt eller en værktøjslinjeknap

\n' + + '\n' + + '

Når det ønskede menupunkt eller den ønskede værktøjslinjeknap er fremhævet, trykkes der på Retur, Enter\n' + + ' eller mellemrumstasten for at udføre elementet.

\n' + + '\n' + + '

Naviger i ikke-faneopdelte dialogbokse

\n' + + '\n' + + '

I ikke-faneopdelte dialogbokse får den første interaktive komponent fokus, når dialogboksen åbnes.

\n' + + '\n' + + '

Naviger mellem interaktive dialogbokskomponenter ved at trykke på Tab eller Shift+Tab.

\n' + + '\n' + + '

Naviger i faneopdelte dialogbokse

\n' + + '\n' + + '

I faneopdelte dialogbokse får den første knap i fanemenuen fokus, når dialogboksen åbnes.

\n' + + '\n' + + '

Naviger mellem interaktive komponenter i denne dialogboksfane ved at trykke på Tab eller\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Skift til en anden dialogboksfane ved at fokusere på fanemenuen og derefter trykke på den relevante piletast\n' + + ' for at køre igennem de tilgængelige faner.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/de.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/de.js new file mode 100644 index 0000000..b8711ed --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/de.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.de', +'

Grundlagen der Tastaturnavigation

\n' + + '\n' + + '
\n' + + '
Fokus auf Menüleiste
\n' + + '
Windows oder Linux: ALT+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Fokus auf Symbolleiste
\n' + + '
Windows oder Linux: ALT+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Fokus auf Fußzeile
\n' + + '
Windows oder Linux: ALT+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Benachrichtigung fokussieren
\n' + + '
Windows oder Linux: ALT+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Fokus auf kontextbezogene Symbolleiste
\n' + + '
Windows, Linux oder macOS: STRG+F9
\n' + + '
\n' + + '\n' + + '

Die Navigation beginnt beim ersten Benutzeroberflächenelement, welches hervorgehoben ist. Falls sich das erste Element im Pfad der Fußzeile befindet,\n' + + ' ist es unterstrichen.

\n' + + '\n' + + '

Zwischen Abschnitten der Benutzeroberfläche navigieren

\n' + + '\n' + + '

Um von einem Abschnitt der Benutzeroberfläche zum nächsten zu wechseln, drücken Sie TAB.

\n' + + '\n' + + '

Um von einem Abschnitt der Benutzeroberfläche zum vorherigen zu wechseln, drücken Sie UMSCHALT+TAB.

\n' + + '\n' + + '

Die Abschnitte der Benutzeroberfläche haben folgende TAB-Reihenfolge:

\n' + + '\n' + + '
    \n' + + '
  1. Menüleiste
  2. \n' + + '
  3. Einzelne Gruppen der Symbolleiste
  4. \n' + + '
  5. Randleiste
  6. \n' + + '
  7. Elementpfad in der Fußzeile
  8. \n' + + '
  9. Umschaltfläche „Wörter zählen“ in der Fußzeile
  10. \n' + + '
  11. Branding-Link in der Fußzeile
  12. \n' + + '
  13. Editor-Ziehpunkt zur Größenänderung in der Fußzeile
  14. \n' + + '
\n' + + '\n' + + '

Falls ein Abschnitt der Benutzeroberflächen nicht vorhanden ist, wird er übersprungen.

\n' + + '\n' + + '

Wenn in der Fußzeile die Tastaturnavigation fokussiert ist und keine Randleiste angezeigt wird, wechselt der Fokus durch Drücken von UMSCHALT+TAB\n' + + ' zur ersten Gruppe der Symbolleiste, nicht zur letzten.

\n' + + '\n' + + '

Innerhalb von Abschnitten der Benutzeroberfläche navigieren

\n' + + '\n' + + '

Um von einem Element der Benutzeroberfläche zum nächsten zu wechseln, drücken Sie die entsprechende Pfeiltaste.

\n' + + '\n' + + '

Die Pfeiltasten Links und Rechts

\n' + + '\n' + + '
    \n' + + '
  • wechseln zwischen Menüs in der Menüleiste.
  • \n' + + '
  • öffnen das Untermenü eines Menüs.
  • \n' + + '
  • wechseln zwischen Schaltflächen in einer Gruppe der Symbolleiste.
  • \n' + + '
  • wechseln zwischen Elementen im Elementpfad der Fußzeile.
  • \n' + + '
\n' + + '\n' + + '

Die Pfeiltasten Abwärts und Aufwärts

\n' + + '\n' + + '
    \n' + + '
  • wechseln zwischen Menüelementen in einem Menü.
  • \n' + + '
  • wechseln zwischen Elementen in einem Popupmenü der Symbolleiste.
  • \n' + + '
\n' + + '\n' + + '

Die Pfeiltasten rotieren innerhalb des fokussierten Abschnitts der Benutzeroberfläche.

\n' + + '\n' + + '

Um ein geöffnetes Menü, ein geöffnetes Untermenü oder ein geöffnetes Popupmenü zu schließen, drücken Sie die ESC-Taste.

\n' + + '\n' + + '

Wenn sich der aktuelle Fokus ganz oben in einem bestimmten Abschnitt der Benutzeroberfläche befindet, wird durch Drücken der ESC-Taste auch\n' + + ' die Tastaturnavigation beendet.

\n' + + '\n' + + '

Ein Menüelement oder eine Symbolleistenschaltfläche ausführen

\n' + + '\n' + + '

Wenn das gewünschte Menüelement oder die gewünschte Symbolleistenschaltfläche hervorgehoben ist, drücken Sie Zurück, Eingabe\n' + + ' oder die Leertaste, um das Element auszuführen.

\n' + + '\n' + + '

In Dialogfeldern ohne Registerkarten navigieren

\n' + + '\n' + + '

In Dialogfeldern ohne Registerkarten ist beim Öffnen eines Dialogfelds die erste interaktive Komponente fokussiert.

\n' + + '\n' + + '

Navigieren Sie zwischen den interaktiven Komponenten eines Dialogfelds, indem Sie TAB oder UMSCHALT+TAB drücken.

\n' + + '\n' + + '

In Dialogfeldern mit Registerkarten navigieren

\n' + + '\n' + + '

In Dialogfeldern mit Registerkarten ist beim Öffnen eines Dialogfelds die erste Schaltfläche eines Registerkartenmenüs fokussiert.

\n' + + '\n' + + '

Navigieren Sie zwischen den interaktiven Komponenten auf dieser Registerkarte des Dialogfelds, indem Sie TAB oder\n' + + ' UMSCHALT+TAB drücken.

\n' + + '\n' + + '

Wechseln Sie zu einer anderen Registerkarte des Dialogfelds, indem Sie den Fokus auf das Registerkartenmenü legen und dann die entsprechende Pfeiltaste\n' + + ' drücken, um durch die verfügbaren Registerkarten zu rotieren.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/el.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/el.js new file mode 100644 index 0000000..98afabe --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/el.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.el', +'

Έναρξη πλοήγησης μέσω πληκτρολογίου

\n' + + '\n' + + '
\n' + + '
Εστίαση στη γραμμή μενού
\n' + + '
Windows ή Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Εστίαση στη γραμμή εργαλείων
\n' + + '
Windows ή Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Εστίαση στο υποσέλιδο
\n' + + '
Windows ή Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Εστίαση στην ειδοποίηση
\n' + + '
Windows ή Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Εστίαση σε γραμμή εργαλείων βάσει περιεχομένου
\n' + + '
Windows, Linux ή macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Η πλοήγηση θα ξεκινήσει από το πρώτο στοιχείο περιβάλλοντος χρήστη, που θα επισημαίνεται ή θα είναι υπογραμμισμένο,\n' + + ' όπως στην περίπτωση της διαδρομής του στοιχείου Υποσέλιδου.

\n' + + '\n' + + '

Πλοήγηση μεταξύ ενοτήτων του περιβάλλοντος χρήστη

\n' + + '\n' + + '

Για να μετακινηθείτε από μια ενότητα περιβάλλοντος χρήστη στην επόμενη, πιέστε το πλήκτρο Tab.

\n' + + '\n' + + '

Για να μετακινηθείτε από μια ενότητα περιβάλλοντος χρήστη στην προηγούμενη, πιέστε τα πλήκτρα Shift+Tab.

\n' + + '\n' + + '

Η σειρά Tab αυτών των ενοτήτων περιβάλλοντος χρήστη είναι η εξής:

\n' + + '\n' + + '
    \n' + + '
  1. Γραμμή μενού
  2. \n' + + '
  3. Κάθε ομάδα γραμμής εργαλείων
  4. \n' + + '
  5. Πλαϊνή γραμμή
  6. \n' + + '
  7. Διαδρομή στοιχείου στο υποσέλιδο
  8. \n' + + '
  9. Κουμπί εναλλαγής μέτρησης λέξεων στο υποσέλιδο
  10. \n' + + '
  11. Σύνδεσμος επωνυμίας στο υποσέλιδο
  12. \n' + + '
  13. Λαβή αλλαγής μεγέθους προγράμματος επεξεργασίας στο υποσέλιδο
  14. \n' + + '
\n' + + '\n' + + '

Εάν δεν εμφανίζεται ενότητα περιβάλλοντος χρήστη, παραλείπεται.

\n' + + '\n' + + '

Εάν η εστίαση πλοήγησης βρίσκεται στο πληκτρολόγιο και δεν υπάρχει εμφανής πλαϊνή γραμμή, εάν πιέσετε Shift+Tab\n' + + ' η εστίαση μετακινείται στην πρώτη ομάδα γραμμής εργαλείων, όχι στην τελευταία.

\n' + + '\n' + + '

Πλοήγηση εντός των ενοτήτων του περιβάλλοντος χρήστη

\n' + + '\n' + + '

Για να μετακινηθείτε από ένα στοιχείο περιβάλλοντος χρήστη στο επόμενο, πιέστε το αντίστοιχο πλήκτρο βέλους.

\n' + + '\n' + + '

Με τα πλήκτρα αριστερού και δεξιού βέλους

\n' + + '\n' + + '
    \n' + + '
  • γίνεται μετακίνηση μεταξύ των μενού στη γραμμή μενού.
  • \n' + + '
  • ανοίγει ένα υπομενού σε ένα μενού.
  • \n' + + '
  • γίνεται μετακίνηση μεταξύ κουμπιών σε μια ομάδα γραμμής εργαλείων.
  • \n' + + '
  • γίνεται μετακίνηση μεταξύ στοιχείων στη διαδρομή στοιχείου στο υποσέλιδο.
  • \n' + + '
\n' + + '\n' + + '

Με τα πλήκτρα επάνω και κάτω βέλους

\n' + + '\n' + + '
    \n' + + '
  • γίνεται μετακίνηση μεταξύ των στοιχείων μενού σε ένα μενού.
  • \n' + + '
  • γίνεται μετακίνηση μεταξύ των στοιχείων μενού σε ένα αναδυόμενο μενού γραμμής εργαλείων.
  • \n' + + '
\n' + + '\n' + + '

Με τα πλήκτρα βέλους γίνεται κυκλική μετακίνηση εντός της εστιασμένης ενότητας περιβάλλοντος χρήστη.

\n' + + '\n' + + '

Για να κλείσετε ένα ανοιχτό μενού, ένα ανοιχτό υπομενού ή ένα ανοιχτό αναδυόμενο μενού, πιέστε το πλήκτρο Esc.

\n' + + '\n' + + '

Εάν η τρέχουσα εστίαση βρίσκεται στην κορυφή μιας ενότητας περιβάλλοντος χρήστη, πιέζοντας το πλήκτρο Esc,\n' + + ' γίνεται επίσης πλήρης έξοδος από την πλοήγηση μέσω πληκτρολογίου.

\n' + + '\n' + + '

Εκτέλεση ενός στοιχείου μενού ή κουμπιού γραμμής εργαλείων

\n' + + '\n' + + '

Όταν το επιθυμητό στοιχείο μενού ή κουμπί γραμμής εργαλείων είναι επισημασμένο, πιέστε τα πλήκτρα Return, Enter,\n' + + ' ή το πλήκτρο διαστήματος για να εκτελέσετε το στοιχείο.

\n' + + '\n' + + '

Πλοήγηση σε παράθυρα διαλόγου χωρίς καρτέλες

\n' + + '\n' + + '

Σε παράθυρα διαλόγου χωρίς καρτέλες, το πρώτο αλληλεπιδραστικό στοιχείο λαμβάνει την εστίαση όταν ανοίγει το παράθυρο διαλόγου.

\n' + + '\n' + + '

Μπορείτε να πλοηγηθείτε μεταξύ των αλληλεπιδραστικών στοιχείων παραθύρων διαλόγων πιέζοντας τα πλήκτρα Tab ή Shift+Tab.

\n' + + '\n' + + '

Πλοήγηση σε παράθυρα διαλόγου με καρτέλες

\n' + + '\n' + + '

Σε παράθυρα διαλόγου με καρτέλες, το πρώτο κουμπί στο μενού καρτέλας λαμβάνει την εστίαση όταν ανοίγει το παράθυρο διαλόγου.

\n' + + '\n' + + '

Μπορείτε να πλοηγηθείτε μεταξύ των αλληλεπιδραστικών στοιχείων αυτής της καρτέλα διαλόγου πιέζοντας τα πλήκτρα Tab ή\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Μπορείτε να κάνετε εναλλαγή σε άλλη καρτέλα του παραθύρου διαλόγου, μεταφέροντας την εστίαση στο μενού καρτέλας και πιέζοντας το κατάλληλο πλήκτρο βέλους\n' + + ' για να μετακινηθείτε κυκλικά στις διαθέσιμες καρτέλες.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/en.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/en.js new file mode 100644 index 0000000..5dd753e --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/en.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.en', +'

Begin keyboard navigation

\n' + + '\n' + + '
\n' + + '
Focus the Menu bar
\n' + + '
Windows or Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Focus the Toolbar
\n' + + '
Windows or Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Focus the footer
\n' + + '
Windows or Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Focus the notification
\n' + + '
Windows or Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Focus a contextual toolbar
\n' + + '
Windows, Linux or macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Navigation will start at the first UI item, which will be highlighted, or underlined in the case of the first item in\n' + + ' the Footer element path.

\n' + + '\n' + + '

Navigate between UI sections

\n' + + '\n' + + '

To move from one UI section to the next, press Tab.

\n' + + '\n' + + '

To move from one UI section to the previous, press Shift+Tab.

\n' + + '\n' + + '

The Tab order of these UI sections is:

\n' + + '\n' + + '
    \n' + + '
  1. Menu bar
  2. \n' + + '
  3. Each toolbar group
  4. \n' + + '
  5. Sidebar
  6. \n' + + '
  7. Element path in the footer
  8. \n' + + '
  9. Word count toggle button in the footer
  10. \n' + + '
  11. Branding link in the footer
  12. \n' + + '
  13. Editor resize handle in the footer
  14. \n' + + '
\n' + + '\n' + + '

If a UI section is not present, it is skipped.

\n' + + '\n' + + '

If the footer has keyboard navigation focus, and there is no visible sidebar, pressing Shift+Tab\n' + + ' moves focus to the first toolbar group, not the last.

\n' + + '\n' + + '

Navigate within UI sections

\n' + + '\n' + + '

To move from one UI element to the next, press the appropriate Arrow key.

\n' + + '\n' + + '

The Left and Right arrow keys

\n' + + '\n' + + '
    \n' + + '
  • move between menus in the menu bar.
  • \n' + + '
  • open a sub-menu in a menu.
  • \n' + + '
  • move between buttons in a toolbar group.
  • \n' + + '
  • move between items in the footer’s element path.
  • \n' + + '
\n' + + '\n' + + '

The Down and Up arrow keys

\n' + + '\n' + + '
    \n' + + '
  • move between menu items in a menu.
  • \n' + + '
  • move between items in a toolbar pop-up menu.
  • \n' + + '
\n' + + '\n' + + '

Arrow keys cycle within the focused UI section.

\n' + + '\n' + + '

To close an open menu, an open sub-menu, or an open pop-up menu, press the Esc key.

\n' + + '\n' + + '

If the current focus is at the ‘top’ of a particular UI section, pressing the Esc key also exits\n' + + ' keyboard navigation entirely.

\n' + + '\n' + + '

Execute a menu item or toolbar button

\n' + + '\n' + + '

When the desired menu item or toolbar button is highlighted, press Return, Enter,\n' + + ' or the Space bar to execute the item.

\n' + + '\n' + + '

Navigate non-tabbed dialogs

\n' + + '\n' + + '

In non-tabbed dialogs, the first interactive component takes focus when the dialog opens.

\n' + + '\n' + + '

Navigate between interactive dialog components by pressing Tab or Shift+Tab.

\n' + + '\n' + + '

Navigate tabbed dialogs

\n' + + '\n' + + '

In tabbed dialogs, the first button in the tab menu takes focus when the dialog opens.

\n' + + '\n' + + '

Navigate between interactive components of this dialog tab by pressing Tab or\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Switch to another dialog tab by giving the tab menu focus and then pressing the appropriate Arrow\n' + + ' key to cycle through the available tabs.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/es.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/es.js new file mode 100644 index 0000000..e426c2e --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/es.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.es', +'

Iniciar la navegación con el teclado

\n' + + '\n' + + '
\n' + + '
Enfocar la barra de menús
\n' + + '
Windows o Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Enfocar la barra de herramientas
\n' + + '
Windows o Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Enfocar el pie de página
\n' + + '
Windows o Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Enfocar la notificación
\n' + + '
Windows o Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Enfocar una barra de herramientas contextual
\n' + + '
Windows, Linux o macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

La navegación comenzará por el primer elemento de la interfaz de usuario (IU), de tal manera que se resaltará, o bien se subrayará si se trata del primer elemento de\n' + + ' la ruta de elemento del pie de página.

\n' + + '\n' + + '

Navegar entre las secciones de la IU

\n' + + '\n' + + '

Para pasar de una sección de la IU a la siguiente, pulse la tecla Tab.

\n' + + '\n' + + '

Para pasar de una sección de la IU a la anterior, pulse Mayús+Tab.

\n' + + '\n' + + '

El orden de tabulación de estas secciones de la IU es:

\n' + + '\n' + + '
    \n' + + '
  1. Barra de menús
  2. \n' + + '
  3. Cada grupo de barra de herramientas
  4. \n' + + '
  5. Barra lateral
  6. \n' + + '
  7. Ruta del elemento en el pie de página
  8. \n' + + '
  9. Botón de alternancia de recuento de palabras en el pie de página
  10. \n' + + '
  11. Enlace de personalización de marca en el pie de página
  12. \n' + + '
  13. Controlador de cambio de tamaño en el pie de página
  14. \n' + + '
\n' + + '\n' + + '

Si una sección de la IU no está presente, esta se omite.

\n' + + '\n' + + '

Si el pie de página tiene un enfoque de navegación con el teclado y no hay ninguna barra lateral visible, al pulsar Mayús+Tab,\n' + + ' el enfoque se moverá al primer grupo de barra de herramientas, en lugar de al último.

\n' + + '\n' + + '

Navegar dentro de las secciones de la IU

\n' + + '\n' + + '

Para pasar de un elemento de la IU al siguiente, pulse la tecla de flecha correspondiente.

\n' + + '\n' + + '

Las teclas de flecha izquierda y derecha permiten

\n' + + '\n' + + '
    \n' + + '
  • desplazarse entre los menús de la barra de menús.
  • \n' + + '
  • abrir el submenú de un menú.
  • \n' + + '
  • desplazarse entre los botones de un grupo de barra de herramientas.
  • \n' + + '
  • desplazarse entre los elementos de la ruta de elemento del pie de página.
  • \n' + + '
\n' + + '\n' + + '

Las teclas de flecha abajo y arriba permiten

\n' + + '\n' + + '
    \n' + + '
  • desplazarse entre los elementos de menú de un menú.
  • \n' + + '
  • desplazarse entre los elementos de un menú emergente de una barra de herramientas.
  • \n' + + '
\n' + + '\n' + + '

Las teclas de flecha van cambiando dentro de la sección de la IU enfocada.

\n' + + '\n' + + '

Para cerrar un menú, un submenú o un menú emergente que estén abiertos, pulse la tecla Esc.

\n' + + '\n' + + '

Si el enfoque actual se encuentra en la parte superior de una sección de la IU determinada, al pulsar la tecla Esc saldrá\n' + + ' de la navegación con el teclado por completo.

\n' + + '\n' + + '

Ejecutar un elemento de menú o un botón de barra de herramientas

\n' + + '\n' + + '

Si el elemento de menú o el botón de barra de herramientas deseado está resaltado, pulse la tecla Retorno o Entrar,\n' + + ' o la barra espaciadora para ejecutar el elemento.

\n' + + '\n' + + '

Navegar por cuadros de diálogo sin pestañas

\n' + + '\n' + + '

En los cuadros de diálogo sin pestañas, el primer componente interactivo se enfoca al abrirse el cuadro de diálogo.

\n' + + '\n' + + '

Para navegar entre los componentes interactivos del cuadro de diálogo, pulse las teclas Tab o Mayús+Tab.

\n' + + '\n' + + '

Navegar por cuadros de diálogo con pestañas

\n' + + '\n' + + '

En los cuadros de diálogo con pestañas, el primer botón del menú de pestaña se enfoca al abrirse el cuadro de diálogo.

\n' + + '\n' + + '

Para navegar entre componentes interactivos de esta pestaña del cuadro de diálogo, pulse las teclas Tab o\n' + + ' Mayús+Tab.

\n' + + '\n' + + '

Si desea cambiar a otra pestaña del cuadro de diálogo, enfoque el menú de pestañas y, a continuación, pulse la tecla de flecha\n' + + ' correspondiente para moverse por las pestañas disponibles.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/eu.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/eu.js new file mode 100644 index 0000000..c18b940 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/eu.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.eu', +'

Hasi teklatuaren nabigazioa

\n' + + '\n' + + '
\n' + + '
Fokuratu menu-barra
\n' + + '
Windows edo Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Fokuratu tresna-barra
\n' + + '
Windows edo Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Fokuratu orri-oina
\n' + + '
Windows edo Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Fokuratu jakinarazpena
\n' + + '
Windows edo Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Fokuratu testuinguruaren tresna-barra
\n' + + '
Windows, Linux edo macOS: Ktrl+F9
\n' + + '
\n' + + '\n' + + '

Nabigazioa EIko lehen elementuan hasiko da: elementu hori nabarmendu egingo da, edo azpimarratu lehen elementua bada\n' + + ' orri-oineko elementuaren bidea.

\n' + + '\n' + + '

Nabigatu EIko atalen artean

\n' + + '\n' + + '

EIko atal batetik hurrengora mugitzeko, sakatu Tabuladorea.

\n' + + '\n' + + '

EIko atal batetik aurrekora mugitzeko, sakatu Maius+Tabuladorea.

\n' + + '\n' + + '

EIko atal hauen Tabuladorea da:

\n' + + '\n' + + '
    \n' + + '
  1. Menu-barra
  2. \n' + + '
  3. Tresna-barraren talde bakoitza
  4. \n' + + '
  5. Alboko barra
  6. \n' + + '
  7. Orri-oineko elementuaren bidea
  8. \n' + + '
  9. Orri-oneko urrats-kontaketa txandakatzeko botoia
  10. \n' + + '
  11. Orri-oineko marken esteka
  12. \n' + + '
  13. Orri-oineko editorearen tamaina aldatzeko heldulekua
  14. \n' + + '
\n' + + '\n' + + '

EIko atal bat ez badago, saltatu egin da.

\n' + + '\n' + + '

Orri-oinak teklatuaren nabigazioa fokuratuta badago, eta alboko barra ikusgai ez badago, Maius+Tabuladorea sakatuz gero,\n' + + ' fokua tresna-barrako lehen taldera eramaten da, ez azkenera.

\n' + + '\n' + + '

Nabigatu EIko atalen barruan

\n' + + '\n' + + '

EIko elementu batetik hurrengora mugitzeko, sakatu dagokion Gezia tekla.

\n' + + '\n' + + '

Ezkerrera eta Eskuinera gezi-teklak

\n' + + '\n' + + '
    \n' + + '
  • menu-barrako menuen artean mugitzen da.
  • \n' + + '
  • ireki azpimenu bat menuan.
  • \n' + + '
  • mugitu botoi batetik bestera tresna-barren talde batean.
  • \n' + + '
  • mugitu orri-oineko elementuaren bideko elementu batetik bestera.
  • \n' + + '
\n' + + '\n' + + '

Gora eta Behera gezi-teklak

\n' + + '\n' + + '
    \n' + + '
  • mugitu menu bateko menu-elementuen artean.
  • \n' + + '
  • mugitu tresna-barrako menu gainerakor bateko menu-elementuen artean.
  • \n' + + '
\n' + + '\n' + + '

Gezia teklen zikloa nabarmendutako EI atalen barruan.

\n' + + '\n' + + '

Irekitako menu bat ixteko, ireki azpimenua, edo ireki menu gainerakorra, sakatu Ihes tekla.

\n' + + '\n' + + '

Une horretan fokuratzea EIko atal jakin baten "goialdean" badago, Ihes tekla sakatuz gero\n' + + ' teklatuaren nabigaziotik irtengo zara.

\n' + + '\n' + + '

Exekutatu menuko elementu bat edo tresna-barrako botoi bat

\n' + + '\n' + + '

Nahi den menuaren elementua edo tresna-barraren botoia nabarmenduta dagoenean, sakatu Itzuli, Sartu\n' + + ' edo Zuriune-barra elementua exekutatzeko.

\n' + + '\n' + + '

Nabigatu fitxarik gabeko elkarrizketak

\n' + + '\n' + + '

Fitxarik gabeko elkarrizketetan, lehen osagai interaktiboa fokuratzen da elkarrizketa irekitzen denean.

\n' + + '\n' + + '

Nabigatu elkarrizketa interaktiboko osagai batetik bestera Tabuladorea edo Maius+Tabuladorea sakatuta.

\n' + + '\n' + + '

Nabigatu fitxadun elkarrizketak

\n' + + '\n' + + '

Fitxadun elkarrizketetan, fitxa-menuko lehen botoia fokuratzen da elkarrizketa irekitzen denean.

\n' + + '\n' + + '

Nabigatu elkarrizketa-fitxa honen interaktiboko osagai batetik bestera Tabuladorea edo\n' + + ' Maius+Tabuladorea sakatuta.

\n' + + '\n' + + '

Aldatu beste elkarrizketa-fitxa batera fitxa-menua fokuratu eta dagokion Gezia\n' + + ' tekla sakatzeko, erabilgarri dauden fitxa batetik bestera txandakatzeko.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/fa.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/fa.js new file mode 100644 index 0000000..2a55012 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/fa.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.fa', +'

شروع پیمایش صفحه‌کلید

\n' + + '\n' + + '
\n' + + '
تمرکز بر نوار منو
\n' + + '
Windows یا Linux:‎‏: Alt+F9
\n' + + '
‎‏macOS: ⌥F9‎‏
\n' + + '
تمرکز بر نوار ابزار
\n' + + '
Windows یا Linux‎‏: Alt+F10
\n' + + '
‎‏macOS: ⌥F10‎‏
\n' + + '
تمرکز بر پانویس
\n' + + '
Windows یا Linux‎‏: Alt+F11
\n' + + '
‎‏macOS: ⌥F11‎‏
\n' + + '
تمرکز اعلان
\n' + + '
ویندوز یا لینوکس: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
تمرکز بر نوار ابزار بافتاری
\n' + + '
Windows ،Linux یا macOS:‏ Ctrl+F9
\n' + + '
\n' + + '\n' + + '

پیمایش در اولین مورد رابط کاربری شروع می‌شود و درخصوص اولین مورد در\n' + + ' مسیر عنصر پانویس، برجسته یا زیرخط‌دار می‌شود.

\n' + + '\n' + + '

پیمایش بین بخش‌های رابط کاربری

\n' + + '\n' + + '

برای جابجایی از یک بخش رابط کاربری به بخش بعدی، Tab را فشار دهید.

\n' + + '\n' + + '

برای جابجایی از یک بخش رابط کاربری به بخش قبلی، Shift+Tab را فشار دهید.

\n' + + '\n' + + '

ترتیب Tab این بخش‌های رابط کاربری عبارتند از:

\n' + + '\n' + + '
    \n' + + '
  1. نوار منو
  2. \n' + + '
  3. هر گروه نوار ابزار
  4. \n' + + '
  5. نوار کناری
  6. \n' + + '
  7. مسیر عنصر در پانویس
  8. \n' + + '
  9. دکمه تغییر وضعیت تعداد کلمات در پانویس
  10. \n' + + '
  11. پیوند نمانام‌سازی در پانویس
  12. \n' + + '
  13. دسته تغییر اندازه ویرایشگر در پانویس
  14. \n' + + '
\n' + + '\n' + + '

اگر بخشی از رابط کاربری موجود نباشد، رد می‌شود.

\n' + + '\n' + + '

اگر پانویس دارای تمرکز بر پیمایش صفحه‌کلید باشد،‌ و نوار کناری قابل‌مشاهده وجود ندارد، فشردن Shift+Tab\n' + + ' تمرکز را به گروه نوار ابزار اول می‌برد، نه آخر.

\n' + + '\n' + + '

پیمایش در بخش‌های رابط کاربری

\n' + + '\n' + + '

برای جابجایی از یک عنصر رابط کاربری به بعدی، کلید جهت‌نمای مناسب را فشار دهید.

\n' + + '\n' + + '

کلیدهای جهت‌نمای چپ و راست

\n' + + '\n' + + '
    \n' + + '
  • جابجایی بین منوها در نوار منو.
  • \n' + + '
  • باز کردن منوی فرعی در یک منو.
  • \n' + + '
  • جابجایی بین دکمه‌ها در یک گروه نوار ابزار.
  • \n' + + '
  • جابجایی بین موارد در مسیر عنصر پانویس.
  • \n' + + '
\n' + + '\n' + + '

کلیدهای جهت‌نمای پایین و بالا

\n' + + '\n' + + '
    \n' + + '
  • جابجایی بین موارد منو در یک منو.
  • \n' + + '
  • جابجایی بین موارد در یک منوی بازشوی نوار ابزار.
  • \n' + + '
\n' + + '\n' + + '

کلیدهایجهت‌نما در بخش رابط کاربری متمرکز می‌چرخند.

\n' + + '\n' + + '

برای بستن یک منوی باز، یک منوی فرعی باز، یا یک منوی بازشوی باز، کلید Esc را فشار دهید.

\n' + + '\n' + + '

اگر تمرکز فعلی در «بالای» یک بخش رابط کاربری خاص است، فشردن کلید Esc نیز موجب\n' + + ' خروج کامل از پیمایش صفحه‌کلید می‌شود.

\n' + + '\n' + + '

اجرای یک مورد منو یا دکمه نوار ابزار

\n' + + '\n' + + '

وقتی مورد منو یا دکمه نوار ابزار مورد نظر هایلایت شد، دکمه بازگشت، Enter،\n' + + ' یا نوار Space را فشار دهید تا مورد را اجرا کنید.

\n' + + '\n' + + '

پیمایش در کادرهای گفتگوی بدون زبانه

\n' + + '\n' + + '

در کادرهای گفتگوی بدون زبانه، وقتی کادر گفتگو باز می‌شود، اولین جزء تعاملی متمرکز می‌شود.

\n' + + '\n' + + '

با فشردن Tab یا Shift+Tab، بین اجزای کادر گفتگوی تعاملی پیمایش کنید.

\n' + + '\n' + + '

پیمایش کادرهای گفتگوی زبانه‌دار

\n' + + '\n' + + '

در کادرهای گفتگوی زبانه‌دار، وقتی کادر گفتگو باز می‌شود، اولین دکمه در منوی زبانه متمرکز می‌شود.

\n' + + '\n' + + '

با فشردن Tab یا\n' + + ' Shift+Tab، بین اجزای تعاملی این زبانه کادر گفتگو پیمایش کنید.

\n' + + '\n' + + '

با دادن تمرکز به منوی زبانه و سپس فشار دادن کلید جهت‌نمای\n' + + ' مناسب برای چرخش میان زبانه‌های موجود، به زبانه کادر گفتگوی دیگری بروید.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/fi.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/fi.js new file mode 100644 index 0000000..f01dc91 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/fi.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.fi', +'

Näppäimistönavigoinnin aloittaminen

\n' + + '\n' + + '
\n' + + '
Siirrä kohdistus valikkopalkkiin
\n' + + '
Windows tai Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Siirrä kohdistus työkalupalkkiin
\n' + + '
Windows tai Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Siirrä kohdistus alatunnisteeseen
\n' + + '
Windows tai Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Keskitä ilmoitukseen
\n' + + '
Windows ja Linux: Alt + F12
\n' + + '
macOS: ⌥F12
\n' + + '
Siirrä kohdistus kontekstuaaliseen työkalupalkkiin
\n' + + '
Windows, Linux tai macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Navigointi aloitetaan ensimmäisestä käyttöliittymän kohteesta, joka joko korostetaan tai alleviivataan, jos\n' + + ' kyseessä on Alatunniste-elementin polun ensimmäinen kohde.

\n' + + '\n' + + '

Käyttöliittymän eri osien välillä navigointi

\n' + + '\n' + + '

Paina sarkainnäppäintä siirtyäksesi käyttöliittymän osasta seuraavaan.

\n' + + '\n' + + '

Jos haluat siirtyä edelliseen käyttöliittymän osaan, paina Shift+sarkainnäppäin.

\n' + + '\n' + + '

Sarkainnäppäin siirtää sinua näissä käyttöliittymän osissa tässä järjestyksessä:

\n' + + '\n' + + '
    \n' + + '
  1. Valikkopalkki
  2. \n' + + '
  3. Työkalupalkin ryhmät
  4. \n' + + '
  5. Sivupalkki
  6. \n' + + '
  7. Elementin polku alatunnisteessa
  8. \n' + + '
  9. Sanalaskurin vaihtopainike alatunnisteessa
  10. \n' + + '
  11. Brändäyslinkki alatunnisteessa
  12. \n' + + '
  13. Editorin koon muuttamisen kahva alatunnisteessa
  14. \n' + + '
\n' + + '\n' + + '

Jos jotakin käyttöliittymän osaa ei ole, se ohitetaan.

\n' + + '\n' + + '

Jos kohdistus on siirretty alatunnisteeseen näppäimistönavigoinnilla eikä sivupalkkia ole näkyvissä, Shift+sarkainnäppäin\n' + + ' siirtää kohdistuksen työkalupalkin ensimmäiseen ryhmään, eikä viimeiseen.

\n' + + '\n' + + '

Käyttöliittymän eri osien sisällä navigointi

\n' + + '\n' + + '

Paina nuolinäppäimiä siirtyäksesi käyttöliittymäelementistä seuraavaan.

\n' + + '\n' + + '

Vasen- ja Oikea-nuolinäppäimet

\n' + + '\n' + + '
    \n' + + '
  • siirtävät sinua valikkopalkin valikoiden välillä.
  • \n' + + '
  • avaavat valikon alavalikon.
  • \n' + + '
  • siirtävät sinua työkalupalkin ryhmän painikkeiden välillä.
  • \n' + + '
  • siirtävät sinua kohteiden välillä alatunnisteen elementin polussa.
  • \n' + + '
\n' + + '\n' + + '

Alas- ja Ylös-nuolinäppäimet

\n' + + '\n' + + '
    \n' + + '
  • siirtävät sinua valikon valikkokohteiden välillä.
  • \n' + + '
  • siirtävät sinua työkalupalkin ponnahdusvalikon kohteiden välillä.
  • \n' + + '
\n' + + '\n' + + '

Nuolinäppäimet siirtävät sinua käyttöliittymän korostetun osan sisällä syklissä.

\n' + + '\n' + + '

Paina Esc-näppäintä sulkeaksesi avoimen valikon, avataksesi alavalikon tai avataksesi ponnahdusvalikon.

\n' + + '\n' + + '

Jos kohdistus on käyttöliittymän tietyn osion ylälaidassa, Esc-näppäimen painaminen\n' + + ' poistuu myös näppäimistönavigoinnista kokonaan.

\n' + + '\n' + + '

Suorita valikkokohde tai työkalupalkin painike

\n' + + '\n' + + '

Kun haluamasi valikkokohde tai työkalupalkin painike on korostettuna, paina Return-, Enter-\n' + + ' tai välilyöntinäppäintä suorittaaksesi kohteen.

\n' + + '\n' + + '

Välilehdittömissä valintaikkunoissa navigointi

\n' + + '\n' + + '

Kun välilehdetön valintaikkuna avautuu, kohdistus siirtyy sen ensimmäiseen interaktiiviseen komponenttiin.

\n' + + '\n' + + '

Voit siirtyä valintaikkunan interaktiivisten komponenttien välillä painamalla sarkainnäppäintä tai Shift+sarkainnäppäin.

\n' + + '\n' + + '

Välilehdellisissä valintaikkunoissa navigointi

\n' + + '\n' + + '

Kun välilehdellinen valintaikkuna avautuu, kohdistus siirtyy välilehtivalikon ensimmäiseen painikkeeseen.

\n' + + '\n' + + '

Voit siirtyä valintaikkunan välilehden interaktiivisen komponenttien välillä painamalla sarkainnäppäintä tai\n' + + ' Shift+sarkainnäppäin.

\n' + + '\n' + + '

Voit siirtyä valintaikkunan toiseen välilehteen siirtämällä kohdistuksen välilehtivalikkoon ja painamalla sopivaa nuolinäppäintä\n' + + ' siirtyäksesi käytettävissä olevien välilehtien välillä syklissä.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/fr_FR.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/fr_FR.js new file mode 100644 index 0000000..3f611e8 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/fr_FR.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.fr_FR', +'

Débuter la navigation au clavier

\n' + + '\n' + + '
\n' + + '
Cibler la barre du menu
\n' + + '
Windows ou Linux : Alt+F9
\n' + + '
macOS : ⌥F9
\n' + + "
Cibler la barre d'outils
\n" + + '
Windows ou Linux : Alt+F10
\n' + + '
macOS : ⌥F10
\n' + + '
Cibler le pied de page
\n' + + '
Windows ou Linux : Alt+F11
\n' + + '
macOS : ⌥F11
\n' + + '
Cibler la notification
\n' + + '
Windows ou Linux : Alt+F12
\n' + + '
macOS : ⌥F12
\n' + + "
Cibler une barre d'outils contextuelle
\n" + + '
Windows, Linux ou macOS : Ctrl+F9
\n' + + '
\n' + + '\n' + + "

La navigation débutera sur le premier élément de l'interface utilisateur, qui sera mis en surbrillance ou bien souligné dans le cas du premier élément du\n" + + " chemin d'éléments du pied de page.

\n" + + '\n' + + "

Naviguer entre les sections de l'interface utilisateur

\n" + + '\n' + + "

Pour passer d'une section de l'interface utilisateur à la suivante, appuyez sur Tabulation.

\n" + + '\n' + + "

Pour passer d'une section de l'interface utilisateur à la précédente, appuyez sur Maj+Tabulation.

\n" + + '\n' + + "

L'ordre de Tabulation de ces sections de l'interface utilisateur est le suivant :

\n" + + '\n' + + '
    \n' + + '
  1. Barre du menu
  2. \n' + + "
  3. Chaque groupe de barres d'outils
  4. \n" + + '
  5. Barre latérale
  6. \n' + + "
  7. Chemin d'éléments du pied de page
  8. \n" + + "
  9. Bouton d'activation du compteur de mots dans le pied de page
  10. \n" + + '
  11. Lien de marque dans le pied de page
  12. \n' + + "
  13. Poignée de redimensionnement de l'éditeur dans le pied de page
  14. \n" + + '
\n' + + '\n' + + "

Si une section de l'interface utilisateur n'est pas présente, elle sera ignorée.

\n" + + '\n' + + "

Si le pied de page comporte un ciblage par navigation au clavier et qu'il n'y a aucune barre latérale visible, appuyer sur Maj+Tabulation\n" + + " déplace le ciblage vers le premier groupe de barres d'outils et non le dernier.

\n" + + '\n' + + "

Naviguer au sein des sections de l'interface utilisateur

\n" + + '\n' + + "

Pour passer d'un élément de l'interface utilisateur au suivant, appuyez sur la Flèche appropriée.

\n" + + '\n' + + '

Les touches fléchées Gauche et Droite

\n' + + '\n' + + '
    \n' + + '
  • se déplacent entre les menus de la barre des menus.
  • \n' + + "
  • ouvrent un sous-menu au sein d'un menu.
  • \n" + + "
  • se déplacent entre les boutons d'un groupe de barres d'outils.
  • \n" + + "
  • se déplacent entre les éléments du chemin d'éléments du pied de page.
  • \n" + + '
\n' + + '\n' + + '

Les touches fléchées Bas et Haut

\n' + + '\n' + + '
    \n' + + "
  • se déplacent entre les éléments de menu au sein d'un menu.
  • \n" + + "
  • se déplacent entre les éléments au sein d'un menu contextuel de barre d'outils.
  • \n" + + '
\n' + + '\n' + + "

Les Flèches parcourent la section de l'interface utilisateur ciblée.

\n" + + '\n' + + '

Pour fermer un menu ouvert, un sous-menu ouvert ou un menu contextuel ouvert, appuyez sur Echap.

\n' + + '\n' + + "

Si l'actuel ciblage se trouve en « haut » d'une section spécifique de l'interface utilisateur, appuyer sur Echap permet également de quitter\n" + + ' entièrement la navigation au clavier.

\n' + + '\n' + + "

Exécuter un élément de menu ou un bouton de barre d'outils

\n" + + '\n' + + "

Lorsque l'élément de menu ou le bouton de barre d'outils désiré est mis en surbrillance, appuyez sur la touche Retour arrière, Entrée\n" + + " ou la Barre d'espace pour exécuter l'élément.

\n" + + '\n' + + '

Naviguer au sein de dialogues sans onglets

\n' + + '\n' + + "

Dans les dialogues sans onglets, le premier composant interactif est ciblé lorsque le dialogue s'ouvre.

\n" + + '\n' + + '

Naviguez entre les composants du dialogue interactif en appuyant sur Tabulation ou Maj+Tabulation.

\n' + + '\n' + + '

Naviguer au sein de dialogues avec onglets

\n' + + '\n' + + "

Dans les dialogues avec onglets, le premier bouton du menu de l'onglet est ciblé lorsque le dialogue s'ouvre.

\n" + + '\n' + + '

Naviguez entre les composants interactifs de cet onglet de dialogue en appuyant sur Tabulation ou\n' + + ' Maj+Tabulation.

\n' + + '\n' + + "

Passez à un autre onglet de dialogue en ciblant le menu de l'onglet et en appuyant sur la Flèche\n" + + ' appropriée pour parcourir les onglets disponibles.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/he_IL.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/he_IL.js new file mode 100644 index 0000000..7d6513a --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/he_IL.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.he_IL', +'

התחל ניווט במקלדת

\n' + + '\n' + + '
\n' + + '
התמקד בשורת התפריטים
\n' + + '
Windows או Linux:‏ Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
העבר מיקוד לסרגל הכלים
\n' + + '
Windows או Linux:‏ Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
העבר מיקוד לכותרת התחתונה
\n' + + '
Windows או Linux:‏ Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
העבר מיקוד להודעה
\n' + + '
Windows או Linux:‏ Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
העבר מיקוד לסרגל כלים הקשרי
\n' + + '
Windows‏, Linux או macOS:‏ Ctrl+F9
\n' + + '
\n' + + '\n' + + '

הניווט יתחיל ברכיב הראשון במשך, שיודגש או שיהיה מתחתיו קו תחתון במקרה של הפריט הראשון\n' + + ' הנתיב של רכיב הכותרת התחתונה.

\n' + + '\n' + + '

עבור בין מקטעים במסך

\n' + + '\n' + + '

כדי לעבור בין המקטעים במסך, הקש Tab.

\n' + + '\n' + + '

כדי לעבור למקטע הקודם במסך, הקש Shift+Tab.

\n' + + '\n' + + '

הסדר מבחינת מקש Tab של הרכיבים במסך:

\n' + + '\n' + + '
    \n' + + '
  1. שורת התפריטים
  2. \n' + + '
  3. כל קבוצה בסרגל הכלים
  4. \n' + + '
  5. הסרגל הצידי
  6. \n' + + '
  7. נתיב של רכיב בכותרת התחתונה
  8. \n' + + '
  9. לחצן לספירת מילים בכותרת התחתונה
  10. \n' + + '
  11. קישור של המותג בכותרת התחתונה
  12. \n' + + '
  13. ידית לשינוי גודל עבור העורך בכותרת התחתונה
  14. \n' + + '
\n' + + '\n' + + '

אם רכיב כלשהו במסך לא מופיע, המערכת תדלג עליו.

\n' + + '\n' + + '

אם בכותרת התחתונה יש מיקוד של ניווט במקלדת, ולא מופיע סרגל בצד, יש להקיש Shift+Tab\n' + + ' מעביר את המיקוד לקבוצה הראשונה בסרגל הכלים, לא האחרונה.

\n' + + '\n' + + '

עבור בתוך מקטעים במסך

\n' + + '\n' + + '

כדי לעבור מרכיב אחד לרכיב אחר במסך, הקש על מקש החץ המתאים.

\n' + + '\n' + + '

מקשי החיצים שמאלה וימינה

\n' + + '\n' + + '
    \n' + + '
  • עבור בין תפריטים בשורת התפריטים.
  • \n' + + '
  • פתח תפריט משני בתפריט.
  • \n' + + '
  • עבור בין לחצנים בקבוצה בסרגל הכלים.
  • \n' + + '
  • עבור בין פריטים ברכיב בכותרת התחתונה.
  • \n' + + '
\n' + + '\n' + + '

מקשי החיצים למטה ולמעלה

\n' + + '\n' + + '
    \n' + + '
  • עבור בין פריטים בתפריט.
  • \n' + + '
  • עבור בין פריטים בחלון הקובץ של סרגל הכלים.
  • \n' + + '
\n' + + '\n' + + '

מקשי החצים משתנים בתוך המקטע במסך שעליו נמצא המיקוד.

\n' + + '\n' + + '

כדי לסגור תפריט פתוח, תפריט משני פתוח או חלון קופץ, הקש על Esc.

\n' + + '\n' + + "

אם המיקוד הוא על החלק 'העליון' של מקטע מסוים במסך, הקשה על Esc מביאה גם ליציאה\n" + + ' מהניווט במקלדת לחלוטין.

\n' + + '\n' + + '

הפעל פריט בתפריט או לחצן בסרגל הכלים

\n' + + '\n' + + '

כאשר הפריט הרצוי בתפריט או הלחצן בסרגל הכלים מודגשים, הקש על Return, Enter,\n' + + ' או על מקש הרווח כדי להפעיל את הפריט.

\n' + + '\n' + + '

ניווט בחלונות דו-שיח בלי כרטיסיות

\n' + + '\n' + + '

בחלונות דו-שיח בלי כרטיסיות, הרכיב האינטראקטיבי הראשון מקבל את המיקוד כאשר החלון נפתח.

\n' + + '\n' + + '

עבור בין רכיבים אינטראקטיביים בחלון על ידי הקשה על Tab או Shift+Tab.

\n' + + '\n' + + '

ניווט בחלונות דו-שיח עם כרטיסיות

\n' + + '\n' + + '

בחלונות דו-שיח עם כרטיסיות, הלחצן הראשון בתפריט מקבל את המיקוד כאשר החלון נפתח.

\n' + + '\n' + + '

עבור בין רכיבים אינטראקטיביים בחלון על ידי הקשה על Tab או\n' + + ' Shift+Tab.

\n' + + '\n' + + '

עבור לכרטיסיה אחרת בחלון על ידי העברת המיקוד לתפריט הכרטיסיות והקשה על החץהמתאים\n' + + ' כדי לעבור בין הכרטיסיות הזמינות.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/hi.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/hi.js new file mode 100644 index 0000000..ef59a5c --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/hi.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.hi', +'

कीबोर्ड नेविगेशन शुरू करें

\n' + + '\n' + + '
\n' + + '
मेन्यू बार पर फ़ोकस करें
\n' + + '
Windows या Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
टूलबार पर फ़ोकस करें
\n' + + '
Windows या Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
फ़ुटर पर फ़ोकस करें
\n' + + '
Windows या Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
नोटिफ़िकेशन फ़ोकस
\n' + + '
Windows या Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
प्रासंगिक टूलबार पर फ़ोकस करें
\n' + + '
Windows, Linux या macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

नेविगेशन पहले UI आइटम पर शुरू होगा, जिसे हाइलाइट किया जाएगा या पहले आइटम के मामले में फ़ुटर तत्व पथ में\n' + + ' रेखांकित किया जाएगा।

\n' + + '\n' + + '

UI सेक्शन के बीच नेविगेट करें

\n' + + '\n' + + '

एक UI सेक्शन से दूसरे सेक्शन में जाने के लिए, Tab दबाएं।

\n' + + '\n' + + '

एक UI सेक्शन से पिछले सेक्शन में जाने के लिए, Shift+Tab दबाएं।

\n' + + '\n' + + '

इन UI सेक्शन का Tab क्रम नीचे दिया गया है:

\n' + + '\n' + + '
    \n' + + '
  1. मेन्यू बार
  2. \n' + + '
  3. प्रत्येक टूलबार समूह
  4. \n' + + '
  5. साइडबार
  6. \n' + + '
  7. फ़ुटर में तत्व पथ
  8. \n' + + '
  9. फ़ुटर में शब्द गणना टॉगल बटन
  10. \n' + + '
  11. फ़ुटर में ब्रांडिंग लिंक
  12. \n' + + '
  13. फ़ुटर में संपादक का आकार बदलने का हैंडल
  14. \n' + + '
\n' + + '\n' + + '

अगर कोई UI सेक्शन मौजूद नहीं है, तो उसे छोड़ दिया जाता है।

\n' + + '\n' + + '

अगर फ़ुटर में कीबोर्ड नेविगेशन फ़ोकस है, और कोई दिखा देने वाला साइडबार नहीं है, तो Shift+Tab दबाने से\n' + + ' फ़ोकस पहले टूलबार समूह पर चला जाता है, पिछले पर नहीं।

\n' + + '\n' + + '

UI सेक्शन के भीतर नेविगेट करें

\n' + + '\n' + + '

एक UI तत्व से दूसरे में जाने के लिए उपयुक्त ऐरो कुंजी दबाएं।

\n' + + '\n' + + '

बाएं और दाएं ऐरो कुंजियां

\n' + + '\n' + + '
    \n' + + '
  • मेन्यू बार में मेन्यू के बीच ले जाती हैं।
  • \n' + + '
  • मेन्यू में एक सब-मेन्यू खोलें।
  • \n' + + '
  • टूलबार समूह में बटनों के बीच ले जाएं।
  • \n' + + '
  • फ़ुटर के तत्व पथ में आइटम के बीच ले जाएं।
  • \n' + + '
\n' + + '\n' + + '

नीचे और ऊपर ऐरो कुंजियां

\n' + + '\n' + + '
    \n' + + '
  • मेन्यू में मेन्यू आइटम के बीच ले जाती हैं।
  • \n' + + '
  • टूलबार पॉप-अप मेन्यू में आइटम के बीच ले जाएं।
  • \n' + + '
\n' + + '\n' + + '

फ़ोकस वाले UI सेक्शन के भीतर ऐरो कुंजियां चलाती रहती हैं।

\n' + + '\n' + + '

कोई खुला मेन्यू, कोई खुला सब-मेन्यू या कोई खुला पॉप-अप मेन्यू बंद करने के लिए Esc कुंजी दबाएं।

\n' + + '\n' + + "

अगर मौजूदा फ़ोकस किसी विशेष UI सेक्शन के 'शीर्ष' पर है, तो Esc कुंजी दबाने से भी\n" + + ' कीबोर्ड नेविगेशन पूरी तरह से बाहर हो जाता है।

\n' + + '\n' + + '

मेन्यू आइटम या टूलबार बटन निष्पादित करें

\n' + + '\n' + + '

जब वांछित मेन्यू आइटम या टूलबार बटन हाइलाइट किया जाता है, तो आइटम को निष्पादित करने के लिए Return, Enter,\n' + + ' या Space bar दबाएं।

\n' + + '\n' + + '

गैर-टैब वाले डायलॉग पर नेविगेट करें

\n' + + '\n' + + '

गैर-टैब वाले डायलॉग में, डायलॉग खुलने पर पहला इंटरैक्टिव घटक फ़ोकस लेता है।

\n' + + '\n' + + '

Tab or Shift+Tab दबाकर इंटरैक्टिव डायलॉग घटकों के बीच नेविगेट करें।

\n' + + '\n' + + '

टैब किए गए डायलॉग पर नेविगेट करें

\n' + + '\n' + + '

टैब किए गए डायलॉग में, डायलॉग खुलने पर टैब मेन्यू में पहला बटन फ़ोकस लेता है।

\n' + + '\n' + + '

इस डायलॉग टैब के इंटरैक्टिव घटकों के बीच नेविगेट करने के लिए Tab या\n' + + ' Shift+Tab दबाएं।

\n' + + '\n' + + '

टैब मेन्यू को फ़ोकस देकर और फिर उपलब्ध टैब में के बीच जाने के लिए उपयुक्त ऐरो\n' + + ' कुंजी दबाकर दूसरे डायलॉग टैब पर स्विच करें।

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/hr.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/hr.js new file mode 100644 index 0000000..1bf35c5 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/hr.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.hr', +'

Početak navigacije na tipkovnici

\n' + + '\n' + + '
\n' + + '
Fokusiranje trake izbornika
\n' + + '
Windows ili Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Fokusiranje alatne trake
\n' + + '
Windows ili Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Fokusiranje podnožja
\n' + + '
Windows ili Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Fokusiranje obavijesti
\n' + + '
Windows ili Linux: Alt + F12
\n' + + '
macOS: ⌥F12
\n' + + '
Fokusiranje kontekstne alatne trake
\n' + + '
Windows, Linux ili macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Navigacija će započeti kod prve stavke na korisničkom sučelju, koja će biti istaknuta ili podcrtana ako se radi o prvoj stavci u\n' + + ' putu elementa u podnožju.

\n' + + '\n' + + '

Navigacija između dijelova korisničkog sučelja

\n' + + '\n' + + '

Za pomicanje s jednog dijela korisničkog sučelja na drugi pritisnite tabulator.

\n' + + '\n' + + '

Za pomicanje s jednog dijela korisničkog sučelja na prethodni pritisnite Shift + tabulator.

\n' + + '\n' + + '

Ovo je redoslijed pomicanja tabulatora po dijelovima korisničkog sučelja:

\n' + + '\n' + + '
    \n' + + '
  1. Traka izbornika
  2. \n' + + '
  3. Pojedinačne grupe na alatnoj traci
  4. \n' + + '
  5. Bočna traka
  6. \n' + + '
  7. Put elemenata u podnožju
  8. \n' + + '
  9. Gumb za pomicanje po broju riječi u podnožju
  10. \n' + + '
  11. Veza na brand u podnožju
  12. \n' + + '
  13. Značajka za promjenu veličine alata za uređivanje u podnožju
  14. \n' + + '
\n' + + '\n' + + '

Ako neki dio korisničkog sučelja nije naveden, on se preskače.

\n' + + '\n' + + '

Ako u podnožju postoji fokus za navigaciju na tipkovnici, a nema vidljive bočne trake, pritiskom na Shift + tabulator\n' + + ' fokus se prebacuje na prvu skupinu na alatnoj traci, ne na zadnju.

\n' + + '\n' + + '

Navigacija unutar dijelova korisničkog sučelja

\n' + + '\n' + + '

Za pomicanje s jednog elementa korisničkog sučelja na drugi pritisnite tipku s odgovarajućom strelicom.

\n' + + '\n' + + '

Tipke s lijevom i desnom strelicom

\n' + + '\n' + + '
    \n' + + '
  • služe za pomicanje između izbornika na alatnoj traci.
  • \n' + + '
  • otvaraju podizbornik unutar izbornika.
  • \n' + + '
  • služe za pomicanje između gumba unutar skupina na alatnoj traci.
  • \n' + + '
  • služe za pomicanje između stavki na elementu puta u podnožju.
  • \n' + + '
\n' + + '\n' + + '

Tipke s donjom i gornjom strelicom

\n' + + '\n' + + '
    \n' + + '
  • služe za pomicanje između stavki unutar izbornika.
  • \n' + + '
  • služe za pomicanje između stavki na alatnoj traci skočnog izbornika.
  • \n' + + '
\n' + + '\n' + + '

Tipkama strelica kružno se pomičete unutar dijela korisničkog sučelja koji je u fokusu.

\n' + + '\n' + + '

Za zatvaranje otvorenog izbornika, otvorenog podizbornika ili otvorenog skočnog izbornika pritisnite tipku Esc.

\n' + + '\n' + + '

Ako je fokus trenutačno postavljen na vrh pojedinačnog dijela korisničkog sučelja, pritiskom na tipku Esc također\n' + + ' u potpunosti zatvarate navigaciju na tipkovnici.

\n' + + '\n' + + '

Izvršavanje radnji putem stavki izbornika ili gumba na alatnoj traci

\n' + + '\n' + + '

Nakon što se istakne stavka izbornika ili gumb na alatnoj traci s radnjom koju želite izvršiti, pritisnite tipku Return, Enter\n' + + ' ili razmak da biste pokrenuli željenu radnju.

\n' + + '\n' + + '

Navigacija dijaloškim okvirima izvan kartica

\n' + + '\n' + + '

Prilikom otvaranja dijaloških okvira izvan kartica fokus se nalazi na prvoj interaktivnoj komponenti.

\n' + + '\n' + + '

Navigaciju između interaktivnih dijaloških komponenata vršite pritiskom na tabulator ili Shift + tabulator.

\n' + + '\n' + + '

Navigacija dijaloškim okvirima u karticama

\n' + + '\n' + + '

Prilikom otvaranja dijaloških okvira u karticama fokus se nalazi na prvom gumbu u izborniku unutar kartice.

\n' + + '\n' + + '

Navigaciju između interaktivnih komponenata dijaloškog okvira u kartici vršite pritiskom na tabulator ili\n' + + ' Shift + tabulator.

\n' + + '\n' + + '

Na karticu s drugim dijaloškim okvirom možete se prebaciti tako da stavite fokus na izbornik kartice pa pritisnete tipku s odgovarajućom strelicom\n' + + ' za kružno pomicanje između dostupnih kartica.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/hu_HU.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/hu_HU.js new file mode 100644 index 0000000..5c984bb --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/hu_HU.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.hu_HU', +'

Billentyűzetes navigáció indítása

\n' + + '\n' + + '
\n' + + '
Fókusz a menüsávra
\n' + + '
Windows és Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Fókusz az eszköztárra
\n' + + '
Windows és Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Fókusz a láblécre
\n' + + '
Windows és Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Ráközelítés az értesítésre
\n' + + '
Windows vagy Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Fókusz egy környezetfüggő eszköztárra
\n' + + '
Windows, Linux és macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

A navigáció az első felhasználói felületi elemnél kezdődik, amelyet a rendszer kiemel, illetve aláhúz, amennyiben az az első elem\n' + + ' a lábléc elemútvonalán.

\n' + + '\n' + + '

Navigálás a felhasználói felület szakaszai között

\n' + + '\n' + + '

A felhasználói felület következő szakaszára váltáshoz nyomja meg a Tab billentyűt.

\n' + + '\n' + + '

A felhasználói felület előző szakaszára váltáshoz nyomja meg a Shift+Tab billentyűt.

\n' + + '\n' + + '

A Tab billentyűvel a felhasználói felület szakaszai között a következő sorrendben vált:

\n' + + '\n' + + '
    \n' + + '
  1. Menüsáv
  2. \n' + + '
  3. Az egyes eszköztárcsoportok
  4. \n' + + '
  5. Oldalsáv
  6. \n' + + '
  7. Elemútvonal a láblécen
  8. \n' + + '
  9. Szószámátkapcsoló gomb a láblécen
  10. \n' + + '
  11. Márkalink a láblécen
  12. \n' + + '
  13. Szerkesztő átméretezési fogópontja a láblécen
  14. \n' + + '
\n' + + '\n' + + '

Ha a felhasználói felület valamelyik eleme nincs jelen, a rendszer kihagyja.

\n' + + '\n' + + '

Ha a billentyűzetes navigáció fókusza a láblécen van, és nincs látható oldalsáv, a Shift+Tab\n' + + ' billentyűkombináció lenyomásakor az első eszköztárcsoportra ugrik a fókusz, nem az utolsóra.

\n' + + '\n' + + '

Navigálás a felhasználói felület szakaszain belül

\n' + + '\n' + + '

A felhasználói felület következő elemére váltáshoz nyomja meg a megfelelő nyílbillentyűt.

\n' + + '\n' + + '

A bal és a jobb nyílgomb

\n' + + '\n' + + '
    \n' + + '
  • a menüsávban a menük között vált.
  • \n' + + '
  • a menükben megnyit egy almenüt.
  • \n' + + '
  • az eszköztárcsoportban a gombok között vált.
  • \n' + + '
  • a lábléc elemútvonalán az elemek között vált.
  • \n' + + '
\n' + + '\n' + + '

A le és a fel nyílgomb

\n' + + '\n' + + '
    \n' + + '
  • a menükben a menüpontok között vált.
  • \n' + + '
  • az eszköztár előugró menüjében az elemek között vált.
  • \n' + + '
\n' + + '\n' + + '

A nyílbillentyűk lenyomásával körkörösen lépkedhet a fókuszban lévő felhasználói felületi szakasz elemei között.

\n' + + '\n' + + '

A megnyitott menüket, almenüket és előugró menüket az Esc billentyűvel zárhatja be.

\n' + + '\n' + + '

Ha a fókusz az aktuális felületi elem „felső” részén van, az Esc billentyűvel az egész\n' + + ' billentyűzetes navigációból kilép.

\n' + + '\n' + + '

Menüpont vagy eszköztárgomb aktiválása

\n' + + '\n' + + '

Amikor a kívánt menüelem vagy eszköztárgomb van kijelölve, nyomja meg a Return, az Enter\n' + + ' vagy a Szóköz billentyűt az adott elem vagy gomb aktiválásához.

\n' + + '\n' + + '

Navigálás a lapokkal nem rendelkező párbeszédablakokban

\n' + + '\n' + + '

A lapokkal nem rendelkező párbeszédablakokban az első interaktív összetevő kapja a fókuszt, amikor a párbeszédpanel megnyílik.

\n' + + '\n' + + '

A párbeszédpanelek interaktív összetevői között a Tab vagy a Shift+Tab billentyűvel navigálhat.

\n' + + '\n' + + '

Navigálás a lapokkal rendelkező párbeszédablakokban

\n' + + '\n' + + '

A lapokkal rendelkező párbeszédablakokban a lapmenü első gombja kapja a fókuszt, amikor a párbeszédpanel megnyílik.

\n' + + '\n' + + '

A párbeszédpanel e lapjának interaktív összetevői között a Tab vagy\n' + + ' Shift+Tab billentyűvel navigálhat.

\n' + + '\n' + + '

A párbeszédablak másik lapjára úgy léphet, hogy a fókuszt a lapmenüre állítja, majd lenyomja a megfelelő nyílbillentyűt\n' + + ' a rendelkezésre álló lapok közötti lépkedéshez.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/id.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/id.js new file mode 100644 index 0000000..d607dd1 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/id.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.id', +'

Memulai navigasi keyboard

\n' + + '\n' + + '
\n' + + '
Fokus pada bilah Menu
\n' + + '
Windows atau Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Fokus pada Bilah Alat
\n' + + '
Windows atau Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Fokus pada footer
\n' + + '
Windows atau Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Fokuskan pemberitahuan
\n' + + '
Windows atau Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Fokus pada bilah alat kontekstual
\n' + + '
Windows, Linux, atau macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Navigasi akan dimulai dari item pertama UI, yang akan disorot atau digarisbawahi di\n' + + ' alur elemen Footer.

\n' + + '\n' + + '

Berpindah antar-bagian UI

\n' + + '\n' + + '

Untuk berpindah dari satu bagian UI ke bagian berikutnya, tekan Tab.

\n' + + '\n' + + '

Untuk berpindah dari satu bagian UI ke bagian sebelumnya, tekan Shift+Tab.

\n' + + '\n' + + '

Urutan Tab bagian-bagian UI ini adalah:

\n' + + '\n' + + '
    \n' + + '
  1. Bilah menu
  2. \n' + + '
  3. Tiap grup bilah alat
  4. \n' + + '
  5. Bilah sisi
  6. \n' + + '
  7. Alur elemen di footer
  8. \n' + + '
  9. Tombol aktifkan/nonaktifkan jumlah kata di footer
  10. \n' + + '
  11. Tautan merek di footer
  12. \n' + + '
  13. Pengatur pengubahan ukuran editor di footer
  14. \n' + + '
\n' + + '\n' + + '

Jika suatu bagian UI tidak ada, bagian tersebut dilewati.

\n' + + '\n' + + '

Jika fokus navigasi keyboard ada pada footer, tetapi tidak ada bilah sisi yang terlihat, menekan Shift+Tab\n' + + ' akan memindahkan fokus ke grup bilah alat pertama, bukan yang terakhir.

\n' + + '\n' + + '

Berpindah di dalam bagian-bagian UI

\n' + + '\n' + + '

Untuk berpindah dari satu elemen UI ke elemen berikutnya, tekan tombol Panah yang sesuai.

\n' + + '\n' + + '

Tombol panah Kiri dan Kanan untuk

\n' + + '\n' + + '
    \n' + + '
  • berpindah-pindah antar-menu di dalam bilah menu.
  • \n' + + '
  • membuka sub-menu di dalam menu.
  • \n' + + '
  • berpindah-pindah antar-tombol di dalam grup bilah alat.
  • \n' + + '
  • berpindah-pindah antar-item di dalam alur elemen footer.
  • \n' + + '
\n' + + '\n' + + '

Tombol panah Bawah dan Atas untuk

\n' + + '\n' + + '
    \n' + + '
  • berpindah-pindah antar-item menu di dalam menu.
  • \n' + + '
  • berpindah-pindah antar-item di dalam menu pop-up bilah alat.
  • \n' + + '
\n' + + '\n' + + '

Tombol Panah hanya bergerak di dalam bagian UI yang difokuskan.

\n' + + '\n' + + '

Untuk menutup menu, sub-menu, atau menu pop-up yang terbuka, tekan tombol Esc.

\n' + + '\n' + + '

Jika fokus sedang berada di ‘atas’ bagian UI tertentu, menekan tombol Esc juga dapat mengeluarkan fokus\n' + + ' dari seluruh navigasi keyboard.

\n' + + '\n' + + '

Menjalankan item menu atau tombol bilah alat

\n' + + '\n' + + '

Jika item menu atau tombol bilah alat yang diinginkan tersorot, tekan Return, Enter,\n' + + ' atau Spasi untuk menjalankan item.

\n' + + '\n' + + '

Berpindah dalam dialog tanpa tab

\n' + + '\n' + + '

Dalam dialog tanpa tab, fokus diarahkan pada komponen interaktif pertama saat dialog terbuka.

\n' + + '\n' + + '

Berpindah di antara komponen dalam dialog interaktif dengan menekan Tab atau Shift+Tab.

\n' + + '\n' + + '

Berpindah dalam dialog dengan tab

\n' + + '\n' + + '

Dalam dialog yang memiliki tab, fokus diarahkan pada tombol pertama di dalam menu saat dialog terbuka.

\n' + + '\n' + + '

Berpindah di antara komponen-komponen interaktif pada tab dialog ini dengan menekan Tab atau\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Beralih ke tab dialog lain dengan mengarahkan fokus pada menu tab lalu tekan tombol Panah\n' + + ' yang sesuai untuk berpindah ke berbagai tab yang tersedia.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/it.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/it.js new file mode 100644 index 0000000..3a791c9 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/it.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.it', +'

Iniziare la navigazione tramite tastiera

\n' + + '\n' + + '
\n' + + '
Impostare lo stato attivo per la barra dei menu
\n' + + '
Windows o Linux: ALT+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Impostare lo stato attivo per la barra degli strumenti
\n' + + '
Windows o Linux: ALT+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Impostare lo stato attivo per il piè di pagina
\n' + + '
Windows o Linux: ALT+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Metti a fuoco la notifica
\n' + + '
Windows o Linux: ALT+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Impostare lo stato attivo per la barra degli strumenti contestuale
\n' + + '
Windows, Linux o macOS: CTRL+F9
\n' + + '
\n' + + '\n' + + "

La navigazione inizierà dalla prima voce dell'interfaccia utente, che sarà evidenziata o sottolineata nel caso della prima voce\n" + + " nel percorso dell'elemento del piè di pagina.

\n" + + '\n' + + "

Navigare tra le sezioni dell'interfaccia utente

\n" + + '\n' + + "

Per passare da una sezione dell'interfaccia utente alla successiva, premere TAB.

\n" + + '\n' + + "

Per passare da una sezione dell'interfaccia utente alla precedente, premere MAIUSC+TAB.

\n" + + '\n' + + "

L'ordine di tabulazione di queste sezioni dell'interfaccia utente è:

\n" + + '\n' + + '
    \n' + + '
  1. Barra dei menu
  2. \n' + + '
  3. Ogni gruppo di barre degli strumenti
  4. \n' + + '
  5. Barra laterale
  6. \n' + + "
  7. Percorso dell'elemento nel piè di pagina
  8. \n" + + '
  9. Pulsante di attivazione/disattivazione del conteggio delle parole nel piè di pagina
  10. \n' + + '
  11. Collegamento al marchio nel piè di pagina
  12. \n' + + "
  13. Quadratino di ridimensionamento dell'editor nel piè di pagina
  14. \n" + + '
\n' + + '\n' + + "

Se una sezione dell'interfaccia utente non è presente, viene saltata.

\n" + + '\n' + + '

Se il piè di pagina ha lo stato attivo per la navigazione tramite tastiera e non è presente alcuna barra laterale visibile, premendo MAIUSC+TAB\n' + + " si sposta lo stato attivo sul primo gruppo di barre degli strumenti, non sull'ultimo.

\n" + + '\n' + + "

Navigare all'interno delle sezioni dell'interfaccia utente

\n" + + '\n' + + "

Per passare da un elemento dell'interfaccia utente al successivo, premere il tasto freccia appropriato.

\n" + + '\n' + + '

I tasti freccia Sinistra e Destra

\n' + + '\n' + + '
    \n' + + '
  • consentono di spostarsi tra i menu della barra dei menu.
  • \n' + + '
  • aprono un sottomenu in un menu.
  • \n' + + '
  • consentono di spostarsi tra i pulsanti di un gruppo di barre degli strumenti.
  • \n' + + "
  • consentono di spostarsi tra le voci nel percorso dell'elemento del piè di pagina.
  • \n" + + '
\n' + + '\n' + + '

I tasti freccia Giù e Su

\n' + + '\n' + + '
    \n' + + '
  • consentono di spostarsi tra le voci di un menu.
  • \n' + + '
  • consentono di spostarsi tra le voci di un menu a comparsa della barra degli strumenti.
  • \n' + + '
\n' + + '\n' + + "

I tasti freccia consentono di spostarsi all'interno della sezione dell'interfaccia utente con stato attivo.

\n" + + '\n' + + '

Per chiudere un menu aperto, un sottomenu aperto o un menu a comparsa aperto, premere il tasto ESC.

\n' + + '\n' + + "

Se lo stato attivo corrente si trova nella parte superiore di una particolare sezione dell'interfaccia utente, premendo il tasto ESC si esce\n" + + ' completamente dalla navigazione tramite tastiera.

\n' + + '\n' + + '

Eseguire una voce di menu o un pulsante della barra degli strumenti

\n' + + '\n' + + '

Quando la voce di menu o il pulsante della barra degli strumenti desiderati sono evidenziati, premere il tasto diritorno a capo, il tasto Invio\n' + + ' o la barra spaziatrice per eseguirli.

\n' + + '\n' + + '

Navigare nelle finestre di dialogo non a schede

\n' + + '\n' + + "

Nelle finestre di dialogo non a schede, all'apertura della finestra di dialogo diventa attivo il primo componente interattivo.

\n" + + '\n' + + '

Per spostarsi tra i componenti interattivi della finestra di dialogo, premere TAB o MAIUSC+TAB.

\n' + + '\n' + + '

Navigare nelle finestre di dialogo a schede

\n' + + '\n' + + "

Nelle finestre di dialogo a schede, all'apertura della finestra di dialogo diventa attivo il primo pulsante del menu della scheda.

\n" + + '\n' + + '

Per spostarsi tra i componenti interattivi di questa scheda della finestra di dialogo, premere TAB o\n' + + ' MAIUSC+TAB.

\n' + + '\n' + + "

Per passare a un'altra scheda della finestra di dialogo, attivare il menu della scheda e premere il tasto freccia\n" + + ' appropriato per scorrere le schede disponibili.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ja.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ja.js new file mode 100644 index 0000000..26872db --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ja.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.ja', +'

キーボード ナビゲーションの開始

\n' + + '\n' + + '
\n' + + '
メニュー バーをフォーカス
\n' + + '
Windows または Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
ツール バーをフォーカス
\n' + + '
Windows または Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
フッターをフォーカス
\n' + + '
Windows または Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
通知にフォーカス
\n' + + '
Windows または Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
コンテキスト ツール バーをフォーカス
\n' + + '
Windows、Linux または macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

ナビゲーションは最初の UI 項目から開始され、強調表示されるか、フッターの要素パスにある最初の項目の場合は\n' + + ' 下線が引かれます。

\n' + + '\n' + + '

UI セクション間の移動

\n' + + '\n' + + '

次の UI セクションに移動するには、Tab を押します。

\n' + + '\n' + + '

前の UI セクションに移動するには、Shift+Tab を押します。

\n' + + '\n' + + '

これらの UI セクションの Tab の順序:

\n' + + '\n' + + '
    \n' + + '
  1. メニュー バー
  2. \n' + + '
  3. 各ツール バー グループ
  4. \n' + + '
  5. サイド バー
  6. \n' + + '
  7. フッターの要素パス
  8. \n' + + '
  9. フッターの単語数切り替えボタン
  10. \n' + + '
  11. フッターのブランド リンク
  12. \n' + + '
  13. フッターのエディター サイズ変更ハンドル
  14. \n' + + '
\n' + + '\n' + + '

UI セクションが存在しない場合は、スキップされます。

\n' + + '\n' + + '

フッターにキーボード ナビゲーション フォーカスがあり、表示可能なサイド バーがない場合、Shift+Tab を押すと、\n' + + ' フォーカスが最後ではなく最初のツール バー グループに移動します。

\n' + + '\n' + + '

UI セクション内の移動

\n' + + '\n' + + '

次の UI 要素に移動するには、適切な矢印キーを押します。

\n' + + '\n' + + '

左矢印右矢印のキー

\n' + + '\n' + + '
    \n' + + '
  • メニュー バーのメニュー間で移動します。
  • \n' + + '
  • メニュー内のサブメニューを開きます。
  • \n' + + '
  • ツール バー グループのボタン間で移動します。
  • \n' + + '
  • フッターの要素パスの項目間で移動します。
  • \n' + + '
\n' + + '\n' + + '

下矢印上矢印のキー

\n' + + '\n' + + '
    \n' + + '
  • メニュー内のメニュー項目間で移動します。
  • \n' + + '
  • ツール バー ポップアップ メニュー内のメニュー項目間で移動します。
  • \n' + + '
\n' + + '\n' + + '

矢印キーで、フォーカスされた UI セクション内で循環します。

\n' + + '\n' + + '

開いたメニュー、開いたサブメニュー、開いたポップアップ メニューを閉じるには、Esc キーを押します。

\n' + + '\n' + + '

現在のフォーカスが特定の UI セクションの「一番上」にある場合、Esc キーを押すと\n' + + ' キーボード ナビゲーションも完全に閉じられます。

\n' + + '\n' + + '

メニュー項目またはツール バー ボタンの実行

\n' + + '\n' + + '

目的のメニュー項目やツール バー ボタンが強調表示されている場合、リターンEnter、\n' + + ' またはスペース キーを押して項目を実行します。

\n' + + '\n' + + '

タブのないダイアログの移動

\n' + + '\n' + + '

タブのないダイアログでは、ダイアログが開くと最初の対話型コンポーネントがフォーカスされます。

\n' + + '\n' + + '

Tab または Shift+Tab を押して、対話型ダイアログ コンポーネント間で移動します。

\n' + + '\n' + + '

タブ付きダイアログの移動

\n' + + '\n' + + '

タブ付きダイアログでは、ダイアログが開くとタブ メニューの最初のボタンがフォーカスされます。

\n' + + '\n' + + '

Tab または\n' + + ' Shift+Tab を押して、このダイアログ タブの対話型コンポーネント間で移動します。

\n' + + '\n' + + '

タブ メニューをフォーカスしてから適切な矢印キーを押して表示可能なタブを循環して、\n' + + ' 別のダイアログに切り替えます。

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/kk.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/kk.js new file mode 100644 index 0000000..e31532f --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/kk.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.kk', +'

Пернетақта навигациясын бастау

\n' + + '\n' + + '
\n' + + '
Мәзір жолағын фокустау
\n' + + '
Windows немесе Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Құралдар тақтасын фокустау
\n' + + '
Windows немесе Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Төменгі деректемені фокустау
\n' + + '
Windows немесе Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Хабарландыруды белгілеу
\n' + + '
Windows немесе Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Мәтінмәндік құралдар тақтасын фокустау
\n' + + '
Windows, Linux немесе macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Навигация бөлектелетін немесе Төменгі деректеме элементінің жолындағы бірінші элемент жағдайында асты сызылатын\n' + + ' бірінші ПИ элементінен басталады.

\n' + + '\n' + + '

ПИ бөлімдері арасында навигациялау

\n' + + '\n' + + '

Бір ПИ бөлімінен келесісіне өту үшін Tab пернесін басыңыз.

\n' + + '\n' + + '

Бір ПИ бөлімінен алдыңғысына өту үшін Shift+Tab пернесін басыңыз.

\n' + + '\n' + + '

Осы ПИ бөлімдерінің Tab реті:

\n' + + '\n' + + '
    \n' + + '
  1. Мәзір жолағы
  2. \n' + + '
  3. Әрбір құралдар тақтасы тобы
  4. \n' + + '
  5. Бүйірлік жолақ
  6. \n' + + '
  7. Төменгі деректемедегі элемент жолы
  8. \n' + + '
  9. Төменгі деректемедегі сөздер санын ауыстыру түймесі
  10. \n' + + '
  11. Төменгі деректемедегі брендингтік сілтеме
  12. \n' + + '
  13. Төменгі деректемедегі редактор өлшемін өзгерту тұтқасы
  14. \n' + + '
\n' + + '\n' + + '

ПИ бөлімі көрсетілмесе, ол өткізіп жіберіледі.

\n' + + '\n' + + '

Төменгі деректемеде пернетақта навигациясының фокусы болса және бүйірлік жолақ көрінбесе, Shift+Tab тіркесімін басу әрекеті\n' + + ' фокусты соңғысы емес, бірінші құралдар тақтасы тобына жылжытады.

\n' + + '\n' + + '

ПИ бөлімдерінде навигациялау

\n' + + '\n' + + '

Бір ПИ элементінен келесісіне өту үшін Arrow (Көрсеткі) пернесін басыңыз.

\n' + + '\n' + + '

Left (Сол жақ) және Right (Оң жақ) көрсеткі пернелері

\n' + + '\n' + + '
    \n' + + '
  • мәзір жолағындағы мәзірлер арасында жылжыту.
  • \n' + + '
  • мәзірде ішкі мәзірді ашу.
  • \n' + + '
  • құралдар тақтасы тобындағы түймелер арасында жылжыту.
  • \n' + + '
  • төменгі деректеме элементінің жолындағы элементтер арасында жылжыту.
  • \n' + + '
\n' + + '\n' + + '

Down (Төмен) және Up (Жоғары) көрсеткі пернелері

\n' + + '\n' + + '
    \n' + + '
  • мәзірдегі мәзір элементтері арасында жылжыту.
  • \n' + + '
  • құралдар тақтасының ашылмалы мәзіріндегі мәзір элементтері арасында жылжыту.
  • \n' + + '
\n' + + '\n' + + '

Фокусталған ПИ бөліміндегі Arrow (Көрсеткі) пернелерінің циклі.

\n' + + '\n' + + '

Ашық мәзірді жабу үшін ішкі мәзірді ашып немесе ашылмалы мәзірді ашып, Esc пернесін басыңыз.

\n' + + '\n' + + '

Ағымдағы фокус белгілі бір ПИ бөлімінің «үстінде» болса, Esc пернесін басу әрекеті пернетақта\n' + + ' навигациясын толығымен жабады.

\n' + + '\n' + + '

Мәзір элементін немесе құралдар тақтасы түймесін орындау

\n' + + '\n' + + '

Қажетті мәзір элементі немесе құралдар тақтасы түймесі бөлектелген кезде, элементті орындау үшін Return (Қайтару), Enter (Енгізу)\n' + + ' немесе Space bar (Бос орын) пернесін басыңыз.

\n' + + '\n' + + '

Белгіленбеген диалог терезелерін навигациялау

\n' + + '\n' + + '

Белгіленбеген диалог терезелерінде диалог терезесі ашылған кезде бірінші интерактивті құрамдас фокусталады.

\n' + + '\n' + + '

Tab немесе Shift+Tab пернесін басу арқылы интерактивті диалог терезесінің құрамдастары арасында навигациялаңыз.

\n' + + '\n' + + '

Белгіленген диалог терезелерін навигациялау

\n' + + '\n' + + '

Белгіленген диалог терезелерінде диалог терезесі ашылған кезде қойынды мәзіріндегі бірінші түйме фокусталады.

\n' + + '\n' + + '

Tab немесе\n' + + ' Shift+Tab пернесін басу арқылы осы диалог терезесі қойындысының интерактивті құрамдастары арасында навигациялаңыз.

\n' + + '\n' + + '

Қойынды мәзірінің фокусын беру арқылы басқа диалог терезесінің қойындысына ауысып, тиісті Arrow (Көрсеткі)\n' + + ' пернесін басу арқылы қолжетімді қойындылар арасында айналдыруға болады.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ko_KR.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ko_KR.js new file mode 100644 index 0000000..e7c8e7f --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ko_KR.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.ko_KR', +'

키보드 탐색 시작

\n' + + '\n' + + '
\n' + + '
메뉴 모음 포커스 표시
\n' + + '
Windows 또는 Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
도구 모음 포커스 표시
\n' + + '
Windows 또는 Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
푸터 포커스 표시
\n' + + '
Windows 또는 Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
알림 포커스
\n' + + '
Windows 또는 Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
컨텍스트 도구 모음에 포커스 표시
\n' + + '
Windows, Linux 또는 macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

첫 번째 UI 항목에서 탐색이 시작되며, 이때 첫 번째 항목이 강조 표시되거나 푸터 요소 경로에 있는\n' + + ' 경우 밑줄 표시됩니다.

\n' + + '\n' + + '

UI 섹션 간 탐색

\n' + + '\n' + + '

한 UI 섹션에서 다음 UI 섹션으로 이동하려면 Tab(탭)을 누릅니다.

\n' + + '\n' + + '

한 UI 섹션에서 이전 UI 섹션으로 돌아가려면 Shift+Tab(시프트+탭)을 누릅니다.

\n' + + '\n' + + '

이 UI 섹션의 Tab(탭) 순서는 다음과 같습니다.

\n' + + '\n' + + '
    \n' + + '
  1. 메뉴 바
  2. \n' + + '
  3. 각 도구 모음 그룹
  4. \n' + + '
  5. 사이드바
  6. \n' + + '
  7. 푸터의 요소 경로
  8. \n' + + '
  9. 푸터의 단어 수 토글 버튼
  10. \n' + + '
  11. 푸터의 브랜딩 링크
  12. \n' + + '
  13. 푸터의 에디터 크기 변경 핸들
  14. \n' + + '
\n' + + '\n' + + '

UI 섹션이 없는 경우 건너뛰기합니다.

\n' + + '\n' + + '

푸터에 키보드 탐색 포커스가 있고 사이드바는 보이지 않는 경우 Shift+Tab(시프트+탭)을 누르면\n' + + ' 포커스 표시가 마지막이 아닌 첫 번째 도구 모음 그룹으로 이동합니다.

\n' + + '\n' + + '

UI 섹션 내 탐색

\n' + + '\n' + + '

한 UI 요소에서 다음 UI 요소로 이동하려면 적절한 화살표 키를 누릅니다.

\n' + + '\n' + + '

왼쪽오른쪽 화살표 키의 용도:

\n' + + '\n' + + '
    \n' + + '
  • 메뉴 모음에서 메뉴 항목 사이를 이동합니다.
  • \n' + + '
  • 메뉴에서 하위 메뉴를 엽니다.
  • \n' + + '
  • 도구 모음 그룹에서 버튼 사이를 이동합니다.
  • \n' + + '
  • 푸터의 요소 경로에서 항목 간에 이동합니다.
  • \n' + + '
\n' + + '\n' + + '

아래 화살표 키의 용도:

\n' + + '\n' + + '
    \n' + + '
  • 메뉴에서 메뉴 항목 사이를 이동합니다.
  • \n' + + '
  • 도구 모음 팝업 메뉴에서 메뉴 항목 사이를 이동합니다.
  • \n' + + '
\n' + + '\n' + + '

화살표 키는 포커스 표시 UI 섹션 내에서 순환됩니다.

\n' + + '\n' + + '

열려 있는 메뉴, 열려 있는 하위 메뉴 또는 열려 있는 팝업 메뉴를 닫으려면 Esc 키를 누릅니다.

\n' + + '\n' + + "

현재 포커스 표시가 특정 UI 섹션 '상단'에 있는 경우 이때도 Esc 키를 누르면\n" + + ' 키보드 탐색이 완전히 종료됩니다.

\n' + + '\n' + + '

메뉴 항목 또는 도구 모음 버튼 실행

\n' + + '\n' + + '

원하는 메뉴 항목 또는 도구 모음 버튼이 강조 표시되어 있을 때 Return(리턴), Enter(엔터),\n' + + ' 또는 Space bar(스페이스바)를 눌러 해당 항목을 실행합니다.

\n' + + '\n' + + '

탭이 없는 대화 탐색

\n' + + '\n' + + '

탭이 없는 대화의 경우, 첫 번째 대화형 요소가 포커스 표시된 상태로 대화가 열립니다.

\n' + + '\n' + + '

대화형 요소들 사이를 이동할 때는 Tab(탭) 또는 Shift+Tab(시프트+탭)을 누릅니다.

\n' + + '\n' + + '

탭이 있는 대화 탐색

\n' + + '\n' + + '

탭이 있는 대화의 경우, 탭 메뉴에서 첫 번째 버튼이 포커스 표시된 상태로 대화가 열립니다.

\n' + + '\n' + + '

이 대화 탭의 대화형 요소들 사이를 이동할 때는 Tab(탭) 또는\n' + + ' Shift+Tab(시프트+탭)을 누릅니다.

\n' + + '\n' + + '

다른 대화 탭으로 이동하려면 탭 메뉴를 포커스 표시한 다음 적절한 화살표\n' + + ' 키를 눌러 사용 가능한 탭들을 지나 원하는 탭으로 이동합니다.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ms.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ms.js new file mode 100644 index 0000000..2c047bb --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ms.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.ms', +'

Mulakan navigasi papan kekunci

\n' + + '\n' + + '
\n' + + '
Fokus bar Menu
\n' + + '
Windows atau Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Fokus Bar Alat
\n' + + '
Windows atau Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Fokus pengaki
\n' + + '
Windows atau Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Tumpu kepada pemberitahuan
\n' + + '
Windows atau Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Fokus bar alat kontekstual
\n' + + '
Windows, Linux atau macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Navigasi akan bermula pada item UI pertama, yang akan diserlahkan atau digaris bawah dalam saiz item pertama dalam\n' + + ' laluan elemen Pengaki.

\n' + + '\n' + + '

Navigasi antara bahagian UI

\n' + + '\n' + + '

Untuk bergerak dari satu bahagian UI ke yang seterusnya, tekan Tab.

\n' + + '\n' + + '

Untuk bergerak dari satu bahagian UI ke yang sebelumnya, tekan Shift+Tab.

\n' + + '\n' + + '

Tertib Tab bahagian UI ini ialah:

\n' + + '\n' + + '
    \n' + + '
  1. Bar menu
  2. \n' + + '
  3. Setiap kumpulan bar alat
  4. \n' + + '
  5. Bar sisi
  6. \n' + + '
  7. Laluan elemen dalam pengaki
  8. \n' + + '
  9. Butang togol kiraan perkataan dalam pengaki
  10. \n' + + '
  11. Pautan penjenamaan dalam pengaki
  12. \n' + + '
  13. Pemegang saiz semula editor dalam pengaki
  14. \n' + + '
\n' + + '\n' + + '

Jika bahagian UI tidak wujud, ia dilangkau.

\n' + + '\n' + + '

Jika pengaki mempunyai fokus navigasi papan kekunci dan tiada bar sisi kelihatan, menekan Shift+Tab\n' + + ' akan mengalihkan fokus ke kumpulan bar alat pertama, bukannya yang terakhir.

\n' + + '\n' + + '

Navigasi dalam bahagian UI

\n' + + '\n' + + '

Untuk bergerak dari satu elemen UI ke yang seterusnya, tekan kekunci Anak Panah yang bersesuaian.

\n' + + '\n' + + '

Kekunci anak panah Kiri dan Kanan

\n' + + '\n' + + '
    \n' + + '
  • bergerak antara menu dalam bar menu.
  • \n' + + '
  • membukan submenu dalam menu.
  • \n' + + '
  • bergerak antara butang dalam kumpulan bar alat.
  • \n' + + '
  • Laluan elemen dalam pengaki.
  • \n' + + '
\n' + + '\n' + + '

Kekunci anak panah Bawah dan Atas

\n' + + '\n' + + '
    \n' + + '
  • bergerak antara item menu dalam menu.
  • \n' + + '
  • bergerak antara item dalam menu timbul bar alat.
  • \n' + + '
\n' + + '\n' + + '

Kekunci Anak Panah berkitar dalam bahagian UI difokuskan.

\n' + + '\n' + + '

Untuk menutup menu buka, submenu terbuka atau menu timbul terbuka, tekan kekunci Esc.

\n' + + '\n' + + "

Jika fokus semasa berada di bahagian 'atas' bahagian UI tertentu, menekan kekunci Esc juga akan keluar daripada\n" + + ' navigasi papan kekunci sepenuhnya.

\n' + + '\n' + + '

Laksanakan item menu atau butang bar alat

\n' + + '\n' + + '

Apabila item menu atau butang bar alat yang diinginkan diserlahkan, tekan Return, Enter,\n' + + ' atau bar Space untuk melaksanakan item.

\n' + + '\n' + + '

Navigasi ke dialog tidak bertab

\n' + + '\n' + + '

Dalam dialog tidak bertab, komponen interaksi pertama difokuskan apabila dialog dibuka.

\n' + + '\n' + + '

Navigasi antara komponen dialog interaktif dengan menekan Tab atau Shift+Tab.

\n' + + '\n' + + '

Navigasi ke dialog bertab

\n' + + '\n' + + '

Dalam dialog bertab, butang pertama dalam menu tab difokuskan apabila dialog dibuka.

\n' + + '\n' + + '

Navigasi antara komponen interaktif tab dialog ini dengan menekan Tab atau\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Tukar kepada tab dialog lain dengan memfokuskan menu tab, kemudian menekan kekunci Anak Panah yang bersesuaian\n' + + ' untuk berkitar menerusi tab yang tersedia.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/nb_NO.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/nb_NO.js new file mode 100644 index 0000000..071e3f5 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/nb_NO.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.nb_NO', +'

Starte tastaturnavigering

\n' + + '\n' + + '
\n' + + '
Utheve menylinjen
\n' + + '
Windows eller Linux: Alt + F9
\n' + + '
macOS: ⌥F9
\n' + + '
Utheve verktøylinjen
\n' + + '
Windows eller Linux: Alt + F10
\n' + + '
macOS: ⌥F10
\n' + + '
Utheve bunnteksten
\n' + + '
Windows eller Linux: Alt + F11
\n' + + '
macOS: ⌥F11
\n' + + '
Fokuser på varselet
\n' + + '
Windows eller Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Utheve en kontekstuell verktøylinje
\n' + + '
Windows, Linux eller macOS: Ctrl + F9
\n' + + '
\n' + + '\n' + + '

Navigeringen starter ved det første grensesnittelementet, som utheves, eller understrekes når det gjelder det første elementet i\n' + + ' elementstien i bunnteksten.

\n' + + '\n' + + '

Navigere mellom grensesnittdeler

\n' + + '\n' + + '

Du kan bevege deg fra én grensesnittdel til den neste ved å trykke på tabulatortasten.

\n' + + '\n' + + '

Du kan bevege deg fra én grensesnittdel til den forrige ved å trykke på Shift + tabulatortasten.

\n' + + '\n' + + '

Rekkefølgen til tabulatortasten gjennom grensesnittdelene er:

\n' + + '\n' + + '
    \n' + + '
  1. Menylinjen
  2. \n' + + '
  3. Hver gruppe på verktøylinjen
  4. \n' + + '
  5. Sidestolpen
  6. \n' + + '
  7. Elementstien i bunnteksten
  8. \n' + + '
  9. Veksleknappen for ordantall i bunnteksten
  10. \n' + + '
  11. Merkelenken i bunnteksten
  12. \n' + + '
  13. Skaleringshåndtaket for redigeringsprogrammet i bunnteksten
  14. \n' + + '
\n' + + '\n' + + '

Hvis en grensesnittdel ikke er til stede, blir den hoppet over.

\n' + + '\n' + + '

Hvis tastaturnavigeringen har uthevet bunnteksten og det ikke finnes en synlig sidestolpe, kan du trykke på Shift + tabulatortasten\n' + + ' for å flytte fokuset til den første gruppen på verktøylinjen i stedet for den siste.

\n' + + '\n' + + '

Navigere innenfor grensesnittdeler

\n' + + '\n' + + '

Du kan bevege deg fra ett grensesnittelement til det neste ved å trykke på den aktuelle piltasten.

\n' + + '\n' + + '

De venstre og høyre piltastene

\n' + + '\n' + + '
    \n' + + '
  • beveger deg mellom menyer på menylinjen.
  • \n' + + '
  • åpner en undermeny i en meny.
  • \n' + + '
  • beveger deg mellom knapper i en gruppe på verktøylinjen.
  • \n' + + '
  • beveger deg mellom elementer i elementstien i bunnteksten.
  • \n' + + '
\n' + + '\n' + + '

Ned- og opp-piltastene

\n' + + '\n' + + '
    \n' + + '
  • beveger deg mellom menyelementer i en meny.
  • \n' + + '
  • beveger deg mellom elementer i en hurtigmeny på verktøylinjen.
  • \n' + + '
\n' + + '\n' + + '

Med piltastene kan du bevege deg innenfor den uthevede grensesnittdelen.

\n' + + '\n' + + '

Du kan lukke en åpen meny, en åpen undermeny eller en åpen hurtigmeny ved å klikke på Esc-tasten.

\n' + + '\n' + + '

Hvis det øverste nivået i en grensesnittdel er uthevet, kan du ved å trykke på Esc også avslutte\n' + + ' tastaturnavigeringen helt.

\n' + + '\n' + + '

Utføre et menyelement eller en knapp på en verktøylinje

\n' + + '\n' + + '

Når det ønskede menyelementet eller verktøylinjeknappen er uthevet, trykker du på Retur, Enter,\n' + + ' eller mellomromstasten for å utføre elementet.

\n' + + '\n' + + '

Navigere i dialogbokser uten faner

\n' + + '\n' + + '

I dialogbokser uten faner blir den første interaktive komponenten uthevet når dialogboksen åpnes.

\n' + + '\n' + + '

Naviger mellom interaktive komponenter i dialogboksen ved å trykke på tabulatortasten eller Shift + tabulatortasten.

\n' + + '\n' + + '

Navigere i fanebaserte dialogbokser

\n' + + '\n' + + '

I fanebaserte dialogbokser blir den første knappen i fanemenyen uthevet når dialogboksen åpnes.

\n' + + '\n' + + '

Naviger mellom interaktive komponenter i fanen ved å trykke på tabulatortasten eller\n' + + ' Shift + tabulatortasten.

\n' + + '\n' + + '

Veksle til en annen fane i dialogboksen ved å utheve fanemenyen, og trykk deretter på den aktuelle piltasten\n' + + ' for å bevege deg mellom de tilgjengelige fanene.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/nl.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/nl.js new file mode 100644 index 0000000..05c07ae --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/nl.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.nl', +'

Toetsenbordnavigatie starten

\n' + + '\n' + + '
\n' + + '
Focus op de menubalk instellen
\n' + + '
Windows of Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Focus op de werkbalk instellen
\n' + + '
Windows of Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Focus op de voettekst instellen
\n' + + '
Windows of Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Focus op de melding instellen
\n' + + '
Windows of Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Focus op een contextuele werkbalk instellen
\n' + + '
Windows, Linux of macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

De navigatie start bij het eerste UI-item, dat wordt gemarkeerd of onderstreept als het eerste item zich in\n' + + ' in het elementenpad van de voettekst bevindt.

\n' + + '\n' + + '

Navigeren tussen UI-secties

\n' + + '\n' + + '

Druk op Tab om naar de volgende UI-sectie te gaan.

\n' + + '\n' + + '

Druk op Shift+Tab om naar de vorige UI-sectie te gaan.

\n' + + '\n' + + '

De Tab-volgorde van deze UI-secties is:

\n' + + '\n' + + '
    \n' + + '
  1. Menubalk
  2. \n' + + '
  3. Elke werkbalkgroep
  4. \n' + + '
  5. Zijbalk
  6. \n' + + '
  7. Elementenpad in de voettekst
  8. \n' + + '
  9. Wisselknop voor aantal woorden in de voettekst
  10. \n' + + '
  11. Merkkoppeling in de voettekst
  12. \n' + + '
  13. Greep voor het wijzigen van het formaat van de editor in de voettekst
  14. \n' + + '
\n' + + '\n' + + '

Als een UI-sectie niet aanwezig is, wordt deze overgeslagen.

\n' + + '\n' + + '

Als de focus van de toetsenbordnavigatie is ingesteld op de voettekst en er geen zichtbare zijbalk is, kun je op Shift+Tab drukken\n' + + ' om de focus naar de eerste werkbalkgroep in plaats van de laatste te verplaatsen.

\n' + + '\n' + + '

Navigeren binnen UI-secties

\n' + + '\n' + + '

Druk op de pijltjestoets om naar het betreffende UI-element te gaan.

\n' + + '\n' + + '

Met de pijltjestoetsen Links en Rechts

\n' + + '\n' + + '
    \n' + + "
  • wissel je tussen menu's in de menubalk.
  • \n" + + '
  • open je een submenu in een menu.
  • \n' + + '
  • wissel je tussen knoppen in een werkbalkgroep.
  • \n' + + '
  • wissel je tussen items in het elementenpad in de voettekst.
  • \n' + + '
\n' + + '\n' + + '

Met de pijltjestoetsen Omlaag en Omhoog

\n' + + '\n' + + '
    \n' + + '
  • wissel je tussen menu-items in een menu.
  • \n' + + '
  • wissel je tussen items in een werkbalkpop-upmenu.
  • \n' + + '
\n' + + '\n' + + '

Met de pijltjestoetsen wissel je binnen de UI-sectie waarop de focus is ingesteld.

\n' + + '\n' + + '

Druk op de toets Esc om een geopend menu, submenu of pop-upmenu te sluiten.

\n' + + '\n' + + "

Als de huidige focus is ingesteld 'bovenaan' een bepaalde UI-sectie, kun je op de toets Esc drukken\n" + + ' om de toetsenbordnavigatie af te sluiten.

\n' + + '\n' + + '

Een menu-item of werkbalkknop uitvoeren

\n' + + '\n' + + '

Als het gewenste menu-item of de gewenste werkbalkknop is gemarkeerd, kun je op Return, Enter\n' + + ' of de spatiebalk drukken om het item uit te voeren.

\n' + + '\n' + + '

Navigeren in dialoogvensters zonder tabblad

\n' + + '\n' + + '

Als een dialoogvenster zonder tabblad wordt geopend, wordt de focus ingesteld op het eerste interactieve onderdeel.

\n' + + '\n' + + '

Je kunt navigeren tussen interactieve onderdelen van een dialoogvenster door op Tab of Shift+Tab te drukken.

\n' + + '\n' + + '

Navigeren in dialoogvensters met tabblad

\n' + + '\n' + + '

Als een dialoogvenster met tabblad wordt geopend, wordt de focus ingesteld op de eerste knop in het tabbladmenu.

\n' + + '\n' + + '

Je kunt navigeren tussen interactieve onderdelen van dit tabblad van het dialoogvenster door op Tab of\n' + + ' Shift+Tab te drukken.

\n' + + '\n' + + '

Je kunt overschakelen naar een ander tabblad van het dialoogvenster door de focus in te stellen op het tabbladmenu en vervolgens op de juiste pijltjestoets\n' + + ' te drukken om tussen de beschikbare tabbladen te wisselen.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/pl.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/pl.js new file mode 100644 index 0000000..e89f808 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/pl.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.pl', +'

Początek nawigacji przy użyciu klawiatury

\n' + + '\n' + + '
\n' + + '
Ustaw fokus na pasek menu
\n' + + '
Windows lub Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Ustaw fokus na pasek narzędzi
\n' + + '
Windows lub Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Ustaw fokus na sekcję Footer
\n' + + '
Windows lub Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Skup się na powiadomieniu
\n' + + '
Windows lub Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Ustaw fokus na kontekstowy pasek narzędzi
\n' + + '
Windows, Linux lub macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Nawigacja zostanie rozpoczęta od pierwszego elementu interfejsu użytkownika, który jest podświetlony lub — w przypadku pierwszego elementu\n' + + ' w ścieżce elementów w sekcji Footer — podkreślony.

\n' + + '\n' + + '

Nawigacja pomiędzy sekcjami interfejsu użytkownika

\n' + + '\n' + + '

Aby przenieść się z danej sekcji interfejsu użytkownika do następnej, naciśnij Tab.

\n' + + '\n' + + '

Aby przenieść się z danej sekcji interfejsu użytkownika do poprzedniej, naciśnij Shift+Tab.

\n' + + '\n' + + '

Kolejność klawisza Tab w takich sekcjach interfejsu użytkownika jest następująca:

\n' + + '\n' + + '
    \n' + + '
  1. Pasek menu
  2. \n' + + '
  3. Każda grupa na pasku narzędzi
  4. \n' + + '
  5. Pasek boczny
  6. \n' + + '
  7. Ścieżka elementów w sekcji Footer
  8. \n' + + '
  9. Przycisk przełączania liczby słów w sekcji Footer
  10. \n' + + '
  11. Łącze brandujące w sekcji Footer
  12. \n' + + '
  13. Uchwyt zmiany rozmiaru edytora w sekcji Footer
  14. \n' + + '
\n' + + '\n' + + '

Jeżeli nie ma sekcji interfejsu użytkownika, jest to pomijane.

\n' + + '\n' + + '

Jeżeli na sekcji Footer jest ustawiony fokus nawigacji przy użyciu klawiatury i nie ma widocznego paska bocznego, naciśnięcie Shift+Tab\n' + + ' przenosi fokus na pierwszą grupę paska narzędzi, a nie na ostatnią.

\n' + + '\n' + + '

Nawigacja wewnątrz sekcji interfejsu użytkownika

\n' + + '\n' + + '

Aby przenieść się z danego elementu interfejsu użytkownika do następnego, naciśnij odpowiedni klawisz strzałki.

\n' + + '\n' + + '

Klawisze strzałek w prawo i w lewo służą do

\n' + + '\n' + + '
    \n' + + '
  • przenoszenia się pomiędzy menu na pasku menu,
  • \n' + + '
  • otwarcia podmenu w menu,
  • \n' + + '
  • przenoszenia się pomiędzy przyciskami w grupie paska narzędzi,
  • \n' + + '
  • przenoszenia się pomiędzy elementami w ścieżce elementów w sekcji Footer.
  • \n' + + '
\n' + + '\n' + + '

Klawisze strzałek w dół i w górę służą do

\n' + + '\n' + + '
    \n' + + '
  • przenoszenia się pomiędzy elementami menu w menu,
  • \n' + + '
  • przenoszenia się pomiędzy elementami w wyskakującym menu paska narzędzi.
  • \n' + + '
\n' + + '\n' + + '

Klawisze strzałek służą do przemieszczania się w sekcji interfejsu użytkownika z ustawionym fokusem.

\n' + + '\n' + + '

Aby zamknąć otwarte menu, otwarte podmenu lub otwarte menu wyskakujące, naciśnij klawisz Esc.

\n' + + '\n' + + '

Jeżeli fokus jest ustawiony na górze konkretnej sekcji interfejsu użytkownika, naciśnięcie klawisza Esc powoduje wyjście\n' + + ' z nawigacji przy użyciu klawiatury.

\n' + + '\n' + + '

Wykonanie elementu menu lub przycisku paska narzędzi

\n' + + '\n' + + '

Gdy podświetlony jest żądany element menu lub przycisk paska narzędzi, naciśnij klawisz Return, Enter\n' + + ' lub Spacja, aby go wykonać.

\n' + + '\n' + + '

Nawigacja po oknie dialogowym bez kart

\n' + + '\n' + + '

Gdy otwiera się okno dialogowe bez kart, fokus ustawiany jest na pierwszą interaktywną część okna.

\n' + + '\n' + + '

Pomiędzy interaktywnymi częściami okna dialogowego nawiguj, naciskając klawisze Tab lub Shift+Tab.

\n' + + '\n' + + '

Nawigacja po oknie dialogowym z kartami

\n' + + '\n' + + '

W przypadku okna dialogowego z kartami po otwarciu okna dialogowego fokus ustawiany jest na pierwszy przycisk w menu karty.

\n' + + '\n' + + '

Nawigację pomiędzy interaktywnymi częściami karty okna dialogowego prowadzi się poprzez naciskanie klawiszy Tab lub\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Przełączenie się na inną kartę okna dialogowego wykonuje się poprzez ustawienie fokusu na menu karty i naciśnięcie odpowiedniego klawisza strzałki\n' + + ' w celu przemieszczenia się pomiędzy dostępnymi kartami.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/pt_BR.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/pt_BR.js new file mode 100644 index 0000000..2938fcf --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/pt_BR.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.pt_BR', +'

Iniciar navegação pelo teclado

\n' + + '\n' + + '
\n' + + '
Foco na barra de menus
\n' + + '
Windows ou Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Foco na barra de ferramentas
\n' + + '
Windows ou Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Foco no rodapé
\n' + + '
Windows ou Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Foco na notificação
\n' + + '
Windows ou Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Foco na barra de ferramentas contextual
\n' + + '
Windows, Linux ou macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

A navegação inicia no primeiro item da IU, que será destacado ou sublinhado no caso do primeiro item no\n' + + ' caminho do elemento Rodapé.

\n' + + '\n' + + '

Navegar entre seções da IU

\n' + + '\n' + + '

Para ir de uma seção da IU para a seguinte, pressione Tab.

\n' + + '\n' + + '

Para ir de uma seção da IU para a anterior, pressione Shift+Tab.

\n' + + '\n' + + '

A ordem de Tab destas seções da IU é:

\n' + + '\n' + + '
    \n' + + '
  1. Barra de menus
  2. \n' + + '
  3. Cada grupo da barra de ferramentas
  4. \n' + + '
  5. Barra lateral
  6. \n' + + '
  7. Caminho do elemento no rodapé
  8. \n' + + '
  9. Botão de alternar contagem de palavras no rodapé
  10. \n' + + '
  11. Link da marca no rodapé
  12. \n' + + '
  13. Alça de redimensionamento do editor no rodapé
  14. \n' + + '
\n' + + '\n' + + '

Se não houver uma seção da IU, ela será pulada.

\n' + + '\n' + + '

Se o rodapé tiver o foco da navegação pelo teclado e não houver uma barra lateral visível, pressionar Shift+Tab\n' + + ' move o foco para o primeiro grupo da barra de ferramentas, não para o último.

\n' + + '\n' + + '

Navegar dentro das seções da IU

\n' + + '\n' + + '

Para ir de um elemento da IU para o seguinte, pressione a Seta correspondente.

\n' + + '\n' + + '

As teclas de seta Esquerda e Direita

\n' + + '\n' + + '
    \n' + + '
  • movem entre menus na barra de menus.
  • \n' + + '
  • abrem um submenu em um menu.
  • \n' + + '
  • movem entre botões em um grupo da barra de ferramentas.
  • \n' + + '
  • movem entre itens no caminho do elemento do rodapé.
  • \n' + + '
\n' + + '\n' + + '

As teclas de seta Abaixo e Acima

\n' + + '\n' + + '
    \n' + + '
  • movem entre itens de menu em um menu.
  • \n' + + '
  • movem entre itens em um menu suspenso da barra de ferramentas.
  • \n' + + '
\n' + + '\n' + + '

As teclas de Seta alternam dentre a seção da IU em foco.

\n' + + '\n' + + '

Para fechar um menu aberto, um submenu aberto ou um menu suspenso aberto, pressione Esc.

\n' + + '\n' + + '

Se o foco atual estiver no ‘alto’ de determinada seção da IU, pressionar Esc também sai\n' + + ' totalmente da navegação pelo teclado.

\n' + + '\n' + + '

Executar um item de menu ou botão da barra de ferramentas

\n' + + '\n' + + '

Com o item de menu ou botão da barra de ferramentas desejado destacado, pressione Return, Enter,\n' + + ' ou a Barra de espaço para executar o item.

\n' + + '\n' + + '

Navegar por caixas de diálogo sem guias

\n' + + '\n' + + '

Em caixas de diálogo sem guias, o primeiro componente interativo recebe o foco quando a caixa de diálogo abre.

\n' + + '\n' + + '

Navegue entre componentes interativos de caixa de diálogo pressionando Tab ou Shift+Tab.

\n' + + '\n' + + '

Navegar por caixas de diálogo com guias

\n' + + '\n' + + '

Em caixas de diálogo com guias, o primeiro botão no menu da guia recebe o foco quando a caixa de diálogo abre.

\n' + + '\n' + + '

Navegue entre componentes interativos dessa guia da caixa de diálogo pressionando Tab ou\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Alterne para outra guia da caixa de diálogo colocando o foco no menu da guia e pressionando a Seta\n' + + ' adequada para percorrer as guias disponíveis.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/pt_PT.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/pt_PT.js new file mode 100644 index 0000000..03da3d6 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/pt_PT.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.pt_PT', +'

Iniciar navegação com teclado

\n' + + '\n' + + '
\n' + + '
Foco na barra de menu
\n' + + '
Windows ou Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Foco na barra de ferramentas
\n' + + '
Windows ou Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Foco no rodapé
\n' + + '
Windows ou Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Focar a notificação
\n' + + '
Windows ou Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Foco numa barra de ferramentas contextual
\n' + + '
Windows, Linux ou macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

A navegação começará no primeiro item de IU, que estará realçado ou sublinhado, no caso do primeiro item no\n' + + ' caminho do elemento do rodapé.

\n' + + '\n' + + '

Navegar entre secções de IU

\n' + + '\n' + + '

Para se mover de uma secção de IU para a seguinte, prima Tab.

\n' + + '\n' + + '

Para se mover de uma secção de IU para a anterior, prima Shift+Tab.

\n' + + '\n' + + '

A ordem de tabulação destas secções de IU é:

\n' + + '\n' + + '
    \n' + + '
  1. Barra de menu
  2. \n' + + '
  3. Cada grupo da barra de ferramentas
  4. \n' + + '
  5. Barra lateral
  6. \n' + + '
  7. Caminho do elemento no rodapé
  8. \n' + + '
  9. Botão de alternar da contagem de palavras no rodapé
  10. \n' + + '
  11. Ligação da marca no rodapé
  12. \n' + + '
  13. Alça de redimensionamento do editor no rodapé
  14. \n' + + '
\n' + + '\n' + + '

Se uma secção de IU não estiver presente, é ignorada.

\n' + + '\n' + + '

Se o rodapé tiver foco de navegação com teclado e não existir uma barra lateral visível, premir Shift+Tab\n' + + ' move o foco para o primeiro grupo da barra de ferramentas e não para o último.

\n' + + '\n' + + '

Navegar nas secções de IU

\n' + + '\n' + + '

Para se mover de um elemento de IU para o seguinte, prima a tecla de seta adequada.

\n' + + '\n' + + '

As teclas de seta Para a esquerda e Para a direita

\n' + + '\n' + + '
    \n' + + '
  • movem-se entre menus na barra de menu.
  • \n' + + '
  • abrem um submenu num menu.
  • \n' + + '
  • movem-se entre botões num grupo da barra de ferramentas.
  • \n' + + '
  • movem-se entre itens no caminho do elemento do rodapé.
  • \n' + + '
\n' + + '\n' + + '

As teclas de seta Para cima e Para baixo

\n' + + '\n' + + '
    \n' + + '
  • movem-se entre itens de menu num menu.
  • \n' + + '
  • movem-se entre itens num menu de pop-up da barra de ferramentas.
  • \n' + + '
\n' + + '\n' + + '

As teclas de seta deslocam-se ciclicamente na secção de IU em foco.

\n' + + '\n' + + '

Para fechar um menu aberto, um submenu aberto ou um menu de pop-up aberto, prima a tecla Esc.

\n' + + '\n' + + '

Se o foco atual estiver no "topo" de determinada secção de IU, premir a tecla Esc também fecha\n' + + ' completamente a navegação com teclado.

\n' + + '\n' + + '

Executar um item de menu ou botão da barra de ferramentas

\n' + + '\n' + + '

Quando o item de menu ou o botão da barra de ferramentas pretendido estiver realçado, prima Retrocesso, Enter\n' + + ' ou a Barra de espaço para executar o item.

\n' + + '\n' + + '

Navegar em diálogos sem separadores

\n' + + '\n' + + '

Nos diálogos sem separadores, o primeiro componente interativo fica em foco quando o diálogo abre.

\n' + + '\n' + + '

Navegue entre componentes interativos do diálogo, premindo Tab ou Shift+Tab.

\n' + + '\n' + + '

Navegar em diálogos com separadores

\n' + + '\n' + + '

Nos diálogos com separadores, o primeiro botão no menu do separador fica em foco quando o diálogo abre.

\n' + + '\n' + + '

Navegue entre os componentes interativos deste separador do diálogo, premindo Tab ou\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Mude para outro separador do diálogo colocando o menu do separador em foco e, em seguida, premindo a tecla de seta\n' + + ' adequada para se deslocar ciclicamente pelos separadores disponíveis.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ro.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ro.js new file mode 100644 index 0000000..38d3441 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ro.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.ro', +'

Începeți navigarea de la tastatură

\n' + + '\n' + + '
\n' + + '
Focalizare pe bara de meniu
\n' + + '
Windows sau Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Focalizare pe bara de instrumente
\n' + + '
Windows sau Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Focalizare pe subsol
\n' + + '
Windows sau Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Focalizare pe notificare
\n' + + '
Windows sau Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Focalizare pe o bară de instrumente contextuală
\n' + + '
Windows, Linux sau macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Navigarea va începe de la primul element al interfeței cu utilizatorul, care va fi evidențiat sau subliniat în cazul primului element din\n' + + ' calea elementului Subsol.

\n' + + '\n' + + '

Navigați între secțiunile interfeței cu utilizatorul

\n' + + '\n' + + '

Pentru a trece de la o secțiune a interfeței cu utilizatorul la alta, apăsați Tab.

\n' + + '\n' + + '

Pentru a trece de la o secțiune a interfeței cu utilizatorul la cea anterioară, apăsați Shift+Tab.

\n' + + '\n' + + '

Ordinea cu Tab a acestor secțiuni ale interfeței cu utilizatorul este următoarea:

\n' + + '\n' + + '
    \n' + + '
  1. Bara de meniu
  2. \n' + + '
  3. Fiecare grup de bare de instrumente
  4. \n' + + '
  5. Bara laterală
  6. \n' + + '
  7. Calea elementului în subsol
  8. \n' + + '
  9. Buton de comutare a numărului de cuvinte în subsol
  10. \n' + + '
  11. Link de branding în subsol
  12. \n' + + '
  13. Mâner de redimensionare a editorului în subsol
  14. \n' + + '
\n' + + '\n' + + '

În cazul în care o secțiune a interfeței cu utilizatorul nu este prezentă, aceasta este omisă.

\n' + + '\n' + + '

În cazul în care subsolul are focalizarea navigației asupra tastaturii și nu există o bară laterală vizibilă, apăsarea butonului Shift+Tab\n' + + ' mută focalizarea pe primul grup de bare de instrumente, nu pe ultimul.

\n' + + '\n' + + '

Navigați în secțiunile interfeței cu utilizatorul

\n' + + '\n' + + '

Pentru a trece de la un element de interfață cu utilizatorul la următorul, apăsați tasta cu săgeata corespunzătoare.

\n' + + '\n' + + '

Tastele cu săgeți către stânga și dreapta

\n' + + '\n' + + '
    \n' + + '
  • navighează între meniurile din bara de meniuri.
  • \n' + + '
  • deschid un sub-meniu dintr-un meniu.
  • \n' + + '
  • navighează între butoanele dintr-un grup de bare de instrumente.
  • \n' + + '
  • navighează între elementele din calea elementelor subsolului.
  • \n' + + '
\n' + + '\n' + + '

Tastele cu săgeți în sus și în jos

\n' + + '\n' + + '
    \n' + + '
  • navighează între elementele de meniu dintr-un meniu.
  • \n' + + '
  • navighează între elementele unui meniu pop-up din bara de instrumente.
  • \n' + + '
\n' + + '\n' + + '

Tastele cu săgeți navighează în cadrul secțiunii interfeței cu utilizatorul asupra căreia se focalizează.

\n' + + '\n' + + '

Pentru a închide un meniu deschis, un sub-meniu deschis sau un meniu pop-up deschis, apăsați tasta Esc.

\n' + + '\n' + + '

Dacă focalizarea curentă este asupra „părții superioare” a unei anumite secțiuni a interfeței cu utilizatorul, prin apăsarea tastei Esc se iese, de asemenea,\n' + + ' în întregime din navigarea de la tastatură.

\n' + + '\n' + + '

Executarea unui element de meniu sau a unui buton din bara de instrumente

\n' + + '\n' + + '

Atunci când elementul de meniu dorit sau butonul dorit din bara de instrumente este evidențiat, apăsați Return, Enter,\n' + + ' sau bara de spațiu pentru a executa elementul.

\n' + + '\n' + + '

Navigarea de dialoguri fără file

\n' + + '\n' + + '

În dialogurile fără file, prima componentă interactivă beneficiază de focalizare la deschiderea dialogului.

\n' + + '\n' + + '

Navigați între componentele dialogului interactiv apăsând Tab sau Shift+Tab.

\n' + + '\n' + + '

Navigarea de dialoguri cu file

\n' + + '\n' + + '

În dialogurile cu file, primul buton din meniul cu file beneficiază de focalizare la deschiderea dialogului.

\n' + + '\n' + + '

Navigați între componentele interactive ale acestei file de dialog apăsând Tab sau\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Treceți la o altă filă de dialog focalizând asupra meniului cu file și apoi apăsând săgeata corespunzătoare\n' + + ' pentru a parcurge filele disponibile.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ru.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ru.js new file mode 100644 index 0000000..d310f54 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/ru.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.ru', +'

Начните управление с помощью клавиатуры

\n' + + '\n' + + '
\n' + + '
Фокус на панели меню
\n' + + '
Windows или Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Фокус на панели инструментов
\n' + + '
Windows или Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Фокус на нижнем колонтитуле
\n' + + '
Windows или Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Фокус на уведомлении
\n' + + '
Windows или Linux: Alt+12
\n' + + '
macOS: ⌥F12
\n' + + '
Фокус на контекстной панели инструментов
\n' + + '
Windows, Linux или macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Первый доступный для управления элемент интерфейса будет выделен цветом или подчеркнут (если он находится\n' + + ' в пути элементов нижнего колонтитула).

\n' + + '\n' + + '

Переход между разделами пользовательского интерфейса

\n' + + '\n' + + '

Чтобы перейти из текущего раздела интерфейса в следующий, нажмите Tab.

\n' + + '\n' + + '

Чтобы перейти из текущего раздела интерфейса в предыдущий, нажмите Shift+Tab.

\n' + + '\n' + + '

Вкладки разделов интерфейса расположены в следующем порядке:

\n' + + '\n' + + '
    \n' + + '
  1. Панель меню
  2. \n' + + '
  3. Группы панели инструментов
  4. \n' + + '
  5. Боковая панель
  6. \n' + + '
  7. Путь элементов нижнего колонтитула
  8. \n' + + '
  9. Подсчет слов/символов в нижнем колонтитуле
  10. \n' + + '
  11. Брендовая ссылка в нижнем колонтитуле
  12. \n' + + '
  13. Угол для изменения размера окна редактора
  14. \n' + + '
\n' + + '\n' + + '

Если раздел интерфейса отсутствует, он пропускается.

\n' + + '\n' + + '

Если при управлении с клавиатуры фокус находится на нижнем колонтитуле, а видимая боковая панель отсутствует, то при нажатии сочетания клавиш Shift+Tab\n' + + ' фокус переносится на первую группу панели инструментов, а не на последнюю.

\n' + + '\n' + + '

Переход между элементами внутри разделов пользовательского интерфейса

\n' + + '\n' + + '

Чтобы перейти от текущего элемента интерфейса к следующему, нажмите соответствующую клавишу со стрелкой.

\n' + + '\n' + + '

Клавиши со стрелками влево и вправо позволяют

\n' + + '\n' + + '
    \n' + + '
  • перемещаться между разными меню в панели меню.
  • \n' + + '
  • открывать разделы меню.
  • \n' + + '
  • перемещаться между кнопками в группе панели инструментов.
  • \n' + + '
  • перемещаться между элементами в пути элементов нижнего колонтитула.
  • \n' + + '
\n' + + '\n' + + '

Клавиши со стрелками вниз и вверх позволяют

\n' + + '\n' + + '
    \n' + + '
  • перемещаться между элементами одного меню.
  • \n' + + '
  • перемещаться между элементами всплывающего меню в панели инструментов.
  • \n' + + '
\n' + + '\n' + + '

При использовании клавиш со стрелками вы будете циклически перемещаться по элементам в пределах выбранного раздела интерфейса.

\n' + + '\n' + + '

Чтобы закрыть открытое меню, его раздел или всплывающее меню, нажмите клавишу Esc.

\n' + + '\n' + + '

Если фокус находится наверху какого-либо раздела интерфейса, нажатие клавиши Esc также приведет\n' + + ' к выходу из режима управления с помощью клавиатуры.

\n' + + '\n' + + '

Использование элемента меню или кнопки на панели инструментов

\n' + + '\n' + + '

Когда элемент меню или кнопка панели инструментов будут выделены, нажмите Return, Enter\n' + + ' или Space, чтобы их активировать.

\n' + + '\n' + + '

Управление в диалоговом окне без вкладок

\n' + + '\n' + + '

При открытии диалогового окна без вкладок фокус переносится на первый интерактивный компонент.

\n' + + '\n' + + '

Для перехода между интерактивными компонентами диалогового окна нажимайте Tab или Shift+Tab.

\n' + + '\n' + + '

Управление в диалоговом окне с вкладками

\n' + + '\n' + + '

При открытии диалогового окна с вкладками фокус переносится на первую кнопку в меню вкладок.

\n' + + '\n' + + '

Для перехода между интерактивными компонентами этой вкладки диалогового окна нажимайте Tab или\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Для перехода на другую вкладку диалогового окна переместите фокус на меню вкладок, а затем используйте клавиши со стрелками\n' + + ' для циклического переключения между доступными вкладками.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/sk.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/sk.js new file mode 100644 index 0000000..60cc628 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/sk.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.sk', +'

Začíname s navigáciou pomocou klávesnice

\n' + + '\n' + + '
\n' + + '
Prejsť na panel s ponukami
\n' + + '
Windows alebo Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Prejsť na panel nástrojov
\n' + + '
Windows alebo Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Prejsť na pätičku
\n' + + '
Windows alebo Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Zaostriť na oznámenie
\n' + + '
Windows alebo Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Prejsť na kontextový panel nástrojov
\n' + + '
Windows, Linux alebo macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Navigácia začne pri prvej položke používateľského rozhrania, ktorá bude zvýraznená alebo v prípade prvej položky\n' + + ' cesty k pätičke podčiarknutá.

\n' + + '\n' + + '

Navigácia medzi časťami používateľského rozhrania

\n' + + '\n' + + '

Ak sa chcete posunúť z jednej časti používateľského rozhrania do druhej, stlačte tlačidlo Tab.

\n' + + '\n' + + '

Ak sa chcete posunúť z jednej časti používateľského rozhrania do predchádzajúcej, stlačte tlačidlá Shift + Tab.

\n' + + '\n' + + '

Poradie prepínania medzi týmito časťami používateľského rozhrania pri stláčaní tlačidla Tab:

\n' + + '\n' + + '
    \n' + + '
  1. Panel s ponukou
  2. \n' + + '
  3. Každá skupina panela nástrojov
  4. \n' + + '
  5. Bočný panel
  6. \n' + + '
  7. Cesta k prvku v pätičke
  8. \n' + + '
  9. Prepínač počtu slov v pätičke
  10. \n' + + '
  11. Odkaz na informácie o značke v pätičke
  12. \n' + + '
  13. Úchyt na zmenu veľkosti editora v pätičke
  14. \n' + + '
\n' + + '\n' + + '

Ak nejaká časť používateľského rozhrania nie je prítomná, preskočí sa.

\n' + + '\n' + + '

Ak je pätička vybratá na navigáciu pomocou klávesnice a nie je viditeľný bočný panel, stlačením klávesov Shift+Tab\n' + + ' prejdete na prvú skupinu panela nástrojov, nie na poslednú.

\n' + + '\n' + + '

Navigácia v rámci častí používateľského rozhrania

\n' + + '\n' + + '

Ak sa chcete posunúť z jedného prvku používateľského rozhrania na ďalší, stlačte príslušný kláves so šípkou.

\n' + + '\n' + + '

Klávesy so šípkami doľava a doprava

\n' + + '\n' + + '
    \n' + + '
  • umožňujú presun medzi ponukami na paneli ponúk,
  • \n' + + '
  • otvárajú podponuku v rámci ponuky,
  • \n' + + '
  • umožňujú presun medzi tlačidlami v skupine panelov nástrojov,
  • \n' + + '
  • umožňujú presun medzi položkami cesty prvku v pätičke.
  • \n' + + '
\n' + + '\n' + + '

Klávesy so šípkami dole a hore

\n' + + '\n' + + '
    \n' + + '
  • umožňujú presun medzi položkami ponuky,
  • \n' + + '
  • umožňujú presun medzi položkami v kontextovej ponuke panela nástrojov.
  • \n' + + '
\n' + + '\n' + + '

Klávesy so šípkami vykonávajú prepínanie v rámci vybranej časti používateľského rozhrania.

\n' + + '\n' + + '

Ak chcete zatvoriť otvorenú ponuku, otvorenú podponuku alebo otvorenú kontextovú ponuku, stlačte kláves Esc.

\n' + + '\n' + + '

Ak je aktuálne vybratá horná časť konkrétneho používateľského rozhrania, stlačením klávesu Esc úplne ukončíte tiež\n' + + ' navigáciu pomocou klávesnice.

\n' + + '\n' + + '

Vykonanie príkazu položky ponuky alebo tlačidla panela nástrojov

\n' + + '\n' + + '

Keď je zvýraznená požadovaná položka ponuky alebo tlačidlo panela nástrojov, stlačením klávesov Return, Enter\n' + + ' alebo medzerníka vykonáte príslušný príkaz položky.

\n' + + '\n' + + '

Navigácia v dialógových oknách bez záložiek

\n' + + '\n' + + '

Pri otvorení dialógových okien bez záložiek prejdete na prvý interaktívny komponent.

\n' + + '\n' + + '

Medzi interaktívnymi dialógovými komponentmi môžete prechádzať stlačením klávesov Tab alebo Shift+Tab.

\n' + + '\n' + + '

Navigácia v dialógových oknách so záložkami

\n' + + '\n' + + '

Pri otvorení dialógových okien so záložkami prejdete na prvé tlačidlo v ponuke záložiek.

\n' + + '\n' + + '

Medzi interaktívnymi komponentmi tejto dialógovej záložky môžete prechádzať stlačením klávesov Tab alebo\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Ak chcete prepnúť na ďalšiu záložku dialógového okna, prejdite do ponuky záložiek a potom môžete stlačením príslušného klávesu so šípkou\n' + + ' prepínať medzi dostupnými záložkami.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/sl_SI.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/sl_SI.js new file mode 100644 index 0000000..2b25f5a --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/sl_SI.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.sl_SI', +'

Začetek krmarjenja s tipkovnico

\n' + + '\n' + + '
\n' + + '
Fokus na menijsko vrstico
\n' + + '
Windows ali Linux: Alt + F9
\n' + + '
macOS: ⌥F9
\n' + + '
Fokus na orodno vrstico
\n' + + '
Windows ali Linux: Alt + F10
\n' + + '
macOS: ⌥F10
\n' + + '
Fokus na nogo
\n' + + '
Windows ali Linux: Alt + F11
\n' + + '
macOS: ⌥F11
\n' + + '
Označitev obvestila
\n' + + '
Windows ali Linux: Alt + F12
\n' + + '
macOS: ⌥F12
\n' + + '
Fokus na kontekstualno orodno vrstico
\n' + + '
Windows, Linux ali macOS: Ctrl + F9
\n' + + '
\n' + + '\n' + + '

Krmarjenje se bo začelo s prvim elementom uporabniškega vmesnika, ki bo izpostavljena ali podčrtan, če gre za prvi element na\n' + + ' poti do elementa noge.

\n' + + '\n' + + '

Krmarjenje med razdelki uporabniškega vmesnika

\n' + + '\n' + + '

Če se želite pomakniti z enega dela uporabniškega vmesnika na naslednjega, pritisnite tabulatorko.

\n' + + '\n' + + '

Če se želite pomakniti z enega dela uporabniškega vmesnika na prejšnjega, pritisnite shift + tabulatorko.

\n' + + '\n' + + '

Zaporedje teh razdelkov uporabniškega vmesnika, ko pritiskate tabulatorko, je:

\n' + + '\n' + + '
    \n' + + '
  1. Menijska vrstica
  2. \n' + + '
  3. Posamezne skupine orodne vrstice
  4. \n' + + '
  5. Stranska vrstica
  6. \n' + + '
  7. Pod do elementa v nogi
  8. \n' + + '
  9. Gumb za preklop štetja besed v nogi
  10. \n' + + '
  11. Povezava do blagovne znamke v nogi
  12. \n' + + '
  13. Ročaj za spreminjanje velikosti urejevalnika v nogi
  14. \n' + + '
\n' + + '\n' + + '

Če razdelek uporabniškega vmesnika ni prisoten, je preskočen.

\n' + + '\n' + + '

Če ima noga fokus za krmarjenje s tipkovnico in ni vidne stranske vrstice, s pritiskom na shift + tabulatorko\n' + + ' fokus premaknete na prvo skupino orodne vrstice, ne zadnjo.

\n' + + '\n' + + '

Krmarjenje v razdelkih uporabniškega vmesnika

\n' + + '\n' + + '

Če se želite premakniti z enega elementa uporabniškega vmesnika na naslednjega, pritisnite ustrezno puščično tipko.

\n' + + '\n' + + '

Leva in desna puščična tipka

\n' + + '\n' + + '
    \n' + + '
  • omogočata premikanje med meniji v menijski vrstici.
  • \n' + + '
  • odpreta podmeni v meniju.
  • \n' + + '
  • omogočata premikanje med gumbi v skupini orodne vrstice.
  • \n' + + '
  • omogočata premikanje med elementi na poti do elementov noge.
  • \n' + + '
\n' + + '\n' + + '

Spodnja in zgornja puščična tipka

\n' + + '\n' + + '
    \n' + + '
  • omogočata premikanje med elementi menija.
  • \n' + + '
  • omogočata premikanje med elementi v pojavnem meniju orodne vrstice.
  • \n' + + '
\n' + + '\n' + + '

Puščične tipke omogočajo kroženje znotraj razdelka uporabniškega vmesnika, na katerem je fokus.

\n' + + '\n' + + '

Če želite zapreti odprt meni, podmeni ali pojavni meni, pritisnite tipko Esc.

\n' + + '\n' + + '

Če je trenutni fokus na »vrhu« določenega razdelka uporabniškega vmesnika, s pritiskom tipke Esc zaprete\n' + + ' tudi celotno krmarjenje s tipkovnico.

\n' + + '\n' + + '

Izvajanje menijskega elementa ali gumba orodne vrstice

\n' + + '\n' + + '

Ko je označen želeni menijski element ali orodja vrstica, pritisnite vračalko, Enter\n' + + ' ali preslednico, da izvedete element.

\n' + + '\n' + + '

Krmarjenje po pogovornih oknih brez zavihkov

\n' + + '\n' + + '

Ko odprete pogovorno okno brez zavihkov, ima fokus prva interaktivna komponenta.

\n' + + '\n' + + '

Med interaktivnimi komponentami pogovornega okna se premikate s pritiskom tabulatorke ali kombinacije tipke shift + tabulatorke.

\n' + + '\n' + + '

Krmarjenje po pogovornih oknih z zavihki

\n' + + '\n' + + '

Ko odprete pogovorno okno z zavihki, ima fokus prvi gumb v meniju zavihka.

\n' + + '\n' + + '

Med interaktivnimi komponentami tega zavihka pogovornega okna se premikate s pritiskom tabulatorke ali\n' + + ' kombinacije tipke shift + tabulatorke.

\n' + + '\n' + + '

Na drug zavihek pogovornega okna preklopite tako, da fokus prestavite na meni zavihka in nato pritisnete ustrezno puščično\n' + + ' tipko, da se pomaknete med razpoložljivimi zavihki.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/sv_SE.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/sv_SE.js new file mode 100644 index 0000000..c30f2f2 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/sv_SE.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.sv_SE', +'

Påbörja tangentbordsnavigering

\n' + + '\n' + + '
\n' + + '
Fokusera på menyraden
\n' + + '
Windows eller Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Fokusera på verktygsraden
\n' + + '
Windows eller Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Fokusera på verktygsraden
\n' + + '
Windows eller Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Fokusera aviseringen
\n' + + '
Windows eller Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Fokusera på en snabbverktygsrad
\n' + + '
Windows, Linux eller macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Navigeringen börjar vid det första gränssnittsobjektet, vilket är markerat eller understruket om det gäller det första objektet i\n' + + ' sidfotens elementsökväg.

\n' + + '\n' + + '

Navigera mellan UI-avsnitt

\n' + + '\n' + + '

Flytta från ett UI-avsnitt till nästa genom att trycka på Tabb.

\n' + + '\n' + + '

Flytta från ett UI-avsnitt till det föregående genom att trycka på Skift+Tabb.

\n' + + '\n' + + '

Tabb-ordningen för dessa UI-avsnitt är:

\n' + + '\n' + + '
    \n' + + '
  1. Menyrad
  2. \n' + + '
  3. Varje verktygsradsgrupp
  4. \n' + + '
  5. Sidoruta
  6. \n' + + '
  7. Elementsökväg i sidfoten
  8. \n' + + '
  9. Växlingsknapp för ordantal i sidfoten
  10. \n' + + '
  11. Varumärkeslänk i sidfoten
  12. \n' + + '
  13. Storlekshandtag för redigeraren i sidfoten
  14. \n' + + '
\n' + + '\n' + + '

Om ett UI-avsnitt inte finns hoppas det över.

\n' + + '\n' + + '

Om sidfoten har fokus på tangentbordsnavigering, och det inte finns någon synlig sidoruta, flyttas fokus till den första verktygsradsgruppen\n' + + ' när du trycker på Skift+Tabb, inte till den sista.

\n' + + '\n' + + '

Navigera i UI-avsnitt

\n' + + '\n' + + '

Flytta från ett UI-element till nästa genom att trycka på motsvarande piltangent.

\n' + + '\n' + + '

Vänsterpil och högerpil

\n' + + '\n' + + '
    \n' + + '
  • flytta mellan menyer på menyraden.
  • \n' + + '
  • öppna en undermeny på en meny.
  • \n' + + '
  • flytta mellan knappar i en verktygsradgrupp.
  • \n' + + '
  • flytta mellan objekt i sidfotens elementsökväg.
  • \n' + + '
\n' + + '\n' + + '

Nedpil och uppil

\n' + + '\n' + + '
    \n' + + '
  • flytta mellan menyalternativ på en meny.
  • \n' + + '
  • flytta mellan alternativ på en popup-meny på verktygsraden.
  • \n' + + '
\n' + + '\n' + + '

Piltangenterna cirkulerar inom det fokuserade UI-avsnittet.

\n' + + '\n' + + '

Tryck på Esc-tangenten om du vill stänga en öppen meny, undermeny eller popup-meny.

\n' + + '\n' + + '

Om det aktuella fokuset är högst upp i ett UI-avsnitt avlutas även tangentbordsnavigeringen helt när\n' + + ' du trycker på Esc-tangenten.

\n' + + '\n' + + '

Köra ett menyalternativ eller en verktygfältsknapp

\n' + + '\n' + + '

När menyalternativet eller verktygsradsknappen är markerad trycker du på Retur, Enter\n' + + ' eller blanksteg för att köra alternativet.

\n' + + '\n' + + '

Navigera i dialogrutor utan flikar

\n' + + '\n' + + '

I dialogrutor utan flikar är den första interaktiva komponenten i fokus när dialogrutan öppnas.

\n' + + '\n' + + '

Navigera mellan interaktiva dialogkomponenter genom att trycka på Tabb eller Skift+Tabb.

\n' + + '\n' + + '

Navigera i dialogrutor med flikar

\n' + + '\n' + + '

I dialogrutor utan flikar är den första knappen på flikmenyn i fokus när dialogrutan öppnas.

\n' + + '\n' + + '

Navigera mellan interaktiva komponenter på dialogrutefliken genom att trycka på Tabb eller\n' + + ' Skift+Tabb.

\n' + + '\n' + + '

Växla till en annan dialogruta genom att fokusera på flikmenyn och sedan trycka på motsvarande piltangent\n' + + ' för att cirkulera mellan de tillgängliga flikarna.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/th_TH.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/th_TH.js new file mode 100644 index 0000000..562fe7a --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/th_TH.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.th_TH', +'

เริ่มต้นการนำทางด้วยแป้นพิมพ์

\n' + + '\n' + + '
\n' + + '
โฟกัสที่แถบเมนู
\n' + + '
Windows หรือ Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
โฟกัสที่แถบเครื่องมือ
\n' + + '
Windows หรือ Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
โฟกัสที่ส่วนท้าย
\n' + + '
Windows หรือ Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
โฟกัสไปที่การแจ้งเตือน
\n' + + '
Windows หรือ Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
โฟกัสที่แถบเครื่องมือตามบริบท
\n' + + '
Windows, Linux หรือ macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

การนำทางจะเริ่มที่รายการ UI แรก ซึ่งจะมีการไฮไลต์หรือขีดเส้นใต้ไว้ในกรณีที่รายการแรกอยู่ใน\n' + + ' พาธองค์ประกอบส่วนท้าย

\n' + + '\n' + + '

การนำทางระหว่างส่วนต่างๆ ของ UI

\n' + + '\n' + + '

ในการย้ายจากส่วน UI หนึ่งไปยังส่วนถัดไป ให้กด Tab

\n' + + '\n' + + '

ในการย้ายจากส่วน UI หนึ่งไปยังส่วนก่อนหน้า ให้กด Shift+Tab

\n' + + '\n' + + '

ลำดับแท็บของส่วนต่างๆ ของ UI คือ:

\n' + + '\n' + + '
    \n' + + '
  1. แถบเมนู
  2. \n' + + '
  3. แต่ละกลุ่มแถบเครื่องมือ
  4. \n' + + '
  5. แถบข้าง
  6. \n' + + '
  7. พาธองค์ประกอบในส่วนท้าย
  8. \n' + + '
  9. ปุ่มสลับเปิด/ปิดจำนวนคำในส่วนท้าย
  10. \n' + + '
  11. ลิงก์ชื่อแบรนด์ในส่วนท้าย
  12. \n' + + '
  13. จุดจับปรับขนาดของตัวแก้ไขในส่วนท้าย
  14. \n' + + '
\n' + + '\n' + + '

หากส่วน UI ไม่ปรากฏ แสดงว่าถูกข้ามไป

\n' + + '\n' + + '

หากส่วนท้ายมีการโฟกัสการนำทางแป้นพิมพ์และไม่มีแถบข้างปรากฏ การกด Shift+Tab\n' + + ' จะย้ายการโฟกัสไปที่กลุ่มแถบเครื่องมือแรก ไม่ใช่สุดท้าย

\n' + + '\n' + + '

การนำทางภายในส่วนต่างๆ ของ UI

\n' + + '\n' + + '

ในการย้ายจากองค์ประกอบ UI หนึ่งไปยังองค์ประกอบส่วนถัดไป ให้กดปุ่มลูกศรที่เหมาะสม

\n' + + '\n' + + '

ปุ่มลูกศรซ้ายและขวา

\n' + + '\n' + + '
    \n' + + '
  • ย้ายไปมาระหว่างเมนูต่างๆ ในแถบเมนู
  • \n' + + '
  • เปิดเมนูย่อยในเมนู
  • \n' + + '
  • ย้ายไปมาระหว่างปุ่มต่างๆ ในกลุ่มแถบเครื่องมือ
  • \n' + + '
  • ย้ายไปมาระหว่างรายการต่างๆ ในพาธองค์ประกอบของส่วนท้าย
  • \n' + + '
\n' + + '\n' + + '

ปุ่มลูกศรลงและขึ้น

\n' + + '\n' + + '
    \n' + + '
  • ย้ายไปมาระหว่างรายการเมนูต่างๆ ในเมนู
  • \n' + + '
  • ย้ายไปมาระหว่างรายการต่างๆ ในเมนูป๊อบอัพแถบเครื่องมือ
  • \n' + + '
\n' + + '\n' + + '

ปุ่มลูกศรจะเลื่อนไปมาภายในส่วน UI ที่โฟกัส

\n' + + '\n' + + '

ในการปิดเมนูที่เปิดอยู่ เมนูย่อยที่เปิดอยู่ หรือเมนูป๊อบอัพที่เปิดอยู่ ให้กดปุ่ม Esc

\n' + + '\n' + + '

หากโฟกัสปัจจุบันอยู่ที่ ‘ด้านบนสุด’ ของส่วน UI เฉพาะ การกดปุ่ม Esc จะทำให้ออกจาก\n' + + ' การนำทางด้วยแป้นพิมพ์ทั้งหมดเช่นกัน

\n' + + '\n' + + '

การดำเนินการรายการเมนูหรือปุ่มในแถบเครื่องมือ

\n' + + '\n' + + '

เมื่อไฮไลต์รายการเมนูหรือปุ่มในแถบเครื่องมือที่ต้องการ ให้กด Return, Enter\n' + + ' หรือ Space bar เพื่อดำเนินการรายการดังกล่าว

\n' + + '\n' + + '

การนำทางสำหรับกล่องโต้ตอบที่ไม่อยู่ในแท็บ

\n' + + '\n' + + '

ในกล่องโต้ตอบที่ไม่อยู่ในแท็บ จะโฟกัสที่ส่วนประกอบเชิงโต้ตอบแรกเมื่อกล่องโต้ตอบเปิด

\n' + + '\n' + + '

นำทางระหว่างส่วนประกอบเชิงโต้ตอบต่างๆ ของกล่องโต้ตอบ โดยการกด Tab หรือ Shift+Tab

\n' + + '\n' + + '

การนำทางสำหรับกล่องโต้ตอบที่อยู่ในแท็บ

\n' + + '\n' + + '

ในกล่องโต้ตอบที่อยู่ในแท็บ จะโฟกัสที่ปุ่มแรกในเมนูแท็บเมื่อกล่องโต้ตอบเปิด

\n' + + '\n' + + '

นำทางระหว่างส่วนประกอบเชิงโต้ตอบต่างๆ ของแท็บกล่องโต้ตอบนี้โดยการกด Tab หรือ\n' + + ' Shift+Tab

\n' + + '\n' + + '

สลับไปยังแท็บกล่องโต้ตอบอื่นโดยการเลือกโฟกัสที่เมนูแท็บ แล้วกดปุ่มลูกศรที่เหมาะสม\n' + + ' เพื่อเลือกแท็บที่ใช้ได้

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/tr.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/tr.js new file mode 100644 index 0000000..37f39b0 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/tr.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.tr', +'

Klavyeyle gezintiyi başlatma

\n' + + '\n' + + '
\n' + + '
Menü çubuğuna odaklan
\n' + + '
Windows veya Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Araç çubuğuna odaklan
\n' + + '
Windows veya Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Alt bilgiye odaklan
\n' + + '
Windows veya Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Bildirime odakla
\n' + + '
Windows veya Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Bağlamsal araç çubuğuna odaklan
\n' + + '
Windows, Linux veya macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Gezinti ilk kullanıcı arabirimi öğesinden başlar, bu öğe vurgulanır ya da ilk öğe, Alt bilgi elemanı\n' + + ' yolundaysa altı çizilir.

\n' + + '\n' + + '

Kullanıcı arabirimi bölümleri arasında gezinme

\n' + + '\n' + + '

Sonraki kullanıcı arabirimi bölümüne gitmek için Sekme tuşuna basın.

\n' + + '\n' + + '

Önceki kullanıcı arabirimi bölümüne gitmek için Shift+Sekme tuşlarına basın.

\n' + + '\n' + + '

Bu kullanıcı arabirimi bölümlerinin Sekme sırası:

\n' + + '\n' + + '
    \n' + + '
  1. Menü çubuğu
  2. \n' + + '
  3. Her araç çubuğu grubu
  4. \n' + + '
  5. Kenar çubuğu
  6. \n' + + '
  7. Alt bilgide öğe yolu
  8. \n' + + '
  9. Alt bilgide sözcük sayısı geçiş düğmesi
  10. \n' + + '
  11. Alt bilgide marka bağlantısı
  12. \n' + + '
  13. Alt bilgide düzenleyiciyi yeniden boyutlandırma tutamacı
  14. \n' + + '
\n' + + '\n' + + '

Kullanıcı arabirimi bölümü yoksa atlanır.

\n' + + '\n' + + '

Alt bilgide klavyeyle gezinti odağı yoksa ve görünür bir kenar çubuğu mevcut değilse Shift+Sekme tuşlarına basıldığında\n' + + ' odak son araç çubuğu yerine ilk araç çubuğu grubuna taşınır.

\n' + + '\n' + + '

Kullanıcı arabirimi bölümleri içinde gezinme

\n' + + '\n' + + '

Sonraki kullanıcı arabirimi elemanına gitmek için uygun Ok tuşuna basın.

\n' + + '\n' + + '

Sol ve Sağ ok tuşları

\n' + + '\n' + + '
    \n' + + '
  • menü çubuğundaki menüler arasında hareket eder.
  • \n' + + '
  • menüde bir alt menü açar.
  • \n' + + '
  • araç çubuğu grubundaki düğmeler arasında hareket eder.
  • \n' + + '
  • alt bilginin öğe yolundaki öğeler arasında hareket eder.
  • \n' + + '
\n' + + '\n' + + '

Aşağı ve Yukarı ok tuşları

\n' + + '\n' + + '
    \n' + + '
  • menüdeki menü öğeleri arasında hareket eder.
  • \n' + + '
  • araç çubuğu açılır menüsündeki öğeler arasında hareket eder.
  • \n' + + '
\n' + + '\n' + + '

Ok tuşları, odaklanılan kullanıcı arabirimi bölümü içinde döngüsel olarak hareket eder.

\n' + + '\n' + + '

Açık bir menüyü, açık bir alt menüyü veya açık bir açılır menüyü kapatmak için Esc tuşuna basın.

\n' + + '\n' + + '

Geçerli odak belirli bir kullanıcı arabirimi bölümünün "üst" kısmındaysa Esc tuşuna basıldığında\n' + + ' klavyeyle gezintiden de tamamen çıkılır.

\n' + + '\n' + + '

Menü öğesini veya araç çubuğu düğmesini yürütme

\n' + + '\n' + + '

İstediğiniz menü öğesi veya araç çubuğu düğmesi vurgulandığında Return, Enter\n' + + ' veya Ara çubuğu tuşuna basın.

\n' + + '\n' + + '

Sekme bulunmayan iletişim kutularında gezinme

\n' + + '\n' + + '

Sekme bulunmayan iletişim kutularında, iletişim kutusu açıldığında ilk etkileşimli bileşene odaklanılır.

\n' + + '\n' + + '

Etkileşimli iletişim kutusu bileşenleri arasında gezinmek için Sekme veya Shift+ Sekme tuşlarına basın.

\n' + + '\n' + + '

Sekmeli iletişim kutularında gezinme

\n' + + '\n' + + '

Sekmeli iletişim kutularında, iletişim kutusu açıldığında sekme menüsündeki ilk düğmeye odaklanılır.

\n' + + '\n' + + '

Bu iletişim kutusu sekmesinin etkileşimli bileşenleri arasında gezinmek için Sekme veya\n' + + ' Shift+Sekme tuşlarına basın.

\n' + + '\n' + + '

Mevcut sekmeler arasında geçiş yapmak için sekme menüsüne odaklanıp uygun Ok tuşuna basarak\n' + + ' başka bir iletişim kutusu sekmesine geçiş yapın.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/uk.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/uk.js new file mode 100644 index 0000000..028d4a4 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/uk.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.uk', +'

Початок роботи з навігацією за допомогою клавіатури

\n' + + '\n' + + '
\n' + + '
Фокус на рядок меню
\n' + + '
Windows або Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Фокус на панелі інструментів
\n' + + '
Windows або Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Фокус на розділі "Нижній колонтитул"
\n' + + '
Windows або Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Фокус на сповіщення
\n' + + '
Windows або Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Фокус на контекстній панелі інструментів
\n' + + '
Windows, Linux або macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Навігація почнеться з першого елемента інтерфейсу користувача, який буде виділено або підкреслено в разі, якщо перший елемент знаходиться в\n' + + ' шляху до елемента "Нижній колонтитул".

\n' + + '\n' + + '

Навігація між розділами інтерфейсу користувача

\n' + + '\n' + + '

Щоб перейти з одного розділу інтерфейсу користувача до наступного розділу, натисніть клавішу Tab.

\n' + + '\n' + + '

Щоб перейти з одного розділу інтерфейсу користувача до попереднього розділу, натисніть сполучення клавіш Shift+Tab.

\n' + + '\n' + + '

Порядок Вкладок цих розділів інтерфейсу користувача такий:

\n' + + '\n' + + '
    \n' + + '
  1. Рядок меню
  2. \n' + + '
  3. Кожна група панелей інструментів
  4. \n' + + '
  5. Бічна панель
  6. \n' + + '
  7. Шлях до елементів у розділі "Нижній колонтитул"
  8. \n' + + '
  9. Кнопка перемикача "Кількість слів" у розділі "Нижній колонтитул"
  10. \n' + + '
  11. Посилання на брендинг у розділі "Нижній колонтитул"
  12. \n' + + '
  13. Маркер змінення розміру в розділі "Нижній колонтитул"
  14. \n' + + '
\n' + + '\n' + + '

Якщо розділ інтерфейсу користувача відсутній, він пропускається.

\n' + + '\n' + + '

Якщо фокус навігації клавіатури знаходиться на розділі "Нижній колонтитул", але користувач не бачить видиму бічну панель, натисніть Shift+Tab,\n' + + ' щоб перемістити фокус на першу групу панелі інструментів, а не на останню.

\n' + + '\n' + + '

Навігація в межах розділів інтерфейсу користувача

\n' + + '\n' + + '

Щоб перейти з одного елементу інтерфейсу користувача до наступного, натисніть відповідну клавішу зі стрілкою.

\n' + + '\n' + + '

Клавіші зі стрілками Ліворуч і Праворуч

\n' + + '\n' + + '
    \n' + + '
  • переміщують між меню в рядку меню.
  • \n' + + '
  • відкривають вкладене меню в меню.
  • \n' + + '
  • переміщують користувача між кнопками в групі панелі інструментів.
  • \n' + + '
  • переміщують між елементами в шляху до елементів у розділі "Нижній колонтитул".
  • \n' + + '
\n' + + '\n' + + '

Клавіші зі стрілками Вниз і Вгору

\n' + + '\n' + + '
    \n' + + '
  • переміщують між елементами меню в меню.
  • \n' + + '
  • переміщують між елементами в спливаючому меню панелі інструментів.
  • \n' + + '
\n' + + '\n' + + '

Клавіші зі стрілками переміщують фокус циклічно в межах розділу інтерфейсу користувача, на якому знаходиться фокус.

\n' + + '\n' + + '

Щоб закрити відкрите меню, відкрите вкладене меню або відкрите спливаюче меню, натисніть клавішу Esc.

\n' + + '\n' + + '

Якщо поточний фокус знаходиться на верхньому рівні певного розділу інтерфейсу користувача, натискання клавіші Esc також виконує вихід\n' + + ' з навігації за допомогою клавіатури повністю.

\n' + + '\n' + + '

Виконання елементу меню або кнопки панелі інструментів

\n' + + '\n' + + '

Коли потрібний елемент меню або кнопку панелі інструментів виділено, натисніть клавіші Return, Enter,\n' + + ' або Пробіл, щоб виконати цей елемент.

\n' + + '\n' + + '

Навігація по діалоговим вікнам без вкладок

\n' + + '\n' + + '

У діалогових вікнах без вкладок перший інтерактивний компонент приймає фокус, коли відкривається діалогове вікно.

\n' + + '\n' + + '

Переходьте між інтерактивними компонентами діалогового вікна, натискаючи клавіші Tab або Shift+Tab.

\n' + + '\n' + + '

Навігація по діалоговим вікнам з вкладками

\n' + + '\n' + + '

У діалогових вікнах із вкладками перша кнопка в меню вкладки приймає фокус, коли відкривається діалогове вікно.

\n' + + '\n' + + '

Переходьте між інтерактивними компонентами цієї вкладки діалогового вікна, натискаючи клавіші Tab або\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Щоб перейти на іншу вкладку діалогового вікна, перемістіть фокус на меню вкладки, а потім натисніть відповідну клавішу зі стрілкою,\n' + + ' щоб циклічно переходити по доступним вкладкам.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/vi.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/vi.js new file mode 100644 index 0000000..d8eda11 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/vi.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.vi', +'

Bắt đầu điều hướng bàn phím

\n' + + '\n' + + '
\n' + + '
Tập trung vào thanh menu
\n' + + '
Windows hoặc Linux: Alt+F9
\n' + + '
macOS: ⌥F9
\n' + + '
Tập trung vào thanh công cụ
\n' + + '
Windows hoặc Linux: Alt+F10
\n' + + '
macOS: ⌥F10
\n' + + '
Tập trung vào chân trang
\n' + + '
Windows hoặc Linux: Alt+F11
\n' + + '
macOS: ⌥F11
\n' + + '
Tập trung vào thông báo
\n' + + '
Windows hoặc Linux: Alt+F12
\n' + + '
macOS: ⌥F12
\n' + + '
Tập trung vào thanh công cụ ngữ cảnh
\n' + + '
Windows, Linux hoặc macOS: Ctrl+F9
\n' + + '
\n' + + '\n' + + '

Điều hướng sẽ bắt đầu từ mục UI đầu tiên. Mục này sẽ được tô sáng hoặc có gạch dưới (nếu là mục đầu tiên trong\n' + + ' đường dẫn phần tử Chân trang).

\n' + + '\n' + + '

Di chuyển qua lại giữa các phần UI

\n' + + '\n' + + '

Để di chuyển từ một phần UI sang phần tiếp theo, ấn Tab.

\n' + + '\n' + + '

Để di chuyển từ một phần UI về phần trước đó, ấn Shift+Tab.

\n' + + '\n' + + '

Thứ tự Tab của các phần UI này như sau:

\n' + + '\n' + + '
    \n' + + '
  1. Thanh menu
  2. \n' + + '
  3. Từng nhóm thanh công cụ
  4. \n' + + '
  5. Thanh bên
  6. \n' + + '
  7. Đường dẫn phần tử trong chân trang
  8. \n' + + '
  9. Nút chuyển đổi đếm chữ ở chân trang
  10. \n' + + '
  11. Liên kết thương hiệu ở chân trang
  12. \n' + + '
  13. Núm điều tác chỉnh kích cỡ trình soạn thảo ở chân trang
  14. \n' + + '
\n' + + '\n' + + '

Nếu người dùng không thấy một phần UI, thì có nghĩa phần đó bị bỏ qua.

\n' + + '\n' + + '

Nếu ở chân trang có tính năng tập trung điều hướng bàn phím, mà không có thanh bên nào hiện hữu, thao tác ấn Shift+Tab\n' + + ' sẽ chuyển hướng tập trung vào nhóm thanh công cụ đầu tiên, không phải cuối cùng.

\n' + + '\n' + + '

Di chuyển qua lại trong các phần UI

\n' + + '\n' + + '

Để di chuyển từ một phần tử UI sang phần tiếp theo, ấn phím Mũi tên tương ứng cho phù hợp.

\n' + + '\n' + + '

Các phím mũi tên TráiPhải

\n' + + '\n' + + '
    \n' + + '
  • di chuyển giữa các menu trong thanh menu.
  • \n' + + '
  • mở menu phụ trong một menu.
  • \n' + + '
  • di chuyển giữa các nút trong nhóm thanh công cụ.
  • \n' + + '
  • di chuyển giữa các mục trong đường dẫn phần tử của chân trang.
  • \n' + + '
\n' + + '\n' + + '

Các phím mũi tên Hướng xuốngHướng lên

\n' + + '\n' + + '
    \n' + + '
  • di chuyển giữa các mục menu trong menu.
  • \n' + + '
  • di chuyển giữa các mục trong menu thanh công cụ dạng bật lên.
  • \n' + + '
\n' + + '\n' + + '

Các phím mũi tên xoay vòng trong một phần UI tập trung.

\n' + + '\n' + + '

Để đóng một menu mở, một menu phụ đang mở, hoặc một menu dạng bật lên đang mở, hãy ấn phím Esc.

\n' + + '\n' + + '

Nếu trọng tâm hiện tại là ở phần “đầu” của một phần UI cụ thể, thao tác ấn phím Esc cũng sẽ thoát\n' + + ' toàn bộ phần điều hướng bàn phím.

\n' + + '\n' + + '

Thực hiện chức năng của một mục menu hoặc nút thanh công cụ

\n' + + '\n' + + '

Khi mục menu hoặc nút thanh công cụ muốn dùng được tô sáng, hãy ấn Return, Enter,\n' + + ' hoặc Phím cách để thực hiện chức năng mục đó.

\n' + + '\n' + + '

Điều hướng giữa các hộp thoại không có nhiều tab

\n' + + '\n' + + '

Trong các hộp thoại không có nhiều tab, khi hộp thoại mở ra, trọng tâm sẽ hướng vào thành phần tương tác đầu tiên.

\n' + + '\n' + + '

Di chuyển giữa các thành phần hộp thoại tương tác bằng cách ấn Tab hoặc Shift+Tab.

\n' + + '\n' + + '

Điều hướng giữa các hộp thoại có nhiều tab

\n' + + '\n' + + '

Trong các hộp thoại có nhiều tab, khi hộp thoại mở ra, trọng tâm sẽ hướng vào nút đầu tiên trong menu tab.

\n' + + '\n' + + '

Di chuyển giữa các thành phần tương tác của tab hộp thoại này bằng cách ấn Tab hoặc\n' + + ' Shift+Tab.

\n' + + '\n' + + '

Chuyển sang một tab hộp thoại khác bằng cách chuyển trọng tâm vào menu tab, rồi ấn phím Mũi tên phù hợp\n' + + ' để xoay vòng các tab hiện có.

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/zh_CN.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/zh_CN.js new file mode 100644 index 0000000..f7e73d1 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/zh_CN.js @@ -0,0 +1,87 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.zh_CN', +'

开始键盘导航

\n' + + '\n' + + '
\n' + + '
使菜单栏处于焦点
\n' + + '
Windows 或 Linux:Alt+F9
\n' + + '
macOS:⌥F9
\n' + + '
使工具栏处于焦点
\n' + + '
Windows 或 Linux:Alt+F10
\n' + + '
macOS:⌥F10
\n' + + '
使页脚处于焦点
\n' + + '
Windows 或 Linux:Alt+F11
\n' + + '
macOS:⌥F11
\n' + + '
使通知处于焦点
\n' + + '
Windows 或 Linux:Alt+F12
\n' + + '
macOS:⌥F12
\n' + + '
使上下文工具栏处于焦点
\n' + + '
Windows、Linux 或 macOS:Ctrl+F9
\n' + + '
\n' + + '\n' + + '

导航将在第一个 UI 项上开始,其中突出显示该项,或者对于页脚元素路径中的第一项,将为其添加下划线。

\n' + + '\n' + + '

在 UI 部分之间导航

\n' + + '\n' + + '

要从一个 UI 部分移至下一个,请按 Tab

\n' + + '\n' + + '

要从一个 UI 部分移至上一个,请按 Shift+Tab

\n' + + '\n' + + '

这些 UI 部分的 Tab 顺序为:

\n' + + '\n' + + '
    \n' + + '
  1. 菜单栏
  2. \n' + + '
  3. 每个工具栏组
  4. \n' + + '
  5. 边栏
  6. \n' + + '
  7. 页脚中的元素路径
  8. \n' + + '
  9. 页脚中的字数切换按钮
  10. \n' + + '
  11. 页脚中的品牌链接
  12. \n' + + '
  13. 页脚中的编辑器调整大小图柄
  14. \n' + + '
\n' + + '\n' + + '

如果不存在某个 UI 部分,则跳过它。

\n' + + '\n' + + '

如果键盘导航焦点在页脚,并且没有可见的边栏,则按 Shift+Tab 将焦点移至第一个工具栏组而非最后一个。

\n' + + '\n' + + '

在 UI 部分内导航

\n' + + '\n' + + '

要从一个 UI 元素移至下一个,请按相应的箭头键。

\n' + + '\n' + + '

箭头键

\n' + + '\n' + + '
    \n' + + '
  • 在菜单栏中的菜单之间移动。
  • \n' + + '
  • 打开菜单中的子菜单。
  • \n' + + '
  • 在工具栏组中的按钮之间移动。
  • \n' + + '
  • 在页脚的元素路径中的各项之间移动。
  • \n' + + '
\n' + + '\n' + + '

箭头键

\n' + + '\n' + + '
    \n' + + '
  • 在菜单中的菜单项之间移动。
  • \n' + + '
  • 在工具栏弹出菜单中的各项之间移动。
  • \n' + + '
\n' + + '\n' + + '

箭头键在具有焦点的 UI 部分内循环。

\n' + + '\n' + + '

要关闭打开的菜单、打开的子菜单或打开的弹出菜单,请按 Esc 键。

\n' + + '\n' + + '

如果当前的焦点在特定 UI 部分的“顶部”,则按 Esc 键还将完全退出键盘导航。

\n' + + '\n' + + '

执行菜单项或工具栏按钮

\n' + + '\n' + + '

当突出显示所需的菜单项或工具栏按钮时,按 ReturnEnter空格以执行该项。

\n' + + '\n' + + '

在非标签页式对话框中导航

\n' + + '\n' + + '

在非标签页式对话框中,当对话框打开时,第一个交互组件获得焦点。

\n' + + '\n' + + '

通过按 TabShift+Tab,在交互对话框组件之间导航。

\n' + + '\n' + + '

在标签页式对话框中导航

\n' + + '\n' + + '

在标签页式对话框中,当对话框打开时,标签页菜单中的第一个按钮获得焦点。

\n' + + '\n' + + '

通过按 TabShift+Tab,在此对话框的交互组件之间导航。

\n' + + '\n' + + '

通过将焦点移至另一对话框标签页的菜单,然后按相应的箭头键以在可用的标签页间循环,从而切换到该对话框标签页。

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/zh_TW.js b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/zh_TW.js new file mode 100644 index 0000000..5912770 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/js/i18n/keynav/zh_TW.js @@ -0,0 +1,93 @@ +tinymce.Resource.add('tinymce.html-i18n.help-keynav.zh_TW', +'

開始鍵盤瀏覽

\n' + + '\n' + + '
\n' + + '
跳至功能表列
\n' + + '
Windows 或 Linux:Alt+F9
\n' + + '
macOS:⌥F9
\n' + + '
跳至工具列
\n' + + '
Windows 或 Linux:Alt+F10
\n' + + '
macOS:⌥F10
\n' + + '
跳至頁尾
\n' + + '
Windows 或 Linux:Alt+F11
\n' + + '
macOS:⌥F11
\n' + + '
跳至通知
\n' + + '
Windows 或 Linux:Alt+F12
\n' + + '
macOS:⌥F12
\n' + + '
跳至關聯式工具列
\n' + + '
Windows、Linux 或 macOS:Ctrl+F9
\n' + + '
\n' + + '\n' + + '

瀏覽會從第一個 UI 項目開始,該項目會反白顯示,但如果是「頁尾」元素路徑的第一項,\n' + + ' 則加底線。

\n' + + '\n' + + '

在 UI 區段之間瀏覽

\n' + + '\n' + + '

從 UI 區段移至下一個,請按 Tab

\n' + + '\n' + + '

從 UI 區段移回上一個,請按 Shift+Tab

\n' + + '\n' + + '

這些 UI 區段的 Tab 順序如下:

\n' + + '\n' + + '
    \n' + + '
  1. 功能表列
  2. \n' + + '
  3. 各個工具列群組
  4. \n' + + '
  5. 側邊欄
  6. \n' + + '
  7. 頁尾中的元素路徑
  8. \n' + + '
  9. 頁尾中字數切換按鈕
  10. \n' + + '
  11. 頁尾中的品牌連結
  12. \n' + + '
  13. 頁尾中編輯器調整大小控點
  14. \n' + + '
\n' + + '\n' + + '

如果 UI 區段未顯示,表示已略過該區段。

\n' + + '\n' + + '

如果鍵盤瀏覽跳至頁尾,但沒有顯示側邊欄,則按下 Shift+Tab\n' + + ' 會跳至第一個工具列群組,而不是最後一個。

\n' + + '\n' + + '

在 UI 區段之內瀏覽

\n' + + '\n' + + '

在兩個 UI 元素之間移動,請按適當的方向鍵。

\n' + + '\n' + + '

向左向右方向鍵

\n' + + '\n' + + '
    \n' + + '
  • 在功能表列中的功能表之間移動。
  • \n' + + '
  • 開啟功能表中的子功能表。
  • \n' + + '
  • 在工具列群組中的按鈕之間移動。
  • \n' + + '
  • 在頁尾的元素路徑中項目之間移動。
  • \n' + + '
\n' + + '\n' + + '

向下向上方向鍵

\n' + + '\n' + + '
    \n' + + '
  • 在功能表中的功能表項目之間移動。
  • \n' + + '
  • 在工具列快顯功能表中的項目之間移動。
  • \n' + + '
\n' + + '\n' + + '

方向鍵會在所跳至 UI 區段之內循環。

\n' + + '\n' + + '

若要關閉已開啟的功能表、已開啟的子功能表,或已開啟的快顯功能表,請按 Esc 鍵。

\n' + + '\n' + + '

如果目前已跳至特定 UI 區段的「頂端」,則按 Esc 鍵也會結束\n' + + ' 整個鍵盤瀏覽。

\n' + + '\n' + + '

執行功能表列項目或工具列按鈕

\n' + + '\n' + + '

當想要的功能表項目或工具列按鈕已反白顯示時,按 ReturnEnter、\n' + + ' 或空白鍵即可執行該項目。

\n' + + '\n' + + '

瀏覽非索引標籤式對話方塊

\n' + + '\n' + + '

在非索引標籤式對話方塊中,開啟對話方塊時會跳至第一個互動元件。

\n' + + '\n' + + '

TabShift+Tab 即可在互動式對話方塊元件之間瀏覽。

\n' + + '\n' + + '

瀏覽索引標籤式對話方塊

\n' + + '\n' + + '

在索引標籤式對話方塊中,開啟對話方塊時會跳至索引標籤式功能表中的第一個按鈕。

\n' + + '\n' + + '

若要在此對話方塊的互動式元件之間瀏覽,請按 Tab 或\n' + + ' Shift+Tab

\n' + + '\n' + + '

先跳至索引標籤式功能表,然後按適當的方向鍵,即可切換至另一個對話方塊索引標籤,\n' + + ' 以循環瀏覽可用的索引標籤。

\n'); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/help/plugin.min.js b/apps/web-antd/public/tinymce/plugins/help/plugin.min.js new file mode 100644 index 0000000..acddac2 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/help/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");let t=0;const n=e=>{const n=(new Date).getTime(),a=Math.floor(window.crypto.getRandomValues(new Uint32Array(1))[0]/4294967295*1e9);return t++,e+"_"+a+t+String(n)},a=e=>t=>t.options.get(e),r=a("help_tabs"),o=a("forced_plugins"),i=e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=a=e,(r=String).prototype.isPrototypeOf(n)||(null===(o=a.constructor)||void 0===o?void 0:o.name)===r.name)?"string":t;var n,a,r,o})(e);const s=e=>undefined===e;const c=e=>"function"==typeof e,l=()=>false;class m{constructor(e,t){this.tag=e,this.value=t}static some(e){return new m(!0,e)}static none(){return m.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?m.some(e(this.value)):m.none()}bind(e){return this.tag?e(this.value):m.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:m.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return null==e?m.none():m.some(e)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}m.singletonNone=new m(!1);const u=Array.prototype.slice,p=Array.prototype.indexOf,y=(e,t)=>{const n=e.length,a=new Array(n);for(let r=0;r{const n=[];for(let a=0,r=e.length;a{const n=u.call(e,0);return n.sort(t),n},g=Object.keys,k=Object.hasOwnProperty,v=(e,t)=>k.call(e,t);var b=tinymce.util.Tools.resolve("tinymce.Resource"),f=tinymce.util.Tools.resolve("tinymce.util.I18n");const A=(e,t)=>b.load(`tinymce.html-i18n.help-keynav.${t}`,`${e}/js/i18n/keynav/${t}.js`),w=e=>A(e,f.getCode()).catch((()=>A(e,"en")));var C=tinymce.util.Tools.resolve("tinymce.Env");const S=e=>{const t=C.os.isMacOS()||C.os.isiOS(),n=t?{alt:"⌥",ctrl:"⌃",shift:"⇧",meta:"⌘",access:"⌃⌥"}:{meta:"Ctrl ",access:"Shift + Alt "},a=e.split("+"),r=y(a,(e=>{const t=e.toLowerCase().trim();return v(n,t)?n[t]:e}));return t?r.join("").replace(/\s/,""):r.join("+")},M=[{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:["Alt + F12"],action:"Focus to notification"},{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"}],_=()=>({name:"shortcuts",title:"Handy Shortcuts",items:[{type:"table",header:["Action","Shortcut"],cells:y(M,(e=>{const t=y(e.shortcuts,S).join(" or ");return[e.action,t]}))}]}),x=y([{key:"accordion",name:"Accordion"},{key:"anchor",name:"Anchor"},{key:"autolink",name:"Autolink"},{key:"autoresize",name:"Autoresize"},{key:"autosave",name:"Autosave"},{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:"fullscreen",name:"Full Screen"},{key:"help",name:"Help"},{key:"image",name:"Image"},{key:"importcss",name:"Import CSS"},{key:"insertdatetime",name:"Insert Date/Time"},{key:"link",name:"Link"},{key:"lists",name:"Lists"},{key:"advlist",name:"List Styles"},{key:"media",name:"Media"},{key:"nonbreaking",name:"Nonbreaking"},{key:"pagebreak",name:"Page Break"},{key:"preview",name:"Preview"},{key:"quickbars",name:"Quick Toolbars"},{key:"save",name:"Save"},{key:"searchreplace",name:"Search and Replace"},{key:"table",name:"Table"},{key:"textcolor",name:"Text Color"},{key:"visualblocks",name:"Visual Blocks"},{key:"visualchars",name:"Visual Characters"},{key:"wordcount",name:"Word Count"},{key:"a11ychecker",name:"Accessibility Checker",type:"premium"},{key:"typography",name:"Advanced Typography",type:"premium",slug:"advanced-typography"},{key:"ai",name:"AI Assistant",type:"premium"},{key:"casechange",name:"Case Change",type:"premium"},{key:"checklist",name:"Checklist",type:"premium"},{key:"advcode",name:"Enhanced Code Editor",type:"premium"},{key:"mediaembed",name:"Enhanced Media Embed",type:"premium",slug:"introduction-to-mediaembed"},{key:"advtable",name:"Enhanced Tables",type:"premium"},{key:"exportpdf",name:"Export to PDF",type:"premium"},{key:"exportword",name:"Export to Word",type:"premium"},{key:"footnotes",name:"Footnotes",type:"premium"},{key:"formatpainter",name:"Format Painter",type:"premium"},{key:"editimage",name:"Image Editing",type:"premium"},{key:"uploadcare",name:"Image Optimizer Powered by Uploadcare",type:"premium"},{key:"importword",name:"Import from Word",type:"premium"},{key:"inlinecss",name:"Inline CSS",type:"premium",slug:"inline-css"},{key:"linkchecker",name:"Link Checker",type:"premium"},{key:"math",name:"Math",type:"premium"},{key:"markdown",name:"Markdown",type:"premium"},{key:"mentions",name:"Mentions",type:"premium"},{key:"mergetags",name:"Merge Tags",type:"premium"},{key:"pageembed",name:"Page Embed",type:"premium"},{key:"permanentpen",name:"Permanent Pen",type:"premium"},{key:"powerpaste",name:"PowerPaste",type:"premium",slug:"introduction-to-powerpaste"},{key:"revisionhistory",name:"Revision History",type:"premium"},{key:"tinymcespellchecker",name:"Spell Checker",type:"premium",slug:"introduction-to-tiny-spellchecker"},{key:"autocorrect",name:"Spelling Autocorrect",type:"premium"},{key:"tableofcontents",name:"Table of Contents",type:"premium"},{key:"advtemplate",name:"Templates",type:"premium",slug:"advanced-templates"},{key:"tinycomments",name:"Tiny Comments",type:"premium",slug:"introduction-to-tiny-comments"},{key:"tinydrive",name:"Tiny Drive",type:"premium",slug:"tinydrive-introduction"}],(e=>({...e,type:e.type||"opensource",slug:e.slug||e.key}))),T=e=>{const t=e=>`${e.name}`,n=(e,n)=>{return(a=x,r=e=>e.key===n,((e,t,n)=>{for(let a=0,r=e.length;a((e,n)=>{const a=e.plugins[n].getMetadata;if(c(a)){const e=a();return{name:e.name,html:t(e)}}return{name:n,html:n}})(e,n)),(e=>{const n="premium"===e.type?`${e.name}*`:e.name;return{name:n,html:t({name:n,url:`https://www.tiny.cloud/docs/tinymce/7/${e.slug}/`})}}));var a,r},a=e=>{const t=(e=>{const t=g(e.plugins),n=o(e),a=s(n)?["onboarding"]:n.concat(["onboarding"]);return h(t,(e=>!(((e,t)=>p.call(e,t))(a,e)>-1)))})(e),a=d(y(t,(t=>n(e,t))),((e,t)=>e.name.localeCompare(t.name))),r=y(a,(e=>"
  • "+e.html+"
  • ")),i=r.length,c=r.join("");return"

    "+f.translate(["Plugins installed ({0}):",i])+"

      "+c+"
    "},r={type:"htmlpanel",presets:"document",html:[(e=>null==e?"":"
    "+a(e)+"
    ")(e),(()=>{const e=h(x,(({type:e})=>"premium"===e)),t=d(y(e,(e=>e.name)),((e,t)=>e.localeCompare(t))),n=y(t,(e=>`
  • ${e}
  • `)).join("");return"

    "+f.translate("Premium plugins:")+"

    "})()].join("")};return{name:"plugins",title:"Plugins",items:[r]}};var O=tinymce.util.Tools.resolve("tinymce.EditorManager");const P=(e,t,a)=>()=>{(async(e,t,a)=>{const o=_(),s=await(async e=>({name:"keyboardnav",title:"Keyboard Navigation",items:[{type:"htmlpanel",presets:"document",html:await w(e)}]}))(a),c=T(e),l=(()=>{var e,t;const n='TinyMCE '+(e=O.majorVersion,t=O.minorVersion,(0===e.indexOf("@")?"X.X.X":e+"."+t)+"");return{name:"versions",title:"Version",items:[{type:"htmlpanel",html:"

    "+f.translate(["You are using {0}",n])+"

    ",presets:"document"}]}})(),u={[o.name]:o,[s.name]:s,[c.name]:c,[l.name]:l,...t.get()};return m.from(r(e)).fold((()=>(e=>{const t=g(e),n=t.indexOf("versions");return-1!==n&&(t.splice(n,1),t.push("versions")),{tabs:e,names:t}})(u)),(e=>((e,t)=>{const a={},r=y(e,(e=>{var r;if(i(e))return v(t,e)&&(a[e]=t[e]),e;{const t=null!==(r=e.name)&&void 0!==r?r:n("tab-name");return a[t]=e,t}}));return{tabs:a,names:r}})(e,u)))})(e,t,a).then((({tabs:t,names:n})=>{const a={type:"tabpanel",tabs:(e=>{const t=[],n=e=>{t.push(e)};for(let t=0;t{return v(n=t,a=e)?m.from(n[a]):m.none();var n,a})))};e.windowManager.open({title:"Help",size:"medium",body:a,buttons:[{type:"cancel",name:"close",text:"Close",primary:!0}],initialData:{}})}))};e.add("help",((e,t)=>{const a=(()=>{let e={};return{get:()=>e,set:t=>{e=t}}})(),r=(e=>({addTab:t=>{var a;const r=null!==(a=t.name)&&void 0!==a?a:n("tab-name"),o=e.get();o[r]=t,e.set(o)}}))(a);(e=>{(0,e.options.register)("help_tabs",{processor:"array"})})(e);const o=P(e,a,t);return((e,t)=>{e.ui.registry.addButton("help",{icon:"help",tooltip:"Help",onAction:t,context:"any"}),e.ui.registry.addMenuItem("help",{text:"Help",icon:"help",shortcut:"Alt+0",onAction:t,context:"any"})})(e,o),((e,t)=>{e.addCommand("mceHelp",t)})(e,o),e.shortcuts.add("Alt+0","Open help dialog","mceHelp"),((e,t)=>{e.on("init",(()=>{w(t)}))})(e,t),r}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/image/plugin.min.js b/apps/web-antd/public/tinymce/plugins/image/plugin.min.js new file mode 100644 index 0000000..9480158 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/image/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=Object.getPrototypeOf,a=(e,t,a)=>{var i;return!!a(e,t.prototype)||(null===(i=e.constructor)||void 0===i?void 0:i.name)===t.name},i=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&a(e,String,((e,t)=>t.isPrototypeOf(e)))?"string":t})(t)===e,s=e=>t=>typeof t===e,r=i("string"),o=i("object"),n=e=>((e,i)=>o(e)&&a(e,i,((e,a)=>t(e)===a)))(e,Object),l=i("array"),c=e=>null===e;const m=s("boolean"),d=e=>!(e=>null==e)(e),g=s("function"),u=s("number"),p=()=>{};class h{constructor(e,t){this.tag=e,this.value=t}static some(e){return new h(!0,e)}static none(){return h.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?h.some(e(this.value)):h.none()}bind(e){return this.tag?e(this.value):h.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:h.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return d(e)?h.some(e):h.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}h.singletonNone=new h(!1);const b=Object.keys,v=Object.hasOwnProperty,y=(e,t)=>v.call(e,t),f=Array.prototype.push,w=e=>{const t=[];for(let a=0,i=e.length;a{((e,t,a)=>{if(!(r(a)||m(a)||u(a)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",a,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,a+"")})(e.dom,t,a)},D=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},_=D;var C=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),I=tinymce.util.Tools.resolve("tinymce.util.URI");const U=e=>e.length>0,S=e=>t=>t.options.get(e),x=S("image_dimensions"),N=S("image_advtab"),T=S("image_uploadtab"),E=S("image_prepend_url"),L=S("image_class_list"),O=S("image_description"),j=S("image_title"),M=S("image_caption"),R=S("image_list"),k=S("a11y_advanced_options"),z=S("automatic_uploads"),B=(e,t)=>Math.max(parseInt(e,10),parseInt(t,10)),P=e=>(e&&(e=e.replace(/px$/,"")),e),F=e=>(e.length>0&&/^[0-9]+$/.test(e)&&(e+="px"),e),H=e=>"IMG"===e.nodeName&&(e.hasAttribute("data-mce-object")||e.hasAttribute("data-mce-placeholder")),G=(e,t)=>{const a=e.options.get;return I.isDomSafe(t,"img",{allow_html_data_urls:a("allow_html_data_urls"),allow_script_urls:a("allow_script_urls"),allow_svg_data_urls:a("allow_svg_data_urls")})},W=C.DOM,$=e=>e.style.marginLeft&&e.style.marginRight&&e.style.marginLeft===e.style.marginRight?P(e.style.marginLeft):"",V=e=>e.style.marginTop&&e.style.marginBottom&&e.style.marginTop===e.style.marginBottom?P(e.style.marginTop):"",K=e=>e.style.borderWidth?P(e.style.borderWidth):"",Z=(e,t)=>{var a;return e.hasAttribute(t)&&null!==(a=e.getAttribute(t))&&void 0!==a?a:""},q=e=>null!==e.parentNode&&"FIGURE"===e.parentNode.nodeName,J=(e,t,a)=>{""===a||null===a?e.removeAttribute(t):e.setAttribute(t,a)},Q=(e,t)=>{const a=e.getAttribute("style"),i=t(null!==a?a:"");i.length>0?(e.setAttribute("style",i),e.setAttribute("data-mce-style",i)):e.removeAttribute("style")},X=(e,t)=>(e,a,i)=>{const s=e.style;s[a]?(s[a]=F(i),Q(e,t)):J(e,a,i)},Y=(e,t)=>e.style[t]?P(e.style[t]):Z(e,t),ee=(e,t)=>{const a=F(t);e.style.marginLeft=a,e.style.marginRight=a},te=(e,t)=>{const a=F(t);e.style.marginTop=a,e.style.marginBottom=a},ae=(e,t)=>{const a=F(t);e.style.borderWidth=a},ie=(e,t)=>{e.style.borderStyle=t},se=e=>{var t;return null!==(t=e.style.borderStyle)&&void 0!==t?t:""},re=e=>d(e)&&"FIGURE"===e.nodeName,oe=e=>0===W.getAttrib(e,"alt").length&&"presentation"===W.getAttrib(e,"role"),ne=e=>oe(e)?"":Z(e,"alt"),le=(e,t)=>{var a;const i=document.createElement("img");return J(i,"style",t.style),($(i)||""!==t.hspace)&&ee(i,t.hspace),(V(i)||""!==t.vspace)&&te(i,t.vspace),(K(i)||""!==t.border)&&ae(i,t.border),(se(i)||""!==t.borderStyle)&&ie(i,t.borderStyle),e(null!==(a=i.getAttribute("style"))&&void 0!==a?a:"")},ce=(e,t)=>({src:Z(t,"src"),alt:ne(t),title:Z(t,"title"),width:Y(t,"width"),height:Y(t,"height"),class:Z(t,"class"),style:e(Z(t,"style")),caption:q(t),hspace:$(t),vspace:V(t),border:K(t),borderStyle:se(t),isDecorative:oe(t)}),me=(e,t,a,i,s)=>{a[i]!==t[i]&&s(e,i,String(a[i]))},de=(e,t,a)=>{if(a){W.setAttrib(e,"role","presentation");const t=_(e);A(t,"alt","")}else{if(c(t)){_(e).dom.removeAttribute("alt")}else{const a=_(e);A(a,"alt",t)}"presentation"===W.getAttrib(e,"role")&&W.setAttrib(e,"role","")}},ge=(e,t)=>(a,i,s)=>{e(a,s),Q(a,t)},ue=(e,t,a)=>{const i=ce(e,a);me(a,i,t,"caption",((e,t,a)=>(e=>{q(e)?(e=>{const t=e.parentNode;d(t)&&(W.insertAfter(e,t),W.remove(t))})(e):(e=>{const t=W.create("figure",{class:"image"});W.insertAfter(t,e),t.appendChild(e),t.appendChild(W.create("figcaption",{contentEditable:"true"},"Caption")),t.contentEditable="false"})(e)})(e))),me(a,i,t,"src",J),me(a,i,t,"title",J),me(a,i,t,"width",X(0,e)),me(a,i,t,"height",X(0,e)),me(a,i,t,"class",J),me(a,i,t,"style",ge(((e,t)=>J(e,"style",t)),e)),me(a,i,t,"hspace",ge(ee,e)),me(a,i,t,"vspace",ge(te,e)),me(a,i,t,"border",ge(ae,e)),me(a,i,t,"borderStyle",ge(ie,e)),((e,t,a)=>{a.alt===t.alt&&a.isDecorative===t.isDecorative||de(e,a.alt,a.isDecorative)})(a,i,t)},pe=(e,t)=>{const a=(e=>{if(e.margin){const t=String(e.margin).split(" ");switch(t.length){case 1:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[0],e["margin-bottom"]=e["margin-bottom"]||t[0],e["margin-left"]=e["margin-left"]||t[0];break;case 2:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[0],e["margin-left"]=e["margin-left"]||t[1];break;case 3:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[2],e["margin-left"]=e["margin-left"]||t[1];break;case 4:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[2],e["margin-left"]=e["margin-left"]||t[3]}delete e.margin}return e})(e.dom.styles.parse(t)),i=e.dom.styles.parse(e.dom.styles.serialize(a));return e.dom.styles.serialize(i)},he=e=>{const t=e.selection.getNode(),a=e.dom.getParent(t,"figure.image");return a?e.dom.select("img",a)[0]:t&&("IMG"!==t.nodeName||H(t))?null:t},be=(e,t)=>{var a;const i=e.dom,s=(t=>{const a={};var i;return((e,t,a,i)=>{((e,t)=>{const a=b(e);for(let i=0,s=a.length;i{(t(e,s)?a:i)(e,s)}))})(t,((t,a)=>!e.schema.isValidChild(a,"figure")),(i=a,(e,t)=>{i[t]=e}),p),a})(e.schema.getTextBlockElements()),r=i.getParent(t.parentNode,(e=>{return t=s,a=e.nodeName,y(t,a)&&void 0!==t[a]&&null!==t[a];var t,a}),e.getBody());return r&&null!==(a=i.split(r,t))&&void 0!==a?a:t},ve=(e,t)=>{const a=((t,a)=>{const i=document.createElement("img");if(ue((t=>pe(e,t)),{...a,caption:!1},i),de(i,a.alt,a.isDecorative),a.caption){const e=W.create("figure",{class:"image"});return e.appendChild(i),e.appendChild(W.create("figcaption",{contentEditable:"true"},"Caption")),e.contentEditable="false",e}return i})(0,t);e.dom.setAttrib(a,"data-mce-id","__mcenew"),e.focus(),e.selection.setContent(a.outerHTML);const i=e.dom.select('*[data-mce-id="__mcenew"]')[0];if(e.dom.setAttrib(i,"data-mce-id",null),re(i)){const t=be(e,i);e.selection.select(t)}else e.selection.select(i)},ye=(e,t)=>{const a=he(e);if(a){const i={...ce((t=>pe(e,t)),a),...t},s=((e,t)=>{const a=t.src;return{...t,src:G(e,a)?a:""}})(e,i);i.src?((e,t)=>{const a=he(e);if(a)if(ue((t=>pe(e,t)),t,a),((e,t)=>{e.dom.setAttrib(t,"src",t.getAttribute("src"))})(e,a),re(a.parentNode)){e.dom.setStyle(a,"float","");const t=a.parentNode;be(e,t),e.selection.select(a.parentNode)}else e.selection.select(a),((e,t,a)=>{const i=()=>{a.onload=a.onerror=null,e.selection&&(e.selection.select(a),e.nodeChanged())};a.onload=()=>{t.width||t.height||!x(e)||e.dom.setAttribs(a,{width:String(a.clientWidth),height:String(a.clientHeight)}),i()},a.onerror=i})(e,t,a)})(e,s):((e,t)=>{if(t){const a=e.dom.is(t.parentNode,"figure.image")?t.parentNode:t;e.dom.remove(a),e.focus(),e.nodeChanged(),e.dom.isEmpty(e.getBody())&&(e.setContent(""),e.selection.setCursorLocation())}})(e,a)}else t.src&&ve(e,{src:"",alt:"",title:"",width:"",height:"",class:"",style:"",caption:!1,hspace:"",vspace:"",border:"",borderStyle:"",isDecorative:!1,...t})},fe=(we=(e,t)=>n(e)&&n(t)?fe(e,t):t,(...e)=>{if(0===e.length)throw new Error("Can't merge zero objects");const t={};for(let a=0;ar(e.value)?e.value:"",Ce=(e,t)=>{const a=[];return De.each(e,(e=>{const i=(e=>r(e.text)?e.text:r(e.title)?e.title:"")(e);if(void 0!==e.menu){const s=Ce(e.menu,t);a.push({text:i,items:s})}else{const s=t(e);a.push({text:i,value:s})}})),a},Ie=(e=_e)=>t=>t?h.from(t).map((t=>Ce(t,e))):h.none(),Ue=(e,t)=>(e=>{for(let i=0;iy(e,"items"))(a=e[i])?Ue(a.items,t):a.value===t?h.some(a):h.none();if(s.isSome())return s}var a;return h.none()})(e),Se=Ie,xe=(e,t)=>e.bind((e=>Ue(e,t))),Ne=e=>{const t=Se((t=>e.convertURL(t.value||t.url||"","src"))),a=new Promise((a=>{((e,t)=>{const a=R(e);r(a)?fetch(a).then((e=>{e.ok&&e.json().then(t)})):g(a)?a(t):t(a)})(e,(e=>{a(t(e).map((e=>w([[{text:"None",value:""}],e]))))}))})),i=(A=L(e),Ie(_e)(A)),s=N(e),o=T(e),n=(e=>U(e.options.get("images_upload_url")))(e),l=(e=>d(e.options.get("images_upload_handler")))(e),c=(e=>{const t=he(e);return t?ce((t=>pe(e,t)),t):{src:"",alt:"",title:"",width:"",height:"",class:"",style:"",caption:!1,hspace:"",vspace:"",border:"",borderStyle:"",isDecorative:!1}})(e),m=O(e),u=j(e),p=x(e),b=M(e),v=k(e),y=z(e),f=h.some(E(e)).filter((e=>r(e)&&e.length>0));var A;return a.then((e=>({image:c,imageList:e,classList:i,hasAdvTab:s,hasUploadTab:o,hasUploadUrl:n,hasUploadHandler:l,hasDescription:m,hasImageTitle:u,hasDimensions:p,hasImageCaption:b,prependURL:f,hasAccessibilityOptions:v,automaticUploads:y})))},Te=e=>{const t=e.imageList.map((e=>({name:"images",type:"listbox",label:"Image list",items:e}))),a={name:"alt",type:"input",label:"Alternative description",enabled:!(e.hasAccessibilityOptions&&e.image.isDecorative)},i=e.classList.map((e=>({name:"classes",type:"listbox",label:"Class",items:e})));return w([[{name:"src",type:"urlinput",filetype:"image",label:"Source",picker_text:"Browse files"}],t.toArray(),e.hasAccessibilityOptions&&e.hasDescription?[{type:"label",label:"Accessibility",items:[{name:"isDecorative",type:"checkbox",label:"Image is decorative"}]}]:[],e.hasDescription?[a]:[],e.hasImageTitle?[{name:"title",type:"input",label:"Image title"}]:[],e.hasDimensions?[{name:"dimensions",type:"sizeinput"}]:[],[{...(s=e.classList.isSome()&&e.hasImageCaption,s?{type:"grid",columns:2}:{type:"panel"}),items:w([i.toArray(),e.hasImageCaption?[{type:"label",label:"Caption",items:[{type:"checkbox",name:"caption",label:"Show caption"}]}]:[]])}]]);var s},Ee=e=>({title:"General",name:"general",items:Te(e)}),Le=Te,Oe=e=>({src:{value:e.src,meta:{}},images:e.src,alt:e.alt,title:e.title,dimensions:{width:e.width,height:e.height},classes:e.class,caption:e.caption,style:e.style,vspace:e.vspace,border:e.border,hspace:e.hspace,borderstyle:e.borderStyle,fileinput:[],isDecorative:e.isDecorative}),je=(e,t)=>({src:e.src.value,alt:null!==e.alt&&0!==e.alt.length||!t?e.alt:null,title:e.title,width:e.dimensions.width,height:e.dimensions.height,class:e.classes,style:e.style,caption:e.caption,hspace:e.hspace,vspace:e.vspace,border:e.border,borderStyle:e.borderstyle,isDecorative:e.isDecorative}),Me=(e,t,a,i)=>{((e,t)=>{const a=t.getData();((e,t)=>/^(?:[a-zA-Z]+:)?\/\//.test(t)?h.none():e.prependURL.bind((e=>t.substring(0,e.length)!==e?h.some(e+t):h.none())))(e,a.src.value).each((e=>{t.setData({src:{value:e,meta:a.src.meta}})}))})(t,i),((e,t)=>{const a=t.getData(),i=a.src.meta;if(void 0!==i){const s=fe({},a);((e,t,a)=>{e.hasDescription&&r(a.alt)&&(t.alt=a.alt),e.hasAccessibilityOptions&&(t.isDecorative=a.isDecorative||t.isDecorative||!1),e.hasImageTitle&&r(a.title)&&(t.title=a.title),e.hasDimensions&&(r(a.width)&&(t.dimensions.width=a.width),r(a.height)&&(t.dimensions.height=a.height)),r(a.class)&&xe(e.classList,a.class).each((e=>{t.classes=e.value})),e.hasImageCaption&&m(a.caption)&&(t.caption=a.caption),e.hasAdvTab&&(r(a.style)&&(t.style=a.style),r(a.vspace)&&(t.vspace=a.vspace),r(a.border)&&(t.border=a.border),r(a.hspace)&&(t.hspace=a.hspace),r(a.borderstyle)&&(t.borderstyle=a.borderstyle))})(e,s,i),t.setData(s)}})(t,i),((e,t,a,i)=>{const s=i.getData(),r=s.src.value,o=s.src.meta||{};o.width||o.height||!t.hasDimensions||(U(r)?e.imageSize(r).then((e=>{a.open&&i.setData({dimensions:e})})).catch((e=>console.error(e))):i.setData({dimensions:{width:"",height:""}}))})(e,t,a,i),((e,t,a)=>{const i=a.getData(),s=xe(e.imageList,i.src.value);t.prevImage=s,a.setData({images:s.map((e=>e.value)).getOr("")})})(t,a,i)},Re=(e,t,a,i)=>{const s=i.getData();var r;i.block("Uploading image"),(r=s.fileinput,(e=>0{i.unblock()}),(s=>{const r=URL.createObjectURL(s),o=()=>{i.unblock(),URL.revokeObjectURL(r)},n=s=>{i.setData({src:{value:s,meta:{}}}),i.showTab("general"),Me(e,t,a,i),i.focus("src")};var l;(l=s,new Promise(((e,t)=>{const a=new FileReader;a.onload=()=>{e(a.result)},a.onerror=()=>{var e;t(null===(e=a.error)||void 0===e?void 0:e.message)},a.readAsDataURL(l)}))).then((a=>{const l=e.createBlobCache(s,r,a);t.automaticUploads?e.uploadImage(l).then((e=>{n(e.url),o()})).catch((t=>{o(),e.alertErr(t,(()=>{i.focus("fileinput")}))})):(e.addToBlobCache(l),n(l.blobUri()),i.unblock())}))}))},ke=(e,t,a)=>(i,s)=>{"src"===s.name?Me(e,t,a,i):"images"===s.name?((e,t,a,i)=>{const s=i.getData(),r=xe(t.imageList,s.images);r.each((e=>{const t=""===s.alt||a.prevImage.map((e=>e.text===s.alt)).getOr(!1);t?""===e.value?i.setData({src:e,alt:a.prevAlt}):i.setData({src:e,alt:e.text}):i.setData({src:e})})),a.prevImage=r,Me(e,t,a,i)})(e,t,a,i):"alt"===s.name?a.prevAlt=i.getData().alt:"fileinput"===s.name?Re(e,t,a,i):"isDecorative"===s.name&&i.setEnabled("alt",!i.getData().isDecorative)},ze=e=>()=>{e.open=!1},Be=e=>e.hasAdvTab||e.hasUploadUrl||e.hasUploadHandler?{type:"tabpanel",tabs:w([[Ee(e)],e.hasAdvTab?[{title:"Advanced",name:"advanced",items:[{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"}]}]}]}]:[],e.hasUploadTab&&(e.hasUploadUrl||e.hasUploadHandler)?[{title:"Upload",name:"upload",items:[{type:"dropzone",name:"fileinput"}]}]:[]])}:{type:"panel",items:Le(e)},Pe=(e,t,a)=>i=>{const s=fe(Oe(t.image),i.getData()),r={...s,style:le(a.normalizeCss,je(s,!1))};e.execCommand("mceUpdateImage",!1,je(r,t.hasAccessibilityOptions)),e.editorUpload.uploadImagesAuto(),i.close()},Fe=e=>t=>G(e,t)?(e=>new Promise((t=>{const a=document.createElement("img"),i=e=>{a.parentNode&&a.parentNode.removeChild(a),t(e)};a.addEventListener("load",(()=>{const e={width:B(a.width,a.clientWidth),height:B(a.height,a.clientHeight)};i(Promise.resolve(e))})),a.addEventListener("error",(()=>{i(Promise.reject(`Failed to get image dimensions for: ${e}`))}));const s=a.style;s.visibility="hidden",s.position="fixed",s.bottom=s.left="0px",s.width=s.height="auto",document.body.appendChild(a),a.src=e})))(e.documentBaseURI.toAbsolute(t)).then((e=>({width:String(e.width),height:String(e.height)}))):Promise.resolve({width:"",height:""}),He=e=>(t,a,i)=>{var s;return e.editorUpload.blobCache.create({blob:t,blobUri:a,name:null===(s=t.name)||void 0===s?void 0:s.replace(/\.[^\.]+$/,""),filename:t.name,base64:i.split(",")[1]})},Ge=e=>t=>{e.editorUpload.blobCache.add(t)},We=e=>(t,a)=>{e.windowManager.alert(t,a)},$e=e=>t=>pe(e,t),Ve=e=>t=>e.dom.parseStyle(t),Ke=e=>(t,a)=>e.dom.serializeStyle(t,a),Ze=e=>t=>Ae(e).upload([t],!1).then((e=>{var t;return 0===e.length?Promise.reject("Failed to upload image"):!1===e[0].status?Promise.reject(null===(t=e[0].error)||void 0===t?void 0:t.message):e[0]})),qe=e=>{const t={imageSize:Fe(e),addToBlobCache:Ge(e),createBlobCache:He(e),alertErr:We(e),normalizeCss:$e(e),parseStyle:Ve(e),serializeStyle:Ke(e),uploadImage:Ze(e)};return{open:()=>{Ne(e).then((a=>{const i=(e=>({prevImage:xe(e.imageList,e.image.src),prevAlt:e.image.alt,open:!0}))(a);return{title:"Insert/Edit Image",size:"normal",body:Be(a),buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:Oe(a.image),onSubmit:Pe(e,a,t),onChange:ke(t,a,i),onClose:ze(i)}})).then(e.windowManager.open)}}},Je=e=>{const t=e.attr("class");return d(t)&&/\bimage\b/.test(t)},Qe=e=>t=>{let a=t.length;const i=t=>{t.attr("contenteditable",e?"true":null)};for(;a--;){const s=t[a];Je(s)&&(s.attr("contenteditable",e?"false":null),De.each(s.getAll("figcaption"),i))}},Xe=e=>t=>{const a=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",a),a(),()=>{e.off("NodeChange",a)}};e.add("image",(e=>{(e=>{const t=e.options.register;t("image_dimensions",{processor:"boolean",default:!0}),t("image_advtab",{processor:"boolean",default:!1}),t("image_uploadtab",{processor:"boolean",default:!0}),t("image_prepend_url",{processor:"string",default:""}),t("image_class_list",{processor:"object[]"}),t("image_description",{processor:"boolean",default:!0}),t("image_title",{processor:"boolean",default:!1}),t("image_caption",{processor:"boolean",default:!1}),t("image_list",{processor:e=>{const t=!1===e||r(e)||((e,t)=>{if(l(e)){for(let a=0,i=e.length;a{e.on("PreInit",(()=>{e.parser.addNodeFilter("figure",Qe(!0)),e.serializer.addNodeFilter("figure",Qe(!1))}))})(e),(e=>{e.ui.registry.addToggleButton("image",{icon:"image",tooltip:"Insert/edit image",onAction:qe(e).open,onSetup:t=>{t.setActive(d(he(e)));const a=e.selection.selectorChangedWithUnbind("img:not([data-mce-object]):not([data-mce-placeholder]),figure.image",t.setActive).unbind,i=Xe(e)(t);return()=>{a(),i()}}}),e.ui.registry.addMenuItem("image",{icon:"image",text:"Image...",onAction:qe(e).open,onSetup:Xe(e)}),e.ui.registry.addContextMenu("image",{update:t=>e.selection.isEditable()&&(re(t)||"IMG"===t.nodeName&&!H(t))?["image"]:[]})})(e),(e=>{e.addCommand("mceImage",qe(e).open),e.addCommand("mceUpdateImage",((t,a)=>{e.undoManager.transact((()=>ye(e,a)))}))})(e)}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/importcss/plugin.min.js b/apps/web-antd/public/tinymce/plugins/importcss/plugin.min.js new file mode 100644 index 0000000..b1b1a5e --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/importcss/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(s=r=e,(o=String).prototype.isPrototypeOf(s)||(null===(n=r.constructor)||void 0===n?void 0:n.name)===o.name)?"string":t;var s,r,o,n})(t)===e,s=t("string"),r=t("object"),o=t("array"),n=e=>"function"==typeof e;var c=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),i=tinymce.util.Tools.resolve("tinymce.EditorManager"),l=tinymce.util.Tools.resolve("tinymce.Env"),a=tinymce.util.Tools.resolve("tinymce.util.Tools");const p=e=>t=>t.options.get(e),u=p("importcss_merge_classes"),m=p("importcss_exclusive"),f=p("importcss_selector_converter"),y=p("importcss_selector_filter"),d=p("importcss_groups"),h=p("importcss_append"),g=p("importcss_file_filter"),_=p("skin"),v=p("skin_url"),b=Array.prototype.push,x=/^\.(?:ephox|tiny-pageembed|mce)(?:[.-]+\w+)+$/,T=e=>s(e)?t=>-1!==t.indexOf(e):e instanceof RegExp?t=>e.test(t):e,S=(e,t)=>{let s={};const r=/^(?:([a-z0-9\-_]+))?(\.[a-z0-9_\-\.]+)$/i.exec(t);if(!r)return;const o=r[1],n=r[2].substr(1).split(".").join(" "),c=a.makeMap("a,img");return r[1]?(s={title:t},e.schema.getTextBlockElements()[o]?s.block=o:e.schema.getBlockElements()[o]||c[o.toLowerCase()]?s.selector=o:s.inline=o):r[2]&&(s={inline:"span",title:t.substr(1),classes:n}),u(e)?s.classes=n:s.attributes={class:n},s},k=(e,t)=>null===t||m(e),M=e=>{e.on("init",(()=>{const t=(()=>{const e=[],t=[],s={};return{addItemToGroup:(e,r)=>{s[e]?s[e].push(r):(t.push(e),s[e]=[r])},addItem:t=>{e.push(t)},toFormats:()=>{return(r=t,n=e=>{const t=s[e];return 0===t.length?[]:[{title:e,items:t}]},(e=>{const t=[];for(let s=0,r=e.length;s{const s=e.length,r=new Array(s);for(let o=0;oa.map(e,(e=>a.extend({},e,{original:e,selectors:{},filter:T(e.filter)}))))(d(e)),u=(t,s)=>{if(((e,t,s,r)=>!(k(e,s)?t in r:t in s.selectors))(e,t,s,r)){((e,t,s,r)=>{k(e,s)?r[t]=!0:s.selectors[t]=!0})(e,t,s,r);const o=((e,t,s,r)=>{let o;const n=f(e);return o=r&&r.selector_converter?r.selector_converter:n||(()=>S(e,s)),o.call(t,s,r)})(e,e.plugins.importcss,t,s);if(o){const t=o.name||c.DOM.uniqueId();return e.formatter.register(t,o),{title:o.title,format:t}}}return null};a.each(((e,t,r)=>{const o=[],n={},c=(t,n)=>{let p,u=t.href;if(u=(e=>{const t=l.cacheSuffix;return s(e)&&(e=e.replace("?"+t,"").replace("&"+t,"")),e})(u),u&&(!r||r(u,n))&&!((e,t)=>{const s=_(e);if(s){const r=v(e),o=r?e.documentBaseURI.toAbsolute(r):i.baseURL+"/skins/ui/"+s,n=i.baseURL+"/skins/content/",c=e.editorManager.suffix;return t===o+"/content"+(e.inline?".inline":"")+`${c}.css`||-1!==t.indexOf(n)}return!1})(e,u)){a.each(t.imports,(e=>{c(e,!0)}));try{p=t.cssRules||t.rules}catch(e){}a.each(p,(e=>{e.styleSheet&&e.styleSheet?c(e.styleSheet,!0):e.selectorText&&a.each(e.selectorText.split(","),(e=>{o.push(a.trim(e))}))}))}};a.each(e.contentCSS,(e=>{n[e]=!0})),r||(r=(e,t)=>t||n[e]);try{a.each(t.styleSheets,(e=>{c(e)}))}catch(e){}return o})(e,e.getDoc(),T(g(e))),(e=>{if(!x.test(e)&&(!n||n(e))){const s=((e,t)=>a.grep(e,(e=>!e.filter||e.filter(t))))(p,e);if(s.length>0)a.each(s,(s=>{const r=u(e,s);r&&t.addItemToGroup(s.title,r)}));else{const s=u(e,null);s&&t.addItem(s)}}}));const m=t.toFormats();e.dispatch("addStyleModifications",{items:m,replace:!h(e)})}))};e.add("importcss",(e=>((e=>{const t=e.options.register,o=e=>s(e)||n(e)||r(e);t("importcss_merge_classes",{processor:"boolean",default:!0}),t("importcss_exclusive",{processor:"boolean",default:!0}),t("importcss_selector_converter",{processor:"function"}),t("importcss_selector_filter",{processor:o}),t("importcss_file_filter",{processor:o}),t("importcss_groups",{processor:"object[]"}),t("importcss_append",{processor:"boolean",default:!1})})(e),M(e),(e=>({convertSelectorToFormat:t=>S(e,t)}))(e))))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/insertdatetime/plugin.min.js b/apps/web-antd/public/tinymce/plugins/insertdatetime/plugin.min.js new file mode 100644 index 0000000..8a05382 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/insertdatetime/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),a=t("insertdatetime_dateformat"),n=t("insertdatetime_timeformat"),r=t("insertdatetime_formats"),s=t("insertdatetime_element"),i="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),o="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),l="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),m="January February March April May June July August September October November December".split(" "),c=(e,t)=>{if((e=""+e).length(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=t.replace("%D","%m/%d/%Y")).replace("%r","%I:%M:%S %p")).replace("%Y",""+a.getFullYear())).replace("%y",""+a.getYear())).replace("%m",c(a.getMonth()+1,2))).replace("%d",c(a.getDate(),2))).replace("%H",""+c(a.getHours(),2))).replace("%M",""+c(a.getMinutes(),2))).replace("%S",""+c(a.getSeconds(),2))).replace("%I",""+((a.getHours()+11)%12+1))).replace("%p",a.getHours()<12?"AM":"PM")).replace("%B",""+e.translate(m[a.getMonth()]))).replace("%b",""+e.translate(l[a.getMonth()]))).replace("%A",""+e.translate(o[a.getDay()]))).replace("%a",""+e.translate(i[a.getDay()]))).replace("%%","%"),u=(e,t)=>{if(s(e)&&e.selection.isEditable()){const a=d(e,t);let n;n=/%[HMSIp]/.test(t)?d(e,"%Y-%m-%dT%H:%M"):d(e,"%Y-%m-%d");const r=e.dom.getParent(e.selection.getStart(),"time");r?((e,t,a,n)=>{const r=e.dom.create("time",{datetime:a},n);e.dom.replace(r,t),e.selection.select(r,!0),e.selection.collapse(!1)})(e,r,n,a):e.insertContent('")}else e.insertContent(d(e,t))};var p=tinymce.util.Tools.resolve("tinymce.util.Tools");const g=e=>t=>{const a=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",a),a(),()=>{e.off("NodeChange",a)}};e.add("insertdatetime",(e=>{(e=>{const t=e.options.register;t("insertdatetime_dateformat",{processor:"string",default:e.translate("%Y-%m-%d")}),t("insertdatetime_timeformat",{processor:"string",default:e.translate("%H:%M:%S")}),t("insertdatetime_formats",{processor:"string[]",default:["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"]}),t("insertdatetime_element",{processor:"boolean",default:!1})})(e),(e=>{e.addCommand("mceInsertDate",((t,n)=>{u(e,null!=n?n:a(e))})),e.addCommand("mceInsertTime",((t,a)=>{u(e,null!=a?a:n(e))}))})(e),(e=>{const t=r(e),a=(e=>{let t=e;return{get:()=>t,set:e=>{t=e}}})((e=>{const t=r(e);return t.length>0?t[0]:n(e)})(e)),s=t=>e.execCommand("mceInsertDate",!1,t);e.ui.registry.addSplitButton("insertdatetime",{icon:"insert-time",tooltip:"Insert date/time",select:e=>e===a.get(),fetch:a=>{a(p.map(t,(t=>({type:"choiceitem",text:d(e,t),value:t}))))},onAction:e=>{s(a.get())},onItemAction:(e,t)=>{a.set(t),s(t)},onSetup:g(e)});const i=e=>()=>{a.set(e),s(e)};e.ui.registry.addNestedMenuItem("insertdatetime",{icon:"insert-time",text:"Date/time",getSubmenuItems:()=>p.map(t,(t=>({type:"menuitem",text:d(e,t),onAction:i(t)}))),onSetup:g(e)})})(e)}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/link/plugin.min.js b/apps/web-antd/public/tinymce/plugins/link/plugin.min.js new file mode 100644 index 0000000..d8c40c7 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/link/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=o=e,(r=String).prototype.isPrototypeOf(n)||(null===(l=o.constructor)||void 0===l?void 0:l.name)===r.name)?"string":t;var n,o,r,l})(t)===e,n=e=>t=>typeof t===e,o=t("string"),r=t("object"),l=t("array"),s=e=>null===e;const i=n("boolean"),a=e=>!(e=>null==e)(e),c=n("function"),u=(e,t)=>{if(l(e)){for(let n=0,o=e.length;n{},d=(e,t)=>e===t;class m{constructor(e,t){this.tag=e,this.value=t}static some(e){return new m(!0,e)}static none(){return m.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?m.some(e(this.value)):m.none()}bind(e){return this.tag?e(this.value):m.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:m.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return a(e)?m.some(e):m.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}m.singletonNone=new m(!1);const h=Array.prototype.indexOf,p=Array.prototype.push,f=e=>{const t=[];for(let n=0,o=e.length;n{for(let n=0;ne.exists((e=>n(e,t))),b=e=>{const t=[],n=e=>{t.push(e)};for(let t=0;te?m.some(t):m.none(),y=e=>t=>t.options.get(e),_=y("link_assume_external_targets"),w=y("link_context_toolbar"),C=y("link_list"),O=y("link_default_target"),S=y("link_default_protocol"),A=y("link_target_list"),N=y("link_rel_list"),E=y("link_class_list"),R=y("link_title"),T=y("allow_unsafe_link_target"),L=y("link_quicklink"),P=y("link_attributes_postprocess"),M=Object.keys,D=Object.hasOwnProperty,B=(e,t)=>D.call(e,t);var I=tinymce.util.Tools.resolve("tinymce.util.URI"),K=tinymce.util.Tools.resolve("tinymce.dom.TreeWalker"),j=tinymce.util.Tools.resolve("tinymce.util.Tools");const U=e=>a(e)&&"a"===e.nodeName.toLowerCase(),q=e=>U(e)&&!!$(e),F=(e,t)=>{if(e.collapsed)return[];{const n=e.cloneContents(),o=n.firstChild,r=new K(o,n),l=[];let s=o;do{t(s)&&l.push(s)}while(s=r.next());return l}},V=e=>/^\w+:/i.test(e),$=e=>{var t,n;return null!==(n=null!==(t=e.getAttribute("data-mce-href"))&&void 0!==t?t:e.getAttribute("href"))&&void 0!==n?n:""},z=(e,t)=>{const n=["noopener"],o=e?e.split(/\s+/):[],r=e=>e.filter((e=>-1===j.inArray(n,e))),l=t?(e=>(e=r(e)).length>0?e.concat(n):n)(o):r(o);return l.length>0?(e=>j.trim(e.sort().join(" ")))(l):""},G=(e,t)=>(t=t||W(e.selection.getRng())[0]||e.selection.getNode(),Z(t)?m.from(e.dom.select("a[href]",t)[0]):m.from(e.dom.getParent(t,"a[href]"))),H=(e,t)=>G(e,t).isSome(),J=(e,t)=>t.fold((()=>e.getContent({format:"text"})),(e=>e.innerText||e.textContent||"")).replace(/\uFEFF/g,""),W=e=>F(e,q),Q=e=>j.grep(e,q),X=e=>Q(e).length>0,Y=e=>{const t=e.schema.getTextInlineElements();if(G(e).exists((e=>e.hasAttribute("data-mce-block"))))return!1;const n=e.selection.getRng();return!!n.collapsed||0===F(n,(e=>1===e.nodeType&&!U(e)&&!B(t,e.nodeName.toLowerCase()))).length},Z=e=>a(e)&&"FIGURE"===e.nodeName&&/\bimage\b/i.test(e.className),ee=(e,t,n)=>{const o=e.selection.getNode(),r=G(e,o),l=((e,t)=>{const n={...t};if(0===N(e).length&&!T(e)){const e=z(n.rel,"_blank"===n.target);n.rel=e||null}return m.from(n.target).isNone()&&!1===A(e)&&(n.target=O(e)),n.href=((e,t)=>"http"!==t&&"https"!==t||V(e)?e:t+"://"+e)(n.href,_(e)),n})(e,(e=>{return t=["title","rel","class","target"],n=(t,n)=>(e[n].each((e=>{t[n]=e.length>0?e:null})),t),o={href:e.href},((e,t)=>{for(let n=0,o=e.length;n{o=n(o,e)})),o;var t,n,o})(n)),s=P(e);a(s)&&s(l),e.undoManager.transact((()=>{n.href===t.href&&t.attach(),r.fold((()=>{((e,t,n,o)=>{const r=e.dom;Z(t)?le(r,t,o):n.fold((()=>{e.execCommand("mceInsertLink",!1,o);const t=e.selection.getEnd(),n=r.createRng();n.setStartAfter(t),n.setEndAfter(t),e.selection.setRng(n)}),(t=>{e.insertContent(r.createHTML("a",o,r.encode(t)))}))})(e,o,n.text,l)}),(t=>{e.focus(),((e,t,n,o)=>{n.each((e=>{B(t,"innerText")?t.innerText=e:t.textContent=e})),e.dom.setAttribs(t,o);const r=e.dom.createRng();r.setStartAfter(t),r.setEndAfter(t),e.selection.setRng(r)})(e,t,n.text,l)}))}))},te=e=>{const{class:t,href:n,rel:o,target:r,text:l,title:i}=e;return(e=>{const t={};var n;return((e,t,n,o)=>{((e,t)=>{const n=M(e);for(let o=0,r=n.length;o{(t(e,r)?n:o)(e,r)}))})(e,((e,t)=>!1===s(e)),(n=t,(e,t)=>{n[t]=e}),g),t})({class:t.getOrNull(),href:n,rel:o.getOrNull(),target:r.getOrNull(),text:l.getOrNull(),title:i.getOrNull()})},ne=(e,t,n)=>{const o=((e,t)=>{const n=e.options.get,o={allow_html_data_urls:n("allow_html_data_urls"),allow_script_urls:n("allow_script_urls"),allow_svg_data_urls:n("allow_svg_data_urls")},r=t.href;return{...t,href:I.isDomSafe(r,"a",o)?r:""}})(e,n);e.hasPlugin("rtc",!0)?e.execCommand("createlink",!1,te(o)):ee(e,t,o)},oe=e=>{e.hasPlugin("rtc",!0)?e.execCommand("unlink"):(e=>{e.undoManager.transact((()=>{const t=e.selection.getNode();Z(t)?re(e,t):(e=>{const t=e.dom,n=e.selection,o=n.getBookmark(),r=n.getRng().cloneRange(),l=t.getParent(r.startContainer,"a[href]",e.getBody()),s=t.getParent(r.endContainer,"a[href]",e.getBody());l&&r.setStartBefore(l),s&&r.setEndAfter(s),n.setRng(r),e.execCommand("unlink"),n.moveToBookmark(o)})(e),e.focus()}))})(e)},re=(e,t)=>{var n;const o=e.dom.select("img",t)[0];if(o){const r=e.dom.getParents(o,"a[href]",t)[0];r&&(null===(n=r.parentNode)||void 0===n||n.insertBefore(o,r),e.dom.remove(r))}},le=(e,t,n)=>{var o;const r=e.select("img",t)[0];if(r){const t=e.create("a",n);null===(o=r.parentNode)||void 0===o||o.insertBefore(t,r),t.appendChild(r)}},se=e=>o(e.value)?e.value:"",ie=(e,t)=>{const n=[];return j.each(e,(e=>{const r=(e=>o(e.text)?e.text:o(e.title)?e.title:"")(e);if(void 0!==e.menu){const o=ie(e.menu,t);n.push({text:r,items:o})}else{const o=t(e);n.push({text:r,value:o})}})),n},ae=(e=se)=>t=>m.from(t).map((t=>ie(t,e))),ce=e=>ae(se)(e),ue=ae,ge=(e,t)=>n=>({name:e,type:"listbox",label:t,items:n}),de=se,me=(e,t)=>k(t,(t=>(e=>{return B(t=e,n="items")&&void 0!==t[n]&&null!==t[n];var t,n})(t)?me(e,t.items):x(t.value===e,t))),he=(e,t)=>{const n={text:e.text,title:e.title},o=(e,o)=>{const r=(l=t,s=o,"link"===s?l.link:"anchor"===s?l.anchor:m.none()).getOr([]);var l,s;return((e,t,n,o)=>{const r=o[t],l=e.length>0;return void 0!==r?me(r,n).map((t=>({url:{value:t.value,meta:{text:l?e:t.text,attach:g}},text:l?e:t.text}))):m.none()})(n.text,o,r,e)};return{onChange:(e,t)=>{const r=t.name;return"url"===r?(e=>{const t=(o=e.url,x(n.text.length<=0,m.from(null===(r=o.meta)||void 0===r?void 0:r.text).getOr(o.value)));var o,r;const l=(e=>{var t;return x(n.title.length<=0,m.from(null===(t=e.meta)||void 0===t?void 0:t.title).getOr(""))})(e.url);return t.isSome()||l.isSome()?m.some({...t.map((e=>({text:e}))).getOr({}),...l.map((e=>({title:e}))).getOr({})}):m.none()})(e()):((e,t)=>h.call(e,t))(["anchor","link"],r)>-1?o(e(),r):"text"===r||"title"===r?(n[r]=e()[r],m.none()):m.none()}}};var pe=tinymce.util.Tools.resolve("tinymce.util.Delay");const fe=e=>{const t=e.href;return t.indexOf("@")>0&&-1===t.indexOf("/")&&-1===t.indexOf("mailto:")?m.some({message:"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",preprocess:e=>({...e,href:"mailto:"+t})}):m.none()},ke=(e,t)=>n=>{const o=n.href;return 1===e&&!V(o)||0===e&&/^\s*www(\.|\d\.)/i.test(o)?m.some({message:`The URL you entered seems to be an external link. Do you want to add the required ${t}:// prefix?`,preprocess:e=>({...e,href:t+"://"+o})}):m.none()},ve=e=>{const t=e.dom.select("a:not([href])"),n=f(((e,t)=>{const n=e.length,o=new Array(n);for(let r=0;r{const t=e.name||e.id;return t?[{text:t,value:"#"+t}]:[]})));return n.length>0?m.some([{text:"None",value:""}].concat(n)):m.none()},be=e=>{const t=E(e);return t.length>0?ce(t):m.none()},xe=e=>{try{return m.some(JSON.parse(e))}catch(e){return m.none()}},ye=(e,t)=>{const n=N(e);if(n.length>0){const o=v(t,"_blank"),r=e=>z(de(e),o);return(!1===T(e)?ue(r):ce)(n)}return m.none()},_e=[{text:"Current window",value:""},{text:"New window",value:"_blank"}],we=e=>{const t=A(e);return l(t)?ce(t).orThunk((()=>m.some(_e))):!1===t?m.none():m.some(_e)},Ce=(e,t,n)=>{const o=e.getAttrib(t,n);return null!==o&&o.length>0?m.some(o):m.none()},Oe=(e,t)=>(e=>{const t=t=>e.convertURL(t.value||t.url||"","href"),n=C(e);return new Promise((e=>{o(n)?fetch(n).then((e=>e.ok?e.text().then(xe):Promise.reject())).then(e,(()=>e(m.none()))):c(n)?n((t=>e(m.some(t)))):e(m.from(n))})).then((e=>e.bind(ue(t)).map((e=>e.length>0?[{text:"None",value:""}].concat(e):e))))})(e).then((n=>{const o=((e,t)=>{const n=e.dom,o=Y(e)?m.some(J(e.selection,t)):m.none(),r=t.bind((e=>m.from(n.getAttrib(e,"href")))),l=t.bind((e=>m.from(n.getAttrib(e,"target")))),s=t.bind((e=>Ce(n,e,"rel"))),i=t.bind((e=>Ce(n,e,"class")));return{url:r,text:o,title:t.bind((e=>Ce(n,e,"title"))),target:l,rel:s,linkClass:i}})(e,t);return{anchor:o,catalogs:{targets:we(e),rels:ye(e,o.target),classes:be(e),anchor:ve(e),link:n},optNode:t,flags:{titleEnabled:R(e)}}})),Se=e=>{const t=(e=>{const t=G(e);return Oe(e,t)})(e);t.then((t=>{const n=((e,t)=>n=>{const o=n.getData();if(!o.url.value)return oe(e),void n.close();const r=e=>m.from(o[e]).filter((n=>!v(t.anchor[e],n))),l={href:o.url.value,text:r("text"),target:r("target"),rel:r("rel"),class:r("linkClass"),title:r("title")},s={href:o.url.value,attach:void 0!==o.url.meta&&o.url.meta.attach?o.url.meta.attach:g};((e,t)=>k([fe,ke(_(e),S(e))],(e=>e(t))).fold((()=>Promise.resolve(t)),(n=>new Promise((o=>{((e,t,n)=>{const o=e.selection.getRng();pe.setEditorTimeout(e,(()=>{e.windowManager.confirm(t,(t=>{e.selection.setRng(o),n(t)}))}))})(e,n.message,(e=>{o(e?n.preprocess(t):t)}))})))))(e,l).then((t=>{ne(e,s,t)})),n.close()})(e,t);return((e,t,n)=>{const o=e.anchor.text.map((()=>({name:"text",type:"input",label:"Text to display"}))).toArray(),r=e.flags.titleEnabled?[{name:"title",type:"input",label:"Title"}]:[],l=((e,t)=>{const n=e.anchor,o=n.url.getOr("");return{url:{value:o,meta:{original:{value:o}}},text:n.text.getOr(""),title:n.title.getOr(""),anchor:o,link:o,rel:n.rel.getOr(""),target:n.target.or(t).getOr(""),linkClass:n.linkClass.getOr("")}})(e,m.from(O(n))),s=e.catalogs,i=he(l,s);return{title:"Insert/Edit Link",size:"normal",body:{type:"panel",items:f([[{name:"url",type:"urlinput",filetype:"file",label:"URL",picker_text:"Browse links"}],o,r,b([s.anchor.map(ge("anchor","Anchors")),s.rels.map(ge("rel","Rel")),s.targets.map(ge("target","Open link in...")),s.link.map(ge("link","Link list")),s.classes.map(ge("linkClass","Class"))])])},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:l,onChange:(e,{name:t})=>{i.onChange(e.getData,{name:t}).each((t=>{e.setData(t)}))},onSubmit:t}})(t,n,e)})).then((t=>{e.windowManager.open(t)}))};var Ae=tinymce.util.Tools.resolve("tinymce.util.VK");const Ne=(e,t)=>{if(t){const o=$(t);if(/^#/.test(o)){const t=e.dom.select(`${o},[name="${n=o,((e,t)=>((e,t)=>""===t||e.length>=t.length&&e.substr(0,0+t.length)===t)(e,t))(n,"#")?(e=>e.substring(1))(n):n}"]`);t.length&&e.selection.scrollIntoView(t[0],!0)}else(e=>{const t=document.createElement("a");t.target="_blank",t.href=e,t.rel="noreferrer noopener";const n=new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window});document.dispatchEvent(n),((e,t)=>{document.body.appendChild(e),e.dispatchEvent(t),document.body.removeChild(e)})(t,n)})(t.href)}var n},Ee=(e,t)=>{const n=Q(e.dom.getParents(t));return x(1===n.length,n[0])},Re=e=>e.selection.isCollapsed()||(e=>{const t=e.selection.getRng(),n=t.startContainer;return q(n)&&t.startContainer===t.endContainer&&1===e.dom.select("img",n).length})(e)?Ee(e,e.selection.getStart()):(e=>{const t=W(e.selection.getRng());return x(t.length>0,t[0]).or(Ee(e,e.selection.getNode()))})(e),Te=e=>()=>{e.execCommand("mceLink",!1,{dialog:!0})},Le=(e,t)=>(e.on("NodeChange",t),()=>e.off("NodeChange",t)),Pe=e=>t=>{const n=()=>{t.setActive(!e.mode.isReadOnly()&&H(e,e.selection.getNode())),t.setEnabled(e.selection.isEditable())};return n(),Le(e,n)},Me=e=>t=>{const n=()=>{t.setEnabled(e.selection.isEditable())};return n(),Le(e,n)},De=e=>t=>{const n=e.dom.getParents(e.selection.getStart()),o=n=>{t.setEnabled((t=>{return X(t)||(n=e.selection.getRng(),W(n).length>0);var n})(n)&&e.selection.isEditable())};return o(n),Le(e,(e=>o(e.parents)))},Be=e=>{const t=(e=>{const t=(()=>{const e=(e=>{const t=(e=>{let t=e;return{get:()=>t,set:e=>{t=e}}})(m.none()),n=()=>t.get().each(e);return{clear:()=>{n(),t.set(m.none())},isSet:()=>t.get().isSome(),get:()=>t.get(),set:e=>{n(),t.set(m.some(e))}}})(g);return{...e,on:t=>e.get().each(t)}})(),n=()=>t.get().or(Re(e));return e.on("contextmenu",(n=>{Ee(e,n.target).each(t.set)})),e.on("SelectionChange",(()=>{t.isSet()||Re(e).each(t.set)})),e.on("click",(n=>{t.clear();const o=Q(e.dom.getParents(n.target));1===o.length&&Ae.metaKeyPressed(n)&&(n.preventDefault(),Ne(e,o[0]))})),e.on("keydown",(o=>{t.clear(),!o.isDefaultPrevented()&&13===o.keyCode&&(e=>!0===e.altKey&&!1===e.shiftKey&&!1===e.ctrlKey&&!1===e.metaKey)(o)&&n().each((t=>{o.preventDefault(),Ne(e,t)}))})),{gotoSelectedLink:()=>n().each((t=>Ne(e,t)))}})(e);((e,t)=>{e.ui.registry.addToggleButton("link",{icon:"link",tooltip:"Insert/edit link",shortcut:"Meta+K",onAction:Te(e),onSetup:Pe(e)}),e.ui.registry.addButton("openlink",{icon:"new-tab",tooltip:"Open link",onAction:t.gotoSelectedLink,onSetup:De(e)}),e.ui.registry.addButton("unlink",{icon:"unlink",tooltip:"Remove link",onAction:()=>oe(e),onSetup:De(e)})})(e,t),((e,t)=>{e.ui.registry.addMenuItem("openlink",{text:"Open link",icon:"new-tab",onAction:t.gotoSelectedLink,onSetup:De(e)}),e.ui.registry.addMenuItem("link",{icon:"link",text:"Link...",shortcut:"Meta+K",onAction:Te(e),onSetup:Me(e)}),e.ui.registry.addMenuItem("unlink",{icon:"unlink",text:"Remove link",onAction:()=>oe(e),onSetup:De(e)})})(e,t),(e=>{e.ui.registry.addContextMenu("link",{update:t=>e.dom.isEditable(t)?X(e.dom.getParents(t,"a"))?"link unlink openlink":"link":""})})(e),((e,t)=>{const n=t=>{const n=e.selection.getNode();return t.setEnabled(H(e,n)&&e.selection.isEditable()),g};e.ui.registry.addContextForm("quicklink",{launch:{type:"contextformtogglebutton",icon:"link",tooltip:"Link",onSetup:Pe(e)},label:"Link",predicate:t=>w(e)&&H(e,t),initValue:()=>G(e).fold((()=>""),$),commands:[{type:"contextformtogglebutton",icon:"link",tooltip:"Link",primary:!0,onSetup:t=>{const n=e.selection.getNode();return t.setActive(H(e,n)),Pe(e)(t)},onAction:t=>{const n=t.getValue(),o=(t=>{const n=G(e),o=Y(e);if(n.isNone()&&o){const o=J(e.selection,n);return x(0===o.length,t)}return m.none()})(n);ne(e,{href:n,attach:g},{href:n,text:o,title:m.none(),rel:m.none(),target:m.from(O(e)),class:m.none()}),(e=>{e.selection.collapse(!1)})(e),t.hide()}},{type:"contextformbutton",icon:"unlink",tooltip:"Remove link",onSetup:n,onAction:t=>{oe(e),t.hide()}},{type:"contextformbutton",icon:"new-tab",tooltip:"Open link",onSetup:n,onAction:e=>{t.gotoSelectedLink(),e.hide()}}]})})(e,t)};e.add("link",(e=>{(e=>{const t=e.options.register;t("link_assume_external_targets",{processor:e=>{const t=o(e)||i(e);return t?!0===e?{value:1,valid:t}:"http"===e||"https"===e?{value:e,valid:t}:{value:0,valid:t}:{valid:!1,message:"Must be a string or a boolean."}},default:!1}),t("link_context_toolbar",{processor:"boolean",default:!1}),t("link_list",{processor:e=>o(e)||c(e)||u(e,r)}),t("link_default_target",{processor:"string"}),t("link_default_protocol",{processor:"string",default:"https"}),t("link_target_list",{processor:e=>i(e)||u(e,r),default:!0}),t("link_rel_list",{processor:"object[]",default:[]}),t("link_class_list",{processor:"object[]",default:[]}),t("link_title",{processor:"boolean",default:!0}),t("allow_unsafe_link_target",{processor:"boolean",default:!1}),t("link_quicklink",{processor:"boolean",default:!1}),t("link_attributes_postprocess",{processor:"function"})})(e),(e=>{e.addCommand("mceLink",((t,n)=>{!0!==(null==n?void 0:n.dialog)&&L(e)?e.dispatch("contexttoolbar-show",{toolbarKey:"quicklink"}):Se(e)}))})(e),Be(e),(e=>{e.addShortcut("Meta+K","",(()=>{e.execCommand("mceLink")}))})(e)}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/lists/plugin.min.js b/apps/web-antd/public/tinymce/plugins/lists/plugin.min.js new file mode 100644 index 0000000..ba49b0b --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/lists/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=o=e,(r=String).prototype.isPrototypeOf(n)||(null===(s=o.constructor)||void 0===s?void 0:s.name)===r.name)?"string":t;var n,o,r,s})(t)===e,n=e=>t=>typeof t===e,o=t("string"),r=t("object"),s=t("array"),i=n("boolean"),l=e=>!(e=>null==e)(e),a=n("function"),d=n("number"),c=()=>{},m=e=>()=>e,u=(e,t)=>e===t,p=e=>t=>!e(t),g=m(!1);class h{constructor(e,t){this.tag=e,this.value=t}static some(e){return new h(!0,e)}static none(){return h.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?h.some(e(this.value)):h.none()}bind(e){return this.tag?e(this.value):h.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:h.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return l(e)?h.some(e):h.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}h.singletonNone=new h(!1);const f=Array.prototype.slice,y=Array.prototype.indexOf,v=Array.prototype.push,C=(e,t)=>{return n=e,o=t,y.call(n,o)>-1;var n,o},b=(e,t)=>{for(let n=0,o=e.length;n{const n=e.length,o=new Array(n);for(let r=0;r{for(let n=0,o=e.length;n{const n=[];for(let o=0,r=e.length;o(S(e,((e,o)=>{n=t(n,e,o)})),n),A=(e,t,n)=>{for(let o=0,r=e.length;oA(e,t,g),x=(e,t)=>(e=>{const t=[];for(let n=0,o=e.length;n{const t=f.call(e,0);return t.reverse(),t},E=(e,t)=>t>=0&&tE(e,0),D=e=>E(e,e.length-1),B=(e,t)=>{const n=[],o=a(t)?e=>b(n,(n=>t(n,e))):e=>C(n,e);for(let t=0,r=e.length;te.exists((e=>n(e,t))),P=(e,t,n)=>e.isSome()&&t.isSome()?h.some(n(e.getOrDie(),t.getOrDie())):h.none(),I=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},R=(e,t)=>{const n=(t||document).createElement("div");if(n.innerHTML=e,!n.hasChildNodes()||n.childNodes.length>1){const t="HTML does not have a single root node";throw console.error(t,e),new Error(t)}return I(n.childNodes[0])},U=(e,t)=>{const n=(t||document).createElement(e);return I(n)},$=I,_=(e,t)=>{const n=e.dom;if(1!==n.nodeType)return!1;{const e=n;if(void 0!==e.matches)return e.matches(t);if(void 0!==e.msMatchesSelector)return e.msMatchesSelector(t);if(void 0!==e.webkitMatchesSelector)return e.webkitMatchesSelector(t);if(void 0!==e.mozMatchesSelector)return e.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}},H=(e,t)=>e.dom===t.dom,F=_,V="undefined"!=typeof window?window:Function("return this;")(),j=(e,t)=>((e,t)=>{let n=null!=t?t:V;for(let t=0;t{const t=j("ownerDocument.defaultView",e);return r(e)&&((e=>((e,t)=>{const n=((e,t)=>j(e,t))(e,t);if(null==n)throw new Error(e+" not available on this browser");return n})("HTMLElement",e))(t).prototype.isPrototypeOf(e)||/^HTML\w*Element$/.test(K(e).constructor.name))},Q=e=>e.dom.nodeName.toLowerCase(),W=e=>e.dom.nodeType,q=e=>t=>W(t)===e,Z=e=>G(e)&&z(e.dom),G=q(1),J=q(3),X=q(11),Y=e=>t=>G(t)&&Q(t)===e,ee=e=>h.from(e.dom.parentNode).map($),te=e=>N(e.dom.childNodes,$),ne=(e,t)=>{const n=e.dom.childNodes;return h.from(n[t]).map($)},oe=e=>ne(e,0),re=e=>ne(e,e.dom.childNodes.length-1),se=e=>$(e.dom.host),ie=e=>{const t=J(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;const n=t.ownerDocument;return(e=>{const t=(e=>$(e.dom.getRootNode()))(e);return X(n=t)&&l(n.dom.host)?h.some(t):h.none();var n})($(t)).fold((()=>n.body.contains(t)),(o=ie,r=se,e=>o(r(e))));var o,r};var le=(e,t,n,o,r)=>e(n,o)?h.some(n):a(r)&&r(n)?h.none():t(n,o,r);const ae=(e,t,n)=>{let o=e.dom;const r=a(n)?n:g;for(;o.parentNode;){o=o.parentNode;const e=$(o);if(t(e))return h.some(e);if(r(e))break}return h.none()},de=(e,t,n)=>le(((e,t)=>t(e)),ae,e,t,n),ce=(e,t,n)=>ae(e,(e=>_(e,t)),n),me=(e,t)=>{ee(e).each((n=>{n.dom.insertBefore(t.dom,e.dom)}))},ue=(e,t)=>{e.dom.appendChild(t.dom)},pe=(e,t)=>{S(t,(t=>{ue(e,t)}))},ge=e=>{e.dom.textContent="",S(te(e),(e=>{he(e)}))},he=e=>{const t=e.dom;null!==t.parentNode&&t.parentNode.removeChild(t)};var fe=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),ye=tinymce.util.Tools.resolve("tinymce.dom.TreeWalker"),ve=tinymce.util.Tools.resolve("tinymce.util.VK");const Ce=e=>N(e,$),be=Object.keys,Ne=(e,t)=>{const n=be(e);for(let o=0,r=n.length;o{const n=e.dom;Ne(t,((e,t)=>{((e,t,n)=>{if(!(o(n)||i(n)||d(n)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",n,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,n+"")})(n,t,e)}))},Le=e=>O(e.dom.attributes,((e,t)=>(e[t.name]=t.value,e)),{}),Oe=e=>(e=>$(e.dom.cloneNode(!0)))(e),Ae=(e,t)=>{const n=((e,t)=>{const n=U(t),o=Le(e);return Se(n,o),n})(e,t);var o,r;r=n,(e=>h.from(e.dom.nextSibling).map($))(o=e).fold((()=>{ee(o).each((e=>{ue(e,r)}))}),(e=>{me(e,r)}));const s=te(e);return pe(n,s),he(e),n};var Te=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),xe=tinymce.util.Tools.resolve("tinymce.util.Tools");const ke=e=>t=>l(t)&&t.nodeName.toLowerCase()===e,Ee=e=>t=>l(t)&&e.test(t.nodeName),we=e=>l(e)&&3===e.nodeType,De=e=>l(e)&&1===e.nodeType,Be=Ee(/^(OL|UL|DL)$/),Me=Ee(/^(OL|UL)$/),Pe=ke("ol"),Ie=Ee(/^(LI|DT|DD)$/),Re=Ee(/^(DT|DD)$/),Ue=Ee(/^(TH|TD)$/),$e=ke("br"),_e=(e,t)=>l(t)&&t.nodeName in e.schema.getTextBlockElements(),He=(e,t)=>l(e)&&e.nodeName in t,Fe=(e,t)=>l(t)&&t.nodeName in e.schema.getVoidElements(),Ve=(e,t,n)=>{const o=e.isEmpty(t);return!(n&&e.select("span[data-mce-type=bookmark]",t).length>0)&&o},je=(e,t)=>e.isChildOf(t,e.getRoot()),Ke=e=>t=>t.options.get(e),ze=Ke("lists_indent_on_tab"),Qe=Ke("forced_root_block"),We=Ke("forced_root_block_attrs"),qe=(e,t,n={})=>{const o=e.dom,r=e.schema.getBlockElements(),s=o.createFragment(),i=Qe(e),l=We(e);let a,d,c=!1;for(d=o.create(i,{...l,...n.style?{style:n.style}:{}}),He(t.firstChild,r)||s.appendChild(d);a=t.firstChild;){const e=a.nodeName;c||"SPAN"===e&&"bookmark"===a.getAttribute("data-mce-type")||(c=!0),He(a,r)?(s.appendChild(a),d=null):(d||(d=o.create(i,l),s.appendChild(d)),d.appendChild(a))}return!c&&d&&d.appendChild(o.create("br",{"data-mce-bogus":"1"})),s},Ze=Te.DOM,Ge=Y("dd"),Je=Y("dt"),Xe=(e,t)=>{var n;Ge(t)?Ae(t,"dt"):Je(t)&&(n=t,h.from(n.dom.parentElement).map($)).each((n=>((e,t,n)=>{const o=Ze.select('span[data-mce-type="bookmark"]',t),r=qe(e,n),s=Ze.createRng();s.setStartAfter(n),s.setEndAfter(t);const i=s.extractContents();for(let t=i.firstChild;t;t=t.firstChild)if("LI"===t.nodeName&&e.dom.isEmpty(t)){Ze.remove(t);break}e.dom.isEmpty(i)||Ze.insertAfter(i,t),Ze.insertAfter(r,t);const l=n.parentElement;l&&Ve(e.dom,l)&&(e=>{const t=e.parentNode;t&&xe.each(o,(e=>{t.insertBefore(e,n.parentNode)})),Ze.remove(e)})(l),Ze.remove(n),Ve(e.dom,t)&&Ze.remove(t)})(e,n.dom,t.dom)))},Ye=e=>{Je(e)&&Ae(e,"dd")},et=(e,t)=>{if(we(e))return{container:e,offset:t};const n=fe.getNode(e,t);return we(n)?{container:n,offset:t>=e.childNodes.length?n.data.length:0}:n.previousSibling&&we(n.previousSibling)?{container:n.previousSibling,offset:n.previousSibling.data.length}:n.nextSibling&&we(n.nextSibling)?{container:n.nextSibling,offset:0}:{container:e,offset:t}},tt=e=>{const t=e.cloneRange(),n=et(e.startContainer,e.startOffset);t.setStart(n.container,n.offset);const o=et(e.endContainer,e.endOffset);return t.setEnd(o.container,o.offset),t},nt=["OL","UL","DL"],ot=nt.join(","),rt=(e,t)=>{const n=t||e.selection.getStart(!0);return e.dom.getParent(n,ot,lt(e,n))},st=e=>{const t=e.selection.getSelectedBlocks();return L(((e,t)=>{const n=xe.map(t,(t=>e.dom.getParent(t,"li,dd,dt",lt(e,t))||t));return B(n)})(e,t),Ie)},it=(e,t)=>{const n=e.dom.getParents(t,"TD,TH");return n.length>0?n[0]:e.getBody()},lt=(e,t)=>{const n=e.dom.getParents(t,e.dom.isBlock),o=T(n,(t=>{return(t=>t.nodeName.toLowerCase()!==Qe(e))(t)&&(n=e.schema,!Be(o=t)&&!Ie(o)&&b(nt,(e=>n.isValidChild(o.nodeName,e))));var n,o}));return o.getOr(e.getBody())},at=(e,t)=>{const n=e.dom.getParents(t,"ol,ul",lt(e,t));return D(n)},dt=(e,t)=>{const n=N(t,(t=>at(e,t).getOr(t)));return B(n)},ct=e=>/\btox\-/.test(e.className),mt=(e,t)=>A(e,Be,Ue).exists((e=>e.nodeName===t&&!ct(e))),ut=(e,t)=>null!==t&&!e.dom.isEditable(t),pt=(e,t)=>{const n=e.dom.getParent(t,"ol,ul,dl");return ut(e,n)||!e.selection.isEditable()},gt=(e,t)=>{const n=e.selection.getNode();return t({parents:e.dom.getParents(n),element:n}),e.on("NodeChange",t),()=>e.off("NodeChange",t)},ht=(e,t)=>{const n=(t||document).createDocumentFragment();return S(e,(e=>{n.appendChild(e.dom)})),$(n)},ft=(e,t,n)=>e.dispatch("ListMutation",{action:t,element:n}),yt=(vt=/^\s+|\s+$/g,e=>e.replace(vt,""));var vt;const Ct=(e,t,n)=>{((e,t,n)=>{if(!o(n))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",n,":: Element ",e),new Error("CSS value must be a string: "+n);(e=>void 0!==e.style&&a(e.style.getPropertyValue))(e)&&e.style.setProperty(t,n)})(e.dom,t,n)},bt=e=>F(e,"OL,UL"),Nt=e=>oe(e).exists(bt),St=e=>"listAttributes"in e,Lt=e=>"isComment"in e,Ot=e=>e.depth>0,At=e=>e.isSelected,Tt=e=>{const t=te(e),n=re(e).exists(bt)?t.slice(0,-1):t;return N(n,Oe)},xt=(e,t)=>{ue(e.item,t.list)},kt=(e,t)=>{const n={list:U(t,e),item:U("li",e)};return ue(n.list,n.item),n},Et=(e,t,n)=>{const o=t.slice(0,n.depth);return D(o).each((t=>{if(St(n)){const o=((e,t,n)=>{const o=U("li",e);return Se(o,t),pe(o,n),o})(e,n.itemAttributes,n.content);((e,t)=>{ue(e.list,t),e.item=t})(t,o),((e,t)=>{Q(e.list)!==t.listType&&(e.list=Ae(e.list,t.listType)),Se(e.list,t.listAttributes)})(t,n)}else if((e=>"isFragment"in e)(n))pe(t.item,n.content);else{const e=R(`\x3c!--${n.content}--\x3e`);ue(t.list,e)}})),o},wt=(e,t)=>{let n=h.none();const o=O(t,((t,o,r)=>Lt(o)?0===r?(n=h.some(o),t):Et(e,t,o):o.depth>t.length?((e,t,n)=>{const o=((e,t,n)=>{const o=[];for(let r=0;r{for(let t=1;t{for(let t=0;t{St(t)&&(Se(e.list,t.listAttributes),Se(e.item,t.itemAttributes)),pe(e.item,t.content)}))})(o,n),r=o,P(D(t),w(r),xt),t.concat(o)})(e,t,o):Et(e,t,o)),[]);return n.each((e=>{const t=R(`\x3c!--${e.content}--\x3e`);w(o).each((e=>{((e,t)=>{oe(e).fold((()=>{ue(e,t)}),(n=>{e.dom.insertBefore(t.dom,n.dom)}))})(e.list,t)}))})),w(o).map((e=>e.list))},Dt=e=>(S(e,((t,n)=>{((e,t)=>{const n=e[t].depth,o=e=>e.depth===n&&!e.dirty,r=e=>e.depthA(e.slice(t+1),o,r)))})(e,n).fold((()=>{t.dirty&&St(t)&&(e=>{e.listAttributes=((e,t)=>{const n={};var o;return((e,t,n,o)=>{Ne(e,((e,r)=>{(t(e,r)?n:o)(e,r)}))})(e,t,(o=n,(e,t)=>{o[t]=e}),c),n})(e.listAttributes,((e,t)=>"start"!==t))})(t)}),(e=>{return o=e,void(St(n=t)&&St(o)&&(n.listType=o.listType,n.listAttributes={...o.listAttributes}));var n,o}))})),e),Bt=(e,t,n,o)=>{var r,s;if(8===W(s=o)||"#comment"===Q(s))return[{depth:e+1,content:null!==(r=o.dom.nodeValue)&&void 0!==r?r:"",dirty:!1,isSelected:!1,isComment:!0}];t.each((e=>{H(e.start,o)&&n.set(!0)}));const i=((e,t,n)=>ee(e).filter(G).map((o=>({depth:t,dirty:!1,isSelected:n,content:Tt(e),itemAttributes:Le(e),listAttributes:Le(o),listType:Q(o),isInPreviousLi:!1}))))(o,e,n.get());t.each((e=>{H(e.end,o)&&n.set(!1)}));const l=re(o).filter(bt).map((o=>Pt(e,t,n,o))).getOr([]);return i.toArray().concat(l)},Mt=(e,t,n,o)=>oe(o).filter(bt).fold((()=>Bt(e,t,n,o)),(r=>{const s=O(te(o),((o,s,i)=>{if(0===i)return o;if(F(s,"LI"))return o.concat(Bt(e,t,n,s));{const t={isFragment:!0,depth:e,content:[s],isSelected:!1,dirty:!1,parentListType:Q(r)};return o.concat(t)}}),[]);return Pt(e,t,n,r).concat(s)})),Pt=(e,t,n,o)=>x(te(o),(o=>(bt(o)?Pt:Mt)(e+1,t,n,o))),It=(e,t,n)=>{const o=((e,t)=>{const n=(()=>{let e=!1;return{get:()=>e,set:t=>{e=t}}})();return N(e,(e=>({sourceList:e,entries:Pt(0,t,n,e)})))})(t,(e=>{const t=N(st(e),$);return P(T(t,p(Nt)),T(k(t),p(Nt)),((e,t)=>({start:e,end:t})))})(e));S(o,(t=>{((e,t)=>{S(L(e,At),(e=>((e,t)=>{switch(e){case"Indent":t.depth++;break;case"Outdent":t.depth--;break;case"Flatten":t.depth=0}t.dirty=!0})(t,e)))})(t.entries,n);const o=((e,t)=>x(((e,t)=>{if(0===e.length)return[];{let n=t(e[0]);const o=[];let r=[];for(let s=0,i=e.length;sw(t).exists(Ot)?((e,t)=>{const n=Dt(t);return wt(e.contentDocument,n).toArray()})(e,t):((e,t)=>{const n=Dt(t);return N(n,(t=>{const n=Lt(t)?ht([R(`\x3c!--${t.content}--\x3e`)]):ht(t.content),o=St(t)?t.itemAttributes:{};return $(qe(e,n.dom,o))}))})(e,t))))(e,t.entries);var r;S(o,(t=>{ft(e,"Indent"===n?"IndentList":"OutdentList",t.dom)})),r=t.sourceList,S(o,(e=>{me(r,e)})),he(t.sourceList)}))},Rt=(e,t)=>{const n=Ce((e=>{const t=(e=>{const t=at(e,e.selection.getStart()),n=L(e.selection.getSelectedBlocks(),Me);return t.toArray().concat(n)})(e),n=(e=>{const t=e.selection.getStart();return e.dom.getParents(t,"ol,ul",lt(e,t))})(e);return T(n,(e=>{return t=$(e),ee(t).exists((e=>Ie(e.dom)&&oe(e).exists((e=>!Be(e.dom)))&&re(e).exists((e=>!Be(e.dom)))));var t})).fold((()=>dt(e,t)),(e=>[e]))})(e)),o=Ce((e=>L(st(e),Re))(e));let r=!1;if(n.length||o.length){const s=e.selection.getBookmark();It(e,n,t),((e,t,n)=>{S(n,"Indent"===t?Ye:t=>Xe(e,t))})(e,t,o),e.selection.moveToBookmark(s),e.selection.setRng(tt(e.selection.getRng())),e.nodeChanged(),r=!0}return r},Ut=(e,t)=>!(e=>{const t=rt(e);return ut(e,t)||!e.selection.isEditable()})(e)&&Rt(e,t),$t=e=>Ut(e,"Indent"),_t=e=>Ut(e,"Outdent"),Ht=e=>Ut(e,"Flatten"),Ft=e=>"\ufeff"===e;var Vt=tinymce.util.Tools.resolve("tinymce.dom.BookmarkManager");const jt=Te.DOM,Kt=e=>{const t={},n=n=>{let o=e[n?"startContainer":"endContainer"],r=e[n?"startOffset":"endOffset"];if(De(o)){const e=jt.create("span",{"data-mce-type":"bookmark"});o.hasChildNodes()?(r=Math.min(r,o.childNodes.length-1),n?o.insertBefore(e,o.childNodes[r]):jt.insertAfter(e,o.childNodes[r])):o.appendChild(e),o=e,r=0}t[n?"startContainer":"endContainer"]=o,t[n?"startOffset":"endOffset"]=r};return n(!0),e.collapsed||n(),t},zt=e=>{const t=t=>{let n=e[t?"startContainer":"endContainer"],o=e[t?"startOffset":"endOffset"];if(n){if(De(n)&&n.parentNode){const e=n;o=(e=>{var t;let n=null===(t=e.parentNode)||void 0===t?void 0:t.firstChild,o=0;for(;n;){if(n===e)return o;De(n)&&"bookmark"===n.getAttribute("data-mce-type")||o++,n=n.nextSibling}return-1})(n),n=n.parentNode,jt.remove(e),!n.hasChildNodes()&&jt.isBlock(n)&&n.appendChild(jt.create("br"))}e[t?"startContainer":"endContainer"]=n,e[t?"startOffset":"endOffset"]=o}};t(!0),t();const n=jt.createRng();return n.setStart(e.startContainer,e.startOffset),e.endContainer&&n.setEnd(e.endContainer,e.endOffset),tt(n)},Qt=e=>{switch(e){case"UL":return"ToggleUlList";case"OL":return"ToggleOlList";case"DL":return"ToggleDLList"}},Wt=(e,t)=>{xe.each(t,((t,n)=>{e.setAttribute(n,t)}))},qt=(e,t,n)=>{((e,t,n)=>{const o=n["list-style-type"]?n["list-style-type"]:null;e.setStyle(t,"list-style-type",o)})(e,t,n),((e,t,n)=>{Wt(t,n["list-attributes"]),xe.each(e.select("li",t),(e=>{Wt(e,n["list-item-attributes"])}))})(e,t,n)},Zt=(e,t)=>l(t)&&!He(t,e.schema.getBlockElements()),Gt=(e,t,n,o)=>{let r=t[n?"startContainer":"endContainer"];const s=t[n?"startOffset":"endOffset"];De(r)&&(r=r.childNodes[Math.min(s,r.childNodes.length-1)]||r),!n&&$e(r.nextSibling)&&(r=r.nextSibling);const i=(t,n)=>{var r;const s=new ye(t,(t=>{for(;!e.dom.isBlock(t)&&t.parentNode&&o!==t;)t=t.parentNode;return t})(t)),i=n?"next":"prev";let l;for(;l=s[i]();)if(!Fe(e,l)&&!Ft(l.textContent)&&0!==(null===(r=l.textContent)||void 0===r?void 0:r.length))return h.some(l);return h.none()};if(n&&we(r))if(Ft(r.textContent))r=i(r,!1).getOr(r);else for(null!==r.parentNode&&Zt(e,r.parentNode)&&(r=r.parentNode);null!==r.previousSibling&&(Zt(e,r.previousSibling)||we(r.previousSibling));)r=r.previousSibling;if(!n&&we(r))if(Ft(r.textContent))r=i(r,!0).getOr(r);else for(null!==r.parentNode&&Zt(e,r.parentNode)&&(r=r.parentNode);null!==r.nextSibling&&(Zt(e,r.nextSibling)||we(r.nextSibling));)r=r.nextSibling;for(;r.parentNode!==o;){const t=r.parentNode;if(_e(e,r))return r;if(/^(TD|TH)$/.test(t.nodeName))return r;r=t}return r},Jt=(e,t,n)=>{const o=e.selection.getRng();let r="LI";const s=lt(e,((e,t)=>{const n=e.selection.getStart(!0),o=Gt(e,t,!0,e.getBody());return r=$(o),s=$(t.commonAncestorContainer),i=r,l=function(e,...t){return(...n)=>{const o=t.concat(n);return e.apply(null,o)}}(H,s),ae(i,l,void 0).isSome()?t.commonAncestorContainer:n;var r,s,i,l})(e,o)),i=e.dom;if("false"===i.getContentEditable(e.selection.getNode()))return;"DL"===(t=t.toUpperCase())&&(r="DT");const l=Kt(o),a=L(((e,t,n)=>{const o=[],r=e.dom,s=Gt(e,t,!0,n),i=Gt(e,t,!1,n);let l;const a=[];for(let e=s;e&&(a.push(e),e!==i);e=e.nextSibling);return xe.each(a,(t=>{var s;if(_e(e,t))return o.push(t),void(l=null);if(r.isBlock(t)||$e(t))return $e(t)&&r.remove(t),void(l=null);const i=t.nextSibling;Vt.isBookmarkNode(t)&&(Be(i)||_e(e,i)||!i&&t.parentNode===n)?l=null:(l||(l=r.create("p"),null===(s=t.parentNode)||void 0===s||s.insertBefore(l,t),o.push(l)),l.appendChild(t))})),o})(e,o,s),e.dom.isEditable);xe.each(a,(o=>{let s;const l=o.previousSibling,a=o.parentNode;Ie(a)||(l&&Be(l)&&l.nodeName===t&&((e,t,n)=>{const o=e.getStyle(t,"list-style-type");let r=n?n["list-style-type"]:"";return r=null===r?"":r,o===r})(i,l,n)?(s=l,o=i.rename(o,r),l.appendChild(o)):(s=i.create(t),a.insertBefore(s,o),s.appendChild(o),o=i.rename(o,r)),((e,t)=>{xe.each(["margin","margin-right","margin-bottom","margin-left","margin-top","padding","padding-right","padding-bottom","padding-left","padding-top"],(n=>e.setStyle(t,n,"")))})(i,o),qt(i,s,n),Yt(e.dom,s))})),e.selection.setRng(zt(l))},Xt=(e,t,n)=>{return((e,t)=>Be(e)&&e.nodeName===(null==t?void 0:t.nodeName))(t,n)&&((e,t,n)=>e.getStyle(t,"list-style-type",!0)===e.getStyle(n,"list-style-type",!0))(e,t,n)&&(o=n,t.className===o.className);var o},Yt=(e,t)=>{let n,o=t.nextSibling;if(Xt(e,t,o)){const r=o;for(;n=r.firstChild;)t.appendChild(n);e.remove(r)}if(o=t.previousSibling,Xt(e,t,o)){const r=o;for(;n=r.lastChild;)t.insertBefore(n,t.firstChild);e.remove(r)}},en=(e,t,n,o)=>{if(t.nodeName!==n){const r=e.dom.rename(t,n);qt(e.dom,r,o),ft(e,Qt(n),r)}else qt(e.dom,t,o),ft(e,Qt(n),t)},tn=(e,t,n,o)=>{if(t.classList.forEach(((e,n,o)=>{e.startsWith("tox-")&&(o.remove(e),0===o.length&&t.removeAttribute("class"))})),t.nodeName!==n){const r=e.dom.rename(t,n);qt(e.dom,r,o),ft(e,Qt(n),r)}else qt(e.dom,t,o),ft(e,Qt(n),t)},nn=e=>"list-style-type"in e,on=(e,t,n)=>{const o=rt(e);if(pt(e,o))return;const s=(e=>{const t=rt(e),n=e.selection.getSelectedBlocks();return((e,t)=>l(e)&&1===t.length&&t[0]===e)(t,n)?(e=>L(e.querySelectorAll(ot),Be))(t):L(n,(e=>Be(e)&&t!==e))})(e),i=r(n)?n:{};s.length>0?((e,t,n,o,r)=>{const s=Be(t);if(!s||t.nodeName!==o||nn(r)||ct(t)){Jt(e,o,r);const i=Kt(e.selection.getRng()),l=s?[t,...n]:n,a=s&&ct(t)?tn:en;xe.each(l,(t=>{a(e,t,o,r)})),e.selection.setRng(zt(i))}else Ht(e)})(e,o,s,t,i):((e,t,n,o)=>{if(t!==e.getBody())if(t)if(t.nodeName!==n||nn(o)||ct(t)){const r=Kt(e.selection.getRng());ct(t)&&t.classList.forEach(((e,n,o)=>{e.startsWith("tox-")&&(o.remove(e),0===o.length&&t.removeAttribute("class"))})),qt(e.dom,t,o);const s=e.dom.rename(t,n);Yt(e.dom,s),e.selection.setRng(zt(r)),Jt(e,n,o),ft(e,Qt(n),s)}else Ht(e);else Jt(e,n,o),ft(e,Qt(n),t)})(e,o,t,i)},rn=Te.DOM,sn=(e,t)=>{const n=xe.grep(e.select("ol,ul",t));xe.each(n,(t=>{((e,t)=>{const n=t.parentElement;if(n&&"LI"===n.nodeName&&n.firstChild===t){const o=n.previousSibling;o&&"LI"===o.nodeName?(o.appendChild(t),Ve(e,n)&&rn.remove(n)):rn.setStyle(n,"listStyleType","none")}if(Be(n)){const e=n.previousSibling;e&&"LI"===e.nodeName&&e.appendChild(t)}})(e,t)}))},ln=(e,t,n,o)=>{let r=t.startContainer;const s=t.startOffset;if(we(r)&&(n?s0))return r;const i=e.schema.getNonEmptyElements();De(r)&&(r=fe.getNode(r,s));const l=new ye(r,o);n&&((e,t)=>!!$e(t)&&e.isBlock(t.nextSibling)&&!$e(t.previousSibling))(e.dom,r)&&l.next();const a=n?l.next.bind(l):l.prev2.bind(l);for(;r=a();){if("LI"===r.nodeName&&!r.hasChildNodes())return r;if(i[r.nodeName])return r;if(we(r)&&r.data.length>0)return r}return null},an=(e,t)=>{const n=t.childNodes;return 1===n.length&&!Be(n[0])&&e.isBlock(n[0])},dn=e=>h.from(e).map($).filter(Z).exists((e=>((e,t=!1)=>{return ie(e)?e.dom.isContentEditable:(n=e,le(((e,t)=>_(e,t)),ce,n,"[contenteditable]",void 0)).fold(m(t),(e=>"true"===(e=>e.dom.contentEditable)(e)));var n})(e)&&!C(["details"],Q(e)))),cn=(e,t,n)=>{let o;const r=an(e,n)?n.firstChild:n;if(((e,t)=>{an(e,t)&&dn(t.firstChild)&&e.remove(t.firstChild,!0)})(e,t),!Ve(e,t,!0))for(;o=t.firstChild;)r.appendChild(o)},mn=(e,t,n)=>{let o;const r=t.parentNode;if(!je(e,t)||!je(e,n))return;Be(n.lastChild)&&(o=n.lastChild),r===n.lastChild&&$e(r.previousSibling)&&e.remove(r.previousSibling);const s=n.lastChild;s&&$e(s)&&t.hasChildNodes()&&e.remove(s),Ve(e,n,!0)&&ge($(n)),cn(e,t,n),o&&n.appendChild(o);const i=((e,t)=>{const n=e.dom,o=t.dom;return n!==o&&n.contains(o)})($(n),$(t))?e.getParents(t,Be,n):[];e.remove(t),S(i,(t=>{Ve(e,t)&&t!==e.getRoot()&&e.remove(t)}))},un=(e,t)=>{const n=e.dom,o=e.selection,r=o.getStart(),s=it(e,r),i=n.getParent(o.getStart(),"LI",s);if(i){const r=i.parentElement;if(r===e.getBody()&&Ve(n,r))return!0;const l=tt(o.getRng()),a=n.getParent(ln(e,l,t,s),"LI",s),d=a&&(t?n.isChildOf(i,a):n.isChildOf(a,i));if(a&&a!==i&&!d)return e.undoManager.transact((()=>{var n,o;t?((e,t,n,o)=>{const r=e.dom;if(r.isEmpty(o))((e,t,n)=>{ge($(n)),mn(e.dom,t,n),e.selection.setCursorLocation(n,0)})(e,n,o);else{const s=Kt(t);mn(r,n,o),e.selection.setRng(zt(s))}})(e,l,a,i):(null===(o=(n=i).parentNode)||void 0===o?void 0:o.firstChild)===n?_t(e):((e,t,n,o)=>{const r=Kt(t);mn(e.dom,n,o);const s=zt(r);e.selection.setRng(s)})(e,l,i,a)})),!0;if(d&&!t&&a!==i){const t=l.commonAncestorContainer.parentElement;return!(!t||n.isChildOf(a,t)||(e.undoManager.transact((()=>{const o=Kt(l);cn(n,t,a),t.remove();const r=zt(o);e.selection.setRng(r)})),0))}if(!a&&!t&&0===l.startOffset&&0===l.endOffset)return e.undoManager.transact((()=>{Ht(e)})),!0}return!1},pn=e=>{const t=e.selection.getStart(),n=it(e,t);return e.dom.getParent(t,"LI,DT,DD",n)||st(e).length>0},gn=(e,t)=>{const n=e.selection;return!pt(e,n.getNode())&&(n.isCollapsed()?((e,t)=>un(e,t)||((e,t)=>{const n=e.dom,o=e.selection.getStart(),r=it(e,o),s=n.getParent(o,n.isBlock,r);if(s&&n.isEmpty(s,void 0,{checkRootAsContent:!0})){const o=tt(e.selection.getRng()),i=ln(e,o,t,r),l=n.getParent(i,"LI",r);if(i&&l){const a=e=>C(["td","th","caption"],Q(e)),d=e=>e.dom===r;return!!((e,t,n=u)=>P(e,t,n).getOr(e.isNone()&&t.isNone()))(de($(l),a,d),de($(o.startContainer),a,d),H)&&(e.undoManager.transact((()=>{const o=l.parentNode;((e,t,n)=>{const o=e.getParent(t.parentNode,e.isBlock,n);e.remove(t),o&&e.isEmpty(o)&&e.remove(o)})(n,s,r),Yt(n,o),e.selection.select(i,!0),e.selection.collapse(t)})),!0)}}return!1})(e,t))(e,t):(e=>!!pn(e)&&(e.undoManager.transact((()=>{let t=!0;const n=()=>t=!1;e.on("input",n),e.execCommand("Delete"),e.off("input",n),t&&e.dispatch("input"),sn(e.dom,e.getBody())})),!0))(e))},hn=e=>{const t=k(yt(e).split("")),n=N(t,((e,t)=>{const n=e.toUpperCase().charCodeAt(0)-"A".charCodeAt(0)+1;return Math.pow(26,t)*n}));return O(n,((e,t)=>e+t),0)},fn=e=>{if(--e<0)return"";{const t=e%26,n=Math.floor(e/26);return fn(n)+String.fromCharCode("A".charCodeAt(0)+t)}},yn=e=>{const t=parseInt(e.start,10);return M(e.listStyleType,"upper-alpha")?fn(t):M(e.listStyleType,"lower-alpha")?fn(t).toLowerCase():e.start},vn=(e,t)=>()=>{const n=rt(e);return l(n)&&n.nodeName===t},Cn=e=>{e.addCommand("mceListProps",(()=>{(e=>{const t=rt(e);Pe(t)&&!pt(e,t)&&e.windowManager.open({title:"List Properties",body:{type:"panel",items:[{type:"input",name:"start",label:"Start list at number",inputMode:"numeric"}]},initialData:{start:yn({start:e.dom.getAttrib(t,"start","1"),listStyleType:h.from(e.dom.getStyle(t,"list-style-type"))})},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],onSubmit:t=>{(e=>{switch((e=>/^[0-9]+$/.test(e)?2:/^[A-Z]+$/.test(e)?0:/^[a-z]+$/.test(e)?1:e.length>0?4:3)(e)){case 2:return h.some({listStyleType:h.none(),start:e});case 0:return h.some({listStyleType:h.some("upper-alpha"),start:hn(e).toString()});case 1:return h.some({listStyleType:h.some("lower-alpha"),start:hn(e).toString()});case 3:return h.some({listStyleType:h.none(),start:""});case 4:return h.none()}})(t.getData().start).each((t=>{e.execCommand("mceListUpdate",!1,{attrs:{start:"1"===t.start?"":t.start},styles:{"list-style-type":t.listStyleType.getOr("")}})})),t.close()}})})(e)}))};var bn=tinymce.util.Tools.resolve("tinymce.html.Node");const Nn=e=>3===e.type,Sn=e=>0===e.length,Ln=e=>{const t=(t,n)=>{const o=bn.create("li");S(t,(e=>o.append(e))),n?e.insert(o,n,!0):e.append(o)},n=O(e.children(),((e,n)=>Nn(n)?[...e,n]:Sn(e)||Nn(n)?e:(t(e,n),[])),[]);Sn(n)||t(n)},On=(e,t)=>n=>(n.setEnabled(e.selection.isEditable()),gt(e,(o=>{n.setActive(mt(o.parents,t)),n.setEnabled(!pt(e,o.element)&&e.selection.isEditable())}))),An=(e,t)=>n=>gt(e,(o=>n.setEnabled(mt(o.parents,t)&&!pt(e,o.element))));e.add("lists",(e=>((e=>{(0,e.options.register)("lists_indent_on_tab",{processor:"boolean",default:!0})})(e),(e=>{e.on("PreInit",(()=>{const{parser:t}=e;t.addNodeFilter("ul,ol",(e=>S(e,Ln)))}))})(e),e.hasPlugin("rtc",!0)?Cn(e):((e=>{ze(e)&&(e=>{e.on("keydown",(t=>{t.keyCode!==ve.TAB||ve.metaKeyPressed(t)||e.undoManager.transact((()=>{(t.shiftKey?_t(e):$t(e))&&t.preventDefault()}))}))})(e),(e=>{e.on("ExecCommand",(t=>{const n=t.command.toLowerCase();"delete"!==n&&"forwarddelete"!==n||!pn(e)||sn(e.dom,e.getBody())})),e.on("keydown",(t=>{t.keyCode===ve.BACKSPACE?gn(e,!1)&&t.preventDefault():t.keyCode===ve.DELETE&&gn(e,!0)&&t.preventDefault()}))})(e)})(e),(e=>{e.on("BeforeExecCommand",(t=>{const n=t.command.toLowerCase();"indent"===n?$t(e):"outdent"===n&&_t(e)})),e.addCommand("InsertUnorderedList",((t,n)=>{on(e,"UL",n)})),e.addCommand("InsertOrderedList",((t,n)=>{on(e,"OL",n)})),e.addCommand("InsertDefinitionList",((t,n)=>{on(e,"DL",n)})),e.addCommand("RemoveList",(()=>{Ht(e)})),Cn(e),e.addCommand("mceListUpdate",((t,n)=>{r(n)&&((e,t)=>{const n=rt(e);null===n||pt(e,n)||e.undoManager.transact((()=>{r(t.styles)&&e.dom.setStyles(n,t.styles),r(t.attrs)&&Ne(t.attrs,((t,o)=>e.dom.setAttrib(n,o,t)))}))})(e,n)})),e.addQueryStateHandler("InsertUnorderedList",vn(e,"UL")),e.addQueryStateHandler("InsertOrderedList",vn(e,"OL")),e.addQueryStateHandler("InsertDefinitionList",vn(e,"DL"))})(e)),(e=>{const t=t=>()=>e.execCommand(t);e.hasPlugin("advlist")||(e.ui.registry.addToggleButton("numlist",{icon:"ordered-list",active:!1,tooltip:"Numbered list",onAction:t("InsertOrderedList"),onSetup:On(e,"OL")}),e.ui.registry.addToggleButton("bullist",{icon:"unordered-list",active:!1,tooltip:"Bullet list",onAction:t("InsertUnorderedList"),onSetup:On(e,"UL")}))})(e),(e=>{const t={text:"List properties...",icon:"ordered-list",onAction:()=>e.execCommand("mceListProps"),onSetup:An(e,"OL")};e.ui.registry.addMenuItem("listprops",t),e.ui.registry.addContextMenu("lists",{update:t=>{const n=rt(e,t);return Pe(n)?["listprops"]:[]}})})(e),(e=>({backspaceDelete:t=>{gn(e,t)}}))(e))))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/media/plugin.min.js b/apps/web-antd/public/tinymce/plugins/media/plugin.min.js new file mode 100644 index 0000000..5a31076 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/media/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(r=o=e,(a=String).prototype.isPrototypeOf(r)||(null===(s=o.constructor)||void 0===s?void 0:s.name)===a.name)?"string":t;var r,o,a,s})(t)===e,r=t("string"),o=t("object"),a=t("array"),s=e=>!(e=>null==e)(e);class i{constructor(e,t){this.tag=e,this.value=t}static some(e){return new i(!0,e)}static none(){return i.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?i.some(e(this.value)):i.none()}bind(e){return this.tag?e(this.value):i.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:i.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return s(e)?i.some(e):i.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}i.singletonNone=new i(!1);const n=Array.prototype.push,l=(e,t)=>{for(let r=0,o=e.length;r{const t=[];for(let r=0,o=e.length;rh(e,t)?i.from(e[t]):i.none(),h=(e,t)=>u.call(e,t),p=e=>t=>t.options.get(e),g=p("audio_template_callback"),b=p("video_template_callback"),w=p("iframe_template_callback"),v=p("media_live_embeds"),f=p("media_filter_html"),y=p("media_url_resolver"),x=p("media_alt_source"),_=p("media_poster"),k=p("media_dimensions");var j=tinymce.util.Tools.resolve("tinymce.util.Tools"),O=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),A=tinymce.util.Tools.resolve("tinymce.html.DomParser");const S=O.DOM,$=e=>e.replace(/px$/,""),C=e=>{const t=e.attr("style"),r=t?S.parseStyle(t):{};return{type:"ephox-embed-iri",source:e.attr("data-ephox-embed-iri"),altsource:"",poster:"",width:d(r,"max-width").map($).getOr(""),height:d(r,"max-height").map($).getOr("")}},T=(e,t)=>{let r={};for(let o=A({validate:!1,forced_root_block:!1},t).parse(e);o;o=o.walk())if(1===o.type){const e=o.name;if(o.attr("data-ephox-embed-iri")){r=C(o);break}r.source||"param"!==e||(r.source=o.attr("movie")),"iframe"!==e&&"object"!==e&&"embed"!==e&&"video"!==e&&"audio"!==e||(r.type||(r.type=e),r=j.extend(o.attributes.map,r)),"source"===e&&(r.source?r.altsource||(r.altsource=o.attr("src")):r.source=o.attr("src")),"img"!==e||r.poster||(r.poster=o.attr("src"))}return r.source=r.source||r.src||"",r.altsource=r.altsource||"",r.poster=r.poster||"",r},z=e=>{var t;const r=null!==(t=e.toLowerCase().split(".").pop())&&void 0!==t?t:"";return d({mp3:"audio/mpeg",m4a:"audio/x-m4a",wav:"audio/wav",mp4:"video/mp4",webm:"video/webm",ogg:"video/ogg",swf:"application/x-shockwave-flash"},r).getOr("")};var D=tinymce.util.Tools.resolve("tinymce.html.Node"),F=tinymce.util.Tools.resolve("tinymce.html.Serializer");const M=(e,t={})=>A({forced_root_block:!1,validate:!1,allow_conditional_comments:!0,...t},e),N=O.DOM,P=e=>/^[0-9.]+$/.test(e)?e+"px":e,R=(e,t)=>{const r=t.attr("style"),o=r?N.parseStyle(r):{};s(e.width)&&(o["max-width"]=P(e.width)),s(e.height)&&(o["max-height"]=P(e.height)),t.attr("style",N.serializeStyle(o))},E=["source","altsource"],U=(e,t,r,o)=>{let a=0,s=0;const i=M(o);i.addNodeFilter("source",(e=>a=e.length));const n=i.parse(e);for(let e=n;e;e=e.walk())if(1===e.type){const o=e.name;if(e.attr("data-ephox-embed-iri")){R(t,e);break}switch(o){case"video":case"object":case"embed":case"img":case"iframe":void 0!==t.height&&void 0!==t.width&&(e.attr("width",t.width),e.attr("height",t.height))}if(r)switch(o){case"video":e.attr("poster",t.poster),e.attr("src",null);for(let r=a;r<2;r++)if(t[E[r]]){const o=new D("source",1);o.attr("src",t[E[r]]),o.attr("type",t[E[r]+"mime"]||null),e.append(o)}break;case"iframe":e.attr("src",t.source);break;case"object":const r=e.getAll("img").length>0;if(t.poster&&!r){e.attr("src",t.poster);const r=new D("img",1);r.attr("src",t.poster),r.attr("width",t.width),r.attr("height",t.height),e.append(r)}break;case"source":if(s<2&&(e.attr("src",t[E[s]]),e.attr("type",t[E[s]+"mime"]||null),!t[E[s]])){e.remove();continue}s++;break;case"img":t.poster||e.remove()}}return F({},o).serialize(n)},L=[{regex:/youtu\.be\/([\w\-_\?&=.]+)/i,type:"iframe",w:560,h:314,url:"www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/youtube\.com(.+)v=([^&]+)(&([a-z0-9&=\-_]+))?/i,type:"iframe",w:560,h:314,url:"www.youtube.com/embed/$2?$4",allowFullscreen:!0},{regex:/youtube.com\/embed\/([a-z0-9\?&=\-_]+)/i,type:"iframe",w:560,h:314,url:"www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/vimeo\.com\/([0-9]+)\?h=(\w+)/,type:"iframe",w:425,h:350,url:"player.vimeo.com/video/$1?h=$2&title=0&byline=0&portrait=0&color=8dc7dc",allowFullscreen:!0},{regex:/vimeo\.com\/(.*)\/([0-9]+)\?h=(\w+)/,type:"iframe",w:425,h:350,url:"player.vimeo.com/video/$2?h=$3&title=0&byline=0",allowFullscreen:!0},{regex:/vimeo\.com\/([0-9]+)/,type:"iframe",w:425,h:350,url:"player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc",allowFullscreen:!0},{regex:/vimeo\.com\/(.*)\/([0-9]+)/,type:"iframe",w:425,h:350,url:"player.vimeo.com/video/$2?title=0&byline=0",allowFullscreen:!0},{regex:/maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,type:"iframe",w:425,h:350,url:'maps.google.com/maps/ms?msid=$2&output=embed"',allowFullscreen:!1},{regex:/dailymotion\.com\/video\/([^_]+)/,type:"iframe",w:480,h:270,url:"www.dailymotion.com/embed/video/$1",allowFullscreen:!0},{regex:/dai\.ly\/([^_]+)/,type:"iframe",w:480,h:270,url:"www.dailymotion.com/embed/video/$1",allowFullscreen:!0}],I=(e,t)=>{const r=(e=>{const t=e.match(/^(https?:\/\/|www\.)(.+)$/i);return t&&t.length>1?"www."===t[1]?"https://":t[1]:"https://"})(t),o=e.regex.exec(t);let a=r+e.url;if(s(o))for(let e=0;eo[e]?o[e]:""));return a.replace(/\?$/,"")},B=e=>{const t=L.filter((t=>t.regex.test(e)));return t.length>0?j.extend({},t[0],{url:I(t[0],e)}):null},G=(e,t)=>{var r;const o=j.extend({},t);if(!o.source&&(j.extend(o,T(null!==(r=o.embed)&&void 0!==r?r:"",e.schema)),!o.source))return"";o.altsource||(o.altsource=""),o.poster||(o.poster=""),o.source=e.convertURL(o.source,"source"),o.altsource=e.convertURL(o.altsource,"source"),o.sourcemime=z(o.source),o.altsourcemime=z(o.altsource),o.poster=e.convertURL(o.poster,"poster");const a=B(o.source);if(a&&(o.source=a.url,o.type=a.type,o.allowfullscreen=a.allowFullscreen,o.width=o.width||String(a.w),o.height=o.height||String(a.h)),o.embed)return U(o.embed,o,!0,e.schema);{const t=g(e),r=b(e),a=w(e);return o.width=o.width||"300",o.height=o.height||"150",j.each(o,((t,r)=>{o[r]=e.dom.encode(""+t)})),"iframe"===o.type?((e,t)=>{if(t)return t(e);{const t=e.allowfullscreen?' allowFullscreen="1"':"";return'"}})(o,a):"application/x-shockwave-flash"===o.sourcemime?(e=>{let t='';return e.poster&&(t+=''),t+="",t})(o):-1!==o.sourcemime.indexOf("audio")?((e,t)=>t?t(e):'")(o,t):((e,t)=>t?t(e):'")(o,r)}},W=e=>e.hasAttribute("data-mce-object")||e.hasAttribute("data-ephox-embed-iri"),q={},H=e=>t=>G(e,t),J=(e,t)=>{const r=y(e);return r?((e,t,r)=>new Promise(((o,a)=>{const s=r=>(r.html&&(q[e.source]=r),o({url:e.source,html:r.html?r.html:t(e)}));q[e.source]?s(q[e.source]):r({url:e.source}).then(s).catch(a)})))(t,H(e),r):((e,t)=>Promise.resolve({html:t(e),url:e.source}))(t,H(e))},K=(e,t)=>{const r={};return d(e,"dimensions").each((e=>{l(["width","height"],(o=>{d(t,o).orThunk((()=>d(e,o))).each((e=>r[o]=e))}))})),r},Q=(e,t)=>{const r=t&&"dimensions"!==t?((e,t)=>d(t,e).bind((e=>d(e,"meta"))))(t,e).getOr({}):{},a=((e,t,r)=>a=>{const s=()=>d(e,a),n=()=>d(t,a),l=e=>d(e,"value").bind((e=>e.length>0?i.some(e):i.none()));return{[a]:(a===r?s().bind((e=>o(e)?l(e).orThunk(n):n().orThunk((()=>i.from(e))))):n().orThunk((()=>s().bind((e=>o(e)?l(e):i.from(e)))))).getOr("")}})(e,r,t);return{...a("source"),...a("altsource"),...a("poster"),...a("embed"),...K(e,r)}},V=e=>{const t={...e,source:{value:d(e,"source").getOr("")},altsource:{value:d(e,"altsource").getOr("")},poster:{value:d(e,"poster").getOr("")}};return l(["width","height"],(r=>{d(e,r).each((e=>{const o=t.dimensions||{};o[r]=e,t.dimensions=o}))})),t},X=e=>t=>{const r=t&&t.msg?"Media embed handler error: "+t.msg:"Media embed handler threw unknown error.";e.notificationManager.open({type:"error",text:r})},Y=(e,t)=>o=>{if(r(o.url)&&o.url.trim().length>0){const r=o.html,a={...T(r,t.schema),source:o.url,embed:r};e.setData(V(a))}},Z=(e,t)=>{const r=e.dom.select("*[data-mce-object]");e.insertContent(t),((e,t)=>{const r=e.dom.select("*[data-mce-object]");for(let e=0;e=0;o--)t[e]===r[o]&&r.splice(o,1);e.selection.select(r[0])})(e,r),e.nodeChanged()},ee=(e,t)=>s(t)&&"ephox-embed-iri"===t&&s(B(e)),te=(e,t)=>((e,t)=>e.width!==t.width||e.height!==t.height)(e,t)&&ee(t.source,e.type),re=e=>{const t=(e=>{const t=e.selection.getNode(),r=W(t)?e.serializer.serialize(t,{selection:!0}):"",o=T(r,e.schema),a=(()=>{if(ee(o.source,o.type)){const r=e.dom.getRect(t);return{width:r.w.toString().replace(/px$/,""),height:r.h.toString().replace(/px$/,"")}}return{}})();return{embed:r,...o,...a}})(e),r=(e=>{let t=e;return{get:()=>t,set:e=>{t=e}}})(t),o=V(t),a=k(e)?[{type:"sizeinput",name:"dimensions",label:"Constrain proportions",constrain:!0}]:[],s={title:"General",name:"general",items:c([[{name:"source",type:"urlinput",filetype:"media",label:"Source",picker_text:"Browse files"}],a])},i=[];x(e)&&i.push({name:"altsource",type:"urlinput",filetype:"media",label:"Alternative source URL"}),_(e)&&i.push({name:"poster",type:"urlinput",filetype:"image",label:"Media poster (Image URL)"});const n={title:"Advanced",name:"advanced",items:i},l=[s,{title:"Embed",items:[{type:"textarea",name:"embed",label:"Paste your embed code below:"}]}];i.length>0&&l.push(n);const m={type:"tabpanel",tabs:l},u=e.windowManager.open({title:"Insert/Edit Media",size:"normal",body:m,buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],onSubmit:t=>{const o=Q(t.getData());((e,t,r)=>{var o,a;t.embed=te(e,t)&&k(r)?G(r,{...t,embed:""}):U(null!==(o=t.embed)&&void 0!==o?o:"",t,!1,r.schema),t.embed&&(e.source===t.source||(a=t.source,h(q,a)))?Z(r,t.embed):J(r,t).then((e=>{Z(r,e.html)})).catch(X(r))})(r.get(),o,e),t.close()},onChange:(t,o)=>{switch(o.name){case"source":((t,r)=>{const o=Q(r.getData(),"source");t.source!==o.source&&(Y(u,e)({url:o.source,html:""}),J(e,o).then(Y(u,e)).catch(X(e)))})(r.get(),t);break;case"embed":(t=>{var r;const o=Q(t.getData()),a=T(null!==(r=o.embed)&&void 0!==r?r:"",e.schema);t.setData(V(a))})(t);break;case"dimensions":case"altsource":case"poster":((t,r,o)=>{const a=Q(t.getData(),r),s=te(o,a)&&k(e)?{...a,embed:""}:a,i=G(e,s);t.setData(V({...s,embed:i}))})(t,o.name,r.get())}r.set(Q(t.getData()))},initialData:o})};var oe=tinymce.util.Tools.resolve("tinymce.Env");const ae=e=>{const t=e.name;return"iframe"===t||"video"===t||"audio"===t},se=(e,t,r,o=null)=>{const a=e.attr(r);return s(a)?a:h(t,r)?null:o},ie=(e,t,r)=>{const o="img"===t.name||"video"===e.name,a=o?"300":null,s="audio"===e.name?"30":"150",i=o?s:null;t.attr({width:se(e,r,"width",a),height:se(e,r,"height",i)})},ne=(e,t)=>{const r=t.name,o=new D("img",1);return ce(e,t,o),ie(t,o,{}),o.attr({style:t.attr("style"),src:oe.transparentSrc,"data-mce-object":r,class:"mce-object mce-object-"+r}),o},le=(e,t)=>{var r;const o=t.name,a=new D("span",1);a.attr({contentEditable:"false",style:t.attr("style"),"data-mce-object":o,class:"mce-preview-object mce-object-"+o}),ce(e,t,a);const i=e.dom.parseStyle(null!==(r=t.attr("style"))&&void 0!==r?r:""),n=new D(o,1);if(ie(t,n,i),n.attr({src:t.attr("src"),style:t.attr("style"),class:t.attr("class")}),"iframe"===o)n.attr({allowfullscreen:t.attr("allowfullscreen"),frameborder:"0",sandbox:t.attr("sandbox"),referrerpolicy:t.attr("referrerpolicy")});else{l(["controls","crossorigin","currentTime","loop","muted","poster","preload"],(e=>{n.attr(e,t.attr(e))}));const r=a.attr("data-mce-html");s(r)&&((e,t,r,o)=>{const a=M(e.schema).parse(o,{context:t});for(;a.firstChild;)r.append(a.firstChild)})(e,o,n,unescape(r))}const c=new D("span",1);return c.attr("class","mce-shim"),a.append(n),a.append(c),a},ce=(e,t,r)=>{var o;const a=null!==(o=t.attributes)&&void 0!==o?o:[];let s=a.length;for(;s--;){const t=a[s].name;let o=a[s].value;"width"===t||"height"===t||"style"===t||(n="data-mce-",(i=t).length>=9&&i.substr(0,9)===n)||("data"!==t&&"src"!==t||(o=e.convertURL(o,t)),r.attr("data-mce-p-"+t,o))}var i,n;const c=F({inner:!0},e.schema),m=new D("div",1);l(t.children(),(e=>m.append(e)));const u=c.serialize(m);u&&(r.attr("data-mce-html",escape(u)),r.empty())},me=e=>{const t=e.attr("class");return r(t)&&/\btiny-pageembed\b/.test(t)},ue=e=>{let t=e;for(;t=t.parent;)if(t.attr("data-ephox-embed-iri")||me(t))return!0;return!1},de=(e,t,r)=>{const o=(0,e.options.get)("xss_sanitization"),a=f(e);return M(e.schema,{sanitize:o,validate:a}).parse(r,{context:t})},he=e=>t=>{const r=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",r),r(),()=>{e.off("NodeChange",r)}};e.add("media",(e=>((e=>{const t=e.options.register;t("audio_template_callback",{processor:"function"}),t("video_template_callback",{processor:"function"}),t("iframe_template_callback",{processor:"function"}),t("media_live_embeds",{processor:"boolean",default:!0}),t("media_filter_html",{processor:"boolean",default:!0}),t("media_url_resolver",{processor:"function"}),t("media_alt_source",{processor:"boolean",default:!0}),t("media_poster",{processor:"boolean",default:!0}),t("media_dimensions",{processor:"boolean",default:!0})})(e),(e=>{e.addCommand("mceMedia",(()=>{re(e)}))})(e),(e=>{const t=()=>e.execCommand("mceMedia");e.ui.registry.addToggleButton("media",{tooltip:"Insert/edit media",icon:"embed",onAction:t,onSetup:t=>{const r=e.selection;t.setActive(W(r.getNode()));const o=r.selectorChangedWithUnbind("img[data-mce-object],span[data-mce-object],div[data-ephox-embed-iri]",t.setActive).unbind,a=he(e)(t);return()=>{o(),a()}}}),e.ui.registry.addMenuItem("media",{icon:"embed",text:"Media...",onAction:t,onSetup:he(e)})})(e),(e=>{e.on("ResolveName",(e=>{let t;1===e.target.nodeType&&(t=e.target.getAttribute("data-mce-object"))&&(e.name=t)}))})(e),(e=>{e.on("PreInit",(()=>{const{schema:t,serializer:r,parser:o}=e,a=t.getBoolAttrs();l("webkitallowfullscreen mozallowfullscreen".split(" "),(e=>{a[e]={}})),((e,t)=>{const r=m(e);for(let o=0,a=r.length;o{const o=t.getElementRule(r);o&&l(e,(e=>{o.attributes[e]={},o.attributesOrder.push(e)}))})),o.addNodeFilter("iframe,video,audio,object,embed",(e=>t=>{let r,o=t.length;for(;o--;)r=t[o],r.parent&&(r.parent.attr("data-mce-object")||(ae(r)&&v(e)?ue(r)||r.replace(le(e,r)):ue(r)||r.replace(ne(e,r))))})(e)),r.addAttributeFilter("data-mce-object",((t,r)=>{var o;let a=t.length;for(;a--;){const s=t[a];if(!s.parent)continue;const i=s.attr(r),n=new D(i,1);if("audio"!==i){const e=s.attr("class");e&&-1!==e.indexOf("mce-preview-object")&&s.firstChild?n.attr({width:s.firstChild.attr("width"),height:s.firstChild.attr("height")}):n.attr({width:s.attr("width"),height:s.attr("height")})}n.attr({style:s.attr("style")});const c=null!==(o=s.attributes)&&void 0!==o?o:[];let m=c.length;for(;m--;){const e=c[m].name;0===e.indexOf("data-mce-p-")&&n.attr(e.substr(11),c[m].value)}const u=s.attr("data-mce-html");if(u){const t=de(e,i,unescape(u));l(t.children(),(e=>n.append(e)))}s.replace(n)}}))})),e.on("SetContent",(()=>{const t=e.dom;l(t.select("span.mce-preview-object"),(e=>{0===t.select("span.mce-shim",e).length&&t.add(e,"span",{class:"mce-shim"})}))}))})(e),(e=>{e.on("mousedown",(t=>{const r=e.dom.getParent(t.target,".mce-preview-object");r&&"2"===e.dom.getAttrib(r,"data-mce-selected")&&t.stopImmediatePropagation()})),e.on("click keyup touchend",(()=>{const t=e.selection.getNode();t&&e.dom.hasClass(t,"mce-preview-object")&&e.dom.getAttrib(t,"data-mce-selected")&&t.setAttribute("data-mce-selected","2")})),e.on("ObjectResized",(t=>{const r=t.target;if(r.getAttribute("data-mce-object")){let o=r.getAttribute("data-mce-html");o&&(o=unescape(o),r.setAttribute("data-mce-html",escape(U(o,{width:String(t.width),height:String(t.height)},!1,e.schema))))}}))})(e),(e=>({showDialog:()=>{re(e)}}))(e))))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/nonbreaking/plugin.min.js b/apps/web-antd/public/tinymce/plugins/nonbreaking/plugin.min.js new file mode 100644 index 0000000..048e6d7 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/nonbreaking/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=n=>e=>typeof e===n,o=e("boolean"),a=e("number"),t=n=>e=>e.options.get(n),i=t("nonbreaking_force_tab"),s=t("nonbreaking_wrap"),r=(n,e)=>{let o="";for(let a=0;a{const o=s(n)||n.plugins.visualchars?`${r(" ",e)}`:r(" ",e);n.undoManager.transact((()=>n.insertContent(o)))};var l=tinymce.util.Tools.resolve("tinymce.util.VK");const u=n=>e=>{const o=()=>{e.setEnabled(n.selection.isEditable())};return n.on("NodeChange",o),o(),()=>{n.off("NodeChange",o)}};n.add("nonbreaking",(n=>{(n=>{const e=n.options.register;e("nonbreaking_force_tab",{processor:n=>o(n)?{value:n?3:0,valid:!0}:a(n)?{value:n,valid:!0}:{valid:!1,message:"Must be a boolean or number."},default:!1}),e("nonbreaking_wrap",{processor:"boolean",default:!0})})(n),(n=>{n.addCommand("mceNonBreaking",(()=>{c(n,1)}))})(n),(n=>{const e=()=>n.execCommand("mceNonBreaking");n.ui.registry.addButton("nonbreaking",{icon:"non-breaking",tooltip:"Nonbreaking space",onAction:e,onSetup:u(n)}),n.ui.registry.addMenuItem("nonbreaking",{icon:"non-breaking",text:"Nonbreaking space",onAction:e,onSetup:u(n)})})(n),(n=>{const e=i(n);e>0&&n.on("keydown",(o=>{if(o.keyCode===l.TAB&&!o.isDefaultPrevented()){if(o.shiftKey)return;o.preventDefault(),o.stopImmediatePropagation(),c(n,e)}}))})(n)}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/pagebreak/plugin.min.js b/apps/web-antd/public/tinymce/plugins/pagebreak/plugin.min.js new file mode 100644 index 0000000..b498342 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/pagebreak/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=tinymce.util.Tools.resolve("tinymce.Env");const t=e=>a=>a.options.get(e),n=t("pagebreak_separator"),o=t("pagebreak_split_block"),r="mce-pagebreak",s=e=>{const t=``;return e?`

    ${t}

    `:t},c=e=>a=>{const t=()=>{a.setEnabled(e.selection.isEditable())};return e.on("NodeChange",t),t(),()=>{e.off("NodeChange",t)}};e.add("pagebreak",(e=>{(e=>{const a=e.options.register;a("pagebreak_separator",{processor:"string",default:"\x3c!-- pagebreak --\x3e"}),a("pagebreak_split_block",{processor:"boolean",default:!1})})(e),(e=>{e.addCommand("mcePageBreak",(()=>{e.insertContent(s(o(e)))}))})(e),(e=>{const a=()=>e.execCommand("mcePageBreak");e.ui.registry.addButton("pagebreak",{icon:"page-break",tooltip:"Page break",onAction:a,onSetup:c(e)}),e.ui.registry.addMenuItem("pagebreak",{text:"Page break",icon:"page-break",onAction:a,onSetup:c(e)})})(e),(e=>{const a=n(e),t=()=>o(e),c=new RegExp(a.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,(e=>"\\"+e)),"gi");e.on("BeforeSetContent",(e=>{e.content=e.content.replace(c,s(t()))})),e.on("PreInit",(()=>{e.serializer.addNodeFilter("img",(n=>{let o,s,c=n.length;for(;c--;)if(o=n[c],s=o.attr("class"),s&&-1!==s.indexOf(r)){const n=o.parent;if(n&&e.schema.getBlockElements()[n.name]&&t()){n.type=3,n.value=a,n.raw=!0,o.remove();continue}o.type=3,o.value=a,o.raw=!0}}))}))})(e),(e=>{e.on("ResolveName",(a=>{"IMG"===a.target.nodeName&&e.dom.hasClass(a.target,r)&&(a.name="pagebreak")}))})(e)}))}(); \ No newline at end of file diff --git a/apps/web-antd/public/tinymce/plugins/preview/plugin.min.js b/apps/web-antd/public/tinymce/plugins/preview/plugin.min.js new file mode 100644 index 0000000..41e9891 --- /dev/null +++ b/apps/web-antd/public/tinymce/plugins/preview/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 7.8.0 (TBD) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>undefined===e;class r{constructor(e,t){this.tag=e,this.value=t}static some(e){return new r(!0,e)}static none(){return r.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?r.some(e(this.value)):r.none()}bind(e){return this.tag?e(this.value):r.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:r.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return null==e?r.none():r.some(e)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}r.singletonNone=new r(!1);const n=e=>()=>e,s=n(!1),i=(e,t)=>((e,t,n)=>{for(let s=0,i=e.length;sa(0,0),a=(e,t)=>({major:e,minor:t}),c={nu:a,detect:(e,t)=>{const r=String(t).toLowerCase();return 0===e.length?o():((e,t)=>{const r=((e,t)=>{for(let r=0;rNumber(t.replace(r,"$"+e));return a(n(1),n(2))})(e,r)},unknown:o},u=(e,t)=>{const r=String(t).toLowerCase();return i(e,(e=>e.search(r)))},d=(e,r,n=0,s)=>{const i=e.indexOf(r,n);return-1!==i&&(!!t(s)||i+r.length<=s)},l=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,h=e=>t=>d(t,e),m=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:e=>d(e,"edge/")&&d(e,"chrome")&&d(e,"safari")&&d(e,"applewebkit")},{name:"Chromium",brand:"Chromium",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,l],search:e=>d(e,"chrome")&&!d(e,"chromeframe")},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:e=>d(e,"msie")||d(e,"trident")},{name:"Opera",versionRegexes:[l,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:h("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:h("firefox")},{name:"Safari",versionRegexes:[l,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:e=>(d(e,"safari")||d(e,"mobile/"))&&d(e,"applewebkit")}],v=[{name:"Windows",search:h("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:e=>d(e,"iphone")||d(e,"ipad"),versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:h("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"macOS",search:h("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:h("linux"),versionRegexes:[]},{name:"Solaris",search:h("sunos"),versionRegexes:[]},{name:"FreeBSD",search:h("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:h("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}],g={browsers:n(m),oses:n(v)},p="Edge",w="Chromium",f="Opera",x="Firefox",S="Safari",y=e=>{const t=e.current,r=e.version,n=e=>()=>t===e;return{current:t,version:r,isEdge:n(p),isChromium:n(w),isIE:n("IE"),isOpera:n(f),isFirefox:n(x),isSafari:n(S)}},b=()=>y({current:void 0,version:c.unknown()}),O=y,R=(n(p),n(w),n("IE"),n(f),n(x),n(S),"Windows"),C="Android",A="Linux",k="macOS",D="Solaris",E="FreeBSD",I="ChromeOS",P=e=>{const t=e.current,r=e.version,n=e=>()=>t===e;return{current:t,version:r,isWindows:n(R),isiOS:n("iOS"),isAndroid:n(C),isMacOS:n(k),isLinux:n(A),isSolaris:n(D),isFreeBSD:n(E),isChromeOS:n(I)}},T=()=>P({current:void 0,version:c.unknown()}),_=P,B=(n(R),n("iOS"),n(C),n(A),n(k),n(D),n(E),n(I),(e,t,s)=>{const o=g.browsers(),a=g.oses(),d=t.bind((e=>((e,t)=>((e,t)=>{for(let r=0;r{const r=t.brand.toLowerCase();return i(e,(e=>{var t;return r===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())})).map((e=>({current:e.name,version:c.nu(parseInt(t.version,10),0)})))})))(o,e))).orThunk((()=>((e,t)=>u(e,t).map((e=>{const r=c.detect(e.versionRegexes,t);return{current:e.name,version:r}})))(o,e))).fold(b,O),l=((e,t)=>u(e,t).map((e=>{const r=c.detect(e.versionRegexes,t);return{current:e.name,version:r}})))(a,e).fold(T,_),h=((e,t,r,s)=>{const i=e.isiOS()&&!0===/ipad/i.test(r),o=e.isiOS()&&!i,a=e.isiOS()||e.isAndroid(),c=a||s("(pointer:coarse)"),u=i||!o&&a&&s("(min-device-width:768px)"),d=o||a&&!u,l=t.isSafari()&&e.isiOS()&&!1===/safari/i.test(r),h=!d&&!u&&!l;return{isiPad:n(i),isiPhone:n(o),isTablet:n(u),isPhone:n(d),isTouch:n(c),isAndroid:e.isAndroid,isiOS:e.isiOS,isWebView:n(l),isDesktop:n(h)}})(l,d,e,s);return{browser:d,os:l,deviceType:h}}),L=e=>window.matchMedia(e).matches;let N=(e=>{let t,r=!1;return(...n)=>(r||(r=!0,t=e.apply(null,n)),t)})((()=>B(window.navigator.userAgent,r.from(window.navigator.userAgentData),L)));const F=()=>N();var M=tinymce.util.Tools.resolve("tinymce.util.Tools");const $=e=>t=>t.options.get(e),W=$("content_style"),U=$("content_css_cors"),K=$("body_class"),j=$("body_id"),V=e=>{const t=(e=>{var t;let r="";const n=e.dom.encode,s=null!==(t=W(e))&&void 0!==t?t:"";r+=``;const i=U(e)?' crossorigin="anonymous"':"";M.each(e.contentCSS,(t=>{r+='"})),s&&(r+='");const o=j(e),a=K(e),c=e.getBody().dir,u=c?' dir="'+n(c)+'"':"";return""+r+'"+e.getContent()+(()=>{const e=F().os.isMacOS()||F().os.isiOS();return` + + diff --git a/apps/web-antd/src/assets/imgs/diy/app-nav-bar-mp.png b/apps/web-antd/src/assets/imgs/diy/app-nav-bar-mp.png new file mode 100644 index 0000000..c982804 Binary files /dev/null and b/apps/web-antd/src/assets/imgs/diy/app-nav-bar-mp.png differ diff --git a/apps/web-antd/src/assets/imgs/diy/statusBar.png b/apps/web-antd/src/assets/imgs/diy/statusBar.png new file mode 100644 index 0000000..b85562e Binary files /dev/null and b/apps/web-antd/src/assets/imgs/diy/statusBar.png differ diff --git a/apps/web-antd/src/assets/imgs/wechat.png b/apps/web-antd/src/assets/imgs/wechat.png new file mode 100644 index 0000000..6afc5e4 Binary files /dev/null and b/apps/web-antd/src/assets/imgs/wechat.png differ diff --git a/apps/web-antd/src/bootstrap.ts b/apps/web-antd/src/bootstrap.ts new file mode 100644 index 0000000..be5a5ed --- /dev/null +++ b/apps/web-antd/src/bootstrap.ts @@ -0,0 +1,82 @@ +import { createApp, watchEffect } from 'vue'; +import VueDOMPurifyHTML from 'vue-dompurify-html'; + +import { registerAccessDirective } from '@vben/access'; +import { registerLoadingDirective } from '@vben/common-ui/es/loading'; +import { preferences } from '@vben/preferences'; +import { initStores } from '@vben/stores'; +import '@vben/styles'; +import '@vben/styles/antd'; + +import { useTitle } from '@vueuse/core'; + +import { $t, setupI18n } from '#/locales'; +import { setupFormCreate } from '#/plugins/form-create'; + +import { initComponentAdapter } from './adapter/component'; +import { initSetupVbenForm } from './adapter/form'; +import App from './app.vue'; +import { router } from './router'; + +async function bootstrap(namespace: string) { + // 初始化组件适配器 + await initComponentAdapter(); + + // 初始化表单组件 + await initSetupVbenForm(); + + // // 设置弹窗的默认配置 + // setDefaultModalProps({ + // fullscreenButton: false, + // }); + // // 设置抽屉的默认配置 + // setDefaultDrawerProps({ + // zIndex: 1020, + // }); + + const app = createApp(App); + app.use(VueDOMPurifyHTML); + + // 注册v-loading指令 + registerLoadingDirective(app, { + loading: 'loading', // 在这里可以自定义指令名称,也可以明确提供false表示不注册这个指令 + spinning: 'spinning', + }); + + // 国际化 i18n 配置 + await setupI18n(app); + + // 配置 pinia-store + await initStores(app, { namespace }); + + // 安装权限指令 + registerAccessDirective(app); + + // 初始化 tippy + const { initTippy } = await import('@vben/common-ui/es/tippy'); + initTippy(app); + + // 配置路由及路由守卫 + app.use(router); + + // formCreate + setupFormCreate(app); + + // 配置Motion插件 + const { MotionPlugin } = await import('@vben/plugins/motion'); + app.use(MotionPlugin); + + // 动态更新标题 + watchEffect(() => { + if (preferences.app.dynamicTitle) { + const routeTitle = router.currentRoute.value.meta?.title; + const pageTitle = + (routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name; + useTitle(pageTitle); + } + }); + + app.mount('#app'); +} + +export { bootstrap }; diff --git a/apps/web-antd/src/components/cron-tab/cron-tab.vue b/apps/web-antd/src/components/cron-tab/cron-tab.vue new file mode 100644 index 0000000..242ecb5 --- /dev/null +++ b/apps/web-antd/src/components/cron-tab/cron-tab.vue @@ -0,0 +1,961 @@ + + + + + diff --git a/apps/web-antd/src/components/cron-tab/index.ts b/apps/web-antd/src/components/cron-tab/index.ts new file mode 100644 index 0000000..8f4baae --- /dev/null +++ b/apps/web-antd/src/components/cron-tab/index.ts @@ -0,0 +1 @@ +export { default as CronTab } from './cron-tab.vue'; diff --git a/apps/web-antd/src/components/cron-tab/types.ts b/apps/web-antd/src/components/cron-tab/types.ts new file mode 100644 index 0000000..2adf942 --- /dev/null +++ b/apps/web-antd/src/components/cron-tab/types.ts @@ -0,0 +1,266 @@ +export interface ShortcutsType { + text: string; + value: string; +} + +export interface CronRange { + start: number | string | undefined; + end: number | string | undefined; +} + +export interface CronLoop { + start: number | string | undefined; + end: number | string | undefined; +} + +export interface CronItem { + type: string; + range: CronRange; + loop: CronLoop; + appoint: string[]; + last?: string; +} + +export interface CronValue { + second: CronItem; + minute: CronItem; + hour: CronItem; + day: CronItem; + month: CronItem; + week: CronItem & { last: string }; + year: CronItem; +} + +export interface WeekOption { + value: string; + label: string; +} + +export interface CronData { + second: string[]; + minute: string[]; + hour: string[]; + day: string[]; + month: string[]; + week: WeekOption[]; + year: number[]; +} + +const getYear = (): number[] => { + const v: number[] = []; + const y = new Date().getFullYear(); + for (let i = 0; i < 11; i++) { + v.push(y + i); + } + return v; +}; + +export const CronValueDefault: CronValue = { + second: { + type: '0', + range: { + start: 1, + end: 2, + }, + loop: { + start: 0, + end: 1, + }, + appoint: [], + }, + minute: { + type: '0', + range: { + start: 1, + end: 2, + }, + loop: { + start: 0, + end: 1, + }, + appoint: [], + }, + hour: { + type: '0', + range: { + start: 1, + end: 2, + }, + loop: { + start: 0, + end: 1, + }, + appoint: [], + }, + day: { + type: '0', + range: { + start: 1, + end: 2, + }, + loop: { + start: 1, + end: 1, + }, + appoint: [], + }, + month: { + type: '0', + range: { + start: 1, + end: 2, + }, + loop: { + start: 1, + end: 1, + }, + appoint: [], + }, + week: { + type: '5', + range: { + start: '2', + end: '3', + }, + loop: { + start: 0, + end: '2', + }, + last: '2', + appoint: [], + }, + year: { + type: '-1', + range: { + start: getYear()[0], + end: getYear()[1], + }, + loop: { + start: getYear()[0], + end: 1, + }, + appoint: [], + }, +}; + +export const CronDataDefault: CronData = { + second: [ + '0', + '5', + '15', + '20', + '25', + '30', + '35', + '40', + '45', + '50', + '55', + '59', + ], + minute: [ + '0', + '5', + '15', + '20', + '25', + '30', + '35', + '40', + '45', + '50', + '55', + '59', + ], + hour: [ + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '10', + '11', + '12', + '13', + '14', + '15', + '16', + '17', + '18', + '19', + '20', + '21', + '22', + '23', + ], + day: [ + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '10', + '11', + '12', + '13', + '14', + '15', + '16', + '17', + '18', + '19', + '20', + '21', + '22', + '23', + '24', + '25', + '26', + '27', + '28', + '29', + '30', + '31', + ], + month: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'], + week: [ + { + value: '1', + label: '周日', + }, + { + value: '2', + label: '周一', + }, + { + value: '3', + label: '周二', + }, + { + value: '4', + label: '周三', + }, + { + value: '5', + label: '周四', + }, + { + value: '6', + label: '周五', + }, + { + value: '7', + label: '周六', + }, + ], + year: getYear(), +}; diff --git a/apps/web-antd/src/components/cropper/cropper-avatar.vue b/apps/web-antd/src/components/cropper/cropper-avatar.vue new file mode 100644 index 0000000..72c71d0 --- /dev/null +++ b/apps/web-antd/src/components/cropper/cropper-avatar.vue @@ -0,0 +1,123 @@ + + + diff --git a/apps/web-antd/src/components/cropper/cropper-modal.vue b/apps/web-antd/src/components/cropper/cropper-modal.vue new file mode 100644 index 0000000..01effd7 --- /dev/null +++ b/apps/web-antd/src/components/cropper/cropper-modal.vue @@ -0,0 +1,302 @@ + + + diff --git a/apps/web-antd/src/components/cropper/cropper.vue b/apps/web-antd/src/components/cropper/cropper.vue new file mode 100644 index 0000000..54b2629 --- /dev/null +++ b/apps/web-antd/src/components/cropper/cropper.vue @@ -0,0 +1,176 @@ + + + + + diff --git a/apps/web-antd/src/components/cropper/index.ts b/apps/web-antd/src/components/cropper/index.ts new file mode 100644 index 0000000..43fd89f --- /dev/null +++ b/apps/web-antd/src/components/cropper/index.ts @@ -0,0 +1,3 @@ +export { default as CropperAvatar } from './cropper-avatar.vue'; +export { default as CropperImage } from './cropper.vue'; +export type { CropperType } from './typing'; diff --git a/apps/web-antd/src/components/cropper/typing.ts b/apps/web-antd/src/components/cropper/typing.ts new file mode 100644 index 0000000..f471274 --- /dev/null +++ b/apps/web-antd/src/components/cropper/typing.ts @@ -0,0 +1,68 @@ +import type { ButtonProps } from 'ant-design-vue'; +import type Cropper from 'cropperjs'; + +import type { CSSProperties } from 'vue'; + +export interface apiFunParams { + file: Blob; + filename: string; + name: string; +} + +export interface CropendResult { + imgBase64: string; + imgInfo: Cropper.Data; +} + +export interface CropperProps { + src?: string; + alt?: string; + circled?: boolean; + realTimePreview?: boolean; + height?: number | string; + crossorigin?: '' | 'anonymous' | 'use-credentials' | undefined; + imageStyle?: CSSProperties; + options?: Cropper.Options; +} + +export interface CropperAvatarProps { + width?: number | string; + value?: string; + showBtn?: boolean; + btnProps?: ButtonProps; + btnText?: string; + uploadApi?: (params: apiFunParams) => Promise; + size?: number; +} + +export interface CropperModalProps { + circled?: boolean; + uploadApi?: (params: apiFunParams) => Promise; + src?: string; + size?: number; +} + +export const defaultOptions: Cropper.Options = { + aspectRatio: 1, + zoomable: true, + zoomOnTouch: true, + zoomOnWheel: true, + cropBoxMovable: true, + cropBoxResizable: true, + toggleDragModeOnDblclick: true, + autoCrop: true, + background: true, + highlight: true, + center: true, + responsive: true, + restore: true, + checkCrossOrigin: true, + checkOrientation: true, + scalable: true, + modal: true, + guides: true, + movable: true, + rotatable: true, +}; + +export type { Cropper as CropperType }; diff --git a/apps/web-antd/src/components/description/description.vue b/apps/web-antd/src/components/description/description.vue new file mode 100644 index 0000000..d591e57 --- /dev/null +++ b/apps/web-antd/src/components/description/description.vue @@ -0,0 +1,195 @@ + diff --git a/apps/web-antd/src/components/description/index.ts b/apps/web-antd/src/components/description/index.ts new file mode 100644 index 0000000..a707c48 --- /dev/null +++ b/apps/web-antd/src/components/description/index.ts @@ -0,0 +1,3 @@ +export { default as Description } from './description.vue'; +export * from './typing'; +export { useDescription } from './use-description'; diff --git a/apps/web-antd/src/components/description/typing.ts b/apps/web-antd/src/components/description/typing.ts new file mode 100644 index 0000000..97cd8ca --- /dev/null +++ b/apps/web-antd/src/components/description/typing.ts @@ -0,0 +1,43 @@ +import type { DescriptionsProps } from 'ant-design-vue/es/descriptions'; +import type { JSX } from 'vue/jsx-runtime'; + +import type { CSSProperties, VNode } from 'vue'; + +import type { Recordable } from '@vben/types'; + +export interface DescriptionItemSchema { + labelMinWidth?: number; + contentMinWidth?: number; + labelStyle?: CSSProperties; // 自定义标签样式 + field: string; // 对应 data 中的字段名 + label: JSX.Element | string | VNode; // 内容的描述 + span?: number; // 包含列的数量 + show?: (...arg: any) => boolean; // 是否显示 + slot?: string; // 插槽名称 + render?: ( + val: any, + data?: Recordable, + ) => Element | JSX.Element | number | string | undefined | VNode; // 自定义需要展示的内容 +} + +export interface DescriptionProps extends DescriptionsProps { + useCard?: boolean; // 是否包含卡片组件 + schema: DescriptionItemSchema[]; // 描述项配置 + data: Recordable; // 数据 + title?: string; // 标题 + bordered?: boolean; // 是否包含边框 + column?: + | number + | { + lg: number; + md: number; + sm: number; + xl: number; + xs: number; + xxl: number; + }; // 列数 +} + +export interface DescInstance { + setDescProps(descProps: Partial): void; +} diff --git a/apps/web-antd/src/components/description/use-description.ts b/apps/web-antd/src/components/description/use-description.ts new file mode 100644 index 0000000..fd24920 --- /dev/null +++ b/apps/web-antd/src/components/description/use-description.ts @@ -0,0 +1,31 @@ +import type { Component } from 'vue'; + +import type { DescInstance, DescriptionProps } from './typing'; + +import { h, reactive } from 'vue'; + +import Description from './description.vue'; + +export function useDescription(options?: Partial) { + const propsState = reactive>(options || {}); + + const api: DescInstance = { + setDescProps: (descProps: Partial): void => { + Object.assign(propsState, descProps); + }, + }; + + // 创建一个包装组件,将 propsState 合并到 props 中 + const DescriptionWrapper: Component = { + name: 'UseDescription', + inheritAttrs: false, + setup(_props, { attrs, slots }) { + return () => { + // @ts-ignore - 避免类型实例化过深 + return h(Description, { ...propsState, ...attrs }, slots); + }; + }, + }; + + return [DescriptionWrapper, api] as const; +} diff --git a/apps/web-antd/src/components/dict-tag/dict-tag.vue b/apps/web-antd/src/components/dict-tag/dict-tag.vue new file mode 100644 index 0000000..14cc34d --- /dev/null +++ b/apps/web-antd/src/components/dict-tag/dict-tag.vue @@ -0,0 +1,71 @@ + + + diff --git a/apps/web-antd/src/components/dict-tag/index.ts b/apps/web-antd/src/components/dict-tag/index.ts new file mode 100644 index 0000000..881265a --- /dev/null +++ b/apps/web-antd/src/components/dict-tag/index.ts @@ -0,0 +1 @@ +export { default as DictTag } from './dict-tag.vue'; diff --git a/apps/web-antd/src/components/form-create/components/area-select.vue b/apps/web-antd/src/components/form-create/components/area-select.vue new file mode 100644 index 0000000..9a025ed --- /dev/null +++ b/apps/web-antd/src/components/form-create/components/area-select.vue @@ -0,0 +1,153 @@ + + + + diff --git a/apps/web-antd/src/components/form-create/components/dept-select.vue b/apps/web-antd/src/components/form-create/components/dept-select.vue new file mode 100644 index 0000000..98fa254 --- /dev/null +++ b/apps/web-antd/src/components/form-create/components/dept-select.vue @@ -0,0 +1,205 @@ + + + + diff --git a/apps/web-antd/src/components/form-create/components/dict-select.vue b/apps/web-antd/src/components/form-create/components/dict-select.vue new file mode 100644 index 0000000..03a5274 --- /dev/null +++ b/apps/web-antd/src/components/form-create/components/dict-select.vue @@ -0,0 +1,74 @@ + + + + diff --git a/apps/web-antd/src/components/form-create/components/iframe.vue b/apps/web-antd/src/components/form-create/components/iframe.vue new file mode 100644 index 0000000..ef6234c --- /dev/null +++ b/apps/web-antd/src/components/form-create/components/iframe.vue @@ -0,0 +1,94 @@ + + + + + + diff --git a/apps/web-antd/src/components/form-create/components/use-api-select.tsx b/apps/web-antd/src/components/form-create/components/use-api-select.tsx new file mode 100644 index 0000000..dba12f3 --- /dev/null +++ b/apps/web-antd/src/components/form-create/components/use-api-select.tsx @@ -0,0 +1,373 @@ +import type { ApiSelectProps } from '#/components/form-create/typing'; + +import { defineComponent, onMounted, ref, useAttrs } from 'vue'; + +import { useUserStore } from '@vben/stores'; +import { isEmpty } from '@vben/utils'; + +import { + Checkbox, + CheckboxGroup, + Radio, + RadioGroup, + Select, + SelectOption, +} from 'ant-design-vue'; + +import { requestClient } from '#/api/request'; + +export function useApiSelect(option: ApiSelectProps) { + return defineComponent({ + name: option.name, + props: { + // 选项标签 + labelField: { + type: String, + default: () => option.labelField ?? 'label', + }, + // 选项的值 + valueField: { + type: String, + default: () => option.valueField ?? 'value', + }, + // api 接口 + url: { + type: String, + default: () => option.url ?? '', + }, + // 请求类型 + method: { + type: String, + default: 'GET', + }, + // 选项解析函数 + parseFunc: { + type: String, + default: '', + }, + // 请求参数 + data: { + type: String, + default: '', + }, + // 选择器类型,下拉框 select、多选框 checkbox、单选框 radio + selectType: { + type: String, + default: 'select', + }, + // 是否多选 + multiple: { + type: Boolean, + default: false, + }, + // 是否远程搜索 + remote: { + type: Boolean, + default: false, + }, + // 远程搜索时携带的参数 + remoteField: { + type: String, + default: 'label', + }, + // 返回值类型(用于部门选择器等):id 返回 ID,name 返回名称 + returnType: { + type: String, + default: 'id', + }, + // 是否默认选中当前用户(仅用于 UserSelect) + defaultCurrentUser: { + type: Boolean, + default: false, + }, + }, + setup(props, { emit }) { + const attrs = useAttrs(); + const options = ref([]); // 下拉数据 + const loading = ref(false); // 是否正在从远程获取数据 + const queryParam = ref(); // 当前输入的值 + + // 检查是否有有效的预设值 + function hasValidPresetValue(): boolean { + const value = attrs.modelValue; + if (value === undefined || value === null || value === '') { + return false; + } + if (Array.isArray(value)) { + return value.length > 0; + } + return true; + } + + // 设置默认当前用户 + function setDefaultCurrentUser(): void { + if (option.name !== 'UserSelect' || !props.defaultCurrentUser) { + return; + } + if (hasValidPresetValue()) { + return; + } + const userStore = useUserStore(); + const currentUserId = userStore.userInfo?.id; + if (currentUserId) { + const defaultValue = props.multiple ? [currentUserId] : currentUserId; + emit('update:modelValue', defaultValue); + } + } + + const getOptions = async () => { + options.value = []; + // 接口选择器 + if (isEmpty(props.url)) { + return; + } + + switch (props.method) { + case 'GET': { + let url: string = props.url; + if (props.remote && queryParam.value !== undefined) { + url = url.includes('?') + ? `${url}&${props.remoteField}=${queryParam.value}` + : `${url}?${props.remoteField}=${queryParam.value}`; + } + parseOptions(await requestClient.get(url)); + break; + } + case 'POST': { + const data: any = JSON.parse(props.data); + if (props.remote) { + data[props.remoteField] = queryParam.value; + } + parseOptions(await requestClient.post(props.url, data)); + break; + } + } + }; + + function parseOptions(data: any) { + // 情况一:如果有自定义解析函数优先使用自定义解析 + if (!isEmpty(props.parseFunc)) { + options.value = parseFunc()?.(data); + return; + } + // 情况二:返回的直接是一个列表 + if (Array.isArray(data)) { + parseOptions0(data); + return; + } + // 情况二:返回的是分页数据,尝试读取 list + data = data.list; + if (!!data && Array.isArray(data)) { + parseOptions0(data); + return; + } + // 情况三:不是 yudao-vue-pro 标准返回 + console.warn( + `接口[${props.url}] 返回结果不是 yudao-vue-pro 标准返回建议采用自定义解析函数处理`, + ); + } + + function parseOptions0(data: any[]) { + if (Array.isArray(data)) { + options.value = data.map((item: any) => { + const label = parseExpression(item, props.labelField); + let value = parseExpression(item, props.valueField); + + // 根据 returnType 决定返回值 + // 如果设置了 returnType 为 'name',则返回 label 作为 value + if (props.returnType === 'name') { + value = label; + } + + return { + label, + value, + }; + }); + return; + } + console.warn(`接口[${props.url}] 返回结果不是一个数组`); + } + + function parseFunc() { + let parse: any = null; + if (props.parseFunc) { + // 解析字符串函数 + // eslint-disable-next-line no-new-func + parse = new Function(`return ${props.parseFunc}`)(); + } + return parse; + } + + function parseExpression(data: any, template: string) { + // 检测是否使用了表达式 + if (!template.includes('${')) { + return data[template]; + } + // 正则表达式匹配模板字符串中的 ${...} + const pattern = /\$\{([^}]*)\}/g; + // 使用replace函数配合正则表达式和回调函数来进行替换 + return template.replaceAll(pattern, (_, expr) => { + // expr 是匹配到的 ${} 内的表达式(这里是属性名),从 data 中获取对应的值 + const result = data[expr.trim()]; // 去除前后空白,以防用户输入带空格的属性名 + if (!result) { + console.warn( + `接口选择器选项模版[${template}][${expr.trim()}] 解析值失败结果为[${result}], 请检查属性名称是否存在于接口返回值中,存在则忽略此条!!!`, + ); + } + return result; + }); + } + + const remoteMethod = async (query: any) => { + if (!query) { + return; + } + loading.value = true; + try { + queryParam.value = query; + await getOptions(); + } finally { + loading.value = false; + } + }; + + onMounted(async () => { + await getOptions(); + // 设置默认当前用户(仅用于 UserSelect) + setDefaultCurrentUser(); + }); + + const buildSelect = () => { + const { + modelValue, + 'onUpdate:modelValue': onUpdateModelValue, + ...restAttrs + } = attrs; + + if (props.multiple) { + // fix:多写此步是为了解决 multiple 属性问题 + return ( + + ); + } + return ( + + ); + }; + const buildCheckbox = () => { + const { + modelValue, + 'onUpdate:modelValue': onUpdateModelValue, + ...restAttrs + } = attrs; + if (isEmpty(options.value)) { + options.value = [ + { label: '选项1', value: '选项1' }, + { label: '选项2', value: '选项2' }, + ]; + } + return ( + + {options.value.map( + (item: { label: any; value: any }, index: any) => ( + + {item.label} + + ), + )} + + ); + }; + const buildRadio = () => { + const { + modelValue, + 'onUpdate:modelValue': onUpdateModelValue, + ...restAttrs + } = attrs; + if (isEmpty(options.value)) { + options.value = [ + { label: '选项1', value: '选项1' }, + { label: '选项2', value: '选项2' }, + ]; + } + return ( + + {options.value.map( + (item: { label: any; value: any }, index: any) => ( + + {item.label} + + ), + )} + + ); + }; + return () => ( + <> + {(() => { + switch (props.selectType) { + case 'checkbox': { + return buildCheckbox(); + } + case 'radio': { + return buildRadio(); + } + case 'select': { + return buildSelect(); + } + default: { + return buildSelect(); + } + } + })()} + + ); + }, + }); +} diff --git a/apps/web-antd/src/components/form-create/components/use-images-upload.tsx b/apps/web-antd/src/components/form-create/components/use-images-upload.tsx new file mode 100644 index 0000000..a57cbaa --- /dev/null +++ b/apps/web-antd/src/components/form-create/components/use-images-upload.tsx @@ -0,0 +1,24 @@ +import { defineComponent } from 'vue'; + +import ImageUpload from '#/components/upload/image-upload.vue'; + +export function useImagesUpload() { + return defineComponent({ + name: 'ImagesUpload', + props: { + multiple: { + type: Boolean, + default: true, + }, + maxNumber: { + type: Number, + default: 5, + }, + }, + setup(props) { + return () => ( + + ); + }, + }); +} diff --git a/apps/web-antd/src/components/form-create/helpers.ts b/apps/web-antd/src/components/form-create/helpers.ts new file mode 100644 index 0000000..af08c66 --- /dev/null +++ b/apps/web-antd/src/components/form-create/helpers.ts @@ -0,0 +1,273 @@ +import type { Rule } from '@form-create/ant-design-vue'; + +import type { Ref } from 'vue'; + +import type { Menu } from '#/components/form-create/typing'; + +import { isRef, nextTick, onMounted } from 'vue'; + +import formCreate from '@form-create/ant-design-vue'; + +import { apiSelectRule } from '#/components/form-create/rules/data'; + +import { + useDictSelectRule, + useEditorRule, + useSelectRule, + useUploadFileRule, + useUploadImageRule, + useUploadImagesRule, + useIframeRule, + useAreaSelectRule, +} from './rules'; + +/** 编码表单 Conf */ +export function encodeConf(designerRef: any) { + // 关联案例:https://gitee.com/yudaocode/yudao-ui-admin-vue3/pulls/834/ + return formCreate.toJson(designerRef.value.getOption()); +} + +/** 解码表单 Conf */ +export function decodeConf(conf: string) { + return formCreate.parseJson(conf); +} + +/** 编码表单 Fields */ +export function encodeFields(designerRef: any) { + const rule = designerRef.value.getRule(); + const fields: string[] = []; + rule.forEach((item: any) => { + fields.push(formCreate.toJson(item)); + }); + return fields; +} + +/** 解码表单 Fields */ +export function decodeFields(fields: string[]) { + const rule: Rule[] = []; + fields.forEach((item) => { + rule.push(formCreate.parseJson(item)); + }); + return rule; +} + +/** 设置表单的 Conf 和 Fields,适用 FcDesigner 场景 */ +export function setConfAndFields( + designerRef: any, + conf: string, + fields: string | string[], +) { + designerRef.value.setOption(decodeConf(conf)); + // 处理 fields 参数类型,确保传入 decodeFields 的是 string[] 类型 + const fieldsArray = Array.isArray(fields) ? fields : [fields]; + designerRef.value.setRule(decodeFields(fieldsArray)); +} + +/** 设置表单的 Conf 和 Fields,适用 form-create 场景 */ +export function setConfAndFields2( + detailPreview: any, + conf: string, + fields: string[], + value?: any, +) { + if (isRef(detailPreview)) { + detailPreview = detailPreview.value; + } + detailPreview.option = decodeConf(conf); + detailPreview.rule = decodeFields(fields); + if (value) { + detailPreview.value = value; + } +} + +export function makeRequiredRule() { + return { + type: 'Required', + field: 'formCreate$required', + title: '是否必填', + }; +} + +export function localeProps( + t: (msg: string) => any, + prefix: string, + rules: any[], +) { + return rules.map((rule: { field: string; title: any }) => { + if (rule.field === 'formCreate$required') { + rule.title = t('props.required') || rule.title; + } else if (rule.field && rule.field !== '_optionType') { + rule.title = t(`components.${prefix}.${rule.field}`) || rule.title; + } + return rule; + }); +} + +/** + * 解析表单组件的 field, title 等字段(递归,如果组件包含子组件) + * + * @param rule 组件的生成规则 https://www.form-create.com/v3/guide/rule + * @param fields 解析后表单组件字段 + * @param parentTitle 如果是子表单,子表单的标题,默认为空 + */ +export function parseFormFields( + rule: Record, + fields: Array> = [], + parentTitle: string = '', +) { + const { type, field, $required, title: tempTitle, children } = rule; + if (field && tempTitle) { + let title = tempTitle; + if (parentTitle) { + title = `${parentTitle}.${tempTitle}`; + } + let required = false; + if ($required) { + required = true; + } + fields.push({ + field, + title, + type, + required, + }); + // TODO 子表单 需要处理子表单字段 + // if (type === 'group' && rule.props?.rule && Array.isArray(rule.props.rule)) { + // // 解析子表单的字段 + // rule.props.rule.forEach((item) => { + // parseFields(item, fieldsPermission, title) + // }) + // } + } + if (children && Array.isArray(children)) { + children.forEach((rule) => { + parseFormFields(rule, fields); + }); + } +} + +/** + * 表单设计器增强 hook + * 新增 + * - 文件上传 + * - 单图上传 + * - 多图上传 + * - 字典选择器 + * - 用户选择器 + * - 部门选择器 + * - 富文本 + */ +export async function useFormCreateDesigner(designer: Ref) { + const editorRule = useEditorRule(); + const uploadFileRule = useUploadFileRule(); + const uploadImageRule = useUploadImageRule(); + const uploadImagesRule = useUploadImagesRule(); + const iframeRule = useIframeRule(); + const areaSelectRule = useAreaSelectRule(); + + /** 构建表单组件 */ + function buildFormComponents() { + // 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代 + designer.value?.removeMenuItem('upload'); + // 移除自带的富文本组件规则,使用 editorRule 替代 + designer.value?.removeMenuItem('fc-editor'); + const components = [ + editorRule, + uploadFileRule, + uploadImageRule, + uploadImagesRule, + iframeRule, + areaSelectRule, + ]; + components.forEach((component) => { + // 插入组件规则 + designer.value?.addComponent(component); + // 插入拖拽按钮到 `main` 分类下 + designer.value?.appendMenuItem('main', { + icon: component.icon, + name: component.name, + label: component.label, + }); + }); + } + + const userSelectRule = useSelectRule({ + name: 'UserSelect', + label: '用户选择器', + icon: 'icon-eye', + props: [ + { + type: 'switch', + field: 'defaultCurrentUser', + title: '默认选中当前用户', + value: false, + }, + ], + }); + const deptSelectRule = useSelectRule({ + name: 'DeptSelect', + label: '部门选择器', + icon: 'icon-tree', + props: [ + { + type: 'select', + field: 'returnType', + title: '返回值类型', + value: 'id', + options: [ + { label: '部门编号', value: 'id' }, + { label: '部门名称', value: 'name' }, + ], + }, + { + type: 'switch', + field: 'defaultCurrentDept', + title: '默认选中当前部门', + value: false, + }, + ], + }); + const dictSelectRule = useDictSelectRule(); + const apiSelectRule0 = useSelectRule({ + name: 'ApiSelect', + label: '接口选择器', + icon: 'icon-json', + props: [...apiSelectRule], + event: ['click', 'change', 'visibleChange', 'clear', 'blur', 'focus'], + }); + + /** 构建系统字段菜单 */ + function buildSystemMenu() { + // 移除自带的下拉选择器组件,使用 currencySelectRule 替代 + // designer.value?.removeMenuItem('select') + // designer.value?.removeMenuItem('radio') + // designer.value?.removeMenuItem('checkbox') + const components = [ + userSelectRule, + deptSelectRule, + dictSelectRule, + apiSelectRule0, + ]; + const menu: Menu = { + name: 'system', + title: '系统字段', + list: components.map((component) => { + // 插入组件规则 + designer.value?.addComponent(component); + // 插入拖拽按钮到 `system` 分类下 + return { + icon: component.icon, + name: component.name, + label: component.label, + }; + }), + }; + designer.value?.addMenu(menu); + } + + onMounted(async () => { + await nextTick(); + buildFormComponents(); + buildSystemMenu(); + }); +} diff --git a/apps/web-antd/src/components/form-create/index.ts b/apps/web-antd/src/components/form-create/index.ts new file mode 100644 index 0000000..2c51215 --- /dev/null +++ b/apps/web-antd/src/components/form-create/index.ts @@ -0,0 +1,3 @@ +export { useApiSelect } from './components/use-api-select'; + +export * from './helpers'; diff --git a/apps/web-antd/src/components/form-create/rules/data.ts b/apps/web-antd/src/components/form-create/rules/data.ts new file mode 100644 index 0000000..edef445 --- /dev/null +++ b/apps/web-antd/src/components/form-create/rules/data.ts @@ -0,0 +1,182 @@ +/* eslint-disable no-template-curly-in-string */ +const selectRule = [ + { + type: 'select', + field: 'selectType', + title: '选择器类型', + value: 'select', + options: [ + { label: '下拉框', value: 'select' }, + { label: '单选框', value: 'radio' }, + { label: '多选框', value: 'checkbox' }, + ], + // 参考 https://www.form-create.com/v3/guide/control 组件联动,单选框和多选框不需要多选属性 + control: [ + { + value: 'select', + condition: '==', + method: 'hidden', + rule: [ + 'multiple', + 'clearable', + 'collapseTags', + 'multipleLimit', + 'allowCreate', + 'filterable', + 'noMatchText', + 'remote', + 'remoteMethod', + 'reserveKeyword', + 'defaultFirstOption', + 'automaticDropdown', + ], + }, + ], + }, + { + type: 'switch', + field: 'filterable', + title: '是否可搜索', + }, + { type: 'switch', field: 'multiple', title: '是否多选' }, + { + type: 'switch', + field: 'disabled', + title: '是否禁用', + }, + { type: 'switch', field: 'clearable', title: '是否可以清空选项' }, + { + type: 'switch', + field: 'collapseTags', + title: '多选时是否将选中值按文字的形式展示', + }, + { + type: 'inputNumber', + field: 'multipleLimit', + title: '多选时用户最多可以选择的项目数,为 0 则不限制', + props: { min: 0 }, + }, + { + type: 'input', + field: 'autocomplete', + title: 'autocomplete 属性', + }, + { type: 'input', field: 'placeholder', title: '占位符' }, + { type: 'switch', field: 'allowCreate', title: '是否允许用户创建新条目' }, + { + type: 'input', + field: 'noMatchText', + title: '搜索条件无匹配时显示的文字', + }, + { type: 'input', field: 'noDataText', title: '选项为空时显示的文字' }, + { + type: 'switch', + field: 'reserveKeyword', + title: '多选且可搜索时,是否在选中一个选项后保留当前的搜索关键词', + }, + { + type: 'switch', + field: 'defaultFirstOption', + title: '在输入框按下回车,选择第一个匹配项', + }, + { + type: 'switch', + field: 'popperAppendToBody', + title: '是否将弹出框插入至 body 元素', + value: true, + }, + { + type: 'switch', + field: 'automaticDropdown', + title: '对于不可搜索的 Select,是否在输入框获得焦点后自动弹出选项菜单', + }, +]; + +const apiSelectRule = [ + { + type: 'input', + field: 'url', + title: 'url 地址', + props: { + placeholder: '/system/user/simple-list', + }, + }, + { + type: 'select', + field: 'method', + title: '请求类型', + value: 'GET', + options: [ + { label: 'GET', value: 'GET' }, + { label: 'POST', value: 'POST' }, + ], + control: [ + { + value: 'GET', + condition: '!=', + method: 'hidden', + rule: [ + { + type: 'input', + field: 'data', + title: '请求参数 JSON 格式', + props: { + autoSize: true, // 特殊:ele 里是 autosize,antd 里是 autoSize + type: 'textarea', + placeholder: '{"type": 1}', + }, + }, + ], + }, + ], + }, + { + type: 'input', + field: 'labelField', + title: 'label 属性', + info: '可以使用 el 表达式:${属性},来实现复杂数据组合。如:${nickname}-${id}', + props: { + placeholder: 'nickname', + }, + }, + { + type: 'input', + field: 'valueField', + title: 'value 属性', + info: '可以使用 el 表达式:${属性},来实现复杂数据组合。如:${nickname}-${id}', + props: { + placeholder: 'id', + }, + }, + { + type: 'input', + field: 'parseFunc', + title: '选项解析函数', + info: `data 为接口返回值,需要写一个匿名函数解析返回值为选择器 options 列表 + (data: any)=>{ label: string; value: any }[]`, + props: { + autoSize: true, // 特殊:ele 里是 autosize,antd 里是 autoSize + rows: { minRows: 2, maxRows: 6 }, + type: 'textarea', + placeholder: ` + function (data) { + console.log(data) + return data.list.map(item=> ({label: item.nickname,value: item.id})) + }`, + }, + }, + { + type: 'switch', + field: 'remote', + info: '是否可搜索', + title: '其中的选项是否从服务器远程加载', + }, + { + type: 'input', + field: 'remoteField', + title: '请求参数', + info: '远程请求时请求携带的参数名称,如:name', + }, +]; + +export { apiSelectRule, selectRule }; diff --git a/apps/web-antd/src/components/form-create/rules/index.ts b/apps/web-antd/src/components/form-create/rules/index.ts new file mode 100644 index 0000000..dc3391f --- /dev/null +++ b/apps/web-antd/src/components/form-create/rules/index.ts @@ -0,0 +1,8 @@ +export { useAreaSelectRule } from './use-area-select-rule'; +export { useDictSelectRule } from './use-dict-select'; +export { useEditorRule } from './use-editor-rule'; +export { useIframeRule } from './use-iframe-rule'; +export { useSelectRule } from './use-select-rule'; +export { useUploadFileRule } from './use-upload-file-rule'; +export { useUploadImageRule } from './use-upload-image-rule'; +export { useUploadImagesRule } from './use-upload-images-rule'; diff --git a/apps/web-antd/src/components/form-create/rules/use-area-select-rule.ts b/apps/web-antd/src/components/form-create/rules/use-area-select-rule.ts new file mode 100644 index 0000000..f42e082 --- /dev/null +++ b/apps/web-antd/src/components/form-create/rules/use-area-select-rule.ts @@ -0,0 +1,76 @@ +import { + localeProps, + makeRequiredRule, +} from '#/components/form-create/helpers'; +import { AreaLevelEnum } from '@vben/constants'; + +/** 省市区选择器规则 */ +export function useAreaSelectRule() { + const label = '省市区选择器'; + const name = 'AreaSelect'; + + return { + icon: 'icon-location', + label, + name, + rule() { + return { + type: name, + field: `area_${Date.now()}`, + title: label, + info: '', + $required: false, + modelField: 'value', // 特殊:ele 里是 model-value,antd 里是 value + }; + }, + props(_: any, { t }: any) { + return localeProps(t, `${name}.props`, [ + makeRequiredRule(), + { + type: 'select', + field: 'level', + title: '选择层级', + value: AreaLevelEnum.DISTRICT, + options: [ + { label: '省', value: AreaLevelEnum.PROVINCE }, + { label: '省/市', value: AreaLevelEnum.CITY }, + { label: '省/市/区', value: AreaLevelEnum.DISTRICT }, + ], + info: '限制可选择的地区层级', + }, + { + type: 'input', + field: 'placeholder', + title: '占位符', + value: '请选择省市区', + }, + { + type: 'switch', + field: 'clearable', + title: '是否可清空', + value: true, + }, + { + type: 'switch', + field: 'showAllLevels', + title: '显示完整路径', + value: true, + info: '输入框中是否显示选中值的完整路径', + }, + { + type: 'input', + field: 'separator', + title: '分隔符', + value: '/', + info: '选项分隔符', + }, + { + type: 'switch', + field: 'disabled', + title: '是否禁用', + value: false, + }, + ]); + }, + }; +} diff --git a/apps/web-antd/src/components/form-create/rules/use-dict-select.ts b/apps/web-antd/src/components/form-create/rules/use-dict-select.ts new file mode 100644 index 0000000..08171a2 --- /dev/null +++ b/apps/web-antd/src/components/form-create/rules/use-dict-select.ts @@ -0,0 +1,70 @@ +import type { SystemDictTypeApi } from '#/api/system/dict/type'; + +import { onMounted, ref } from 'vue'; + +import { buildUUID, cloneDeep } from '@vben/utils'; + +import { getSimpleDictTypeList } from '#/api/system/dict/type'; +import { + localeProps, + makeRequiredRule, +} from '#/components/form-create/helpers'; +import { selectRule } from '#/components/form-create/rules/data'; + +/** 字典选择器规则,如果规则使用到动态数据则需要单独配置不能使用 useSelectRule */ +export function useDictSelectRule() { + const label = '字典选择器'; + const name = 'DictSelect'; + const rules = cloneDeep(selectRule); + const dictOptions = ref<{ label: string; value: string }[]>([]); // 字典类型下拉数据 + onMounted(async () => { + const data = await getSimpleDictTypeList(); + if (!data || data.length === 0) { + return; + } + dictOptions.value = + data?.map((item: SystemDictTypeApi.DictType) => ({ + label: item.name, + value: item.type, + })) ?? []; + }); + return { + icon: 'icon-descriptions', + label, + name, + rule() { + return { + type: name, + field: buildUUID(), + title: label, + info: '', + $required: false, + modelField: 'value', // 特殊:ele 里是 model-value,antd 里是 value + }; + }, + props(_: any, { t }: any) { + return localeProps(t, `${name}.props`, [ + makeRequiredRule(), + { + type: 'select', + field: 'dictType', + title: '字典类型', + value: '', + options: dictOptions.value, + }, + { + type: 'select', + field: 'valueType', + title: '字典值类型', + value: 'str', + options: [ + { label: '数字', value: 'int' }, + { label: '字符串', value: 'str' }, + { label: '布尔值', value: 'bool' }, + ], + }, + ...rules, + ]); + }, + }; +} diff --git a/apps/web-antd/src/components/form-create/rules/use-editor-rule.ts b/apps/web-antd/src/components/form-create/rules/use-editor-rule.ts new file mode 100644 index 0000000..dcde682 --- /dev/null +++ b/apps/web-antd/src/components/form-create/rules/use-editor-rule.ts @@ -0,0 +1,36 @@ +import { buildUUID } from '@vben/utils'; + +import { + localeProps, + makeRequiredRule, +} from '#/components/form-create/helpers'; + +export function useEditorRule() { + const label = '富文本'; + const name = 'Tinymce'; + return { + icon: 'icon-editor', + label, + name, + rule() { + return { + type: name, + field: buildUUID(), + title: label, + info: '', + $required: false, + }; + }, + props(_: any, { t }: any) { + return localeProps(t, `${name}.props`, [ + makeRequiredRule(), + { + type: 'input', + field: 'height', + title: '高度', + }, + { type: 'switch', field: 'readonly', title: '是否只读' }, + ]); + }, + }; +} diff --git a/apps/web-antd/src/components/form-create/rules/use-iframe-rule.ts b/apps/web-antd/src/components/form-create/rules/use-iframe-rule.ts new file mode 100644 index 0000000..39d26d7 --- /dev/null +++ b/apps/web-antd/src/components/form-create/rules/use-iframe-rule.ts @@ -0,0 +1,77 @@ +import { buildUUID } from '@vben/utils'; + +import { + localeProps, + makeRequiredRule, +} from '#/components/form-create/helpers'; + +/** iframe 组件规则 */ +export function useIframeRule() { + const label = '网页 iframe'; + const name = 'IframeComponent'; + + return { + icon: 'icon-link', + label, + name, + rule() { + return { + type: name, + field: buildUUID(), + title: label, + info: '', + $required: false, + modelField: 'value', // 特殊:ele 里是 model-value,antd 里是 value + }; + }, + props(_: any, { t }: any) { + return localeProps(t, `${name}.props`, [ + makeRequiredRule(), + { + type: 'input', + field: 'url', + title: 'URL 地址', + value: '', + info: '请输入完整的 HTTP 或 HTTPS 地址', + }, + { + type: 'input', + field: 'height', + title: 'iframe 高度', + value: '500px', + info: '支持 px、%、vh 等单位', + }, + { + type: 'input', + field: 'width', + title: 'iframe 宽度', + value: '100%', + info: '支持 px、%、vw 等单位', + }, + { + type: 'select', + field: 'loading', + title: '加载方式', + value: 'lazy', + options: [ + { label: '懒加载', value: 'lazy' }, + { label: '立即加载', value: 'eager' }, + ], + }, + { + type: 'switch', + field: 'allowfullscreen', + title: '允许全屏', + value: true, + }, + { + type: 'input', + field: 'sandbox', + title: 'sandbox 属性', + value: '', + info: '安全沙箱限制,如:allow-scripts allow-same-origin', + }, + ]); + }, + }; +} diff --git a/apps/web-antd/src/components/form-create/rules/use-select-rule.ts b/apps/web-antd/src/components/form-create/rules/use-select-rule.ts new file mode 100644 index 0000000..fc89b9a --- /dev/null +++ b/apps/web-antd/src/components/form-create/rules/use-select-rule.ts @@ -0,0 +1,56 @@ +import type { SelectRuleOption } from '#/components/form-create/typing'; + +import { buildUUID, cloneDeep } from '@vben/utils'; + +import { + localeProps, + makeRequiredRule, +} from '#/components/form-create/helpers'; +import { selectRule } from '#/components/form-create/rules/data'; + +/** + * 通用选择器规则 hook + * + * @param option 规则配置 + */ +export function useSelectRule(option: SelectRuleOption) { + const label = option.label; + const name = option.name; + const rules = cloneDeep(selectRule); + return { + icon: option.icon, + label, + name, + event: option.event, + rule() { + // 构建基础规则 + const baseRule: any = { + type: name, + field: buildUUID(), + title: label, + info: '', + $required: false, + }; + // 将自定义 props 的默认值添加到 rule 的 props 中 + if (option.props && option.props.length > 0) { + baseRule.props = {}; + option.props.forEach((prop: any) => { + if (prop.field && prop.value !== undefined) { + baseRule.props[prop.field] = prop.value; + } + }); + } + return baseRule; + }, + props(_: any, { t }: any) { + if (!option.props) { + option.props = []; + } + return localeProps(t, `${name}.props`, [ + makeRequiredRule(), + ...option.props, + ...rules, + ]); + }, + }; +} diff --git a/apps/web-antd/src/components/form-create/rules/use-upload-file-rule.ts b/apps/web-antd/src/components/form-create/rules/use-upload-file-rule.ts new file mode 100644 index 0000000..91c21e5 --- /dev/null +++ b/apps/web-antd/src/components/form-create/rules/use-upload-file-rule.ts @@ -0,0 +1,84 @@ +import { buildUUID } from '@vben/utils'; + +import { + localeProps, + makeRequiredRule, +} from '#/components/form-create/helpers'; + +export function useUploadFileRule() { + const label = '文件上传'; + const name = 'FileUpload'; + return { + icon: 'icon-upload', + label, + name, + rule() { + return { + type: name, + field: buildUUID(), + title: label, + info: '', + $required: false, + }; + }, + props(_: any, { t }: any) { + return localeProps(t, `${name}.props`, [ + makeRequiredRule(), + { + type: 'select', + field: 'fileType', + title: '文件类型', + value: ['doc', 'xls', 'ppt', 'txt', 'pdf'], + options: [ + { label: 'doc', value: 'doc' }, + { label: 'xls', value: 'xls' }, + { label: 'ppt', value: 'ppt' }, + { label: 'txt', value: 'txt' }, + { label: 'pdf', value: 'pdf' }, + ], + props: { + mode: 'multiple', + }, + }, + { + type: 'switch', + field: 'autoUpload', + title: '是否在选取文件后立即进行上传', + value: true, + }, + { + type: 'switch', + field: 'drag', + title: '拖拽上传', + value: false, + }, + { + type: 'switch', + field: 'isShowTip', + title: '是否显示提示', + value: true, + }, + { + type: 'inputNumber', + field: 'fileSize', + title: '大小限制(MB)', + value: 5, + props: { min: 0 }, + }, + { + type: 'inputNumber', + field: 'limit', + title: '数量限制', + value: 5, + props: { min: 0 }, + }, + { + type: 'switch', + field: 'disabled', + title: '是否禁用', + value: false, + }, + ]); + }, + }; +} diff --git a/apps/web-antd/src/components/form-create/rules/use-upload-image-rule.ts b/apps/web-antd/src/components/form-create/rules/use-upload-image-rule.ts new file mode 100644 index 0000000..58dd71d --- /dev/null +++ b/apps/web-antd/src/components/form-create/rules/use-upload-image-rule.ts @@ -0,0 +1,93 @@ +import { buildUUID } from '@vben/utils'; + +import { + localeProps, + makeRequiredRule, +} from '#/components/form-create/helpers'; + +export function useUploadImageRule() { + const label = '单图上传'; + const name = 'ImageUpload'; + return { + icon: 'icon-image', + label, + name, + rule() { + return { + type: name, + field: buildUUID(), + title: label, + info: '', + $required: false, + }; + }, + props(_: any, { t }: any) { + return localeProps(t, `${name}.props`, [ + makeRequiredRule(), + { + type: 'switch', + field: 'drag', + title: '拖拽上传', + value: false, + }, + { + type: 'select', + field: 'fileType', + title: '图片类型限制', + value: ['image/jpeg', 'image/png', 'image/gif'], + options: [ + { label: 'image/apng', value: 'image/apng' }, + { label: 'image/bmp', value: 'image/bmp' }, + { label: 'image/gif', value: 'image/gif' }, + { label: 'image/jpeg', value: 'image/jpeg' }, + { label: 'image/pjpeg', value: 'image/pjpeg' }, + { label: 'image/svg+xml', value: 'image/svg+xml' }, + { label: 'image/tiff', value: 'image/tiff' }, + { label: 'image/webp', value: 'image/webp' }, + { label: 'image/x-icon', value: 'image/x-icon' }, + ], + props: { + mode: 'multiple', + }, + }, + { + type: 'inputNumber', + field: 'fileSize', + title: '大小限制(MB)', + value: 5, + props: { min: 0 }, + }, + { + type: 'input', + field: 'height', + title: '组件高度', + value: '150px', + }, + { + type: 'input', + field: 'width', + title: '组件宽度', + value: '150px', + }, + { + type: 'input', + field: 'borderradius', + title: '组件边框圆角', + value: '8px', + }, + { + type: 'switch', + field: 'disabled', + title: '是否显示删除按钮', + value: true, + }, + { + type: 'switch', + field: 'showBtnText', + title: '是否显示按钮文字', + value: true, + }, + ]); + }, + }; +} diff --git a/apps/web-antd/src/components/form-create/rules/use-upload-images-rule.ts b/apps/web-antd/src/components/form-create/rules/use-upload-images-rule.ts new file mode 100644 index 0000000..b1559ac --- /dev/null +++ b/apps/web-antd/src/components/form-create/rules/use-upload-images-rule.ts @@ -0,0 +1,89 @@ +import { buildUUID } from '@vben/utils'; + +import { + localeProps, + makeRequiredRule, +} from '#/components/form-create/helpers'; + +export function useUploadImagesRule() { + const label = '多图上传'; + const name = 'ImagesUpload'; + return { + icon: 'icon-image', + label, + name, + rule() { + return { + type: name, + field: buildUUID(), + title: label, + info: '', + $required: false, + }; + }, + props(_: any, { t }: any) { + return localeProps(t, `${name}.props`, [ + makeRequiredRule(), + { + type: 'switch', + field: 'drag', + title: '拖拽上传', + value: false, + }, + { + type: 'select', + field: 'fileType', + title: '图片类型限制', + value: ['image/jpeg', 'image/png', 'image/gif'], + options: [ + { label: 'image/apng', value: 'image/apng' }, + { label: 'image/bmp', value: 'image/bmp' }, + { label: 'image/gif', value: 'image/gif' }, + { label: 'image/jpeg', value: 'image/jpeg' }, + { label: 'image/pjpeg', value: 'image/pjpeg' }, + { label: 'image/svg+xml', value: 'image/svg+xml' }, + { label: 'image/tiff', value: 'image/tiff' }, + { label: 'image/webp', value: 'image/webp' }, + { label: 'image/x-icon', value: 'image/x-icon' }, + ], + props: { + mode: 'multiple', + maxNumber: 5, + }, + }, + { + type: 'inputNumber', + field: 'fileSize', + title: '大小限制(MB)', + value: 5, + props: { min: 0 }, + }, + { + type: 'inputNumber', + field: 'limit', + title: '数量限制', + value: 5, + props: { min: 0 }, + }, + { + type: 'input', + field: 'height', + title: '组件高度', + value: '150px', + }, + { + type: 'input', + field: 'width', + title: '组件宽度', + value: '150px', + }, + { + type: 'input', + field: 'borderradius', + title: '组件边框圆角', + value: '8px', + }, + ]); + }, + }; +} diff --git a/apps/web-antd/src/components/form-create/typing.ts b/apps/web-antd/src/components/form-create/typing.ts new file mode 100644 index 0000000..35c1a39 --- /dev/null +++ b/apps/web-antd/src/components/form-create/typing.ts @@ -0,0 +1,39 @@ +/** 数据字典 Select 选择器组件 Props 类型 */ +export interface DictSelectProps { + dictType: string; // 字典类型 + valueType?: 'bool' | 'int' | 'str'; // 字典值类型 + selectType?: 'checkbox' | 'radio' | 'select'; // 选择器类型,下拉框 select、多选框 checkbox、单选框 radio + formCreateInject?: any; +} + +/** 左侧拖拽按钮 */ +export interface MenuItem { + label: string; + name: string; + icon: string; +} + +/** 左侧拖拽按钮分类 */ +export interface Menu { + title: string; + name: string; + list: MenuItem[]; +} + +/** 通用 API 下拉组件 Props 类型 */ +export interface ApiSelectProps { + name: string; // 组件名称 + labelField?: string; // 选项标签 + valueField?: string; // 选项的值 + url?: string; // url 接口 + isDict?: boolean; // 是否字典选择器 +} + +/** 选择组件规则配置类型 */ +export interface SelectRuleOption { + label: string; // label 名称 + name: string; // 组件名称 + icon: string; // 组件图标 + props?: any[]; // 组件规则 + event?: any[]; // 事件配置 +} diff --git a/apps/web-antd/src/components/map/index.ts b/apps/web-antd/src/components/map/index.ts new file mode 100644 index 0000000..c8b84da --- /dev/null +++ b/apps/web-antd/src/components/map/index.ts @@ -0,0 +1,3 @@ +export { default as MapDialog } from './src/map-dialog.vue'; + +export { loadBaiduMapSdk } from './src/utils'; diff --git a/apps/web-antd/src/components/map/src/map-dialog.vue b/apps/web-antd/src/components/map/src/map-dialog.vue new file mode 100644 index 0000000..7b8c0bd --- /dev/null +++ b/apps/web-antd/src/components/map/src/map-dialog.vue @@ -0,0 +1,287 @@ + + + + diff --git a/apps/web-antd/src/components/map/src/utils.ts b/apps/web-antd/src/components/map/src/utils.ts new file mode 100644 index 0000000..c5ff378 --- /dev/null +++ b/apps/web-antd/src/components/map/src/utils.ts @@ -0,0 +1,63 @@ +/* eslint-disable @typescript-eslint/no-dynamic-delete */ +/** + * 百度地图 SDK 加载工具 + */ + +// 扩展 Window 接口以包含百度地图 GL API +declare global { + interface Window { + BMapGL: any; + } +} + +// 全局回调名称 +const CALLBACK_NAME = '__BAIDU_MAP_LOAD_CALLBACK__'; + +// SDK 加载状态 +let loadPromise: null | Promise = null; + +/** + * 加载百度地图 GL SDK + * @param timeout 超时时间(毫秒),默认 10000 + * @returns Promise + */ +export const loadBaiduMapSdk = (timeout = 10_000): Promise => { + // 已加载完成 + if (window.BMapGL) { + return Promise.resolve(); + } + + // 正在加载中,返回同一个 Promise + if (loadPromise) { + return loadPromise; + } + + loadPromise = new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + loadPromise = null; + reject(new Error('百度地图 SDK 加载超时')); + }, timeout); + + // 全局回调 + (window as any)[CALLBACK_NAME] = () => { + clearTimeout(timeoutId); + delete (window as any)[CALLBACK_NAME]; + resolve(); + }; + + // 创建 script 标签 + const script = document.createElement('script'); + script.src = `https://api.map.baidu.com/api?v=1.0&type=webgl&ak=${ + import.meta.env.VITE_BAIDU_MAP_KEY + }&callback=${CALLBACK_NAME}`; + script.addEventListener('onerror', () => { + clearTimeout(timeoutId); + loadPromise = null; + delete (window as any)[CALLBACK_NAME]; + reject(new Error('百度地图 SDK 加载失败')); + }); + document.body.append(script); + }); + + return loadPromise; +}; diff --git a/apps/web-antd/src/components/markdown-view/index.ts b/apps/web-antd/src/components/markdown-view/index.ts new file mode 100644 index 0000000..742bce8 --- /dev/null +++ b/apps/web-antd/src/components/markdown-view/index.ts @@ -0,0 +1,3 @@ +export { default as MarkdownView } from './markdown-view.vue'; + +export * from './typing'; diff --git a/apps/web-antd/src/components/markdown-view/markdown-view.vue b/apps/web-antd/src/components/markdown-view/markdown-view.vue new file mode 100644 index 0000000..373957a --- /dev/null +++ b/apps/web-antd/src/components/markdown-view/markdown-view.vue @@ -0,0 +1,206 @@ + + + + + diff --git a/apps/web-antd/src/components/markdown-view/typing.ts b/apps/web-antd/src/components/markdown-view/typing.ts new file mode 100644 index 0000000..350bbcf --- /dev/null +++ b/apps/web-antd/src/components/markdown-view/typing.ts @@ -0,0 +1,3 @@ +export type MarkdownViewProps = { + content: string; +}; diff --git a/apps/web-antd/src/components/operate-log/index.ts b/apps/web-antd/src/components/operate-log/index.ts new file mode 100644 index 0000000..cf38b5e --- /dev/null +++ b/apps/web-antd/src/components/operate-log/index.ts @@ -0,0 +1,3 @@ +export { default as OperateLog } from './operate-log.vue'; + +export type { OperateLogProps } from './typing'; diff --git a/apps/web-antd/src/components/operate-log/operate-log.vue b/apps/web-antd/src/components/operate-log/operate-log.vue new file mode 100644 index 0000000..8b49466 --- /dev/null +++ b/apps/web-antd/src/components/operate-log/operate-log.vue @@ -0,0 +1,59 @@ + + + diff --git a/apps/web-antd/src/components/operate-log/typing.ts b/apps/web-antd/src/components/operate-log/typing.ts new file mode 100644 index 0000000..773237b --- /dev/null +++ b/apps/web-antd/src/components/operate-log/typing.ts @@ -0,0 +1,5 @@ +import type { SystemOperateLogApi } from '#/api/system/operate-log'; + +export interface OperateLogProps { + logList: SystemOperateLogApi.OperateLog[]; // 操作日志列表 +} diff --git a/apps/web-antd/src/components/shortcut-date-range-picker/index.ts b/apps/web-antd/src/components/shortcut-date-range-picker/index.ts new file mode 100644 index 0000000..a3ee515 --- /dev/null +++ b/apps/web-antd/src/components/shortcut-date-range-picker/index.ts @@ -0,0 +1 @@ +export { default as ShortcutDateRangePicker } from './shortcut-date-range-picker.vue'; diff --git a/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue b/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue new file mode 100644 index 0000000..5a3ce05 --- /dev/null +++ b/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-antd/src/components/table-action/icons.ts b/apps/web-antd/src/components/table-action/icons.ts new file mode 100644 index 0000000..578265f --- /dev/null +++ b/apps/web-antd/src/components/table-action/icons.ts @@ -0,0 +1,16 @@ +export const ACTION_ICON = { + DOWNLOAD: 'lucide:download', + UPLOAD: 'lucide:upload', + ADD: 'lucide:plus', + EDIT: 'lucide:edit', + DELETE: 'lucide:trash-2', + REFRESH: 'lucide:refresh-cw', + SEARCH: 'lucide:search', + FILTER: 'lucide:filter', + MORE: 'lucide:ellipsis-vertical', + VIEW: 'lucide:eye', + COPY: 'lucide:copy', + CLOSE: 'lucide:x', + BOOK: 'lucide:book', + AUDIT: 'lucide:file-check', +}; diff --git a/apps/web-antd/src/components/table-action/index.ts b/apps/web-antd/src/components/table-action/index.ts new file mode 100644 index 0000000..672c0a5 --- /dev/null +++ b/apps/web-antd/src/components/table-action/index.ts @@ -0,0 +1,4 @@ +export * from './icons'; + +export { default as TableAction } from './table-action.vue'; +export * from './typing'; diff --git a/apps/web-antd/src/components/table-action/table-action.vue b/apps/web-antd/src/components/table-action/table-action.vue new file mode 100644 index 0000000..679f6fc --- /dev/null +++ b/apps/web-antd/src/components/table-action/table-action.vue @@ -0,0 +1,278 @@ + + + + + + diff --git a/apps/web-antd/src/components/table-action/typing.ts b/apps/web-antd/src/components/table-action/typing.ts new file mode 100644 index 0000000..1e44fb2 --- /dev/null +++ b/apps/web-antd/src/components/table-action/typing.ts @@ -0,0 +1,31 @@ +import type { + ButtonProps, + ButtonType, +} from 'ant-design-vue/es/button/buttonTypes'; +import type { TooltipProps } from 'ant-design-vue/es/tooltip/Tooltip'; + +export interface PopConfirm { + title: string; + okText?: string; + cancelText?: string; + confirm: () => void; + cancel?: () => void; + icon?: string; + disabled?: boolean; +} + +export interface ActionItem extends ButtonProps { + onClick?: () => void; + type?: ButtonType; + label?: string; + color?: 'error' | 'success' | 'warning'; + icon?: string; + popConfirm?: PopConfirm; + disabled?: boolean; + divider?: boolean; + // 权限编码控制是否显示 + auth?: string[]; + // 业务控制是否显示 + ifShow?: ((action: ActionItem) => boolean) | boolean; + tooltip?: string | TooltipProps; +} diff --git a/apps/web-antd/src/components/tinymce/editor.vue b/apps/web-antd/src/components/tinymce/editor.vue new file mode 100644 index 0000000..722073c --- /dev/null +++ b/apps/web-antd/src/components/tinymce/editor.vue @@ -0,0 +1,344 @@ + + + + + + diff --git a/apps/web-antd/src/components/tinymce/helper.ts b/apps/web-antd/src/components/tinymce/helper.ts new file mode 100644 index 0000000..1f98dda --- /dev/null +++ b/apps/web-antd/src/components/tinymce/helper.ts @@ -0,0 +1,85 @@ +const validEvents = new Set([ + 'onActivate', + 'onAddUndo', + 'onBeforeAddUndo', + 'onBeforeExecCommand', + 'onBeforeGetContent', + 'onBeforePaste', + 'onBeforeRenderUI', + 'onBeforeSetContent', + 'onBlur', + 'onChange', + 'onClearUndos', + 'onClick', + 'onContextMenu', + 'onCopy', + 'onCut', + 'onDblclick', + 'onDeactivate', + 'onDirty', + 'onDrag', + 'onDragDrop', + 'onDragEnd', + 'onDragGesture', + 'onDragOver', + 'onDrop', + 'onExecCommand', + 'onFocus', + 'onFocusIn', + 'onFocusOut', + 'onGetContent', + 'onHide', + 'onInit', + 'onKeyDown', + 'onKeyPress', + 'onKeyUp', + 'onLoadContent', + 'onMouseDown', + 'onMouseEnter', + 'onMouseLeave', + 'onMouseMove', + 'onMouseOut', + 'onMouseOver', + 'onMouseUp', + 'onNodeChange', + 'onObjectResized', + 'onObjectResizeStart', + 'onObjectSelected', + 'onPaste', + 'onPostProcess', + 'onPostRender', + 'onPreProcess', + 'onProgressState', + 'onRedo', + 'onRemove', + 'onReset', + 'onSaveContent', + 'onSelectionChange', + 'onSetAttrib', + 'onSetContent', + 'onShow', + 'onSubmit', + 'onUndo', + 'onVisualAid', +]); + +const isValidKey = (key: string) => validEvents.has(key); + +export const bindHandlers = ( + initEvent: Event, + listeners: any, + editor: any, +): void => { + Object.keys(listeners) + .filter((element) => isValidKey(element)) + .forEach((key: string) => { + const handler = listeners[key]; + if (typeof handler === 'function') { + if (key === 'onInit') { + handler(initEvent, editor); + } else { + editor.on(key.slice(2), (e: any) => handler(e, editor)); + } + } + }); +}; diff --git a/apps/web-antd/src/components/tinymce/img-upload.vue b/apps/web-antd/src/components/tinymce/img-upload.vue new file mode 100644 index 0000000..e5d47bb --- /dev/null +++ b/apps/web-antd/src/components/tinymce/img-upload.vue @@ -0,0 +1,84 @@ + + + + diff --git a/apps/web-antd/src/components/tinymce/index.ts b/apps/web-antd/src/components/tinymce/index.ts new file mode 100644 index 0000000..c277d78 --- /dev/null +++ b/apps/web-antd/src/components/tinymce/index.ts @@ -0,0 +1 @@ +export { default as Tinymce } from './editor.vue'; diff --git a/apps/web-antd/src/components/tinymce/tinymce.ts b/apps/web-antd/src/components/tinymce/tinymce.ts new file mode 100644 index 0000000..45a867b --- /dev/null +++ b/apps/web-antd/src/components/tinymce/tinymce.ts @@ -0,0 +1,17 @@ +// Any plugins you want to setting has to be imported +// Detail plugins list see https://www.tiny.cloud/docs/plugins/ +// Custom builds see https://www.tiny.cloud/download/custom-builds/ +// colorpicker/contextmenu/textcolor plugin is now built in to the core editor, please remove it from your editor configuration + +export const plugins = + 'preview importcss searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link media codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help emoticons accordion'; + +// 和 vben2.0 不同,从 https://www.tiny.cloud/ 拷贝 Vue 部分,然后去掉 importword exportword exportpdf | math 部分,并额外增加最后一行(来自 vben2.0 差异的部分) +export const toolbar = + 'undo redo | accordion accordionremove | \\\n' + + ' blocks fontfamily fontsize | bold italic underline strikethrough | \\\n' + + ' align numlist bullist | link image | table media | \\\n' + + ' lineheight outdent indent | forecolor backcolor removeformat | \\\n' + + ' charmap emoticons | code fullscreen preview | save print | \\\n' + + ' pagebreak anchor codesample | ltr rtl | \\\n' + + ' hr searchreplace alignleft aligncenter alignright blockquote subscript superscript'; diff --git a/apps/web-antd/src/components/upload/file-upload.vue b/apps/web-antd/src/components/upload/file-upload.vue new file mode 100644 index 0000000..3838642 --- /dev/null +++ b/apps/web-antd/src/components/upload/file-upload.vue @@ -0,0 +1,361 @@ + + + + + diff --git a/apps/web-antd/src/components/upload/image-upload.vue b/apps/web-antd/src/components/upload/image-upload.vue new file mode 100644 index 0000000..b78d8f1 --- /dev/null +++ b/apps/web-antd/src/components/upload/image-upload.vue @@ -0,0 +1,355 @@ + + + + + diff --git a/apps/web-antd/src/components/upload/index.ts b/apps/web-antd/src/components/upload/index.ts new file mode 100644 index 0000000..14e57fe --- /dev/null +++ b/apps/web-antd/src/components/upload/index.ts @@ -0,0 +1,3 @@ +export { default as FileUpload } from './file-upload.vue'; +export { default as ImageUpload } from './image-upload.vue'; +export { default as InputUpload } from './input-upload.vue'; diff --git a/apps/web-antd/src/components/upload/input-upload.vue b/apps/web-antd/src/components/upload/input-upload.vue new file mode 100644 index 0000000..90b2f4f --- /dev/null +++ b/apps/web-antd/src/components/upload/input-upload.vue @@ -0,0 +1,78 @@ + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/conversation/list.vue b/apps/web-antd/src/views/ai/chat/index/modules/conversation/list.vue new file mode 100644 index 0000000..f150e62 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/conversation/list.vue @@ -0,0 +1,435 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/conversation/update-form.vue b/apps/web-antd/src/views/ai/chat/index/modules/conversation/update-form.vue new file mode 100644 index 0000000..fda49d7 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/conversation/update-form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/message/file-upload.vue b/apps/web-antd/src/views/ai/chat/index/modules/message/file-upload.vue new file mode 100644 index 0000000..3d5e27f --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/message/file-upload.vue @@ -0,0 +1,304 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/message/files.vue b/apps/web-antd/src/views/ai/chat/index/modules/message/files.vue new file mode 100644 index 0000000..ed163a0 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/message/files.vue @@ -0,0 +1,53 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/message/knowledge.vue b/apps/web-antd/src/views/ai/chat/index/modules/message/knowledge.vue new file mode 100644 index 0000000..960188c --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/message/knowledge.vue @@ -0,0 +1,103 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/message/list-empty.vue b/apps/web-antd/src/views/ai/chat/index/modules/message/list-empty.vue new file mode 100644 index 0000000..f97a054 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/message/list-empty.vue @@ -0,0 +1,37 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/message/list.vue b/apps/web-antd/src/views/ai/chat/index/modules/message/list.vue new file mode 100644 index 0000000..a841ee2 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/message/list.vue @@ -0,0 +1,243 @@ + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/message/loading.vue b/apps/web-antd/src/views/ai/chat/index/modules/message/loading.vue new file mode 100644 index 0000000..5928a19 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/message/loading.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/message/new-conversation.vue b/apps/web-antd/src/views/ai/chat/index/modules/message/new-conversation.vue new file mode 100644 index 0000000..41c08ce --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/message/new-conversation.vue @@ -0,0 +1,23 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/message/reasoning.vue b/apps/web-antd/src/views/ai/chat/index/modules/message/reasoning.vue new file mode 100644 index 0000000..de3175d --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/message/reasoning.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/message/web-search.vue b/apps/web-antd/src/views/ai/chat/index/modules/message/web-search.vue new file mode 100644 index 0000000..d48a94c --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/message/web-search.vue @@ -0,0 +1,173 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/role/category-list.vue b/apps/web-antd/src/views/ai/chat/index/modules/role/category-list.vue new file mode 100644 index 0000000..91f6d64 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/role/category-list.vue @@ -0,0 +1,43 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/role/list.vue b/apps/web-antd/src/views/ai/chat/index/modules/role/list.vue new file mode 100644 index 0000000..544dfb0 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/role/list.vue @@ -0,0 +1,126 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/index/modules/role/repository.vue b/apps/web-antd/src/views/ai/chat/index/modules/role/repository.vue new file mode 100644 index 0000000..e9236a6 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/index/modules/role/repository.vue @@ -0,0 +1,249 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/manager/data.ts b/apps/web-antd/src/views/ai/chat/manager/data.ts new file mode 100644 index 0000000..f8dcb1f --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/manager/data.ts @@ -0,0 +1,223 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemUserApi } from '#/api/system/user'; + +import { DICT_TYPE } from '@vben/constants'; + +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 关联数据 */ +let userList: SystemUserApi.User[] = []; +getSimpleUserList().then((data) => (userList = data)); + +/** 列表的搜索表单 */ +export function useGridFormSchemaConversation(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + placeholder: '请输入用户编号', + allowClear: true, + }, + }, + { + fieldName: 'title', + label: '聊天标题', + component: 'Input', + componentProps: { + placeholder: '请输入聊天标题', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumnsConversation(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '对话编号', + fixed: 'left', + minWidth: 180, + }, + { + field: 'title', + title: '对话标题', + minWidth: 180, + fixed: 'left', + }, + { + title: '用户', + minWidth: 180, + field: 'userId', + formatter: ({ cellValue }) => { + if (cellValue === 0) { + return '系统'; + } + return userList.find((user) => user.id === cellValue)?.nickname || '-'; + }, + }, + { + field: 'roleName', + title: '角色', + minWidth: 180, + }, + { + field: 'model', + title: '模型标识', + minWidth: 180, + }, + { + field: 'messageCount', + title: '消息数', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'temperature', + title: '温度参数', + minWidth: 80, + }, + { + title: '回复数 Token 数', + field: 'maxTokens', + minWidth: 120, + }, + { + title: '上下文数量', + field: 'maxContexts', + minWidth: 120, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchemaMessage(): VbenFormSchema[] { + return [ + { + fieldName: 'conversationId', + label: '对话编号', + component: 'Input', + componentProps: { + placeholder: '请输入对话编号', + allowClear: true, + }, + }, + { + fieldName: 'userId', + label: '用户编号', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择用户编号', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumnsMessage(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '消息编号', + fixed: 'left', + minWidth: 180, + }, + { + field: 'conversationId', + title: '对话编号', + minWidth: 180, + fixed: 'left', + }, + { + title: '用户', + minWidth: 180, + field: 'userId', + formatter: ({ cellValue }) => + userList.find((user) => user.id === cellValue)?.nickname || '-', + }, + { + field: 'roleName', + title: '角色', + minWidth: 180, + }, + { + field: 'type', + title: '消息类型', + minWidth: 100, + }, + { + field: 'model', + title: '模型标识', + minWidth: 180, + }, + { + field: 'content', + title: '消息内容', + minWidth: 300, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'replyId', + title: '回复消息编号', + minWidth: 180, + }, + { + title: '携带上下文', + field: 'useContext', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + minWidth: 100, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-antd/src/views/ai/chat/manager/index.vue b/apps/web-antd/src/views/ai/chat/manager/index.vue new file mode 100644 index 0000000..69c4e84 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/manager/index.vue @@ -0,0 +1,29 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/manager/modules/conversation-list.vue b/apps/web-antd/src/views/ai/chat/manager/modules/conversation-list.vue new file mode 100644 index 0000000..6bfe702 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/manager/modules/conversation-list.vue @@ -0,0 +1,94 @@ + + + diff --git a/apps/web-antd/src/views/ai/chat/manager/modules/message-list.vue b/apps/web-antd/src/views/ai/chat/manager/modules/message-list.vue new file mode 100644 index 0000000..bf6bd57 --- /dev/null +++ b/apps/web-antd/src/views/ai/chat/manager/modules/message-list.vue @@ -0,0 +1,91 @@ + + + diff --git a/apps/web-antd/src/views/ai/image/index/index.vue b/apps/web-antd/src/views/ai/image/index/index.vue new file mode 100644 index 0000000..16fdb5b --- /dev/null +++ b/apps/web-antd/src/views/ai/image/index/index.vue @@ -0,0 +1,131 @@ + + + diff --git a/apps/web-antd/src/views/ai/image/index/modules/card.vue b/apps/web-antd/src/views/ai/image/index/modules/card.vue new file mode 100644 index 0000000..57b12e6 --- /dev/null +++ b/apps/web-antd/src/views/ai/image/index/modules/card.vue @@ -0,0 +1,133 @@ + + diff --git a/apps/web-antd/src/views/ai/image/index/modules/common/index.vue b/apps/web-antd/src/views/ai/image/index/modules/common/index.vue new file mode 100644 index 0000000..bd10987 --- /dev/null +++ b/apps/web-antd/src/views/ai/image/index/modules/common/index.vue @@ -0,0 +1,218 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/conversation/list.vue b/apps/web-ele/src/views/ai/chat/index/modules/conversation/list.vue new file mode 100644 index 0000000..0280554 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/conversation/list.vue @@ -0,0 +1,442 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/conversation/update-form.vue b/apps/web-ele/src/views/ai/chat/index/modules/conversation/update-form.vue new file mode 100644 index 0000000..6a7ae84 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/conversation/update-form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/message/file-upload.vue b/apps/web-ele/src/views/ai/chat/index/modules/message/file-upload.vue new file mode 100644 index 0000000..eff1b57 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/message/file-upload.vue @@ -0,0 +1,304 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/message/files.vue b/apps/web-ele/src/views/ai/chat/index/modules/message/files.vue new file mode 100644 index 0000000..ed163a0 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/message/files.vue @@ -0,0 +1,53 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/message/knowledge.vue b/apps/web-ele/src/views/ai/chat/index/modules/message/knowledge.vue new file mode 100644 index 0000000..6feff41 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/message/knowledge.vue @@ -0,0 +1,103 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/message/list-empty.vue b/apps/web-ele/src/views/ai/chat/index/modules/message/list-empty.vue new file mode 100644 index 0000000..f97a054 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/message/list-empty.vue @@ -0,0 +1,37 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/message/list.vue b/apps/web-ele/src/views/ai/chat/index/modules/message/list.vue new file mode 100644 index 0000000..36630d1 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/message/list.vue @@ -0,0 +1,243 @@ + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/message/loading.vue b/apps/web-ele/src/views/ai/chat/index/modules/message/loading.vue new file mode 100644 index 0000000..a5e0765 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/message/loading.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/message/new-conversation.vue b/apps/web-ele/src/views/ai/chat/index/modules/message/new-conversation.vue new file mode 100644 index 0000000..339af17 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/message/new-conversation.vue @@ -0,0 +1,25 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/message/reasoning.vue b/apps/web-ele/src/views/ai/chat/index/modules/message/reasoning.vue new file mode 100644 index 0000000..de3175d --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/message/reasoning.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/message/web-search.vue b/apps/web-ele/src/views/ai/chat/index/modules/message/web-search.vue new file mode 100644 index 0000000..d48a94c --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/message/web-search.vue @@ -0,0 +1,173 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/role/category-list.vue b/apps/web-ele/src/views/ai/chat/index/modules/role/category-list.vue new file mode 100644 index 0000000..96f32a1 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/role/category-list.vue @@ -0,0 +1,43 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/role/list.vue b/apps/web-ele/src/views/ai/chat/index/modules/role/list.vue new file mode 100644 index 0000000..a3f3e40 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/role/list.vue @@ -0,0 +1,123 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/index/modules/role/repository.vue b/apps/web-ele/src/views/ai/chat/index/modules/role/repository.vue new file mode 100644 index 0000000..20bc9e4 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/index/modules/role/repository.vue @@ -0,0 +1,263 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/manager/data.ts b/apps/web-ele/src/views/ai/chat/manager/data.ts new file mode 100644 index 0000000..266d44c --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/manager/data.ts @@ -0,0 +1,223 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemUserApi } from '#/api/system/user'; + +import { DICT_TYPE } from '@vben/constants'; + +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 关联数据 */ +let userList: SystemUserApi.User[] = []; +getSimpleUserList().then((data) => (userList = data)); + +/** 列表的搜索表单 */ +export function useGridFormSchemaConversation(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + placeholder: '请输入用户编号', + clearable: true, + }, + }, + { + fieldName: 'title', + label: '聊天标题', + component: 'Input', + componentProps: { + placeholder: '请输入聊天标题', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumnsConversation(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '对话编号', + fixed: 'left', + minWidth: 180, + }, + { + field: 'title', + title: '对话标题', + minWidth: 180, + fixed: 'left', + }, + { + title: '用户', + minWidth: 180, + field: 'userId', + formatter: ({ cellValue }) => { + if (cellValue === 0) { + return '系统'; + } + return userList.find((user) => user.id === cellValue)?.nickname || '-'; + }, + }, + { + field: 'roleName', + title: '角色', + minWidth: 180, + }, + { + field: 'model', + title: '模型标识', + minWidth: 180, + }, + { + field: 'messageCount', + title: '消息数', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'temperature', + title: '温度参数', + minWidth: 80, + }, + { + title: '回复数 Token 数', + field: 'maxTokens', + minWidth: 120, + }, + { + title: '上下文数量', + field: 'maxContexts', + minWidth: 120, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchemaMessage(): VbenFormSchema[] { + return [ + { + fieldName: 'conversationId', + label: '对话编号', + component: 'Input', + componentProps: { + placeholder: '请输入对话编号', + clearable: true, + }, + }, + { + fieldName: 'userId', + label: '用户编号', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择用户编号', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumnsMessage(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '消息编号', + fixed: 'left', + minWidth: 180, + }, + { + field: 'conversationId', + title: '对话编号', + minWidth: 180, + fixed: 'left', + }, + { + title: '用户', + minWidth: 180, + field: 'userId', + formatter: ({ cellValue }) => + userList.find((user) => user.id === cellValue)?.nickname || '-', + }, + { + field: 'roleName', + title: '角色', + minWidth: 180, + }, + { + field: 'type', + title: '消息类型', + minWidth: 100, + }, + { + field: 'model', + title: '模型标识', + minWidth: 180, + }, + { + field: 'content', + title: '消息内容', + minWidth: 300, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'replyId', + title: '回复消息编号', + minWidth: 180, + }, + { + title: '携带上下文', + field: 'useContext', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + minWidth: 100, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/chat/manager/index.vue b/apps/web-ele/src/views/ai/chat/manager/index.vue new file mode 100644 index 0000000..e87c3d3 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/manager/index.vue @@ -0,0 +1,29 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/manager/modules/conversation-list.vue b/apps/web-ele/src/views/ai/chat/manager/modules/conversation-list.vue new file mode 100644 index 0000000..b6ea3dc --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/manager/modules/conversation-list.vue @@ -0,0 +1,93 @@ + + + diff --git a/apps/web-ele/src/views/ai/chat/manager/modules/message-list.vue b/apps/web-ele/src/views/ai/chat/manager/modules/message-list.vue new file mode 100644 index 0000000..f568214 --- /dev/null +++ b/apps/web-ele/src/views/ai/chat/manager/modules/message-list.vue @@ -0,0 +1,90 @@ + + + diff --git a/apps/web-ele/src/views/ai/image/index/index.vue b/apps/web-ele/src/views/ai/image/index/index.vue new file mode 100644 index 0000000..1a2f842 --- /dev/null +++ b/apps/web-ele/src/views/ai/image/index/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-ele/src/views/ai/image/index/modules/card.vue b/apps/web-ele/src/views/ai/image/index/modules/card.vue new file mode 100644 index 0000000..91018c7 --- /dev/null +++ b/apps/web-ele/src/views/ai/image/index/modules/card.vue @@ -0,0 +1,136 @@ + + diff --git a/apps/web-ele/src/views/ai/image/index/modules/common/index.vue b/apps/web-ele/src/views/ai/image/index/modules/common/index.vue new file mode 100644 index 0000000..c0197e4 --- /dev/null +++ b/apps/web-ele/src/views/ai/image/index/modules/common/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/ai/image/index/modules/dall3/index.vue b/apps/web-ele/src/views/ai/image/index/modules/dall3/index.vue new file mode 100644 index 0000000..299b93f --- /dev/null +++ b/apps/web-ele/src/views/ai/image/index/modules/dall3/index.vue @@ -0,0 +1,260 @@ + + + diff --git a/apps/web-ele/src/views/ai/image/index/modules/detail.vue b/apps/web-ele/src/views/ai/image/index/modules/detail.vue new file mode 100644 index 0000000..7959a44 --- /dev/null +++ b/apps/web-ele/src/views/ai/image/index/modules/detail.vue @@ -0,0 +1,206 @@ + + + diff --git a/apps/web-ele/src/views/ai/image/index/modules/list.vue b/apps/web-ele/src/views/ai/image/index/modules/list.vue new file mode 100644 index 0000000..9036549 --- /dev/null +++ b/apps/web-ele/src/views/ai/image/index/modules/list.vue @@ -0,0 +1,222 @@ + + + diff --git a/apps/web-ele/src/views/ai/image/index/modules/midjourney/index.vue b/apps/web-ele/src/views/ai/image/index/modules/midjourney/index.vue new file mode 100644 index 0000000..5c847ba --- /dev/null +++ b/apps/web-ele/src/views/ai/image/index/modules/midjourney/index.vue @@ -0,0 +1,257 @@ + + + diff --git a/apps/web-ele/src/views/ai/image/index/modules/stable-diffusion/index.vue b/apps/web-ele/src/views/ai/image/index/modules/stable-diffusion/index.vue new file mode 100644 index 0000000..5d7914f --- /dev/null +++ b/apps/web-ele/src/views/ai/image/index/modules/stable-diffusion/index.vue @@ -0,0 +1,309 @@ + + + diff --git a/apps/web-ele/src/views/ai/image/manager/data.ts b/apps/web-ele/src/views/ai/image/manager/data.ts new file mode 100644 index 0000000..68cc3c4 --- /dev/null +++ b/apps/web-ele/src/views/ai/image/manager/data.ts @@ -0,0 +1,180 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemUserApi } from '#/api/system/user'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +let userList: SystemUserApi.User[] = []; +async function getUserData() { + userList = await getSimpleUserList(); +} + +getUserData(); + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择用户编号', + clearable: true, + }, + }, + { + fieldName: 'platform', + label: '平台', + component: 'Select', + componentProps: { + placeholder: '请选择平台', + clearable: true, + options: getDictOptions(DICT_TYPE.AI_PLATFORM, 'string'), + }, + }, + { + fieldName: 'status', + label: '绘画状态', + component: 'Select', + componentProps: { + placeholder: '请选择绘画状态', + clearable: true, + options: getDictOptions(DICT_TYPE.AI_IMAGE_STATUS, 'number'), + }, + }, + { + fieldName: 'publicStatus', + label: '是否发布', + component: 'Select', + componentProps: { + placeholder: '请选择是否发布', + clearable: true, + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onPublicStatusChange?: ( + newStatus: boolean, + row: any, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 180, + fixed: 'left', + }, + { + field: 'picUrl', + title: '图片', + minWidth: 110, + fixed: 'left', + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'userId', + title: '用户', + minWidth: 180, + formatter: ({ cellValue }) => + userList.find((user) => user.id === cellValue)?.nickname || '-', + }, + { + field: 'platform', + title: '平台', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_PLATFORM }, + }, + }, + { + field: 'model', + title: '模型', + minWidth: 180, + }, + { + field: 'status', + title: '绘画状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_IMAGE_STATUS }, + }, + }, + { + minWidth: 100, + title: '是否发布', + field: 'publicStatus', + align: 'center', + cellRender: { + attrs: { beforeChange: onPublicStatusChange }, + name: 'CellSwitch', + props: { + activeValue: true, + inactiveValue: false, + }, + }, + }, + { + field: 'prompt', + title: '提示词', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'width', + title: '宽度', + minWidth: 180, + }, + { + field: 'height', + title: '高度', + minWidth: 180, + }, + { + field: 'errorMessage', + title: '错误信息', + minWidth: 180, + }, + { + field: 'taskId', + title: '任务编号', + minWidth: 180, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/image/manager/index.vue b/apps/web-ele/src/views/ai/image/manager/index.vue new file mode 100644 index 0000000..72830e7 --- /dev/null +++ b/apps/web-ele/src/views/ai/image/manager/index.vue @@ -0,0 +1,116 @@ + + + diff --git a/apps/web-ele/src/views/ai/image/square/index.vue b/apps/web-ele/src/views/ai/image/square/index.vue new file mode 100644 index 0000000..636aade --- /dev/null +++ b/apps/web-ele/src/views/ai/image/square/index.vue @@ -0,0 +1,90 @@ + + diff --git a/apps/web-ele/src/views/ai/knowledge/document/data.ts b/apps/web-ele/src/views/ai/knowledge/document/data.ts new file mode 100644 index 0000000..668fb09 --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/document/data.ts @@ -0,0 +1,180 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { AiKnowledgeDocumentApi } from '#/api/ai/knowledge/document'; + +import { AiModelTypeEnum, CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getModelSimpleList } from '#/api/ai/model/model'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '知识库名称', + rules: 'required', + }, + { + fieldName: 'description', + label: '知识库描述', + component: 'Textarea', + componentProps: { + rows: 3, + placeholder: '请输入知识库描述', + }, + }, + { + component: 'ApiSelect', + fieldName: 'embeddingModelId', + label: '向量模型', + componentProps: { + api: () => getModelSimpleList(AiModelTypeEnum.EMBEDDING), + labelField: 'name', + valueField: 'id', + allowClear: true, + placeholder: '请选择向量模型', + }, + rules: 'required', + }, + { + fieldName: 'topK', + label: '检索 topK', + component: 'InputNumber', + componentProps: { + placeholder: '请输入检索 topK', + min: 0, + max: 10, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'similarityThreshold', + label: '检索相似度阈值', + component: 'InputNumber', + componentProps: { + placeholder: '请输入检索相似度阈值', + min: 0, + max: 1, + step: 0.01, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '是否启用', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '文件名称', + component: 'Input', + componentProps: { + placeholder: '请输入文件名称', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '是否启用', + component: 'Select', + componentProps: { + placeholder: '请选择是否启用', + allowClear: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onStatusChange?: ( + newStatus: number, + row: AiKnowledgeDocumentApi.KnowledgeDocument, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '文档编号', + minWidth: 100, + }, + { + field: 'name', + title: '文件名称', + minWidth: 200, + }, + { + field: 'contentLength', + title: '字符数', + minWidth: 100, + }, + { + field: 'tokens', + title: 'Token 数', + minWidth: 100, + }, + { + field: 'segmentMaxTokens', + title: '分片最大 Token 数', + minWidth: 150, + }, + { + field: 'retrievalCount', + title: '召回次数', + minWidth: 100, + }, + { + field: 'status', + title: '是否启用', + minWidth: 100, + align: 'center', + cellRender: { + attrs: { beforeChange: onStatusChange }, + name: 'CellSwitch', + props: { + activeValue: CommonStatusEnum.ENABLE, + inactiveValue: CommonStatusEnum.DISABLE, + }, + }, + }, + { + field: 'createTime', + title: '上传时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + minWidth: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/knowledge/document/form/index.vue b/apps/web-ele/src/views/ai/knowledge/document/form/index.vue new file mode 100644 index 0000000..1ef2429 --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/document/form/index.vue @@ -0,0 +1,200 @@ + + + diff --git a/apps/web-ele/src/views/ai/knowledge/document/form/modules/process-step.vue b/apps/web-ele/src/views/ai/knowledge/document/form/modules/process-step.vue new file mode 100644 index 0000000..e790c73 --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/document/form/modules/process-step.vue @@ -0,0 +1,158 @@ + + + diff --git a/apps/web-ele/src/views/ai/knowledge/document/form/modules/split-step.vue b/apps/web-ele/src/views/ai/knowledge/document/form/modules/split-step.vue new file mode 100644 index 0000000..e2c9781 --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/document/form/modules/split-step.vue @@ -0,0 +1,286 @@ + + + diff --git a/apps/web-ele/src/views/ai/knowledge/document/form/modules/upload-step.vue b/apps/web-ele/src/views/ai/knowledge/document/form/modules/upload-step.vue new file mode 100644 index 0000000..456aafd --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/document/form/modules/upload-step.vue @@ -0,0 +1,270 @@ + + + diff --git a/apps/web-ele/src/views/ai/knowledge/document/index.vue b/apps/web-ele/src/views/ai/knowledge/document/index.vue new file mode 100644 index 0000000..df0fc71 --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/document/index.vue @@ -0,0 +1,191 @@ + + + diff --git a/apps/web-ele/src/views/ai/knowledge/knowledge/data.ts b/apps/web-ele/src/views/ai/knowledge/knowledge/data.ts new file mode 100644 index 0000000..1e69f2c --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/knowledge/data.ts @@ -0,0 +1,172 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { AiModelTypeEnum, CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getModelSimpleList } from '#/api/ai/model/model'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '知识库名称', + componentProps: { + placeholder: '请输入知识库名称', + }, + rules: 'required', + }, + { + fieldName: 'description', + label: '知识库描述', + component: 'Textarea', + componentProps: { + rows: 3, + placeholder: '请输入知识库描述', + }, + }, + { + component: 'ApiSelect', + fieldName: 'embeddingModelId', + label: '向量模型', + componentProps: { + api: () => getModelSimpleList(AiModelTypeEnum.EMBEDDING), + labelField: 'name', + valueField: 'id', + allowClear: true, + placeholder: '请选择向量模型', + }, + rules: 'required', + }, + { + fieldName: 'topK', + label: '检索 topK', + component: 'InputNumber', + componentProps: { + placeholder: '请输入检索 topK', + min: 0, + max: 10, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'similarityThreshold', + label: '检索相似度阈值', + component: 'InputNumber', + componentProps: { + placeholder: '请输入检索相似度阈值', + min: 0, + max: 1, + step: 0.01, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '是否启用', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '知识库名称', + component: 'Input', + componentProps: { + placeholder: '请输入知识库名称', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '是否启用', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择是否启用', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'name', + title: '知识库名称', + minWidth: 150, + }, + { + field: 'description', + title: '知识库描述', + minWidth: 200, + }, + { + field: 'embeddingModel', + title: '向量化模型', + minWidth: 150, + }, + { + field: 'status', + title: '是否启用', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/knowledge/knowledge/index.vue b/apps/web-ele/src/views/ai/knowledge/knowledge/index.vue new file mode 100644 index 0000000..55cfbcc --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/knowledge/index.vue @@ -0,0 +1,166 @@ + + + diff --git a/apps/web-ele/src/views/ai/knowledge/knowledge/modules/form.vue b/apps/web-ele/src/views/ai/knowledge/knowledge/modules/form.vue new file mode 100644 index 0000000..5daf714 --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/knowledge/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/ai/knowledge/knowledge/retrieval/index.vue b/apps/web-ele/src/views/ai/knowledge/knowledge/retrieval/index.vue new file mode 100644 index 0000000..1af68df --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/knowledge/retrieval/index.vue @@ -0,0 +1,214 @@ + + diff --git a/apps/web-ele/src/views/ai/knowledge/segment/data.ts b/apps/web-ele/src/views/ai/knowledge/segment/data.ts new file mode 100644 index 0000000..33cb64b --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/segment/data.ts @@ -0,0 +1,130 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { AiKnowledgeSegmentApi } from '#/api/ai/knowledge/segment'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'documentId', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'content', + label: '切片内容', + component: 'Textarea', + componentProps: { + placeholder: '请输入切片内容', + rows: 6, + showCount: true, + }, + rules: 'required', + }, + ]; +} +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'documentId', + label: '文档编号', + component: 'Input', + componentProps: { + placeholder: '请输入文档编号', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '是否启用', + component: 'Select', + componentProps: { + placeholder: '请选择是否启用', + allowClear: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onStatusChange?: ( + newStatus: number, + row: AiKnowledgeSegmentApi.KnowledgeSegment, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '分段编号', + minWidth: 100, + }, + { + type: 'expand', + width: 40, + slots: { content: 'expand_content' }, + }, + { + field: 'content', + title: '切片内容', + minWidth: 250, + }, + { + field: 'contentLength', + title: '字符数', + minWidth: 100, + }, + { + field: 'tokens', + title: 'token 数量', + minWidth: 120, + }, + { + field: 'retrievalCount', + title: '召回次数', + minWidth: 100, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + align: 'center', + cellRender: { + attrs: { beforeChange: onStatusChange }, + name: 'CellSwitch', + props: { + activeValue: CommonStatusEnum.ENABLE, + inactiveValue: CommonStatusEnum.DISABLE, + }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/knowledge/segment/index.vue b/apps/web-ele/src/views/ai/knowledge/segment/index.vue new file mode 100644 index 0000000..980a904 --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/segment/index.vue @@ -0,0 +1,171 @@ + + + diff --git a/apps/web-ele/src/views/ai/knowledge/segment/modules/form.vue b/apps/web-ele/src/views/ai/knowledge/segment/modules/form.vue new file mode 100644 index 0000000..1b4b135 --- /dev/null +++ b/apps/web-ele/src/views/ai/knowledge/segment/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/ai/mindmap/index/index.vue b/apps/web-ele/src/views/ai/mindmap/index/index.vue new file mode 100644 index 0000000..0bdb46e --- /dev/null +++ b/apps/web-ele/src/views/ai/mindmap/index/index.vue @@ -0,0 +1,99 @@ + + + diff --git a/apps/web-ele/src/views/ai/mindmap/index/modules/left.vue b/apps/web-ele/src/views/ai/mindmap/index/modules/left.vue new file mode 100644 index 0000000..f2bd48c --- /dev/null +++ b/apps/web-ele/src/views/ai/mindmap/index/modules/left.vue @@ -0,0 +1,75 @@ + + diff --git a/apps/web-ele/src/views/ai/mindmap/index/modules/right.vue b/apps/web-ele/src/views/ai/mindmap/index/modules/right.vue new file mode 100644 index 0000000..5adc66a --- /dev/null +++ b/apps/web-ele/src/views/ai/mindmap/index/modules/right.vue @@ -0,0 +1,215 @@ + + + + + diff --git a/apps/web-ele/src/views/ai/mindmap/manager/data.ts b/apps/web-ele/src/views/ai/mindmap/manager/data.ts new file mode 100644 index 0000000..967981d --- /dev/null +++ b/apps/web-ele/src/views/ai/mindmap/manager/data.ts @@ -0,0 +1,97 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemUserApi } from '#/api/system/user'; + +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 关联数据 */ +let userList: SystemUserApi.User[] = []; +getSimpleUserList().then((data) => (userList = data)); + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择用户', + allowClear: true, + }, + }, + { + fieldName: 'prompt', + label: '提示词', + component: 'Input', + componentProps: { + placeholder: '请输入提示词', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 180, + fixed: 'left', + }, + { + field: 'userId', + title: '用户', + minWidth: 180, + formatter: ({ cellValue }) => + userList.find((user) => user.id === cellValue)?.nickname || '-', + }, + { + field: 'prompt', + title: '提示词', + minWidth: 180, + }, + { + field: 'generatedContent', + title: '思维导图', + minWidth: 300, + }, + { + field: 'model', + title: '模型', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'errorMessage', + title: '错误信息', + minWidth: 180, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/mindmap/manager/index.vue b/apps/web-ele/src/views/ai/mindmap/manager/index.vue new file mode 100644 index 0000000..9684dfc --- /dev/null +++ b/apps/web-ele/src/views/ai/mindmap/manager/index.vue @@ -0,0 +1,120 @@ + + + diff --git a/apps/web-ele/src/views/ai/model/apiKey/data.ts b/apps/web-ele/src/views/ai/model/apiKey/data.ts new file mode 100644 index 0000000..1c307ed --- /dev/null +++ b/apps/web-ele/src/views/ai/model/apiKey/data.ts @@ -0,0 +1,147 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'platform', + label: '所属平台', + component: 'Select', + componentProps: { + placeholder: '请选择所属平台', + options: getDictOptions(DICT_TYPE.AI_PLATFORM, 'string'), + allowClear: true, + }, + rules: 'required', + }, + { + component: 'Input', + fieldName: 'name', + label: '名称', + rules: 'required', + componentProps: { + placeholder: '请输入名称', + }, + }, + { + component: 'Input', + fieldName: 'apiKey', + label: '密钥', + rules: 'required', + componentProps: { + placeholder: '请输入密钥', + }, + }, + { + component: 'Input', + fieldName: 'url', + label: '自定义 API URL', + componentProps: { + placeholder: '请输入自定义 API URL', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名称', + component: 'Input', + componentProps: { + placeholder: '请输入名称', + allowClear: true, + }, + }, + { + fieldName: 'platform', + label: '平台', + component: 'Select', + componentProps: { + allowClear: true, + placeholder: '请选择平台', + options: getDictOptions(DICT_TYPE.AI_PLATFORM, 'string'), + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + allowClear: true, + placeholder: '请选择状态', + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'platform', + title: '所属平台', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_PLATFORM }, + }, + minWidth: 100, + }, + { + field: 'name', + title: '名称', + minWidth: 120, + }, + { + field: 'apiKey', + title: '密钥', + minWidth: 140, + }, + { + field: 'url', + title: '自定义 API URL', + minWidth: 180, + }, + { + field: 'status', + title: '状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + minWidth: 80, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/model/apiKey/index.vue b/apps/web-ele/src/views/ai/model/apiKey/index.vue new file mode 100644 index 0000000..a6b5181 --- /dev/null +++ b/apps/web-ele/src/views/ai/model/apiKey/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-ele/src/views/ai/model/apiKey/modules/form.vue b/apps/web-ele/src/views/ai/model/apiKey/modules/form.vue new file mode 100644 index 0000000..c7e5388 --- /dev/null +++ b/apps/web-ele/src/views/ai/model/apiKey/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/ai/model/chatRole/data.ts b/apps/web-ele/src/views/ai/model/chatRole/data.ts new file mode 100644 index 0000000..ab70227 --- /dev/null +++ b/apps/web-ele/src/views/ai/model/chatRole/data.ts @@ -0,0 +1,318 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { AiModelTypeEnum, CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getSimpleKnowledgeList } from '#/api/ai/knowledge/knowledge'; +import { getModelSimpleList } from '#/api/ai/model/model'; +import { getToolSimpleList } from '#/api/ai/model/tool'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'formType', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '角色名称', + rules: 'required', + componentProps: { + placeholder: '请输入角色名称', + }, + }, + { + component: 'ImageUpload', + fieldName: 'avatar', + label: '角色头像', + rules: 'required', + }, + { + fieldName: 'modelId', + label: '绑定模型', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择绑定模型', + api: () => getModelSimpleList(AiModelTypeEnum.CHAT), + labelField: 'name', + valueField: 'id', + allowClear: true, + }, + dependencies: { + triggerFields: ['formType'], + show: (values) => { + return values.formType === 'create' || values.formType === 'update'; + }, + }, + }, + { + component: 'Input', + fieldName: 'category', + label: '角色类别', + rules: 'required', + componentProps: { + placeholder: '请输入角色类别', + }, + dependencies: { + triggerFields: ['formType'], + show: (values) => { + return values.formType === 'create' || values.formType === 'update'; + }, + }, + }, + { + component: 'Textarea', + fieldName: 'description', + label: '角色描述', + componentProps: { + placeholder: '请输入角色描述', + }, + rules: 'required', + }, + { + fieldName: 'systemMessage', + label: '角色设定', + component: 'Textarea', + componentProps: { + placeholder: '请输入角色设定', + }, + rules: 'required', + }, + { + fieldName: 'knowledgeIds', + label: '引用知识库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择引用知识库', + api: getSimpleKnowledgeList, + labelField: 'name', + mode: 'multiple', + valueField: 'id', + allowClear: true, + }, + }, + { + fieldName: 'toolIds', + label: '引用工具', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择引用工具', + api: getToolSimpleList, + mode: 'multiple', + labelField: 'name', + valueField: 'id', + allowClear: true, + }, + }, + { + fieldName: 'mcpClientNames', + label: '引用 MCP', + component: 'Select', + componentProps: { + placeholder: '请选择 MCP', + options: getDictOptions(DICT_TYPE.AI_MCP_CLIENT_NAME, 'string'), + mode: 'multiple', + allowClear: true, + }, + }, + { + fieldName: 'publicStatus', + label: '是否公开', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + }, + defaultValue: true, + dependencies: { + triggerFields: ['formType'], + show: (values) => { + return values.formType === 'create' || values.formType === 'update'; + }, + }, + rules: 'required', + }, + { + fieldName: 'sort', + label: '角色排序', + component: 'InputNumber', + componentProps: { + placeholder: '请输入角色排序', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['formType'], + show: (values) => { + return values.formType === 'create' || values.formType === 'update'; + }, + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '开启状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + dependencies: { + triggerFields: ['formType'], + show: (values) => { + return values.formType === 'create' || values.formType === 'update'; + }, + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '角色名称', + component: 'Input', + componentProps: { + placeholder: '请输入角色名称', + }, + }, + { + fieldName: 'category', + label: '角色类别', + component: 'Input', + componentProps: { + placeholder: '请输入角色类别', + }, + }, + { + fieldName: 'publicStatus', + label: '是否公开', + component: 'Select', + componentProps: { + placeholder: '请选择是否公开', + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + allowClear: true, + }, + defaultValue: true, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '角色名称', + minWidth: 100, + }, + { + title: '绑定模型', + field: 'modelName', + minWidth: 100, + }, + { + title: '角色头像', + field: 'avatar', + minWidth: 140, + cellRender: { + name: 'CellImage', + props: { + width: 40, + height: 40, + }, + }, + }, + { + title: '角色类别', + field: 'category', + minWidth: 100, + }, + { + title: '角色描述', + field: 'description', + minWidth: 100, + }, + { + title: '角色设定', + field: 'systemMessage', + minWidth: 100, + }, + { + title: '知识库', + field: 'knowledgeIds', + minWidth: 100, + formatter: ({ cellValue }) => { + return !cellValue || cellValue.length === 0 + ? '-' + : `引用${cellValue.length}个`; + }, + }, + { + title: '工具', + field: 'toolIds', + minWidth: 100, + formatter: ({ cellValue }) => { + return !cellValue || cellValue.length === 0 + ? '-' + : `引用${cellValue.length}个`; + }, + }, + { + title: 'MCP', + field: 'mcpClientNames', + minWidth: 100, + formatter: ({ cellValue }) => { + return !cellValue || cellValue.length === 0 + ? '-' + : `引用${cellValue.length}个`; + }, + }, + { + field: 'publicStatus', + title: '是否公开', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + minWidth: 80, + }, + { + field: 'status', + title: '状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + minWidth: 80, + }, + { + title: '角色排序', + field: 'sort', + minWidth: 80, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/model/chatRole/index.vue b/apps/web-ele/src/views/ai/model/chatRole/index.vue new file mode 100644 index 0000000..16e7840 --- /dev/null +++ b/apps/web-ele/src/views/ai/model/chatRole/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-ele/src/views/ai/model/chatRole/modules/form.vue b/apps/web-ele/src/views/ai/model/chatRole/modules/form.vue new file mode 100644 index 0000000..35c44d2 --- /dev/null +++ b/apps/web-ele/src/views/ai/model/chatRole/modules/form.vue @@ -0,0 +1,87 @@ + + + diff --git a/apps/web-ele/src/views/ai/model/model/data.ts b/apps/web-ele/src/views/ai/model/model/data.ts new file mode 100644 index 0000000..a29e31a --- /dev/null +++ b/apps/web-ele/src/views/ai/model/model/data.ts @@ -0,0 +1,272 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { AiModelApiKeyApi } from '#/api/ai/model/apiKey'; + +import { AiModelTypeEnum, CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getApiKeySimpleList } from '#/api/ai/model/apiKey'; + +/** 关联数据 */ +let apiKeyList: AiModelApiKeyApi.ApiKey[] = []; +getApiKeySimpleList().then((data) => (apiKeyList = data)); + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'platform', + label: '所属平台', + component: 'Select', + componentProps: { + placeholder: '请选择所属平台', + options: getDictOptions(DICT_TYPE.AI_PLATFORM, 'string'), + allowClear: true, + }, + rules: 'required', + }, + { + fieldName: 'type', + label: '模型类型', + component: 'Select', + componentProps: (values) => { + return { + placeholder: '请输入模型类型', + disabled: !!values.id, + options: getDictOptions(DICT_TYPE.AI_MODEL_TYPE, 'number'), + allowClear: true, + }; + }, + rules: 'required', + }, + { + fieldName: 'keyId', + label: 'API 秘钥', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择 API 秘钥', + api: getApiKeySimpleList, + labelField: 'name', + valueField: 'id', + allowClear: true, + }, + rules: 'required', + }, + { + component: 'Input', + fieldName: 'name', + label: '模型名字', + rules: 'required', + componentProps: { + placeholder: '请输入模型名字', + }, + }, + { + component: 'Input', + fieldName: 'model', + label: '模型标识', + rules: 'required', + componentProps: { + placeholder: '请输入模型标识', + }, + }, + { + fieldName: 'sort', + label: '模型排序', + component: 'InputNumber', + componentProps: { + placeholder: '请输入模型排序', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '开启状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'temperature', + label: '温度参数', + component: 'InputNumber', + componentProps: { + placeholder: '请输入温度参数', + min: 0, + max: 2, + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['type'], + show: (values) => { + return [AiModelTypeEnum.CHAT].includes(values.type); + }, + }, + rules: 'required', + }, + { + fieldName: 'maxTokens', + label: '回复数 Token 数', + component: 'InputNumber', + componentProps: { + min: 0, + max: 8192, + placeholder: '请输入回复数 Token 数', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['type'], + show: (values) => { + return [AiModelTypeEnum.CHAT].includes(values.type); + }, + }, + rules: 'required', + }, + { + fieldName: 'maxContexts', + label: '上下文数量', + component: 'InputNumber', + componentProps: { + min: 0, + max: 20, + placeholder: '请输入上下文数量', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['type'], + show: (values) => { + return [AiModelTypeEnum.CHAT].includes(values.type); + }, + }, + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '模型名字', + component: 'Input', + componentProps: { + placeholder: '请输入模型名字', + allowClear: true, + }, + }, + { + fieldName: 'model', + label: '模型标识', + component: 'Input', + componentProps: { + placeholder: '请输入模型标识', + allowClear: true, + }, + }, + { + fieldName: 'platform', + label: '模型平台', + component: 'Input', + componentProps: { + placeholder: '请输入模型平台', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'platform', + title: '所属平台', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_PLATFORM }, + }, + minWidth: 100, + }, + { + field: 'type', + title: '模型类型', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_MODEL_TYPE }, + }, + minWidth: 100, + }, + { + field: 'name', + title: '模型名字', + minWidth: 180, + }, + { + title: '模型标识', + field: 'model', + minWidth: 180, + }, + { + title: 'API 秘钥', + field: 'keyId', + formatter: ({ cellValue }) => { + return ( + apiKeyList.find((apiKey) => apiKey.id === cellValue)?.name || '-' + ); + }, + minWidth: 140, + }, + { + title: '排序', + field: 'sort', + minWidth: 80, + }, + { + field: 'status', + title: '状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + minWidth: 80, + }, + { + field: 'temperature', + title: '温度参数', + minWidth: 100, + }, + { + title: '回复数 Token 数', + field: 'maxTokens', + minWidth: 140, + }, + { + title: '上下文数量', + field: 'maxContexts', + minWidth: 120, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/model/model/index.vue b/apps/web-ele/src/views/ai/model/model/index.vue new file mode 100644 index 0000000..0448809 --- /dev/null +++ b/apps/web-ele/src/views/ai/model/model/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-ele/src/views/ai/model/model/modules/form.vue b/apps/web-ele/src/views/ai/model/model/modules/form.vue new file mode 100644 index 0000000..10727a6 --- /dev/null +++ b/apps/web-ele/src/views/ai/model/model/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/ai/model/tool/data.ts b/apps/web-ele/src/views/ai/model/tool/data.ts new file mode 100644 index 0000000..d8897ed --- /dev/null +++ b/apps/web-ele/src/views/ai/model/tool/data.ts @@ -0,0 +1,123 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + + { + component: 'Input', + fieldName: 'name', + label: '工具名称', + rules: 'required', + componentProps: { + placeholder: '请输入工具名称', + }, + }, + { + component: 'Textarea', + fieldName: 'description', + label: '工具描述', + componentProps: { + placeholder: '请输入工具描述', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + defaultValue: CommonStatusEnum.ENABLE, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '工具名称', + component: 'Input', + componentProps: { + placeholder: '请输入工具名称', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + allowClear: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '工具编号', + minWidth: 100, + }, + { + field: 'name', + title: '工具名称', + minWidth: 120, + }, + { + field: 'description', + title: '工具描述', + minWidth: 140, + }, + { + field: 'status', + title: '状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + minWidth: 80, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/model/tool/index.vue b/apps/web-ele/src/views/ai/model/tool/index.vue new file mode 100644 index 0000000..18c2dd3 --- /dev/null +++ b/apps/web-ele/src/views/ai/model/tool/index.vue @@ -0,0 +1,131 @@ + + + diff --git a/apps/web-ele/src/views/ai/model/tool/modules/form.vue b/apps/web-ele/src/views/ai/model/tool/modules/form.vue new file mode 100644 index 0000000..afe7c21 --- /dev/null +++ b/apps/web-ele/src/views/ai/model/tool/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/ai/music/index/index.vue b/apps/web-ele/src/views/ai/music/index/index.vue new file mode 100644 index 0000000..af00e18 --- /dev/null +++ b/apps/web-ele/src/views/ai/music/index/index.vue @@ -0,0 +1,29 @@ + + + diff --git a/apps/web-ele/src/views/ai/music/index/list/audioBar/index.vue b/apps/web-ele/src/views/ai/music/index/list/audioBar/index.vue new file mode 100644 index 0000000..961620a --- /dev/null +++ b/apps/web-ele/src/views/ai/music/index/list/audioBar/index.vue @@ -0,0 +1,99 @@ + + + diff --git a/apps/web-ele/src/views/ai/music/index/list/index.vue b/apps/web-ele/src/views/ai/music/index/list/index.vue new file mode 100644 index 0000000..1e0dde3 --- /dev/null +++ b/apps/web-ele/src/views/ai/music/index/list/index.vue @@ -0,0 +1,100 @@ + + + + diff --git a/apps/web-ele/src/views/ai/music/index/list/songCard/index.vue b/apps/web-ele/src/views/ai/music/index/list/songCard/index.vue new file mode 100644 index 0000000..2d7bdb6 --- /dev/null +++ b/apps/web-ele/src/views/ai/music/index/list/songCard/index.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/ai/music/index/list/songInfo/index.vue b/apps/web-ele/src/views/ai/music/index/list/songInfo/index.vue new file mode 100644 index 0000000..eb4fbc8 --- /dev/null +++ b/apps/web-ele/src/views/ai/music/index/list/songInfo/index.vue @@ -0,0 +1,25 @@ + + + diff --git a/apps/web-ele/src/views/ai/music/index/mode/desc.vue b/apps/web-ele/src/views/ai/music/index/mode/desc.vue new file mode 100644 index 0000000..bcf9a01 --- /dev/null +++ b/apps/web-ele/src/views/ai/music/index/mode/desc.vue @@ -0,0 +1,66 @@ + + + diff --git a/apps/web-ele/src/views/ai/music/index/mode/index.vue b/apps/web-ele/src/views/ai/music/index/mode/index.vue new file mode 100644 index 0000000..813ea73 --- /dev/null +++ b/apps/web-ele/src/views/ai/music/index/mode/index.vue @@ -0,0 +1,38 @@ + + + diff --git a/apps/web-ele/src/views/ai/music/index/mode/lyric.vue b/apps/web-ele/src/views/ai/music/index/mode/lyric.vue new file mode 100644 index 0000000..c64f915 --- /dev/null +++ b/apps/web-ele/src/views/ai/music/index/mode/lyric.vue @@ -0,0 +1,107 @@ + + + diff --git a/apps/web-ele/src/views/ai/music/index/title/index.vue b/apps/web-ele/src/views/ai/music/index/title/index.vue new file mode 100644 index 0000000..04dc58b --- /dev/null +++ b/apps/web-ele/src/views/ai/music/index/title/index.vue @@ -0,0 +1,27 @@ + + + diff --git a/apps/web-ele/src/views/ai/music/manager/data.ts b/apps/web-ele/src/views/ai/music/manager/data.ts new file mode 100644 index 0000000..7b5c63a --- /dev/null +++ b/apps/web-ele/src/views/ai/music/manager/data.ts @@ -0,0 +1,202 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemUserApi } from '#/api/system/user'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 关联数据 */ +let userList: SystemUserApi.User[] = []; +getSimpleUserList().then((data) => (userList = data)); + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择用户编号', + clearable: true, + }, + }, + { + fieldName: 'title', + label: '音乐名称', + component: 'Input', + componentProps: { + placeholder: '请输入音乐名称', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '绘画状态', + component: 'Select', + componentProps: { + placeholder: '请选择绘画状态', + clearable: true, + options: getDictOptions(DICT_TYPE.AI_MUSIC_STATUS, 'number'), + }, + }, + { + fieldName: 'generateMode', + label: '生成模式', + component: 'Select', + componentProps: { + placeholder: '请选择生成模式', + clearable: true, + options: getDictOptions(DICT_TYPE.AI_GENERATE_MODE, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'publicStatus', + label: '是否发布', + component: 'Select', + componentProps: { + placeholder: '请选择是否发布', + clearable: true, + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onPublicStatusChange?: ( + newStatus: boolean, + row: any, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 180, + fixed: 'left', + }, + { + title: '音乐名称', + minWidth: 180, + fixed: 'left', + field: 'title', + }, + { + minWidth: 180, + title: '用户', + field: 'userId', + formatter: ({ cellValue }) => { + return userList.find((user) => user.id === cellValue)?.nickname || '-'; + }, + }, + { + field: 'status', + title: '音乐状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_MUSIC_STATUS }, + }, + }, + { + field: 'model', + title: '模型', + minWidth: 180, + }, + { + title: '内容', + minWidth: 180, + slots: { default: 'content' }, + }, + { + field: 'duration', + title: '时长(秒)', + minWidth: 100, + }, + { + field: 'prompt', + title: '提示词', + minWidth: 180, + }, + { + field: 'lyric', + title: '歌词', + minWidth: 180, + }, + { + field: 'gptDescriptionPrompt', + title: '描述', + minWidth: 180, + }, + { + field: 'generateMode', + title: '生成模式', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_GENERATE_MODE }, + }, + }, + { + field: 'tags', + title: '风格标签', + minWidth: 180, + cellRender: { + name: 'CellTags', + }, + }, + { + minWidth: 100, + title: '是否发布', + field: 'publicStatus', + align: 'center', + cellRender: { + attrs: { beforeChange: onPublicStatusChange }, + name: 'CellSwitch', + props: { + activeValue: true, + inactiveValue: false, + }, + }, + }, + { + field: 'taskId', + title: '任务编号', + minWidth: 180, + }, + { + field: 'errorMessage', + title: '错误信息', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/music/manager/index.vue b/apps/web-ele/src/views/ai/music/manager/index.vue new file mode 100644 index 0000000..d0e04cb --- /dev/null +++ b/apps/web-ele/src/views/ai/music/manager/index.vue @@ -0,0 +1,152 @@ + + + diff --git a/apps/web-ele/src/views/ai/workflow/data.ts b/apps/web-ele/src/views/ai/workflow/data.ts new file mode 100644 index 0000000..5decf9f --- /dev/null +++ b/apps/web-ele/src/views/ai/workflow/data.ts @@ -0,0 +1,97 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'code', + label: '流程标识', + component: 'Input', + componentProps: { + placeholder: '请输入流程标识', + allowClear: true, + }, + }, + { + fieldName: 'name', + label: '流程名称', + component: 'Input', + componentProps: { + placeholder: '请输入流程名称', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'code', + title: '流程标识', + minWidth: 150, + }, + { + field: 'name', + title: '流程名称', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/workflow/form/index.vue b/apps/web-ele/src/views/ai/workflow/form/index.vue new file mode 100644 index 0000000..ca206ff --- /dev/null +++ b/apps/web-ele/src/views/ai/workflow/form/index.vue @@ -0,0 +1,288 @@ + + + diff --git a/apps/web-ele/src/views/ai/workflow/form/modules/basic-info.vue b/apps/web-ele/src/views/ai/workflow/form/modules/basic-info.vue new file mode 100644 index 0000000..09f8725 --- /dev/null +++ b/apps/web-ele/src/views/ai/workflow/form/modules/basic-info.vue @@ -0,0 +1,70 @@ + + + diff --git a/apps/web-ele/src/views/ai/workflow/form/modules/workflow-design.vue b/apps/web-ele/src/views/ai/workflow/form/modules/workflow-design.vue new file mode 100644 index 0000000..3acb5ad --- /dev/null +++ b/apps/web-ele/src/views/ai/workflow/form/modules/workflow-design.vue @@ -0,0 +1,286 @@ + + + diff --git a/apps/web-ele/src/views/ai/workflow/index.vue b/apps/web-ele/src/views/ai/workflow/index.vue new file mode 100644 index 0000000..ab31d47 --- /dev/null +++ b/apps/web-ele/src/views/ai/workflow/index.vue @@ -0,0 +1,124 @@ + + + diff --git a/apps/web-ele/src/views/ai/write/index/index.vue b/apps/web-ele/src/views/ai/write/index/index.vue new file mode 100644 index 0000000..04b5514 --- /dev/null +++ b/apps/web-ele/src/views/ai/write/index/index.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/ai/write/index/modules/left.vue b/apps/web-ele/src/views/ai/write/index/modules/left.vue new file mode 100644 index 0000000..a364265 --- /dev/null +++ b/apps/web-ele/src/views/ai/write/index/modules/left.vue @@ -0,0 +1,250 @@ + + + diff --git a/apps/web-ele/src/views/ai/write/index/modules/right.vue b/apps/web-ele/src/views/ai/write/index/modules/right.vue new file mode 100644 index 0000000..bd0a468 --- /dev/null +++ b/apps/web-ele/src/views/ai/write/index/modules/right.vue @@ -0,0 +1,144 @@ + + + + diff --git a/apps/web-ele/src/views/ai/write/index/modules/tag.vue b/apps/web-ele/src/views/ai/write/index/modules/tag.vue new file mode 100644 index 0000000..ed758fc --- /dev/null +++ b/apps/web-ele/src/views/ai/write/index/modules/tag.vue @@ -0,0 +1,33 @@ + + + + diff --git a/apps/web-ele/src/views/ai/write/manager/data.ts b/apps/web-ele/src/views/ai/write/manager/data.ts new file mode 100644 index 0000000..02f39e8 --- /dev/null +++ b/apps/web-ele/src/views/ai/write/manager/data.ts @@ -0,0 +1,171 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemUserApi } from '#/api/system/user'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 关联数据 */ +let userList: SystemUserApi.User[] = []; +getSimpleUserList().then((data) => (userList = data)); + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择用户', + allowClear: true, + }, + }, + { + fieldName: 'type', + label: '写作类型', + component: 'Select', + componentProps: { + allowClear: true, + placeholder: '请选择写作类型', + options: getDictOptions(DICT_TYPE.AI_WRITE_TYPE, 'number'), + }, + }, + { + fieldName: 'platform', + label: '平台', + component: 'Select', + componentProps: { + allowClear: true, + placeholder: '请选择平台', + options: getDictOptions(DICT_TYPE.AI_PLATFORM, 'string'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 180, + fixed: 'left', + }, + { + minWidth: 180, + title: '用户', + field: 'userId', + formatter: ({ cellValue }) => { + return userList.find((user) => user.id === cellValue)?.nickname || '-'; + }, + }, + { + field: 'type', + title: '写作类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_WRITE_TYPE }, + }, + }, + { + field: 'platform', + title: '平台', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_WRITE_TYPE }, + }, + }, + { + field: 'model', + title: '模型', + minWidth: 180, + }, + { + field: 'prompt', + title: '生成内容提示', + minWidth: 180, + }, + { + field: 'generatedContent', + title: '生成的内容', + minWidth: 180, + }, + { + field: 'originalContent', + title: '原文', + minWidth: 180, + }, + { + field: 'length', + title: '长度', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_WRITE_LENGTH }, + }, + }, + { + field: 'format', + title: '格式', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_WRITE_FORMAT }, + }, + }, + { + field: 'tone', + title: '语气', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_WRITE_TONE }, + }, + }, + { + field: 'language', + title: '语言', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.AI_WRITE_LANGUAGE }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'errorMessage', + title: '错误信息', + minWidth: 180, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/ai/write/manager/index.vue b/apps/web-ele/src/views/ai/write/manager/index.vue new file mode 100644 index 0000000..fa73240 --- /dev/null +++ b/apps/web-ele/src/views/ai/write/manager/index.vue @@ -0,0 +1,90 @@ + + + diff --git a/apps/web-ele/src/views/bpm/category/data.ts b/apps/web-ele/src/views/bpm/category/data.ts new file mode 100644 index 0000000..6aaf6e6 --- /dev/null +++ b/apps/web-ele/src/views/bpm/category/data.ts @@ -0,0 +1,178 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '分类名', + component: 'Input', + componentProps: { + placeholder: '请输入分类名', + }, + rules: 'required', + }, + { + label: '分类标志', + fieldName: 'code', + component: 'Input', + componentProps: { + placeholder: '请输入分类标志', + }, + rules: 'required', + }, + { + fieldName: 'description', + label: '分类描述', + component: 'Textarea', + componentProps: { + placeholder: '请输入分类描述', + }, + }, + { + fieldName: 'status', + label: '分类状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'sort', + label: '分类排序', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入分类排序', + controlsPosition: 'right', + class: '!w-full', + }, + }, + ]; +} + +/** 重命名的表单 */ +export function useRenameFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '分类名', + component: 'Input', + componentProps: { + placeholder: '请输入分类名', + }, + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '分类名', + component: 'Input', + componentProps: { + placeholder: '请输入分类名', + allowClear: true, + }, + }, + { + fieldName: 'code', + label: '分类标志', + component: 'Input', + componentProps: { + placeholder: '请输入分类标志', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '分类状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择分类状态', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '分类编号', + minWidth: 100, + }, + { + field: 'name', + title: '分类名', + minWidth: 200, + }, + { + field: 'code', + title: '分类标志', + minWidth: 200, + }, + { + field: 'description', + title: '分类描述', + minWidth: 200, + }, + { + field: 'status', + title: '分类状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'sort', + title: '分类排序', + minWidth: 100, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/category/index.vue b/apps/web-ele/src/views/bpm/category/index.vue new file mode 100644 index 0000000..c747e8a --- /dev/null +++ b/apps/web-ele/src/views/bpm/category/index.vue @@ -0,0 +1,129 @@ + + + diff --git a/apps/web-ele/src/views/bpm/category/modules/form.vue b/apps/web-ele/src/views/bpm/category/modules/form.vue new file mode 100644 index 0000000..4494d9d --- /dev/null +++ b/apps/web-ele/src/views/bpm/category/modules/form.vue @@ -0,0 +1,86 @@ + + + diff --git a/apps/web-ele/src/views/bpm/category/modules/rename-form.vue b/apps/web-ele/src/views/bpm/category/modules/rename-form.vue new file mode 100644 index 0000000..5882fe9 --- /dev/null +++ b/apps/web-ele/src/views/bpm/category/modules/rename-form.vue @@ -0,0 +1,80 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/index.ts b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/index.ts new file mode 100644 index 0000000..411e2ce --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/index.ts @@ -0,0 +1,2 @@ +// 导出 BPMN 流程设计器相关组件 +export * from './package'; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/ProcessDesigner.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/ProcessDesigner.vue new file mode 100644 index 0000000..e77301f --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/ProcessDesigner.vue @@ -0,0 +1,683 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/ProcessViewer.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/ProcessViewer.vue new file mode 100644 index 0000000..881f70a --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/ProcessViewer.vue @@ -0,0 +1,427 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/index.ts b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/index.ts new file mode 100644 index 0000000..cc2dc24 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/index.ts @@ -0,0 +1,8 @@ +import MyProcessDesigner from './ProcessDesigner.vue'; + +MyProcessDesigner.install = function (Vue: any) { + Vue.component(MyProcessDesigner.name, MyProcessDesigner); +}; + +// 流程图的设计器,可编辑 +export default MyProcessDesigner; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/index2.ts b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/index2.ts new file mode 100644 index 0000000..9f085a7 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/index2.ts @@ -0,0 +1,8 @@ +import MyProcessViewer from './ProcessViewer.vue'; + +MyProcessViewer.install = function (Vue: any) { + Vue.component(MyProcessViewer.name, MyProcessViewer); +}; + +// 流程图的查看器,不可编辑 +export default MyProcessViewer; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/content-pad/contentPadProvider.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/content-pad/contentPadProvider.js new file mode 100644 index 0000000..638317f --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/content-pad/contentPadProvider.js @@ -0,0 +1,443 @@ +import { getChildLanes } from 'bpmn-js/lib/features/modeling/util/LaneUtil'; +import { isAny } from 'bpmn-js/lib/features/modeling/util/ModelingUtil'; +import { isEventSubProcess, isExpanded } from 'bpmn-js/lib/util/DiUtil'; +import { is } from 'bpmn-js/lib/util/ModelUtil'; +import { hasPrimaryModifier } from 'diagram-js/lib/util/Mouse'; + +/** + * A provider for BPMN 2.0 elements context pad + */ +export default function ContextPadProvider( + config, + injector, + eventBus, + contextPad, + modeling, + elementFactory, + connect, + create, + popupMenu, + canvas, + rules, + translate, +) { + config = config || {}; + + contextPad.registerProvider(this); + + this._contextPad = contextPad; + + this._modeling = modeling; + + this._elementFactory = elementFactory; + this._connect = connect; + this._create = create; + this._popupMenu = popupMenu; + this._canvas = canvas; + this._rules = rules; + this._translate = translate; + + if (config.autoPlace !== false) { + this._autoPlace = injector.get('autoPlace', false); + } + + eventBus.on('create.end', 250, (event) => { + const context = event.context; + const shape = context.shape; + + if (!hasPrimaryModifier(event) || !contextPad.isOpen(shape)) { + return; + } + + const entries = contextPad.getEntries(shape); + + if (entries.replace) { + entries.replace.action.click(event, shape); + } + }); +} + +ContextPadProvider.$inject = [ + 'config.contextPad', + 'injector', + 'eventBus', + 'contextPad', + 'modeling', + 'elementFactory', + 'connect', + 'create', + 'popupMenu', + 'canvas', + 'rules', + 'translate', + 'elementRegistry', +]; + +ContextPadProvider.prototype.getContextPadEntries = function (element) { + const autoPlace = this._autoPlace; + const canvas = this._canvas; + const connect = this._connect; + const contextPad = this._contextPad; + const create = this._create; + const elementFactory = this._elementFactory; + const modeling = this._modeling; + const popupMenu = this._popupMenu; + const rules = this._rules; + const translate = this._translate; + + const actions = {}; + + if (element.type === 'label') { + return actions; + } + + const businessObject = element.businessObject; + + function startConnect(event, element) { + connect.start(event, element); + } + + function removeElement() { + modeling.removeElements([element]); + } + + function getReplaceMenuPosition(element) { + const Y_OFFSET = 5; + + const diagramContainer = canvas.getContainer(); + const pad = contextPad.getPad(element).html; + + const diagramRect = diagramContainer.getBoundingClientRect(); + const padRect = pad.getBoundingClientRect(); + + const top = padRect.top - diagramRect.top; + const left = padRect.left - diagramRect.left; + + const pos = { + x: left, + y: top + padRect.height + Y_OFFSET, + }; + + return pos; + } + + /** + * Create an append action + * + * @param {string} type + * @param {string} className + * @param {string} [title] + * @param {object} [options] + * + * @return {object} descriptor + */ + function appendAction(type, className, title, options) { + if (typeof title !== 'string') { + options = title; + title = translate('Append {type}', { type: type.replace(/^bpmn:/, '') }); + } + + function appendStart(event, element) { + const shape = elementFactory.createShape( + Object.assign({ type }, options), + ); + create.start(event, shape, { + source: element, + }); + } + + const append = autoPlace + ? function (event, element) { + const shape = elementFactory.createShape( + Object.assign({ type }, options), + ); + + autoPlace.append(element, shape); + } + : appendStart; + + return { + group: 'model', + className, + title, + action: { + dragstart: appendStart, + click: append, + }, + }; + } + + function splitLaneHandler(count) { + return function (event, element) { + // actual split + modeling.splitLane(element, count); + + // refresh context pad after split to + // get rid of split icons + contextPad.open(element, true); + }; + } + + if ( + isAny(businessObject, ['bpmn:Lane', 'bpmn:Participant']) && + isExpanded(businessObject) + ) { + const childLanes = getChildLanes(element); + + Object.assign(actions, { + 'lane-insert-above': { + group: 'lane-insert-above', + className: 'bpmn-icon-lane-insert-above', + title: translate('Add Lane above'), + action: { + click(event, element) { + modeling.addLane(element, 'top'); + }, + }, + }, + }); + + if (childLanes.length < 2) { + if (element.height >= 120) { + Object.assign(actions, { + 'lane-divide-two': { + group: 'lane-divide', + className: 'bpmn-icon-lane-divide-two', + title: translate('Divide into two Lanes'), + action: { + click: splitLaneHandler(2), + }, + }, + }); + } + + if (element.height >= 180) { + Object.assign(actions, { + 'lane-divide-three': { + group: 'lane-divide', + className: 'bpmn-icon-lane-divide-three', + title: translate('Divide into three Lanes'), + action: { + click: splitLaneHandler(3), + }, + }, + }); + } + } + + Object.assign(actions, { + 'lane-insert-below': { + group: 'lane-insert-below', + className: 'bpmn-icon-lane-insert-below', + title: translate('Add Lane below'), + action: { + click(event, element) { + modeling.addLane(element, 'bottom'); + }, + }, + }, + }); + } + + if (is(businessObject, 'bpmn:FlowNode')) { + if (is(businessObject, 'bpmn:EventBasedGateway')) { + Object.assign(actions, { + 'append.receive-task': appendAction( + 'bpmn:ReceiveTask', + 'bpmn-icon-receive-task', + translate('Append ReceiveTask'), + ), + 'append.message-intermediate-event': appendAction( + 'bpmn:IntermediateCatchEvent', + 'bpmn-icon-intermediate-event-catch-message', + translate('Append MessageIntermediateCatchEvent'), + { eventDefinitionType: 'bpmn:MessageEventDefinition' }, + ), + 'append.timer-intermediate-event': appendAction( + 'bpmn:IntermediateCatchEvent', + 'bpmn-icon-intermediate-event-catch-timer', + translate('Append TimerIntermediateCatchEvent'), + { eventDefinitionType: 'bpmn:TimerEventDefinition' }, + ), + 'append.condition-intermediate-event': appendAction( + 'bpmn:IntermediateCatchEvent', + 'bpmn-icon-intermediate-event-catch-condition', + translate('Append ConditionIntermediateCatchEvent'), + { eventDefinitionType: 'bpmn:ConditionalEventDefinition' }, + ), + 'append.signal-intermediate-event': appendAction( + 'bpmn:IntermediateCatchEvent', + 'bpmn-icon-intermediate-event-catch-signal', + translate('Append SignalIntermediateCatchEvent'), + { eventDefinitionType: 'bpmn:SignalEventDefinition' }, + ), + }); + } else if ( + isEventType( + businessObject, + 'bpmn:BoundaryEvent', + 'bpmn:CompensateEventDefinition', + ) + ) { + Object.assign(actions, { + 'append.compensation-activity': appendAction( + 'bpmn:Task', + 'bpmn-icon-task', + translate('Append compensation activity'), + { + isForCompensation: true, + }, + ), + }); + } else if ( + !is(businessObject, 'bpmn:EndEvent') && + !businessObject.isForCompensation && + !isEventType( + businessObject, + 'bpmn:IntermediateThrowEvent', + 'bpmn:LinkEventDefinition', + ) && + !isEventSubProcess(businessObject) + ) { + Object.assign(actions, { + 'append.end-event': appendAction( + 'bpmn:EndEvent', + 'bpmn-icon-end-event-none', + translate('Append EndEvent'), + ), + 'append.gateway': appendAction( + 'bpmn:ExclusiveGateway', + 'bpmn-icon-gateway-none', + translate('Append Gateway'), + ), + 'append.append-task': appendAction( + 'bpmn:UserTask', + 'bpmn-icon-user-task', + translate('Append Task'), + ), + 'append.intermediate-event': appendAction( + 'bpmn:IntermediateThrowEvent', + 'bpmn-icon-intermediate-event-none', + translate('Append Intermediate/Boundary Event'), + ), + }); + } + } + + if (!popupMenu.isEmpty(element, 'bpmn-replace')) { + // Replace menu entry + Object.assign(actions, { + replace: { + group: 'edit', + className: 'bpmn-icon-screw-wrench', + title: '修改类型', + action: { + click(event, element) { + const position = Object.assign(getReplaceMenuPosition(element), { + cursor: { x: event.x, y: event.y }, + }); + + popupMenu.open(element, 'bpmn-replace', position); + }, + }, + }, + }); + } + + if ( + isAny(businessObject, [ + 'bpmn:FlowNode', + 'bpmn:InteractionNode', + 'bpmn:DataObjectReference', + 'bpmn:DataStoreReference', + ]) + ) { + Object.assign(actions, { + 'append.text-annotation': appendAction( + 'bpmn:TextAnnotation', + 'bpmn-icon-text-annotation', + ), + + connect: { + group: 'connect', + className: 'bpmn-icon-connection-multi', + title: translate( + `Connect using ${ + businessObject.isForCompensation ? '' : 'Sequence/MessageFlow or ' + }Association`, + ), + action: { + click: startConnect, + dragstart: startConnect, + }, + }, + }); + } + + if ( + isAny(businessObject, [ + 'bpmn:DataObjectReference', + 'bpmn:DataStoreReference', + ]) + ) { + Object.assign(actions, { + connect: { + group: 'connect', + className: 'bpmn-icon-connection-multi', + title: translate('Connect using DataInputAssociation'), + action: { + click: startConnect, + dragstart: startConnect, + }, + }, + }); + } + + if (is(businessObject, 'bpmn:Group')) { + Object.assign(actions, { + 'append.text-annotation': appendAction( + 'bpmn:TextAnnotation', + 'bpmn-icon-text-annotation', + ), + }); + } + + // delete element entry, only show if allowed by rules + let deleteAllowed = rules.allowed('elements.delete', { elements: [element] }); + + if (Array.isArray(deleteAllowed)) { + // was the element returned as a deletion candidate? + deleteAllowed = deleteAllowed[0] === element; + } + + if (deleteAllowed) { + Object.assign(actions, { + delete: { + group: 'edit', + className: 'bpmn-icon-trash', + title: translate('Remove'), + action: { + click: removeElement, + }, + }, + }); + } + + return actions; +}; + +// helpers ///////// + +function isEventType(eventBo, type, definition) { + const isType = eventBo.$instanceOf(type); + let isDefinition = false; + + const definitions = eventBo.eventDefinitions || []; + definitions.forEach((def) => { + if (def.$type === definition) { + isDefinition = true; + } + }); + + return isType && isDefinition; +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/content-pad/index.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/content-pad/index.js new file mode 100644 index 0000000..d5325ae --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/content-pad/index.js @@ -0,0 +1,6 @@ +import CustomContextPadProvider from './contentPadProvider'; + +export default { + __init__: ['contextPadProvider'], + contextPadProvider: ['type', CustomContextPadProvider], +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/defaultEmpty.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/defaultEmpty.js new file mode 100644 index 0000000..5c25d8e --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/defaultEmpty.js @@ -0,0 +1,26 @@ +function defaultEmpty(key, name, type) { + if (!type) type = 'camunda'; + const TYPE_TARGET = { + activiti: 'http://activiti.org/bpmn', + camunda: 'http://bpmn.io/schema/bpmn', + flowable: 'http://flowable.org/bpmn', + }; + return ` + + + + + + + +`; +} + +export default defaultEmpty; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/descriptor/activitiDescriptor.json b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/descriptor/activitiDescriptor.json new file mode 100644 index 0000000..8797852 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/descriptor/activitiDescriptor.json @@ -0,0 +1,1007 @@ +{ + "name": "Activiti", + "uri": "http://activiti.org/bpmn", + "prefix": "activiti", + "xml": { + "tagAlias": "lowerCase" + }, + "associations": [], + "types": [ + { + "name": "Definitions", + "isAbstract": true, + "extends": ["bpmn:Definitions"], + "properties": [ + { + "name": "diagramRelationId", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "InOutBinding", + "superClass": ["Element"], + "isAbstract": true, + "properties": [ + { + "name": "source", + "isAttr": true, + "type": "String" + }, + { + "name": "sourceExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "target", + "isAttr": true, + "type": "String" + }, + { + "name": "businessKey", + "isAttr": true, + "type": "String" + }, + { + "name": "local", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "variables", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "In", + "superClass": ["InOutBinding"], + "meta": { + "allowedIn": ["bpmn:CallActivity"] + } + }, + { + "name": "Out", + "superClass": ["InOutBinding"], + "meta": { + "allowedIn": ["bpmn:CallActivity"] + } + }, + { + "name": "AsyncCapable", + "isAbstract": true, + "extends": ["bpmn:Activity", "bpmn:Gateway", "bpmn:Event"], + "properties": [ + { + "name": "async", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "asyncBefore", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "asyncAfter", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "exclusive", + "isAttr": true, + "type": "Boolean", + "default": true + } + ] + }, + { + "name": "JobPriorized", + "isAbstract": true, + "extends": ["bpmn:Process", "activiti:AsyncCapable"], + "properties": [ + { + "name": "jobPriority", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "SignalEventDefinition", + "isAbstract": true, + "extends": ["bpmn:SignalEventDefinition"], + "properties": [ + { + "name": "async", + "isAttr": true, + "type": "Boolean", + "default": false + } + ] + }, + { + "name": "ErrorEventDefinition", + "isAbstract": true, + "extends": ["bpmn:ErrorEventDefinition"], + "properties": [ + { + "name": "errorCodeVariable", + "isAttr": true, + "type": "String" + }, + { + "name": "errorMessageVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Error", + "isAbstract": true, + "extends": ["bpmn:Error"], + "properties": [ + { + "name": "activiti:errorMessage", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "PotentialStarter", + "superClass": ["Element"], + "properties": [ + { + "name": "resourceAssignmentExpression", + "type": "bpmn:ResourceAssignmentExpression" + } + ] + }, + { + "name": "FormSupported", + "isAbstract": true, + "extends": ["bpmn:StartEvent", "bpmn:UserTask"], + "properties": [ + { + "name": "formHandlerClass", + "isAttr": true, + "type": "String" + }, + { + "name": "formKey", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "TemplateSupported", + "isAbstract": true, + "extends": ["bpmn:Process", "bpmn:FlowElement"], + "properties": [ + { + "name": "modelerTemplate", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Initiator", + "isAbstract": true, + "extends": ["bpmn:StartEvent"], + "properties": [ + { + "name": "initiator", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "ScriptTask", + "isAbstract": true, + "extends": ["bpmn:ScriptTask"], + "properties": [ + { + "name": "resultVariable", + "isAttr": true, + "type": "String" + }, + { + "name": "resource", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Process", + "isAbstract": true, + "extends": ["bpmn:Process"], + "properties": [ + { + "name": "candidateStarterGroups", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateStarterUsers", + "isAttr": true, + "type": "String" + }, + { + "name": "versionTag", + "isAttr": true, + "type": "String" + }, + { + "name": "historyTimeToLive", + "isAttr": true, + "type": "String" + }, + { + "name": "isStartableInTasklist", + "isAttr": true, + "type": "Boolean", + "default": true + }, + { + "name": "executionListener", + "isAbstract": true, + "type": "Expression" + } + ] + }, + { + "name": "EscalationEventDefinition", + "isAbstract": true, + "extends": ["bpmn:EscalationEventDefinition"], + "properties": [ + { + "name": "escalationCodeVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "FormalExpression", + "isAbstract": true, + "extends": ["bpmn:FormalExpression"], + "properties": [ + { + "name": "resource", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "multiinstance_type", + "superClass": ["Element"] + }, + { + "name": "multiinstance_condition", + "superClass": ["Element"] + }, + { + "name": "Assignable", + "extends": ["bpmn:UserTask"], + "properties": [ + { + "name": "assignee", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateUsers", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateGroups", + "isAttr": true, + "type": "String" + }, + { + "name": "dueDate", + "isAttr": true, + "type": "String" + }, + { + "name": "followUpDate", + "isAttr": true, + "type": "String" + }, + { + "name": "priority", + "isAttr": true, + "type": "String" + }, + { + "name": "multiinstance_condition", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateStrategy", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateParam", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "CallActivity", + "extends": ["bpmn:CallActivity"], + "properties": [ + { + "name": "calledElementBinding", + "isAttr": true, + "type": "String", + "default": "latest" + }, + { + "name": "calledElementVersion", + "isAttr": true, + "type": "String" + }, + { + "name": "calledElementVersionTag", + "isAttr": true, + "type": "String" + }, + { + "name": "calledElementTenantId", + "isAttr": true, + "type": "String" + }, + { + "name": "caseRef", + "isAttr": true, + "type": "String" + }, + { + "name": "caseBinding", + "isAttr": true, + "type": "String", + "default": "latest" + }, + { + "name": "caseVersion", + "isAttr": true, + "type": "String" + }, + { + "name": "caseTenantId", + "isAttr": true, + "type": "String" + }, + { + "name": "variableMappingClass", + "isAttr": true, + "type": "String" + }, + { + "name": "variableMappingDelegateExpression", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "ServiceTaskLike", + "extends": [ + "bpmn:ServiceTask", + "bpmn:BusinessRuleTask", + "bpmn:SendTask", + "bpmn:MessageEventDefinition" + ], + "properties": [ + { + "name": "expression", + "isAttr": true, + "type": "String" + }, + { + "name": "class", + "isAttr": true, + "type": "String" + }, + { + "name": "delegateExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "resultVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "DmnCapable", + "extends": ["bpmn:BusinessRuleTask"], + "properties": [ + { + "name": "decisionRef", + "isAttr": true, + "type": "String" + }, + { + "name": "decisionRefBinding", + "isAttr": true, + "type": "String", + "default": "latest" + }, + { + "name": "decisionRefVersion", + "isAttr": true, + "type": "String" + }, + { + "name": "mapDecisionResult", + "isAttr": true, + "type": "String", + "default": "resultList" + }, + { + "name": "decisionRefTenantId", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "ExternalCapable", + "extends": ["activiti:ServiceTaskLike"], + "properties": [ + { + "name": "type", + "isAttr": true, + "type": "String" + }, + { + "name": "topic", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "TaskPriorized", + "extends": ["bpmn:Process", "activiti:ExternalCapable"], + "properties": [ + { + "name": "taskPriority", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Properties", + "superClass": ["Element"], + "meta": { + "allowedIn": ["*"] + }, + "properties": [ + { + "name": "values", + "type": "Property", + "isMany": true + } + ] + }, + { + "name": "Property", + "superClass": ["Element"], + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "value", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "Connector", + "superClass": ["Element"], + "meta": { + "allowedIn": ["activiti:ServiceTaskLike"] + }, + "properties": [ + { + "name": "inputOutput", + "type": "InputOutput" + }, + { + "name": "connectorId", + "type": "String" + } + ] + }, + { + "name": "InputOutput", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:FlowNode", "activiti:Connector"] + }, + "properties": [ + { + "name": "inputOutput", + "type": "InputOutput" + }, + { + "name": "connectorId", + "type": "String" + }, + { + "name": "inputParameters", + "isMany": true, + "type": "InputParameter" + }, + { + "name": "outputParameters", + "isMany": true, + "type": "OutputParameter" + } + ] + }, + { + "name": "InputOutputParameter", + "properties": [ + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + }, + { + "name": "definition", + "type": "InputOutputParameterDefinition" + } + ] + }, + { + "name": "InputOutputParameterDefinition", + "isAbstract": true + }, + { + "name": "List", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "items", + "isMany": true, + "type": "InputOutputParameterDefinition" + } + ] + }, + { + "name": "Map", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "entries", + "isMany": true, + "type": "Entry" + } + ] + }, + { + "name": "Entry", + "properties": [ + { + "name": "key", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + }, + { + "name": "definition", + "type": "InputOutputParameterDefinition" + } + ] + }, + { + "name": "Value", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "id", + "isAttr": true, + "type": "String" + }, + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + } + ] + }, + { + "name": "Script", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "scriptFormat", + "isAttr": true, + "type": "String" + }, + { + "name": "resource", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + } + ] + }, + { + "name": "Field", + "superClass": ["Element"], + "meta": { + "allowedIn": [ + "activiti:ServiceTaskLike", + "activiti:ExecutionListener", + "activiti:TaskListener" + ] + }, + "properties": [ + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "expression", + "type": "String" + }, + { + "name": "stringValue", + "isAttr": true, + "type": "String" + }, + { + "name": "string", + "type": "String" + } + ] + }, + { + "name": "InputParameter", + "superClass": ["InputOutputParameter"] + }, + { + "name": "OutputParameter", + "superClass": ["InputOutputParameter"] + }, + { + "name": "Collectable", + "isAbstract": true, + "extends": ["bpmn:MultiInstanceLoopCharacteristics"], + "superClass": ["activiti:AsyncCapable"], + "properties": [ + { + "name": "collection", + "isAttr": true, + "type": "String" + }, + { + "name": "elementVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "FailedJobRetryTimeCycle", + "superClass": ["Element"], + "meta": { + "allowedIn": [ + "activiti:AsyncCapable", + "bpmn:MultiInstanceLoopCharacteristics" + ] + }, + "properties": [ + { + "name": "body", + "isBody": true, + "type": "String" + } + ] + }, + { + "name": "ExecutionListener", + "superClass": ["Element"], + "meta": { + "allowedIn": [ + "bpmn:Task", + "bpmn:ServiceTask", + "bpmn:UserTask", + "bpmn:BusinessRuleTask", + "bpmn:ScriptTask", + "bpmn:ReceiveTask", + "bpmn:ManualTask", + "bpmn:ExclusiveGateway", + "bpmn:SequenceFlow", + "bpmn:ParallelGateway", + "bpmn:InclusiveGateway", + "bpmn:EventBasedGateway", + "bpmn:StartEvent", + "bpmn:IntermediateCatchEvent", + "bpmn:IntermediateThrowEvent", + "bpmn:EndEvent", + "bpmn:BoundaryEvent", + "bpmn:CallActivity", + "bpmn:SubProcess", + "bpmn:Process" + ] + }, + "properties": [ + { + "name": "expression", + "isAttr": true, + "type": "String" + }, + { + "name": "class", + "isAttr": true, + "type": "String" + }, + { + "name": "delegateExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "event", + "isAttr": true, + "type": "String" + }, + { + "name": "script", + "type": "Script" + }, + { + "name": "fields", + "type": "Field", + "isMany": true + } + ] + }, + { + "name": "TaskListener", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "expression", + "isAttr": true, + "type": "String" + }, + { + "name": "class", + "isAttr": true, + "type": "String" + }, + { + "name": "delegateExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "event", + "isAttr": true, + "type": "String" + }, + { + "name": "script", + "type": "Script" + }, + { + "name": "fields", + "type": "Field", + "isMany": true + } + ] + }, + { + "name": "FormProperty", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"] + }, + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "type", + "type": "String", + "isAttr": true + }, + { + "name": "required", + "type": "String", + "isAttr": true + }, + { + "name": "readable", + "type": "String", + "isAttr": true + }, + { + "name": "writable", + "type": "String", + "isAttr": true + }, + { + "name": "variable", + "type": "String", + "isAttr": true + }, + { + "name": "expression", + "type": "String", + "isAttr": true + }, + { + "name": "datePattern", + "type": "String", + "isAttr": true + }, + { + "name": "default", + "type": "String", + "isAttr": true + }, + { + "name": "values", + "type": "Value", + "isMany": true + } + ] + }, + { + "name": "FormProperty", + "superClass": ["Element"], + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "label", + "type": "String", + "isAttr": true + }, + { + "name": "type", + "type": "String", + "isAttr": true + }, + { + "name": "datePattern", + "type": "String", + "isAttr": true + }, + { + "name": "defaultValue", + "type": "String", + "isAttr": true + }, + { + "name": "properties", + "type": "Properties" + }, + { + "name": "validation", + "type": "Validation" + }, + { + "name": "values", + "type": "Value", + "isMany": true + } + ] + }, + { + "name": "Validation", + "superClass": ["Element"], + "properties": [ + { + "name": "constraints", + "type": "Constraint", + "isMany": true + } + ] + }, + { + "name": "Constraint", + "superClass": ["Element"], + "properties": [ + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "config", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "ConditionalEventDefinition", + "isAbstract": true, + "extends": ["bpmn:ConditionalEventDefinition"], + "properties": [ + { + "name": "variableName", + "isAttr": true, + "type": "String" + }, + { + "name": "variableEvent", + "isAttr": true, + "type": "String" + } + ] + } + ], + "emumerations": [] +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/descriptor/camundaDescriptor.json b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/descriptor/camundaDescriptor.json new file mode 100644 index 0000000..18fe802 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/descriptor/camundaDescriptor.json @@ -0,0 +1,1023 @@ +{ + "name": "Camunda", + "uri": "http://camunda.org/schema/1.0/bpmn", + "prefix": "camunda", + "xml": { + "tagAlias": "lowerCase" + }, + "associations": [], + "types": [ + { + "name": "Definitions", + "isAbstract": true, + "extends": ["bpmn:Definitions"], + "properties": [ + { + "name": "diagramRelationId", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "InOutBinding", + "superClass": ["Element"], + "isAbstract": true, + "properties": [ + { + "name": "source", + "isAttr": true, + "type": "String" + }, + { + "name": "sourceExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "target", + "isAttr": true, + "type": "String" + }, + { + "name": "businessKey", + "isAttr": true, + "type": "String" + }, + { + "name": "local", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "variables", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "In", + "superClass": ["InOutBinding"], + "meta": { + "allowedIn": ["bpmn:CallActivity", "bpmn:SignalEventDefinition"] + } + }, + { + "name": "Out", + "superClass": ["InOutBinding"], + "meta": { + "allowedIn": ["bpmn:CallActivity"] + } + }, + { + "name": "AsyncCapable", + "isAbstract": true, + "extends": ["bpmn:Activity", "bpmn:Gateway", "bpmn:Event"], + "properties": [ + { + "name": "async", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "asyncBefore", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "asyncAfter", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "exclusive", + "isAttr": true, + "type": "Boolean", + "default": true + } + ] + }, + { + "name": "JobPriorized", + "isAbstract": true, + "extends": ["bpmn:Process", "camunda:AsyncCapable"], + "properties": [ + { + "name": "jobPriority", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "SignalEventDefinition", + "isAbstract": true, + "extends": ["bpmn:SignalEventDefinition"], + "properties": [ + { + "name": "async", + "isAttr": true, + "type": "Boolean", + "default": false + } + ] + }, + { + "name": "ErrorEventDefinition", + "isAbstract": true, + "extends": ["bpmn:ErrorEventDefinition"], + "properties": [ + { + "name": "errorCodeVariable", + "isAttr": true, + "type": "String" + }, + { + "name": "errorMessageVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Error", + "isAbstract": true, + "extends": ["bpmn:Error"], + "properties": [ + { + "name": "camunda:errorMessage", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "PotentialStarter", + "superClass": ["Element"], + "properties": [ + { + "name": "resourceAssignmentExpression", + "type": "bpmn:ResourceAssignmentExpression" + } + ] + }, + { + "name": "FormSupported", + "isAbstract": true, + "extends": ["bpmn:StartEvent", "bpmn:UserTask"], + "properties": [ + { + "name": "formHandlerClass", + "isAttr": true, + "type": "String" + }, + { + "name": "formKey", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "TemplateSupported", + "isAbstract": true, + "extends": ["bpmn:Process", "bpmn:FlowElement"], + "properties": [ + { + "name": "modelerTemplate", + "isAttr": true, + "type": "String" + }, + { + "name": "modelerTemplateVersion", + "isAttr": true, + "type": "Integer" + } + ] + }, + { + "name": "Initiator", + "isAbstract": true, + "extends": ["bpmn:StartEvent"], + "properties": [ + { + "name": "initiator", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "ScriptTask", + "isAbstract": true, + "extends": ["bpmn:ScriptTask"], + "properties": [ + { + "name": "resultVariable", + "isAttr": true, + "type": "String" + }, + { + "name": "resource", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Process", + "isAbstract": true, + "extends": ["bpmn:Process"], + "properties": [ + { + "name": "candidateStarterGroups", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateStarterUsers", + "isAttr": true, + "type": "String" + }, + { + "name": "versionTag", + "isAttr": true, + "type": "String" + }, + { + "name": "historyTimeToLive", + "isAttr": true, + "type": "String" + }, + { + "name": "isStartableInTasklist", + "isAttr": true, + "type": "Boolean", + "default": true + } + ] + }, + { + "name": "EscalationEventDefinition", + "isAbstract": true, + "extends": ["bpmn:EscalationEventDefinition"], + "properties": [ + { + "name": "escalationCodeVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "FormalExpression", + "isAbstract": true, + "extends": ["bpmn:FormalExpression"], + "properties": [ + { + "name": "resource", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Assignable", + "extends": ["bpmn:UserTask"], + "properties": [ + { + "name": "assignee", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateUsers", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateGroups", + "isAttr": true, + "type": "String" + }, + { + "name": "dueDate", + "isAttr": true, + "type": "String" + }, + { + "name": "followUpDate", + "isAttr": true, + "type": "String" + }, + { + "name": "priority", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateStrategy", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateParam", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "CallActivity", + "extends": ["bpmn:CallActivity"], + "properties": [ + { + "name": "calledElementBinding", + "isAttr": true, + "type": "String", + "default": "latest" + }, + { + "name": "calledElementVersion", + "isAttr": true, + "type": "String" + }, + { + "name": "calledElementVersionTag", + "isAttr": true, + "type": "String" + }, + { + "name": "calledElementTenantId", + "isAttr": true, + "type": "String" + }, + { + "name": "caseRef", + "isAttr": true, + "type": "String" + }, + { + "name": "caseBinding", + "isAttr": true, + "type": "String", + "default": "latest" + }, + { + "name": "caseVersion", + "isAttr": true, + "type": "String" + }, + { + "name": "caseTenantId", + "isAttr": true, + "type": "String" + }, + { + "name": "variableMappingClass", + "isAttr": true, + "type": "String" + }, + { + "name": "variableMappingDelegateExpression", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "ServiceTaskLike", + "extends": [ + "bpmn:ServiceTask", + "bpmn:BusinessRuleTask", + "bpmn:SendTask", + "bpmn:MessageEventDefinition" + ], + "properties": [ + { + "name": "expression", + "isAttr": true, + "type": "String" + }, + { + "name": "class", + "isAttr": true, + "type": "String" + }, + { + "name": "delegateExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "resultVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "DmnCapable", + "extends": ["bpmn:BusinessRuleTask"], + "properties": [ + { + "name": "decisionRef", + "isAttr": true, + "type": "String" + }, + { + "name": "decisionRefBinding", + "isAttr": true, + "type": "String", + "default": "latest" + }, + { + "name": "decisionRefVersion", + "isAttr": true, + "type": "String" + }, + { + "name": "mapDecisionResult", + "isAttr": true, + "type": "String", + "default": "resultList" + }, + { + "name": "decisionRefTenantId", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "ExternalCapable", + "extends": ["camunda:ServiceTaskLike"], + "properties": [ + { + "name": "type", + "isAttr": true, + "type": "String" + }, + { + "name": "topic", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "TaskPriorized", + "extends": ["bpmn:Process", "camunda:ExternalCapable"], + "properties": [ + { + "name": "taskPriority", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Properties", + "superClass": ["Element"], + "meta": { + "allowedIn": ["*"] + }, + "properties": [ + { + "name": "values", + "type": "Property", + "isMany": true + } + ] + }, + { + "name": "Property", + "superClass": ["Element"], + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "value", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "Connector", + "superClass": ["Element"], + "meta": { + "allowedIn": ["camunda:ServiceTaskLike"] + }, + "properties": [ + { + "name": "inputOutput", + "type": "InputOutput" + }, + { + "name": "connectorId", + "type": "String" + } + ] + }, + { + "name": "InputOutput", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:FlowNode", "camunda:Connector"] + }, + "properties": [ + { + "name": "inputOutput", + "type": "InputOutput" + }, + { + "name": "connectorId", + "type": "String" + }, + { + "name": "inputParameters", + "isMany": true, + "type": "InputParameter" + }, + { + "name": "outputParameters", + "isMany": true, + "type": "OutputParameter" + } + ] + }, + { + "name": "InputOutputParameter", + "properties": [ + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + }, + { + "name": "definition", + "type": "InputOutputParameterDefinition" + } + ] + }, + { + "name": "InputOutputParameterDefinition", + "isAbstract": true + }, + { + "name": "List", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "items", + "isMany": true, + "type": "InputOutputParameterDefinition" + } + ] + }, + { + "name": "Map", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "entries", + "isMany": true, + "type": "Entry" + } + ] + }, + { + "name": "Entry", + "properties": [ + { + "name": "key", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + }, + { + "name": "definition", + "type": "InputOutputParameterDefinition" + } + ] + }, + { + "name": "Value", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "id", + "isAttr": true, + "type": "String" + }, + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + } + ] + }, + { + "name": "Script", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "scriptFormat", + "isAttr": true, + "type": "String" + }, + { + "name": "resource", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + } + ] + }, + { + "name": "Field", + "superClass": ["Element"], + "meta": { + "allowedIn": [ + "camunda:ServiceTaskLike", + "camunda:ExecutionListener", + "camunda:TaskListener" + ] + }, + "properties": [ + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "expression", + "type": "String" + }, + { + "name": "stringValue", + "isAttr": true, + "type": "String" + }, + { + "name": "string", + "type": "String" + } + ] + }, + { + "name": "InputParameter", + "superClass": ["InputOutputParameter"] + }, + { + "name": "OutputParameter", + "superClass": ["InputOutputParameter"] + }, + { + "name": "Collectable", + "isAbstract": true, + "extends": ["bpmn:MultiInstanceLoopCharacteristics"], + "superClass": ["camunda:AsyncCapable"], + "properties": [ + { + "name": "collection", + "isAttr": true, + "type": "String" + }, + { + "name": "elementVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "FailedJobRetryTimeCycle", + "superClass": ["Element"], + "meta": { + "allowedIn": [ + "camunda:AsyncCapable", + "bpmn:MultiInstanceLoopCharacteristics" + ] + }, + "properties": [ + { + "name": "body", + "isBody": true, + "type": "String" + } + ] + }, + { + "name": "ExecutionListener", + "superClass": ["Element"], + "meta": { + "allowedIn": [ + "bpmn:Task", + "bpmn:ServiceTask", + "bpmn:UserTask", + "bpmn:BusinessRuleTask", + "bpmn:ScriptTask", + "bpmn:ReceiveTask", + "bpmn:ManualTask", + "bpmn:ExclusiveGateway", + "bpmn:SequenceFlow", + "bpmn:ParallelGateway", + "bpmn:InclusiveGateway", + "bpmn:EventBasedGateway", + "bpmn:StartEvent", + "bpmn:IntermediateCatchEvent", + "bpmn:IntermediateThrowEvent", + "bpmn:EndEvent", + "bpmn:BoundaryEvent", + "bpmn:CallActivity", + "bpmn:SubProcess", + "bpmn:Process" + ] + }, + "properties": [ + { + "name": "expression", + "isAttr": true, + "type": "String" + }, + { + "name": "class", + "isAttr": true, + "type": "String" + }, + { + "name": "delegateExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "event", + "isAttr": true, + "type": "String" + }, + { + "name": "script", + "type": "Script" + }, + { + "name": "fields", + "type": "Field", + "isMany": true + } + ] + }, + { + "name": "TaskListener", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "expression", + "isAttr": true, + "type": "String" + }, + { + "name": "class", + "isAttr": true, + "type": "String" + }, + { + "name": "delegateExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "event", + "isAttr": true, + "type": "String" + }, + { + "name": "script", + "type": "Script" + }, + { + "name": "fields", + "type": "Field", + "isMany": true + }, + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "eventDefinitions", + "type": "bpmn:TimerEventDefinition", + "isMany": true + } + ] + }, + { + "name": "FormProperty", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"] + }, + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "type", + "type": "String", + "isAttr": true + }, + { + "name": "required", + "type": "String", + "isAttr": true + }, + { + "name": "readable", + "type": "String", + "isAttr": true + }, + { + "name": "writable", + "type": "String", + "isAttr": true + }, + { + "name": "variable", + "type": "String", + "isAttr": true + }, + { + "name": "expression", + "type": "String", + "isAttr": true + }, + { + "name": "datePattern", + "type": "String", + "isAttr": true + }, + { + "name": "default", + "type": "String", + "isAttr": true + }, + { + "name": "values", + "type": "Value", + "isMany": true + } + ] + }, + { + "name": "FormData", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"] + }, + "properties": [ + { + "name": "fields", + "type": "FormField", + "isMany": true + }, + { + "name": "businessKey", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "FormField", + "superClass": ["Element"], + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "label", + "type": "String", + "isAttr": true + }, + { + "name": "type", + "type": "String", + "isAttr": true + }, + { + "name": "datePattern", + "type": "String", + "isAttr": true + }, + { + "name": "defaultValue", + "type": "String", + "isAttr": true + }, + { + "name": "properties", + "type": "Properties" + }, + { + "name": "validation", + "type": "Validation" + }, + { + "name": "values", + "type": "Value", + "isMany": true + } + ] + }, + { + "name": "Validation", + "superClass": ["Element"], + "properties": [ + { + "name": "constraints", + "type": "Constraint", + "isMany": true + } + ] + }, + { + "name": "Constraint", + "superClass": ["Element"], + "properties": [ + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "config", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "ConditionalEventDefinition", + "isAbstract": true, + "extends": ["bpmn:ConditionalEventDefinition"], + "properties": [ + { + "name": "variableName", + "isAttr": true, + "type": "String" + }, + { + "name": "variableEvents", + "isAttr": true, + "type": "String" + } + ] + } + ], + "emumerations": [] +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/descriptor/flowableDescriptor.json b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/descriptor/flowableDescriptor.json new file mode 100644 index 0000000..2a929bd --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/descriptor/flowableDescriptor.json @@ -0,0 +1,1496 @@ +{ + "name": "Flowable", + "uri": "http://flowable.org/bpmn", + "prefix": "flowable", + "xml": { + "tagAlias": "lowerCase" + }, + "associations": [], + "types": [ + { + "name": "InOutBinding", + "superClass": ["Element"], + "isAbstract": true, + "properties": [ + { + "name": "source", + "isAttr": true, + "type": "String" + }, + { + "name": "sourceExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "target", + "isAttr": true, + "type": "String" + }, + { + "name": "businessKey", + "isAttr": true, + "type": "String" + }, + { + "name": "local", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "variables", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "In", + "superClass": ["InOutBinding"], + "meta": { + "allowedIn": ["bpmn:CallActivity"] + } + }, + { + "name": "Out", + "superClass": ["InOutBinding"], + "meta": { + "allowedIn": ["bpmn:CallActivity"] + } + }, + { + "name": "AsyncCapable", + "isAbstract": true, + "extends": ["bpmn:Activity", "bpmn:Gateway", "bpmn:Event"], + "properties": [ + { + "name": "async", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "asyncBefore", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "asyncAfter", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "exclusive", + "isAttr": true, + "type": "Boolean", + "default": true + } + ] + }, + { + "name": "JobPriorized", + "isAbstract": true, + "extends": ["bpmn:Process", "flowable:AsyncCapable"], + "properties": [ + { + "name": "jobPriority", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "SignalEventDefinition", + "isAbstract": true, + "extends": ["bpmn:SignalEventDefinition"], + "properties": [ + { + "name": "async", + "isAttr": true, + "type": "Boolean", + "default": false + } + ] + }, + { + "name": "ErrorEventDefinition", + "isAbstract": true, + "extends": ["bpmn:ErrorEventDefinition"], + "properties": [ + { + "name": "errorCodeVariable", + "isAttr": true, + "type": "String" + }, + { + "name": "errorMessageVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Error", + "isAbstract": true, + "extends": ["bpmn:Error"], + "properties": [ + { + "name": "flowable:errorMessage", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "PotentialStarter", + "superClass": ["Element"], + "properties": [ + { + "name": "resourceAssignmentExpression", + "type": "bpmn:ResourceAssignmentExpression" + } + ] + }, + { + "name": "FormSupported", + "isAbstract": true, + "extends": ["bpmn:StartEvent", "bpmn:UserTask"], + "properties": [ + { + "name": "formHandlerClass", + "isAttr": true, + "type": "String" + }, + { + "name": "formKey", + "isAttr": true, + "type": "String" + }, + { + "name": "formType", + "isAttr": true, + "type": "String" + }, + { + "name": "formReadOnly", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "formInit", + "isAttr": true, + "type": "Boolean", + "default": true + } + ] + }, + { + "name": "TemplateSupported", + "isAbstract": true, + "extends": ["bpmn:Process", "bpmn:FlowElement"], + "properties": [ + { + "name": "modelerTemplate", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Initiator", + "isAbstract": true, + "extends": ["bpmn:StartEvent"], + "properties": [ + { + "name": "initiator", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "ScriptTask", + "isAbstract": true, + "extends": ["bpmn:ScriptTask"], + "properties": [ + { + "name": "resultVariable", + "isAttr": true, + "type": "String" + }, + { + "name": "resource", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Process", + "isAbstract": true, + "extends": ["bpmn:Process"], + "properties": [ + { + "name": "candidateStarterGroups", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateStarterUsers", + "isAttr": true, + "type": "String" + }, + { + "name": "versionTag", + "isAttr": true, + "type": "String" + }, + { + "name": "historyTimeToLive", + "isAttr": true, + "type": "String" + }, + { + "name": "isStartableInTasklist", + "isAttr": true, + "type": "Boolean", + "default": true + } + ] + }, + { + "name": "EscalationEventDefinition", + "isAbstract": true, + "extends": ["bpmn:EscalationEventDefinition"], + "properties": [ + { + "name": "escalationCodeVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "FormalExpression", + "isAbstract": true, + "extends": ["bpmn:FormalExpression"], + "properties": [ + { + "name": "resource", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Assignable", + "extends": ["bpmn:UserTask"], + "properties": [ + { + "name": "assignee", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateUsers", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateGroups", + "isAttr": true, + "type": "String" + }, + { + "name": "dueDate", + "isAttr": true, + "type": "String" + }, + { + "name": "followUpDate", + "isAttr": true, + "type": "String" + }, + { + "name": "priority", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateStrategy", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateParam", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Assignee", + "supperClass": "Element", + "meta": { + "allowedIn": ["*"] + }, + "properties": [ + { + "name": "label", + "type": "String", + "isAttr": true + }, + { + "name": "viewId", + "type": "Number", + "isAttr": true + } + ] + }, + { + "name": "CallActivity", + "extends": ["bpmn:CallActivity"], + "properties": [ + { + "name": "calledElementBinding", + "isAttr": true, + "type": "String", + "default": "latest" + }, + { + "name": "calledElementVersion", + "isAttr": true, + "type": "String" + }, + { + "name": "calledElementVersionTag", + "isAttr": true, + "type": "String" + }, + { + "name": "calledElementTenantId", + "isAttr": true, + "type": "String" + }, + { + "name": "caseRef", + "isAttr": true, + "type": "String" + }, + { + "name": "caseBinding", + "isAttr": true, + "type": "String", + "default": "latest" + }, + { + "name": "caseVersion", + "isAttr": true, + "type": "String" + }, + { + "name": "caseTenantId", + "isAttr": true, + "type": "String" + }, + { + "name": "variableMappingClass", + "isAttr": true, + "type": "String" + }, + { + "name": "variableMappingDelegateExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "calledElementType", + "isAttr": true, + "type": "String" + }, + { + "name": "processInstanceName", + "isAttr": true, + "type": "String" + }, + { + "name": "inheritBusinessKey", + "isAttr": true, + "type": "Boolean" + }, + { + "name": "businessKey", + "isAttr": true, + "type": "String" + }, + { + "name": "inheritVariables", + "isAttr": true, + "type": "Boolean" + } + ] + }, + { + "name": "ServiceTaskLike", + "extends": [ + "bpmn:ServiceTask", + "bpmn:BusinessRuleTask", + "bpmn:SendTask", + "bpmn:MessageEventDefinition" + ], + "properties": [ + { + "name": "expression", + "isAttr": true, + "type": "String" + }, + { + "name": "class", + "isAttr": true, + "type": "String" + }, + { + "name": "delegateExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "resultVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "DmnCapable", + "extends": ["bpmn:BusinessRuleTask"], + "properties": [ + { + "name": "decisionRef", + "isAttr": true, + "type": "String" + }, + { + "name": "decisionRefBinding", + "isAttr": true, + "type": "String", + "default": "latest" + }, + { + "name": "decisionRefVersion", + "isAttr": true, + "type": "String" + }, + { + "name": "mapDecisionResult", + "isAttr": true, + "type": "String", + "default": "resultList" + }, + { + "name": "decisionRefTenantId", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "ExternalCapable", + "extends": ["flowable:ServiceTaskLike"], + "properties": [ + { + "name": "type", + "isAttr": true, + "type": "String" + }, + { + "name": "topic", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "TaskPriorized", + "extends": ["bpmn:Process", "flowable:ExternalCapable"], + "properties": [ + { + "name": "taskPriority", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Properties", + "superClass": ["Element"], + "meta": { + "allowedIn": ["*"] + }, + "properties": [ + { + "name": "values", + "type": "Property", + "isMany": true + } + ] + }, + { + "name": "Property", + "superClass": ["Element"], + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "value", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "Button", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "code", + "type": "String", + "isAttr": true + }, + { + "name": "isHide", + "type": "String", + "isAttr": true + }, + { + "name": "next", + "type": "String", + "isAttr": true + }, + { + "name": "sort", + "type": "Integer", + "isAttr": true + } + ] + }, + { + "name": "Assignee", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "type", + "type": "String", + "isAttr": true + }, + { + "name": "value", + "type": "String", + "isAttr": true + }, + { + "name": "condition", + "type": "String", + "isAttr": true + }, + { + "name": "operationType", + "type": "String", + "isAttr": true + }, + { + "name": "sort", + "type": "Integer", + "isAttr": true + } + ] + }, + { + "name": "Connector", + "superClass": ["Element"], + "meta": { + "allowedIn": ["flowable:ServiceTaskLike"] + }, + "properties": [ + { + "name": "inputOutput", + "type": "InputOutput" + }, + { + "name": "connectorId", + "type": "String" + } + ] + }, + { + "name": "InputOutput", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:FlowNode", "flowable:Connector"] + }, + "properties": [ + { + "name": "inputOutput", + "type": "InputOutput" + }, + { + "name": "connectorId", + "type": "String" + }, + { + "name": "inputParameters", + "isMany": true, + "type": "InputParameter" + }, + { + "name": "outputParameters", + "isMany": true, + "type": "OutputParameter" + } + ] + }, + { + "name": "InputOutputParameter", + "properties": [ + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + }, + { + "name": "definition", + "type": "InputOutputParameterDefinition" + } + ] + }, + { + "name": "InputOutputParameterDefinition", + "isAbstract": true + }, + { + "name": "List", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "items", + "isMany": true, + "type": "InputOutputParameterDefinition" + } + ] + }, + { + "name": "Map", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "entries", + "isMany": true, + "type": "Entry" + } + ] + }, + { + "name": "Entry", + "properties": [ + { + "name": "key", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + }, + { + "name": "definition", + "type": "InputOutputParameterDefinition" + } + ] + }, + { + "name": "Value", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "id", + "isAttr": true, + "type": "String" + }, + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + } + ] + }, + { + "name": "Script", + "superClass": ["InputOutputParameterDefinition"], + "properties": [ + { + "name": "scriptFormat", + "isAttr": true, + "type": "String" + }, + { + "name": "resource", + "isAttr": true, + "type": "String" + }, + { + "name": "value", + "isBody": true, + "type": "String" + } + ] + }, + { + "name": "Field", + "superClass": ["Element"], + "meta": { + "allowedIn": [ + "flowable:ServiceTaskLike", + "flowable:ExecutionListener", + "flowable:TaskListener" + ] + }, + "properties": [ + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "expression", + "type": "String" + }, + { + "name": "stringValue", + "isAttr": true, + "type": "String" + }, + { + "name": "string", + "type": "String" + } + ] + }, + { + "name": "ChildField", + "superClass": ["Element"], + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "type", + "type": "String", + "isAttr": true + }, + { + "name": "required", + "type": "String", + "isAttr": true + }, + { + "name": "readable", + "type": "String", + "isAttr": true + }, + { + "name": "writable", + "type": "String", + "isAttr": true + }, + { + "name": "variable", + "type": "String", + "isAttr": true + }, + { + "name": "expression", + "type": "String", + "isAttr": true + }, + { + "name": "datePattern", + "type": "String", + "isAttr": true + }, + { + "name": "default", + "type": "String", + "isAttr": true + }, + { + "name": "values", + "type": "Value", + "isMany": true + } + ] + }, + { + "name": "InputParameter", + "superClass": ["InputOutputParameter"] + }, + { + "name": "OutputParameter", + "superClass": ["InputOutputParameter"] + }, + { + "name": "Collectable", + "isAbstract": true, + "extends": ["bpmn:MultiInstanceLoopCharacteristics"], + "superClass": ["flowable:AsyncCapable"], + "properties": [ + { + "name": "collection", + "isAttr": true, + "type": "String" + }, + { + "name": "elementVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "FailedJobRetryTimeCycle", + "superClass": ["Element"], + "meta": { + "allowedIn": [ + "flowable:AsyncCapable", + "bpmn:MultiInstanceLoopCharacteristics" + ] + }, + "properties": [ + { + "name": "body", + "isBody": true, + "type": "String" + } + ] + }, + { + "name": "ExecutionListener", + "superClass": ["Element"], + "meta": { + "allowedIn": [ + "bpmn:Task", + "bpmn:ServiceTask", + "bpmn:UserTask", + "bpmn:BusinessRuleTask", + "bpmn:ScriptTask", + "bpmn:ReceiveTask", + "bpmn:ManualTask", + "bpmn:ExclusiveGateway", + "bpmn:SequenceFlow", + "bpmn:ParallelGateway", + "bpmn:InclusiveGateway", + "bpmn:EventBasedGateway", + "bpmn:StartEvent", + "bpmn:IntermediateCatchEvent", + "bpmn:IntermediateThrowEvent", + "bpmn:EndEvent", + "bpmn:BoundaryEvent", + "bpmn:CallActivity", + "bpmn:SubProcess", + "bpmn:Process" + ] + }, + "properties": [ + { + "name": "expression", + "isAttr": true, + "type": "String" + }, + { + "name": "class", + "isAttr": true, + "type": "String" + }, + { + "name": "delegateExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "event", + "isAttr": true, + "type": "String" + }, + { + "name": "script", + "type": "Script" + }, + { + "name": "fields", + "type": "Field", + "isMany": true + } + ] + }, + { + "name": "TaskListener", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "expression", + "isAttr": true, + "type": "String" + }, + { + "name": "class", + "isAttr": true, + "type": "String" + }, + { + "name": "delegateExpression", + "isAttr": true, + "type": "String" + }, + { + "name": "event", + "isAttr": true, + "type": "String" + }, + { + "name": "script", + "type": "Script" + }, + { + "name": "fields", + "type": "Field", + "isMany": true + }, + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "eventDefinitions", + "type": "bpmn:TimerEventDefinition", + "isMany": true + } + ] + }, + { + "name": "FormProperty", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"] + }, + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "type", + "type": "String", + "isAttr": true + }, + { + "name": "required", + "type": "String", + "isAttr": true + }, + { + "name": "readable", + "type": "String", + "isAttr": true + }, + { + "name": "writable", + "type": "String", + "isAttr": true + }, + { + "name": "variable", + "type": "String", + "isAttr": true + }, + { + "name": "expression", + "type": "String", + "isAttr": true + }, + { + "name": "datePattern", + "type": "String", + "isAttr": true + }, + { + "name": "default", + "type": "String", + "isAttr": true + }, + { + "name": "values", + "type": "Value", + "isMany": true + }, + { + "name": "children", + "type": "ChildField", + "isMany": true + }, + { + "name": "extensionElements", + "type": "bpmn:ExtensionElements", + "isMany": true + } + ] + }, + { + "name": "FormData", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"] + }, + "properties": [ + { + "name": "fields", + "type": "FormField", + "isMany": true + }, + { + "name": "businessKey", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "FormField", + "superClass": ["Element"], + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "label", + "type": "String", + "isAttr": true + }, + { + "name": "type", + "type": "String", + "isAttr": true + }, + { + "name": "datePattern", + "type": "String", + "isAttr": true + }, + { + "name": "defaultValue", + "type": "String", + "isAttr": true + }, + { + "name": "properties", + "type": "Properties" + }, + { + "name": "validation", + "type": "Validation" + }, + { + "name": "values", + "type": "Value", + "isMany": true + } + ] + }, + { + "name": "Validation", + "superClass": ["Element"], + "properties": [ + { + "name": "constraints", + "type": "Constraint", + "isMany": true + } + ] + }, + { + "name": "Constraint", + "superClass": ["Element"], + "properties": [ + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "config", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "ConditionalEventDefinition", + "isAbstract": true, + "extends": ["bpmn:ConditionalEventDefinition"], + "properties": [ + { + "name": "variableName", + "isAttr": true, + "type": "String" + }, + { + "name": "variableEvent", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Condition", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:SequenceFlow"] + }, + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "field", + "type": "String", + "isAttr": true + }, + { + "name": "compare", + "type": "String", + "isAttr": true + }, + { + "name": "value", + "type": "String", + "isAttr": true + }, + { + "name": "logic", + "type": "String", + "isAttr": true + }, + { + "name": "sort", + "type": "Integer", + "isAttr": true + } + ] + }, + { + "name": "AssignStartUserHandlerType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "RejectHandlerType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "RejectReturnTaskId", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "String", + "isBody": true + } + ] + }, + { + "name": "AssignEmptyHandlerType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "AssignEmptyUserIds", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "String", + "isBody": true + } + ] + }, + { + "name": "ButtonsSetting", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "flowable:id", + "type": "Integer", + "isAttr": true + }, + { + "name": "flowable:enable", + "type": "Boolean", + "isAttr": true + }, + { + "name": "flowable:displayName", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "FieldsPermission", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "flowable:field", + "type": "String", + "isAttr": true + }, + { + "name": "flowable:title", + "type": "String", + "isAttr": true + }, + { + "name": "flowable:permission", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "BoundaryEventType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:BoundaryEvent"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "TimeoutHandlerType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:BoundaryEvent"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "ApproveType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "ApproveMethod", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "CandidateStrategy", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "CandidateParam", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "String", + "isBody": true + } + ] + }, + { + "name": "SignEnable", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Boolean", + "isBody": true + } + ] + }, + { + "name": "SkipExpression", + "extends": ["bpmn:UserTask"], + "properties": [ + { + "name": "skipExpression", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "ReasonRequire", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Boolean", + "isBody": true + } + ] + } + ], + "emumerations": [] +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/activiti/activitiExtension.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/activiti/activitiExtension.js new file mode 100644 index 0000000..54d5060 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/activiti/activitiExtension.js @@ -0,0 +1,94 @@ +const ALLOWED_TYPES = { + FailedJobRetryTimeCycle: [ + 'bpmn:StartEvent', + 'bpmn:BoundaryEvent', + 'bpmn:IntermediateCatchEvent', + 'bpmn:Activity', + ], + Connector: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'], + Field: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'], +}; + +function is(element, type) { + return ( + element && + typeof element.$instanceOf === 'function' && + element.$instanceOf(type) + ); +} + +function exists(element) { + return element && element.length > 0; +} + +function includesType(collection, type) { + return ( + exists(collection) && + collection.some((element) => { + return is(element, type); + }) + ); +} + +function anyType(element, types) { + return types.some((type) => { + return is(element, type); + }); +} + +function isAllowed(propName, propDescriptor, newElement) { + const name = propDescriptor.name; + const types = ALLOWED_TYPES[name.replace(/activiti:/, '')]; + + return name === propName && anyType(newElement, types); +} + +function ActivitiModdleExtension(eventBus) { + eventBus.on( + 'property.clone', + function (context) { + const newElement = context.newElement; + const propDescriptor = context.propertyDescriptor; + + this.canCloneProperty(newElement, propDescriptor); + }, + this, + ); +} + +ActivitiModdleExtension.$inject = ['eventBus']; + +ActivitiModdleExtension.prototype.canCloneProperty = function ( + newElement, + propDescriptor, +) { + if ( + isAllowed('activiti:FailedJobRetryTimeCycle', propDescriptor, newElement) + ) { + return ( + includesType(newElement.eventDefinitions, 'bpmn:TimerEventDefinition') || + includesType(newElement.eventDefinitions, 'bpmn:SignalEventDefinition') || + is( + newElement.loopCharacteristics, + 'bpmn:MultiInstanceLoopCharacteristics', + ) + ); + } + + if (isAllowed('activiti:Connector', propDescriptor, newElement)) { + return includesType( + newElement.eventDefinitions, + 'bpmn:MessageEventDefinition', + ); + } + + if (isAllowed('activiti:Field', propDescriptor, newElement)) { + return includesType( + newElement.eventDefinitions, + 'bpmn:MessageEventDefinition', + ); + } +}; + +// module.exports = ActivitiModdleExtension; +export default ActivitiModdleExtension; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/activiti/index.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/activiti/index.js new file mode 100644 index 0000000..7c38ff4 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/activiti/index.js @@ -0,0 +1,11 @@ +/* + * @author igdianov + * address https://github.com/igdianov/activiti-bpmn-moddle + * */ + +import activitiExtension from './activitiExtension'; + +export default { + __init__: ['ActivitiModdleExtension'], + ActivitiModdleExtension: ['type', activitiExtension], +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/camunda/extension.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/camunda/extension.js new file mode 100644 index 0000000..3956be6 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/camunda/extension.js @@ -0,0 +1,156 @@ +import { isFunction, isObject } from '@vben/utils'; + +const WILDCARD = '*'; + +function CamundaModdleExtension(eventBus) { + // eslint-disable-next-line unicorn/no-this-assignment, @typescript-eslint/no-this-alias + const self = this; + + eventBus.on('moddleCopy.canCopyProperty', (context) => { + const parent = context.parent; + const property = context.property; + + return self.canCopyProperty(property, parent); + }); +} + +CamundaModdleExtension.$inject = ['eventBus']; + +/** + * Check wether to disallow copying property. + */ +CamundaModdleExtension.prototype.canCopyProperty = function (property, parent) { + // (1) check wether property is allowed in parent + if (isObject(property) && !isAllowedInParent(property, parent)) { + return false; + } + + // (2) check more complex scenarios + + if (is(property, 'camunda:InputOutput') && !this.canHostInputOutput(parent)) { + return false; + } + + if ( + isAny(property, ['camunda:Connector', 'camunda:Field']) && + !this.canHostConnector(parent) + ) { + return false; + } + + if (is(property, 'camunda:In') && !this.canHostIn(parent)) { + return false; + } +}; + +CamundaModdleExtension.prototype.canHostInputOutput = function (parent) { + // allowed in camunda:Connector + const connector = getParent(parent, 'camunda:Connector'); + + if (connector) { + return true; + } + + // special rules inside bpmn:FlowNode + const flowNode = getParent(parent, 'bpmn:FlowNode'); + + if (!flowNode) { + return false; + } + + if ( + isAny(flowNode, ['bpmn:StartEvent', 'bpmn:Gateway', 'bpmn:BoundaryEvent']) + ) { + return false; + } + + return !(is(flowNode, 'bpmn:SubProcess') && flowNode.get('triggeredByEvent')); +}; + +CamundaModdleExtension.prototype.canHostConnector = function (parent) { + const serviceTaskLike = getParent(parent, 'camunda:ServiceTaskLike'); + + if (is(serviceTaskLike, 'bpmn:MessageEventDefinition')) { + // only allow on throw and end events + return ( + getParent(parent, 'bpmn:IntermediateThrowEvent') || + getParent(parent, 'bpmn:EndEvent') + ); + } + + return true; +}; + +CamundaModdleExtension.prototype.canHostIn = function (parent) { + const callActivity = getParent(parent, 'bpmn:CallActivity'); + + if (callActivity) { + return true; + } + + const signalEventDefinition = getParent(parent, 'bpmn:SignalEventDefinition'); + + if (signalEventDefinition) { + // only allow on throw and end events + return ( + getParent(parent, 'bpmn:IntermediateThrowEvent') || + getParent(parent, 'bpmn:EndEvent') + ); + } + + return true; +}; + +// module.exports = CamundaModdleExtension; +export default CamundaModdleExtension; + +// helpers ////////// + +function is(element, type) { + return ( + element && isFunction(element.$instanceOf) && element.$instanceOf(type) + ); +} + +function isAny(element, types) { + return types.some((t) => { + return is(element, t); + }); +} + +function getParent(element, type) { + if (!type) { + return element.$parent; + } + + if (is(element, type)) { + return element; + } + + if (!element.$parent) { + return; + } + + return getParent(element.$parent, type); +} + +function isAllowedInParent(property, parent) { + // (1) find property descriptor + const descriptor = + property.$type && property.$model.getTypeDescriptor(property.$type); + + const allowedIn = descriptor && descriptor.meta && descriptor.meta.allowedIn; + + if (!allowedIn || isWildcard(allowedIn)) { + return true; + } + + // (2) check wether property has parent of allowed type + return allowedIn.some((type) => { + return getParent(parent, type); + }); +} + +function isWildcard(allowedIn) { + return allowedIn.includes(WILDCARD); +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/camunda/index.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/camunda/index.js new file mode 100644 index 0000000..f20d5eb --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/camunda/index.js @@ -0,0 +1,6 @@ +import extension from './extension'; + +export default { + __init__: ['camundaModdleExtension'], + camundaModdleExtension: ['type', extension], +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/flowable/flowableExtension.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/flowable/flowableExtension.js new file mode 100644 index 0000000..25fa1cc --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/flowable/flowableExtension.js @@ -0,0 +1,94 @@ +const ALLOWED_TYPES = { + FailedJobRetryTimeCycle: [ + 'bpmn:StartEvent', + 'bpmn:BoundaryEvent', + 'bpmn:IntermediateCatchEvent', + 'bpmn:Activity', + ], + Connector: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'], + Field: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'], +}; + +function is(element, type) { + return ( + element && + typeof element.$instanceOf === 'function' && + element.$instanceOf(type) + ); +} + +function exists(element) { + return element && element.length > 0; +} + +function includesType(collection, type) { + return ( + exists(collection) && + collection.some((element) => { + return is(element, type); + }) + ); +} + +function anyType(element, types) { + return types.some((type) => { + return is(element, type); + }); +} + +function isAllowed(propName, propDescriptor, newElement) { + const name = propDescriptor.name; + const types = ALLOWED_TYPES[name.replace(/flowable:/, '')]; + + return name === propName && anyType(newElement, types); +} + +function FlowableModdleExtension(eventBus) { + eventBus.on( + 'property.clone', + function (context) { + const newElement = context.newElement; + const propDescriptor = context.propertyDescriptor; + + this.canCloneProperty(newElement, propDescriptor); + }, + this, + ); +} + +FlowableModdleExtension.$inject = ['eventBus']; + +FlowableModdleExtension.prototype.canCloneProperty = function ( + newElement, + propDescriptor, +) { + if ( + isAllowed('flowable:FailedJobRetryTimeCycle', propDescriptor, newElement) + ) { + return ( + includesType(newElement.eventDefinitions, 'bpmn:TimerEventDefinition') || + includesType(newElement.eventDefinitions, 'bpmn:SignalEventDefinition') || + is( + newElement.loopCharacteristics, + 'bpmn:MultiInstanceLoopCharacteristics', + ) + ); + } + + if (isAllowed('flowable:Connector', propDescriptor, newElement)) { + return includesType( + newElement.eventDefinitions, + 'bpmn:MessageEventDefinition', + ); + } + + if (isAllowed('flowable:Field', propDescriptor, newElement)) { + return includesType( + newElement.eventDefinitions, + 'bpmn:MessageEventDefinition', + ); + } +}; + +// module.exports = FlowableModdleExtension; +export default FlowableModdleExtension; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/flowable/index.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/flowable/index.js new file mode 100644 index 0000000..8647467 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/extension-moddle/flowable/index.js @@ -0,0 +1,10 @@ +/* + * @author igdianov + * address https://github.com/igdianov/activiti-bpmn-moddle + * */ +import flowableExtension from './flowableExtension'; + +export default { + __init__: ['FlowableModdleExtension'], + FlowableModdleExtension: ['type', flowableExtension], +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/palette/CustomPalette.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/palette/CustomPalette.js new file mode 100644 index 0000000..75b491c --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/palette/CustomPalette.js @@ -0,0 +1,234 @@ +import PaletteProvider from 'bpmn-js/lib/features/palette/PaletteProvider'; + +export default function CustomPalette( + palette, + create, + elementFactory, + spaceTool, + lassoTool, + handTool, + globalConnect, + translate, +) { + PaletteProvider.call( + this, + palette, + create, + elementFactory, + spaceTool, + lassoTool, + handTool, + globalConnect, + translate, + 2000, + ); +} + +const F = function () {}; // 核心,利用空对象作为中介; +F.prototype = PaletteProvider.prototype; // 核心,将父类的原型赋值给空对象F; + +// 利用中介函数重写原型链方法 +F.prototype.getPaletteEntries = function () { + const actions = {}; + const create = this._create; + const elementFactory = this._elementFactory; + const spaceTool = this._spaceTool; + const lassoTool = this._lassoTool; + const handTool = this._handTool; + const globalConnect = this._globalConnect; + const translate = this._translate; + + function createAction(type, group, className, title, options) { + function createListener(event) { + const shape = Object.assign( + elementFactory.createShape({ type }, options), + ); + + if (options) { + shape.businessObject.di.isExpanded = options.isExpanded; + } + + create.start(event, shape); + } + + const shortType = type.replace(/^bpmn:/, ''); + + return { + group, + className, + title: title || translate('Create {type}', { type: shortType }), + action: { + dragstart: createListener, + click: createListener, + }, + }; + } + + function createSubprocess(event) { + const subProcess = elementFactory.createShape({ + type: 'bpmn:SubProcess', + x: 0, + y: 0, + isExpanded: true, + }); + + const startEvent = elementFactory.createShape({ + type: 'bpmn:StartEvent', + x: 40, + y: 82, + parent: subProcess, + }); + + create.start(event, [subProcess, startEvent], { + hints: { + autoSelect: [startEvent], + }, + }); + } + + function createParticipant(event) { + create.start(event, elementFactory.createParticipantShape()); + } + + Object.assign(actions, { + 'hand-tool': { + group: 'tools', + className: 'bpmn-icon-hand-tool', + title: '激活抓手工具', + // title: translate("Activate the hand tool"), + action: { + click(event) { + handTool.activateHand(event); + }, + }, + }, + 'lasso-tool': { + group: 'tools', + className: 'bpmn-icon-lasso-tool', + title: translate('Activate the lasso tool'), + action: { + click(event) { + lassoTool.activateSelection(event); + }, + }, + }, + 'space-tool': { + group: 'tools', + className: 'bpmn-icon-space-tool', + title: translate('Activate the create/remove space tool'), + action: { + click(event) { + spaceTool.activateSelection(event); + }, + }, + }, + 'global-connect-tool': { + group: 'tools', + className: 'bpmn-icon-connection-multi', + title: translate('Activate the global connect tool'), + action: { + click(event) { + globalConnect.toggle(event); + }, + }, + }, + 'tool-separator': { + group: 'tools', + separator: true, + }, + 'create.start-event': createAction( + 'bpmn:StartEvent', + 'event', + 'bpmn-icon-start-event-none', + translate('Create StartEvent'), + ), + 'create.intermediate-event': createAction( + 'bpmn:IntermediateThrowEvent', + 'event', + 'bpmn-icon-intermediate-event-none', + translate('Create Intermediate/Boundary Event'), + ), + 'create.end-event': createAction( + 'bpmn:EndEvent', + 'event', + 'bpmn-icon-end-event-none', + translate('Create EndEvent'), + ), + 'create.exclusive-gateway': createAction( + 'bpmn:ExclusiveGateway', + 'gateway', + 'bpmn-icon-gateway-none', + translate('Create Gateway'), + ), + 'create.user-task': createAction( + 'bpmn:UserTask', + 'activity', + 'bpmn-icon-user-task', + translate('Create User Task'), + ), + 'create.call-activity': createAction( + 'bpmn:CallActivity', + 'activity', + 'bpmn-icon-call-activity', + translate('Create Call Activity'), + ), + 'create.service-task': createAction( + 'bpmn:ServiceTask', + 'activity', + 'bpmn-icon-service', + translate('Create Service Task'), + ), + 'create.data-object': createAction( + 'bpmn:DataObjectReference', + 'data-object', + 'bpmn-icon-data-object', + translate('Create DataObjectReference'), + ), + 'create.data-store': createAction( + 'bpmn:DataStoreReference', + 'data-store', + 'bpmn-icon-data-store', + translate('Create DataStoreReference'), + ), + 'create.subprocess-expanded': { + group: 'activity', + className: 'bpmn-icon-subprocess-expanded', + title: translate('Create expanded SubProcess'), + action: { + dragstart: createSubprocess, + click: createSubprocess, + }, + }, + 'create.participant-expanded': { + group: 'collaboration', + className: 'bpmn-icon-participant', + title: translate('Create Pool/Participant'), + action: { + dragstart: createParticipant, + click: createParticipant, + }, + }, + 'create.group': createAction( + 'bpmn:Group', + 'artifact', + 'bpmn-icon-group', + translate('Create Group'), + ), + }); + + return actions; +}; + +CustomPalette.$inject = [ + 'palette', + 'create', + 'elementFactory', + 'spaceTool', + 'lassoTool', + 'handTool', + 'globalConnect', + 'translate', +]; + +CustomPalette.prototype = new F(); // 核心,将 F的实例赋值给子类; +CustomPalette.prototype.constructor = CustomPalette; // 修复子类CustomPalette的构造器指向,防止原型链的混乱; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/palette/index.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/palette/index.js new file mode 100644 index 0000000..afe1367 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/palette/index.js @@ -0,0 +1,22 @@ +// import PaletteModule from "diagram-js/lib/features/palette"; +// import CreateModule from "diagram-js/lib/features/create"; +// import SpaceToolModule from "diagram-js/lib/features/space-tool"; +// import LassoToolModule from "diagram-js/lib/features/lasso-tool"; +// import HandToolModule from "diagram-js/lib/features/hand-tool"; +// import GlobalConnectModule from "diagram-js/lib/features/global-connect"; +// import translate from "diagram-js/lib/i18n/translate"; +// +// import PaletteProvider from "./paletteProvider"; +// +// export default { +// __depends__: [PaletteModule, CreateModule, SpaceToolModule, LassoToolModule, HandToolModule, GlobalConnectModule, translate], +// __init__: ["paletteProvider"], +// paletteProvider: ["type", PaletteProvider] +// }; + +import CustomPalette from './CustomPalette'; + +export default { + __init__: ['paletteProvider'], + paletteProvider: ['type', CustomPalette], +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/palette/paletteProvider.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/palette/paletteProvider.js new file mode 100644 index 0000000..70a27a9 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/palette/paletteProvider.js @@ -0,0 +1,219 @@ +/** + * A palette provider for BPMN 2.0 elements. + */ +export default function PaletteProvider( + palette, + create, + elementFactory, + spaceTool, + lassoTool, + handTool, + globalConnect, + translate, +) { + this._palette = palette; + this._create = create; + this._elementFactory = elementFactory; + this._spaceTool = spaceTool; + this._lassoTool = lassoTool; + this._handTool = handTool; + this._globalConnect = globalConnect; + this._translate = translate; + + palette.registerProvider(this); +} + +PaletteProvider.$inject = [ + 'palette', + 'create', + 'elementFactory', + 'spaceTool', + 'lassoTool', + 'handTool', + 'globalConnect', + 'translate', +]; + +PaletteProvider.prototype.getPaletteEntries = function () { + const actions = {}; + const create = this._create; + const elementFactory = this._elementFactory; + const spaceTool = this._spaceTool; + const lassoTool = this._lassoTool; + const handTool = this._handTool; + const globalConnect = this._globalConnect; + const translate = this._translate; + + function createAction(type, group, className, title, options) { + function createListener(event) { + const shape = elementFactory.createShape( + Object.assign({ type }, options), + ); + + if (options) { + shape.businessObject.di.isExpanded = options.isExpanded; + } + + create.start(event, shape); + } + + const shortType = type.replace(/^bpmn:/, ''); + + return { + group, + className, + title: title || translate('Create {type}', { type: shortType }), + action: { + dragstart: createListener, + click: createListener, + }, + }; + } + + function createSubprocess(event) { + const subProcess = elementFactory.createShape({ + type: 'bpmn:SubProcess', + x: 0, + y: 0, + isExpanded: true, + }); + + const startEvent = elementFactory.createShape({ + type: 'bpmn:StartEvent', + x: 40, + y: 82, + parent: subProcess, + }); + + create.start(event, [subProcess, startEvent], { + hints: { + autoSelect: [startEvent], + }, + }); + } + + function createParticipant(event) { + create.start(event, elementFactory.createParticipantShape()); + } + + Object.assign(actions, { + 'hand-tool': { + group: 'tools', + className: 'bpmn-icon-hand-tool', + title: translate('Activate the hand tool'), + action: { + click(event) { + handTool.activateHand(event); + }, + }, + }, + 'lasso-tool': { + group: 'tools', + className: 'bpmn-icon-lasso-tool', + title: translate('Activate the lasso tool'), + action: { + click(event) { + lassoTool.activateSelection(event); + }, + }, + }, + 'space-tool': { + group: 'tools', + className: 'bpmn-icon-space-tool', + title: translate('Activate the create/remove space tool'), + action: { + click(event) { + spaceTool.activateSelection(event); + }, + }, + }, + 'global-connect-tool': { + group: 'tools', + className: 'bpmn-icon-connection-multi', + title: translate('Activate the global connect tool'), + action: { + click(event) { + globalConnect.toggle(event); + }, + }, + }, + 'tool-separator': { + group: 'tools', + separator: true, + }, + 'create.start-event': createAction( + 'bpmn:StartEvent', + 'event', + 'bpmn-icon-start-event-none', + translate('Create StartEvent'), + ), + 'create.intermediate-event': createAction( + 'bpmn:IntermediateThrowEvent', + 'event', + 'bpmn-icon-intermediate-event-none', + translate('Create Intermediate/Boundary Event'), + ), + 'create.end-event': createAction( + 'bpmn:EndEvent', + 'event', + 'bpmn-icon-end-event-none', + translate('Create EndEvent'), + ), + 'create.exclusive-gateway': createAction( + 'bpmn:ExclusiveGateway', + 'gateway', + 'bpmn-icon-gateway-none', + translate('Create Gateway'), + ), + 'create.user-task': createAction( + 'bpmn:UserTask', + 'activity', + 'bpmn-icon-user-task', + translate('Create User Task'), + ), + 'create.service-task': createAction( + 'bpmn:ServiceTask', + 'activity', + 'bpmn-icon-service', + translate('Create Service Task'), + ), + 'create.data-object': createAction( + 'bpmn:DataObjectReference', + 'data-object', + 'bpmn-icon-data-object', + translate('Create DataObjectReference'), + ), + 'create.data-store': createAction( + 'bpmn:DataStoreReference', + 'data-store', + 'bpmn-icon-data-store', + translate('Create DataStoreReference'), + ), + 'create.subprocess-expanded': { + group: 'activity', + className: 'bpmn-icon-subprocess-expanded', + title: translate('Create expanded SubProcess'), + action: { + dragstart: createSubprocess, + click: createSubprocess, + }, + }, + 'create.participant-expanded': { + group: 'collaboration', + className: 'bpmn-icon-participant', + title: translate('Create Pool/Participant'), + action: { + dragstart: createParticipant, + click: createParticipant, + }, + }, + 'create.group': createAction( + 'bpmn:Group', + 'artifact', + 'bpmn-icon-group', + translate('Create Group'), + ), + }); + + return actions; +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/translate/customTranslate.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/translate/customTranslate.js new file mode 100644 index 0000000..cc6ad6e --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/translate/customTranslate.js @@ -0,0 +1,44 @@ +// import translations from "./zh"; +// +// export default function customTranslate(template, replacements) { +// replacements = replacements || {}; +// +// // Translate +// template = translations[template] || template; +// +// // Replace +// return template.replace(/{([^}]+)}/g, function(_, key) { +// let str = replacements[key]; +// if ( +// translations[replacements[key]] !== null && +// translations[replacements[key]] !== "undefined" +// ) { +// // eslint-disable-next-line no-mixed-spaces-and-tabs +// str = translations[replacements[key]]; +// // eslint-disable-next-line no-mixed-spaces-and-tabs +// } +// return str || "{" + key + "}"; +// }); +// } + +export default function customTranslate(translations) { + return function (template, replacements) { + replacements = replacements || {}; + // 将模板和翻译字典的键统一转换为小写进行匹配 + const lowerTemplate = template.toLowerCase(); + const translation = Object.keys(translations).find( + (key) => key.toLowerCase() === lowerTemplate, + ); + + // 如果找到匹配的翻译,使用翻译后的模板 + if (translation) { + template = translations[translation]; + } + + // 替换模板中的占位符 + return template.replaceAll(/\{([^}]+)\}/g, (_, key) => { + // 如果替换值存在,返回替换值;否则返回原始占位符 + return replacements[key] === undefined ? `{${key}}` : replacements[key]; + }); + }; +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/translate/zh.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/translate/zh.js new file mode 100644 index 0000000..4d25da7 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/designer/plugins/translate/zh.js @@ -0,0 +1,256 @@ +/* eslint-disable no-template-curly-in-string */ +/** + * This is a sample file that should be replaced with the actual translation. + * + * Checkout https://github.com/bpmn-io/bpmn-js-i18n for a list of available + * translations and labels to translate. + */ +export default { + // 添加部分 + 'Append EndEvent': '追加结束事件', + 'Append Gateway': '追加网关', + 'Append Task': '追加任务', + 'Append Intermediate/Boundary Event': '追加中间抛出事件/边界事件', + TextAnnotation: '文本注释', + 'Activate the global connect tool': '激活全局连接工具', + 'Append {type}': '添加 {type}', + 'Add Lane above': '在上面添加道', + 'Divide into two Lanes': '分割成两个道', + 'Divide into three Lanes': '分割成三个道', + 'Add Lane below': '在下面添加道', + 'Append compensation activity': '追加补偿活动', + 'Change type': '修改类型', + 'Connect using Association': '使用关联连接', + 'Connect using Sequence/MessageFlow or Association': + '使用顺序/消息流或者关联连接', + 'Connect using DataInputAssociation': '使用数据输入关联连接', + Remove: '移除', + 'Activate the hand tool': '激活抓手工具', + 'Activate the lasso tool': '激活套索工具', + 'Activate the create/remove space tool': '激活创建/删除空间工具', + 'Create expanded SubProcess': '创建扩展子过程', + 'Create IntermediateThrowEvent/BoundaryEvent': '创建中间抛出事件/边界事件', + 'Create Pool/Participant': '创建池/参与者', + 'Participant Multiplicity': '参与者多重性', + 'Empty pool/participant (removes content)': '清空池/参与者(移除内容)', + 'Empty pool/participant': '收缩池/参与者', + 'Expanded pool/participant': '展开池/参与者', + 'Parallel Multi-Instance': '并行多重事件', + 'Sequential Multi-Instance': '时序多重事件', + DataObjectReference: '数据对象参考', + DataStoreReference: '数据存储参考', + 'Data object reference': '数据对象引用 ', + 'Data store reference': '数据存储引用 ', + Loop: '循环', + 'Ad-hoc': '即席', + 'Create {type}': '创建 {type}', + Task: '任务', + 'Send Task': '发送任务', + 'Receive Task': '接收任务', + 'User Task': '用户任务', + 'Manual Task': '手工任务', + 'Business Rule Task': '业务规则任务', + 'Service Task': '服务任务', + 'Script Task': '脚本任务', + 'Call Activity': '调用活动', + 'Sub-Process (collapsed)': '子流程(折叠的)', + 'Sub-Process (expanded)': '子流程(展开的)', + 'Ad-hoc sub-process': '即席子流程', + 'Ad-hoc sub-process (collapsed)': '即席子流程(折叠的)', + 'Ad-hoc sub-process (expanded)': '即席子流程(展开的)', + 'Start Event': '开始事件', + StartEvent: '开始事件', + 'Intermediate Throw Event': '中间事件', + 'End Event': '结束事件', + EndEvent: '结束事件', + 'Create StartEvent': '创建开始事件', + 'Create EndEvent': '创建结束事件', + 'Create Task': '创建任务', + 'Create User Task': '创建用户任务', + 'Create Call Activity': '创建调用活动', + 'Create Service Task': '创建服务任务', + 'Create Gateway': '创建网关', + 'Create DataObjectReference': '创建数据对象', + 'Create DataStoreReference': '创建数据存储', + 'Create Group': '创建分组', + 'Create Intermediate/Boundary Event': '创建中间/边界事件', + 'Message Start Event': '消息开始事件', + 'Timer Start Event': '定时开始事件', + 'Conditional Start Event': '条件开始事件', + 'Signal Start Event': '信号开始事件', + 'Error Start Event': '错误开始事件', + 'Escalation Start Event': '升级开始事件', + 'Compensation Start Event': '补偿开始事件', + 'Message Start Event (non-interrupting)': '消息开始事件(非中断)', + 'Timer Start Event (non-interrupting)': '定时开始事件(非中断)', + 'Conditional Start Event (non-interrupting)': '条件开始事件(非中断)', + 'Signal Start Event (non-interrupting)': '信号开始事件(非中断)', + 'Escalation Start Event (non-interrupting)': '升级开始事件(非中断)', + 'Message Intermediate Catch Event': '消息中间捕获事件', + 'Message Intermediate Throw Event': '消息中间抛出事件', + 'Timer Intermediate Catch Event': '定时中间捕获事件', + 'Escalation Intermediate Throw Event': '升级中间抛出事件', + 'Conditional Intermediate Catch Event': '条件中间捕获事件', + 'Link Intermediate Catch Event': '链接中间捕获事件', + 'Link Intermediate Throw Event': '链接中间抛出事件', + 'Compensation Intermediate Throw Event': '补偿中间抛出事件', + 'Signal Intermediate Catch Event': '信号中间捕获事件', + 'Signal Intermediate Throw Event': '信号中间抛出事件', + 'Message End Event': '消息结束事件', + 'Escalation End Event': '定时结束事件', + 'Error End Event': '错误结束事件', + 'Cancel End Event': '取消结束事件', + 'Compensation End Event': '补偿结束事件', + 'Signal End Event': '信号结束事件', + 'Terminate End Event': '终止结束事件', + 'Message Boundary Event': '消息边界事件', + 'Message Boundary Event (non-interrupting)': '消息边界事件(非中断)', + 'Timer Boundary Event': '定时边界事件', + 'Timer Boundary Event (non-interrupting)': '定时边界事件(非中断)', + 'Escalation Boundary Event': '升级边界事件', + 'Escalation Boundary Event (non-interrupting)': '升级边界事件(非中断)', + 'Conditional Boundary Event': '条件边界事件', + 'Conditional Boundary Event (non-interrupting)': '条件边界事件(非中断)', + 'Error Boundary Event': '错误边界事件', + 'Cancel Boundary Event': '取消边界事件', + 'Signal Boundary Event': '信号边界事件', + 'Signal Boundary Event (non-interrupting)': '信号边界事件(非中断)', + 'Compensation Boundary Event': '补偿边界事件', + 'Exclusive Gateway': '互斥网关', + 'Parallel Gateway': '并行网关', + 'Inclusive Gateway': '相容网关', + 'Complex Gateway': '复杂网关', + 'Event-based Gateway': '事件网关', + Transaction: '转运', + 'sub-process': '子流程', + 'Event sub-process': '事件子流程', + 'Collapsed Pool': '折叠池', + 'Expanded Pool': '展开池', + + // Errors + 'no parent for {element} in {parent}': '在{parent}里,{element}没有父类', + 'no shape type specified': '没有指定的形状类型', + 'flow elements must be children of pools/participants': + '流元素必须是池/参与者的子类', + 'out of bounds release': 'out of bounds release', + 'more than {count} child lanes': '子道大于{count} ', + 'element required': '元素不能为空', + 'diagram not part of bpmn:Definitions': '流程图不符合bpmn规范', + 'no diagram to display': '没有可展示的流程图', + 'no process or collaboration to display': '没有可展示的流程/协作', + 'element {element} referenced by {referenced}#{property} not yet drawn': + '由{referenced}#{property}引用的{element}元素仍未绘制', + 'already rendered {element}': '{element} 已被渲染', + 'failed to import {element}': '导入{element}失败', + // 属性面板的参数 + Id: '编号', + Name: '名称', + General: '常规', + Details: '详情', + 'Message Name': '消息名称', + Message: '消息', + Initiator: '创建者', + 'Asynchronous Continuations': '持续异步', + 'Asynchronous Before': '异步前', + 'Asynchronous After': '异步后', + 'Job Configuration': '工作配置', + Exclusive: '排除', + 'Job Priority': '工作优先级', + 'Retry Time Cycle': '重试时间周期', + Documentation: '文档', + 'Element Documentation': '元素文档', + 'History Configuration': '历史配置', + 'History Time To Live': '历史的生存时间', + Forms: '表单', + 'Form Key': '表单key', + 'Form Fields': '表单字段', + 'Business Key': '业务key', + 'Form Field': '表单字段', + ID: '编号', + Type: '类型', + Label: '名称', + 'Default Value': '默认值', + 'Default Flow': '默认流转路径', + 'Conditional Flow': '条件流转路径', + 'Sequence Flow': '普通流转路径', + Validation: '校验', + 'Add Constraint': '添加约束', + Config: '配置', + Properties: '属性', + 'Add Property': '添加属性', + Value: '值', + Listeners: '监听器', + 'Execution Listener': '执行监听', + 'Event Type': '事件类型', + 'Listener Type': '监听器类型', + 'Java Class': 'Java类', + Expression: '表达式', + 'Must provide a value': '必须提供一个值', + 'Delegate Expression': '代理表达式', + Script: '脚本', + 'Script Format': '脚本格式', + 'Script Type': '脚本类型', + 'Inline Script': '内联脚本', + 'External Script': '外部脚本', + Resource: '资源', + 'Field Injection': '字段注入', + Extensions: '扩展', + 'Input/Output': '输入/输出', + 'Input Parameters': '输入参数', + 'Output Parameters': '输出参数', + Parameters: '参数', + 'Output Parameter': '输出参数', + 'Timer Definition Type': '定时器定义类型', + 'Timer Definition': '定时器定义', + Date: '日期', + Duration: '持续', + Cycle: '循环', + Signal: '信号', + 'Signal Name': '信号名称', + Escalation: '升级', + Error: '错误', + 'Link Name': '链接名称', + Condition: '条件名称', + 'Variable Name': '变量名称', + 'Variable Event': '变量事件', + 'Specify more than one variable change event as a comma separated list.': + '多个变量事件以逗号隔开', + 'Wait for Completion': '等待完成', + 'Activity Ref': '活动参考', + 'Version Tag': '版本标签', + Executable: '可执行文件', + 'External Task Configuration': '扩展任务配置', + 'Task Priority': '任务优先级', + External: '外部', + Connector: '连接器', + 'Must configure Connector': '必须配置连接器', + 'Connector Id': '连接器编号', + Implementation: '实现方式', + 'Field Injections': '字段注入', + Fields: '字段', + 'Result Variable': '结果变量', + Topic: '主题', + 'Configure Connector': '配置连接器', + 'Input Parameter': '输入参数', + Assignee: '代理人', + 'Candidate Users': '候选用户', + 'Candidate Groups': '候选组', + 'Due Date': '到期时间', + 'Follow Up Date': '跟踪日期', + Priority: '优先级', + 'The follow up date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)': + '跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00', + 'The due date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)': + '跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00', + Variables: '变量', + 'Candidate Starter Configuration': '候选人起动器配置', + 'Candidate Starter Groups': '候选人起动器组', + 'This maps to the process definition key.': '这映射到流程定义键。', + 'Candidate Starter Users': '候选人起动器的用户', + 'Specify more than one user as a comma separated list.': + '指定多个用户作为逗号分隔的列表。', + 'Tasklist Configuration': 'Tasklist配置', + Startable: '启动', + 'Specify more than one group as a comma separated list.': + '指定多个组作为逗号分隔的列表。', +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/index.ts b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/index.ts new file mode 100644 index 0000000..f27319a --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/index.ts @@ -0,0 +1,9 @@ +import './theme/index.scss'; +import 'bpmn-js/dist/assets/diagram-js.css'; +import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'; +import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'; +import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'; + +export { default as MyProcessDesigner } from './designer'; +export { default as MyProcessViewer } from './designer/index2'; +export { default as MyProcessPenal } from './penal'; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/palette/ProcessPalette.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/palette/ProcessPalette.vue new file mode 100644 index 0000000..6d0ac70 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/palette/ProcessPalette.vue @@ -0,0 +1,30 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/PropertiesPanel.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/PropertiesPanel.vue new file mode 100644 index 0000000..5e482c8 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/PropertiesPanel.vue @@ -0,0 +1,399 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/base/ElementBaseInfo.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/base/ElementBaseInfo.vue new file mode 100644 index 0000000..3887645 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/base/ElementBaseInfo.vue @@ -0,0 +1,225 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/ElementCustomConfig.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/ElementCustomConfig.vue new file mode 100644 index 0000000..8c8cc6f --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/ElementCustomConfig.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/components/BoundaryEventTimer.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/components/BoundaryEventTimer.vue new file mode 100644 index 0000000..2a03164 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/components/BoundaryEventTimer.vue @@ -0,0 +1,305 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/components/UserTaskCustomConfig.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/components/UserTaskCustomConfig.vue new file mode 100644 index 0000000..ac4a731 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/components/UserTaskCustomConfig.vue @@ -0,0 +1,663 @@ + + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/data.ts b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/data.ts new file mode 100644 index 0000000..cd88300 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/custom-config/data.ts @@ -0,0 +1,13 @@ +import BoundaryEventTimer from './components/BoundaryEventTimer.vue'; +import UserTaskCustomConfig from './components/UserTaskCustomConfig.vue'; + +export const CustomConfigMap = { + UserTask: { + name: '用户任务', + component: UserTaskCustomConfig, + }, + BoundaryEventTimerEventDefinition: { + name: '定时边界事件(非中断)', + component: BoundaryEventTimer, + }, +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/flow-condition/FlowCondition.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/flow-condition/FlowCondition.vue new file mode 100644 index 0000000..b922db0 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/flow-condition/FlowCondition.vue @@ -0,0 +1,234 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/form/ElementForm.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/form/ElementForm.vue new file mode 100644 index 0000000..3c8b781 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/form/ElementForm.vue @@ -0,0 +1,337 @@ + + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/index.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/index.js new file mode 100644 index 0000000..1688cf7 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/index.js @@ -0,0 +1,7 @@ +import MyPropertiesPanel from './PropertiesPanel.vue'; + +MyPropertiesPanel.install = function (Vue) { + Vue.component(MyPropertiesPanel.name, MyPropertiesPanel); +}; + +export default MyPropertiesPanel; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/ElementListeners.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/ElementListeners.vue new file mode 100644 index 0000000..e4cb2fe --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/ElementListeners.vue @@ -0,0 +1,573 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/ListenerFieldModal.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/ListenerFieldModal.vue new file mode 100644 index 0000000..5d1c57a --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/ListenerFieldModal.vue @@ -0,0 +1,111 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/UserTaskListeners.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/UserTaskListeners.vue new file mode 100644 index 0000000..af7a1c6 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/UserTaskListeners.vue @@ -0,0 +1,552 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/utilSelf.ts b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/utilSelf.ts new file mode 100644 index 0000000..2cfd78d --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/utilSelf.ts @@ -0,0 +1,101 @@ +// 初始化表单数据 +import { cloneDeep } from '@vben/utils'; + +export function initListenerForm(listener: any) { + let self = { + ...listener, + }; + if (listener.script) { + self = { + ...listener, + ...listener.script, + scriptType: listener.script.resource ? 'externalScript' : 'inlineScript', + }; + } + if ( + listener.event === 'timeout' && + listener.eventDefinitions && + listener.eventDefinitions.length > 0 + ) { + let k = ''; + for (const key in listener.eventDefinitions[0]) { + // console.log(listener.eventDefinitions, key); + if (key.includes('time')) { + k = key; + self.eventDefinitionType = key.replace('time', '').toLowerCase(); + } + } + // console.log(k); + self.eventTimeDefinitions = listener.eventDefinitions[0][k].body; + } + return self; +} + +export function initListenerType(listener: any) { + let listenerType; + if (listener.class) listenerType = 'classListener'; + if (listener.expression) listenerType = 'expressionListener'; + if (listener.delegateExpression) listenerType = 'delegateExpressionListener'; + if (listener.script) listenerType = 'scriptListener'; + return { + ...cloneDeep(listener), + ...listener.script, + listenerType, + }; +} + +/** 将 ProcessListenerDO 转换成 initListenerForm 想同的 Form 对象 */ +export function initListenerForm2(processListener: any) { + switch (processListener.valueType) { + case 'class': { + return { + listenerType: 'classListener', + class: processListener.value, + event: processListener.event, + fields: [], + id: undefined, + }; + } + case 'delegateExpression': { + return { + listenerType: 'delegateExpressionListener', + delegateExpression: processListener.value, + event: processListener.event, + fields: [], + id: undefined, + }; + } + case 'expression': { + return { + listenerType: 'expressionListener', + expression: processListener.value, + event: processListener.event, + fields: [], + id: undefined, + }; + } + // No default + } + throw new Error('未知的监听器类型'); +} + +export const listenerType = { + classListener: 'Java 类', + expressionListener: '表达式', + delegateExpressionListener: '代理表达式', + scriptListener: '脚本', +}; + +export const eventType = { + create: '创建', + assignment: '指派', + complete: '完成', + delete: '删除', + update: '更新', + timeout: '超时', +}; + +export const fieldType = { + string: '字符串', + expression: '表达式', +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/multi-instance/ElementMultiInstance.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/multi-instance/ElementMultiInstance.vue new file mode 100644 index 0000000..f7ca142 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/multi-instance/ElementMultiInstance.vue @@ -0,0 +1,545 @@ + + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/other/ElementOtherConfig.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/other/ElementOtherConfig.vue new file mode 100644 index 0000000..f0fb820 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/other/ElementOtherConfig.vue @@ -0,0 +1,73 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/properties/ElementProperties.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/properties/ElementProperties.vue new file mode 100644 index 0000000..dfde667 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/properties/ElementProperties.vue @@ -0,0 +1,249 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/signal-message/SignalAndMessage.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/signal-message/SignalAndMessage.vue new file mode 100644 index 0000000..9821b04 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/signal-message/SignalAndMessage.vue @@ -0,0 +1,337 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/signal-message/SignalMessageModal.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/signal-message/SignalMessageModal.vue new file mode 100644 index 0000000..45d185d --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/signal-message/SignalMessageModal.vue @@ -0,0 +1,85 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/ElementTask.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/ElementTask.vue new file mode 100644 index 0000000..8775cb9 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/ElementTask.vue @@ -0,0 +1,93 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/data.ts b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/data.ts new file mode 100644 index 0000000..d453b38 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/data.ts @@ -0,0 +1,40 @@ +import CallActivity from './task-components/CallActivity.vue'; +import ReceiveTask from './task-components/ReceiveTask.vue'; +import ScriptTask from './task-components/ScriptTask.vue'; +import ServiceTask from './task-components/ServiceTask.vue'; +import UserTask from './task-components/UserTask.vue'; + +export const installedComponent = { + UserTask: { + name: '用户任务', + component: UserTask, + }, + ServiceTask: { + name: '服务任务', + component: ServiceTask, + }, + ScriptTask: { + name: '脚本任务', + component: ScriptTask, + }, + ReceiveTask: { + name: '接收任务', + component: ReceiveTask, + }, + CallActivity: { + name: '调用活动', + component: CallActivity, + }, +}; + +export const getTaskCollapseItemName = ( + elementType: keyof typeof installedComponent, +) => { + return installedComponent[elementType].name; +}; + +export const isTaskCollapseItemShow = ( + elementType: keyof typeof installedComponent, +) => { + return installedComponent[elementType]; +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/CallActivity.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/CallActivity.vue new file mode 100644 index 0000000..dfdf176 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/CallActivity.vue @@ -0,0 +1,418 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/HttpHeaderEditor.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/HttpHeaderEditor.vue new file mode 100644 index 0000000..6c994b6 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/HttpHeaderEditor.vue @@ -0,0 +1,126 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/ReceiveTask.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/ReceiveTask.vue new file mode 100644 index 0000000..affd1cd --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/ReceiveTask.vue @@ -0,0 +1,141 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/ScriptTask.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/ScriptTask.vue new file mode 100644 index 0000000..c15dad1 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/ScriptTask.vue @@ -0,0 +1,119 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/ServiceTask.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/ServiceTask.vue new file mode 100644 index 0000000..2994f1e --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/ServiceTask.vue @@ -0,0 +1,487 @@ + + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/UserTask.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/UserTask.vue new file mode 100644 index 0000000..632505a --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/task/task-components/UserTask.vue @@ -0,0 +1,570 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/time-event-config/CycleConfig.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/time-event-config/CycleConfig.vue new file mode 100644 index 0000000..650f166 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/time-event-config/CycleConfig.vue @@ -0,0 +1,391 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/time-event-config/DurationConfig.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/time-event-config/DurationConfig.vue new file mode 100644 index 0000000..b817b09 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/time-event-config/DurationConfig.vue @@ -0,0 +1,95 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/time-event-config/TimeEventConfig.vue b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/time-event-config/TimeEventConfig.vue new file mode 100644 index 0000000..f3992a8 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/penal/time-event-config/TimeEventConfig.vue @@ -0,0 +1,361 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/theme/index.scss b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/theme/index.scss new file mode 100644 index 0000000..a2d32d4 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/theme/index.scss @@ -0,0 +1,120 @@ +@use './process-designer'; +@use './process-panel'; + +$success-color: #4eb819; +$primary-color: #409eff; +$danger-color: #f56c6c; +$cancel-color: #909399; + +.process-viewer { + position: relative; + background: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+') + repeat !important; + border: 1px solid #efefef; + + .success-arrow { + fill: $success-color; + stroke: $success-color; + } + + .success-conditional { + fill: white; + stroke: $success-color; + } + + .success.djs-connection { + .djs-visual path { + stroke: $success-color !important; + //marker-end: url(#sequenceflow-end-white-success)!important; + } + } + + .success.djs-connection.condition-expression { + .djs-visual path { + //marker-start: url(#conditional-flow-marker-white-success)!important; + } + } + + .success.djs-shape { + .djs-visual rect { + fill: $success-color !important; + fill-opacity: 0.15 !important; + stroke: $success-color !important; + } + + .djs-visual polygon { + stroke: $success-color !important; + } + + .djs-visual path:nth-child(2) { + fill: $success-color !important; + stroke: $success-color !important; + } + + .djs-visual circle { + fill: $success-color !important; + fill-opacity: 0.15 !important; + stroke: $success-color !important; + } + } + + .primary.djs-shape { + .djs-visual rect { + fill: $primary-color !important; + fill-opacity: 0.15 !important; + stroke: $primary-color !important; + } + + .djs-visual polygon { + stroke: $primary-color !important; + } + + .djs-visual circle { + fill: $primary-color !important; + fill-opacity: 0.15 !important; + stroke: $primary-color !important; + } + } + + .danger.djs-shape { + .djs-visual rect { + fill: $danger-color !important; + fill-opacity: 0.15 !important; + stroke: $danger-color !important; + } + + .djs-visual polygon { + stroke: $danger-color !important; + } + + .djs-visual circle { + fill: $danger-color !important; + fill-opacity: 0.15 !important; + stroke: $danger-color !important; + } + } + + .cancel.djs-shape { + .djs-visual rect { + fill: $cancel-color !important; + fill-opacity: 0.15 !important; + stroke: $cancel-color !important; + } + + .djs-visual polygon { + stroke: $cancel-color !important; + } + + .djs-visual circle { + fill: $cancel-color !important; + fill-opacity: 0.15 !important; + stroke: $cancel-color !important; + } + } +} + +.process-viewer .djs-tooltip-container, +.process-viewer .djs-overlay-container, +.process-viewer .djs-palette { + display: none; +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/theme/process-designer.scss b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/theme/process-designer.scss new file mode 100644 index 0000000..83418ca --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/theme/process-designer.scss @@ -0,0 +1,183 @@ +@use 'bpmn-js-token-simulation/assets/css/bpmn-js-token-simulation.css'; + +// 边框被 token-simulation 样式覆盖了 +.djs-palette { + background: var(--palette-background-color); + border: solid 1px var(--palette-border-color) !important; + border-radius: 2px; +} + +.my-process-designer { + box-sizing: border-box; + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + + .my-process-designer__header { + width: 100%; + min-height: 36px; + + .el-button { + text-align: center; + } + + .el-button-group { + margin: 4px; + } + + .el-tooltip__popper { + .el-button { + width: 100%; + padding-right: 8px; + padding-left: 8px; + text-align: left; + } + + .el-button:hover { + color: #fff; + background: rgb(64 158 255 / 80%); + } + } + + .align { + position: relative; + + i { + &::after { + position: absolute; + content: '|'; + // transform: rotate(90deg) translate(200%, 60%); + transform: rotate(180deg) translate(271%, -10%); + } + } + } + + .align.align-left i { + transform: rotate(90deg); + } + + .align.align-right i { + transform: rotate(-90deg); + } + + .align.align-top i { + transform: rotate(180deg); + } + + .align.align-bottom i { + transform: rotate(0deg); + } + + .align.align-center i { + transform: rotate(0deg); + + &::after { + // transform: rotate(90deg) translate(0, 60%); + transform: rotate(0deg) translate(-0%, -5%); + } + } + + .align.align-middle i { + transform: rotate(-90deg); + + &::after { + // transform: rotate(90deg) translate(0, 60%); + transform: rotate(0deg) translate(0, -10%); + } + } + } + + .my-process-designer__container { + display: inline-flex; + flex: 1; + width: 100%; + + .my-process-designer__canvas { + position: relative; + flex: 1; + height: 100%; + background: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+') + repeat !important; + + div.toggle-mode { + display: none; + } + } + + .my-process-designer__property-panel { + z-index: 10; + height: 100%; + overflow: scroll; + overflow-y: auto; + + * { + box-sizing: border-box; + } + } + // svg { + // width: 100%; + // height: 100%; + // min-height: 100%; + // overflow: hidden; + // } + } +} + +//侧边栏配置 +// .djs-palette .two-column .open { +.open { + // .djs-palette.open { + .djs-palette-entries { + div[class^='bpmn-icon-']::before, + div[class*='bpmn-icon-']::before { + line-height: unset; + } + + div.entry { + position: relative; + } + + div.entry:hover { + &::after { + position: absolute; + top: 0; + right: -10px; + bottom: 0; + z-index: 100; + box-sizing: border-box; + display: inline-block; + width: max-content; + padding: 0 16px; + overflow: hidden; + font-size: 0.5em; + font-variant: normal; + vertical-align: text-bottom; + text-transform: none; + text-decoration: inherit; + content: attr(title); + background: #fafafa; + border: 1px solid #ccc; + border-radius: 4px; + box-shadow: 0 0 6px #eee; + transform: translateX(100%); + } + } + } +} + +pre { + height: 100%; + max-height: calc(80vh - 32px); + margin: 0; + overflow: hidden; + overflow-y: auto; +} + +.hljs { + white-space: pre-wrap; +} + +.hljs * { + font-family: Consolas, Monaco, monospace; +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/theme/process-panel.scss b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/theme/process-panel.scss new file mode 100644 index 0000000..f818588 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/theme/process-panel.scss @@ -0,0 +1,127 @@ +.process-panel__container { + box-sizing: border-box; + max-height: 100%; + padding: 0 8px; + overflow-y: scroll; + border-left: 1px solid #eee; + box-shadow: 0 0 8px #ccc; +} + +.panel-tab__title { + padding: 0 8px; + font-size: 1.1em; + font-weight: 600; + line-height: 1.2em; + + i { + margin-right: 8px; + font-size: 1.2em; + } +} + +.panel-tab__content { + box-sizing: border-box; + width: 100%; + padding: 8px 16px; + border-top: 1px solid #eee; + + .panel-tab__content--title { + display: flex; + justify-content: space-between; + padding-bottom: 8px; + + span { + flex: 1; + text-align: left; + } + } +} + +.element-property { + display: flex; + align-items: flex-start; + width: 100%; + margin: 8px 0; + + .element-property__label { + box-sizing: border-box; + display: block; + width: 90px; + padding-right: 12px; + overflow: hidden; + font-size: 14px; + line-height: 32px; + text-align: right; + } + + .element-property__value { + flex: 1; + line-height: 32px; + } + + .el-form-item { + width: 100%; + padding-bottom: 18px; + margin-bottom: 0; + } +} + +.list-property { + flex-direction: column; + + .element-listener-item { + display: inline-grid; + grid-template-columns: 16px auto 32px 32px; + column-gap: 8px; + width: 100%; + } + + .element-listener-item + .element-listener-item { + margin-top: 8px; + } +} + +.listener-filed__title { + display: inline-flex; + align-items: center; + justify-content: space-between; + width: 100%; + margin-top: 0; + + span { + width: 200px; + font-size: 14px; + text-align: left; + } + + i { + margin-right: 8px; + } +} + +.element-drawer__button { + display: inline-flex; + justify-content: space-around; + width: 100%; + margin-top: 8px; +} + +.element-drawer__button > .el-button { + width: 100%; +} + +.el-collapse-item__content { + padding-bottom: 0; +} + +.el-input.is-disabled .el-input__inner { + color: #999; +} + +.el-form-item.el-form-item--mini { + margin-bottom: 0; + + & + .el-form-item { + margin-top: 16px; + } +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/utils.ts b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/utils.ts new file mode 100644 index 0000000..b8bf532 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/package/utils.ts @@ -0,0 +1,94 @@ +const bpmnInstances = () => (window as any)?.bpmnInstances; +// 创建监听器实例 +export function createListenerObject(options, isTask, prefix) { + const listenerObj = Object.create(null); + listenerObj.event = options.event; + isTask && (listenerObj.id = options.id); // 任务监听器特有的 id 字段 + switch (options.listenerType) { + case 'delegateExpressionListener': { + listenerObj.delegateExpression = options.delegateExpression; + break; + } + case 'expressionListener': { + listenerObj.expression = options.expression; + break; + } + case 'scriptListener': { + listenerObj.script = createScriptObject(options, prefix); + break; + } + default: { + listenerObj.class = options.class; + } + } + // 注入字段 + if (options.fields) { + listenerObj.fields = options.fields.map((field) => { + return createFieldObject(field, prefix); + }); + } + // 任务监听器的 定时器 设置 + if (isTask && options.event === 'timeout' && !!options.eventDefinitionType) { + const timeDefinition = bpmnInstances().moddle.create( + 'bpmn:FormalExpression', + { + body: options.eventTimeDefinitions, + }, + ); + const TimerEventDefinition = bpmnInstances().moddle.create( + 'bpmn:TimerEventDefinition', + { + id: `TimerEventDefinition_${uuid(8)}`, + [`time${options.eventDefinitionType.replace(/^\S/, (s) => s.toUpperCase())}`]: + timeDefinition, + }, + ); + listenerObj.eventDefinitions = [TimerEventDefinition]; + } + return bpmnInstances().moddle.create( + `${prefix}:${isTask ? 'TaskListener' : 'ExecutionListener'}`, + listenerObj, + ); +} + +// 创建 监听器的注入字段 实例 +export function createFieldObject(option, prefix) { + const { name, fieldType, string, expression } = option; + const fieldConfig = + fieldType === 'string' ? { name, string } : { name, expression }; + return bpmnInstances().moddle.create(`${prefix}:Field`, fieldConfig); +} + +// 创建脚本实例 +export function createScriptObject(options, prefix) { + const { scriptType, scriptFormat, value, resource } = options; + const scriptConfig = + scriptType === 'inlineScript' + ? { scriptFormat, value } + : { scriptFormat, resource }; + return bpmnInstances().moddle.create(`${prefix}:Script`, scriptConfig); +} + +// 更新元素扩展属性 +export function updateElementExtensions(element, extensionList) { + const extensions = bpmnInstances().moddle.create('bpmn:ExtensionElements', { + values: extensionList, + }); + // 直接使用原始元素对象,不需要toRaw包装 + bpmnInstances().modeling.updateProperties(element, { + extensionElements: extensions, + }); +} + +// 创建一个id +export function uuid( + length = 8, + charsString = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', +) { + let result = ''; + + for (let i = length; i > 0; --i) { + result += charsString[Math.floor(Math.random() * charsString.length)]; + } + return result; +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/highlight/index.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/highlight/index.js new file mode 100644 index 0000000..c8d7096 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/highlight/index.js @@ -0,0 +1,8 @@ +import hljs from 'highlight.js/lib/core'; +import jsonLanguage from 'highlight.js/lib/languages/json'; +import xmlLanguage from 'highlight.js/lib/languages/xml'; + +hljs.registerLanguage('xml', xmlLanguage); +hljs.registerLanguage('json', jsonLanguage); + +export default hljs; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/custom-renderer/CustomRenderer.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/custom-renderer/CustomRenderer.js new file mode 100644 index 0000000..506a1b3 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/custom-renderer/CustomRenderer.js @@ -0,0 +1,30 @@ +import BpmnRenderer from 'bpmn-js/lib/draw/BpmnRenderer'; + +export default function CustomRenderer( + config, + eventBus, + styles, + pathMap, + canvas, + textRenderer, +) { + BpmnRenderer.call( + this, + config, + eventBus, + styles, + pathMap, + canvas, + textRenderer, + 2000, + ); + + this.handlers.label = function () { + return null; + }; +} + +const F = function () {}; // 核心,利用空对象作为中介; +F.prototype = BpmnRenderer.prototype; // 核心,将父类的原型赋值给空对象F; +CustomRenderer.prototype = new F(); // 核心,将 F的实例赋值给子类; +CustomRenderer.prototype.constructor = CustomRenderer; // 修复子类CustomRenderer的构造器指向,防止原型链的混乱; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/custom-renderer/index.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/custom-renderer/index.js new file mode 100644 index 0000000..a1842ec --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/custom-renderer/index.js @@ -0,0 +1,6 @@ +import CustomRenderer from './CustomRenderer'; + +export default { + __init__: ['customRenderer'], + customRenderer: ['type', CustomRenderer], +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/rules/CustomRules.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/rules/CustomRules.js new file mode 100644 index 0000000..49ed6e3 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/rules/CustomRules.js @@ -0,0 +1,16 @@ +import BpmnRules from 'bpmn-js/lib/features/rules/BpmnRules'; +import inherits from 'inherits'; + +export default function CustomRules(eventBus) { + BpmnRules.call(this, eventBus); +} + +inherits(CustomRules, BpmnRules); + +CustomRules.prototype.canDrop = function () { + return false; +}; + +CustomRules.prototype.canMove = function () { + return false; +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/rules/index.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/rules/index.js new file mode 100644 index 0000000..838b93e --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/modules/rules/index.js @@ -0,0 +1,6 @@ +import CustomRules from './CustomRules'; + +export default { + __init__: ['customRules'], + customRules: ['type', CustomRules], +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/translations.ts b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/translations.ts new file mode 100644 index 0000000..75c6155 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/translations.ts @@ -0,0 +1,25 @@ +/** + * This is a sample file that should be replaced with the actual translation. + * + * Checkout https://github.com/bpmn-io/bpmn-js-i18n for a list of available + * translations and labels to translate. + */ +export default { + 'Exclusive Gateway': 'Exklusives Gateway', + 'Parallel Gateway': 'Paralleles Gateway', + 'Inclusive Gateway': 'Inklusives Gateway', + 'Complex Gateway': 'Komplexes Gateway', + 'Event based Gateway': 'Ereignis-basiertes Gateway', + 'Message Start Event': '消息启动事件', + 'Timer Start Event': '定时启动事件', + 'Conditional Start Event': '条件启动事件', + 'Signal Start Event': '信号启动事件', + 'Error Start Event': '错误启动事件', + 'Escalation Start Event': '升级启动事件', + 'Compensation Start Event': '补偿启动事件', + 'Message Start Event (non-interrupting)': '消息启动事件 (非中断)', + 'Timer Start Event (non-interrupting)': '定时启动事件 (非中断)', + 'Conditional Start Event (non-interrupting)': '条件启动事件 (非中断)', + 'Signal Start Event (non-interrupting)': '信号启动事件 (非中断)', + 'Escalation Start Event (non-interrupting)': '升级启动事件 (非中断)', +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/utils/directive/clickOutSide.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/utils/directive/clickOutSide.js new file mode 100644 index 0000000..e8ea772 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/utils/directive/clickOutSide.js @@ -0,0 +1,40 @@ +// outside.js + +const ctx = '@@clickoutsideContext'; + +export default { + bind(el, binding, vnode) { + const ele = el; + const documentHandler = (e) => { + if (!vnode.context || ele.contains(e.target)) { + return false; + } + // 调用指令回调 + if (binding.expression) { + vnode.context[el[ctx].methodName](e); + } else { + el[ctx].bindingFn(e); + } + }; + // 将方法添加到ele + ele[ctx] = { + documentHandler, + methodName: binding.expression, + bindingFn: binding.value, + }; + + setTimeout(() => { + document.addEventListener('touchstart', documentHandler); // 为document绑定事件 + }); + }, + update(el, binding) { + const ele = el; + ele[ctx].methodName = binding.expression; + ele[ctx].bindingFn = binding.value; + }, + unbind(el) { + document.removeEventListener('touchstart', el[ctx].documentHandler); // 解绑 + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete el[ctx]; + }, +}; diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/utils/index.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/utils/index.js new file mode 100644 index 0000000..973685a --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/utils/index.js @@ -0,0 +1,10 @@ +export function debounce(fn, delay = 500) { + let timer; + return function (...args) { + if (timer) { + clearTimeout(timer); + timer = null; + } + timer = setTimeout(fn.bind(this, ...args), delay); + }; +} diff --git a/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/utils/xml2json.js b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/utils/xml2json.js new file mode 100644 index 0000000..3370a47 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/bpmn-process-designer/src/utils/xml2json.js @@ -0,0 +1,50 @@ +function xmlStr2XmlObj(xmlStr) { + let xmlObj = {}; + if (document.all) { + const xmlDom = new window.ActiveXObject('Microsoft.XMLDOM'); + xmlDom.loadXML(xmlStr); + xmlObj = xmlDom; + } else { + xmlObj = new DOMParser().parseFromString(xmlStr, 'text/xml'); + } + return xmlObj; +} + +function xml2json(xml) { + try { + let obj = {}; + if (xml.children.length > 0) { + for (let i = 0; i < xml.children.length; i++) { + const item = xml.children.item(i); + const nodeName = item.nodeName; + if (obj[nodeName] === undefined) { + obj[nodeName] = xml2json(item); + } else { + if (obj[nodeName].push === undefined) { + const old = obj[nodeName]; + obj[nodeName] = []; + obj[nodeName].push(old); + } + obj[nodeName].push(xml2json(item)); + } + } + } else { + obj = xml.textContent; + } + return obj; + } catch (error) { + console.warn(error.message); + } +} + +function xmlObj2json(xml) { + const xmlObj = xmlStr2XmlObj(xml); + console.warn(xmlObj); + let jsonObj = {}; + if (xmlObj.childNodes.length > 0) { + jsonObj = xml2json(xmlObj); + } + return jsonObj; +} + +export default xmlObj2json; diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/child-process-node-config.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/child-process-node-config.vue new file mode 100644 index 0000000..bf9d637 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/child-process-node-config.vue @@ -0,0 +1,779 @@ + + + + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/condition-node-config.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/condition-node-config.vue new file mode 100644 index 0000000..d51eb57 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/condition-node-config.vue @@ -0,0 +1,197 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/copy-task-node-config.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/copy-task-node-config.vue new file mode 100644 index 0000000..461268b --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/copy-task-node-config.vue @@ -0,0 +1,472 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue new file mode 100644 index 0000000..2366eb9 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue @@ -0,0 +1,235 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/condition-dialog.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/condition-dialog.vue new file mode 100644 index 0000000..5fc3042 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/condition-dialog.vue @@ -0,0 +1,79 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/condition.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/condition.vue new file mode 100644 index 0000000..88171bc --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/condition.vue @@ -0,0 +1,313 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/http-request-param-setting.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/http-request-param-setting.vue new file mode 100644 index 0000000..43550ea --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/http-request-param-setting.vue @@ -0,0 +1,223 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/http-request-setting.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/http-request-setting.vue new file mode 100644 index 0000000..1561174 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/http-request-setting.vue @@ -0,0 +1,168 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/user-task-listener.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/user-task-listener.vue new file mode 100644 index 0000000..244e472 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/modules/user-task-listener.vue @@ -0,0 +1,109 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/router-node-config.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/router-node-config.vue new file mode 100644 index 0000000..8f89070 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/router-node-config.vue @@ -0,0 +1,291 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/start-user-node-config.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/start-user-node-config.vue new file mode 100644 index 0000000..bae452f --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/start-user-node-config.vue @@ -0,0 +1,268 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/trigger-node-config.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/trigger-node-config.vue new file mode 100644 index 0000000..0614bb5 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/trigger-node-config.vue @@ -0,0 +1,683 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/user-task-node-config.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/user-task-node-config.vue new file mode 100644 index 0000000..496d4a8 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/user-task-node-config.vue @@ -0,0 +1,1180 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/utils.ts b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/utils.ts new file mode 100644 index 0000000..ee5e068 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes-config/utils.ts @@ -0,0 +1,48 @@ +import { APPROVE_TYPE, ApproveType, TimeUnitType } from '../../consts'; + +/** 获取条件节点默认的名称 */ +export function getDefaultConditionNodeName( + index: number, + defaultFlow: boolean | undefined, +): string { + if (defaultFlow) { + return '其它情况'; + } + return `条件${index + 1}`; +} + +/** 获取包容分支条件节点默认的名称 */ +export function getDefaultInclusiveConditionNodeName( + index: number, + defaultFlow: boolean | undefined, +): string { + if (defaultFlow) { + return '其它情况'; + } + return `包容条件${index + 1}`; +} + +/** 转换时间单位字符串为枚举值 */ +export function convertTimeUnit(strTimeUnit: string) { + if (strTimeUnit === 'M') { + return TimeUnitType.MINUTE; + } + if (strTimeUnit === 'H') { + return TimeUnitType.HOUR; + } + if (strTimeUnit === 'D') { + return TimeUnitType.DAY; + } + return TimeUnitType.HOUR; +} + +/** 根据审批类型获取对应的文本描述 */ +export function getApproveTypeText(approveType: ApproveType): string { + let approveTypeText = ''; + APPROVE_TYPE.forEach((item) => { + if (item.value === approveType) { + approveTypeText = item.label; + } + }); + return approveTypeText; +} diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/child-process-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/child-process-node.vue new file mode 100644 index 0000000..cb4b928 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/child-process-node.vue @@ -0,0 +1,127 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/copy-task-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/copy-task-node.vue new file mode 100644 index 0000000..33b3758 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/copy-task-node.vue @@ -0,0 +1,120 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/delay-timer-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/delay-timer-node.vue new file mode 100644 index 0000000..cdde90a --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/delay-timer-node.vue @@ -0,0 +1,117 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/end-event-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/end-event-node.vue new file mode 100644 index 0000000..bf6a2c1 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/end-event-node.vue @@ -0,0 +1,61 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/exclusive-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/exclusive-node.vue new file mode 100644 index 0000000..34562ae --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/exclusive-node.vue @@ -0,0 +1,307 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/inclusive-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/inclusive-node.vue new file mode 100644 index 0000000..d3cf1b4 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/inclusive-node.vue @@ -0,0 +1,309 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/process-instance-data.ts b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/process-instance-data.ts new file mode 100644 index 0000000..a9f2a06 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/process-instance-data.ts @@ -0,0 +1,56 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +/** 流程实例列表字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'startUser', + title: '发起人', + slots: { + default: ({ row }: { row: any }) => { + return row.startUser?.nickname; + }, + }, + minWidth: 100, + }, + { + field: 'deptName', + title: '部门', + slots: { + default: ({ row }: { row: any }) => { + return row.startUser?.deptName; + }, + }, + minWidth: 100, + }, + { + field: 'createTime', + title: '开始时间', + formatter: 'formatDateTime', + minWidth: 140, + }, + { + field: 'endTime', + title: '结束时间', + formatter: 'formatDateTime', + minWidth: 140, + }, + { + field: 'status', + title: '流程状态', + minWidth: 90, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS }, + }, + }, + { + field: 'durationInMillis', + title: '耗时', + minWidth: 100, + formatter: 'formatPast2', + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/process-instance-modal.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/process-instance-modal.vue new file mode 100644 index 0000000..c66bcef --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/process-instance-modal.vue @@ -0,0 +1,45 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/task-list-data.ts b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/task-list-data.ts new file mode 100644 index 0000000..fbb2d0e --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/task-list-data.ts @@ -0,0 +1,61 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +/** 审批记录列表字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'assigneeUser', + title: '审批人', + slots: { + default: ({ row }: { row: any }) => { + return row.assigneeUser?.nickname || row.ownerUser?.nickname; + }, + }, + minWidth: 100, + }, + { + field: 'deptName', + title: '部门', + slots: { + default: ({ row }: { row: any }) => { + return row.assigneeUser?.deptName || row.ownerUser?.deptName; + }, + }, + minWidth: 100, + }, + { + field: 'createTime', + title: '开始时间', + formatter: 'formatDateTime', + minWidth: 140, + }, + { + field: 'endTime', + title: '结束时间', + formatter: 'formatDateTime', + minWidth: 140, + }, + { + field: 'status', + title: '审批状态', + minWidth: 90, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_TASK_STATUS }, + }, + }, + { + field: 'reason', + title: '审批建议', + minWidth: 160, + }, + { + field: 'durationInMillis', + title: '耗时', + minWidth: 100, + formatter: 'formatPast2', + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/task-list-modal.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/task-list-modal.vue new file mode 100644 index 0000000..baa4cc7 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/modules/task-list-modal.vue @@ -0,0 +1,48 @@ + + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/node-handler.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/node-handler.vue new file mode 100644 index 0000000..af40f45 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/node-handler.vue @@ -0,0 +1,355 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/parallel-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/parallel-node.vue new file mode 100644 index 0000000..1c13a78 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/parallel-node.vue @@ -0,0 +1,230 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/router-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/router-node.vue new file mode 100644 index 0000000..4305283 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/router-node.vue @@ -0,0 +1,119 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/start-user-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/start-user-node.vue new file mode 100644 index 0000000..73775c5 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/start-user-node.vue @@ -0,0 +1,128 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/trigger-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/trigger-node.vue new file mode 100644 index 0000000..37d1541 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/trigger-node.vue @@ -0,0 +1,122 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/user-task-node.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/user-task-node.vue new file mode 100644 index 0000000..a95b333 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/nodes/user-task-node.vue @@ -0,0 +1,154 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/process-node-tree.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/process-node-tree.vue new file mode 100644 index 0000000..6773700 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/process-node-tree.vue @@ -0,0 +1,164 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/simple-process-designer.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/simple-process-designer.vue new file mode 100644 index 0000000..d66629c --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/simple-process-designer.vue @@ -0,0 +1,255 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/simple-process-model.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/simple-process-model.vue new file mode 100644 index 0000000..d4fa3b1 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/simple-process-model.vue @@ -0,0 +1,267 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/components/simple-process-viewer.vue b/apps/web-ele/src/views/bpm/components/simple-process-design/components/simple-process-viewer.vue new file mode 100644 index 0000000..95cf3f3 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/components/simple-process-viewer.vue @@ -0,0 +1,45 @@ + + diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/consts.ts b/apps/web-ele/src/views/bpm/components/simple-process-design/consts.ts new file mode 100644 index 0000000..e811314 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/consts.ts @@ -0,0 +1,888 @@ +import { BpmNodeTypeEnum, BpmTaskStatusEnum } from '@vben/constants'; + +interface DictDataType { + label: string; + value: number | string; +} + +// 用户任务的审批类型。 【参考飞书】 +export enum ApproveType { + /** + * 自动通过 + */ + AUTO_APPROVE = 2, + /** + * 自动拒绝 + */ + AUTO_REJECT = 3, + /** + * 人工审批 + */ + USER = 1, +} + +// 多人审批方式类型枚举 ( 用于审批节点 ) +export enum ApproveMethodType { + /** + * 多人或签(通过只需一人,拒绝只需一人) + */ + ANY_APPROVE = 3, + + /** + * 多人会签(按通过比例) + */ + APPROVE_BY_RATIO = 2, + + /** + * 随机挑选一人审批 + */ + RANDOM_SELECT_ONE_APPROVE = 1, + /** + * 多人依次审批 + */ + SEQUENTIAL_APPROVE = 4, +} + +export enum NodeId { + /** + * 发起人节点 Id + */ + END_EVENT_NODE_ID = 'EndEvent', + + /** + * 发起人节点 Id + */ + START_USER_NODE_ID = 'StartUserNode', +} + +// 条件配置类型 ( 用于条件节点配置 ) +export enum ConditionType { + /** + * 条件表达式 + */ + EXPRESSION = 1, + + /** + * 条件规则 + */ + RULE = 2, +} + +// 操作按钮类型枚举 (用于审批节点) +export enum OperationButtonType { + /** + * 加签 + */ + ADD_SIGN = 5, + /** + * 通过 + */ + APPROVE = 1, + /** + * 抄送 + */ + COPY = 7, + /** + * 委派 + */ + DELEGATE = 4, + /** + * 拒绝 + */ + REJECT = 2, + /** + * 退回 + */ + RETURN = 6, + /** + * 转办 + */ + TRANSFER = 3, +} + +// 审批拒绝类型枚举 +export enum RejectHandlerType { + /** + * 结束流程 + */ + FINISH_PROCESS = 1, + /** + * 驳回到指定节点 + */ + RETURN_USER_TASK = 2, +} + +// 用户任务超时处理类型枚举 +export enum TimeoutHandlerType { + /** + * 自动同意 + */ + APPROVE = 2, + /** + * 自动拒绝 + */ + REJECT = 3, + /** + * 自动提醒 + */ + REMINDER = 1, +} + +// 用户任务的审批人为空时,处理类型枚举 +export enum AssignEmptyHandlerType { + /** + * 自动通过 + */ + APPROVE = 1, + /** + * 转交给流程管理员 + */ + ASSIGN_ADMIN = 4, + /** + * 指定人员审批 + */ + ASSIGN_USER = 3, + /** + * 自动拒绝 + */ + REJECT = 2, +} + +// 用户任务的审批人与发起人相同时,处理类型枚举 +export enum AssignStartUserHandlerType { + /** + * 转交给部门负责人审批 + */ + ASSIGN_DEPT_LEADER = 3, + /** + * 自动跳过【参考飞书】:1)如果当前节点还有其他审批人,则交由其他审批人进行审批;2)如果当前节点没有其他审批人,则该节点自动通过 + */ + SKIP = 2, + /** + * 由发起人对自己审批 + */ + START_USER_AUDIT = 1, +} + +// 时间单位枚举 +export enum TimeUnitType { + /** + * 天 + */ + DAY = 3, + /** + * 小时 + */ + HOUR = 2, + /** + * 分钟 + */ + MINUTE = 1, +} + +/** + * 表单权限的枚举 + */ +export enum FieldPermissionType { + /** + * 隐藏 + */ + NONE = '3', + /** + * 只读 + */ + READ = '1', + /** + * 编辑 + */ + WRITE = '2', +} + +/** + * 延迟类型 + */ +export enum DelayTypeEnum { + /** + * 固定日期时间 + */ + FIXED_DATE_TIME = 2, + /** + * 固定时长 + */ + FIXED_TIME_DURATION = 1, +} + +/** + * 触发器类型枚举 + */ +export enum TriggerTypeEnum { + /** + * 表单数据删除触发器 + */ + FORM_DELETE = 11, + /** + * 表单数据更新触发器 + */ + FORM_UPDATE = 10, + /** + * 接收 HTTP 回调请求触发器 + */ + HTTP_CALLBACK = 2, + /** + * 发送 HTTP 请求触发器 + */ + HTTP_REQUEST = 1, +} + +export enum ChildProcessStartUserTypeEnum { + /** + * 表单 + */ + FROM_FORM = 2, + /** + * 同主流程发起人 + */ + MAIN_PROCESS_START_USER = 1, +} + +export enum ChildProcessStartUserEmptyTypeEnum { + /** + * 子流程管理员 + */ + CHILD_PROCESS_ADMIN = 2, + /** + * 主流程管理员 + */ + MAIN_PROCESS_ADMIN = 3, + /** + * 同主流程发起人 + */ + MAIN_PROCESS_START_USER = 1, +} + +export enum ChildProcessMultiInstanceSourceTypeEnum { + /** + * 固定数量 + */ + FIXED_QUANTITY = 1, + /** + * 多选表单 + */ + MULTIPLE_FORM = 3, + /** + * 数字表单 + */ + NUMBER_FORM = 2, +} + +// 候选人策略枚举 ( 用于审批节点。抄送节点 ) +export enum CandidateStrategy { + /** + * 审批人自选 + */ + APPROVE_USER_SELECT = 34, + /** + * 部门的负责人 + */ + DEPT_LEADER = 21, + /** + * 部门成员 + */ + DEPT_MEMBER = 20, + /** + * 流程表达式 + */ + EXPRESSION = 60, + /** + * 表单内部门负责人 + */ + FORM_DEPT_LEADER = 51, + /** + * 表单内用户字段 + */ + FORM_USER = 50, + /** + * 连续多级部门的负责人 + */ + MULTI_LEVEL_DEPT_LEADER = 23, + /** + * 指定岗位 + */ + POST = 22, + /** + * 指定角色 + */ + ROLE = 10, + /** + * 发起人自己 + */ + START_USER = 36, + /** + * 发起人部门负责人 + */ + START_USER_DEPT_LEADER = 37, + /** + * 发起人连续多级部门的负责人 + */ + START_USER_MULTI_LEVEL_DEPT_LEADER = 38, + /** + * 发起人自选 + */ + START_USER_SELECT = 35, + /** + * 指定用户 + */ + USER = 30, + /** + * 指定用户组 + */ + USER_GROUP = 40, +} + +export enum BpmHttpRequestParamTypeEnum { + /** + * 固定值 + */ + FIXED_VALUE = 1, + /** + * 表单 + */ + FROM_FORM = 2, +} + +// 这里定义 HTTP 请求参数类型 +export type HttpRequestParam = { + key: string; + type: number; + value: string; +}; + +// 监听器结构定义 +export type ListenerHandler = { + body?: HttpRequestParam[]; + enable: boolean; + header?: HttpRequestParam[]; + path?: string; +}; + +/** + * 条件规则结构定义 + */ +export type ConditionRule = { + leftSide: string | undefined; + opCode: string; + rightSide: string | undefined; +}; + +/** + * 条件结构定义 + */ +export type Condition = { + // 条件规则的逻辑关系是否为且 + and: boolean; + rules: ConditionRule[]; +}; + +/** + * 条件组结构定义 + */ +export type ConditionGroup = { + // 条件组的逻辑关系是否为且 + and: boolean; + // 条件数组 + conditions: Condition[]; +}; + +/** + * 条件节点设置结构定义,用于条件节点 + */ +export type ConditionSetting = { + // 条件表达式 + conditionExpression?: string; + // 条件组 + conditionGroups?: ConditionGroup; + // 条件类型 + conditionType?: ConditionType; + // 是否默认的条件 + defaultFlow?: boolean; +}; + +/** + * 审批拒绝结构定义 + */ +export type RejectHandler = { + // 退回节点 Id + returnNodeId?: string; + // 审批拒绝类型 + type: RejectHandlerType; +}; + +/** + * 审批超时结构定义 + */ +export type TimeoutHandler = { + // 是否开启超时处理 + enable: boolean; + // 执行动作是自动提醒, 最大提醒次数 + maxRemindCount?: number; + // 超时时间设置 + timeDuration?: string; + // 超时执行的动作 + type?: number; +}; + +/** + * 审批人为空的结构定义 + */ +export type AssignEmptyHandler = { + // 审批人为空的处理类型 + type: AssignEmptyHandlerType; + // 指定用户的编号数组 + userIds?: number[]; +}; + +/** + * 延迟设置 + */ +export type DelaySetting = { + // 延迟时间表达式 + delayTime: string; + // 延迟类型 + delayType: number; +}; + +/** + * 路由分支结构定义 + */ +export type RouterSetting = { + conditionExpression: string; + conditionGroups: ConditionGroup; + conditionType: ConditionType; + nodeId: string | undefined; +}; + +/** + * 操作按钮权限结构定义 + */ +export type ButtonSetting = { + displayName: string; + enable: boolean; + id: OperationButtonType; +}; + +/** + * HTTP 请求触发器结构定义 + */ +export type HttpRequestTriggerSetting = { + // 请求体参数设置 + body?: HttpRequestParam[]; + // 请求头参数设置 + header?: HttpRequestParam[]; + // 请求响应设置 + response?: Record[]; + // 请求 URL + url: string; +}; + +/** + * 流程表单触发器配置结构定义 + */ +export type FormTriggerSetting = { + // 条件表达式 + conditionExpression?: string; + // 条件组 + conditionGroups?: ConditionGroup; + // 条件类型 + conditionType?: ConditionType; + // 删除表单字段配置 + deleteFields?: string[]; + // 更新表单字段配置 + updateFormFields?: Record; +}; + +/** + * 触发器节点结构定义 + */ +export type TriggerSetting = { + formSettings?: FormTriggerSetting[]; + httpRequestSetting?: HttpRequestTriggerSetting; + type: TriggerTypeEnum; +}; + +export type IOParameter = { + source: string; + target: string; +}; + +export type StartUserSetting = { + emptyType?: ChildProcessStartUserEmptyTypeEnum; + formField?: string; + type: ChildProcessStartUserTypeEnum; +}; + +export type TimeoutSetting = { + enable: boolean; + timeExpression?: string; + type?: DelayTypeEnum; +}; + +export type MultiInstanceSetting = { + approveRatio?: number; + enable: boolean; + sequential?: boolean; + source?: string; + sourceType?: ChildProcessMultiInstanceSourceTypeEnum; +}; + +/** + * 子流程节点结构定义 + */ +export type ChildProcessSetting = { + async: boolean; + calledProcessDefinitionKey: string; + calledProcessDefinitionName: string; + inVariables?: IOParameter[]; + multiInstanceSetting: MultiInstanceSetting; + outVariables?: IOParameter[]; + skipStartUserNode: boolean; + startUserSetting: StartUserSetting; + timeoutSetting: TimeoutSetting; +}; + +/** + * 节点结构定义 + */ +export interface SimpleFlowNode { + id: string; + type: BpmNodeTypeEnum; + name: string; + showText?: string; + // 孩子节点 + childNode?: SimpleFlowNode; + // 条件节点 + conditionNodes?: SimpleFlowNode[]; + // 审批类型 + approveType?: ApproveType; + // 候选人策略 + candidateStrategy?: number; + // 候选人参数 + candidateParam?: string; + // 多人审批方式 + approveMethod?: ApproveMethodType; + // 通过比例 + approveRatio?: number; + // 审批按钮设置 + buttonsSetting?: any[]; + // 表单权限 + fieldsPermission?: Array>; + // 审批任务超时处理 + timeoutHandler?: TimeoutHandler; + // 审批任务拒绝处理 + rejectHandler?: RejectHandler; + // 审批人为空的处理 + assignEmptyHandler?: AssignEmptyHandler; + // 审批节点的审批人与发起人相同时,对应的处理类型 + assignStartUserHandlerType?: number; + // 创建任务监听器 + taskCreateListener?: ListenerHandler; + // 创建任务监听器 + taskAssignListener?: ListenerHandler; + // 创建任务监听器 + taskCompleteListener?: ListenerHandler; + // 条件设置 + conditionSetting?: ConditionSetting; + // 活动的状态,用于前端节点状态展示 + activityStatus?: BpmTaskStatusEnum; + // 延迟设置 + delaySetting?: DelaySetting; + // 路由分支 + routerGroups?: RouterSetting[]; + defaultFlowId?: string; + // 签名 + signEnable?: boolean; + // 审批意见 + reasonRequire?: boolean; + // 跳过表达式 + skipExpression?: string; + // 触发器设置 + triggerSetting?: TriggerSetting; + // 子流程 + childProcessSetting?: ChildProcessSetting; +} + +/** + * 条件组默认值 + */ +export const DEFAULT_CONDITION_GROUP_VALUE = { + and: true, + conditions: [ + { + and: true, + rules: [ + { + opCode: '==', + leftSide: undefined, + rightSide: '', + }, + ], + }, + ], +}; + +export const NODE_DEFAULT_TEXT = new Map(); +NODE_DEFAULT_TEXT.set(BpmNodeTypeEnum.USER_TASK_NODE, '请配置审批人'); +NODE_DEFAULT_TEXT.set(BpmNodeTypeEnum.COPY_TASK_NODE, '请配置抄送人'); +NODE_DEFAULT_TEXT.set(BpmNodeTypeEnum.CONDITION_NODE, '请设置条件'); +NODE_DEFAULT_TEXT.set(BpmNodeTypeEnum.START_USER_NODE, '请设置发起人'); +NODE_DEFAULT_TEXT.set(BpmNodeTypeEnum.DELAY_TIMER_NODE, '请设置延迟器'); +NODE_DEFAULT_TEXT.set(BpmNodeTypeEnum.ROUTER_BRANCH_NODE, '请设置路由节点'); +NODE_DEFAULT_TEXT.set(BpmNodeTypeEnum.TRIGGER_NODE, '请设置触发器'); +NODE_DEFAULT_TEXT.set(BpmNodeTypeEnum.TRANSACTOR_NODE, '请设置办理人'); +NODE_DEFAULT_TEXT.set(BpmNodeTypeEnum.CHILD_PROCESS_NODE, '请设置子流程'); + +export const NODE_DEFAULT_NAME = new Map(); +NODE_DEFAULT_NAME.set(BpmNodeTypeEnum.USER_TASK_NODE, '审批人'); +NODE_DEFAULT_NAME.set(BpmNodeTypeEnum.COPY_TASK_NODE, '抄送人'); +NODE_DEFAULT_NAME.set(BpmNodeTypeEnum.CONDITION_NODE, '条件'); +NODE_DEFAULT_NAME.set(BpmNodeTypeEnum.START_USER_NODE, '发起人'); +NODE_DEFAULT_NAME.set(BpmNodeTypeEnum.DELAY_TIMER_NODE, '延迟器'); +NODE_DEFAULT_NAME.set(BpmNodeTypeEnum.ROUTER_BRANCH_NODE, '路由分支'); +NODE_DEFAULT_NAME.set(BpmNodeTypeEnum.TRIGGER_NODE, '触发器'); +NODE_DEFAULT_NAME.set(BpmNodeTypeEnum.TRANSACTOR_NODE, '办理人'); +NODE_DEFAULT_NAME.set(BpmNodeTypeEnum.CHILD_PROCESS_NODE, '子流程'); + +// 候选人策略。暂时不从字典中取。 后续可能调整。控制显示顺序 +export const CANDIDATE_STRATEGY: DictDataType[] = [ + { label: '指定成员', value: CandidateStrategy.USER as any }, + { label: '指定角色', value: CandidateStrategy.ROLE as any }, + { label: '指定岗位', value: CandidateStrategy.POST as any }, + { label: '部门成员', value: CandidateStrategy.DEPT_MEMBER as any }, + { label: '部门负责人', value: CandidateStrategy.DEPT_LEADER as any }, + { + label: '连续多级部门负责人', + value: CandidateStrategy.MULTI_LEVEL_DEPT_LEADER as any, + }, + { label: '发起人自选', value: CandidateStrategy.START_USER_SELECT as any }, + { label: '审批人自选', value: CandidateStrategy.APPROVE_USER_SELECT as any }, + { label: '发起人本人', value: CandidateStrategy.START_USER as any }, + { + label: '发起人部门负责人', + value: CandidateStrategy.START_USER_DEPT_LEADER as any, + }, + { + label: '发起人连续部门负责人', + value: CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER as any, + }, + { label: '用户组', value: CandidateStrategy.USER_GROUP as any }, + { label: '表单内用户字段', value: CandidateStrategy.FORM_USER as any }, + { + label: '表单内部门负责人', + value: CandidateStrategy.FORM_DEPT_LEADER as any, + }, + { label: '流程表达式', value: CandidateStrategy.EXPRESSION as any }, +]; +// 审批节点 的审批类型 +export const APPROVE_TYPE: DictDataType[] = [ + { label: '人工审批', value: ApproveType.USER as any }, + { label: '自动通过', value: ApproveType.AUTO_APPROVE as any }, + { label: '自动拒绝', value: ApproveType.AUTO_REJECT as any }, +]; + +export const APPROVE_METHODS: DictDataType[] = [ + { + label: '按顺序依次审批', + value: ApproveMethodType.SEQUENTIAL_APPROVE as any, + }, + { + label: '会签(可同时审批,至少 % 人必须审批通过)', + value: ApproveMethodType.APPROVE_BY_RATIO as any, + }, + { + label: '或签(可同时审批,有一人通过即可)', + value: ApproveMethodType.ANY_APPROVE as any, + }, + { + label: '随机挑选一人审批', + value: ApproveMethodType.RANDOM_SELECT_ONE_APPROVE as any, + }, +]; + +export const CONDITION_CONFIG_TYPES: DictDataType[] = [ + { label: '条件规则', value: ConditionType.RULE as any }, + { label: '条件表达式', value: ConditionType.EXPRESSION as any }, +]; + +// 时间单位类型 +export const TIME_UNIT_TYPES: DictDataType[] = [ + { label: '分钟', value: TimeUnitType.MINUTE as any }, + { label: '小时', value: TimeUnitType.HOUR as any }, + { label: '天', value: TimeUnitType.DAY as any }, +]; +// 超时处理执行动作类型 +export const TIMEOUT_HANDLER_TYPES: DictDataType[] = [ + { label: '自动提醒', value: 1 }, + { label: '自动同意', value: 2 }, + { label: '自动拒绝', value: 3 }, +]; +export const REJECT_HANDLER_TYPES: DictDataType[] = [ + { label: '终止流程', value: RejectHandlerType.FINISH_PROCESS as any }, + { label: '驳回到指定节点', value: RejectHandlerType.RETURN_USER_TASK as any }, + // { label: '结束任务', value: RejectHandlerType.FINISH_TASK } +]; +export const ASSIGN_EMPTY_HANDLER_TYPES: DictDataType[] = [ + { label: '自动通过', value: 1 }, + { label: '自动拒绝', value: 2 }, + { label: '指定成员审批', value: 3 }, + { label: '转交给流程管理员', value: 4 }, +]; +export const ASSIGN_START_USER_HANDLER_TYPES: DictDataType[] = [ + { label: '由发起人对自己审批', value: 1 }, + { label: '自动跳过', value: 2 }, + { label: '转交给部门负责人审批', value: 3 }, +]; + +// 比较运算符 +export const COMPARISON_OPERATORS: DictDataType[] = [ + { + value: '==', + label: '等于', + }, + { + value: '!=', + label: '不等于', + }, + { + value: '>', + label: '大于', + }, + { + value: '>=', + label: '大于等于', + }, + { + value: '<', + label: '小于', + }, + { + value: '<=', + label: '小于等于', + }, +]; +// 审批操作按钮名称 +export const OPERATION_BUTTON_NAME = new Map(); +OPERATION_BUTTON_NAME.set(OperationButtonType.APPROVE, '通过'); +OPERATION_BUTTON_NAME.set(OperationButtonType.REJECT, '拒绝'); +OPERATION_BUTTON_NAME.set(OperationButtonType.TRANSFER, '转办'); +OPERATION_BUTTON_NAME.set(OperationButtonType.DELEGATE, '委派'); +OPERATION_BUTTON_NAME.set(OperationButtonType.ADD_SIGN, '加签'); +OPERATION_BUTTON_NAME.set(OperationButtonType.RETURN, '退回'); +OPERATION_BUTTON_NAME.set(OperationButtonType.COPY, '抄送'); + +// 默认的按钮权限设置 +export const DEFAULT_BUTTON_SETTING: ButtonSetting[] = [ + { id: OperationButtonType.APPROVE, displayName: '通过', enable: true }, + { id: OperationButtonType.REJECT, displayName: '拒绝', enable: true }, + { id: OperationButtonType.TRANSFER, displayName: '转办', enable: true }, + { id: OperationButtonType.DELEGATE, displayName: '委派', enable: true }, + { id: OperationButtonType.ADD_SIGN, displayName: '加签', enable: true }, + { id: OperationButtonType.RETURN, displayName: '退回', enable: true }, +]; + +// 办理人默认的按钮权限设置 +export const TRANSACTOR_DEFAULT_BUTTON_SETTING: ButtonSetting[] = [ + { id: OperationButtonType.APPROVE, displayName: '办理', enable: true }, + { id: OperationButtonType.REJECT, displayName: '拒绝', enable: false }, + { id: OperationButtonType.TRANSFER, displayName: '转办', enable: false }, + { id: OperationButtonType.DELEGATE, displayName: '委派', enable: false }, + { id: OperationButtonType.ADD_SIGN, displayName: '加签', enable: false }, + { id: OperationButtonType.RETURN, displayName: '退回', enable: false }, +]; + +// 发起人的按钮权限。暂时定死,不可以编辑 +export const START_USER_BUTTON_SETTING: ButtonSetting[] = [ + { id: OperationButtonType.APPROVE, displayName: '提交', enable: true }, + { id: OperationButtonType.REJECT, displayName: '拒绝', enable: false }, + { id: OperationButtonType.TRANSFER, displayName: '转办', enable: false }, + { id: OperationButtonType.DELEGATE, displayName: '委派', enable: false }, + { id: OperationButtonType.ADD_SIGN, displayName: '加签', enable: false }, + { id: OperationButtonType.RETURN, displayName: '退回', enable: false }, +]; + +export const MULTI_LEVEL_DEPT: DictDataType[] = [ + { label: '第 1 级部门', value: 1 }, + { label: '第 2 级部门', value: 2 }, + { label: '第 3 级部门', value: 3 }, + { label: '第 4 级部门', value: 4 }, + { label: '第 5 级部门', value: 5 }, + { label: '第 6 级部门', value: 6 }, + { label: '第 7 级部门', value: 7 }, + { label: '第 8 级部门', value: 8 }, + { label: '第 9 级部门', value: 9 }, + { label: '第 10 级部门', value: 10 }, + { label: '第 11 级部门', value: 11 }, + { label: '第 12 级部门', value: 12 }, + { label: '第 13 级部门', value: 13 }, + { label: '第 14 级部门', value: 14 }, + { label: '第 15 级部门', value: 15 }, +]; + +export const DELAY_TYPE = [ + { label: '固定时长', value: DelayTypeEnum.FIXED_TIME_DURATION }, + { label: '固定日期', value: DelayTypeEnum.FIXED_DATE_TIME }, +]; + +export const BPM_HTTP_REQUEST_PARAM_TYPES = [ + { + value: 1, + label: '固定值', + }, + { + value: 2, + label: '表单', + }, +]; + +export const TRIGGER_TYPES: DictDataType[] = [ + { label: '发送 HTTP 请求', value: TriggerTypeEnum.HTTP_REQUEST as any }, + { label: '接收 HTTP 回调', value: TriggerTypeEnum.HTTP_CALLBACK as any }, + { label: '修改表单数据', value: TriggerTypeEnum.FORM_UPDATE as any }, + { label: '删除表单数据', value: TriggerTypeEnum.FORM_DELETE as any }, +]; + +export const CHILD_PROCESS_START_USER_TYPE = [ + { + label: '同主流程发起人', + value: ChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER, + }, + { label: '从表单中获取', value: ChildProcessStartUserTypeEnum.FROM_FORM }, +]; + +export const CHILD_PROCESS_START_USER_EMPTY_TYPE = [ + { + label: '同主流程发起人', + value: ChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER, + }, + { + label: '子流程管理员', + value: ChildProcessStartUserEmptyTypeEnum.CHILD_PROCESS_ADMIN, + }, + { + label: '主流程管理员', + value: ChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN, + }, +]; + +export const CHILD_PROCESS_MULTI_INSTANCE_SOURCE_TYPE = [ + { + label: '固定数量', + value: ChildProcessMultiInstanceSourceTypeEnum.FIXED_QUANTITY, + }, + { + label: '数字表单', + value: ChildProcessMultiInstanceSourceTypeEnum.NUMBER_FORM, + }, + { + label: '多选表单', + value: ChildProcessMultiInstanceSourceTypeEnum.MULTIPLE_FORM, + }, +]; diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/helpers.ts b/apps/web-ele/src/views/bpm/components/simple-process-design/helpers.ts new file mode 100644 index 0000000..0971c7d --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/helpers.ts @@ -0,0 +1,793 @@ +import type { Ref } from 'vue'; + +import type { + ConditionGroup, + HttpRequestParam, + SimpleFlowNode, +} from './consts'; + +import type { BpmUserGroupApi } from '#/api/bpm/userGroup'; +import type { SystemDeptApi } from '#/api/system/dept'; +import type { SystemPostApi } from '#/api/system/post'; +import type { SystemRoleApi } from '#/api/system/role'; +import type { SystemUserApi } from '#/api/system/user'; + +import { inject, nextTick, ref, toRaw, unref, watch } from 'vue'; + +import { + BpmNodeTypeEnum, + BpmTaskStatusEnum, + ProcessVariableEnum, +} from '@vben/constants'; + +import { + ApproveMethodType, + AssignEmptyHandlerType, + AssignStartUserHandlerType, + CandidateStrategy, + COMPARISON_OPERATORS, + ConditionType, + FieldPermissionType, + NODE_DEFAULT_NAME, + RejectHandlerType, +} from './consts'; + +export function useWatchNode(props: { + flowNode: SimpleFlowNode; +}): Ref { + const node = ref(props.flowNode); + watch( + () => props.flowNode, + (newValue) => { + node.value = newValue; + }, + ); + return node; +} + +// 解析 formCreate 所有表单字段, 并返回 +// TODO @jason:这个逻辑,和 antd 对应的逻辑不太一致; +function parseFormCreateFields(formFields?: string[]) { + const result: Array> = []; + if (formFields) { + formFields.forEach((fieldStr: string) => { + parseFormFields(JSON.parse(fieldStr), result); + }); + } + return result; +} + +/** + * 解析表单组件的 field, title 等字段(递归,如果组件包含子组件) + * + * @param rule 组件的生成规则 https://www.form-create.com/v3/guide/rule + * @param fields 解析后表单组件字段 + * @param parentTitle 如果是子表单,子表单的标题,默认为空 + */ +export const parseFormFields = ( + rule: Record, + fields: Array> = [], + parentTitle: string = '', +) => { + const { type, field, $required, title: tempTitle, children } = rule; + if (field && tempTitle) { + let title = tempTitle; + if (parentTitle) { + title = `${parentTitle}.${tempTitle}`; + } + let required = false; + if ($required) { + required = true; + } + fields.push({ + field, + title, + type, + required, + }); + // TODO 子表单 需要处理子表单字段 + // if (type === 'group' && rule.props?.rule && Array.isArray(rule.props.rule)) { + // // 解析子表单的字段 + // rule.props.rule.forEach((item) => { + // parseFields(item, fieldsPermission, title) + // }) + // } + } + if (children && Array.isArray(children)) { + children.forEach((rule) => { + parseFormFields(rule, fields); + }); + } +}; + +/** + * @description 表单数据权限配置,用于发起人节点 、审批节点、抄送节点 + */ +export function useFormFieldsPermission( + defaultPermission: FieldPermissionType, +) { + // 字段权限配置. 需要有 field, title, permissioin 属性 + const fieldsPermissionConfig = ref>>([]); + + const formType = inject>('formType', ref()); // 表单类型 + + const formFields = inject>('formFields', ref([])); // 流程表单字段 + + function getNodeConfigFormFields( + nodeFormFields?: Array>, + ) { + nodeFormFields = toRaw(nodeFormFields); + fieldsPermissionConfig.value = + !nodeFormFields || nodeFormFields.length === 0 + ? getDefaultFieldsPermission(unref(formFields)) + : mergeFieldsPermission(nodeFormFields, unref(formFields)); + } + // 合并已经设置的表单字段权限,当前流程表单字段 (可能新增,或删除了字段) + function mergeFieldsPermission( + formFieldsPermisson: Array>, + formFields?: string[], + ) { + let mergedFieldsPermission: Array> = []; + if (formFields) { + mergedFieldsPermission = parseFormCreateFields(formFields).map((item) => { + const found = formFieldsPermisson.find( + (fieldPermission) => fieldPermission.field === item.field, + ); + return { + field: item.field, + title: item.title, + permission: found ? found.permission : defaultPermission, + }; + }); + } + return mergedFieldsPermission; + } + + // 默认的表单权限: 获取表单的所有字段,设置字段默认权限为只读 + function getDefaultFieldsPermission(formFields?: string[]) { + let defaultFieldsPermission: Array> = []; + if (formFields) { + defaultFieldsPermission = parseFormCreateFields(formFields).map( + (item) => { + return { + field: item.field, + title: item.title, + permission: defaultPermission, + }; + }, + ); + } + return defaultFieldsPermission; + } + + // 获取表单的所有字段,作为下拉框选项 + const formFieldOptions = parseFormCreateFields(unref(formFields)); + + return { + formType, + fieldsPermissionConfig, + formFieldOptions, + getNodeConfigFormFields, + }; +} + +/** + * @description 获取流程表单的字段 + */ +export function useFormFields() { + const formFields = inject>('formFields', ref([])); // 流程表单字段 + return parseFormCreateFields(unref(formFields)); +} + +// TODO @芋艿:后续需要把各种类似 useFormFieldsPermission 的逻辑,抽成一个通用方法。 +/** + * @description 获取流程表单的字段和发起人字段 + */ +export function useFormFieldsAndStartUser() { + const injectFormFields = inject>('formFields', ref([])); // 流程表单字段 + const formFields = parseFormCreateFields(unref(injectFormFields)); + // 添加发起人 + formFields.unshift({ + field: ProcessVariableEnum.START_USER_ID, + title: '发起人', + required: true, + }); + return formFields; +} + +export type UserTaskFormType = { + approveMethod: ApproveMethodType; + approveRatio?: number; + assignEmptyHandlerType?: AssignEmptyHandlerType; + assignEmptyHandlerUserIds?: number[]; + assignStartUserHandlerType?: AssignStartUserHandlerType; + buttonsSetting: any[]; + candidateStrategy: CandidateStrategy; + deptIds?: number[]; // 部门 + deptLevel?: number; // 部门层级 + expression?: string; // 流程表达式 + formDept?: string; // 表单内部门字段 + formUser?: string; // 表单内用户字段 + maxRemindCount?: number; + postIds?: number[]; // 岗位 + reasonRequire: boolean; + rejectHandlerType?: RejectHandlerType; + returnNodeId?: string; + roleIds?: number[]; // 角色 + signEnable: boolean; + skipExpression?: string; // 跳过表达式 + taskAssignListener?: { + body: HttpRequestParam[]; + header: HttpRequestParam[]; + }; + taskAssignListenerEnable?: boolean; + taskAssignListenerPath?: string; + taskCompleteListener?: { + body: HttpRequestParam[]; + header: HttpRequestParam[]; + }; + taskCompleteListenerEnable?: boolean; + taskCompleteListenerPath?: string; + taskCreateListener?: { + body: HttpRequestParam[]; + header: HttpRequestParam[]; + }; + taskCreateListenerEnable?: boolean; + taskCreateListenerPath?: string; + timeDuration?: number; + timeoutHandlerEnable?: boolean; + timeoutHandlerType?: number; + userGroups?: number[]; // 用户组 + userIds?: number[]; // 用户 +}; + +export type CopyTaskFormType = { + candidateStrategy: CandidateStrategy; + deptIds?: number[]; // 部门 + deptLevel?: number; // 部门层级 + expression?: string; // 流程表达式 + formDept?: string; // 表单内部门字段 + formUser?: string; // 表单内用户字段 + postIds?: number[]; // 岗位 + roleIds?: number[]; // 角色 + userGroups?: number[]; // 用户组 + userIds?: number[]; // 用户 +}; + +/** + * @description 节点表单数据。 用于审批节点、抄送节点 + */ +export function useNodeForm(nodeType: BpmNodeTypeEnum) { + const roleOptions = inject>('roleList', ref([])); // 角色列表 + const postOptions = inject>('postList', ref([])); // 岗位列表 + const userOptions = inject>('userList', ref([])); // 用户列表 + const deptOptions = inject>('deptList', ref([])); // 部门列表 + const userGroupOptions = inject>( + 'userGroupList', + ref([]), + ); // 用户组列表 + const deptTreeOptions = inject>( + 'deptTree', + ref([]), + ); // 部门树 + const formFields = inject>('formFields', ref([])); // 流程表单字段 + const configForm = ref(); + + if ( + nodeType === BpmNodeTypeEnum.USER_TASK_NODE || + nodeType === BpmNodeTypeEnum.TRANSACTOR_NODE + ) { + configForm.value = { + candidateStrategy: CandidateStrategy.USER, + approveMethod: ApproveMethodType.SEQUENTIAL_APPROVE, + approveRatio: 100, + rejectHandlerType: RejectHandlerType.FINISH_PROCESS, + assignStartUserHandlerType: AssignStartUserHandlerType.START_USER_AUDIT, + returnNodeId: '', + timeoutHandlerEnable: false, + timeoutHandlerType: 1, + timeDuration: 6, // 默认 6小时 + maxRemindCount: 1, // 默认 提醒 1次 + buttonsSetting: [], + }; + } + configForm.value = { + candidateStrategy: CandidateStrategy.USER, + }; + + function getShowText(): string { + let showText = ''; + // 指定成员 + if ( + configForm.value?.candidateStrategy === CandidateStrategy.USER && + configForm.value?.userIds?.length > 0 + ) { + const candidateNames: string[] = []; + userOptions?.value.forEach((item: any) => { + if (configForm.value?.userIds?.includes(item.id)) { + candidateNames.push(item.nickname); + } + }); + showText = `指定成员:${candidateNames.join(',')}`; + } + // 指定角色 + if ( + configForm.value?.candidateStrategy === CandidateStrategy.ROLE && + configForm.value.roleIds?.length > 0 + ) { + const candidateNames: string[] = []; + roleOptions?.value.forEach((item: any) => { + if (configForm.value?.roleIds?.includes(item.id)) { + candidateNames.push(item.name); + } + }); + showText = `指定角色:${candidateNames.join(',')}`; + } + // 指定部门 + if ( + (configForm.value?.candidateStrategy === CandidateStrategy.DEPT_MEMBER || + configForm.value?.candidateStrategy === CandidateStrategy.DEPT_LEADER || + configForm.value?.candidateStrategy === + CandidateStrategy.MULTI_LEVEL_DEPT_LEADER) && + configForm.value?.deptIds?.length > 0 + ) { + const candidateNames: string[] = []; + deptOptions?.value.forEach((item) => { + if (configForm.value?.deptIds?.includes(item.id)) { + candidateNames.push(item.name); + } + }); + if ( + configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER + ) { + showText = `部门成员:${candidateNames.join(',')}`; + } else if ( + configForm.value.candidateStrategy === CandidateStrategy.DEPT_LEADER + ) { + showText = `部门的负责人:${candidateNames.join(',')}`; + } else { + showText = `多级部门的负责人:${candidateNames.join(',')}`; + } + } + + // 指定岗位 + if ( + configForm.value?.candidateStrategy === CandidateStrategy.POST && + configForm.value.postIds?.length > 0 + ) { + const candidateNames: string[] = []; + postOptions?.value.forEach((item) => { + if (configForm.value?.postIds?.includes(item.id)) { + candidateNames.push(item.name); + } + }); + showText = `指定岗位: ${candidateNames.join(',')}`; + } + // 指定用户组 + if ( + configForm.value?.candidateStrategy === CandidateStrategy.USER_GROUP && + configForm.value?.userGroups?.length > 0 + ) { + const candidateNames: string[] = []; + userGroupOptions?.value.forEach((item) => { + if (configForm.value?.userGroups?.includes(item.id)) { + candidateNames.push(item.name); + } + }); + showText = `指定用户组: ${candidateNames.join(',')}`; + } + + // 表单内用户字段 + if (configForm.value?.candidateStrategy === CandidateStrategy.FORM_USER) { + const formFieldOptions = parseFormCreateFields(unref(formFields)); + const item = formFieldOptions.find( + (item) => item.field === configForm.value?.formUser, + ); + showText = `表单用户:${item?.title}`; + } + + // 表单内部门负责人 + if ( + configForm.value?.candidateStrategy === CandidateStrategy.FORM_DEPT_LEADER + ) { + showText = `表单内部门负责人`; + } + + // 审批人自选 + if ( + configForm.value?.candidateStrategy === + CandidateStrategy.APPROVE_USER_SELECT + ) { + showText = `审批人自选`; + } + + // 发起人自选 + if ( + configForm.value?.candidateStrategy === + CandidateStrategy.START_USER_SELECT + ) { + showText = `发起人自选`; + } + // 发起人自己 + if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER) { + showText = `发起人自己`; + } + // 发起人的部门负责人 + if ( + configForm.value?.candidateStrategy === + CandidateStrategy.START_USER_DEPT_LEADER + ) { + showText = `发起人的部门负责人`; + } + // 发起人的部门负责人 + if ( + configForm.value?.candidateStrategy === + CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER + ) { + showText = `发起人连续部门负责人`; + } + // 流程表达式 + if (configForm.value?.candidateStrategy === CandidateStrategy.EXPRESSION) { + showText = `流程表达式:${configForm.value.expression}`; + } + return showText; + } + + /** + * 处理候选人参数的赋值 + */ + function handleCandidateParam() { + let candidateParam: string | undefined; + if (!configForm.value) { + return candidateParam; + } + switch (configForm.value.candidateStrategy) { + case CandidateStrategy.DEPT_LEADER: + case CandidateStrategy.DEPT_MEMBER: { + candidateParam = configForm.value.deptIds?.join(','); + break; + } + case CandidateStrategy.EXPRESSION: { + candidateParam = configForm.value.expression; + break; + } + // 表单内部门的负责人 + case CandidateStrategy.FORM_DEPT_LEADER: { + // 候选人参数格式: | 分隔 。左边为表单内部门字段。 右边为部门层级 + const deptFieldOnForm = configForm.value.formDept; + candidateParam = deptFieldOnForm?.concat( + `|${configForm.value.deptLevel}`, + ); + break; + } + case CandidateStrategy.FORM_USER: { + candidateParam = configForm.value?.formUser; + break; + } + // 指定连续多级部门的负责人 + case CandidateStrategy.MULTI_LEVEL_DEPT_LEADER: { + // 候选人参数格式: | 分隔 。左边为部门(多个部门用 , 分隔)。 右边为部门层级 + const deptIds = configForm.value.deptIds?.join(','); + candidateParam = deptIds?.concat(`|${configForm.value.deptLevel}`); + break; + } + case CandidateStrategy.POST: { + candidateParam = configForm.value.postIds?.join(','); + break; + } + case CandidateStrategy.ROLE: { + candidateParam = configForm.value.roleIds?.join(','); + break; + } + // 发起人部门负责人 + case CandidateStrategy.START_USER_DEPT_LEADER: + case CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER: { + candidateParam = `${configForm.value.deptLevel}`; + break; + } + case CandidateStrategy.USER: { + candidateParam = configForm.value.userIds?.join(','); + break; + } + case CandidateStrategy.USER_GROUP: { + candidateParam = configForm.value.userGroups?.join(','); + break; + } + default: { + break; + } + } + return candidateParam; + } + /** + * 解析候选人参数 + */ + function parseCandidateParam( + candidateStrategy: CandidateStrategy, + candidateParam: string | undefined, + ) { + if (!configForm.value || !candidateParam) { + return; + } + switch (candidateStrategy) { + case CandidateStrategy.DEPT_LEADER: + case CandidateStrategy.DEPT_MEMBER: { + configForm.value.deptIds = candidateParam + .split(',') + .map((item) => +item); + break; + } + case CandidateStrategy.EXPRESSION: { + configForm.value.expression = candidateParam; + break; + } + // 表单内的部门负责人 + case CandidateStrategy.FORM_DEPT_LEADER: { + // 候选人参数格式: | 分隔 。左边为表单内的部门字段。 右边为部门层级 + const paramArray = candidateParam.split('|'); + if (paramArray.length > 1) { + configForm.value.formDept = paramArray[0]; + if (paramArray[1]) configForm.value.deptLevel = +paramArray[1]; + } + break; + } + case CandidateStrategy.FORM_USER: { + configForm.value.formUser = candidateParam; + break; + } + // 指定连续多级部门的负责人 + case CandidateStrategy.MULTI_LEVEL_DEPT_LEADER: { + // 候选人参数格式: | 分隔 。左边为部门(多个部门用 , 分隔)。 右边为部门层级 + const paramArray = candidateParam.split('|') as string[]; + if (paramArray.length > 1) { + configForm.value.deptIds = paramArray[0] + ?.split(',') + .map((item) => +item); + if (paramArray[1]) configForm.value.deptLevel = +paramArray[1]; + } + break; + } + case CandidateStrategy.POST: { + configForm.value.postIds = candidateParam + .split(',') + .map((item) => +item); + break; + } + case CandidateStrategy.ROLE: { + configForm.value.roleIds = candidateParam + .split(',') + .map((item) => +item); + break; + } + // 发起人部门负责人 + case CandidateStrategy.START_USER_DEPT_LEADER: + case CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER: { + configForm.value.deptLevel = +candidateParam; + break; + } + case CandidateStrategy.USER: { + configForm.value.userIds = candidateParam + .split(',') + .map((item) => +item); + break; + } + case CandidateStrategy.USER_GROUP: { + configForm.value.userGroups = candidateParam + .split(',') + .map((item) => +item); + break; + } + default: { + break; + } + } + } + return { + configForm, + roleOptions, + postOptions, + userOptions, + userGroupOptions, + deptTreeOptions, + handleCandidateParam, + parseCandidateParam, + getShowText, + }; +} + +/** + * @description 抽屉配置 + */ +export function useDrawer() { + // 抽屉配置是否可见 + const settingVisible = ref(false); + // 关闭配置抽屉 + function closeDrawer() { + settingVisible.value = false; + } + // 打开配置抽屉 + function openDrawer() { + settingVisible.value = true; + } + return { + settingVisible, + closeDrawer, + openDrawer, + }; +} + +/** + * @description 节点名称配置 + */ +export function useNodeName(nodeType: BpmNodeTypeEnum) { + // 节点名称 + const nodeName = ref(); + // 节点名称输入框 + const showInput = ref(false); + // 输入框的引用 + const inputRef = ref(null); + // 点击节点名称编辑图标 + function clickIcon() { + showInput.value = true; + } + // 修改节点名称 + function changeNodeName() { + showInput.value = false; + nodeName.value = + nodeName.value || (NODE_DEFAULT_NAME.get(nodeType) as string); + } + // 监听 showInput 的变化,当变为 true 时自动聚焦 + watch(showInput, (value) => { + if (value) { + nextTick(() => { + inputRef.value?.focus(); + }); + } + }); + + return { + nodeName, + showInput, + inputRef, + clickIcon, + changeNodeName, + }; +} + +export function useNodeName2( + node: Ref, + nodeType: BpmNodeTypeEnum, +) { + // 显示节点名称输入框 + const showInput = ref(false); + // 输入框的引用 + const inputRef = ref(null); + + // 监听 showInput 的变化,当变为 true 时自动聚焦 + watch(showInput, (value) => { + if (value) { + nextTick(() => { + inputRef.value?.focus(); + }); + } + }); + + // 修改节点名称 + function changeNodeName() { + showInput.value = false; + node.value.name = + node.value.name || (NODE_DEFAULT_NAME.get(nodeType) as string); + console.warn('node.value.name===>', node.value.name); + } + // 点击节点标题进行输入 + function clickTitle() { + showInput.value = true; + } + return { + showInput, + inputRef, + clickTitle, + changeNodeName, + }; +} + +/** + * @description 根据节点任务状态,获取节点任务状态样式 + */ +export function useTaskStatusClass( + taskStatus: BpmTaskStatusEnum | undefined, +): string { + if (!taskStatus) { + return ''; + } + if (taskStatus === BpmTaskStatusEnum.APPROVE) { + return 'status-pass'; + } + if (taskStatus === BpmTaskStatusEnum.RUNNING) { + return 'status-running'; + } + if (taskStatus === BpmTaskStatusEnum.REJECT) { + return 'status-reject'; + } + if (taskStatus === BpmTaskStatusEnum.CANCEL) { + return 'status-cancel'; + } + return ''; +} + +/** 条件组件文字展示 */ +export function getConditionShowText( + conditionType: ConditionType | undefined, + conditionExpression: string | undefined, + conditionGroups: ConditionGroup | undefined, + fieldOptions: Array>, +) { + let showText: string | undefined; + if (conditionType === ConditionType.EXPRESSION && conditionExpression) { + showText = `表达式:${conditionExpression}`; + } + if (conditionType === ConditionType.RULE) { + // 条件组是否为与关系 + const groupAnd = conditionGroups?.and; + let warningMessage: string | undefined; + const conditionGroup = conditionGroups?.conditions.map((item) => { + return `(${item.rules + .map((rule) => { + if (rule.leftSide && rule.rightSide) { + return `${getFormFieldTitle( + fieldOptions, + rule.leftSide, + )} ${getOpName(rule.opCode)} ${rule.rightSide}`; + } else { + // 有一条规则不完善。提示错误 + warningMessage = '请完善条件规则'; + return ''; + } + }) + .join(item.and ? ' 且 ' : ' 或 ')} ) `; + }); + showText = warningMessage + ? '' + : conditionGroup?.join(groupAnd ? ' 且 ' : ' 或 '); + } + return showText; +} + +/** 获取表单字段名称*/ +function getFormFieldTitle( + fieldOptions: Array>, + field: string, +) { + const item = fieldOptions.find((item) => item.field === field); + return item?.title; +} + +/** 获取操作符名称 */ +function getOpName(opCode: string): string | undefined { + const opName = COMPARISON_OPERATORS.find( + (item: any) => item.value === opCode, + ); + return opName?.label; +} + +/** 获取条件节点默认的名称 */ +export function getDefaultConditionNodeName( + index: number, + defaultFlow: boolean | undefined, +): string { + if (defaultFlow) { + return '其它情况'; + } + return `条件${index + 1}`; +} + +/** 获取包容分支条件节点默认的名称 */ +export function getDefaultInclusiveConditionNodeName( + index: number, + defaultFlow: boolean | undefined, +): string { + if (defaultFlow) { + return '其它情况'; + } + return `包容条件${index + 1}`; +} diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/index.ts b/apps/web-ele/src/views/bpm/components/simple-process-design/index.ts new file mode 100644 index 0000000..91f11f4 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/index.ts @@ -0,0 +1,12 @@ +import './styles/simple-process-designer.scss'; + +export { default as HttpRequestSetting } from './components/nodes-config/modules/http-request-setting.vue'; + +export { default as SimpleProcessDesigner } from './components/simple-process-designer.vue'; + +export { default as SimpleProcessViewer } from './components/simple-process-viewer.vue'; + +export type { SimpleFlowNode } from './consts'; + +// TODO @jaosn:和 antd 对应的文件,不太一样 +export { parseFormFields } from './helpers'; diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/styles/iconfont.ttf b/apps/web-ele/src/views/bpm/components/simple-process-design/styles/iconfont.ttf new file mode 100644 index 0000000..06f4e31 Binary files /dev/null and b/apps/web-ele/src/views/bpm/components/simple-process-design/styles/iconfont.ttf differ diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/styles/iconfont.woff b/apps/web-ele/src/views/bpm/components/simple-process-design/styles/iconfont.woff new file mode 100644 index 0000000..0724e75 Binary files /dev/null and b/apps/web-ele/src/views/bpm/components/simple-process-design/styles/iconfont.woff differ diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/styles/iconfont.woff2 b/apps/web-ele/src/views/bpm/components/simple-process-design/styles/iconfont.woff2 new file mode 100644 index 0000000..c904bb6 Binary files /dev/null and b/apps/web-ele/src/views/bpm/components/simple-process-design/styles/iconfont.woff2 differ diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/styles/simple-process-designer.scss b/apps/web-ele/src/views/bpm/components/simple-process-design/styles/simple-process-designer.scss new file mode 100644 index 0000000..8f6dc85 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/styles/simple-process-designer.scss @@ -0,0 +1,758 @@ +// TODO 整个样式是不是要重新优化一下 +// iconfont 样式 +@font-face { + font-family: iconfont; /* Project id 4495938 */ + src: + url('iconfont.woff2?t=1737639517142') format('woff2'), + url('iconfont.woff?t=1737639517142') format('woff'), + url('iconfont.ttf?t=1737639517142') format('truetype'); +} +// 配置节点头部 +.config-header { + display: flex; + flex-direction: column; + + .node-name { + display: flex; + align-items: center; + height: 24px; + font-size: 16px; + line-height: 24px; + cursor: pointer; + } + + .divide-line { + width: 100%; + height: 1px; + margin-top: 16px; + background: #eee; + } + + .config-editable-input { + max-width: 510px; + height: 24px; + font-size: 16px; + line-height: 24px; + border: 1px solid #d9d9d9; + border-radius: 4px; + transition: all 0.3s; + + &:focus { + outline: 0; + border-color: #40a9ff; + box-shadow: 0 0 0 2px rgb(24 144 255 / 20%); + } + } +} +// 节点连线气泡卡片样式 +.handler-item-wrapper { + display: flex; + flex-wrap: wrap; + width: 320px; + cursor: pointer; + + .handler-item { + display: flex; + flex-direction: column; + align-items: center; + margin-top: 12px; + } + + .handler-item-icon { + width: 50px; + height: 50px; + text-align: center; + user-select: none; + background: #fff; + border: 1px solid #e2e2e2; + border-radius: 50%; + + &:hover { + background: #e2e2e2; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 10%); + } + + .icon-size { + font-size: 25px; + line-height: 50px; + } + } + + .approve { + color: #ff943e; + } + + .copy { + color: #3296fa; + } + + .condition { + color: #67c23a; + } + + .parallel { + color: #626aef; + } + + .inclusive { + color: #345da2; + } + + .delay { + color: #e47470; + } + + .trigger { + color: #3373d2; + } + + .router { + color: #ca3a31; + } + + .transactor { + color: #309; + } + + .child-process { + color: #963; + } + + .async-child-process { + color: #066; + } + + .handler-item-text { + width: 80px; + margin-top: 4px; + font-size: 13px; + text-align: center; + } +} +// Simple 流程模型样式 +.simple-process-model-container { + width: 100%; + height: 100%; + padding-top: 32px; + overflow-x: auto; + background-color: #fafafa; + + .simple-process-model { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-width: fit-content; + background: url('./svg/simple-process-bg.svg') 0 0 repeat; + transform: scale(1); + transform-origin: 50% 0 0; + // 节点容器 定义节点宽度 + .node-container { + width: 200px; + } + // 节点 + .node-box { + position: relative; + display: flex; + flex-direction: column; + min-height: 70px; + padding: 5px 10px 8px; + cursor: pointer; + background-color: #fff; + border: 2px solid transparent; + border-radius: 8px; + box-shadow: 0 1px 4px 0 rgb(10 30 65 / 16%); + transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1); + + &.status-pass { + background-color: #a9da90; + border-color: #67c23a; + } + + &.status-pass:hover { + border-color: #67c23a; + } + + &.status-running { + background-color: #e7f0fe; + border-color: #5a9cf8; + } + + &.status-running:hover { + border-color: #5a9cf8; + } + + &.status-reject { + background-color: #f6e5e5; + border-color: #e47470; + } + + &.status-reject:hover { + border-color: #e47470; + } + + &:hover { + border-color: #0089ff; + + .node-toolbar { + opacity: 1; + } + + .branch-node-move { + display: flex; + } + } + + // 普通节点标题 + .node-title-container { + display: flex; + align-items: center; + padding: 4px; + cursor: pointer; + border-radius: 4px 4px 0 0; + + .node-title-icon { + display: flex; + align-items: center; + + &.user-task { + color: #ff943e; + } + + &.copy-task { + color: #3296fa; + } + + &.start-user { + color: #676565; + } + + &.delay-node { + color: #e47470; + } + + &.trigger-node { + color: #3373d2; + } + + &.router-node { + color: #ca3a31; + } + + &.transactor-task { + color: #309; + } + + &.child-process { + color: #963; + } + + &.async-child-process { + color: #066; + } + } + + .node-title { + margin-left: 4px; + overflow: hidden; + text-overflow: ellipsis; + font-size: 14px; + font-weight: 600; + line-height: 18px; + color: #1f1f1f; + white-space: nowrap; + + &:hover { + border-bottom: 1px dashed #f60; + } + } + } + + // 条件节点标题 + .branch-node-title-container { + display: flex; + align-items: center; + justify-content: space-between; + padding: 4px 0; + cursor: pointer; + border-radius: 4px 4px 0 0; + + .input-max-width { + max-width: 115px !important; + } + + .branch-title { + overflow: hidden; + text-overflow: ellipsis; + font-size: 13px; + font-weight: 600; + color: #f60; + white-space: nowrap; + + &:hover { + border-bottom: 1px dashed #000; + } + } + + .branch-priority { + min-width: 50px; + font-size: 12px; + } + } + + .node-content { + display: flex; + align-items: center; + justify-content: space-between; + min-height: 32px; + padding: 4px 8px; + margin-top: 4px; + line-height: 32px; + color: #111f2c; + background: rgb(0 0 0 / 3%); + border-radius: 4px; + + .node-text { + display: -webkit-box; + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 2; /* 这将限制文本显示为两行 */ + font-size: 14px; + line-height: 24px; + word-break: break-all; + -webkit-box-orient: vertical; + } + } + + //条件节点内容 + .branch-node-content { + display: flex; + align-items: center; + min-height: 32px; + padding: 4px 0; + margin-top: 4px; + line-height: 32px; + color: #111f2c; + background: rgb(0 0 0 / 3%); + border-radius: 4px; + + .branch-node-text { + display: -webkit-box; + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 1; /* 这将限制文本显示为一行 */ + font-size: 12px; + line-height: 24px; + word-break: break-all; + -webkit-box-orient: vertical; + } + } + + // 节点操作 :删除 + .node-toolbar { + position: absolute; + top: -20px; + right: 0; + display: flex; + opacity: 0; + + .toolbar-icon { + vertical-align: middle; + text-align: center; + } + } + + // 条件节点左右移动 + .branch-node-move { + position: absolute; + display: none; + align-items: center; + justify-content: center; + width: 10px; + height: 100%; + cursor: pointer; + } + + .move-node-left { + top: 0; + left: -2px; + background: rgb(126 134 142 / 8%); + border-top-left-radius: 8px; + border-bottom-left-radius: 8px; + } + + .move-node-right { + top: 0; + right: -2px; + background: rgb(126 134 142 / 8%); + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; + } + } + + .node-config-error { + border-color: #ff5219 !important; + } + // 普通节点包装 + .node-wrapper { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + // 节点连线处理 + .node-handler-wrapper { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 70px; + user-select: none; + + &::before { + position: absolute; + top: 0; + z-index: 0; + width: 2px; + height: 100%; + margin: auto; + content: ''; + background-color: #dedede; + } + + .node-handler { + .add-icon { + position: relative; + top: -5px; + display: flex; + align-items: center; + justify-content: center; + width: 25px; + height: 25px; + color: #fff; + cursor: pointer; + background-color: #0089ff; + border-radius: 50%; + + &:hover { + transform: scale(1.1); + } + } + } + + .node-handler-arrow { + position: absolute; + bottom: 0; + left: 50%; + display: flex; + transform: translateX(-50%); + } + } + + // 条件节点包装 + .branch-node-wrapper { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-top: 16px; + + .branch-node-container { + position: relative; + display: flex; + min-width: fit-content; + + &::before { + position: absolute; + left: 50%; + width: 4px; + height: 100%; + content: ''; + background-color: #fafafa; + transform: translate(-50%); + } + + .branch-node-add { + position: absolute; + top: -18px; + left: 50%; + z-index: 1; + display: flex; + align-items: center; + height: 36px; + padding: 0 10px; + font-size: 12px; + line-height: 36px; + border: 2px solid #dedede; + border-radius: 18px; + transform: translateX(-50%); + transform-origin: center center; + } + + .branch-node-readonly { + position: absolute; + top: -18px; + left: 50%; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + background-color: #fff; + border: 2px solid #dedede; + border-radius: 50%; + transform: translateX(-50%); + transform-origin: center center; + + &.status-pass { + background-color: #e9f4e2; + border-color: #6bb63c; + } + + &.status-pass:hover { + border-color: #6bb63c; + } + + .icon-size { + font-size: 22px; + + &.condition { + color: #67c23a; + } + + &.parallel { + color: #626aef; + } + + &.inclusive { + color: #345da2; + } + } + } + + .branch-node-item { + position: relative; + display: flex; + flex-shrink: 0; + flex-direction: column; + align-items: center; + min-width: 280px; + padding: 40px 40px 0; + background: transparent; + border-top: 2px solid #dedede; + border-bottom: 2px solid #dedede; + + &::before { + position: absolute; + inset: 0; + width: 2px; + height: 100%; + margin: auto; + content: ''; + background-color: #dedede; + } + } + // 覆盖条件节点第一个节点左上角的线 + .branch-line-first-top { + position: absolute; + top: -5px; + left: -1px; + width: 50%; + height: 7px; + content: ''; + background-color: #fafafa; + } + // 覆盖条件节点第一个节点左下角的线 + .branch-line-first-bottom { + position: absolute; + bottom: -5px; + left: -1px; + width: 50%; + height: 7px; + content: ''; + background-color: #fafafa; + } + // 覆盖条件节点最后一个节点右上角的线 + .branch-line-last-top { + position: absolute; + top: -5px; + right: -1px; + width: 50%; + height: 7px; + content: ''; + background-color: #fafafa; + } + // 覆盖条件节点最后一个节点右下角的线 + .branch-line-last-bottom { + position: absolute; + right: -1px; + bottom: -5px; + width: 50%; + height: 7px; + content: ''; + background-color: #fafafa; + } + } + } + + .node-fixed-name { + display: inline-block; + width: auto; + padding: 0 4px; + overflow: hidden; + text-overflow: ellipsis; + text-align: center; + white-space: nowrap; + } + // 开始节点包装 + .start-node-wrapper { + position: relative; + margin-top: 16px; + + .start-node-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + .start-node-box { + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + width: 90px; + height: 36px; + padding: 3px 4px; + color: #212121; + cursor: pointer; + background: #fafafa; + border-radius: 30px; + box-shadow: 0 1px 5px 0 rgb(10 30 65 / 8%); + } + } + } + + // 结束节点包装 + .end-node-wrapper { + margin-bottom: 16px; + + .end-node-box { + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + width: 80px; + height: 36px; + color: #212121; + background-color: #fff; + border: 2px solid transparent; + border-radius: 30px; + box-shadow: 0 1px 5px 0 rgb(10 30 65 / 8%); + + &.status-pass { + background-color: #a9da90; + border-color: #6bb63c; + } + + &.status-pass:hover { + border-color: #6bb63c; + } + + &.status-reject { + background-color: #f6e5e5; + border-color: #e47470; + } + + &.status-reject:hover { + border-color: #e47470; + } + + &.status-cancel { + background-color: #eaeaeb; + border-color: #919398; + } + + &.status-cancel:hover { + border-color: #919398; + } + } + } + + // 可编辑的 title 输入框 + .editable-title-input { + max-width: 145px; + height: 20px; + margin-left: 4px; + font-size: 12px; + line-height: 20px; + border: 1px solid #d9d9d9; + border-radius: 4px; + transition: all 0.3s; + + &:focus { + outline: 0; + border-color: #40a9ff; + box-shadow: 0 0 0 2px rgb(24 144 255 / 20%); + } + } + } +} + +.iconfont { + font-family: iconfont !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-trigger::before { + content: '\e6d3'; +} + +.icon-router::before { + content: '\e6b2'; +} + +.icon-delay::before { + content: '\e600'; +} + +.icon-start-user::before { + content: '\e679'; +} + +.icon-inclusive::before { + content: '\e602'; +} + +.icon-copy::before { + content: '\e7eb'; +} + +.icon-transactor::before { + content: '\e61c'; +} + +.icon-exclusive::before { + content: '\e717'; +} + +.icon-approve::before { + content: '\e715'; +} + +.icon-parallel::before { + content: '\e688'; +} + +.icon-async-child-process::before { + content: '\e6f2'; +} + +.icon-child-process::before { + content: '\e6c1'; +} diff --git a/apps/web-ele/src/views/bpm/components/simple-process-design/styles/svg/simple-process-bg.svg b/apps/web-ele/src/views/bpm/components/simple-process-design/styles/svg/simple-process-bg.svg new file mode 100644 index 0000000..eb23ab5 --- /dev/null +++ b/apps/web-ele/src/views/bpm/components/simple-process-design/styles/svg/simple-process-bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/web-ele/src/views/bpm/form/data.ts b/apps/web-ele/src/views/bpm/form/data.ts new file mode 100644 index 0000000..315c41d --- /dev/null +++ b/apps/web-ele/src/views/bpm/form/data.ts @@ -0,0 +1,61 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '表单名称', + component: 'Input', + componentProps: { + placeholder: '请输入表单名称', + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'name', + title: '表单名称', + minWidth: 200, + }, + { + field: 'status', + title: '状态', + minWidth: 200, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 240, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/form/designer/data.ts b/apps/web-ele/src/views/bpm/form/designer/data.ts new file mode 100644 index 0000000..20740cb --- /dev/null +++ b/apps/web-ele/src/views/bpm/form/designer/data.ts @@ -0,0 +1,46 @@ +import type { VbenFormSchema } from '#/adapter/form'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '表单名称', + component: 'Input', + componentProps: { + placeholder: '请输入表单名称', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/form/designer/index.vue b/apps/web-ele/src/views/bpm/form/designer/index.vue new file mode 100644 index 0000000..f3e03e0 --- /dev/null +++ b/apps/web-ele/src/views/bpm/form/designer/index.vue @@ -0,0 +1,154 @@ + + + diff --git a/apps/web-ele/src/views/bpm/form/designer/modules/form.vue b/apps/web-ele/src/views/bpm/form/designer/modules/form.vue new file mode 100644 index 0000000..9b95870 --- /dev/null +++ b/apps/web-ele/src/views/bpm/form/designer/modules/form.vue @@ -0,0 +1,111 @@ + + + diff --git a/apps/web-ele/src/views/bpm/form/index.vue b/apps/web-ele/src/views/bpm/form/index.vue new file mode 100644 index 0000000..c4e6125 --- /dev/null +++ b/apps/web-ele/src/views/bpm/form/index.vue @@ -0,0 +1,185 @@ + + + diff --git a/apps/web-ele/src/views/bpm/form/modules/detail.vue b/apps/web-ele/src/views/bpm/form/modules/detail.vue new file mode 100644 index 0000000..ad23d23 --- /dev/null +++ b/apps/web-ele/src/views/bpm/form/modules/detail.vue @@ -0,0 +1,49 @@ + + + diff --git a/apps/web-ele/src/views/bpm/group/data.ts b/apps/web-ele/src/views/bpm/group/data.ts new file mode 100644 index 0000000..4ecf77c --- /dev/null +++ b/apps/web-ele/src/views/bpm/group/data.ts @@ -0,0 +1,167 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemUserApi } from '#/api/system/user'; + +import { h } from 'vue'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { ElTag } from 'element-plus'; + +import { z } from '#/adapter/form'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 关联数据 */ +let userList: SystemUserApi.User[] = []; +getSimpleUserList().then((data) => (userList = data)); + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '组名', + component: 'Input', + componentProps: { + placeholder: '请输入组名', + }, + rules: 'required', + }, + { + fieldName: 'description', + label: '描述', + component: 'Textarea', + componentProps: { + placeholder: '请输入描述', + }, + }, + { + fieldName: 'userIds', + label: '成员', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择成员', + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + mode: 'tags', + }, + rules: z.array(z.number()).min(1, '请选择成员').default([]), + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '组名', + component: 'Input', + componentProps: { + placeholder: '请输入组名', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + placeholder: '请选择状态', + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'name', + title: '组名', + minWidth: 200, + }, + { + field: 'description', + title: '描述', + minWidth: 200, + }, + { + field: 'userIds', + title: '成员', + minWidth: 200, + slots: { + default: ({ row }) => { + const userIds = row.userIds || []; + return userIds.map((userId: number) => + h( + ElTag, + { + type: 'primary', + class: 'mr-1', + }, + () => userList.find((u) => u.id === userId)?.nickname, + ), + ); + }, + }, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/group/index.vue b/apps/web-ele/src/views/bpm/group/index.vue new file mode 100644 index 0000000..bc65d61 --- /dev/null +++ b/apps/web-ele/src/views/bpm/group/index.vue @@ -0,0 +1,129 @@ + + + diff --git a/apps/web-ele/src/views/bpm/group/modules/form.vue b/apps/web-ele/src/views/bpm/group/modules/form.vue new file mode 100644 index 0000000..c470eed --- /dev/null +++ b/apps/web-ele/src/views/bpm/group/modules/form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/bpm/model/data.ts b/apps/web-ele/src/views/bpm/model/data.ts new file mode 100644 index 0000000..59405e7 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/data.ts @@ -0,0 +1,49 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { BpmModelApi } from '#/api/bpm/model'; + +import { DICT_TYPE } from '@vben/constants'; + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '流程名称', + minWidth: 200, + slots: { default: 'name' }, + }, + { + field: 'startUserIds', + title: '可见范围', + minWidth: 150, + slots: { default: 'startUserIds' }, + }, + { + field: 'type', + title: '流程类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_MODEL_TYPE }, + }, + }, + { + field: 'formType', + title: '表单信息', + minWidth: 150, + slots: { default: 'formInfo' }, + }, + { + field: 'deploymentTime', + title: '最后发布', + minWidth: 280, + slots: { default: 'deploymentTime' }, + }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/model/definition/data.ts b/apps/web-ele/src/views/bpm/model/definition/data.ts new file mode 100644 index 0000000..c5dff80 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/definition/data.ts @@ -0,0 +1,73 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '定义编号', + minWidth: 250, + }, + { + field: 'name', + title: '流程名称', + minWidth: 150, + }, + { + field: 'icon', + title: '流程图标', + minWidth: 100, + cellRender: { + name: 'CellImage', + props: { + width: 32, + height: 32, + class: 'rounded', + }, + }, + }, + { + field: 'startUsers', + title: '可见范围', + minWidth: 100, + slots: { default: 'startUsers' }, + }, + { + field: 'modelType', + title: '流程类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_MODEL_TYPE }, + }, + }, + { + field: 'formType', + title: '表单信息', + minWidth: 150, + slots: { default: 'formInfo' }, + }, + { + field: 'version', + title: '流程版本', + minWidth: 80, + cellRender: { + name: 'CellTag', + }, + }, + { + field: 'deploymentTime', + title: '部署时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/model/definition/index.vue b/apps/web-ele/src/views/bpm/model/definition/index.vue new file mode 100644 index 0000000..7934c76 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/definition/index.vue @@ -0,0 +1,151 @@ + + + diff --git a/apps/web-ele/src/views/bpm/model/form/index.vue b/apps/web-ele/src/views/bpm/model/form/index.vue new file mode 100644 index 0000000..3a73cae --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/form/index.vue @@ -0,0 +1,507 @@ + + + diff --git a/apps/web-ele/src/views/bpm/model/form/modules/basic-info.vue b/apps/web-ele/src/views/bpm/model/form/modules/basic-info.vue new file mode 100644 index 0000000..8d92278 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/form/modules/basic-info.vue @@ -0,0 +1,450 @@ + + + diff --git a/apps/web-ele/src/views/bpm/model/form/modules/bpm-model-editor.vue b/apps/web-ele/src/views/bpm/model/form/modules/bpm-model-editor.vue new file mode 100644 index 0000000..c1a2e67 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/form/modules/bpm-model-editor.vue @@ -0,0 +1,130 @@ + + + + + diff --git a/apps/web-ele/src/views/bpm/model/form/modules/custom-print-template.vue b/apps/web-ele/src/views/bpm/model/form/modules/custom-print-template.vue new file mode 100644 index 0000000..0f58215 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/form/modules/custom-print-template.vue @@ -0,0 +1,117 @@ + + + diff --git a/apps/web-ele/src/views/bpm/model/form/modules/extra-setting.vue b/apps/web-ele/src/views/bpm/model/form/modules/extra-setting.vue new file mode 100644 index 0000000..853ea54 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/form/modules/extra-setting.vue @@ -0,0 +1,619 @@ + + diff --git a/apps/web-ele/src/views/bpm/model/form/modules/form-design.vue b/apps/web-ele/src/views/bpm/model/form/modules/form-design.vue new file mode 100644 index 0000000..b522dc9 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/form/modules/form-design.vue @@ -0,0 +1,184 @@ + + diff --git a/apps/web-ele/src/views/bpm/model/form/modules/process-design.vue b/apps/web-ele/src/views/bpm/model/form/modules/process-design.vue new file mode 100644 index 0000000..8f2495b --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/form/modules/process-design.vue @@ -0,0 +1,81 @@ + + diff --git a/apps/web-ele/src/views/bpm/model/form/modules/simple-model-design.vue b/apps/web-ele/src/views/bpm/model/form/modules/simple-model-design.vue new file mode 100644 index 0000000..ba8ae33 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/form/modules/simple-model-design.vue @@ -0,0 +1,48 @@ + + diff --git a/apps/web-ele/src/views/bpm/model/form/modules/tinymce-plugin.ts b/apps/web-ele/src/views/bpm/model/form/modules/tinymce-plugin.ts new file mode 100644 index 0000000..145dc89 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/form/modules/tinymce-plugin.ts @@ -0,0 +1,78 @@ +/** TinyMCE 自定义功能: + * - processrecord 按钮:插入流程记录占位元素 + * - @ 自动补全:插入 mention 占位元素 + */ + +// @ts-ignore TinyMCE 全局或通过打包器提供 +import type { Editor } from 'tinymce'; + +export interface MentionItem { + id: string; + name: string; +} + +/** 在编辑器 setup 回调中注册流程记录按钮和 @ 自动补全 */ +export function setupTinyPlugins( + editor: Editor, + getMentionList: () => MentionItem[], +) { + // 按钮:流程记录 + editor.ui.registry.addButton('processrecord', { + text: '流程记录', + tooltip: '插入流程记录占位', + onAction: () => { + // 流程记录占位显示, 仅用于显示。process-print.vue 组件中会替换掉 + editor.insertContent( + [ + '
    ', + '', + '', + '', + '', + '', + '', + '
    流程记录
    节点操作
    ', + '
    ', + ].join(''), + ); + }, + }); + + // @ 自动补全 + editor.ui.registry.addAutocompleter('bpmMention', { + trigger: '@', + minChars: 0, + columns: 1, + fetch: ( + pattern: string, + _maxResults: number, + _fetchOptions: Record, + ) => { + const list = getMentionList(); + const keyword = (pattern || '').toLowerCase().trim(); + const data = list + .filter((i) => i.name.toLowerCase().includes(keyword)) + .map((i) => ({ + value: i.id, + text: i.name, + })); + return Promise.resolve(data); + }, + onAction: ( + autocompleteApi: any, + rng: Range, + value: string, + _meta: Record, + ) => { + const list = getMentionList(); + const item = list.find((i) => i.id === value); + const name = item ? item.name : value; + const info = encodeURIComponent(JSON.stringify({ id: value })); + editor.selection.setRng(rng); + editor.insertContent( + `@${name}`, + ); + autocompleteApi.hide(); + }, + }); +} diff --git a/apps/web-ele/src/views/bpm/model/index.vue b/apps/web-ele/src/views/bpm/model/index.vue new file mode 100644 index 0000000..e66062b --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/index.vue @@ -0,0 +1,220 @@ + + + diff --git a/apps/web-ele/src/views/bpm/model/modules/category-draggable-model.vue b/apps/web-ele/src/views/bpm/model/modules/category-draggable-model.vue new file mode 100644 index 0000000..bb6fd00 --- /dev/null +++ b/apps/web-ele/src/views/bpm/model/modules/category-draggable-model.vue @@ -0,0 +1,750 @@ + + + + + diff --git a/apps/web-ele/src/views/bpm/oa/leave/create.vue b/apps/web-ele/src/views/bpm/oa/leave/create.vue new file mode 100644 index 0000000..7f08c69 --- /dev/null +++ b/apps/web-ele/src/views/bpm/oa/leave/create.vue @@ -0,0 +1,282 @@ + + + diff --git a/apps/web-ele/src/views/bpm/oa/leave/data.ts b/apps/web-ele/src/views/bpm/oa/leave/data.ts new file mode 100644 index 0000000..9570f42 --- /dev/null +++ b/apps/web-ele/src/views/bpm/oa/leave/data.ts @@ -0,0 +1,205 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDate } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'type', + label: '请假类型', + component: 'Select', + componentProps: { + placeholder: '请选择请假类型', + options: getDictOptions(DICT_TYPE.BPM_OA_LEAVE_TYPE, 'number'), + allowClear: true, + }, + rules: 'required', + }, + + { + fieldName: 'startTime', + label: '开始时间', + component: 'DatePicker', + componentProps: { + placeholder: '请选择开始时间', + showTime: true, + valueFormat: 'x', + format: 'YYYY-MM-DD HH:mm:ss', + }, + rules: 'required', + }, + { + fieldName: 'endTime', + label: '结束时间', + component: 'DatePicker', + componentProps: { + placeholder: '请选择结束时间', + showTime: true, + valueFormat: 'x', + format: 'YYYY-MM-DD HH:mm:ss', + }, + rules: 'required', + }, + { + fieldName: 'reason', + label: '原因', + component: 'Textarea', + componentProps: { + placeholder: '请输入原因', + }, + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'type', + label: '请假类型', + component: 'Select', + componentProps: { + placeholder: '请选择请假类型', + options: getDictOptions(DICT_TYPE.BPM_OA_LEAVE_TYPE, 'number'), + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '审批结果', + component: 'Select', + componentProps: { + placeholder: '请选择审批结果', + allowClear: true, + options: getDictOptions( + DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, + 'number', + ), + }, + }, + { + fieldName: 'reason', + label: '原因', + component: 'Input', + componentProps: { + placeholder: '请输入原因', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '申请编号', + minWidth: 100, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS }, + }, + }, + { + field: 'startTime', + title: '开始时间', + minWidth: 180, + formatter: 'formatDate', + }, + { + field: 'endTime', + title: '结束时间', + minWidth: 180, + formatter: 'formatDate', + }, + { + field: 'type', + title: '请假类型', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_OA_LEAVE_TYPE }, + }, + }, + { + field: 'reason', + title: '原因', + minWidth: 150, + }, + { + field: 'createTime', + title: '申请时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 240, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情 */ +export function useDetailFormSchema(): DescriptionItemSchema[] { + return [ + { + label: '请假类型', + field: 'type', + render: (val) => + h(DictTag, { + type: DICT_TYPE.BPM_OA_LEAVE_TYPE, + value: val, + }), + }, + { + label: '开始时间', + field: 'startTime', + render: (val) => formatDate(val) as string, + }, + { + label: '结束时间', + field: 'endTime', + render: (val) => formatDate(val) as string, + }, + { + label: '原因', + field: 'reason', + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/oa/leave/detail.vue b/apps/web-ele/src/views/bpm/oa/leave/detail.vue new file mode 100644 index 0000000..cb34024 --- /dev/null +++ b/apps/web-ele/src/views/bpm/oa/leave/detail.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/bpm/oa/leave/index.vue b/apps/web-ele/src/views/bpm/oa/leave/index.vue new file mode 100644 index 0000000..ba3ff5e --- /dev/null +++ b/apps/web-ele/src/views/bpm/oa/leave/index.vue @@ -0,0 +1,196 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processExpression/components/index.ts b/apps/web-ele/src/views/bpm/processExpression/components/index.ts new file mode 100644 index 0000000..4047767 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processExpression/components/index.ts @@ -0,0 +1 @@ +export { default as ProcessExpressionSelectModal } from './select-modal.vue'; diff --git a/apps/web-ele/src/views/bpm/processExpression/components/select-modal.vue b/apps/web-ele/src/views/bpm/processExpression/components/select-modal.vue new file mode 100644 index 0000000..f293b34 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processExpression/components/select-modal.vue @@ -0,0 +1,93 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processExpression/data.ts b/apps/web-ele/src/views/bpm/processExpression/data.ts new file mode 100644 index 0000000..76b16d2 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processExpression/data.ts @@ -0,0 +1,126 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'expression', + label: '表达式', + component: 'Textarea', + componentProps: { + placeholder: '请输入表达式', + }, + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'name', + title: '名字', + minWidth: 200, + }, + + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'expression', + title: '表达式', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/processExpression/index.vue b/apps/web-ele/src/views/bpm/processExpression/index.vue new file mode 100644 index 0000000..658ea45 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processExpression/index.vue @@ -0,0 +1,135 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processExpression/modules/form.vue b/apps/web-ele/src/views/bpm/processExpression/modules/form.vue new file mode 100644 index 0000000..9fb9814 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processExpression/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/create/index.vue b/apps/web-ele/src/views/bpm/processInstance/create/index.vue new file mode 100644 index 0000000..a6579f7 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/create/index.vue @@ -0,0 +1,321 @@ + + + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/create/modules/form.vue b/apps/web-ele/src/views/bpm/processInstance/create/modules/form.vue new file mode 100644 index 0000000..7c5ed29 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/create/modules/form.vue @@ -0,0 +1,372 @@ + + + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/data.ts b/apps/web-ele/src/views/bpm/processInstance/data.ts new file mode 100644 index 0000000..883cc97 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/data.ts @@ -0,0 +1,122 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getCategorySimpleList } from '#/api/bpm/category'; +import { getSimpleProcessDefinitionList } from '#/api/bpm/definition'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '流程名称', + component: 'Input', + componentProps: { + placeholder: '请输入流程名称', + allowClear: true, + }, + }, + { + fieldName: 'processDefinitionId', + label: '所属流程', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择流程定义', + allowClear: true, + api: getSimpleProcessDefinitionList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'category', + label: '流程分类', + component: 'ApiSelect', + componentProps: { + placeholder: '请输入流程分类', + allowClear: true, + api: getCategorySimpleList, + labelField: 'name', + valueField: 'code', + }, + }, + { + fieldName: 'status', + label: '流程状态', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, + 'number', + ), + placeholder: '请选择流程状态', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '发起时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '流程名称', + minWidth: 200, + fixed: 'left', + }, + { + field: 'summary', + title: '摘要', + minWidth: 200, + slots: { + default: 'slot-summary', + }, + }, + { + field: 'categoryName', + title: '流程分类', + minWidth: 120, + fixed: 'left', + }, + { + field: 'status', + title: '流程状态', + minWidth: 250, + slots: { + default: 'slot-status', + }, + }, + { + field: 'startTime', + title: '发起时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'endTime', + title: '结束时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/index.vue b/apps/web-ele/src/views/bpm/processInstance/detail/index.vue new file mode 100644 index 0000000..8e63ada --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/detail/index.vue @@ -0,0 +1,426 @@ + + + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/bpm-viewer.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/bpm-viewer.vue new file mode 100644 index 0000000..0055df1 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/bpm-viewer.vue @@ -0,0 +1,59 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/operation-button.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/operation-button.vue new file mode 100644 index 0000000..28f1fe4 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/operation-button.vue @@ -0,0 +1,1422 @@ + + diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/process-print.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/process-print.vue new file mode 100644 index 0000000..8569373 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/process-print.vue @@ -0,0 +1,299 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/signature.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/signature.vue new file mode 100644 index 0000000..c89cbbc --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/signature.vue @@ -0,0 +1,63 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/simple-bpm-viewer.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/simple-bpm-viewer.vue new file mode 100644 index 0000000..751f390 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/simple-bpm-viewer.vue @@ -0,0 +1,178 @@ + + diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/task-list.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/task-list.vue new file mode 100644 index 0000000..b522d11 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/task-list.vue @@ -0,0 +1,200 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue new file mode 100644 index 0000000..f085a63 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue @@ -0,0 +1,486 @@ + + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/index.vue b/apps/web-ele/src/views/bpm/processInstance/index.vue new file mode 100644 index 0000000..b4d8589 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/index.vue @@ -0,0 +1,220 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/manager/data.ts b/apps/web-ele/src/views/bpm/processInstance/manager/data.ts new file mode 100644 index 0000000..a356cd0 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/manager/data.ts @@ -0,0 +1,156 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getCategorySimpleList } from '#/api/bpm/category'; +import { getSimpleProcessDefinitionList } from '#/api/bpm/definition'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'startUserId', + label: '发起人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择发起人', + allowClear: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'name', + label: '流程名称', + component: 'Input', + componentProps: { + placeholder: '请输入流程名称', + allowClear: true, + }, + }, + { + fieldName: 'processDefinitionId', + label: '所属流程', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择流程定义', + allowClear: true, + api: getSimpleProcessDefinitionList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'category', + label: '流程分类', + component: 'ApiSelect', + componentProps: { + placeholder: '请输入流程分类', + allowClear: true, + api: getCategorySimpleList, + labelField: 'name', + valueField: 'code', + }, + }, + { + fieldName: 'status', + label: '流程状态', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, + 'number', + ), + placeholder: '请选择流程状态', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '发起时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '流程编号', + minWidth: 320, + fixed: 'left', + }, + { + field: 'name', + title: '流程名称', + minWidth: 200, + fixed: 'left', + }, + { + field: 'categoryName', + title: '流程分类', + minWidth: 120, + fixed: 'left', + }, + { + field: 'startUser.nickname', + title: '流程发起人', + minWidth: 120, + }, + { + field: 'startUser.deptName', + title: '发起部门', + minWidth: 120, + }, + { + field: 'status', + title: '流程状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS }, + }, + }, + { + field: 'startTime', + title: '发起时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'endTime', + title: '结束时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'durationInMillis', + title: '流程耗时', + minWidth: 180, + formatter: 'formatPast2', + }, + { + field: 'tasks', + title: '当前审批任务', + minWidth: 320, + slots: { default: 'tasks' }, + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/processInstance/manager/index.vue b/apps/web-ele/src/views/bpm/processInstance/manager/index.vue new file mode 100644 index 0000000..0afcbc4 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/manager/index.vue @@ -0,0 +1,148 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processInstance/report/data.ts b/apps/web-ele/src/views/bpm/processInstance/report/data.ts new file mode 100644 index 0000000..dc099b5 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/report/data.ts @@ -0,0 +1,157 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { + VxeGridPropTypes, + VxeTableGridOptions, +} from '#/adapter/vxe-table'; +import type { BpmProcessInstanceApi } from '#/api/bpm/processInstance'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +interface FormField { + field: string; + title: string; + type: string; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema( + formFields: FormField[] = [], +): VbenFormSchema[] { + // 基础搜索字段配置 + const baseFormSchema: VbenFormSchema[] = [ + { + fieldName: 'startUserId', + label: '发起人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择发起人', + allowClear: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'name', + label: '流程名称', + component: 'Input', + componentProps: { + placeholder: '请输入流程名称', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '流程状态', + component: 'Select', + componentProps: { + placeholder: '请选择流程状态', + allowClear: true, + options: getDictOptions( + DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, + 'number', + ), + }, + }, + { + fieldName: 'createTime', + label: '发起时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'endTime', + label: '结束时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; + + // 动态表单字段配置:目前支持 input 和 textarea 类型 + const dynamicFormSchema: VbenFormSchema[] = formFields + .filter((item) => ['input', 'textarea'].includes(item.type)) + .map((item) => ({ + fieldName: `formFieldsParams.${item.field}`, + label: item.title, + component: 'Input', + componentProps: { + placeholder: `请输入${item.title}`, + allowClear: true, + }, + })); + + return [...baseFormSchema, ...dynamicFormSchema]; +} + +/** 列表的字段 */ +export function useGridColumns( + formFields: FormField[] = [], +): VxeTableGridOptions['columns'] { + // 基础列配置 + const baseColumns: VxeGridPropTypes.Columns = + [ + { + field: 'name', + title: '流程名称', + minWidth: 250, + fixed: 'left', + }, + { + field: 'startUser.nickname', + title: '流程发起人', + minWidth: 200, + }, + { + field: 'status', + title: '流程状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS }, + }, + }, + { + field: 'startTime', + title: '发起时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'endTime', + title: '结束时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + ]; + + // 动态表单字段列配置:根据表单字段生成对应的列,从 formVariables 中获取值 + const formFieldColumns = formFields.map((item) => ({ + field: `formVariables.${item.field}`, + title: item.title, + minWidth: 120, + formatter: ({ row }: any) => { + return row.formVariables?.[item.field] ?? ''; + }, + })); + + return [ + ...baseColumns, + ...formFieldColumns, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/processInstance/report/index.vue b/apps/web-ele/src/views/bpm/processInstance/report/index.vue new file mode 100644 index 0000000..5c8641a --- /dev/null +++ b/apps/web-ele/src/views/bpm/processInstance/report/index.vue @@ -0,0 +1,163 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processListener/components/data.ts b/apps/web-ele/src/views/bpm/processListener/components/data.ts new file mode 100644 index 0000000..48a9b40 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processListener/components/data.ts @@ -0,0 +1,37 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +/** 选择监听器弹窗的列表字段 */ +// TODO @jason:和 antd 对应的,不太一致; +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { field: 'name', title: '名字', minWidth: 120 }, + { + field: 'type', + title: '类型', + minWidth: 200, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_PROCESS_LISTENER_TYPE }, + }, + }, + { field: 'event', title: '事件', minWidth: 200 }, + { + field: 'valueType', + title: '值类型', + minWidth: 200, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_PROCESS_LISTENER_VALUE_TYPE }, + }, + }, + { field: 'value', title: '值', minWidth: 150 }, + { + title: '操作', + width: 100, + slots: { default: 'action' }, + fixed: 'right', + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/processListener/components/index.ts b/apps/web-ele/src/views/bpm/processListener/components/index.ts new file mode 100644 index 0000000..04dbccf --- /dev/null +++ b/apps/web-ele/src/views/bpm/processListener/components/index.ts @@ -0,0 +1 @@ +export { default as ProcessListenerSelectModal } from './select-modal.vue'; diff --git a/apps/web-ele/src/views/bpm/processListener/components/select-modal.vue b/apps/web-ele/src/views/bpm/processListener/components/select-modal.vue new file mode 100644 index 0000000..f18ed0d --- /dev/null +++ b/apps/web-ele/src/views/bpm/processListener/components/select-modal.vue @@ -0,0 +1,97 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processListener/data.ts b/apps/web-ele/src/views/bpm/processListener/data.ts new file mode 100644 index 0000000..ea26dbf --- /dev/null +++ b/apps/web-ele/src/views/bpm/processListener/data.ts @@ -0,0 +1,210 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +export const EVENT_EXECUTION_OPTIONS = [ + { + label: '开始', + value: 'start', + }, + { + label: '结束', + value: 'end', + }, +]; + +export const EVENT_OPTIONS = [ + { label: '创建', value: 'create' }, + { label: '指派', value: 'assignment' }, + { label: '完成', value: 'complete' }, + { label: '删除', value: 'delete' }, + { label: '更新', value: 'update' }, + { label: '超时', value: 'timeout' }, +]; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'type', + label: '类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.BPM_PROCESS_LISTENER_TYPE, 'string'), + placeholder: '请选择类型', + allowClear: true, + }, + rules: 'required', + }, + { + fieldName: 'event', + label: '事件', + component: 'Select', + componentProps: { + options: EVENT_OPTIONS, + placeholder: '请选择事件', + allowClear: true, + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + trigger: (values) => (values.event = undefined), + componentProps: (values) => ({ + options: + values.type === 'execution' + ? EVENT_EXECUTION_OPTIONS + : EVENT_OPTIONS, + }), + }, + }, + { + fieldName: 'valueType', + label: '值类型', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.BPM_PROCESS_LISTENER_VALUE_TYPE, + 'string', + ), + placeholder: '请选择值类型', + allowClear: true, + }, + rules: 'required', + }, + { + fieldName: 'value', + label: '类路径|表达式', + component: 'Input', + rules: 'required', + dependencies: { + triggerFields: ['valueType'], + trigger: (values) => (values.value = undefined), + componentProps: (values) => ({ + placeholder: + values.valueType === 'class' ? '请输入类路径' : '请输入表达式', + }), + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + allowClear: true, + }, + }, + { + fieldName: 'type', + label: '类型', + component: 'Select', + componentProps: { + placeholder: '请选择类型', + options: getDictOptions(DICT_TYPE.BPM_PROCESS_LISTENER_TYPE, 'string'), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'name', + title: '名字', + minWidth: 200, + }, + { + field: 'type', + title: '类型', + minWidth: 200, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_PROCESS_LISTENER_TYPE }, + }, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'event', + title: '事件', + minWidth: 200, + }, + { + field: 'valueType', + title: '值类型', + minWidth: 200, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_PROCESS_LISTENER_VALUE_TYPE }, + }, + }, + { + field: 'value', + title: '值', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/processListener/index.vue b/apps/web-ele/src/views/bpm/processListener/index.vue new file mode 100644 index 0000000..fee6371 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processListener/index.vue @@ -0,0 +1,135 @@ + + + diff --git a/apps/web-ele/src/views/bpm/processListener/modules/form.vue b/apps/web-ele/src/views/bpm/processListener/modules/form.vue new file mode 100644 index 0000000..0e9a926 --- /dev/null +++ b/apps/web-ele/src/views/bpm/processListener/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/bpm/task/copy/data.ts b/apps/web-ele/src/views/bpm/task/copy/data.ts new file mode 100644 index 0000000..202887d --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/copy/data.ts @@ -0,0 +1,92 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '流程名称', + component: 'Input', + componentProps: { + placeholder: '请输入流程名称', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '抄送时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'processInstanceName', + title: '流程名称', + minWidth: 200, + }, + { + field: 'summary', + title: '摘要', + minWidth: 200, + formatter: ({ cellValue }) => { + return cellValue && cellValue.length > 0 + ? cellValue + .map((item: any) => `${item.key} : ${item.value}`) + .join('\n') + : '-'; + }, + }, + { + field: 'startUser.nickname', + title: '流程发起人', + minWidth: 120, + }, + { + field: 'processInstanceStartTime', + title: '流程发起时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'activityName', + title: '抄送节点', + minWidth: 120, + }, + { + field: 'createUser.nickname', + title: '抄送人', + minWidth: 120, + formatter: ({ cellValue }) => { + return cellValue || '-'; + }, + }, + { + field: 'reason', + title: '抄送意见', + minWidth: 180, + }, + { + field: 'createTime', + title: '抄送时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/task/copy/index.vue b/apps/web-ele/src/views/bpm/task/copy/index.vue new file mode 100644 index 0000000..21dcec3 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/copy/index.vue @@ -0,0 +1,85 @@ + + + diff --git a/apps/web-ele/src/views/bpm/task/done/data.ts b/apps/web-ele/src/views/bpm/task/done/data.ts new file mode 100644 index 0000000..3c5e9f6 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/done/data.ts @@ -0,0 +1,154 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getCategorySimpleList } from '#/api/bpm/category'; +import { getSimpleProcessDefinitionList } from '#/api/bpm/definition'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '任务名称', + component: 'Input', + componentProps: { + placeholder: '请输入任务名称', + allowClear: true, + }, + }, + { + fieldName: 'processDefinitionKey', + label: '所属流程', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择流程定义', + allowClear: true, + api: getSimpleProcessDefinitionList, + labelField: 'name', + valueField: 'key', + }, + }, + { + fieldName: 'category', + label: '流程分类', + component: 'ApiSelect', + componentProps: { + placeholder: '请输入流程分类', + allowClear: true, + api: getCategorySimpleList, + labelField: 'name', + valueField: 'code', + }, + }, + { + fieldName: 'status', + label: '审批状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.BPM_TASK_STATUS, 'number'), + placeholder: '请选择审批状态', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '发起时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'processInstance.name', + title: '流程', + minWidth: 200, + }, + { + field: 'processInstance.summary', + title: '摘要', + minWidth: 200, + formatter: ({ cellValue }) => { + return cellValue && cellValue.length > 0 + ? cellValue + .map((item: any) => `${item.key} : ${item.value}`) + .join('\n') + : '-'; + }, + }, + { + field: 'processInstance.startUser.nickname', + title: '发起人', + minWidth: 120, + }, + { + field: 'processInstance.createTime', + title: '发起时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'name', + title: '当前任务', + minWidth: 180, + }, + { + field: 'createTime', + title: '任务开始时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'endTime', + title: '任务结束时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'status', + title: '审批状态', + minWidth: 180, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_TASK_STATUS }, + }, + }, + { + field: 'reason', + title: '审批建议', + minWidth: 180, + }, + { + field: 'durationInMillis', + title: '耗时', + minWidth: 180, + formatter: 'formatPast2', + }, + { + field: 'processInstanceId', + title: '流程编号', + minWidth: 280, + }, + { + field: 'id', + title: '任务编号', + minWidth: 280, + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/task/done/index.vue b/apps/web-ele/src/views/bpm/task/done/index.vue new file mode 100644 index 0000000..15efbd1 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/done/index.vue @@ -0,0 +1,114 @@ + + + diff --git a/apps/web-ele/src/views/bpm/task/manager/data.ts b/apps/web-ele/src/views/bpm/task/manager/data.ts new file mode 100644 index 0000000..947982b --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/manager/data.ts @@ -0,0 +1,104 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '任务名称', + component: 'Input', + componentProps: { + placeholder: '请输入任务名称', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'processInstance.name', + title: '流程', + minWidth: 200, + }, + { + field: 'processInstance.startUser.nickname', + title: '发起人', + minWidth: 120, + }, + { + field: 'name', + title: '当前任务', + minWidth: 180, + }, + { + field: 'createTime', + title: '任务开始时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'endTime', + title: '任务结束时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'assigneeUser.nickname', + title: '审批人', + minWidth: 180, + }, + { + field: 'status', + title: '审批状态', + minWidth: 180, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_TASK_STATUS }, + }, + }, + { + field: 'reason', + title: '审批建议', + minWidth: 180, + }, + { + field: 'durationInMillis', + title: '耗时', + minWidth: 180, + formatter: 'formatPast2', + }, + { + field: 'processInstanceId', + title: '流程编号', + minWidth: 280, + }, + { + field: 'id', + title: '任务编号', + minWidth: 280, + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/task/manager/index.vue b/apps/web-ele/src/views/bpm/task/manager/index.vue new file mode 100644 index 0000000..2c320a0 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/manager/index.vue @@ -0,0 +1,79 @@ + + + diff --git a/apps/web-ele/src/views/bpm/task/todo/data.ts b/apps/web-ele/src/views/bpm/task/todo/data.ts new file mode 100644 index 0000000..0b1efd7 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/todo/data.ts @@ -0,0 +1,131 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getCategorySimpleList } from '#/api/bpm/category'; +import { getSimpleProcessDefinitionList } from '#/api/bpm/definition'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '任务名称', + component: 'Input', + componentProps: { + placeholder: '请输入任务名称', + allowClear: true, + }, + }, + { + fieldName: 'processDefinitionKey', + label: '所属流程', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择流程定义', + allowClear: true, + api: getSimpleProcessDefinitionList, + labelField: 'name', + valueField: 'key', + }, + }, + { + fieldName: 'category', + label: '流程分类', + component: 'ApiSelect', + componentProps: { + placeholder: '请输入流程分类', + allowClear: true, + api: getCategorySimpleList, + labelField: 'name', + valueField: 'code', + }, + }, + { + fieldName: 'status', + label: '流程状态', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, + 'number', + ), + placeholder: '请选择流程状态', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '发起时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'processInstance.name', + title: '流程', + minWidth: 200, + }, + { + field: 'processInstance.summary', + title: '摘要', + minWidth: 200, + formatter: ({ cellValue }) => { + return cellValue && cellValue.length > 0 + ? cellValue + .map((item: any) => `${item.key} : ${item.value}`) + .join('\n') + : '-'; + }, + }, + { + field: 'processInstance.startUser.nickname', + title: '发起人', + minWidth: 120, + }, + { + field: 'processInstance.createTime', + title: '发起时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'name', + title: '当前任务', + minWidth: 180, + }, + { + field: 'createTime', + title: '任务时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'processInstanceId', + title: '流程编号', + minWidth: 280, + }, + { + field: 'id', + title: '任务编号', + minWidth: 280, + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/task/todo/index.vue b/apps/web-ele/src/views/bpm/task/todo/index.vue new file mode 100644 index 0000000..d808307 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/todo/index.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/crm/backlog/data.ts b/apps/web-ele/src/views/crm/backlog/data.ts new file mode 100644 index 0000000..d0b66d1 --- /dev/null +++ b/apps/web-ele/src/views/crm/backlog/data.ts @@ -0,0 +1,102 @@ +import type { Ref } from 'vue'; + +export interface LeftSideItem { + name: string; + menu: string; + count: Ref; +} + +/** 跟进状态 */ +export const FOLLOWUP_STATUS = [ + { label: '待跟进', value: false }, + { label: '已跟进', value: true }, +]; + +/** 归属范围 */ +export const SCENE_TYPES = [ + { label: '我负责的', value: 1 }, + { label: '我参与的', value: 2 }, + { label: '下属负责的', value: 3 }, +]; + +/** 联系状态 */ +export const CONTACT_STATUS = [ + { label: '今日需联系', value: 1 }, + { label: '已逾期', value: 2 }, + { label: '已联系', value: 3 }, +]; + +/** 审批状态 */ +export const AUDIT_STATUS = [ + { label: '待审批', value: 10 }, + { label: '审核通过', value: 20 }, + { label: '审核不通过', value: 30 }, +]; + +/** 回款提醒类型 */ +export const RECEIVABLE_REMIND_TYPE = [ + { label: '待回款', value: 1 }, + { label: '已逾期', value: 2 }, + { label: '已回款', value: 3 }, +]; + +/** 合同过期状态 */ +export const CONTRACT_EXPIRY_TYPE = [ + { label: '即将过期', value: 1 }, + { label: '已过期', value: 2 }, +]; + +/** 左侧菜单 */ +export const useLeftSides = ( + customerTodayContactCount: Ref, + clueFollowCount: Ref, + customerFollowCount: Ref, + customerPutPoolRemindCount: Ref, + contractAuditCount: Ref, + contractRemindCount: Ref, + receivableAuditCount: Ref, + receivablePlanRemindCount: Ref, +): LeftSideItem[] => { + return [ + { + name: '今日需联系客户', + menu: 'customerTodayContact', + count: customerTodayContactCount, + }, + { + name: '分配给我的线索', + menu: 'clueFollow', + count: clueFollowCount, + }, + { + name: '分配给我的客户', + menu: 'customerFollow', + count: customerFollowCount, + }, + { + name: '待进入公海的客户', + menu: 'customerPutPoolRemind', + count: customerPutPoolRemindCount, + }, + { + name: '待审核合同', + menu: 'contractAudit', + count: contractAuditCount, + }, + { + name: '待审核回款', + menu: 'receivableAudit', + count: receivableAuditCount, + }, + { + name: '待回款提醒', + menu: 'receivablePlanRemind', + count: receivablePlanRemindCount, + }, + { + name: '即将到期的合同', + menu: 'contractRemind', + count: contractRemindCount, + }, + ]; +}; diff --git a/apps/web-ele/src/views/crm/backlog/index.vue b/apps/web-ele/src/views/crm/backlog/index.vue new file mode 100644 index 0000000..fed2241 --- /dev/null +++ b/apps/web-ele/src/views/crm/backlog/index.vue @@ -0,0 +1,115 @@ + + diff --git a/apps/web-ele/src/views/crm/backlog/modules/clue-follow-list.vue b/apps/web-ele/src/views/crm/backlog/modules/clue-follow-list.vue new file mode 100644 index 0000000..bd072ba --- /dev/null +++ b/apps/web-ele/src/views/crm/backlog/modules/clue-follow-list.vue @@ -0,0 +1,79 @@ + + + + diff --git a/apps/web-ele/src/views/crm/backlog/modules/contract-audit-list.vue b/apps/web-ele/src/views/crm/backlog/modules/contract-audit-list.vue new file mode 100644 index 0000000..5e4631c --- /dev/null +++ b/apps/web-ele/src/views/crm/backlog/modules/contract-audit-list.vue @@ -0,0 +1,124 @@ + + + + diff --git a/apps/web-ele/src/views/crm/backlog/modules/contract-remind-list.vue b/apps/web-ele/src/views/crm/backlog/modules/contract-remind-list.vue new file mode 100644 index 0000000..e35662c --- /dev/null +++ b/apps/web-ele/src/views/crm/backlog/modules/contract-remind-list.vue @@ -0,0 +1,125 @@ + + + + diff --git a/apps/web-ele/src/views/crm/backlog/modules/customer-follow-list.vue b/apps/web-ele/src/views/crm/backlog/modules/customer-follow-list.vue new file mode 100644 index 0000000..09ac5de --- /dev/null +++ b/apps/web-ele/src/views/crm/backlog/modules/customer-follow-list.vue @@ -0,0 +1,79 @@ + + + + diff --git a/apps/web-ele/src/views/crm/backlog/modules/customer-put-pool-remind-list.vue b/apps/web-ele/src/views/crm/backlog/modules/customer-put-pool-remind-list.vue new file mode 100644 index 0000000..15ac870 --- /dev/null +++ b/apps/web-ele/src/views/crm/backlog/modules/customer-put-pool-remind-list.vue @@ -0,0 +1,79 @@ + + + + diff --git a/apps/web-ele/src/views/crm/backlog/modules/customer-today-contact-list.vue b/apps/web-ele/src/views/crm/backlog/modules/customer-today-contact-list.vue new file mode 100644 index 0000000..f1770d3 --- /dev/null +++ b/apps/web-ele/src/views/crm/backlog/modules/customer-today-contact-list.vue @@ -0,0 +1,89 @@ + + + + diff --git a/apps/web-ele/src/views/crm/backlog/modules/receivable-audit-list.vue b/apps/web-ele/src/views/crm/backlog/modules/receivable-audit-list.vue new file mode 100644 index 0000000..d8f8d16 --- /dev/null +++ b/apps/web-ele/src/views/crm/backlog/modules/receivable-audit-list.vue @@ -0,0 +1,106 @@ + + + + diff --git a/apps/web-ele/src/views/crm/backlog/modules/receivable-plan-remind-list.vue b/apps/web-ele/src/views/crm/backlog/modules/receivable-plan-remind-list.vue new file mode 100644 index 0000000..7561331 --- /dev/null +++ b/apps/web-ele/src/views/crm/backlog/modules/receivable-plan-remind-list.vue @@ -0,0 +1,104 @@ + + + + diff --git a/apps/web-ele/src/views/crm/business/components/data.ts b/apps/web-ele/src/views/crm/business/components/data.ts new file mode 100644 index 0000000..10ecb5a --- /dev/null +++ b/apps/web-ele/src/views/crm/business/components/data.ts @@ -0,0 +1,52 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +/** 商机关联列表列定义 */ +export function useBusinessDetailListColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'name', + title: '商机名称', + fixed: 'left', + slots: { default: 'name' }, + }, + { + field: 'customerName', + title: '客户名称', + fixed: 'left', + slots: { default: 'customerName' }, + }, + { + field: 'totalPrice', + title: '商机金额(元)', + formatter: 'formatAmount2', + }, + { + field: 'dealTime', + title: '预计成交日期', + formatter: 'formatDate', + }, + { + field: 'ownerUserName', + title: '负责人', + }, + { + field: 'ownerUserDeptName', + title: '所属部门', + }, + { + field: 'statusTypeName', + title: '商机状态组', + fixed: 'right', + }, + { + field: 'statusName', + title: '商机阶段', + fixed: 'right', + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/business/components/detail-list-modal.vue b/apps/web-ele/src/views/crm/business/components/detail-list-modal.vue new file mode 100644 index 0000000..9b3bfee --- /dev/null +++ b/apps/web-ele/src/views/crm/business/components/detail-list-modal.vue @@ -0,0 +1,149 @@ + + + + diff --git a/apps/web-ele/src/views/crm/business/components/detail-list.vue b/apps/web-ele/src/views/crm/business/components/detail-list.vue new file mode 100644 index 0000000..e57ac8f --- /dev/null +++ b/apps/web-ele/src/views/crm/business/components/detail-list.vue @@ -0,0 +1,215 @@ + + + + diff --git a/apps/web-ele/src/views/crm/business/components/index.ts b/apps/web-ele/src/views/crm/business/components/index.ts new file mode 100644 index 0000000..a63de47 --- /dev/null +++ b/apps/web-ele/src/views/crm/business/components/index.ts @@ -0,0 +1 @@ +export { default as BusinessDetailsList } from './detail-list.vue'; diff --git a/apps/web-ele/src/views/crm/business/data.ts b/apps/web-ele/src/views/crm/business/data.ts new file mode 100644 index 0000000..93bcf41 --- /dev/null +++ b/apps/web-ele/src/views/crm/business/data.ts @@ -0,0 +1,281 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { useUserStore } from '@vben/stores'; +import { erpPriceMultiply } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getBusinessStatusTypeSimpleList } from '#/api/crm/business/status'; +import { getCustomerSimpleList } from '#/api/crm/customer'; +import { getSimpleUserList } from '#/api/system/user'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '商机名称', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入商机名称', + allowClear: true, + }, + }, + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择负责人', + allowClear: true, + }, + defaultValue: userStore.userInfo?.id, + rules: 'required', + }, + { + fieldName: 'customerId', + label: '客户名称', + component: 'ApiSelect', + componentProps: { + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择客户', + allowClear: true, + }, + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.customerDefault, + }, + rules: 'required', + }, + { + fieldName: 'contactId', + label: '合同名称', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'statusTypeId', + label: '商机状态组', + component: 'ApiSelect', + componentProps: { + api: getBusinessStatusTypeSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择商机状态组', + allowClear: true, + }, + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + rules: 'required', + }, + { + fieldName: 'dealTime', + label: '预计成交日期', + component: 'DatePicker', + componentProps: { + showTime: false, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + placeholder: '请选择预计成交日期', + class: '!w-full', + }, + }, + { + fieldName: 'product', + label: '产品清单', + component: 'Input', + formItemClass: 'col-span-3', + componentProps: { + placeholder: '请输入产品清单', + allowClear: true, + }, + }, + { + fieldName: 'totalProductPrice', + label: '产品总金额', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + disabled: true, + placeholder: '请输入产品总金额', + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional().default(0), + }, + { + fieldName: 'discountPercent', + label: '整单折扣(%)', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + placeholder: '请输入整单折扣', + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).max(100).optional().default(0), + }, + { + fieldName: 'totalPrice', + label: '折扣后金额', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + disabled: true, + placeholder: '请输入折扣后金额', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['totalProductPrice', 'discountPercent'], + trigger(values, form) { + const discountPrice = + erpPriceMultiply( + values.totalProductPrice, + values.discountPercent / 100, + ) ?? 0; + form.setFieldValue( + 'totalPrice', + values.totalProductPrice - discountPrice, + ); + }, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '商机名称', + component: 'Input', + componentProps: { + placeholder: '请输入商机名称', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '商机名称', + fixed: 'left', + width: 160, + slots: { default: 'name' }, + }, + { + field: 'customerName', + title: '客户名称', + fixed: 'left', + width: 120, + slots: { default: 'customerName' }, + }, + { + field: 'totalPrice', + title: '商机金额(元)', + width: 140, + formatter: 'formatAmount2', + }, + { + field: 'dealTime', + title: '预计成交日期', + formatter: 'formatDate', + width: 180, + }, + { + field: 'remark', + title: '备注', + width: 200, + }, + { + field: 'contactNextTime', + title: '下次联系时间', + formatter: 'formatDateTime', + width: 180, + }, + { + field: 'ownerUserName', + title: '负责人', + width: 100, + }, + { + field: 'ownerUserDeptName', + title: '所属部门', + width: 100, + }, + { + field: 'contactLastTime', + title: '最后跟进时间', + formatter: 'formatDateTime', + width: 180, + }, + { + field: 'updateTime', + title: '更新时间', + formatter: 'formatDateTime', + width: 180, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + width: 180, + }, + { + field: 'creatorName', + title: '创建人', + width: 100, + }, + { + field: 'statusTypeName', + title: '商机状态组', + fixed: 'right', + width: 140, + }, + { + field: 'statusName', + title: '商机阶段', + fixed: 'right', + width: 120, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/business/detail/data.ts b/apps/web-ele/src/views/crm/business/detail/data.ts new file mode 100644 index 0000000..1cb1c49 --- /dev/null +++ b/apps/web-ele/src/views/crm/business/detail/data.ts @@ -0,0 +1,141 @@ +import type { Ref } from 'vue'; + +import type { VbenFormSchema } from '#/adapter/form'; +import type { CrmBusinessApi } from '#/api/crm/business'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { erpPriceInputFormatter, formatDateTime } from '@vben/utils'; + +import { + DEFAULT_STATUSES, + getBusinessStatusSimpleList, +} from '#/api/crm/business/status'; + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'customerName', + label: '客户名称', + }, + { + field: 'totalPrice', + label: '商机金额(元)', + render: (val) => erpPriceInputFormatter(val), + }, + { + field: 'statusTypeName', + label: '商机组', + }, + { + field: 'ownerUserName', + label: '负责人', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} + +/** 详情页的基础字段 */ +export function useDetailBaseSchema(): DescriptionItemSchema[] { + return [ + { + field: 'name', + label: '商机名称', + }, + { + field: 'customerName', + label: '客户名称', + }, + { + field: 'totalPrice', + label: '商机金额(元)', + render: (val) => erpPriceInputFormatter(val), + }, + { + field: 'dealTime', + label: '预计成交日期', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'contactNextTime', + label: '下次联系时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'statusTypeName', + label: '商机状态组', + }, + { + field: 'statusName', + label: '商机阶段', + }, + { + field: 'remark', + label: '备注', + }, + ]; +} + +/** 商机状态更新表单 */ +export function useStatusFormSchema( + formData: Ref, +): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'statusId', + label: '商机状态', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'endStatus', + label: '商机状态', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'status', + label: '商机阶段', + component: 'Select', + dependencies: { + triggerFields: [''], + async componentProps() { + const statusList = await getBusinessStatusSimpleList( + formData.value?.statusTypeId ?? 0, + ); + const statusOptions = statusList.map((item) => ({ + label: `${item.name}(赢单率:${item.percent}%)`, + value: item.id, + })); + const options = DEFAULT_STATUSES.map((item) => ({ + label: `${item.name}(赢单率:${item.percent}%)`, + value: item.endStatus, + })); + statusOptions.push(...options); + return { + options: statusOptions, + }; + }, + }, + rules: 'required', + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/business/detail/index.vue b/apps/web-ele/src/views/crm/business/detail/index.vue new file mode 100644 index 0000000..1a3fbb8 --- /dev/null +++ b/apps/web-ele/src/views/crm/business/detail/index.vue @@ -0,0 +1,191 @@ + + + diff --git a/apps/web-ele/src/views/crm/business/detail/modules/info.vue b/apps/web-ele/src/views/crm/business/detail/modules/info.vue new file mode 100644 index 0000000..7e8753b --- /dev/null +++ b/apps/web-ele/src/views/crm/business/detail/modules/info.vue @@ -0,0 +1,36 @@ + + + diff --git a/apps/web-ele/src/views/crm/business/detail/modules/status-form.vue b/apps/web-ele/src/views/crm/business/detail/modules/status-form.vue new file mode 100644 index 0000000..53df20a --- /dev/null +++ b/apps/web-ele/src/views/crm/business/detail/modules/status-form.vue @@ -0,0 +1,85 @@ + + + diff --git a/apps/web-ele/src/views/crm/business/index.vue b/apps/web-ele/src/views/crm/business/index.vue new file mode 100644 index 0000000..f5eae10 --- /dev/null +++ b/apps/web-ele/src/views/crm/business/index.vue @@ -0,0 +1,208 @@ + + + diff --git a/apps/web-ele/src/views/crm/business/modules/form.vue b/apps/web-ele/src/views/crm/business/modules/form.vue new file mode 100644 index 0000000..051cfe7 --- /dev/null +++ b/apps/web-ele/src/views/crm/business/modules/form.vue @@ -0,0 +1,121 @@ + + + diff --git a/apps/web-ele/src/views/crm/business/status/data.ts b/apps/web-ele/src/views/crm/business/status/data.ts new file mode 100644 index 0000000..d5e5608 --- /dev/null +++ b/apps/web-ele/src/views/crm/business/status/data.ts @@ -0,0 +1,112 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { handleTree } from '@vben/utils'; + +import { getDeptList } from '#/api/system/dept'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '状态组名', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入状态组名', + }, + }, + { + fieldName: 'deptIds', + label: '应用部门', + component: 'ApiTreeSelect', + componentProps: { + api: async () => { + const data = await getDeptList(); + return handleTree(data); + }, + multiple: true, + fieldNames: { label: 'name', value: 'id', children: 'children' }, + placeholder: '请选择应用部门', + defaultExpandAll: true, + }, + help: '不选择部门时,默认全公司生效', + }, + { + fieldName: 'statuses', + label: '阶段设置', + component: 'Input', + rules: 'required', + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '状态组名', + }, + { + field: 'deptNames', + title: '应用部门', + formatter: ({ cellValue }) => + cellValue?.length > 0 ? cellValue.join(' ') : '全公司', + }, + { + field: 'creator', + title: '创建人', + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 160, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 商机状态阶段列表列配置 */ +export function useFormColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'defaultStatus', + title: '阶段', + minWidth: 100, + slots: { default: 'defaultStatus' }, + }, + { + field: 'name', + title: '阶段名称', + minWidth: 100, + slots: { default: 'name' }, + }, + { + field: 'percent', + title: '赢单率(%)', + minWidth: 100, + slots: { default: 'percent' }, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/business/status/index.vue b/apps/web-ele/src/views/crm/business/status/index.vue new file mode 100644 index 0000000..f04101c --- /dev/null +++ b/apps/web-ele/src/views/crm/business/status/index.vue @@ -0,0 +1,136 @@ + + + diff --git a/apps/web-ele/src/views/crm/business/status/modules/form.vue b/apps/web-ele/src/views/crm/business/status/modules/form.vue new file mode 100644 index 0000000..3be655c --- /dev/null +++ b/apps/web-ele/src/views/crm/business/status/modules/form.vue @@ -0,0 +1,208 @@ + + + diff --git a/apps/web-ele/src/views/crm/clue/data.ts b/apps/web-ele/src/views/crm/clue/data.ts new file mode 100644 index 0000000..fccd2bf --- /dev/null +++ b/apps/web-ele/src/views/crm/clue/data.ts @@ -0,0 +1,327 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { useUserStore } from '@vben/stores'; + +import { getAreaTree } from '#/api/system/area'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '线索名称', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入线索名称', + }, + }, + { + fieldName: 'source', + label: '客户来源', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_SOURCE, 'number'), + placeholder: '请选择客户来源', + }, + rules: 'required', + }, + { + fieldName: 'mobile', + label: '手机', + component: 'Input', + componentProps: { + placeholder: '请输入手机号', + }, + }, + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + clearable: true, + placeholder: '请选择负责人', + }, + defaultValue: userStore.userInfo?.id, + rules: 'required', + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + }, + { + fieldName: 'telephone', + label: '电话', + component: 'Input', + componentProps: { + placeholder: '请输入电话', + }, + }, + { + fieldName: 'email', + label: '邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入邮箱', + }, + }, + { + fieldName: 'wechat', + label: '微信', + component: 'Input', + componentProps: { + placeholder: '请输入微信', + }, + }, + { + fieldName: 'qq', + label: 'QQ', + component: 'Input', + componentProps: { + placeholder: '请输入 QQ', + }, + }, + { + fieldName: 'industryId', + label: '客户行业', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_INDUSTRY, 'number'), + placeholder: '请选择客户行业', + }, + }, + { + fieldName: 'level', + label: '客户级别', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_LEVEL, 'number'), + placeholder: '请选择客户级别', + }, + }, + { + fieldName: 'areaId', + label: '地址', + component: 'ApiTreeSelect', + componentProps: { + api: getAreaTree, + fieldNames: { label: 'name', value: 'id', children: 'children' }, + placeholder: '请选择地址', + }, + }, + { + fieldName: 'detailAddress', + label: '详细地址', + component: 'Input', + componentProps: { + placeholder: '请输入详细地址', + }, + }, + { + fieldName: 'contactNextTime', + label: '下次联系时间', + component: 'DatePicker', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + placeholder: '请选择下次联系时间', + class: '!w-full', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '线索名称', + component: 'Input', + componentProps: { + placeholder: '请输入线索名称', + clearable: true, + }, + }, + { + fieldName: 'transformStatus', + label: '转化状态', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '未转化', value: false }, + { label: '已转化', value: true }, + ], + placeholder: '请选择转化状态', + clearable: true, + }, + defaultValue: false, + }, + { + fieldName: 'mobile', + label: '手机号', + component: 'Input', + componentProps: { + placeholder: '请输入手机号', + clearable: true, + }, + }, + { + fieldName: 'telephone', + label: '电话', + component: 'Input', + componentProps: { + placeholder: '请输入电话', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + placeholder: ['开始日期', '结束日期'], + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '线索名称', + fixed: 'left', + minWidth: 160, + slots: { + default: 'name', + }, + }, + { + field: 'source', + title: '线索来源', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_SOURCE }, + }, + }, + { + field: 'mobile', + title: '手机', + minWidth: 120, + }, + { + field: 'telephone', + title: '电话', + minWidth: 130, + }, + { + field: 'email', + title: '邮箱', + minWidth: 180, + }, + { + field: 'detailAddress', + title: '地址', + minWidth: 180, + }, + { + field: 'industryId', + title: '客户行业', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY }, + }, + }, + { + field: 'level', + title: '客户级别', + minWidth: 135, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_LEVEL }, + }, + }, + { + field: 'contactNextTime', + title: '下次联系时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + }, + { + field: 'contactLastTime', + title: '最后跟进时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'contactLastContent', + title: '最后跟进记录', + minWidth: 200, + }, + { + field: 'ownerUserName', + title: '负责人', + minWidth: 100, + }, + { + field: 'ownerUserDeptName', + title: '所属部门', + minWidth: 100, + }, + { + field: 'updateTime', + title: '更新时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + title: '操作', + width: 140, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/clue/detail/data.ts b/apps/web-ele/src/views/crm/clue/detail/data.ts new file mode 100644 index 0000000..9536eb7 --- /dev/null +++ b/apps/web-ele/src/views/crm/clue/detail/data.ts @@ -0,0 +1,111 @@ +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; + +/** 详情头部的配置 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'source', + label: '线索来源', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_CUSTOMER_SOURCE, + value: val, + }), + }, + { + field: 'mobile', + label: '手机', + }, + { + field: 'ownerUserName', + label: '负责人', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} + +/** 详情基本信息的配置 */ +export function useDetailBaseSchema(): DescriptionItemSchema[] { + return [ + { + field: 'name', + label: '线索名称', + }, + { + field: 'source', + label: '客户来源', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_CUSTOMER_SOURCE, + value: val, + }), + }, + { + field: 'mobile', + label: '手机', + }, + { + field: 'telephone', + label: '电话', + }, + { + field: 'email', + label: '邮箱', + }, + { + field: 'areaName', + label: '地址', + render: (val, data) => { + const areaName = val ?? ''; + const detailAddress = data?.detailAddress ?? ''; + return [areaName, detailAddress].filter((item) => !!item).join(' '); + }, + }, + { + field: 'qq', + label: 'QQ', + }, + { + field: 'wechat', + label: '微信', + }, + { + field: 'industryId', + label: '客户行业', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY, + value: val, + }), + }, + { + field: 'level', + label: '客户级别', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_CUSTOMER_LEVEL, + value: val, + }), + }, + { + field: 'contactNextTime', + label: '下次联系时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'remark', + label: '备注', + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/clue/detail/index.vue b/apps/web-ele/src/views/crm/clue/detail/index.vue new file mode 100644 index 0000000..e7e6f8d --- /dev/null +++ b/apps/web-ele/src/views/crm/clue/detail/index.vue @@ -0,0 +1,174 @@ + + + diff --git a/apps/web-ele/src/views/crm/clue/detail/modules/info.vue b/apps/web-ele/src/views/crm/clue/detail/modules/info.vue new file mode 100644 index 0000000..676b005 --- /dev/null +++ b/apps/web-ele/src/views/crm/clue/detail/modules/info.vue @@ -0,0 +1,36 @@ + + + diff --git a/apps/web-ele/src/views/crm/clue/index.vue b/apps/web-ele/src/views/crm/clue/index.vue new file mode 100644 index 0000000..db011a9 --- /dev/null +++ b/apps/web-ele/src/views/crm/clue/index.vue @@ -0,0 +1,193 @@ + + + diff --git a/apps/web-ele/src/views/crm/clue/modules/form.vue b/apps/web-ele/src/views/crm/clue/modules/form.vue new file mode 100644 index 0000000..db3f753 --- /dev/null +++ b/apps/web-ele/src/views/crm/clue/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/crm/contact/components/data.ts b/apps/web-ele/src/views/crm/contact/components/data.ts new file mode 100644 index 0000000..b2e63f7 --- /dev/null +++ b/apps/web-ele/src/views/crm/contact/components/data.ts @@ -0,0 +1,62 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +/** 联系人明细列表列配置 */ +export function useDetailListColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'name', + title: '姓名', + fixed: 'left', + slots: { default: 'name' }, + }, + { + field: 'customerName', + title: '客户名称', + fixed: 'left', + slots: { default: 'customerName' }, + }, + { + field: 'sex', + title: '性别', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, + }, + }, + { + field: 'mobile', + title: '手机', + }, + { + field: 'telephone', + title: '电话', + }, + { + field: 'email', + title: '邮箱', + }, + { + field: 'post', + title: '职位', + }, + { + field: 'detailAddress', + title: '地址', + }, + { + field: 'master', + title: '关键决策人', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/contact/components/detail-list-modal.vue b/apps/web-ele/src/views/crm/contact/components/detail-list-modal.vue new file mode 100644 index 0000000..9d665ce --- /dev/null +++ b/apps/web-ele/src/views/crm/contact/components/detail-list-modal.vue @@ -0,0 +1,148 @@ + + + + diff --git a/apps/web-ele/src/views/crm/contact/components/detail-list.vue b/apps/web-ele/src/views/crm/contact/components/detail-list.vue new file mode 100644 index 0000000..b49e768 --- /dev/null +++ b/apps/web-ele/src/views/crm/contact/components/detail-list.vue @@ -0,0 +1,210 @@ + + + + diff --git a/apps/web-ele/src/views/crm/contact/components/index.ts b/apps/web-ele/src/views/crm/contact/components/index.ts new file mode 100644 index 0000000..d16cd53 --- /dev/null +++ b/apps/web-ele/src/views/crm/contact/components/index.ts @@ -0,0 +1 @@ +export { default as ContactDetailsList } from './detail-list.vue'; diff --git a/apps/web-ele/src/views/crm/contact/data.ts b/apps/web-ele/src/views/crm/contact/data.ts new file mode 100644 index 0000000..c0d13b2 --- /dev/null +++ b/apps/web-ele/src/views/crm/contact/data.ts @@ -0,0 +1,366 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { useUserStore } from '@vben/stores'; + +import { getSimpleContactList } from '#/api/crm/contact'; +import { getCustomerSimpleList } from '#/api/crm/customer'; +import { getAreaTree } from '#/api/system/area'; +import { getSimpleUserList } from '#/api/system/user'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '联系人姓名', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入联系人姓名', + }, + }, + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + rules: 'required', + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择负责人', + }, + defaultValue: userStore.userInfo?.id, + }, + { + fieldName: 'customerId', + label: '客户名称', + component: 'ApiSelect', + rules: 'required', + componentProps: { + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择客户', + }, + }, + { + fieldName: 'mobile', + label: '手机', + component: 'Input', + componentProps: { + placeholder: '请输入手机号', + }, + }, + { + fieldName: 'telephone', + label: '电话', + component: 'Input', + componentProps: { + placeholder: '请输入电话', + }, + }, + { + fieldName: 'email', + label: '邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入邮箱', + }, + }, + { + fieldName: 'wechat', + label: '微信', + component: 'Input', + componentProps: { + placeholder: '请输入微信', + }, + }, + { + fieldName: 'qq', + label: 'QQ', + component: 'Input', + componentProps: { + placeholder: '请输入QQ', + }, + }, + { + fieldName: 'post', + label: '职位', + component: 'Input', + componentProps: { + placeholder: '请输入职位', + }, + }, + { + fieldName: 'master', + label: '关键决策人', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + placeholder: '请选择是否关键决策人', + }, + defaultValue: false, + }, + { + fieldName: 'sex', + label: '性别', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + placeholder: '请选择性别', + }, + }, + { + fieldName: 'parentId', + label: '直属上级', + component: 'ApiSelect', + componentProps: { + api: getSimpleContactList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择直属上级', + }, + }, + { + fieldName: 'areaId', + label: '地址', + component: 'ApiTreeSelect', + componentProps: { + api: getAreaTree, + fieldNames: { label: 'name', value: 'id', children: 'children' }, + placeholder: '请选择地址', + }, + }, + { + fieldName: 'detailAddress', + label: '详细地址', + component: 'Input', + componentProps: { + placeholder: '请输入详细地址', + }, + }, + { + fieldName: 'contactNextTime', + label: '下次联系时间', + component: 'DatePicker', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + placeholder: '请选择下次联系时间', + class: '!w-full', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择客户', + }, + }, + { + fieldName: 'name', + label: '姓名', + component: 'Input', + componentProps: { + placeholder: '请输入联系人姓名', + allowClear: true, + }, + }, + { + fieldName: 'mobile', + label: '手机号', + component: 'Input', + componentProps: { + placeholder: '请输入手机号', + allowClear: true, + }, + }, + { + fieldName: 'telephone', + label: '电话', + component: 'Input', + componentProps: { + placeholder: '请输入电话', + allowClear: true, + }, + }, + { + fieldName: 'wechat', + label: '微信', + component: 'Input', + componentProps: { + placeholder: '请输入微信', + allowClear: true, + }, + }, + { + fieldName: 'email', + label: '电子邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入电子邮箱', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '联系人姓名', + fixed: 'left', + minWidth: 240, + slots: { default: 'name' }, + }, + { + field: 'customerName', + title: '客户名称', + fixed: 'left', + minWidth: 240, + slots: { default: 'customerName' }, + }, + { + field: 'mobile', + title: '手机', + minWidth: 120, + }, + { + field: 'telephone', + title: '电话', + minWidth: 130, + }, + { + field: 'email', + title: '邮箱', + minWidth: 180, + }, + { + field: 'post', + title: '职位', + minWidth: 120, + }, + { + field: 'areaName', + title: '地址', + minWidth: 120, + }, + { + field: 'detailAddress', + title: '详细地址', + minWidth: 180, + }, + { + field: 'master', + title: '关键决策人', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'parentId', + title: '直属上级', + minWidth: 120, + slots: { default: 'parentId' }, + }, + { + field: 'contactNextTime', + title: '下次联系时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'sex', + title: '性别', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, + }, + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + }, + { + field: 'contactLastTime', + title: '最后跟进时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'ownerUserName', + title: '负责人', + minWidth: 120, + }, + { + field: 'ownerUserDeptName', + title: '所属部门', + minWidth: 120, + }, + { + field: 'updateTime', + title: '更新时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/contact/detail/data.ts b/apps/web-ele/src/views/crm/contact/detail/data.ts new file mode 100644 index 0000000..3f10193 --- /dev/null +++ b/apps/web-ele/src/views/crm/contact/detail/data.ts @@ -0,0 +1,106 @@ +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; + +/** 详情页的基础字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'customerName', + label: '客户名称', + }, + { + field: 'post', + label: '职务', + }, + { + field: 'mobile', + label: '手机', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} + +/** 详情页的基础字段 */ +export function useDetailBaseSchema(): DescriptionItemSchema[] { + return [ + { + field: 'name', + label: '姓名', + }, + { + field: 'customerName', + label: '客户名称', + }, + { + field: 'mobile', + label: '手机', + }, + { + field: 'telephone', + label: '电话', + }, + { + field: 'email', + label: '邮箱', + }, + { + field: 'qq', + label: 'QQ', + }, + { + field: 'wechat', + label: '微信', + }, + { + field: 'areaName', + label: '地址', + render: (val, data) => { + const areaName = val ?? ''; + const detailAddress = data?.detailAddress ?? ''; + return [areaName, detailAddress].filter((item) => !!item).join(' '); + }, + }, + { + field: 'post', + label: '职务', + }, + { + field: 'parentName', + label: '直属上级', + }, + { + field: 'master', + label: '关键决策人', + render: (val) => + h(DictTag, { + type: DICT_TYPE.INFRA_BOOLEAN_STRING, + value: val, + }), + }, + { + field: 'sex', + label: '性别', + render: (val) => + h(DictTag, { type: DICT_TYPE.SYSTEM_USER_SEX, value: val }), + }, + { + field: 'contactNextTime', + label: '下次联系时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'remark', + label: '备注', + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/contact/detail/index.vue b/apps/web-ele/src/views/crm/contact/detail/index.vue new file mode 100644 index 0000000..4cf2286 --- /dev/null +++ b/apps/web-ele/src/views/crm/contact/detail/index.vue @@ -0,0 +1,158 @@ + + + diff --git a/apps/web-ele/src/views/crm/contact/detail/modules/info.vue b/apps/web-ele/src/views/crm/contact/detail/modules/info.vue new file mode 100644 index 0000000..0a56400 --- /dev/null +++ b/apps/web-ele/src/views/crm/contact/detail/modules/info.vue @@ -0,0 +1,36 @@ + + + diff --git a/apps/web-ele/src/views/crm/contact/index.vue b/apps/web-ele/src/views/crm/contact/index.vue new file mode 100644 index 0000000..7f1ea9e --- /dev/null +++ b/apps/web-ele/src/views/crm/contact/index.vue @@ -0,0 +1,213 @@ + + + diff --git a/apps/web-ele/src/views/crm/contact/modules/form.vue b/apps/web-ele/src/views/crm/contact/modules/form.vue new file mode 100644 index 0000000..5b0b3c7 --- /dev/null +++ b/apps/web-ele/src/views/crm/contact/modules/form.vue @@ -0,0 +1,80 @@ + + + diff --git a/apps/web-ele/src/views/crm/contract/components/data.ts b/apps/web-ele/src/views/crm/contract/components/data.ts new file mode 100644 index 0000000..c314faa --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/components/data.ts @@ -0,0 +1,92 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { erpPriceInputFormatter } from '@vben/utils'; + +export function useDetailListColumns(): VxeTableGridOptions['columns'] { + return [ + { + title: '合同编号', + field: 'no', + minWidth: 150, + fixed: 'left', + }, + { + title: '合同名称', + field: 'name', + minWidth: 150, + fixed: 'left', + slots: { default: 'name' }, + }, + { + title: '合同金额(元)', + field: 'totalPrice', + minWidth: 150, + formatter: 'formatAmount2', + }, + { + title: '合同开始时间', + field: 'startTime', + minWidth: 150, + formatter: 'formatDateTime', + }, + { + title: '合同结束时间', + field: 'endTime', + minWidth: 150, + formatter: 'formatDateTime', + }, + { + title: '已回款金额(元)', + field: 'totalReceivablePrice', + minWidth: 150, + formatter: 'formatAmount2', + }, + { + title: '未回款金额(元)', + field: 'unpaidPrice', + minWidth: 150, + formatter: ({ row }) => { + return erpPriceInputFormatter( + row.totalPrice - row.totalReceivablePrice, + ); + }, + }, + { + title: '负责人', + field: 'ownerUserName', + minWidth: 150, + }, + { + title: '所属部门', + field: 'ownerUserDeptName', + minWidth: 150, + }, + { + title: '创建时间', + field: 'createTime', + minWidth: 150, + formatter: 'formatDateTime', + }, + { + title: '创建人', + field: 'creatorName', + minWidth: 150, + }, + { + title: '备注', + field: 'remark', + minWidth: 150, + }, + { + title: '合同状态', + field: 'auditStatus', + fixed: 'right', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_AUDIT_STATUS }, + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/contract/components/detail-list.vue b/apps/web-ele/src/views/crm/contract/components/detail-list.vue new file mode 100644 index 0000000..63dc35c --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/components/detail-list.vue @@ -0,0 +1,133 @@ + + + + diff --git a/apps/web-ele/src/views/crm/contract/components/index.ts b/apps/web-ele/src/views/crm/contract/components/index.ts new file mode 100644 index 0000000..d9f6179 --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/components/index.ts @@ -0,0 +1 @@ +export { default as ContractDetailsList } from './detail-list.vue'; diff --git a/apps/web-ele/src/views/crm/contract/config/data.ts b/apps/web-ele/src/views/crm/contract/config/data.ts new file mode 100644 index 0000000..c45dc50 --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/config/data.ts @@ -0,0 +1,40 @@ +import type { VbenFormSchema } from '#/adapter/form'; + +import { z } from '#/adapter/form'; + +export const schema: VbenFormSchema[] = [ + { + component: 'RadioGroup', + fieldName: 'notifyEnabled', + label: '提前提醒设置', + componentProps: { + options: [ + { label: '提醒', value: true }, + { label: '不提醒', value: false }, + ], + }, + defaultValue: true, + }, + { + component: 'Input', + fieldName: 'notifyDays', + componentProps: { + placeholder: '请输入天数', + class: '!w-full', + }, + renderComponentContent: () => ({ + prepend: () => '提前', + append: () => '天提醒', + }), + rules: z.coerce.number().int().min(0, '天数不能小于 0'), + dependencies: { + triggerFields: ['notifyEnabled'], + show: (values) => values.notifyEnabled, + trigger(values) { + if (!values.notifyEnabled) { + values.notifyDays = undefined; + } + }, + }, + }, +]; diff --git a/apps/web-ele/src/views/crm/contract/config/index.vue b/apps/web-ele/src/views/crm/contract/config/index.vue new file mode 100644 index 0000000..c3dbb08 --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/config/index.vue @@ -0,0 +1,61 @@ + + + diff --git a/apps/web-ele/src/views/crm/contract/data.ts b/apps/web-ele/src/views/crm/contract/data.ts new file mode 100644 index 0000000..db2ee86 --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/data.ts @@ -0,0 +1,421 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { useUserStore } from '@vben/stores'; +import { erpPriceInputFormatter, erpPriceMultiply } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getSimpleBusinessList } from '#/api/crm/business'; +import { getSimpleContactList } from '#/api/crm/contact'; +import { getCustomerSimpleList } from '#/api/crm/customer'; +import { getSimpleUserList } from '#/api/system/user'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '合同编号', + component: 'Input', + componentProps: { + placeholder: '保存时自动生成', + disabled: true, + }, + }, + { + fieldName: 'name', + label: '合同名称', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入合同名称', + }, + }, + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + defaultValue: userStore.userInfo?.id, + rules: 'required', + }, + { + fieldName: 'customerId', + label: '客户名称', + component: 'ApiSelect', + rules: 'required', + componentProps: { + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择客户', + }, + }, + { + fieldName: 'businessId', + label: '商机名称', + component: 'Select', + componentProps: { + options: [], + placeholder: '请选择商机', + }, + dependencies: { + triggerFields: ['customerId'], + disabled: (values) => !values.customerId, + async componentProps(values) { + if (!values.customerId) { + return { + options: [], + placeholder: '请选择客户', + }; + } + const res = await getSimpleBusinessList(); + const list = res.filter( + (item) => item.customerId === values.customerId, + ); + return { + options: list.map((item) => ({ + label: item.name, + value: item.id, + })), + placeholder: '请选择商机', + }; + }, + }, + }, + { + fieldName: 'orderDate', + label: '下单日期', + component: 'DatePicker', + rules: 'required', + componentProps: { + format: 'YYYY-MM-DD', + valueFormat: 'x', + placeholder: '请选择下单日期', + class: '!w-full', + }, + }, + { + fieldName: 'startTime', + label: '合同开始时间', + component: 'DatePicker', + componentProps: { + format: 'YYYY-MM-DD', + valueFormat: 'x', + placeholder: '请选择合同开始时间', + class: '!w-full', + }, + }, + { + fieldName: 'endTime', + label: '合同结束时间', + component: 'DatePicker', + componentProps: { + format: 'YYYY-MM-DD', + valueFormat: 'x', + placeholder: '请选择合同结束时间', + class: '!w-full', + }, + }, + { + fieldName: 'signUserId', + label: '公司签约人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + defaultValue: userStore.userInfo?.id, + }, + { + fieldName: 'signContactId', + label: '客户签约人', + component: 'Select', + componentProps: { + options: [], + placeholder: '请选择客户签约人', + }, + dependencies: { + triggerFields: ['customerId'], + disabled: (values) => !values.customerId, + async componentProps(values) { + if (!values.customerId) { + return { + options: [], + placeholder: '请选择客户', + }; + } + const res = await getSimpleContactList(); + const list = res.filter( + (item) => item.customerId === values.customerId, + ); + return { + options: list.map((item) => ({ + label: item.name, + value: item.id, + })), + placeholder: '请选择客户签约人', + }; + }, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 4, + }, + }, + { + fieldName: 'product', + label: '产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + fieldName: 'totalProductPrice', + label: '产品总金额', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + placeholder: '请输入产品总金额', + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional().default(0), + }, + { + fieldName: 'discountPercent', + label: '整单折扣(%)', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + placeholder: '请输入整单折扣', + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).max(100).optional().default(0), + }, + { + fieldName: 'totalPrice', + label: '折扣后金额', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['totalProductPrice', 'discountPercent'], + trigger(values, form) { + const discountPrice = + erpPriceMultiply( + values.totalProductPrice, + values.discountPercent / 100, + ) ?? 0; + form.setFieldValue( + 'totalPrice', + values.totalProductPrice - discountPrice, + ); + }, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '合同编号', + component: 'Input', + componentProps: { + placeholder: '请输入合同编号', + clearable: true, + }, + }, + { + fieldName: 'name', + label: '合同名称', + component: 'Input', + componentProps: { + placeholder: '请输入合同名称', + clearable: true, + }, + }, + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择客户', + clearable: true, + }, + }, + ]; +} + +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + title: '合同编号', + field: 'no', + minWidth: 180, + fixed: 'left', + }, + { + title: '合同名称', + field: 'name', + minWidth: 160, + fixed: 'left', + slots: { default: 'name' }, + }, + { + title: '客户名称', + field: 'customerName', + minWidth: 120, + slots: { default: 'customerName' }, + }, + { + title: '商机名称', + field: 'businessName', + minWidth: 130, + slots: { default: 'businessName' }, + }, + { + title: '合同金额(元)', + field: 'totalPrice', + minWidth: 140, + formatter: 'formatAmount2', + }, + { + title: '下单时间', + field: 'orderDate', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '合同开始时间', + field: 'startTime', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '合同结束时间', + field: 'endTime', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '客户签约人', + field: 'signContactName', + minWidth: 130, + slots: { default: 'signContactName' }, + }, + { + title: '公司签约人', + field: 'signUserName', + minWidth: 130, + }, + { + title: '备注', + field: 'remark', + minWidth: 200, + }, + { + title: '已回款金额(元)', + field: 'totalReceivablePrice', + minWidth: 140, + formatter: 'formatAmount2', + }, + { + title: '未回款金额(元)', + field: 'unReceivablePrice', + minWidth: 140, + formatter: ({ row }) => { + return erpPriceInputFormatter( + row.totalPrice - row.totalReceivablePrice, + ); + }, + }, + { + title: '最后跟进时间', + field: 'contactLastTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '负责人', + field: 'ownerUserName', + minWidth: 120, + }, + { + title: '所属部门', + field: 'ownerUserDeptName', + minWidth: 100, + }, + { + title: '更新时间', + field: 'updateTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '创建时间', + field: 'createTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '创建人', + field: 'creatorName', + minWidth: 120, + }, + { + title: '合同状态', + field: 'auditStatus', + fixed: 'right', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_AUDIT_STATUS }, + }, + }, + { + title: '操作', + field: 'actions', + fixed: 'right', + minWidth: 130, + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/contract/detail/data.ts b/apps/web-ele/src/views/crm/contract/detail/data.ts new file mode 100644 index 0000000..bfe7b56 --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/detail/data.ts @@ -0,0 +1,100 @@ +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { erpPriceInputFormatter, formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; + +/** 详情头部的配置 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'customerName', + label: '客户名称', + }, + { + field: 'totalPrice', + label: '合同金额(元)', + render: (val) => erpPriceInputFormatter(val) as string, + }, + { + field: 'orderDate', + label: '下单时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'totalReceivablePrice', + label: '回款金额(元)', + render: (val) => erpPriceInputFormatter(val) as string, + }, + { + field: 'ownerUserName', + label: '负责人', + }, + ]; +} + +/** 详情基本信息的配置 */ +export function useDetailBaseSchema(): DescriptionItemSchema[] { + return [ + { + field: 'no', + label: '合同编号', + }, + { + field: 'name', + label: '合同名称', + }, + { + field: 'customerName', + label: '客户名称', + }, + { + field: 'businessName', + label: '商机名称', + }, + { + field: 'totalPrice', + label: '合同金额(元)', + render: (val) => erpPriceInputFormatter(val) as string, + }, + { + field: 'orderDate', + label: '下单时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'startTime', + label: '合同开始时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'endTime', + label: '合同结束时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'signContactName', + label: '客户签约人', + }, + { + field: 'signUserName', + label: '公司签约人', + }, + { + field: 'remark', + label: '备注', + }, + { + field: 'auditStatus', + label: '合同状态', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_AUDIT_STATUS, + value: val, + }), + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/contract/detail/index.vue b/apps/web-ele/src/views/crm/contract/detail/index.vue new file mode 100644 index 0000000..9581c81 --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/detail/index.vue @@ -0,0 +1,170 @@ + + + diff --git a/apps/web-ele/src/views/crm/contract/detail/modules/info.vue b/apps/web-ele/src/views/crm/contract/detail/modules/info.vue new file mode 100644 index 0000000..31f1d8c --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/detail/modules/info.vue @@ -0,0 +1,36 @@ + + + diff --git a/apps/web-ele/src/views/crm/contract/index.vue b/apps/web-ele/src/views/crm/contract/index.vue new file mode 100644 index 0000000..50adfc1 --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/index.vue @@ -0,0 +1,267 @@ + + + diff --git a/apps/web-ele/src/views/crm/contract/modules/form.vue b/apps/web-ele/src/views/crm/contract/modules/form.vue new file mode 100644 index 0000000..b390654 --- /dev/null +++ b/apps/web-ele/src/views/crm/contract/modules/form.vue @@ -0,0 +1,121 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/data.ts b/apps/web-ele/src/views/crm/customer/data.ts new file mode 100644 index 0000000..a3fdcf4 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/data.ts @@ -0,0 +1,396 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { z } from '@vben/common-ui'; +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { useUserStore } from '@vben/stores'; + +import { getAreaTree } from '#/api/system/area'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '客户名称', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入客户名称', + allowClear: true, + }, + }, + { + fieldName: 'source', + label: '客户来源', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_SOURCE, 'number'), + placeholder: '请选择客户来源', + allowClear: true, + }, + }, + { + fieldName: 'mobile', + label: '手机', + component: 'Input', + componentProps: { + placeholder: '请输入手机', + allowClear: true, + }, + }, + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择负责人', + allowClear: true, + }, + defaultValue: userStore.userInfo?.id, + rules: 'required', + }, + { + fieldName: 'telephone', + label: '电话', + component: 'Input', + componentProps: { + placeholder: '请输入电话', + allowClear: true, + }, + }, + { + fieldName: 'email', + label: '邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入邮箱', + allowClear: true, + }, + }, + { + fieldName: 'wechat', + label: '微信', + component: 'Input', + componentProps: { + placeholder: '请输入微信', + allowClear: true, + }, + }, + { + fieldName: 'qq', + label: 'QQ', + component: 'Input', + componentProps: { + placeholder: '请输入QQ', + allowClear: true, + }, + }, + { + fieldName: 'industryId', + label: '客户行业', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_INDUSTRY, 'number'), + placeholder: '请选择客户行业', + allowClear: true, + }, + }, + { + fieldName: 'level', + label: '客户级别', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_LEVEL, 'number'), + placeholder: '请选择客户级别', + allowClear: true, + }, + }, + { + fieldName: 'areaId', + label: '地址', + component: 'ApiTreeSelect', + componentProps: { + api: getAreaTree, + fieldNames: { label: 'name', value: 'id', children: 'children' }, + placeholder: '请选择地址', + allowClear: true, + }, + }, + { + fieldName: 'detailAddress', + label: '详细地址', + component: 'Input', + componentProps: { + placeholder: '请输入详细地址', + allowClear: true, + }, + }, + { + fieldName: 'contactNextTime', + label: '下次联系时间', + component: 'DatePicker', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + placeholder: '请选择下次联系时间', + allowClear: true, + class: '!w-full', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '客户名称', + component: 'Input', + componentProps: { + placeholder: '请输入客户名称', + allowClear: true, + }, + }, + { + fieldName: 'mobile', + label: '手机号', + component: 'Input', + componentProps: { + placeholder: '请输入手机号', + allowClear: true, + }, + }, + { + fieldName: 'telephone', + label: '电话', + component: 'Input', + componentProps: { + placeholder: '请输入电话', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + placeholder: ['开始日期', '结束日期'], + allowClear: true, + }, + }, + ]; +} + +/** 导入客户的表单 */ +export function useImportFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择负责人', + allowClear: true, + class: 'w-full', + }, + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + rules: 'required', + }, + { + fieldName: 'file', + label: '客户数据', + component: 'Upload', + rules: 'required', + help: '仅允许导入 xls、xlsx 格式文件', + }, + { + fieldName: 'updateSupport', + label: '是否覆盖', + component: 'Switch', + componentProps: { + activeValue: true, + inactiveValue: false, + }, + rules: z.boolean().default(false), + help: '是否更新已经存在的客户数据', + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '客户名称', + fixed: 'left', + minWidth: 160, + slots: { default: 'name' }, + }, + { + field: 'source', + title: '客户来源', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_SOURCE }, + }, + }, + { + field: 'mobile', + title: '手机', + minWidth: 120, + }, + { + field: 'telephone', + title: '电话', + minWidth: 130, + }, + { + field: 'email', + title: '邮箱', + minWidth: 180, + }, + { + field: 'level', + title: '客户级别', + minWidth: 135, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_LEVEL }, + }, + }, + { + field: 'industryId', + title: '客户行业', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY }, + }, + }, + { + field: 'contactNextTime', + title: '下次联系时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + }, + { + field: 'lockStatus', + title: '锁定状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'dealStatus', + title: '成交状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'contactLastTime', + title: '最后跟进时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'contactLastContent', + title: '最后跟进记录', + minWidth: 200, + }, + { + field: 'detailAddress', + title: '地址', + minWidth: 180, + }, + { + field: 'poolDay', + title: '距离进入公海天数', + minWidth: 140, + formatter: ({ cellValue }) => + cellValue === null ? '-' : `${cellValue} 天`, + }, + { + field: 'ownerUserName', + title: '负责人', + minWidth: 100, + }, + { + field: 'ownerUserDeptName', + title: '所属部门', + minWidth: 100, + }, + { + field: 'updateTime', + title: '更新时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 100, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/customer/detail/data.ts b/apps/web-ele/src/views/crm/customer/detail/data.ts new file mode 100644 index 0000000..9d55b40 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/detail/data.ts @@ -0,0 +1,130 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { useUserStore } from '@vben/stores'; +import { formatDateTime } from '@vben/utils'; + +import { getSimpleUserList } from '#/api/system/user'; +import { DictTag } from '#/components/dict-tag'; + +/** 分配客户表单 */ +export function useDistributeFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + defaultValue: userStore.userInfo?.id, + rules: 'required', + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'level', + label: '客户级别', + render: (val) => + h(DictTag, { type: DICT_TYPE.CRM_CUSTOMER_LEVEL, value: val }), + }, + { + field: 'dealStatus', + label: '成交状态', + render: (val) => (val ? '已成交' : '未成交'), + }, + { + field: 'ownerUserName', + label: '负责人', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} + +/** 详情页的基础字段 */ +export function useDetailBaseSchema(): DescriptionItemSchema[] { + return [ + { + field: 'name', + label: '客户名称', + }, + { + field: 'source', + label: '客户来源', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_CUSTOMER_SOURCE, + value: val, + }), + }, + { + field: 'mobile', + label: '手机', + }, + { + field: 'telephone', + label: '电话', + }, + { + field: 'email', + label: '邮箱', + }, + { + field: 'areaName', + label: '地址', + render: (val, data) => { + const areaName = val ?? ''; + const detailAddress = data?.detailAddress ?? ''; + return [areaName, detailAddress].filter(Boolean).join(' '); + }, + }, + { + field: 'qq', + label: 'QQ', + }, + { + field: 'wechat', + label: '微信', + }, + { + field: 'industryId', + label: '客户行业', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY, + value: val, + }), + }, + { + field: 'contactNextTime', + label: '下次联系时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'remark', + label: '备注', + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/customer/detail/index.vue b/apps/web-ele/src/views/crm/customer/detail/index.vue new file mode 100644 index 0000000..77c0e1b --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/detail/index.vue @@ -0,0 +1,311 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/detail/modules/distribute-form.vue b/apps/web-ele/src/views/crm/customer/detail/modules/distribute-form.vue new file mode 100644 index 0000000..aa7ca2c --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/detail/modules/distribute-form.vue @@ -0,0 +1,69 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/detail/modules/info.vue b/apps/web-ele/src/views/crm/customer/detail/modules/info.vue new file mode 100644 index 0000000..abeaa24 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/detail/modules/info.vue @@ -0,0 +1,36 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/index.vue b/apps/web-ele/src/views/crm/customer/index.vue new file mode 100644 index 0000000..b3f67b0 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/index.vue @@ -0,0 +1,217 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/limitConfig/data.ts b/apps/web-ele/src/views/crm/customer/limitConfig/data.ts new file mode 100644 index 0000000..675019a --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/limitConfig/data.ts @@ -0,0 +1,156 @@ +import type { VbenFormSchema } from '@vben/common-ui'; + +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { handleTree } from '@vben/utils'; + +import { LimitConfType } from '#/api/crm/customer/limitConfig'; +import { getSimpleDeptList } from '#/api/system/dept'; +import { getSimpleUserList } from '#/api/system/user'; + +/** 新增/修改的表单 */ +export function useFormSchema(confType: LimitConfType): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'type', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'userIds', + label: '规则适用人群', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + mode: 'multiple', + allowClear: true, + placeholder: '请选择规则适用人群', + }, + }, + { + fieldName: 'deptIds', + label: '规则适用部门', + component: 'ApiTreeSelect', + componentProps: { + api: async () => { + const data = await getSimpleDeptList(); + return handleTree(data); + }, + multiple: true, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择规则适用部门', + defaultExpandAll: true, + }, + }, + { + fieldName: 'maxCount', + label: + confType === LimitConfType.CUSTOMER_QUANTITY_LIMIT + ? '拥有客户数上限' + : '锁定客户数上限', + component: 'InputNumber', + componentProps: { + placeholder: `请输入${ + LimitConfType.CUSTOMER_QUANTITY_LIMIT === confType + ? '拥有客户数上限' + : '锁定客户数上限' + }`, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'dealCountEnabled', + label: '成交客户是否占用拥有客户数', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + }, + dependencies: { + triggerFields: [''], + show: () => confType === LimitConfType.CUSTOMER_QUANTITY_LIMIT, + }, + defaultValue: false, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + confType: LimitConfType, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + fixed: 'left', + }, + { + field: 'users', + title: '规则适用人群', + formatter: ({ cellValue }) => { + return cellValue + .map((user: any) => { + return user.nickname; + }) + .join(','); + }, + }, + { + field: 'depts', + title: '规则适用部门', + formatter: ({ cellValue }) => { + return cellValue + .map((dept: any) => { + return dept.name; + }) + .join(','); + }, + }, + { + field: 'maxCount', + title: + confType === LimitConfType.CUSTOMER_QUANTITY_LIMIT + ? '拥有客户数上限' + : '锁定客户数上限', + }, + { + field: 'dealCountEnabled', + title: '成交客户是否占用拥有客户数', + visible: confType === LimitConfType.CUSTOMER_QUANTITY_LIMIT, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/customer/limitConfig/index.vue b/apps/web-ele/src/views/crm/customer/limitConfig/index.vue new file mode 100644 index 0000000..a4cedb1 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/limitConfig/index.vue @@ -0,0 +1,172 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/limitConfig/modules/form.vue b/apps/web-ele/src/views/crm/customer/limitConfig/modules/form.vue new file mode 100644 index 0000000..ded5a12 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/limitConfig/modules/form.vue @@ -0,0 +1,100 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/modules/form.vue b/apps/web-ele/src/views/crm/customer/modules/form.vue new file mode 100644 index 0000000..549adc9 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/modules/form.vue @@ -0,0 +1,85 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/modules/import-form.vue b/apps/web-ele/src/views/crm/customer/modules/import-form.vue new file mode 100644 index 0000000..f85545d --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/modules/import-form.vue @@ -0,0 +1,86 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/pool/data.ts b/apps/web-ele/src/views/crm/customer/pool/data.ts new file mode 100644 index 0000000..d057b67 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/pool/data.ts @@ -0,0 +1,161 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '客户名称', + component: 'Input', + componentProps: { + placeholder: '请输入客户名称', + allowClear: true, + }, + }, + { + fieldName: 'mobile', + label: '手机', + component: 'Input', + componentProps: { + placeholder: '请输入手机', + allowClear: true, + }, + }, + { + fieldName: 'industryId', + label: '所属行业', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_INDUSTRY, 'number'), + placeholder: '请选择所属行业', + allowClear: true, + }, + }, + { + fieldName: 'level', + label: '客户级别', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_LEVEL, 'number'), + placeholder: '请选择客户级别', + allowClear: true, + }, + }, + { + fieldName: 'source', + label: '客户来源', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_SOURCE, 'number'), + placeholder: '请选择客户来源', + allowClear: true, + }, + }, + ]; +} + +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + title: '客户名称', + field: 'name', + minWidth: 160, + fixed: 'left', + slots: { default: 'name' }, + }, + { + title: '客户来源', + field: 'source', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_SOURCE }, + }, + }, + { + title: '手机', + field: 'mobile', + minWidth: 120, + }, + { + title: '电话', + field: 'telephone', + minWidth: 120, + }, + { + title: '邮箱', + field: 'email', + minWidth: 140, + }, + { + title: '客户级别', + field: 'level', + minWidth: 135, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_LEVEL }, + }, + }, + { + title: '客户行业', + field: 'industryId', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY }, + }, + }, + { + title: '下次联系时间', + field: 'contactNextTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '备注', + field: 'remark', + minWidth: 200, + }, + { + title: '成交状态', + field: 'dealStatus', + minWidth: 80, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + title: '最后跟进时间', + field: 'contactLastTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '最后跟进记录', + field: 'contactLastContent', + minWidth: 200, + }, + { + title: '更新时间', + field: 'updateTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '创建时间', + field: 'createTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '创建人', + field: 'creatorName', + minWidth: 100, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/customer/pool/index.vue b/apps/web-ele/src/views/crm/customer/pool/index.vue new file mode 100644 index 0000000..abdc0d3 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/pool/index.vue @@ -0,0 +1,97 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/poolConfig/data.ts b/apps/web-ele/src/views/crm/customer/poolConfig/data.ts new file mode 100644 index 0000000..5fa6e26 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/poolConfig/data.ts @@ -0,0 +1,83 @@ +import type { VbenFormSchema } from '#/adapter/form'; + +import { z } from '#/adapter/form'; + +export const schema: VbenFormSchema[] = [ + { + component: 'RadioGroup', + fieldName: 'enabled', + label: '客户公海规则设置', + componentProps: { + options: [ + { label: '开启', value: true }, + { label: '关闭', value: false }, + ], + }, + }, + { + component: 'Input', + fieldName: 'contactExpireDays', + componentProps: { + placeholder: '请输入天数', + class: '!w-full', + }, + renderComponentContent: () => ({ + append: () => '天不跟进或', + }), + rules: z.coerce.number().int().min(0, '天数不能小于 0'), + dependencies: { + triggerFields: ['enabled'], + show: (value) => value.enabled, + }, + }, + { + component: 'Input', + fieldName: 'dealExpireDays', + componentProps: { + placeholder: '请输入天数', + class: '!w-full', + }, + renderComponentContent: () => ({ + prepend: () => '或', + append: () => '天未成交', + }), + rules: z.coerce.number().int().min(0, '天数不能小于 0'), + dependencies: { + triggerFields: ['enabled'], + show: (value) => value.enabled, + }, + }, + { + component: 'RadioGroup', + fieldName: 'notifyEnabled', + label: '提前提醒设置', + componentProps: { + options: [ + { label: '开启', value: true }, + { label: '关闭', value: false }, + ], + }, + dependencies: { + triggerFields: ['enabled'], + show: (value) => value.enabled, + }, + defaultValue: false, + }, + { + component: 'Input', + fieldName: 'notifyDays', + componentProps: { + placeholder: '请输入天数', + class: '!w-full', + }, + renderComponentContent: () => ({ + prepend: () => '提前', + append: () => '天提醒', + }), + rules: z.coerce.number().int().min(0, '天数不能小于 0'), + dependencies: { + triggerFields: ['notifyEnabled'], + show: (value) => value.enabled && value.notifyEnabled, + }, + }, +]; diff --git a/apps/web-ele/src/views/crm/customer/poolConfig/index.vue b/apps/web-ele/src/views/crm/customer/poolConfig/index.vue new file mode 100644 index 0000000..5a40003 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/poolConfig/index.vue @@ -0,0 +1,69 @@ + + + diff --git a/apps/web-ele/src/views/crm/followup/data.ts b/apps/web-ele/src/views/crm/followup/data.ts new file mode 100644 index 0000000..514a2d9 --- /dev/null +++ b/apps/web-ele/src/views/crm/followup/data.ts @@ -0,0 +1,195 @@ +import type { Ref } from 'vue'; + +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDateTime } from '@vben/utils'; + +import { getBusinessPageByCustomer } from '#/api/crm/business'; +import { getContactPageByCustomer } from '#/api/crm/contact'; +import { BizTypeEnum } from '#/api/crm/permission'; + +/** 新增/修改的表单 */ +export function useFormSchema( + bizId: Ref, +): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'bizId', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'bizType', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'type', + label: '跟进类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_FOLLOW_UP_TYPE, 'number'), + }, + rules: 'required', + }, + { + fieldName: 'nextTime', + label: '下次联系时间', + component: 'DatePicker', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + placeholder: '请选择下次联系时间', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'content', + label: '跟进内容', + component: 'Textarea', + rules: 'required', + }, + { + fieldName: 'picUrls', + label: '图片', + component: 'ImageUpload', + }, + { + fieldName: 'fileUrls', + label: '附件', + component: 'FileUpload', + }, + { + fieldName: 'contactIds', + label: '关联联系人', + component: 'ApiSelect', + componentProps: { + api: async () => { + if (!bizId.value) { + return []; + } + const res = await getContactPageByCustomer({ + pageNo: 1, + pageSize: 100, + customerId: bizId.value, + }); + return res.list; + }, + labelField: 'name', + valueField: 'id', + mode: 'multiple', + }, + }, + { + fieldName: 'businessIds', + label: '关联商机', + component: 'ApiSelect', + componentProps: { + api: async () => { + if (!bizId.value) { + return []; + } + const res = await getBusinessPageByCustomer({ + pageNo: 1, + pageSize: 100, + customerId: bizId.value, + }); + return res.list; + }, + labelField: 'name', + valueField: 'id', + mode: 'multiple', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + bizType: number, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + }, + { field: 'creatorName', title: '跟进人' }, + { + field: 'type', + title: '跟进类型', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_FOLLOW_UP_TYPE }, + }, + }, + { field: 'content', title: '跟进内容' }, + { + field: 'nextTime', + title: '下次联系时间', + formatter: 'formatDateTime', + }, + { + field: 'contacts', + title: '关联联系人', + visible: bizType === BizTypeEnum.CRM_CUSTOMER, + slots: { default: 'contacts' }, + }, + { + field: 'businesses', + title: '关联商机', + visible: bizType === BizTypeEnum.CRM_CUSTOMER, + slots: { default: 'businesses' }, + }, + { + field: 'actions', + title: '操作', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的系统字段 */ +export function useFollowUpDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'ownerUserName', + label: '负责人', + }, + { + field: 'contactLastContent', + label: '最后跟进记录', + }, + { + field: 'contactLastTime', + label: '最后跟进时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'creatorName', + label: '创建人', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'updateTime', + label: '更新时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/followup/index.ts b/apps/web-ele/src/views/crm/followup/index.ts new file mode 100644 index 0000000..911cbed --- /dev/null +++ b/apps/web-ele/src/views/crm/followup/index.ts @@ -0,0 +1 @@ +export { default as FollowUp } from './index.vue'; diff --git a/apps/web-ele/src/views/crm/followup/index.vue b/apps/web-ele/src/views/crm/followup/index.vue new file mode 100644 index 0000000..03fea55 --- /dev/null +++ b/apps/web-ele/src/views/crm/followup/index.vue @@ -0,0 +1,165 @@ + + + diff --git a/apps/web-ele/src/views/crm/followup/modules/form.vue b/apps/web-ele/src/views/crm/followup/modules/form.vue new file mode 100644 index 0000000..51df040 --- /dev/null +++ b/apps/web-ele/src/views/crm/followup/modules/form.vue @@ -0,0 +1,81 @@ + + + diff --git a/apps/web-ele/src/views/crm/permission/index.ts b/apps/web-ele/src/views/crm/permission/index.ts new file mode 100644 index 0000000..2988df4 --- /dev/null +++ b/apps/web-ele/src/views/crm/permission/index.ts @@ -0,0 +1,2 @@ +export { default as PermissionList } from './modules/list.vue'; +export { default as TransferForm } from './modules/transfer-form.vue'; diff --git a/apps/web-ele/src/views/crm/permission/modules/data.ts b/apps/web-ele/src/views/crm/permission/modules/data.ts new file mode 100644 index 0000000..fdbe9bc --- /dev/null +++ b/apps/web-ele/src/views/crm/permission/modules/data.ts @@ -0,0 +1,233 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { BizTypeEnum, PermissionLevelEnum } from '#/api/crm/permission'; +import { getSimpleUserList } from '#/api/system/user'; + +/** 新增/修改的表单 */ +export function useTransferFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'newOwnerUserId', + label: '选择新负责人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'oldOwnerHandler', + label: '老负责人', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '加入团队', + value: true, + }, + { + label: '移除', + value: false, + }, + ], + }, + rules: 'required', + }, + { + fieldName: 'oldOwnerPermissionLevel', + label: '老负责人权限级别', + component: 'RadioGroup', + componentProps: { + options: getDictOptions( + DICT_TYPE.CRM_PERMISSION_LEVEL, + 'number', + ).filter((dict) => dict.value !== PermissionLevelEnum.OWNER), + }, + dependencies: { + triggerFields: ['oldOwnerHandler'], + show: (values) => values.oldOwnerHandler, + trigger(values) { + if (!values.oldOwnerHandler) { + values.oldOwnerPermissionLevel = undefined; + } + }, + }, + rules: 'required', + }, + { + fieldName: 'toBizTypes', + label: '同时转移', + component: 'CheckboxGroup', + componentProps: { + options: [ + { + label: '联系人', + value: BizTypeEnum.CRM_CONTACT, + }, + { + label: '商机', + value: BizTypeEnum.CRM_BUSINESS, + }, + { + label: '合同', + value: BizTypeEnum.CRM_CONTRACT, + }, + ], + }, + }, + ]; +} + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'bizId', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'ids', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'userId', + label: '选择人员', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + dependencies: { + triggerFields: ['ids'], + show: (values) => { + return values.ids === undefined; + }, + }, + }, + { + fieldName: 'level', + label: '权限级别', + component: 'RadioGroup', + componentProps: { + options: getDictOptions( + DICT_TYPE.CRM_PERMISSION_LEVEL, + 'number', + ).filter((dict) => dict.value !== PermissionLevelEnum.OWNER), + }, + rules: 'required', + }, + { + fieldName: 'bizType', + label: 'Crm 类型', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '联系人', + value: BizTypeEnum.CRM_CONTACT, + }, + { + label: '商机', + value: BizTypeEnum.CRM_BUSINESS, + }, + { + label: '合同', + value: BizTypeEnum.CRM_CONTRACT, + }, + ], + }, + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'toBizTypes', + label: '同时添加至', + component: 'CheckboxGroup', + componentProps: { + options: [ + { + label: '联系人', + value: BizTypeEnum.CRM_CONTACT, + }, + { + label: '商机', + value: BizTypeEnum.CRM_BUSINESS, + }, + { + label: '合同', + value: BizTypeEnum.CRM_CONTRACT, + }, + ], + }, + dependencies: { + triggerFields: ['ids', 'bizType'], + show: (values) => { + return ( + values.ids === undefined && + values.bizType === BizTypeEnum.CRM_CUSTOMER + ); + }, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + }, + { + field: 'nickname', + title: '姓名', + }, + { + field: 'deptName', + title: '部门', + }, + { + field: 'postNames', + title: '岗位', + }, + { + field: 'level', + title: '权限级别', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_PERMISSION_LEVEL }, + }, + }, + { + field: 'createTime', + title: '加入时间', + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/permission/modules/form.vue b/apps/web-ele/src/views/crm/permission/modules/form.vue new file mode 100644 index 0000000..949a77f --- /dev/null +++ b/apps/web-ele/src/views/crm/permission/modules/form.vue @@ -0,0 +1,90 @@ + + + diff --git a/apps/web-ele/src/views/crm/permission/modules/list.vue b/apps/web-ele/src/views/crm/permission/modules/list.vue new file mode 100644 index 0000000..957f0dd --- /dev/null +++ b/apps/web-ele/src/views/crm/permission/modules/list.vue @@ -0,0 +1,265 @@ + + + diff --git a/apps/web-ele/src/views/crm/permission/modules/transfer-form.vue b/apps/web-ele/src/views/crm/permission/modules/transfer-form.vue new file mode 100644 index 0000000..e823d48 --- /dev/null +++ b/apps/web-ele/src/views/crm/permission/modules/transfer-form.vue @@ -0,0 +1,120 @@ + + + diff --git a/apps/web-ele/src/views/crm/product/category/data.ts b/apps/web-ele/src/views/crm/product/category/data.ts new file mode 100644 index 0000000..d271c8f --- /dev/null +++ b/apps/web-ele/src/views/crm/product/category/data.ts @@ -0,0 +1,97 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { CrmProductCategoryApi } from '#/api/crm/product/category'; + +import { handleTree } from '@vben/utils'; + +import { getProductCategoryList } from '#/api/crm/product/category'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'parentId', + label: '上级分类', + component: 'ApiTreeSelect', + componentProps: { + clearable: true, + api: async () => { + const data = await getProductCategoryList(); + data.unshift({ + id: 0, + name: '顶级分类', + } as CrmProductCategoryApi.ProductCategory); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择上级分类', + showSearch: true, + defaultExpandAll: true, + }, + rules: 'selectRequired', + }, + { + fieldName: 'name', + label: '分类名称', + component: 'Input', + componentProps: { + placeholder: '请输入分类名称', + }, + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '分类名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入分类名称', + }, + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '分类名称', + treeNode: true, + }, + { + field: 'id', + title: '分类编号', + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + }, + { + field: 'actions', + title: '操作', + width: 250, + fixed: 'right', + slots: { + default: 'actions', + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/product/category/index.vue b/apps/web-ele/src/views/crm/product/category/index.vue new file mode 100644 index 0000000..3aa4c03 --- /dev/null +++ b/apps/web-ele/src/views/crm/product/category/index.vue @@ -0,0 +1,168 @@ + + + diff --git a/apps/web-ele/src/views/crm/product/category/modules/form.vue b/apps/web-ele/src/views/crm/product/category/modules/form.vue new file mode 100644 index 0000000..329dcdf --- /dev/null +++ b/apps/web-ele/src/views/crm/product/category/modules/form.vue @@ -0,0 +1,94 @@ + + + diff --git a/apps/web-ele/src/views/crm/product/components/data.ts b/apps/web-ele/src/views/crm/product/components/data.ts new file mode 100644 index 0000000..266a912 --- /dev/null +++ b/apps/web-ele/src/views/crm/product/components/data.ts @@ -0,0 +1,111 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +/** 产品详情列表的列定义 */ +export function useDetailListColumns( + showBusinessPrice: boolean, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'productName', + title: '产品名称', + }, + { + field: 'productNo', + title: '产品条码', + }, + { + field: 'productUnit', + title: '产品单位', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_PRODUCT_UNIT }, + }, + }, + { + field: 'productPrice', + title: '产品价格(元)', + formatter: 'formatAmount2', + }, + { + field: 'businessPrice', + title: '商机价格(元)', + formatter: 'formatAmount2', + visible: showBusinessPrice, + }, + { + field: 'contractPrice', + title: '合同价格(元)', + formatter: 'formatAmount2', + visible: !showBusinessPrice, + }, + { + field: 'count', + title: '数量', + formatter: 'formatAmount3', + }, + { + field: 'totalPrice', + title: '合计金额(元)', + formatter: 'formatAmount2', + }, + ]; +} + +/** 产品编辑表格的列定义 */ +export function useProductEditTableColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50 }, + { + field: 'productId', + title: '产品名称', + minWidth: 100, + slots: { default: 'productId' }, + }, + { + field: 'productNo', + title: '条码', + minWidth: 150, + }, + { + field: 'productUnit', + title: '单位', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_PRODUCT_UNIT }, + }, + }, + { + field: 'productPrice', + title: '价格(元)', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'sellingPrice', + title: '售价(元)', + minWidth: 100, + slots: { default: 'sellingPrice' }, + }, + { + field: 'count', + title: '数量', + minWidth: 100, + slots: { default: 'count' }, + }, + { + field: 'totalPrice', + title: '合计', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/product/components/detail-list.vue b/apps/web-ele/src/views/crm/product/components/detail-list.vue new file mode 100644 index 0000000..5ce23bc --- /dev/null +++ b/apps/web-ele/src/views/crm/product/components/detail-list.vue @@ -0,0 +1,79 @@ + + + + diff --git a/apps/web-ele/src/views/crm/product/components/edit-table.vue b/apps/web-ele/src/views/crm/product/components/edit-table.vue new file mode 100644 index 0000000..0be8808 --- /dev/null +++ b/apps/web-ele/src/views/crm/product/components/edit-table.vue @@ -0,0 +1,201 @@ + + + diff --git a/apps/web-ele/src/views/crm/product/components/index.ts b/apps/web-ele/src/views/crm/product/components/index.ts new file mode 100644 index 0000000..dc52792 --- /dev/null +++ b/apps/web-ele/src/views/crm/product/components/index.ts @@ -0,0 +1,2 @@ +export { default as ProductDetailsList } from './detail-list.vue'; +export { default as ProductEditTable } from './edit-table.vue'; diff --git a/apps/web-ele/src/views/crm/product/data.ts b/apps/web-ele/src/views/crm/product/data.ts new file mode 100644 index 0000000..ef6efe9 --- /dev/null +++ b/apps/web-ele/src/views/crm/product/data.ts @@ -0,0 +1,231 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { useUserStore } from '@vben/stores'; +import { handleTree } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getProductCategoryList } from '#/api/crm/product/category'; +import { getSimpleUserList } from '#/api/system/user'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '产品名称', + rules: 'required', + componentProps: { + placeholder: '请输入产品名称', + clearable: true, + }, + }, + { + component: 'ApiSelect', + fieldName: 'ownerUserId', + label: '负责人', + rules: 'required', + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择负责人', + clearable: true, + }, + defaultValue: userStore.userInfo?.id, + }, + { + component: 'Input', + fieldName: 'no', + label: '产品编码', + rules: 'required', + componentProps: { + placeholder: '请输入产品编码', + clearable: true, + }, + }, + { + component: 'ApiTreeSelect', + fieldName: 'categoryId', + label: '产品类型', + rules: 'required', + componentProps: { + api: async () => { + const data = await getProductCategoryList(); + return handleTree(data); + }, + fieldNames: { label: 'name', value: 'id', children: 'children' }, + placeholder: '请选择产品类型', + clearable: true, + }, + }, + { + fieldName: 'unit', + label: '产品单位', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_PRODUCT_UNIT, 'number'), + placeholder: '请选择产品单位', + clearable: true, + }, + rules: 'required', + }, + { + component: 'InputNumber', + fieldName: 'price', + label: '价格(元)', + rules: 'required', + componentProps: { + min: 0, + precision: 2, + step: 0.1, + placeholder: '请输入产品价格', + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + component: 'Textarea', + fieldName: 'description', + label: '产品描述', + componentProps: { + placeholder: '请输入产品描述', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '上架状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_PRODUCT_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '产品名称', + component: 'Input', + componentProps: { + placeholder: '请输入产品名称', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '上架状态', + component: 'Select', + componentProps: { + clearable: true, + placeholder: '请选择上架状态', + options: getDictOptions(DICT_TYPE.CRM_PRODUCT_STATUS, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '产品编号', + visible: false, + }, + { + field: 'name', + title: '产品名称', + minWidth: 240, + slots: { default: 'name' }, + }, + { + field: 'categoryName', + title: '产品类型', + minWidth: 120, + }, + { + field: 'unit', + title: '产品单位', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_PRODUCT_UNIT }, + }, + }, + { + field: 'no', + title: '产品编码', + minWidth: 120, + }, + { + field: 'price', + title: '价格(元)', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'description', + title: '产品描述', + minWidth: 200, + }, + { + field: 'status', + title: '上架状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_PRODUCT_STATUS }, + }, + minWidth: 120, + }, + { + field: 'ownerUserName', + title: '负责人', + minWidth: 120, + }, + { + field: 'updateTime', + title: '更新时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + title: '操作', + width: 160, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/product/detail/data.ts b/apps/web-ele/src/views/crm/product/detail/data.ts new file mode 100644 index 0000000..0adf792 --- /dev/null +++ b/apps/web-ele/src/views/crm/product/detail/data.ts @@ -0,0 +1,72 @@ +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { erpPriceInputFormatter } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'categoryName', + label: '产品类别', + }, + { + field: 'unit', + label: '产品单位', + render: (val) => + h(DictTag, { type: DICT_TYPE.CRM_PRODUCT_UNIT, value: val }), + }, + { + field: 'price', + label: '产品价格(元)', + render: (val) => erpPriceInputFormatter(val), + }, + { + field: 'no', + label: '产品编码', + }, + ]; +} + +/** 详情页的基础字段 */ +export function useDetailBaseSchema(): DescriptionItemSchema[] { + return [ + { + field: 'name', + label: '产品名称', + }, + { + field: 'no', + label: '产品编码', + }, + { + field: 'price', + label: '价格(元)', + render: (val) => erpPriceInputFormatter(val), + }, + { + field: 'description', + label: '产品描述', + }, + { + field: 'categoryName', + label: '产品类型', + }, + { + field: 'status', + label: '是否上下架', + render: (val) => + h(DictTag, { type: DICT_TYPE.CRM_PRODUCT_STATUS, value: val }), + }, + { + field: 'unit', + label: '产品单位', + render: (val) => + h(DictTag, { type: DICT_TYPE.CRM_PRODUCT_UNIT, value: val }), + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/product/detail/index.vue b/apps/web-ele/src/views/crm/product/detail/index.vue new file mode 100644 index 0000000..7886b6c --- /dev/null +++ b/apps/web-ele/src/views/crm/product/detail/index.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/crm/product/detail/modules/info.vue b/apps/web-ele/src/views/crm/product/detail/modules/info.vue new file mode 100644 index 0000000..813bad2 --- /dev/null +++ b/apps/web-ele/src/views/crm/product/detail/modules/info.vue @@ -0,0 +1,23 @@ + + + diff --git a/apps/web-ele/src/views/crm/product/index.vue b/apps/web-ele/src/views/crm/product/index.vue new file mode 100644 index 0000000..07ad1ca --- /dev/null +++ b/apps/web-ele/src/views/crm/product/index.vue @@ -0,0 +1,157 @@ + + + diff --git a/apps/web-ele/src/views/crm/product/modules/form.vue b/apps/web-ele/src/views/crm/product/modules/form.vue new file mode 100644 index 0000000..ef022e6 --- /dev/null +++ b/apps/web-ele/src/views/crm/product/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/crm/receivable/components/data.ts b/apps/web-ele/src/views/crm/receivable/components/data.ts new file mode 100644 index 0000000..4f3f0e1 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/components/data.ts @@ -0,0 +1,73 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +/** 详情列表的字段 */ +export function useDetailListColumns(): VxeTableGridOptions['columns'] { + return [ + { + title: '回款编号', + field: 'no', + minWidth: 150, + fixed: 'left', + }, + { + title: '客户名称', + field: 'customerName', + minWidth: 150, + }, + { + title: '合同编号', + field: 'contract.no', + minWidth: 150, + }, + { + title: '回款日期', + field: 'returnTime', + minWidth: 150, + formatter: 'formatDateTime', + }, + { + title: '回款金额(元)', + field: 'price', + minWidth: 150, + formatter: 'formatAmount2', + }, + { + title: '回款方式', + field: 'returnType', + minWidth: 150, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE }, + }, + }, + { + title: '负责人', + field: 'ownerUserName', + minWidth: 150, + }, + { + title: '备注', + field: 'remark', + minWidth: 150, + }, + { + title: '回款状态', + field: 'auditStatus', + minWidth: 100, + fixed: 'right', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_AUDIT_STATUS }, + }, + }, + { + title: '操作', + field: 'actions', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/receivable/components/detail-list.vue b/apps/web-ele/src/views/crm/receivable/components/detail-list.vue new file mode 100644 index 0000000..fb2f935 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/components/detail-list.vue @@ -0,0 +1,144 @@ + + + + diff --git a/apps/web-ele/src/views/crm/receivable/components/index.ts b/apps/web-ele/src/views/crm/receivable/components/index.ts new file mode 100644 index 0000000..971ab65 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/components/index.ts @@ -0,0 +1 @@ +export { default as ReceivableDetailsList } from './detail-list.vue'; diff --git a/apps/web-ele/src/views/crm/receivable/data.ts b/apps/web-ele/src/views/crm/receivable/data.ts new file mode 100644 index 0000000..d81d147 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/data.ts @@ -0,0 +1,301 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { useUserStore } from '@vben/stores'; + +import { getContractSimpleList } from '#/api/crm/contract'; +import { getCustomerSimpleList } from '#/api/crm/customer'; +import { + getReceivablePlan, + getReceivablePlanSimpleList, +} from '#/api/crm/receivable/plan'; +import { getSimpleUserList } from '#/api/system/user'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '回款编号', + component: 'Input', + componentProps: { + placeholder: '保存时自动生成', + disabled: true, + }, + }, + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + rules: 'required', + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择负责人', + allowClear: true, + }, + defaultValue: userStore.userInfo?.id, + }, + { + fieldName: 'customerId', + label: '客户名称', + component: 'ApiSelect', + rules: 'required', + componentProps: { + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择客户', + }, + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + }, + { + fieldName: 'contractId', + label: '合同名称', + component: 'Select', + rules: 'required', + dependencies: { + triggerFields: ['customerId'], + disabled: (values) => !values.customerId || values.id, + async componentProps(values) { + if (values.customerId) { + if (!values.id) { + // 特殊:只有在【新增】时,才清空合同编号 + values.contractId = undefined; + } + const contracts = await getContractSimpleList(values.customerId); + return { + options: contracts.map((item) => ({ + label: item.name, + value: item.id, + })), + placeholder: '请选择合同', + } as any; + } + }, + }, + }, + { + fieldName: 'planId', + label: '回款期数', + component: 'Select', + rules: 'required', + dependencies: { + triggerFields: ['contractId'], + disabled: (values) => !values.contractId, + async componentProps(values) { + if (values.contractId) { + values.planId = undefined; + const plans = await getReceivablePlanSimpleList( + values.customerId, + values.contractId, + ); + return { + options: plans.map((item) => ({ + label: item.period, + value: item.id, + })), + placeholder: '请选择回款期数', + onChange: async (value: any) => { + const plan = await getReceivablePlan(value); + values.returnTime = plan?.returnTime; + values.price = plan?.price; + values.returnType = plan?.returnType; + }, + } as any; + } + }, + }, + }, + { + fieldName: 'returnType', + label: '回款方式', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE, 'number'), + placeholder: '请选择回款方式', + }, + }, + { + fieldName: 'price', + label: '回款金额', + component: 'InputNumber', + rules: 'required', + componentProps: { + placeholder: '请输入回款金额', + min: 0, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'returnTime', + label: '回款日期', + component: 'DatePicker', + rules: 'required', + componentProps: { + placeholder: '请选择回款日期', + valueFormat: 'x', + format: 'YYYY-MM-DD', + class: '!w-full', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 4, + }, + formItemClass: 'md:col-span-2', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '回款编号', + component: 'Input', + componentProps: { + placeholder: '请输入回款编号', + allowClear: true, + }, + }, + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择客户', + allowClear: true, + }, + }, + ]; +} + +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + title: '回款编号', + field: 'no', + minWidth: 160, + fixed: 'left', + slots: { default: 'no' }, + }, + { + title: '客户名称', + field: 'customerName', + minWidth: 150, + slots: { default: 'customerName' }, + }, + { + title: '合同编号', + field: 'contract', + minWidth: 160, + slots: { default: 'contractNo' }, + }, + { + title: '回款日期', + field: 'returnTime', + minWidth: 150, + formatter: 'formatDateTime', + }, + { + title: '回款金额(元)', + field: 'price', + minWidth: 150, + formatter: 'formatAmount2', + }, + { + title: '回款方式', + field: 'returnType', + minWidth: 150, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE }, + }, + }, + { + title: '备注', + field: 'remark', + minWidth: 150, + }, + { + title: '合同金额(元)', + field: 'contract.totalPrice', + minWidth: 150, + formatter: 'formatAmount2', + }, + { + title: '负责人', + field: 'ownerUserName', + minWidth: 150, + }, + { + title: '所属部门', + field: 'ownerUserDeptName', + minWidth: 150, + }, + { + title: '更新时间', + field: 'updateTime', + minWidth: 150, + formatter: 'formatDateTime', + }, + { + title: '创建时间', + field: 'createTime', + minWidth: 150, + formatter: 'formatDateTime', + }, + { + title: '创建人', + field: 'creatorName', + minWidth: 150, + }, + { + title: '回款状态', + field: 'auditStatus', + minWidth: 100, + fixed: 'right', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_AUDIT_STATUS }, + }, + }, + { + title: '操作', + field: 'actions', + minWidth: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/receivable/detail/data.ts b/apps/web-ele/src/views/crm/receivable/detail/data.ts new file mode 100644 index 0000000..dcceec5 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/detail/data.ts @@ -0,0 +1,105 @@ +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { erpPriceInputFormatter, formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'customerName', + label: '客户名称', + }, + { + field: 'totalPrice', + label: '合同金额(元)', + render: (val, data) => + erpPriceInputFormatter(val ?? data?.contract?.totalPrice ?? 0), + }, + { + field: 'returnTime', + label: '回款日期', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'price', + label: '回款金额(元)', + render: (val) => erpPriceInputFormatter(val), + }, + { + field: 'ownerUserName', + label: '负责人', + }, + ]; +} + +/** 详情页的基础字段 */ +export function useDetailBaseSchema(): DescriptionItemSchema[] { + return [ + { + field: 'no', + label: '回款编号', + }, + { + field: 'customerName', + label: '客户名称', + }, + { + field: 'contract', + label: '合同编号', + render: (val, data) => + val && data?.contract?.no ? data?.contract?.no : '', + }, + { + field: 'returnTime', + label: '回款日期', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'price', + label: '回款金额', + render: (val) => erpPriceInputFormatter(val), + }, + { + field: 'returnType', + label: '回款方式', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE, + value: val, + }), + }, + { + field: 'remark', + label: '备注', + }, + ]; +} + +/** 系统信息字段 */ +export function useDetailSystemSchema(): DescriptionItemSchema[] { + return [ + { + field: 'ownerUserName', + label: '负责人', + }, + { + field: 'creatorName', + label: '创建人', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'updateTime', + label: '更新时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/receivable/detail/index.vue b/apps/web-ele/src/views/crm/receivable/detail/index.vue new file mode 100644 index 0000000..70579ef --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/detail/index.vue @@ -0,0 +1,132 @@ + + + diff --git a/apps/web-ele/src/views/crm/receivable/detail/modules/info.vue b/apps/web-ele/src/views/crm/receivable/detail/modules/info.vue new file mode 100644 index 0000000..f7d18e3 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/detail/modules/info.vue @@ -0,0 +1,35 @@ + + + diff --git a/apps/web-ele/src/views/crm/receivable/index.vue b/apps/web-ele/src/views/crm/receivable/index.vue new file mode 100644 index 0000000..a5a1604 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/index.vue @@ -0,0 +1,263 @@ + + + diff --git a/apps/web-ele/src/views/crm/receivable/modules/form.vue b/apps/web-ele/src/views/crm/receivable/modules/form.vue new file mode 100644 index 0000000..ada8f56 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/modules/form.vue @@ -0,0 +1,102 @@ + + + diff --git a/apps/web-ele/src/views/crm/receivable/plan/components/data.ts b/apps/web-ele/src/views/crm/receivable/plan/components/data.ts new file mode 100644 index 0000000..9a67c0b --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/plan/components/data.ts @@ -0,0 +1,62 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +/** 详情列表的字段 */ +export function useDetailListColumns(): VxeTableGridOptions['columns'] { + return [ + { + title: '客户名称', + field: 'customerName', + minWidth: 150, + }, + { + title: '合同编号', + field: 'contractNo', + minWidth: 150, + }, + { + title: '期数', + field: 'period', + minWidth: 150, + }, + { + title: '计划回款(元)', + field: 'price', + minWidth: 150, + formatter: 'formatAmount2', + }, + { + title: '计划回款日期', + field: 'returnTime', + minWidth: 150, + formatter: 'formatDateTime', + }, + { + title: '提前几天提醒', + field: 'remindDays', + minWidth: 150, + }, + { + title: '提醒日期', + field: 'remindTime', + minWidth: 150, + formatter: 'formatDateTime', + }, + { + title: '负责人', + field: 'ownerUserName', + minWidth: 150, + }, + { + title: '备注', + field: 'remark', + minWidth: 150, + }, + { + title: '操作', + field: 'actions', + width: 240, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/receivable/plan/components/detail-list.vue b/apps/web-ele/src/views/crm/receivable/plan/components/detail-list.vue new file mode 100644 index 0000000..1aa30b9 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/plan/components/detail-list.vue @@ -0,0 +1,147 @@ + + + + diff --git a/apps/web-ele/src/views/crm/receivable/plan/components/index.ts b/apps/web-ele/src/views/crm/receivable/plan/components/index.ts new file mode 100644 index 0000000..cbb4b12 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/plan/components/index.ts @@ -0,0 +1,2 @@ +export { default as ReceivablePlanDetailsInfo } from '../detail/modules/info.vue'; +export { default as ReceivablePlanDetailsList } from './detail-list.vue'; diff --git a/apps/web-ele/src/views/crm/receivable/plan/data.ts b/apps/web-ele/src/views/crm/receivable/plan/data.ts new file mode 100644 index 0000000..50b67f6 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/plan/data.ts @@ -0,0 +1,289 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { useUserStore } from '@vben/stores'; +import { erpPriceInputFormatter } from '@vben/utils'; + +import { getContractSimpleList } from '#/api/crm/contract'; +import { getCustomerSimpleList } from '#/api/crm/customer'; +import { getSimpleUserList } from '#/api/system/user'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + fieldName: 'period', + label: '期数', + component: 'Input', + componentProps: { + placeholder: '保存时自动生成', + disabled: true, + }, + }, + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + defaultValue: userStore.userInfo?.id, + rules: 'required', + }, + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + rules: 'required', + componentProps: { + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择客户', + allowClear: true, + }, + }, + { + fieldName: 'contractId', + label: '合同', + component: 'Select', + rules: 'required', + componentProps: { + options: [], + placeholder: '请选择合同', + allowClear: true, + }, + dependencies: { + triggerFields: ['customerId'], + disabled: (values) => !values.customerId, + async componentProps(values) { + if (!values.customerId) { + return { + options: [], + placeholder: '请选择客户', + }; + } + const res = await getContractSimpleList(values.customerId); + return { + options: res.map((item) => ({ + label: item.name, + value: item.id, + })), + placeholder: '请选择合同', + onChange: (value: number) => { + const contract = res.find((item) => item.id === value); + if (contract) { + values.price = + contract.totalPrice - contract.totalReceivablePrice; + } + }, + }; + }, + }, + }, + { + fieldName: 'price', + label: '计划回款金额', + component: 'InputNumber', + rules: 'required', + componentProps: { + placeholder: '请输入计划回款金额', + min: 0, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'returnTime', + label: '计划回款日期', + component: 'DatePicker', + rules: 'required', + componentProps: { + placeholder: '请选择计划回款日期', + valueFormat: 'x', + format: 'YYYY-MM-DD', + class: '!w-full', + }, + defaultValue: new Date(), + }, + { + fieldName: 'remindDays', + label: '提前几天提醒', + component: 'InputNumber', + componentProps: { + placeholder: '请输入提前几天提醒', + min: 0, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'returnType', + label: '回款方式', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE, 'number'), + placeholder: '请选择回款方式', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 4, + }, + formItemClass: 'md:col-span-2', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择客户', + allowClear: true, + }, + }, + { + fieldName: 'contractNo', + label: '合同编号', + component: 'Input', + componentProps: { + placeholder: '请输入合同编号', + allowClear: true, + }, + }, + ]; +} + +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + title: '客户名称', + field: 'customerName', + minWidth: 150, + fixed: 'left', + slots: { default: 'customerName' }, + }, + { + title: '合同编号', + field: 'contractNo', + minWidth: 200, + }, + { + title: '期数', + field: 'period', + minWidth: 150, + slots: { default: 'period' }, + }, + { + title: '计划回款金额(元)', + field: 'price', + minWidth: 160, + formatter: 'formatAmount2', + }, + { + title: '计划回款日期', + field: 'returnTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '提前几天提醒', + field: 'remindDays', + minWidth: 150, + }, + { + title: '提醒日期', + field: 'remindTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '回款方式', + field: 'returnType', + minWidth: 130, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE }, + }, + }, + { + title: '备注', + field: 'remark', + minWidth: 120, + }, + { + title: '负责人', + field: 'ownerUserName', + minWidth: 120, + }, + { + title: '实际回款金额(元)', + field: 'receivable.price', + minWidth: 160, + formatter: 'formatAmount2', + }, + { + title: '实际回款日期', + field: 'receivable.returnTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '未回款金额(元)', + field: 'unpaidPrice', + minWidth: 160, + formatter: ({ row }) => { + if (row.receivable) { + return erpPriceInputFormatter(row.price - row.receivable.price); + } + return erpPriceInputFormatter(row.price); + }, + }, + { + title: '更新时间', + field: 'updateTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '创建时间', + field: 'createTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '创建人', + field: 'creatorName', + minWidth: 100, + }, + { + title: '操作', + field: 'actions', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/receivable/plan/detail/data.ts b/apps/web-ele/src/views/crm/receivable/plan/detail/data.ts new file mode 100644 index 0000000..5059f02 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/plan/detail/data.ts @@ -0,0 +1,124 @@ +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { erpPriceInputFormatter, formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'customerName', + label: '客户名称', + }, + { + field: 'contractNo', + label: '合同编号', + }, + { + field: 'price', + label: '计划回款金额', + render: (val) => erpPriceInputFormatter(val), + }, + { + field: 'returnTime', + label: '计划回款日期', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'receivable', + label: '实际回款金额', + render: (val) => erpPriceInputFormatter(val?.price ?? 0), + }, + ]; +} + +/** 详情页的基础字段 */ +export function useDetailBaseSchema(): DescriptionItemSchema[] { + return [ + { + field: 'period', + label: '期数', + }, + { + field: 'customerName', + label: '客户名称', + }, + { + field: 'contractNo', + label: '合同编号', + }, + { + field: 'returnTime', + label: '计划回款日期', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'price', + label: '计划回款金额', + render: (val) => erpPriceInputFormatter(val), + }, + { + field: 'returnType', + label: '计划回款方式', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE, + value: val, + }), + }, + { + field: 'remindDays', + label: '提前几天提醒', + }, + { + field: 'receivable', + label: '实际回款金额', + render: (val) => erpPriceInputFormatter(val ?? 0), + }, + { + field: 'receivableRemain', + label: '未回款金额', + render: (val, data) => { + const paid = data?.receivable?.price ?? 0; + return erpPriceInputFormatter(Math.max(val - paid, 0)); + }, + }, + { + field: 'receivable.returnTime', + label: '实际回款日期', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'remark', + label: '备注', + }, + ]; +} + +/** 系统信息字段 */ +export function useDetailSystemSchema(): DescriptionItemSchema[] { + return [ + { + field: 'ownerUserName', + label: '负责人', + }, + { + field: 'creatorName', + label: '创建人', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'updateTime', + label: '更新时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/receivable/plan/detail/index.vue b/apps/web-ele/src/views/crm/receivable/plan/detail/index.vue new file mode 100644 index 0000000..0a568de --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/plan/detail/index.vue @@ -0,0 +1,135 @@ + + + diff --git a/apps/web-ele/src/views/crm/receivable/plan/detail/modules/info.vue b/apps/web-ele/src/views/crm/receivable/plan/detail/modules/info.vue new file mode 100644 index 0000000..7aa6f8d --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/plan/detail/modules/info.vue @@ -0,0 +1,35 @@ + + + diff --git a/apps/web-ele/src/views/crm/receivable/plan/index.vue b/apps/web-ele/src/views/crm/receivable/plan/index.vue new file mode 100644 index 0000000..b662692 --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/plan/index.vue @@ -0,0 +1,228 @@ + + + diff --git a/apps/web-ele/src/views/crm/receivable/plan/modules/form.vue b/apps/web-ele/src/views/crm/receivable/plan/modules/form.vue new file mode 100644 index 0000000..7b6230f --- /dev/null +++ b/apps/web-ele/src/views/crm/receivable/plan/modules/form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/crm/statistics/customer/chartOptions.ts b/apps/web-ele/src/views/crm/statistics/customer/chartOptions.ts new file mode 100644 index 0000000..3838338 --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/customer/chartOptions.ts @@ -0,0 +1,490 @@ +import { DICT_TYPE } from '@vben/constants'; +import { getDictLabel } from '@vben/hooks'; + +const getLegend = (extra: Record = {}) => ({ + top: 10, + ...extra, +}); + +const getGrid = (extra: Record = {}) => ({ + left: 20, + right: 20, + bottom: 20, + containLabel: true, + ...extra, +}); + +const getTooltip = (extra: Record = {}) => ({ + trigger: 'axis', + axisPointer: { + type: 'shadow', + }, + ...extra, +}); + +export function getChartOptions(activeTabName: any, res: any): any { + switch (activeTabName) { + // 客户转化率分析 + case 'conversionStat': { + return { + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '客户转化率', + type: 'line', + data: res.map((item: any) => { + return { + name: item.time, + value: item.customerCreateCount + ? ( + (item.customerDealCount / item.customerCreateCount) * + 100 + ).toFixed(2) + : 0, + }; + }), + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '客户转化率分析' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + yAxis: { + type: 'value', + name: '转化率(%)', + }, + xAxis: { + type: 'category', + name: '日期', + data: res.map((s: any) => s.time), + }, + }; + } + case 'customerSummary': { + return { + grid: getGrid({ + bottom: '8%', + left: '5%', + right: '5%', + top: 80, + }), + legend: getLegend(), + series: [ + { + name: '新增客户数', + type: 'bar', + yAxisIndex: 0, + data: res.map((item: any) => item.customerCreateCount), + }, + { + name: '成交客户数', + type: 'bar', + yAxisIndex: 1, + data: res.map((item: any) => item.customerDealCount), + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '客户总量分析' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + yAxis: [ + { + type: 'value', + name: '新增客户数', + min: 0, + minInterval: 1, // 显示整数刻度 + }, + { + type: 'value', + name: '成交客户数', + min: 0, + minInterval: 1, // 显示整数刻度 + splitLine: { + lineStyle: { + type: 'dotted', // 右侧网格线虚化, 减少混乱 + opacity: 0.7, + }, + }, + }, + ], + xAxis: { + type: 'category', + name: '日期', + data: res.map((item: any) => item.time), + }, + }; + } + case 'dealCycleByArea': { + const data = res.map((s: any) => { + return { + areaName: s.areaName, + customerDealCycle: s.customerDealCycle, + customerDealCount: s.customerDealCount, + }; + }); + return { + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '成交周期(天)', + type: 'bar', + data: data.map((s: any) => s.customerDealCycle), + yAxisIndex: 0, + }, + { + name: '成交客户数', + type: 'bar', + data: data.map((s: any) => s.customerDealCount), + yAxisIndex: 1, + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '成交周期分析' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + yAxis: [ + { + type: 'value', + name: '成交周期(天)', + min: 0, + minInterval: 1, // 显示整数刻度 + }, + { + type: 'value', + name: '成交客户数', + min: 0, + minInterval: 1, // 显示整数刻度 + splitLine: { + lineStyle: { + type: 'dotted', // 右侧网格线虚化, 减少混乱 + opacity: 0.7, + }, + }, + }, + ], + xAxis: { + type: 'category', + name: '区域', + data: data.map((s: any) => s.areaName), + }, + }; + } + case 'dealCycleByProduct': { + const data = res.map((s: any) => { + return { + productName: s.productName ?? '未知', + customerDealCycle: s.customerDealCount, + customerDealCount: s.customerDealCount, + }; + }); + return { + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '成交周期(天)', + type: 'bar', + data: data.map((s: any) => s.customerDealCycle), + yAxisIndex: 0, + }, + { + name: '成交客户数', + type: 'bar', + data: data.map((s: any) => s.customerDealCount), + yAxisIndex: 1, + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '成交周期分析' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + yAxis: [ + { + type: 'value', + name: '成交周期(天)', + min: 0, + minInterval: 1, // 显示整数刻度 + }, + { + type: 'value', + name: '成交客户数', + min: 0, + minInterval: 1, // 显示整数刻度 + splitLine: { + lineStyle: { + type: 'dotted', // 右侧网格线虚化, 减少混乱 + opacity: 0.7, + }, + }, + }, + ], + xAxis: { + type: 'category', + name: '产品名称', + data: data.map((s: any) => s.productName), + }, + }; + } + case 'dealCycleByUser': { + const customerDealCycleByDate = res.customerDealCycleByDate; + const customerDealCycleByUser = res.customerDealCycleByUser; + return { + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '成交周期(天)', + type: 'bar', + data: customerDealCycleByDate.map((s: any) => s.customerDealCycle), + yAxisIndex: 0, + }, + { + name: '成交客户数', + type: 'bar', + data: customerDealCycleByUser.map((s: any) => s.customerDealCount), + yAxisIndex: 1, + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '成交周期分析' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + yAxis: [ + { + type: 'value', + name: '成交周期(天)', + min: 0, + minInterval: 1, // 显示整数刻度 + }, + { + type: 'value', + name: '成交客户数', + min: 0, + minInterval: 1, // 显示整数刻度 + splitLine: { + lineStyle: { + type: 'dotted', // 右侧网格线虚化, 减少混乱 + opacity: 0.7, + }, + }, + }, + ], + xAxis: { + type: 'category', + name: '日期', + data: customerDealCycleByDate.map((s: any) => s.time), + }, + }; + } + // 客户跟进次数分析 + case 'followUpSummary': { + return { + grid: getGrid({ + right: 30, // 让 X 轴右侧显示完整 + }), + legend: getLegend(), + series: [ + { + name: '跟进客户数', + type: 'bar', + yAxisIndex: 0, + data: res.map((s: any) => s.followUpCustomerCount), + }, + { + name: '跟进次数', + type: 'bar', + yAxisIndex: 1, + data: res.map((s: any) => s.followUpRecordCount), + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '客户跟进次数分析' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + yAxis: [ + { + type: 'value', + name: '跟进客户数', + min: 0, + minInterval: 1, // 显示整数刻度 + }, + { + type: 'value', + name: '跟进次数', + min: 0, + minInterval: 1, // 显示整数刻度 + splitLine: { + lineStyle: { + type: 'dotted', // 右侧网格线虚化, 减少混乱 + opacity: 0.7, + }, + }, + }, + ], + xAxis: { + type: 'category', + name: '日期', + axisTick: { + alignWithLabel: true, + }, + data: res.map((s: any) => s.time), + }, + }; + } + // 客户跟进方式分析 + case 'followUpType': { + return { + title: { + text: '客户跟进方式分析', + left: 'center', + }, + legend: getLegend({ + left: 'left', + }), + tooltip: getTooltip({ + trigger: 'item', + axisPointer: undefined, + formatter: '{b} : {c}% ', + }), + toolbox: { + feature: { + saveAsImage: { show: true, name: '客户跟进方式分析' }, // 保存为图片 + }, + }, + series: [ + { + name: '跟进方式', + type: 'pie', + radius: '50%', + data: res.map((s: any) => { + return { + name: getDictLabel( + DICT_TYPE.CRM_FOLLOW_UP_TYPE, + s.followUpType, + ), + value: s.followUpRecordCount, + }; + }), + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)', + }, + }, + }, + ], + }; + } + case 'poolSummary': { + return { + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '进入公海客户数', + type: 'bar', + yAxisIndex: 0, + data: res.map((s: any) => s.customerPutCount), + }, + { + name: '公海领取客户数', + type: 'bar', + yAxisIndex: 1, + data: res.map((s: any) => s.customerTakeCount), + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '公海客户分析' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + yAxis: [ + { + type: 'value', + name: '进入公海客户数', + min: 0, + minInterval: 1, // 显示整数刻度 + }, + { + type: 'value', + name: '公海领取客户数', + min: 0, + minInterval: 1, // 显示整数刻度 + splitLine: { + lineStyle: { + type: 'dotted', // 右侧网格线虚化, 减少混乱 + opacity: 0.7, + }, + }, + }, + ], + xAxis: { + type: 'category', + name: '日期', + data: res.map((s: any) => s.time), + }, + }; + } + default: { + return {}; + } + } +} diff --git a/apps/web-ele/src/views/crm/statistics/customer/data.ts b/apps/web-ele/src/views/crm/statistics/customer/data.ts new file mode 100644 index 0000000..b0cd09d --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/customer/data.ts @@ -0,0 +1,401 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { useUserStore } from '@vben/stores'; +import { + beginOfDay, + endOfDay, + erpCalculatePercentage, + formatDateTime, + handleTree, +} from '@vben/utils'; + +import { getSimpleDeptList } from '#/api/system/dept'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +const userStore = useUserStore(); + +export const customerSummaryTabs = [ + { + tab: '客户总量分析', + key: 'customerSummary', + }, + { + tab: '客户跟进次数分析', + key: 'followUpSummary', + }, + { + tab: '客户跟进方式分析', + key: 'followUpType', + }, + { + tab: '客户转化率分析', + key: 'conversionStat', + }, + { + tab: '公海客户分析', + key: 'poolSummary', + }, + { + tab: '员工客户成交周期分析', + key: 'dealCycleByUser', + }, + { + tab: '地区客户成交周期分析', + key: 'dealCycleByArea', + }, + { + tab: '产品客户成交周期分析', + key: 'dealCycleByProduct', + }, +]; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'times', + label: '时间范围', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + }, + defaultValue: [ + formatDateTime(beginOfDay(new Date(Date.now() - 3600 * 1000 * 24 * 7))), + formatDateTime(endOfDay(new Date(Date.now() - 3600 * 1000 * 24))), + ], + }, + { + fieldName: 'interval', + label: '时间间隔', + component: 'Select', + componentProps: { + allowClear: true, + placeholder: '请选择时间间隔', + options: getDictOptions(DICT_TYPE.DATE_INTERVAL, 'number'), + }, + defaultValue: 2, + }, + { + fieldName: 'deptId', + label: '归属部门', + component: 'ApiTreeSelect', + componentProps: { + api: async () => { + const data = await getSimpleDeptList(); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + defaultExpandAll: true, + placeholder: '请选择归属部门', + }, + defaultValue: userStore.userInfo?.deptId, + }, + { + fieldName: 'userId', + label: '员工', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择员工', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + activeTabName: any, +): VxeTableGridOptions['columns'] { + switch (activeTabName) { + case 'conversionStat': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'customerName', + title: '客户名称', + minWidth: 100, + }, + { + field: 'contractName', + title: '合同名称', + minWidth: 200, + }, + { + field: 'totalPrice', + title: '合同总金额', + minWidth: 200, + formatter: 'formatAmount2', + }, + { + field: 'receivablePrice', + title: '回款金额', + minWidth: 200, + formatter: 'formatAmount2', + }, + { + field: 'source', + title: '客户来源', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_SOURCE }, + }, + }, + { + field: 'industryId', + title: '客户行业', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY }, + }, + }, + { + field: 'ownerUserName', + title: '负责人', + minWidth: 200, + }, + { + field: 'creatorUserName', + title: '创建人', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 200, + formatter: 'formatDateTime', + }, + { + field: 'orderDate', + title: '下单日期', + minWidth: 200, + formatter: 'formatDateTime', + }, + ]; + } + case 'customerSummary': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'ownerUserName', + title: '员工姓名', + minWidth: 100, + }, + { + field: 'customerCreateCount', + title: '新增客户数', + minWidth: 200, + }, + { + field: 'customerDealCount', + title: '成交客户数', + minWidth: 200, + }, + { + field: 'customerDealRate', + title: '客户成交率(%)', + minWidth: 200, + formatter: ({ row }) => { + return erpCalculatePercentage( + row.customerDealCount, + row.customerCreateCount, + ); + }, + }, + { + field: 'contractPrice', + title: '合同总金额', + minWidth: 200, + formatter: 'formatAmount2', + }, + { + field: 'receivablePrice', + title: '回款金额', + minWidth: 200, + formatter: 'formatAmount2', + }, + { + field: 'creceivablePrice', + title: '未回款金额', + minWidth: 200, + formatter: ({ row }) => { + return erpCalculatePercentage( + row.receivablePrice, + row.contractPrice, + ); + }, + }, + { + field: 'ccreceivablePrice', + title: '回款完成率(%)', + formatter: ({ row }) => { + return erpCalculatePercentage( + row.receivablePrice, + row.contractPrice, + ); + }, + }, + ]; + } + case 'dealCycleByArea': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'areaName', + title: '区域', + minWidth: 200, + }, + { + field: 'customerDealCycle', + title: '成交周期(天)', + minWidth: 200, + }, + { + field: 'customerDealCount', + title: '成交客户数', + minWidth: 200, + }, + ]; + } + case 'dealCycleByProduct': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'productName', + title: '产品名称', + minWidth: 200, + }, + { + field: 'customerDealCycle', + title: '成交周期(天)', + minWidth: 200, + }, + { + field: 'customerDealCount', + title: '成交客户数', + minWidth: 200, + }, + ]; + } + case 'dealCycleByUser': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'ownerUserName', + title: '日期', + minWidth: 200, + }, + { + field: 'customerDealCycle', + title: '成交周期(天)', + minWidth: 200, + }, + { + field: 'customerDealCount', + title: '成交客户数', + minWidth: 200, + }, + ]; + } + case 'followUpSummary': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'ownerUserName', + title: '员工姓名', + minWidth: 200, + }, + { + field: 'followUpRecordCount', + title: '跟进次数', + minWidth: 200, + }, + { + field: 'followUpCustomerCount', + title: '跟进客户数', + minWidth: 200, + }, + ]; + } + case 'followUpType': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'followUpType', + title: '跟进方式', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_FOLLOW_UP_TYPE }, + }, + }, + { + field: 'followUpRecordCount', + title: '个数', + minWidth: 200, + }, + { + field: 'portion', + title: '占比(%)', + minWidth: 200, + }, + ]; + } + case 'poolSummary': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'ownerUserName', + title: '员工姓名', + minWidth: 200, + }, + { + field: 'customerPutCount', + title: '进入公海客户数', + minWidth: 200, + }, + { + field: 'customerTakeCount', + title: '公海领取客户数', + minWidth: 200, + }, + ]; + } + default: { + return []; + } + } +} diff --git a/apps/web-ele/src/views/crm/statistics/customer/index.vue b/apps/web-ele/src/views/crm/statistics/customer/index.vue new file mode 100644 index 0000000..58cf1ef --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/customer/index.vue @@ -0,0 +1,98 @@ + + + diff --git a/apps/web-ele/src/views/crm/statistics/funnel/chartOptions.ts b/apps/web-ele/src/views/crm/statistics/funnel/chartOptions.ts new file mode 100644 index 0000000..e7ce475 --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/funnel/chartOptions.ts @@ -0,0 +1,279 @@ +import { erpCalculatePercentage } from '@vben/utils'; + +const getLegend = (extra: Record = {}) => ({ + top: 10, + ...extra, +}); + +const getGrid = (extra: Record = {}) => ({ + left: 20, + right: 20, + bottom: 20, + containLabel: true, + ...extra, +}); + +const getTooltip = (extra: Record = {}) => ({ + trigger: 'axis', + axisPointer: { + type: 'shadow', + }, + ...extra, +}); + +export function getChartOptions( + activeTabName: any, + active: boolean, + res: any, +): any { + switch (activeTabName) { + case 'businessInversionRateSummary': { + return { + color: ['#6ca2ff', '#6ac9d7', '#ff7474'], + tooltip: getTooltip(), + legend: getLegend({ + data: ['赢单转化率', '商机总数', '赢单商机数'], + bottom: '0px', + itemWidth: 14, + }), + grid: getGrid({ + top: '40px', + left: '40px', + right: '40px', + bottom: '40px', + borderColor: '#fff', + }), + xAxis: [ + { + type: 'category', + data: res.map((s: any) => s.time), + axisTick: { + alignWithLabel: true, + lineStyle: { width: 0 }, + }, + axisLabel: { + color: '#BDBDBD', + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { color: '#BDBDBD' }, + }, + splitLine: { + show: false, + }, + }, + ], + yAxis: [ + { + type: 'value', + name: '赢单转化率', + axisTick: { + alignWithLabel: true, + lineStyle: { width: 0 }, + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}%', + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { color: '#BDBDBD' }, + }, + splitLine: { + show: false, + }, + }, + { + type: 'value', + name: '商机数', + axisTick: { + alignWithLabel: true, + lineStyle: { width: 0 }, + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}个', + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { color: '#BDBDBD' }, + }, + splitLine: { + show: false, + }, + }, + ], + series: [ + { + name: '赢单转化率', + type: 'line', + yAxisIndex: 0, + data: res.map((s: any) => + erpCalculatePercentage(s.businessWinCount, s.businessCount), + ), + }, + { + name: '商机总数', + type: 'bar', + yAxisIndex: 1, + barWidth: 15, + data: res.map((s: any) => s.businessCount), + }, + { + name: '赢单商机数', + type: 'bar', + yAxisIndex: 1, + barWidth: 15, + data: res.map((s: any) => s.businessWinCount), + }, + ], + }; + } + case 'businessSummary': { + return { + grid: getGrid({ + left: 30, + right: 30, // 让 X 轴右侧显示完整 + }), + legend: getLegend(), + series: [ + { + name: '新增商机数量', + type: 'bar', + yAxisIndex: 0, + data: res.map((s: any) => s.businessCreateCount), + }, + { + name: '新增商机金额', + type: 'bar', + yAxisIndex: 1, + data: res.map((s: any) => s.totalPrice), + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '新增商机分析' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + yAxis: [ + { + type: 'value', + name: '新增商机数量', + min: 0, + minInterval: 1, // 显示整数刻度 + }, + { + type: 'value', + name: '新增商机金额', + min: 0, + minInterval: 1, // 显示整数刻度 + splitLine: { + lineStyle: { + type: 'dotted', // 右侧网格线虚化, 减少混乱 + opacity: 0.7, + }, + }, + }, + ], + xAxis: { + type: 'category', + name: '日期', + data: res.map((s: any) => s.time), + }, + }; + } + case 'funnel': { + // tips:写死 value 值是为了保持漏斗顺序不变 + const list: { name: string; value: number }[] = []; + if (active) { + list.push( + { value: 60, name: `客户-${res.customerCount || 0}个` }, + { value: 40, name: `商机-${res.businessCount || 0}个` }, + { value: 20, name: `赢单-${res.businessWinCount || 0}个` }, + ); + } else { + list.push( + { + value: res.customerCount || 0, + name: `客户-${res.customerCount || 0}个`, + }, + { + value: res.businessCount || 0, + name: `商机-${res.businessCount || 0}个`, + }, + { + value: res.businessWinCount || 0, + name: `赢单-${res.businessWinCount || 0}个`, + }, + ); + } + return { + title: { + text: '销售漏斗', + }, + tooltip: getTooltip({ + trigger: 'item', + axisPointer: undefined, + formatter: '{a}
    {b}', + }), + toolbox: { + feature: { + dataView: { readOnly: false }, + restore: {}, + saveAsImage: {}, + }, + }, + legend: getLegend({ + data: ['客户', '商机', '赢单'], + }), + series: [ + { + name: '销售漏斗', + type: 'funnel', + left: '10%', + top: 60, + bottom: 60, + width: '80%', + min: 0, + max: 100, + minSize: '0%', + maxSize: '100%', + sort: 'descending', + gap: 2, + label: { + show: true, + position: 'inside', + }, + labelLine: { + length: 10, + lineStyle: { + width: 1, + type: 'solid', + }, + }, + itemStyle: { + borderColor: '#fff', + borderWidth: 1, + }, + emphasis: { + label: { + fontSize: 20, + }, + }, + data: list, + }, + ], + }; + } + default: { + return {}; + } + } +} diff --git a/apps/web-ele/src/views/crm/statistics/funnel/data.ts b/apps/web-ele/src/views/crm/statistics/funnel/data.ts new file mode 100644 index 0000000..76ee951 --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/funnel/data.ts @@ -0,0 +1,271 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { useUserStore } from '@vben/stores'; +import { beginOfDay, endOfDay, formatDateTime, handleTree } from '@vben/utils'; + +import { getSimpleDeptList } from '#/api/system/dept'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +const userStore = useUserStore(); + +export const customerSummaryTabs = [ + { + tab: '销售漏斗分析', + key: 'funnel', + }, + { + tab: '新增商机分析', + key: 'businessSummary', + }, + { + tab: '商机转化率分析', + key: 'businessInversionRateSummary', + }, +]; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'times', + label: '时间范围', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + }, + defaultValue: [ + formatDateTime(beginOfDay(new Date(Date.now() - 3600 * 1000 * 24 * 7))), + formatDateTime(endOfDay(new Date(Date.now() - 3600 * 1000 * 24))), + ], + }, + { + fieldName: 'interval', + label: '时间间隔', + component: 'Select', + componentProps: { + allowClear: true, + placeholder: '请选择时间间隔', + options: getDictOptions(DICT_TYPE.DATE_INTERVAL, 'number'), + }, + defaultValue: 2, + }, + { + fieldName: 'deptId', + label: '归属部门', + component: 'ApiTreeSelect', + componentProps: { + api: async () => { + const data = await getSimpleDeptList(); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + defaultExpandAll: true, + placeholder: '请选择归属部门', + }, + defaultValue: userStore.userInfo?.deptId, + }, + { + fieldName: 'userId', + label: '员工', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + allowClear: true, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择员工', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + activeTabName: any, +): VxeTableGridOptions['columns'] { + switch (activeTabName) { + case 'businessInversionRateSummary': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'name', + title: '商机名称', + minWidth: 100, + }, + { + field: 'customerName', + title: '客户名称', + minWidth: 200, + }, + { + field: 'totalPrice', + title: '商机金额(元)', + minWidth: 200, + formatter: 'formatAmount2', + }, + { + field: 'dealTime', + title: '预计成交日期', + minWidth: 200, + formatter: 'formatDateTime', + }, + { + field: 'ownerUserName', + title: '负责人', + minWidth: 200, + }, + { + field: 'ownerUserDeptName', + title: '所属部门', + minWidth: 200, + }, + { + field: 'contactLastTime', + title: '最后跟进时间', + minWidth: 200, + formatter: 'formatDateTime', + }, + { + field: 'updateTime', + title: '更新时间', + minWidth: 200, + formatter: 'formatDateTime', + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 200, + formatter: 'formatDateTime', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 100, + }, + { + field: 'statusTypeName', + title: '商机状态组', + minWidth: 100, + }, + { + field: 'statusName', + title: '商机阶段', + minWidth: 100, + }, + ]; + } + case 'businessSummary': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'name', + title: '商机名称', + minWidth: 100, + }, + { + field: 'customerName', + title: '客户名称', + minWidth: 200, + }, + { + field: 'totalPrice', + title: '商机金额(元)', + minWidth: 200, + formatter: 'formatAmount2', + }, + { + field: 'dealTime', + title: '预计成交日期', + minWidth: 200, + formatter: 'formatDateTime', + }, + { + field: 'ownerUserName', + title: '负责人', + minWidth: 200, + }, + { + field: 'ownerUserDeptName', + title: '所属部门', + minWidth: 200, + }, + { + field: 'contactLastTime', + title: '最后跟进时间', + minWidth: 200, + formatter: 'formatDateTime', + }, + { + field: 'updateTime', + title: '更新时间', + minWidth: 200, + formatter: 'formatDateTime', + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 200, + formatter: 'formatDateTime', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 100, + }, + { + field: 'statusTypeName', + title: '商机状态组', + minWidth: 100, + }, + { + field: 'statusName', + title: '商机阶段', + minWidth: 100, + }, + ]; + } + case 'funnel': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'endStatus', + title: '阶段', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_BUSINESS_END_STATUS_TYPE }, + }, + }, + { + field: 'businessCount', + title: '商机数', + minWidth: 200, + }, + { + field: 'totalPrice', + title: '商机总金额(元)', + minWidth: 200, + formatter: 'formatAmount2', + }, + ]; + } + default: { + return []; + } + } +} diff --git a/apps/web-ele/src/views/crm/statistics/funnel/index.vue b/apps/web-ele/src/views/crm/statistics/funnel/index.vue new file mode 100644 index 0000000..7c11afd --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/funnel/index.vue @@ -0,0 +1,144 @@ + + + diff --git a/apps/web-ele/src/views/crm/statistics/performance/chartOptions.ts b/apps/web-ele/src/views/crm/statistics/performance/chartOptions.ts new file mode 100644 index 0000000..073c625 --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/performance/chartOptions.ts @@ -0,0 +1,395 @@ +const getLegend = (extra: Record = {}) => ({ + top: 10, + ...extra, +}); + +const getGrid = (extra: Record = {}) => ({ + left: 20, + right: 20, + bottom: 20, + containLabel: true, + ...extra, +}); + +const getTooltip = (extra: Record = {}) => ({ + trigger: 'axis', + axisPointer: { + type: 'shadow', + }, + ...extra, +}); + +export function getChartOptions(activeTabName: any, res: any): any { + switch (activeTabName) { + case 'ContractCountPerformance': { + return { + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '当月合同数量(个)', + type: 'line', + data: res.map((s: any) => s.currentMonthCount), + }, + { + name: '上月合同数量(个)', + type: 'line', + data: res.map((s: any) => s.lastMonthCount), + }, + { + name: '去年同月合同数量(个)', + type: 'line', + data: res.map((s: any) => s.lastYearCount), + }, + { + name: '环比增长率(%)', + type: 'line', + yAxisIndex: 1, + data: res.map((s: any) => + s.lastMonthCount === 0 + ? 'NULL' + : ( + ((s.currentMonthCount - s.lastMonthCount) / + s.lastMonthCount) * + 100 + ).toFixed(2), + ), + }, + { + name: '同比增长率(%)', + type: 'line', + yAxisIndex: 1, + data: res.map((s: any) => + s.lastYearCount === 0 + ? 'NULL' + : ( + ((s.currentMonthCount - s.lastYearCount) / + s.lastYearCount) * + 100 + ).toFixed(2), + ), + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '客户总量分析' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + yAxis: [ + { + type: 'value', + name: '数量(个)', + axisTick: { + show: false, + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}', + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { + color: '#BDBDBD', + }, + }, + splitLine: { + show: true, + lineStyle: { + color: '#e6e6e6', + }, + }, + }, + { + type: 'value', + name: '', + axisTick: { + alignWithLabel: true, + lineStyle: { + width: 0, + }, + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}%', + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { + color: '#BDBDBD', + }, + }, + splitLine: { + show: true, + lineStyle: { + color: '#e6e6e6', + }, + }, + }, + ], + xAxis: { + type: 'category', + name: '日期', + data: res.map((s: any) => s.time), + }, + }; + } + case 'ContractPricePerformance': { + return { + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '当月合同金额(元)', + type: 'line', + data: res.map((s: any) => s.currentMonthCount), + }, + { + name: '上月合同金额(元)', + type: 'line', + data: res.map((s: any) => s.lastMonthCount), + }, + { + name: '去年同月合同金额(元)', + type: 'line', + data: res.map((s: any) => s.lastYearCount), + }, + { + name: '环比增长率(%)', + type: 'line', + yAxisIndex: 1, + data: res.map((s: any) => + s.lastMonthCount === 0 + ? 'NULL' + : ( + ((s.currentMonthCount - s.lastMonthCount) / + s.lastMonthCount) * + 100 + ).toFixed(2), + ), + }, + { + name: '同比增长率(%)', + type: 'line', + yAxisIndex: 1, + data: res.map((s: any) => + s.lastYearCount === 0 + ? 'NULL' + : ( + ((s.currentMonthCount - s.lastYearCount) / + s.lastYearCount) * + 100 + ).toFixed(2), + ), + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '客户总量分析' }, // 保存为图片 + }, + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow', + }, + }, + yAxis: [ + { + type: 'value', + name: '金额(元)', + axisTick: { + show: false, + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}', + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { + color: '#BDBDBD', + }, + }, + splitLine: { + show: true, + lineStyle: { + color: '#e6e6e6', + }, + }, + }, + { + type: 'value', + name: '', + axisTick: { + alignWithLabel: true, + lineStyle: { + width: 0, + }, + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}%', + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { + color: '#BDBDBD', + }, + }, + splitLine: { + show: true, + lineStyle: { + color: '#e6e6e6', + }, + }, + }, + ], + xAxis: { + type: 'category', + name: '日期', + data: res.map((s: any) => s.time), + }, + }; + } + case 'ReceivablePricePerformance': { + return { + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '当月回款金额(元)', + type: 'line', + data: res.map((s: any) => s.currentMonthCount), + }, + { + name: '上月回款金额(元)', + type: 'line', + data: res.map((s: any) => s.lastMonthCount), + }, + { + name: '去年同月回款金额(元)', + type: 'line', + data: res.map((s: any) => s.lastYearCount), + }, + { + name: '环比增长率(%)', + type: 'line', + yAxisIndex: 1, + data: res.map((s: any) => + s.lastMonthCount === 0 + ? 'NULL' + : ( + ((s.currentMonthCount - s.lastMonthCount) / + s.lastMonthCount) * + 100 + ).toFixed(2), + ), + }, + { + name: '同比增长率(%)', + type: 'line', + yAxisIndex: 1, + data: res.map((s: any) => + s.lastYearCount === 0 + ? 'NULL' + : ( + ((s.currentMonthCount - s.lastYearCount) / + s.lastYearCount) * + 100 + ).toFixed(2), + ), + }, + ], + toolbox: { + feature: { + dataZoom: { + xAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '客户总量分析' }, // 保存为图片 + }, + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow', + }, + }, + yAxis: [ + { + type: 'value', + name: '金额(元)', + axisTick: { + show: false, + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}', + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { + color: '#BDBDBD', + }, + }, + splitLine: { + show: true, + lineStyle: { + color: '#e6e6e6', + }, + }, + }, + { + type: 'value', + name: '', + axisTick: { + alignWithLabel: true, + lineStyle: { + width: 0, + }, + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}%', + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { + color: '#BDBDBD', + }, + }, + splitLine: { + show: true, + lineStyle: { + color: '#e6e6e6', + }, + }, + }, + ], + xAxis: { + type: 'category', + name: '日期', + data: res.map((s: any) => s.time), + }, + }; + } + default: { + return {}; + } + } +} diff --git a/apps/web-ele/src/views/crm/statistics/performance/data.ts b/apps/web-ele/src/views/crm/statistics/performance/data.ts new file mode 100644 index 0000000..41a964c --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/performance/data.ts @@ -0,0 +1,71 @@ +import type { VbenFormSchema } from '#/adapter/form'; + +import { useUserStore } from '@vben/stores'; +import { handleTree } from '@vben/utils'; + +import { getSimpleDeptList } from '#/api/system/dept'; +import { getSimpleUserList } from '#/api/system/user'; + +const userStore = useUserStore(); + +export const customerSummaryTabs = [ + { + tab: '员工合同数量统计', + key: 'ContractCountPerformance', + }, + { + tab: '员工合同金额统计', + key: 'ContractPricePerformance', + }, + { + tab: '员工回款金额统计', + key: 'ReceivablePricePerformance', + }, +]; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'time', + label: '选择年份', + component: 'DatePicker', + componentProps: { + type: 'year', + format: 'YYYY', + valueFormat: 'YYYY', + placeholder: '请选择年份', + }, + defaultValue: new Date().getFullYear().toString(), + }, + { + fieldName: 'deptId', + label: '归属部门', + component: 'ApiTreeSelect', + componentProps: { + api: async () => { + const data = await getSimpleDeptList(); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + defaultExpandAll: true, + placeholder: '请选择归属部门', + }, + defaultValue: userStore.userInfo?.deptId, + }, + { + fieldName: 'userId', + label: '员工', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择员工', + allowClear: true, + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/statistics/performance/index.vue b/apps/web-ele/src/views/crm/statistics/performance/index.vue new file mode 100644 index 0000000..8271ed7 --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/performance/index.vue @@ -0,0 +1,186 @@ + + + diff --git a/apps/web-ele/src/views/crm/statistics/portrait/chartOptions.ts b/apps/web-ele/src/views/crm/statistics/portrait/chartOptions.ts new file mode 100644 index 0000000..7088c22 --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/portrait/chartOptions.ts @@ -0,0 +1,241 @@ +import { DICT_TYPE } from '@vben/constants'; +import { getDictLabel } from '@vben/hooks'; + +function areaReplace(areaName: string) { + if (!areaName) { + return areaName; + } + return areaName + .replace('维吾尔自治区', '') + .replace('壮族自治区', '') + .replace('回族自治区', '') + .replace('自治区', '') + .replace('省', ''); +} + +const getPieTooltip = (extra: Record = {}) => ({ + trigger: 'item', + ...extra, +}); + +const getPieLegend = (extra: Record = {}) => ({ + orient: 'vertical', + left: 'left', + ...extra, +}); + +const getPieSeries = (name: string, data: any[]) => ({ + name, + type: 'pie', + radius: ['40%', '70%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: 10, + borderColor: '#fff', + borderWidth: 2, + }, + label: { + show: false, + position: 'center', + }, + emphasis: { + label: { + show: true, + fontSize: 40, + fontWeight: 'bold', + }, + }, + labelLine: { + show: false, + }, + data, +}); + +const getPiePanel = ({ + data, + legendExtra, + seriesName, + title, + tooltipExtra, +}: { + data: any[]; + legendExtra?: Record; + seriesName: string; + title: string; + tooltipExtra?: Record; +}) => ({ + title: { + text: title, + left: 'center', + }, + tooltip: getPieTooltip(tooltipExtra), + legend: getPieLegend(legendExtra), + toolbox: { + feature: { + saveAsImage: { show: true, name: title }, + }, + }, + series: [getPieSeries(seriesName, data)], +}); + +export function getChartOptions(activeTabName: any, res: any): any { + switch (activeTabName) { + case 'area': { + const data = res.map((item: any) => { + return { + ...item, + areaName: areaReplace(item.areaName), + }; + }); + let leftMin = 0; + let leftMax = 0; + let rightMin = 0; + let rightMax = 0; + data.forEach((item: any) => { + leftMin = Math.min(leftMin, item.customerCount || 0); + leftMax = Math.max(leftMax, item.customerCount || 0); + rightMin = Math.min(rightMin, item.dealCount || 0); + rightMax = Math.max(rightMax, item.dealCount || 0); + }); + return { + left: { + title: { + text: '全部客户', + left: 'center', + }, + tooltip: { + trigger: 'item', + showDelay: 0, + transitionDuration: 0.2, + }, + visualMap: { + text: ['高', '低'], + realtime: false, + calculable: true, + top: 'middle', + inRange: { + color: ['yellow', 'lightskyblue', 'orangered'], + }, + min: leftMin, + max: leftMax, + }, + series: [ + { + name: '客户地域分布', + type: 'map', + map: 'china', + roam: false, + selectedMode: false, + data: data.map((item: any) => { + return { + name: item.areaName, + value: item.customerCount || 0, + }; + }), + }, + ], + }, + right: { + title: { + text: '成交客户', + left: 'center', + }, + tooltip: { + trigger: 'item', + showDelay: 0, + transitionDuration: 0.2, + }, + visualMap: { + text: ['高', '低'], + realtime: false, + calculable: true, + top: 'middle', + inRange: { + color: ['yellow', 'lightskyblue', 'orangered'], + }, + min: rightMin, + max: rightMax, + }, + series: [ + { + name: '客户地域分布', + type: 'map', + map: 'china', + roam: false, + selectedMode: false, + data: data.map((item: any) => { + return { + name: item.areaName, + value: item.dealCount || 0, + }; + }), + }, + ], + }, + }; + } + case 'industry': { + return { + left: getPiePanel({ + title: '全部客户', + seriesName: '全部客户', + data: res.map((r: any) => ({ + name: getDictLabel(DICT_TYPE.CRM_CUSTOMER_INDUSTRY, r.industryId), + value: r.customerCount, + })), + }), + right: getPiePanel({ + title: '成交客户', + seriesName: '成交客户', + data: res.map((r: any) => ({ + name: getDictLabel(DICT_TYPE.CRM_CUSTOMER_INDUSTRY, r.industryId), + value: r.dealCount, + })), + }), + }; + } + case 'level': { + return { + left: getPiePanel({ + title: '全部客户', + seriesName: '全部客户', + data: res.map((r: any) => ({ + name: getDictLabel(DICT_TYPE.CRM_CUSTOMER_LEVEL, r.level), + value: r.customerCount, + })), + }), + right: getPiePanel({ + title: '成交客户', + seriesName: '成交客户', + data: res.map((r: any) => ({ + name: getDictLabel(DICT_TYPE.CRM_CUSTOMER_LEVEL, r.level), + value: r.dealCount, + })), + }), + }; + } + case 'source': { + return { + left: getPiePanel({ + title: '全部客户', + seriesName: '全部客户', + data: res.map((r: any) => ({ + name: getDictLabel(DICT_TYPE.CRM_CUSTOMER_SOURCE, r.source), + value: r.customerCount, + })), + }), + right: getPiePanel({ + title: '成交客户', + seriesName: '成交客户', + data: res.map((r: any) => ({ + name: getDictLabel(DICT_TYPE.CRM_CUSTOMER_SOURCE, r.source), + value: r.dealCount, + })), + }), + }; + } + default: { + return {}; + } + } +} diff --git a/apps/web-ele/src/views/crm/statistics/portrait/data.ts b/apps/web-ele/src/views/crm/statistics/portrait/data.ts new file mode 100644 index 0000000..e471da3 --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/portrait/data.ts @@ -0,0 +1,200 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { useUserStore } from '@vben/stores'; +import { beginOfDay, endOfDay, formatDateTime, handleTree } from '@vben/utils'; + +import { getSimpleDeptList } from '#/api/system/dept'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +const userStore = useUserStore(); + +export const customerSummaryTabs = [ + { + tab: '城市分布分析', + key: 'area', + }, + { + tab: '客户级别分析', + key: 'level', + }, + { + tab: '客户来源分析', + key: 'source', + }, + { + tab: '客户行业分析', + key: 'industry', + }, +]; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'times', + label: '时间范围', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + }, + defaultValue: [ + formatDateTime(beginOfDay(new Date(Date.now() - 3600 * 1000 * 24 * 7))), + formatDateTime(endOfDay(new Date(Date.now() - 3600 * 1000 * 24))), + ], + }, + { + fieldName: 'deptId', + label: '归属部门', + component: 'ApiTreeSelect', + componentProps: { + api: async () => { + const data = await getSimpleDeptList(); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + defaultExpandAll: true, + placeholder: '请选择归属部门', + }, + defaultValue: userStore.userInfo?.deptId, + }, + { + fieldName: 'userId', + label: '员工', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择员工', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + activeTabName: any, +): VxeTableGridOptions['columns'] { + switch (activeTabName) { + case 'industry': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'industryId', + title: '客户行业', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY }, + }, + }, + { + field: 'customerCount', + title: '客户个数', + minWidth: 200, + }, + { + field: 'dealCount', + title: '成交个数', + minWidth: 200, + }, + { + field: 'industryPortion', + title: '行业占比(%)', + minWidth: 200, + }, + { + field: 'dealPortion', + title: '成交占比(%)', + minWidth: 200, + }, + ]; + } + case 'level': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'level', + title: '客户级别', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_LEVEL }, + }, + }, + { + field: 'customerCount', + title: '客户个数', + minWidth: 200, + }, + { + field: 'dealCount', + title: '成交个数', + minWidth: 200, + }, + { + field: 'industryPortion', + title: '行业占比(%)', + minWidth: 200, + }, + { + field: 'dealPortion', + title: '成交占比(%)', + minWidth: 200, + }, + ]; + } + case 'source': { + return [ + { + type: 'seq', + title: '序号', + }, + { + field: 'source', + title: '客户来源', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_SOURCE }, + }, + }, + { + field: 'customerCount', + title: '客户个数', + minWidth: 200, + }, + { + field: 'dealCount', + title: '成交个数', + minWidth: 200, + }, + { + field: 'industryPortion', + title: '行业占比(%)', + minWidth: 200, + }, + { + field: 'dealPortion', + title: '成交占比(%)', + minWidth: 200, + }, + ]; + } + default: { + return []; + } + } +} diff --git a/apps/web-ele/src/views/crm/statistics/portrait/index.vue b/apps/web-ele/src/views/crm/statistics/portrait/index.vue new file mode 100644 index 0000000..5eed968 --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/portrait/index.vue @@ -0,0 +1,103 @@ + + + diff --git a/apps/web-ele/src/views/crm/statistics/rank/chartOptions.ts b/apps/web-ele/src/views/crm/statistics/rank/chartOptions.ts new file mode 100644 index 0000000..aceffbc --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/rank/chartOptions.ts @@ -0,0 +1,346 @@ +import { cloneDeep } from '@vben/utils'; + +const getLegend = (extra: Record = {}) => ({ + top: 10, + ...extra, +}); + +const getGrid = (extra: Record = {}) => ({ + left: 20, + right: 20, + bottom: 20, + containLabel: true, + ...extra, +}); + +const getTooltip = () => ({ + trigger: 'axis', + axisPointer: { + type: 'shadow', + }, +}); + +export function getChartOptions(activeTabName: any, res: any): any { + switch (activeTabName) { + case 'contactCountRank': { + return { + dataset: { + dimensions: ['nickname', 'count'], + source: cloneDeep(res).toReversed(), + }, + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '新增联系人数排行', + type: 'bar', + }, + ], + toolbox: { + feature: { + dataZoom: { + yAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '新增联系人数排行' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + xAxis: { + type: 'value', + name: '新增联系人数(个)', + }, + yAxis: { + type: 'category', + name: '创建人', + }, + }; + } + case 'contractCountRank': { + return { + dataset: { + dimensions: ['nickname', 'count'], + source: cloneDeep(res).toReversed(), + }, + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '签约合同排行', + type: 'bar', + }, + ], + toolbox: { + feature: { + dataZoom: { + yAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '签约合同排行' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + xAxis: { + type: 'value', + name: '签约合同数(个)', + }, + yAxis: { + type: 'category', + name: '签订人', + }, + }; + } + case 'contractPriceRank': { + return { + dataset: { + dimensions: ['nickname', 'count'], + source: cloneDeep(res).toReversed(), + }, + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '合同金额排行', + type: 'bar', + }, + ], + toolbox: { + feature: { + dataZoom: { + yAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '合同金额排行' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + xAxis: { + type: 'value', + name: '合同金额(元)', + }, + yAxis: { + type: 'category', + name: '签订人', + }, + }; + } + case 'customerCountRank': { + return { + dataset: { + dimensions: ['nickname', 'count'], + source: cloneDeep(res).toReversed(), + }, + grid: getGrid(), + legend: getLegend(), + series: [ + { + name: '新增客户数排行', + type: 'bar', + }, + ], + toolbox: { + feature: { + dataZoom: { + yAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '新增客户数排行' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + xAxis: { + type: 'value', + name: '新增客户数(个)', + }, + yAxis: { + type: 'category', + name: '创建人', + }, + }; + } + case 'followCountRank': { + return { + dataset: { + dimensions: ['nickname', 'count'], + source: cloneDeep(res).toReversed(), + }, + grid: { + left: 20, + right: 20, + bottom: 20, + containLabel: true, + }, + legend: { + top: 50, + }, + series: [ + { + name: '跟进次数排行', + type: 'bar', + }, + ], + toolbox: { + feature: { + dataZoom: { + yAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '跟进次数排行' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + xAxis: { + type: 'value', + name: '跟进次数(次)', + }, + yAxis: { + type: 'category', + name: '员工', + }, + }; + } + case 'followCustomerCountRank': { + return { + dataset: { + dimensions: ['nickname', 'count'], + source: cloneDeep(res).toReversed(), + }, + grid: { + left: 20, + right: 20, + bottom: 20, + containLabel: true, + }, + legend: { + top: 50, + }, + series: [ + { + name: '跟进客户数排行', + type: 'bar', + }, + ], + toolbox: { + feature: { + dataZoom: { + yAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '跟进客户数排行' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + xAxis: { + type: 'value', + name: '跟进客户数(个)', + }, + yAxis: { + type: 'category', + name: '员工', + }, + }; + } + case 'productSalesRank': { + return { + dataset: { + dimensions: ['nickname', 'count'], + source: cloneDeep(res).toReversed(), + }, + grid: { + left: 20, + right: 20, + bottom: 20, + containLabel: true, + }, + legend: { + top: 50, + }, + series: [ + { + name: '产品销量排行', + type: 'bar', + }, + ], + toolbox: { + feature: { + dataZoom: { + yAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '产品销量排行' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + xAxis: { + type: 'value', + name: '产品销量', + }, + yAxis: { + type: 'category', + name: '员工', + }, + }; + } + case 'receivablePriceRank': { + return { + dataset: { + dimensions: ['nickname', 'count'], + source: cloneDeep(res).toReversed(), + }, + grid: { + left: 20, + right: 20, + bottom: 20, + containLabel: true, + }, + legend: { + top: 50, + }, + series: [ + { + name: '回款金额排行', + type: 'bar', + }, + ], + toolbox: { + feature: { + dataZoom: { + yAxisIndex: false, // 数据区域缩放:Y 轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { show: true, name: '回款金额排行' }, // 保存为图片 + }, + }, + tooltip: getTooltip(), + xAxis: { + type: 'value', + name: '回款金额(元)', + }, + yAxis: { + type: 'category', + name: '签订人', + nameGap: 30, + }, + }; + } + default: { + return {}; + } + } +} diff --git a/apps/web-ele/src/views/crm/statistics/rank/data.ts b/apps/web-ele/src/views/crm/statistics/rank/data.ts new file mode 100644 index 0000000..1a52d2a --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/rank/data.ts @@ -0,0 +1,277 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { useUserStore } from '@vben/stores'; +import { beginOfDay, endOfDay, formatDateTime, handleTree } from '@vben/utils'; + +import { getSimpleDeptList } from '#/api/system/dept'; +import { getRangePickerDefaultProps } from '#/utils'; + +const userStore = useUserStore(); + +export const customerSummaryTabs = [ + { + tab: '合同金额排行', + key: 'contractPriceRank', + }, + { + tab: '回款金额排行', + key: 'receivablePriceRank', + }, + { + tab: '签约合同排行', + key: 'contractCountRank', + }, + { + tab: '产品销量排行', + key: 'productSalesRank', + }, + { + tab: '新增客户数排行', + key: 'customerCountRank', + }, + { + tab: '新增联系人数排行', + key: 'contactCountRank', + }, + { + tab: '跟进次数排行', + key: 'followCountRank', + }, + { + tab: '跟进客户数排行', + key: 'followCustomerCountRank', + }, +]; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'times', + label: '时间范围', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + }, + defaultValue: [ + formatDateTime(beginOfDay(new Date(Date.now() - 3600 * 1000 * 24 * 7))), + formatDateTime(endOfDay(new Date(Date.now() - 3600 * 1000 * 24))), + ], + }, + { + fieldName: 'deptId', + label: '归属部门', + component: 'ApiTreeSelect', + componentProps: { + api: async () => { + const data = await getSimpleDeptList(); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + defaultExpandAll: true, + placeholder: '请选择归属部门', + }, + defaultValue: userStore.userInfo?.deptId, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + activeTabName: any, +): VxeTableGridOptions['columns'] { + switch (activeTabName) { + case 'contactCountRank': { + return [ + { + type: 'seq', + title: '公司排名', + }, + { + field: 'nickname', + title: '创建人', + minWidth: 200, + }, + { + field: 'deptName', + title: '部门', + minWidth: 200, + }, + { + field: 'count', + title: '新增联系人数(个)', + minWidth: 200, + }, + ]; + } + case 'contractCountRank': { + return [ + { + type: 'seq', + title: '公司排名', + }, + { + field: 'nickname', + title: '签订人', + minWidth: 200, + }, + { + field: 'deptName', + title: '部门', + minWidth: 200, + }, + { + field: 'count', + title: '签约合同数(个)', + minWidth: 200, + }, + ]; + } + case 'contractPriceRank': { + return [ + { + type: 'seq', + title: '公司排名', + }, + { + field: 'nickname', + title: '签订人', + minWidth: 200, + }, + { + field: 'deptName', + title: '部门', + minWidth: 200, + }, + { + field: 'count', + title: '合同金额(元)', + minWidth: 200, + formatter: 'formatAmount2', + }, + ]; + } + case 'customerCountRank': { + return [ + { + type: 'seq', + title: '公司排名', + }, + { + field: 'nickname', + title: '签订人', + minWidth: 200, + }, + { + field: 'deptName', + title: '部门', + minWidth: 200, + }, + { + field: 'count', + title: '新增客户数(个)', + minWidth: 200, + }, + ]; + } + case 'followCountRank': { + return [ + { + type: 'seq', + title: '公司排名', + }, + { + field: 'nickname', + title: '签订人', + minWidth: 200, + }, + { + field: 'deptName', + title: '部门', + minWidth: 200, + }, + { + field: 'count', + title: '跟进次数(次)', + minWidth: 200, + }, + ]; + } + case 'followCustomerCountRank': { + return [ + { + type: 'seq', + title: '公司排名', + }, + { + field: 'nickname', + title: '签订人', + minWidth: 200, + }, + { + field: 'deptName', + title: '部门', + minWidth: 200, + }, + { + field: 'count', + title: '跟进客户数(个)', + minWidth: 200, + }, + ]; + } + case 'productSalesRank': { + return [ + { + type: 'seq', + title: '公司排名', + }, + { + field: 'nickname', + title: '签订人', + minWidth: 200, + }, + { + field: 'deptName', + title: '部门', + minWidth: 200, + }, + { + field: 'count', + title: '产品销量', + minWidth: 200, + }, + ]; + } + case 'receivablePriceRank': { + return [ + { + type: 'seq', + title: '公司排名', + }, + { + field: 'nickname', + title: '签订人', + minWidth: 200, + }, + { + field: 'deptName', + title: '部门', + minWidth: 200, + }, + { + field: 'count', + title: '回款金额(元)', + minWidth: 200, + formatter: 'formatAmount2', + }, + ]; + } + default: { + return []; + } + } +} diff --git a/apps/web-ele/src/views/crm/statistics/rank/index.vue b/apps/web-ele/src/views/crm/statistics/rank/index.vue new file mode 100644 index 0000000..8253b2b --- /dev/null +++ b/apps/web-ele/src/views/crm/statistics/rank/index.vue @@ -0,0 +1,107 @@ + + + diff --git a/apps/web-ele/src/views/dashboard/analytics/analytics-trends.vue b/apps/web-ele/src/views/dashboard/analytics/analytics-trends.vue new file mode 100644 index 0000000..f1f0b23 --- /dev/null +++ b/apps/web-ele/src/views/dashboard/analytics/analytics-trends.vue @@ -0,0 +1,98 @@ + + + diff --git a/apps/web-ele/src/views/dashboard/analytics/analytics-visits-data.vue b/apps/web-ele/src/views/dashboard/analytics/analytics-visits-data.vue new file mode 100644 index 0000000..190fb41 --- /dev/null +++ b/apps/web-ele/src/views/dashboard/analytics/analytics-visits-data.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/dashboard/analytics/analytics-visits-sales.vue b/apps/web-ele/src/views/dashboard/analytics/analytics-visits-sales.vue new file mode 100644 index 0000000..6ff5208 --- /dev/null +++ b/apps/web-ele/src/views/dashboard/analytics/analytics-visits-sales.vue @@ -0,0 +1,46 @@ + + + diff --git a/apps/web-ele/src/views/dashboard/analytics/analytics-visits-source.vue b/apps/web-ele/src/views/dashboard/analytics/analytics-visits-source.vue new file mode 100644 index 0000000..0915c7a --- /dev/null +++ b/apps/web-ele/src/views/dashboard/analytics/analytics-visits-source.vue @@ -0,0 +1,65 @@ + + + diff --git a/apps/web-ele/src/views/dashboard/analytics/analytics-visits.vue b/apps/web-ele/src/views/dashboard/analytics/analytics-visits.vue new file mode 100644 index 0000000..7e0f101 --- /dev/null +++ b/apps/web-ele/src/views/dashboard/analytics/analytics-visits.vue @@ -0,0 +1,55 @@ + + + diff --git a/apps/web-ele/src/views/dashboard/analytics/index.vue b/apps/web-ele/src/views/dashboard/analytics/index.vue new file mode 100644 index 0000000..5e3d6d2 --- /dev/null +++ b/apps/web-ele/src/views/dashboard/analytics/index.vue @@ -0,0 +1,90 @@ + + + diff --git a/apps/web-ele/src/views/dashboard/workspace/index.vue b/apps/web-ele/src/views/dashboard/workspace/index.vue new file mode 100644 index 0000000..4e15e7d --- /dev/null +++ b/apps/web-ele/src/views/dashboard/workspace/index.vue @@ -0,0 +1,260 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/account/data.ts b/apps/web-ele/src/views/erp/finance/account/data.ts new file mode 100644 index 0000000..497d4e3 --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/account/data.ts @@ -0,0 +1,188 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { ErpAccountApi } from '#/api/erp/finance/account'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '名称', + rules: 'required', + componentProps: { + placeholder: '请输入名称', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + + { + fieldName: 'sort', + label: '排序', + component: 'InputNumber', + componentProps: { + placeholder: '请输入排序', + precision: 0, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + defaultValue: 0, + }, + { + fieldName: 'defaultStatus', + label: '是否默认', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '是', + value: true, + }, + { + label: '否', + value: false, + }, + ], + }, + rules: z.boolean().default(false).optional(), + }, + { + fieldName: 'no', + label: '编码', + component: 'Input', + componentProps: { + placeholder: '请输入编码', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 3, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名称', + component: 'Input', + componentProps: { + placeholder: '请输入名称', + allowClear: true, + }, + }, + { + fieldName: 'no', + label: '编码', + component: 'Input', + componentProps: { + placeholder: '请输入编码', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onDefaultStatusChange?: ( + newStatus: boolean, + row: ErpAccountApi.Account, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '名称', + minWidth: 150, + }, + { + field: 'no', + title: '编码', + minWidth: 120, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + showOverflow: 'tooltip', + }, + { + field: 'sort', + title: '排序', + minWidth: 80, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'defaultStatus', + title: '是否默认', + minWidth: 100, + cellRender: { + attrs: { beforeChange: onDefaultStatusChange }, + name: 'CellSwitch', + props: { + activeValue: true, + inactiveValue: false, + }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/finance/account/index.vue b/apps/web-ele/src/views/erp/finance/account/index.vue new file mode 100644 index 0000000..1f54939 --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/account/index.vue @@ -0,0 +1,175 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/account/modules/form.vue b/apps/web-ele/src/views/erp/finance/account/modules/form.vue new file mode 100644 index 0000000..eced899 --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/account/modules/form.vue @@ -0,0 +1,86 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/payment/data.ts b/apps/web-ele/src/views/erp/finance/payment/data.ts new file mode 100644 index 0000000..1161721 --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/payment/data.ts @@ -0,0 +1,592 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpPriceInputFormatter } from '@vben/utils'; + +import { getAccountSimpleList } from '#/api/erp/finance/account'; +import { getSupplierSimpleList } from '#/api/erp/purchase/supplier'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '付款单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'paymentTime', + label: '付款时间', + component: 'DatePicker', + componentProps: { + disabled: formType === 'detail', + placeholder: '选择付款时间', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'ApiSelect', + componentProps: { + disabled: formType === 'detail', + placeholder: '请选择供应商', + clearable: true, + filterable: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'financeUserId', + label: '财务人员', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择财务人员', + clearable: true, + filterable: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autosize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '采购入库、退货单', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + fieldName: 'accountId', + label: '付款账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择付款账户', + clearable: true, + filterable: true, + api: getAccountSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'totalPrice', + label: '合计付款', + component: 'InputNumber', + componentProps: { + placeholder: '合计付款', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'discountPrice', + label: '优惠金额', + component: 'InputNumber', + componentProps: { + disabled: formType === 'detail', + placeholder: '请输入优惠金额', + precision: 2, + formatter: erpPriceInputFormatter, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'paymentPrice', + label: '实际付款', + component: 'InputNumber', + componentProps: { + placeholder: '实际付款', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['totalPrice', 'discountPrice'], + componentProps: (values) => { + const totalPrice = values.totalPrice || 0; + const discountPrice = values.discountPrice || 0; + values.paymentPrice = totalPrice - discountPrice; + return {}; + }, + }, + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + disabled: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'bizNo', + title: '采购单据编号', + minWidth: 200, + }, + { + field: 'totalPrice', + title: '应付金额', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'paidPrice', + title: '已付金额', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'paymentPrice', + title: '本次付款', + minWidth: 115, + fixed: 'right', + slots: { default: 'paymentPrice' }, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '付款单号', + component: 'Input', + componentProps: { + placeholder: '请输入付款单号', + clearable: true, + }, + }, + { + fieldName: 'paymentTime', + label: '付款时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择供应商', + clearable: true, + filterable: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + clearable: true, + filterable: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'financeUserId', + label: '财务人员', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择财务人员', + clearable: true, + filterable: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'accountId', + label: '付款账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择付款账户', + clearable: true, + filterable: true, + api: getAccountSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择状态', + clearable: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + clearable: true, + }, + }, + { + fieldName: 'bizNo', + label: '采购单号', + component: 'Input', + componentProps: { + placeholder: '请输入采购单号', + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '付款单号', + width: 180, + fixed: 'left', + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'paymentTime', + title: '付款时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'financeUserName', + title: '财务人员', + minWidth: 120, + }, + { + field: 'accountName', + title: '付款账户', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '合计付款', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'discountPrice', + title: '优惠金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'paymentPrice', + title: '实际付款', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 90, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 采购入库单选择表单的配置项 */ +export function usePurchaseInGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '入库单号', + component: 'Input', + componentProps: { + placeholder: '请输入入库单号', + clearable: true, + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'Input', + componentProps: { + disabled: true, + placeholder: '已自动选择供应商', + }, + }, + { + fieldName: 'paymentStatus', + label: '付款状态', + component: 'Select', + componentProps: { + options: [ + { label: '未付款', value: 0 }, + { label: '部分付款', value: 1 }, + { label: '全部付款', value: 2 }, + ], + placeholder: '请选择付款状态', + clearable: true, + }, + }, + ]; +} + +/** 采购入库单选择列表的字段 */ +export function usePurchaseInGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '入库单号', + width: 200, + fixed: 'left', + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'inTime', + title: '入库时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'totalPrice', + title: '应付金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'paymentPrice', + title: '已付金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'unPaymentPrice', + title: '未付金额', + formatter: ({ row }) => { + return erpPriceInputFormatter(row.totalPrice - row.paymentPrice || 0); + }, + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + ]; +} + +/** 采购退货单选择表单的配置项 */ +export function useSaleReturnGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '退货单号', + component: 'Input', + componentProps: { + placeholder: '请输入退货单号', + clearable: true, + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'Input', + componentProps: { + disabled: true, + placeholder: '已自动选择供应商', + }, + }, + { + fieldName: 'refundStatus', + label: '退款状态', + component: 'Select', + componentProps: { + options: [ + { label: '未退款', value: 0 }, + { label: '部分退款', value: 1 }, + { label: '全部退款', value: 2 }, + ], + placeholder: '请选择退款状态', + clearable: true, + }, + }, + ]; +} + +/** 采购退货单选择列表的字段 */ +export function useSaleReturnGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '退货单号', + width: 200, + fixed: 'left', + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'returnTime', + title: '退货时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'totalPrice', + title: '应退金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'refundPrice', + title: '已退金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'unRefundPrice', + title: '未退金额', + formatter: ({ row }) => { + return erpPriceInputFormatter(row.totalPrice - row.refundPrice || 0); + }, + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/finance/payment/index.vue b/apps/web-ele/src/views/erp/finance/payment/index.vue new file mode 100644 index 0000000..5c6750b --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/payment/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/payment/modules/form.vue b/apps/web-ele/src/views/erp/finance/payment/modules/form.vue new file mode 100644 index 0000000..fe8796e --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/payment/modules/form.vue @@ -0,0 +1,195 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/payment/modules/item-form.vue b/apps/web-ele/src/views/erp/finance/payment/modules/item-form.vue new file mode 100644 index 0000000..54fd089 --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/payment/modules/item-form.vue @@ -0,0 +1,302 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/payment/modules/purchase-in-select.vue b/apps/web-ele/src/views/erp/finance/payment/modules/purchase-in-select.vue new file mode 100644 index 0000000..8169157 --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/payment/modules/purchase-in-select.vue @@ -0,0 +1,113 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/payment/modules/sale-return-select.vue b/apps/web-ele/src/views/erp/finance/payment/modules/sale-return-select.vue new file mode 100644 index 0000000..ec57fd5 --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/payment/modules/sale-return-select.vue @@ -0,0 +1,117 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/receipt/data.ts b/apps/web-ele/src/views/erp/finance/receipt/data.ts new file mode 100644 index 0000000..19e463c --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/receipt/data.ts @@ -0,0 +1,592 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpPriceInputFormatter } from '@vben/utils'; + +import { getAccountSimpleList } from '#/api/erp/finance/account'; +import { getCustomerSimpleList } from '#/api/erp/sale/customer'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '收款单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'receiptTime', + label: '收款时间', + component: 'DatePicker', + componentProps: { + disabled: formType === 'detail', + placeholder: '选择收款时间', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + disabled: formType === 'detail', + placeholder: '请选择客户', + allowClear: true, + showSearch: true, + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'financeUserId', + label: '财务人员', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择财务人员', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '销售出库、退货单', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + fieldName: 'accountId', + label: '收款账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择收款账户', + allowClear: true, + showSearch: true, + api: getAccountSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'totalPrice', + label: '合计收款', + component: 'InputNumber', + componentProps: { + placeholder: '合计收款', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'discountPrice', + label: '优惠金额', + component: 'InputNumber', + componentProps: { + disabled: formType === 'detail', + placeholder: '请输入优惠金额', + precision: 2, + formatter: erpPriceInputFormatter, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'receiptPrice', + label: '实际收款', + component: 'InputNumber', + componentProps: { + placeholder: '实际收款', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['totalPrice', 'discountPrice'], + componentProps: (values) => { + const totalPrice = values.totalPrice || 0; + const discountPrice = values.discountPrice || 0; + values.receiptPrice = totalPrice - discountPrice; + return {}; + }, + }, + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + disabled: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'bizNo', + title: '销售单据编号', + minWidth: 200, + }, + { + field: 'totalPrice', + title: '应收金额', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'receiptedPrice', + title: '已收金额', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'receiptPrice', + title: '本次收款', + minWidth: 115, + fixed: 'right', + slots: { default: 'receiptPrice' }, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '收款单号', + component: 'Input', + componentProps: { + placeholder: '请输入收款单号', + allowClear: true, + }, + }, + { + fieldName: 'receiptTime', + label: '收款时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择客户', + allowClear: true, + showSearch: true, + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'financeUserId', + label: '财务人员', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择财务人员', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'accountId', + label: '收款账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择收款账户', + allowClear: true, + showSearch: true, + api: getAccountSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + { + fieldName: 'bizNo', + label: '销售单号', + component: 'Input', + componentProps: { + placeholder: '请输入销售单号', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '收款单号', + width: 180, + fixed: 'left', + }, + { + field: 'customerName', + title: '客户', + minWidth: 120, + }, + { + field: 'receiptTime', + title: '收款时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'financeUserName', + title: '财务人员', + minWidth: 120, + }, + { + field: 'accountName', + title: '收款账户', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '合计收款', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'discountPrice', + title: '优惠金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'receiptPrice', + title: '实际收款', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 90, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 销售出库单选择表单的配置项 */ +export function useSaleOutGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '出库单号', + component: 'Input', + componentProps: { + placeholder: '请输入出库单号', + allowClear: true, + }, + }, + { + fieldName: 'customerId', + label: '客户', + component: 'Input', + componentProps: { + disabled: true, + placeholder: '已自动选择客户', + }, + }, + { + fieldName: 'receiptStatus', + label: '收款状态', + component: 'Select', + componentProps: { + options: [ + { label: '未收款', value: 0 }, + { label: '部分收款', value: 1 }, + { label: '全部收款', value: 2 }, + ], + placeholder: '请选择收款状态', + allowClear: true, + }, + }, + ]; +} + +/** 销售出库单选择列表的字段 */ +export function useSaleOutGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '出库单号', + width: 200, + fixed: 'left', + }, + { + field: 'customerName', + title: '客户', + minWidth: 120, + }, + { + field: 'outTime', + title: '出库时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'totalPrice', + title: '应收金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'receiptPrice', + title: '已收金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'unReceiptPrice', + title: '未收金额', + formatter: ({ row }) => { + return erpPriceInputFormatter(row.totalPrice - row.receiptPrice || 0); + }, + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + ]; +} + +/** 销售退货单选择表单的配置项 */ +export function useSaleReturnGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '退货单号', + component: 'Input', + componentProps: { + placeholder: '请输入退货单号', + allowClear: true, + }, + }, + { + fieldName: 'customerId', + label: '客户', + component: 'Input', + componentProps: { + disabled: true, + placeholder: '已自动选择客户', + }, + }, + { + fieldName: 'refundStatus', + label: '退款状态', + component: 'Select', + componentProps: { + options: [ + { label: '未退款', value: 0 }, + { label: '部分退款', value: 1 }, + { label: '全部退款', value: 2 }, + ], + placeholder: '请选择退款状态', + allowClear: true, + }, + }, + ]; +} + +/** 销售退货单选择列表的字段 */ +export function useSaleReturnGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '退货单号', + width: 200, + fixed: 'left', + }, + { + field: 'customerName', + title: '客户', + minWidth: 120, + }, + { + field: 'returnTime', + title: '退货时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'totalPrice', + title: '应退金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'refundPrice', + title: '已退金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'unRefundPrice', + title: '未退金额', + formatter: ({ row }) => { + return erpPriceInputFormatter(row.totalPrice - row.refundPrice || 0); + }, + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/finance/receipt/index.vue b/apps/web-ele/src/views/erp/finance/receipt/index.vue new file mode 100644 index 0000000..53a84ee --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/receipt/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/receipt/modules/form.vue b/apps/web-ele/src/views/erp/finance/receipt/modules/form.vue new file mode 100644 index 0000000..8464cce --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/receipt/modules/form.vue @@ -0,0 +1,209 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/receipt/modules/item-form.vue b/apps/web-ele/src/views/erp/finance/receipt/modules/item-form.vue new file mode 100644 index 0000000..be746db --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/receipt/modules/item-form.vue @@ -0,0 +1,299 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/receipt/modules/sale-out-select.vue b/apps/web-ele/src/views/erp/finance/receipt/modules/sale-out-select.vue new file mode 100644 index 0000000..b5d2def --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/receipt/modules/sale-out-select.vue @@ -0,0 +1,110 @@ + + + diff --git a/apps/web-ele/src/views/erp/finance/receipt/modules/sale-return-select.vue b/apps/web-ele/src/views/erp/finance/receipt/modules/sale-return-select.vue new file mode 100644 index 0000000..8bef717 --- /dev/null +++ b/apps/web-ele/src/views/erp/finance/receipt/modules/sale-return-select.vue @@ -0,0 +1,114 @@ + + + diff --git a/apps/web-ele/src/views/erp/home/index.vue b/apps/web-ele/src/views/erp/home/index.vue new file mode 100644 index 0000000..9f6f2ea --- /dev/null +++ b/apps/web-ele/src/views/erp/home/index.vue @@ -0,0 +1,51 @@ + + + diff --git a/apps/web-ele/src/views/erp/home/modules/summary-card.vue b/apps/web-ele/src/views/erp/home/modules/summary-card.vue new file mode 100644 index 0000000..ff98e55 --- /dev/null +++ b/apps/web-ele/src/views/erp/home/modules/summary-card.vue @@ -0,0 +1,69 @@ + + + diff --git a/apps/web-ele/src/views/erp/home/modules/time-summary-chart.vue b/apps/web-ele/src/views/erp/home/modules/time-summary-chart.vue new file mode 100644 index 0000000..fe164eb --- /dev/null +++ b/apps/web-ele/src/views/erp/home/modules/time-summary-chart.vue @@ -0,0 +1,161 @@ + + + diff --git a/apps/web-ele/src/views/erp/product/category/data.ts b/apps/web-ele/src/views/erp/product/category/data.ts new file mode 100644 index 0000000..4256e52 --- /dev/null +++ b/apps/web-ele/src/views/erp/product/category/data.ts @@ -0,0 +1,149 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { ErpProductCategoryApi } from '#/api/erp/product/category'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { handleTree } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getProductCategoryList } from '#/api/erp/product/category'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'parentId', + label: '上级分类', + component: 'ApiTreeSelect', + componentProps: { + allowClear: true, + api: async () => { + const data = await getProductCategoryList(); + data.unshift({ + id: 0, + name: '顶级分类', + }); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择上级分类', + defaultExpandAll: true, + }, + rules: 'selectRequired', + }, + { + fieldName: 'name', + label: '分类名称', + component: 'Input', + componentProps: { + placeholder: '请输入分类名称', + }, + rules: 'required', + }, + { + fieldName: 'code', + label: '分类编码', + component: 'Input', + componentProps: { + placeholder: '请输入分类编码', + }, + rules: 'required', + }, + { + fieldName: 'sort', + label: '显示顺序', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入显示顺序', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 查询表单 */ +export function useQueryFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'name', + label: '分类名称', + componentProps: { + placeholder: '请输入分类名称', + allowClear: true, + }, + }, + { + component: 'Select', + fieldName: 'status', + label: '开启状态', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择开启状态', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '分类名称', + align: 'left', + treeNode: true, + }, + { + field: 'code', + title: '分类编码', + }, + { + field: 'sort', + title: '显示顺序', + }, + { + field: 'status', + title: '分类状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/product/category/index.vue b/apps/web-ele/src/views/erp/product/category/index.vue new file mode 100644 index 0000000..19c20d3 --- /dev/null +++ b/apps/web-ele/src/views/erp/product/category/index.vue @@ -0,0 +1,183 @@ + + + diff --git a/apps/web-ele/src/views/erp/product/category/modules/form.vue b/apps/web-ele/src/views/erp/product/category/modules/form.vue new file mode 100644 index 0000000..981feb5 --- /dev/null +++ b/apps/web-ele/src/views/erp/product/category/modules/form.vue @@ -0,0 +1,91 @@ + + + diff --git a/apps/web-ele/src/views/erp/product/product/data.ts b/apps/web-ele/src/views/erp/product/product/data.ts new file mode 100644 index 0000000..80bb961 --- /dev/null +++ b/apps/web-ele/src/views/erp/product/product/data.ts @@ -0,0 +1,258 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { handleTree } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getProductCategorySimpleList } from '#/api/erp/product/category'; +import { getProductUnitSimpleList } from '#/api/erp/product/unit'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '名称', + rules: 'required', + componentProps: { + placeholder: '请输入名称', + }, + }, + { + fieldName: 'barCode', + label: '条码', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入条码', + }, + }, + { + fieldName: 'categoryId', + label: '分类', + component: 'ApiTreeSelect', + componentProps: { + api: async () => { + const data = await getProductCategorySimpleList(); + return handleTree(data); + }, + + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择分类', + defaultExpandAll: true, + }, + rules: 'required', + }, + { + fieldName: 'unitId', + label: '单位', + component: 'ApiSelect', + componentProps: { + api: getProductUnitSimpleList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择单位', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'standard', + label: '规格', + component: 'Input', + componentProps: { + placeholder: '请输入规格', + }, + }, + { + fieldName: 'expiryDay', + label: '保质期天数', + component: 'InputNumber', + componentProps: { + placeholder: '请输入保质期天数', + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'weight', + label: '重量(kg)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入重量(kg)', + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'purchasePrice', + label: '采购价格', + component: 'InputNumber', + componentProps: { + placeholder: '请输入采购价格,单位:元', + precision: 2, + min: 0, + step: 0.01, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'salePrice', + label: '销售价格', + component: 'InputNumber', + componentProps: { + placeholder: '请输入销售价格,单位:元', + precision: 2, + min: 0, + step: 0.01, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'minPrice', + label: '最低价格', + component: 'InputNumber', + componentProps: { + placeholder: '请输入最低价格,单位:元', + precision: 2, + min: 0, + step: 0.01, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名称', + component: 'Input', + componentProps: { + placeholder: '请输入名称', + allowClear: true, + }, + }, + { + fieldName: 'categoryId', + label: '分类', + component: 'ApiTreeSelect', + componentProps: { + api: async () => { + const data = await getProductCategorySimpleList(); + return handleTree(data); + }, + + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择分类', + defaultExpandAll: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'barCode', + title: '条码', + minWidth: 120, + }, + { + field: 'name', + title: '名称', + minWidth: 200, + }, + { + field: 'standard', + title: '规格', + minWidth: 100, + }, + { + field: 'categoryName', + title: '分类', + minWidth: 120, + }, + { + field: 'unitName', + title: '单位', + minWidth: 100, + }, + { + field: 'purchasePrice', + title: '采购价格', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'salePrice', + title: '销售价格', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'minPrice', + title: '最低价格', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/product/product/index.vue b/apps/web-ele/src/views/erp/product/product/index.vue new file mode 100644 index 0000000..f6bce71 --- /dev/null +++ b/apps/web-ele/src/views/erp/product/product/index.vue @@ -0,0 +1,150 @@ + + + diff --git a/apps/web-ele/src/views/erp/product/product/modules/form.vue b/apps/web-ele/src/views/erp/product/product/modules/form.vue new file mode 100644 index 0000000..baed5a7 --- /dev/null +++ b/apps/web-ele/src/views/erp/product/product/modules/form.vue @@ -0,0 +1,85 @@ + + + diff --git a/apps/web-ele/src/views/erp/product/unit/data.ts b/apps/web-ele/src/views/erp/product/unit/data.ts new file mode 100644 index 0000000..0914528 --- /dev/null +++ b/apps/web-ele/src/views/erp/product/unit/data.ts @@ -0,0 +1,101 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '单位名称', + rules: 'required', + componentProps: { + placeholder: '请输入单位名称', + }, + }, + { + fieldName: 'status', + label: '单位状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '单位名称', + component: 'Input', + componentProps: { + placeholder: '请输入单位名称', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '单位状态', + component: 'Select', + componentProps: { + placeholder: '请选择单位状态', + allowClear: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '单位编号', + minWidth: 100, + }, + { + field: 'name', + title: '单位名称', + minWidth: 200, + }, + { + field: 'status', + title: '单位状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/product/unit/index.vue b/apps/web-ele/src/views/erp/product/unit/index.vue new file mode 100644 index 0000000..1997240 --- /dev/null +++ b/apps/web-ele/src/views/erp/product/unit/index.vue @@ -0,0 +1,149 @@ + + + diff --git a/apps/web-ele/src/views/erp/product/unit/modules/form.vue b/apps/web-ele/src/views/erp/product/unit/modules/form.vue new file mode 100644 index 0000000..70b3a98 --- /dev/null +++ b/apps/web-ele/src/views/erp/product/unit/modules/form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/in/data.ts b/apps/web-ele/src/views/erp/purchase/in/data.ts new file mode 100644 index 0000000..4b4233c --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/in/data.ts @@ -0,0 +1,624 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpNumberFormatter, erpPriceInputFormatter } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getAccountSimpleList } from '#/api/erp/finance/account'; +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getSupplierSimpleList } from '#/api/erp/purchase/supplier'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '入库单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'inTime', + label: '入库时间', + component: 'DatePicker', + componentProps: { + disabled: formType === 'detail', + placeholder: '选择入库时间', + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'orderNo', + label: '关联订单', + component: 'Input', + formItemClass: 'col-span-1', + rules: 'required', + componentProps: { + placeholder: '请选择关联订单', + disabled: formType === 'detail', + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'ApiSelect', + componentProps: { + disabled: true, + placeholder: '请选择供应商', + allowClear: true, + showSearch: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '入库产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + fieldName: 'discountPercent', + label: '优惠率(%)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入优惠率', + min: 0, + max: 100, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional(), + }, + { + fieldName: 'discountPrice', + label: '付款优惠', + component: 'InputNumber', + componentProps: { + placeholder: '付款优惠', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'discountedPrice', + label: '优惠后金额', + component: 'InputNumber', + componentProps: { + placeholder: '优惠后金额', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['totalPrice', 'otherPrice'], + componentProps: (values) => { + const totalPrice = values.totalPrice || 0; + const otherPrice = values.otherPrice || 0; + values.discountedPrice = totalPrice - otherPrice; + return {}; + }, + }, + }, + { + fieldName: 'otherPrice', + label: '其他费用', + component: 'InputNumber', + componentProps: { + disabled: formType === 'detail', + placeholder: '请输入其他费用', + precision: 2, + formatter: erpPriceInputFormatter, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'accountId', + label: '结算账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择结算账户', + allowClear: true, + showSearch: true, + api: getAccountSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'totalPrice', + label: '应付金额', + component: 'InputNumber', + componentProps: { + precision: 2, + min: 0, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional(), + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + formData?: any[], + disabled?: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'warehouseId', + title: '仓库名称', + minWidth: 200, + slots: { default: 'warehouseId' }, + }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '库存', + minWidth: 80, + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + field: 'totalCount', + title: '原数量', + formatter: 'formatAmount3', + minWidth: 120, + fixed: 'right', + visible: formData && formData[0]?.inCount !== undefined, + }, + { + field: 'inCount', + title: '已入库', + formatter: 'formatAmount3', + minWidth: 120, + fixed: 'right', + visible: formData && formData[0]?.returnCount !== undefined, + }, + { + field: 'count', + title: '数量', + minWidth: 120, + fixed: 'right', + slots: { default: 'count' }, + }, + { + field: 'productPrice', + title: '产品单价', + fixed: 'right', + minWidth: 120, + slots: { default: 'productPrice' }, + }, + { + field: 'totalProductPrice', + fixed: 'right', + title: '产品金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + fixed: 'right', + field: 'taxPercent', + title: '税率(%)', + minWidth: 105, + slots: { default: 'taxPercent' }, + }, + { + fixed: 'right', + field: 'taxPrice', + title: '税额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'totalPrice', + fixed: 'right', + title: '合计金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '入库单号', + component: 'Input', + componentProps: { + placeholder: '请输入入库单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'inTime', + label: '入库时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择供应商', + allowClear: true, + showSearch: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'orderNo', + label: '关联订单', + component: 'Input', + componentProps: { + placeholder: '请输入关联订单号', + allowClear: true, + }, + }, + { + fieldName: 'accountId', + label: '结算账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择结算账户', + allowClear: true, + showSearch: true, + api: getAccountSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'paymentStatus', + label: '付款状态', + component: 'Select', + componentProps: { + options: [ + { label: '未付款', value: 0 }, + { label: '部分付款', value: 1 }, + { label: '全部付款', value: 2 }, + ], + placeholder: '请选择付款状态', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '审批状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择审批状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '入库单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'inTime', + title: '入库时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '应付金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'paymentPrice', + title: '已付金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'unPaymentPrice', + title: '未付金额', + formatter: ({ row }) => { + return `${erpNumberFormatter(row.totalPrice - row.paymentPrice, 2)}元`; + }, + minWidth: 120, + }, + { + field: 'status', + title: '审批状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useOrderGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '订单单号', + component: 'Input', + componentProps: { + placeholder: '请输入订单单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'orderTime', + label: '订单时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useOrderGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'radio', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '订单单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'orderTime', + title: '订单时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'inCount', + title: '入库数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalProductPrice', + title: '金额合计', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '含税金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/purchase/in/index.vue b/apps/web-ele/src/views/erp/purchase/in/index.vue new file mode 100644 index 0000000..2b5c1cb --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/in/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/in/modules/form.vue b/apps/web-ele/src/views/erp/purchase/in/modules/form.vue new file mode 100644 index 0000000..21cfadf --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/in/modules/form.vue @@ -0,0 +1,231 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/in/modules/item-form.vue b/apps/web-ele/src/views/erp/purchase/in/modules/item-form.vue new file mode 100644 index 0000000..6ec8a50 --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/in/modules/item-form.vue @@ -0,0 +1,310 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/in/modules/purchase-order-select.vue b/apps/web-ele/src/views/erp/purchase/in/modules/purchase-order-select.vue new file mode 100644 index 0000000..0f1815f --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/in/modules/purchase-order-select.vue @@ -0,0 +1,124 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/order/data.ts b/apps/web-ele/src/views/erp/purchase/order/data.ts new file mode 100644 index 0000000..489af22 --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/order/data.ts @@ -0,0 +1,454 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpPriceInputFormatter } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getAccountSimpleList } from '#/api/erp/finance/account'; +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getSupplierSimpleList } from '#/api/erp/purchase/supplier'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '订单单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'orderTime', + label: '订单时间', + component: 'DatePicker', + componentProps: { + placeholder: '选择订单时间', + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + label: '供应商', + fieldName: 'supplierId', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择供应商', + allowClear: true, + showSearch: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '采购产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + fieldName: 'discountPercent', + label: '优惠率(%)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入优惠率', + min: 0, + max: 100, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional(), + }, + { + fieldName: 'discountPrice', + label: '付款优惠', + component: 'InputNumber', + componentProps: { + placeholder: '付款优惠', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'totalPrice', + label: '优惠后金额', + component: 'InputNumber', + componentProps: { + placeholder: '优惠后金额', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'accountId', + label: '结算账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择结算账户', + allowClear: true, + showSearch: true, + api: getAccountSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + component: 'InputNumber', + componentProps: { + placeholder: '请输入支付订金', + precision: 2, + min: 0, + controlsPosition: 'right', + class: '!w-full', + }, + fieldName: 'depositPrice', + label: '支付订金', + rules: z.number().min(0).optional(), + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + disabled: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '库存', + minWidth: 80, + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + field: 'count', + title: '数量', + minWidth: 120, + fixed: 'right', + slots: { default: 'count' }, + }, + { + field: 'productPrice', + title: '产品单价', + minWidth: 120, + fixed: 'right', + slots: { default: 'productPrice' }, + }, + { + field: 'totalProductPrice', + title: '金额', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount2', + }, + { + field: 'taxPercent', + title: '税率(%)', + minWidth: 105, + fixed: 'right', + slots: { default: 'taxPercent' }, + }, + { + field: 'taxPrice', + title: '税额', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount2', + }, + { + field: 'totalPrice', + title: '税额合计', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '订单单号', + component: 'Input', + componentProps: { + placeholder: '请输入订单单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'orderTime', + label: '订单时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择供应商', + allowClear: true, + showSearch: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + { + fieldName: 'inStatus', + label: '入库状态', + component: 'Select', + componentProps: { + options: [ + { label: '未入库', value: 0 }, + { label: '部分入库', value: 1 }, + { label: '全部入库', value: 2 }, + ], + placeholder: '请选择入库状态', + allowClear: true, + }, + }, + { + fieldName: 'returnStatus', + label: '退货状态', + component: 'Select', + componentProps: { + options: [ + { label: '未退货', value: 0 }, + { label: '部分退货', value: 1 }, + { label: '全部退货', value: 2 }, + ], + placeholder: '请选择退货状态', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '订单单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'orderTime', + title: '订单时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'inCount', + title: '入库数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'returnCount', + title: '退货数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalProductPrice', + title: '金额合计', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '含税金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'depositPrice', + title: '支付订金', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/purchase/order/index.vue b/apps/web-ele/src/views/erp/purchase/order/index.vue new file mode 100644 index 0000000..024e3c2 --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/order/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/order/modules/form.vue b/apps/web-ele/src/views/erp/purchase/order/modules/form.vue new file mode 100644 index 0000000..03e9129 --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/order/modules/form.vue @@ -0,0 +1,172 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/order/modules/item-form.vue b/apps/web-ele/src/views/erp/purchase/order/modules/item-form.vue new file mode 100644 index 0000000..0d32f3a --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/order/modules/item-form.vue @@ -0,0 +1,329 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/return/data.ts b/apps/web-ele/src/views/erp/purchase/return/data.ts new file mode 100644 index 0000000..6a26869 --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/return/data.ts @@ -0,0 +1,617 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpNumberFormatter, erpPriceInputFormatter } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getAccountSimpleList } from '#/api/erp/finance/account'; +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getSupplierSimpleList } from '#/api/erp/purchase/supplier'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '退货单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'returnTime', + label: '退货时间', + component: 'DatePicker', + componentProps: { + disabled: formType === 'detail', + placeholder: '选择退货时间', + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'orderNo', + label: '关联订单', + component: 'Input', + formItemClass: 'col-span-1', + rules: 'required', + componentProps: { + placeholder: '请选择关联订单', + disabled: formType === 'detail', + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'ApiSelect', + componentProps: { + disabled: true, + placeholder: '请选择供应商', + allowClear: true, + showSearch: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '退货产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + fieldName: 'discountPercent', + label: '优惠率(%)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入优惠率', + min: 0, + max: 100, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional(), + }, + { + fieldName: 'discountPrice', + label: '退款优惠', + component: 'InputNumber', + componentProps: { + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'discountedPrice', + label: '优惠后金额', + component: 'InputNumber', + componentProps: { + placeholder: '优惠后金额', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['totalPrice', 'otherPrice'], + componentProps: (values) => { + const totalPrice = values.totalPrice || 0; + const otherPrice = values.otherPrice || 0; + values.discountedPrice = totalPrice - otherPrice; + return {}; + }, + }, + }, + { + fieldName: 'otherPrice', + label: '其他费用', + component: 'InputNumber', + componentProps: { + disabled: formType === 'detail', + placeholder: '请输入其他费用', + precision: 2, + formatter: erpPriceInputFormatter, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'accountId', + label: '结算账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择结算账户', + allowClear: true, + showSearch: true, + api: getAccountSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'totalPrice', + label: '应退金额', + component: 'InputNumber', + componentProps: { + precision: 2, + min: 0, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional(), + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + formData?: any[], + disabled?: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'warehouseId', + title: '仓库名称', + minWidth: 200, + slots: { default: 'warehouseId' }, + }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '库存', + minWidth: 80, + formatter: 'formatAmount3', + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + field: 'inCount', + title: '已入库', + formatter: 'formatAmount3', + minWidth: 120, + fixed: 'right', + visible: formData && formData[0]?.inCount !== undefined, + }, + { + field: 'returnCount', + title: '已退货', + formatter: 'formatAmount3', + minWidth: 120, + fixed: 'right', + visible: formData && formData[0]?.returnCount !== undefined, + }, + { + field: 'count', + title: '数量', + minWidth: 120, + fixed: 'right', + slots: { default: 'count' }, + }, + { + field: 'productPrice', + title: '产品单价', + fixed: 'right', + minWidth: 120, + slots: { default: 'productPrice' }, + }, + { + field: 'totalProductPrice', + fixed: 'right', + title: '产品金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + fixed: 'right', + field: 'taxPercent', + title: '税率(%)', + minWidth: 105, + slots: { default: 'taxPercent' }, + }, + { + fixed: 'right', + field: 'taxPrice', + title: '税额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'totalPrice', + fixed: 'right', + title: '合计金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '退货单号', + component: 'Input', + componentProps: { + placeholder: '请输入退货单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'returnTime', + label: '退货时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择供应商', + allowClear: true, + showSearch: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'orderNo', + label: '关联订单', + component: 'Input', + componentProps: { + placeholder: '请输入关联订单号', + allowClear: true, + }, + }, + { + fieldName: 'refundStatus', + label: '退款状态', + component: 'Select', + componentProps: { + options: [ + { label: '未退款', value: 0 }, + { label: '部分退款', value: 1 }, + { label: '全部退款', value: 2 }, + ], + placeholder: '请选择退款状态', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '审批状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择审批状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '退货单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '退货产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'returnTime', + title: '退货时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '应退金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'refundPrice', + title: '已退金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'unRefundPrice', + title: '未退金额', + formatter: ({ row }) => { + return `${erpNumberFormatter(row.totalPrice - row.refundPrice, 2)}元`; + }, + minWidth: 120, + }, + { + field: 'status', + title: '审批状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useOrderGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '订单单号', + component: 'Input', + componentProps: { + placeholder: '请输入订单单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'orderTime', + label: '订单时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useOrderGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'radio', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '订单单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'orderTime', + title: '订单时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'inCount', + title: '已入库数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'returnCount', + title: '已退货数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalProductPrice', + title: '金额合计', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '含税金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/purchase/return/index.vue b/apps/web-ele/src/views/erp/purchase/return/index.vue new file mode 100644 index 0000000..91c9cfb --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/return/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/return/modules/form.vue b/apps/web-ele/src/views/erp/purchase/return/modules/form.vue new file mode 100644 index 0000000..f496ae0 --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/return/modules/form.vue @@ -0,0 +1,231 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/return/modules/item-form.vue b/apps/web-ele/src/views/erp/purchase/return/modules/item-form.vue new file mode 100644 index 0000000..93e24ed --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/return/modules/item-form.vue @@ -0,0 +1,312 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/return/modules/purchase-order-select.vue b/apps/web-ele/src/views/erp/purchase/return/modules/purchase-order-select.vue new file mode 100644 index 0000000..8b6ae10 --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/return/modules/purchase-order-select.vue @@ -0,0 +1,124 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/supplier/data.ts b/apps/web-ele/src/views/erp/purchase/supplier/data.ts new file mode 100644 index 0000000..d433c09 --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/supplier/data.ts @@ -0,0 +1,234 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '供应商名称', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入供应商名称', + }, + }, + { + fieldName: 'contact', + label: '联系人', + component: 'Input', + componentProps: { + placeholder: '请输入联系人', + }, + }, + { + fieldName: 'mobile', + label: '手机号码', + component: 'Input', + componentProps: { + placeholder: '请输入手机号码', + }, + }, + { + fieldName: 'telephone', + label: '联系电话', + component: 'Input', + componentProps: { + placeholder: '请输入联系电话', + }, + }, + { + fieldName: 'email', + label: '电子邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入电子邮箱', + }, + }, + { + fieldName: 'fax', + label: '传真', + component: 'Input', + componentProps: { + placeholder: '请输入传真', + }, + }, + { + fieldName: 'status', + label: '开启状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'sort', + label: '排序', + component: 'InputNumber', + componentProps: { + placeholder: '请输入排序', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'taxNo', + label: '纳税人识别号', + component: 'Input', + componentProps: { + placeholder: '请输入纳税人识别号', + }, + }, + { + fieldName: 'taxPercent', + label: '税率(%)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入税率', + min: 0, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'bankName', + label: '开户行', + component: 'Input', + componentProps: { + placeholder: '请输入开户行', + }, + }, + { + fieldName: 'bankAccount', + label: '开户账号', + component: 'Input', + componentProps: { + placeholder: '请输入开户账号', + }, + }, + { + fieldName: 'bankAddress', + label: '开户地址', + component: 'Input', + componentProps: { + placeholder: '请输入开户地址', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 3, + }, + formItemClass: 'col-span-2', + }, + ]; +} + +/** 搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '供应商名称', + component: 'Input', + componentProps: { + placeholder: '请输入供应商名称', + allowClear: true, + }, + }, + { + fieldName: 'mobile', + label: '手机号码', + component: 'Input', + componentProps: { + placeholder: '请输入手机号码', + allowClear: true, + }, + }, + { + fieldName: 'telephone', + label: '联系电话', + component: 'Input', + componentProps: { + placeholder: '请输入联系电话', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '供应商名称', + minWidth: 150, + }, + { + field: 'contact', + title: '联系人', + minWidth: 120, + }, + { + field: 'mobile', + title: '手机号码', + minWidth: 130, + }, + { + field: 'telephone', + title: '联系电话', + minWidth: 130, + }, + { + field: 'email', + title: '电子邮箱', + minWidth: 180, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'sort', + title: '排序', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + showOverflow: 'tooltip', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/purchase/supplier/index.vue b/apps/web-ele/src/views/erp/purchase/supplier/index.vue new file mode 100644 index 0000000..915adb7 --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/supplier/index.vue @@ -0,0 +1,153 @@ + + + diff --git a/apps/web-ele/src/views/erp/purchase/supplier/modules/form.vue b/apps/web-ele/src/views/erp/purchase/supplier/modules/form.vue new file mode 100644 index 0000000..653dd5c --- /dev/null +++ b/apps/web-ele/src/views/erp/purchase/supplier/modules/form.vue @@ -0,0 +1,90 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/customer/data.ts b/apps/web-ele/src/views/erp/sale/customer/data.ts new file mode 100644 index 0000000..adfdd56 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/customer/data.ts @@ -0,0 +1,241 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '客户名称', + rules: 'required', + componentProps: { + placeholder: '请输入客户名称', + }, + }, + { + fieldName: 'contact', + label: '联系人', + component: 'Input', + componentProps: { + placeholder: '请输入联系人', + }, + }, + { + fieldName: 'mobile', + label: '手机号码', + component: 'Input', + componentProps: { + placeholder: '请输入手机号码', + }, + }, + { + fieldName: 'telephone', + label: '联系电话', + component: 'Input', + componentProps: { + placeholder: '请输入联系电话', + }, + }, + { + fieldName: 'email', + label: '电子邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入电子邮箱', + }, + }, + { + fieldName: 'fax', + label: '传真', + component: 'Input', + componentProps: { + placeholder: '请输入传真', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'sort', + label: '排序', + component: 'InputNumber', + componentProps: { + placeholder: '请输入排序', + precision: 0, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'taxNo', + label: '纳税人识别号', + component: 'Input', + componentProps: { + placeholder: '请输入纳税人识别号', + }, + }, + { + fieldName: 'taxPercent', + label: '税率(%)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入税率', + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).max(100).optional(), + }, + { + fieldName: 'bankName', + label: '开户行名称', + component: 'Input', + componentProps: { + placeholder: '请输入开户行名称', + }, + }, + { + fieldName: 'bankAccount', + label: '开户行账号', + component: 'Input', + componentProps: { + placeholder: '请输入开户行账号', + }, + }, + { + fieldName: 'bankAddress', + label: '开户行地址', + component: 'Input', + componentProps: { + placeholder: '请输入开户行地址', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 3, + }, + formItemClass: 'col-span-2', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '客户名称', + component: 'Input', + componentProps: { + placeholder: '请输入客户名称', + allowClear: true, + }, + }, + { + fieldName: 'mobile', + label: '手机号码', + component: 'Input', + componentProps: { + placeholder: '请输入手机号码', + allowClear: true, + }, + }, + { + fieldName: 'email', + label: '邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入邮箱', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '客户名称', + minWidth: 150, + }, + { + field: 'contact', + title: '联系人', + minWidth: 120, + }, + { + field: 'mobile', + title: '手机号码', + minWidth: 130, + }, + { + field: 'telephone', + title: '联系电话', + minWidth: 130, + }, + { + field: 'email', + title: '电子邮箱', + minWidth: 180, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'sort', + title: '排序', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + showOverflow: 'tooltip', + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/sale/customer/index.vue b/apps/web-ele/src/views/erp/sale/customer/index.vue new file mode 100644 index 0000000..c2e3bc9 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/customer/index.vue @@ -0,0 +1,149 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/customer/modules/form.vue b/apps/web-ele/src/views/erp/sale/customer/modules/form.vue new file mode 100644 index 0000000..d744556 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/customer/modules/form.vue @@ -0,0 +1,86 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/order/data.ts b/apps/web-ele/src/views/erp/sale/order/data.ts new file mode 100644 index 0000000..b153750 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/order/data.ts @@ -0,0 +1,467 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpPriceInputFormatter } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getAccountSimpleList } from '#/api/erp/finance/account'; +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getCustomerSimpleList } from '#/api/erp/sale/customer'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '订单单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'orderTime', + label: '订单时间', + component: 'DatePicker', + componentProps: { + placeholder: '选择订单时间', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + label: '客户', + fieldName: 'customerId', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择客户', + allowClear: true, + showSearch: true, + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'saleUserId', + label: '销售人员', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择销售人员', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '销售产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + fieldName: 'discountPercent', + label: '优惠率(%)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入优惠率', + min: 0, + max: 100, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional(), + }, + { + fieldName: 'discountPrice', + label: '付款优惠', + component: 'InputNumber', + componentProps: { + placeholder: '收款优惠', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'totalPrice', + label: '优惠后金额', + component: 'InputNumber', + componentProps: { + placeholder: '优惠后金额', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'accountId', + label: '结算账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择结算账户', + allowClear: true, + showSearch: true, + api: getAccountSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + component: 'InputNumber', + componentProps: { + placeholder: '请输入收取订金', + precision: 2, + min: 0, + controlsPosition: 'right', + class: '!w-full', + }, + fieldName: 'depositPrice', + label: '收取订金', + rules: z.number().min(0).optional(), + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + disabled: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '库存', + minWidth: 80, + formatter: 'formatAmount3', + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + field: 'count', + title: '数量', + minWidth: 120, + fixed: 'right', + slots: { default: 'count' }, + }, + { + field: 'productPrice', + title: '产品单价', + minWidth: 120, + fixed: 'right', + slots: { default: 'productPrice' }, + }, + { + field: 'totalProductPrice', + title: '金额', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount2', + }, + { + field: 'taxPercent', + title: '税率(%)', + minWidth: 105, + fixed: 'right', + slots: { default: 'taxPercent' }, + }, + { + field: 'taxPrice', + title: '税额', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount2', + }, + { + field: 'totalPrice', + title: '税额合计', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '订单单号', + component: 'Input', + componentProps: { + placeholder: '请输入订单单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'orderTime', + label: '订单时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'supplierId', + label: '客户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择客户', + allowClear: true, + showSearch: true, + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + { + fieldName: 'outStatus', + label: '出库状态', + component: 'Select', + componentProps: { + options: [ + { label: '未出库', value: 0 }, + { label: '部分出库', value: 1 }, + { label: '全部出库', value: 2 }, + ], + placeholder: '请选择出库状态', + allowClear: true, + }, + }, + { + fieldName: 'returnStatus', + label: '退货状态', + component: 'Select', + componentProps: { + options: [ + { label: '未退货', value: 0 }, + { label: '部分退货', value: 1 }, + { label: '全部退货', value: 2 }, + ], + placeholder: '请选择退货状态', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '订单单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'customerName', + title: '客户', + minWidth: 120, + }, + { + field: 'orderTime', + title: '订单时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'outCount', + title: '出库数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'returnCount', + title: '退货数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalProductPrice', + title: '金额合计', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '含税金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'depositPrice', + title: '收取订金', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/sale/order/index.vue b/apps/web-ele/src/views/erp/sale/order/index.vue new file mode 100644 index 0000000..e681b86 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/order/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/order/modules/form.vue b/apps/web-ele/src/views/erp/sale/order/modules/form.vue new file mode 100644 index 0000000..53dd591 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/order/modules/form.vue @@ -0,0 +1,162 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/order/modules/item-form.vue b/apps/web-ele/src/views/erp/sale/order/modules/item-form.vue new file mode 100644 index 0000000..0a0aef7 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/order/modules/item-form.vue @@ -0,0 +1,328 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/out/data.ts b/apps/web-ele/src/views/erp/sale/out/data.ts new file mode 100644 index 0000000..76f8e22 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/out/data.ts @@ -0,0 +1,637 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpNumberFormatter, erpPriceInputFormatter } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getAccountSimpleList } from '#/api/erp/finance/account'; +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getCustomerSimpleList } from '#/api/erp/sale/customer'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '出库单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'outTime', + label: '出库时间', + component: 'DatePicker', + componentProps: { + disabled: formType === 'detail', + placeholder: '选择出库时间', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'orderNo', + label: '关联订单', + component: 'Input', + formItemClass: 'col-span-1', + rules: 'required', + componentProps: { + placeholder: '请选择关联订单', + disabled: formType === 'detail', + }, + }, + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + disabled: true, + placeholder: '请选择客户', + allowClear: true, + showSearch: true, + api: getCustomerSimpleList, + fieldNames: { + label: 'name', + value: 'id', + }, + }, + rules: 'required', + }, + { + fieldName: 'saleUserId', + label: '销售人员', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择销售人员', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + fieldNames: { + label: 'nickname', + value: 'id', + }, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '出库产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + fieldName: 'discountPercent', + label: '优惠率(%)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入优惠率', + min: 0, + max: 100, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional(), + }, + { + fieldName: 'discountPrice', + label: '收款优惠', + component: 'InputNumber', + componentProps: { + placeholder: '付款优惠', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'discountedPrice', + label: '优惠后金额', + component: 'InputNumber', + componentProps: { + placeholder: '优惠后金额', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['totalPrice', 'otherPrice'], + componentProps: (values) => { + const totalPrice = values.totalPrice || 0; + const otherPrice = values.otherPrice || 0; + values.discountedPrice = totalPrice - otherPrice; + return {}; + }, + }, + }, + { + fieldName: 'otherPrice', + label: '其他费用', + component: 'InputNumber', + componentProps: { + disabled: formType === 'detail', + placeholder: '请输入其他费用', + precision: 2, + formatter: erpPriceInputFormatter, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'accountId', + label: '结算账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择结算账户', + disabled: true, + allowClear: true, + showSearch: true, + api: getAccountSimpleList, + fieldNames: { + label: 'name', + value: 'id', + }, + }, + }, + { + fieldName: 'totalPrice', + label: '应收金额', + component: 'InputNumber', + componentProps: { + precision: 2, + min: 0, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional(), + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + formData?: any[], + disabled?: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'warehouseId', + title: '仓库名称', + minWidth: 200, + slots: { default: 'warehouseId' }, + }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '库存', + minWidth: 80, + formatter: 'formatAmount3', + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + field: 'totalCount', + title: '原数量', + formatter: 'formatAmount3', + minWidth: 120, + fixed: 'right', + visible: formData && formData[0]?.outCount !== undefined, + }, + { + field: 'outCount', + title: '已出库', + formatter: 'formatAmount3', + minWidth: 120, + fixed: 'right', + visible: formData && formData[0]?.returnCount !== undefined, + }, + { + field: 'count', + title: '数量', + minWidth: 120, + fixed: 'right', + slots: { default: 'count' }, + }, + { + field: 'productPrice', + title: '产品单价', + fixed: 'right', + minWidth: 120, + slots: { default: 'productPrice' }, + }, + { + field: 'totalProductPrice', + fixed: 'right', + title: '产品金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + fixed: 'right', + field: 'taxPercent', + title: '税率(%)', + minWidth: 105, + slots: { default: 'taxPercent' }, + }, + { + fixed: 'right', + field: 'taxPrice', + title: '税额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'totalPrice', + fixed: 'right', + title: '合计金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '出库单号', + component: 'Input', + componentProps: { + placeholder: '请输入出库单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + fieldNames: { + label: 'name', + value: 'id', + }, + }, + }, + { + fieldName: 'outTime', + label: '出库时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择客户', + allowClear: true, + showSearch: true, + api: getCustomerSimpleList, + fieldNames: { + label: 'name', + value: 'id', + }, + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + fieldNames: { + label: 'nickname', + value: 'id', + }, + }, + }, + { + fieldName: 'orderNo', + label: '关联订单', + component: 'Input', + componentProps: { + placeholder: '请输入关联订单号', + allowClear: true, + }, + }, + { + fieldName: 'receiptStatus', + label: '收款状态', + component: 'Select', + componentProps: { + options: [ + { label: '未收款', value: 0 }, + { label: '部分收款', value: 1 }, + { label: '全部收款', value: 2 }, + ], + placeholder: '请选择收款状态', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '审批状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择审批状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '出库单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'customerName', + title: '客户', + minWidth: 120, + }, + { + field: 'outTime', + title: '出库时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '应收金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'receiptPrice', + title: '已收金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'unReceiptPrice', + title: '未收金额', + formatter: ({ row }) => { + return `${erpNumberFormatter(row.totalPrice - row.receiptPrice, 2)}元`; + }, + minWidth: 120, + }, + { + field: 'status', + title: '审批状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useOrderGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '订单单号', + component: 'Input', + componentProps: { + placeholder: '请输入订单单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'orderTime', + label: '订单时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useOrderGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'radio', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '订单单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'customerName', + title: '客户', + minWidth: 120, + }, + { + field: 'orderTime', + title: '订单时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'outCount', + title: '出库数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalProductPrice', + title: '金额合计', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '含税金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/sale/out/index.vue b/apps/web-ele/src/views/erp/sale/out/index.vue new file mode 100644 index 0000000..528e7f5 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/out/index.vue @@ -0,0 +1,223 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/out/modules/form.vue b/apps/web-ele/src/views/erp/sale/out/modules/form.vue new file mode 100644 index 0000000..123f2f3 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/out/modules/form.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/out/modules/item-form.vue b/apps/web-ele/src/views/erp/sale/out/modules/item-form.vue new file mode 100644 index 0000000..3ec5996 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/out/modules/item-form.vue @@ -0,0 +1,310 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/out/modules/sale-order-select.vue b/apps/web-ele/src/views/erp/sale/out/modules/sale-order-select.vue new file mode 100644 index 0000000..de19126 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/out/modules/sale-order-select.vue @@ -0,0 +1,124 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/return/data.ts b/apps/web-ele/src/views/erp/sale/return/data.ts new file mode 100644 index 0000000..9138f35 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/return/data.ts @@ -0,0 +1,624 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpNumberFormatter, erpPriceInputFormatter } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getAccountSimpleList } from '#/api/erp/finance/account'; +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getCustomerSimpleList } from '#/api/erp/sale/customer'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '退货单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'returnTime', + label: '退货时间', + component: 'DatePicker', + componentProps: { + disabled: formType === 'detail', + placeholder: '选择退货时间', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'orderNo', + label: '关联订单', + component: 'Input', + formItemClass: 'col-span-1', + rules: 'required', + componentProps: { + placeholder: '请选择关联订单', + disabled: formType === 'detail', + }, + }, + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + disabled: true, + placeholder: '请选择客户', + allowClear: true, + showSearch: true, + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'saleUserId', + label: '销售人员', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择销售人员', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '退货产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + fieldName: 'discountPercent', + label: '优惠率(%)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入优惠率', + min: 0, + max: 100, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional(), + }, + { + fieldName: 'discountPrice', + label: '退款优惠', + component: 'InputNumber', + componentProps: { + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'discountedPrice', + label: '优惠后金额', + component: 'InputNumber', + componentProps: { + placeholder: '优惠后金额', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['totalPrice', 'otherPrice'], + componentProps: (values) => { + const totalPrice = values.totalPrice || 0; + const otherPrice = values.otherPrice || 0; + values.discountedPrice = totalPrice - otherPrice; + return {}; + }, + }, + }, + { + fieldName: 'otherPrice', + label: '其他费用', + component: 'InputNumber', + componentProps: { + disabled: formType === 'detail', + placeholder: '请输入其他费用', + precision: 2, + formatter: erpPriceInputFormatter, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'accountId', + label: '结算账户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择结算账户', + disabled: true, + allowClear: true, + showSearch: true, + api: getAccountSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'totalPrice', + label: '应收金额', + component: 'InputNumber', + componentProps: { + precision: 2, + min: 0, + disabled: true, + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0).optional(), + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + formData?: any[], + disabled?: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'warehouseId', + title: '仓库名称', + minWidth: 200, + slots: { default: 'warehouseId' }, + }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '库存', + minWidth: 80, + formatter: 'formatAmount3', + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + field: 'totalCount', + title: '已出库', + formatter: 'formatAmount3', + minWidth: 120, + fixed: 'right', + visible: formData && formData[0]?.outCount !== undefined, + }, + { + field: 'returnCount', + title: '已退货', + formatter: 'formatAmount3', + minWidth: 120, + fixed: 'right', + visible: formData && formData[0]?.returnCount !== undefined, + }, + { + field: 'count', + title: '数量', + minWidth: 120, + fixed: 'right', + slots: { default: 'count' }, + }, + { + field: 'productPrice', + title: '产品单价', + fixed: 'right', + minWidth: 120, + slots: { default: 'productPrice' }, + }, + { + field: 'totalProductPrice', + fixed: 'right', + title: '产品金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + fixed: 'right', + field: 'taxPercent', + title: '税率(%)', + minWidth: 105, + slots: { default: 'taxPercent' }, + }, + { + fixed: 'right', + field: 'taxPrice', + title: '税额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'totalPrice', + fixed: 'right', + title: '合计金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '退货单号', + component: 'Input', + componentProps: { + placeholder: '请输入退货单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'returnTime', + label: '退货时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择客户', + allowClear: true, + showSearch: true, + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'orderNo', + label: '关联订单', + component: 'Input', + componentProps: { + placeholder: '请输入关联订单号', + allowClear: true, + }, + }, + { + fieldName: 'refundStatus', + label: '退款状态', + component: 'Select', + componentProps: { + options: [ + { label: '未退款', value: 0 }, + { label: '部分退款', value: 1 }, + { label: '全部退款', value: 2 }, + ], + placeholder: '请选择退款状态', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '审批状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择审批状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '退货单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '退货产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'customerName', + title: '客户', + minWidth: 120, + }, + { + field: 'returnTime', + title: '退货时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '应收金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'refundPrice', + title: '已退金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'unRefundPrice', + title: '未退金额', + formatter: ({ row }) => { + return `${erpNumberFormatter(row.totalPrice - row.refundPrice, 2)}元`; + }, + minWidth: 120, + }, + { + field: 'status', + title: '审批状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useOrderGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '订单单号', + component: 'Input', + componentProps: { + placeholder: '请输入订单单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'orderTime', + label: '订单时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useOrderGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'radio', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '订单单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'customerName', + title: '客户', + minWidth: 120, + }, + { + field: 'orderTime', + title: '订单时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'returnCount', + title: '已退货数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalProductPrice', + title: '金额合计', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '含税金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/sale/return/index.vue b/apps/web-ele/src/views/erp/sale/return/index.vue new file mode 100644 index 0000000..5a76a96 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/return/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/return/modules/form.vue b/apps/web-ele/src/views/erp/sale/return/modules/form.vue new file mode 100644 index 0000000..35f59a9 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/return/modules/form.vue @@ -0,0 +1,231 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/return/modules/item-form.vue b/apps/web-ele/src/views/erp/sale/return/modules/item-form.vue new file mode 100644 index 0000000..3e169a9 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/return/modules/item-form.vue @@ -0,0 +1,310 @@ + + + diff --git a/apps/web-ele/src/views/erp/sale/return/modules/sale-order-select.vue b/apps/web-ele/src/views/erp/sale/return/modules/sale-order-select.vue new file mode 100644 index 0000000..05d4746 --- /dev/null +++ b/apps/web-ele/src/views/erp/sale/return/modules/sale-order-select.vue @@ -0,0 +1,124 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/check/data.ts b/apps/web-ele/src/views/erp/stock/check/data.ts new file mode 100644 index 0000000..c4beb2c --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/check/data.ts @@ -0,0 +1,307 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '盘点单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'checkTime', + label: '盘点时间', + component: 'DatePicker', + componentProps: { + placeholder: '选择盘点时间', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + disabled: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'warehouseId', + title: '仓库名称', + minWidth: 150, + slots: { default: 'warehouseId' }, + }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '账面库存', + minWidth: 80, + formatter: 'formatAmount3', + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + field: 'actualCount', + title: '实际库存', + minWidth: 120, + fixed: 'right', + slots: { default: 'actualCount' }, + formatter: 'formatAmount3', + }, + { + field: 'count', + title: '盈亏数量', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount3', + }, + { + field: 'productPrice', + title: '产品单价', + minWidth: 120, + fixed: 'right', + slots: { default: 'productPrice' }, + }, + { + field: 'totalPrice', + title: '金额', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '盘点单号', + component: 'Input', + componentProps: { + placeholder: '请输入盘点单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'checkTime', + label: '盘点时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '盘点单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'checkTime', + title: '盘点时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '总金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/stock/check/index.vue b/apps/web-ele/src/views/erp/stock/check/index.vue new file mode 100644 index 0000000..144ab76 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/check/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/check/modules/form.vue b/apps/web-ele/src/views/erp/stock/check/modules/form.vue new file mode 100644 index 0000000..72e504a --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/check/modules/form.vue @@ -0,0 +1,132 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/check/modules/item-form.vue b/apps/web-ele/src/views/erp/stock/check/modules/item-form.vue new file mode 100644 index 0000000..545c1a6 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/check/modules/item-form.vue @@ -0,0 +1,312 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/in/data.ts b/apps/web-ele/src/views/erp/stock/in/data.ts new file mode 100644 index 0000000..9b59ce9 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/in/data.ts @@ -0,0 +1,332 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getSupplierSimpleList } from '#/api/erp/purchase/supplier'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '入库单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'inTime', + label: '入库时间', + component: 'DatePicker', + componentProps: { + placeholder: '选择入库时间', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + label: '供应商', + fieldName: 'supplierId', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择供应商', + allowClear: true, + showSearch: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '入库产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + disabled: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'warehouseId', + title: '仓库名称', + minWidth: 150, + slots: { default: 'warehouseId' }, + }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '库存', + minWidth: 80, + formatter: 'formatAmount3', + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + field: 'count', + title: '数量', + minWidth: 120, + fixed: 'right', + slots: { default: 'count' }, + }, + { + field: 'productPrice', + title: '产品单价', + minWidth: 120, + fixed: 'right', + slots: { default: 'productPrice' }, + }, + { + field: 'totalPrice', + title: '金额', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '入库单号', + component: 'Input', + componentProps: { + placeholder: '请输入入库单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'inTime', + label: '入库时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择供应商', + allowClear: true, + showSearch: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '入库单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'inTime', + title: '入库时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '总金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/stock/in/index.vue b/apps/web-ele/src/views/erp/stock/in/index.vue new file mode 100644 index 0000000..4f6e1da --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/in/index.vue @@ -0,0 +1,223 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/in/modules/form.vue b/apps/web-ele/src/views/erp/stock/in/modules/form.vue new file mode 100644 index 0000000..8d1e420 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/in/modules/form.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/in/modules/item-form.vue b/apps/web-ele/src/views/erp/stock/in/modules/item-form.vue new file mode 100644 index 0000000..2fa3431 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/in/modules/item-form.vue @@ -0,0 +1,301 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/move/data.ts b/apps/web-ele/src/views/erp/stock/move/data.ts new file mode 100644 index 0000000..0b4ffea --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/move/data.ts @@ -0,0 +1,318 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '调度单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'moveTime', + label: '调度时间', + component: 'DatePicker', + componentProps: { + placeholder: '选择调度时间', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + disabled: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'fromWarehouseId', + title: '调出仓库', + minWidth: 150, + slots: { default: 'fromWarehouseId' }, + }, + { + field: 'toWarehouseId', + title: '调入仓库', + minWidth: 150, + slots: { default: 'toWarehouseId' }, + }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '库存', + minWidth: 80, + formatter: 'formatAmount3', + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + field: 'count', + title: '数量', + minWidth: 120, + fixed: 'right', + slots: { default: 'count' }, + }, + { + field: 'productPrice', + title: '产品单价', + minWidth: 120, + fixed: 'right', + slots: { default: 'productPrice' }, + }, + { + field: 'totalPrice', + title: '金额', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '调度单号', + component: 'Input', + componentProps: { + placeholder: '请输入调度单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'moveTime', + label: '调度时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'fromWarehouseId', + label: '调出仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择调出仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'toWarehouseId', + label: '调入仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择调入仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '调度单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'moveTime', + title: '调度时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '总金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/stock/move/index.vue b/apps/web-ele/src/views/erp/stock/move/index.vue new file mode 100644 index 0000000..c0a6481 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/move/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/move/modules/form.vue b/apps/web-ele/src/views/erp/stock/move/modules/form.vue new file mode 100644 index 0000000..94c879b --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/move/modules/form.vue @@ -0,0 +1,132 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/move/modules/item-form.vue b/apps/web-ele/src/views/erp/stock/move/modules/item-form.vue new file mode 100644 index 0000000..8b3764c --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/move/modules/item-form.vue @@ -0,0 +1,321 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/out/data.ts b/apps/web-ele/src/views/erp/stock/out/data.ts new file mode 100644 index 0000000..eb11d68 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/out/data.ts @@ -0,0 +1,332 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getCustomerSimpleList } from '#/api/erp/sale/customer'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(formType: string): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'no', + label: '出库单号', + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + }, + { + fieldName: 'outTime', + label: '出库时间', + component: 'DatePicker', + componentProps: { + placeholder: '选择出库时间', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + rules: 'required', + }, + { + label: '客户', + fieldName: 'customerId', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择客户', + allowClear: true, + showSearch: true, + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 1, maxRows: 1 }, + disabled: formType === 'detail', + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'fileUrl', + label: '附件', + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: formType !== 'detail', + disabled: formType === 'detail', + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'items', + label: '出库产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + ]; +} + +/** 表单的明细表格列 */ +export function useFormItemColumns( + disabled: boolean, +): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'warehouseId', + title: '仓库名称', + minWidth: 150, + slots: { default: 'warehouseId' }, + }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '库存', + minWidth: 80, + formatter: 'formatAmount3', + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + field: 'count', + title: '数量', + minWidth: 120, + fixed: 'right', + slots: { default: 'count' }, + }, + { + field: 'productPrice', + title: '产品单价', + minWidth: 120, + fixed: 'right', + slots: { default: 'productPrice' }, + }, + { + field: 'totalPrice', + title: '金额', + minWidth: 120, + fixed: 'right', + formatter: 'formatAmount2', + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + visible: !disabled, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '出库单号', + component: 'Input', + componentProps: { + placeholder: '请输入出库单号', + allowClear: true, + }, + }, + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'outTime', + label: '出库时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'customerId', + label: '客户', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择客户', + allowClear: true, + showSearch: true, + api: getCustomerSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + placeholder: '请选择状态', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '出库单号', + width: 200, + fixed: 'left', + }, + { + field: 'productNames', + title: '产品信息', + showOverflow: 'tooltip', + minWidth: 120, + }, + { + field: 'customerName', + title: '客户', + minWidth: 120, + }, + { + field: 'outTime', + title: '出库时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 120, + }, + { + field: 'totalCount', + title: '总数量', + formatter: 'formatAmount3', + minWidth: 120, + }, + { + field: 'totalPrice', + title: '总金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/stock/out/index.vue b/apps/web-ele/src/views/erp/stock/out/index.vue new file mode 100644 index 0000000..96c244e --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/out/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/out/modules/form.vue b/apps/web-ele/src/views/erp/stock/out/modules/form.vue new file mode 100644 index 0000000..4d84dd3 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/out/modules/form.vue @@ -0,0 +1,132 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/out/modules/item-form.vue b/apps/web-ele/src/views/erp/stock/out/modules/item-form.vue new file mode 100644 index 0000000..5aa4f9a --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/out/modules/item-form.vue @@ -0,0 +1,299 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/record/data.ts b/apps/web-ele/src/views/erp/stock/record/data.ts new file mode 100644 index 0000000..e4e3d0e --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/record/data.ts @@ -0,0 +1,133 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'bizType', + label: '类型', + component: 'Select', + componentProps: { + placeholder: '请选择类型', + allowClear: true, + options: getDictOptions(DICT_TYPE.ERP_STOCK_RECORD_BIZ_TYPE, 'number'), + }, + }, + { + fieldName: 'bizNo', + label: '业务单号', + component: 'Input', + componentProps: { + placeholder: '请输入业务单号', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'productName', + title: '产品名称', + minWidth: 150, + }, + { + field: 'categoryName', + title: '产品分类', + width: 120, + }, + { + field: 'unitName', + title: '产品单位', + width: 100, + }, + { + field: 'warehouseName', + title: '仓库', + width: 120, + }, + { + field: 'bizType', + title: '类型', + width: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_STOCK_RECORD_BIZ_TYPE }, + }, + }, + { + field: 'bizNo', + title: '出入库单号', + width: 200, + showOverflow: 'tooltip', + }, + { + field: 'createTime', + title: '出入库日期', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'count', + title: '出入库数量', + width: 120, + formatter: 'formatAmount3', + }, + { + field: 'totalCount', + title: '库存量', + width: 100, + formatter: 'formatAmount3', + }, + { + field: 'creatorName', + title: '操作人', + width: 100, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/stock/record/index.vue b/apps/web-ele/src/views/erp/stock/record/index.vue new file mode 100644 index 0000000..8c97503 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/record/index.vue @@ -0,0 +1,79 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/stock/data.ts b/apps/web-ele/src/views/erp/stock/stock/data.ts new file mode 100644 index 0000000..037bb9c --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/stock/data.ts @@ -0,0 +1,69 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; + +/** 搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'productName', + title: '产品名称', + minWidth: 150, + }, + { + field: 'unitName', + title: '产品单位', + minWidth: 100, + }, + { + field: 'categoryName', + title: '产品分类', + minWidth: 120, + }, + { + field: 'count', + title: '库存量', + minWidth: 100, + formatter: 'formatAmount3', + }, + { + field: 'warehouseName', + title: '仓库', + minWidth: 120, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/stock/stock/index.vue b/apps/web-ele/src/views/erp/stock/stock/index.vue new file mode 100644 index 0000000..2b20d74 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/stock/index.vue @@ -0,0 +1,79 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/warehouse/data.ts b/apps/web-ele/src/views/erp/stock/warehouse/data.ts new file mode 100644 index 0000000..0f38019 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/warehouse/data.ts @@ -0,0 +1,209 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { ErpWarehouseApi } from '#/api/erp/stock/warehouse'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '仓库名称', + component: 'Input', + componentProps: { + placeholder: '请输入仓库名称', + }, + rules: 'required', + }, + { + fieldName: 'address', + label: '仓库地址', + component: 'Input', + componentProps: { + placeholder: '请输入仓库地址', + }, + }, + { + fieldName: 'status', + label: '开启状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'warehousePrice', + label: '仓储费(元)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入仓储费,单位:元/天/KG', + min: 0, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'truckagePrice', + label: '搬运费(元)', + component: 'InputNumber', + componentProps: { + placeholder: '请输入搬运费,单位:元', + min: 0, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'principal', + label: '负责人', + component: 'Input', + componentProps: { + placeholder: '请输入负责人', + }, + }, + { + fieldName: 'sort', + label: '排序', + component: 'InputNumber', + componentProps: { + placeholder: '请输入排序', + precision: 0, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '仓库名称', + component: 'Input', + componentProps: { + placeholder: '请输入仓库名称', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '仓库状态', + component: 'Select', + componentProps: { + placeholder: '请选择仓库状态', + allowClear: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onDefaultStatusChange?: ( + newStatus: boolean, + row: ErpWarehouseApi.Warehouse, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '仓库名称', + minWidth: 150, + }, + { + field: 'address', + title: '仓库地址', + minWidth: 200, + showOverflow: 'tooltip', + }, + { + field: 'warehousePrice', + title: '仓储费', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'truckagePrice', + title: '搬运费', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'principal', + title: '负责人', + minWidth: 100, + }, + { + field: 'sort', + title: '排序', + minWidth: 80, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'defaultStatus', + title: '是否默认', + minWidth: 100, + cellRender: { + attrs: { beforeChange: onDefaultStatusChange }, + name: 'CellSwitch', + props: { + activeValue: true, + inactiveValue: false, + }, + }, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + showOverflow: 'tooltip', + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/erp/stock/warehouse/index.vue b/apps/web-ele/src/views/erp/stock/warehouse/index.vue new file mode 100644 index 0000000..48669e1 --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/warehouse/index.vue @@ -0,0 +1,179 @@ + + + diff --git a/apps/web-ele/src/views/erp/stock/warehouse/modules/form.vue b/apps/web-ele/src/views/erp/stock/warehouse/modules/form.vue new file mode 100644 index 0000000..5bd04fd --- /dev/null +++ b/apps/web-ele/src/views/erp/stock/warehouse/modules/form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/infra/apiAccessLog/data.ts b/apps/web-ele/src/views/infra/apiAccessLog/data.ts new file mode 100644 index 0000000..fb59f59 --- /dev/null +++ b/apps/web-ele/src/views/infra/apiAccessLog/data.ts @@ -0,0 +1,273 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { JsonViewer } from '@vben/common-ui'; +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入用户编号', + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + clearable: true, + placeholder: '请选择用户类型', + }, + }, + { + fieldName: 'applicationName', + label: '应用名', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入应用名', + }, + }, + { + fieldName: 'beginTime', + label: '请求时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'duration', + label: '执行时长', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入执行时长', + }, + }, + { + fieldName: 'resultCode', + label: '结果码', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入结果码', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '日志编号', + minWidth: 100, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 100, + }, + { + field: 'userType', + title: '用户类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.USER_TYPE }, + }, + }, + { + field: 'applicationName', + title: '应用名', + minWidth: 150, + }, + { + field: 'requestMethod', + title: '请求方法', + minWidth: 80, + }, + { + field: 'requestUrl', + title: '请求地址', + minWidth: 300, + }, + { + field: 'beginTime', + title: '请求时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'duration', + title: '执行时长', + minWidth: 120, + formatter: ({ row }) => `${row.duration} ms`, + }, + { + field: 'resultCode', + title: '操作结果', + minWidth: 150, + formatter: ({ row }) => { + return row.resultCode === 0 ? '成功' : `失败(${row.resultMsg})`; + }, + }, + { + field: 'operateModule', + title: '操作模块', + minWidth: 150, + }, + { + field: 'operateName', + title: '操作名', + minWidth: 220, + }, + { + field: 'operateType', + title: '操作类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_OPERATE_TYPE }, + }, + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'id', + label: '日志编号', + }, + { + field: 'traceId', + label: '链路追踪', + }, + { + field: 'applicationName', + label: '应用名', + }, + { + field: 'userId', + label: '用户Id', + }, + { + field: 'userType', + label: '用户类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.USER_TYPE, + value: val, + }); + }, + }, + { + field: 'userIp', + label: '用户 IP', + }, + { + field: 'userAgent', + label: '用户 UA', + }, + { + field: 'requestMethod', + label: '请求信息', + render: (val, data) => { + if (val && data?.requestUrl) { + return `${val} ${data.requestUrl}`; + } + return ''; + }, + }, + { + field: 'requestParams', + label: '请求参数', + render: (val) => { + if (val) { + return h(JsonViewer, { + value: JSON.parse(val), + previewMode: true, + }); + } + return ''; + }, + }, + { + field: 'responseBody', + label: '请求结果', + }, + { + label: '请求时间', + field: 'beginTime', + render: (val, data) => { + if (val && data?.endTime) { + return `${formatDateTime(val)} ~ ${formatDateTime(data.endTime)}`; + } + return ''; + }, + }, + { + label: '请求耗时', + field: 'duration', + render: (val) => { + return val ? `${val} ms` : ''; + }, + }, + { + label: '操作结果', + field: 'resultCode', + render: (val, data) => { + if (val === 0) { + return '正常'; + } else if (val > 0 && data?.resultMsg) { + return `失败 | ${val} | ${data.resultMsg}`; + } + return ''; + }, + }, + { + field: 'operateModule', + label: '操作模块', + }, + { + field: 'operateName', + label: '操作名', + }, + { + field: 'operateType', + label: '操作类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.INFRA_OPERATE_TYPE, + value: val, + }); + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/infra/apiAccessLog/index.vue b/apps/web-ele/src/views/infra/apiAccessLog/index.vue new file mode 100644 index 0000000..6ba4dad --- /dev/null +++ b/apps/web-ele/src/views/infra/apiAccessLog/index.vue @@ -0,0 +1,107 @@ + + + diff --git a/apps/web-ele/src/views/infra/apiAccessLog/modules/detail.vue b/apps/web-ele/src/views/infra/apiAccessLog/modules/detail.vue new file mode 100644 index 0000000..0b3c4c7 --- /dev/null +++ b/apps/web-ele/src/views/infra/apiAccessLog/modules/detail.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/infra/apiErrorLog/data.ts b/apps/web-ele/src/views/infra/apiErrorLog/data.ts new file mode 100644 index 0000000..e669a77 --- /dev/null +++ b/apps/web-ele/src/views/infra/apiErrorLog/data.ts @@ -0,0 +1,249 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { JsonViewer } from '@vben/common-ui'; +import { DICT_TYPE, InfraApiErrorLogProcessStatusEnum } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入用户编号', + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + clearable: true, + placeholder: '请选择用户类型', + }, + }, + { + fieldName: 'applicationName', + label: '应用名', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入应用名', + }, + }, + { + fieldName: 'exceptionTime', + label: '异常时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'processStatus', + label: '处理状态', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS, + 'number', + ), + clearable: true, + placeholder: '请选择处理状态', + }, + defaultValue: InfraApiErrorLogProcessStatusEnum.INIT, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '日志编号', + minWidth: 100, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 100, + }, + { + field: 'userType', + title: '用户类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.USER_TYPE }, + }, + }, + { + field: 'applicationName', + title: '应用名', + minWidth: 150, + }, + { + field: 'requestMethod', + title: '请求方法', + minWidth: 80, + }, + { + field: 'requestUrl', + title: '请求地址', + minWidth: 200, + }, + { + field: 'exceptionTime', + title: '异常发生时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'exceptionName', + title: '异常名', + minWidth: 180, + }, + { + field: 'processStatus', + title: '处理状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS }, + }, + }, + { + title: '操作', + minWidth: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'id', + label: '日志编号', + }, + { + field: 'traceId', + label: '链路追踪', + }, + { + field: 'applicationName', + label: '应用名', + }, + { + field: 'userId', + label: '用户Id', + }, + { + field: 'userType', + label: '用户类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.USER_TYPE, + value: val, + }); + }, + }, + { + field: 'userIp', + label: '用户 IP', + }, + { + field: 'userAgent', + label: '用户 UA', + }, + { + field: 'requestMethod', + label: '请求信息', + render: (val, data) => { + if (val && data?.requestUrl) { + return `${val} ${data.requestUrl}`; + } + return ''; + }, + }, + { + field: 'requestParams', + label: '请求参数', + render: (val) => { + if (val) { + return h(JsonViewer, { + value: JSON.parse(val), + previewMode: true, + }); + } + return ''; + }, + }, + { + field: 'exceptionTime', + label: '异常时间', + render: (val) => { + return formatDateTime(val) as string; + }, + }, + { + field: 'exceptionName', + label: '异常名', + }, + { + field: 'exceptionStackTrace', + label: '异常堆栈', + show: (val) => !val, + render: (val) => { + if (val) { + return h('textarea', { + value: val, + style: + 'width: 100%; min-height: 200px; max-height: 400px; resize: vertical;', + readonly: true, + }); + } + return ''; + }, + }, + { + field: 'processStatus', + label: '处理状态', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS, + value: val, + }); + }, + }, + { + field: 'processUserId', + label: '处理人', + show: (val) => !val, + }, + { + field: 'processTime', + label: '处理时间', + show: (val) => !val, + render: (val) => { + return formatDateTime(val) as string; + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/infra/apiErrorLog/index.vue b/apps/web-ele/src/views/infra/apiErrorLog/index.vue new file mode 100644 index 0000000..964217c --- /dev/null +++ b/apps/web-ele/src/views/infra/apiErrorLog/index.vue @@ -0,0 +1,156 @@ + + + diff --git a/apps/web-ele/src/views/infra/apiErrorLog/modules/detail.vue b/apps/web-ele/src/views/infra/apiErrorLog/modules/detail.vue new file mode 100644 index 0000000..705cfdc --- /dev/null +++ b/apps/web-ele/src/views/infra/apiErrorLog/modules/detail.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/infra/build/index.vue b/apps/web-ele/src/views/infra/build/index.vue new file mode 100644 index 0000000..53ec087 --- /dev/null +++ b/apps/web-ele/src/views/infra/build/index.vue @@ -0,0 +1,181 @@ + + + + diff --git a/apps/web-ele/src/views/infra/codegen/data.ts b/apps/web-ele/src/views/infra/codegen/data.ts new file mode 100644 index 0000000..f421263 --- /dev/null +++ b/apps/web-ele/src/views/infra/codegen/data.ts @@ -0,0 +1,553 @@ +import type { Recordable } from '@vben/types'; + +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { InfraCodegenApi } from '#/api/infra/codegen'; +import type { SystemMenuApi } from '#/api/system/menu'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { IconifyIcon } from '@vben/icons'; +import { handleTree } from '@vben/utils'; + +import { getDataSourceConfigList } from '#/api/infra/data-source-config'; +import { getMenuList } from '#/api/system/menu'; +import { $t } from '#/locales'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 导入数据库表的表单 */ +export function useImportTableFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'dataSourceConfigId', + label: '数据源', + component: 'ApiSelect', + componentProps: { + api: getDataSourceConfigList, + labelField: 'name', + valueField: 'id', + autoSelect: 'first', + placeholder: '请选择数据源', + }, + rules: 'selectRequired', + }, + { + fieldName: 'name', + label: '表名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入表名称', + }, + }, + { + fieldName: 'comment', + label: '表描述', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入表描述', + }, + }, + ]; +} + +/** 导入数据库表表格列定义 */ +export function useImportTableColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { field: 'name', title: '表名称', minWidth: 200 }, + { field: 'comment', title: '表描述', minWidth: 200 }, + ]; +} + +/** 基本信息表单的 schema */ +export function useBasicInfoFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'tableName', + label: '表名称', + component: 'Input', + componentProps: { + placeholder: '请输入仓库名称', + }, + rules: 'required', + }, + { + fieldName: 'tableComment', + label: '表描述', + component: 'Input', + componentProps: { + placeholder: '请输入表描述', + }, + rules: 'required', + }, + { + fieldName: 'className', + label: '实体类名称', + component: 'Input', + componentProps: { + placeholder: '请输入实体类名称', + }, + rules: 'required', + help: '默认去除表名的前缀。如果存在重复,则需要手动添加前缀,避免 MyBatis 报 Alias 重复的问题。', + }, + { + fieldName: 'author', + label: '作者', + component: 'Input', + componentProps: { + placeholder: '请输入作者', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + rows: 3, + placeholder: '请输入备注', + }, + formItemClass: 'md:col-span-2', + }, + ]; +} + +/** 生成信息表单基础 schema */ +export function useGenerationInfoBaseFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Select', + fieldName: 'templateType', + label: '生成模板', + componentProps: { + options: getDictOptions( + DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE, + 'number', + ), + class: 'w-full', + }, + rules: 'selectRequired', + }, + { + component: 'Select', + fieldName: 'frontType', + label: '前端类型', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_CODEGEN_FRONT_TYPE, 'number'), + class: 'w-full', + }, + rules: 'selectRequired', + }, + { + component: 'Select', + fieldName: 'scene', + label: '生成场景', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_CODEGEN_SCENE, 'number'), + class: 'w-full', + }, + rules: 'selectRequired', + }, + { + fieldName: 'parentMenuId', + label: '上级菜单', + help: '分配到指定菜单下,例如 系统管理', + component: 'ApiTreeSelect', + componentProps: { + clearable: true, + api: async () => { + const data = await getMenuList(); + data.unshift({ + id: 0, + name: '顶级菜单', + } as SystemMenuApi.Menu); + return handleTree(data); + }, + class: 'w-full', + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择上级菜单', + checkStrictly: true, + filterTreeNode(input: string, node: Recordable) { + if (!input || input.length === 0) { + return true; + } + const name: string = node.label ?? ''; + if (!name) return false; + return name.includes(input) || $t(name).includes(input); + }, + showSearch: true, + defaultExpandedKeys: [0], + }, + rules: 'selectRequired', + renderComponentContent() { + return { + title({ label, icon }: { icon: string; label: string }) { + const components = []; + if (!label) return ''; + if (icon) { + components.push(h(IconifyIcon, { class: 'size-4', icon })); + } + components.push(h('span', { class: '' }, $t(label || ''))); + return h('div', { class: 'flex items-center gap-1' }, components); + }, + }; + }, + }, + { + component: 'Input', + fieldName: 'moduleName', + label: '模块名', + help: '模块名,即一级目录,例如 system、infra、tool 等等', + rules: 'required', + }, + { + component: 'Input', + fieldName: 'businessName', + label: '业务名', + help: '业务名,即二级目录,例如 user、permission、dict 等等', + rules: 'required', + }, + { + component: 'Input', + fieldName: 'className', + label: '类名称', + help: '类名称(首字母大写),例如SysUser、SysMenu、SysDictData 等等', + rules: 'required', + }, + { + component: 'Input', + fieldName: 'classComment', + label: '类描述', + help: '用作类描述,例如 用户', + rules: 'required', + }, + ]; +} + +/** 树表信息 schema */ +export function useGenerationInfoTreeFormSchema( + columns: InfraCodegenApi.CodegenColumn[] = [], +): VbenFormSchema[] { + return [ + { + component: 'Divider', + fieldName: 'treeDivider', + label: '', + renderComponentContent: () => { + return { + default: () => ['树表信息'], + }; + }, + formItemClass: 'md:col-span-2', + }, + { + component: 'Select', + fieldName: 'treeParentColumnId', + label: '父编号字段', + help: '树显示的父编码字段名,例如 parent_Id', + componentProps: { + class: 'w-full', + clearable: true, + placeholder: '请选择', + options: columns.map((column) => ({ + label: column.columnName, + value: column.id, + })), + }, + rules: 'selectRequired', + }, + { + component: 'Select', + fieldName: 'treeNameColumnId', + label: '名称字段', + help: '树节点显示的名称字段,一般是 name', + componentProps: { + class: 'w-full', + clearable: true, + placeholder: '请选择名称字段', + options: columns.map((column) => ({ + label: column.columnName, + value: column.id, + })), + }, + rules: 'selectRequired', + }, + ]; +} + +/** 主子表信息 schema */ +export function useGenerationInfoSubTableFormSchema( + columns: InfraCodegenApi.CodegenColumn[] = [], + tables: InfraCodegenApi.CodegenTable[] = [], +): VbenFormSchema[] { + return [ + { + component: 'Divider', + fieldName: 'subDivider', + label: '', + renderComponentContent: () => { + return { + default: () => ['主子表信息'], + }; + }, + formItemClass: 'md:col-span-2', + }, + { + component: 'Select', + fieldName: 'masterTableId', + label: '关联的主表', + help: '关联主表(父表)的表名, 如:system_user', + componentProps: { + class: 'w-full', + clearable: true, + placeholder: '请选择', + options: tables.map((table) => ({ + label: `${table.tableName}:${table.tableComment}`, + value: table.id, + })), + }, + rules: 'selectRequired', + }, + { + component: 'Select', + fieldName: 'subJoinColumnId', + label: '子表关联的字段', + help: '子表关联的字段, 如:user_id', + componentProps: { + class: 'w-full', + clearable: true, + placeholder: '请选择', + options: columns.map((column) => ({ + label: `${column.columnName}:${column.columnComment}`, + value: column.id, + })), + }, + rules: 'selectRequired', + }, + { + component: 'RadioGroup', + fieldName: 'subJoinMany', + label: '关联关系', + help: '主表与子表的关联关系', + componentProps: { + class: 'w-full', + clearable: true, + placeholder: '请选择', + options: [ + { + label: '一对多', + value: true, + }, + { + label: '一对一', + value: false, + }, + ], + }, + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'tableName', + label: '表名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入表名称', + }, + }, + { + fieldName: 'tableComment', + label: '表描述', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入表描述', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + getDataSourceConfigName?: (dataSourceConfigId: number) => string | undefined, +): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'dataSourceConfigId', + title: '数据源', + minWidth: 120, + formatter: ({ cellValue }) => getDataSourceConfigName?.(cellValue) || '-', + }, + { + field: 'tableName', + title: '表名称', + minWidth: 200, + }, + { + field: 'tableComment', + title: '表描述', + minWidth: 200, + }, + { + field: 'className', + title: '实体', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'updateTime', + title: '更新时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 代码生成表格列定义 */ +export function useCodegenColumnTableColumns(): VxeTableGridOptions['columns'] { + return [ + { field: 'columnName', title: '字段列名', minWidth: 130 }, + { + field: 'columnComment', + title: '字段描述', + minWidth: 100, + slots: { default: 'columnComment' }, + }, + { field: 'dataType', title: '物理类型', minWidth: 100 }, + { + field: 'javaType', + title: 'Java 类型', + minWidth: 130, + slots: { default: 'javaType' }, + params: { + options: [ + { label: 'Long', value: 'Long' }, + { label: 'String', value: 'String' }, + { label: 'Integer', value: 'Integer' }, + { label: 'Double', value: 'Double' }, + { label: 'BigDecimal', value: 'BigDecimal' }, + { label: 'LocalDateTime', value: 'LocalDateTime' }, + { label: 'Boolean', value: 'Boolean' }, + ], + }, + }, + { + field: 'javaField', + title: 'Java 属性', + minWidth: 100, + slots: { default: 'javaField' }, + }, + { + field: 'createOperation', + title: '插入', + width: 40, + slots: { default: 'createOperation' }, + }, + { + field: 'updateOperation', + title: '编辑', + width: 40, + slots: { default: 'updateOperation' }, + }, + { + field: 'listOperationResult', + title: '列表', + width: 40, + slots: { default: 'listOperationResult' }, + }, + { + field: 'listOperation', + title: '查询', + width: 40, + slots: { default: 'listOperation' }, + }, + { + field: 'listOperationCondition', + title: '查询方式', + minWidth: 100, + slots: { default: 'listOperationCondition' }, + params: { + options: [ + { label: '=', value: '=' }, + { label: '!=', value: '!=' }, + { label: '>', value: '>' }, + { label: '>=', value: '>=' }, + { label: '<', value: '<' }, + { label: '<=', value: '<=' }, + { label: 'LIKE', value: 'LIKE' }, + { label: 'BETWEEN', value: 'BETWEEN' }, + ], + }, + }, + { + field: 'nullable', + title: '允许空', + width: 60, + slots: { default: 'nullable' }, + }, + { + field: 'htmlType', + title: '显示类型', + width: 130, + slots: { default: 'htmlType' }, + params: { + options: [ + { label: '文本框', value: 'input' }, + { label: '文本域', value: 'textarea' }, + { label: '下拉框', value: 'select' }, + { label: '单选框', value: 'radio' }, + { label: '复选框', value: 'checkbox' }, + { label: '日期控件', value: 'datetime' }, + { label: '图片上传', value: 'imageUpload' }, + { label: '文件上传', value: 'fileUpload' }, + { label: '富文本控件', value: 'editor' }, + ], + }, + }, + { + field: 'dictType', + title: '字典类型', + width: 120, + slots: { default: 'dictType' }, + }, + { + field: 'example', + title: '示例', + minWidth: 100, + slots: { default: 'example' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/infra/codegen/edit/index.vue b/apps/web-ele/src/views/infra/codegen/edit/index.vue new file mode 100644 index 0000000..63161ed --- /dev/null +++ b/apps/web-ele/src/views/infra/codegen/edit/index.vue @@ -0,0 +1,169 @@ + + + diff --git a/apps/web-ele/src/views/infra/codegen/index.vue b/apps/web-ele/src/views/infra/codegen/index.vue new file mode 100644 index 0000000..cab2e64 --- /dev/null +++ b/apps/web-ele/src/views/infra/codegen/index.vue @@ -0,0 +1,283 @@ + + diff --git a/apps/web-ele/src/views/infra/codegen/modules/basic-info.vue b/apps/web-ele/src/views/infra/codegen/modules/basic-info.vue new file mode 100644 index 0000000..00c4991 --- /dev/null +++ b/apps/web-ele/src/views/infra/codegen/modules/basic-info.vue @@ -0,0 +1,45 @@ + + diff --git a/apps/web-ele/src/views/infra/codegen/modules/column-info.vue b/apps/web-ele/src/views/infra/codegen/modules/column-info.vue new file mode 100644 index 0000000..2404e94 --- /dev/null +++ b/apps/web-ele/src/views/infra/codegen/modules/column-info.vue @@ -0,0 +1,177 @@ + + + diff --git a/apps/web-ele/src/views/infra/codegen/modules/generation-info.vue b/apps/web-ele/src/views/infra/codegen/modules/generation-info.vue new file mode 100644 index 0000000..56ffe61 --- /dev/null +++ b/apps/web-ele/src/views/infra/codegen/modules/generation-info.vue @@ -0,0 +1,176 @@ + + + diff --git a/apps/web-ele/src/views/infra/codegen/modules/import-table.vue b/apps/web-ele/src/views/infra/codegen/modules/import-table.vue new file mode 100644 index 0000000..89a6cb4 --- /dev/null +++ b/apps/web-ele/src/views/infra/codegen/modules/import-table.vue @@ -0,0 +1,130 @@ + + + diff --git a/apps/web-ele/src/views/infra/codegen/modules/preview-code.vue b/apps/web-ele/src/views/infra/codegen/modules/preview-code.vue new file mode 100644 index 0000000..4eb1104 --- /dev/null +++ b/apps/web-ele/src/views/infra/codegen/modules/preview-code.vue @@ -0,0 +1,279 @@ + + + diff --git a/apps/web-ele/src/views/infra/config/data.ts b/apps/web-ele/src/views/infra/config/data.ts new file mode 100644 index 0000000..c5fd28c --- /dev/null +++ b/apps/web-ele/src/views/infra/config/data.ts @@ -0,0 +1,185 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'category', + label: '参数分类', + component: 'Input', + componentProps: { + placeholder: '请输入参数分类', + }, + rules: 'required', + }, + { + fieldName: 'name', + label: '参数名称', + component: 'Input', + componentProps: { + placeholder: '请输入参数名称', + }, + rules: 'required', + }, + { + fieldName: 'key', + label: '参数键名', + component: 'Input', + componentProps: { + placeholder: '请输入参数键名', + }, + rules: 'required', + }, + { + fieldName: 'value', + label: '参数键值', + component: 'Input', + componentProps: { + placeholder: '请输入参数键值', + }, + rules: 'required', + }, + { + fieldName: 'visible', + label: '是否可见', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + }, + defaultValue: true, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '参数名称', + component: 'Input', + componentProps: { + placeholder: '请输入参数名称', + clearable: true, + }, + }, + { + fieldName: 'key', + label: '参数键名', + component: 'Input', + componentProps: { + placeholder: '请输入参数键名', + clearable: true, + }, + }, + { + fieldName: 'type', + label: '系统内置', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_CONFIG_TYPE, 'number'), + placeholder: '请选择系统内置', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '参数主键', + minWidth: 100, + }, + { + field: 'category', + title: '参数分类', + minWidth: 120, + }, + { + field: 'name', + title: '参数名称', + minWidth: 200, + }, + { + field: 'key', + title: '参数键名', + minWidth: 200, + }, + { + field: 'value', + title: '参数键值', + minWidth: 150, + }, + { + field: 'visible', + title: '是否可见', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'type', + title: '系统内置', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_CONFIG_TYPE }, + }, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 160, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/infra/config/index.vue b/apps/web-ele/src/views/infra/config/index.vue new file mode 100644 index 0000000..1869904 --- /dev/null +++ b/apps/web-ele/src/views/infra/config/index.vue @@ -0,0 +1,183 @@ + + + diff --git a/apps/web-ele/src/views/infra/config/modules/form.vue b/apps/web-ele/src/views/infra/config/modules/form.vue new file mode 100644 index 0000000..777f29d --- /dev/null +++ b/apps/web-ele/src/views/infra/config/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/infra/dataSourceConfig/data.ts b/apps/web-ele/src/views/infra/dataSourceConfig/data.ts new file mode 100644 index 0000000..6f4c602 --- /dev/null +++ b/apps/web-ele/src/views/infra/dataSourceConfig/data.ts @@ -0,0 +1,92 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '数据源名称', + component: 'Input', + componentProps: { + placeholder: '请输入数据源名称', + }, + rules: 'required', + }, + { + fieldName: 'url', + label: '数据源连接', + component: 'Input', + componentProps: { + placeholder: '请输入数据源连接', + }, + rules: 'required', + }, + { + fieldName: 'username', + label: '用户名', + component: 'Input', + componentProps: { + placeholder: '请输入用户名', + }, + rules: 'required', + }, + { + fieldName: 'password', + label: '密码', + component: 'Input', + componentProps: { + placeholder: '请输入密码', + type: 'password', + }, + rules: 'required', + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '主键编号', + minWidth: 100, + }, + { + field: 'name', + title: '数据源名称', + minWidth: 150, + }, + { + field: 'url', + title: '数据源连接', + minWidth: 300, + }, + { + field: 'username', + title: '用户名', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 160, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/infra/dataSourceConfig/index.vue b/apps/web-ele/src/views/infra/dataSourceConfig/index.vue new file mode 100644 index 0000000..3727b2b --- /dev/null +++ b/apps/web-ele/src/views/infra/dataSourceConfig/index.vue @@ -0,0 +1,162 @@ + + + diff --git a/apps/web-ele/src/views/infra/dataSourceConfig/modules/form.vue b/apps/web-ele/src/views/infra/dataSourceConfig/modules/form.vue new file mode 100644 index 0000000..6291c74 --- /dev/null +++ b/apps/web-ele/src/views/infra/dataSourceConfig/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo01/data.ts b/apps/web-ele/src/views/infra/demo/demo01/data.ts new file mode 100644 index 0000000..d2242a8 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo01/data.ts @@ -0,0 +1,152 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { Demo01ContactApi } from '#/api/infra/demo/demo01'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + rules: 'required', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + }, + }, + { + fieldName: 'birthday', + label: '出生年', + rules: 'required', + component: 'DatePicker', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + placeholder: '请选择出生年', + class: '!w-full', + }, + }, + { + fieldName: 'description', + label: '简介', + rules: 'required', + component: 'RichTextarea', + }, + { + fieldName: 'avatar', + label: '头像', + component: 'ImageUpload', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + placeholder: '请选择性别', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'sex', + title: '性别', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, + }, + }, + { + field: 'birthday', + title: '出生年', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + field: 'description', + title: '简介', + minWidth: 120, + }, + { + field: 'avatar', + title: '头像', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 160, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/infra/demo/demo01/index.vue b/apps/web-ele/src/views/infra/demo/demo01/index.vue new file mode 100644 index 0000000..4b5455a --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo01/index.vue @@ -0,0 +1,185 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo01/modules/form.vue b/apps/web-ele/src/views/infra/demo/demo01/modules/form.vue new file mode 100644 index 0000000..d97dd9c --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo01/modules/form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo02/data.ts b/apps/web-ele/src/views/infra/demo/demo02/data.ts new file mode 100644 index 0000000..7dc36ae --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo02/data.ts @@ -0,0 +1,120 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { Demo02CategoryApi } from '#/api/infra/demo/demo02'; + +import { handleTree } from '@vben/utils'; + +import { getDemo02CategoryList } from '#/api/infra/demo/demo02'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'parentId', + label: '上级示例分类', + component: 'ApiTreeSelect', + componentProps: { + clearable: true, + api: async () => { + const data = await getDemo02CategoryList({}); + data.unshift({ + id: 0, + name: '顶级示例分类', + }); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择上级示例分类', + defaultExpandAll: true, + }, + rules: 'selectRequired', + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'parentId', + label: '父级编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入父级编号', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + treeNode: true, + }, + { + field: 'parentId', + title: '父级编号', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/infra/demo/demo02/index.vue b/apps/web-ele/src/views/infra/demo/demo02/index.vue new file mode 100644 index 0000000..b5eab45 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo02/index.vue @@ -0,0 +1,175 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo02/modules/form.vue b/apps/web-ele/src/views/infra/demo/demo02/modules/form.vue new file mode 100644 index 0000000..2f4a581 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo02/modules/form.vue @@ -0,0 +1,91 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/erp/data.ts b/apps/web-ele/src/views/infra/demo/demo03/erp/data.ts new file mode 100644 index 0000000..63580aa --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/erp/data.ts @@ -0,0 +1,381 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + rules: 'required', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + }, + }, + { + fieldName: 'birthday', + label: '出生日期', + rules: 'required', + component: 'DatePicker', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + placeholder: '请选择出生日期', + class: '!w-full', + }, + }, + { + fieldName: 'description', + label: '简介', + rules: 'required', + component: 'RichTextarea', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + placeholder: '请选择性别', + }, + }, + { + fieldName: 'description', + label: '简介', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入简介', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'sex', + title: '性别', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, + }, + }, + { + field: 'birthday', + title: '出生日期', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + field: 'description', + title: '简介', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ==================== 子表(学生课程) ==================== + +/** 新增/修改的表单 */ +export function useDemo03CourseFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'score', + label: '分数', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入分数', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useDemo03CourseGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'studentId', + label: '学生编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入学生编号', + }, + }, + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'score', + label: '分数', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入分数', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useDemo03CourseGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'studentId', + title: '学生编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'score', + title: '分数', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ==================== 子表(学生班级) ==================== + +/** 新增/修改的表单 */ +export function useDemo03GradeFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'teacher', + label: '班主任', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入班主任', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useDemo03GradeGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'studentId', + label: '学生编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入学生编号', + }, + }, + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'teacher', + label: '班主任', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入班主任', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useDemo03GradeGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'studentId', + title: '学生编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'teacher', + title: '班主任', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/infra/demo/demo03/erp/index.vue b/apps/web-ele/src/views/infra/demo/demo03/erp/index.vue new file mode 100644 index 0000000..043dd98 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/erp/index.vue @@ -0,0 +1,207 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-course-form.vue b/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-course-form.vue new file mode 100644 index 0000000..dfb34f1 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-course-form.vue @@ -0,0 +1,92 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-course-list.vue b/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-course-list.vue new file mode 100644 index 0000000..076e33a --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-course-list.vue @@ -0,0 +1,197 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-grade-form.vue b/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-grade-form.vue new file mode 100644 index 0000000..0b41e20 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-grade-form.vue @@ -0,0 +1,92 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-grade-list.vue b/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-grade-list.vue new file mode 100644 index 0000000..c4b42fa --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/erp/modules/demo03-grade-list.vue @@ -0,0 +1,197 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/erp/modules/form.vue b/apps/web-ele/src/views/infra/demo/demo03/erp/modules/form.vue new file mode 100644 index 0000000..b0ad481 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/erp/modules/form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/inner/data.ts b/apps/web-ele/src/views/infra/demo/demo03/inner/data.ts new file mode 100644 index 0000000..e79cf78 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/inner/data.ts @@ -0,0 +1,275 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { Demo03StudentApi } from '#/api/infra/demo/demo03/inner'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + rules: 'required', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + }, + }, + { + fieldName: 'birthday', + label: '出生日期', + rules: 'required', + component: 'DatePicker', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: '!w-full', + }, + }, + { + fieldName: 'description', + label: '简介', + rules: 'required', + component: 'RichTextarea', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + placeholder: '请选择性别', + }, + }, + { + fieldName: 'description', + label: '简介', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入简介', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { type: 'expand', width: 80, slots: { content: 'expand_content' } }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'sex', + title: '性别', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, + }, + }, + { + field: 'birthday', + title: '出生日期', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + field: 'description', + title: '简介', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ==================== 子表(学生课程) ==================== + +/** 新增/修改列表的字段 */ +export function useDemo03CourseGridEditColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '名字', + minWidth: 120, + slots: { default: 'name' }, + }, + { + field: 'score', + title: '分数', + minWidth: 120, + slots: { default: 'score' }, + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的字段 */ +export function useDemo03CourseGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'studentId', + title: '学生编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'score', + title: '分数', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + ]; +} + +// ==================== 子表(学生班级) ==================== + +/** 新增/修改的表单 */ +export function useDemo03GradeFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'teacher', + label: '班主任', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入班主任', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useDemo03GradeGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'studentId', + title: '学生编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'teacher', + title: '班主任', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-ele/src/views/infra/demo/demo03/inner/index.vue b/apps/web-ele/src/views/infra/demo/demo03/inner/index.vue new file mode 100644 index 0000000..eadfc82 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/inner/index.vue @@ -0,0 +1,201 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-course-form.vue b/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-course-form.vue new file mode 100644 index 0000000..0402bf4 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-course-form.vue @@ -0,0 +1,119 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-course-list.vue b/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-course-list.vue new file mode 100644 index 0000000..50297db --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-course-list.vue @@ -0,0 +1,56 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-grade-form.vue b/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-grade-form.vue new file mode 100644 index 0000000..3e28546 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-grade-form.vue @@ -0,0 +1,51 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-grade-list.vue b/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-grade-list.vue new file mode 100644 index 0000000..1ad2db7 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/inner/modules/demo03-grade-list.vue @@ -0,0 +1,56 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/inner/modules/form.vue b/apps/web-ele/src/views/infra/demo/demo03/inner/modules/form.vue new file mode 100644 index 0000000..753a689 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/inner/modules/form.vue @@ -0,0 +1,119 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/normal/data.ts b/apps/web-ele/src/views/infra/demo/demo03/normal/data.ts new file mode 100644 index 0000000..ef76bdd --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/normal/data.ts @@ -0,0 +1,211 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + rules: 'required', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + }, + }, + { + fieldName: 'birthday', + label: '出生日期', + rules: 'required', + component: 'DatePicker', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + placeholder: '请选择出生日期', + class: '!w-full', + }, + }, + { + fieldName: 'description', + label: '简介', + rules: 'required', + component: 'RichTextarea', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + placeholder: '请选择性别', + }, + }, + { + fieldName: 'description', + label: '简介', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入简介', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'sex', + title: '性别', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, + }, + }, + { + field: 'birthday', + title: '出生日期', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + field: 'description', + title: '简介', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ==================== 子表(学生课程) ==================== + +/** 新增/修改列表的字段 */ +export function useDemo03CourseGridEditColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '名字', + minWidth: 120, + slots: { default: 'name' }, + }, + { + field: 'score', + title: '分数', + minWidth: 120, + slots: { default: 'score' }, + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ==================== 子表(学生班级) ==================== + +/** 新增/修改的表单 */ +export function useDemo03GradeFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'teacher', + label: '班主任', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入班主任', + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/infra/demo/demo03/normal/index.vue b/apps/web-ele/src/views/infra/demo/demo03/normal/index.vue new file mode 100644 index 0000000..7c8c07d --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/normal/index.vue @@ -0,0 +1,185 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/normal/modules/demo03-course-form.vue b/apps/web-ele/src/views/infra/demo/demo03/normal/modules/demo03-course-form.vue new file mode 100644 index 0000000..f460aee --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/normal/modules/demo03-course-form.vue @@ -0,0 +1,118 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/normal/modules/demo03-grade-form.vue b/apps/web-ele/src/views/infra/demo/demo03/normal/modules/demo03-grade-form.vue new file mode 100644 index 0000000..5d5f396 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/normal/modules/demo03-grade-form.vue @@ -0,0 +1,51 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/demo03/normal/modules/form.vue b/apps/web-ele/src/views/infra/demo/demo03/normal/modules/form.vue new file mode 100644 index 0000000..7b9d1b0 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/demo03/normal/modules/form.vue @@ -0,0 +1,119 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo01/index.vue b/apps/web-ele/src/views/infra/demo/general/demo01/index.vue new file mode 100644 index 0000000..0da2e0a --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo01/index.vue @@ -0,0 +1,314 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo01/modules/form.vue b/apps/web-ele/src/views/infra/demo/general/demo01/modules/form.vue new file mode 100644 index 0000000..05c2cf7 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo01/modules/form.vue @@ -0,0 +1,149 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo02/index.vue b/apps/web-ele/src/views/infra/demo/general/demo02/index.vue new file mode 100644 index 0000000..500cbe2 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo02/index.vue @@ -0,0 +1,264 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo02/modules/form.vue b/apps/web-ele/src/views/infra/demo/general/demo02/modules/form.vue new file mode 100644 index 0000000..e7743ec --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo02/modules/form.vue @@ -0,0 +1,138 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/erp/index.vue b/apps/web-ele/src/views/infra/demo/general/demo03/erp/index.vue new file mode 100644 index 0000000..9c62a60 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/erp/index.vue @@ -0,0 +1,342 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-course-form.vue b/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-course-form.vue new file mode 100644 index 0000000..dbabbae --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-course-form.vue @@ -0,0 +1,114 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-course-list.vue b/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-course-list.vue new file mode 100644 index 0000000..32abd38 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-course-list.vue @@ -0,0 +1,294 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-grade-form.vue b/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-grade-form.vue new file mode 100644 index 0000000..62c5a78 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-grade-form.vue @@ -0,0 +1,114 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-grade-list.vue b/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-grade-list.vue new file mode 100644 index 0000000..adc374d --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/demo03-grade-list.vue @@ -0,0 +1,294 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/form.vue b/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/form.vue new file mode 100644 index 0000000..d9cc415 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/erp/modules/form.vue @@ -0,0 +1,140 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/inner/index.vue b/apps/web-ele/src/views/infra/demo/general/demo03/inner/index.vue new file mode 100644 index 0000000..7fca75c --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/inner/index.vue @@ -0,0 +1,335 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-course-form.vue b/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-course-form.vue new file mode 100644 index 0000000..06cea78 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-course-form.vue @@ -0,0 +1,95 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-course-list.vue b/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-course-list.vue new file mode 100644 index 0000000..678042a --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-course-list.vue @@ -0,0 +1,59 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-grade-form.vue b/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-grade-form.vue new file mode 100644 index 0000000..c399fc3 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-grade-form.vue @@ -0,0 +1,67 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-grade-list.vue b/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-grade-list.vue new file mode 100644 index 0000000..4272b63 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/demo03-grade-list.vue @@ -0,0 +1,59 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/form.vue b/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/form.vue new file mode 100644 index 0000000..63ee76c --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/inner/modules/form.vue @@ -0,0 +1,176 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/normal/index.vue b/apps/web-ele/src/views/infra/demo/general/demo03/normal/index.vue new file mode 100644 index 0000000..3824493 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/normal/index.vue @@ -0,0 +1,314 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/normal/modules/demo03-course-form.vue b/apps/web-ele/src/views/infra/demo/general/demo03/normal/modules/demo03-course-form.vue new file mode 100644 index 0000000..7382839 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/normal/modules/demo03-course-form.vue @@ -0,0 +1,95 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/normal/modules/demo03-grade-form.vue b/apps/web-ele/src/views/infra/demo/general/demo03/normal/modules/demo03-grade-form.vue new file mode 100644 index 0000000..9357c68 --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/normal/modules/demo03-grade-form.vue @@ -0,0 +1,67 @@ + + + diff --git a/apps/web-ele/src/views/infra/demo/general/demo03/normal/modules/form.vue b/apps/web-ele/src/views/infra/demo/general/demo03/normal/modules/form.vue new file mode 100644 index 0000000..9dd6a5f --- /dev/null +++ b/apps/web-ele/src/views/infra/demo/general/demo03/normal/modules/form.vue @@ -0,0 +1,176 @@ + + + diff --git a/apps/web-ele/src/views/infra/druid/index.vue b/apps/web-ele/src/views/infra/druid/index.vue new file mode 100644 index 0000000..01ec58d --- /dev/null +++ b/apps/web-ele/src/views/infra/druid/index.vue @@ -0,0 +1,36 @@ + + + + diff --git a/apps/web-ele/src/views/mall/promotion/components/diy-editor/util.ts b/apps/web-ele/src/views/mall/promotion/components/diy-editor/util.ts new file mode 100644 index 0000000..8926ca5 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/components/diy-editor/util.ts @@ -0,0 +1,115 @@ +import type { NavigationBarProperty } from './components/mobile/navigation-bar/config'; +import type { PageConfigProperty } from './components/mobile/page-config/config'; +import type { TabBarProperty } from './components/mobile/tab-bar/config'; + +/** 页面装修组件 */ +export interface DiyComponent { + uid?: number; // 用于区分同一种组件的不同实例 + id: string; // 组件唯一标识 + name: string; // 组件名称 + icon: string; // 组件图标 + /* + 组件位置: + top: 固定于手机顶部,例如 顶部的导航栏 + bottom: 固定于手机底部,例如 底部的菜单导航栏 + center: 位于手机中心,每个组件占一行,顺序向下排列 + 空:同 center + fixed: 由组件自己决定位置,如弹窗位于手机中心、浮动按钮一般位于手机右下角 + */ + position?: '' | 'bottom' | 'center' | 'fixed' | 'top'; + property: T; // 组件属性 +} + +/** 页面装修组件库 */ +export interface DiyComponentLibrary { + name: string; // 组件库名称 + extended: boolean; // 是否展开 + components: string[]; // 组件列表 +} + +/** 组件样式 */ +export interface ComponentStyle { + bgType: 'color' | 'img'; // 背景类型 + bgColor: string; // 背景颜色 + bgImg: string; // 背景图片 + // 外边距 + margin: number; + marginTop: number; + marginRight: number; + marginBottom: number; + marginLeft: number; + // 内边距 + padding: number; + paddingTop: number; + paddingRight: number; + paddingBottom: number; + paddingLeft: number; + // 边框圆角 + borderRadius: number; + borderTopLeftRadius: number; + borderTopRightRadius: number; + borderBottomRightRadius: number; + borderBottomLeftRadius: number; +} + +/** 页面配置 */ +export interface PageConfig { + page: PageConfigProperty; // 页面属性 + navigationBar: NavigationBarProperty; // 顶部导航栏属性 + tabBar?: TabBarProperty; // 底部导航菜单属性 + + components: PageComponent[]; // 页面组件列表 +} + +export type PageComponent = Pick, 'id' | 'property'>; // 页面组件,只保留组件 ID,组件属性 + +/** 页面组件库 */ +export const PAGE_LIBS = [ + { + name: '基础组件', + extended: true, + components: [ + 'SearchBar', + 'NoticeBar', + 'MenuSwiper', + 'MenuGrid', + 'MenuList', + 'Popover', + 'FloatingActionButton', + ], + }, + { + name: '图文组件', + extended: true, + components: [ + 'ImageBar', + 'Carousel', + 'TitleBar', + 'VideoPlayer', + 'Divider', + 'MagicCube', + 'HotZone', + ], + }, + { + name: '商品组件', + extended: true, + components: ['ProductCard', 'ProductList'], + }, + { + name: '用户组件', + extended: true, + components: ['UserCard', 'UserOrder', 'UserWallet', 'UserCoupon'], + }, + { + name: '营销组件', + extended: true, + components: [ + 'PromotionCombination', + 'PromotionSeckill', + 'PromotionPoint', + 'CouponCard', + 'PromotionArticle', + ], + }, +] as DiyComponentLibrary[]; diff --git a/apps/web-ele/src/views/mall/promotion/components/draggable/index.vue b/apps/web-ele/src/views/mall/promotion/components/draggable/index.vue new file mode 100644 index 0000000..3c673a7 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/components/draggable/index.vue @@ -0,0 +1,95 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/components/index.ts b/apps/web-ele/src/views/mall/promotion/components/index.ts new file mode 100644 index 0000000..6dbe001 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/components/index.ts @@ -0,0 +1,10 @@ +export { default as AppLinkInput } from './app-link-input/index.vue'; +export { default as AppLinkSelectDialog } from './app-link-input/select-dialog.vue'; +export { default as ColorInput } from './color-input/index.vue'; +export { default as DiyEditor } from './diy-editor/index.vue'; +export { type DiyComponentLibrary, PAGE_LIBS } from './diy-editor/util'; +export { default as Draggable } from './draggable/index.vue'; +export { default as InputWithColor } from './input-with-color/index.vue'; + +export { default as MagicCubeEditor } from './magic-cube-editor/index.vue'; +export { default as VerticalButtonGroup } from './vertical-button-group/index.vue'; diff --git a/apps/web-ele/src/views/mall/promotion/components/input-with-color/index.vue b/apps/web-ele/src/views/mall/promotion/components/input-with-color/index.vue new file mode 100644 index 0000000..d825678 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/components/input-with-color/index.vue @@ -0,0 +1,44 @@ + + + + diff --git a/apps/web-ele/src/views/mall/promotion/components/magic-cube-editor/index.vue b/apps/web-ele/src/views/mall/promotion/components/magic-cube-editor/index.vue new file mode 100644 index 0000000..5f45238 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/components/magic-cube-editor/index.vue @@ -0,0 +1,254 @@ + + diff --git a/apps/web-ele/src/views/mall/promotion/components/magic-cube-editor/util.ts b/apps/web-ele/src/views/mall/promotion/components/magic-cube-editor/util.ts new file mode 100644 index 0000000..d55cd4b --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/components/magic-cube-editor/util.ts @@ -0,0 +1,71 @@ +/** 坐标点 */ +export interface Point { + x: number; + y: number; +} + +/** 矩形 */ +export interface Rect { + left: number; // 左上角 X 轴坐标 + top: number; // 左上角 Y 轴坐标 + right: number; // 右下角 X 轴坐标 + bottom: number; // 右下角 Y 轴坐标 + width: number; // 矩形宽度 + height: number; // 矩形高度 +} + +/** + * 判断两个矩形是否重叠 + * + * @param a 矩形 A + * @param b 矩形 B + */ +export function isOverlap(a: Rect, b: Rect): boolean { + return ( + a.left < b.left + b.width && + a.left + a.width > b.left && + a.top < b.top + b.height && + a.height + a.top > b.top + ); +} + +/** + * 检查坐标点是否在矩形内 + * @param hotArea 矩形 + * @param point 坐标 + */ +export function isContains(hotArea: Rect, point: Point): boolean { + return ( + point.x >= hotArea.left && + point.x < hotArea.right && + point.y >= hotArea.top && + point.y < hotArea.bottom + ); +} + +/** + * 在两个坐标点中间,创建一个矩形 + * + * 存在以下情况: + * 1. 两个坐标点是同一个位置,只占一个位置的正方形,宽高都为 1 + * 2. X 轴坐标相同,只占一行的矩形,高度为 1 + * 3. Y 轴坐标相同,只占一列的矩形,宽度为 1 + * 4. 多行多列的矩形 + * + * @param a 坐标点一 + * @param b 坐标点二 + */ +export function createRect(a: Point, b: Point): Rect { + // 计算矩形的范围 + let [left, left2] = [a.x, b.x].toSorted(); + left = left ?? 0; + left2 = left2 ?? 0; + let [top, top2] = [a.y, b.y].toSorted(); + top = top ?? 0; + top2 = top2 ?? 0; + const right = left2 + 1; + const bottom = top2 + 1; + const height = bottom - top; + const width = right - left; + return { left, right, top, bottom, height, width }; +} diff --git a/apps/web-ele/src/views/mall/promotion/components/vertical-button-group/index.vue b/apps/web-ele/src/views/mall/promotion/components/vertical-button-group/index.vue new file mode 100644 index 0000000..16f4b33 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/components/vertical-button-group/index.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/apps/web-ele/src/views/mall/promotion/coupon/components/index.ts b/apps/web-ele/src/views/mall/promotion/coupon/components/index.ts new file mode 100644 index 0000000..24cb4e2 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/components/index.ts @@ -0,0 +1,2 @@ +export { default as CouponSelect } from './select.vue'; +export { default as CouponSendForm } from './send-form.vue'; diff --git a/apps/web-ele/src/views/mall/promotion/coupon/components/select-data.ts b/apps/web-ele/src/views/mall/promotion/coupon/components/select-data.ts new file mode 100644 index 0000000..4820881 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/components/select-data.ts @@ -0,0 +1,119 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { + discountFormat, + remainedCountFormat, + takeLimitCountFormat, + validityTypeFormat, +} from '../formatter'; + +/** 优惠券选择的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '优惠券名称', + component: 'Input', + componentProps: { + placeholder: '请输入优惠券名称', + clearable: true, + }, + }, + { + fieldName: 'discountType', + label: '优惠类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.PROMOTION_DISCOUNT_TYPE, 'number'), + placeholder: '请选择优惠类型', + clearable: true, + }, + }, + ]; +} + +/** 优惠券选择的表格列 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 55 }, + { + field: 'name', + title: '优惠券名称', + minWidth: 140, + }, + { + field: 'productScope', + title: '类型', + minWidth: 80, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_PRODUCT_SCOPE }, + }, + }, + { + field: 'discountType', + title: '优惠类型', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_DISCOUNT_TYPE }, + }, + }, + { + field: 'discountPrice', + title: '优惠力度', + minWidth: 100, + formatter: ({ row }) => discountFormat(row), + }, + { + field: 'takeType', + title: '领取方式', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE }, + }, + }, + { + field: 'validityType', + title: '使用时间', + minWidth: 185, + align: 'center', + formatter: ({ row }) => validityTypeFormat(row), + }, + { + field: 'totalCount', + title: '发放数量', + minWidth: 100, + align: 'center', + }, + { + field: 'remainedCount', + title: '剩余数量', + minWidth: 100, + align: 'center', + formatter: ({ row }) => remainedCountFormat(row), + }, + { + field: 'takeLimitCount', + title: '领取上限', + minWidth: 100, + align: 'center', + formatter: ({ row }) => takeLimitCountFormat(row), + }, + { + field: 'status', + title: '状态', + minWidth: 80, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/coupon/components/select.vue b/apps/web-ele/src/views/mall/promotion/coupon/components/select.vue new file mode 100644 index 0000000..386ba7b --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/components/select.vue @@ -0,0 +1,97 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/coupon/components/send-form-data.ts b/apps/web-ele/src/views/mall/promotion/coupon/components/send-form-data.ts new file mode 100644 index 0000000..6961bfa --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/components/send-form-data.ts @@ -0,0 +1,64 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { + discountFormat, + remainedCountFormat, + usePriceFormat, + validityTypeFormat, +} from '../formatter'; + +/** 搜索表单的 schema */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'name', + label: '优惠券名称', + componentProps: { + placeholder: '请输入优惠券名称', + clearable: true, + }, + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns(): VxeGridProps['columns'] { + return [ + { + title: '优惠券名称', + field: 'name', + minWidth: 120, + }, + { + title: '优惠金额 / 折扣', + field: 'discount', + minWidth: 120, + formatter: ({ row }) => discountFormat(row), + }, + { + title: '最低消费', + field: 'usePrice', + minWidth: 100, + formatter: ({ row }) => usePriceFormat(row), + }, + { + title: '有效期限', + field: 'validityType', + minWidth: 140, + formatter: ({ row }) => validityTypeFormat(row), + }, + { + title: '剩余数量', + minWidth: 100, + formatter: ({ row }) => remainedCountFormat(row), + }, + { + title: '操作', + width: 100, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/coupon/components/send-form.vue b/apps/web-ele/src/views/mall/promotion/coupon/components/send-form.vue new file mode 100644 index 0000000..38cad53 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/components/send-form.vue @@ -0,0 +1,85 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/coupon/data.ts b/apps/web-ele/src/views/mall/promotion/coupon/data.ts new file mode 100644 index 0000000..2c5dc8b --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/data.ts @@ -0,0 +1,111 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +import { getRangePickerDefaultProps } from '#/utils'; + +import { discountFormat } from './formatter'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'nickname', + label: '会员昵称', + component: 'Input', + componentProps: { + placeholder: '请输入会员昵称', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '领取时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'nickname', + title: '会员昵称', + minWidth: 100, + }, + { + field: 'name', + title: '优惠券名称', + minWidth: 140, + }, + { + field: 'productScope', + title: '类型', + minWidth: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_PRODUCT_SCOPE }, + }, + }, + { + field: 'discountType', + title: '优惠', + minWidth: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_DISCOUNT_TYPE }, + }, + }, + { + field: 'discountPrice', + title: '优惠力度', + minWidth: 110, + formatter: ({ row }) => { + return discountFormat(row); + }, + }, + { + field: 'takeType', + title: '领取方式', + minWidth: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE }, + }, + }, + { + field: 'status', + title: '状态', + minWidth: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_COUPON_STATUS }, + }, + }, + { + field: 'createTime', + title: '领取时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'useTime', + title: '使用时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'actions', + title: '操作', + width: 100, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/coupon/formatter.ts b/apps/web-ele/src/views/mall/promotion/coupon/formatter.ts new file mode 100644 index 0000000..2f34863 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/formatter.ts @@ -0,0 +1,64 @@ +import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate'; + +import { + CouponTemplateValidityTypeEnum, + PromotionDiscountTypeEnum, +} from '@vben/constants'; +import { floatToFixed2, formatDate } from '@vben/utils'; + +/** 格式化【优惠金额/折扣】 */ +export function discountFormat(row: MallCouponTemplateApi.CouponTemplate) { + if (row.discountType === PromotionDiscountTypeEnum.PRICE.type) { + return `¥${floatToFixed2(row.discountPrice)}`; + } + if (row.discountType === PromotionDiscountTypeEnum.PERCENT.type) { + return `${row.discountPercent}%`; + } + return `未知【${row.discountType}】`; +} + +/** 格式化【领取上限】 */ +export function takeLimitCountFormat( + row: MallCouponTemplateApi.CouponTemplate, +) { + if (row.takeLimitCount) { + if (row.takeLimitCount === -1) { + return '无领取限制'; + } + return `${row.takeLimitCount} 张/人`; + } else { + return ' '; + } +} + +/** 格式化【有效期限】 */ +export function validityTypeFormat(row: MallCouponTemplateApi.CouponTemplate) { + if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) { + return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`; + } + if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) { + return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`; + } + return `未知【${row.validityType}】`; +} + +/** 格式化【totalCount】 */ +export function totalCountFormat(row: MallCouponTemplateApi.CouponTemplate) { + if (row.totalCount === -1) { + return '不限制'; + } + return row.totalCount; +} + +/** 格式化【剩余数量】 */ +export function remainedCountFormat(row: MallCouponTemplateApi.CouponTemplate) { + if (row.totalCount === -1) { + return '不限制'; + } + return row.totalCount - row.takeCount; +} + +/** 格式化【最低消费】 */ +export function usePriceFormat(row: MallCouponTemplateApi.CouponTemplate) { + return `¥${floatToFixed2(row.usePrice)}`; +} diff --git a/apps/web-ele/src/views/mall/promotion/coupon/index.vue b/apps/web-ele/src/views/mall/promotion/coupon/index.vue new file mode 100644 index 0000000..17580fc --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/index.vue @@ -0,0 +1,148 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/coupon/template/data.ts b/apps/web-ele/src/views/mall/promotion/coupon/template/data.ts new file mode 100644 index 0000000..0b00c14 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/template/data.ts @@ -0,0 +1,485 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate'; + +import { + CommonStatusEnum, + CouponTemplateTakeTypeEnum, + CouponTemplateValidityTypeEnum, + DICT_TYPE, + PromotionDiscountTypeEnum, + PromotionProductScopeEnum, +} from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +import { + discountFormat, + remainedCountFormat, + takeLimitCountFormat, + totalCountFormat, + validityTypeFormat, +} from '../formatter'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '优惠券名称', + component: 'Input', + componentProps: { + placeholder: '请输入优惠券名称', + }, + rules: 'required', + }, + { + fieldName: 'description', + label: '优惠券描述', + component: 'Textarea', + componentProps: { + placeholder: '请输入优惠券描述', + }, + }, + { + fieldName: 'productScope', + label: '优惠劵类型', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.PROMOTION_PRODUCT_SCOPE, 'number'), + }, + rules: 'required', + defaultValue: PromotionProductScopeEnum.ALL.scope, + }, + { + fieldName: 'productSpuIds', + label: '商品', + component: 'Input', + componentProps: { + placeholder: '请选择商品', + }, + dependencies: { + triggerFields: ['productScope', 'productScopeValues'], + show: (model) => + model.productScope === PromotionProductScopeEnum.SPU.scope, + trigger(values, form) { + // 当加载已有数据时,根据 productScopeValues 设置 productSpuIds + if ( + values.productScope === PromotionProductScopeEnum.SPU.scope && + values.productScopeValues + ) { + form.setFieldValue('productSpuIds', values.productScopeValues); + } + }, + }, + rules: 'required', + }, + { + fieldName: 'productCategoryIds', + label: '商品分类', + component: 'Input', + componentProps: { + placeholder: '请选择商品分类', + }, + dependencies: { + triggerFields: ['productScope', 'productScopeValues'], + show: (model) => + model.productScope === PromotionProductScopeEnum.CATEGORY.scope, + trigger(values, form) { + // 当加载已有数据时,根据 productScopeValues 设置 productCategoryIds + if ( + values.productScope === PromotionProductScopeEnum.CATEGORY.scope && + values.productScopeValues + ) { + const categoryIds = values.productScopeValues; + // 单选时使用数组不能反显,取第一个元素 + form.setFieldValue( + 'productCategoryIds', + Array.isArray(categoryIds) && categoryIds.length > 0 + ? categoryIds[0] + : categoryIds, + ); + } + }, + }, + rules: 'required', + }, + { + fieldName: 'discountType', + label: '优惠类型', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.PROMOTION_DISCOUNT_TYPE, 'number'), + }, + rules: 'required', + defaultValue: PromotionDiscountTypeEnum.PRICE.type, + }, + { + fieldName: 'discountPrice', + label: '优惠券面额', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + placeholder: '请输入优惠金额,单位:元', + addonAfter: '元', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['discountType'], + show: (model) => + model.discountType === PromotionDiscountTypeEnum.PRICE.type, + }, + rules: 'required', + }, + { + fieldName: 'discountPercent', + label: '优惠券折扣', + component: 'InputNumber', + componentProps: { + min: 1, + max: 9.9, + precision: 1, + placeholder: '优惠券折扣不能小于 1 折,且不可大于 9.9 折', + addonAfter: '折', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['discountType'], + show: (model) => + model.discountType === PromotionDiscountTypeEnum.PERCENT.type, + }, + rules: 'required', + }, + { + fieldName: 'discountLimitPrice', + label: '最多优惠', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + placeholder: '请输入最多优惠', + addonAfter: '元', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['discountType'], + show: (model) => + model.discountType === PromotionDiscountTypeEnum.PERCENT.type, + }, + rules: 'required', + }, + { + fieldName: 'usePrice', + label: '满多少元可以使用', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + placeholder: '无门槛请设为 0', + addonAfter: '元', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'takeType', + label: '领取方式', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE, 'number'), + }, + rules: 'required', + defaultValue: CouponTemplateTakeTypeEnum.USER.type, + }, + { + fieldName: 'totalCount', + label: '发放数量', + component: 'InputNumber', + componentProps: { + min: -1, + placeholder: '发放数量,没有之后不能领取或发放,-1 为不限制', + addonAfter: '张', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['takeType'], + show: (model) => + model.takeType === CouponTemplateTakeTypeEnum.USER.type, + }, + rules: 'required', + }, + { + fieldName: 'takeLimitCount', + label: '每人限领个数', + component: 'InputNumber', + componentProps: { + min: -1, + placeholder: '设置为 -1 时,可无限领取', + addonAfter: '张', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['takeType'], + show: (model) => model.takeType === 1, + }, + rules: 'required', + }, + { + fieldName: 'validityType', + label: '有效期类型', + component: 'RadioGroup', + componentProps: { + options: getDictOptions( + DICT_TYPE.PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE, + 'number', + ), + }, + defaultValue: CouponTemplateValidityTypeEnum.DATE.type, + rules: 'required', + }, + { + fieldName: 'validTimes', + label: '固定日期', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + valueFormat: 'x', + }, + dependencies: { + triggerFields: ['validityType'], + show: (model) => + model.validityType === CouponTemplateValidityTypeEnum.DATE.type, + }, + rules: 'required', + }, + { + fieldName: 'fixedStartTerm', + label: '领取日期', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '第 0 为今天生效', + addonBefore: '第', + addonAfter: '天', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['validityType'], + show: (model) => + model.validityType === CouponTemplateValidityTypeEnum.TERM.type, + }, + rules: 'required', + }, + { + fieldName: 'fixedEndTerm', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入结束天数', + addonBefore: '至', + addonAfter: '天有效', + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['validityType'], + show: (model) => + model.validityType === CouponTemplateValidityTypeEnum.TERM.type, + }, + rules: 'required', + }, + { + fieldName: 'productScopeValues', + component: 'Input', + dependencies: { + triggerFields: ['productScope', 'productSpuIds', 'productCategoryIds'], + show: () => false, + trigger(values, form) { + switch (values.productScope) { + case PromotionProductScopeEnum.CATEGORY.scope: { + const categoryIds = Array.isArray(values.productCategoryIds) + ? values.productCategoryIds + : [values.productCategoryIds]; + form.setFieldValue('productScopeValues', categoryIds); + break; + } + case PromotionProductScopeEnum.SPU.scope: { + form.setFieldValue('productScopeValues', values.productSpuIds); + break; + } + } + }, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '优惠券名称', + component: 'Input', + componentProps: { + placeholder: '请输入优惠劵名', + clearable: true, + }, + }, + { + fieldName: 'discountType', + label: '优惠类型', + component: 'Select', + componentProps: { + placeholder: '请选择优惠类型', + clearable: true, + options: getDictOptions(DICT_TYPE.PROMOTION_DISCOUNT_TYPE, 'number'), + }, + }, + { + fieldName: 'status', + label: '优惠券状态', + component: 'Select', + componentProps: { + placeholder: '请选择优惠券状态', + clearable: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onStatusChange?: ( + newStatus: number, + row: MallCouponTemplateApi.CouponTemplate, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '优惠券名称', + minWidth: 140, + }, + { + field: 'productScope', + title: '类型', + minWidth: 130, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_PRODUCT_SCOPE }, + }, + }, + { + field: 'discountType', + title: '优惠', + minWidth: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_DISCOUNT_TYPE }, + }, + }, + { + field: 'discountPrice', + title: '优惠力度', + minWidth: 110, + formatter: ({ row }) => { + return discountFormat(row); + }, + }, + { + field: 'takeType', + title: '领取方式', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE }, + }, + }, + { + field: 'validityType', + title: '使用时间', + minWidth: 180, + formatter: ({ row }) => { + return validityTypeFormat(row); + }, + }, + { + field: 'totalCount', + title: '发放数量', + minWidth: 100, + formatter: ({ row }) => { + return totalCountFormat(row); + }, + }, + { + field: 'remainedCount', + title: '剩余数量', + minWidth: 100, + formatter: ({ row }) => { + return remainedCountFormat(row); + }, + }, + { + field: 'takeLimitCount', + title: '领取上限', + minWidth: 100, + formatter: ({ row }) => { + return takeLimitCountFormat(row); + }, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + align: 'center', + cellRender: { + attrs: { beforeChange: onStatusChange }, + name: 'CellSwitch', + props: { + activeValue: CommonStatusEnum.ENABLE, + inactiveValue: CommonStatusEnum.DISABLE, + }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/coupon/template/index.vue b/apps/web-ele/src/views/mall/promotion/coupon/template/index.vue new file mode 100644 index 0000000..cbe9993 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/template/index.vue @@ -0,0 +1,161 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/coupon/template/modules/form.vue b/apps/web-ele/src/views/mall/promotion/coupon/template/modules/form.vue new file mode 100644 index 0000000..a7f4996 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/coupon/template/modules/form.vue @@ -0,0 +1,178 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/discountActivity/data.ts b/apps/web-ele/src/views/mall/promotion/discountActivity/data.ts new file mode 100644 index 0000000..559f744 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/discountActivity/data.ts @@ -0,0 +1,167 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDate } from '@vben/utils'; + +/** 表单配置 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '活动名称', + component: 'Input', + componentProps: { + placeholder: '请输入活动名称', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '活动状态', + component: 'Select', + componentProps: { + placeholder: '请选择活动状态', + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: 'required', + }, + { + fieldName: 'startTime', + label: '开始时间', + component: 'DatePicker', + componentProps: { + placeholder: '请选择开始时间', + showTime: false, + valueFormat: 'x', + format: 'YYYY-MM-DD', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'endTime', + label: '结束时间', + component: 'DatePicker', + componentProps: { + placeholder: '请选择结束时间', + showTime: false, + valueFormat: 'x', + format: 'YYYY-MM-DD', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 4, + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'spuIds', + label: '活动商品', + component: 'Input', + formItemClass: 'col-span-2', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '活动名称', + component: 'Input', + componentProps: { + placeholder: '请输入活动名称', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '活动状态', + component: 'Select', + componentProps: { + placeholder: '请选择活动状态', + clearable: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + { + fieldName: 'activeTime', + label: '活动时间', + component: 'RangePicker', + componentProps: { + placeholder: ['开始时间', '结束时间'], + clearable: true, + valueFormat: 'YYYY-MM-DD HH:mm:ss', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '活动编号', + minWidth: 80, + }, + { + field: 'name', + title: '活动名称', + minWidth: 140, + }, + { + field: 'activityTime', + title: '活动时间', + minWidth: 210, + formatter: ({ row }) => { + if (!row.startTime || !row.endTime) return ''; + return `${formatDate(row.startTime, 'YYYY-MM-DD')} ~ ${formatDate(row.endTime, 'YYYY-MM-DD')}`; + }, + }, + { + field: 'status', + title: '活动状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/discountActivity/index.vue b/apps/web-ele/src/views/mall/promotion/discountActivity/index.vue new file mode 100644 index 0000000..b9a5e72 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/discountActivity/index.vue @@ -0,0 +1,164 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/discountActivity/modules/form.vue b/apps/web-ele/src/views/mall/promotion/discountActivity/modules/form.vue new file mode 100644 index 0000000..3dd8c18 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/discountActivity/modules/form.vue @@ -0,0 +1,364 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/diy/page/data.ts b/apps/web-ele/src/views/mall/promotion/diy/page/data.ts new file mode 100644 index 0000000..cec26ff --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/diy/page/data.ts @@ -0,0 +1,110 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单配置 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '页面名称', + component: 'Input', + componentProps: { + placeholder: '请输入页面名称', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 4, + }, + }, + { + fieldName: 'previewPicUrls', + component: 'ImageUpload', + label: '预览图', + componentProps: { + maxNumber: 10, + multiple: true, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '页面名称', + component: 'Input', + componentProps: { + placeholder: '请输入页面名称', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 80, + }, + { + field: 'previewPicUrls', + title: '预览图', + minWidth: 120, + cellRender: { + name: 'CellImages', + }, + }, + { + field: 'name', + title: '页面名称', + minWidth: 150, + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/diy/page/decorate/index.vue b/apps/web-ele/src/views/mall/promotion/diy/page/decorate/index.vue new file mode 100644 index 0000000..2dddd59 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/diy/page/decorate/index.vue @@ -0,0 +1,65 @@ + + diff --git a/apps/web-ele/src/views/mall/promotion/diy/page/index.vue b/apps/web-ele/src/views/mall/promotion/diy/page/index.vue new file mode 100644 index 0000000..af3b0cf --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/diy/page/index.vue @@ -0,0 +1,152 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/diy/page/modules/form.vue b/apps/web-ele/src/views/mall/promotion/diy/page/modules/form.vue new file mode 100644 index 0000000..b44b4a6 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/diy/page/modules/form.vue @@ -0,0 +1,84 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/diy/template/data.ts b/apps/web-ele/src/views/mall/promotion/diy/template/data.ts new file mode 100644 index 0000000..e3c8f14 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/diy/template/data.ts @@ -0,0 +1,121 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 表单配置 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '模板名称', + component: 'Input', + componentProps: { + placeholder: '请输入模板名称', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 4, + }, + }, + { + fieldName: 'previewPicUrls', + component: 'ImageUpload', + label: '预览图', + componentProps: { + maxNumber: 10, + multiple: true, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '模板名称', + component: 'Input', + componentProps: { + placeholder: '请输入模板名称', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 80, + }, + { + field: 'previewPicUrls', + title: '预览图', + minWidth: 120, + cellRender: { + name: 'CellImages', + }, + }, + { + field: 'name', + title: '模板名称', + minWidth: 150, + }, + { + field: 'used', + title: '是否使用', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 250, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/diy/template/decorate/index.vue b/apps/web-ele/src/views/mall/promotion/diy/template/decorate/index.vue new file mode 100644 index 0000000..b2fd164 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/diy/template/decorate/index.vue @@ -0,0 +1,215 @@ + + diff --git a/apps/web-ele/src/views/mall/promotion/diy/template/index.vue b/apps/web-ele/src/views/mall/promotion/diy/template/index.vue new file mode 100644 index 0000000..df68ff8 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/diy/template/index.vue @@ -0,0 +1,180 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/diy/template/modules/form.vue b/apps/web-ele/src/views/mall/promotion/diy/template/modules/form.vue new file mode 100644 index 0000000..8e088d7 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/diy/template/modules/form.vue @@ -0,0 +1,86 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/a.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/a.png new file mode 100644 index 0000000..3293900 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/a.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/aini.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/aini.png new file mode 100644 index 0000000..02cf5c4 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/aini.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/aixin.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/aixin.png new file mode 100644 index 0000000..25e6422 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/aixin.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/baiyan.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/baiyan.png new file mode 100644 index 0000000..d16260a Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/baiyan.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/bizui.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/bizui.png new file mode 100644 index 0000000..a3b1800 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/bizui.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/buhaoyisi.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/buhaoyisi.png new file mode 100644 index 0000000..54c4b3f Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/buhaoyisi.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/bukesiyi.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/bukesiyi.png new file mode 100644 index 0000000..5f272e3 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/bukesiyi.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/dajing.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/dajing.png new file mode 100644 index 0000000..8649727 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/dajing.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/danao.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/danao.png new file mode 100644 index 0000000..aa85a29 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/danao.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/daxiao.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/daxiao.png new file mode 100644 index 0000000..26206bc Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/daxiao.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/dianzan.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/dianzan.png new file mode 100644 index 0000000..2e7f00e Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/dianzan.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/emo.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/emo.png new file mode 100644 index 0000000..9c84551 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/emo.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/esi.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/esi.png new file mode 100644 index 0000000..84e9726 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/esi.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/fadai.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/fadai.png new file mode 100644 index 0000000..0772de2 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/fadai.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/fankun.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/fankun.png new file mode 100644 index 0000000..6e18dac Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/fankun.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/feiwen.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/feiwen.png new file mode 100644 index 0000000..be97616 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/feiwen.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/fennu.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/fennu.png new file mode 100644 index 0000000..20c5733 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/fennu.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/ganga.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/ganga.png new file mode 100644 index 0000000..30ec329 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/ganga.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/ganmao.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/ganmao.png new file mode 100644 index 0000000..35bbb89 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/ganmao.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/hanyan.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/hanyan.png new file mode 100644 index 0000000..a0bc838 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/hanyan.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/haochi.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/haochi.png new file mode 100644 index 0000000..2e52b6b Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/haochi.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/hongxin.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/hongxin.png new file mode 100644 index 0000000..65b5de8 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/hongxin.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/huaixiao.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/huaixiao.png new file mode 100644 index 0000000..bc0e76c Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/huaixiao.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/jingkong.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/jingkong.png new file mode 100644 index 0000000..7aa6584 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/jingkong.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/jingshu.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/jingshu.png new file mode 100644 index 0000000..0e984d6 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/jingshu.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/jingya.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/jingya.png new file mode 100644 index 0000000..9ba6bab Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/jingya.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/kaixin.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/kaixin.png new file mode 100644 index 0000000..29c9f5d Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/kaixin.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/keai.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/keai.png new file mode 100644 index 0000000..d3b582c Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/keai.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/keshui.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/keshui.png new file mode 100644 index 0000000..cef489e Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/keshui.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/kun.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/kun.png new file mode 100644 index 0000000..1ddc388 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/kun.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/lengku.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/lengku.png new file mode 100644 index 0000000..c5c6fee Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/lengku.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/liuhan.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/liuhan.png new file mode 100644 index 0000000..e6ddc6f Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/liuhan.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/liukoushui.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/liukoushui.png new file mode 100644 index 0000000..3e2fba6 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/liukoushui.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/liulei.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/liulei.png new file mode 100644 index 0000000..dbf8204 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/liulei.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/mengbi.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/mengbi.png new file mode 100644 index 0000000..a4206ee Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/mengbi.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/mianwubiaoqing.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/mianwubiaoqing.png new file mode 100644 index 0000000..6f315b9 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/mianwubiaoqing.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/nanguo.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/nanguo.png new file mode 100644 index 0000000..19b9fb9 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/nanguo.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/outu.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/outu.png new file mode 100644 index 0000000..2f9a06d Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/outu.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/picture.svg b/apps/web-ele/src/views/mall/promotion/kefu/asserts/picture.svg new file mode 100644 index 0000000..8811d49 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/asserts/picture.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/shengqi.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/shengqi.png new file mode 100644 index 0000000..7dce41d Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/shengqi.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/shuizhuo.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/shuizhuo.png new file mode 100644 index 0000000..97d0f0a Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/shuizhuo.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/tianshi.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/tianshi.png new file mode 100644 index 0000000..eb922dd Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/tianshi.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/xiaodiaoya.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/xiaodiaoya.png new file mode 100644 index 0000000..29fbc0e Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/xiaodiaoya.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/xiaoku.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/xiaoku.png new file mode 100644 index 0000000..88a169d Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/xiaoku.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/xinsui.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/xinsui.png new file mode 100644 index 0000000..a0f572a Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/xinsui.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/xiong.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/xiong.png new file mode 100644 index 0000000..43dfd70 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/xiong.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/yiwen.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/yiwen.png new file mode 100644 index 0000000..4c0da70 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/yiwen.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/yun.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/yun.png new file mode 100644 index 0000000..56e5d02 Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/yun.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/asserts/ziya.png b/apps/web-ele/src/views/mall/promotion/kefu/asserts/ziya.png new file mode 100644 index 0000000..593ef5e Binary files /dev/null and b/apps/web-ele/src/views/mall/promotion/kefu/asserts/ziya.png differ diff --git a/apps/web-ele/src/views/mall/promotion/kefu/index.vue b/apps/web-ele/src/views/mall/promotion/kefu/index.vue new file mode 100644 index 0000000..096cb0c --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/index.vue @@ -0,0 +1,122 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/conversation-list.vue b/apps/web-ele/src/views/mall/promotion/kefu/modules/conversation-list.vue new file mode 100644 index 0000000..9f22f84 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/conversation-list.vue @@ -0,0 +1,250 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/member/member-info.vue b/apps/web-ele/src/views/mall/promotion/kefu/modules/member/member-info.vue new file mode 100644 index 0000000..4b87f37 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/member/member-info.vue @@ -0,0 +1,224 @@ + + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/member/order-browsing-history.vue b/apps/web-ele/src/views/mall/promotion/kefu/modules/member/order-browsing-history.vue new file mode 100644 index 0000000..a7a5fa6 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/member/order-browsing-history.vue @@ -0,0 +1,47 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/member/product-browsing-history.vue b/apps/web-ele/src/views/mall/promotion/kefu/modules/member/product-browsing-history.vue new file mode 100644 index 0000000..c35d87b --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/member/product-browsing-history.vue @@ -0,0 +1,58 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/message-list.vue b/apps/web-ele/src/views/mall/promotion/kefu/modules/message-list.vue new file mode 100644 index 0000000..6331870 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/message-list.vue @@ -0,0 +1,429 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/message/message-item.vue b/apps/web-ele/src/views/mall/promotion/kefu/modules/message/message-item.vue new file mode 100644 index 0000000..7c8e315 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/message/message-item.vue @@ -0,0 +1,25 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/message/order-item.vue b/apps/web-ele/src/views/mall/promotion/kefu/modules/message/order-item.vue new file mode 100644 index 0000000..ff0ecd9 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/message/order-item.vue @@ -0,0 +1,121 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/message/product-item.vue b/apps/web-ele/src/views/mall/promotion/kefu/modules/message/product-item.vue new file mode 100644 index 0000000..da58082 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/message/product-item.vue @@ -0,0 +1,73 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/constants.ts b/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/constants.ts new file mode 100644 index 0000000..266a6cf --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/constants.ts @@ -0,0 +1,17 @@ +/** 客服消息类型枚举类 */ +export const KeFuMessageContentTypeEnum = { + TEXT: 1, // 文本消息 + IMAGE: 2, // 图片消息 + VOICE: 3, // 语音消息 + VIDEO: 4, // 视频消息 + SYSTEM: 5, // 系统消息 + // ========== 商城特殊消息 ========== + PRODUCT: 10, // 商品消息 + ORDER: 11, // 订单消息" +}; + +/** Promotion 的 WebSocket 消息类型枚举类 */ +export const WebSocketMessageTypeConstants = { + KEFU_MESSAGE_TYPE: 'kefu_message_type', // 客服消息类型 + KEFU_MESSAGE_ADMIN_READ: 'kefu_message_read_status_change', // 客服消息管理员已读 +}; diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/emoji-select-popover.vue b/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/emoji-select-popover.vue new file mode 100644 index 0000000..2d14ec1 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/emoji-select-popover.vue @@ -0,0 +1,53 @@ + + + + diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/emoji.ts b/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/emoji.ts new file mode 100644 index 0000000..f1bd193 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/emoji.ts @@ -0,0 +1,126 @@ +import { onMounted, ref } from 'vue'; + +import { isEmpty } from '@vben/utils'; + +const emojiList = [ + { name: '[笑掉牙]', file: 'xiaodiaoya.png' }, + { name: '[可爱]', file: 'keai.png' }, + { name: '[冷酷]', file: 'lengku.png' }, + { name: '[闭嘴]', file: 'bizui.png' }, + { name: '[生气]', file: 'shengqi.png' }, + { name: '[惊恐]', file: 'jingkong.png' }, + { name: '[瞌睡]', file: 'keshui.png' }, + { name: '[大笑]', file: 'daxiao.png' }, + { name: '[爱心]', file: 'aixin.png' }, + { name: '[坏笑]', file: 'huaixiao.png' }, + { name: '[飞吻]', file: 'feiwen.png' }, + { name: '[疑问]', file: 'yiwen.png' }, + { name: '[开心]', file: 'kaixin.png' }, + { name: '[发呆]', file: 'fadai.png' }, + { name: '[流泪]', file: 'liulei.png' }, + { name: '[汗颜]', file: 'hanyan.png' }, + { name: '[惊悚]', file: 'jingshu.png' }, + { name: '[困~]', file: 'kun.png' }, + { name: '[心碎]', file: 'xinsui.png' }, + { name: '[天使]', file: 'tianshi.png' }, + { name: '[晕]', file: 'yun.png' }, + { name: '[啊]', file: 'a.png' }, + { name: '[愤怒]', file: 'fennu.png' }, + { name: '[睡着]', file: 'shuizhuo.png' }, + { name: '[面无表情]', file: 'mianwubiaoqing.png' }, + { name: '[难过]', file: 'nanguo.png' }, + { name: '[犯困]', file: 'fankun.png' }, + { name: '[好吃]', file: 'haochi.png' }, + { name: '[呕吐]', file: 'outu.png' }, + { name: '[龇牙]', file: 'ziya.png' }, + { name: '[懵比]', file: 'mengbi.png' }, + { name: '[白眼]', file: 'baiyan.png' }, + { name: '[饿死]', file: 'esi.png' }, + { name: '[凶]', file: 'xiong.png' }, + { name: '[感冒]', file: 'ganmao.png' }, + { name: '[流汗]', file: 'liuhan.png' }, + { name: '[笑哭]', file: 'xiaoku.png' }, + { name: '[流口水]', file: 'liukoushui.png' }, + { name: '[尴尬]', file: 'ganga.png' }, + { name: '[惊讶]', file: 'jingya.png' }, + { name: '[大惊]', file: 'dajing.png' }, + { name: '[不好意思]', file: 'buhaoyisi.png' }, + { name: '[大闹]', file: 'danao.png' }, + { name: '[不可思议]', file: 'bukesiyi.png' }, + { name: '[爱你]', file: 'aini.png' }, + { name: '[红心]', file: 'hongxin.png' }, + { name: '[点赞]', file: 'dianzan.png' }, + { name: '[恶魔]', file: 'emo.png' }, +]; + +export interface Emoji { + name: string; + url: string; +} + +export function useEmoji() { + const emojiPathList = ref([]); + + /** 加载本地图片 */ + async function initStaticEmoji() { + const pathList = import.meta.glob('../../asserts/*.{png,jpg,jpeg,svg}'); + for (const path in pathList) { + const imageModule: any = await pathList[path]?.(); + emojiPathList.value.push({ path, src: imageModule.default }); + } + } + + /** 初始化 */ + onMounted(async () => { + if (isEmpty(emojiPathList.value)) { + await initStaticEmoji(); + } + }); + + /** + * 将文本中的表情替换成图片 + * + * @return 替换后的文本 + * @param content 消息内容 + */ + function replaceEmoji(content: string) { + let newData = content; + if (typeof newData !== 'object') { + const reg = /\[(.+?)\]/g; // [] 中括号 + const zhEmojiName = newData.match(reg); + if (zhEmojiName) { + zhEmojiName.forEach((item) => { + const emojiFile = getEmojiFileByName(item); + newData = newData.replace( + item, + ``, + ); + }); + } + } + return newData; + } + + /** 获得所有表情 */ + function getEmojiList(): Emoji[] { + return emojiList.map((item) => ({ + url: getEmojiFileByName(item.name), + name: item.name, + })) as Emoji[]; + } + + function getEmojiFileByName(name: string) { + for (const emoji of emojiList) { + if (emoji.name === name) { + const emojiPath = emojiPathList.value.find( + (item: { path: string; src: string }) => + item.path.includes(emoji.file), + ); + return emojiPath ? emojiPath.src : undefined; + } + } + return false; + } + + return { replaceEmoji, getEmojiList }; +} diff --git a/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/picture-select-upload.vue b/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/picture-select-upload.vue new file mode 100644 index 0000000..b991f04 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/kefu/modules/tools/picture-select-upload.vue @@ -0,0 +1,90 @@ + + + + diff --git a/apps/web-ele/src/views/mall/promotion/point/activity/data.ts b/apps/web-ele/src/views/mall/promotion/point/activity/data.ts new file mode 100644 index 0000000..7823157 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/point/activity/data.ts @@ -0,0 +1,138 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { fenToYuan } from '@vben/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'status', + label: '活动状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择活动状态', + clearable: true, + }, + }, + ]; +} + +/** 列表的表格列 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '活动编号', + minWidth: 80, + }, + { + field: 'picUrl', + title: '商品图片', + minWidth: 80, + cellRender: { + name: 'CellImage', + props: { + height: 40, + }, + }, + }, + { + field: 'spuName', + title: '商品标题', + minWidth: 300, + }, + { + field: 'marketPrice', + title: '原价', + minWidth: 100, + formatter: ({ row }) => `¥${fenToYuan(row.marketPrice)}`, + }, + { + field: 'status', + title: '活动状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'stock', + title: '库存', + minWidth: 80, + }, + { + field: 'totalStock', + title: '总库存', + minWidth: 80, + }, + { + field: 'redeemedQuantity', + title: '已兑换数量', + minWidth: 100, + formatter: ({ row }) => { + return (row.totalStock || 0) - (row.stock || 0); + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'sort', + label: '排序', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入排序', + controlsPosition: 'right', + class: '!w-full', + }, + defaultValue: 0, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 4, + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'spuId', + label: '活动商品', + component: 'Input', + rules: 'required', + formItemClass: 'col-span-2', + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/point/activity/index.vue b/apps/web-ele/src/views/mall/promotion/point/activity/index.vue new file mode 100644 index 0000000..dc8b105 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/point/activity/index.vue @@ -0,0 +1,157 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/point/activity/modules/form.vue b/apps/web-ele/src/views/mall/promotion/point/activity/modules/form.vue new file mode 100644 index 0000000..bf21ae0 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/point/activity/modules/form.vue @@ -0,0 +1,294 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/point/components/index.ts b/apps/web-ele/src/views/mall/promotion/point/components/index.ts new file mode 100644 index 0000000..4271f4e --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/point/components/index.ts @@ -0,0 +1,2 @@ +export { default as PointShowcase } from './showcase.vue'; +export { default as PointTableSelect } from './table-select.vue'; diff --git a/apps/web-ele/src/views/mall/promotion/point/components/showcase.vue b/apps/web-ele/src/views/mall/promotion/point/components/showcase.vue new file mode 100644 index 0000000..597395e --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/point/components/showcase.vue @@ -0,0 +1,149 @@ + + + + diff --git a/apps/web-ele/src/views/mall/promotion/point/components/table-select.vue b/apps/web-ele/src/views/mall/promotion/point/components/table-select.vue new file mode 100644 index 0000000..d4c1a2a --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/point/components/table-select.vue @@ -0,0 +1,240 @@ + + + + diff --git a/apps/web-ele/src/views/mall/promotion/rewardActivity/data.ts b/apps/web-ele/src/views/mall/promotion/rewardActivity/data.ts new file mode 100644 index 0000000..c1232e4 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/rewardActivity/data.ts @@ -0,0 +1,255 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { + DICT_TYPE, + PromotionConditionTypeEnum, + PromotionProductScopeEnum, +} from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { $t } from '@vben/locales'; + +import { z } from '#/adapter/form'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '活动名称', + component: 'Input', + componentProps: { + placeholder: '请输入活动名称', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '活动状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择活动状态', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '活动时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的表格列 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '活动名称', + minWidth: 200, + }, + { + field: 'productScope', + title: '活动范围', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_PRODUCT_SCOPE }, + }, + }, + { + field: 'startTime', + title: '活动开始时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'endTime', + title: '活动结束时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '活动名称', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入活动名称', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 4, + allowClear: true, + }, + }, + { + fieldName: 'startAndEndTime', + label: '活动时间', + component: 'RangePicker', + rules: 'required', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + placeholder: [ + $t('utils.rangePicker.beginTime'), + $t('utils.rangePicker.endTime'), + ], + }, + }, + { + fieldName: 'conditionType', + label: '条件类型', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.PROMOTION_CONDITION_TYPE, 'number'), + buttonStyle: 'solid', + optionType: 'button', + }, + rules: z.number().default(PromotionConditionTypeEnum.PRICE.type), + }, + { + fieldName: 'productScope', + label: '活动范围', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.PROMOTION_PRODUCT_SCOPE, 'number'), + buttonStyle: 'solid', + optionType: 'button', + }, + rules: z.number().default(PromotionProductScopeEnum.ALL.scope), + }, + { + fieldName: 'productSpuIds', + label: '选择商品', + component: 'Input', + dependencies: { + triggerFields: ['productScope', 'productScopeValues'], + show: (values) => { + return values.productScope === PromotionProductScopeEnum.SPU.scope; + }, + trigger(values, form) { + // 当加载已有数据时,根据 productScopeValues 设置 productSpuIds + if ( + values.productScope === PromotionProductScopeEnum.SPU.scope && + values.productScopeValues + ) { + form.setFieldValue('productSpuIds', values.productScopeValues); + } + }, + }, + rules: 'required', + }, + { + fieldName: 'productCategoryIds', + label: '选择分类', + component: 'Input', + dependencies: { + triggerFields: ['productScope', 'productScopeValues'], + show: (values) => { + return ( + values.productScope === PromotionProductScopeEnum.CATEGORY.scope + ); + }, + trigger(values, form) { + // 当加载已有数据时,根据 productScopeValues 设置 productCategoryIds + if ( + values.productScope === PromotionProductScopeEnum.CATEGORY.scope && + values.productScopeValues + ) { + const categoryIds = values.productScopeValues; + // 单选时使用数组不能反显,取第一个元素 + form.setFieldValue( + 'productCategoryIds', + Array.isArray(categoryIds) && categoryIds.length > 0 + ? categoryIds[0] + : categoryIds, + ); + } + }, + }, + rules: 'required', + }, + { + fieldName: 'rules', + label: '优惠设置', + component: 'Input', + formItemClass: 'items-start', + rules: z + .array(z.any()) + .min(1, { message: '请添加至少一条优惠规则' }) + .default([]), + }, + { + fieldName: 'productScopeValues', // 隐藏字段:用于自动同步 productScopeValues + component: 'Input', + dependencies: { + triggerFields: ['productScope', 'productSpuIds', 'productCategoryIds'], + show: () => false, + trigger(values, form) { + switch (values.productScope) { + case PromotionProductScopeEnum.CATEGORY.scope: { + const categoryIds = Array.isArray(values.productCategoryIds) + ? values.productCategoryIds + : [values.productCategoryIds]; + form.setFieldValue('productScopeValues', categoryIds); + break; + } + case PromotionProductScopeEnum.SPU.scope: { + form.setFieldValue('productScopeValues', values.productSpuIds); + break; + } + } + }, + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/rewardActivity/index.vue b/apps/web-ele/src/views/mall/promotion/rewardActivity/index.vue new file mode 100644 index 0000000..1b5d52a --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/rewardActivity/index.vue @@ -0,0 +1,158 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/rewardActivity/modules/form.vue b/apps/web-ele/src/views/mall/promotion/rewardActivity/modules/form.vue new file mode 100644 index 0000000..1bf6a89 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/rewardActivity/modules/form.vue @@ -0,0 +1,157 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/rewardActivity/modules/reward-rule-coupon-select.vue b/apps/web-ele/src/views/mall/promotion/rewardActivity/modules/reward-rule-coupon-select.vue new file mode 100644 index 0000000..ae400c2 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/rewardActivity/modules/reward-rule-coupon-select.vue @@ -0,0 +1,160 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/rewardActivity/modules/reward-rule.vue b/apps/web-ele/src/views/mall/promotion/rewardActivity/modules/reward-rule.vue new file mode 100644 index 0000000..afe05ed --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/rewardActivity/modules/reward-rule.vue @@ -0,0 +1,187 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/seckill/activity/data.ts b/apps/web-ele/src/views/mall/promotion/seckill/activity/data.ts new file mode 100644 index 0000000..b9e3a1d --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/seckill/activity/data.ts @@ -0,0 +1,244 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getSimpleSeckillConfigList } from '#/api/mall/promotion/seckill/seckillConfig'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '活动名称', + component: 'Input', + componentProps: { + placeholder: '请输入活动名称', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '活动状态', + component: 'Select', + componentProps: { + placeholder: '请选择活动状态', + clearable: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 新增/编辑的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '秒杀活动名称', + component: 'Input', + componentProps: { + placeholder: '请输入活动名称', + }, + rules: 'required', + formItemClass: 'col-span-2', + }, + { + fieldName: 'startTime', + label: '活动开始时间', + component: 'DatePicker', + componentProps: { + placeholder: '请选择活动开始时间', + type: 'datetime', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: 'w-full', + }, + rules: 'required', + }, + { + fieldName: 'endTime', + label: '活动结束时间', + component: 'DatePicker', + componentProps: { + placeholder: '请选择活动结束时间', + type: 'datetime', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + class: 'w-full', + }, + rules: 'required', + }, + { + fieldName: 'configIds', + label: '秒杀时段', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择秒杀时段', + multiple: true, + api: getSimpleSeckillConfigList, + labelField: 'name', + valueField: 'id', + class: 'w-full', + }, + rules: 'required', + formItemClass: 'col-span-2', + }, + { + fieldName: 'totalLimitCount', + label: '总限购数量', + component: 'InputNumber', + componentProps: { + placeholder: '请输入总限购数量', + min: 0, + class: 'w-full', + }, + rules: z.number().min(0).default(0), + }, + { + fieldName: 'singleLimitCount', + label: '单次限购数量', + component: 'InputNumber', + componentProps: { + placeholder: '请输入单次限购数量', + min: 0, + class: 'w-full', + }, + rules: z.number().min(0).default(0), + }, + { + fieldName: 'sort', + label: '排序', + component: 'InputNumber', + componentProps: { + placeholder: '请输入排序', + min: 0, + class: 'w-full', + }, + rules: z.number().min(0).default(0), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 4, + }, + formItemClass: 'col-span-2', + }, + { + fieldName: 'spuId', + label: '秒杀商品', + component: 'Input', + formItemClass: 'col-span-2', + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '活动编号', + minWidth: 80, + }, + { + field: 'name', + title: '活动名称', + minWidth: 140, + }, + { + field: 'configIds', + title: '秒杀时段', + minWidth: 220, + slots: { default: 'configIds' }, + }, + { + field: 'startTime', + title: '活动时间', + minWidth: 210, + slots: { default: 'timeRange' }, + }, + { + field: 'picUrl', + title: '商品图片', + minWidth: 80, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'spuName', + title: '商品标题', + minWidth: 300, + }, + { + field: 'marketPrice', + title: '原价', + minWidth: 100, + formatter: ({ row }) => `¥${(row.marketPrice / 100).toFixed(2)}`, + }, + { + field: 'seckillPrice', + title: '秒杀价', + minWidth: 100, + formatter: ({ row }) => { + if (!(row.products || row.products.length === 0)) { + return '¥0.00'; + } + const seckillPrice = Math.min( + ...row.products.map((item: any) => item.seckillPrice), + ); + return `¥${(seckillPrice / 100).toFixed(2)}`; + }, + }, + { + field: 'status', + title: '活动状态', + align: 'center', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'stock', + title: '库存', + align: 'center', + minWidth: 80, + }, + { + field: 'totalStock', + title: '总库存', + align: 'center', + minWidth: 80, + }, + { + field: 'createTime', + title: '创建时间', + align: 'center', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + align: 'center', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/seckill/activity/formatter.ts b/apps/web-ele/src/views/mall/promotion/seckill/activity/formatter.ts new file mode 100644 index 0000000..5ec39d3 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/seckill/activity/formatter.ts @@ -0,0 +1,37 @@ +import { formatDate } from '@vben/utils'; + +// 全局变量,用于存储配置列表 +let configList: any[] = []; + +/** 设置配置列表 */ +export function setConfigList(list: any[]) { + configList = list; +} + +/** 格式化配置名称 */ +export function formatConfigNames(configId: number | string): string { + const config = configList.find((item) => item.id === configId); + return config === null || config === undefined + ? '' + : `${config.name}[${config.startTime} ~ ${config.endTime}]`; +} + +/** 格式化秒杀价格 */ +export function formatSeckillPrice(products: any[]): string { + if (!products || products.length === 0) { + return '¥0.00'; + } + const seckillPrice = Math.min(...products.map((item) => item.seckillPrice)); + return `¥${(seckillPrice / 100).toFixed(2)}`; +} + +/** 格式化活动时间范围 */ +export function formatTimeRange( + startTime: Date | string | undefined, + endTime: Date | string | undefined, +): string { + if (startTime && endTime) { + return `${formatDate(startTime, 'YYYY-MM-DD')} ~ ${formatDate(endTime, 'YYYY-MM-DD')}`; + } + return ''; +} diff --git a/apps/web-ele/src/views/mall/promotion/seckill/activity/index.vue b/apps/web-ele/src/views/mall/promotion/seckill/activity/index.vue new file mode 100644 index 0000000..8ac8f39 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/seckill/activity/index.vue @@ -0,0 +1,191 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/seckill/activity/modules/form.vue b/apps/web-ele/src/views/mall/promotion/seckill/activity/modules/form.vue new file mode 100644 index 0000000..6575f39 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/seckill/activity/modules/form.vue @@ -0,0 +1,281 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/seckill/components/index.ts b/apps/web-ele/src/views/mall/promotion/seckill/components/index.ts new file mode 100644 index 0000000..dd45216 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/seckill/components/index.ts @@ -0,0 +1 @@ +export { default as SeckillShowcase } from './showcase.vue'; diff --git a/apps/web-ele/src/views/mall/promotion/seckill/components/showcase.vue b/apps/web-ele/src/views/mall/promotion/seckill/components/showcase.vue new file mode 100644 index 0000000..fd3ec97 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/seckill/components/showcase.vue @@ -0,0 +1,147 @@ + + + + diff --git a/apps/web-ele/src/views/mall/promotion/seckill/components/table-select.vue b/apps/web-ele/src/views/mall/promotion/seckill/components/table-select.vue new file mode 100644 index 0000000..ec3315b --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/seckill/components/table-select.vue @@ -0,0 +1,277 @@ + + + + diff --git a/apps/web-ele/src/views/mall/promotion/seckill/config/data.ts b/apps/web-ele/src/views/mall/promotion/seckill/config/data.ts new file mode 100644 index 0000000..85a7bf4 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/seckill/config/data.ts @@ -0,0 +1,153 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MallSeckillConfigApi } from '#/api/mall/promotion/seckill/seckillConfig'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '秒杀时段名称', + component: 'Input', + componentProps: { + placeholder: '请输入秒杀时段名称', + }, + rules: 'required', + }, + { + fieldName: 'startTime', + label: '开始时间点', + component: 'TimePicker', + componentProps: { + format: 'HH:mm', + valueFormat: 'HH:mm', + placeholder: '请选择开始时间点', + }, + rules: 'required', + }, + { + fieldName: 'endTime', + label: '结束时间点', + component: 'TimePicker', + componentProps: { + format: 'HH:mm', + valueFormat: 'HH:mm', + placeholder: '请选择结束时间点', + }, + rules: 'required', + }, + { + fieldName: 'sliderPicUrls', + label: '秒杀轮播图', + component: 'ImageUpload', + componentProps: { + multiple: true, + maxNumber: 5, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '秒杀时段名称', + component: 'Input', + componentProps: { + placeholder: '请输入秒杀时段名称', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + placeholder: '请选择状态', + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns( + onStatusChange?: ( + newStatus: number, + row: MallSeckillConfigApi.SeckillConfig, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + title: '秒杀时段名称', + field: 'name', + minWidth: 200, + }, + { + title: '开始时间点', + field: 'startTime', + minWidth: 120, + }, + { + title: '结束时间点', + field: 'endTime', + minWidth: 120, + }, + { + title: '秒杀轮播图', + field: 'sliderPicUrls', + minWidth: 100, + cellRender: { + name: 'CellImages', + }, + }, + { + title: '活动状态', + field: 'status', + minWidth: 100, + cellRender: { + attrs: { beforeChange: onStatusChange }, + name: 'CellSwitch', + props: { + checkedValue: 1, + checkedChildren: '启用', + unCheckedValue: 0, + unCheckedChildren: '禁用', + }, + }, + }, + { + title: '创建时间', + field: 'createTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/promotion/seckill/config/index.vue b/apps/web-ele/src/views/mall/promotion/seckill/config/index.vue new file mode 100644 index 0000000..073c763 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/seckill/config/index.vue @@ -0,0 +1,152 @@ + + + diff --git a/apps/web-ele/src/views/mall/promotion/seckill/config/modules/form.vue b/apps/web-ele/src/views/mall/promotion/seckill/config/modules/form.vue new file mode 100644 index 0000000..36aaf29 --- /dev/null +++ b/apps/web-ele/src/views/mall/promotion/seckill/config/modules/form.vue @@ -0,0 +1,90 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/member/index.vue b/apps/web-ele/src/views/mall/statistics/member/index.vue new file mode 100644 index 0000000..1e3f9dd --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/member/index.vue @@ -0,0 +1,113 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/area-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/area-card.vue new file mode 100644 index 0000000..7c71385 --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/member/modules/area-card.vue @@ -0,0 +1,101 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/area-chart-options.ts b/apps/web-ele/src/views/mall/statistics/member/modules/area-chart-options.ts new file mode 100644 index 0000000..b09f492 --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/member/modules/area-chart-options.ts @@ -0,0 +1,130 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MallMemberStatisticsApi } from '#/api/mall/statistics/member'; + +import { fenToYuan } from '@vben/utils'; + +/** 会员地域分布图表配置 */ +export function getAreaChartOptions( + data: MallMemberStatisticsApi.AreaStatisticsRespVO[], +): any { + if (!data || data.length === 0) { + return { + title: { + text: '暂无数据', + left: 'center', + top: 'center', + textStyle: { + color: '#999', + fontSize: 14, + }, + }, + }; + } + + // 计算 min 和 max 值 + let min = Number.POSITIVE_INFINITY; + let max = Number.NEGATIVE_INFINITY; + const mapData = data.map((item) => { + const payUserCount = item.orderPayUserCount || 0; + min = Math.min(min, payUserCount); + max = Math.max(max, payUserCount); + return { + ...item, + name: item.areaName, + value: payUserCount, + }; + }); + // 如果所有值都为 0,设置合理的 min 和 max 值 + if (min === max && min === 0) { + min = 0; + max = 10; + } + + // 返回图表配置 + return { + tooltip: { + trigger: 'item', + formatter: (params: any) => { + const itemData = params?.data; + if (!itemData) { + return `${params?.name || ''}
    暂无数据`; + } + return `${itemData.areaName || params.name}
    +会员数量:${itemData.userCount || 0}
    +订单创建数量:${itemData.orderCreateUserCount || 0}
    +订单支付数量:${itemData.orderPayUserCount || 0}
    +订单支付金额:¥${Number(fenToYuan(itemData.orderPayPrice || 0)).toFixed(2)}`; + }, + }, + visualMap: { + text: ['高', '低'], + realtime: false, + calculable: true, + top: 'middle', + left: 10, + min, + max, + inRange: { + color: ['#e6f3ff', '#1890ff', '#0050b3'], + }, + }, + series: [ + { + name: '会员地域分布', + type: 'map', + map: 'china', + roam: false, + selectedMode: false, + itemStyle: { + borderColor: '#389e0d', + borderWidth: 0.5, + }, + emphasis: { + itemStyle: { + areaColor: '#ffec3d', + borderWidth: 1, + }, + }, + data: mapData, + }, + ], + }; +} + +/** VXE Grid 表格列配置 */ +export function getAreaTableColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'areaName', + title: '省份', + minWidth: 80, + sortable: true, + showOverflow: 'tooltip', + }, + { + field: 'userCount', + title: '会员数量', + minWidth: 100, + sortable: true, + }, + { + field: 'orderCreateUserCount', + title: '订单创建数量', + minWidth: 120, + sortable: true, + }, + { + field: 'orderPayUserCount', + title: '订单支付数量', + minWidth: 120, + sortable: true, + }, + { + field: 'orderPayPrice', + title: '订单支付金额', + minWidth: 120, + sortable: true, + formatter: 'formatFenToYuanAmount', + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue new file mode 100644 index 0000000..845fd85 --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue @@ -0,0 +1,147 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/sex-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/sex-card.vue new file mode 100644 index 0000000..b646619 --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/member/modules/sex-card.vue @@ -0,0 +1,65 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/sex-chart-options.ts b/apps/web-ele/src/views/mall/statistics/member/modules/sex-chart-options.ts new file mode 100644 index 0000000..81a7faf --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/member/modules/sex-chart-options.ts @@ -0,0 +1,28 @@ +/** 会员性别比例图表配置 */ +export function getSexChartOptions(data: any[]): any { + return { + tooltip: { + trigger: 'item', + confine: true, + formatter: '{a}
    {b} : {c} ({d}%)', + }, + legend: { + orient: 'vertical', + left: 'right', + }, + series: [ + { + name: '会员性别', + type: 'pie', + roseType: 'area', + label: { + show: false, + }, + labelLine: { + show: false, + }, + data, + }, + ], + }; +} diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/terminal-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/terminal-card.vue new file mode 100644 index 0000000..50c088c --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/member/modules/terminal-card.vue @@ -0,0 +1,59 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/terminal-chart-options.ts b/apps/web-ele/src/views/mall/statistics/member/modules/terminal-chart-options.ts new file mode 100644 index 0000000..c3233bd --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/member/modules/terminal-chart-options.ts @@ -0,0 +1,27 @@ +/** 会员终端统计图配置 */ +export function getTerminalChartOptions(data: any[]): any { + return { + tooltip: { + trigger: 'item', + confine: true, + formatter: '{a}
    {b} : {c} ({d}%)', + }, + legend: { + orient: 'vertical', + left: 'right', + }, + series: [ + { + name: '会员终端', + type: 'pie', + label: { + show: false, + }, + labelLine: { + show: false, + }, + data, + }, + ], + }; +} diff --git a/apps/web-ele/src/views/mall/statistics/product/index.vue b/apps/web-ele/src/views/mall/statistics/product/index.vue new file mode 100644 index 0000000..2e38340 --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/product/index.vue @@ -0,0 +1,27 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/product/modules/rank-card.vue b/apps/web-ele/src/views/mall/statistics/product/modules/rank-card.vue new file mode 100644 index 0000000..0a7e34e --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/product/modules/rank-card.vue @@ -0,0 +1,138 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/product/modules/summary-card.vue b/apps/web-ele/src/views/mall/statistics/product/modules/summary-card.vue new file mode 100644 index 0000000..5d6b9bf --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/product/modules/summary-card.vue @@ -0,0 +1,261 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/product/modules/summary-chart-options.ts b/apps/web-ele/src/views/mall/statistics/product/modules/summary-chart-options.ts new file mode 100644 index 0000000..ec6e474 --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/product/modules/summary-chart-options.ts @@ -0,0 +1,129 @@ +/** 商品统计折线图配置 */ +export function getProductSummaryChartOptions(data: any[]): any { + // 处理数据:将金额从分转换为元 + const processedData = data.map((item) => ({ + ...item, + orderPayPrice: Number((item.orderPayPrice / 100).toFixed(2)), + afterSaleRefundPrice: Number((item.afterSaleRefundPrice / 100).toFixed(2)), + })); + + return { + dataset: { + dimensions: [ + 'time', + 'browseCount', + 'browseUserCount', + 'orderPayPrice', + 'afterSaleRefundPrice', + ], + source: processedData, + }, + grid: { + left: 20, + right: 20, + bottom: 20, + top: 80, + containLabel: true, + }, + legend: { + top: 50, + }, + series: [ + { + name: '商品浏览量', + type: 'line', + smooth: true, + itemStyle: { color: '#B37FEB' }, + }, + { + name: '商品访客数', + type: 'line', + smooth: true, + itemStyle: { color: '#FFAB2B' }, + }, + { + name: '支付金额', + type: 'bar', + smooth: true, + yAxisIndex: 1, + itemStyle: { color: '#1890FF' }, + }, + { + name: '退款金额', + type: 'bar', + smooth: true, + yAxisIndex: 1, + itemStyle: { color: '#00C050' }, + }, + ], + toolbox: { + feature: { + // 数据区域缩放 + dataZoom: { + yAxisIndex: false, // Y轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { + show: true, + name: '商品状况', + }, // 保存为图片 + }, + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + }, + padding: [5, 10], + }, + xAxis: { + type: 'category', + boundaryGap: true, + axisTick: { + show: false, + }, + }, + yAxis: [ + { + type: 'value', + name: '金额', + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + axisLabel: { + color: '#7F8B9C', + }, + splitLine: { + show: true, + lineStyle: { + color: '#F5F7F9', + }, + }, + }, + { + type: 'value', + name: '数量', + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + axisLabel: { + color: '#7F8B9C', + }, + splitLine: { + show: true, + lineStyle: { + color: '#F5F7F9', + }, + }, + }, + ], + }; +} diff --git a/apps/web-ele/src/views/mall/statistics/trade/index.vue b/apps/web-ele/src/views/mall/statistics/trade/index.vue new file mode 100644 index 0000000..0207bde --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/trade/index.vue @@ -0,0 +1,120 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/trade/modules/trend-card.vue b/apps/web-ele/src/views/mall/statistics/trade/modules/trend-card.vue new file mode 100644 index 0000000..8dd3f27 --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/trade/modules/trend-card.vue @@ -0,0 +1,293 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/trade/modules/trend-chart-options.ts b/apps/web-ele/src/views/mall/statistics/trade/modules/trend-chart-options.ts new file mode 100644 index 0000000..899a6a3 --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/trade/modules/trend-chart-options.ts @@ -0,0 +1,124 @@ +import type { MallTradeStatisticsApi } from '#/api/mall/statistics/trade'; + +import { fenToYuan } from '@vben/utils'; + +/** 交易趋势折线图配置 */ +export function getTradeTrendChartOptions( + data: MallTradeStatisticsApi.TradeTrendSummaryRespVO[], +): any { + // 处理数据:将分转换为元 + const processedData = data.map((item) => ({ + ...item, + turnoverPrice: Number(fenToYuan(item.turnoverPrice)), + orderPayPrice: Number(fenToYuan(item.orderPayPrice)), + rechargePrice: Number(fenToYuan(item.rechargePrice)), + expensePrice: Number(fenToYuan(item.expensePrice)), + })); + + return { + dataset: { + dimensions: [ + 'date', + 'turnoverPrice', + 'orderPayPrice', + 'rechargePrice', + 'expensePrice', + ], + source: processedData, + }, + grid: { + left: 20, + right: 20, + bottom: 20, + top: 80, + containLabel: true, + }, + legend: { + top: 50, + }, + series: [ + { + name: '营业额', + type: 'line', + smooth: true, + itemStyle: { color: '#1890FF' }, + }, + { + name: '商品支付金额', + type: 'line', + smooth: true, + itemStyle: { color: '#722ED1' }, + }, + { + name: '充值金额', + type: 'line', + smooth: true, + itemStyle: { color: '#FAAD14' }, + }, + { + name: '支出金额', + type: 'line', + smooth: true, + itemStyle: { color: '#52C41A' }, + }, + ], + toolbox: { + feature: { + // 数据区域缩放 + dataZoom: { + yAxisIndex: false, // Y轴不缩放 + }, + brush: { + type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮 + }, + saveAsImage: { + show: true, + name: '交易状况', + }, // 保存为图片 + }, + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + }, + padding: [5, 10], + formatter(params: any) { + let result = `
    ${params[0].data.time}
    `; + params.forEach((item: any) => { + result += `
    + + ${item.seriesName}: ¥${item.data[item.dimensionNames[item.encode.y[0]]]} +
    `; + }); + return result; + }, + }, + xAxis: { + type: 'category', + boundaryGap: false, + axisTick: { + show: false, + }, + }, + yAxis: { + type: 'value', + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + axisLabel: { + formatter: '¥{value}', + color: '#7F8B9C', + }, + splitLine: { + show: true, + lineStyle: { + color: '#F5F7F9', + }, + }, + }, + }; +} diff --git a/apps/web-ele/src/views/mall/trade/afterSale/data.ts b/apps/web-ele/src/views/mall/trade/afterSale/data.ts new file mode 100644 index 0000000..2aa4ecc --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/afterSale/data.ts @@ -0,0 +1,172 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeGridPropTypes } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 拒绝售后表单的 schema 配置 */ +export function useDisagreeFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Textarea', + fieldName: 'reason', + label: '拒绝原因', + componentProps: { + placeholder: '请输入拒绝原因', + rows: 4, + }, + rules: z.string().min(2, { message: '拒绝原因不能少于 2 个字符' }), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'spuName', + label: '商品名称', + component: 'Input', + componentProps: { + placeholder: '请输入商品名称', + }, + }, + { + fieldName: 'no', + label: '退款编号', + component: 'Input', + componentProps: { + placeholder: '请输入退款编号', + }, + }, + { + fieldName: 'orderNo', + label: '订单编号', + component: 'Input', + componentProps: { + placeholder: '请输入订单编号', + }, + }, + { + fieldName: 'status', + label: '售后状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.TRADE_AFTER_SALE_STATUS, 'number'), + placeholder: '请选择售后状态', + clearable: true, + }, + }, + { + fieldName: 'way', + label: '售后方式', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.TRADE_AFTER_SALE_WAY, 'number'), + placeholder: '请选择售后方式', + clearable: true, + }, + }, + { + fieldName: 'type', + label: '售后类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.TRADE_AFTER_SALE_TYPE, 'number'), + placeholder: '请选择售后类型', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns(): VxeGridPropTypes.Columns { + return [ + { + field: 'no', + title: '退款编号', + fixed: 'left', + minWidth: 200, + }, + { + field: 'orderNo', + title: '订单编号', + fixed: 'left', + minWidth: 200, + slots: { default: 'orderNo' }, + }, + { + field: 'productInfo', + title: '商品信息', + minWidth: 600, + slots: { default: 'productInfo' }, + }, + { + field: 'refundPrice', + title: '订单金额', + width: 120, + formatter: 'formatAmount2', + }, + { + field: 'user.nickname', + title: '买家', + minWidth: 120, + }, + { + field: 'createTime', + title: '申请时间', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'status', + title: '售后状态', + width: 100, + cellRender: { + name: 'CellDict', + props: { + type: DICT_TYPE.TRADE_AFTER_SALE_STATUS, + }, + }, + }, + { + field: 'way', + title: '售后方式', + width: 100, + cellRender: { + name: 'CellDict', + props: { + type: DICT_TYPE.TRADE_AFTER_SALE_WAY, + }, + }, + }, + { + title: '操作', + width: 160, + fixed: 'right', + align: 'center', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/afterSale/detail/data.ts b/apps/web-ele/src/views/mall/trade/afterSale/detail/data.ts new file mode 100644 index 0000000..1e532c9 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/afterSale/detail/data.ts @@ -0,0 +1,221 @@ +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { fenToYuan, formatDate } from '@vben/utils'; + +import { ElImage } from 'element-plus'; + +import { DictTag } from '#/components/dict-tag'; + +/** 订单信息 schema */ +export function useOrderInfoSchema(): DescriptionItemSchema[] { + return [ + { + field: 'orderNo', + label: '订单号', + }, + { + field: 'order.deliveryType', + label: '配送方式', + render: (val) => + h(DictTag, { + type: DICT_TYPE.TRADE_DELIVERY_TYPE, + value: val, + }), + }, + { + field: 'order.type', + label: '订单类型', + render: (val) => + h(DictTag, { + type: DICT_TYPE.TRADE_ORDER_TYPE, + value: val, + }), + }, + { + field: 'order.receiverName', + label: '收货人', + }, + { + field: 'order.userRemark', + label: '买家留言', + }, + { + field: 'order.terminal', + label: '订单来源', + render: (val) => + h(DictTag, { + type: DICT_TYPE.TERMINAL, + value: val, + }), + }, + { + field: 'order.receiverMobile', + label: '联系电话', + }, + { + field: 'order.remark', + label: '商家备注', + }, + { + field: 'order.payOrderId', + label: '支付单号', + }, + { + field: 'order.payChannelCode', + label: '付款方式', + render: (val) => + h(DictTag, { + type: DICT_TYPE.PAY_CHANNEL_CODE, + value: val, + }), + }, + { + field: 'user.nickname', + label: '买家', + }, + ]; +} + +/** 售后信息 schema */ +export function useAfterSaleInfoSchema(): DescriptionItemSchema[] { + return [ + { + field: 'no', + label: '退款编号', + }, + { + field: 'auditTime', + label: '申请时间', + render: (val) => formatDate(val) as string, + }, + { + field: 'type', + label: '售后类型', + render: (val) => + h(DictTag, { + type: DICT_TYPE.TRADE_AFTER_SALE_TYPE, + value: val, + }), + }, + { + field: 'way', + label: '售后方式', + render: (val) => + h(DictTag, { + type: DICT_TYPE.TRADE_AFTER_SALE_WAY, + value: val, + }), + }, + { + field: 'refundPrice', + label: '退款金额', + render: (val) => fenToYuan(val ?? 0), + }, + { + field: 'applyReason', + label: '退款原因', + }, + { + field: 'applyDescription', + label: '补充描述', + }, + { + field: 'applyPicUrls', + label: '凭证图片', + render: (val) => { + const images = val || []; + return h( + 'div', + { class: 'flex gap-10px' }, + images.map((url: string, index: number) => + h(ElImage, { + key: index, + src: url, + width: 60, + height: 60, + }), + ), + ); + }, + }, + ]; +} + +/** 退款状态 schema */ +export function useRefundStatusSchema(): DescriptionItemSchema[] { + return [ + { + field: 'status', + label: '退款状态', + render: (val) => + h(DictTag, { + type: DICT_TYPE.TRADE_AFTER_SALE_STATUS, + value: val, + }), + }, + { + field: 'reminder', + label: '提醒', + render: () => + h('div', { class: 'text-red-500 mb-10px' }, [ + h('div', '如果未发货,请点击同意退款给买家。'), + h('div', '如果实际已发货,请主动与买家联系。'), + h('div', '如果订单整体退款后,优惠券和余额会退还给买家.'), + ]), + }, + ]; +} + +/** 商品信息 columns */ +export function useProductColumns() { + return [ + { + field: 'spuName', + title: '商品信息', + minWidth: 300, + slots: { default: 'spuName' }, + }, + { + field: 'price', + title: '商品原价', + minWidth: 150, + formatter: 'formatFenToYuanAmount', + }, + { + field: 'count', + title: '数量', + minWidth: 100, + }, + { + field: 'payPrice', + title: '合计', + minWidth: 150, + formatter: 'formatFenToYuanAmount', + }, + ]; +} + +/** 操作日志 columns */ +export function useOperateLogSchema() { + return [ + { + field: 'createTime', + title: '操作时间', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'userType', + title: '操作人', + width: 100, + slots: { default: 'userType' }, + }, + { + field: 'content', + title: '操作内容', + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/afterSale/detail/index.vue b/apps/web-ele/src/views/mall/trade/afterSale/detail/index.vue new file mode 100644 index 0000000..66d4e6b --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/afterSale/detail/index.vue @@ -0,0 +1,307 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/afterSale/index.vue b/apps/web-ele/src/views/mall/trade/afterSale/index.vue new file mode 100644 index 0000000..8afaae7 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/afterSale/index.vue @@ -0,0 +1,157 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/afterSale/modules/disagree-form.vue b/apps/web-ele/src/views/mall/trade/afterSale/modules/disagree-form.vue new file mode 100644 index 0000000..c9d1adf --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/afterSale/modules/disagree-form.vue @@ -0,0 +1,78 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/brokerage/record/data.ts b/apps/web-ele/src/views/mall/trade/brokerage/record/data.ts new file mode 100644 index 0000000..a6ed265 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/brokerage/record/data.ts @@ -0,0 +1,137 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { fenToYuan } from '@vben/utils'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + placeholder: '请输入用户编号', + clearable: true, + }, + }, + { + fieldName: 'bizType', + label: '业务类型', + component: 'Select', + componentProps: { + placeholder: '请选择业务类型', + clearable: true, + options: getDictOptions(DICT_TYPE.BROKERAGE_RECORD_BIZ_TYPE, 'number'), + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + placeholder: '请选择状态', + clearable: true, + options: getDictOptions(DICT_TYPE.BROKERAGE_RECORD_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 60, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 80, + }, + { + field: 'userAvatar', + title: '头像', + minWidth: 70, + cellRender: { + name: 'CellImage', + props: { + height: 40, + width: 40, + shape: 'circle', + }, + }, + }, + { + field: 'userNickname', + title: '昵称', + minWidth: 80, + }, + { + field: 'bizType', + title: '业务类型', + minWidth: 85, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BROKERAGE_RECORD_BIZ_TYPE }, + }, + }, + { + field: 'bizId', + title: '业务编号', + minWidth: 80, + }, + { + field: 'title', + title: '标题', + minWidth: 110, + }, + { + field: 'price', + title: '金额', + minWidth: 60, + formatter: ({ row }) => `¥${fenToYuan(row.price)}`, + }, + { + field: 'description', + title: '说明', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 85, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BROKERAGE_RECORD_STATUS }, + }, + }, + { + field: 'unfreezeTime', + title: '解冻时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'createTime', + title: '创建时间', + width: 180, + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/brokerage/record/index.vue b/apps/web-ele/src/views/mall/trade/brokerage/record/index.vue new file mode 100644 index 0000000..a959648 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/brokerage/record/index.vue @@ -0,0 +1,56 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/brokerage/user/data.ts b/apps/web-ele/src/views/mall/trade/brokerage/user/data.ts new file mode 100644 index 0000000..903935b --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/brokerage/user/data.ts @@ -0,0 +1,367 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MallBrokerageUserApi } from '#/api/mall/trade/brokerage/user'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { fenToYuan } from '@vben/utils'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'bindUserId', + label: '推广员编号', + component: 'Input', + componentProps: { + placeholder: '请输入推广员编号', + clearable: true, + }, + }, + { + fieldName: 'brokerageEnabled', + label: '推广资格', + component: 'Select', + componentProps: { + placeholder: '请选择推广资格', + clearable: true, + options: [ + { label: '有', value: true }, + { label: '无', value: false }, + ], + }, + defaultValue: true, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onBrokerageEnabledChange?: ( + newEnabled: boolean, + row: MallBrokerageUserApi.BrokerageUser, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '用户编号', + minWidth: 80, + }, + { + field: 'avatar', + title: '头像', + minWidth: 70, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'nickname', + title: '昵称', + minWidth: 80, + }, + { + field: 'brokerageUserCount', + title: '推广人数', + minWidth: 80, + }, + { + field: 'brokerageOrderCount', + title: '推广订单数量', + minWidth: 110, + }, + { + field: 'brokerageOrderPrice', + title: '推广订单金额', + minWidth: 110, + formatter: ({ row }) => `¥${fenToYuan(row.brokerageOrderPrice)}`, + }, + { + field: 'withdrawPrice', + title: '已提现金额', + minWidth: 100, + formatter: ({ row }) => `¥${fenToYuan(row.withdrawPrice)}`, + }, + { + field: 'withdrawCount', + title: '已提现次数', + minWidth: 100, + }, + { + field: 'price', + title: '未提现金额', + minWidth: 100, + formatter: ({ row }) => `¥${fenToYuan(row.price)}`, + }, + { + field: 'frozenPrice', + title: '冻结中佣金', + minWidth: 100, + formatter: ({ row }) => `¥${fenToYuan(row.frozenPrice)}`, + }, + { + field: 'brokerageEnabled', + title: '推广资格', + minWidth: 80, + align: 'center', + cellRender: { + attrs: { beforeChange: onBrokerageEnabledChange }, + name: 'CellSwitch', + props: { + activeValue: true, + inactiveValue: false, + activeText: '有', + inactiveText: '无', + }, + }, + }, + { + field: 'brokerageTime', + title: '成为推广员时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'bindUserId', + title: '上级推广员编号', + minWidth: 150, + }, + { + field: 'bindUserTime', + title: '推广员绑定时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 创建分销员表单配置 */ +export function useCreateFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '分销员编号', + component: 'Input', + componentProps: { + placeholder: '请输入分销员编号', + }, + rules: 'required', + }, + { + fieldName: 'bindUserId', + label: '上级推广员编号', + component: 'Input', + componentProps: { + placeholder: '请输入上级推广员编号', + }, + rules: 'required', + }, + ]; +} + +/** 修改分销用户表单配置 */ +export function useUpdateFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'bindUserId', + label: '上级推广员编号', + component: 'Input', + componentProps: { + placeholder: '请输入上级推广员编号', + }, + rules: 'required', + }, + ]; +} + +/** 用户列表弹窗搜索表单配置 */ +export function useUserListFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'level', + label: '用户类型', + component: 'Select', + componentProps: { + options: [ + { label: '全部', value: undefined }, + { label: '一级推广人', value: '1' }, + { label: '二级推广人', value: '2' }, + ], + clearable: true, + }, + }, + { + fieldName: 'bindUserTime', + label: '绑定时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 用户列表弹窗表格列配置 */ +export function useUserListColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '用户编号', + minWidth: 80, + }, + { + field: 'avatar', + title: '头像', + minWidth: 70, + cellRender: { + name: 'CellImage', + props: { + width: 24, + height: 24, + shape: 'circle', + }, + }, + }, + { + field: 'nickname', + title: '昵称', + minWidth: 80, + }, + { + field: 'brokerageUserCount', + title: '推广人数', + minWidth: 80, + }, + { + field: 'brokerageOrderCount', + title: '推广订单数量', + minWidth: 110, + }, + { + field: 'brokerageEnabled', + title: '推广资格', + minWidth: 80, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'bindUserTime', + title: '绑定时间', + width: 180, + formatter: 'formatDateTime', + }, + ]; +} + +/** 推广订单列表弹窗搜索表单配置 */ +export function useOrderListFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'sourceUserLevel', + label: '用户类型', + component: 'Select', + componentProps: { + options: [ + { label: '全部', value: 0 }, + { label: '一级推广人', value: 1 }, + { label: '二级推广人', value: 2 }, + ], + }, + defaultValue: 0, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + placeholder: '请选择状态', + clearable: true, + options: getDictOptions(DICT_TYPE.BROKERAGE_RECORD_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 推广订单列表弹窗表格列配置 */ +export function useOrderListColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'bizId', + title: '订单编号', + minWidth: 80, + }, + { + field: 'sourceUserId', + title: '用户编号', + minWidth: 80, + }, + { + field: 'sourceUserAvatar', + title: '头像', + minWidth: 70, + cellRender: { + name: 'CellImage', + props: { + width: 24, + height: 24, + }, + }, + }, + { + field: 'sourceUserNickname', + title: '昵称', + minWidth: 80, + }, + { + field: 'price', + title: '佣金', + minWidth: 100, + formatter: ({ row }) => `¥${fenToYuan(row.price)}`, + }, + { + field: 'status', + title: '状态', + minWidth: 85, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BROKERAGE_RECORD_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + width: 180, + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/brokerage/user/index.vue b/apps/web-ele/src/views/mall/trade/brokerage/user/index.vue new file mode 100644 index 0000000..5b7d958 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/brokerage/user/index.vue @@ -0,0 +1,210 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/brokerage/user/modules/create-form.vue b/apps/web-ele/src/views/mall/trade/brokerage/user/modules/create-form.vue new file mode 100644 index 0000000..0ceb8bc --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/brokerage/user/modules/create-form.vue @@ -0,0 +1,191 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/brokerage/user/modules/order-list-modal.vue b/apps/web-ele/src/views/mall/trade/brokerage/user/modules/order-list-modal.vue new file mode 100644 index 0000000..7e9520f --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/brokerage/user/modules/order-list-modal.vue @@ -0,0 +1,61 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/brokerage/user/modules/update-form.vue b/apps/web-ele/src/views/mall/trade/brokerage/user/modules/update-form.vue new file mode 100644 index 0000000..f89a7e1 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/brokerage/user/modules/update-form.vue @@ -0,0 +1,161 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/brokerage/user/modules/user-list-modal.vue b/apps/web-ele/src/views/mall/trade/brokerage/user/modules/user-list-modal.vue new file mode 100644 index 0000000..4066748 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/brokerage/user/modules/user-list-modal.vue @@ -0,0 +1,52 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/brokerage/withdraw/data.ts b/apps/web-ele/src/views/mall/trade/brokerage/withdraw/data.ts new file mode 100644 index 0000000..86452dd --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/brokerage/withdraw/data.ts @@ -0,0 +1,148 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + placeholder: '请输入用户编号', + allowClear: true, + }, + }, + { + fieldName: 'type', + label: '提现类型', + component: 'Select', + componentProps: { + placeholder: '请选择提现类型', + allowClear: true, + options: getDictOptions(DICT_TYPE.BROKERAGE_WITHDRAW_TYPE, 'number'), + }, + }, + { + fieldName: 'userAccount', + label: '账号', + component: 'Input', + componentProps: { + placeholder: '请输入账号', + allowClear: true, + }, + }, + { + fieldName: 'userName', + label: '真实姓名', + component: 'Input', + componentProps: { + placeholder: '请输入真实姓名', + allowClear: true, + }, + }, + { + fieldName: 'bankName', + label: '提现银行', + component: 'Select', + componentProps: { + placeholder: '请选择提现银行', + allowClear: true, + options: getDictOptions(DICT_TYPE.BROKERAGE_BANK_NAME, 'string'), + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + placeholder: '请选择状态', + allowClear: true, + options: getDictOptions(DICT_TYPE.BROKERAGE_WITHDRAW_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '申请时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 80, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 80, + }, + { + field: 'userNickname', + title: '用户昵称', + minWidth: 80, + }, + { + field: 'price', + title: '提现金额', + minWidth: 80, + formatter: 'formatAmount2', + }, + { + field: 'feePrice', + title: '提现手续费', + minWidth: 80, + formatter: 'formatAmount2', + }, + { + field: 'type', + title: '提现方式', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BROKERAGE_WITHDRAW_TYPE }, + }, + }, + { + title: '提现信息', + minWidth: 200, + slots: { default: 'withdraw-info' }, + }, + { + field: 'createTime', + title: '申请时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'remark', + title: '备注', + minWidth: 120, + }, + { + title: '状态', + minWidth: 200, + slots: { default: 'status-info' }, + }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/brokerage/withdraw/index.vue b/apps/web-ele/src/views/mall/trade/brokerage/withdraw/index.vue new file mode 100644 index 0000000..633f9af --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/brokerage/withdraw/index.vue @@ -0,0 +1,233 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/config/data.ts b/apps/web-ele/src/views/mall/trade/config/data.ts new file mode 100644 index 0000000..6e91a59 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/config/data.ts @@ -0,0 +1,255 @@ +import type { VbenFormSchema } from '#/adapter/form'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +export const schema: VbenFormSchema[] = [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'type', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'afterSaleRefundReasons', + label: '退款理由', + component: 'Select', + componentProps: { + placeholder: '请直接输入退款理由', + multiple: true, + options: [], + class: 'w-full', + allowCreate: true, + filterable: true, + reserveKeyword: false, + }, + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'afterSale', + }, + }, + { + fieldName: 'afterSaleReturnReasons', + label: '退货理由', + component: 'Select', + componentProps: { + placeholder: '请直接输入退货理由', + multiple: true, + options: [], + class: 'w-full', + allowCreate: true, + filterable: true, + reserveKeyword: false, + }, + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'afterSale', + }, + }, + { + fieldName: 'deliveryExpressFreeEnabled', + label: '启用包邮', + component: 'Switch', + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'delivery', + }, + help: '商城是否启用全场包邮', + }, + { + fieldName: 'deliveryExpressFreePrice', + label: '满额包邮', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + placeholder: '请输入满额包邮金额', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'delivery', + }, + help: '商城商品满多少金额即可包邮,单位:元', + }, + { + fieldName: 'deliveryPickUpEnabled', + label: '启用门店自提', + component: 'Switch', + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'delivery', + }, + }, + { + fieldName: 'brokerageEnabled', + label: '启用分佣', + component: 'Switch', + help: '商城是否开启分销模式', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'brokerage', + }, + }, + { + fieldName: 'brokerageEnabledCondition', + label: '分佣模式', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.BROKERAGE_ENABLED_CONDITION, 'number'), + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'brokerage', + }, + help: '人人分销:每个用户都可以成为推广员 \n 指定分销:仅可在后台手动设置推广员', + }, + { + fieldName: 'brokerageBindMode', + label: '分销关系绑定', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.BROKERAGE_BIND_MODE, 'number'), + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'brokerage', + }, + help: '首次绑定:只要用户没有推广人,随时都可以绑定推广关系 \n 注册绑定:只有新用户注册时或首次进入系统时才可以绑定推广关系', + }, + { + fieldName: 'brokeragePosterUrls', + label: '分销海报图', + component: 'ImageUpload', + componentProps: { + maxNumber: 9, + }, + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'brokerage', + }, + help: '个人中心分销海报图片,建议尺寸 600x1000', + }, + { + fieldName: 'brokerageFirstPercent', + label: '一级返佣比例(%)', + component: 'InputNumber', + componentProps: { + min: 0, + max: 100, + placeholder: '请输入一级返佣比例', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'brokerage', + }, + help: '订单交易成功后给推广人返佣的百分比', + }, + { + fieldName: 'brokerageSecondPercent', + label: '二级返佣比例(%)', + component: 'InputNumber', + componentProps: { + min: 0, + max: 100, + placeholder: '请输入二级返佣比例', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'brokerage', + }, + help: '订单交易成功后给推广人的推荐人返佣的百分比', + }, + { + fieldName: 'brokerageFrozenDays', + label: '佣金冻结天数', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入佣金冻结天数', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'brokerage', + }, + help: '防止用户退款,佣金被提现了,所以需要设置佣金冻结时间,单位:天', + }, + { + fieldName: 'brokerageWithdrawMinPrice', + label: '提现最低金额(元)', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 2, + placeholder: '请输入提现最低金额', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'brokerage', + }, + help: '用户提现最低金额限制,单位:元', + }, + { + fieldName: 'brokerageWithdrawFeePercent', + label: '提现手续费(%)', + component: 'InputNumber', + componentProps: { + min: 0, + max: 100, + precision: 2, + placeholder: '请输入提现手续费百分比', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'brokerage', + }, + help: '提现手续费百分比,范围 0-100,0 为无提现手续费。例:设置 10,即收取 10% 手续费,提现10 元,到账 9 元,1 元手续费', + }, + { + fieldName: 'brokerageWithdrawTypes', + label: '提现方式', + component: 'CheckboxGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.BROKERAGE_WITHDRAW_TYPE, 'number'), + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => values.type === 'brokerage', + }, + help: '商城开通提现的付款方式', + }, +]; diff --git a/apps/web-ele/src/views/mall/trade/config/index.vue b/apps/web-ele/src/views/mall/trade/config/index.vue new file mode 100644 index 0000000..39745b8 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/config/index.vue @@ -0,0 +1,99 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/delivery/express/data.ts b/apps/web-ele/src/views/mall/trade/delivery/express/data.ts new file mode 100644 index 0000000..7e0b676 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/express/data.ts @@ -0,0 +1,156 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'code', + label: '公司编码', + componentProps: { + placeholder: '请输入快递编码', + }, + rules: 'required', + }, + { + component: 'Input', + fieldName: 'name', + label: '公司名称', + componentProps: { + placeholder: '请输入快递名称', + }, + rules: 'required', + }, + { + component: 'ImageUpload', + fieldName: 'logo', + label: '公司 logo', + rules: 'required', + help: '推荐 180x180 图片分辨率', + }, + { + fieldName: 'sort', + label: '显示顺序', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入显示顺序', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '开启状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '快递公司名称', + component: 'Input', + componentProps: { + placeholder: '请输入快递公司名称', + allowClear: true, + }, + }, + { + fieldName: 'code', + label: '快递公司编号', + component: 'Input', + componentProps: { + placeholder: '请输入快递公司编号', + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + placeholder: '请选择状态', + allowClear: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'code', + title: '公司编码', + minWidth: 120, + }, + { + field: 'name', + title: '公司名称', + minWidth: 150, + }, + { + field: 'logo', + title: '公司 logo', + minWidth: 120, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'sort', + title: '显示顺序', + minWidth: 100, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/delivery/express/index.vue b/apps/web-ele/src/views/mall/trade/delivery/express/index.vue new file mode 100644 index 0000000..06cb743 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/express/index.vue @@ -0,0 +1,143 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/delivery/express/modules/form.vue b/apps/web-ele/src/views/mall/trade/delivery/express/modules/form.vue new file mode 100644 index 0000000..5db07b9 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/express/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/data.ts b/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/data.ts new file mode 100644 index 0000000..bb1b0ce --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/data.ts @@ -0,0 +1,228 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 计费方式列标题映射 */ +export const CHARGE_MODE_TITLE_MAP: Record< + number, + { + extraCountTitle: string; + startCountTitle: string; + } +> = { + 1: { startCountTitle: '首件', extraCountTitle: '续件' }, + 2: { startCountTitle: '首件重量(kg)', extraCountTitle: '续件重量(kg)' }, + 3: { startCountTitle: '首件体积(m³)', extraCountTitle: '续件体积(m³)' }, +}; + +/** 包邮方式列标题映射 */ +export const FREE_MODE_TITLE_MAP: Record = { + 1: { freeCountTitle: '包邮件数' }, + 2: { freeCountTitle: '包邮重量(kg)' }, + 3: { freeCountTitle: '包邮体积(m³)' }, +}; + +/** 运费设置表格列 */ +export function useChargesColumns( + chargeMode = 1, +): VxeTableGridOptions['columns'] { + const chargeTitleMap = CHARGE_MODE_TITLE_MAP[chargeMode]; + return [ + { + field: 'areaIds', + title: '区域', + minWidth: 300, + slots: { default: 'areaIds' }, + }, + { + field: 'startCount', + title: chargeTitleMap?.startCountTitle, + width: 120, + slots: { default: 'startCount' }, + }, + { + field: 'startPrice', + title: '运费(元)', + width: 120, + slots: { default: 'startPrice' }, + }, + { + field: 'extraCount', + title: chargeTitleMap?.extraCountTitle, + width: 120, + slots: { default: 'extraCount' }, + }, + { + field: 'extraPrice', + title: '续费(元)', + width: 120, + slots: { default: 'extraPrice' }, + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 包邮设置表格列 */ +export function useFreesColumns( + chargeMode = 1, +): VxeTableGridOptions['columns'] { + const freeTitleMap = FREE_MODE_TITLE_MAP[chargeMode]; + return [ + { + field: 'areaIds', + title: '区域', + minWidth: 300, + slots: { default: 'areaIds' }, + }, + { + field: 'freeCount', + title: freeTitleMap?.freeCountTitle, + width: 120, + slots: { default: 'freeCount' }, + }, + { + field: 'freePrice', + title: '包邮金额(元)', + width: 120, + slots: { default: 'freePrice' }, + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '模板名称', + componentProps: { + placeholder: '请输入模板名称', + }, + rules: 'required', + }, + { + fieldName: 'chargeMode', + label: '计费方式', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.EXPRESS_CHARGE_MODE, 'number'), + }, + rules: z.number().default(1), + }, + { + fieldName: 'sort', + label: '显示顺序', + component: 'InputNumber', + componentProps: { + placeholder: '请输入显示顺序', + min: 0, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'charges', + label: '运费设置', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + fieldName: 'frees', + label: '包邮设置', + component: 'Input', + formItemClass: 'col-span-3', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '模板名称', + component: 'Input', + componentProps: { + placeholder: '请输入模板名称', + clearable: true, + }, + }, + { + fieldName: 'chargeMode', + label: '计费方式', + component: 'Select', + componentProps: { + placeholder: '请选择计费方式', + clearable: true, + options: getDictOptions(DICT_TYPE.EXPRESS_CHARGE_MODE, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'name', + title: '模板名称', + minWidth: 200, + }, + { + field: 'chargeMode', + title: '计费方式', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.EXPRESS_CHARGE_MODE }, + }, + }, + { + field: 'sort', + title: '显示顺序', + minWidth: 100, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/index.vue b/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/index.vue new file mode 100644 index 0000000..fef3235 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/index.vue @@ -0,0 +1,132 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/modules/charge-item-form.vue b/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/modules/charge-item-form.vue new file mode 100644 index 0000000..9025baa --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/modules/charge-item-form.vue @@ -0,0 +1,231 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/modules/form.vue b/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/modules/form.vue new file mode 100644 index 0000000..25b8c23 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/modules/form.vue @@ -0,0 +1,197 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/modules/free-item-form.vue b/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/modules/free-item-form.vue new file mode 100644 index 0000000..bbdfacf --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/expressTemplate/modules/free-item-form.vue @@ -0,0 +1,202 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/delivery/pickUpOrder/data.ts b/apps/web-ele/src/views/mall/trade/delivery/pickUpOrder/data.ts new file mode 100644 index 0000000..cdfa7b5 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/pickUpOrder/data.ts @@ -0,0 +1,164 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeGridPropTypes } from '#/adapter/vxe-table'; +import type { MallDeliveryPickUpStoreApi } from '#/api/mall/trade/delivery/pickUpStore'; + +import { ref } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { useUserStore } from '@vben/stores'; + +import { getSimpleDeliveryPickUpStoreList } from '#/api/mall/trade/delivery/pickUpStore'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 关联数据 */ +const userStore = useUserStore(); +const pickUpStoreList = ref( + [], +); +getSimpleDeliveryPickUpStoreList().then((res) => { + pickUpStoreList.value = res; + // 移除自己无法核销的门店 + const userId = userStore?.userInfo?.id; + pickUpStoreList.value = pickUpStoreList.value.filter((item) => + item.verifyUserIds?.includes(userId), + ); +}); + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'pickUpStoreIds', + label: '自提门店', + component: 'Select', + componentProps: { + options: pickUpStoreList, + props: { + label: 'name', + value: 'id', + }, + placeholder: '请选择自提门店', + }, + defaultValue: pickUpStoreList.value[0]?.id, + }, + { + fieldName: 'no', + label: '订单号', + component: 'Input', + componentProps: { + placeholder: '请输入订单号', + clearable: true, + }, + }, + { + fieldName: 'userId', + label: '用户 UID', + component: 'Input', + componentProps: { + placeholder: '请输入用户 UID', + clearable: true, + }, + }, + { + fieldName: 'userNickname', + label: '用户昵称', + component: 'Input', + componentProps: { + placeholder: '请输入用户昵称', + clearable: true, + }, + }, + { + fieldName: 'userMobile', + label: '用户电话', + component: 'Input', + componentProps: { + placeholder: '请输入用户电话', + clearable: true, + }, + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns(): VxeGridPropTypes.Columns { + return [ + { + field: 'no', + title: '订单号', + fixed: 'left', + minWidth: 180, + }, + { + field: 'user.nickname', + title: '用户信息', + minWidth: 100, + }, + { + field: 'brokerageUser.nickname', + title: '推荐人信息', + minWidth: 100, + }, + { + field: 'spuName', + title: '商品信息', + minWidth: 300, + slots: { default: 'spuName' }, + }, + { + field: 'payPrice', + title: '实付金额(元)', + formatter: 'formatAmount2', + minWidth: 180, + }, + { + field: 'storeStaffName', + title: '核销员', + minWidth: 160, + }, + { + field: 'pickUpStoreId', + title: '核销门店', + minWidth: 160, + formatter: ({ row }) => { + return ( + pickUpStoreList.value.find((item) => item.id === row.pickUpStoreId) + ?.name || '' + ); + }, + }, + { + field: 'payStatus', + title: '支付状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + minWidth: 80, + }, + { + field: 'status', + title: '订单状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.TRADE_ORDER_STATUS }, + }, + minWidth: 80, + }, + { + field: 'createTime', + title: '下单时间', + formatter: 'formatDateTime', + minWidth: 160, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/delivery/pickUpOrder/index.vue b/apps/web-ele/src/views/mall/trade/delivery/pickUpOrder/index.vue new file mode 100644 index 0000000..c4f704c --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/pickUpOrder/index.vue @@ -0,0 +1,291 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/data.ts b/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/data.ts new file mode 100644 index 0000000..19922a0 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/data.ts @@ -0,0 +1,265 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getAreaTree } from '#/api/system/area'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '门店名称', + rules: 'required', + componentProps: { + placeholder: '请输入门店名称', + }, + }, + { + component: 'Input', + fieldName: 'phone', + label: '门店手机', + rules: 'mobileRequired', + componentProps: { + placeholder: '请输入门店手机', + }, + }, + { + component: 'ImageUpload', + fieldName: 'logo', + label: '门店 logo', + rules: 'required', + formItemClass: 'col-span-2', + componentProps: { + placeholder: '请上传门店 logo', + }, + help: '推荐 180x180 图片分辨率', + }, + { + component: 'Textarea', + fieldName: 'introduction', + label: '门店简介', + formItemClass: 'col-span-2', + componentProps: { + placeholder: '请输入门店简介', + rows: 4, + }, + }, + { + fieldName: 'areaId', + label: '门店所在地区', + component: 'ApiTreeSelect', + rules: 'required', + componentProps: { + api: getAreaTree, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择省市区', + }, + }, + { + component: 'Input', + fieldName: 'detailAddress', + label: '门店详细地址', + rules: 'required', + componentProps: { + placeholder: '请输入门店详细地址', + }, + }, + { + component: 'TimePicker', + fieldName: 'rangeTime', + label: '营业时间', + rules: 'required', + componentProps: { + isRange: true, + format: 'HH:mm', + }, + }, + { + fieldName: 'status', + label: '门店状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + component: 'Input', + fieldName: 'longitude', + label: '经度', + rules: 'required', + componentProps: { + placeholder: '请输入门店经度', + }, + }, + { + component: 'Input', + fieldName: 'latitude', + label: '纬度', + rules: 'required', + componentProps: { + placeholder: '请输入门店纬度', + }, + }, + ]; +} + +/** 绑定店员的表单 */ +export function useBindFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '门店名称', + dependencies: { + triggerFields: ['id'], + disabled: true, + }, + }, + { + component: 'ApiSelect', + fieldName: 'verifyUserIds', + label: '门店店员', + rules: 'required', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + multiple: true, + clearable: true, + placeholder: '请选择门店店员', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'phone', + label: '门店手机', + component: 'Input', + componentProps: { + placeholder: '请输入门店手机', + clearable: true, + }, + }, + { + fieldName: 'name', + label: '门店名称', + component: 'Input', + componentProps: { + placeholder: '请输入门店名称', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '门店状态', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择门店状态', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 80, + }, + { + field: 'logo', + title: '门店 logo', + minWidth: 100, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'name', + title: '门店名称', + minWidth: 150, + }, + { + field: 'phone', + title: '门店手机', + minWidth: 120, + }, + { + field: 'detailAddress', + title: '地址', + minWidth: 200, + }, + { + field: 'openingTime', + title: '营业时间', + minWidth: 160, + formatter: ({ row }) => { + return `${row.openingTime} ~ ${row.closingTime}`; + }, + }, + { + field: 'status', + title: '开启状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 160, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/index.vue b/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/index.vue new file mode 100644 index 0000000..8f470c0 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/index.vue @@ -0,0 +1,150 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/modules/bind-form.vue b/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/modules/bind-form.vue new file mode 100644 index 0000000..5d747f3 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/modules/bind-form.vue @@ -0,0 +1,85 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/modules/form.vue b/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/modules/form.vue new file mode 100644 index 0000000..0ca3656 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/delivery/pickUpStore/modules/form.vue @@ -0,0 +1,157 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/order/data.ts b/apps/web-ele/src/views/mall/trade/order/data.ts new file mode 100644 index 0000000..e94a07b --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/order/data.ts @@ -0,0 +1,450 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeGridPropTypes } from '#/adapter/vxe-table'; +import type { MallDeliveryPickUpStoreApi } from '#/api/mall/trade/delivery/pickUpStore'; + +import { DeliveryTypeEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { convertToInteger, formatToFraction } from '@vben/utils'; + +import { getSimpleDeliveryExpressList } from '#/api/mall/trade/delivery/express'; +import { getSimpleDeliveryPickUpStoreList } from '#/api/mall/trade/delivery/pickUpStore'; +import { getAreaTree } from '#/api/system/area'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 关联数据 */ +let pickUpStoreList: MallDeliveryPickUpStoreApi.DeliveryPickUpStore[] = []; +getSimpleDeliveryPickUpStoreList().then((data) => { + pickUpStoreList = data; +}); + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'status', + label: '订单状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.TRADE_ORDER_STATUS, 'number'), + placeholder: '请选择订单状态', + clearable: true, + }, + }, + { + fieldName: 'payChannelCode', + label: '支付方式', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.PAY_CHANNEL_CODE, 'number'), + placeholder: '请选择支付方式', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'terminal', + label: '订单来源', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.TERMINAL, 'number'), + placeholder: '请选择订单来源', + clearable: true, + }, + }, + { + fieldName: 'deliveryType', + label: '配送方式', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.TRADE_DELIVERY_TYPE, 'number'), + placeholder: '请选择配送方式', + clearable: true, + }, + }, + { + fieldName: 'logisticsId', + label: '快递公司', + component: 'ApiSelect', + componentProps: { + api: getSimpleDeliveryExpressList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择快递公司', + clearable: true, + }, + dependencies: { + triggerFields: ['deliveryType'], + show: (values) => values.deliveryType === DeliveryTypeEnum.EXPRESS.type, + }, + }, + { + fieldName: 'pickUpStoreId', + label: '自提门店', + component: 'ApiSelect', + componentProps: { + api: getSimpleDeliveryPickUpStoreList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择自提门店', + clearable: true, + }, + dependencies: { + triggerFields: ['deliveryType'], + show: (values) => values.deliveryType === DeliveryTypeEnum.PICK_UP.type, + }, + }, + { + fieldName: 'pickUpVerifyCode', + label: '核销码', + component: 'Input', + componentProps: { + placeholder: '请输入核销码', + clearable: true, + }, + dependencies: { + triggerFields: ['deliveryType'], + show: (values) => values.deliveryType === DeliveryTypeEnum.PICK_UP.type, + }, + }, + { + fieldName: 'no', + label: '订单号', + component: 'Input', + componentProps: { + placeholder: '请输入订单号', + clearable: true, + }, + }, + { + fieldName: 'userId', + label: '用户 UID', + component: 'Input', + componentProps: { + placeholder: '请输入用户 UID', + clearable: true, + }, + }, + { + fieldName: 'userNickname', + label: '用户昵称', + component: 'Input', + componentProps: { + placeholder: '请输入用户昵称', + clearable: true, + }, + }, + { + fieldName: 'userMobile', + label: '用户电话', + component: 'Input', + componentProps: { + placeholder: '请输入用户电话', + clearable: true, + }, + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns(): VxeGridPropTypes.Columns { + return [ + { + type: 'expand', + width: 80, + slots: { content: 'expand_content' }, + fixed: 'left', + }, + { + field: 'no', + title: '订单号', + fixed: 'left', + minWidth: 180, + }, + { + field: 'createTime', + title: '下单时间', + formatter: 'formatDateTime', + minWidth: 160, + }, + { + field: 'terminal', + title: '订单来源', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.TERMINAL }, + }, + minWidth: 120, + }, + { + field: 'payChannelCode', + title: '支付方式', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_CHANNEL_CODE }, + }, + minWidth: 120, + }, + { + field: 'payTime', + title: '支付时间', + formatter: 'formatDateTime', + minWidth: 160, + }, + { + field: 'type', + title: '订单类型', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.TRADE_ORDER_TYPE }, + }, + minWidth: 80, + }, + { + field: 'payPrice', + title: '实际支付', + formatter: 'formatAmount2', + minWidth: 180, + }, + { + field: 'user', + title: '买家/收货人', + formatter: ({ row }) => { + if (row.deliveryType === DeliveryTypeEnum.EXPRESS.type) { + return `买家:${row.user?.nickname} / 收货人: ${row.receiverName} ${row.receiverMobile}${row.receiverAreaName}${row.receiverDetailAddress}`; + } + if (row.deliveryType === DeliveryTypeEnum.PICK_UP.type) { + return `门店名称:${pickUpStoreList.find((item) => item.id === row.pickUpStoreId)?.name} / + 门店手机:${pickUpStoreList.find((item) => item.id === row.pickUpStoreId)?.phone} / + 自提门店:${pickUpStoreList.find((item) => item.id === row.pickUpStoreId)?.detailAddress} + `; + } + return ''; + }, + minWidth: 180, + }, + { + field: 'deliveryType', + title: '配送方式', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.TRADE_DELIVERY_TYPE }, + }, + minWidth: 80, + }, + { + field: 'status', + title: '订单状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.TRADE_ORDER_STATUS }, + }, + minWidth: 80, + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 订单备注表单配置 */ +export function useRemarkFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + type: 'textarea', + rows: 3, + }, + }, + ]; +} + +/** 订单调价表单配置 */ +export function usePriceFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'payPrice', + label: '应付金额(总)', + component: 'Input', + componentProps: { + placeholder: '请输入应付金额(总)', + disabled: true, + formatter: (value: string) => `${value}元`, + }, + }, + { + fieldName: 'adjustPrice', + label: '订单调价', + component: 'InputNumber', + componentProps: { + placeholder: '请输入订单调价', + step: 0.1, + precision: 2, + controlsPosition: 'right', + class: '!w-full', + }, + help: '订单调价。 正数,加价;负数,减价', + rules: 'required', + }, + { + fieldName: 'newPayPrice', + label: '调价后', + component: 'Input', + componentProps: { + placeholder: '', + formatter: (value: string) => `${value}元`, + }, + dependencies: { + triggerFields: ['payPrice', 'adjustPrice'], + disabled: true, + trigger(values, form) { + const originalPrice = convertToInteger(values.payPrice); + const adjustPrice = convertToInteger(values.adjustPrice); + const newPrice = originalPrice + adjustPrice; + form.setFieldValue('newPayPrice', formatToFraction(newPrice)); + }, + }, + }, + ]; +} + +/** 订单修改地址表单配置 */ +export function useAddressFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'receiverName', + label: '收件人', + component: 'Input', + componentProps: { + placeholder: '请输入收件人名称', + }, + rules: 'required', + }, + { + fieldName: 'receiverMobile', + label: '手机号', + component: 'Input', + componentProps: { + placeholder: '请输入收件人手机号', + }, + rules: 'required', + }, + { + fieldName: 'receiverAreaId', + label: '所在地', + component: 'ApiTreeSelect', + componentProps: { + api: getAreaTree, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择收件人所在地', + defaultExpandAll: true, + }, + rules: 'required', + }, + { + fieldName: 'receiverDetailAddress', + label: '详细地址', + component: 'Input', + componentProps: { + placeholder: '请输入收件人详细地址', + type: 'textarea', + rows: 3, + }, + rules: 'required', + }, + ]; +} + +/** 订单发货表单配置 */ +export function useDeliveryFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'expressType', + label: '发货方式', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '快递', value: 'express' }, + { label: '无需发货', value: 'none' }, + ], + }, + defaultValue: 'express', + }, + { + fieldName: 'logisticsId', + label: '物流公司', + component: 'ApiSelect', + componentProps: { + api: getSimpleDeliveryExpressList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择物流公司', + }, + dependencies: { + triggerFields: ['expressType'], + show: (values) => values.expressType === 'express', + }, + rules: 'required', + }, + { + fieldName: 'logisticsNo', + label: '物流单号', + component: 'Input', + componentProps: { + placeholder: '请输入物流单号', + }, + dependencies: { + triggerFields: ['expressType'], + show: (values) => values.expressType === 'express', + }, + rules: 'required', + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/order/detail/data.ts b/apps/web-ele/src/views/mall/trade/order/detail/data.ts new file mode 100644 index 0000000..febf4ed --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/order/detail/data.ts @@ -0,0 +1,255 @@ +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { fenToYuan, formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; + +/** 订单基础信息 schema */ +export function useOrderInfoSchema(): DescriptionItemSchema[] { + return [ + { + field: 'no', + label: '订单号', + }, + { + field: 'user.nickname', + label: '买家', + }, + { + field: 'type', + label: '订单类型', + render: (val) => + h(DictTag, { + type: DICT_TYPE.TRADE_ORDER_TYPE, + value: val, + }), + }, + { + field: 'terminal', + label: '订单来源', + render: (val) => + h(DictTag, { + type: DICT_TYPE.TERMINAL, + value: val, + }), + }, + { + field: 'userRemark', + label: '买家留言', + }, + { + field: 'remark', + label: '商家备注', + }, + { + field: 'payOrderId', + label: '支付单号', + }, + { + field: 'payChannelCode', + label: '付款方式', + render: (val) => + h(DictTag, { + type: DICT_TYPE.PAY_CHANNEL_CODE, + value: val, + }), + }, + { + field: 'brokerageUser.nickname', + label: '推广用户', + }, + ]; +} + +/** 订单状态信息 schema */ +export function useOrderStatusSchema(): DescriptionItemSchema[] { + return [ + { + field: 'status', + label: '订单状态', + render: (val) => + h(DictTag, { + type: DICT_TYPE.TRADE_ORDER_STATUS, + value: val, + }), + }, + { + field: 'reminder', + label: '提醒', + render: () => + h('div', { class: 'space-y-1' }, [ + h('div', '买家付款成功后,货款将直接进入您的商户号(微信、支付宝)'), + h('div', '请及时关注你发出的包裹状态,确保可以配送至买家手中'), + h( + 'div', + '如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商', + ), + ]), + }, + ]; +} + +/** 订单金额信息 schema */ +export function useOrderPriceSchema(): DescriptionItemSchema[] { + return [ + { + field: 'totalPrice', + label: '商品总额', + render: (val) => `${fenToYuan(val ?? 0)} 元`, + }, + { + field: 'deliveryPrice', + label: '运费金额', + render: (val) => `${fenToYuan(val ?? 0)} 元`, + }, + { + field: 'adjustPrice', + label: '订单调价', + render: (val) => `${fenToYuan(val ?? 0)} 元`, + }, + { + field: 'couponPrice', + label: '优惠劵优惠', + render: (val) => + h('span', { class: 'text-red-500' }, `${fenToYuan(val ?? 0)} 元`), + }, + { + field: 'vipPrice', + label: 'VIP 优惠', + render: (val) => + h('span', { class: 'text-red-500' }, `${fenToYuan(val ?? 0)} 元`), + }, + { + field: 'discountPrice', + label: '活动优惠', + render: (val) => + h('span', { class: 'text-red-500' }, `${fenToYuan(val ?? 0)} 元`), + }, + { + field: 'pointPrice', + label: '积分抵扣', + render: (val) => + h('span', { class: 'text-red-500' }, `${fenToYuan(val ?? 0)} 元`), + }, + { + field: 'payPrice', + label: '应付金额', + render: (val) => `${fenToYuan(val ?? 0)} 元`, + }, + ]; +} + +/** 收货信息 schema */ +export function useDeliveryInfoSchema(): DescriptionItemSchema[] { + return [ + { + field: 'deliveryType', + label: '配送方式', + render: (val) => + h(DictTag, { + type: DICT_TYPE.TRADE_DELIVERY_TYPE, + value: val, + }), + }, + { + field: 'receiverName', + label: '收货人', + }, + { + field: 'receiverMobile', + label: '联系电话', + }, + { + field: 'receiverAddress', + label: '收货地址', + render: (val, data) => `${data?.receiverAreaName} ${val}`.trim(), + }, + { + field: 'deliveryTime', + label: '发货时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} + +/** 商品信息 columns */ +export function useProductColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'spuName', + title: '商品', + minWidth: 300, + slots: { default: 'spuName' }, + }, + { + field: 'price', + title: '商品原价', + width: 150, + formatter: 'formatFenToYuanAmount', + }, + { + field: 'count', + title: '数量', + width: 100, + }, + { + field: 'payPrice', + title: '合计', + width: 150, + formatter: 'formatFenToYuanAmount', + }, + { + field: 'afterSaleStatus', + title: '售后状态', + width: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.TRADE_ORDER_ITEM_AFTER_SALE_STATUS }, + }, + }, + ]; +} + +/** 物流详情 columns */ +export function useExpressTrackColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'time', + title: '时间', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'content', + title: '物流状态', + minWidth: 300, + }, + ]; +} + +/** 操作日志 columns */ +export function useOperateLogColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'createTime', + title: '操作时间', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'userType', + title: '操作人', + width: 100, + slots: { default: 'userType' }, + }, + { + field: 'content', + title: '操作内容', + minWidth: 200, + }, + ]; +} diff --git a/apps/web-ele/src/views/mall/trade/order/detail/index.vue b/apps/web-ele/src/views/mall/trade/order/detail/index.vue new file mode 100644 index 0000000..4a84bd8 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/order/detail/index.vue @@ -0,0 +1,341 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/order/index.vue b/apps/web-ele/src/views/mall/trade/order/index.vue new file mode 100644 index 0000000..c19b0fd --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/order/index.vue @@ -0,0 +1,182 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/order/modules/address-form.vue b/apps/web-ele/src/views/mall/trade/order/modules/address-form.vue new file mode 100644 index 0000000..18712c9 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/order/modules/address-form.vue @@ -0,0 +1,77 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/order/modules/delivery-form.vue b/apps/web-ele/src/views/mall/trade/order/modules/delivery-form.vue new file mode 100644 index 0000000..1e95cc8 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/order/modules/delivery-form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/order/modules/price-form.vue b/apps/web-ele/src/views/mall/trade/order/modules/price-form.vue new file mode 100644 index 0000000..bb6eafd --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/order/modules/price-form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/mall/trade/order/modules/remark-form.vue b/apps/web-ele/src/views/mall/trade/order/modules/remark-form.vue new file mode 100644 index 0000000..7fb5d29 --- /dev/null +++ b/apps/web-ele/src/views/mall/trade/order/modules/remark-form.vue @@ -0,0 +1,78 @@ + + + diff --git a/apps/web-ele/src/views/member/config/data.ts b/apps/web-ele/src/views/member/config/data.ts new file mode 100644 index 0000000..7004d70 --- /dev/null +++ b/apps/web-ele/src/views/member/config/data.ts @@ -0,0 +1,55 @@ +import type { VbenFormSchema } from '#/adapter/form'; + +export const schema: VbenFormSchema[] = [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Switch', + fieldName: 'pointTradeDeductEnable', + label: '积分抵扣', + help: '下单积分是否抵用订单金额', + }, + { + component: 'InputNumber', + fieldName: 'pointTradeDeductUnitPrice', + label: '积分抵扣', + help: '积分抵用比例(1 积分抵多少金额),单位:元', + componentProps: { + min: 0, + precision: 2, + placeholder: '请输入积分抵扣单价', + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + component: 'InputNumber', + fieldName: 'pointTradeDeductMaxPrice', + label: '积分抵扣最大值', + help: '单次下单积分使用上限,0 不限制', + componentProps: { + min: 0, + placeholder: '请输入积分抵扣最大值', + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + component: 'InputNumber', + fieldName: 'pointTradeGivePoint', + label: '1 元赠送多少分', + help: '下单支付金额按比例赠送积分(实际支付 1 元赠送多少积分)', + componentProps: { + min: 0, + placeholder: '请输入赠送积分比例', + controlsPosition: 'right', + class: '!w-full', + }, + }, +]; diff --git a/apps/web-ele/src/views/member/config/index.vue b/apps/web-ele/src/views/member/config/index.vue new file mode 100644 index 0000000..a3eefd2 --- /dev/null +++ b/apps/web-ele/src/views/member/config/index.vue @@ -0,0 +1,67 @@ + + + diff --git a/apps/web-ele/src/views/member/group/data.ts b/apps/web-ele/src/views/member/group/data.ts new file mode 100644 index 0000000..75b8b3d --- /dev/null +++ b/apps/web-ele/src/views/member/group/data.ts @@ -0,0 +1,124 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '分组名称', + component: 'Input', + componentProps: { + placeholder: '请输入分组名称', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '分组名称', + component: 'Input', + componentProps: { + placeholder: '请输入分组名称', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + placeholder: ['开始日期', '结束日期'], + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'name', + title: '分组名称', + minWidth: 150, + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + showOverflow: 'tooltip', + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/member/group/index.vue b/apps/web-ele/src/views/member/group/index.vue new file mode 100644 index 0000000..e7e06ed --- /dev/null +++ b/apps/web-ele/src/views/member/group/index.vue @@ -0,0 +1,125 @@ + + + diff --git a/apps/web-ele/src/views/member/group/modules/form.vue b/apps/web-ele/src/views/member/group/modules/form.vue new file mode 100644 index 0000000..6e36fe2 --- /dev/null +++ b/apps/web-ele/src/views/member/group/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/member/level/data.ts b/apps/web-ele/src/views/member/level/data.ts new file mode 100644 index 0000000..535dddf --- /dev/null +++ b/apps/web-ele/src/views/member/level/data.ts @@ -0,0 +1,192 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '等级名称', + component: 'Input', + componentProps: { + placeholder: '请输入等级名称', + }, + rules: 'required', + }, + { + fieldName: 'level', + label: '等级', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 0, + placeholder: '请输入等级', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'experience', + label: '升级经验', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 0, + placeholder: '请输入升级经验', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'discountPercent', + label: '享受折扣(%)', + component: 'InputNumber', + componentProps: { + min: 0, + max: 100, + precision: 0, + placeholder: '请输入享受折扣', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'icon', + label: '等级图标', + component: 'ImageUpload', + }, + { + fieldName: 'backgroundUrl', + label: '等级背景图', + component: 'ImageUpload', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '等级名称', + component: 'Input', + componentProps: { + placeholder: '请输入等级名称', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + placeholder: '请选择状态', + clearable: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '等级编号', + minWidth: 80, + }, + { + field: 'icon', + title: '等级图标', + minWidth: 100, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'backgroundUrl', + title: '等级背景图', + minWidth: 120, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'name', + title: '等级名称', + minWidth: 120, + }, + { + field: 'level', + title: '等级', + minWidth: 80, + }, + { + field: 'experience', + title: '升级经验', + minWidth: 100, + }, + { + field: 'discountPercent', + title: '享受折扣(%)', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 80, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/member/level/index.vue b/apps/web-ele/src/views/member/level/index.vue new file mode 100644 index 0000000..3284397 --- /dev/null +++ b/apps/web-ele/src/views/member/level/index.vue @@ -0,0 +1,133 @@ + + + diff --git a/apps/web-ele/src/views/member/level/modules/form.vue b/apps/web-ele/src/views/member/level/modules/form.vue new file mode 100644 index 0000000..087d0d4 --- /dev/null +++ b/apps/web-ele/src/views/member/level/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/member/point/record/data.ts b/apps/web-ele/src/views/member/point/record/data.ts new file mode 100644 index 0000000..0ddb072 --- /dev/null +++ b/apps/web-ele/src/views/member/point/record/data.ts @@ -0,0 +1,121 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { ElTag } from 'element-plus'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'nickname', + label: '用户', + component: 'Input', + componentProps: { + placeholder: '请输入用户昵称', + clearable: true, + }, + }, + { + fieldName: 'bizType', + label: '业务类型', + component: 'Select', + componentProps: { + placeholder: '请选择业务类型', + clearable: true, + options: getDictOptions(DICT_TYPE.MEMBER_POINT_BIZ_TYPE, 'number'), + }, + }, + { + fieldName: 'title', + label: '积分标题', + component: 'Input', + componentProps: { + placeholder: '请输入积分标题', + clearable: true, + }, + }, + { + fieldName: 'createDate', + label: '获得时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'createTime', + title: '获得时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'nickname', + title: '用户', + minWidth: 150, + }, + { + field: 'point', + title: '获得积分', + minWidth: 120, + slots: { + default: ({ row }) => { + return h( + ElTag, + { + type: row.point > 0 ? 'primary' : 'danger', + }, + () => (row.point > 0 ? `+${row.point}` : row.point), + ); + }, + }, + }, + { + field: 'totalPoint', + title: '总积分', + minWidth: 100, + }, + { + field: 'title', + title: '标题', + minWidth: 200, + }, + { + field: 'description', + title: '描述', + minWidth: 200, + }, + { + field: 'bizId', + title: '业务编码', + minWidth: 120, + }, + { + field: 'bizType', + title: '业务类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MEMBER_POINT_BIZ_TYPE }, + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/member/point/record/index.vue b/apps/web-ele/src/views/member/point/record/index.vue new file mode 100644 index 0000000..cbc15c6 --- /dev/null +++ b/apps/web-ele/src/views/member/point/record/index.vue @@ -0,0 +1,54 @@ + + + diff --git a/apps/web-ele/src/views/member/signin/config/data.ts b/apps/web-ele/src/views/member/signin/config/data.ts new file mode 100644 index 0000000..e3b17dc --- /dev/null +++ b/apps/web-ele/src/views/member/signin/config/data.ts @@ -0,0 +1,108 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'InputNumber', + fieldName: 'day', + label: '签到天数', + help: '只允许设置 1-7,默认签到 7 天为一个周期', + componentProps: { + min: 1, + max: 7, + precision: 0, + placeholder: '请输入签到天数', + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(1).max(7, '签到天数必须在 1-7 之间'), + }, + { + component: 'InputNumber', + fieldName: 'point', + label: '获得积分', + componentProps: { + min: 0, + precision: 0, + placeholder: '请输入获得积分', + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0, '获得积分不能小于 0'), + }, + { + component: 'InputNumber', + fieldName: 'experience', + label: '奖励经验', + componentProps: { + min: 0, + precision: 0, + placeholder: '请输入奖励经验', + controlsPosition: 'right', + class: '!w-full', + }, + rules: z.number().min(0, '奖励经验不能小于 0'), + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'day', + title: '签到天数', + minWidth: 120, + formatter: ({ cellValue }) => ['第', cellValue, '天'].join(' '), + }, + { + field: 'point', + title: '获得积分', + minWidth: 120, + }, + { + field: 'experience', + title: '奖励经验', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/member/signin/config/index.vue b/apps/web-ele/src/views/member/signin/config/index.vue new file mode 100644 index 0000000..3b253a4 --- /dev/null +++ b/apps/web-ele/src/views/member/signin/config/index.vue @@ -0,0 +1,131 @@ + + + diff --git a/apps/web-ele/src/views/member/signin/config/modules/form.vue b/apps/web-ele/src/views/member/signin/config/modules/form.vue new file mode 100644 index 0000000..f545399 --- /dev/null +++ b/apps/web-ele/src/views/member/signin/config/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/member/signin/record/data.ts b/apps/web-ele/src/views/member/signin/record/data.ts new file mode 100644 index 0000000..8217b3f --- /dev/null +++ b/apps/web-ele/src/views/member/signin/record/data.ts @@ -0,0 +1,85 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { h } from 'vue'; + +import { ElTag } from 'element-plus'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'nickname', + label: '签到用户', + component: 'Input', + componentProps: { + placeholder: '请输入签到用户', + clearable: true, + }, + }, + { + fieldName: 'day', + label: '签到天数', + component: 'Input', + componentProps: { + placeholder: '请输入签到天数', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '签到时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'nickname', + title: '签到用户', + minWidth: 150, + }, + { + field: 'day', + title: '签到天数', + minWidth: 120, + formatter: ({ cellValue }) => ['第', cellValue, '天'].join(' '), + }, + { + field: 'point', + title: '获得积分', + minWidth: 120, + slots: { + default: ({ row }) => { + return h( + ElTag, + { + type: row.point > 0 ? 'primary' : 'danger', + }, + () => (row.point > 0 ? `+${row.point}` : row.point), + ); + }, + }, + }, + { + field: 'createTime', + title: '签到时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-ele/src/views/member/signin/record/index.vue b/apps/web-ele/src/views/member/signin/record/index.vue new file mode 100644 index 0000000..d5a36b7 --- /dev/null +++ b/apps/web-ele/src/views/member/signin/record/index.vue @@ -0,0 +1,53 @@ + + + diff --git a/apps/web-ele/src/views/member/tag/data.ts b/apps/web-ele/src/views/member/tag/data.ts new file mode 100644 index 0000000..d5e24d1 --- /dev/null +++ b/apps/web-ele/src/views/member/tag/data.ts @@ -0,0 +1,79 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '标签名称', + componentProps: { + placeholder: '请输入标签名称', + }, + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '标签名称', + component: 'Input', + componentProps: { + placeholder: '请输入标签名称', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + placeholder: ['开始日期', '结束日期'], + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'name', + title: '标签名称', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/member/tag/index.vue b/apps/web-ele/src/views/member/tag/index.vue new file mode 100644 index 0000000..6bc4124 --- /dev/null +++ b/apps/web-ele/src/views/member/tag/index.vue @@ -0,0 +1,131 @@ + + + diff --git a/apps/web-ele/src/views/member/tag/modules/form.vue b/apps/web-ele/src/views/member/tag/modules/form.vue new file mode 100644 index 0000000..c1bffdd --- /dev/null +++ b/apps/web-ele/src/views/member/tag/modules/form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/member/user/data.ts b/apps/web-ele/src/views/member/user/data.ts new file mode 100644 index 0000000..d64a178 --- /dev/null +++ b/apps/web-ele/src/views/member/user/data.ts @@ -0,0 +1,499 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { h } from 'vue'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { convertToInteger, formatToFraction } from '@vben/utils'; + +import { ElTag } from 'element-plus'; + +import { z } from '#/adapter/form'; +import { getSimpleGroupList } from '#/api/member/group'; +import { getSimpleLevelList } from '#/api/member/level'; +import { getSimpleTagList } from '#/api/member/tag'; +import { getAreaTree } from '#/api/system/area'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'mobile', + label: '手机号', + component: 'Input', + componentProps: { + placeholder: '请输入手机号', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE).optional(), + }, + { + fieldName: 'nickname', + label: '用户昵称', + component: 'Input', + componentProps: { + placeholder: '请输入用户昵称', + }, + }, + { + fieldName: 'avatar', + label: '头像', + component: 'ImageUpload', + }, + { + fieldName: 'name', + label: '真实名字', + component: 'Input', + componentProps: { + placeholder: '请输入真实名字', + }, + }, + { + fieldName: 'sex', + label: '用户性别', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + }, + }, + { + fieldName: 'birthday', + label: '出生日期', + component: 'DatePicker', + componentProps: { + format: 'YYYY-MM-DD', + valueFormat: 'x', + placeholder: '请选择出生日期', + class: '!w-full', + }, + }, + { + fieldName: 'areaId', + label: '所在地', + component: 'ApiTreeSelect', + componentProps: { + api: getAreaTree, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择所在地', + }, + }, + { + fieldName: 'tagIds', + label: '用户标签', + component: 'ApiSelect', + componentProps: { + api: getSimpleTagList, + labelField: 'name', + valueField: 'id', + multiple: true, + placeholder: '请选择用户标签', + }, + }, + { + fieldName: 'groupId', + label: '用户分组', + component: 'ApiSelect', + componentProps: { + api: getSimpleGroupList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择用户分组', + }, + }, + { + fieldName: 'mark', + label: '会员备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入会员备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'nickname', + label: '用户昵称', + component: 'Input', + componentProps: { + placeholder: '请输入用户昵称', + clearable: true, + }, + }, + { + fieldName: 'mobile', + label: '手机号', + component: 'Input', + componentProps: { + placeholder: '请输入手机号', + clearable: true, + }, + }, + { + fieldName: 'loginDate', + label: '登录时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '注册时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'tagIds', + label: '用户标签', + component: 'ApiSelect', + componentProps: { + api: getSimpleTagList, + labelField: 'name', + valueField: 'id', + multiple: true, + placeholder: '请选择用户标签', + clearable: true, + }, + }, + { + fieldName: 'levelId', + label: '用户等级', + component: 'ApiSelect', + componentProps: { + api: getSimpleLevelList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择用户等级', + clearable: true, + }, + }, + { + fieldName: 'groupId', + label: '用户分组', + component: 'ApiSelect', + componentProps: { + api: getSimpleGroupList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择用户分组', + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + }, + { + field: 'id', + title: '用户编号', + minWidth: 100, + }, + { + field: 'avatar', + title: '头像', + minWidth: 80, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'mobile', + title: '手机号', + minWidth: 120, + }, + { + field: 'nickname', + title: '昵称', + minWidth: 120, + }, + { + field: 'levelName', + title: '等级', + minWidth: 100, + }, + { + field: 'groupName', + title: '分组', + minWidth: 100, + }, + { + field: 'tagNames', + title: '用户标签', + minWidth: 150, + slots: { + default: ({ row }) => { + return row.tagNames?.map((tagName: string, index: number) => { + return h( + ElTag, + { + key: index, + class: 'mr-1', + type: 'primary', + }, + () => tagName, + ); + }); + }, + }, + }, + { + field: 'point', + title: '积分', + minWidth: 80, + }, + { + field: 'status', + title: '状态', + minWidth: 80, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'loginDate', + title: '登录时间', + minWidth: 160, + formatter: 'formatDateTime', + }, + { + field: 'createTime', + title: '注册时间', + minWidth: 160, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 修改用户等级 */ +export function useLevelFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + label: '用户编号', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'nickname', + label: '用户昵称', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'levelId', + label: '用户等级', + component: 'ApiSelect', + componentProps: { + api: getSimpleLevelList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择用户等级', + clearable: true, + }, + }, + { + fieldName: 'reason', + label: '修改原因', + component: 'Textarea', + componentProps: { + placeholder: '请输入修改原因', + }, + rules: 'required', + }, + ]; +} + +/** 修改用户余额 */ +export function useBalanceFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + label: '用户编号', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'nickname', + label: '用户昵称', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'balance', + label: '变动前余额(元)', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'changeType', + label: '变动类型', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '增加', value: 1 }, + { label: '减少', value: -1 }, + ], + }, + defaultValue: 1, + }, + { + fieldName: 'changeBalance', + label: '变动余额(元)', + component: 'InputNumber', + rules: 'required', + componentProps: { + min: 0, + precision: 2, + step: 0.1, + placeholder: '请输入变动余额', + controlsPosition: 'right', + class: '!w-full', + }, + defaultValue: 0, + }, + { + fieldName: 'balanceResult', + label: '变动后余额(元)', + component: 'Input', + dependencies: { + triggerFields: ['balance', 'changeBalance', 'changeType'], + disabled: true, + trigger(values, form) { + form.setFieldValue( + 'balanceResult', + formatToFraction( + convertToInteger(values.balance) + + convertToInteger(values.changeBalance) * values.changeType, + ), + ); + }, + }, + }, + ]; +} + +/** 修改用户积分 */ +export function usePointFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + label: '用户编号', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'nickname', + label: '用户昵称', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'point', + label: '变动前积分', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'changeType', + label: '变动类型', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '增加', value: 1 }, + { label: '减少', value: -1 }, + ], + }, + defaultValue: 1, + }, + { + fieldName: 'changePoint', + label: '变动积分', + component: 'InputNumber', + rules: 'required', + componentProps: { + min: 0, + precision: 0, + placeholder: '请输入变动积分', + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'pointResult', + label: '变动后积分', + component: 'Input', + componentProps: { + placeholder: '', + }, + dependencies: { + triggerFields: ['point', 'changePoint', 'changeType'], + disabled: true, + trigger(values, form) { + form.setFieldValue( + 'pointResult', + values.point + values.changePoint * values.changeType || + values.point, + ); + }, + }, + rules: z.number().min(0), + }, + ]; +} diff --git a/apps/web-ele/src/views/member/user/detail/index.vue b/apps/web-ele/src/views/member/user/detail/index.vue new file mode 100644 index 0000000..bf2ef4c --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/index.vue @@ -0,0 +1,127 @@ + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/account-info.vue b/apps/web-ele/src/views/member/user/detail/modules/account-info.vue new file mode 100644 index 0000000..d99cbf0 --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/account-info.vue @@ -0,0 +1,79 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/address-list.vue b/apps/web-ele/src/views/member/user/detail/modules/address-list.vue new file mode 100644 index 0000000..488058e --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/address-list.vue @@ -0,0 +1,87 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/after-sale-list.vue b/apps/web-ele/src/views/member/user/detail/modules/after-sale-list.vue new file mode 100644 index 0000000..5661f01 --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/after-sale-list.vue @@ -0,0 +1,156 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/balance-list.vue b/apps/web-ele/src/views/member/user/detail/modules/balance-list.vue new file mode 100644 index 0000000..86b148c --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/balance-list.vue @@ -0,0 +1,43 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/basic-info.vue b/apps/web-ele/src/views/member/user/detail/modules/basic-info.vue new file mode 100644 index 0000000..c6e3891 --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/basic-info.vue @@ -0,0 +1,98 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/brokerage-list.vue b/apps/web-ele/src/views/member/user/detail/modules/brokerage-list.vue new file mode 100644 index 0000000..5adb98f --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/brokerage-list.vue @@ -0,0 +1,125 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/coupon-list.vue b/apps/web-ele/src/views/member/user/detail/modules/coupon-list.vue new file mode 100644 index 0000000..51b908f --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/coupon-list.vue @@ -0,0 +1,156 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/experience-record-list.vue b/apps/web-ele/src/views/member/user/detail/modules/experience-record-list.vue new file mode 100644 index 0000000..cd3d71e --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/experience-record-list.vue @@ -0,0 +1,150 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/favorite-list.vue b/apps/web-ele/src/views/member/user/detail/modules/favorite-list.vue new file mode 100644 index 0000000..7fa7231 --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/favorite-list.vue @@ -0,0 +1,98 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/order-list.vue b/apps/web-ele/src/views/member/user/detail/modules/order-list.vue new file mode 100644 index 0000000..37b562b --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/order-list.vue @@ -0,0 +1,133 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/point-list.vue b/apps/web-ele/src/views/member/user/detail/modules/point-list.vue new file mode 100644 index 0000000..40ef482 --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/point-list.vue @@ -0,0 +1,68 @@ + + + diff --git a/apps/web-ele/src/views/member/user/detail/modules/sign-list.vue b/apps/web-ele/src/views/member/user/detail/modules/sign-list.vue new file mode 100644 index 0000000..afede65 --- /dev/null +++ b/apps/web-ele/src/views/member/user/detail/modules/sign-list.vue @@ -0,0 +1,65 @@ + + + diff --git a/apps/web-ele/src/views/member/user/index.vue b/apps/web-ele/src/views/member/user/index.vue new file mode 100644 index 0000000..6e166cd --- /dev/null +++ b/apps/web-ele/src/views/member/user/index.vue @@ -0,0 +1,212 @@ + + + diff --git a/apps/web-ele/src/views/member/user/modules/balance-form.vue b/apps/web-ele/src/views/member/user/modules/balance-form.vue new file mode 100644 index 0000000..0a5c34f --- /dev/null +++ b/apps/web-ele/src/views/member/user/modules/balance-form.vue @@ -0,0 +1,96 @@ + + + diff --git a/apps/web-ele/src/views/member/user/modules/form.vue b/apps/web-ele/src/views/member/user/modules/form.vue new file mode 100644 index 0000000..b70c081 --- /dev/null +++ b/apps/web-ele/src/views/member/user/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/member/user/modules/level-form.vue b/apps/web-ele/src/views/member/user/modules/level-form.vue new file mode 100644 index 0000000..50d5c6f --- /dev/null +++ b/apps/web-ele/src/views/member/user/modules/level-form.vue @@ -0,0 +1,81 @@ + + + diff --git a/apps/web-ele/src/views/member/user/modules/point-form.vue b/apps/web-ele/src/views/member/user/modules/point-form.vue new file mode 100644 index 0000000..16d810d --- /dev/null +++ b/apps/web-ele/src/views/member/user/modules/point-form.vue @@ -0,0 +1,83 @@ + + + diff --git a/apps/web-ele/src/views/mp/account/data.ts b/apps/web-ele/src/views/mp/account/data.ts new file mode 100644 index 0000000..d520153 --- /dev/null +++ b/apps/web-ele/src/views/mp/account/data.ts @@ -0,0 +1,143 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeGridPropTypes } from '#/adapter/vxe-table'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名称', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入名称', + }, + }, + { + fieldName: 'account', + label: '微信号', + component: 'Input', + help: '在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 账号详情] 中能找到「微信号」', + rules: 'required', + componentProps: { + placeholder: '请输入微信号', + }, + }, + { + fieldName: 'appId', + label: 'appId', + component: 'Input', + help: '在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 基本设置] 中能找到「开发者ID(AppID)」', + rules: 'required', + componentProps: { + placeholder: '请输入公众号 appId', + }, + }, + { + fieldName: 'appSecret', + label: 'appSecret', + component: 'Input', + help: '在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 基本设置] 中能找到「开发者密码(AppSecret)」', + rules: 'required', + componentProps: { + placeholder: '请输入公众号 appSecret', + }, + }, + { + fieldName: 'token', + label: 'token', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入公众号 token', + }, + }, + { + fieldName: 'aesKey', + label: '消息加解密密钥', + component: 'Input', + componentProps: { + placeholder: '请输入消息加解密密钥', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 搜索表单配置 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名称', + component: 'Input', + componentProps: { + placeholder: '请输入名称', + clearable: true, + }, + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns(): VxeGridPropTypes.Columns { + return [ + { + title: '名称', + field: 'name', + minWidth: 150, + }, + { + title: '微信号', + field: 'account', + minWidth: 180, + }, + { + title: 'appId', + field: 'appId', + minWidth: 180, + }, + { + title: '服务器地址(URL)', + field: 'utl', + minWidth: 360, + slots: { + default: ({ row }) => { + return `http://服务端地址/admin-api/mp/open/${row.appId}`; + }, + }, + }, + { + title: '二维码', + field: 'qrCodeUrl', + minWidth: 120, + cellRender: { name: 'CellImage' }, + }, + { + title: '备注', + field: 'remark', + minWidth: 150, + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/account/index.vue b/apps/web-ele/src/views/mp/account/index.vue new file mode 100644 index 0000000..ff77958 --- /dev/null +++ b/apps/web-ele/src/views/mp/account/index.vue @@ -0,0 +1,178 @@ + + + diff --git a/apps/web-ele/src/views/mp/account/modules/form.vue b/apps/web-ele/src/views/mp/account/modules/form.vue new file mode 100644 index 0000000..792f9e0 --- /dev/null +++ b/apps/web-ele/src/views/mp/account/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/mp/autoReply/data.ts b/apps/web-ele/src/views/mp/autoReply/data.ts new file mode 100644 index 0000000..2f8c3e4 --- /dev/null +++ b/apps/web-ele/src/views/mp/autoReply/data.ts @@ -0,0 +1,147 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeGridPropTypes } from '#/adapter/vxe-table'; + +import { markRaw } from 'vue'; + +import { + AutoReplyMsgType, + DICT_TYPE, + RequestMessageTypes, +} from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { WxReply } from '#/views/mp/components'; + +/** 获取表格列配置 */ +export function useGridColumns( + msgType: AutoReplyMsgType, +): VxeGridPropTypes.Columns { + const columns: VxeGridPropTypes.Columns = []; + // 请求消息类型列(仅消息回复显示) + if (msgType === AutoReplyMsgType.Message) { + columns.push({ + field: 'requestMessageType', + title: '请求消息类型', + minWidth: 120, + }); + } + // 关键词列(仅关键词回复显示) + if (msgType === AutoReplyMsgType.Keyword) { + columns.push({ + field: 'requestKeyword', + title: '关键词', + minWidth: 150, + }); + } + // 匹配类型列(仅关键词回复显示) + if (msgType === AutoReplyMsgType.Keyword) { + columns.push({ + field: 'requestMatch', + title: '匹配类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MP_AUTO_REPLY_REQUEST_MATCH }, + }, + }); + } + // 回复消息类型列 + columns.push( + { + field: 'responseMessageType', + title: '回复消息类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MP_MESSAGE_TYPE }, + }, + }, + { + field: 'responseContent', + title: '回复内容', + minWidth: 200, + slots: { default: 'replyContent' }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 140, + fixed: 'right', + slots: { default: 'actions' }, + }, + ); + return columns; +} + +/** 新增/修改的表单 */ +export function useFormSchema(msgType: AutoReplyMsgType): VbenFormSchema[] { + const schema: VbenFormSchema[] = []; + // 消息类型(仅消息回复显示) + if (msgType === AutoReplyMsgType.Message) { + schema.push({ + fieldName: 'requestMessageType', + label: '消息类型', + component: 'Select', + componentProps: { + placeholder: '请选择', + options: getDictOptions(DICT_TYPE.MP_MESSAGE_TYPE).filter((d) => + RequestMessageTypes.has(d.value as string), + ), + }, + }); + } + // 匹配类型(仅关键词回复显示) + if (msgType === AutoReplyMsgType.Keyword) { + schema.push({ + fieldName: 'requestMatch', + label: '匹配类型', + component: 'Select', + componentProps: { + placeholder: '请选择匹配类型', + allowClear: true, + options: getDictOptions( + DICT_TYPE.MP_AUTO_REPLY_REQUEST_MATCH, + 'number', + ), + }, + rules: 'required', + }); + } + // 关键词(仅关键词回复显示) + if (msgType === AutoReplyMsgType.Keyword) { + schema.push({ + fieldName: 'requestKeyword', + label: '关键词', + component: 'Input', + componentProps: { + placeholder: '请输入内容', + allowClear: true, + }, + rules: 'required', + }); + } + // 回复消息 + schema.push({ + fieldName: 'reply', + label: '回复消息', + component: markRaw(WxReply), + modelPropName: 'modelValue', + }); + return schema; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'accountId', + label: '公众号', + component: 'Input', + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/autoReply/index.vue b/apps/web-ele/src/views/mp/autoReply/index.vue new file mode 100644 index 0000000..4ed1b84 --- /dev/null +++ b/apps/web-ele/src/views/mp/autoReply/index.vue @@ -0,0 +1,233 @@ + + + diff --git a/apps/web-ele/src/views/mp/autoReply/modules/content.vue b/apps/web-ele/src/views/mp/autoReply/modules/content.vue new file mode 100644 index 0000000..caa022c --- /dev/null +++ b/apps/web-ele/src/views/mp/autoReply/modules/content.vue @@ -0,0 +1,57 @@ + + + diff --git a/apps/web-ele/src/views/mp/autoReply/modules/form.vue b/apps/web-ele/src/views/mp/autoReply/modules/form.vue new file mode 100644 index 0000000..ef7eaaa --- /dev/null +++ b/apps/web-ele/src/views/mp/autoReply/modules/form.vue @@ -0,0 +1,156 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/index.ts b/apps/web-ele/src/views/mp/components/index.ts new file mode 100644 index 0000000..abab7ff --- /dev/null +++ b/apps/web-ele/src/views/mp/components/index.ts @@ -0,0 +1,9 @@ +export { default as WxAccountSelect } from './wx-account-select/wx-account-select.vue'; +export { default as WxLocation } from './wx-location/wx-location.vue'; +export { default as WxMaterialSelect } from './wx-material-select/wx-material-select.vue'; +export { default as WxMsg } from './wx-msg/wx-msg.vue'; +export { default as WxMusic } from './wx-music/wx-music.vue'; +export { default as WxNews } from './wx-news/wx-news.vue'; +export { default as WxReply } from './wx-reply/wx-reply.vue'; +export { default as WxVideoPlayer } from './wx-video-play/wx-video-play.vue'; +export { default as WxVoicePlayer } from './wx-voice-play/wx-voice-play.vue'; diff --git a/apps/web-ele/src/views/mp/components/wx-account-select/wx-account-select.vue b/apps/web-ele/src/views/mp/components/wx-account-select/wx-account-select.vue new file mode 100644 index 0000000..5a37a5b --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-account-select/wx-account-select.vue @@ -0,0 +1,72 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-location/types.ts b/apps/web-ele/src/views/mp/components/wx-location/types.ts new file mode 100644 index 0000000..9566c2a --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-location/types.ts @@ -0,0 +1,6 @@ +export interface WxLocationProps { + label: string; + locationX: number; + locationY: number; + qqMapKey?: string; +} diff --git a/apps/web-ele/src/views/mp/components/wx-location/wx-location.vue b/apps/web-ele/src/views/mp/components/wx-location/wx-location.vue new file mode 100644 index 0000000..99130bd --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-location/wx-location.vue @@ -0,0 +1,72 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-material-select/wx-material-select.vue b/apps/web-ele/src/views/mp/components/wx-material-select/wx-material-select.vue new file mode 100644 index 0000000..3a6a0e0 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-material-select/wx-material-select.vue @@ -0,0 +1,559 @@ + + + + + diff --git a/apps/web-ele/src/views/mp/components/wx-msg/msg-event.vue b/apps/web-ele/src/views/mp/components/wx-msg/msg-event.vue new file mode 100644 index 0000000..12b86cd --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-msg/msg-event.vue @@ -0,0 +1,54 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-msg/msg-list.vue b/apps/web-ele/src/views/mp/components/wx-msg/msg-list.vue new file mode 100644 index 0000000..8bed75e --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-msg/msg-list.vue @@ -0,0 +1,82 @@ + + diff --git a/apps/web-ele/src/views/mp/components/wx-msg/msg.vue b/apps/web-ele/src/views/mp/components/wx-msg/msg.vue new file mode 100644 index 0000000..1a9ab50 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-msg/msg.vue @@ -0,0 +1,92 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-msg/wx-msg.vue b/apps/web-ele/src/views/mp/components/wx-msg/wx-msg.vue new file mode 100644 index 0000000..f6ca8c5 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-msg/wx-msg.vue @@ -0,0 +1,176 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-music/types.ts b/apps/web-ele/src/views/mp/components/wx-music/types.ts new file mode 100644 index 0000000..5164f53 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-music/types.ts @@ -0,0 +1,7 @@ +export interface WxMusicProps { + title?: string; + description?: string; + musicUrl?: string; + hqMusicUrl?: string; + thumbMediaUrl: string; +} diff --git a/apps/web-ele/src/views/mp/components/wx-music/wx-music.vue b/apps/web-ele/src/views/mp/components/wx-music/wx-music.vue new file mode 100644 index 0000000..959b940 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-music/wx-music.vue @@ -0,0 +1,54 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-news/wx-news.vue b/apps/web-ele/src/views/mp/components/wx-news/wx-news.vue new file mode 100644 index 0000000..6e52761 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-news/wx-news.vue @@ -0,0 +1,57 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-reply/tab-image.vue b/apps/web-ele/src/views/mp/components/wx-reply/tab-image.vue new file mode 100644 index 0000000..c8700ab --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-reply/tab-image.vue @@ -0,0 +1,158 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-reply/tab-music.vue b/apps/web-ele/src/views/mp/components/wx-reply/tab-music.vue new file mode 100644 index 0000000..728609d --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-reply/tab-music.vue @@ -0,0 +1,146 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-reply/tab-news.vue b/apps/web-ele/src/views/mp/components/wx-reply/tab-news.vue new file mode 100644 index 0000000..c6cd948 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-reply/tab-news.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-reply/tab-text.vue b/apps/web-ele/src/views/mp/components/wx-reply/tab-text.vue new file mode 100644 index 0000000..790f7fa --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-reply/tab-text.vue @@ -0,0 +1,32 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-reply/tab-video.vue b/apps/web-ele/src/views/mp/components/wx-reply/tab-video.vue new file mode 100644 index 0000000..13be729 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-reply/tab-video.vue @@ -0,0 +1,145 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-reply/tab-voice.vue b/apps/web-ele/src/views/mp/components/wx-reply/tab-voice.vue new file mode 100644 index 0000000..3893f94 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-reply/tab-voice.vue @@ -0,0 +1,158 @@ + + diff --git a/apps/web-ele/src/views/mp/components/wx-reply/types.ts b/apps/web-ele/src/views/mp/components/wx-reply/types.ts new file mode 100644 index 0000000..502b4c5 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-reply/types.ts @@ -0,0 +1,42 @@ +import type { Ref } from 'vue'; + +import type { ReplyType } from '@vben/constants'; + +import { unref } from 'vue'; + +export interface Reply { + accountId: number; + articles?: any[]; + content?: null | string; + description?: null | string; + hqMusicUrl?: null | string; + introduction?: null | string; + mediaId?: null | string; + musicUrl?: null | string; + name?: null | string; + thumbMediaId?: null | string; + thumbMediaUrl?: null | string; + title?: null | string; + type: ReplyType; + url?: null | string; +} + +/** 利用旧的 reply[accountId, type] 初始化新的 Reply */ +export function createEmptyReply(old: Ref | Reply): Reply { + return { + accountId: unref(old).accountId, + articles: [], + content: null, + description: null, + hqMusicUrl: null, + introduction: null, + mediaId: null, + musicUrl: null, + name: null, + thumbMediaId: null, + thumbMediaUrl: null, + title: null, + type: unref(old).type, + url: null, + }; +} diff --git a/apps/web-ele/src/views/mp/components/wx-reply/wx-reply.vue b/apps/web-ele/src/views/mp/components/wx-reply/wx-reply.vue new file mode 100644 index 0000000..f80dece --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-reply/wx-reply.vue @@ -0,0 +1,171 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-video-play/wx-video-play.vue b/apps/web-ele/src/views/mp/components/wx-video-play/wx-video-play.vue new file mode 100644 index 0000000..520d2e5 --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-video-play/wx-video-play.vue @@ -0,0 +1,48 @@ + + + diff --git a/apps/web-ele/src/views/mp/components/wx-voice-play/wx-voice-play.vue b/apps/web-ele/src/views/mp/components/wx-voice-play/wx-voice-play.vue new file mode 100644 index 0000000..70b8efa --- /dev/null +++ b/apps/web-ele/src/views/mp/components/wx-voice-play/wx-voice-play.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/mp/draft/data.ts b/apps/web-ele/src/views/mp/draft/data.ts new file mode 100644 index 0000000..1ee1e10 --- /dev/null +++ b/apps/web-ele/src/views/mp/draft/data.ts @@ -0,0 +1,45 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { formatDateTime } from '@vben/utils'; + +/** 获取表格列配置 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'cover', + title: '图片', + width: 360, + slots: { default: 'cover' }, + }, + { + field: 'title', + title: '标题', + slots: { default: 'title' }, + }, + { + field: 'updateTime', + title: '修改时间', + formatter: ({ row }) => { + return formatDateTime(row.updateTime * 1000); + }, + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'accountId', + label: '公众号', + component: 'Input', + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/draft/index.vue b/apps/web-ele/src/views/mp/draft/index.vue new file mode 100644 index 0000000..e6bfa4f --- /dev/null +++ b/apps/web-ele/src/views/mp/draft/index.vue @@ -0,0 +1,267 @@ + + + + + diff --git a/apps/web-ele/src/views/mp/draft/modules/cover-select.vue b/apps/web-ele/src/views/mp/draft/modules/cover-select.vue new file mode 100644 index 0000000..0a4a302 --- /dev/null +++ b/apps/web-ele/src/views/mp/draft/modules/cover-select.vue @@ -0,0 +1,146 @@ + + + diff --git a/apps/web-ele/src/views/mp/draft/modules/form.vue b/apps/web-ele/src/views/mp/draft/modules/form.vue new file mode 100644 index 0000000..e77e8f6 --- /dev/null +++ b/apps/web-ele/src/views/mp/draft/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/mp/draft/modules/news-form.vue b/apps/web-ele/src/views/mp/draft/modules/news-form.vue new file mode 100644 index 0000000..632e385 --- /dev/null +++ b/apps/web-ele/src/views/mp/draft/modules/news-form.vue @@ -0,0 +1,260 @@ + + + diff --git a/apps/web-ele/src/views/mp/freePublish/data.ts b/apps/web-ele/src/views/mp/freePublish/data.ts new file mode 100644 index 0000000..82cfb5f --- /dev/null +++ b/apps/web-ele/src/views/mp/freePublish/data.ts @@ -0,0 +1,59 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeGridPropTypes } from '#/adapter/vxe-table'; +import type { MpAccountApi } from '#/api/mp/account'; + +import { formatDateTime } from '@vben/utils'; + +import { getSimpleAccountList } from '#/api/mp/account'; + +let accountList: MpAccountApi.Account[] = []; +getSimpleAccountList().then((data) => (accountList = data)); + +/** 搜索表单配置 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'accountId', + label: '公众号', + component: 'Select', + componentProps: { + options: accountList.map((item) => ({ + label: item.name, + value: item.id, + })), + placeholder: '请选择公众号', + clearable: true, + }, + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns(): VxeGridPropTypes.Columns { + return [ + { + field: 'cover', + title: '图片', + width: 360, + slots: { default: 'cover' }, + }, + { + field: 'title', + title: '标题', + slots: { default: 'title' }, + }, + { + field: 'updateTime', + title: '修改时间', + formatter: ({ row }) => { + return formatDateTime(row.updateTime * 1000); + }, + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/freePublish/index.vue b/apps/web-ele/src/views/mp/freePublish/index.vue new file mode 100644 index 0000000..fdd6915 --- /dev/null +++ b/apps/web-ele/src/views/mp/freePublish/index.vue @@ -0,0 +1,172 @@ + + + + + diff --git a/apps/web-ele/src/views/mp/hooks/useUpload.ts b/apps/web-ele/src/views/mp/hooks/useUpload.ts new file mode 100644 index 0000000..3a8d21f --- /dev/null +++ b/apps/web-ele/src/views/mp/hooks/useUpload.ts @@ -0,0 +1,76 @@ +import { ElMessage } from 'element-plus'; + +import { $t } from '#/locales'; + +export enum UploadType { + Image = 'image', + Video = 'video', + Voice = 'voice', +} + +interface UploadTypeConfig { + allowTypes: string[]; + maxSizeMB: number; + i18nKey: string; +} + +export interface UploadRawFile { + name: string; + size: number; + type: string; +} + +const UPLOAD_CONFIGS: Record = { + [UploadType.Image]: { + allowTypes: [ + 'image/jpeg', + 'image/png', + 'image/gif', + 'image/bmp', + 'image/jpg', + ], + maxSizeMB: 2, + i18nKey: 'mp.upload.image', + }, + [UploadType.Video]: { + allowTypes: ['video/mp4'], + maxSizeMB: 10, + i18nKey: 'mp.upload.video', + }, + [UploadType.Voice]: { + allowTypes: [ + 'audio/mp3', + 'audio/mpeg', + 'audio/wma', + 'audio/wav', + 'audio/amr', + ], + maxSizeMB: 2, + i18nKey: 'mp.upload.voice', + }, +}; + +export const useBeforeUpload = (type: UploadType, maxSizeMB?: number) => { + const fn = (rawFile: UploadRawFile): boolean => { + const config = UPLOAD_CONFIGS[type]; + const finalMaxSize = maxSizeMB ?? config.maxSizeMB; + + // 格式不正确 + if (!config.allowTypes.includes(rawFile.type)) { + const typeName = $t(config.i18nKey); + ElMessage.error($t('mp.upload.invalidFormat', [typeName])); + return false; + } + + // 大小不正确 + if (rawFile.size / 1024 / 1024 > finalMaxSize) { + const typeName = $t(config.i18nKey); + ElMessage.error($t('mp.upload.maxSize', [typeName, finalMaxSize])); + return false; + } + + return true; + }; + + return fn; +}; diff --git a/apps/web-ele/src/views/mp/material/index.vue b/apps/web-ele/src/views/mp/material/index.vue new file mode 100644 index 0000000..b1dcb2f --- /dev/null +++ b/apps/web-ele/src/views/mp/material/index.vue @@ -0,0 +1,259 @@ + + + diff --git a/apps/web-ele/src/views/mp/material/modules/UploadFile.vue b/apps/web-ele/src/views/mp/material/modules/UploadFile.vue new file mode 100644 index 0000000..fe364e9 --- /dev/null +++ b/apps/web-ele/src/views/mp/material/modules/UploadFile.vue @@ -0,0 +1,110 @@ + + + diff --git a/apps/web-ele/src/views/mp/material/modules/UploadVideo.vue b/apps/web-ele/src/views/mp/material/modules/UploadVideo.vue new file mode 100644 index 0000000..cbf187e --- /dev/null +++ b/apps/web-ele/src/views/mp/material/modules/UploadVideo.vue @@ -0,0 +1,169 @@ + + + diff --git a/apps/web-ele/src/views/mp/material/modules/data.ts b/apps/web-ele/src/views/mp/material/modules/data.ts new file mode 100644 index 0000000..cd3e07a --- /dev/null +++ b/apps/web-ele/src/views/mp/material/modules/data.ts @@ -0,0 +1,145 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MpMaterialApi } from '#/api/mp/material'; + +/** 视频表格列配置 */ +export function useVideoGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'mediaId', + title: '编号', + align: 'center', + width: 160, + }, + { + field: 'name', + title: '文件名', + align: 'center', + minWidth: 100, + }, + { + field: 'title', + title: '标题', + align: 'center', + minWidth: 200, + }, + { + field: 'introduction', + title: '介绍', + align: 'center', + minWidth: 220, + }, + { + field: 'video', + title: '视频', + align: 'center', + width: 220, + slots: { default: 'video' }, + }, + { + field: 'createTime', + title: '上传时间', + align: 'center', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'actions', + title: '操作', + align: 'center', + fixed: 'right', + width: 180, + slots: { default: 'actions' }, + }, + ]; +} + +/** 语音表格列配置 */ +export function useVoiceGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'mediaId', + title: '编号', + align: 'center', + width: 160, + }, + { + field: 'name', + title: '文件名', + align: 'center', + minWidth: 100, + }, + { + field: 'voice', + title: '语音', + align: 'center', + width: 220, + slots: { default: 'voice' }, + }, + { + field: 'createTime', + title: '上传时间', + align: 'center', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'actions', + title: '操作', + align: 'center', + fixed: 'right', + width: 160, + slots: { default: 'actions' }, + }, + ]; +} + +/** 图片表格列配置 */ +export function useImageGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'mediaId', + title: '编号', + align: 'center', + width: 400, + }, + { + field: 'name', + title: '文件名', + align: 'center', + width: 200, + }, + { + field: 'url', + title: '图片', + align: 'center', + width: 200, + slots: { default: 'image' }, + }, + { + field: 'createTime', + title: '上传时间', + align: 'center', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'actions', + title: '操作', + align: 'center', + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'accountId', + label: '公众号', + component: 'Input', + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/material/modules/upload.ts b/apps/web-ele/src/views/mp/material/modules/upload.ts new file mode 100644 index 0000000..2a2707d --- /dev/null +++ b/apps/web-ele/src/views/mp/material/modules/upload.ts @@ -0,0 +1,46 @@ +import type { UploadProps } from 'element-plus'; + +import type { UploadRawFile } from '#/views/mp/hooks/useUpload'; + +import { useAccessStore } from '@vben/stores'; + +import { UploadType, useBeforeUpload } from '#/views/mp/hooks/useUpload'; + +const accessStore = useAccessStore(); +const HEADERS = { Authorization: `Bearer ${accessStore.accessToken}` }; // 请求头 +const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-permanent`; // 上传地址 + +interface UploadData { + accountId: number; + introduction: string; + title: string; + type: UploadType; +} + +const beforeImageUpload: UploadProps['beforeUpload'] = function ( + rawFile: UploadRawFile, +) { + return useBeforeUpload(UploadType.Image, 2)(rawFile); +}; + +const beforeVoiceUpload: UploadProps['beforeUpload'] = function ( + rawFile: UploadRawFile, +) { + return useBeforeUpload(UploadType.Voice, 2)(rawFile); +}; + +const beforeVideoUpload: UploadProps['beforeUpload'] = function ( + rawFile: UploadRawFile, +) { + return useBeforeUpload(UploadType.Video, 10)(rawFile); +}; + +export { + beforeImageUpload, + beforeVideoUpload, + beforeVoiceUpload, + HEADERS, + UPLOAD_URL, + type UploadData, + UploadType, +}; diff --git a/apps/web-ele/src/views/mp/menu/assets/iphone_backImg.png b/apps/web-ele/src/views/mp/menu/assets/iphone_backImg.png new file mode 100644 index 0000000..bb09591 Binary files /dev/null and b/apps/web-ele/src/views/mp/menu/assets/iphone_backImg.png differ diff --git a/apps/web-ele/src/views/mp/menu/assets/menu_foot.png b/apps/web-ele/src/views/mp/menu/assets/menu_foot.png new file mode 100644 index 0000000..4a89d4b Binary files /dev/null and b/apps/web-ele/src/views/mp/menu/assets/menu_foot.png differ diff --git a/apps/web-ele/src/views/mp/menu/assets/menu_head.png b/apps/web-ele/src/views/mp/menu/assets/menu_head.png new file mode 100644 index 0000000..248cfb7 Binary files /dev/null and b/apps/web-ele/src/views/mp/menu/assets/menu_head.png differ diff --git a/apps/web-ele/src/views/mp/menu/data.ts b/apps/web-ele/src/views/mp/menu/data.ts new file mode 100644 index 0000000..ddb2bea --- /dev/null +++ b/apps/web-ele/src/views/mp/menu/data.ts @@ -0,0 +1,31 @@ +import type { VbenFormSchema } from '#/adapter/form'; + +import { getSimpleAccountList } from '#/api/mp/account'; + +/** 菜单未选中标识 */ +export const MENU_NOT_SELECTED = '__MENU_NOT_SELECTED__'; + +/** 菜单级别枚举 */ +export enum Level { + Child = '2', + Parent = '1', + Undefined = '0', +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'accountId', + label: '公众号', + component: 'ApiSelect', + componentProps: { + api: getSimpleAccountList, + labelField: 'name', + valueField: 'id', + autoSelect: 'first', + placeholder: '请选择公众号', + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/menu/index.vue b/apps/web-ele/src/views/mp/menu/index.vue new file mode 100644 index 0000000..b4a0ec5 --- /dev/null +++ b/apps/web-ele/src/views/mp/menu/index.vue @@ -0,0 +1,374 @@ + + + diff --git a/apps/web-ele/src/views/mp/menu/modules/editor.vue b/apps/web-ele/src/views/mp/menu/modules/editor.vue new file mode 100644 index 0000000..103b2de --- /dev/null +++ b/apps/web-ele/src/views/mp/menu/modules/editor.vue @@ -0,0 +1,222 @@ + + + diff --git a/apps/web-ele/src/views/mp/menu/modules/previewer.vue b/apps/web-ele/src/views/mp/menu/modules/previewer.vue new file mode 100644 index 0000000..ba7c24c --- /dev/null +++ b/apps/web-ele/src/views/mp/menu/modules/previewer.vue @@ -0,0 +1,206 @@ + + + + + diff --git a/apps/web-ele/src/views/mp/menu/modules/types.ts b/apps/web-ele/src/views/mp/menu/modules/types.ts new file mode 100644 index 0000000..ae0edbd --- /dev/null +++ b/apps/web-ele/src/views/mp/menu/modules/types.ts @@ -0,0 +1,116 @@ +export interface Replay { + title: string; + description: string; + picUrl: string; + url: string; +} + +export type MenuType = + | '' + | 'article_view_limited' + | 'click' + | 'location_select' + | 'pic_photo_or_album' + | 'pic_sysphoto' + | 'pic_weixin' + | 'scancode_push' + | 'scancode_waitmsg' + | 'view'; + +interface _RawMenu { + // db + id: number; + parentId: number; + accountId: number; + appId: string; + createTime: number; + + // mp-native + name: string; + menuKey: string; + type: MenuType; + url: string; + miniProgramAppId: string; + miniProgramPagePath: string; + articleId: string; + replyMessageType: string; + replyContent: string; + replyMediaId: string; + replyMediaUrl: string; + replyThumbMediaId: string; + replyThumbMediaUrl: string; + replyTitle: string; + replyDescription: string; + replyArticles: Replay; + replyMusicUrl: string; + replyHqMusicUrl: string; +} + +export type RawMenu = Partial<_RawMenu>; + +interface _Reply { + type: string; + accountId: number; + content: string; + mediaId: string; + url: string; + thumbMediaId: string; + thumbMediaUrl: string; + title: string; + description: string; + articles: null | Replay[]; + musicUrl: string; + hqMusicUrl: string; +} + +export type Reply = Partial<_Reply>; + +interface _Menu extends RawMenu { + children: _Menu[]; + reply: Reply; +} + +export type Menu = Partial<_Menu>; + +export const menuOptions = [ + { + value: 'view', + label: '跳转网页', + }, + { + value: 'miniprogram', + label: '跳转小程序', + }, + { + value: 'click', + label: '点击回复', + }, + { + value: 'article_view_limited', + label: '跳转图文消息', + }, + { + value: 'scancode_push', + label: '扫码直接返回结果', + }, + { + value: 'scancode_waitmsg', + label: '扫码回复', + }, + { + value: 'pic_sysphoto', + label: '系统拍照发图', + }, + { + value: 'pic_photo_or_album', + label: '拍照或者相册', + }, + { + value: 'pic_weixin', + label: '微信相册', + }, + { + value: 'location_select', + label: '选择地理位置', + }, +]; diff --git a/apps/web-ele/src/views/mp/message/data.ts b/apps/web-ele/src/views/mp/message/data.ts new file mode 100644 index 0000000..1f07fb1 --- /dev/null +++ b/apps/web-ele/src/views/mp/message/data.ts @@ -0,0 +1,94 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MpMessageApi } from '#/api/mp/message'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'accountId', + label: '公众号', + component: 'Input', + }, + { + fieldName: 'type', + label: '消息类型', + component: 'Select', + componentProps: { + placeholder: '请选择消息类型', + options: getDictOptions(DICT_TYPE.MP_MESSAGE_TYPE), + clearable: true, + }, + }, + { + fieldName: 'openid', + label: '用户标识', + component: 'Input', + componentProps: { + placeholder: '请输入用户标识', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'createTime', + title: '发送时间', + width: 180, + align: 'center', + slots: { default: 'createTime' }, + }, + { + field: 'type', + title: '消息类型', + width: 80, + align: 'center', + }, + { + field: 'sendFrom', + title: '发送方', + width: 80, + align: 'center', + slots: { default: 'sendFrom' }, + }, + { + field: 'openid', + title: '用户标识', + width: 300, + align: 'center', + }, + { + field: 'content', + title: '内容', + align: 'left', + minWidth: 320, + slots: { default: 'content' }, + }, + { + field: 'actions', + title: '操作', + width: 120, + align: 'center', + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/message/index.vue b/apps/web-ele/src/views/mp/message/index.vue new file mode 100644 index 0000000..8f49171 --- /dev/null +++ b/apps/web-ele/src/views/mp/message/index.vue @@ -0,0 +1,239 @@ + + + diff --git a/apps/web-ele/src/views/mp/messageTemplate/data.ts b/apps/web-ele/src/views/mp/messageTemplate/data.ts new file mode 100644 index 0000000..8dadf55 --- /dev/null +++ b/apps/web-ele/src/views/mp/messageTemplate/data.ts @@ -0,0 +1,143 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeGridPropTypes } from '#/adapter/vxe-table'; + +import { getUserPage } from '#/api/mp/user'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'accountId', + label: '公众号', + component: 'Input', + }, + ]; +} + +/** 发送消息模板表单 */ +export function useSendFormSchema(accountId?: number): VbenFormSchema[] { + return [ + { + fieldName: 'id', + label: '模板编号', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'title', + label: '模板标题', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'userId', + label: '用户', + component: 'ApiSelect', + componentProps: { + api: async () => { + if (!accountId) { + return []; + } + const data = await getUserPage({ + pageNo: 1, + pageSize: 100, + accountId, + }); + return (data.list || []).map((user) => ({ + label: user.nickname || user.openid, + value: user.id, + })); + }, + filterable: true, + placeholder: '请选择用户', + }, + rules: 'required', + }, + { + fieldName: 'data', + label: '模板数据', + component: 'Textarea', + componentProps: { + rows: 4, + placeholder: + '请输入模板数据(JSON 格式),例如:{"keyword1": {"value": "测试内容"}}', + }, + }, + { + fieldName: 'url', + label: '跳转链接', + component: 'Input', + componentProps: { + placeholder: '请输入跳转链接', + }, + }, + { + fieldName: 'miniProgramAppId', + label: '小程序 appId', + component: 'Input', + componentProps: { + placeholder: '请输入小程序 appId', + }, + }, + { + fieldName: 'miniProgramPagePath', + label: '小程序页面路径', + component: 'Input', + componentProps: { + placeholder: '请输入小程序页面路径', + }, + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns(): VxeGridPropTypes.Columns { + return [ + { + title: '公众号模板 ID', + field: 'templateId', + minWidth: 400, + }, + { + title: '标题', + field: 'title', + minWidth: 150, + }, + { + title: '模板内容', + field: 'content', + minWidth: 400, + }, + { + title: '模板示例', + field: 'example', + minWidth: 200, + }, + { + title: '一级行业', + field: 'primaryIndustry', + minWidth: 120, + }, + { + title: '二级行业', + field: 'deputyIndustry', + minWidth: 120, + }, + { + title: '创建时间', + field: 'createTime', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + title: '操作', + width: 140, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/messageTemplate/index.vue b/apps/web-ele/src/views/mp/messageTemplate/index.vue new file mode 100644 index 0000000..67405fb --- /dev/null +++ b/apps/web-ele/src/views/mp/messageTemplate/index.vue @@ -0,0 +1,165 @@ + + + diff --git a/apps/web-ele/src/views/mp/messageTemplate/modules/send-form.vue b/apps/web-ele/src/views/mp/messageTemplate/modules/send-form.vue new file mode 100644 index 0000000..ef809aa --- /dev/null +++ b/apps/web-ele/src/views/mp/messageTemplate/modules/send-form.vue @@ -0,0 +1,103 @@ + + + diff --git a/apps/web-ele/src/views/mp/statistics/chart-options.ts b/apps/web-ele/src/views/mp/statistics/chart-options.ts new file mode 100644 index 0000000..700cb34 --- /dev/null +++ b/apps/web-ele/src/views/mp/statistics/chart-options.ts @@ -0,0 +1,163 @@ +import type { MpStatisticsApi } from '#/api/mp/statistics'; + +/** 用户增减数据图表配置项 */ +export function userSummaryOption( + data: MpStatisticsApi.StatisticsUserSummaryRespVO[], + dates: string[], +): any { + return { + color: ['#67C23A', '#E5323E'], + legend: { + data: ['新增用户', '取消关注的用户'], + }, + tooltip: {}, + xAxis: { + data: dates, + }, + yAxis: { + minInterval: 1, + }, + series: [ + { + name: '新增用户', + type: 'bar', + label: { + show: true, + }, + barGap: 0, + data: data.map((item) => item.newUser), // 新增用户的数据 + }, + { + name: '取消关注的用户', + type: 'bar', + label: { + show: true, + }, + data: data.map((item) => item.cancelUser), // 取消关注的用户的数据 + }, + ], + }; +} + +/** 累计用户数据图表配置项 */ +export function userCumulateOption( + data: MpStatisticsApi.StatisticsUserCumulateRespVO[], + dates: string[], +): any { + return { + legend: { + data: ['累计用户量'], + }, + xAxis: { + type: 'category', + data: dates, + }, + yAxis: { + minInterval: 1, + }, + series: [ + { + name: '累计用户量', + data: data.map((item) => item.cumulateUser), // 累计用户量的数据 + type: 'line', + smooth: true, + label: { + show: true, + }, + }, + ], + }; +} + +/** 消息发送概况数据图表配置项 */ +export function upstreamMessageOption( + data: MpStatisticsApi.StatisticsUpstreamMessageRespVO[], + dates: string[], +): any { + return { + color: ['#67C23A', '#E5323E'], + legend: { + data: ['用户发送人数', '用户发送条数'], + }, + tooltip: {}, + xAxis: { + data: dates, // X 轴的日期范围 + }, + yAxis: { + minInterval: 1, + }, + series: [ + { + name: '用户发送人数', + type: 'line', + smooth: true, + label: { + show: true, + }, + data: data.map((item) => item.msgUser), // 用户发送人数的数据 + }, + { + name: '用户发送条数', + type: 'line', + smooth: true, + label: { + show: true, + }, + data: data.map((item) => item.msgCount), // 用户发送条数的数据 + }, + ], + }; +} + +/** 接口分析况数据图表配置项 */ +export function interfaceSummaryOption( + data: MpStatisticsApi.StatisticsInterfaceSummaryRespVO[], + dates: string[], +): any { + return { + color: ['#67C23A', '#E5323E', '#E6A23C', '#409EFF'], + legend: { + data: ['被动回复用户消息的次数', '失败次数', '最大耗时', '总耗时'], + }, + tooltip: {}, + xAxis: { + data: dates, // X 轴的日期范围 + }, + yAxis: {}, + series: [ + { + name: '被动回复用户消息的次数', + type: 'bar', + label: { + show: true, + }, + barGap: 0, + data: data.map((item) => item.callbackCount), // 被动回复用户消息的次数的数据 + }, + { + name: '失败次数', + type: 'bar', + label: { + show: true, + }, + data: data.map((item) => item.failCount), // 失败次数的数据 + }, + { + name: '最大耗时', + type: 'bar', + label: { + show: true, + }, + data: data.map((item) => item.maxTimeCost), // 最大耗时的数据 + }, + { + name: '总耗时', + type: 'bar', + label: { + show: true, + }, + data: data.map((item) => item.totalTimeCost), // 总耗时的数据 + }, + ], + }; +} diff --git a/apps/web-ele/src/views/mp/statistics/data.ts b/apps/web-ele/src/views/mp/statistics/data.ts new file mode 100644 index 0000000..b1e34ef --- /dev/null +++ b/apps/web-ele/src/views/mp/statistics/data.ts @@ -0,0 +1,27 @@ +import type { VbenFormSchema } from '#/adapter/form'; + +import { beginOfDay, endOfDay, formatDateTime } from '@vben/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'accountId', + label: '公众号', + component: 'Input', + }, + { + fieldName: 'dateRange', + label: '时间范围', + component: 'RangePicker', + componentProps: { + format: 'YYYY-MM-DD', + valueFormat: 'YYYY-MM-DD HH:mm:ss', + }, + defaultValue: [ + formatDateTime(beginOfDay(new Date(Date.now() - 3600 * 1000 * 24 * 7))), + formatDateTime(endOfDay(new Date(Date.now() - 3600 * 1000 * 24))), + ], + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/statistics/index.vue b/apps/web-ele/src/views/mp/statistics/index.vue new file mode 100644 index 0000000..180ff6d --- /dev/null +++ b/apps/web-ele/src/views/mp/statistics/index.vue @@ -0,0 +1,157 @@ + + + diff --git a/apps/web-ele/src/views/mp/tag/data.ts b/apps/web-ele/src/views/mp/tag/data.ts new file mode 100644 index 0000000..ffce47f --- /dev/null +++ b/apps/web-ele/src/views/mp/tag/data.ts @@ -0,0 +1,78 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeGridPropTypes } from '#/adapter/vxe-table'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'accountId', + label: '公众号', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '标签名称', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入名称', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'accountId', + label: '公众号', + component: 'Input', + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns(): VxeGridPropTypes.Columns { + return [ + { + title: '编号', + field: 'id', + minWidth: 80, + }, + { + title: '标签名称', + field: 'name', + minWidth: 150, + }, + { + title: '粉丝数', + field: 'count', + minWidth: 100, + }, + { + title: '创建时间', + field: 'createTime', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + title: '操作', + width: 140, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/tag/index.vue b/apps/web-ele/src/views/mp/tag/index.vue new file mode 100644 index 0000000..8ae00b5 --- /dev/null +++ b/apps/web-ele/src/views/mp/tag/index.vue @@ -0,0 +1,177 @@ + + + diff --git a/apps/web-ele/src/views/mp/tag/modules/form.vue b/apps/web-ele/src/views/mp/tag/modules/form.vue new file mode 100644 index 0000000..ca1bf4a --- /dev/null +++ b/apps/web-ele/src/views/mp/tag/modules/form.vue @@ -0,0 +1,83 @@ + + + diff --git a/apps/web-ele/src/views/mp/user/data.ts b/apps/web-ele/src/views/mp/user/data.ts new file mode 100644 index 0000000..2935544 --- /dev/null +++ b/apps/web-ele/src/views/mp/user/data.ts @@ -0,0 +1,124 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +/** 修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'nickname', + label: '昵称', + component: 'Input', + componentProps: { + placeholder: '请输入昵称', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'accountId', + label: '公众号', + component: 'Input', + }, + { + fieldName: 'openid', + label: '用户标识', + component: 'Input', + componentProps: { + placeholder: '请输入用户标识', + clearable: true, + }, + }, + { + fieldName: 'nickname', + label: '昵称', + component: 'Input', + componentProps: { + placeholder: '请输入昵称', + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'openid', + title: '用户标识', + minWidth: 260, + }, + { + field: 'headImageUrl', + title: '用户头像', + minWidth: 80, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'nickname', + title: '昵称', + minWidth: 120, + }, + { + field: 'remark', + title: '备注', + minWidth: 120, + }, + { + field: 'tagIds', + title: '标签', + minWidth: 200, + cellRender: { + name: 'CellTags', + }, + }, + { + field: 'subscribeStatus', + title: '订阅状态', + minWidth: 100, + align: 'center', + formatter: ({ cellValue }) => { + return cellValue === 0 ? '已订阅' : '未订阅'; + }, + }, + { + field: 'subscribeTime', + title: '订阅时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mp/user/index.vue b/apps/web-ele/src/views/mp/user/index.vue new file mode 100644 index 0000000..42212f8 --- /dev/null +++ b/apps/web-ele/src/views/mp/user/index.vue @@ -0,0 +1,137 @@ + + + diff --git a/apps/web-ele/src/views/mp/user/modules/form.vue b/apps/web-ele/src/views/mp/user/modules/form.vue new file mode 100644 index 0000000..dc1c687 --- /dev/null +++ b/apps/web-ele/src/views/mp/user/modules/form.vue @@ -0,0 +1,80 @@ + + + diff --git a/apps/web-ele/src/views/pay/app/data.ts b/apps/web-ele/src/views/pay/app/data.ts new file mode 100644 index 0000000..8ee1919 --- /dev/null +++ b/apps/web-ele/src/views/pay/app/data.ts @@ -0,0 +1,664 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { PayAppApi } from '#/api/pay/app'; + +import { h } from 'vue'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { InputUpload } from '#/components/upload'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '应用名', + component: 'Input', + componentProps: { + placeholder: '请输入应用名', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '开启状态', + component: 'Select', + componentProps: { + placeholder: '请选择开启状态', + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onStatusChange?: ( + newStatus: number, + row: PayAppApi.App, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'appKey', + title: '应用标识', + minWidth: 40, + }, + { + field: 'name', + title: '应用名', + minWidth: 40, + }, + { + field: 'status', + title: '状态', + align: 'center', + minWidth: 40, + cellRender: { + attrs: { beforeChange: onStatusChange }, + name: 'CellSwitch', + props: { + activeValue: CommonStatusEnum.ENABLE, + inactiveValue: CommonStatusEnum.DISABLE, + }, + }, + }, + { + title: '支付宝配置', + children: [ + { + title: 'APP', + slots: { + default: 'alipayAppConfig', + }, + }, + { + title: 'PC 网站', + slots: { + default: 'alipayPCConfig', + }, + }, + { + title: 'WAP 网站', + slots: { + default: 'alipayWAPConfig', + }, + minWidth: 10, + }, + { + title: '扫码', + slots: { + default: 'alipayQrConfig', + }, + }, + { + title: '条码', + slots: { + default: 'alipayBarConfig', + }, + }, + ], + }, + { + title: '微信配置', + children: [ + { + title: '小程序', + slots: { + default: 'wxLiteConfig', + }, + }, + { + title: 'JSAPI', + slots: { + default: 'wxPubConfig', + }, + }, + { + title: 'APP', + slots: { + default: 'wxAppConfig', + }, + }, + { + title: 'Native', + slots: { + default: 'wxNativeConfig', + }, + }, + { + title: 'WAP 网站', + slots: { + default: 'wxWapConfig', + }, + minWidth: 10, + }, + { + title: '条码', + slots: { + default: 'wxBarConfig', + }, + }, + ], + }, + { + title: '钱包支付配置', + field: 'walletConfig', + slots: { + default: 'walletConfig', + }, + }, + { + title: '模拟支付配置', + field: 'mockConfig', + slots: { + default: 'mockConfig', + }, + }, + { + title: '操作', + width: 140, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 应用新增/修改的表单 */ +export function useAppFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '应用名', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入应用名', + }, + }, + { + fieldName: 'appKey', + label: '应用标识', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入应用标识', + }, + }, + { + fieldName: 'status', + label: '开启状态', + component: 'RadioGroup', + rules: z.number().default(CommonStatusEnum.ENABLE), + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + { + fieldName: 'orderNotifyUrl', + label: '支付结果的回调地址', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入支付结果的回调地址', + }, + }, + { + fieldName: 'refundNotifyUrl', + label: '退款结果的回调地址', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入退款结果的回调地址', + }, + }, + { + fieldName: 'transferNotifyUrl', + label: '转账结果的回调地址', + component: 'Input', + componentProps: { + placeholder: '请输入转账结果的回调地址', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + rows: 3, + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 渠道新增/修改的表单 */ +export function useChannelFormSchema(formType: string = ''): VbenFormSchema[] { + const schema: VbenFormSchema[] = [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + label: '应用编号', + fieldName: 'appId', + component: 'Input', + dependencies: { + show: () => false, + triggerFields: [''], + }, + }, + { + label: '渠道编码', + fieldName: 'code', + component: 'Input', + dependencies: { + show: () => false, + triggerFields: [''], + }, + }, + { + label: '渠道费率', + fieldName: 'feeRate', + component: 'InputNumber', + rules: 'required', + componentProps: { + placeholder: '请输入渠道费率', + addonAfter: '%', + controlsPosition: 'right', + class: '!w-full', + }, + defaultValue: 0, + }, + { + label: '渠道状态', + fieldName: 'status', + component: 'RadioGroup', + rules: z.number().default(CommonStatusEnum.ENABLE), + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; + // 添加通用字段 + // 根据类型添加特定字段 + if (formType.includes('alipay_')) { + schema.push( + { + label: '开放平台 APPID', + fieldName: 'config.appId', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入开放平台 APPID', + }, + }, + { + label: '网关地址', + fieldName: 'config.serverUrl', + component: 'RadioGroup', + rules: 'required', + componentProps: { + options: [ + { + value: 'https://openapi.alipay.com/gateway.do', + label: '线上环境', + }, + { + value: 'https://openapi-sandbox.dl.alipaydev.com/gateway.do', + label: '沙箱环境', + }, + ], + }, + }, + { + label: '算法类型', + fieldName: 'config.signType', + component: 'RadioGroup', + rules: 'required', + componentProps: { + options: [ + { + value: 'RSA2', + label: 'RSA2', + }, + ], + }, + defaultValue: 'RSA2', + }, + { + label: '公钥类型', + fieldName: 'config.mode', + component: 'RadioGroup', + rules: 'required', + componentProps: { + options: [ + { + value: 1, + label: '公钥模式', + }, + { + value: 2, + label: '证书模式', + }, + ], + }, + }, + { + label: '应用私钥', + fieldName: 'config.privateKey', + component: 'Textarea', + rules: 'required', + componentProps: { + placeholder: '请输入应用私钥', + rows: 3, + }, + }, + { + label: '支付宝公钥', + fieldName: 'config.alipayPublicKey', + component: 'Textarea', + rules: 'required', + componentProps: { + placeholder: '请输入支付宝公钥', + rows: 3, + }, + dependencies: { + show(values: any) { + return values?.config?.mode === 1; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + { + label: '商户公钥应用证书', + fieldName: 'config.appCertContent', + component: h(InputUpload, { + inputType: 'textarea', + textareaProps: { + rows: 3, + placeholder: '请上传商户公钥应用证书', + }, + fileUploadProps: { + accept: ['crt'], + }, + }), + rules: 'required', + dependencies: { + show(values: any) { + return values?.config?.mode === 2; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + { + label: '支付宝公钥证书', + fieldName: 'config.alipayPublicCertContent', + component: h(InputUpload, { + inputType: 'textarea', + textareaProps: { rows: 3, placeholder: '请上传支付宝公钥证书' }, + fileUploadProps: { + accept: ['crt'], + }, + }), + rules: 'required', + dependencies: { + show(values: any) { + return values?.config?.mode === 2; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + { + label: '根证书', + fieldName: 'config.rootCertContent', + component: h(InputUpload, { + inputType: 'textarea', + textareaProps: { rows: 3, placeholder: '请上传根证书' }, + fileUploadProps: { + accept: ['crt'], + }, + }), + rules: 'required', + dependencies: { + show(values: any) { + return values?.config?.mode === 2; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + { + label: '接口内容加密方式', + fieldName: 'config.encryptType', + component: 'RadioGroup', + rules: 'required', + componentProps: { + options: [ + { + value: 'NONE', + label: '无加密', + }, + { + value: 'AES', + label: 'AES', + }, + ], + }, + defaultValue: 'NONE', + }, + { + label: '接口内容加密密钥', + fieldName: 'config.encryptKey', + component: 'Input', + rules: 'required', + dependencies: { + show(values: any) { + return values?.config?.encryptType === 'AES'; + }, + triggerFields: ['config.encryptType', 'encryptType', 'config'], + }, + }, + ); + } else if (formType.includes('wx_')) { + schema.push( + { + label: '微信 APPID', + fieldName: 'config.appId', + help: '前往微信商户平台[https://pay.weixin.qq.com/index.php/extend/merchant_appid/mapay_platform/account_manage]查看 APPID', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入微信 APPID', + }, + }, + { + label: '商户号', + fieldName: 'config.mchId', + help: '前往微信商户平台[https://pay.weixin.qq.com/index.php/extend/pay_setting]查看商户号', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入商户号', + }, + }, + { + label: 'API 版本', + fieldName: 'config.apiVersion', + component: 'RadioGroup', + rules: 'required', + componentProps: { + options: [ + { + label: 'v2', + value: 'v2', + }, + { + label: 'v3', + value: 'v3', + }, + ], + }, + }, + { + label: '商户密钥', + fieldName: 'config.mchKey', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入商户密钥', + }, + dependencies: { + show(values: any) { + return values?.config?.apiVersion === 'v2'; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + { + label: 'apiclient_cert.p12 证书', + fieldName: 'config.keyContent', + component: h(InputUpload, { + inputType: 'textarea', + textareaProps: { + rows: 3, + placeholder: '请上传 apiclient_cert.p12 证书', + }, + fileUploadProps: { + accept: ['p12'], + }, + }), + rules: 'required', + dependencies: { + show(values: any) { + return values?.config?.apiVersion === 'v2'; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + { + label: 'API V3 密钥', + fieldName: 'config.apiV3Key', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入 API V3 密钥', + }, + dependencies: { + show(values: any) { + return values?.config?.apiVersion === 'v3'; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + { + label: 'apiclient_key.pem 证书', + fieldName: 'config.privateKeyContent', + component: h(InputUpload, { + inputType: 'textarea', + textareaProps: { + rows: 3, + placeholder: '请上传 apiclient_key.pem 证书', + }, + fileUploadProps: { + accept: ['pem'], + }, + }), + rules: 'required', + dependencies: { + show(values: any) { + return values?.config?.apiVersion === 'v3'; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + { + label: '证书序列号', + fieldName: 'config.certSerialNo', + component: 'Input', + help: '前往微信商户平台[https://pay.weixin.qq.com/index.php/core/cert/api_cert#/api-cert-manage]查看证书序列号', + rules: 'required', + componentProps: { + placeholder: '请输入证书序列号', + }, + dependencies: { + show(values: any) { + return values?.config?.apiVersion === 'v3'; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + { + label: 'public_key.pem 证书', + fieldName: 'config.publicKeyContent', + component: h(InputUpload, { + inputType: 'textarea', + textareaProps: { + rows: 3, + placeholder: '请上传 public_key.pem 证书', + }, + fileUploadProps: { + accept: ['pem'], + }, + }), + dependencies: { + show(values: any) { + return values?.config?.apiVersion === 'v3'; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + { + label: '公钥 ID', + fieldName: 'config.publicKeyId', + component: 'Input', + help: '微信支付公钥产品简介及使用说明[https://pay.weixin.qq.com/doc/v3/merchant/4012153196]', + rules: 'required', + componentProps: { + placeholder: '请输入公钥 ID', + }, + dependencies: { + show(values: any) { + return values?.config?.apiVersion === 'v3'; + }, + triggerFields: ['config.mode', 'mode', 'config'], + }, + }, + ); + } + // 添加备注字段(所有类型都有) + schema.push({ + label: '备注', + fieldName: 'remark', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + }, + }); + return schema; +} diff --git a/apps/web-ele/src/views/pay/app/index.vue b/apps/web-ele/src/views/pay/app/index.vue new file mode 100644 index 0000000..57920fe --- /dev/null +++ b/apps/web-ele/src/views/pay/app/index.vue @@ -0,0 +1,262 @@ + + + diff --git a/apps/web-ele/src/views/pay/app/modules/app-form.vue b/apps/web-ele/src/views/pay/app/modules/app-form.vue new file mode 100644 index 0000000..0f41f2c --- /dev/null +++ b/apps/web-ele/src/views/pay/app/modules/app-form.vue @@ -0,0 +1,83 @@ + + diff --git a/apps/web-ele/src/views/pay/app/modules/channel-form.vue b/apps/web-ele/src/views/pay/app/modules/channel-form.vue new file mode 100644 index 0000000..834e509 --- /dev/null +++ b/apps/web-ele/src/views/pay/app/modules/channel-form.vue @@ -0,0 +1,139 @@ + + + diff --git a/apps/web-ele/src/views/pay/cashier/data.ts b/apps/web-ele/src/views/pay/cashier/data.ts new file mode 100644 index 0000000..eb0cec9 --- /dev/null +++ b/apps/web-ele/src/views/pay/cashier/data.ts @@ -0,0 +1,83 @@ +import { + SvgAlipayAppIcon, + SvgAlipayBarIcon, + SvgAlipayPcIcon, + SvgAlipayQrIcon, + SvgAlipayWapIcon, + SvgMockIcon, + SvgWalletIcon, + SvgWxAppIcon, + SvgWxBarIcon, + SvgWxLiteIcon, + SvgWxNativeIcon, + SvgWxPubIcon, +} from '@vben/icons'; + +export const channelsAlipay = [ + { + name: '支付宝 PC 网站支付', + icon: SvgAlipayPcIcon, + code: 'alipay_pc', + }, + { + name: '支付宝 Wap 网站支付', + icon: SvgAlipayWapIcon, + code: 'alipay_wap', + }, + { + name: '支付宝 App 网站支付', + icon: SvgAlipayAppIcon, + code: 'alipay_app', + }, + { + name: '支付宝扫码支付', + icon: SvgAlipayQrIcon, + code: 'alipay_qr', + }, + { + name: '支付宝条码支付', + icon: SvgAlipayBarIcon, + code: 'alipay_bar', + }, +]; + +export const channelsWechat = [ + { + name: '微信公众号支付', + icon: SvgWxPubIcon, + code: 'wx_pub', + }, + { + name: '微信小程序支付', + icon: SvgWxLiteIcon, + code: 'wx_lite', + }, + { + name: '微信 App 支付', + icon: SvgWxAppIcon, + code: 'wx_app', + }, + { + name: '微信扫码支付', + icon: SvgWxNativeIcon, + code: 'wx_native', + }, + { + name: '微信条码支付', + icon: SvgWxBarIcon, + code: 'wx_bar', + }, +]; + +export const channelsMock = [ + { + name: '钱包支付', + icon: SvgWalletIcon, + code: 'wallet', + }, + { + name: '模拟支付', + icon: SvgMockIcon, + code: 'mock', + }, +]; diff --git a/apps/web-ele/src/views/pay/cashier/index.vue b/apps/web-ele/src/views/pay/cashier/index.vue new file mode 100644 index 0000000..ed5d450 --- /dev/null +++ b/apps/web-ele/src/views/pay/cashier/index.vue @@ -0,0 +1,397 @@ + + diff --git a/apps/web-ele/src/views/pay/demo/order/data.ts b/apps/web-ele/src/views/pay/demo/order/data.ts new file mode 100644 index 0000000..b88fba3 --- /dev/null +++ b/apps/web-ele/src/views/pay/demo/order/data.ts @@ -0,0 +1,115 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { formatDateTime } from '@vben/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'spuId', + label: '商品', + component: 'Select', + componentProps: { + options: [ + { label: '华为手机 --- 1.00元', value: 1 }, + { label: '小米电视 --- 10.00元', value: 2 }, + { label: '苹果手表 --- 100.00元', value: 3 }, + { label: '华硕笔记本 --- 1000.00元', value: 4 }, + { label: '蔚来汽车 --- 200000.00元', value: 5 }, + ], + placeholder: '请选择下单商品', + clearable: true, + }, + rules: 'required', + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '订单编号', + minWidth: 100, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 100, + }, + { + field: 'spuName', + title: '商品名字', + minWidth: 150, + }, + { + field: 'price', + title: '支付价格', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'refundPrice', + title: '退款金额', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'payOrderId', + title: '支付单号', + minWidth: 120, + }, + { + field: 'payStatus', + title: '是否支付', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'payTime', + title: '支付时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'refundTime', + title: '退款时间', + minWidth: 180, + formatter: ({ cellValue, row }) => { + if (cellValue) { + return formatDateTime(cellValue) as string; + } + if (row.payRefundId) { + return '退款中,等待退款结果'; + } + return ''; + }, + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/pay/demo/order/index.vue b/apps/web-ele/src/views/pay/demo/order/index.vue new file mode 100644 index 0000000..cbfee2b --- /dev/null +++ b/apps/web-ele/src/views/pay/demo/order/index.vue @@ -0,0 +1,148 @@ + + + diff --git a/apps/web-ele/src/views/pay/demo/order/modules/form.vue b/apps/web-ele/src/views/pay/demo/order/modules/form.vue new file mode 100644 index 0000000..36b1b9d --- /dev/null +++ b/apps/web-ele/src/views/pay/demo/order/modules/form.vue @@ -0,0 +1,55 @@ + + + diff --git a/apps/web-ele/src/views/pay/demo/withdraw/data.ts b/apps/web-ele/src/views/pay/demo/withdraw/data.ts new file mode 100644 index 0000000..d2622c0 --- /dev/null +++ b/apps/web-ele/src/views/pay/demo/withdraw/data.ts @@ -0,0 +1,168 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'subject', + label: '提现标题', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入提现标题', + }, + }, + { + fieldName: 'price', + label: '提现金额', + component: 'InputNumber', + rules: 'required', + componentProps: { + min: 1, + precision: 2, + step: 0.01, + placeholder: '请输入提现金额', + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'type', + label: '提现类型', + component: 'Select', + rules: 'required', + componentProps: { + options: [ + { label: '支付宝', value: 1 }, + { label: '微信余额', value: 2 }, + { label: '钱包余额', value: 3 }, + ], + placeholder: '请选择提现类型', + }, + }, + { + fieldName: 'userAccount', + label: '收款人账号', + component: 'Input', + rules: 'required', + dependencies: { + triggerFields: ['type'], + componentProps: (values) => { + const type = values.type; + let placeholder = '请输入收款人账号'; + switch (type) { + case 1: { + placeholder = '请输入支付宝账号'; + break; + } + case 2: { + placeholder = '请输入微信 openid'; + break; + } + case 3: { + placeholder = '请输入钱包编号'; + break; + } + } + return { + placeholder, + }; + }, + }, + }, + { + fieldName: 'userName', + label: '收款人姓名', + component: 'Input', + componentProps: { + placeholder: '请输入收款人姓名', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '提现单编号', + minWidth: 100, + }, + { + field: 'subject', + title: '提现标题', + minWidth: 150, + }, + { + field: 'type', + title: '提现类型', + minWidth: 100, + slots: { default: 'type' }, + }, + { + field: 'price', + title: '提现金额', + minWidth: 100, + formatter: 'formatAmount2', + }, + { + field: 'userName', + title: '收款人姓名', + minWidth: 120, + }, + { + field: 'userAccount', + title: '收款人账号', + minWidth: 150, + }, + { + field: 'status', + title: '提现状态', + minWidth: 100, + slots: { default: 'status' }, + }, + { + field: 'payTransferId', + title: '转账单号', + minWidth: 120, + }, + { + field: 'transferChannelCode', + title: '转账渠道', + minWidth: 130, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_CHANNEL_CODE }, + }, + }, + { + field: 'transferTime', + title: '转账时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'transferErrorMsg', + title: '转账失败原因', + minWidth: 150, + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/pay/demo/withdraw/index.vue b/apps/web-ele/src/views/pay/demo/withdraw/index.vue new file mode 100644 index 0000000..6357705 --- /dev/null +++ b/apps/web-ele/src/views/pay/demo/withdraw/index.vue @@ -0,0 +1,145 @@ + + + diff --git a/apps/web-ele/src/views/pay/demo/withdraw/modules/form.vue b/apps/web-ele/src/views/pay/demo/withdraw/modules/form.vue new file mode 100644 index 0000000..2370988 --- /dev/null +++ b/apps/web-ele/src/views/pay/demo/withdraw/modules/form.vue @@ -0,0 +1,55 @@ + + + diff --git a/apps/web-ele/src/views/pay/notify/data.ts b/apps/web-ele/src/views/pay/notify/data.ts new file mode 100644 index 0000000..5917b41 --- /dev/null +++ b/apps/web-ele/src/views/pay/notify/data.ts @@ -0,0 +1,271 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDateTime } from '@vben/utils'; + +import { getAppList } from '#/api/pay/app'; +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'appId', + label: '应用编号', + component: 'ApiSelect', + componentProps: { + api: getAppList, + labelField: 'name', + valueField: 'id', + autoSelect: 'first', + placeholder: '请选择应用编号', + }, + }, + { + fieldName: 'type', + label: '通知类型', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.PAY_NOTIFY_TYPE, 'number'), + placeholder: '请选择通知类型', + }, + }, + { + fieldName: 'dataId', + label: '关联编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入关联编号', + }, + }, + { + fieldName: 'status', + label: '通知状态', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.PAY_NOTIFY_STATUS, 'number'), + placeholder: '请选择通知状态', + }, + }, + { + fieldName: 'merchantOrderId', + label: '商户订单编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入商户订单编号', + }, + }, + { + fieldName: 'merchantRefundId', + label: '商户退款编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入商户退款编号', + }, + }, + { + fieldName: 'merchantTransferId', + label: '商户转账编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入商户转账编号', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '任务编号', + minWidth: 100, + }, + { + field: 'appName', + title: '应用名称', + minWidth: 150, + }, + { + field: 'merchantInfo', + title: '商户单信息', + minWidth: 240, + slots: { + default: 'merchantInfo', + }, + }, + { + field: 'type', + title: '通知类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_NOTIFY_TYPE }, + }, + }, + { + field: 'dataId', + title: '关联编号', + minWidth: 120, + }, + { + field: 'status', + title: '通知状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_NOTIFY_STATUS }, + }, + }, + { + field: 'lastExecuteTime', + title: '最后通知时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'nextNotifyTime', + title: '下次通知时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'notifyTimes', + title: '通知次数', + minWidth: 120, + formatter: ({ row }) => `${row.notifyTimes} / ${row.maxNotifyTimes}`, + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'appId', + label: '应用编号', + }, + { + field: 'appName', + label: '应用名称', + }, + { + field: 'type', + label: '通知类型', + render: (val) => + h(DictTag, { + type: DICT_TYPE.PAY_NOTIFY_TYPE, + value: val, + }), + }, + { + field: 'dataId', + label: '关联编号', + }, + { + field: 'status', + label: '通知状态', + render: (val) => + h(DictTag, { + type: DICT_TYPE.PAY_NOTIFY_STATUS, + value: val, + }), + }, + { + field: 'merchantOrderId', + label: '商户订单编号', + }, + { + field: 'lastExecuteTime', + label: '最后通知时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'nextNotifyTime', + label: '下次通知时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'notifyTimes', + label: '通知次数', + }, + { + field: 'maxNotifyTimes', + label: '最大通知次数', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'updateTime', + label: '更新时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} + +/** 详情的日志字段 */ +export function useDetailLogColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '日志编号', + minWidth: 120, + }, + { + field: 'status', + title: '通知状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_NOTIFY_STATUS }, + }, + }, + { + field: 'notifyTimes', + title: '通知次数', + minWidth: 120, + }, + { + field: 'createTime', + title: '通知时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'response', + title: '响应结果', + minWidth: 200, + }, + ]; +} diff --git a/apps/web-ele/src/views/pay/notify/index.vue b/apps/web-ele/src/views/pay/notify/index.vue new file mode 100644 index 0000000..9821fb9 --- /dev/null +++ b/apps/web-ele/src/views/pay/notify/index.vue @@ -0,0 +1,104 @@ + + diff --git a/apps/web-ele/src/views/pay/notify/modules/detail.vue b/apps/web-ele/src/views/pay/notify/modules/detail.vue new file mode 100644 index 0000000..d5b7bb7 --- /dev/null +++ b/apps/web-ele/src/views/pay/notify/modules/detail.vue @@ -0,0 +1,79 @@ + + + diff --git a/apps/web-ele/src/views/pay/order/data.ts b/apps/web-ele/src/views/pay/order/data.ts new file mode 100644 index 0000000..ff55e09 --- /dev/null +++ b/apps/web-ele/src/views/pay/order/data.ts @@ -0,0 +1,271 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpPriceInputFormatter, formatDateTime } from '@vben/utils'; + +import { ElTag } from 'element-plus'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'appId', + label: '应用编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入应用编号', + }, + }, + { + fieldName: 'channelCode', + label: '支付渠道', + component: 'Select', + componentProps: { + clearable: true, + placeholder: '请选择支付渠道', + options: getDictOptions(DICT_TYPE.PAY_CHANNEL_CODE, 'string'), + }, + }, + { + fieldName: 'merchantOrderId', + label: '商户单号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入商户单号', + }, + }, + { + fieldName: 'no', + label: '支付单号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入支付单号', + }, + }, + { + fieldName: 'channelOrderNo', + label: '渠道单号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入渠道单号', + }, + }, + { + fieldName: 'status', + label: '支付状态', + component: 'Select', + componentProps: { + clearable: true, + placeholder: '请选择支付状态', + options: getDictOptions(DICT_TYPE.PAY_ORDER_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'price', + title: '支付金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'refundPrice', + title: '退款金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'channelFeePrice', + title: '手续金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'no', + title: '订单号', + minWidth: 240, + slots: { + default: 'no', + }, + }, + { + field: 'status', + title: '支付状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_ORDER_STATUS }, + }, + }, + { + field: 'channelCode', + title: '支付渠道', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_CHANNEL_CODE }, + }, + }, + { + field: 'successTime', + title: '支付时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'appName', + title: '支付应用', + minWidth: 150, + }, + { + field: 'subject', + title: '商品标题', + minWidth: 200, + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'merchantOrderId', + label: '商户单号', + }, + { + field: 'no', + label: '支付单号', + }, + { + field: 'appId', + label: '应用编号', + }, + { + field: 'appName', + label: '应用名称', + }, + { + field: 'status', + label: '支付状态', + render: (val) => + h(DictTag, { + type: DICT_TYPE.PAY_ORDER_STATUS, + value: val, + }), + }, + { + field: 'price', + label: '支付金额', + render: (val) => `¥${erpPriceInputFormatter(val)}`, + }, + { + field: 'channelFeePrice', + label: '手续费', + render: (val) => `¥${erpPriceInputFormatter(val)}`, + }, + { + field: 'channelFeeRate', + label: '手续费比例', + render: (val) => `${erpPriceInputFormatter(val)}%`, + }, + { + field: 'successTime', + label: '支付时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'expireTime', + label: '失效时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'updateTime', + label: '更新时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'subject', + label: '商品标题', + }, + { + field: 'body', + label: '商品描述', + }, + { + field: 'channelCode', + label: '支付渠道', + render: (val) => + h(DictTag, { + type: DICT_TYPE.PAY_CHANNEL_CODE, + value: val, + }), + }, + { + field: 'userIp', + label: '支付 IP', + }, + { + field: 'channelOrderNo', + label: '渠道单号', + render: (val) => (val ? h(ElTag, { color: 'green' }, () => val) : ''), + }, + { + field: 'channelUserId', + label: '渠道用户', + }, + { + field: 'refundPrice', + label: '退款金额', + render: (val) => `¥${erpPriceInputFormatter(val)}`, + }, + { + field: 'notifyUrl', + label: '通知 URL', + }, + { + field: 'channelNotifyData', + label: '支付通道异步回调内容', + }, + ]; +} diff --git a/apps/web-ele/src/views/pay/order/index.vue b/apps/web-ele/src/views/pay/order/index.vue new file mode 100644 index 0000000..adf9818 --- /dev/null +++ b/apps/web-ele/src/views/pay/order/index.vue @@ -0,0 +1,134 @@ + + + diff --git a/apps/web-ele/src/views/pay/order/modules/detail.vue b/apps/web-ele/src/views/pay/order/modules/detail.vue new file mode 100644 index 0000000..99c261d --- /dev/null +++ b/apps/web-ele/src/views/pay/order/modules/detail.vue @@ -0,0 +1,50 @@ + + diff --git a/apps/web-ele/src/views/pay/refund/data.ts b/apps/web-ele/src/views/pay/refund/data.ts new file mode 100644 index 0000000..8e1afd6 --- /dev/null +++ b/apps/web-ele/src/views/pay/refund/data.ts @@ -0,0 +1,280 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpPriceInputFormatter, formatDateTime } from '@vben/utils'; + +import { ElTag } from 'element-plus'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'appId', + label: '应用编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入应用编号', + }, + }, + { + fieldName: 'channelCode', + label: '退款渠道', + component: 'Select', + componentProps: { + clearable: true, + placeholder: '请选择退款渠道', + options: getDictOptions(DICT_TYPE.PAY_CHANNEL_CODE, 'string'), + }, + }, + { + fieldName: 'merchantOrderId', + label: '商户单号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入商户单号', + }, + }, + { + fieldName: 'merchantRefundId', + label: '退款单号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入退款单号', + }, + }, + { + fieldName: 'channelOrderNo', + label: '渠道单号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入渠道单号', + }, + }, + { + fieldName: 'channelRefundNo', + label: '渠道退款单号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入渠道退款单号', + }, + }, + { + fieldName: 'status', + label: '退款状态', + component: 'Select', + componentProps: { + clearable: true, + placeholder: '请选择退款状态', + options: getDictOptions(DICT_TYPE.PAY_REFUND_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'payPrice', + title: '支付金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'refundPrice', + title: '退款金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'merchantRefundId', + title: '退款单号', + minWidth: 240, + slots: { + default: 'no', + }, + }, + { + field: 'status', + title: '退款状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_REFUND_STATUS }, + }, + }, + { + field: 'channelCode', + title: '退款渠道', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_CHANNEL_CODE }, + }, + }, + { + field: 'successTime', + title: '退款时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'reason', + title: '退款原因', + minWidth: 200, + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + // 基本信息部分 + { + field: 'merchantRefundId', + label: '商户退款单号', + render: (val) => h(ElTag, {}, () => val || '-'), + }, + { + field: 'channelRefundNo', + label: '渠道退款单号', + render: (val) => h(ElTag, { type: 'success' }, () => val || '-'), + }, + { + field: 'merchantOrderId', + label: '商户支付单号', + render: (val) => h(ElTag, {}, () => val || '-'), + }, + { + field: 'channelOrderNo', + label: '渠道支付单号', + render: (val) => h(ElTag, { type: 'success' }, () => val || '-'), + }, + { + field: 'appId', + label: '应用编号', + }, + { + field: 'appName', + label: '应用名称', + }, + { + field: 'payPrice', + label: '支付金额', + render: (val) => + h( + ElTag, + { type: 'success' }, + () => `¥${erpPriceInputFormatter(val || 0)}`, + ), + }, + { + field: 'refundPrice', + label: '退款金额', + render: (val) => + h( + ElTag, + { type: 'danger' }, + () => `¥${erpPriceInputFormatter(val || 0)}`, + ), + }, + { + field: 'status', + label: '退款状态', + render: (val) => + h(DictTag, { + type: DICT_TYPE.PAY_REFUND_STATUS, + value: val, + }), + }, + { + field: 'successTime', + label: '退款时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'updateTime', + label: '更新时间', + render: (val) => formatDateTime(val) as string, + }, + // 渠道信息部分 + { + field: 'channelCode', + label: '退款渠道', + render: (val) => + h(DictTag, { + type: DICT_TYPE.PAY_CHANNEL_CODE, + value: val, + }), + }, + { + field: 'reason', + label: '退款原因', + }, + { + field: 'userIp', + label: '退款 IP', + }, + { + field: 'notifyUrl', + label: '通知 URL', + }, + // 错误信息部分 + { + field: 'channelErrorCode', + label: '渠道错误码', + }, + { + field: 'channelErrorMsg', + label: '渠道错误码描述', + }, + { + field: 'channelNotifyData', + label: '支付通道异步回调内容', + }, + ]; +} diff --git a/apps/web-ele/src/views/pay/refund/index.vue b/apps/web-ele/src/views/pay/refund/index.vue new file mode 100644 index 0000000..c363ec2 --- /dev/null +++ b/apps/web-ele/src/views/pay/refund/index.vue @@ -0,0 +1,126 @@ + + diff --git a/apps/web-ele/src/views/pay/refund/modules/detail.vue b/apps/web-ele/src/views/pay/refund/modules/detail.vue new file mode 100644 index 0000000..1b93a77 --- /dev/null +++ b/apps/web-ele/src/views/pay/refund/modules/detail.vue @@ -0,0 +1,51 @@ + + + diff --git a/apps/web-ele/src/views/pay/transfer/data.ts b/apps/web-ele/src/views/pay/transfer/data.ts new file mode 100644 index 0000000..0e3b1a0 --- /dev/null +++ b/apps/web-ele/src/views/pay/transfer/data.ts @@ -0,0 +1,268 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { erpPriceInputFormatter, formatDateTime } from '@vben/utils'; + +import { ElTag } from 'element-plus'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '转账单号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入转账单号', + }, + }, + { + fieldName: 'channelCode', + label: '转账渠道', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.PAY_CHANNEL_CODE), + clearable: true, + placeholder: '请选择支付渠道', + }, + }, + { + fieldName: 'merchantTransferId', + label: '商户单号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入商户单号', + }, + }, + { + fieldName: 'type', + label: '类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.PAY_TRANSFER_TYPE), + clearable: true, + placeholder: '请选择类型', + }, + }, + { + fieldName: 'status', + label: '转账状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.PAY_TRANSFER_STATUS), + clearable: true, + placeholder: '请选择转账状态', + }, + }, + { + fieldName: 'userName', + label: '收款人姓名', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入收款人姓名', + }, + }, + { + fieldName: 'userAccount', + label: '收款人账号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入收款人账号', + }, + }, + { + fieldName: 'channelTransferNo', + label: '渠道单号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入渠道单号', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'price', + title: '转账金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'merchantTransferId', + title: '转账单号', + minWidth: 350, + slots: { + default: 'no', + }, + }, + { + field: 'status', + title: '转账状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_TRANSFER_STATUS }, + }, + }, + { + field: 'channelCode', + title: '转账渠道', + minWidth: 140, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PAY_CHANNEL_CODE }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'successTime', + title: '转账时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'subject', + title: '转账标题', + minWidth: 150, + }, + { + field: 'appName', + title: '支付应用', + minWidth: 150, + }, + { + field: 'userName', + title: '收款人姓名', + minWidth: 150, + }, + { + field: 'userAccount', + title: '收款账号', + minWidth: 200, + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'merchantTransferId', + label: '商户单号', + render: (val) => h(ElTag, {}, () => val), + }, + { + field: 'no', + label: '转账单号', + render: (val) => h(ElTag, { color: 'orange' }, () => val), + }, + { + field: 'appId', + label: '应用编号', + }, + { + field: 'status', + label: '转账状态', + render: (val) => + h(DictTag, { + type: DICT_TYPE.PAY_TRANSFER_STATUS, + value: val, + }), + }, + { + field: 'price', + label: '转账金额', + render: (val) => + h( + ElTag, + { color: 'success' }, + () => `¥${erpPriceInputFormatter(val || 0)}`, + ), + }, + { + field: 'successTime', + label: '转账时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'userName', + label: '收款人姓名', + }, + { + field: 'userAccount', + label: '收款人账号', + }, + { + field: 'channelCode', + label: '支付渠道', + render: (val) => + h(DictTag, { + type: DICT_TYPE.PAY_CHANNEL_CODE, + value: val, + }), + }, + { + field: 'userIp', + label: '支付 IP', + }, + { + field: 'channelTransferNo', + label: '渠道单号', + render: (val) => (val ? h(ElTag, { color: 'success' }, () => val) : ''), + }, + { + field: 'notifyUrl', + label: '通知 URL', + }, + { + field: 'channelNotifyData', + label: '转账渠道通知内容', + }, + ]; +} diff --git a/apps/web-ele/src/views/pay/transfer/index.vue b/apps/web-ele/src/views/pay/transfer/index.vue new file mode 100644 index 0000000..e93f0c2 --- /dev/null +++ b/apps/web-ele/src/views/pay/transfer/index.vue @@ -0,0 +1,124 @@ + + + diff --git a/apps/web-ele/src/views/pay/transfer/modules/detail.vue b/apps/web-ele/src/views/pay/transfer/modules/detail.vue new file mode 100644 index 0000000..86dd915 --- /dev/null +++ b/apps/web-ele/src/views/pay/transfer/modules/detail.vue @@ -0,0 +1,51 @@ + + + diff --git a/apps/web-ele/src/views/pay/wallet/balance/data.ts b/apps/web-ele/src/views/pay/wallet/balance/data.ts new file mode 100644 index 0000000..2b30e86 --- /dev/null +++ b/apps/web-ele/src/views/pay/wallet/balance/data.ts @@ -0,0 +1,137 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + placeholder: '请输入用户编号', + clearable: true, + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + placeholder: '请选择用户类型', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + title: '编号', + field: 'id', + minWidth: 100, + }, + { + title: '用户编号', + field: 'userId', + minWidth: 120, + }, + { + title: '用户类型', + field: 'userType', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.USER_TYPE }, + }, + }, + { + title: '余额', + field: 'balance', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + title: '累计支出', + field: 'totalExpense', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + title: '累计充值', + field: 'totalRecharge', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + title: '冻结金额', + field: 'freezePrice', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + title: '创建时间', + field: 'createTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + field: 'actions', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 钱包交易记录列表字段 */ +export function useTransactionGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'title', + title: '关联业务标题', + minWidth: 200, + }, + { + field: 'price', + title: '交易金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'balance', + title: '钱包余额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'createTime', + title: '交易时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-ele/src/views/pay/wallet/balance/index.vue b/apps/web-ele/src/views/pay/wallet/balance/index.vue new file mode 100644 index 0000000..7235632 --- /dev/null +++ b/apps/web-ele/src/views/pay/wallet/balance/index.vue @@ -0,0 +1,83 @@ + + + diff --git a/apps/web-ele/src/views/pay/wallet/balance/modules/detail.vue b/apps/web-ele/src/views/pay/wallet/balance/modules/detail.vue new file mode 100644 index 0000000..96749fd --- /dev/null +++ b/apps/web-ele/src/views/pay/wallet/balance/modules/detail.vue @@ -0,0 +1,65 @@ + + diff --git a/apps/web-ele/src/views/pay/wallet/rechargePackage/data.ts b/apps/web-ele/src/views/pay/wallet/rechargePackage/data.ts new file mode 100644 index 0000000..41caff6 --- /dev/null +++ b/apps/web-ele/src/views/pay/wallet/rechargePackage/data.ts @@ -0,0 +1,151 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '套餐名称', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入套餐名称', + }, + }, + { + fieldName: 'payPrice', + label: '支付金额(元)', + component: 'InputNumber', + rules: z.number().min(0, '支付金额不能小于0'), + componentProps: { + min: 0, + precision: 2, + step: 0.01, + placeholder: '请输入支付金额', + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'bonusPrice', + label: '赠送金额(元)', + component: 'InputNumber', + rules: z.number().min(0, '赠送金额不能小于0'), + componentProps: { + min: 0, + precision: 2, + step: 0.01, + placeholder: '请输入赠送金额', + controlsPosition: 'right', + class: '!w-full', + }, + }, + { + fieldName: 'status', + label: '开启状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '套餐名称', + component: 'Input', + componentProps: { + placeholder: '请输入套餐名称', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '套餐编号', + minWidth: 100, + }, + { + field: 'name', + title: '套餐名称', + minWidth: 150, + }, + { + field: 'payPrice', + title: '支付金额', + minWidth: 120, + formatter: 'formatFenToYuanAmount', + }, + { + field: 'bonusPrice', + title: '赠送金额', + minWidth: 120, + formatter: 'formatFenToYuanAmount', + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 160, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/pay/wallet/rechargePackage/index.vue b/apps/web-ele/src/views/pay/wallet/rechargePackage/index.vue new file mode 100644 index 0000000..3d89c7b --- /dev/null +++ b/apps/web-ele/src/views/pay/wallet/rechargePackage/index.vue @@ -0,0 +1,130 @@ + + + diff --git a/apps/web-ele/src/views/pay/wallet/rechargePackage/modules/form.vue b/apps/web-ele/src/views/pay/wallet/rechargePackage/modules/form.vue new file mode 100644 index 0000000..2e1243c --- /dev/null +++ b/apps/web-ele/src/views/pay/wallet/rechargePackage/modules/form.vue @@ -0,0 +1,101 @@ + + + diff --git a/apps/web-ele/src/views/system/area/data.ts b/apps/web-ele/src/views/system/area/data.ts new file mode 100644 index 0000000..e6cc06c --- /dev/null +++ b/apps/web-ele/src/views/system/area/data.ts @@ -0,0 +1,48 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemAreaApi } from '#/api/system/area'; + +import { z } from '#/adapter/form'; + +/** 查询 IP 的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'ip', + label: 'IP 地址', + component: 'Input', + componentProps: { + placeholder: '请输入 IP 地址', + }, + rules: z.string().ip({ message: '请输入正确的 IP 地址' }), + }, + { + fieldName: 'result', + label: '地址', + component: 'Input', + componentProps: { + placeholder: '展示查询 IP 结果', + readonly: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '地区编码', + minWidth: 120, + align: 'left', + fixed: 'left', + treeNode: true, + }, + { + field: 'name', + title: '地区名称', + minWidth: 200, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/area/index.vue b/apps/web-ele/src/views/system/area/index.vue new file mode 100644 index 0000000..a071419 --- /dev/null +++ b/apps/web-ele/src/views/system/area/index.vue @@ -0,0 +1,79 @@ + + + diff --git a/apps/web-ele/src/views/system/area/modules/form.vue b/apps/web-ele/src/views/system/area/modules/form.vue new file mode 100644 index 0000000..5bce43c --- /dev/null +++ b/apps/web-ele/src/views/system/area/modules/form.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/system/dept/components/index.ts b/apps/web-ele/src/views/system/dept/components/index.ts new file mode 100644 index 0000000..04d2b61 --- /dev/null +++ b/apps/web-ele/src/views/system/dept/components/index.ts @@ -0,0 +1 @@ +export { default as DeptSelectModal } from './select-modal.vue'; diff --git a/apps/web-ele/src/views/system/dept/components/select-modal.vue b/apps/web-ele/src/views/system/dept/components/select-modal.vue new file mode 100644 index 0000000..81e7378 --- /dev/null +++ b/apps/web-ele/src/views/system/dept/components/select-modal.vue @@ -0,0 +1,141 @@ + + diff --git a/apps/web-ele/src/views/system/dept/data.ts b/apps/web-ele/src/views/system/dept/data.ts new file mode 100644 index 0000000..4f03592 --- /dev/null +++ b/apps/web-ele/src/views/system/dept/data.ts @@ -0,0 +1,163 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemDeptApi } from '#/api/system/dept'; +import type { SystemUserApi } from '#/api/system/user'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { handleTree } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getDeptList } from '#/api/system/dept'; +import { getSimpleUserList } from '#/api/system/user'; + +/** 关联数据 */ +let userList: SystemUserApi.User[] = []; +getSimpleUserList().then((data) => (userList = data)); + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'parentId', + label: '上级部门', + component: 'ApiTreeSelect', + componentProps: { + clearable: true, + api: async () => { + const data = await getDeptList(); + data.unshift({ + id: 0, + name: '顶级部门', + }); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择上级部门', + defaultExpandAll: true, + checkStrictly: true, + }, + rules: 'selectRequired', + }, + { + fieldName: 'name', + label: '部门名称', + component: 'Input', + componentProps: { + placeholder: '请输入部门名称', + }, + rules: 'required', + }, + { + fieldName: 'sort', + label: '显示顺序', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入显示顺序', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'leaderUserId', + label: '负责人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择负责人', + clearable: true, + }, + rules: z.number().optional(), + }, + { + fieldName: 'phone', + label: '联系电话', + component: 'Input', + componentProps: { + maxLength: 11, + placeholder: '请输入联系电话', + }, + rules: 'mobileRequired', + }, + { + fieldName: 'email', + label: '邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入邮箱', + }, + rules: z.string().email('邮箱格式不正确').or(z.literal('')).optional(), + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'name', + title: '部门名称', + minWidth: 150, + align: 'left', + fixed: 'left', + treeNode: true, + }, + { + field: 'leaderUserId', + title: '负责人', + minWidth: 150, + formatter: ({ cellValue }) => + userList.find((user) => user.id === cellValue)?.nickname || '-', + }, + { + field: 'sort', + title: '显示顺序', + minWidth: 100, + }, + { + field: 'status', + title: '部门状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/dept/index.vue b/apps/web-ele/src/views/system/dept/index.vue new file mode 100644 index 0000000..0d3e39c --- /dev/null +++ b/apps/web-ele/src/views/system/dept/index.vue @@ -0,0 +1,193 @@ + + + diff --git a/apps/web-ele/src/views/system/dept/modules/form.vue b/apps/web-ele/src/views/system/dept/modules/form.vue new file mode 100644 index 0000000..b013618 --- /dev/null +++ b/apps/web-ele/src/views/system/dept/modules/form.vue @@ -0,0 +1,84 @@ + + + diff --git a/apps/web-ele/src/views/system/dict/data.ts b/apps/web-ele/src/views/system/dict/data.ts new file mode 100644 index 0000000..a8fe7c6 --- /dev/null +++ b/apps/web-ele/src/views/system/dict/data.ts @@ -0,0 +1,347 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getSimpleDictTypeList } from '#/api/system/dict/type'; + +// ============================== 字典类型 ============================== + +/** 类型新增/修改的表单 */ +export function useTypeFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '字典名称', + component: 'Input', + componentProps: { + placeholder: '请输入字典名称', + }, + rules: 'required', + }, + { + fieldName: 'type', + label: '字典类型', + component: 'Input', + componentProps: (values) => { + return { + placeholder: '请输入字典类型', + disabled: !!values.id, + }; + }, + rules: 'required', + dependencies: { + triggerFields: [''], + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 类型列表的搜索表单 */ +export function useTypeGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '字典名称', + component: 'Input', + componentProps: { + placeholder: '请输入字典名称', + clearable: true, + }, + }, + { + fieldName: 'type', + label: '字典类型', + component: 'Input', + componentProps: { + placeholder: '请输入字典类型', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + clearable: true, + }, + }, + ]; +} + +/** 类型列表的字段 */ +export function useTypeGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '字典编号', + minWidth: 100, + }, + { + field: 'name', + title: '字典名称', + minWidth: 200, + }, + { + field: 'type', + title: '字典类型', + minWidth: 220, + }, + { + field: 'status', + title: '状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'remark', + title: '备注', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + minWidth: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ============================== 字典数据 ============================== + +// TODO @芋艿:后续针对 antd,增加 +/** 颜色选项 */ +const colorOptions = [ + { value: '', label: '无' }, + { value: 'processing', label: '主要' }, + { value: 'success', label: '成功' }, + { value: 'default', label: '默认' }, + { value: 'warning', label: '警告' }, + { value: 'error', label: '危险' }, + { value: 'pink', label: 'pink' }, + { value: 'red', label: 'red' }, + { value: 'orange', label: 'orange' }, + { value: 'green', label: 'green' }, + { value: 'cyan', label: 'cyan' }, + { value: 'blue', label: 'blue' }, + { value: 'purple', label: 'purple' }, +]; + +/** 数据新增/修改的表单 */ +export function useDataFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'dictType', + label: '字典类型', + component: 'ApiSelect', + componentProps: (values) => { + return { + api: getSimpleDictTypeList, + placeholder: '请输入字典类型', + labelField: 'name', + valueField: 'type', + disabled: !!values.id, + }; + }, + rules: 'required', + dependencies: { + triggerFields: [''], + }, + }, + { + fieldName: 'label', + label: '数据标签', + component: 'Input', + componentProps: { + placeholder: '请输入数据标签', + }, + rules: 'required', + }, + { + fieldName: 'value', + label: '数据键值', + component: 'Input', + componentProps: { + placeholder: '请输入数据键值', + }, + rules: 'required', + }, + { + fieldName: 'sort', + label: '显示排序', + component: 'InputNumber', + componentProps: { + placeholder: '请输入显示排序', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'colorType', + label: '颜色类型', + component: 'Select', + componentProps: { + options: colorOptions, + placeholder: '请选择颜色类型', + }, + }, + { + fieldName: 'cssClass', + label: 'CSS Class', + component: 'Input', + componentProps: { + placeholder: '请输入 CSS Class', + }, + help: '输入 hex 模式的颜色, 例如 #108ee9', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 字典数据列表搜索表单 */ +export function useDataGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'label', + label: '字典标签', + component: 'Input', + componentProps: { + placeholder: '请输入字典标签', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + clearable: true, + }, + }, + ]; +} + +/** 字典数据表格列 */ +export function useDataGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '字典编码', + minWidth: 100, + }, + { + field: 'label', + title: '字典标签', + minWidth: 180, + }, + { + field: 'value', + title: '字典键值', + minWidth: 100, + }, + { + field: 'sort', + title: '字典排序', + minWidth: 100, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'colorType', + title: '颜色类型', + minWidth: 120, + }, + { + field: 'cssClass', + title: 'CSS Class', + minWidth: 120, + }, + { + title: '创建时间', + field: 'createTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + minWidth: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/dict/index.vue b/apps/web-ele/src/views/system/dict/index.vue new file mode 100644 index 0000000..8d82425 --- /dev/null +++ b/apps/web-ele/src/views/system/dict/index.vue @@ -0,0 +1,33 @@ + + + diff --git a/apps/web-ele/src/views/system/dict/modules/data-form.vue b/apps/web-ele/src/views/system/dict/modules/data-form.vue new file mode 100644 index 0000000..6f32030 --- /dev/null +++ b/apps/web-ele/src/views/system/dict/modules/data-form.vue @@ -0,0 +1,90 @@ + + + diff --git a/apps/web-ele/src/views/system/dict/modules/data-grid.vue b/apps/web-ele/src/views/system/dict/modules/data-grid.vue new file mode 100644 index 0000000..54053c3 --- /dev/null +++ b/apps/web-ele/src/views/system/dict/modules/data-grid.vue @@ -0,0 +1,202 @@ + + + diff --git a/apps/web-ele/src/views/system/dict/modules/type-form.vue b/apps/web-ele/src/views/system/dict/modules/type-form.vue new file mode 100644 index 0000000..5e7cce3 --- /dev/null +++ b/apps/web-ele/src/views/system/dict/modules/type-form.vue @@ -0,0 +1,86 @@ + + + diff --git a/apps/web-ele/src/views/system/dict/modules/type-grid.vue b/apps/web-ele/src/views/system/dict/modules/type-grid.vue new file mode 100644 index 0000000..d2e7ec0 --- /dev/null +++ b/apps/web-ele/src/views/system/dict/modules/type-grid.vue @@ -0,0 +1,189 @@ + + + diff --git a/apps/web-ele/src/views/system/loginlog/data.ts b/apps/web-ele/src/views/system/loginlog/data.ts new file mode 100644 index 0000000..daa67c1 --- /dev/null +++ b/apps/web-ele/src/views/system/loginlog/data.ts @@ -0,0 +1,147 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'username', + label: '用户名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入用户名称', + }, + }, + { + fieldName: 'userIp', + label: '登录地址', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入登录地址', + }, + }, + { + fieldName: 'createTime', + label: '登录时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '日志编号', + minWidth: 100, + }, + { + field: 'logType', + title: '登录类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_LOGIN_TYPE }, + }, + }, + { + field: 'username', + title: '用户名称', + minWidth: 180, + }, + { + field: 'userIp', + title: '登录地址', + minWidth: 180, + }, + { + field: 'userAgent', + title: '浏览器', + minWidth: 200, + }, + { + field: 'result', + title: '登录结果', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_LOGIN_RESULT }, + }, + }, + { + field: 'createTime', + title: '登录日期', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'id', + label: '日志编号', + }, + { + field: 'logType', + label: '登录类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.SYSTEM_LOGIN_TYPE, + value: val, + }); + }, + }, + { + field: 'username', + label: '用户名称', + }, + { + field: 'userIp', + label: '登录地址', + }, + { + field: 'userAgent', + label: '浏览器', + }, + { + field: 'result', + label: '登录结果', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.SYSTEM_LOGIN_RESULT, + value: val, + }); + }, + }, + { + field: 'createTime', + label: '登录日期', + render: (val) => formatDateTime(val) as string, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/loginlog/index.vue b/apps/web-ele/src/views/system/loginlog/index.vue new file mode 100644 index 0000000..f5c5dd9 --- /dev/null +++ b/apps/web-ele/src/views/system/loginlog/index.vue @@ -0,0 +1,104 @@ + + + diff --git a/apps/web-ele/src/views/system/loginlog/modules/detail.vue b/apps/web-ele/src/views/system/loginlog/modules/detail.vue new file mode 100644 index 0000000..d1c9bea --- /dev/null +++ b/apps/web-ele/src/views/system/loginlog/modules/detail.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/system/mail/account/data.ts b/apps/web-ele/src/views/system/mail/account/data.ts new file mode 100644 index 0000000..ce36cb0 --- /dev/null +++ b/apps/web-ele/src/views/system/mail/account/data.ts @@ -0,0 +1,183 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'mail', + label: '邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入邮箱', + }, + rules: 'required', + }, + { + fieldName: 'username', + label: '用户名', + component: 'Input', + componentProps: { + placeholder: '请输入用户名', + }, + rules: 'required', + }, + { + fieldName: 'password', + label: '密码', + component: 'Input', + componentProps: { + showPassword: true, + placeholder: '请输入密码', + }, + rules: 'required', + }, + { + fieldName: 'host', + label: 'SMTP 服务器域名', + component: 'Input', + componentProps: { + placeholder: '请输入 SMTP 服务器域名', + }, + rules: 'required', + }, + { + fieldName: 'port', + label: 'SMTP 服务器端口', + component: 'InputNumber', + componentProps: { + placeholder: '请输入 SMTP 服务器端口', + min: 0, + max: 65_535, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'sslEnable', + label: '是否开启 SSL', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + }, + rules: z.boolean().default(true), + }, + { + fieldName: 'starttlsEnable', + label: '是否开启 STARTTLS', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + }, + rules: z.boolean().default(false), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'mail', + label: '邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入邮箱', + clearable: true, + }, + }, + { + fieldName: 'username', + label: '用户名', + component: 'Input', + componentProps: { + placeholder: '请输入用户名', + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'mail', + title: '邮箱', + minWidth: 160, + }, + { + field: 'username', + title: '用户名', + minWidth: 160, + }, + { + field: 'host', + title: 'SMTP 服务器域名', + minWidth: 150, + }, + { + field: 'port', + title: 'SMTP 服务器端口', + minWidth: 130, + }, + { + field: 'sslEnable', + title: '是否开启 SSL', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'starttlsEnable', + title: '是否开启 STARTTLS', + minWidth: 145, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/mail/account/index.vue b/apps/web-ele/src/views/system/mail/account/index.vue new file mode 100644 index 0000000..6a15a08 --- /dev/null +++ b/apps/web-ele/src/views/system/mail/account/index.vue @@ -0,0 +1,172 @@ + + diff --git a/apps/web-ele/src/views/system/mail/account/modules/form.vue b/apps/web-ele/src/views/system/mail/account/modules/form.vue new file mode 100644 index 0000000..a7fc397 --- /dev/null +++ b/apps/web-ele/src/views/system/mail/account/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/system/mail/log/data.ts b/apps/web-ele/src/views/system/mail/log/data.ts new file mode 100644 index 0000000..cef8cd7 --- /dev/null +++ b/apps/web-ele/src/views/system/mail/log/data.ts @@ -0,0 +1,259 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDateTime } from '@vben/utils'; + +import { getSimpleMailAccountList } from '#/api/system/mail/account'; +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'sendTime', + label: '发送时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入用户编号', + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + clearable: true, + placeholder: '请选择用户类型', + }, + }, + { + fieldName: 'sendStatus', + label: '发送状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_MAIL_SEND_STATUS, 'number'), + clearable: true, + placeholder: '请选择发送状态', + }, + }, + { + fieldName: 'accountId', + label: '邮箱账号', + component: 'ApiSelect', + componentProps: { + api: getSimpleMailAccountList, + labelField: 'mail', + valueField: 'id', + clearable: true, + placeholder: '请选择邮箱账号', + }, + }, + { + fieldName: 'templateId', + label: '模板编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入模板编号', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'sendTime', + title: '发送时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'userType', + title: '接收用户', + minWidth: 150, + slots: { default: 'userInfo' }, + }, + { + field: 'toMails', + title: '接收信息', + minWidth: 300, + formatter: ({ row }) => { + const lines: string[] = []; + if (row.toMails && row.toMails.length > 0) { + lines.push(`收件:${row.toMails.join('、')}`); + } + if (row.ccMails && row.ccMails.length > 0) { + lines.push(`抄送:${row.ccMails.join('、')}`); + } + if (row.bccMails && row.bccMails.length > 0) { + lines.push(`密送:${row.bccMails.join('、')}`); + } + return lines.join('\n'); + }, + }, + { + field: 'templateTitle', + title: '邮件标题', + minWidth: 120, + }, + { + field: 'templateContent', + title: '邮件内容', + minWidth: 300, + }, + { + field: 'fromMail', + title: '发送邮箱', + minWidth: 120, + }, + { + field: 'sendStatus', + title: '发送状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_MAIL_SEND_STATUS }, + }, + }, + { + field: 'templateCode', + title: '模板编码', + minWidth: 120, + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'id', + label: '编号', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => { + return formatDateTime(val) as string; + }, + }, + { + field: 'fromMail', + label: '发送邮箱', + }, + { + field: 'userId', + label: '接收用户', + render: (val, data) => { + if (data?.userType && val) { + return h('div', [ + h(DictTag, { + type: DICT_TYPE.USER_TYPE, + value: data.userType, + }), + ` (${val})`, + ]); + } + return '无'; + }, + }, + { + field: 'toMails', + label: '接收信息', + render: (val, data) => { + const lines: string[] = []; + if (val && val.length > 0) { + lines.push(`收件:${val.join('、')}`); + } + if (data?.ccMails && data.ccMails.length > 0) { + lines.push(`抄送:${data.ccMails.join('、')}`); + } + if (data?.bccMails && data.bccMails.length > 0) { + lines.push(`密送:${data.bccMails.join('、')}`); + } + return h( + 'div', + { + style: { whiteSpace: 'pre-line' }, + }, + lines.join('\n'), + ); + }, + }, + { + field: 'templateId', + label: '模板编号', + }, + { + field: 'templateCode', + label: '模板编码', + }, + { + field: 'templateTitle', + label: '邮件标题', + }, + { + field: 'templateContent', + label: '邮件内容', + span: 2, + render: (val) => { + return h('div', { + innerHTML: val || '', + }); + }, + }, + { + field: 'sendStatus', + label: '发送状态', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.SYSTEM_MAIL_SEND_STATUS, + value: val, + }); + }, + }, + { + field: 'sendTime', + label: '发送时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'sendMessageId', + label: '发送消息编号', + }, + { + field: 'sendException', + label: '发送异常', + }, + ]; +} diff --git a/apps/web-ele/src/views/system/mail/log/index.vue b/apps/web-ele/src/views/system/mail/log/index.vue new file mode 100644 index 0000000..548f485 --- /dev/null +++ b/apps/web-ele/src/views/system/mail/log/index.vue @@ -0,0 +1,92 @@ + + diff --git a/apps/web-ele/src/views/system/mail/log/modules/detail.vue b/apps/web-ele/src/views/system/mail/log/modules/detail.vue new file mode 100644 index 0000000..ab0daa7 --- /dev/null +++ b/apps/web-ele/src/views/system/mail/log/modules/detail.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/system/mail/template/data.ts b/apps/web-ele/src/views/system/mail/template/data.ts new file mode 100644 index 0000000..876ebcc --- /dev/null +++ b/apps/web-ele/src/views/system/mail/template/data.ts @@ -0,0 +1,250 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getSimpleMailAccountList } from '#/api/system/mail/account'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '模板名称', + component: 'Input', + componentProps: { + placeholder: '请输入模板名称', + }, + rules: 'required', + }, + { + fieldName: 'code', + label: '模板编码', + component: 'Input', + componentProps: { + placeholder: '请输入模板编码', + }, + rules: 'required', + }, + { + fieldName: 'accountId', + label: '邮箱账号', + component: 'ApiSelect', + componentProps: { + api: getSimpleMailAccountList, + labelField: 'mail', + valueField: 'id', + placeholder: '请选择邮箱账号', + }, + rules: 'required', + }, + { + fieldName: 'nickname', + label: '发送人名称', + component: 'Input', + componentProps: { + placeholder: '请输入发送人名称', + }, + }, + { + fieldName: 'title', + label: '模板标题', + component: 'Input', + componentProps: { + placeholder: '请输入模板标题', + }, + rules: 'required', + }, + { + fieldName: 'content', + label: '模板内容', + component: 'RichTextarea', + rules: 'required', + }, + { + fieldName: 'status', + label: '开启状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 发送邮件表单 */ +export function useSendMailFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'templateParams', + label: '模板参数', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'content', + label: '模板内容', + component: 'RichTextarea', + componentProps: { + options: { + readonly: true, + }, + }, + }, + { + fieldName: 'toMails', + label: '收件邮箱', + component: 'InputTag', + componentProps: { + placeholder: '请输入收件邮箱,按 Enter 添加', + }, + }, + { + fieldName: 'ccMails', + label: '抄送邮箱', + component: 'InputTag', + componentProps: { + placeholder: '请输入抄送邮箱,按 Enter 添加', + }, + }, + { + fieldName: 'bccMails', + label: '密送邮箱', + component: 'InputTag', + componentProps: { + placeholder: '请输入密送邮箱,按 Enter 添加', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'status', + label: '开启状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + clearable: true, + placeholder: '请选择开启状态', + }, + }, + { + fieldName: 'code', + label: '模板编码', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入模板编码', + }, + }, + { + fieldName: 'name', + label: '模板名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入模板名称', + }, + }, + { + fieldName: 'accountId', + label: '邮箱账号', + component: 'ApiSelect', + componentProps: { + api: getSimpleMailAccountList, + labelField: 'mail', + valueField: 'id', + clearable: true, + placeholder: '请选择邮箱账号', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + getAccountMail?: (accountId: number) => string | undefined, +): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'code', + title: '模板编码', + minWidth: 120, + }, + { + field: 'name', + title: '模板名称', + minWidth: 120, + }, + { + field: 'title', + title: '模板标题', + minWidth: 120, + }, + { + field: 'accountId', + title: '邮箱账号', + minWidth: 120, + formatter: ({ cellValue }) => getAccountMail?.(cellValue) || '-', + }, + { + field: 'nickname', + title: '发送人名称', + minWidth: 120, + }, + { + field: 'status', + title: '开启状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/mail/template/index.vue b/apps/web-ele/src/views/system/mail/template/index.vue new file mode 100644 index 0000000..6fc015f --- /dev/null +++ b/apps/web-ele/src/views/system/mail/template/index.vue @@ -0,0 +1,205 @@ + + diff --git a/apps/web-ele/src/views/system/mail/template/modules/form.vue b/apps/web-ele/src/views/system/mail/template/modules/form.vue new file mode 100644 index 0000000..4014e46 --- /dev/null +++ b/apps/web-ele/src/views/system/mail/template/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/system/mail/template/modules/send-form.vue b/apps/web-ele/src/views/system/mail/template/modules/send-form.vue new file mode 100644 index 0000000..8f724ed --- /dev/null +++ b/apps/web-ele/src/views/system/mail/template/modules/send-form.vue @@ -0,0 +1,109 @@ + + + diff --git a/apps/web-ele/src/views/system/menu/data.ts b/apps/web-ele/src/views/system/menu/data.ts new file mode 100644 index 0000000..9300d16 --- /dev/null +++ b/apps/web-ele/src/views/system/menu/data.ts @@ -0,0 +1,349 @@ +import type { Recordable } from '@vben/types'; + +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemMenuApi } from '#/api/system/menu'; + +import { h } from 'vue'; + +import { + CommonStatusEnum, + DICT_TYPE, + SystemMenuTypeEnum, +} from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { IconifyIcon } from '@vben/icons'; +import { handleTree, isHttpUrl } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getMenuList } from '#/api/system/menu'; +import { $t } from '#/locales'; +import { componentKeys } from '#/router/routes'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'parentId', + label: '上级菜单', + component: 'ApiTreeSelect', + componentProps: { + clearable: true, + api: async () => { + const data = await getMenuList(); + data.unshift({ + id: 0, + name: '顶级部门', + } as SystemMenuApi.Menu); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择上级菜单', + filterTreeNode(input: string, node: Recordable) { + if (!input || input.length === 0) { + return true; + } + const name: string = node.label ?? ''; + if (!name) return false; + return name.includes(input) || $t(name).includes(input); + }, + showSearch: true, + defaultExpandedKeys: [0], + checkStrictly: true, + }, + rules: 'selectRequired', + renderComponentContent() { + return { + title({ label, icon }: { icon: string; label: string }) { + const components = []; + if (!label) return ''; + if (icon) { + components.push(h(IconifyIcon, { class: 'size-4', icon })); + } + components.push(h('span', { class: '' }, $t(label || ''))); + return h('div', { class: 'flex items-center gap-1' }, components); + }, + }; + }, + }, + { + fieldName: 'name', + label: '菜单名称', + component: 'Input', + componentProps: { + placeholder: '请输入菜单名称', + }, + rules: 'required', + }, + { + fieldName: 'type', + label: '菜单类型', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_MENU_TYPE, 'number'), + }, + rules: z.number().default(SystemMenuTypeEnum.DIR), + }, + { + fieldName: 'icon', + label: '菜单图标', + component: 'IconPicker', + componentProps: { + placeholder: '请选择菜单图标', + prefix: 'carbon', + }, + rules: 'required', + dependencies: { + triggerFields: ['type'], + show: (values) => { + return [SystemMenuTypeEnum.DIR, SystemMenuTypeEnum.MENU].includes( + values.type, + ); + }, + }, + }, + { + fieldName: 'path', + label: '路由地址', + component: 'Input', + componentProps: { + placeholder: '请输入路由地址', + }, + rules: z.string(), + help: '访问的路由地址,如:`user`。如需外网地址时,则以 `http(s)://` 开头', + dependencies: { + triggerFields: ['type', 'parentId'], + show: (values) => { + return [SystemMenuTypeEnum.DIR, SystemMenuTypeEnum.MENU].includes( + values.type, + ); + }, + rules: (values) => { + const schema = z.string().min(1, '路由地址不能为空'); + if (isHttpUrl(values.path)) { + return schema; + } + if (values.parentId === 0) { + return schema.refine( + (path) => path.charAt(0) === '/', + '路径必须以 / 开头', + ); + } + return schema.refine( + (path) => path.charAt(0) !== '/', + '路径不能以 / 开头', + ); + }, + }, + }, + { + fieldName: 'component', + label: '组件地址', + component: 'Input', + componentProps: { + placeholder: '请输入组件地址', + }, + dependencies: { + triggerFields: ['type'], + show: (values) => { + return [SystemMenuTypeEnum.MENU].includes(values.type); + }, + }, + }, + { + fieldName: 'componentName', + label: '组件名称', + component: 'AutoComplete', + componentProps: { + clearable: true, + fetchSuggestions(queryString: string, cb: any) { + const options = componentKeys.map((v) => ({ value: v })); + const createFilter = (qs: string) => { + return (restaurant: any) => { + return restaurant.value.toLowerCase().includes(qs.toLowerCase()); + }; + }; + const results = queryString + ? options.filter(createFilter(queryString)) + : options; + cb(results); + }, + placeholder: '请选择组件名称', + }, + dependencies: { + triggerFields: ['type'], + show: (values) => { + return [SystemMenuTypeEnum.MENU].includes(values.type); + }, + }, + }, + { + fieldName: 'permission', + label: '权限标识', + component: 'Input', + componentProps: { + placeholder: '请输入菜单描述', + }, + dependencies: { + show: (values) => { + return [SystemMenuTypeEnum.BUTTON, SystemMenuTypeEnum.MENU].includes( + values.type, + ); + }, + triggerFields: ['type'], + }, + }, + { + fieldName: 'sort', + label: '显示顺序', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入显示顺序', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '菜单状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'visible', + label: '显示状态', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '显示', value: true }, + { label: '隐藏', value: false }, + ], + }, + rules: 'required', + defaultValue: true, + help: '选择隐藏时,路由将不会出现在侧边栏,但仍然可以访问', + dependencies: { + triggerFields: ['type'], + show: (values) => { + return [SystemMenuTypeEnum.DIR, SystemMenuTypeEnum.MENU].includes( + values.type, + ); + }, + }, + }, + { + fieldName: 'alwaysShow', + label: '总是显示', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '总是', value: true }, + { label: '不是', value: false }, + ], + }, + rules: 'required', + defaultValue: true, + help: '选择不是时,当该菜单只有一个子菜单时,不展示自己,直接展示子菜单', + dependencies: { + triggerFields: ['type'], + show: (values) => { + return [SystemMenuTypeEnum.MENU].includes(values.type); + }, + }, + }, + { + fieldName: 'keepAlive', + label: '缓存状态', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '缓存', value: true }, + { label: '不缓存', value: false }, + ], + }, + rules: 'required', + defaultValue: true, + help: '选择缓存时,则会被 `keep-alive` 缓存,必须填写「组件名称」字段', + dependencies: { + triggerFields: ['type'], + show: (values) => { + return [SystemMenuTypeEnum.MENU].includes(values.type); + }, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '菜单名称', + minWidth: 250, + align: 'left', + fixed: 'left', + slots: { default: 'name' }, + treeNode: true, + }, + { + field: 'type', + title: '菜单类型', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_MENU_TYPE }, + }, + }, + { + field: 'sort', + title: '显示排序', + minWidth: 100, + }, + { + field: 'permission', + title: '权限标识', + minWidth: 200, + }, + { + field: 'path', + title: '组件路径', + minWidth: 200, + }, + { + field: 'componentName', + title: '组件名称', + minWidth: 200, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/menu/index.vue b/apps/web-ele/src/views/system/menu/index.vue new file mode 100644 index 0000000..783bc74 --- /dev/null +++ b/apps/web-ele/src/views/system/menu/index.vue @@ -0,0 +1,181 @@ + + + diff --git a/apps/web-ele/src/views/system/menu/modules/form.vue b/apps/web-ele/src/views/system/menu/modules/form.vue new file mode 100644 index 0000000..9a91c16 --- /dev/null +++ b/apps/web-ele/src/views/system/menu/modules/form.vue @@ -0,0 +1,84 @@ + + + diff --git a/apps/web-ele/src/views/system/notice/data.ts b/apps/web-ele/src/views/system/notice/data.ts new file mode 100644 index 0000000..1746f69 --- /dev/null +++ b/apps/web-ele/src/views/system/notice/data.ts @@ -0,0 +1,134 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'title', + label: '公告标题', + component: 'Input', + componentProps: { + placeholder: '请输入公告标题', + }, + rules: 'required', + }, + { + fieldName: 'type', + label: '公告类型', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_NOTICE_TYPE, 'number'), + }, + rules: 'required', + }, + { + fieldName: 'content', + label: '公告内容', + component: 'RichTextarea', + rules: 'required', + }, + { + fieldName: 'status', + label: '公告状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'title', + label: '公告标题', + component: 'Input', + componentProps: { + placeholder: '请输入公告标题', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '公告状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择公告状态', + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '公告编号', + minWidth: 100, + }, + { + field: 'title', + title: '公告标题', + minWidth: 200, + }, + { + field: 'type', + title: '公告类型', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_NOTICE_TYPE }, + }, + }, + { + field: 'status', + title: '公告状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/notice/index.vue b/apps/web-ele/src/views/system/notice/index.vue new file mode 100644 index 0000000..1809a1a --- /dev/null +++ b/apps/web-ele/src/views/system/notice/index.vue @@ -0,0 +1,191 @@ + + + diff --git a/apps/web-ele/src/views/system/notice/modules/form.vue b/apps/web-ele/src/views/system/notice/modules/form.vue new file mode 100644 index 0000000..f00a497 --- /dev/null +++ b/apps/web-ele/src/views/system/notice/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/system/notify/message/data.ts b/apps/web-ele/src/views/system/notify/message/data.ts new file mode 100644 index 0000000..c786ee1 --- /dev/null +++ b/apps/web-ele/src/views/system/notify/message/data.ts @@ -0,0 +1,237 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入用户编号', + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + placeholder: '请选择用户类型', + }, + }, + { + fieldName: 'templateCode', + label: '模板编码', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入模板编码', + }, + }, + { + fieldName: 'templateType', + label: '模版类型', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, + 'number', + ), + clearable: true, + placeholder: '请选择模版类型', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'userType', + title: '用户类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.USER_TYPE }, + }, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 100, + }, + { + field: 'templateCode', + title: '模板编码', + minWidth: 120, + }, + { + field: 'templateNickname', + title: '发送人名称', + minWidth: 180, + }, + { + field: 'templateContent', + title: '模版内容', + minWidth: 200, + }, + { + field: 'templateParams', + title: '模版参数', + minWidth: 180, + formatter: ({ cellValue }) => { + try { + return JSON.stringify(cellValue); + } catch { + return ''; + } + }, + }, + { + field: 'templateType', + title: '模版类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE }, + }, + }, + { + field: 'readStatus', + title: '是否已读', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'readTime', + title: '阅读时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'id', + label: '编号', + }, + { + field: 'userType', + label: '用户类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.USER_TYPE, + value: val, + }); + }, + }, + { + field: 'userId', + label: '用户编号', + }, + { + field: 'templateId', + label: '模版编号', + }, + { + field: 'templateCode', + label: '模板编码', + }, + { + field: 'templateNickname', + label: '发送人名称', + }, + { + field: 'templateContent', + label: '模版内容', + }, + { + field: 'templateParams', + label: '模版参数', + render: (val) => { + try { + return JSON.stringify(val); + } catch { + return ''; + } + }, + }, + { + field: 'templateType', + label: '模版类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, + value: val, + }); + }, + }, + { + field: 'readStatus', + label: '是否已读', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.INFRA_BOOLEAN_STRING, + value: val, + }); + }, + }, + { + field: 'readTime', + label: '阅读时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/notify/message/index.vue b/apps/web-ele/src/views/system/notify/message/index.vue new file mode 100644 index 0000000..fcac932 --- /dev/null +++ b/apps/web-ele/src/views/system/notify/message/index.vue @@ -0,0 +1,84 @@ + + + diff --git a/apps/web-ele/src/views/system/notify/message/modules/detail.vue b/apps/web-ele/src/views/system/notify/message/modules/detail.vue new file mode 100644 index 0000000..f7dbc8f --- /dev/null +++ b/apps/web-ele/src/views/system/notify/message/modules/detail.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/system/notify/my/data.ts b/apps/web-ele/src/views/system/notify/my/data.ts new file mode 100644 index 0000000..21f051d --- /dev/null +++ b/apps/web-ele/src/views/system/notify/my/data.ts @@ -0,0 +1,137 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'readStatus', + label: '是否已读', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + clearable: true, + placeholder: '请选择是否已读', + }, + }, + { + fieldName: 'createTime', + label: '发送时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + title: '', + width: 40, + type: 'checkbox', + }, + { + field: 'templateNickname', + title: '发送人', + minWidth: 180, + }, + { + field: 'createTime', + title: '发送时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'templateType', + title: '类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE }, + }, + }, + { + field: 'templateContent', + title: '消息内容', + minWidth: 300, + }, + { + field: 'readStatus', + title: '是否已读', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'readTime', + title: '阅读时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'templateNickname', + label: '发送人', + }, + { + field: 'createTime', + label: '发送时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'templateType', + label: '消息类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, + value: val, + }); + }, + }, + { + field: 'readStatus', + label: '是否已读', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.INFRA_BOOLEAN_STRING, + value: val, + }); + }, + }, + { + field: 'readTime', + label: '阅读时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'templateContent', + label: '消息内容', + }, + ]; +} diff --git a/apps/web-ele/src/views/system/notify/my/index.vue b/apps/web-ele/src/views/system/notify/my/index.vue new file mode 100644 index 0000000..9c37b52 --- /dev/null +++ b/apps/web-ele/src/views/system/notify/my/index.vue @@ -0,0 +1,191 @@ + + diff --git a/apps/web-ele/src/views/system/notify/my/modules/detail.vue b/apps/web-ele/src/views/system/notify/my/modules/detail.vue new file mode 100644 index 0000000..f7dbc8f --- /dev/null +++ b/apps/web-ele/src/views/system/notify/my/modules/detail.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/system/notify/template/data.ts b/apps/web-ele/src/views/system/notify/template/data.ts new file mode 100644 index 0000000..5aedc89 --- /dev/null +++ b/apps/web-ele/src/views/system/notify/template/data.ts @@ -0,0 +1,286 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE, UserTypeEnum } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '模板名称', + component: 'Input', + componentProps: { + placeholder: '请输入模板名称', + }, + rules: 'required', + }, + { + fieldName: 'code', + label: '模板编码', + component: 'Input', + componentProps: { + placeholder: '请输入模板编码', + }, + rules: 'required', + }, + { + fieldName: 'nickname', + label: '发送人名称', + component: 'Input', + componentProps: { + placeholder: '请输入发送人名称', + }, + rules: 'required', + }, + { + fieldName: 'content', + label: '模板内容', + component: 'Textarea', + componentProps: { + placeholder: '请输入模板内容', + }, + rules: 'required', + }, + { + fieldName: 'type', + label: '模板类型', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, + 'number', + ), + placeholder: '请选择模板类型', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '模板名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入模板名称', + }, + }, + { + fieldName: 'code', + label: '模板编码', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入模板编码', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + clearable: true, + placeholder: '请选择状态', + }, + }, + { + fieldName: 'type', + label: '模板类型', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, + 'number', + ), + clearable: true, + placeholder: '请选择模板类型', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 发送站内信表单 */ +export function useSendNotifyFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'content', + label: '模板内容', + component: 'Textarea', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'templateCode', + label: '模板编码', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + }, + rules: z.number().default(UserTypeEnum.MEMBER), + }, + { + fieldName: 'userId', + label: '接收人 ID', + component: 'Input', + componentProps: { + placeholder: '请输入用户编号', + }, + dependencies: { + show(values) { + return values.userType === UserTypeEnum.MEMBER; + }, + triggerFields: ['userType'], + }, + rules: 'required', + }, + { + fieldName: 'userId', + label: '接收人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择接收人', + }, + dependencies: { + show(values) { + return values.userType === UserTypeEnum.ADMIN; + }, + triggerFields: ['userType'], + }, + rules: 'required', + }, + { + fieldName: 'templateParams', + label: '模板参数', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'name', + title: '模板名称', + minWidth: 120, + }, + { + field: 'code', + title: '模板编码', + minWidth: 120, + }, + { + field: 'nickname', + title: '发送人名称', + minWidth: 120, + }, + { + field: 'content', + title: '模板内容', + minWidth: 200, + }, + { + field: 'type', + title: '模板类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE }, + }, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'remark', + title: '备注', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/notify/template/index.vue b/apps/web-ele/src/views/system/notify/template/index.vue new file mode 100644 index 0000000..33c2bf8 --- /dev/null +++ b/apps/web-ele/src/views/system/notify/template/index.vue @@ -0,0 +1,207 @@ + + + diff --git a/apps/web-ele/src/views/system/notify/template/modules/form.vue b/apps/web-ele/src/views/system/notify/template/modules/form.vue new file mode 100644 index 0000000..3ce13ff --- /dev/null +++ b/apps/web-ele/src/views/system/notify/template/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/system/notify/template/modules/send-form.vue b/apps/web-ele/src/views/system/notify/template/modules/send-form.vue new file mode 100644 index 0000000..0ed7404 --- /dev/null +++ b/apps/web-ele/src/views/system/notify/template/modules/send-form.vue @@ -0,0 +1,112 @@ + + + diff --git a/apps/web-ele/src/views/system/oauth2/client/data.ts b/apps/web-ele/src/views/system/oauth2/client/data.ts new file mode 100644 index 0000000..5705cb0 --- /dev/null +++ b/apps/web-ele/src/views/system/oauth2/client/data.ts @@ -0,0 +1,261 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'clientId', + label: '客户端编号', + component: 'Input', + componentProps: { + placeholder: '请输入客户端编号', + }, + rules: 'required', + }, + { + fieldName: 'secret', + label: '客户端密钥', + component: 'Input', + componentProps: { + placeholder: '请输入客户端密钥', + }, + rules: 'required', + }, + { + fieldName: 'name', + label: '应用名', + component: 'Input', + componentProps: { + placeholder: '请输入应用名', + }, + rules: 'required', + }, + { + fieldName: 'logo', + label: '应用图标', + component: 'ImageUpload', + rules: 'required', + }, + { + fieldName: 'description', + label: '应用描述', + component: 'Textarea', + componentProps: { + placeholder: '请输入应用描述', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'accessTokenValiditySeconds', + label: '访问令牌的有效期', + component: 'InputNumber', + componentProps: { + placeholder: '请输入访问令牌的有效期,单位:秒', + min: 0, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'refreshTokenValiditySeconds', + label: '刷新令牌的有效期', + component: 'InputNumber', + componentProps: { + placeholder: '请输入刷新令牌的有效期,单位:秒', + min: 0, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'authorizedGrantTypes', + label: '授权类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_OAUTH2_GRANT_TYPE), + multiple: true, + placeholder: '请输入授权类型', + }, + rules: 'required', + }, + { + fieldName: 'scopes', + label: '授权范围', + component: 'InputTag', + componentProps: { + placeholder: '请输入授权范围', + }, + }, + { + fieldName: 'autoApproveScopes', + label: '自动授权范围', + component: 'Select', + componentProps: { + placeholder: '请输入自动授权范围', + multiple: true, + options: [], + }, + dependencies: { + triggerFields: ['scopes'], + componentProps: (values) => ({ + options: values.scopes + ? values.scopes.map((scope: string) => ({ + label: scope, + value: scope, + })) + : [], + }), + }, + }, + { + fieldName: 'redirectUris', + label: '可重定向的 URI 地址', + component: 'InputTag', + componentProps: { + placeholder: '请输入可重定向的 URI 地址', + }, + rules: 'required', + }, + { + fieldName: 'authorities', + label: '权限', + component: 'InputTag', + componentProps: { + placeholder: '请输入权限', + }, + }, + { + fieldName: 'resourceIds', + label: '资源', + component: 'InputTag', + componentProps: { + placeholder: '请输入资源', + }, + }, + { + fieldName: 'additionalInformation', + label: '附加信息', + component: 'Textarea', + componentProps: { + placeholder: '请输入附加信息,JSON 格式数据', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '应用名', + component: 'Input', + componentProps: { + placeholder: '请输入应用名', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + clearable: true, + placeholder: '请输入状态', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'clientId', + title: '客户端编号', + minWidth: 120, + }, + { + field: 'secret', + title: '客户端密钥', + minWidth: 120, + }, + { + field: 'name', + title: '应用名', + minWidth: 120, + }, + { + field: 'logo', + title: '应用图标', + minWidth: 100, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'status', + title: '状态', + minWidth: 80, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'accessTokenValiditySeconds', + title: '访问令牌的有效期', + minWidth: 150, + formatter: ({ cellValue }) => `${cellValue} 秒`, + }, + { + field: 'refreshTokenValiditySeconds', + title: '刷新令牌的有效期', + minWidth: 150, + formatter: ({ cellValue }) => `${cellValue} 秒`, + }, + { + field: 'authorizedGrantTypes', + title: '授权类型', + minWidth: 100, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/oauth2/client/index.vue b/apps/web-ele/src/views/system/oauth2/client/index.vue new file mode 100644 index 0000000..2ee4047 --- /dev/null +++ b/apps/web-ele/src/views/system/oauth2/client/index.vue @@ -0,0 +1,176 @@ + + + diff --git a/apps/web-ele/src/views/system/oauth2/client/modules/form.vue b/apps/web-ele/src/views/system/oauth2/client/modules/form.vue new file mode 100644 index 0000000..927e423 --- /dev/null +++ b/apps/web-ele/src/views/system/oauth2/client/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/system/oauth2/token/data.ts b/apps/web-ele/src/views/system/oauth2/token/data.ts new file mode 100644 index 0000000..51a9d59 --- /dev/null +++ b/apps/web-ele/src/views/system/oauth2/token/data.ts @@ -0,0 +1,93 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + placeholder: '请输入用户编号', + clearable: true, + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + placeholder: '请选择用户类型', + clearable: true, + }, + }, + { + fieldName: 'clientId', + label: '客户端编号', + component: 'Input', + componentProps: { + placeholder: '请输入客户端编号', + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'accessToken', + title: '访问令牌', + minWidth: 300, + }, + { + field: 'refreshToken', + title: '刷新令牌', + minWidth: 300, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 100, + }, + { + field: 'userType', + title: '用户类型', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.USER_TYPE }, + }, + }, + { + field: 'clientId', + title: '客户端编号', + minWidth: 120, + }, + { + field: 'expiresTime', + title: '过期时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/oauth2/token/index.vue b/apps/web-ele/src/views/system/oauth2/token/index.vue new file mode 100644 index 0000000..e2af944 --- /dev/null +++ b/apps/web-ele/src/views/system/oauth2/token/index.vue @@ -0,0 +1,143 @@ + + + diff --git a/apps/web-ele/src/views/system/operatelog/data.ts b/apps/web-ele/src/views/system/operatelog/data.ts new file mode 100644 index 0000000..aa67c8e --- /dev/null +++ b/apps/web-ele/src/views/system/operatelog/data.ts @@ -0,0 +1,200 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { formatDateTime } from '@vben/utils'; + +import { getSimpleUserList } from '#/api/system/user'; +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '操作人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + clearable: true, + placeholder: '请选择操作人员', + }, + }, + { + fieldName: 'type', + label: '操作模块', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入操作模块', + }, + }, + { + fieldName: 'subType', + label: '操作名', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入操作名', + }, + }, + { + fieldName: 'action', + label: '操作内容', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入操作内容', + }, + }, + { + fieldName: 'createTime', + label: '操作时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'bizId', + label: '业务编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入业务编号', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '日志编号', + minWidth: 100, + }, + { + field: 'userName', + title: '操作人', + minWidth: 120, + }, + { + field: 'type', + title: '操作模块', + minWidth: 120, + }, + { + field: 'subType', + title: '操作名', + minWidth: 160, + }, + { + field: 'action', + title: '操作内容', + minWidth: 200, + }, + { + field: 'createTime', + title: '操作时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'bizId', + title: '业务编号', + minWidth: 120, + }, + { + field: 'userIp', + title: '操作 IP', + minWidth: 120, + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'id', + label: '日志编号', + }, + { + field: 'traceId', + label: '链路追踪', + show: (data) => !data?.traceId, + }, + { + field: 'userId', + label: '操作人编号', + }, + { + field: 'userType', + label: '操作人类型', + render: (val) => h(DictTag, { type: DICT_TYPE.USER_TYPE, value: val }), + }, + { + field: 'userName', + label: '操作人名字', + }, + { + field: 'userIp', + label: '操作人 IP', + }, + { + field: 'userAgent', + label: '操作人 UA', + }, + { + field: 'type', + label: '操作模块', + }, + { + field: 'subType', + label: '操作名', + }, + { + field: 'action', + label: '操作内容', + }, + { + field: 'extra', + label: '操作拓展参数', + show: (val) => !val, + }, + { + field: 'requestUrl', + label: '请求 URL', + render: (val, data) => { + if (data?.requestMethod && val) { + return `${data.requestMethod} ${val}`; + } + return ''; + }, + }, + { + field: 'createTime', + label: '操作时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'bizId', + label: '业务编号', + }, + ]; +} diff --git a/apps/web-ele/src/views/system/operatelog/index.vue b/apps/web-ele/src/views/system/operatelog/index.vue new file mode 100644 index 0000000..a67735d --- /dev/null +++ b/apps/web-ele/src/views/system/operatelog/index.vue @@ -0,0 +1,104 @@ + + + diff --git a/apps/web-ele/src/views/system/operatelog/modules/detail.vue b/apps/web-ele/src/views/system/operatelog/modules/detail.vue new file mode 100644 index 0000000..f4d8ae9 --- /dev/null +++ b/apps/web-ele/src/views/system/operatelog/modules/detail.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/system/post/data.ts b/apps/web-ele/src/views/system/post/data.ts new file mode 100644 index 0000000..d9c94a3 --- /dev/null +++ b/apps/web-ele/src/views/system/post/data.ts @@ -0,0 +1,155 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '岗位名称', + componentProps: { + placeholder: '请输入岗位名称', + }, + rules: 'required', + }, + { + component: 'Input', + fieldName: 'code', + label: '岗位编码', + componentProps: { + placeholder: '请输入岗位编码', + }, + rules: 'required', + }, + { + fieldName: 'sort', + label: '显示顺序', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入显示顺序', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '岗位状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '岗位备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入岗位备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '岗位名称', + component: 'Input', + componentProps: { + placeholder: '请输入岗位名称', + clearable: true, + }, + }, + { + fieldName: 'code', + label: '岗位编码', + component: 'Input', + componentProps: { + placeholder: '请输入岗位编码', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '岗位状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择岗位状态', + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '岗位编号', + minWidth: 200, + }, + { + field: 'name', + title: '岗位名称', + minWidth: 200, + }, + { + field: 'code', + title: '岗位编码', + minWidth: 200, + }, + { + field: 'sort', + title: '显示顺序', + minWidth: 100, + }, + { + field: 'remark', + title: '岗位备注', + minWidth: 200, + }, + { + field: 'status', + title: '岗位状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/post/index.vue b/apps/web-ele/src/views/system/post/index.vue new file mode 100644 index 0000000..1d0c826 --- /dev/null +++ b/apps/web-ele/src/views/system/post/index.vue @@ -0,0 +1,183 @@ + + + diff --git a/apps/web-ele/src/views/system/post/modules/form.vue b/apps/web-ele/src/views/system/post/modules/form.vue new file mode 100644 index 0000000..87453a2 --- /dev/null +++ b/apps/web-ele/src/views/system/post/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/system/role/data.ts b/apps/web-ele/src/views/system/role/data.ts new file mode 100644 index 0000000..2d1ecb0 --- /dev/null +++ b/apps/web-ele/src/views/system/role/data.ts @@ -0,0 +1,264 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { + CommonStatusEnum, + DICT_TYPE, + SystemDataScopeEnum, +} from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '角色名称', + component: 'Input', + componentProps: { + placeholder: '请输入角色名称', + }, + rules: 'required', + }, + { + fieldName: 'code', + label: '角色标识', + component: 'Input', + componentProps: { + placeholder: '请输入角色标识', + }, + rules: 'required', + }, + { + fieldName: 'sort', + label: '显示顺序', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入显示顺序', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '角色状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '角色备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入角色备注', + }, + }, + ]; +} + +/** 分配数据权限的表单 */ +export function useAssignDataPermissionFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '角色名称', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + component: 'Input', + fieldName: 'code', + label: '角色标识', + componentProps: { + disabled: true, + }, + }, + { + component: 'Select', + fieldName: 'dataScope', + label: '权限范围', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE, 'number'), + }, + }, + { + fieldName: 'dataScopeDeptIds', + label: '部门范围', + component: 'Input', + formItemClass: 'items-start', + dependencies: { + triggerFields: ['dataScope'], + show: (values) => { + return values.dataScope === SystemDataScopeEnum.DEPT_CUSTOM; + }, + }, + }, + ]; +} + +/** 分配菜单的表单 */ +export function useAssignMenuFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '角色名称', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'code', + label: '角色标识', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'menuIds', + label: '菜单权限', + component: 'Input', + formItemClass: 'items-start', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '角色名称', + component: 'Input', + componentProps: { + placeholder: '请输入角色名称', + clearable: true, + }, + }, + { + fieldName: 'code', + label: '角色标识', + component: 'Input', + componentProps: { + placeholder: '请输入角色标识', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '角色状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择角色状态', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '角色编号', + minWidth: 100, + }, + { + field: 'name', + title: '角色名称', + minWidth: 200, + }, + { + field: 'type', + title: '角色类型', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_ROLE_TYPE }, + }, + }, + { + field: 'code', + title: '角色标识', + minWidth: 200, + }, + { + field: 'sort', + title: '显示顺序', + minWidth: 100, + }, + { + field: 'remark', + title: '角色备注', + minWidth: 100, + }, + { + field: 'status', + title: '角色状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 240, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/role/index.vue b/apps/web-ele/src/views/system/role/index.vue new file mode 100644 index 0000000..de79b99 --- /dev/null +++ b/apps/web-ele/src/views/system/role/index.vue @@ -0,0 +1,232 @@ + + + diff --git a/apps/web-ele/src/views/system/role/modules/assign-data-permission-form.vue b/apps/web-ele/src/views/system/role/modules/assign-data-permission-form.vue new file mode 100644 index 0000000..c78f904 --- /dev/null +++ b/apps/web-ele/src/views/system/role/modules/assign-data-permission-form.vue @@ -0,0 +1,167 @@ + + + diff --git a/apps/web-ele/src/views/system/role/modules/assign-menu-form.vue b/apps/web-ele/src/views/system/role/modules/assign-menu-form.vue new file mode 100644 index 0000000..463a16a --- /dev/null +++ b/apps/web-ele/src/views/system/role/modules/assign-menu-form.vue @@ -0,0 +1,169 @@ + + + diff --git a/apps/web-ele/src/views/system/role/modules/form.vue b/apps/web-ele/src/views/system/role/modules/form.vue new file mode 100644 index 0000000..90522e3 --- /dev/null +++ b/apps/web-ele/src/views/system/role/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/system/sms/channel/data.ts b/apps/web-ele/src/views/system/sms/channel/data.ts new file mode 100644 index 0000000..f244c49 --- /dev/null +++ b/apps/web-ele/src/views/system/sms/channel/data.ts @@ -0,0 +1,193 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'signature', + label: '短信签名', + component: 'Input', + componentProps: { + placeholder: '请输入短信签名', + }, + rules: 'required', + }, + { + fieldName: 'code', + label: '渠道编码', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE, 'string'), + placeholder: '请选择短信渠道', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '启用状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + { + fieldName: 'apiKey', + label: '短信 API 的账号', + component: 'Input', + componentProps: { + placeholder: '请输入短信 API 的账号', + }, + rules: 'required', + }, + { + fieldName: 'apiSecret', + label: '短信 API 的密钥', + component: 'Input', + componentProps: { + placeholder: '请输入短信 API 的密钥', + }, + }, + { + fieldName: 'callbackUrl', + label: '短信发送回调 URL', + component: 'Input', + componentProps: { + placeholder: '请输入短信发送回调 URL', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'signature', + label: '短信签名', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入短信签名', + }, + }, + { + fieldName: 'code', + label: '渠道编码', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE, 'string'), + placeholder: '请选择短信渠道', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'signature', + title: '短信签名', + minWidth: 120, + }, + { + field: 'code', + title: '渠道编码', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE }, + }, + }, + { + field: 'status', + title: '启用状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'apiKey', + title: '短信 API 的账号', + minWidth: 180, + }, + { + field: 'apiSecret', + title: '短信 API 的密钥', + minWidth: 180, + }, + { + field: 'callbackUrl', + title: '短信发送回调 URL', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'remark', + title: '备注', + minWidth: 120, + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/sms/channel/index.vue b/apps/web-ele/src/views/system/sms/channel/index.vue new file mode 100644 index 0000000..b4400a2 --- /dev/null +++ b/apps/web-ele/src/views/system/sms/channel/index.vue @@ -0,0 +1,173 @@ + + + diff --git a/apps/web-ele/src/views/system/sms/channel/modules/form.vue b/apps/web-ele/src/views/system/sms/channel/modules/form.vue new file mode 100644 index 0000000..2e11fc8 --- /dev/null +++ b/apps/web-ele/src/views/system/sms/channel/modules/form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/system/sms/log/data.ts b/apps/web-ele/src/views/system/sms/log/data.ts new file mode 100644 index 0000000..3657516 --- /dev/null +++ b/apps/web-ele/src/views/system/sms/log/data.ts @@ -0,0 +1,265 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDateTime } from '@vben/utils'; + +import { getSimpleSmsChannelList } from '#/api/system/sms/channel'; +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'mobile', + label: '手机号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入手机号', + }, + }, + { + fieldName: 'channelId', + label: '短信渠道', + component: 'ApiSelect', + componentProps: { + api: getSimpleSmsChannelList, + labelField: 'signature', + valueField: 'id', + clearable: true, + placeholder: '请选择短信渠道', + }, + }, + { + fieldName: 'templateId', + label: '模板编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入模板编号', + }, + }, + { + fieldName: 'sendStatus', + label: '发送状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_SMS_SEND_STATUS, 'number'), + clearable: true, + placeholder: '请选择发送状态', + }, + }, + { + fieldName: 'sendTime', + label: '发送时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'receiveStatus', + label: '接收状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_SMS_RECEIVE_STATUS, 'number'), + clearable: true, + placeholder: '请选择接收状态', + }, + }, + { + fieldName: 'receiveTime', + label: '接收时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'mobile', + title: '手机号', + minWidth: 120, + }, + { + field: 'templateContent', + title: '短信内容', + minWidth: 300, + }, + { + field: 'sendStatus', + title: '发送状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_SMS_SEND_STATUS }, + }, + }, + { + field: 'sendTime', + title: '发送时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'receiveStatus', + title: '接收状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_SMS_RECEIVE_STATUS }, + }, + }, + { + field: 'receiveTime', + title: '接收时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'channelCode', + title: '短信渠道', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE }, + }, + }, + { + field: 'templateId', + title: '模板编号', + minWidth: 100, + }, + { + field: 'templateType', + title: '短信类型', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_SMS_TEMPLATE_TYPE }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'mobile', + label: '手机号', + }, + { + field: 'channelCode', + label: '短信渠道', + }, + { + field: 'templateId', + label: '模板编号', + }, + { + field: 'templateType', + label: '模板类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.SYSTEM_SMS_TEMPLATE_TYPE, + value: val, + }); + }, + }, + { + field: 'templateContent', + label: '短信内容', + }, + { + field: 'sendStatus', + label: '发送状态', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.SYSTEM_SMS_SEND_STATUS, + value: val, + }); + }, + }, + { + field: 'sendTime', + label: '发送时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'apiSendCode', + label: 'API 发送编码', + }, + { + field: 'apiSendMsg', + label: 'API 发送消息', + }, + { + field: 'receiveStatus', + label: '接收状态', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.SYSTEM_SMS_RECEIVE_STATUS, + value: val, + }); + }, + }, + { + field: 'receiveTime', + label: '接收时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'apiReceiveCode', + label: 'API 接收编码', + }, + { + field: 'apiReceiveMsg', + label: 'API 接收消息', + span: 2, + }, + { + field: 'apiRequestId', + label: 'API 请求 ID', + }, + { + field: 'apiSerialNo', + label: 'API 序列号', + }, + ]; +} diff --git a/apps/web-ele/src/views/system/sms/log/index.vue b/apps/web-ele/src/views/system/sms/log/index.vue new file mode 100644 index 0000000..0bd3a92 --- /dev/null +++ b/apps/web-ele/src/views/system/sms/log/index.vue @@ -0,0 +1,104 @@ + + + diff --git a/apps/web-ele/src/views/system/sms/log/modules/detail.vue b/apps/web-ele/src/views/system/sms/log/modules/detail.vue new file mode 100644 index 0000000..37af10f --- /dev/null +++ b/apps/web-ele/src/views/system/sms/log/modules/detail.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/system/sms/template/data.ts b/apps/web-ele/src/views/system/sms/template/data.ts new file mode 100644 index 0000000..0a3d3e8 --- /dev/null +++ b/apps/web-ele/src/views/system/sms/template/data.ts @@ -0,0 +1,272 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getSimpleSmsChannelList } from '#/api/system/sms/channel'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'type', + label: '短信类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_SMS_TEMPLATE_TYPE, 'number'), + placeholder: '请选择短信类型', + }, + rules: 'required', + }, + { + fieldName: 'name', + label: '模板名称', + component: 'Input', + componentProps: { + placeholder: '请输入模板名称', + }, + rules: 'required', + }, + { + fieldName: 'code', + label: '模板编码', + component: 'Input', + componentProps: { + placeholder: '请输入模板编码', + }, + rules: 'required', + }, + { + fieldName: 'channelId', + label: '短信渠道', + component: 'ApiSelect', + componentProps: { + api: getSimpleSmsChannelList, + labelField: 'signature', + valueField: 'id', + placeholder: '请选择短信渠道', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '开启状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'content', + label: '模板内容', + component: 'Textarea', + componentProps: { + placeholder: '请输入模板内容', + rows: 4, + }, + rules: 'required', + }, + { + fieldName: 'apiTemplateId', + label: '短信 API 的模板编号', + component: 'Input', + componentProps: { + placeholder: '请输入短信 API 的模板编号', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'type', + label: '短信类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_SMS_TEMPLATE_TYPE, 'number'), + clearable: true, + placeholder: '请选择短信类型', + }, + }, + { + fieldName: 'status', + label: '开启状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + clearable: true, + placeholder: '请选择开启状态', + }, + }, + { + fieldName: 'code', + label: '模板编码', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入模板编码', + }, + }, + { + fieldName: 'name', + label: '模板名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入模板名称', + }, + }, + { + fieldName: 'channelId', + label: '短信渠道', + component: 'ApiSelect', + componentProps: { + api: getSimpleSmsChannelList, + labelField: 'signature', + valueField: 'id', + clearable: true, + placeholder: '请选择短信渠道', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 发送短信表单 */ +export function useSendSmsFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'content', + label: '模板内容', + component: 'Textarea', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'mobile', + label: '手机号码', + component: 'Input', + componentProps: { + placeholder: '请输入手机号码', + }, + rules: 'required', + }, + { + fieldName: 'templateParams', + label: '模板参数', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'type', + title: '短信类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_SMS_TEMPLATE_TYPE }, + }, + }, + { + field: 'name', + title: '模板名称', + minWidth: 120, + }, + { + field: 'code', + title: '模板编码', + minWidth: 120, + }, + { + field: 'content', + title: '模板内容', + minWidth: 200, + }, + { + field: 'status', + title: '开启状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'apiTemplateId', + title: '短信 API 的模板编号', + minWidth: 180, + }, + { + field: 'channelCode', + title: '短信渠道', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'remark', + title: '备注', + minWidth: 120, + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/sms/template/index.vue b/apps/web-ele/src/views/system/sms/template/index.vue new file mode 100644 index 0000000..0d340c2 --- /dev/null +++ b/apps/web-ele/src/views/system/sms/template/index.vue @@ -0,0 +1,207 @@ + + + diff --git a/apps/web-ele/src/views/system/sms/template/modules/form.vue b/apps/web-ele/src/views/system/sms/template/modules/form.vue new file mode 100644 index 0000000..25aea86 --- /dev/null +++ b/apps/web-ele/src/views/system/sms/template/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/system/sms/template/modules/send-form.vue b/apps/web-ele/src/views/system/sms/template/modules/send-form.vue new file mode 100644 index 0000000..a02b8e0 --- /dev/null +++ b/apps/web-ele/src/views/system/sms/template/modules/send-form.vue @@ -0,0 +1,109 @@ + + + diff --git a/apps/web-ele/src/views/system/social/client/data.ts b/apps/web-ele/src/views/system/social/client/data.ts new file mode 100644 index 0000000..1fcf77a --- /dev/null +++ b/apps/web-ele/src/views/system/social/client/data.ts @@ -0,0 +1,220 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { + CommonStatusEnum, + DICT_TYPE, + SystemUserSocialTypeEnum, +} from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '应用名', + component: 'Input', + componentProps: { + placeholder: '请输入应用名', + }, + rules: 'required', + }, + { + fieldName: 'socialType', + label: '社交平台', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_SOCIAL_TYPE, 'number'), + placeholder: '请选择社交平台', + }, + rules: 'required', + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + }, + rules: 'required', + }, + { + fieldName: 'clientId', + label: '客户端编号', + component: 'Input', + componentProps: { + placeholder: '请输入客户端编号,对应各平台的 appKey', + }, + rules: 'required', + }, + { + fieldName: 'clientSecret', + label: '客户端密钥', + component: 'Input', + componentProps: { + placeholder: '请输入客户端密钥,对应各平台的 appSecret', + }, + rules: 'required', + }, + { + fieldName: 'agentId', + label: 'agentId', + component: 'Input', + componentProps: { + placeholder: '授权方的网页应用 ID,有则填', + }, + dependencies: { + triggerFields: ['socialType'], + show: (values) => + values.socialType === SystemUserSocialTypeEnum.WECHAT_ENTERPRISE.type, + }, + }, + { + fieldName: 'publicKey', + label: 'publicKey', + component: 'Input', + componentProps: { + placeholder: '请输入 publicKey 公钥', + }, + dependencies: { + triggerFields: ['socialType'], + show: (values) => values.socialType === 40, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '应用名', + component: 'Input', + componentProps: { + placeholder: '请输入应用名', + clearable: true, + }, + }, + { + fieldName: 'socialType', + label: '社交平台', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_SOCIAL_TYPE, 'number'), + placeholder: '请选择社交平台', + clearable: true, + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + placeholder: '请选择用户类型', + clearable: true, + }, + }, + { + fieldName: 'clientId', + label: '客户端编号', + component: 'Input', + componentProps: { + placeholder: '请输入客户端编号', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 100, + }, + { + field: 'name', + title: '应用名', + minWidth: 120, + }, + { + field: 'socialType', + title: '社交平台', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_SOCIAL_TYPE }, + }, + }, + { + field: 'userType', + title: '用户类型', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.USER_TYPE }, + }, + }, + { + field: 'clientId', + title: '客户端编号', + minWidth: 180, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/social/client/index.vue b/apps/web-ele/src/views/system/social/client/index.vue new file mode 100644 index 0000000..9c7b733 --- /dev/null +++ b/apps/web-ele/src/views/system/social/client/index.vue @@ -0,0 +1,173 @@ + + + diff --git a/apps/web-ele/src/views/system/social/client/modules/form.vue b/apps/web-ele/src/views/system/social/client/modules/form.vue new file mode 100644 index 0000000..47bd5fd --- /dev/null +++ b/apps/web-ele/src/views/system/social/client/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/system/social/user/data.ts b/apps/web-ele/src/views/system/social/user/data.ts new file mode 100644 index 0000000..77847d0 --- /dev/null +++ b/apps/web-ele/src/views/system/social/user/data.ts @@ -0,0 +1,162 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { ElImage } from 'element-plus'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'type', + label: '社交平台', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_SOCIAL_TYPE, 'number'), + placeholder: '请选择社交平台', + clearable: true, + }, + }, + { + fieldName: 'nickname', + label: '用户昵称', + component: 'Input', + componentProps: { + placeholder: '请输入用户昵称', + clearable: true, + }, + }, + { + fieldName: 'openid', + label: '社交 openid', + component: 'Input', + componentProps: { + placeholder: '请输入社交 openid', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'type', + title: '社交平台', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_SOCIAL_TYPE }, + }, + }, + { + field: 'openid', + title: '社交 openid', + minWidth: 180, + }, + { + field: 'nickname', + title: '用户昵称', + minWidth: 120, + }, + { + field: 'avatar', + title: '用户头像', + minWidth: 100, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'updateTime', + title: '更新时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'type', + label: '社交平台', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.SYSTEM_SOCIAL_TYPE, + value: val, + }); + }, + }, + { + field: 'nickname', + label: '用户昵称', + }, + { + field: 'avatar', + label: '用户头像', + render: (val) => { + if (val) { + return h(ElImage, { + src: val, + previewSrcList: [val], + class: 'w-10 h-10 cursor-pointer', + previewTeleported: true, + }); + } + return '无'; + }, + }, + { + field: 'token', + label: '社交 token', + }, + { + field: 'rawTokenInfo', + label: '原始 Token 数据', + }, + { + field: 'rawUserInfo', + label: '原始 User 数据', + }, + { + field: 'code', + label: '最后一次的认证 code', + }, + { + field: 'state', + label: '最后一次的认证 state', + }, + ]; +} diff --git a/apps/web-ele/src/views/system/social/user/index.vue b/apps/web-ele/src/views/system/social/user/index.vue new file mode 100644 index 0000000..11dc331 --- /dev/null +++ b/apps/web-ele/src/views/system/social/user/index.vue @@ -0,0 +1,79 @@ + + + diff --git a/apps/web-ele/src/views/system/social/user/modules/detail.vue b/apps/web-ele/src/views/system/social/user/modules/detail.vue new file mode 100644 index 0000000..a4edf00 --- /dev/null +++ b/apps/web-ele/src/views/system/social/user/modules/detail.vue @@ -0,0 +1,53 @@ + + + diff --git a/apps/web-ele/src/views/system/tenant/data.ts b/apps/web-ele/src/views/system/tenant/data.ts new file mode 100644 index 0000000..54ac877 --- /dev/null +++ b/apps/web-ele/src/views/system/tenant/data.ts @@ -0,0 +1,259 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemTenantPackageApi } from '#/api/system/tenant-package'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getTenantPackageList } from '#/api/system/tenant-package'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 关联数据 */ +let tenantPackageList: SystemTenantPackageApi.TenantPackage[] = []; +getTenantPackageList().then((data) => (tenantPackageList = data)); + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '租户名称', + component: 'Input', + componentProps: { + placeholder: '请输入租户名称', + }, + rules: 'required', + }, + { + fieldName: 'packageId', + label: '租户套餐', + component: 'ApiSelect', + componentProps: { + api: getTenantPackageList, + labelField: 'name', + valueField: 'id', + placeholder: '请选择租户套餐', + }, + rules: 'required', + }, + { + fieldName: 'contactName', + label: '联系人', + component: 'Input', + componentProps: { + placeholder: '请输入联系人', + }, + rules: 'required', + }, + { + fieldName: 'contactMobile', + label: '联系手机', + component: 'Input', + componentProps: { + placeholder: '请输入联系手机', + }, + rules: 'mobile', + }, + { + label: '用户名称', + fieldName: 'username', + component: 'Input', + componentProps: { + placeholder: '请输入用户名称', + }, + rules: 'required', + dependencies: { + triggerFields: ['id'], + show: (values) => !values.id, + }, + }, + { + label: '用户密码', + fieldName: 'password', + component: 'Input', + componentProps: { + showPassword: true, + }, + rules: 'required', + dependencies: { + triggerFields: ['id'], + show: (values) => !values.id, + }, + }, + { + label: '账号额度', + fieldName: 'accountCount', + component: 'InputNumber', + componentProps: { + placeholder: '请输入账号额度', + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + label: '过期时间', + fieldName: 'expireTime', + component: 'DatePicker', + componentProps: { + format: 'YYYY-MM-DD', + valueFormat: 'x', + placeholder: '请选择过期时间', + class: '!w-full', + }, + rules: 'required', + }, + { + label: '绑定域名', + fieldName: 'websites', + component: 'InputTag', + componentProps: { + placeholder: '请输入绑定域名', + }, + }, + { + fieldName: 'status', + label: '租户状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '租户名', + component: 'Input', + componentProps: { + placeholder: '请输入租户名', + clearable: true, + }, + }, + { + fieldName: 'contactName', + label: '联系人', + component: 'Input', + componentProps: { + placeholder: '请输入联系人', + clearable: true, + }, + }, + { + fieldName: 'contactMobile', + label: '联系手机', + component: 'Input', + componentProps: { + placeholder: '请输入联系手机', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + placeholder: '请选择状态', + clearable: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '租户编号', + minWidth: 100, + }, + { + field: 'name', + title: '租户名', + minWidth: 180, + }, + { + field: 'packageId', + title: '租户套餐', + minWidth: 180, + formatter: ({ cellValue }) => { + return cellValue === 0 + ? '系统租户' + : tenantPackageList.find((pkg) => pkg.id === cellValue)?.name || '-'; + }, + }, + { + field: 'contactName', + title: '联系人', + minWidth: 100, + }, + { + field: 'contactMobile', + title: '联系手机', + minWidth: 180, + }, + { + field: 'accountCount', + title: '账号额度', + minWidth: 100, + }, + { + field: 'expireTime', + title: '过期时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'websites', + title: '绑定域名', + minWidth: 180, + }, + { + field: 'status', + title: '租户状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/tenant/index.vue b/apps/web-ele/src/views/system/tenant/index.vue new file mode 100644 index 0000000..25a1be3 --- /dev/null +++ b/apps/web-ele/src/views/system/tenant/index.vue @@ -0,0 +1,186 @@ + + diff --git a/apps/web-ele/src/views/system/tenant/modules/form.vue b/apps/web-ele/src/views/system/tenant/modules/form.vue new file mode 100644 index 0000000..ccdd99f --- /dev/null +++ b/apps/web-ele/src/views/system/tenant/modules/form.vue @@ -0,0 +1,80 @@ + + diff --git a/apps/web-ele/src/views/system/tenantPackage/data.ts b/apps/web-ele/src/views/system/tenantPackage/data.ts new file mode 100644 index 0000000..01f165e --- /dev/null +++ b/apps/web-ele/src/views/system/tenantPackage/data.ts @@ -0,0 +1,131 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { z } from '#/adapter/form'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '套餐名称', + component: 'Input', + componentProps: { + placeholder: '请输入套餐名称', + }, + rules: 'required', + }, + { + fieldName: 'menuIds', + label: '菜单权限', + component: 'Input', + formItemClass: 'items-start', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '套餐名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入套餐名称', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + clearable: true, + placeholder: '请选择状态', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '套餐编号', + minWidth: 100, + }, + { + field: 'name', + title: '套餐名称', + minWidth: 180, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/tenantPackage/index.vue b/apps/web-ele/src/views/system/tenantPackage/index.vue new file mode 100644 index 0000000..4a76c12 --- /dev/null +++ b/apps/web-ele/src/views/system/tenantPackage/index.vue @@ -0,0 +1,173 @@ + + + diff --git a/apps/web-ele/src/views/system/tenantPackage/modules/form.vue b/apps/web-ele/src/views/system/tenantPackage/modules/form.vue new file mode 100644 index 0000000..c789d64 --- /dev/null +++ b/apps/web-ele/src/views/system/tenantPackage/modules/form.vue @@ -0,0 +1,161 @@ + + + diff --git a/apps/web-ele/src/views/system/user/components/index.ts b/apps/web-ele/src/views/system/user/components/index.ts new file mode 100644 index 0000000..9f00ad1 --- /dev/null +++ b/apps/web-ele/src/views/system/user/components/index.ts @@ -0,0 +1 @@ +export { default as UserSelectModal } from './select-modal.vue'; diff --git a/apps/web-ele/src/views/system/user/components/select-modal.vue b/apps/web-ele/src/views/system/user/components/select-modal.vue new file mode 100644 index 0000000..266edca --- /dev/null +++ b/apps/web-ele/src/views/system/user/components/select-modal.vue @@ -0,0 +1,517 @@ + + + + + diff --git a/apps/web-ele/src/views/system/user/data.ts b/apps/web-ele/src/views/system/user/data.ts new file mode 100644 index 0000000..813ed7e --- /dev/null +++ b/apps/web-ele/src/views/system/user/data.ts @@ -0,0 +1,353 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { SystemUserApi } from '#/api/system/user'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { $t } from '@vben/locales'; +import { handleTree } from '@vben/utils'; + +import { z } from '#/adapter/form'; +import { getDeptList } from '#/api/system/dept'; +import { getSimplePostList } from '#/api/system/post'; +import { getSimpleRoleList } from '#/api/system/role'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'username', + label: '用户名称', + component: 'Input', + componentProps: { + placeholder: '请输入用户名称', + }, + rules: 'required', + }, + { + label: '用户密码', + fieldName: 'password', + component: 'Input', + componentProps: { + showPassword: true, + }, + rules: 'required', + dependencies: { + triggerFields: ['id'], + show: (values) => !values.id, + }, + }, + { + fieldName: 'nickname', + label: '用户昵称', + component: 'Input', + componentProps: { + placeholder: '请输入用户昵称', + }, + rules: 'required', + }, + { + fieldName: 'deptId', + label: '归属部门', + component: 'ApiTreeSelect', + componentProps: { + api: async () => { + const data = await getDeptList(); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择归属部门', + defaultExpandAll: true, + checkStrictly: true, + }, + }, + { + fieldName: 'postIds', + label: '岗位', + component: 'ApiSelect', + componentProps: { + api: getSimplePostList, + labelField: 'name', + valueField: 'id', + multiple: true, + placeholder: '请选择岗位', + }, + }, + { + fieldName: 'email', + label: '邮箱', + component: 'Input', + rules: z.string().email('邮箱格式不正确').or(z.literal('')).optional(), + componentProps: { + placeholder: '请输入邮箱', + }, + }, + { + fieldName: 'mobile', + label: '手机号码', + component: 'Input', + componentProps: { + placeholder: '请输入手机号码', + }, + }, + { + fieldName: 'sex', + label: '用户性别', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + }, + rules: z.number().default(1), + }, + { + fieldName: 'status', + label: '用户状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 重置密码的表单 */ +export function useResetPasswordFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'VbenInputPassword', + componentProps: { + passwordStrength: true, + placeholder: '请输入新密码', + }, + dependencies: { + rules(values) { + return z + .string({ message: '请输入新密码' }) + .min(5, '密码长度不能少于 5 个字符') + .max(20, '密码长度不能超过 20 个字符') + .refine( + (value) => value !== values.oldPassword, + '新旧密码不能相同', + ); + }, + triggerFields: ['newPassword', 'oldPassword'], + }, + fieldName: 'newPassword', + label: '新密码', + rules: 'required', + }, + { + component: 'VbenInputPassword', + componentProps: { + passwordStrength: true, + placeholder: $t('authentication.confirmPassword'), + }, + dependencies: { + rules(values) { + return z + .string({ message: '请输入确认密码' }) + .min(5, '密码长度不能少于 5 个字符') + .max(20, '密码长度不能超过 20 个字符') + .refine( + (value) => value === values.newPassword, + '新密码和确认密码不一致', + ); + }, + triggerFields: ['newPassword', 'confirmPassword'], + }, + fieldName: 'confirmPassword', + label: '确认密码', + rules: 'required', + }, + ]; +} + +/** 分配角色的表单 */ +export function useAssignRoleFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'username', + label: '用户名称', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'nickname', + label: '用户昵称', + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'roleIds', + label: '角色', + component: 'ApiSelect', + componentProps: { + api: getSimpleRoleList, + labelField: 'name', + valueField: 'id', + multiple: true, + placeholder: '请选择角色', + }, + }, + ]; +} + +/** 用户导入的表单 */ +export function useImportFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'file', + label: '用户数据', + component: 'Upload', + rules: 'required', + help: '仅允许导入 xls、xlsx 格式文件', + }, + { + fieldName: 'updateSupport', + label: '是否覆盖', + component: 'Switch', + componentProps: { + checkedChildren: '是', + unCheckedChildren: '否', + }, + rules: z.boolean().default(false), + help: '是否更新已经存在的用户数据', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'username', + label: '用户名称', + component: 'Input', + componentProps: { + placeholder: '请输入用户名称', + clearable: true, + }, + }, + { + fieldName: 'mobile', + label: '手机号码', + component: 'Input', + componentProps: { + placeholder: '请输入手机号码', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onStatusChange?: ( + newStatus: number, + row: SystemUserApi.User, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '用户编号', + minWidth: 100, + }, + { + field: 'username', + title: '用户名称', + minWidth: 120, + }, + { + field: 'nickname', + title: '用户昵称', + minWidth: 120, + }, + { + field: 'deptName', + title: '部门', + minWidth: 120, + }, + { + field: 'mobile', + title: '手机号码', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + align: 'center', + cellRender: { + attrs: { beforeChange: onStatusChange }, + name: 'CellSwitch', + props: { + activeValue: CommonStatusEnum.ENABLE, + inactiveValue: CommonStatusEnum.DISABLE, + }, + }, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/system/user/index.vue b/apps/web-ele/src/views/system/user/index.vue new file mode 100644 index 0000000..e56a898 --- /dev/null +++ b/apps/web-ele/src/views/system/user/index.vue @@ -0,0 +1,296 @@ + + + diff --git a/apps/web-ele/src/views/system/user/modules/assign-role-form.vue b/apps/web-ele/src/views/system/user/modules/assign-role-form.vue new file mode 100644 index 0000000..9d3e0d8 --- /dev/null +++ b/apps/web-ele/src/views/system/user/modules/assign-role-form.vue @@ -0,0 +1,78 @@ + + + diff --git a/apps/web-ele/src/views/system/user/modules/dept-tree.vue b/apps/web-ele/src/views/system/user/modules/dept-tree.vue new file mode 100644 index 0000000..9c4d5a8 --- /dev/null +++ b/apps/web-ele/src/views/system/user/modules/dept-tree.vue @@ -0,0 +1,81 @@ + + + diff --git a/apps/web-ele/src/views/system/user/modules/form.vue b/apps/web-ele/src/views/system/user/modules/form.vue new file mode 100644 index 0000000..e20eb82 --- /dev/null +++ b/apps/web-ele/src/views/system/user/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/system/user/modules/import-form.vue b/apps/web-ele/src/views/system/user/modules/import-form.vue new file mode 100644 index 0000000..6222bf4 --- /dev/null +++ b/apps/web-ele/src/views/system/user/modules/import-form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/system/user/modules/reset-password-form.vue b/apps/web-ele/src/views/system/user/modules/reset-password-form.vue new file mode 100644 index 0000000..bd6ef27 --- /dev/null +++ b/apps/web-ele/src/views/system/user/modules/reset-password-form.vue @@ -0,0 +1,66 @@ + + + diff --git a/apps/web-ele/tailwind.config.mjs b/apps/web-ele/tailwind.config.mjs new file mode 100644 index 0000000..f17f556 --- /dev/null +++ b/apps/web-ele/tailwind.config.mjs @@ -0,0 +1 @@ +export { default } from '@vben/tailwind-config'; diff --git a/apps/web-ele/tsconfig.json b/apps/web-ele/tsconfig.json new file mode 100644 index 0000000..33f79aa --- /dev/null +++ b/apps/web-ele/tsconfig.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web-app.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "#/*": ["./src/*"] + }, + "allowJs": true + }, + "references": [{ "path": "./tsconfig.node.json" }], + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] +} diff --git a/apps/web-ele/tsconfig.node.json b/apps/web-ele/tsconfig.node.json new file mode 100644 index 0000000..c2f0d86 --- /dev/null +++ b/apps/web-ele/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/node.json", + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "noEmit": false + }, + "include": ["vite.config.mts"] +} diff --git a/apps/web-ele/vite.config.mts b/apps/web-ele/vite.config.mts new file mode 100644 index 0000000..8a36bcb --- /dev/null +++ b/apps/web-ele/vite.config.mts @@ -0,0 +1,27 @@ +import { defineConfig } from '@vben/vite-config'; + +import ElementPlus from 'unplugin-element-plus/vite'; + +export default defineConfig(async () => { + return { + application: {}, + vite: { + plugins: [ + ElementPlus({ + format: 'esm', + }), + ], + server: { + proxy: { + '/admin-api': { + changeOrigin: true, + rewrite: (path) => path.replace(/^\/admin-api/, ''), + // mock代理目标地址 + target: 'http://localhost:48080/admin-api', + ws: true, + }, + }, + }, + }, + }; +}); diff --git a/apps/web-naive/.env b/apps/web-naive/.env new file mode 100644 index 0000000..063ed61 --- /dev/null +++ b/apps/web-naive/.env @@ -0,0 +1,35 @@ +# 应用标题 +VITE_APP_TITLE=芋道管理系统 + +# 应用命名空间,用于缓存、store等功能的前缀,确保隔离 +VITE_APP_NAMESPACE=yudao-vben-naive + +# 对store进行加密的密钥,在将store持久化到localStorage时会使用该密钥进行加密 +VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key + +# 是否开启模拟数据 +VITE_NITRO_MOCK=false + +# 租户开关 +VITE_APP_TENANT_ENABLE=true + +# 验证码的开关 +VITE_APP_CAPTCHA_ENABLE=false + +# 文档地址的开关 +VITE_APP_DOCALERT_ENABLE=true + +# 百度统计 +VITE_APP_BAIDU_CODE = e98f2eab6ceb8688bc6d8fc5332ff093 + +# GoView域名 +VITE_GOVIEW_URL='http://127.0.0.1:3000' + +# API 加解密 +VITE_APP_API_ENCRYPT_ENABLE = true +VITE_APP_API_ENCRYPT_HEADER = X-Api-Encrypt +VITE_APP_API_ENCRYPT_ALGORITHM = AES +VITE_APP_API_ENCRYPT_REQUEST_KEY = 52549111389893486934626385991395 +VITE_APP_API_ENCRYPT_RESPONSE_KEY = 96103715984234343991809655248883 +# VITE_APP_API_ENCRYPT_REQUEST_KEY = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCls2rIpnGdYnLFgz1XU13GbNQ5DloyPpvW00FPGjqn5Z6JpK+kDtVlnkhwR87iRrE5Vf2WNqRX6vzbLSgveIQY8e8oqGCb829myjf1MuI+ZzN4ghf/7tEYhZJGPI9AbfxFqBUzm+kR3/HByAI22GLT96WM26QiMK8n3tIP/yiLswIDAQAB +# VITE_APP_API_ENCRYPT_RESPONSE_KEY = MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOH8IfIFxL/MR9XIg1UDv5z1fGXQI93E8wrU4iPFovL/sEt9uSgSkjyidC2O7N+m7EKtoN6b1u7cEwXSkwf3kfK0jdWLSQaNpX5YshqXCBzbDfugDaxuyYrNA4/tIMs7mzZAk0APuRXB35Dmupou7Yw7TFW/7QhQmGfzeEKULQvnAgMBAAECgYAw8LqlQGyQoPv5p3gRxEMOCfgL0JzD3XBJKztiRd35RDh40Nx1ejgjW4dPioFwGiVWd2W8cAGHLzALdcQT2KDJh+T/tsd4SPmI6uSBBK6Ff2DkO+kFFcuYvfclQQKqxma5CaZOSqhgenacmgTMFeg2eKlY3symV6JlFNu/IKU42QJBAOhxAK/Eq3e61aYQV2JSguhMR3b8NXJJRroRs/QHEanksJtl+M+2qhkC9nQVXBmBkndnkU/l2tYcHfSBlAyFySMCQQD445tgm/J2b6qMQmuUGQAYDN8FIkHjeKmha+l/fv0igWm8NDlBAem91lNDIPBUzHL1X1+pcts5bjmq99YdOnhtAkAg2J8dN3B3idpZDiQbC8fd5bGPmdI/pSUudAP27uzLEjr2qrE/QPPGdwm2m7IZFJtK7kK1hKio6u48t/bg0iL7AkEAuUUs94h+v702Fnym+jJ2CHEkXvz2US8UDs52nWrZYiM1o1y4tfSHm8H8bv8JCAa9GHyriEawfBraILOmllFdLQJAQSRZy4wmlaG48MhVXodB85X+VZ9krGXZ2TLhz7kz9iuToy53l9jTkESt6L5BfBDCVdIwcXLYgK+8KFdHN5W7HQ== diff --git a/apps/web-naive/.env.analyze b/apps/web-naive/.env.analyze new file mode 100644 index 0000000..ffafa8d --- /dev/null +++ b/apps/web-naive/.env.analyze @@ -0,0 +1,7 @@ +# public path +VITE_BASE=/ + +# Basic interface address SPA +VITE_GLOB_API_URL=/api + +VITE_VISUALIZER=true diff --git a/apps/web-naive/.env.development b/apps/web-naive/.env.development new file mode 100644 index 0000000..0cc3410 --- /dev/null +++ b/apps/web-naive/.env.development @@ -0,0 +1,21 @@ +# 端口号 +VITE_PORT=5888 + +VITE_BASE=/ + +# 请求路径 +VITE_BASE_URL=http://127.0.0.1:48080 +# 接口地址 +VITE_GLOB_API_URL=/admin-api +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务 +VITE_UPLOAD_TYPE=server +# 是否打开 devtools,true 为打开,false 为关闭 +VITE_DEVTOOLS=false + +# 是否注入全局loading +VITE_INJECT_APP_LOADING=true + +# 默认登录用户名 +VITE_APP_DEFAULT_USERNAME=admin +# 默认登录密码 +VITE_APP_DEFAULT_PASSWORD=admin123 diff --git a/apps/web-naive/.env.production b/apps/web-naive/.env.production new file mode 100644 index 0000000..910fd64 --- /dev/null +++ b/apps/web-naive/.env.production @@ -0,0 +1,23 @@ +VITE_BASE=/ + +# 请求路径 +VITE_BASE_URL=http://127.0.0.1:48080 +# 接口地址 +VITE_GLOB_API_URL=http://127.0.0.1:48080/admin-api +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务 +VITE_UPLOAD_TYPE=server + +# 是否开启压缩,可以设置为 none, brotli, gzip +VITE_COMPRESS=none + +# 是否开启 PWA +VITE_PWA=false + +# vue-router 的模式 +VITE_ROUTER_HISTORY=hash + +# 是否注入全局loading +VITE_INJECT_APP_LOADING=true + +# 打包后是否生成dist.zip +VITE_ARCHIVER=true diff --git a/apps/web-naive/index.html b/apps/web-naive/index.html new file mode 100644 index 0000000..7ea6384 --- /dev/null +++ b/apps/web-naive/index.html @@ -0,0 +1,35 @@ + + + + + + + + + + + + <%= VITE_APP_TITLE %> + + + + +
    + + + diff --git a/apps/web-naive/package.json b/apps/web-naive/package.json new file mode 100644 index 0000000..1f11799 --- /dev/null +++ b/apps/web-naive/package.json @@ -0,0 +1,51 @@ +{ + "name": "@vben/web-naive", + "version": "5.6.0", + "homepage": "https://vben.pro", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "apps/web-naive" + }, + "license": "MIT", + "author": { + "name": "vben", + "email": "ann.vben@gmail.com", + "url": "https://github.com/anncwb" + }, + "type": "module", + "scripts": { + "build": "pnpm vite build --mode production", + "build:analyze": "pnpm vite build --mode analyze", + "dev": "pnpm vite --mode development", + "preview": "vite preview", + "typecheck": "vue-tsc --noEmit --skipLibCheck" + }, + "imports": { + "#/*": "./src/*" + }, + "dependencies": { + "@form-create/naive-ui": "catalog:", + "@vben/access": "workspace:*", + "@vben/common-ui": "workspace:*", + "@vben/constants": "workspace:*", + "@vben/hooks": "workspace:*", + "@vben/icons": "workspace:*", + "@vben/layouts": "workspace:*", + "@vben/locales": "workspace:*", + "@vben/plugins": "workspace:*", + "@vben/preferences": "workspace:*", + "@vben/request": "workspace:*", + "@vben/stores": "workspace:*", + "@vben/styles": "workspace:*", + "@vben/types": "workspace:*", + "@vben/utils": "workspace:*", + "@vueuse/core": "catalog:", + "dayjs": "catalog:", + "naive-ui": "catalog:", + "pinia": "catalog:", + "vue": "catalog:", + "vue-router": "catalog:" + } +} diff --git a/apps/web-naive/postcss.config.mjs b/apps/web-naive/postcss.config.mjs new file mode 100644 index 0000000..3d80704 --- /dev/null +++ b/apps/web-naive/postcss.config.mjs @@ -0,0 +1 @@ +export { default } from '@vben/tailwind-config/postcss'; diff --git a/apps/web-naive/public/favicon.ico b/apps/web-naive/public/favicon.ico new file mode 100644 index 0000000..fcf9818 Binary files /dev/null and b/apps/web-naive/public/favicon.ico differ diff --git a/apps/web-naive/public/wx-xingyu.png b/apps/web-naive/public/wx-xingyu.png new file mode 100644 index 0000000..da2e45a Binary files /dev/null and b/apps/web-naive/public/wx-xingyu.png differ diff --git a/apps/web-naive/src/adapter/component/index.ts b/apps/web-naive/src/adapter/component/index.ts new file mode 100644 index 0000000..700e7c0 --- /dev/null +++ b/apps/web-naive/src/adapter/component/index.ts @@ -0,0 +1,241 @@ +/** + * 通用组件共同的使用的基础组件,原先放在 adapter/form 内部,限制了使用范围,这里提取出来,方便其他地方使用 + * 可用于 vben-form、vben-modal、vben-drawer 等组件使用, + */ + +import type { Component } from 'vue'; + +import type { BaseFormComponentType } from '@vben/common-ui'; +import type { Recordable } from '@vben/types'; + +import { defineAsyncComponent, defineComponent, h, ref } from 'vue'; + +import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui'; +import { $t } from '@vben/locales'; + +import { message } from '#/adapter/naive'; +import { FileUpload, ImageUpload } from '#/components/upload'; + +const NAutoComplete = defineAsyncComponent(() => + import('naive-ui/es/auto-complete').then((res) => res.NAutoComplete), +); +const NButton = defineAsyncComponent(() => + import('naive-ui/es/button').then((res) => res.NButton), +); +const NCheckbox = defineAsyncComponent(() => + import('naive-ui/es/checkbox').then((res) => res.NCheckbox), +); +const NCheckboxGroup = defineAsyncComponent(() => + import('naive-ui/es/checkbox').then((res) => res.NCheckboxGroup), +); +const NDatePicker = defineAsyncComponent(() => + import('naive-ui/es/date-picker').then((res) => res.NDatePicker), +); +const NDivider = defineAsyncComponent(() => + import('naive-ui/es/divider').then((res) => res.NDivider), +); +const NInput = defineAsyncComponent(() => + import('naive-ui/es/input').then((res) => res.NInput), +); +const NInputNumber = defineAsyncComponent(() => + import('naive-ui/es/input-number').then((res) => res.NInputNumber), +); +const NRadio = defineAsyncComponent(() => + import('naive-ui/es/radio').then((res) => res.NRadio), +); +const NRadioButton = defineAsyncComponent(() => + import('naive-ui/es/radio').then((res) => res.NRadioButton), +); +const NRadioGroup = defineAsyncComponent(() => + import('naive-ui/es/radio').then((res) => res.NRadioGroup), +); +const NSelect = defineAsyncComponent(() => + import('naive-ui/es/select').then((res) => res.NSelect), +); +const NSpace = defineAsyncComponent(() => + import('naive-ui/es/space').then((res) => res.NSpace), +); +const NSwitch = defineAsyncComponent(() => + import('naive-ui/es/switch').then((res) => res.NSwitch), +); +const NTimePicker = defineAsyncComponent(() => + import('naive-ui/es/time-picker').then((res) => res.NTimePicker), +); +const NTreeSelect = defineAsyncComponent(() => + import('naive-ui/es/tree-select').then((res) => res.NTreeSelect), +); +const NUpload = defineAsyncComponent(() => + import('naive-ui/es/upload').then((res) => res.NUpload), +); + +const withDefaultPlaceholder = ( + component: T, + type: 'input' | 'select', + componentProps: Recordable = {}, +) => { + return defineComponent({ + name: component.name, + inheritAttrs: false, + setup: (props: any, { attrs, expose, slots }) => { + const placeholder = + props?.placeholder || + attrs?.placeholder || + $t(`ui.placeholder.${type}`); + // 透传组件暴露的方法 + const innerRef = ref(); + expose( + new Proxy( + {}, + { + get: (_target, key) => innerRef.value?.[key], + has: (_target, key) => key in (innerRef.value || {}), + }, + ), + ); + return () => + h( + component, + { ...componentProps, placeholder, ...props, ...attrs, ref: innerRef }, + slots, + ); + }, + }); +}; + +// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 +export type ComponentType = + | 'ApiSelect' + | 'ApiTreeSelect' + | 'AutoComplete' + | 'Checkbox' + | 'CheckboxGroup' + | 'DatePicker' + | 'Divider' + | 'FileUpload' + | 'IconPicker' + | 'ImageUpload' + | 'Input' + | 'InputNumber' + | 'RadioGroup' + | 'Select' + | 'Space' + | 'Switch' + | 'TimePicker' + | 'TreeSelect' + | 'Upload' + | BaseFormComponentType; + +async function initComponentAdapter() { + const components: Partial> = { + // 如果你的组件体积比较大,可以使用异步加载 + // Button: () => + // import('xxx').then((res) => res.Button), + + ApiSelect: withDefaultPlaceholder( + { + ...ApiComponent, + name: 'ApiSelect', + }, + 'select', + { + component: NSelect, + modelPropName: 'value', + }, + ), + ApiTreeSelect: withDefaultPlaceholder( + { + ...ApiComponent, + name: 'ApiTreeSelect', + }, + 'select', + { + component: NTreeSelect, + nodeKey: 'value', + loadingSlot: 'arrow', + keyField: 'value', + modelPropName: 'value', + optionsPropName: 'options', + visibleEvent: 'onVisibleChange', + }, + ), + AutoComplete: NAutoComplete, + Checkbox: NCheckbox, + CheckboxGroup: (props, { attrs, slots }) => { + let defaultSlot; + if (Reflect.has(slots, 'default')) { + defaultSlot = slots.default; + } else { + const { options } = attrs; + if (Array.isArray(options)) { + defaultSlot = () => options.map((option) => h(NCheckbox, option)); + } + } + return h( + NCheckboxGroup, + { ...props, ...attrs }, + { default: defaultSlot }, + ); + }, + DatePicker: NDatePicker, + // 自定义默认按钮 + DefaultButton: (props, { attrs, slots }) => { + return h(NButton, { ...props, attrs, type: 'default' }, slots); + }, + // 自定义主要按钮 + PrimaryButton: (props, { attrs, slots }) => { + return h(NButton, { ...props, attrs, type: 'primary' }, slots); + }, + Divider: NDivider, + IconPicker: withDefaultPlaceholder(IconPicker, 'select', { + iconSlot: 'suffix', + inputComponent: NInput, + }), + Input: withDefaultPlaceholder(NInput, 'input'), + InputNumber: withDefaultPlaceholder(NInputNumber, 'input'), + RadioGroup: (props, { attrs, slots }) => { + let defaultSlot; + if (Reflect.has(slots, 'default')) { + defaultSlot = slots.default; + } else { + const { options } = attrs; + if (Array.isArray(options)) { + defaultSlot = () => + options.map((option) => + h(attrs.isButton ? NRadioButton : NRadio, option), + ); + } + } + const groupRender = h( + NRadioGroup, + { ...props, ...attrs }, + { default: defaultSlot }, + ); + return attrs.isButton + ? h(NSpace, { vertical: true }, () => groupRender) + : groupRender; + }, + Select: withDefaultPlaceholder(NSelect, 'select'), + Space: NSpace, + Switch: NSwitch, + TimePicker: NTimePicker, + TreeSelect: withDefaultPlaceholder(NTreeSelect, 'select'), + Upload: NUpload, + FileUpload, + ImageUpload, + }; + + // 将组件注册到全局共享状态中 + globalShareState.setComponents(components); + + // 定义全局共享状态中的消息提示 + globalShareState.defineMessage({ + // 复制成功消息提示 + copyPreferencesSuccess: (title, content) => { + message.success(content || title, { + duration: 0, + }); + }, + }); +} + +export { initComponentAdapter }; diff --git a/apps/web-naive/src/adapter/form.ts b/apps/web-naive/src/adapter/form.ts new file mode 100644 index 0000000..6d6ea00 --- /dev/null +++ b/apps/web-naive/src/adapter/form.ts @@ -0,0 +1,66 @@ +import type { + VbenFormSchema as FormSchema, + VbenFormProps, +} from '@vben/common-ui'; + +import type { ComponentType } from './component'; + +import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; +import { $t } from '@vben/locales'; +import { isMobile } from '@vben/utils'; + +async function initSetupVbenForm() { + setupVbenForm({ + config: { + // naive-ui组件的空值为null,不能是undefined,否则重置表单时不生效 + emptyStateValue: null, + baseModelPropName: 'value', + modelPropNameMap: { + Checkbox: 'checked', + Radio: 'checked', + Upload: 'fileList', + DatePicker: 'formatted-value', + }, + }, + defineRules: { + required: (value, _params, ctx) => { + if (value === undefined || value === null || value.length === 0) { + return $t('ui.formRules.required', [ctx.label]); + } + return true; + }, + selectRequired: (value, _params, ctx) => { + if (value === undefined || value === null) { + return $t('ui.formRules.selectRequired', [ctx.label]); + } + return true; + }, + // 手机号非必填 + mobile: (value, _params, ctx) => { + if (value === undefined || value === null || value.length === 0) { + return true; + } else if (!isMobile(value)) { + return $t('ui.formRules.mobile', [ctx.label]); + } + return true; + }, + // 手机号必填 + mobileRequired: (value, _params, ctx) => { + if (value === undefined || value === null || value.length === 0) { + return $t('ui.formRules.required', [ctx.label]); + } + if (!isMobile(value)) { + return $t('ui.formRules.mobile', [ctx.label]); + } + return true; + }, + }, + }); +} + +const useVbenForm = useForm; + +export { initSetupVbenForm, useVbenForm, z }; + +export type VbenFormSchema = FormSchema; +export type { VbenFormProps }; diff --git a/apps/web-naive/src/adapter/naive.ts b/apps/web-naive/src/adapter/naive.ts new file mode 100644 index 0000000..1eb7b7b --- /dev/null +++ b/apps/web-naive/src/adapter/naive.ts @@ -0,0 +1,25 @@ +import { computed } from 'vue'; + +import { preferences } from '@vben/preferences'; +import '@vben/styles'; + +import { createDiscreteApi, darkTheme, lightTheme } from 'naive-ui'; + +const themeOverridesProviderProps = computed(() => ({ + themeOverrides: preferences.theme.mode === 'light' ? lightTheme : darkTheme, +})); + +const themeProviderProps = computed(() => ({ + theme: preferences.theme.mode === 'light' ? lightTheme : darkTheme, +})); + +export const { dialog, loadingBar, message, modal, notification } = + createDiscreteApi( + ['message', 'dialog', 'notification', 'loadingBar', 'modal'], + { + configProviderProps: themeProviderProps, + loadingBarProviderProps: themeOverridesProviderProps, + messageProviderProps: themeOverridesProviderProps, + notificationProviderProps: themeOverridesProviderProps, + }, + ); diff --git a/apps/web-naive/src/adapter/vxe-table.ts b/apps/web-naive/src/adapter/vxe-table.ts new file mode 100644 index 0000000..95f69e6 --- /dev/null +++ b/apps/web-naive/src/adapter/vxe-table.ts @@ -0,0 +1,220 @@ +import type { VxeTableGridOptions } from '@vben/plugins/vxe-table'; + +import { h } from 'vue'; + +import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table'; +import { + erpCountInputFormatter, + erpNumberFormatter, + fenToYuan, + formatFileSize, + formatPast2, +} from '@vben/utils'; + +import { NButton, NImage, NImageGroup, NSwitch, NTag } from 'naive-ui'; + +import { $t } from '#/locales'; + +import DictTag from '../components/dict-tag/dict-tag.vue'; +import { useVbenForm } from './form'; + +setupVbenVxeTable({ + configVxeTable: (vxeUI) => { + vxeUI.setConfig({ + grid: { + align: 'center', + border: false, + columnConfig: { + resizable: true, + }, + minHeight: 180, + formConfig: { + // 全局禁用vxe-table的表单配置,使用formOptions + enabled: false, + }, + toolbarConfig: { + import: false, // 是否导入 + export: false, // 是否导出 + refresh: true, // 是否刷新 + print: false, // 是否打印 + zoom: true, // 是否缩放 + custom: true, // 是否自定义配置 + }, + customConfig: { + mode: 'modal', + }, + proxyConfig: { + autoLoad: true, + response: { + result: 'list', + total: 'total', + }, + showActiveMsg: true, + showResponseMsg: false, + }, + pagerConfig: { + enabled: true, + }, + sortConfig: { + multiple: true, + }, + round: true, + showOverflow: true, + size: 'small', + } as VxeTableGridOptions, + }); + + // 表格配置项可以用 cellRender: { name: 'CellImage' }, + vxeUI.renderer.add('CellImage', { + renderTableDefault(renderOpts, params) { + const { props } = renderOpts; + const { column, row } = params; + return h(NImage, { src: row[column.field], ...props }); + }, + }); + + vxeUI.renderer.add('CellImages', { + renderTableDefault(_renderOpts, params) { + const { column, row } = params; + if (column && column.field && row[column.field]) { + return h(NImageGroup, { srcList: row[column.field] }); + } + return ''; + }, + }); + + // 表格配置项可以用 cellRender: { name: 'CellLink' }, + vxeUI.renderer.add('CellLink', { + renderTableDefault(renderOpts) { + const { props } = renderOpts; + return h( + NButton, + { size: 'small', type: 'primary', quaternary: true }, + { default: () => props?.text }, + ); + }, + }); + + // 表格配置项可以用 cellRender: { name: 'CellTag' }, + vxeUI.renderer.add('CellTag', { + renderTableDefault(renderOpts, params) { + const { props } = renderOpts; + const { column, row } = params; + return h(NTag, { color: props?.color }, () => row[column.field]); + }, + }); + + vxeUI.renderer.add('CellTags', { + renderTableDefault(renderOpts, params) { + const { props } = renderOpts; + const { column, row } = params; + if (!row[column.field] || !Array.isArray(row[column.field])) { + return ''; + } + return h( + 'div', + { class: 'flex items-center justify-center' }, + { + default: () => + row[column.field].map((item: any) => + h(NTag, { color: props?.color }, { default: () => item }), + ), + }, + ); + }, + }); + + // 表格配置项可以用 cellRender: { name: 'CellDict', props:{dictType: ''} }, + vxeUI.renderer.add('CellDict', { + renderTableDefault(renderOpts, params) { + const { props } = renderOpts; + const { column, row } = params; + if (!props) { + return ''; + } + // 使用 DictTag 组件替代原来的实现 + return h(DictTag, { + type: props.type, + value: row[column.field]?.toString(), + }); + }, + }); + + // 表格配置项可以用 cellRender: { name: 'CellSwitch', props: { beforeChange: () => {} } }, + // add by 芋艿:from https://github.com/vbenjs/vue-vben-admin/blob/main/playground/src/adapter/vxe-table.ts#L97-L123 + vxeUI.renderer.add('CellSwitch', { + renderTableDefault({ attrs, props }, { column, row }) { + const loadingKey = `__loading_${column.field}`; + const finallyProps = { + inlinePrompt: true, + checkedValue: 0, + uncheckedValue: 1, + ...props, + value: row[column.field], + loading: row[loadingKey] ?? false, + 'onUpdate:value': onChange, + }; + + async function onChange(newVal: any) { + row[loadingKey] = true; + try { + const result = await attrs?.beforeChange?.(newVal, row); + if (result !== false) { + row[column.field] = newVal; + } + } finally { + row[loadingKey] = false; + } + } + + return h(NSwitch, finallyProps, { + checked: () => h('p', props?.checkedChildren ?? $t('common.enabled')), + unchecked: () => + h('p', props?.uncheckedChildren ?? $t('common.disabled')), + }); + }, + }); + + // 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化 + // vxeUI.formats.add + vxeUI.formats.add('formatPast2', { + tableCellFormatMethod({ cellValue }) { + return formatPast2(cellValue); + }, + }); + + // add by 星语:数量格式化,保留 3 位 + vxeUI.formats.add('formatAmount3', { + tableCellFormatMethod({ cellValue }) { + if (cellValue === null || cellValue === undefined) { + return ''; + } + return erpCountInputFormatter(cellValue); + }, + }); + // add by 星语:数量格式化,保留 2 位 + vxeUI.formats.add('formatAmount2', { + tableCellFormatMethod({ cellValue }, digits = 2) { + return `${erpNumberFormatter(cellValue, digits)}`; + }, + }); + + vxeUI.formats.add('formatFenToYuanAmount', { + tableCellFormatMethod({ cellValue }, digits = 2) { + return `${erpNumberFormatter(fenToYuan(cellValue), digits)}`; + }, + }); + + vxeUI.formats.add('formatFileSize', { + tableCellFormatMethod({ cellValue }, digits = 2) { + return formatFileSize(cellValue, digits); + }, + }); + }, + useVbenForm, +}); + +export { useVbenVxeGrid }; + +export * from '#/components/table-action'; +export type * from '@vben/plugins/vxe-table'; diff --git a/apps/web-naive/src/api/core/auth.ts b/apps/web-naive/src/api/core/auth.ts new file mode 100644 index 0000000..604644a --- /dev/null +++ b/apps/web-naive/src/api/core/auth.ts @@ -0,0 +1,161 @@ +import type { AuthPermissionInfo } from '@vben/types'; + +import { baseRequestClient, requestClient } from '#/api/request'; + +export namespace AuthApi { + /** 登录接口参数 */ + export interface LoginParams { + password?: string; + username?: string; + captchaVerification?: string; + // 绑定社交登录时,需要传递如下参数 + socialType?: number; + socialCode?: string; + socialState?: string; + } + + /** 登录接口返回值 */ + export interface LoginResult { + accessToken: string; + refreshToken: string; + userId: number; + expiresTime: number; + } + + /** 租户信息返回值 */ + export interface TenantResult { + id: number; + name: string; + } + + /** 手机验证码获取接口参数 */ + export interface SmsCodeParams { + mobile: string; + scene: number; + } + + /** 手机验证码登录接口参数 */ + export interface SmsLoginParams { + mobile: string; + code: string; + } + + /** 注册接口参数 */ + export interface RegisterParams { + username: string; + password: string; + captchaVerification: string; + } + + /** 重置密码接口参数 */ + export interface ResetPasswordParams { + password: string; + mobile: string; + code: string; + } + + /** 社交快捷登录接口参数 */ + export interface SocialLoginParams { + type: number; + code: string; + state: string; + } +} + +/** 登录 */ +export async function loginApi(data: AuthApi.LoginParams) { + return requestClient.post('/system/auth/login', data, { + headers: { + isEncrypt: false, + }, + }); +} + +/** 刷新 accessToken */ +export async function refreshTokenApi(refreshToken: string) { + return baseRequestClient.post( + `/system/auth/refresh-token?refreshToken=${refreshToken}`, + ); +} + +/** 退出登录 */ +export async function logoutApi(accessToken: string) { + return baseRequestClient.post( + '/system/auth/logout', + {}, + { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }, + ); +} + +/** 获取权限信息 */ +export async function getAuthPermissionInfoApi() { + return requestClient.get( + '/system/auth/get-permission-info', + ); +} + +/** 获取租户列表 */ +export async function getTenantSimpleList() { + return requestClient.get( + `/system/tenant/simple-list`, + ); +} + +/** 使用租户域名,获得租户信息 */ +export async function getTenantByWebsite(website: string) { + return requestClient.get( + `/system/tenant/get-by-website?website=${website}`, + ); +} + +/** 获取验证码 */ +export async function getCaptcha(data: any) { + return baseRequestClient.post('/system/captcha/get', data); +} + +/** 校验验证码 */ +export async function checkCaptcha(data: any) { + return baseRequestClient.post('/system/captcha/check', data); +} + +/** 获取登录验证码 */ +export async function sendSmsCode(data: AuthApi.SmsCodeParams) { + return requestClient.post('/system/auth/send-sms-code', data); +} + +/** 短信验证码登录 */ +export async function smsLogin(data: AuthApi.SmsLoginParams) { + return requestClient.post('/system/auth/sms-login', data); +} + +/** 注册 */ +export async function register(data: AuthApi.RegisterParams) { + return requestClient.post('/system/auth/register', data); +} + +/** 通过短信重置密码 */ +export async function smsResetPassword(data: AuthApi.ResetPasswordParams) { + return requestClient.post('/system/auth/reset-password', data); +} + +/** 社交授权的跳转 */ +export async function socialAuthRedirect(type: number, redirectUri: string) { + return requestClient.get('/system/auth/social-auth-redirect', { + params: { + type, + redirectUri, + }, + }); +} + +/** 社交快捷登录 */ +export async function socialLogin(data: AuthApi.SocialLoginParams) { + return requestClient.post( + '/system/auth/social-login', + data, + ); +} diff --git a/apps/web-naive/src/api/core/index.ts b/apps/web-naive/src/api/core/index.ts new file mode 100644 index 0000000..269586e --- /dev/null +++ b/apps/web-naive/src/api/core/index.ts @@ -0,0 +1 @@ +export * from './auth'; diff --git a/apps/web-naive/src/api/index.ts b/apps/web-naive/src/api/index.ts new file mode 100644 index 0000000..4b0e041 --- /dev/null +++ b/apps/web-naive/src/api/index.ts @@ -0,0 +1 @@ +export * from './core'; diff --git a/apps/web-naive/src/api/infra/api-access-log/index.ts b/apps/web-naive/src/api/infra/api-access-log/index.ts new file mode 100644 index 0000000..656e380 --- /dev/null +++ b/apps/web-naive/src/api/infra/api-access-log/index.ts @@ -0,0 +1,44 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace InfraApiAccessLogApi { + /** API 访问日志信息 */ + export interface ApiAccessLog { + id: number; + traceId: string; + userId: number; + userType: number; + applicationName: string; + requestMethod: string; + requestParams: string; + responseBody: string; + requestUrl: string; + userIp: string; + userAgent: string; + operateModule: string; + operateName: string; + operateType: number; + beginTime: string; + endTime: string; + duration: number; + resultCode: number; + resultMsg: string; + createTime: string; + } +} + +/** 查询 API 访问日志列表 */ +export function getApiAccessLogPage(params: PageParam) { + return requestClient.get>( + '/infra/api-access-log/page', + { params }, + ); +} + +/** 导出 API 访问日志 */ +export function exportApiAccessLog(params: any) { + return requestClient.download('/infra/api-access-log/export-excel', { + params, + }); +} diff --git a/apps/web-naive/src/api/infra/api-error-log/index.ts b/apps/web-naive/src/api/infra/api-error-log/index.ts new file mode 100644 index 0000000..863f73e --- /dev/null +++ b/apps/web-naive/src/api/infra/api-error-log/index.ts @@ -0,0 +1,55 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace InfraApiErrorLogApi { + /** API 错误日志信息 */ + export interface ApiErrorLog { + id: number; + traceId: string; + userId: number; + userType: number; + applicationName: string; + requestMethod: string; + requestParams: string; + requestUrl: string; + userIp: string; + userAgent: string; + exceptionTime: string; + exceptionName: string; + exceptionMessage: string; + exceptionRootCauseMessage: string; + exceptionStackTrace: string; + exceptionClassName: string; + exceptionFileName: string; + exceptionMethodName: string; + exceptionLineNumber: number; + processUserId: number; + processStatus: number; + processTime: string; + resultCode: number; + createTime: string; + } +} + +/** 查询 API 错误日志列表 */ +export function getApiErrorLogPage(params: PageParam) { + return requestClient.get>( + '/infra/api-error-log/page', + { params }, + ); +} + +/** 更新 API 错误日志的处理状态 */ +export function updateApiErrorLogStatus(id: number, processStatus: number) { + return requestClient.put( + `/infra/api-error-log/update-status?id=${id}&processStatus=${processStatus}`, + ); +} + +/** 导出 API 错误日志 */ +export function exportApiErrorLog(params: any) { + return requestClient.download('/infra/api-error-log/export-excel', { + params, + }); +} diff --git a/apps/web-naive/src/api/infra/codegen/index.ts b/apps/web-naive/src/api/infra/codegen/index.ts new file mode 100644 index 0000000..992d41d --- /dev/null +++ b/apps/web-naive/src/api/infra/codegen/index.ts @@ -0,0 +1,168 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace InfraCodegenApi { + /** 代码生成表定义 */ + export interface CodegenTable { + id: number; + tableId: number; + isParentMenuIdValid: boolean; + dataSourceConfigId: number; + scene: number; + tableName: string; + tableComment: string; + remark: string; + moduleName: string; + businessName: string; + className: string; + classComment: string; + author: string; + createTime: Date; + updateTime: Date; + templateType: number; + parentMenuId: number; + } + + /** 代码生成字段定义 */ + export interface CodegenColumn { + id: number; + tableId: number; + columnName: string; + dataType: string; + columnComment: string; + nullable: number; + primaryKey: number; + ordinalPosition: number; + javaType: string; + javaField: string; + dictType: string; + example: string; + createOperation: number; + updateOperation: number; + listOperation: number; + listOperationCondition: string; + listOperationResult: number; + htmlType: string; + } + + /** 数据库表定义 */ + export interface DatabaseTable { + name: string; + comment: string; + } + + /** 代码生成详情 */ + export interface CodegenDetail { + table: CodegenTable; + columns: CodegenColumn[]; + } + + /** 代码预览 */ + export interface CodegenPreview { + filePath: string; + code: string; + } + + /** 更新代码生成请求 */ + export interface CodegenUpdateReqVO { + table: any | CodegenTable; + columns: CodegenColumn[]; + } + + /** 创建代码生成请求 */ + export interface CodegenCreateListReqVO { + dataSourceConfigId?: number; + tableNames: string[]; + } +} + +/** 查询列表代码生成表定义 */ +export function getCodegenTableList(dataSourceConfigId: number) { + return requestClient.get( + '/infra/codegen/table/list?', + { + params: { dataSourceConfigId }, + }, + ); +} + +/** 查询列表代码生成表定义 */ +export function getCodegenTablePage(params: PageParam) { + return requestClient.get>( + '/infra/codegen/table/page', + { params }, + ); +} + +/** 查询详情代码生成表定义 */ +export function getCodegenTable(tableId: number) { + return requestClient.get( + '/infra/codegen/detail', + { + params: { tableId }, + }, + ); +} + +/** 修改代码生成表定义 */ +export function updateCodegenTable(data: InfraCodegenApi.CodegenUpdateReqVO) { + return requestClient.put('/infra/codegen/update', data); +} + +/** 基于数据库的表结构,同步数据库的表和字段定义 */ +export function syncCodegenFromDB(tableId: number) { + return requestClient.put( + '/infra/codegen/sync-from-db', + {}, + { + params: { tableId }, + }, + ); +} + +/** 预览生成代码 */ +export function previewCodegen(tableId: number) { + return requestClient.get( + '/infra/codegen/preview', + { + params: { tableId }, + }, + ); +} + +/** 下载生成代码 */ +export function downloadCodegen(tableId: number) { + return requestClient.download('/infra/codegen/download', { + params: { tableId }, + }); +} + +/** 获得表定义 */ +export function getSchemaTableList(params: any) { + return requestClient.get( + '/infra/codegen/db/table/list', + { params }, + ); +} + +/** 基于数据库的表结构,创建代码生成器的表定义 */ +export function createCodegenList( + data: InfraCodegenApi.CodegenCreateListReqVO, +) { + return requestClient.post('/infra/codegen/create-list', data); +} + +/** 删除代码生成表定义 */ +export function deleteCodegenTable(tableId: number) { + return requestClient.delete('/infra/codegen/delete', { + params: { tableId }, + }); +} + +/** 批量删除代码生成表定义 */ +export function deleteCodegenTableList(tableIds: number[]) { + return requestClient.delete( + `/infra/codegen/delete-list?tableIds=${tableIds.join(',')}`, + ); +} diff --git a/apps/web-naive/src/api/infra/config/index.ts b/apps/web-naive/src/api/infra/config/index.ts new file mode 100644 index 0000000..aa80bcb --- /dev/null +++ b/apps/web-naive/src/api/infra/config/index.ts @@ -0,0 +1,67 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace InfraConfigApi { + /** 参数配置信息 */ + export interface Config { + id?: number; + category: string; + name: string; + key: string; + value: string; + type: number; + visible: boolean; + remark: string; + createTime?: Date; + } +} + +/** 查询参数列表 */ +export function getConfigPage(params: PageParam) { + return requestClient.get>( + '/infra/config/page', + { + params, + }, + ); +} + +/** 查询参数详情 */ +export function getConfig(id: number) { + return requestClient.get(`/infra/config/get?id=${id}`); +} + +/** 根据参数键名查询参数值 */ +export function getConfigKey(configKey: string) { + return requestClient.get( + `/infra/config/get-value-by-key?key=${configKey}`, + ); +} + +/** 新增参数 */ +export function createConfig(data: InfraConfigApi.Config) { + return requestClient.post('/infra/config/create', data); +} + +/** 修改参数 */ +export function updateConfig(data: InfraConfigApi.Config) { + return requestClient.put('/infra/config/update', data); +} + +/** 删除参数 */ +export function deleteConfig(id: number) { + return requestClient.delete(`/infra/config/delete?id=${id}`); +} + +/** 批量删除参数 */ +export function deleteConfigList(ids: number[]) { + return requestClient.delete(`/infra/config/delete-list?ids=${ids.join(',')}`); +} + +/** 导出参数 */ +export function exportConfig(params: any) { + return requestClient.download('/infra/config/export-excel', { + params, + }); +} diff --git a/apps/web-naive/src/api/infra/data-source-config/index.ts b/apps/web-naive/src/api/infra/data-source-config/index.ts new file mode 100644 index 0000000..81a3b0e --- /dev/null +++ b/apps/web-naive/src/api/infra/data-source-config/index.ts @@ -0,0 +1,53 @@ +import { requestClient } from '#/api/request'; + +export namespace InfraDataSourceConfigApi { + /** 数据源配置信息 */ + export interface DataSourceConfig { + id?: number; + name: string; + url: string; + username: string; + password: string; + createTime?: Date; + } +} + +/** 查询数据源配置列表 */ +export function getDataSourceConfigList() { + return requestClient.get( + '/infra/data-source-config/list', + ); +} + +/** 查询数据源配置详情 */ +export function getDataSourceConfig(id: number) { + return requestClient.get( + `/infra/data-source-config/get?id=${id}`, + ); +} + +/** 新增数据源配置 */ +export function createDataSourceConfig( + data: InfraDataSourceConfigApi.DataSourceConfig, +) { + return requestClient.post('/infra/data-source-config/create', data); +} + +/** 修改数据源配置 */ +export function updateDataSourceConfig( + data: InfraDataSourceConfigApi.DataSourceConfig, +) { + return requestClient.put('/infra/data-source-config/update', data); +} + +/** 删除数据源配置 */ +export function deleteDataSourceConfig(id: number) { + return requestClient.delete(`/infra/data-source-config/delete?id=${id}`); +} + +/** 批量删除数据源配置 */ +export function deleteDataSourceConfigList(ids: number[]) { + return requestClient.delete( + `/infra/data-source-config/delete-list?ids=${ids.join(',')}`, + ); +} diff --git a/apps/web-naive/src/api/infra/demo/demo01/index.ts b/apps/web-naive/src/api/infra/demo/demo01/index.ts new file mode 100644 index 0000000..e180a76 --- /dev/null +++ b/apps/web-naive/src/api/infra/demo/demo01/index.ts @@ -0,0 +1,61 @@ +import type { Dayjs } from 'dayjs'; + +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace Demo01ContactApi { + /** 示例联系人信息 */ + export interface Demo01Contact { + id: number; // 编号 + name?: string; // 名字 + sex?: number; // 性别 + birthday?: Dayjs | string; // 出生年 + description?: string; // 简介 + avatar: string; // 头像 + } +} + +/** 查询示例联系人分页 */ +export function getDemo01ContactPage(params: PageParam) { + return requestClient.get>( + '/infra/demo01-contact/page', + { params }, + ); +} + +/** 查询示例联系人详情 */ +export function getDemo01Contact(id: number) { + return requestClient.get( + `/infra/demo01-contact/get?id=${id}`, + ); +} + +/** 新增示例联系人 */ +export function createDemo01Contact(data: Demo01ContactApi.Demo01Contact) { + return requestClient.post('/infra/demo01-contact/create', data); +} + +/** 修改示例联系人 */ +export function updateDemo01Contact(data: Demo01ContactApi.Demo01Contact) { + return requestClient.put('/infra/demo01-contact/update', data); +} + +/** 删除示例联系人 */ +export function deleteDemo01Contact(id: number) { + return requestClient.delete(`/infra/demo01-contact/delete?id=${id}`); +} + +/** 批量删除示例联系人 */ +export function deleteDemo01ContactList(ids: number[]) { + return requestClient.delete( + `/infra/demo01-contact/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 导出示例联系人 */ +export function exportDemo01Contact(params: any) { + return requestClient.download('/infra/demo01-contact/export-excel', { + params, + }); +} diff --git a/apps/web-naive/src/api/infra/demo/demo02/index.ts b/apps/web-naive/src/api/infra/demo/demo02/index.ts new file mode 100644 index 0000000..b4edd74 --- /dev/null +++ b/apps/web-naive/src/api/infra/demo/demo02/index.ts @@ -0,0 +1,48 @@ +import { requestClient } from '#/api/request'; + +export namespace Demo02CategoryApi { + /** 示例分类信息 */ + export interface Demo02Category { + id: number; // 编号 + name?: string; // 名字 + parentId?: number; // 父级编号 + children?: Demo02Category[]; + } +} + +/** 查询示例分类列表 */ +export function getDemo02CategoryList(params: any) { + return requestClient.get( + '/infra/demo02-category/list', + { params }, + ); +} + +/** 查询示例分类详情 */ +export function getDemo02Category(id: number) { + return requestClient.get( + `/infra/demo02-category/get?id=${id}`, + ); +} + +/** 新增示例分类 */ +export function createDemo02Category(data: Demo02CategoryApi.Demo02Category) { + return requestClient.post('/infra/demo02-category/create', data); +} + +/** 修改示例分类 */ +export function updateDemo02Category(data: Demo02CategoryApi.Demo02Category) { + return requestClient.put('/infra/demo02-category/update', data); +} + +/** 删除示例分类 */ +export function deleteDemo02Category(id: number) { + return requestClient.delete(`/infra/demo02-category/delete?id=${id}`); +} + +/** 导出示例分类 */ +export function exportDemo02Category(params: any) { + return requestClient.download('/infra/demo02-category/export-excel', { + params, + }); +} diff --git a/apps/web-naive/src/api/infra/demo/demo03/erp/index.ts b/apps/web-naive/src/api/infra/demo/demo03/erp/index.ts new file mode 100644 index 0000000..6dc7e35 --- /dev/null +++ b/apps/web-naive/src/api/infra/demo/demo03/erp/index.ts @@ -0,0 +1,168 @@ +import type { Dayjs } from 'dayjs'; + +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace Demo03StudentApi { + /** 学生课程信息 */ + export interface Demo03Course { + id: number; // 编号 + studentId?: number; // 学生编号 + name?: string; // 名字 + score?: number; // 分数 + } + + /** 学生班级信息 */ + export interface Demo03Grade { + id: number; // 编号 + studentId?: number; // 学生编号 + name?: string; // 名字 + teacher?: string; // 班主任 + } + + /** 学生信息 */ + export interface Demo03Student { + id: number; // 编号 + name?: string; // 名字 + sex?: number; // 性别 + birthday?: Dayjs | string; // 出生日期 + description?: string; // 简介 + } +} + +/** 查询学生分页 */ +export function getDemo03StudentPage(params: PageParam) { + return requestClient.get>( + '/infra/demo03-student-erp/page', + { params }, + ); +} + +/** 查询学生详情 */ +export function getDemo03Student(id: number) { + return requestClient.get( + `/infra/demo03-student-erp/get?id=${id}`, + ); +} + +/** 新增学生 */ +export function createDemo03Student(data: Demo03StudentApi.Demo03Student) { + return requestClient.post('/infra/demo03-student-erp/create', data); +} + +/** 修改学生 */ +export function updateDemo03Student(data: Demo03StudentApi.Demo03Student) { + return requestClient.put('/infra/demo03-student-erp/update', data); +} + +/** 删除学生 */ +export function deleteDemo03Student(id: number) { + return requestClient.delete(`/infra/demo03-student-erp/delete?id=${id}`); +} + +/** 批量删除学生 */ +export function deleteDemo03StudentList(ids: number[]) { + return requestClient.delete( + `/infra/demo03-student-erp/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 导出学生 */ +export function exportDemo03Student(params: any) { + return requestClient.download('/infra/demo03-student-erp/export-excel', { + params, + }); +} + +// ==================== 子表(学生课程) ==================== + +/** 获得学生课程分页 */ +export function getDemo03CoursePage(params: PageParam) { + return requestClient.get>( + `/infra/demo03-student-erp/demo03-course/page`, + { params }, + ); +} +/** 新增学生课程 */ +export function createDemo03Course(data: Demo03StudentApi.Demo03Course) { + return requestClient.post( + `/infra/demo03-student-erp/demo03-course/create`, + data, + ); +} + +/** 修改学生课程 */ +export function updateDemo03Course(data: Demo03StudentApi.Demo03Course) { + return requestClient.put( + `/infra/demo03-student-erp/demo03-course/update`, + data, + ); +} + +/** 删除学生课程 */ +export function deleteDemo03Course(id: number) { + return requestClient.delete( + `/infra/demo03-student-erp/demo03-course/delete?id=${id}`, + ); +} + +/** 批量删除学生课程 */ +export function deleteDemo03CourseList(ids: number[]) { + return requestClient.delete( + `/infra/demo03-student-erp/demo03-course/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 获得学生课程 */ +export function getDemo03Course(id: number) { + return requestClient.get( + `/infra/demo03-student-erp/demo03-course/get?id=${id}`, + ); +} + +// ==================== 子表(学生班级) ==================== + +/** 获得学生班级分页 */ +export function getDemo03GradePage(params: PageParam) { + return requestClient.get>( + `/infra/demo03-student-erp/demo03-grade/page`, + { params }, + ); +} +/** 新增学生班级 */ +export function createDemo03Grade(data: Demo03StudentApi.Demo03Grade) { + return requestClient.post( + `/infra/demo03-student-erp/demo03-grade/create`, + data, + ); +} + +/** 修改学生班级 */ +export function updateDemo03Grade(data: Demo03StudentApi.Demo03Grade) { + return requestClient.put( + `/infra/demo03-student-erp/demo03-grade/update`, + data, + ); +} + +/** 删除学生班级 */ +export function deleteDemo03Grade(id: number) { + return requestClient.delete( + `/infra/demo03-student-erp/demo03-grade/delete?id=${id}`, + ); +} + +/** 批量删除学生班级 */ +export function deleteDemo03GradeList(ids: number[]) { + return requestClient.delete( + `/infra/demo03-student-erp/demo03-grade/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 获得学生班级 */ +export function getDemo03Grade(id: number) { + return requestClient.get( + `/infra/demo03-student-erp/demo03-grade/get?id=${id}`, + ); +} diff --git a/apps/web-naive/src/api/infra/demo/demo03/inner/index.ts b/apps/web-naive/src/api/infra/demo/demo03/inner/index.ts new file mode 100644 index 0000000..02bfbcc --- /dev/null +++ b/apps/web-naive/src/api/infra/demo/demo03/inner/index.ts @@ -0,0 +1,96 @@ +import type { Dayjs } from 'dayjs'; + +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace Demo03StudentApi { + /** 学生课程信息 */ + export interface Demo03Course { + id: number; // 编号 + studentId?: number; // 学生编号 + name?: string; // 名字 + score?: number; // 分数 + } + + /** 学生班级信息 */ + export interface Demo03Grade { + id: number; // 编号 + studentId?: number; // 学生编号 + name?: string; // 名字 + teacher?: string; // 班主任 + } + + /** 学生信息 */ + export interface Demo03Student { + id: number; // 编号 + name?: string; // 名字 + sex?: number; // 性别 + birthday?: Dayjs | string; // 出生日期 + description?: string; // 简介 + demo03courses?: Demo03Course[]; + demo03grade?: Demo03Grade; + } +} + +/** 查询学生分页 */ +export function getDemo03StudentPage(params: PageParam) { + return requestClient.get>( + '/infra/demo03-student-inner/page', + { params }, + ); +} + +/** 查询学生详情 */ +export function getDemo03Student(id: number) { + return requestClient.get( + `/infra/demo03-student-inner/get?id=${id}`, + ); +} + +/** 新增学生 */ +export function createDemo03Student(data: Demo03StudentApi.Demo03Student) { + return requestClient.post('/infra/demo03-student-inner/create', data); +} + +/** 修改学生 */ +export function updateDemo03Student(data: Demo03StudentApi.Demo03Student) { + return requestClient.put('/infra/demo03-student-inner/update', data); +} + +/** 删除学生 */ +export function deleteDemo03Student(id: number) { + return requestClient.delete(`/infra/demo03-student-inner/delete?id=${id}`); +} + +/** 批量删除学生 */ +export function deleteDemo03StudentList(ids: number[]) { + return requestClient.delete( + `/infra/demo03-student-inner/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 导出学生 */ +export function exportDemo03Student(params: any) { + return requestClient.download('/infra/demo03-student-inner/export-excel', { + params, + }); +} + +// ==================== 子表(学生课程) ==================== + +/** 获得学生课程列表 */ +export function getDemo03CourseListByStudentId(studentId: number) { + return requestClient.get( + `/infra/demo03-student-inner/demo03-course/list-by-student-id?studentId=${studentId}`, + ); +} + +// ==================== 子表(学生班级) ==================== + +/** 获得学生班级 */ +export function getDemo03GradeByStudentId(studentId: number) { + return requestClient.get( + `/infra/demo03-student-inner/demo03-grade/get-by-student-id?studentId=${studentId}`, + ); +} diff --git a/apps/web-naive/src/api/infra/demo/demo03/normal/index.ts b/apps/web-naive/src/api/infra/demo/demo03/normal/index.ts new file mode 100644 index 0000000..2a085a1 --- /dev/null +++ b/apps/web-naive/src/api/infra/demo/demo03/normal/index.ts @@ -0,0 +1,96 @@ +import type { Dayjs } from 'dayjs'; + +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace Demo03StudentApi { + /** 学生课程信息 */ + export interface Demo03Course { + id: number; // 编号 + studentId?: number; // 学生编号 + name?: string; // 名字 + score?: number; // 分数 + } + + /** 学生班级信息 */ + export interface Demo03Grade { + id: number; // 编号 + studentId?: number; // 学生编号 + name?: string; // 名字 + teacher?: string; // 班主任 + } + + /** 学生信息 */ + export interface Demo03Student { + id: number; // 编号 + name?: string; // 名字 + sex?: number; // 性别 + birthday?: Dayjs | string; // 出生日期 + description?: string; // 简介 + demo03courses?: Demo03Course[]; + demo03grade?: Demo03Grade; + } +} + +/** 查询学生分页 */ +export function getDemo03StudentPage(params: PageParam) { + return requestClient.get>( + '/infra/demo03-student-normal/page', + { params }, + ); +} + +/** 查询学生详情 */ +export function getDemo03Student(id: number) { + return requestClient.get( + `/infra/demo03-student-normal/get?id=${id}`, + ); +} + +/** 新增学生 */ +export function createDemo03Student(data: Demo03StudentApi.Demo03Student) { + return requestClient.post('/infra/demo03-student-normal/create', data); +} + +/** 修改学生 */ +export function updateDemo03Student(data: Demo03StudentApi.Demo03Student) { + return requestClient.put('/infra/demo03-student-normal/update', data); +} + +/** 删除学生 */ +export function deleteDemo03Student(id: number) { + return requestClient.delete(`/infra/demo03-student-normal/delete?id=${id}`); +} + +/** 批量删除学生 */ +export function deleteDemo03StudentList(ids: number[]) { + return requestClient.delete( + `/infra/demo03-student-normal/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 导出学生 */ +export function exportDemo03Student(params: any) { + return requestClient.download('/infra/demo03-student-normal/export-excel', { + params, + }); +} + +// ==================== 子表(学生课程) ==================== + +/** 获得学生课程列表 */ +export function getDemo03CourseListByStudentId(studentId: number) { + return requestClient.get( + `/infra/demo03-student-normal/demo03-course/list-by-student-id?studentId=${studentId}`, + ); +} + +// ==================== 子表(学生班级) ==================== + +/** 获得学生班级 */ +export function getDemo03GradeByStudentId(studentId: number) { + return requestClient.get( + `/infra/demo03-student-normal/demo03-grade/get-by-student-id?studentId=${studentId}`, + ); +} diff --git a/apps/web-naive/src/api/infra/file-config/index.ts b/apps/web-naive/src/api/infra/file-config/index.ts new file mode 100644 index 0000000..3b1e82e --- /dev/null +++ b/apps/web-naive/src/api/infra/file-config/index.ts @@ -0,0 +1,84 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace InfraFileConfigApi { + /** 文件客户端配置 */ + export interface FileClientConfig { + basePath: string; + host?: string; + port?: number; + username?: string; + password?: string; + mode?: string; + endpoint?: string; + bucket?: string; + accessKey?: string; + accessSecret?: string; + pathStyle?: boolean; + enablePublicAccess?: boolean; + region?: string; + domain: string; + } + + /** 文件配置信息 */ + export interface FileConfig { + id?: number; + name: string; + storage?: number; + master: boolean; + visible: boolean; + config: FileClientConfig; + remark: string; + createTime?: Date; + } +} + +/** 查询文件配置列表 */ +export function getFileConfigPage(params: PageParam) { + return requestClient.get>( + '/infra/file-config/page', + { + params, + }, + ); +} + +/** 查询文件配置详情 */ +export function getFileConfig(id: number) { + return requestClient.get( + `/infra/file-config/get?id=${id}`, + ); +} + +/** 更新文件配置为主配置 */ +export function updateFileConfigMaster(id: number) { + return requestClient.put(`/infra/file-config/update-master?id=${id}`); +} + +/** 新增文件配置 */ +export function createFileConfig(data: InfraFileConfigApi.FileConfig) { + return requestClient.post('/infra/file-config/create', data); +} + +/** 修改文件配置 */ +export function updateFileConfig(data: InfraFileConfigApi.FileConfig) { + return requestClient.put('/infra/file-config/update', data); +} + +/** 删除文件配置 */ +export function deleteFileConfig(id: number) { + return requestClient.delete(`/infra/file-config/delete?id=${id}`); +} + +/** 批量删除文件配置 */ +export function deleteFileConfigList(ids: number[]) { + return requestClient.delete( + `/infra/file-config/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 测试文件配置 */ +export function testFileConfig(id: number) { + return requestClient.get(`/infra/file-config/test?id=${id}`); +} diff --git a/apps/web-naive/src/api/infra/file/index.ts b/apps/web-naive/src/api/infra/file/index.ts new file mode 100644 index 0000000..edf0693 --- /dev/null +++ b/apps/web-naive/src/api/infra/file/index.ts @@ -0,0 +1,78 @@ +import type { AxiosRequestConfig, PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +/** Axios 上传进度事件 */ +export type AxiosProgressEvent = AxiosRequestConfig['onUploadProgress']; + +export namespace InfraFileApi { + /** 文件信息 */ + export interface File { + id?: number; + configId?: number; + path: string; + name?: string; + url?: string; + size?: number; + type?: string; + createTime?: Date; + } + + /** 文件预签名地址 */ + export interface FilePresignedUrlRespVO { + configId: number; // 文件配置编号 + uploadUrl: string; // 文件上传 URL + url: string; // 文件 URL + path: string; // 文件路径 + } + + /** 上传文件 */ + export interface FileUploadReqVO { + file: globalThis.File; + directory?: string; + } +} + +/** 查询文件列表 */ +export function getFilePage(params: PageParam) { + return requestClient.get>('/infra/file/page', { + params, + }); +} + +/** 删除文件 */ +export function deleteFile(id: number) { + return requestClient.delete(`/infra/file/delete?id=${id}`); +} + +/** 批量删除文件 */ +export function deleteFileList(ids: number[]) { + return requestClient.delete(`/infra/file/delete-list?ids=${ids.join(',')}`); +} + +/** 获取文件预签名地址 */ +export function getFilePresignedUrl(name: string, directory?: string) { + return requestClient.get( + '/infra/file/presigned-url', + { + params: { name, directory }, + }, + ); +} + +/** 创建文件 */ +export function createFile(data: InfraFileApi.File) { + return requestClient.post('/infra/file/create', data); +} + +/** 上传文件 */ +export function uploadFile( + data: InfraFileApi.FileUploadReqVO, + onUploadProgress?: AxiosProgressEvent, +) { + // 特殊:由于 upload 内部封装,即使 directory 为 undefined,也会传递给后端 + if (!data.directory) { + delete data.directory; + } + return requestClient.upload('/infra/file/upload', data, { onUploadProgress }); +} diff --git a/apps/web-naive/src/api/infra/job-log/index.ts b/apps/web-naive/src/api/infra/job-log/index.ts new file mode 100644 index 0000000..e115b9d --- /dev/null +++ b/apps/web-naive/src/api/infra/job-log/index.ts @@ -0,0 +1,41 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace InfraJobLogApi { + /** 任务日志信息 */ + export interface JobLog { + id?: number; + jobId: number; + handlerName: string; + handlerParam: string; + cronExpression: string; + executeIndex: string; + beginTime: Date; + endTime: Date; + duration: string; + status: number; + createTime?: string; + result: string; + } +} + +/** 查询任务日志列表 */ +export function getJobLogPage(params: PageParam) { + return requestClient.get>( + '/infra/job-log/page', + { params }, + ); +} + +/** 查询任务日志详情 */ +export function getJobLog(id: number) { + return requestClient.get( + `/infra/job-log/get?id=${id}`, + ); +} + +/** 导出定时任务日志 */ +export function exportJobLog(params: any) { + return requestClient.download('/infra/job-log/export-excel', { params }); +} diff --git a/apps/web-naive/src/api/infra/job/index.ts b/apps/web-naive/src/api/infra/job/index.ts new file mode 100644 index 0000000..04848dd --- /dev/null +++ b/apps/web-naive/src/api/infra/job/index.ts @@ -0,0 +1,77 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace InfraJobApi { + /** 任务信息 */ + export interface Job { + id?: number; + name: string; + status: number; + handlerName: string; + handlerParam: string; + cronExpression: string; + retryCount: number; + retryInterval: number; + monitorTimeout: number; + createTime?: Date; + nextTimes?: Date[]; + } +} + +/** 查询任务列表 */ +export function getJobPage(params: PageParam) { + return requestClient.get>('/infra/job/page', { + params, + }); +} + +/** 查询任务详情 */ +export function getJob(id: number) { + return requestClient.get(`/infra/job/get?id=${id}`); +} + +/** 新增任务 */ +export function createJob(data: InfraJobApi.Job) { + return requestClient.post('/infra/job/create', data); +} + +/** 修改定时任务调度 */ +export function updateJob(data: InfraJobApi.Job) { + return requestClient.put('/infra/job/update', data); +} + +/** 删除定时任务调度 */ +export function deleteJob(id: number) { + return requestClient.delete(`/infra/job/delete?id=${id}`); +} + +/** 批量删除定时任务调度 */ +export function deleteJobList(ids: number[]) { + return requestClient.delete(`/infra/job/delete-list?ids=${ids.join(',')}`); +} + +/** 导出定时任务调度 */ +export function exportJob(params: any) { + return requestClient.download('/infra/job/export-excel', { params }); +} + +/** 任务状态修改 */ +export function updateJobStatus(id: number, status: number) { + return requestClient.put('/infra/job/update-status', undefined, { + params: { + id, + status, + }, + }); +} + +/** 定时任务立即执行一次 */ +export function runJob(id: number) { + return requestClient.put(`/infra/job/trigger?id=${id}`); +} + +/** 获得定时任务的下 n 次执行时间 */ +export function getJobNextTimes(id: number) { + return requestClient.get(`/infra/job/get_next_times?id=${id}`); +} diff --git a/apps/web-naive/src/api/infra/redis/index.ts b/apps/web-naive/src/api/infra/redis/index.ts new file mode 100644 index 0000000..cb8179d --- /dev/null +++ b/apps/web-naive/src/api/infra/redis/index.ts @@ -0,0 +1,190 @@ +import { requestClient } from '#/api/request'; + +export namespace InfraRedisApi { + /** Redis 信息 */ + export interface RedisInfo { + io_threaded_reads_processed: string; + tracking_clients: string; + uptime_in_seconds: string; + cluster_connections: string; + current_cow_size: string; + maxmemory_human: string; + aof_last_cow_size: string; + master_replid2: string; + mem_replication_backlog: string; + aof_rewrite_scheduled: string; + total_net_input_bytes: string; + rss_overhead_ratio: string; + hz: string; + current_cow_size_age: string; + redis_build_id: string; + errorstat_BUSYGROUP: string; + aof_last_bgrewrite_status: string; + multiplexing_api: string; + client_recent_max_output_buffer: string; + allocator_resident: string; + mem_fragmentation_bytes: string; + aof_current_size: string; + repl_backlog_first_byte_offset: string; + tracking_total_prefixes: string; + redis_mode: string; + redis_git_dirty: string; + aof_delayed_fsync: string; + allocator_rss_bytes: string; + repl_backlog_histlen: string; + io_threads_active: string; + rss_overhead_bytes: string; + total_system_memory: string; + loading: string; + evicted_keys: string; + maxclients: string; + cluster_enabled: string; + redis_version: string; + repl_backlog_active: string; + mem_aof_buffer: string; + allocator_frag_bytes: string; + io_threaded_writes_processed: string; + instantaneous_ops_per_sec: string; + used_memory_human: string; + total_error_replies: string; + role: string; + maxmemory: string; + used_memory_lua: string; + rdb_current_bgsave_time_sec: string; + used_memory_startup: string; + used_cpu_sys_main_thread: string; + lazyfree_pending_objects: string; + aof_pending_bio_fsync: string; + used_memory_dataset_perc: string; + allocator_frag_ratio: string; + arch_bits: string; + used_cpu_user_main_thread: string; + mem_clients_normal: string; + expired_time_cap_reached_count: string; + unexpected_error_replies: string; + mem_fragmentation_ratio: string; + aof_last_rewrite_time_sec: string; + master_replid: string; + aof_rewrite_in_progress: string; + lru_clock: string; + maxmemory_policy: string; + run_id: string; + latest_fork_usec: string; + tracking_total_items: string; + total_commands_processed: string; + expired_keys: string; + errorstat_ERR: string; + used_memory: string; + module_fork_in_progress: string; + errorstat_WRONGPASS: string; + aof_buffer_length: string; + dump_payload_sanitizations: string; + mem_clients_slaves: string; + keyspace_misses: string; + server_time_usec: string; + executable: string; + lazyfreed_objects: string; + db0: string; + used_memory_peak_human: string; + keyspace_hits: string; + rdb_last_cow_size: string; + aof_pending_rewrite: string; + used_memory_overhead: string; + active_defrag_hits: string; + tcp_port: string; + uptime_in_days: string; + used_memory_peak_perc: string; + current_save_keys_processed: string; + blocked_clients: string; + total_reads_processed: string; + expire_cycle_cpu_milliseconds: string; + sync_partial_err: string; + used_memory_scripts_human: string; + aof_current_rewrite_time_sec: string; + aof_enabled: string; + process_supervised: string; + master_repl_offset: string; + used_memory_dataset: string; + used_cpu_user: string; + rdb_last_bgsave_status: string; + tracking_total_keys: string; + atomicvar_api: string; + allocator_rss_ratio: string; + client_recent_max_input_buffer: string; + clients_in_timeout_table: string; + aof_last_write_status: string; + mem_allocator: string; + used_memory_scripts: string; + used_memory_peak: string; + process_id: string; + master_failover_state: string; + errorstat_NOAUTH: string; + used_cpu_sys: string; + repl_backlog_size: string; + connected_slaves: string; + current_save_keys_total: string; + gcc_version: string; + total_system_memory_human: string; + sync_full: string; + connected_clients: string; + module_fork_last_cow_size: string; + total_writes_processed: string; + allocator_active: string; + total_net_output_bytes: string; + pubsub_channels: string; + current_fork_perc: string; + active_defrag_key_hits: string; + rdb_changes_since_last_save: string; + instantaneous_input_kbps: string; + used_memory_rss_human: string; + configured_hz: string; + expired_stale_perc: string; + active_defrag_misses: string; + used_cpu_sys_children: string; + number_of_cached_scripts: string; + sync_partial_ok: string; + used_memory_lua_human: string; + rdb_last_save_time: string; + pubsub_patterns: string; + slave_expires_tracked_keys: string; + redis_git_sha1: string; + used_memory_rss: string; + rdb_last_bgsave_time_sec: string; + os: string; + mem_not_counted_for_evict: string; + active_defrag_running: string; + rejected_connections: string; + aof_rewrite_buffer_length: string; + total_forks: string; + active_defrag_key_misses: string; + allocator_allocated: string; + aof_base_size: string; + instantaneous_output_kbps: string; + second_repl_offset: string; + rdb_bgsave_in_progress: string; + used_cpu_user_children: string; + total_connections_received: string; + migrate_cached_sockets: string; + } + + /** Redis 命令统计 */ + export interface RedisCommandStats { + command: string; + calls: number; + usec: number; + } + + /** Redis 监控信息 */ + export interface RedisMonitorInfo { + info: RedisInfo; + dbSize: number; + commandStats: RedisCommandStats[]; + } +} + +/** 获取 Redis 监控信息 */ +export function getRedisMonitorInfo() { + return requestClient.get( + '/infra/redis/get-monitor-info', + ); +} diff --git a/apps/web-naive/src/api/request.ts b/apps/web-naive/src/api/request.ts new file mode 100644 index 0000000..44f7587 --- /dev/null +++ b/apps/web-naive/src/api/request.ts @@ -0,0 +1,186 @@ +/** + * 该文件可自行根据业务逻辑进行调整 + */ +import type { RequestClientOptions } from '@vben/request'; + +import { isTenantEnable, useAppConfig } from '@vben/hooks'; +import { preferences } from '@vben/preferences'; +import { + authenticateResponseInterceptor, + defaultResponseInterceptor, + errorMessageResponseInterceptor, + RequestClient, +} from '@vben/request'; +import { useAccessStore } from '@vben/stores'; +import { createApiEncrypt } from '@vben/utils'; + +import { message } from '#/adapter/naive'; +import { useAuthStore } from '#/store'; + +import { refreshTokenApi } from './core'; + +const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); +const tenantEnable = isTenantEnable(); +const apiEncrypt = createApiEncrypt(import.meta.env); + +function createRequestClient(baseURL: string, options?: RequestClientOptions) { + const client = new RequestClient({ + ...options, + baseURL, + }); + + /** + * 重新认证逻辑 + */ + async function doReAuthenticate() { + console.warn('Access token or refresh token is invalid or expired. '); + const accessStore = useAccessStore(); + const authStore = useAuthStore(); + accessStore.setAccessToken(null); + if ( + preferences.app.loginExpiredMode === 'modal' && + accessStore.isAccessChecked + ) { + accessStore.setLoginExpired(true); + } else { + await authStore.logout(); + } + } + + /** + * 刷新token逻辑 + */ + async function doRefreshToken() { + const accessStore = useAccessStore(); + const refreshToken = accessStore.refreshToken as string; + if (!refreshToken) { + throw new Error('Refresh token is null!'); + } + const resp = await refreshTokenApi(refreshToken); + const newToken = resp?.data?.data?.accessToken; + // add by 芋艿:这里一定要抛出 resp.data,从而触发 authenticateResponseInterceptor 中,刷新令牌失败!!! + if (!newToken) { + throw resp.data; + } + accessStore.setAccessToken(newToken); + return newToken; + } + + function formatToken(token: null | string) { + return token ? `Bearer ${token}` : null; + } + + // 请求头处理 + client.addRequestInterceptor({ + fulfilled: async (config) => { + const accessStore = useAccessStore(); + + config.headers.Authorization = formatToken(accessStore.accessToken); + config.headers['Accept-Language'] = preferences.app.locale; + // 添加租户编号 + config.headers['tenant-id'] = tenantEnable + ? accessStore.tenantId + : undefined; + // 只有登录时,才设置 visit-tenant-id 访问租户 + config.headers['visit-tenant-id'] = tenantEnable + ? accessStore.visitTenantId + : undefined; + + // 是否 API 加密 + if ((config.headers || {}).isEncrypt) { + try { + // 加密请求数据 + if (config.data) { + config.data = apiEncrypt.encryptRequest(config.data); + // 设置加密标识头 + config.headers[apiEncrypt.getEncryptHeader()] = 'true'; + } + } catch (error) { + console.error('请求数据加密失败:', error); + throw error; + } + } + return config; + }, + }); + + // API 解密响应拦截器 + client.addResponseInterceptor({ + fulfilled: (response) => { + // 检查是否需要解密响应数据 + const encryptHeader = apiEncrypt.getEncryptHeader(); + const isEncryptResponse = + response.headers[encryptHeader] === 'true' || + response.headers[encryptHeader.toLowerCase()] === 'true'; + if (isEncryptResponse && typeof response.data === 'string') { + try { + // 解密响应数据 + response.data = apiEncrypt.decryptResponse(response.data); + } catch (error) { + console.error('响应数据解密失败:', error); + throw new Error(`响应数据解密失败: ${(error as Error).message}`); + } + } + return response; + }, + }); + + // 处理返回的响应数据格式 + client.addResponseInterceptor( + defaultResponseInterceptor({ + codeField: 'code', + dataField: 'data', + successCode: 0, + }), + ); + + // token过期的处理 + client.addResponseInterceptor( + authenticateResponseInterceptor({ + client, + doReAuthenticate, + doRefreshToken, + enableRefreshToken: preferences.app.enableRefreshToken, + formatToken, + }), + ); + + // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里 + client.addResponseInterceptor( + errorMessageResponseInterceptor((msg: string, error) => { + // 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg + // 当前mock接口返回的错误字段是 error 或者 message + const responseData = error?.response?.data ?? {}; + const errorMessage = + responseData?.error ?? responseData?.message ?? responseData.msg ?? ''; + // add by 芋艿:特殊:避免 401 “账号未登录”,重复提示。因为,此时会跳转到登录界面,只需提示一次!!! + if (error?.data?.code === 401) { + return; + } + // 如果没有错误信息,则会根据状态码进行提示 + message.error(errorMessage || msg); + }), + ); + + return client; +} + +export const requestClient = createRequestClient(apiURL, { + responseReturn: 'data', +}); + +export const baseRequestClient = new RequestClient({ baseURL: apiURL }); +baseRequestClient.addRequestInterceptor({ + fulfilled: (config) => { + const accessStore = useAccessStore(); + // 添加租户编号 + config.headers['tenant-id'] = tenantEnable + ? accessStore.tenantId + : undefined; + // 只有登录时,才设置 visit-tenant-id 访问租户 + config.headers['visit-tenant-id'] = tenantEnable + ? accessStore.visitTenantId + : undefined; + return config; + }, +}); diff --git a/apps/web-naive/src/api/system/area/index.ts b/apps/web-naive/src/api/system/area/index.ts new file mode 100644 index 0000000..8d3361d --- /dev/null +++ b/apps/web-naive/src/api/system/area/index.ts @@ -0,0 +1,24 @@ +import { requestClient } from '#/api/request'; + +export namespace SystemAreaApi { + /** 地区信息 */ + export interface Area { + id?: number; + name: string; + code: string; + parentId?: number; + sort?: number; + status?: number; + createTime?: Date; + } +} + +/** 获得地区树 */ +export function getAreaTree() { + return requestClient.get('/system/area/tree'); +} + +/** 获得 IP 对应的地区名 */ +export function getAreaByIp(ip: string) { + return requestClient.get(`/system/area/get-by-ip?ip=${ip}`); +} diff --git a/apps/web-naive/src/api/system/dept/index.ts b/apps/web-naive/src/api/system/dept/index.ts new file mode 100644 index 0000000..d6403d7 --- /dev/null +++ b/apps/web-naive/src/api/system/dept/index.ts @@ -0,0 +1,52 @@ +import { requestClient } from '#/api/request'; + +export namespace SystemDeptApi { + /** 部门信息 */ + export interface Dept { + id?: number; + name: string; + parentId?: number; + status: number; + sort: number; + leaderUserId: number; + phone: string; + email: string; + createTime: Date; + children?: Dept[]; + } +} + +/** 查询部门(精简)列表 */ +export async function getSimpleDeptList() { + return requestClient.get('/system/dept/simple-list'); +} + +/** 查询部门列表 */ +export async function getDeptList() { + return requestClient.get('/system/dept/list'); +} + +/** 查询部门详情 */ +export async function getDept(id: number) { + return requestClient.get(`/system/dept/get?id=${id}`); +} + +/** 新增部门 */ +export async function createDept(data: SystemDeptApi.Dept) { + return requestClient.post('/system/dept/create', data); +} + +/** 修改部门 */ +export async function updateDept(data: SystemDeptApi.Dept) { + return requestClient.put('/system/dept/update', data); +} + +/** 删除部门 */ +export async function deleteDept(id: number) { + return requestClient.delete(`/system/dept/delete?id=${id}`); +} + +/** 批量删除部门 */ +export async function deleteDeptList(ids: number[]) { + return requestClient.delete(`/system/dept/delete-list?ids=${ids.join(',')}`); +} diff --git a/apps/web-naive/src/api/system/dict/data/index.ts b/apps/web-naive/src/api/system/dict/data/index.ts new file mode 100644 index 0000000..28f94d5 --- /dev/null +++ b/apps/web-naive/src/api/system/dict/data/index.ts @@ -0,0 +1,68 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemDictDataApi { + /** 字典数据 */ + export type DictData = { + colorType: string; + createTime: Date; + cssClass: string; + dictType: string; + id?: number; + label: string; + remark: string; + sort?: number; + status: number; + value: string; + }; +} + +// 查询字典数据(精简)列表 +export function getSimpleDictDataList() { + return requestClient.get( + '/system/dict-data/simple-list', + ); +} + +// 查询字典数据列表 +export function getDictDataPage(params: PageParam) { + return requestClient.get>( + '/system/dict-data/page', + { params }, + ); +} + +// 查询字典数据详情 +export function getDictData(id: number) { + return requestClient.get( + `/system/dict-data/get?id=${id}`, + ); +} + +// 新增字典数据 +export function createDictData(data: SystemDictDataApi.DictData) { + return requestClient.post('/system/dict-data/create', data); +} + +// 修改字典数据 +export function updateDictData(data: SystemDictDataApi.DictData) { + return requestClient.put('/system/dict-data/update', data); +} + +// 删除字典数据 +export function deleteDictData(id: number) { + return requestClient.delete(`/system/dict-data/delete?id=${id}`); +} + +// 批量删除字典数据 +export function deleteDictDataList(ids: number[]) { + return requestClient.delete( + `/system/dict-data/delete-list?ids=${ids.join(',')}`, + ); +} + +// 导出字典类型数据 +export function exportDictData(params: any) { + return requestClient.download('/system/dict-data/export-excel', { params }); +} diff --git a/apps/web-naive/src/api/system/dict/type/index.ts b/apps/web-naive/src/api/system/dict/type/index.ts new file mode 100644 index 0000000..7fb4263 --- /dev/null +++ b/apps/web-naive/src/api/system/dict/type/index.ts @@ -0,0 +1,64 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemDictTypeApi { + /** 字典类型 */ + export type DictType = { + createTime: Date; + id?: number; + name: string; + remark: string; + status: number; + type: string; + }; +} + +// 查询字典(精简)列表 +export function getSimpleDictTypeList() { + return requestClient.get( + '/system/dict-type/list-all-simple', + ); +} + +// 查询字典列表 +export function getDictTypePage(params: PageParam) { + return requestClient.get>( + '/system/dict-type/page', + { params }, + ); +} + +// 查询字典详情 +export function getDictType(id: number) { + return requestClient.get( + `/system/dict-type/get?id=${id}`, + ); +} + +// 新增字典 +export function createDictType(data: SystemDictTypeApi.DictType) { + return requestClient.post('/system/dict-type/create', data); +} + +// 修改字典 +export function updateDictType(data: SystemDictTypeApi.DictType) { + return requestClient.put('/system/dict-type/update', data); +} + +// 删除字典 +export function deleteDictType(id: number) { + return requestClient.delete(`/system/dict-type/delete?id=${id}`); +} + +// 批量删除字典 +export function deleteDictTypeList(ids: number[]) { + return requestClient.delete( + `/system/dict-type/delete-list?ids=${ids.join(',')}`, + ); +} + +// 导出字典类型 +export function exportDictType(params: any) { + return requestClient.download('/system/dict-type/export-excel', { params }); +} diff --git a/apps/web-naive/src/api/system/login-log/index.ts b/apps/web-naive/src/api/system/login-log/index.ts new file mode 100644 index 0000000..4be20d9 --- /dev/null +++ b/apps/web-naive/src/api/system/login-log/index.ts @@ -0,0 +1,33 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemLoginLogApi { + /** 登录日志信息 */ + export interface LoginLog { + id: number; + logType: number; + traceId: number; + userId: number; + userType: number; + username: string; + result: number; + status: number; + userIp: string; + userAgent: string; + createTime: string; + } +} + +/** 查询登录日志列表 */ +export function getLoginLogPage(params: PageParam) { + return requestClient.get>( + '/system/login-log/page', + { params }, + ); +} + +/** 导出登录日志 */ +export function exportLoginLog(params: any) { + return requestClient.download('/system/login-log/export-excel', { params }); +} diff --git a/apps/web-naive/src/api/system/mail/account/index.ts b/apps/web-naive/src/api/system/mail/account/index.ts new file mode 100644 index 0000000..7f506fd --- /dev/null +++ b/apps/web-naive/src/api/system/mail/account/index.ts @@ -0,0 +1,64 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemMailAccountApi { + /** 邮箱账号 */ + export interface MailAccount { + id: number; + mail: string; + username: string; + password: string; + host: string; + port: number; + sslEnable: boolean; + starttlsEnable: boolean; + status: number; + createTime: Date; + remark: string; + } +} + +/** 查询邮箱账号列表 */ +export function getMailAccountPage(params: PageParam) { + return requestClient.get>( + '/system/mail-account/page', + { params }, + ); +} + +/** 查询邮箱账号详情 */ +export function getMailAccount(id: number) { + return requestClient.get( + `/system/mail-account/get?id=${id}`, + ); +} + +/** 新增邮箱账号 */ +export function createMailAccount(data: SystemMailAccountApi.MailAccount) { + return requestClient.post('/system/mail-account/create', data); +} + +/** 修改邮箱账号 */ +export function updateMailAccount(data: SystemMailAccountApi.MailAccount) { + return requestClient.put('/system/mail-account/update', data); +} + +/** 删除邮箱账号 */ +export function deleteMailAccount(id: number) { + return requestClient.delete(`/system/mail-account/delete?id=${id}`); +} + +/** 批量删除邮箱账号 */ +export function deleteMailAccountList(ids: number[]) { + return requestClient.delete( + `/system/mail-account/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 获得邮箱账号精简列表 */ +export function getSimpleMailAccountList() { + return requestClient.get( + '/system/mail-account/simple-list', + ); +} diff --git a/apps/web-naive/src/api/system/mail/log/index.ts b/apps/web-naive/src/api/system/mail/log/index.ts new file mode 100644 index 0000000..c32b790 --- /dev/null +++ b/apps/web-naive/src/api/system/mail/log/index.ts @@ -0,0 +1,36 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemMailLogApi { + /** 邮件日志 */ + export interface MailLog { + id: number; + userId: number; + userType: number; + toMails: string[]; + ccMails?: string[]; + bccMails?: string[]; + accountId: number; + fromMail: string; + templateId: number; + templateCode: string; + templateNickname: string; + templateTitle: string; + templateContent: string; + templateParams: string; + sendStatus: number; + sendTime: string; + sendMessageId: string; + sendException: string; + createTime: string; + } +} + +/** 查询邮件日志列表 */ +export function getMailLogPage(params: PageParam) { + return requestClient.get>( + '/system/mail-log/page', + { params }, + ); +} diff --git a/apps/web-naive/src/api/system/mail/template/index.ts b/apps/web-naive/src/api/system/mail/template/index.ts new file mode 100644 index 0000000..9e2a5a7 --- /dev/null +++ b/apps/web-naive/src/api/system/mail/template/index.ts @@ -0,0 +1,71 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemMailTemplateApi { + /** 邮件模版信息 */ + export interface MailTemplate { + id: number; + name: string; + code: string; + accountId: number; + nickname: string; + title: string; + content: string; + params: string[]; + status: number; + remark: string; + createTime: Date; + } + + /** 邮件发送信息 */ + export interface MailSendReqVO { + toMails: string[]; + ccMails?: string[]; + bccMails?: string[]; + templateCode: string; + templateParams: Record; + } +} + +/** 查询邮件模版列表 */ +export function getMailTemplatePage(params: PageParam) { + return requestClient.get>( + '/system/mail-template/page', + { params }, + ); +} + +/** 查询邮件模版详情 */ +export function getMailTemplate(id: number) { + return requestClient.get( + `/system/mail-template/get?id=${id}`, + ); +} + +/** 新增邮件模版 */ +export function createMailTemplate(data: SystemMailTemplateApi.MailTemplate) { + return requestClient.post('/system/mail-template/create', data); +} + +/** 修改邮件模版 */ +export function updateMailTemplate(data: SystemMailTemplateApi.MailTemplate) { + return requestClient.put('/system/mail-template/update', data); +} + +/** 删除邮件模版 */ +export function deleteMailTemplate(id: number) { + return requestClient.delete(`/system/mail-template/delete?id=${id}`); +} + +/** 批量删除邮件模版 */ +export function deleteMailTemplateList(ids: number[]) { + return requestClient.delete( + `/system/mail-template/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 发送邮件 */ +export function sendMail(data: SystemMailTemplateApi.MailSendReqVO) { + return requestClient.post('/system/mail-template/send-mail', data); +} diff --git a/apps/web-naive/src/api/system/menu/index.ts b/apps/web-naive/src/api/system/menu/index.ts new file mode 100644 index 0000000..b296d81 --- /dev/null +++ b/apps/web-naive/src/api/system/menu/index.ts @@ -0,0 +1,59 @@ +import { requestClient } from '#/api/request'; + +export namespace SystemMenuApi { + /** 菜单信息 */ + export interface Menu { + id: number; + name: string; + permission: string; + type: number; + sort: number; + parentId: number; + path: string; + icon: string; + component: string; + componentName?: string; + status: number; + visible: boolean; + keepAlive: boolean; + alwaysShow?: boolean; + createTime: Date; + } +} + +/** 查询菜单(精简)列表 */ +export async function getSimpleMenusList() { + return requestClient.get('/system/menu/simple-list'); +} + +/** 查询菜单列表 */ +export async function getMenuList(params?: Record) { + return requestClient.get('/system/menu/list', { + params, + }); +} + +/** 获取菜单详情 */ +export async function getMenu(id: number) { + return requestClient.get(`/system/menu/get?id=${id}`); +} + +/** 新增菜单 */ +export async function createMenu(data: SystemMenuApi.Menu) { + return requestClient.post('/system/menu/create', data); +} + +/** 修改菜单 */ +export async function updateMenu(data: SystemMenuApi.Menu) { + return requestClient.put('/system/menu/update', data); +} + +/** 删除菜单 */ +export async function deleteMenu(id: number) { + return requestClient.delete(`/system/menu/delete?id=${id}`); +} + +/** 批量删除菜单 */ +export async function deleteMenuList(ids: number[]) { + return requestClient.delete(`/system/menu/delete-list?ids=${ids.join(',')}`); +} diff --git a/apps/web-naive/src/api/system/notice/index.ts b/apps/web-naive/src/api/system/notice/index.ts new file mode 100644 index 0000000..5ae8885 --- /dev/null +++ b/apps/web-naive/src/api/system/notice/index.ts @@ -0,0 +1,59 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemNoticeApi { + /** 公告信息 */ + export interface Notice { + id?: number; + title: string; + type: number; + content: string; + status: number; + remark: string; + creator?: string; + createTime?: Date; + } +} + +/** 查询公告列表 */ +export function getNoticePage(params: PageParam) { + return requestClient.get>( + '/system/notice/page', + { params }, + ); +} + +/** 查询公告详情 */ +export function getNotice(id: number) { + return requestClient.get( + `/system/notice/get?id=${id}`, + ); +} + +/** 新增公告 */ +export function createNotice(data: SystemNoticeApi.Notice) { + return requestClient.post('/system/notice/create', data); +} + +/** 修改公告 */ +export function updateNotice(data: SystemNoticeApi.Notice) { + return requestClient.put('/system/notice/update', data); +} + +/** 删除公告 */ +export function deleteNotice(id: number) { + return requestClient.delete(`/system/notice/delete?id=${id}`); +} + +/** 批量删除公告 */ +export function deleteNoticeList(ids: number[]) { + return requestClient.delete( + `/system/notice/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 推送公告 */ +export function pushNotice(id: number) { + return requestClient.post(`/system/notice/push?id=${id}`); +} diff --git a/apps/web-naive/src/api/system/notify/message/index.ts b/apps/web-naive/src/api/system/notify/message/index.ts new file mode 100644 index 0000000..a8a4e89 --- /dev/null +++ b/apps/web-naive/src/api/system/notify/message/index.ts @@ -0,0 +1,65 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemNotifyMessageApi { + /** 站内信消息信息 */ + export interface NotifyMessage { + id: number; + userId: number; + userType: number; + templateId: number; + templateCode: string; + templateNickname: string; + templateContent: string; + templateType: number; + templateParams: string; + readStatus: boolean; + readTime: Date; + createTime: Date; + } +} + +/** 查询站内信消息列表 */ +export function getNotifyMessagePage(params: PageParam) { + return requestClient.get>( + '/system/notify-message/page', + { params }, + ); +} + +/** 获得我的站内信分页 */ +export function getMyNotifyMessagePage(params: PageParam) { + return requestClient.get>( + '/system/notify-message/my-page', + { params }, + ); +} + +/** 批量标记已读 */ +export function updateNotifyMessageRead(ids: number[]) { + return requestClient.put( + '/system/notify-message/update-read', + {}, + { + params: { ids }, + }, + ); +} + +/** 标记所有站内信为已读 */ +export function updateAllNotifyMessageRead() { + return requestClient.put('/system/notify-message/update-all-read'); +} + +/** 获取当前用户的最新站内信列表 */ +export function getUnreadNotifyMessageList() { + return requestClient.get( + '/system/notify-message/get-unread-list', + ); +} + +/** 获得当前用户的未读站内信数量 */ +export function getUnreadNotifyMessageCount() { + return requestClient.get('/system/notify-message/get-unread-count'); +} diff --git a/apps/web-naive/src/api/system/notify/template/index.ts b/apps/web-naive/src/api/system/notify/template/index.ts new file mode 100644 index 0000000..dd19f4b --- /dev/null +++ b/apps/web-naive/src/api/system/notify/template/index.ts @@ -0,0 +1,79 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemNotifyTemplateApi { + /** 站内信模板信息 */ + export interface NotifyTemplate { + id?: number; + name: string; + nickname: string; + code: string; + content: string; + type?: number; + params: string[]; + status: number; + remark: string; + } + + /** 发送站内信请求 */ + export interface NotifySendReqVO { + userId: number; + userType: number; + templateCode: string; + templateParams: Record; + } +} + +/** 查询站内信模板列表 */ +export function getNotifyTemplatePage(params: PageParam) { + return requestClient.get>( + '/system/notify-template/page', + { params }, + ); +} + +/** 查询站内信模板详情 */ +export function getNotifyTemplate(id: number) { + return requestClient.get( + `/system/notify-template/get?id=${id}`, + ); +} + +/** 新增站内信模板 */ +export function createNotifyTemplate( + data: SystemNotifyTemplateApi.NotifyTemplate, +) { + return requestClient.post('/system/notify-template/create', data); +} + +/** 修改站内信模板 */ +export function updateNotifyTemplate( + data: SystemNotifyTemplateApi.NotifyTemplate, +) { + return requestClient.put('/system/notify-template/update', data); +} + +/** 删除站内信模板 */ +export function deleteNotifyTemplate(id: number) { + return requestClient.delete(`/system/notify-template/delete?id=${id}`); +} + +/** 批量删除站内信模板 */ +export function deleteNotifyTemplateList(ids: number[]) { + return requestClient.delete( + `/system/notify-template/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 导出站内信模板 */ +export function exportNotifyTemplate(params: any) { + return requestClient.download('/system/notify-template/export-excel', { + params, + }); +} + +/** 发送站内信 */ +export function sendNotify(data: SystemNotifyTemplateApi.NotifySendReqVO) { + return requestClient.post('/system/notify-template/send-notify', data); +} diff --git a/apps/web-naive/src/api/system/oauth2/client/index.ts b/apps/web-naive/src/api/system/oauth2/client/index.ts new file mode 100644 index 0000000..5817b85 --- /dev/null +++ b/apps/web-naive/src/api/system/oauth2/client/index.ts @@ -0,0 +1,64 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemOAuth2ClientApi { + /** OAuth2.0 客户端信息 */ + export interface OAuth2Client { + id?: number; + clientId: string; + secret: string; + name: string; + logo: string; + description: string; + status: number; + accessTokenValiditySeconds: number; + refreshTokenValiditySeconds: number; + redirectUris: string[]; + autoApprove: boolean; + authorizedGrantTypes: string[]; + scopes: string[]; + authorities: string[]; + resourceIds: string[]; + additionalInformation: string; + isAdditionalInformationJson: boolean; + createTime?: Date; + } +} + +/** 查询 OAuth2.0 客户端列表 */ +export function getOAuth2ClientPage(params: PageParam) { + return requestClient.get>( + '/system/oauth2-client/page', + { params }, + ); +} + +/** 查询 OAuth2.0 客户端详情 */ +export function getOAuth2Client(id: number) { + return requestClient.get( + `/system/oauth2-client/get?id=${id}`, + ); +} + +/** 新增 OAuth2.0 客户端 */ +export function createOAuth2Client(data: SystemOAuth2ClientApi.OAuth2Client) { + return requestClient.post('/system/oauth2-client/create', data); +} + +/** 修改 OAuth2.0 客户端 */ +export function updateOAuth2Client(data: SystemOAuth2ClientApi.OAuth2Client) { + return requestClient.put('/system/oauth2-client/update', data); +} + +/** 删除 OAuth2.0 客户端 */ +export function deleteOAuth2Client(id: number) { + return requestClient.delete(`/system/oauth2-client/delete?id=${id}`); +} + +/** 批量删除 OAuth2.0 客户端 */ +export function deleteOAuth2ClientList(ids: number[]) { + return requestClient.delete( + `/system/oauth2-client/delete-list?ids=${ids.join(',')}`, + ); +} diff --git a/apps/web-naive/src/api/system/oauth2/open/index.ts b/apps/web-naive/src/api/system/oauth2/open/index.ts new file mode 100644 index 0000000..16d9c7e --- /dev/null +++ b/apps/web-naive/src/api/system/oauth2/open/index.ts @@ -0,0 +1,58 @@ +import { requestClient } from '#/api/request'; + +/** OAuth2.0 授权信息响应 */ +export namespace SystemOAuth2ClientApi { + /** 授权信息 */ + export interface AuthorizeInfoRespVO { + client: { + logo: string; + name: string; + }; + scopes: { + key: string; + value: boolean; + }[]; + } +} + +/** 获得授权信息 */ +export function getAuthorize(clientId: string) { + return requestClient.get( + `/system/oauth2/authorize?clientId=${clientId}`, + ); +} + +/** 发起授权 */ +export function authorize( + responseType: string, + clientId: string, + redirectUri: string, + state: string, + autoApprove: boolean, + checkedScopes: string[], + uncheckedScopes: string[], +) { + // 构建 scopes + const scopes: Record = {}; + for (const scope of checkedScopes) { + scopes[scope] = true; + } + for (const scope of uncheckedScopes) { + scopes[scope] = false; + } + + // 发起请求 + return requestClient.post('/system/oauth2/authorize', null, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + response_type: responseType, + client_id: clientId, + redirect_uri: redirectUri, + state, + auto_approve: autoApprove, + scope: JSON.stringify(scopes), + }, + }); +} diff --git a/apps/web-naive/src/api/system/oauth2/token/index.ts b/apps/web-naive/src/api/system/oauth2/token/index.ts new file mode 100644 index 0000000..bd36979 --- /dev/null +++ b/apps/web-naive/src/api/system/oauth2/token/index.ts @@ -0,0 +1,34 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemOAuth2TokenApi { + /** OAuth2.0 令牌信息 */ + export interface OAuth2Token { + id?: number; + accessToken: string; + refreshToken: string; + userId: number; + userType: number; + clientId: string; + createTime?: Date; + expiresTime?: Date; + } +} + +/** 查询 OAuth2.0 令牌列表 */ +export function getOAuth2TokenPage(params: PageParam) { + return requestClient.get>( + '/system/oauth2-token/page', + { + params, + }, + ); +} + +/** 删除 OAuth2.0 令牌 */ +export function deleteOAuth2Token(accessToken: string) { + return requestClient.delete( + `/system/oauth2-token/delete?accessToken=${accessToken}`, + ); +} diff --git a/apps/web-naive/src/api/system/operate-log/index.ts b/apps/web-naive/src/api/system/operate-log/index.ts new file mode 100644 index 0000000..8b84a26 --- /dev/null +++ b/apps/web-naive/src/api/system/operate-log/index.ts @@ -0,0 +1,39 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemOperateLogApi { + /** 操作日志信息 */ + export interface OperateLog { + id: number; + traceId: string; + userType: number; + userId: number; + userName: string; + type: string; + subType: string; + bizId: number; + action: string; + extra: string; + requestMethod: string; + requestUrl: string; + userIp: string; + userAgent: string; + creator: string; + creatorName: string; + createTime: string; + } +} + +/** 查询操作日志列表 */ +export function getOperateLogPage(params: PageParam) { + return requestClient.get>( + '/system/operate-log/page', + { params }, + ); +} + +/** 导出操作日志 */ +export function exportOperateLog(params: any) { + return requestClient.download('/system/operate-log/export-excel', { params }); +} diff --git a/apps/web-naive/src/api/system/permission/index.ts b/apps/web-naive/src/api/system/permission/index.ts new file mode 100644 index 0000000..9039d9a --- /dev/null +++ b/apps/web-naive/src/api/system/permission/index.ts @@ -0,0 +1,57 @@ +import { requestClient } from '#/api/request'; + +export namespace SystemPermissionApi { + /** 分配用户角色请求 */ + export interface AssignUserRoleReqVO { + userId: number; + roleIds: number[]; + } + + /** 分配角色菜单请求 */ + export interface AssignRoleMenuReqVO { + roleId: number; + menuIds: number[]; + } + + /** 分配角色数据权限请求 */ + export interface AssignRoleDataScopeReqVO { + roleId: number; + dataScope: number; + dataScopeDeptIds: number[]; + } +} + +/** 查询角色拥有的菜单权限 */ +export async function getRoleMenuList(roleId: number) { + return requestClient.get( + `/system/permission/list-role-menus?roleId=${roleId}`, + ); +} + +/** 赋予角色菜单权限 */ +export async function assignRoleMenu( + data: SystemPermissionApi.AssignRoleMenuReqVO, +) { + return requestClient.post('/system/permission/assign-role-menu', data); +} + +/** 赋予角色数据权限 */ +export async function assignRoleDataScope( + data: SystemPermissionApi.AssignRoleDataScopeReqVO, +) { + return requestClient.post('/system/permission/assign-role-data-scope', data); +} + +/** 查询用户拥有的角色数组 */ +export async function getUserRoleList(userId: number) { + return requestClient.get( + `/system/permission/list-user-roles?userId=${userId}`, + ); +} + +/** 赋予用户角色 */ +export async function assignUserRole( + data: SystemPermissionApi.AssignUserRoleReqVO, +) { + return requestClient.post('/system/permission/assign-user-role', data); +} diff --git a/apps/web-naive/src/api/system/post/index.ts b/apps/web-naive/src/api/system/post/index.ts new file mode 100644 index 0000000..8b32ad2 --- /dev/null +++ b/apps/web-naive/src/api/system/post/index.ts @@ -0,0 +1,63 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemPostApi { + /** 岗位信息 */ + export interface Post { + id?: number; + name: string; + code: string; + sort: number; + status: number; + remark: string; + createTime?: Date; + } +} + +/** 查询岗位列表 */ +export function getPostPage(params: PageParam) { + return requestClient.get>( + '/system/post/page', + { + params, + }, + ); +} + +/** 获取岗位精简信息列表 */ +export function getSimplePostList() { + return requestClient.get('/system/post/simple-list'); +} + +/** 查询岗位详情 */ +export function getPost(id: number) { + return requestClient.get(`/system/post/get?id=${id}`); +} + +/** 新增岗位 */ +export function createPost(data: SystemPostApi.Post) { + return requestClient.post('/system/post/create', data); +} + +/** 修改岗位 */ +export function updatePost(data: SystemPostApi.Post) { + return requestClient.put('/system/post/update', data); +} + +/** 删除岗位 */ +export function deletePost(id: number) { + return requestClient.delete(`/system/post/delete?id=${id}`); +} + +/** 批量删除岗位 */ +export function deletePostList(ids: number[]) { + return requestClient.delete(`/system/post/delete-list?ids=${ids.join(',')}`); +} + +/** 导出岗位 */ +export function exportPost(params: any) { + return requestClient.download('/system/post/export-excel', { + params, + }); +} diff --git a/apps/web-naive/src/api/system/role/index.ts b/apps/web-naive/src/api/system/role/index.ts new file mode 100644 index 0000000..23d5ade --- /dev/null +++ b/apps/web-naive/src/api/system/role/index.ts @@ -0,0 +1,63 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemRoleApi { + /** 角色信息 */ + export interface Role { + id?: number; + name: string; + code: string; + sort: number; + status: number; + type: number; + dataScope: number; + dataScopeDeptIds: number[]; + createTime?: Date; + } +} + +/** 查询角色列表 */ +export function getRolePage(params: PageParam) { + return requestClient.get>( + '/system/role/page', + { params }, + ); +} + +/** 查询角色(精简)列表 */ +export function getSimpleRoleList() { + return requestClient.get('/system/role/simple-list'); +} + +/** 查询角色详情 */ +export function getRole(id: number) { + return requestClient.get(`/system/role/get?id=${id}`); +} + +/** 新增角色 */ +export function createRole(data: SystemRoleApi.Role) { + return requestClient.post('/system/role/create', data); +} + +/** 修改角色 */ +export function updateRole(data: SystemRoleApi.Role) { + return requestClient.put('/system/role/update', data); +} + +/** 删除角色 */ +export function deleteRole(id: number) { + return requestClient.delete(`/system/role/delete?id=${id}`); +} + +/** 批量删除角色 */ +export function deleteRoleList(ids: number[]) { + return requestClient.delete(`/system/role/delete-list?ids=${ids.join(',')}`); +} + +/** 导出角色 */ +export function exportRole(params: any) { + return requestClient.download('/system/role/export-excel', { + params, + }); +} diff --git a/apps/web-naive/src/api/system/sms/channel/index.ts b/apps/web-naive/src/api/system/sms/channel/index.ts new file mode 100644 index 0000000..df32aad --- /dev/null +++ b/apps/web-naive/src/api/system/sms/channel/index.ts @@ -0,0 +1,67 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemSmsChannelApi { + /** 短信渠道信息 */ + export interface SmsChannel { + id?: number; + code: string; + status: number; + signature: string; + remark: string; + apiKey: string; + apiSecret: string; + callbackUrl: string; + createTime?: Date; + } +} + +/** 查询短信渠道列表 */ +export function getSmsChannelPage(params: PageParam) { + return requestClient.get>( + '/system/sms-channel/page', + { params }, + ); +} + +/** 获得短信渠道精简列表 */ +export function getSimpleSmsChannelList() { + return requestClient.get( + '/system/sms-channel/simple-list', + ); +} + +/** 查询短信渠道详情 */ +export function getSmsChannel(id: number) { + return requestClient.get( + `/system/sms-channel/get?id=${id}`, + ); +} + +/** 新增短信渠道 */ +export function createSmsChannel(data: SystemSmsChannelApi.SmsChannel) { + return requestClient.post('/system/sms-channel/create', data); +} + +/** 修改短信渠道 */ +export function updateSmsChannel(data: SystemSmsChannelApi.SmsChannel) { + return requestClient.put('/system/sms-channel/update', data); +} + +/** 删除短信渠道 */ +export function deleteSmsChannel(id: number) { + return requestClient.delete(`/system/sms-channel/delete?id=${id}`); +} + +/** 批量删除短信渠道 */ +export function deleteSmsChannelList(ids: number[]) { + return requestClient.delete( + `/system/sms-channel/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 导出短信渠道 */ +export function exportSmsChannel(params: any) { + return requestClient.download('/system/sms-channel/export-excel', { params }); +} diff --git a/apps/web-naive/src/api/system/sms/log/index.ts b/apps/web-naive/src/api/system/sms/log/index.ts new file mode 100644 index 0000000..8344f99 --- /dev/null +++ b/apps/web-naive/src/api/system/sms/log/index.ts @@ -0,0 +1,45 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemSmsLogApi { + /** 短信日志信息 */ + export interface SmsLog { + id?: number; + channelId?: number; + channelCode: string; + templateId?: number; + templateCode: string; + templateType?: number; + templateContent: string; + templateParams?: Record; + apiTemplateId: string; + mobile: string; + userId?: number; + userType?: number; + sendStatus?: number; + sendTime?: string; + apiSendCode: string; + apiSendMsg: string; + apiRequestId: string; + apiSerialNo: string; + receiveStatus?: number; + receiveTime?: string; + apiReceiveCode: string; + apiReceiveMsg: string; + createTime: string; + } +} + +/** 查询短信日志列表 */ +export function getSmsLogPage(params: PageParam) { + return requestClient.get>( + '/system/sms-log/page', + { params }, + ); +} + +/** 导出短信日志 */ +export function exportSmsLog(params: any) { + return requestClient.download('/system/sms-log/export-excel', { params }); +} diff --git a/apps/web-naive/src/api/system/sms/template/index.ts b/apps/web-naive/src/api/system/sms/template/index.ts new file mode 100644 index 0000000..eccfb91 --- /dev/null +++ b/apps/web-naive/src/api/system/sms/template/index.ts @@ -0,0 +1,77 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemSmsTemplateApi { + /** 短信模板信息 */ + export interface SmsTemplate { + id?: number; + type?: number; + status: number; + code: string; + name: string; + content: string; + remark: string; + apiTemplateId: string; + channelId?: number; + channelCode?: string; + params?: string[]; + createTime?: Date; + } + + /** 发送短信请求 */ + export interface SmsSendReqVO { + mobile: string; + templateCode: string; + templateParams: Record; + } +} + +/** 查询短信模板列表 */ +export function getSmsTemplatePage(params: PageParam) { + return requestClient.get>( + '/system/sms-template/page', + { params }, + ); +} + +/** 查询短信模板详情 */ +export function getSmsTemplate(id: number) { + return requestClient.get( + `/system/sms-template/get?id=${id}`, + ); +} + +/** 新增短信模板 */ +export function createSmsTemplate(data: SystemSmsTemplateApi.SmsTemplate) { + return requestClient.post('/system/sms-template/create', data); +} + +/** 修改短信模板 */ +export function updateSmsTemplate(data: SystemSmsTemplateApi.SmsTemplate) { + return requestClient.put('/system/sms-template/update', data); +} + +/** 删除短信模板 */ +export function deleteSmsTemplate(id: number) { + return requestClient.delete(`/system/sms-template/delete?id=${id}`); +} + +/** 批量删除短信模板 */ +export function deleteSmsTemplateList(ids: number[]) { + return requestClient.delete( + `/system/sms-template/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 导出短信模板 */ +export function exportSmsTemplate(params: any) { + return requestClient.download('/system/sms-template/export-excel', { + params, + }); +} + +/** 发送短信 */ +export function sendSms(data: SystemSmsTemplateApi.SmsSendReqVO) { + return requestClient.post('/system/sms-template/send-sms', data); +} diff --git a/apps/web-naive/src/api/system/social/client/index.ts b/apps/web-naive/src/api/system/social/client/index.ts new file mode 100644 index 0000000..55978dd --- /dev/null +++ b/apps/web-naive/src/api/system/social/client/index.ts @@ -0,0 +1,56 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemSocialClientApi { + /** 社交客户端信息 */ + export interface SocialClient { + id?: number; + name: string; + socialType: number; + userType: number; + clientId: string; + clientSecret: string; + agentId?: string; + publicKey?: string; + status: number; + createTime?: Date; + } +} + +/** 查询社交客户端列表 */ +export function getSocialClientPage(params: PageParam) { + return requestClient.get>( + '/system/social-client/page', + { params }, + ); +} + +/** 查询社交客户端详情 */ +export function getSocialClient(id: number) { + return requestClient.get( + `/system/social-client/get?id=${id}`, + ); +} + +/** 新增社交客户端 */ +export function createSocialClient(data: SystemSocialClientApi.SocialClient) { + return requestClient.post('/system/social-client/create', data); +} + +/** 修改社交客户端 */ +export function updateSocialClient(data: SystemSocialClientApi.SocialClient) { + return requestClient.put('/system/social-client/update', data); +} + +/** 删除社交客户端 */ +export function deleteSocialClient(id: number) { + return requestClient.delete(`/system/social-client/delete?id=${id}`); +} + +/** 批量删除社交客户端 */ +export function deleteSocialClientList(ids: number[]) { + return requestClient.delete( + `/system/social-client/delete-list?ids=${ids.join(',')}`, + ); +} diff --git a/apps/web-naive/src/api/system/social/user/index.ts b/apps/web-naive/src/api/system/social/user/index.ts new file mode 100644 index 0000000..b91f150 --- /dev/null +++ b/apps/web-naive/src/api/system/social/user/index.ts @@ -0,0 +1,66 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemSocialUserApi { + /** 社交用户信息 */ + export interface SocialUser { + id?: number; + type: number; + openid: string; + token: string; + rawTokenInfo: string; + nickname: string; + avatar: string; + rawUserInfo: string; + code: string; + state: string; + createTime?: Date; + updateTime?: Date; + } + + /** 社交绑定请求 */ + export interface SocialUserBindReqVO { + type: number; + code: string; + state: string; + } + + /** 取消社交绑定请求 */ + export interface SocialUserUnbindReqVO { + type: number; + openid: string; + } +} + +/** 查询社交用户列表 */ +export function getSocialUserPage(params: PageParam) { + return requestClient.get>( + '/system/social-user/page', + { params }, + ); +} + +/** 查询社交用户详情 */ +export function getSocialUser(id: number) { + return requestClient.get( + `/system/social-user/get?id=${id}`, + ); +} + +/** 社交绑定,使用 code 授权码 */ +export function socialBind(data: SystemSocialUserApi.SocialUserBindReqVO) { + return requestClient.post('/system/social-user/bind', data); +} + +/** 取消社交绑定 */ +export function socialUnbind(data: SystemSocialUserApi.SocialUserUnbindReqVO) { + return requestClient.delete('/system/social-user/unbind', { data }); +} + +/** 获得绑定社交用户列表 */ +export function getBindSocialUserList() { + return requestClient.get( + '/system/social-user/get-bind-list', + ); +} diff --git a/apps/web-naive/src/api/system/tenant-package/index.ts b/apps/web-naive/src/api/system/tenant-package/index.ts new file mode 100644 index 0000000..53be78f --- /dev/null +++ b/apps/web-naive/src/api/system/tenant-package/index.ts @@ -0,0 +1,64 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemTenantPackageApi { + /** 租户套餐信息 */ + export interface TenantPackage { + id: number; + name: string; + status: number; + remark: string; + creator: string; + updater: string; + updateTime: string; + menuIds: number[]; + createTime: Date; + } +} + +/** 租户套餐列表 */ +export function getTenantPackagePage(params: PageParam) { + return requestClient.get>( + '/system/tenant-package/page', + { params }, + ); +} + +/** 查询租户套餐详情 */ +export function getTenantPackage(id: number) { + return requestClient.get(`/system/tenant-package/get?id=${id}`); +} + +/** 新增租户套餐 */ +export function createTenantPackage( + data: SystemTenantPackageApi.TenantPackage, +) { + return requestClient.post('/system/tenant-package/create', data); +} + +/** 修改租户套餐 */ +export function updateTenantPackage( + data: SystemTenantPackageApi.TenantPackage, +) { + return requestClient.put('/system/tenant-package/update', data); +} + +/** 删除租户套餐 */ +export function deleteTenantPackage(id: number) { + return requestClient.delete(`/system/tenant-package/delete?id=${id}`); +} + +/** 批量删除租户套餐 */ +export function deleteTenantPackageList(ids: number[]) { + return requestClient.delete( + `/system/tenant-package/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 获取租户套餐精简信息列表 */ +export function getTenantPackageList() { + return requestClient.get( + '/system/tenant-package/get-simple-list', + ); +} diff --git a/apps/web-naive/src/api/system/tenant/index.ts b/apps/web-naive/src/api/system/tenant/index.ts new file mode 100644 index 0000000..6ee52e1 --- /dev/null +++ b/apps/web-naive/src/api/system/tenant/index.ts @@ -0,0 +1,76 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemTenantApi { + /** 租户信息 */ + export interface Tenant { + id?: number; + name: string; + packageId: number; + contactName: string; + contactMobile: string; + accountCount: number; + expireTime: Date; + websites: string[]; + status: number; + } +} + +/** 租户列表 */ +export function getTenantPage(params: PageParam) { + return requestClient.get>( + '/system/tenant/page', + { params }, + ); +} + +/** 获取租户精简信息列表 */ +export function getSimpleTenantList() { + return requestClient.get( + '/system/tenant/simple-list', + ); +} + +/** 查询租户详情 */ +export function getTenant(id: number) { + return requestClient.get( + `/system/tenant/get?id=${id}`, + ); +} + +/** 获取租户精简信息列表 */ +export function getTenantList() { + return requestClient.get( + '/system/tenant/simple-list', + ); +} + +/** 新增租户 */ +export function createTenant(data: SystemTenantApi.Tenant) { + return requestClient.post('/system/tenant/create', data); +} + +/** 修改租户 */ +export function updateTenant(data: SystemTenantApi.Tenant) { + return requestClient.put('/system/tenant/update', data); +} + +/** 删除租户 */ +export function deleteTenant(id: number) { + return requestClient.delete(`/system/tenant/delete?id=${id}`); +} + +/** 批量删除租户 */ +export function deleteTenantList(ids: number[]) { + return requestClient.delete( + `/system/tenant/delete-list?ids=${ids.join(',')}`, + ); +} + +/** 导出租户 */ +export function exportTenant(params: any) { + return requestClient.download('/system/tenant/export-excel', { + params, + }); +} diff --git a/apps/web-naive/src/api/system/user/index.ts b/apps/web-naive/src/api/system/user/index.ts new file mode 100644 index 0000000..c9f23a4 --- /dev/null +++ b/apps/web-naive/src/api/system/user/index.ts @@ -0,0 +1,88 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace SystemUserApi { + /** 用户信息 */ + export interface User { + id?: number; + username: string; + nickname: string; + deptId: number; + postIds: string[]; + email: string; + mobile: string; + sex: number; + avatar: string; + loginIp: string; + status: number; + remark: string; + createTime?: Date; + } +} + +/** 查询用户管理列表 */ +export function getUserPage(params: PageParam) { + return requestClient.get>( + '/system/user/page', + { params }, + ); +} + +/** 查询用户详情 */ +export function getUser(id: number) { + return requestClient.get(`/system/user/get?id=${id}`); +} + +/** 新增用户 */ +export function createUser(data: SystemUserApi.User) { + return requestClient.post('/system/user/create', data); +} + +/** 修改用户 */ +export function updateUser(data: SystemUserApi.User) { + return requestClient.put('/system/user/update', data); +} + +/** 删除用户 */ +export function deleteUser(id: number) { + return requestClient.delete(`/system/user/delete?id=${id}`); +} + +/** 批量删除用户 */ +export function deleteUserList(ids: number[]) { + return requestClient.delete(`/system/user/delete-list?ids=${ids.join(',')}`); +} + +/** 导出用户 */ +export function exportUser(params: any) { + return requestClient.download('/system/user/export-excel', { params }); +} + +/** 下载用户导入模板 */ +export function importUserTemplate() { + return requestClient.download('/system/user/get-import-template'); +} + +/** 导入用户 */ +export function importUser(file: File, updateSupport: boolean) { + return requestClient.upload('/system/user/import', { + file, + updateSupport, + }); +} + +/** 用户密码重置 */ +export function resetUserPassword(id: number, password: string) { + return requestClient.put('/system/user/update-password', { id, password }); +} + +/** 用户状态修改 */ +export function updateUserStatus(id: number, status: number) { + return requestClient.put('/system/user/update-status', { id, status }); +} + +/** 获取用户精简信息列表 */ +export function getSimpleUserList() { + return requestClient.get('/system/user/simple-list'); +} diff --git a/apps/web-naive/src/api/system/user/profile/index.ts b/apps/web-naive/src/api/system/user/profile/index.ts new file mode 100644 index 0000000..97898e7 --- /dev/null +++ b/apps/web-naive/src/api/system/user/profile/index.ts @@ -0,0 +1,56 @@ +import { requestClient } from '#/api/request'; + +export namespace SystemUserProfileApi { + /** 用户个人中心信息 */ + export interface UserProfileRespVO { + id: number; + username: string; + nickname: string; + email?: string; + mobile?: string; + sex?: number; + avatar?: string; + loginIp: string; + loginDate: string; + createTime: string; + roles: any[]; + dept: any; + posts: any[]; + } + + /** 更新密码请求 */ + export interface UpdatePasswordReqVO { + oldPassword: string; + newPassword: string; + } + + /** 更新个人信息请求 */ + export interface UpdateProfileReqVO { + nickname?: string; + email?: string; + mobile?: string; + sex?: number; + avatar?: string; + } +} + +/** 获取登录用户信息 */ +export function getUserProfile() { + return requestClient.get( + '/system/user/profile/get', + ); +} + +/** 修改用户个人信息 */ +export function updateUserProfile( + data: SystemUserProfileApi.UpdateProfileReqVO, +) { + return requestClient.put('/system/user/profile/update', data); +} + +/** 修改用户个人密码 */ +export function updateUserPassword( + data: SystemUserProfileApi.UpdatePasswordReqVO, +) { + return requestClient.put('/system/user/profile/update-password', data); +} diff --git a/apps/web-naive/src/app.vue b/apps/web-naive/src/app.vue new file mode 100644 index 0000000..23983c5 --- /dev/null +++ b/apps/web-naive/src/app.vue @@ -0,0 +1,56 @@ + + + diff --git a/apps/web-naive/src/bootstrap.ts b/apps/web-naive/src/bootstrap.ts new file mode 100644 index 0000000..df0b2cb --- /dev/null +++ b/apps/web-naive/src/bootstrap.ts @@ -0,0 +1,76 @@ +import { createApp, watchEffect } from 'vue'; + +import { registerAccessDirective } from '@vben/access'; +import { registerLoadingDirective } from '@vben/common-ui'; +import { preferences } from '@vben/preferences'; +import { initStores } from '@vben/stores'; +import '@vben/styles'; +import '@vben/styles/naive'; + +import { useTitle } from '@vueuse/core'; + +import { $t, setupI18n } from '#/locales'; + +import { initComponentAdapter } from './adapter/component'; +import { initSetupVbenForm } from './adapter/form'; +import App from './app.vue'; +import { router } from './router'; + +async function bootstrap(namespace: string) { + // 初始化组件适配器 + await initComponentAdapter(); + + // 初始化表单组件 + await initSetupVbenForm(); + + // // 设置弹窗的默认配置 + // setDefaultModalProps({ + // fullscreenButton: false, + // }); + // // 设置抽屉的默认配置 + // setDefaultDrawerProps({ + // // zIndex: 2000, + // }); + + const app = createApp(App); + + // 注册v-loading指令 + registerLoadingDirective(app, { + loading: 'loading', // 在这里可以自定义指令名称,也可以明确提供false表示不注册这个指令 + spinning: 'spinning', + }); + + // 国际化 i18n 配置 + await setupI18n(app); + + // 配置 pinia-tore + await initStores(app, { namespace }); + + // 安装权限指令 + registerAccessDirective(app); + + // 初始化 tippy + const { initTippy } = await import('@vben/common-ui/es/tippy'); + initTippy(app); + + // 配置路由及路由守卫 + app.use(router); + + // 配置Motion插件 + const { MotionPlugin } = await import('@vben/plugins/motion'); + app.use(MotionPlugin); + + // 动态更新标题 + watchEffect(() => { + if (preferences.app.dynamicTitle) { + const routeTitle = router.currentRoute.value.meta?.title; + const pageTitle = + (routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name; + useTitle(pageTitle); + } + }); + + app.mount('#app'); +} + +export { bootstrap }; diff --git a/apps/web-naive/src/components/cron-tab/cron-tab.vue b/apps/web-naive/src/components/cron-tab/cron-tab.vue new file mode 100644 index 0000000..9125ba1 --- /dev/null +++ b/apps/web-naive/src/components/cron-tab/cron-tab.vue @@ -0,0 +1,955 @@ + + + + + diff --git a/apps/web-naive/src/components/cron-tab/index.ts b/apps/web-naive/src/components/cron-tab/index.ts new file mode 100644 index 0000000..8f4baae --- /dev/null +++ b/apps/web-naive/src/components/cron-tab/index.ts @@ -0,0 +1 @@ +export { default as CronTab } from './cron-tab.vue'; diff --git a/apps/web-naive/src/components/cron-tab/types.ts b/apps/web-naive/src/components/cron-tab/types.ts new file mode 100644 index 0000000..2adf942 --- /dev/null +++ b/apps/web-naive/src/components/cron-tab/types.ts @@ -0,0 +1,266 @@ +export interface ShortcutsType { + text: string; + value: string; +} + +export interface CronRange { + start: number | string | undefined; + end: number | string | undefined; +} + +export interface CronLoop { + start: number | string | undefined; + end: number | string | undefined; +} + +export interface CronItem { + type: string; + range: CronRange; + loop: CronLoop; + appoint: string[]; + last?: string; +} + +export interface CronValue { + second: CronItem; + minute: CronItem; + hour: CronItem; + day: CronItem; + month: CronItem; + week: CronItem & { last: string }; + year: CronItem; +} + +export interface WeekOption { + value: string; + label: string; +} + +export interface CronData { + second: string[]; + minute: string[]; + hour: string[]; + day: string[]; + month: string[]; + week: WeekOption[]; + year: number[]; +} + +const getYear = (): number[] => { + const v: number[] = []; + const y = new Date().getFullYear(); + for (let i = 0; i < 11; i++) { + v.push(y + i); + } + return v; +}; + +export const CronValueDefault: CronValue = { + second: { + type: '0', + range: { + start: 1, + end: 2, + }, + loop: { + start: 0, + end: 1, + }, + appoint: [], + }, + minute: { + type: '0', + range: { + start: 1, + end: 2, + }, + loop: { + start: 0, + end: 1, + }, + appoint: [], + }, + hour: { + type: '0', + range: { + start: 1, + end: 2, + }, + loop: { + start: 0, + end: 1, + }, + appoint: [], + }, + day: { + type: '0', + range: { + start: 1, + end: 2, + }, + loop: { + start: 1, + end: 1, + }, + appoint: [], + }, + month: { + type: '0', + range: { + start: 1, + end: 2, + }, + loop: { + start: 1, + end: 1, + }, + appoint: [], + }, + week: { + type: '5', + range: { + start: '2', + end: '3', + }, + loop: { + start: 0, + end: '2', + }, + last: '2', + appoint: [], + }, + year: { + type: '-1', + range: { + start: getYear()[0], + end: getYear()[1], + }, + loop: { + start: getYear()[0], + end: 1, + }, + appoint: [], + }, +}; + +export const CronDataDefault: CronData = { + second: [ + '0', + '5', + '15', + '20', + '25', + '30', + '35', + '40', + '45', + '50', + '55', + '59', + ], + minute: [ + '0', + '5', + '15', + '20', + '25', + '30', + '35', + '40', + '45', + '50', + '55', + '59', + ], + hour: [ + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '10', + '11', + '12', + '13', + '14', + '15', + '16', + '17', + '18', + '19', + '20', + '21', + '22', + '23', + ], + day: [ + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '10', + '11', + '12', + '13', + '14', + '15', + '16', + '17', + '18', + '19', + '20', + '21', + '22', + '23', + '24', + '25', + '26', + '27', + '28', + '29', + '30', + '31', + ], + month: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'], + week: [ + { + value: '1', + label: '周日', + }, + { + value: '2', + label: '周一', + }, + { + value: '3', + label: '周二', + }, + { + value: '4', + label: '周三', + }, + { + value: '5', + label: '周四', + }, + { + value: '6', + label: '周五', + }, + { + value: '7', + label: '周六', + }, + ], + year: getYear(), +}; diff --git a/apps/web-naive/src/components/description/description.vue b/apps/web-naive/src/components/description/description.vue new file mode 100644 index 0000000..51f0df4 --- /dev/null +++ b/apps/web-naive/src/components/description/description.vue @@ -0,0 +1,198 @@ + diff --git a/apps/web-naive/src/components/description/index.ts b/apps/web-naive/src/components/description/index.ts new file mode 100644 index 0000000..a707c48 --- /dev/null +++ b/apps/web-naive/src/components/description/index.ts @@ -0,0 +1,3 @@ +export { default as Description } from './description.vue'; +export * from './typing'; +export { useDescription } from './use-description'; diff --git a/apps/web-naive/src/components/description/typing.ts b/apps/web-naive/src/components/description/typing.ts new file mode 100644 index 0000000..9ee4896 --- /dev/null +++ b/apps/web-naive/src/components/description/typing.ts @@ -0,0 +1,41 @@ +import type { DescriptionsProps as NDescriptionsProps } from 'naive-ui'; +import type { JSX } from 'vue/jsx-runtime'; + +import type { CSSProperties, VNode } from 'vue'; + +import type { Recordable } from '@vben/types'; + +export interface DescriptionItemSchema { + labelMinWidth?: number; + contentMinWidth?: number; + // 自定义标签样式 + labelStyle?: CSSProperties; + // 对应 data 中的字段名 + field: string; + // 内容的描述 + label: JSX.Element | string | VNode; + // 包含列的数量 + span?: number; + // 是否显示 + show?: (...arg: any) => boolean; + // 插槽名称 + slot?: string; + // 自定义需要展示的内容 + render?: ( + val: any, + data?: Recordable, + ) => Element | JSX.Element | number | string | undefined | VNode; +} + +export interface DescriptionProps extends NDescriptionsProps { + // 是否包含卡片组件 + useCard?: boolean; + // 描述项配置 + schema: DescriptionItemSchema[]; + // 数据 + data: Recordable; +} + +export interface DescInstance { + setDescProps(descProps: Partial): void; +} diff --git a/apps/web-naive/src/components/description/use-description.ts b/apps/web-naive/src/components/description/use-description.ts new file mode 100644 index 0000000..fd24920 --- /dev/null +++ b/apps/web-naive/src/components/description/use-description.ts @@ -0,0 +1,31 @@ +import type { Component } from 'vue'; + +import type { DescInstance, DescriptionProps } from './typing'; + +import { h, reactive } from 'vue'; + +import Description from './description.vue'; + +export function useDescription(options?: Partial) { + const propsState = reactive>(options || {}); + + const api: DescInstance = { + setDescProps: (descProps: Partial): void => { + Object.assign(propsState, descProps); + }, + }; + + // 创建一个包装组件,将 propsState 合并到 props 中 + const DescriptionWrapper: Component = { + name: 'UseDescription', + inheritAttrs: false, + setup(_props, { attrs, slots }) { + return () => { + // @ts-ignore - 避免类型实例化过深 + return h(Description, { ...propsState, ...attrs }, slots); + }; + }, + }; + + return [DescriptionWrapper, api] as const; +} diff --git a/apps/web-naive/src/components/dict-tag/dict-tag.vue b/apps/web-naive/src/components/dict-tag/dict-tag.vue new file mode 100644 index 0000000..8768161 --- /dev/null +++ b/apps/web-naive/src/components/dict-tag/dict-tag.vue @@ -0,0 +1,83 @@ + + + diff --git a/apps/web-naive/src/components/dict-tag/index.ts b/apps/web-naive/src/components/dict-tag/index.ts new file mode 100644 index 0000000..881265a --- /dev/null +++ b/apps/web-naive/src/components/dict-tag/index.ts @@ -0,0 +1 @@ +export { default as DictTag } from './dict-tag.vue'; diff --git a/apps/web-naive/src/components/table-action/icons.ts b/apps/web-naive/src/components/table-action/icons.ts new file mode 100644 index 0000000..88cda59 --- /dev/null +++ b/apps/web-naive/src/components/table-action/icons.ts @@ -0,0 +1,13 @@ +export const ACTION_ICON = { + DOWNLOAD: 'lucide:download', + UPLOAD: 'lucide:upload', + ADD: 'lucide:plus', + EDIT: 'lucide:edit', + DELETE: 'lucide:trash-2', + REFRESH: 'lucide:refresh-cw', + SEARCH: 'lucide:search', + FILTER: 'lucide:filter', + MORE: 'lucide:ellipsis-vertical', + VIEW: 'lucide:eye', + COPY: 'lucide:copy', +}; diff --git a/apps/web-naive/src/components/table-action/index.ts b/apps/web-naive/src/components/table-action/index.ts new file mode 100644 index 0000000..672c0a5 --- /dev/null +++ b/apps/web-naive/src/components/table-action/index.ts @@ -0,0 +1,4 @@ +export * from './icons'; + +export { default as TableAction } from './table-action.vue'; +export * from './typing'; diff --git a/apps/web-naive/src/components/table-action/table-action.vue b/apps/web-naive/src/components/table-action/table-action.vue new file mode 100644 index 0000000..50fd7f8 --- /dev/null +++ b/apps/web-naive/src/components/table-action/table-action.vue @@ -0,0 +1,221 @@ + + + + diff --git a/apps/web-naive/src/components/table-action/typing.ts b/apps/web-naive/src/components/table-action/typing.ts new file mode 100644 index 0000000..ffe4761 --- /dev/null +++ b/apps/web-naive/src/components/table-action/typing.ts @@ -0,0 +1,28 @@ +import type { ButtonProps } from 'naive-ui/es/button/src/Button'; +import type { TooltipProps } from 'naive-ui/es/tooltip/src/Tooltip'; + +export interface PopConfirm { + title: string; + okText?: string; + cancelText?: string; + confirm: () => void; + cancel?: () => void; + icon?: string; + disabled?: boolean; +} + +export interface ActionItem extends ButtonProps { + onClick?: () => void; + type?: ButtonProps['type']; + label?: string; + color?: 'error' | 'success' | 'warning'; + icon?: string; + popConfirm?: PopConfirm; + disabled?: boolean; + divider?: boolean; + // 权限编码控制是否显示 + auth?: string[]; + // 业务控制是否显示 + ifShow?: ((action: ActionItem) => boolean) | boolean; + tooltip?: string | TooltipProps; +} diff --git a/apps/web-naive/src/components/upload/README.md b/apps/web-naive/src/components/upload/README.md new file mode 100644 index 0000000..7a64106 --- /dev/null +++ b/apps/web-naive/src/components/upload/README.md @@ -0,0 +1,260 @@ +# Upload Components - Naive UI 版本 + +本目录包含已重构为 Naive UI 的上传组件。 + +## 组件列表 + +### 1. ImageUpload - 图片上传组件 + +- **文件**: `image-upload.vue` +- **功能**: 专门用于图片上传的组件,支持图片预览 +- **特性**: + - 支持单图/多图上传 + - 支持图片预览(使用 NModal + NImage) + - 支持拖拽上传 + - 自动校验文件类型和大小 + - 支持自定义上传 API + - 支持进度显示 + +### 2. FileUpload - 文件上传组件 + +- **文件**: `file-upload.vue` +- **功能**: 通用文件上传组件 +- **特性**: + - 支持单文件/多文件上传 + - 支持拖拽上传区域 + - 支持文件预览和下载 + - 自动校验文件类型和大小 + - 支持自定义上传 API + - 支持进度显示 + - 支持返回文本内容(用于配置文件等) + +### 3. InputUpload - 输入框上传组件 + +- **文件**: `input-upload.vue` +- **功能**: 结合输入框和文件上传的组件 +- **特性**: + - 支持文本输入框或文本域 + - 支持通过上传文件自动填充内容 + - 使用 NGrid 布局,响应式设计 + +## 使用示例 + +### ImageUpload 图片上传 + +```vue + + + +``` + +### FileUpload 文件上传 + +```vue + + + +``` + +### InputUpload 输入框上传 + +```vue + + + +``` + +## Props 说明 + +### 通用 Props (FileUploadProps) + +| 属性 | 类型 | 默认值 | 说明 | +| ---------------- | -------------------- | ------- | ------------------ | +| modelValue/value | `string \| string[]` | - | v-model 绑定值 | +| accept | `string[]` | `[]` | 接受的文件类型 | +| maxSize | `number` | `2` | 文件最大大小(MB) | +| maxNumber | `number` | `1` | 最大文件数量 | +| multiple | `boolean` | `false` | 是否支持多选 | +| disabled | `boolean` | `false` | 是否禁用 | +| drag | `boolean` | `false` | 是否支持拖拽上传 | +| directory | `string` | - | 上传目录 | +| api | `Function` | - | 自定义上传 API | +| showDescription | `boolean` | - | 是否显示描述文本 | + +### ImageUpload 特有 Props + +| 属性 | 类型 | 默认值 | 说明 | +| --- | --- | --- | --- | +| listType | `string` | `'picture-card'` | 列表类型 | +| accept | `string[]` | `['jpg', 'jpeg', 'png', 'gif', 'webp']` | 接受的图片类型 | +| showDescription | `boolean` | `true` | 是否显示描述文本 | + +### InputUpload 特有 Props + +| 属性 | 类型 | 默认值 | 说明 | +| --------------- | ----------------------- | --------- | ---------------- | +| inputType | `'input' \| 'textarea'` | `'input'` | 输入框类型 | +| inputProps | `InputProps` | - | 输入框属性 | +| fileUploadProps | `FileUploadProps` | - | 文件上传组件属性 | + +## Events + +| 事件名 | 参数 | 说明 | +| --- | --- | --- | +| update:value | `value: string \| string[]` | 值更新事件 | +| update:modelValue | `value: string \| string[]` | v-model 更新事件 | +| change | `value: string \| string[]` | 值变化事件 | +| delete | `file: UploadFileInfo` | 删除文件事件 | +| preview | `file: UploadFileInfo` | 预览文件事件(仅 FileUpload) | +| returnText | `text: string` | 返回文件文本内容(仅 FileUpload) | + +## 辅助工具 + +### useUpload + +- **文件**: `use-upload.ts` +- **功能**: 提供上传相关的工具函数 +- **主要方法**: + - `httpRequest`: 统一的文件上传请求方法 + - `getUploadUrl`: 获取上传 URL + +### useUploadType + +- **功能**: 处理上传类型相关的逻辑 +- **主要方法**: + - `getStringAccept`: 获取 accept 字符串 + - `getHelpText`: 获取帮助文本 + +## 技术栈 + +- **UI 框架**: Naive UI +- **核心组件**: + - NUpload + - NImage + - NImageGroup + - NModal + - NButton + - NGrid + - NInput +- **工具库**: + - @vueuse/core + - @vben/utils + +## 注意事项 + +1. 文件状态使用 Naive UI 的状态值:`'pending' | 'uploading' | 'finished' | 'error' | 'removed'` +2. 所有文件 ID 使用 Naive UI 的 `id` 字段,而不是 `uid` +3. 上传前会自动校验文件类型和大小 +4. 支持两种上传模式: + - 客户端直接上传(S3) + - 通过后端上传 +5. 支持自定义上传 API,如果不提供则使用默认的上传接口 + +## 迁移指南 + +从 Ant Design Vue 迁移到 Naive UI 的主要变化: + +1. **组件导入**: + + ```typescript + // 旧 + import { Upload } from 'ant-design-vue'; + + // 新 + import { NUpload } from 'naive-ui'; + ``` + +2. **文件列表类型**: + + ```typescript + // 旧 + import type { UploadFile } from 'ant-design-vue'; + + // 新 + import type { UploadFileInfo } from 'naive-ui'; + ``` + +3. **状态值**: + + ```typescript + // 旧 + status: 'done'; + + // 新 + status: 'finished'; + ``` + +4. **事件回调**: + + ```typescript + // 旧 + @remove="handleRemove" + function handleRemove(file: UploadFile) { } + + // 新 + @remove="handleRemove" + function handleRemove(options: { file: UploadFileInfo; fileList: UploadFileInfo[] }) { } + ``` + +5. **自定义上传**: + + ```typescript + // 旧 + customRequest(info: UploadRequestOption) { + info.onSuccess!(res); + } + + // 新 + customRequest(options: UploadCustomRequestOptions) { + options.onFinish(); + } + ``` + +## 更新日志 + +### v1.0.0 (2025-01-16) + +- ✅ 将所有上传组件从 Ant Design Vue 重构为 Naive UI +- ✅ 保持原有功能和 API 兼容性 +- ✅ 优化代码结构和类型定义 +- ✅ 修复所有 linter 错误 +- ✅ 添加完整的文档说明 diff --git a/apps/web-naive/src/components/upload/file-upload.vue b/apps/web-naive/src/components/upload/file-upload.vue new file mode 100644 index 0000000..c16f48c --- /dev/null +++ b/apps/web-naive/src/components/upload/file-upload.vue @@ -0,0 +1,345 @@ + + + + + diff --git a/apps/web-naive/src/components/upload/image-upload.vue b/apps/web-naive/src/components/upload/image-upload.vue new file mode 100644 index 0000000..fb38c9d --- /dev/null +++ b/apps/web-naive/src/components/upload/image-upload.vue @@ -0,0 +1,341 @@ + + + + + diff --git a/apps/web-naive/src/components/upload/index.ts b/apps/web-naive/src/components/upload/index.ts new file mode 100644 index 0000000..14e57fe --- /dev/null +++ b/apps/web-naive/src/components/upload/index.ts @@ -0,0 +1,3 @@ +export { default as FileUpload } from './file-upload.vue'; +export { default as ImageUpload } from './image-upload.vue'; +export { default as InputUpload } from './input-upload.vue'; diff --git a/apps/web-naive/src/components/upload/input-upload.vue b/apps/web-naive/src/components/upload/input-upload.vue new file mode 100644 index 0000000..9cfb034 --- /dev/null +++ b/apps/web-naive/src/components/upload/input-upload.vue @@ -0,0 +1,81 @@ + + + diff --git a/apps/web-naive/src/components/upload/typing.ts b/apps/web-naive/src/components/upload/typing.ts new file mode 100644 index 0000000..ada73d2 --- /dev/null +++ b/apps/web-naive/src/components/upload/typing.ts @@ -0,0 +1,39 @@ +import type { AxiosResponse } from '@vben/request'; + +import type { AxiosProgressEvent } from '#/api/infra/file'; + +export enum UploadResultStatus { + DONE = 'done', + ERROR = 'error', + SUCCESS = 'success', + UPLOADING = 'uploading', +} + +export type UploadListType = 'picture' | 'picture-card' | 'text'; + +export interface FileUploadProps { + // 根据后缀,或者其他 + accept?: string[]; + api?: ( + file: File, + onUploadProgress?: AxiosProgressEvent, + ) => Promise>; + // 上传的目录 + directory?: string; + disabled?: boolean; + drag?: boolean; // 是否支持拖拽上传 + helpText?: string; + listType?: UploadListType; + // 最大数量的文件,Infinity不限制 + maxNumber?: number; + modelValue?: string | string[]; // v-model 支持 + // 文件最大多少MB + maxSize?: number; + // 是否支持多选 + multiple?: boolean; + // support xxx.xxx.xx + resultField?: string; + // 是否显示下面的描述 + showDescription?: boolean; + value?: string | string[]; +} diff --git a/apps/web-naive/src/components/upload/use-upload.ts b/apps/web-naive/src/components/upload/use-upload.ts new file mode 100644 index 0000000..2f46f9e --- /dev/null +++ b/apps/web-naive/src/components/upload/use-upload.ts @@ -0,0 +1,168 @@ +import type { Ref } from 'vue'; + +import type { AxiosProgressEvent, InfraFileApi } from '#/api/infra/file'; + +import { computed, unref } from 'vue'; + +import { useAppConfig } from '@vben/hooks'; +import { $t } from '@vben/locales'; + +import { createFile, getFilePresignedUrl, uploadFile } from '#/api/infra/file'; +import { baseRequestClient } from '#/api/request'; + +const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); + +/** + * 上传类型 + */ +enum UPLOAD_TYPE { + // 客户端直接上传(只支持S3服务) + CLIENT = 'client', + // 客户端发送到后端上传 + SERVER = 'server', +} + +export function useUploadType({ + acceptRef, + helpTextRef, + maxNumberRef, + maxSizeRef, +}: { + acceptRef: Ref; + helpTextRef: Ref; + maxNumberRef: Ref; + maxSizeRef: Ref; +}) { + // 文件类型限制 + const getAccept = computed(() => { + const accept = unref(acceptRef); + if (accept && accept.length > 0) { + return accept; + } + return []; + }); + const getStringAccept = computed(() => { + return unref(getAccept) + .map((item) => { + return item.indexOf('/') > 0 || item.startsWith('.') + ? item + : `.${item}`; + }) + .join(','); + }); + + // 支持jpg、jpeg、png格式,不超过2M,最多可选择10张图片,。 + const getHelpText = computed(() => { + const helpText = unref(helpTextRef); + if (helpText) { + return helpText; + } + const helpTexts: string[] = []; + + const accept = unref(acceptRef); + if (accept.length > 0) { + helpTexts.push($t('ui.upload.accept', [accept.join(',')])); + } + + const maxSize = unref(maxSizeRef); + if (maxSize) { + helpTexts.push($t('ui.upload.maxSize', [maxSize])); + } + + const maxNumber = unref(maxNumberRef); + if (maxNumber && maxNumber !== Infinity) { + helpTexts.push($t('ui.upload.maxNumber', [maxNumber])); + } + return helpTexts.join(','); + }); + return { getAccept, getStringAccept, getHelpText }; +} + +// TODO @芋艿:目前保持和 admin-vue3 一致,后续可能重构 +export function useUpload(directory?: string) { + // 后端上传地址 + const uploadUrl = getUploadUrl(); + // 是否使用前端直连上传 + const isClientUpload = + UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE; + // 重写ElUpload上传方法 + async function httpRequest( + file: File, + onUploadProgress?: AxiosProgressEvent, + ) { + // 模式一:前端上传 + if (isClientUpload) { + // 1.1 生成文件名称 + const fileName = await generateFileName(file); + // 1.2 获取文件预签名地址 + const presignedInfo = await getFilePresignedUrl(fileName, directory); + // 1.3 上传文件 + return baseRequestClient + .put(presignedInfo.uploadUrl, file, { + headers: { + 'Content-Type': file.type, + }, + }) + .then(() => { + // 1.4. 记录文件信息到后端(异步) + createFile0(presignedInfo, file); + // 通知成功,数据格式保持与后端上传的返回结果一致 + return { url: presignedInfo.url }; + }); + } else { + // 模式二:后端上传 + return uploadFile({ file, directory }, onUploadProgress); + } + } + + return { + uploadUrl, + httpRequest, + }; +} + +/** + * 获得上传 URL + */ +export function getUploadUrl(): string { + return `${apiURL}/infra/file/upload`; +} + +/** + * 创建文件信息 + * + * @param vo 文件预签名信息 + * @param file 文件 + */ +function createFile0( + vo: InfraFileApi.FilePresignedUrlRespVO, + file: File, +): InfraFileApi.File { + const fileVO = { + configId: vo.configId, + url: vo.url, + path: vo.path, + name: file.name, + type: file.type, + size: file.size, + }; + createFile(fileVO); + return fileVO; +} + +/** + * 生成文件名称(使用算法SHA256) + * + * @param file 要上传的文件 + */ +async function generateFileName(file: File) { + // // 读取文件内容 + // const data = await file.arrayBuffer(); + // const wordArray = CryptoJS.lib.WordArray.create(data); + // // 计算SHA256 + // const sha256 = CryptoJS.SHA256(wordArray).toString(); + // // 拼接后缀 + // const ext = file.name.slice(Math.max(0, file.name.lastIndexOf('.'))); + // return `${sha256}${ext}`; + return file.name; +} diff --git a/apps/web-naive/src/layouts/auth.vue b/apps/web-naive/src/layouts/auth.vue new file mode 100644 index 0000000..8ba66e8 --- /dev/null +++ b/apps/web-naive/src/layouts/auth.vue @@ -0,0 +1,25 @@ + + + diff --git a/apps/web-naive/src/layouts/basic.vue b/apps/web-naive/src/layouts/basic.vue new file mode 100644 index 0000000..256868f --- /dev/null +++ b/apps/web-naive/src/layouts/basic.vue @@ -0,0 +1,271 @@ + + + diff --git a/apps/web-naive/src/layouts/index.ts b/apps/web-naive/src/layouts/index.ts new file mode 100644 index 0000000..a432078 --- /dev/null +++ b/apps/web-naive/src/layouts/index.ts @@ -0,0 +1,6 @@ +const BasicLayout = () => import('./basic.vue'); +const AuthPageLayout = () => import('./auth.vue'); + +const IFrameView = () => import('@vben/layouts').then((m) => m.IFrameView); + +export { AuthPageLayout, BasicLayout, IFrameView }; diff --git a/apps/web-naive/src/locales/README.md b/apps/web-naive/src/locales/README.md new file mode 100644 index 0000000..7b45103 --- /dev/null +++ b/apps/web-naive/src/locales/README.md @@ -0,0 +1,3 @@ +# locale + +每个app使用的国际化可能不同,这里用于扩展国际化的功能,例如扩展 dayjs、antd组件库的多语言切换,以及app本身的国际化文件。 diff --git a/apps/web-naive/src/locales/index.ts b/apps/web-naive/src/locales/index.ts new file mode 100644 index 0000000..d994fb8 --- /dev/null +++ b/apps/web-naive/src/locales/index.ts @@ -0,0 +1,78 @@ +import type { App } from 'vue'; + +import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; + +import { + $t, + setupI18n as coreSetup, + loadLocalesMapFromDir, +} from '@vben/locales'; +import { preferences } from '@vben/preferences'; + +import dayjs from 'dayjs'; + +const modules = import.meta.glob('./langs/**/*.json'); + +const localesMap = loadLocalesMapFromDir( + /\.\/langs\/([^/]+)\/(.*)\.json$/, + modules, +); + +/** + * 加载应用特有的语言包 + * 这里也可以改造为从服务端获取翻译数据 + * @param lang + */ +async function loadMessages(lang: SupportedLanguagesType) { + const [appLocaleMessages] = await Promise.all([ + localesMap[lang]?.(), + loadThirdPartyMessage(lang), + ]); + return appLocaleMessages?.default; +} + +/** + * 加载第三方组件库的语言包 + * @param lang + */ +async function loadThirdPartyMessage(lang: SupportedLanguagesType) { + await loadDayjsLocale(lang); +} + +/** + * 加载dayjs的语言包 + * @param lang + */ +async function loadDayjsLocale(lang: SupportedLanguagesType) { + let locale; + switch (lang) { + case 'en-US': { + locale = await import('dayjs/locale/en'); + break; + } + case 'zh-CN': { + locale = await import('dayjs/locale/zh-cn'); + break; + } + // 默认使用英语 + default: { + locale = await import('dayjs/locale/en'); + } + } + if (locale) { + dayjs.locale(locale); + } else { + console.error(`Failed to load dayjs locale for ${lang}`); + } +} + +async function setupI18n(app: App, options: LocaleSetupOptions = {}) { + await coreSetup(app, { + defaultLocale: preferences.app.locale, + loadMessages, + missingWarn: !import.meta.env.PROD, + ...options, + }); +} + +export { $t, setupI18n }; diff --git a/apps/web-naive/src/locales/langs/en-US/page.json b/apps/web-naive/src/locales/langs/en-US/page.json new file mode 100644 index 0000000..130cb88 --- /dev/null +++ b/apps/web-naive/src/locales/langs/en-US/page.json @@ -0,0 +1,34 @@ +{ + "auth": { + "login": "Login", + "register": "Register", + "codeLogin": "Code Login", + "qrcodeLogin": "Qr Code Login", + "forgetPassword": "Forget Password", + "profile": "Profile" + }, + "dashboard": { + "title": "Dashboard", + "analytics": "Analytics", + "workspace": "Workspace" + }, + "action": { + "action": "Action", + "add": "Add", + "edit": "Edit", + "delete": "Delete", + "save": "Save", + "import": "Import", + "export": "Export", + "submit": "Submit", + "cancel": "Cancel", + "confirm": "Confirm", + "reset": "Reset", + "search": "Search", + "more": "More" + }, + "tenant": { + "placeholder": "Please select tenant", + "success": "Switch tenant success" + } +} diff --git a/apps/web-naive/src/locales/langs/en-US/utils.json b/apps/web-naive/src/locales/langs/en-US/utils.json new file mode 100644 index 0000000..b9206ef --- /dev/null +++ b/apps/web-naive/src/locales/langs/en-US/utils.json @@ -0,0 +1,14 @@ +{ + "rangePicker": { + "today": "Today", + "last7Days": "Last 7 Days", + "last30Days": "Last 30 Days", + "yesterday": "Yesterday", + "thisWeek": "This Week", + "thisMonth": "This Month", + "lastWeek": "Last Week", + "lastMonth": "Last Month", + "beginTime": "Begin Time", + "endTime": "End Time" + } +} diff --git a/apps/web-naive/src/locales/langs/zh-CN/page.json b/apps/web-naive/src/locales/langs/zh-CN/page.json new file mode 100644 index 0000000..d2af3b1 --- /dev/null +++ b/apps/web-naive/src/locales/langs/zh-CN/page.json @@ -0,0 +1,34 @@ +{ + "auth": { + "login": "登录", + "register": "注册", + "codeLogin": "验证码登录", + "qrcodeLogin": "二维码登录", + "forgetPassword": "忘记密码", + "profile": "个人中心" + }, + "dashboard": { + "title": "概览", + "analytics": "分析页", + "workspace": "工作台" + }, + "action": { + "action": "操作", + "add": "新增", + "edit": "编辑", + "delete": "删除", + "save": "保存", + "import": "导入", + "export": "导出", + "submit": "提交", + "cancel": "取消", + "confirm": "确认", + "reset": "重置", + "search": "搜索", + "more": "更多" + }, + "tenant": { + "placeholder": "请选择租户", + "success": "切换租户成功" + } +} diff --git a/apps/web-naive/src/locales/langs/zh-CN/utils.json b/apps/web-naive/src/locales/langs/zh-CN/utils.json new file mode 100644 index 0000000..d26f1f2 --- /dev/null +++ b/apps/web-naive/src/locales/langs/zh-CN/utils.json @@ -0,0 +1,14 @@ +{ + "rangePicker": { + "today": "今天", + "last7Days": "最近 7 天", + "last30Days": "最近 30 天", + "yesterday": "昨天", + "thisWeek": "本周", + "thisMonth": "本月", + "lastWeek": "上周", + "lastMonth": "上月", + "beginTime": "开始时间", + "endTime": "结束时间" + } +} diff --git a/apps/web-naive/src/main.ts b/apps/web-naive/src/main.ts new file mode 100644 index 0000000..5d728a0 --- /dev/null +++ b/apps/web-naive/src/main.ts @@ -0,0 +1,31 @@ +import { initPreferences } from '@vben/preferences'; +import { unmountGlobalLoading } from '@vben/utils'; + +import { overridesPreferences } from './preferences'; + +/** + * 应用初始化完成之后再进行页面加载渲染 + */ +async function initApplication() { + // name用于指定项目唯一标识 + // 用于区分不同项目的偏好设置以及存储数据的key前缀以及其他一些需要隔离的数据 + const env = import.meta.env.PROD ? 'prod' : 'dev'; + const appVersion = import.meta.env.VITE_APP_VERSION; + const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${appVersion}-${env}`; + + // app偏好设置初始化 + await initPreferences({ + namespace, + overrides: overridesPreferences, + }); + + // 启动应用并挂载 + // vue应用主要逻辑及视图 + const { bootstrap } = await import('./bootstrap'); + await bootstrap(namespace); + + // 移除并销毁loading + unmountGlobalLoading(); +} + +initApplication(); diff --git a/apps/web-naive/src/preferences.ts b/apps/web-naive/src/preferences.ts new file mode 100644 index 0000000..73eb135 --- /dev/null +++ b/apps/web-naive/src/preferences.ts @@ -0,0 +1,25 @@ +import { defineOverridesPreferences } from '@vben/preferences'; + +/** + * @description 项目配置文件 + * 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置 + * !!! 更改配置后请清空缓存,否则可能不生效 + */ +export const overridesPreferences = defineOverridesPreferences({ + // overrides + app: { + /** 后端路由模式 */ + accessMode: 'backend', + name: import.meta.env.VITE_APP_TITLE, + enableRefreshToken: true, + }, + footer: { + /** 默认关闭 footer 页脚,因为有一定遮挡 */ + enable: false, + fixed: false, + }, + copyright: { + companyName: import.meta.env.VITE_APP_TITLE, + companySiteLink: 'https://gitee.com/yudaocode/yudao-ui-admin-vben', + }, +}); diff --git a/apps/web-naive/src/router/access.ts b/apps/web-naive/src/router/access.ts new file mode 100644 index 0000000..c4b161a --- /dev/null +++ b/apps/web-naive/src/router/access.ts @@ -0,0 +1,41 @@ +import type { + AppRouteRecordRaw, + ComponentRecordType, + GenerateMenuAndRoutesOptions, +} from '@vben/types'; + +import { generateAccessible } from '@vben/access'; +import { preferences } from '@vben/preferences'; +import { useAccessStore } from '@vben/stores'; +import { convertServerMenuToRouteRecordStringComponent } from '@vben/utils'; + +import { BasicLayout, IFrameView } from '#/layouts'; + +const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue'); + +async function generateAccess(options: GenerateMenuAndRoutesOptions) { + const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue'); + const accessStore = useAccessStore(); + + const layoutMap: ComponentRecordType = { + BasicLayout, + IFrameView, + }; + + return await generateAccessible(preferences.app.accessMode, { + ...options, + fetchMenuListAsync: async () => { + // 由于 yudao 通过 accessStore 读取,所以不在进行 message.loading 提示 + // 补充说明:accessStore.accessMenus 一开始是 AppRouteRecordRaw 类型(后端加载),后面被赋值成 MenuRecordRaw 类型(前端转换) + const accessMenus = accessStore.accessMenus as AppRouteRecordRaw[]; + return convertServerMenuToRouteRecordStringComponent(accessMenus); + }, + // 可以指定没有权限跳转403页面 + forbiddenComponent, + // 如果 route.meta.menuVisibleWithForbidden = true + layoutMap, + pageMap, + }); +} + +export { generateAccess }; diff --git a/apps/web-naive/src/router/guard.ts b/apps/web-naive/src/router/guard.ts new file mode 100644 index 0000000..fa1119e --- /dev/null +++ b/apps/web-naive/src/router/guard.ts @@ -0,0 +1,153 @@ +import type { Router } from 'vue-router'; + +import { LOGIN_PATH } from '@vben/constants'; +import { $t } from '@vben/locales'; +import { preferences } from '@vben/preferences'; +import { useAccessStore, useDictStore, useUserStore } from '@vben/stores'; +import { startProgress, stopProgress } from '@vben/utils'; + +import { message } from '#/adapter/naive'; +import { getSimpleDictDataList } from '#/api/system/dict/data'; +import { accessRoutes, coreRouteNames } from '#/router/routes'; +import { useAuthStore } from '#/store'; + +import { generateAccess } from './access'; + +/** + * 通用守卫配置 + * @param router + */ +function setupCommonGuard(router: Router) { + // 记录已经加载的页面 + const loadedPaths = new Set(); + + router.beforeEach((to) => { + to.meta.loaded = loadedPaths.has(to.path); + + // 页面加载进度条 + if (!to.meta.loaded && preferences.transition.progress) { + startProgress(); + } + return true; + }); + + router.afterEach((to) => { + // 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行 + + loadedPaths.add(to.path); + + // 关闭页面加载进度条 + if (preferences.transition.progress) { + stopProgress(); + } + }); +} + +/** + * 权限访问守卫配置 + * @param router + */ +function setupAccessGuard(router: Router) { + router.beforeEach(async (to, from) => { + const accessStore = useAccessStore(); + const userStore = useUserStore(); + const authStore = useAuthStore(); + const dictStore = useDictStore(); + + // 基本路由,这些路由不需要进入权限拦截 + if (coreRouteNames.includes(to.name as string)) { + if (to.path === LOGIN_PATH && accessStore.accessToken) { + return decodeURIComponent( + (to.query?.redirect as string) || + userStore.userInfo?.homePath || + preferences.app.defaultHomePath, + ); + } + return true; + } + + // accessToken 检查 + if (!accessStore.accessToken) { + // 明确声明忽略权限访问权限,则可以访问 + if (to.meta.ignoreAccess) { + return true; + } + + // 没有访问权限,跳转登录页面 + if (to.fullPath !== LOGIN_PATH) { + return { + path: LOGIN_PATH, + // 如不需要,直接删除 query + query: + to.fullPath === preferences.app.defaultHomePath + ? {} + : { redirect: encodeURIComponent(to.fullPath) }, + // 携带当前跳转的页面,登录后重新跳转该页面 + replace: true, + }; + } + return to; + } + + // 是否已经生成过动态路由 + if (accessStore.isAccessChecked) { + return true; + } + + // 加载字典数据(不阻塞加载) + dictStore.setDictCacheByApi(getSimpleDictDataList); + + // 生成路由表 + // 当前登录用户拥有的角色标识列表 + let userInfo = userStore.userInfo; + if (!userInfo) { + // add by 芋艿:由于 yudao 是 fetchUserInfo 统一加载用户 + 权限信息,所以将 fetchMenuListAsync + const loading = message.loading(`${$t('common.loadingMenu')}...`); + try { + const authPermissionInfo = await authStore.fetchUserInfo(); + if (authPermissionInfo) { + userInfo = authPermissionInfo.user; + } + } finally { + loading.destroy(); + } + } + const userRoles = userStore.userRoles ?? []; + + // 生成菜单和路由 + const { accessibleMenus, accessibleRoutes } = await generateAccess({ + roles: userRoles, + router, + // 则会在菜单中显示,但是访问会被重定向到403 + routes: accessRoutes, + }); + + // 保存菜单信息和路由信息 + accessStore.setAccessMenus(accessibleMenus); + accessStore.setAccessRoutes(accessibleRoutes); + accessStore.setIsAccessChecked(true); + userStore.setUserRoles(userRoles); + const redirectPath = (from.query.redirect ?? + (to.path === preferences.app.defaultHomePath + ? userInfo?.homePath || preferences.app.defaultHomePath + : to.fullPath)) as string; + + return { + ...router.resolve(decodeURIComponent(redirectPath)), + replace: true, + }; + }); +} + +/** + * 项目守卫配置 + * @param router + */ +function createRouterGuard(router: Router) { + /** 通用 */ + setupCommonGuard(router); + /** 权限访问 */ + setupAccessGuard(router); +} + +export { createRouterGuard }; diff --git a/apps/web-naive/src/router/index.ts b/apps/web-naive/src/router/index.ts new file mode 100644 index 0000000..5acec55 --- /dev/null +++ b/apps/web-naive/src/router/index.ts @@ -0,0 +1,40 @@ +import { + createRouter, + createWebHashHistory, + createWebHistory, +} from 'vue-router'; + +import { resetStaticRoutes } from '@vben/utils'; + +import { createRouterGuard } from './guard'; +import { routes } from './routes'; +import { setupBaiduTongJi } from './tongji'; + +/** + * @zh_CN 创建vue-router实例 + */ +const router = createRouter({ + history: + import.meta.env.VITE_ROUTER_HISTORY === 'hash' + ? createWebHashHistory(import.meta.env.VITE_BASE) + : createWebHistory(import.meta.env.VITE_BASE), + // 应该添加到路由的初始路由列表。 + routes, + scrollBehavior: (to, _from, savedPosition) => { + if (savedPosition) { + return savedPosition; + } + return to.hash ? { behavior: 'smooth', el: to.hash } : { left: 0, top: 0 }; + }, + // 是否应该禁止尾部斜杠。 + // strict: true, +}); + +const resetRoutes = () => resetStaticRoutes(router, routes); + +// 创建路由守卫 +createRouterGuard(router); +// 设置百度统计 +setupBaiduTongJi(router); + +export { resetRoutes, router }; diff --git a/apps/web-naive/src/router/routes/core.ts b/apps/web-naive/src/router/routes/core.ts new file mode 100644 index 0000000..22fd001 --- /dev/null +++ b/apps/web-naive/src/router/routes/core.ts @@ -0,0 +1,114 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { LOGIN_PATH } from '@vben/constants'; +import { preferences } from '@vben/preferences'; + +import { $t } from '#/locales'; + +const BasicLayout = () => import('#/layouts/basic.vue'); +const AuthPageLayout = () => import('#/layouts/auth.vue'); +/** 全局404页面 */ +const fallbackNotFoundRoute: RouteRecordRaw = { + component: () => import('#/views/_core/fallback/not-found.vue'), + meta: { + hideInBreadcrumb: true, + hideInMenu: true, + hideInTab: true, + title: '404', + }, + name: 'FallbackNotFound', + path: '/:path(.*)*', +}; + +/** 基本路由,这些路由是必须存在的 */ +const coreRoutes: RouteRecordRaw[] = [ + /** + * 根路由 + * 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。 + * 此路由必须存在,且不应修改 + */ + { + component: BasicLayout, + meta: { + hideInBreadcrumb: true, + title: 'Root', + }, + name: 'Root', + path: '/', + redirect: preferences.app.defaultHomePath, + children: [], + }, + { + component: AuthPageLayout, + meta: { + hideInTab: true, + title: 'Authentication', + }, + name: 'Authentication', + path: '/auth', + redirect: LOGIN_PATH, + children: [ + { + name: 'Login', + path: 'login', + component: () => import('#/views/_core/authentication/login.vue'), + meta: { + title: $t('page.auth.login'), + }, + }, + { + name: 'CodeLogin', + path: 'code-login', + component: () => import('#/views/_core/authentication/code-login.vue'), + meta: { + title: $t('page.auth.codeLogin'), + }, + }, + { + name: 'QrCodeLogin', + path: 'qrcode-login', + component: () => + import('#/views/_core/authentication/qrcode-login.vue'), + meta: { + title: $t('page.auth.qrcodeLogin'), + }, + }, + { + name: 'ForgetPassword', + path: 'forget-password', + component: () => + import('#/views/_core/authentication/forget-password.vue'), + meta: { + title: $t('page.auth.forgetPassword'), + }, + }, + { + name: 'Register', + path: 'register', + component: () => import('#/views/_core/authentication/register.vue'), + meta: { + title: $t('page.auth.register'), + }, + }, + { + name: 'SocialLogin', + path: 'social-login', + component: () => + import('#/views/_core/authentication/social-login.vue'), + meta: { + title: $t('page.auth.login'), + }, + }, + { + name: 'SSOLogin', + path: 'sso-login', + component: () => import('#/views/_core/authentication/sso-login.vue'), + meta: { + title: $t('page.auth.login'), + }, + }, + ], + }, +]; + +export { coreRoutes, fallbackNotFoundRoute }; diff --git a/apps/web-naive/src/router/routes/index.ts b/apps/web-naive/src/router/routes/index.ts new file mode 100644 index 0000000..738f9d3 --- /dev/null +++ b/apps/web-naive/src/router/routes/index.ts @@ -0,0 +1,47 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { mergeRouteModules, traverseTreeValues } from '@vben/utils'; + +import { coreRoutes, fallbackNotFoundRoute } from './core'; + +const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', { + eager: true, +}); + +// 有需要可以自行打开注释,并创建文件夹 +// const externalRouteFiles = import.meta.glob('./external/**/*.ts', { eager: true }); +// const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true }); + +/** 动态路由 */ +const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles); + +/** 外部路由列表,访问这些页面可以不需要Layout,可能用于内嵌在别的系统(不会显示在菜单中) */ +// const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles); +// const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles); +const staticRoutes: RouteRecordRaw[] = []; +const externalRoutes: RouteRecordRaw[] = []; + +/** 路由列表,由基本路由、外部路由和404兜底路由组成 + * 无需走权限验证(会一直显示在菜单中) */ +const routes: RouteRecordRaw[] = [ + ...coreRoutes, + ...externalRoutes, + fallbackNotFoundRoute, +]; + +/** 基本路由列表,这些路由不需要进入权限拦截 */ +const coreRouteNames = traverseTreeValues(coreRoutes, (route) => route.name); + +/** 有权限校验的路由列表,包含动态路由和静态路由 */ +const accessRoutes = [...dynamicRoutes, ...staticRoutes]; + +// add by 芋艿:from https://github.com/vbenjs/vue-vben-admin/blob/main/playground/src/router/routes/index.ts#L38-L45 +const componentKeys: string[] = Object.keys( + import.meta.glob('../../views/**/*.vue'), +) + .filter((item) => !item.includes('/modules/')) + .map((v) => { + const path = v.replace('../../views/', '/'); + return path.endsWith('.vue') ? path.slice(0, -4) : path; + }); +export { accessRoutes, componentKeys, coreRouteNames, routes }; diff --git a/apps/web-naive/src/router/routes/modules/dashboard.ts b/apps/web-naive/src/router/routes/modules/dashboard.ts new file mode 100644 index 0000000..5254dc6 --- /dev/null +++ b/apps/web-naive/src/router/routes/modules/dashboard.ts @@ -0,0 +1,38 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { $t } from '#/locales'; + +const routes: RouteRecordRaw[] = [ + { + meta: { + icon: 'lucide:layout-dashboard', + order: -1, + title: $t('page.dashboard.title'), + }, + name: 'Dashboard', + path: '/dashboard', + children: [ + { + name: 'Analytics', + path: '/analytics', + component: () => import('#/views/dashboard/analytics/index.vue'), + meta: { + affixTab: true, + icon: 'lucide:area-chart', + title: $t('page.dashboard.analytics'), + }, + }, + { + name: 'Workspace', + path: '/workspace', + component: () => import('#/views/dashboard/workspace/index.vue'), + meta: { + icon: 'carbon:workspace', + title: $t('page.dashboard.workspace'), + }, + }, + ], + }, +]; + +export default routes; diff --git a/apps/web-naive/src/router/routes/modules/infra.ts b/apps/web-naive/src/router/routes/modules/infra.ts new file mode 100644 index 0000000..c99b51b --- /dev/null +++ b/apps/web-naive/src/router/routes/modules/infra.ts @@ -0,0 +1,30 @@ +import type { RouteRecordRaw } from 'vue-router'; + +const routes: RouteRecordRaw[] = [ + { + path: '/infra/job/log', + component: () => import('#/views/infra/job/logger/index.vue'), + name: 'InfraJobLog', + meta: { + title: '调度日志', + icon: 'ant-design:history-outlined', + activePath: '/infra/job', + keepAlive: false, + hideInMenu: true, + }, + }, + { + path: '/infra/codegen/edit', + component: () => import('#/views/infra/codegen/edit/index.vue'), + name: 'InfraCodegenEdit', + meta: { + title: '生成配置修改', + icon: 'ic:baseline-view-in-ar', + activePath: '/infra/codegen', + keepAlive: true, + hideInMenu: true, + }, + }, +]; + +export default routes; diff --git a/apps/web-naive/src/router/routes/modules/system.ts b/apps/web-naive/src/router/routes/modules/system.ts new file mode 100644 index 0000000..47e6b16 --- /dev/null +++ b/apps/web-naive/src/router/routes/modules/system.ts @@ -0,0 +1,16 @@ +import type { RouteRecordRaw } from 'vue-router'; + +const routes: RouteRecordRaw[] = [ + { + path: '/system/notify-message', + component: () => import('#/views/system/notify/my/index.vue'), + name: 'MyNotifyMessage', + meta: { + title: '我的站内信', + icon: 'ant-design:message-filled', + hideInMenu: true, + }, + }, +]; + +export default routes; diff --git a/apps/web-naive/src/router/tongji.ts b/apps/web-naive/src/router/tongji.ts new file mode 100644 index 0000000..0aa3715 --- /dev/null +++ b/apps/web-naive/src/router/tongji.ts @@ -0,0 +1,30 @@ +import type { Router } from 'vue-router'; + +declare global { + interface Window { + _hmt: any[]; + } +} + +const HM_ID = import.meta.env.VITE_APP_BAIDU_CODE; + +/** + * 设置百度统计 + * @param router + */ +function setupBaiduTongJi(router: Router) { + // 如果没有配置百度统计的 ID,则不进行设置 + if (!HM_ID) { + return; + } + + // _hmt:用于 router push + window._hmt = window._hmt || []; + + router.afterEach((to) => { + // 添加到 _hmt 中 + window._hmt.push(['_trackPageview', to.fullPath]); + }); +} + +export { setupBaiduTongJi }; diff --git a/apps/web-naive/src/store/auth.ts b/apps/web-naive/src/store/auth.ts new file mode 100644 index 0000000..561c981 --- /dev/null +++ b/apps/web-naive/src/store/auth.ts @@ -0,0 +1,157 @@ +import type { AuthPermissionInfo, Recordable, UserInfo } from '@vben/types'; + +import type { AuthApi } from '#/api'; + +import { ref } from 'vue'; +import { useRouter } from 'vue-router'; + +import { LOGIN_PATH } from '@vben/constants'; +import { preferences } from '@vben/preferences'; +import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores'; + +import { defineStore } from 'pinia'; + +import { notification } from '#/adapter/naive'; +import { + getAuthPermissionInfoApi, + loginApi, + logoutApi, + register, + smsLogin, + socialLogin, +} from '#/api'; +import { $t } from '#/locales'; + +export const useAuthStore = defineStore('auth', () => { + const accessStore = useAccessStore(); + const userStore = useUserStore(); + const router = useRouter(); + + const loginLoading = ref(false); + + /** + * 异步处理登录操作 + * Asynchronously handle the login process + * @param type 登录类型 + * @param params 登录表单数据 + * @param onSuccess 登录成功后的回调函数 + */ + async function authLogin( + type: 'mobile' | 'register' | 'social' | 'username', + params: Recordable, + onSuccess?: () => Promise | void, + ) { + // 异步处理用户登录操作并获取 accessToken + let userInfo: null | UserInfo = null; + try { + let loginResult: AuthApi.LoginResult; + loginLoading.value = true; + switch (type) { + case 'mobile': { + loginResult = await smsLogin(params as AuthApi.SmsLoginParams); + break; + } + case 'register': { + loginResult = await register(params as AuthApi.RegisterParams); + break; + } + case 'social': { + loginResult = await socialLogin(params as AuthApi.SocialLoginParams); + break; + } + default: { + loginResult = await loginApi(params); + } + } + const { accessToken, refreshToken } = loginResult; + + // 如果成功获取到 accessToken + if (accessToken) { + accessStore.setAccessToken(accessToken); + accessStore.setRefreshToken(refreshToken); + + // 获取用户信息并存储到 userStore、accessStore 中 + // TODO @芋艿:清理掉 accessCodes 相关的逻辑 + // const [fetchUserInfoResult, accessCodes] = await Promise.all([ + // fetchUserInfo(), + // // getAccessCodesApi(), + // ]); + const fetchUserInfoResult = await fetchUserInfo(); + + userInfo = fetchUserInfoResult.user; + + if (accessStore.loginExpired) { + accessStore.setLoginExpired(false); + } else { + onSuccess + ? await onSuccess?.() + : await router.push( + userInfo.homePath || preferences.app.defaultHomePath, + ); + } + + if (userInfo?.nickname) { + notification.success({ + content: $t('authentication.loginSuccess'), + description: `${$t('authentication.loginSuccessDesc')}:${userInfo?.nickname}`, + duration: 3000, + }); + } + } + } finally { + loginLoading.value = false; + } + + return { + userInfo, + }; + } + + async function logout(redirect: boolean = true) { + try { + const accessToken = accessStore.accessToken as string; + if (accessToken) { + await logoutApi(accessToken); + } + } catch { + // 不做任何处理 + } + resetAllStores(); + accessStore.setLoginExpired(false); + + // 回登录页带上当前路由地址 + await router.replace({ + path: LOGIN_PATH, + query: redirect + ? { + redirect: encodeURIComponent(router.currentRoute.value.fullPath), + } + : {}, + }); + } + + async function fetchUserInfo() { + // 加载 + let authPermissionInfo: AuthPermissionInfo | null = null; + authPermissionInfo = await getAuthPermissionInfoApi(); + // userStore + userStore.setUserInfo(authPermissionInfo.user); + userStore.setUserRoles(authPermissionInfo.roles); + // accessStore + accessStore.setAccessMenus(authPermissionInfo.menus); + accessStore.setAccessCodes(authPermissionInfo.permissions); + return authPermissionInfo; + } + + function $reset() { + loginLoading.value = false; + } + + return { + $reset, + authLogin, + fetchUserInfo, + loginLoading, + logout, + }; +}); diff --git a/apps/web-naive/src/store/index.ts b/apps/web-naive/src/store/index.ts new file mode 100644 index 0000000..269586e --- /dev/null +++ b/apps/web-naive/src/store/index.ts @@ -0,0 +1 @@ +export * from './auth'; diff --git a/apps/web-naive/src/utils/index.ts b/apps/web-naive/src/utils/index.ts new file mode 100644 index 0000000..800284d --- /dev/null +++ b/apps/web-naive/src/utils/index.ts @@ -0,0 +1 @@ +export * from './rangePickerProps'; diff --git a/apps/web-naive/src/utils/rangePickerProps.ts b/apps/web-naive/src/utils/rangePickerProps.ts new file mode 100644 index 0000000..a3ffaf3 --- /dev/null +++ b/apps/web-naive/src/utils/rangePickerProps.ts @@ -0,0 +1,52 @@ +import dayjs from 'dayjs'; + +import { $t } from '#/locales'; + +/** 时间段选择器拓展 */ +export function getRangePickerDefaultProps() { + return { + startPlaceholder: $t('utils.rangePicker.beginTime'), + endPlaceholder: $t('utils.rangePicker.endTime'), + type: 'datetimerange', + format: 'YYYY-MM-dd HH:mm:ss', + valueFormat: 'YYYY-MM-dd HH:mm:ss', + defaultTime: ['00:00:00', '23:59:59'], + shortcuts: { + [$t('utils.rangePicker.today')]: () => + [ + dayjs().startOf('day').toDate(), + dayjs().endOf('day').toDate(), + ] as const, + [$t('utils.rangePicker.last7Days')]: () => + [ + dayjs().subtract(7, 'day').startOf('day').toDate(), + dayjs().endOf('day').toDate(), + ] as const, + [$t('utils.rangePicker.last30Days')]: () => + [ + dayjs().subtract(30, 'day').startOf('day').toDate(), + dayjs().endOf('day').toDate(), + ] as const, + [$t('utils.rangePicker.yesterday')]: () => + [ + dayjs().subtract(1, 'day').startOf('day').toDate(), + dayjs().subtract(1, 'day').endOf('day').toDate(), + ] as const, + [$t('utils.rangePicker.thisWeek')]: () => + [ + dayjs().startOf('week').toDate(), + dayjs().endOf('day').toDate(), + ] as const, + [$t('utils.rangePicker.thisMonth')]: () => + [ + dayjs().startOf('month').toDate(), + dayjs().endOf('day').toDate(), + ] as const, + [$t('utils.rangePicker.lastWeek')]: () => + [ + dayjs().subtract(1, 'week').startOf('day').toDate(), + dayjs().endOf('day').toDate(), + ] as const, + }, + }; +} diff --git a/apps/web-naive/src/views/_core/README.md b/apps/web-naive/src/views/_core/README.md new file mode 100644 index 0000000..8248afe --- /dev/null +++ b/apps/web-naive/src/views/_core/README.md @@ -0,0 +1,3 @@ +# \_core + +此目录包含应用程序正常运行所需的基本视图。这些视图是应用程序布局中使用的视图。 diff --git a/apps/web-naive/src/views/_core/about/index.vue b/apps/web-naive/src/views/_core/about/index.vue new file mode 100644 index 0000000..0ee5243 --- /dev/null +++ b/apps/web-naive/src/views/_core/about/index.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-naive/src/views/_core/authentication/code-login.vue b/apps/web-naive/src/views/_core/authentication/code-login.vue new file mode 100644 index 0000000..b8c55d8 --- /dev/null +++ b/apps/web-naive/src/views/_core/authentication/code-login.vue @@ -0,0 +1,172 @@ + + + diff --git a/apps/web-naive/src/views/_core/authentication/forget-password.vue b/apps/web-naive/src/views/_core/authentication/forget-password.vue new file mode 100644 index 0000000..e66c899 --- /dev/null +++ b/apps/web-naive/src/views/_core/authentication/forget-password.vue @@ -0,0 +1,215 @@ + + + diff --git a/apps/web-naive/src/views/_core/authentication/login.vue b/apps/web-naive/src/views/_core/authentication/login.vue new file mode 100644 index 0000000..aa1db4c --- /dev/null +++ b/apps/web-naive/src/views/_core/authentication/login.vue @@ -0,0 +1,192 @@ + + + diff --git a/apps/web-naive/src/views/_core/authentication/qrcode-login.vue b/apps/web-naive/src/views/_core/authentication/qrcode-login.vue new file mode 100644 index 0000000..23f5f2d --- /dev/null +++ b/apps/web-naive/src/views/_core/authentication/qrcode-login.vue @@ -0,0 +1,10 @@ + + + diff --git a/apps/web-naive/src/views/_core/authentication/register.vue b/apps/web-naive/src/views/_core/authentication/register.vue new file mode 100644 index 0000000..734f4c2 --- /dev/null +++ b/apps/web-naive/src/views/_core/authentication/register.vue @@ -0,0 +1,221 @@ + + + diff --git a/apps/web-naive/src/views/_core/authentication/social-login.vue b/apps/web-naive/src/views/_core/authentication/social-login.vue new file mode 100644 index 0000000..1052a9a --- /dev/null +++ b/apps/web-naive/src/views/_core/authentication/social-login.vue @@ -0,0 +1,210 @@ + + + diff --git a/apps/web-naive/src/views/_core/authentication/sso-login.vue b/apps/web-naive/src/views/_core/authentication/sso-login.vue new file mode 100644 index 0000000..1bc7ad9 --- /dev/null +++ b/apps/web-naive/src/views/_core/authentication/sso-login.vue @@ -0,0 +1,221 @@ + + + diff --git a/apps/web-naive/src/views/_core/fallback/coming-soon.vue b/apps/web-naive/src/views/_core/fallback/coming-soon.vue new file mode 100644 index 0000000..f394930 --- /dev/null +++ b/apps/web-naive/src/views/_core/fallback/coming-soon.vue @@ -0,0 +1,7 @@ + + + diff --git a/apps/web-naive/src/views/_core/fallback/forbidden.vue b/apps/web-naive/src/views/_core/fallback/forbidden.vue new file mode 100644 index 0000000..8ea65fe --- /dev/null +++ b/apps/web-naive/src/views/_core/fallback/forbidden.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-naive/src/views/_core/fallback/internal-error.vue b/apps/web-naive/src/views/_core/fallback/internal-error.vue new file mode 100644 index 0000000..819a47d --- /dev/null +++ b/apps/web-naive/src/views/_core/fallback/internal-error.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-naive/src/views/_core/fallback/not-found.vue b/apps/web-naive/src/views/_core/fallback/not-found.vue new file mode 100644 index 0000000..4d178e9 --- /dev/null +++ b/apps/web-naive/src/views/_core/fallback/not-found.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-naive/src/views/_core/fallback/offline.vue b/apps/web-naive/src/views/_core/fallback/offline.vue new file mode 100644 index 0000000..5de4a88 --- /dev/null +++ b/apps/web-naive/src/views/_core/fallback/offline.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-naive/src/views/_core/profile/base-setting.vue b/apps/web-naive/src/views/_core/profile/base-setting.vue new file mode 100644 index 0000000..8a113e3 --- /dev/null +++ b/apps/web-naive/src/views/_core/profile/base-setting.vue @@ -0,0 +1,101 @@ + + diff --git a/apps/web-naive/src/views/_core/profile/index.vue b/apps/web-naive/src/views/_core/profile/index.vue new file mode 100644 index 0000000..8740894 --- /dev/null +++ b/apps/web-naive/src/views/_core/profile/index.vue @@ -0,0 +1,49 @@ + + diff --git a/apps/web-naive/src/views/_core/profile/notification-setting.vue b/apps/web-naive/src/views/_core/profile/notification-setting.vue new file mode 100644 index 0000000..324a4b3 --- /dev/null +++ b/apps/web-naive/src/views/_core/profile/notification-setting.vue @@ -0,0 +1,31 @@ + + diff --git a/apps/web-naive/src/views/_core/profile/password-setting.vue b/apps/web-naive/src/views/_core/profile/password-setting.vue new file mode 100644 index 0000000..9857dc8 --- /dev/null +++ b/apps/web-naive/src/views/_core/profile/password-setting.vue @@ -0,0 +1,63 @@ + + diff --git a/apps/web-naive/src/views/_core/profile/security-setting.vue b/apps/web-naive/src/views/_core/profile/security-setting.vue new file mode 100644 index 0000000..be30db5 --- /dev/null +++ b/apps/web-naive/src/views/_core/profile/security-setting.vue @@ -0,0 +1,43 @@ + + diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue new file mode 100644 index 0000000..f1f0b23 --- /dev/null +++ b/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue @@ -0,0 +1,98 @@ + + + diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-data.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-data.vue new file mode 100644 index 0000000..190fb41 --- /dev/null +++ b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-data.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-sales.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-sales.vue new file mode 100644 index 0000000..6ff5208 --- /dev/null +++ b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-sales.vue @@ -0,0 +1,46 @@ + + + diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-source.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-source.vue new file mode 100644 index 0000000..0915c7a --- /dev/null +++ b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-source.vue @@ -0,0 +1,65 @@ + + + diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits.vue new file mode 100644 index 0000000..7e0f101 --- /dev/null +++ b/apps/web-naive/src/views/dashboard/analytics/analytics-visits.vue @@ -0,0 +1,55 @@ + + + diff --git a/apps/web-naive/src/views/dashboard/analytics/index.vue b/apps/web-naive/src/views/dashboard/analytics/index.vue new file mode 100644 index 0000000..5e3d6d2 --- /dev/null +++ b/apps/web-naive/src/views/dashboard/analytics/index.vue @@ -0,0 +1,90 @@ + + + diff --git a/apps/web-naive/src/views/dashboard/workspace/index.vue b/apps/web-naive/src/views/dashboard/workspace/index.vue new file mode 100644 index 0000000..b95d613 --- /dev/null +++ b/apps/web-naive/src/views/dashboard/workspace/index.vue @@ -0,0 +1,266 @@ + + + diff --git a/apps/web-naive/src/views/infra/apiAccessLog/data.ts b/apps/web-naive/src/views/infra/apiAccessLog/data.ts new file mode 100644 index 0000000..7069288 --- /dev/null +++ b/apps/web-naive/src/views/infra/apiAccessLog/data.ts @@ -0,0 +1,273 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { JsonViewer } from '@vben/common-ui'; +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入用户编号', + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + clearable: true, + placeholder: '请选择用户类型', + }, + }, + { + fieldName: 'applicationName', + label: '应用名', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入应用名', + }, + }, + { + fieldName: 'beginTime', + label: '请求时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'duration', + label: '执行时长', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入执行时长', + }, + }, + { + fieldName: 'resultCode', + label: '结果码', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入结果码', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '日志编号', + minWidth: 100, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 100, + }, + { + field: 'userType', + title: '用户类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.USER_TYPE }, + }, + }, + { + field: 'applicationName', + title: '应用名', + minWidth: 150, + }, + { + field: 'requestMethod', + title: '请求方法', + minWidth: 80, + }, + { + field: 'requestUrl', + title: '请求地址', + minWidth: 300, + }, + { + field: 'beginTime', + title: '请求时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'duration', + title: '执行时长', + minWidth: 120, + formatter: ({ cellValue }) => `${cellValue} ms`, + }, + { + field: 'resultCode', + title: '操作结果', + minWidth: 150, + formatter: ({ row }) => { + return row.resultCode === 0 ? '成功' : `失败(${row.resultMsg})`; + }, + }, + { + field: 'operateModule', + title: '操作模块', + minWidth: 150, + }, + { + field: 'operateName', + title: '操作名', + minWidth: 220, + }, + { + field: 'operateType', + title: '操作类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_OPERATE_TYPE }, + }, + }, + { + title: '操作', + width: 80, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'id', + label: '日志编号', + }, + { + field: 'traceId', + label: '链路追踪', + }, + { + field: 'applicationName', + label: '应用名', + }, + { + field: 'userId', + label: '用户Id', + }, + { + field: 'userType', + label: '用户类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.USER_TYPE, + value: val, + }); + }, + }, + { + field: 'userIp', + label: '用户 IP', + }, + { + field: 'userAgent', + label: '用户 UA', + }, + { + field: 'requestMethod', + label: '请求信息', + render: (val, data) => { + if (val && data?.requestUrl) { + return `${val} ${data.requestUrl}`; + } + return ''; + }, + }, + { + field: 'requestParams', + label: '请求参数', + render: (val) => { + if (val) { + return h(JsonViewer, { + value: JSON.parse(val), + previewMode: true, + }); + } + return ''; + }, + }, + { + field: 'responseBody', + label: '请求结果', + }, + { + label: '请求时间', + field: 'beginTime', + render: (val, data) => { + if (val && data?.endTime) { + return `${formatDateTime(val)} ~ ${formatDateTime(data.endTime)}`; + } + return ''; + }, + }, + { + label: '请求耗时', + field: 'duration', + render: (val) => { + return val ? `${val} ms` : ''; + }, + }, + { + label: '操作结果', + field: 'resultCode', + render: (val, data) => { + if (val === 0) { + return '正常'; + } else if (val > 0 && data?.resultMsg) { + return `失败 | ${val} | ${data.resultMsg}`; + } + return ''; + }, + }, + { + field: 'operateModule', + label: '操作模块', + }, + { + field: 'operateName', + label: '操作名', + }, + { + field: 'operateType', + label: '操作类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.INFRA_OPERATE_TYPE, + value: val, + }); + }, + }, + ]; +} diff --git a/apps/web-naive/src/views/infra/apiAccessLog/index.vue b/apps/web-naive/src/views/infra/apiAccessLog/index.vue new file mode 100644 index 0000000..af7cc01 --- /dev/null +++ b/apps/web-naive/src/views/infra/apiAccessLog/index.vue @@ -0,0 +1,107 @@ + + + diff --git a/apps/web-naive/src/views/infra/apiAccessLog/modules/detail.vue b/apps/web-naive/src/views/infra/apiAccessLog/modules/detail.vue new file mode 100644 index 0000000..5fd1e5e --- /dev/null +++ b/apps/web-naive/src/views/infra/apiAccessLog/modules/detail.vue @@ -0,0 +1,49 @@ + + + diff --git a/apps/web-naive/src/views/infra/apiErrorLog/data.ts b/apps/web-naive/src/views/infra/apiErrorLog/data.ts new file mode 100644 index 0000000..87316a9 --- /dev/null +++ b/apps/web-naive/src/views/infra/apiErrorLog/data.ts @@ -0,0 +1,249 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { JsonViewer } from '@vben/common-ui'; +import { DICT_TYPE, InfraApiErrorLogProcessStatusEnum } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDateTime } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入用户编号', + }, + }, + { + fieldName: 'userType', + label: '用户类型', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), + clearable: true, + placeholder: '请选择用户类型', + }, + }, + { + fieldName: 'applicationName', + label: '应用名', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入应用名', + }, + }, + { + fieldName: 'exceptionTime', + label: '异常时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + { + fieldName: 'processStatus', + label: '处理状态', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS, + 'number', + ), + clearable: true, + placeholder: '请选择处理状态', + }, + defaultValue: InfraApiErrorLogProcessStatusEnum.INIT, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '日志编号', + minWidth: 100, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 100, + }, + { + field: 'userType', + title: '用户类型', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.USER_TYPE }, + }, + }, + { + field: 'applicationName', + title: '应用名', + minWidth: 150, + }, + { + field: 'requestMethod', + title: '请求方法', + minWidth: 80, + }, + { + field: 'requestUrl', + title: '请求地址', + minWidth: 200, + }, + { + field: 'exceptionTime', + title: '异常发生时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'exceptionName', + title: '异常名', + minWidth: 180, + }, + { + field: 'processStatus', + title: '处理状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS }, + }, + }, + { + title: '操作', + minWidth: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'id', + label: '日志编号', + }, + { + field: 'traceId', + label: '链路追踪', + }, + { + field: 'applicationName', + label: '应用名', + }, + { + field: 'userId', + label: '用户Id', + }, + { + field: 'userType', + label: '用户类型', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.USER_TYPE, + value: val, + }); + }, + }, + { + field: 'userIp', + label: '用户 IP', + }, + { + field: 'userAgent', + label: '用户 UA', + }, + { + field: 'requestMethod', + label: '请求信息', + render: (val, data) => { + if (val && data?.requestUrl) { + return `${val} ${data.requestUrl}`; + } + return ''; + }, + }, + { + field: 'requestParams', + label: '请求参数', + render: (val) => { + if (val) { + return h(JsonViewer, { + value: JSON.parse(val), + previewMode: true, + }); + } + return ''; + }, + }, + { + field: 'exceptionTime', + label: '异常时间', + render: (val) => { + return formatDateTime(val) as string; + }, + }, + { + field: 'exceptionName', + label: '异常名', + }, + { + field: 'exceptionStackTrace', + label: '异常堆栈', + show: (val) => !val, + render: (val) => { + if (val) { + return h('textarea', { + value: val, + style: + 'width: 100%; min-height: 200px; max-height: 400px; resize: vertical;', + readonly: true, + }); + } + return ''; + }, + }, + { + field: 'processStatus', + label: '处理状态', + render: (val) => { + return h(DictTag, { + type: DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS, + value: val, + }); + }, + }, + { + field: 'processUserId', + label: '处理人', + show: (val) => !val, + }, + { + field: 'processTime', + label: '处理时间', + show: (val) => !val, + render: (val) => { + return formatDateTime(val) as string; + }, + }, + ]; +} diff --git a/apps/web-naive/src/views/infra/apiErrorLog/index.vue b/apps/web-naive/src/views/infra/apiErrorLog/index.vue new file mode 100644 index 0000000..ad9748b --- /dev/null +++ b/apps/web-naive/src/views/infra/apiErrorLog/index.vue @@ -0,0 +1,155 @@ + + + diff --git a/apps/web-naive/src/views/infra/apiErrorLog/modules/detail.vue b/apps/web-naive/src/views/infra/apiErrorLog/modules/detail.vue new file mode 100644 index 0000000..b46a368 --- /dev/null +++ b/apps/web-naive/src/views/infra/apiErrorLog/modules/detail.vue @@ -0,0 +1,49 @@ + + + diff --git a/apps/web-naive/src/views/infra/build/index.vue b/apps/web-naive/src/views/infra/build/index.vue new file mode 100644 index 0000000..a976d98 --- /dev/null +++ b/apps/web-naive/src/views/infra/build/index.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-naive/src/views/infra/codegen/data.ts b/apps/web-naive/src/views/infra/codegen/data.ts new file mode 100644 index 0000000..ed742d8 --- /dev/null +++ b/apps/web-naive/src/views/infra/codegen/data.ts @@ -0,0 +1,553 @@ +import type { Recordable } from '@vben/types'; + +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { InfraCodegenApi } from '#/api/infra/codegen'; +import type { SystemMenuApi } from '#/api/system/menu'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { IconifyIcon } from '@vben/icons'; +import { handleTree } from '@vben/utils'; + +import { getDataSourceConfigList } from '#/api/infra/data-source-config'; +import { getMenuList } from '#/api/system/menu'; +import { $t } from '#/locales'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 导入数据库表的表单 */ +export function useImportTableFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'dataSourceConfigId', + label: '数据源', + component: 'ApiSelect', + componentProps: { + api: getDataSourceConfigList, + labelField: 'name', + valueField: 'id', + autoSelect: 'first', + placeholder: '请选择数据源', + }, + rules: 'selectRequired', + }, + { + fieldName: 'name', + label: '表名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入表名称', + }, + }, + { + fieldName: 'comment', + label: '表描述', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入表描述', + }, + }, + ]; +} + +/** 导入数据库表表格列定义 */ +export function useImportTableColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { field: 'name', title: '表名称', minWidth: 200 }, + { field: 'comment', title: '表描述', minWidth: 200 }, + ]; +} + +/** 基本信息表单的 schema */ +export function useBasicInfoFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'tableName', + label: '表名称', + component: 'Input', + componentProps: { + placeholder: '请输入仓库名称', + }, + rules: 'required', + }, + { + fieldName: 'tableComment', + label: '表描述', + component: 'Input', + componentProps: { + placeholder: '请输入表描述', + }, + rules: 'required', + }, + { + fieldName: 'className', + label: '实体类名称', + component: 'Input', + componentProps: { + placeholder: '请输入实体类名称', + }, + rules: 'required', + help: '默认去除表名的前缀。如果存在重复,则需要手动添加前缀,避免 MyBatis 报 Alias 重复的问题。', + }, + { + fieldName: 'author', + label: '作者', + component: 'Input', + componentProps: { + placeholder: '请输入作者', + }, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + type: 'textarea', + rows: 3, + placeholder: '请输入备注', + }, + formItemClass: 'md:col-span-2', + }, + ]; +} + +/** 生成信息表单基础 schema */ +export function useGenerationInfoBaseFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Select', + fieldName: 'templateType', + label: '生成模板', + componentProps: { + options: getDictOptions( + DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE, + 'number', + ), + class: 'w-full', + }, + rules: 'selectRequired', + }, + { + component: 'Select', + fieldName: 'frontType', + label: '前端类型', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_CODEGEN_FRONT_TYPE, 'number'), + class: 'w-full', + }, + rules: 'selectRequired', + }, + { + component: 'Select', + fieldName: 'scene', + label: '生成场景', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_CODEGEN_SCENE, 'number'), + class: 'w-full', + }, + rules: 'selectRequired', + }, + { + fieldName: 'parentMenuId', + label: '上级菜单', + help: '分配到指定菜单下,例如 系统管理', + component: 'ApiTreeSelect', + componentProps: { + clearable: true, + api: async () => { + const data = await getMenuList(); + data.unshift({ + id: 0, + name: '顶级菜单', + } as SystemMenuApi.Menu); + return handleTree(data); + }, + class: 'w-full', + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择上级菜单', + filterTreeNode(input: string, node: Recordable) { + if (!input || input.length === 0) { + return true; + } + const name: string = node.label ?? ''; + if (!name) return false; + return name.includes(input) || $t(name).includes(input); + }, + showSearch: true, + treeDefaultExpandedKeys: [0], + }, + rules: 'selectRequired', + renderComponentContent() { + return { + title({ label, icon }: { icon: string; label: string }) { + const components = []; + if (!label) return ''; + if (icon) { + components.push(h(IconifyIcon, { class: 'size-4', icon })); + } + components.push(h('span', { class: '' }, $t(label || ''))); + return h('div', { class: 'flex items-center gap-1' }, components); + }, + }; + }, + }, + { + component: 'Input', + fieldName: 'moduleName', + label: '模块名', + help: '模块名,即一级目录,例如 system、infra、tool 等等', + rules: 'required', + }, + { + component: 'Input', + fieldName: 'businessName', + label: '业务名', + help: '业务名,即二级目录,例如 user、permission、dict 等等', + rules: 'required', + }, + { + component: 'Input', + fieldName: 'className', + label: '类名称', + help: '类名称(首字母大写),例如SysUser、SysMenu、SysDictData 等等', + rules: 'required', + }, + { + component: 'Input', + fieldName: 'classComment', + label: '类描述', + help: '用作类描述,例如 用户', + rules: 'required', + }, + ]; +} + +/** 树表信息 schema */ +export function useGenerationInfoTreeFormSchema( + columns: InfraCodegenApi.CodegenColumn[] = [], +): VbenFormSchema[] { + return [ + { + component: 'Divider', + fieldName: 'treeDivider', + label: '', + renderComponentContent: () => { + return { + default: () => ['树表信息'], + }; + }, + formItemClass: 'md:col-span-2', + }, + { + component: 'Select', + fieldName: 'treeParentColumnId', + label: '父编号字段', + help: '树显示的父编码字段名,例如 parent_Id', + componentProps: { + class: 'w-full', + clearable: true, + placeholder: '请选择', + options: columns.map((column) => ({ + label: column.columnName, + value: column.id, + })), + }, + rules: 'selectRequired', + }, + { + component: 'Select', + fieldName: 'treeNameColumnId', + label: '名称字段', + help: '树节点显示的名称字段,一般是 name', + componentProps: { + class: 'w-full', + clearable: true, + placeholder: '请选择名称字段', + options: columns.map((column) => ({ + label: column.columnName, + value: column.id, + })), + }, + rules: 'selectRequired', + }, + ]; +} + +/** 主子表信息 schema */ +export function useGenerationInfoSubTableFormSchema( + columns: InfraCodegenApi.CodegenColumn[] = [], + tables: InfraCodegenApi.CodegenTable[] = [], +): VbenFormSchema[] { + return [ + { + component: 'Divider', + fieldName: 'subDivider', + label: '', + renderComponentContent: () => { + return { + default: () => ['主子表信息'], + }; + }, + formItemClass: 'md:col-span-2', + }, + { + component: 'Select', + fieldName: 'masterTableId', + label: '关联的主表', + help: '关联主表(父表)的表名, 如:system_user', + componentProps: { + class: 'w-full', + clearable: true, + placeholder: '请选择', + options: tables.map((table) => ({ + label: `${table.tableName}:${table.tableComment}`, + value: table.id, + })), + }, + rules: 'selectRequired', + }, + { + component: 'Select', + fieldName: 'subJoinColumnId', + label: '子表关联的字段', + help: '子表关联的字段, 如:user_id', + componentProps: { + class: 'w-full', + clearable: true, + placeholder: '请选择', + options: columns.map((column) => ({ + label: `${column.columnName}:${column.columnComment}`, + value: column.id, + })), + }, + rules: 'selectRequired', + }, + { + component: 'RadioGroup', + fieldName: 'subJoinMany', + label: '关联关系', + help: '主表与子表的关联关系', + componentProps: { + class: 'w-full', + clearable: true, + placeholder: '请选择', + options: [ + { + label: '一对多', + value: true, + }, + { + label: '一对一', + value: false, + }, + ], + }, + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'tableName', + label: '表名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入表名称', + }, + }, + { + fieldName: 'tableComment', + label: '表描述', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入表描述', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + getDataSourceConfigName?: (dataSourceConfigId: number) => string | undefined, +): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'dataSourceConfigId', + title: '数据源', + minWidth: 120, + formatter: ({ cellValue }) => getDataSourceConfigName?.(cellValue) || '-', + }, + { + field: 'tableName', + title: '表名称', + minWidth: 200, + }, + { + field: 'tableComment', + title: '表描述', + minWidth: 200, + }, + { + field: 'className', + title: '实体', + minWidth: 200, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'updateTime', + title: '更新时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 代码生成表格列定义 */ +export function useCodegenColumnTableColumns(): VxeTableGridOptions['columns'] { + return [ + { field: 'columnName', title: '字段列名', minWidth: 130 }, + { + field: 'columnComment', + title: '字段描述', + minWidth: 100, + slots: { default: 'columnComment' }, + }, + { field: 'dataType', title: '物理类型', minWidth: 100 }, + { + field: 'javaType', + title: 'Java 类型', + minWidth: 130, + slots: { default: 'javaType' }, + params: { + options: [ + { label: 'Long', value: 'Long' }, + { label: 'String', value: 'String' }, + { label: 'Integer', value: 'Integer' }, + { label: 'Double', value: 'Double' }, + { label: 'BigDecimal', value: 'BigDecimal' }, + { label: 'LocalDateTime', value: 'LocalDateTime' }, + { label: 'Boolean', value: 'Boolean' }, + ], + }, + }, + { + field: 'javaField', + title: 'Java 属性', + minWidth: 100, + slots: { default: 'javaField' }, + }, + { + field: 'createOperation', + title: '插入', + width: 40, + slots: { default: 'createOperation' }, + }, + { + field: 'updateOperation', + title: '编辑', + width: 40, + slots: { default: 'updateOperation' }, + }, + { + field: 'listOperationResult', + title: '列表', + width: 40, + slots: { default: 'listOperationResult' }, + }, + { + field: 'listOperation', + title: '查询', + width: 40, + slots: { default: 'listOperation' }, + }, + { + field: 'listOperationCondition', + title: '查询方式', + minWidth: 100, + slots: { default: 'listOperationCondition' }, + params: { + options: [ + { label: '=', value: '=' }, + { label: '!=', value: '!=' }, + { label: '>', value: '>' }, + { label: '>=', value: '>=' }, + { label: '<', value: '<' }, + { label: '<=', value: '<=' }, + { label: 'LIKE', value: 'LIKE' }, + { label: 'BETWEEN', value: 'BETWEEN' }, + ], + }, + }, + { + field: 'nullable', + title: '允许空', + width: 60, + slots: { default: 'nullable' }, + }, + { + field: 'htmlType', + title: '显示类型', + width: 130, + slots: { default: 'htmlType' }, + params: { + options: [ + { label: '文本框', value: 'input' }, + { label: '文本域', value: 'textarea' }, + { label: '下拉框', value: 'select' }, + { label: '单选框', value: 'radio' }, + { label: '复选框', value: 'checkbox' }, + { label: '日期控件', value: 'datetime' }, + { label: '图片上传', value: 'imageUpload' }, + { label: '文件上传', value: 'fileUpload' }, + { label: '富文本控件', value: 'editor' }, + ], + }, + }, + { + field: 'dictType', + title: '字典类型', + width: 120, + slots: { default: 'dictType' }, + }, + { + field: 'example', + title: '示例', + minWidth: 100, + slots: { default: 'example' }, + }, + ]; +} diff --git a/apps/web-naive/src/views/infra/codegen/edit/index.vue b/apps/web-naive/src/views/infra/codegen/edit/index.vue new file mode 100644 index 0000000..df0c9e0 --- /dev/null +++ b/apps/web-naive/src/views/infra/codegen/edit/index.vue @@ -0,0 +1,164 @@ + + + diff --git a/apps/web-naive/src/views/infra/codegen/index.vue b/apps/web-naive/src/views/infra/codegen/index.vue new file mode 100644 index 0000000..27cfeca --- /dev/null +++ b/apps/web-naive/src/views/infra/codegen/index.vue @@ -0,0 +1,283 @@ + + diff --git a/apps/web-naive/src/views/infra/codegen/modules/basic-info.vue b/apps/web-naive/src/views/infra/codegen/modules/basic-info.vue new file mode 100644 index 0000000..00c4991 --- /dev/null +++ b/apps/web-naive/src/views/infra/codegen/modules/basic-info.vue @@ -0,0 +1,45 @@ + + diff --git a/apps/web-naive/src/views/infra/codegen/modules/column-info.vue b/apps/web-naive/src/views/infra/codegen/modules/column-info.vue new file mode 100644 index 0000000..e9343af --- /dev/null +++ b/apps/web-naive/src/views/infra/codegen/modules/column-info.vue @@ -0,0 +1,153 @@ + + + diff --git a/apps/web-naive/src/views/infra/codegen/modules/generation-info.vue b/apps/web-naive/src/views/infra/codegen/modules/generation-info.vue new file mode 100644 index 0000000..56ffe61 --- /dev/null +++ b/apps/web-naive/src/views/infra/codegen/modules/generation-info.vue @@ -0,0 +1,176 @@ + + + diff --git a/apps/web-naive/src/views/infra/codegen/modules/import-table.vue b/apps/web-naive/src/views/infra/codegen/modules/import-table.vue new file mode 100644 index 0000000..8000595 --- /dev/null +++ b/apps/web-naive/src/views/infra/codegen/modules/import-table.vue @@ -0,0 +1,129 @@ + + + diff --git a/apps/web-naive/src/views/infra/codegen/modules/preview-code.vue b/apps/web-naive/src/views/infra/codegen/modules/preview-code.vue new file mode 100644 index 0000000..d5a4e43 --- /dev/null +++ b/apps/web-naive/src/views/infra/codegen/modules/preview-code.vue @@ -0,0 +1,268 @@ + + + diff --git a/apps/web-naive/src/views/infra/config/data.ts b/apps/web-naive/src/views/infra/config/data.ts new file mode 100644 index 0000000..c5aaf85 --- /dev/null +++ b/apps/web-naive/src/views/infra/config/data.ts @@ -0,0 +1,186 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'category', + label: '参数分类', + component: 'Input', + componentProps: { + placeholder: '请输入参数分类', + }, + rules: 'required', + }, + { + fieldName: 'name', + label: '参数名称', + component: 'Input', + componentProps: { + placeholder: '请输入参数名称', + }, + rules: 'required', + }, + { + fieldName: 'key', + label: '参数键名', + component: 'Input', + componentProps: { + placeholder: '请输入参数键名', + }, + rules: 'required', + }, + { + fieldName: 'value', + label: '参数键值', + component: 'Input', + componentProps: { + placeholder: '请输入参数键值', + }, + rules: 'required', + }, + { + fieldName: 'visible', + label: '是否可见', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + }, + defaultValue: true, + rules: 'required', + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + type: 'textarea', + placeholder: '请输入备注', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '参数名称', + component: 'Input', + componentProps: { + placeholder: '请输入参数名称', + clearable: true, + }, + }, + { + fieldName: 'key', + label: '参数键名', + component: 'Input', + componentProps: { + placeholder: '请输入参数键名', + clearable: true, + }, + }, + { + fieldName: 'type', + label: '系统内置', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_CONFIG_TYPE, 'number'), + placeholder: '请选择系统内置', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '参数主键', + minWidth: 100, + }, + { + field: 'category', + title: '参数分类', + minWidth: 120, + }, + { + field: 'name', + title: '参数名称', + minWidth: 200, + }, + { + field: 'key', + title: '参数键名', + minWidth: 200, + }, + { + field: 'value', + title: '参数键值', + minWidth: 150, + }, + { + field: 'visible', + title: '是否可见', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'type', + title: '系统内置', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_CONFIG_TYPE }, + }, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 160, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-naive/src/views/infra/config/index.vue b/apps/web-naive/src/views/infra/config/index.vue new file mode 100644 index 0000000..e1e5b1c --- /dev/null +++ b/apps/web-naive/src/views/infra/config/index.vue @@ -0,0 +1,183 @@ + + + diff --git a/apps/web-naive/src/views/infra/config/modules/form.vue b/apps/web-naive/src/views/infra/config/modules/form.vue new file mode 100644 index 0000000..7a5a639 --- /dev/null +++ b/apps/web-naive/src/views/infra/config/modules/form.vue @@ -0,0 +1,81 @@ + + + diff --git a/apps/web-naive/src/views/infra/dataSourceConfig/data.ts b/apps/web-naive/src/views/infra/dataSourceConfig/data.ts new file mode 100644 index 0000000..6f4c602 --- /dev/null +++ b/apps/web-naive/src/views/infra/dataSourceConfig/data.ts @@ -0,0 +1,92 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '数据源名称', + component: 'Input', + componentProps: { + placeholder: '请输入数据源名称', + }, + rules: 'required', + }, + { + fieldName: 'url', + label: '数据源连接', + component: 'Input', + componentProps: { + placeholder: '请输入数据源连接', + }, + rules: 'required', + }, + { + fieldName: 'username', + label: '用户名', + component: 'Input', + componentProps: { + placeholder: '请输入用户名', + }, + rules: 'required', + }, + { + fieldName: 'password', + label: '密码', + component: 'Input', + componentProps: { + placeholder: '请输入密码', + type: 'password', + }, + rules: 'required', + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '主键编号', + minWidth: 100, + }, + { + field: 'name', + title: '数据源名称', + minWidth: 150, + }, + { + field: 'url', + title: '数据源连接', + minWidth: 300, + }, + { + field: 'username', + title: '用户名', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 160, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-naive/src/views/infra/dataSourceConfig/index.vue b/apps/web-naive/src/views/infra/dataSourceConfig/index.vue new file mode 100644 index 0000000..41b9d7e --- /dev/null +++ b/apps/web-naive/src/views/infra/dataSourceConfig/index.vue @@ -0,0 +1,162 @@ + + + diff --git a/apps/web-naive/src/views/infra/dataSourceConfig/modules/form.vue b/apps/web-naive/src/views/infra/dataSourceConfig/modules/form.vue new file mode 100644 index 0000000..0257071 --- /dev/null +++ b/apps/web-naive/src/views/infra/dataSourceConfig/modules/form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo01/data.ts b/apps/web-naive/src/views/infra/demo/demo01/data.ts new file mode 100644 index 0000000..ad3d735 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo01/data.ts @@ -0,0 +1,149 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { Demo01ContactApi } from '#/api/infra/demo/demo01'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'InputNumber', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + rules: 'required', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + }, + }, + { + fieldName: 'birthday', + label: '出生年', + rules: 'required', + component: 'DatePicker', + componentProps: { + type: 'datetime', + valueFormat: 'YYYY-MM-dd HH:mm:ss', + }, + }, + { + fieldName: 'description', + label: '简介', + rules: 'required', + component: 'RichTextarea', + }, + { + fieldName: 'avatar', + label: '头像', + component: 'ImageUpload', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + placeholder: '请选择性别', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'sex', + title: '性别', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, + }, + }, + { + field: 'birthday', + title: '出生年', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + field: 'description', + title: '简介', + minWidth: 120, + }, + { + field: 'avatar', + title: '头像', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 160, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-naive/src/views/infra/demo/demo01/index.vue b/apps/web-naive/src/views/infra/demo/demo01/index.vue new file mode 100644 index 0000000..c59c5bc --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo01/index.vue @@ -0,0 +1,185 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo01/modules/form.vue b/apps/web-naive/src/views/infra/demo/demo01/modules/form.vue new file mode 100644 index 0000000..09bfe8f --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo01/modules/form.vue @@ -0,0 +1,87 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo02/data.ts b/apps/web-naive/src/views/infra/demo/demo02/data.ts new file mode 100644 index 0000000..2028464 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo02/data.ts @@ -0,0 +1,120 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { Demo02CategoryApi } from '#/api/infra/demo/demo02'; + +import { handleTree } from '@vben/utils'; + +import { getDemo02CategoryList } from '#/api/infra/demo/demo02'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'InputNumber', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'parentId', + label: '上级示例分类', + component: 'ApiTreeSelect', + componentProps: { + clearable: true, + api: async () => { + const data = await getDemo02CategoryList({}); + data.unshift({ + id: 0, + name: '顶级示例分类', + }); + return handleTree(data); + }, + labelField: 'name', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择上级示例分类', + treeDefaultExpandAll: true, + }, + rules: 'selectRequired', + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'parentId', + label: '父级编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入父级编号', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + treeNode: true, + }, + { + field: 'parentId', + title: '父级编号', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-naive/src/views/infra/demo/demo02/index.vue b/apps/web-naive/src/views/infra/demo/demo02/index.vue new file mode 100644 index 0000000..b7823cb --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo02/index.vue @@ -0,0 +1,175 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo02/modules/form.vue b/apps/web-naive/src/views/infra/demo/demo02/modules/form.vue new file mode 100644 index 0000000..c400afe --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo02/modules/form.vue @@ -0,0 +1,90 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/erp/data.ts b/apps/web-naive/src/views/infra/demo/demo03/erp/data.ts new file mode 100644 index 0000000..68ad79d --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/erp/data.ts @@ -0,0 +1,378 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'InputNumber', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + rules: 'required', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + }, + }, + { + fieldName: 'birthday', + label: '出生日期', + rules: 'required', + component: 'DatePicker', + componentProps: { + type: 'datetime', + valueFormat: 'YYYY-MM-dd HH:mm:ss', + }, + }, + { + fieldName: 'description', + label: '简介', + rules: 'required', + component: 'RichTextarea', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + placeholder: '请选择性别', + }, + }, + { + fieldName: 'description', + label: '简介', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入简介', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'sex', + title: '性别', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, + }, + }, + { + field: 'birthday', + title: '出生日期', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + field: 'description', + title: '简介', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ==================== 子表(学生课程) ==================== + +/** 新增/修改的表单 */ +export function useDemo03CourseFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'InputNumber', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'score', + label: '分数', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入分数', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useDemo03CourseGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'studentId', + label: '学生编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入学生编号', + }, + }, + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'score', + label: '分数', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入分数', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useDemo03CourseGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'studentId', + title: '学生编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'score', + title: '分数', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ==================== 子表(学生班级) ==================== + +/** 新增/修改的表单 */ +export function useDemo03GradeFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'InputNumber', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'teacher', + label: '班主任', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入班主任', + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useDemo03GradeGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'studentId', + label: '学生编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入学生编号', + }, + }, + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'teacher', + label: '班主任', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入班主任', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useDemo03GradeGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'studentId', + title: '学生编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'teacher', + title: '班主任', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-naive/src/views/infra/demo/demo03/erp/index.vue b/apps/web-naive/src/views/infra/demo/demo03/erp/index.vue new file mode 100644 index 0000000..edbc69e --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/erp/index.vue @@ -0,0 +1,209 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-course-form.vue b/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-course-form.vue new file mode 100644 index 0000000..98b7991 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-course-form.vue @@ -0,0 +1,91 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-course-list.vue b/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-course-list.vue new file mode 100644 index 0000000..09ea3e5 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-course-list.vue @@ -0,0 +1,197 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-grade-form.vue b/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-grade-form.vue new file mode 100644 index 0000000..c120919 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-grade-form.vue @@ -0,0 +1,91 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-grade-list.vue b/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-grade-list.vue new file mode 100644 index 0000000..519fac7 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/erp/modules/demo03-grade-list.vue @@ -0,0 +1,199 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/erp/modules/form.vue b/apps/web-naive/src/views/infra/demo/demo03/erp/modules/form.vue new file mode 100644 index 0000000..79561fb --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/erp/modules/form.vue @@ -0,0 +1,87 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/inner/data.ts b/apps/web-naive/src/views/infra/demo/demo03/inner/data.ts new file mode 100644 index 0000000..241afa3 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/inner/data.ts @@ -0,0 +1,273 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { Demo03StudentApi } from '#/api/infra/demo/demo03/inner'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'InputNumber', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + rules: 'required', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + }, + }, + { + fieldName: 'birthday', + label: '出生日期', + rules: 'required', + component: 'DatePicker', + componentProps: { + type: 'datetime', + valueFormat: 'YYYY-MM-dd HH:mm:ss', + }, + }, + { + fieldName: 'description', + label: '简介', + rules: 'required', + component: 'RichTextarea', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + placeholder: '请选择性别', + }, + }, + { + fieldName: 'description', + label: '简介', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入简介', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { type: 'expand', width: 80, slots: { content: 'expand_content' } }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'sex', + title: '性别', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, + }, + }, + { + field: 'birthday', + title: '出生日期', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + field: 'description', + title: '简介', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ==================== 子表(学生课程) ==================== + +/** 新增/修改列表的字段 */ +export function useDemo03CourseGridEditColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '名字', + minWidth: 120, + slots: { default: 'name' }, + }, + { + field: 'score', + title: '分数', + minWidth: 120, + slots: { default: 'score' }, + }, + { + title: '操作', + width: 280, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的字段 */ +export function useDemo03CourseGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'studentId', + title: '学生编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'score', + title: '分数', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + ]; +} + +// ==================== 子表(学生班级) ==================== + +/** 新增/修改的表单 */ +export function useDemo03GradeFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'InputNumber', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'teacher', + label: '班主任', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入班主任', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useDemo03GradeGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'studentId', + title: '学生编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'teacher', + title: '班主任', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-naive/src/views/infra/demo/demo03/inner/index.vue b/apps/web-naive/src/views/infra/demo/demo03/inner/index.vue new file mode 100644 index 0000000..976b2da --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/inner/index.vue @@ -0,0 +1,203 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-course-form.vue b/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-course-form.vue new file mode 100644 index 0000000..2be8932 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-course-form.vue @@ -0,0 +1,120 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-course-list.vue b/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-course-list.vue new file mode 100644 index 0000000..50297db --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-course-list.vue @@ -0,0 +1,56 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-grade-form.vue b/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-grade-form.vue new file mode 100644 index 0000000..3e28546 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-grade-form.vue @@ -0,0 +1,51 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-grade-list.vue b/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-grade-list.vue new file mode 100644 index 0000000..1ad2db7 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/inner/modules/demo03-grade-list.vue @@ -0,0 +1,56 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/inner/modules/form.vue b/apps/web-naive/src/views/infra/demo/demo03/inner/modules/form.vue new file mode 100644 index 0000000..fcc36ca --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/inner/modules/form.vue @@ -0,0 +1,120 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/normal/data.ts b/apps/web-naive/src/views/infra/demo/demo03/normal/data.ts new file mode 100644 index 0000000..5add375 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/normal/data.ts @@ -0,0 +1,208 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'InputNumber', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + rules: 'required', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + }, + }, + { + fieldName: 'birthday', + label: '出生日期', + rules: 'required', + component: 'DatePicker', + componentProps: { + type: 'datetime', + valueFormat: 'YYYY-MM-dd HH:mm:ss', + }, + }, + { + fieldName: 'description', + label: '简介', + rules: 'required', + component: 'RichTextarea', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '名字', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入名字', + }, + }, + { + fieldName: 'sex', + label: '性别', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + placeholder: '请选择性别', + }, + }, + { + fieldName: 'description', + label: '简介', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入简介', + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'id', + title: '编号', + minWidth: 120, + }, + { + field: 'name', + title: '名字', + minWidth: 120, + }, + { + field: 'sex', + title: '性别', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, + }, + }, + { + field: 'birthday', + title: '出生日期', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + field: 'description', + title: '简介', + minWidth: 120, + }, + { + field: 'createTime', + title: '创建时间', + minWidth: 120, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ==================== 子表(学生课程) ==================== + +/** 新增/修改列表的字段 */ +export function useDemo03CourseGridEditColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '名字', + minWidth: 120, + slots: { default: 'name' }, + }, + { + field: 'score', + title: '分数', + minWidth: 120, + slots: { default: 'score' }, + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +// ==================== 子表(学生班级) ==================== + +/** 新增/修改的表单 */ +export function useDemo03GradeFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'InputNumber', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '名字', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入名字', + }, + }, + { + fieldName: 'teacher', + label: '班主任', + rules: 'required', + component: 'Input', + componentProps: { + placeholder: '请输入班主任', + }, + }, + ]; +} diff --git a/apps/web-naive/src/views/infra/demo/demo03/normal/index.vue b/apps/web-naive/src/views/infra/demo/demo03/normal/index.vue new file mode 100644 index 0000000..35de85d --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/normal/index.vue @@ -0,0 +1,185 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/normal/modules/demo03-course-form.vue b/apps/web-naive/src/views/infra/demo/demo03/normal/modules/demo03-course-form.vue new file mode 100644 index 0000000..4d674cb --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/normal/modules/demo03-course-form.vue @@ -0,0 +1,119 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/normal/modules/demo03-grade-form.vue b/apps/web-naive/src/views/infra/demo/demo03/normal/modules/demo03-grade-form.vue new file mode 100644 index 0000000..5d5f396 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/normal/modules/demo03-grade-form.vue @@ -0,0 +1,51 @@ + + + diff --git a/apps/web-naive/src/views/infra/demo/demo03/normal/modules/form.vue b/apps/web-naive/src/views/infra/demo/demo03/normal/modules/form.vue new file mode 100644 index 0000000..624c941 --- /dev/null +++ b/apps/web-naive/src/views/infra/demo/demo03/normal/modules/form.vue @@ -0,0 +1,120 @@ + + + diff --git a/apps/web-naive/src/views/infra/druid/index.vue b/apps/web-naive/src/views/infra/druid/index.vue new file mode 100644 index 0000000..01ec58d --- /dev/null +++ b/apps/web-naive/src/views/infra/druid/index.vue @@ -0,0 +1,36 @@ + + + diff --git a/packages/effects/common-ui/src/components/iframe/index.ts b/packages/effects/common-ui/src/components/iframe/index.ts new file mode 100644 index 0000000..d437bc0 --- /dev/null +++ b/packages/effects/common-ui/src/components/iframe/index.ts @@ -0,0 +1 @@ +export { default as IFrame } from './iframe.vue'; diff --git a/packages/effects/common-ui/src/components/index.ts b/packages/effects/common-ui/src/components/index.ts new file mode 100644 index 0000000..f2c4fae --- /dev/null +++ b/packages/effects/common-ui/src/components/index.ts @@ -0,0 +1,42 @@ +export * from './api-component'; +export * from './captcha'; +export * from './card/comparison-card'; +export * from './card/statistic-card'; +export * from './card/summary-card'; +export * from './col-page'; +export * from './content-wrap'; +export * from './count-to'; +export * from './cropper'; +export * from './doc-alert'; +export * from './ellipsis-text'; +export * from './icon-picker'; +export * from './iframe'; +export * from './json-viewer'; +export * from './loading'; +export * from './page'; +export * from './resize'; +export * from './tippy'; +export * from './tree'; +export * from '@vben-core/form-ui'; +export * from '@vben-core/popup-ui'; + +// 给文档用 +export { + VbenAvatar, + VbenButton, + VbenButtonGroup, + VbenCheckbox, + VbenCheckButtonGroup, + VbenContextMenu, + VbenCountToAnimator, + VbenFullScreen, + VbenInputPassword, + VbenLoading, + VbenLogo, + VbenPinInput, + VbenSelect, + VbenSpinner, +} from '@vben-core/shadcn-ui'; + +export type { FlattenedItem } from '@vben-core/shadcn-ui'; +export { globalShareState } from '@vben-core/shared/global-state'; diff --git a/packages/effects/common-ui/src/components/json-viewer/index.ts b/packages/effects/common-ui/src/components/json-viewer/index.ts new file mode 100644 index 0000000..1aec78b --- /dev/null +++ b/packages/effects/common-ui/src/components/json-viewer/index.ts @@ -0,0 +1,3 @@ +export { default as JsonViewer } from './index.vue'; + +export * from './types'; diff --git a/packages/effects/common-ui/src/components/json-viewer/index.vue b/packages/effects/common-ui/src/components/json-viewer/index.vue new file mode 100644 index 0000000..f66c318 --- /dev/null +++ b/packages/effects/common-ui/src/components/json-viewer/index.vue @@ -0,0 +1,112 @@ + + + diff --git a/packages/effects/common-ui/src/components/json-viewer/style.scss b/packages/effects/common-ui/src/components/json-viewer/style.scss new file mode 100644 index 0000000..47acb89 --- /dev/null +++ b/packages/effects/common-ui/src/components/json-viewer/style.scss @@ -0,0 +1,98 @@ +.default-json-theme { + font-family: Consolas, Menlo, Courier, monospace; + font-size: 14px; + color: hsl(var(--foreground)); + white-space: nowrap; + background: hsl(var(--background)); + + &.jv-container.boxed { + border: 1px solid hsl(var(--border)); + } + + .jv-ellipsis { + display: inline-block; + padding: 0 4px 2px; + font-size: 0.9em; + line-height: 0.9; + vertical-align: 2px; + color: hsl(var(--secondary-foreground)); + cursor: pointer; + user-select: none; + background-color: hsl(var(--secondary)); + border-radius: 3px; + } + + .jv-button { + color: hsl(var(--primary)); + } + + .jv-key { + color: hsl(var(--heavy-foreground)); + } + + .jv-item { + &.jv-array { + color: hsl(var(--heavy-foreground)); + } + + &.jv-boolean { + color: hsl(var(--red-400)); + } + + &.jv-function { + color: hsl(var(--destructive-foreground)); + } + + &.jv-number { + color: hsl(var(--info-foreground)); + } + + &.jv-number-float { + color: hsl(var(--info-foreground)); + } + + &.jv-number-integer { + color: hsl(var(--info-foreground)); + } + + &.jv-object { + color: hsl(var(--accent-darker)); + } + + &.jv-undefined { + color: hsl(var(--secondary-foreground)); + } + + &.jv-string { + color: hsl(var(--primary)); + overflow-wrap: break-word; + white-space: normal; + } + } + + &.jv-container .jv-code { + padding: 10px; + + &.boxed:not(.open) { + padding-bottom: 20px; + margin-bottom: 10px; + } + + &.open { + padding-bottom: 10px; + } + + .jv-toggle { + &::before { + padding: 0 2px; + border-radius: 2px; + } + + &:hover { + &::before { + background: hsl(var(--accent-foreground)); + } + } + } + } +} diff --git a/packages/effects/common-ui/src/components/json-viewer/types.ts b/packages/effects/common-ui/src/components/json-viewer/types.ts new file mode 100644 index 0000000..8f3a206 --- /dev/null +++ b/packages/effects/common-ui/src/components/json-viewer/types.ts @@ -0,0 +1,44 @@ +export interface JsonViewerProps { + /** 要展示的结构数据 */ + value: any; + /** 展开深度 */ + expandDepth?: number; + /** 是否可复制 */ + copyable?: boolean; + /** 是否排序 */ + sort?: boolean; + /** 显示边框 */ + boxed?: boolean; + /** 主题 */ + theme?: string; + /** 是否展开 */ + expanded?: boolean; + /** 时间格式化函数 */ + timeformat?: (time: Date | number | string) => string; + /** 预览模式 */ + previewMode?: boolean; + /** 显示数组索引 */ + showArrayIndex?: boolean; + /** 显示双引号 */ + showDoubleQuotes?: boolean; +} + +export interface JsonViewerAction { + action: string; + text: string; + trigger: HTMLElement; +} + +export interface JsonViewerValue { + value: any; + path: string; + depth: number; + el: HTMLElement; +} + +export interface JsonViewerToggle { + /** 鼠标事件 */ + event: MouseEvent; + /** 当前展开状态 */ + open: boolean; +} diff --git a/packages/effects/common-ui/src/components/loading/directive.ts b/packages/effects/common-ui/src/components/loading/directive.ts new file mode 100644 index 0000000..973a605 --- /dev/null +++ b/packages/effects/common-ui/src/components/loading/directive.ts @@ -0,0 +1,132 @@ +import type { App, Directive, DirectiveBinding } from 'vue'; + +import { h, render } from 'vue'; + +import { VbenLoading, VbenSpinner } from '@vben-core/shadcn-ui'; +import { isString } from '@vben-core/shared/utils'; + +const LOADING_INSTANCE_KEY = Symbol('loading'); +const SPINNER_INSTANCE_KEY = Symbol('spinner'); + +const CLASS_NAME_RELATIVE = 'spinner-parent--relative'; + +const loadingDirective: Directive = { + mounted(el, binding) { + const instance = h(VbenLoading, getOptions(binding)); + render(instance, el); + + el.classList.add(CLASS_NAME_RELATIVE); + el[LOADING_INSTANCE_KEY] = instance; + }, + unmounted(el) { + const instance = el[LOADING_INSTANCE_KEY]; + el.classList.remove(CLASS_NAME_RELATIVE); + render(null, el); + instance.el.remove(); + + el[LOADING_INSTANCE_KEY] = null; + }, + + updated(el, binding) { + const instance = el[LOADING_INSTANCE_KEY]; + const options = getOptions(binding); + if (options && instance?.component) { + try { + Object.keys(options).forEach((key) => { + instance.component.props[key] = options[key]; + }); + instance.component.update(); + } catch (error) { + console.error( + 'Failed to update loading component in directive:', + error, + ); + } + } + }, +}; + +function getOptions(binding: DirectiveBinding) { + if (binding.value === undefined) { + return { spinning: true }; + } else if (typeof binding.value === 'boolean') { + return { spinning: binding.value }; + } else { + return { ...binding.value }; + } +} + +const spinningDirective: Directive = { + mounted(el, binding) { + const instance = h(VbenSpinner, getOptions(binding)); + render(instance, el); + + el.classList.add(CLASS_NAME_RELATIVE); + el[SPINNER_INSTANCE_KEY] = instance; + }, + unmounted(el) { + const instance = el[SPINNER_INSTANCE_KEY]; + el.classList.remove(CLASS_NAME_RELATIVE); + render(null, el); + instance.el.remove(); + + el[SPINNER_INSTANCE_KEY] = null; + }, + + updated(el, binding) { + const instance = el[SPINNER_INSTANCE_KEY]; + const options = getOptions(binding); + if (options && instance?.component) { + try { + Object.keys(options).forEach((key) => { + instance.component.props[key] = options[key]; + }); + instance.component.update(); + } catch (error) { + console.error( + 'Failed to update spinner component in directive:', + error, + ); + } + } + }, +}; + +type loadingDirectiveParams = { + /** 是否注册loading指令。如果提供一个string,则将指令注册为指定的名称 */ + loading?: boolean | string; + /** 是否注册spinning指令。如果提供一个string,则将指令注册为指定的名称 */ + spinning?: boolean | string; +}; + +/** + * 注册loading指令 + * @param app + * @param params + */ +export function registerLoadingDirective( + app: App, + params?: loadingDirectiveParams, +) { + // 注入一个样式供指令使用,确保容器是相对定位 + const style = document.createElement('style'); + style.id = CLASS_NAME_RELATIVE; + style.innerHTML = ` + .${CLASS_NAME_RELATIVE} { + position: relative !important; + } + `; + document.head.append(style); + if (params?.loading !== false) { + app.directive( + isString(params?.loading) ? params.loading : 'loading', + loadingDirective, + ); + } + if (params?.spinning !== false) { + app.directive( + isString(params?.spinning) ? params.spinning : 'spinning', + spinningDirective, + ); + } +} diff --git a/packages/effects/common-ui/src/components/loading/index.ts b/packages/effects/common-ui/src/components/loading/index.ts new file mode 100644 index 0000000..2fbfb04 --- /dev/null +++ b/packages/effects/common-ui/src/components/loading/index.ts @@ -0,0 +1,3 @@ +export * from './directive'; +export { default as Loading } from './loading.vue'; +export { default as Spinner } from './spinner.vue'; diff --git a/packages/effects/common-ui/src/components/loading/loading.vue b/packages/effects/common-ui/src/components/loading/loading.vue new file mode 100644 index 0000000..faf49e6 --- /dev/null +++ b/packages/effects/common-ui/src/components/loading/loading.vue @@ -0,0 +1,39 @@ + + diff --git a/packages/effects/common-ui/src/components/loading/spinner.vue b/packages/effects/common-ui/src/components/loading/spinner.vue new file mode 100644 index 0000000..caee2bb --- /dev/null +++ b/packages/effects/common-ui/src/components/loading/spinner.vue @@ -0,0 +1,28 @@ + + diff --git a/packages/effects/common-ui/src/components/page/__tests__/page.test.ts b/packages/effects/common-ui/src/components/page/__tests__/page.test.ts new file mode 100644 index 0000000..a89061f --- /dev/null +++ b/packages/effects/common-ui/src/components/page/__tests__/page.test.ts @@ -0,0 +1,89 @@ +import { mount } from '@vue/test-utils'; + +import { describe, expect, it } from 'vitest'; + +import { Page } from '..'; + +describe('page.vue', () => { + it('renders title when passed', () => { + const wrapper = mount(Page, { + props: { + title: 'Test Title', + }, + }); + + expect(wrapper.text()).toContain('Test Title'); + }); + + it('renders description when passed', () => { + const wrapper = mount(Page, { + props: { + description: 'Test Description', + }, + }); + + expect(wrapper.text()).toContain('Test Description'); + }); + + it('renders default slot content', () => { + const wrapper = mount(Page, { + slots: { + default: '

    Default Slot Content

    ', + }, + }); + + expect(wrapper.html()).toContain('

    Default Slot Content

    '); + }); + + it('renders footer slot when showFooter is true', () => { + const wrapper = mount(Page, { + props: { + showFooter: true, + }, + slots: { + footer: '

    Footer Slot Content

    ', + }, + }); + + expect(wrapper.html()).toContain('

    Footer Slot Content

    '); + }); + + it('applies the custom contentClass', () => { + const wrapper = mount(Page, { + props: { + contentClass: 'custom-class', + }, + }); + + const contentDiv = wrapper.find('.p-4'); + expect(contentDiv.classes()).toContain('custom-class'); + }); + + it('does not render title slot if title prop is provided', () => { + const wrapper = mount(Page, { + props: { + title: 'Test Title', + }, + slots: { + title: '

    Title Slot Content

    ', + }, + }); + + expect(wrapper.text()).toContain('Title Slot Content'); + expect(wrapper.html()).not.toContain('Test Title'); + }); + + it('does not render description slot if description prop is provided', () => { + const wrapper = mount(Page, { + props: { + description: 'Test Description', + }, + slots: { + description: '

    Description Slot Content

    ', + }, + }); + + expect(wrapper.text()).toContain('Description Slot Content'); + expect(wrapper.html()).not.toContain('Test Description'); + }); +}); diff --git a/packages/effects/common-ui/src/components/page/index.ts b/packages/effects/common-ui/src/components/page/index.ts new file mode 100644 index 0000000..fd9e02f --- /dev/null +++ b/packages/effects/common-ui/src/components/page/index.ts @@ -0,0 +1,2 @@ +export { default as Page } from './page.vue'; +export * from './types'; diff --git a/packages/effects/common-ui/src/components/page/page.vue b/packages/effects/common-ui/src/components/page/page.vue new file mode 100644 index 0000000..e5522f9 --- /dev/null +++ b/packages/effects/common-ui/src/components/page/page.vue @@ -0,0 +1,121 @@ + + + diff --git a/packages/effects/common-ui/src/components/page/types.ts b/packages/effects/common-ui/src/components/page/types.ts new file mode 100644 index 0000000..c7331ae --- /dev/null +++ b/packages/effects/common-ui/src/components/page/types.ts @@ -0,0 +1,17 @@ +export interface PageProps { + title?: string; + description?: string; + contentClass?: string; + /** + * 根据content可见高度自适应 + */ + autoContentHeight?: boolean; + headerClass?: string; + footerClass?: string; + /** + * Custom height offset value (in pixels) to adjust content area sizing + * when used with autoContentHeight + * @default 0 + */ + heightOffset?: number; +} diff --git a/packages/effects/common-ui/src/components/resize/index.ts b/packages/effects/common-ui/src/components/resize/index.ts new file mode 100644 index 0000000..f937522 --- /dev/null +++ b/packages/effects/common-ui/src/components/resize/index.ts @@ -0,0 +1 @@ +export { default as VResize } from './resize.vue'; diff --git a/packages/effects/common-ui/src/components/resize/resize.vue b/packages/effects/common-ui/src/components/resize/resize.vue new file mode 100644 index 0000000..68be4d9 --- /dev/null +++ b/packages/effects/common-ui/src/components/resize/resize.vue @@ -0,0 +1,1120 @@ + + + + + diff --git a/packages/effects/common-ui/src/components/tippy/directive.ts b/packages/effects/common-ui/src/components/tippy/directive.ts new file mode 100644 index 0000000..ed277d6 --- /dev/null +++ b/packages/effects/common-ui/src/components/tippy/directive.ts @@ -0,0 +1,100 @@ +import type { ComputedRef, Directive } from 'vue'; + +import { useTippy } from 'vue-tippy'; + +export default function useTippyDirective(isDark: ComputedRef) { + const directive: Directive = { + mounted(el, binding, vnode) { + const opts = + typeof binding.value === 'string' + ? { content: binding.value } + : binding.value || {}; + + const modifiers = Object.keys(binding.modifiers || {}); + const placement = modifiers.find((modifier) => modifier !== 'arrow'); + const withArrow = modifiers.includes('arrow'); + + if (placement) { + opts.placement = opts.placement || placement; + } + + if (withArrow) { + opts.arrow = opts.arrow === undefined ? true : opts.arrow; + } + + if (vnode.props && vnode.props.onTippyShow) { + opts.onShow = function (...args: any[]) { + return vnode.props?.onTippyShow(...args); + }; + } + + if (vnode.props && vnode.props.onTippyShown) { + opts.onShown = function (...args: any[]) { + return vnode.props?.onTippyShown(...args); + }; + } + + if (vnode.props && vnode.props.onTippyHidden) { + opts.onHidden = function (...args: any[]) { + return vnode.props?.onTippyHidden(...args); + }; + } + + if (vnode.props && vnode.props.onTippyHide) { + opts.onHide = function (...args: any[]) { + return vnode.props?.onTippyHide(...args); + }; + } + + if (vnode.props && vnode.props.onTippyMount) { + opts.onMount = function (...args: any[]) { + return vnode.props?.onTippyMount(...args); + }; + } + + if (el.getAttribute('title') && !opts.content) { + opts.content = el.getAttribute('title'); + el.removeAttribute('title'); + } + + if (el.getAttribute('content') && !opts.content) { + opts.content = el.getAttribute('content'); + } + + useTippy(el, opts); + }, + unmounted(el) { + if (el.$tippy) { + el.$tippy.destroy(); + } else if (el._tippy) { + el._tippy.destroy(); + } + }, + + updated(el, binding) { + const opts = + typeof binding.value === 'string' + ? { content: binding.value, theme: isDark.value ? '' : 'light' } + : Object.assign( + { theme: isDark.value ? '' : 'light' }, + binding.value, + ); + + if (el.getAttribute('title') && !opts.content) { + opts.content = el.getAttribute('title'); + el.removeAttribute('title'); + } + + if (el.getAttribute('content') && !opts.content) { + opts.content = el.getAttribute('content'); + } + + if (el.$tippy) { + el.$tippy.setProps(opts || {}); + } else if (el._tippy) { + el._tippy.setProps(opts || {}); + } + }, + }; + return directive; +} diff --git a/packages/effects/common-ui/src/components/tippy/index.ts b/packages/effects/common-ui/src/components/tippy/index.ts new file mode 100644 index 0000000..6080e58 --- /dev/null +++ b/packages/effects/common-ui/src/components/tippy/index.ts @@ -0,0 +1,67 @@ +import type { DefaultProps, Props } from 'tippy.js'; + +import type { App, SetupContext } from 'vue'; + +import { h, watchEffect } from 'vue'; +import { setDefaultProps, Tippy as TippyComponent } from 'vue-tippy'; + +import { usePreferences } from '@vben-core/preferences'; + +import useTippyDirective from './directive'; + +import 'tippy.js/dist/tippy.css'; +import 'tippy.js/dist/backdrop.css'; +import 'tippy.js/themes/light.css'; +import 'tippy.js/animations/scale.css'; +import 'tippy.js/animations/shift-toward.css'; +import 'tippy.js/animations/shift-away.css'; +import 'tippy.js/animations/perspective.css'; + +const { isDark } = usePreferences(); +export type TippyProps = Partial< + Props & { + animation?: + | 'fade' + | 'perspective' + | 'scale' + | 'shift-away' + | 'shift-toward' + | boolean; + theme?: 'auto' | 'dark' | 'light'; + } +>; + +export function initTippy(app: App, options?: DefaultProps) { + setDefaultProps({ + allowHTML: true, + delay: [500, 200], + theme: isDark.value ? '' : 'light', + ...options, + }); + if (!options || !Reflect.has(options, 'theme') || options.theme === 'auto') { + watchEffect(() => { + setDefaultProps({ theme: isDark.value ? '' : 'light' }); + }); + } + + app.directive('tippy', useTippyDirective(isDark)); +} + +export const Tippy = (props: any, { attrs, slots }: SetupContext) => { + let theme: string = (attrs.theme as string) ?? 'auto'; + if (theme === 'auto') { + theme = isDark.value ? '' : 'light'; + } + if (theme === 'dark') { + theme = ''; + } + return h( + TippyComponent, + { + ...props, + ...attrs, + theme, + }, + slots, + ); +}; diff --git a/packages/effects/common-ui/src/components/tree/index.ts b/packages/effects/common-ui/src/components/tree/index.ts new file mode 100644 index 0000000..ce3bc5c --- /dev/null +++ b/packages/effects/common-ui/src/components/tree/index.ts @@ -0,0 +1 @@ +export { default as Tree } from './tree.vue'; diff --git a/packages/effects/common-ui/src/components/tree/tree.vue b/packages/effects/common-ui/src/components/tree/tree.vue new file mode 100644 index 0000000..1f2fcc1 --- /dev/null +++ b/packages/effects/common-ui/src/components/tree/tree.vue @@ -0,0 +1,25 @@ + + + diff --git a/packages/effects/common-ui/src/index.ts b/packages/effects/common-ui/src/index.ts new file mode 100644 index 0000000..27bd718 --- /dev/null +++ b/packages/effects/common-ui/src/index.ts @@ -0,0 +1,2 @@ +export * from './components'; +export * from './ui'; diff --git a/packages/effects/common-ui/src/ui/about/about.ts b/packages/effects/common-ui/src/ui/about/about.ts new file mode 100644 index 0000000..c4cf957 --- /dev/null +++ b/packages/effects/common-ui/src/ui/about/about.ts @@ -0,0 +1,14 @@ +import type { Component } from 'vue'; + +interface AboutProps { + description?: string; + name?: string; + title?: string; +} + +interface DescriptionItem { + content: Component | string; + title: string; +} + +export type { AboutProps, DescriptionItem }; diff --git a/packages/effects/common-ui/src/ui/about/about.vue b/packages/effects/common-ui/src/ui/about/about.vue new file mode 100644 index 0000000..bee8b34 --- /dev/null +++ b/packages/effects/common-ui/src/ui/about/about.vue @@ -0,0 +1,183 @@ + + + diff --git a/packages/effects/common-ui/src/ui/about/index.ts b/packages/effects/common-ui/src/ui/about/index.ts new file mode 100644 index 0000000..5860f5b --- /dev/null +++ b/packages/effects/common-ui/src/ui/about/index.ts @@ -0,0 +1 @@ +export { default as About } from './about.vue'; diff --git a/packages/effects/common-ui/src/ui/authentication/auth-title.vue b/packages/effects/common-ui/src/ui/authentication/auth-title.vue new file mode 100644 index 0000000..3ed9a6b --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/auth-title.vue @@ -0,0 +1,13 @@ + diff --git a/packages/effects/common-ui/src/ui/authentication/code-login.vue b/packages/effects/common-ui/src/ui/authentication/code-login.vue new file mode 100644 index 0000000..d7563d8 --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/code-login.vue @@ -0,0 +1,127 @@ + + + diff --git a/packages/effects/common-ui/src/ui/authentication/dingding-login.vue b/packages/effects/common-ui/src/ui/authentication/dingding-login.vue new file mode 100644 index 0000000..80b123c --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/dingding-login.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/packages/effects/common-ui/src/ui/authentication/doc-link.vue b/packages/effects/common-ui/src/ui/authentication/doc-link.vue new file mode 100644 index 0000000..abf43c8 --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/doc-link.vue @@ -0,0 +1,48 @@ + + + diff --git a/packages/effects/common-ui/src/ui/authentication/forget-password.vue b/packages/effects/common-ui/src/ui/authentication/forget-password.vue new file mode 100644 index 0000000..74befbd --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/forget-password.vue @@ -0,0 +1,116 @@ + + + diff --git a/packages/effects/common-ui/src/ui/authentication/index.ts b/packages/effects/common-ui/src/ui/authentication/index.ts new file mode 100644 index 0000000..868f002 --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/index.ts @@ -0,0 +1,9 @@ +export { default as AuthenticationAuthTitle } from './auth-title.vue'; +export { default as AuthenticationCodeLogin } from './code-login.vue'; +export { default as DocLink } from './doc-link.vue'; +export { default as AuthenticationForgetPassword } from './forget-password.vue'; +export { default as AuthenticationLoginExpiredModal } from './login-expired-modal.vue'; +export { default as AuthenticationLogin } from './login.vue'; +export { default as AuthenticationQrCodeLogin } from './qrcode-login.vue'; +export { default as AuthenticationRegister } from './register.vue'; +export type { AuthenticationProps } from './types'; diff --git a/packages/effects/common-ui/src/ui/authentication/login-expired-modal.vue b/packages/effects/common-ui/src/ui/authentication/login-expired-modal.vue new file mode 100644 index 0000000..ef5e6a0 --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/login-expired-modal.vue @@ -0,0 +1,95 @@ + + + diff --git a/packages/effects/common-ui/src/ui/authentication/login.vue b/packages/effects/common-ui/src/ui/authentication/login.vue new file mode 100644 index 0000000..c2a9c4b --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/login.vue @@ -0,0 +1,203 @@ + + + diff --git a/packages/effects/common-ui/src/ui/authentication/qrcode-login.vue b/packages/effects/common-ui/src/ui/authentication/qrcode-login.vue new file mode 100644 index 0000000..5d7cfac --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/qrcode-login.vue @@ -0,0 +1,106 @@ + + + diff --git a/packages/effects/common-ui/src/ui/authentication/register.vue b/packages/effects/common-ui/src/ui/authentication/register.vue new file mode 100644 index 0000000..69a69d4 --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/register.vue @@ -0,0 +1,121 @@ + + + diff --git a/packages/effects/common-ui/src/ui/authentication/third-party-login.vue b/packages/effects/common-ui/src/ui/authentication/third-party-login.vue new file mode 100644 index 0000000..fc36ce9 --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/third-party-login.vue @@ -0,0 +1,55 @@ + + + diff --git a/packages/effects/common-ui/src/ui/authentication/types.ts b/packages/effects/common-ui/src/ui/authentication/types.ts new file mode 100644 index 0000000..cb297e2 --- /dev/null +++ b/packages/effects/common-ui/src/ui/authentication/types.ts @@ -0,0 +1,70 @@ +interface AuthenticationProps { + /** + * @zh_CN 验证码登录路径 + */ + codeLoginPath?: string; + /** + * @zh_CN 忘记密码路径 + */ + forgetPasswordPath?: string; + + /** + * @zh_CN 是否处于加载处理状态 + */ + loading?: boolean; + + /** + * @zh_CN 二维码登录路径 + */ + qrCodeLoginPath?: string; + + /** + * @zh_CN 注册路径 + */ + registerPath?: string; + + /** + * @zh_CN 是否显示验证码登录 + */ + showCodeLogin?: boolean; + /** + * @zh_CN 是否显示忘记密码 + */ + showForgetPassword?: boolean; + + /** + * @zh_CN 是否显示二维码登录 + */ + showQrcodeLogin?: boolean; + + /** + * @zh_CN 是否显示注册按钮 + */ + showRegister?: boolean; + + /** + * @zh_CN 是否显示记住账号 + */ + showRememberMe?: boolean; + + /** + * @zh_CN 是否显示第三方登录 + */ + showThirdPartyLogin?: boolean; + + /** + * @zh_CN 登录框子标题 + */ + subTitle?: string; + + /** + * @zh_CN 登录框标题 + */ + title?: string; + /** + * @zh_CN 提交按钮文本 + */ + submitButtonText?: string; +} + +export type { AuthenticationProps }; diff --git a/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-chart-card.vue b/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-chart-card.vue new file mode 100644 index 0000000..294d517 --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-chart-card.vue @@ -0,0 +1,24 @@ + + + diff --git a/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-charts-tabs.vue b/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-charts-tabs.vue new file mode 100644 index 0000000..453ee5c --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-charts-tabs.vue @@ -0,0 +1,40 @@ + + + diff --git a/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-overview.vue b/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-overview.vue new file mode 100644 index 0000000..18c4929 --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-overview.vue @@ -0,0 +1,55 @@ + + + diff --git a/packages/effects/common-ui/src/ui/dashboard/analysis/index.ts b/packages/effects/common-ui/src/ui/dashboard/analysis/index.ts new file mode 100644 index 0000000..7c67b87 --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/analysis/index.ts @@ -0,0 +1,3 @@ +export { default as AnalysisChartCard } from './analysis-chart-card.vue'; +export { default as AnalysisChartsTabs } from './analysis-charts-tabs.vue'; +export { default as AnalysisOverview } from './analysis-overview.vue'; diff --git a/packages/effects/common-ui/src/ui/dashboard/index.ts b/packages/effects/common-ui/src/ui/dashboard/index.ts new file mode 100644 index 0000000..bc74424 --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/index.ts @@ -0,0 +1,3 @@ +export * from './analysis'; +export type * from './typing'; +export * from './workbench'; diff --git a/packages/effects/common-ui/src/ui/dashboard/typing.ts b/packages/effects/common-ui/src/ui/dashboard/typing.ts new file mode 100644 index 0000000..48fc9c7 --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/typing.ts @@ -0,0 +1,48 @@ +import type { Component } from 'vue'; + +interface AnalysisOverviewItem { + icon: Component | string; + title: string; + totalTitle: string; + totalValue: number; + value: number; +} + +interface WorkbenchProjectItem { + color?: string; + content: string; + date: string; + group: string; + icon: Component | string; + title: string; + url?: string; +} + +interface WorkbenchTrendItem { + avatar: string; + content: string; + date: string; + title: string; +} + +interface WorkbenchTodoItem { + completed: boolean; + content: string; + date: string; + title: string; +} + +interface WorkbenchQuickNavItem { + color?: string; + icon: Component | string; + title: string; + url?: string; +} + +export type { + AnalysisOverviewItem, + WorkbenchProjectItem, + WorkbenchQuickNavItem, + WorkbenchTodoItem, + WorkbenchTrendItem, +}; diff --git a/packages/effects/common-ui/src/ui/dashboard/workbench/index.ts b/packages/effects/common-ui/src/ui/dashboard/workbench/index.ts new file mode 100644 index 0000000..76b7af1 --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/workbench/index.ts @@ -0,0 +1,5 @@ +export { default as WorkbenchHeader } from './workbench-header.vue'; +export { default as WorkbenchProject } from './workbench-project.vue'; +export { default as WorkbenchQuickNav } from './workbench-quick-nav.vue'; +export { default as WorkbenchTodo } from './workbench-todo.vue'; +export { default as WorkbenchTrends } from './workbench-trends.vue'; diff --git a/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-header.vue b/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-header.vue new file mode 100644 index 0000000..a3ea3eb --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-header.vue @@ -0,0 +1,46 @@ + + diff --git a/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-project.vue b/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-project.vue new file mode 100644 index 0000000..236b476 --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-project.vue @@ -0,0 +1,64 @@ + + + diff --git a/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-quick-nav.vue b/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-quick-nav.vue new file mode 100644 index 0000000..86dc5c6 --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-quick-nav.vue @@ -0,0 +1,56 @@ + + + diff --git a/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-todo.vue b/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-todo.vue new file mode 100644 index 0000000..ef34cd0 --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-todo.vue @@ -0,0 +1,63 @@ + + + diff --git a/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-trends.vue b/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-trends.vue new file mode 100644 index 0000000..06f2a5e --- /dev/null +++ b/packages/effects/common-ui/src/ui/dashboard/workbench/workbench-trends.vue @@ -0,0 +1,64 @@ + + + diff --git a/packages/effects/common-ui/src/ui/fallback/fallback.ts b/packages/effects/common-ui/src/ui/fallback/fallback.ts new file mode 100644 index 0000000..5f8e193 --- /dev/null +++ b/packages/effects/common-ui/src/ui/fallback/fallback.ts @@ -0,0 +1,25 @@ +interface FallbackProps { + /** + * 描述 + */ + description?: string; + /** + * @zh_CN 首页路由地址 + * @default / + */ + homePath?: string; + /** + * @zh_CN 默认显示的图片 + * @default pageNotFoundSvg + */ + image?: string; + /** + * @zh_CN 内置类型 + */ + status?: '403' | '404' | '500' | 'coming-soon' | 'offline'; + /** + * @zh_CN 页面提示语 + */ + title?: string; +} +export type { FallbackProps }; diff --git a/packages/effects/common-ui/src/ui/fallback/fallback.vue b/packages/effects/common-ui/src/ui/fallback/fallback.vue new file mode 100644 index 0000000..76eafca --- /dev/null +++ b/packages/effects/common-ui/src/ui/fallback/fallback.vue @@ -0,0 +1,164 @@ + + + diff --git a/packages/effects/common-ui/src/ui/fallback/icons/icon-403.vue b/packages/effects/common-ui/src/ui/fallback/icons/icon-403.vue new file mode 100644 index 0000000..e390867 --- /dev/null +++ b/packages/effects/common-ui/src/ui/fallback/icons/icon-403.vue @@ -0,0 +1,151 @@ + diff --git a/packages/effects/common-ui/src/ui/fallback/icons/icon-404.vue b/packages/effects/common-ui/src/ui/fallback/icons/icon-404.vue new file mode 100644 index 0000000..385cf6a --- /dev/null +++ b/packages/effects/common-ui/src/ui/fallback/icons/icon-404.vue @@ -0,0 +1,154 @@ + diff --git a/packages/effects/common-ui/src/ui/fallback/icons/icon-500.vue b/packages/effects/common-ui/src/ui/fallback/icons/icon-500.vue new file mode 100644 index 0000000..97326b7 --- /dev/null +++ b/packages/effects/common-ui/src/ui/fallback/icons/icon-500.vue @@ -0,0 +1,215 @@ + diff --git a/packages/effects/common-ui/src/ui/fallback/icons/icon-coming-soon.vue b/packages/effects/common-ui/src/ui/fallback/icons/icon-coming-soon.vue new file mode 100644 index 0000000..e511c43 --- /dev/null +++ b/packages/effects/common-ui/src/ui/fallback/icons/icon-coming-soon.vue @@ -0,0 +1,262 @@ + diff --git a/packages/effects/common-ui/src/ui/fallback/icons/icon-offline.vue b/packages/effects/common-ui/src/ui/fallback/icons/icon-offline.vue new file mode 100644 index 0000000..9e50b19 --- /dev/null +++ b/packages/effects/common-ui/src/ui/fallback/icons/icon-offline.vue @@ -0,0 +1,112 @@ + diff --git a/packages/effects/common-ui/src/ui/fallback/icons/warning.svg b/packages/effects/common-ui/src/ui/fallback/icons/warning.svg new file mode 100644 index 0000000..951a905 --- /dev/null +++ b/packages/effects/common-ui/src/ui/fallback/icons/warning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/effects/common-ui/src/ui/fallback/index.ts b/packages/effects/common-ui/src/ui/fallback/index.ts new file mode 100644 index 0000000..f56f665 --- /dev/null +++ b/packages/effects/common-ui/src/ui/fallback/index.ts @@ -0,0 +1,2 @@ +export type * from './fallback'; +export { default as Fallback } from './fallback.vue'; diff --git a/packages/effects/common-ui/src/ui/index.ts b/packages/effects/common-ui/src/ui/index.ts new file mode 100644 index 0000000..8b1db55 --- /dev/null +++ b/packages/effects/common-ui/src/ui/index.ts @@ -0,0 +1,5 @@ +export * from './about'; +export * from './authentication'; +export * from './dashboard'; +export * from './fallback'; +export * from './profile'; diff --git a/packages/effects/common-ui/src/ui/profile/base-setting.vue b/packages/effects/common-ui/src/ui/profile/base-setting.vue new file mode 100644 index 0000000..15fc97b --- /dev/null +++ b/packages/effects/common-ui/src/ui/profile/base-setting.vue @@ -0,0 +1,58 @@ + + diff --git a/packages/effects/common-ui/src/ui/profile/index.ts b/packages/effects/common-ui/src/ui/profile/index.ts new file mode 100644 index 0000000..209a2e8 --- /dev/null +++ b/packages/effects/common-ui/src/ui/profile/index.ts @@ -0,0 +1,6 @@ +export { default as ProfileBaseSetting } from './base-setting.vue'; +export { default as ProfileNotificationSetting } from './notification-setting.vue'; +export { default as ProfilePasswordSetting } from './password-setting.vue'; +export { default as Profile } from './profile.vue'; +export { default as ProfileSecuritySetting } from './security-setting.vue'; +export type * from './types'; diff --git a/packages/effects/common-ui/src/ui/profile/notification-setting.vue b/packages/effects/common-ui/src/ui/profile/notification-setting.vue new file mode 100644 index 0000000..9a3e488 --- /dev/null +++ b/packages/effects/common-ui/src/ui/profile/notification-setting.vue @@ -0,0 +1,53 @@ + + diff --git a/packages/effects/common-ui/src/ui/profile/password-setting.vue b/packages/effects/common-ui/src/ui/profile/password-setting.vue new file mode 100644 index 0000000..06b9b3d --- /dev/null +++ b/packages/effects/common-ui/src/ui/profile/password-setting.vue @@ -0,0 +1,59 @@ + + diff --git a/packages/effects/common-ui/src/ui/profile/profile.vue b/packages/effects/common-ui/src/ui/profile/profile.vue new file mode 100644 index 0000000..47b83b4 --- /dev/null +++ b/packages/effects/common-ui/src/ui/profile/profile.vue @@ -0,0 +1,62 @@ + + diff --git a/packages/effects/common-ui/src/ui/profile/security-setting.vue b/packages/effects/common-ui/src/ui/profile/security-setting.vue new file mode 100644 index 0000000..9a3e488 --- /dev/null +++ b/packages/effects/common-ui/src/ui/profile/security-setting.vue @@ -0,0 +1,53 @@ + + diff --git a/packages/effects/common-ui/src/ui/profile/types.ts b/packages/effects/common-ui/src/ui/profile/types.ts new file mode 100644 index 0000000..e600bde --- /dev/null +++ b/packages/effects/common-ui/src/ui/profile/types.ts @@ -0,0 +1,21 @@ +import type { BasicUserInfo } from '@vben/types'; + +export interface Props { + title?: string; + userInfo: BasicUserInfo | null; + tabs: { + label: string; + value: string; + }[]; +} + +export interface FormSchemaItem { + description: string; + fieldName: string; + label: string; + value: boolean; +} + +export interface SettingProps { + formSchema: FormSchemaItem[]; +} diff --git a/packages/effects/common-ui/tsconfig.json b/packages/effects/common-ui/tsconfig.json new file mode 100644 index 0000000..ce1a891 --- /dev/null +++ b/packages/effects/common-ui/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/effects/hooks/README.md b/packages/effects/hooks/README.md new file mode 100644 index 0000000..54d9ff7 --- /dev/null +++ b/packages/effects/hooks/README.md @@ -0,0 +1,19 @@ +# @vben/hooks + +用于多个 `app` 公用的 hook,继承了 `@vben/hooks` 的所有能力。业务上有通用 hooks 可以放在这里。 + +## 用法 + +### 添加依赖 + +```bash +# 进入目标应用目录,例如 apps/xxxx-app +# cd apps/xxxx-app +pnpm add @vben/hooks +``` + +### 使用 + +```ts +import { useNamespace } from '@vben/hooks'; +``` diff --git a/packages/effects/hooks/package.json b/packages/effects/hooks/package.json new file mode 100644 index 0000000..d115a7e --- /dev/null +++ b/packages/effects/hooks/package.json @@ -0,0 +1,33 @@ +{ + "name": "@vben/hooks", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/effects/hooks" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "dependencies": { + "@vben-core/composables": "workspace:*", + "@vben/preferences": "workspace:*", + "@vben/stores": "workspace:*", + "@vben/types": "workspace:*", + "@vben/utils": "workspace:*", + "@vueuse/core": "catalog:", + "vue": "catalog:", + "vue-router": "catalog:", + "watermark-js-plus": "catalog:" + } +} diff --git a/packages/effects/hooks/src/index.ts b/packages/effects/hooks/src/index.ts new file mode 100644 index 0000000..b795bb3 --- /dev/null +++ b/packages/effects/hooks/src/index.ts @@ -0,0 +1,10 @@ +export * from './use-app-config'; +export * from './use-content-maximize'; +export * from './use-design-tokens'; +export * from './use-dict'; +export * from './use-hover-toggle'; +export * from './use-pagination'; +export * from './use-refresh'; +export * from './use-tabs'; +export * from './use-watermark'; +export * from '@vben-core/composables'; diff --git a/packages/effects/hooks/src/use-app-config.ts b/packages/effects/hooks/src/use-app-config.ts new file mode 100644 index 0000000..4448964 --- /dev/null +++ b/packages/effects/hooks/src/use-app-config.ts @@ -0,0 +1,48 @@ +import type { + ApplicationConfig, + VbenAdminProAppConfigRaw, +} from '@vben/types/global'; + +/** + * 由 vite-inject-app-config 注入的全局配置 + */ +export function useAppConfig( + env: Record, + isProduction: boolean, +): ApplicationConfig { + // 生产环境下,直接使用 window._VBEN_ADMIN_PRO_APP_CONF_ 全局变量 + const config = isProduction + ? window._VBEN_ADMIN_PRO_APP_CONF_ + : (env as VbenAdminProAppConfigRaw); + + const { + VITE_GLOB_API_URL, + VITE_GLOB_AUTH_DINGDING_CORP_ID, + VITE_GLOB_AUTH_DINGDING_CLIENT_ID, + } = config; + + const applicationConfig: ApplicationConfig = { + apiURL: VITE_GLOB_API_URL, + auth: {}, + }; + if (VITE_GLOB_AUTH_DINGDING_CORP_ID && VITE_GLOB_AUTH_DINGDING_CLIENT_ID) { + applicationConfig.auth.dingding = { + clientId: VITE_GLOB_AUTH_DINGDING_CLIENT_ID, + corpId: VITE_GLOB_AUTH_DINGDING_CORP_ID, + }; + } + + return applicationConfig; +} + +export function isTenantEnable(): boolean { + return import.meta.env.VITE_APP_TENANT_ENABLE === 'true'; +} + +export function isCaptchaEnable(): boolean { + return import.meta.env.VITE_APP_CAPTCHA_ENABLE === 'true'; +} + +export function isDocAlertEnable(): boolean { + return import.meta.env.VITE_APP_DOCALERT_ENABLE !== 'false'; +} diff --git a/packages/effects/hooks/src/use-content-maximize.ts b/packages/effects/hooks/src/use-content-maximize.ts new file mode 100644 index 0000000..a580d6e --- /dev/null +++ b/packages/effects/hooks/src/use-content-maximize.ts @@ -0,0 +1,44 @@ +import { updatePreferences, usePreferences } from '@vben/preferences'; +/** + * 主体区域最大化 + */ +export function useContentMaximize() { + const { contentIsMaximize } = usePreferences(); + + function toggleMaximize() { + const isMaximize = contentIsMaximize.value; + + updatePreferences({ + header: { + hidden: !isMaximize, + }, + sidebar: { + hidden: !isMaximize, + }, + }); + } + + /** + * 切换最大化和隐藏 tabbar + */ + function toggleMaximizeAndTabbarHidden() { + const isMaximize = contentIsMaximize.value; + updatePreferences({ + header: { + hidden: !isMaximize, + }, + sidebar: { + hidden: !isMaximize, + }, + tabbar: { + enable: isMaximize, + }, + }); + } + + return { + contentIsMaximize, + toggleMaximize, + toggleMaximizeAndTabbarHidden, + }; +} diff --git a/packages/effects/hooks/src/use-design-tokens.ts b/packages/effects/hooks/src/use-design-tokens.ts new file mode 100644 index 0000000..6a076f3 --- /dev/null +++ b/packages/effects/hooks/src/use-design-tokens.ts @@ -0,0 +1,321 @@ +import { reactive, watch } from 'vue'; + +import { preferences, usePreferences } from '@vben/preferences'; +import { convertToRgb, updateCSSVariables } from '@vben/utils'; + +/** + * 用于适配各个框架的设计系统 + */ + +export function useAntdDesignTokens() { + const rootStyles = getComputedStyle(document.documentElement); + + const tokens = reactive({ + borderRadius: '' as any, + colorBgBase: '', + colorBgContainer: '', + colorBgElevated: '', + colorBgLayout: '', + colorBgMask: '', + colorBorder: '', + colorBorderSecondary: '', + colorError: '', + colorInfo: '', + colorPrimary: '', + colorSuccess: '', + colorTextBase: '', + colorWarning: '', + zIndexPopupBase: 2000, // 调整基础弹层层级,避免下拉等组件被弹窗或者最大化状态下的表格遮挡 + }); + + const getCssVariableValue = (variable: string, isColor: boolean = true) => { + const value = rootStyles.getPropertyValue(variable); + return isColor ? `hsl(${value})` : value; + }; + + watch( + () => preferences.theme, + () => { + tokens.colorPrimary = getCssVariableValue('--primary'); + + tokens.colorInfo = getCssVariableValue('--primary'); + + tokens.colorError = getCssVariableValue('--destructive'); + + tokens.colorWarning = getCssVariableValue('--warning'); + + tokens.colorSuccess = getCssVariableValue('--success'); + + tokens.colorTextBase = getCssVariableValue('--foreground'); + + getCssVariableValue('--primary-foreground'); + + tokens.colorBorderSecondary = tokens.colorBorder = + getCssVariableValue('--border'); + + tokens.colorBgElevated = getCssVariableValue('--popover'); + + tokens.colorBgContainer = getCssVariableValue('--card'); + + tokens.colorBgBase = getCssVariableValue('--background'); + + const radius = Number.parseFloat(getCssVariableValue('--radius', false)); + // 1rem = 16px + tokens.borderRadius = radius * 16; + + tokens.colorBgLayout = getCssVariableValue('--background-deep'); + tokens.colorBgMask = getCssVariableValue('--overlay'); + }, + { immediate: true }, + ); + + return { + tokens, + }; +} + +export function useNaiveDesignTokens() { + const rootStyles = getComputedStyle(document.documentElement); + + const commonTokens = reactive({ + baseColor: '', + bodyColor: '', + borderColor: '', + borderRadius: '', + cardColor: '', + dividerColor: '', + errorColor: '', + errorColorHover: '', + errorColorPressed: '', + errorColorSuppl: '', + invertedColor: '', + modalColor: '', + popoverColor: '', + primaryColor: '', + primaryColorHover: '', + primaryColorPressed: '', + primaryColorSuppl: '', + successColor: '', + successColorHover: '', + successColorPressed: '', + successColorSuppl: '', + tableColor: '', + textColorBase: '', + warningColor: '', + warningColorHover: '', + warningColorPressed: '', + warningColorSuppl: '', + }); + + const getCssVariableValue = (variable: string, isColor: boolean = true) => { + const value = rootStyles.getPropertyValue(variable); + return isColor ? convertToRgb(`hsl(${value})`) : value; + }; + + watch( + () => preferences.theme, + () => { + commonTokens.primaryColor = getCssVariableValue('--primary'); + commonTokens.primaryColorHover = getCssVariableValue('--primary-600'); + commonTokens.primaryColorPressed = getCssVariableValue('--primary-700'); + commonTokens.primaryColorSuppl = getCssVariableValue('--primary-800'); + + commonTokens.errorColor = getCssVariableValue('--destructive'); + commonTokens.errorColorHover = getCssVariableValue('--destructive-600'); + commonTokens.errorColorPressed = getCssVariableValue('--destructive-700'); + commonTokens.errorColorSuppl = getCssVariableValue('--destructive-800'); + + commonTokens.warningColor = getCssVariableValue('--warning'); + commonTokens.warningColorHover = getCssVariableValue('--warning-600'); + commonTokens.warningColorPressed = getCssVariableValue('--warning-700'); + commonTokens.warningColorSuppl = getCssVariableValue('--warning-800'); + + commonTokens.successColor = getCssVariableValue('--success'); + commonTokens.successColorHover = getCssVariableValue('--success-600'); + commonTokens.successColorPressed = getCssVariableValue('--success-700'); + commonTokens.successColorSuppl = getCssVariableValue('--success-800'); + + commonTokens.textColorBase = getCssVariableValue('--foreground'); + + commonTokens.baseColor = getCssVariableValue('--primary-foreground'); + + commonTokens.dividerColor = commonTokens.borderColor = + getCssVariableValue('--border'); + + commonTokens.modalColor = commonTokens.popoverColor = + getCssVariableValue('--popover'); + + commonTokens.tableColor = commonTokens.cardColor = + getCssVariableValue('--card'); + + commonTokens.bodyColor = getCssVariableValue('--background'); + commonTokens.invertedColor = getCssVariableValue('--background-deep'); + + commonTokens.borderRadius = getCssVariableValue('--radius', false); + }, + { immediate: true }, + ); + return { + commonTokens, + }; +} + +export function useElementPlusDesignTokens() { + const { isDark } = usePreferences(); + const rootStyles = getComputedStyle(document.documentElement); + + const getCssVariableValueRaw = (variable: string) => { + return rootStyles.getPropertyValue(variable); + }; + + const getCssVariableValue = (variable: string, isColor: boolean = true) => { + const value = getCssVariableValueRaw(variable); + return isColor ? convertToRgb(`hsl(${value})`) : value; + }; + + watch( + () => preferences.theme, + () => { + const background = getCssVariableValue('--background'); + const border = getCssVariableValue('--border'); + const accent = getCssVariableValue('--accent'); + + const variables: Record = { + '--el-bg-color': background, + '--el-bg-color-overlay': getCssVariableValue('--popover'), + '--el-bg-color-page': getCssVariableValue('--background-deep'), + '--el-border-color': border, + '--el-border-color-dark': border, + '--el-border-color-extra-light': border, + '--el-border-color-hover': accent, + '--el-border-color-light': border, + '--el-border-color-lighter': border, + + '--el-border-radius-base': getCssVariableValue('--radius', false), + '--el-color-danger': getCssVariableValue('--destructive-500'), + '--el-color-danger-dark-2': isDark.value + ? getCssVariableValue('--destructive-400') + : getCssVariableValue('--destructive-600'), + '--el-color-danger-light-3': isDark.value + ? getCssVariableValue('--destructive-600') + : getCssVariableValue('--destructive-400'), + '--el-color-danger-light-5': isDark.value + ? getCssVariableValue('--destructive-700') + : getCssVariableValue('--destructive-300'), + '--el-color-danger-light-7': isDark.value + ? getCssVariableValue('--destructive-800') + : getCssVariableValue('--destructive-200'), + '--el-color-danger-light-8': isDark.value + ? getCssVariableValue('--destructive-900') + : getCssVariableValue('--destructive-100'), + '--el-color-danger-light-9': isDark.value + ? getCssVariableValue('--destructive-950') + : getCssVariableValue('--destructive-50'), + + '--el-color-error': getCssVariableValue('--destructive-500'), + '--el-color-error-dark-2': isDark.value + ? getCssVariableValue('--destructive-400') + : getCssVariableValue('--destructive-600'), + '--el-color-error-light-3': isDark.value + ? getCssVariableValue('--destructive-600') + : getCssVariableValue('--destructive-400'), + '--el-color-error-light-5': isDark.value + ? getCssVariableValue('--destructive-700') + : getCssVariableValue('--destructive-300'), + '--el-color-error-light-7': isDark.value + ? getCssVariableValue('--destructive-800') + : getCssVariableValue('--destructive-200'), + '--el-color-error-light-8': isDark.value + ? getCssVariableValue('--destructive-900') + : getCssVariableValue('--destructive-100'), + '--el-color-error-light-9': isDark.value + ? getCssVariableValue('--destructive-950') + : getCssVariableValue('--destructive-50'), + + '--el-color-info-light-5': border, + '--el-color-info-light-8': border, + '--el-color-info-light-9': getCssVariableValue('--info'), // getCssVariableValue('--secondary'), + + '--el-color-primary': getCssVariableValue('--primary-500'), + '--el-color-primary-dark-2': isDark.value + ? getCssVariableValue('--primary-400') + : getCssVariableValue('--primary-600'), + '--el-color-primary-light-3': isDark.value + ? getCssVariableValue('--primary-600') + : getCssVariableValue('--primary-400'), + '--el-color-primary-light-5': isDark.value + ? getCssVariableValue('--primary-700') + : getCssVariableValue('--primary-300'), + '--el-color-primary-light-7': isDark.value + ? getCssVariableValue('--primary-800') + : getCssVariableValue('--primary-200'), + '--el-color-primary-light-8': isDark.value + ? getCssVariableValue('--primary-900') + : getCssVariableValue('--primary-100'), + '--el-color-primary-light-9': isDark.value + ? getCssVariableValue('--primary-950') + : getCssVariableValue('--primary-50'), + + '--el-color-success': getCssVariableValue('--success-500'), + '--el-color-success-dark-2': isDark.value + ? getCssVariableValue('--success-400') + : getCssVariableValue('--success-600'), + '--el-color-success-light-3': isDark.value + ? getCssVariableValue('--success-600') + : getCssVariableValue('--success-400'), + '--el-color-success-light-5': isDark.value + ? getCssVariableValue('--success-700') + : getCssVariableValue('--success-300'), + '--el-color-success-light-7': isDark.value + ? getCssVariableValue('--success-800') + : getCssVariableValue('--success-200'), + '--el-color-success-light-8': isDark.value + ? getCssVariableValue('--success-900') + : getCssVariableValue('--success-100'), + '--el-color-success-light-9': isDark.value + ? getCssVariableValue('--success-950') + : getCssVariableValue('--success-50'), + + '--el-color-warning': getCssVariableValue('--warning-500'), + '--el-color-warning-dark-2': isDark.value + ? getCssVariableValue('--warning-400') + : getCssVariableValue('--warning-600'), + '--el-color-warning-light-3': isDark.value + ? getCssVariableValue('--warning-600') + : getCssVariableValue('--warning-400'), + '--el-color-warning-light-5': isDark.value + ? getCssVariableValue('--warning-700') + : getCssVariableValue('--warning-300'), + '--el-color-warning-light-7': isDark.value + ? getCssVariableValue('--warning-800') + : getCssVariableValue('--warning-200'), + '--el-color-warning-light-8': isDark.value + ? getCssVariableValue('--warning-900') + : getCssVariableValue('--warning-100'), + '--el-color-warning-light-9': isDark.value + ? getCssVariableValue('--warning-950') + : getCssVariableValue('--warning-50'), + + '--el-fill-color': getCssVariableValue('--accent'), + '--el-fill-color-blank': background, + '--el-fill-color-light': getCssVariableValue('--accent'), + '--el-fill-color-lighter': getCssVariableValue('--accent-lighter'), + + '--el-fill-color-dark': getCssVariableValue('--accent-dark'), + '--el-fill-color-darker': getCssVariableValue('--accent-darker'), + + // 解决ElLoading背景色问题 + '--el-mask-color': isDark.value + ? 'rgba(0,0,0,.8)' + : 'rgba(255,255,255,.9)', + + '--el-text-color-primary': getCssVariableValue('--foreground'), + + '--el-text-color-regular': getCssVariableValue('--foreground'), + }; + + updateCSSVariables(variables, `__vben_design_styles__`); + }, + { immediate: true }, + ); +} diff --git a/packages/effects/hooks/src/use-dict.ts b/packages/effects/hooks/src/use-dict.ts new file mode 100644 index 0000000..a1e49ea --- /dev/null +++ b/packages/effects/hooks/src/use-dict.ts @@ -0,0 +1,87 @@ +import { useDictStore } from '@vben/stores'; +import { isObject } from '@vben/utils'; + +type ColorType = 'error' | 'info' | 'success' | 'warning'; + +export interface DictDataType { + dictType?: string; + label: string; + value: boolean | number | string; + colorType?: ColorType; + cssClass?: string; +} + +export interface NumberDictDataType extends DictDataType { + value: number; +} + +export interface StringDictDataType extends DictDataType { + value: string; +} + +/** + * 获取字典标签 + * + * @param dictType 字典类型 + * @param value 字典值 + * @returns 字典标签 + */ +export function getDictLabel(dictType: string, value: any) { + const dictStore = useDictStore(); + const dictObj = dictStore.getDictData(dictType, value); + return isObject(dictObj) ? dictObj.label : ''; +} + +/** + * 获取字典对象 + * + * @param dictType 字典类型 + * @param value 字典值 + * @returns 字典对象 + */ +export function getDictObj(dictType: string, value: any) { + const dictStore = useDictStore(); + const dictObj = dictStore.getDictData(dictType, value); + return isObject(dictObj) ? dictObj : null; +} + +/** + * 获取字典数组 用于select radio 等 + * + * @param dictType 字典类型 + * @param valueType 字典值类型,默认 string 类型 + * @returns 字典数组 + */ +export function getDictOptions( + dictType: string, + valueType: 'boolean' | 'number' | 'string' = 'string', +): DictDataType[] { + const dictStore = useDictStore(); + const dictOpts = dictStore.getDictOptions(dictType); + const dictOptions: DictDataType[] = []; + if (dictOpts.length > 0) { + let dictValue: boolean | number | string = ''; + dictOpts.forEach((d) => { + switch (valueType) { + case 'boolean': { + dictValue = `${d.value}` === 'true'; + break; + } + case 'number': { + dictValue = Number.parseInt(`${d.value}`); + break; + } + case 'string': { + dictValue = `${d.value}`; + break; + } + // No default + } + dictOptions.push({ + value: dictValue, + label: d.label, + }); + }); + } + return dictOptions.length > 0 ? dictOptions : []; +} diff --git a/packages/effects/hooks/src/use-hover-toggle.ts b/packages/effects/hooks/src/use-hover-toggle.ts new file mode 100644 index 0000000..0bed41d --- /dev/null +++ b/packages/effects/hooks/src/use-hover-toggle.ts @@ -0,0 +1,163 @@ +import type { Arrayable, MaybeElementRef } from '@vueuse/core'; + +import type { Ref } from 'vue'; + +import { computed, effectScope, onUnmounted, ref, unref, watch } from 'vue'; + +import { isFunction } from '@vben/utils'; + +import { useElementHover } from '@vueuse/core'; + +interface HoverDelayOptions { + /** 鼠标进入延迟时间 */ + enterDelay?: (() => number) | number; + /** 鼠标离开延迟时间 */ + leaveDelay?: (() => number) | number; +} + +const DEFAULT_LEAVE_DELAY = 500; // 鼠标离开延迟时间,默认为 500ms +const DEFAULT_ENTER_DELAY = 0; // 鼠标进入延迟时间,默认为 0(立即响应) + +/** + * 监测鼠标是否在元素内部,如果在元素内部则返回 true,否则返回 false + * @param refElement 所有需要检测的元素。支持单个元素、元素数组或响应式引用的元素数组。如果鼠标在任何一个元素内部都会返回 true + * @param delay 延迟更新状态的时间,可以是数字或包含进入/离开延迟的配置对象 + * @returns 返回一个数组,第一个元素是一个 ref,表示鼠标是否在元素内部,第二个元素是一个控制器,可以通过 enable 和 disable 方法来控制监听器的启用和禁用 + */ +export function useHoverToggle( + refElement: Arrayable | Ref, + delay: (() => number) | HoverDelayOptions | number = DEFAULT_LEAVE_DELAY, +) { + // 兼容旧版本API + const normalizedOptions: HoverDelayOptions = + typeof delay === 'number' || isFunction(delay) + ? { enterDelay: DEFAULT_ENTER_DELAY, leaveDelay: delay } + : { + enterDelay: DEFAULT_ENTER_DELAY, + leaveDelay: DEFAULT_LEAVE_DELAY, + ...delay, + }; + + const value = ref(false); + const enterTimer = ref | undefined>(); + const leaveTimer = ref | undefined>(); + const hoverScopes = ref[]>([]); + + // 使用计算属性包装 refElement,使其响应式变化 + const refs = computed(() => { + const raw = unref(refElement); + if (raw === null) return []; + return Array.isArray(raw) ? raw : [raw]; + }); + // 存储所有 hover 状态 + const isHovers = ref>>([]); + + // 更新 hover 监听的函数 + function updateHovers() { + // 停止并清理之前的作用域 + hoverScopes.value.forEach((scope) => scope.stop()); + hoverScopes.value = []; + + isHovers.value = refs.value.map((refEle) => { + if (!refEle) { + return ref(false); + } + const eleRef = computed(() => { + const ele = unref(refEle); + return ele instanceof Element ? ele : (ele?.$el as Element); + }); + + // 为每个元素创建独立的作用域 + const scope = effectScope(); + const hoverRef = scope.run(() => useElementHover(eleRef)) || ref(false); + hoverScopes.value.push(scope); + + return hoverRef; + }); + } + + // 监听元素数量变化,避免过度执行 + const elementsCount = computed(() => { + const raw = unref(refElement); + if (raw === null) return 0; + return Array.isArray(raw) ? raw.length : 1; + }); + + // 初始设置 + updateHovers(); + + // 只在元素数量变化时重新设置监听器 + const stopWatcher = watch(elementsCount, updateHovers, { deep: false }); + + const isOutsideAll = computed(() => isHovers.value.every((v) => !v.value)); + + function clearTimers() { + if (enterTimer.value) { + clearTimeout(enterTimer.value); + enterTimer.value = undefined; + } + if (leaveTimer.value) { + clearTimeout(leaveTimer.value); + leaveTimer.value = undefined; + } + } + + function setValueDelay(val: boolean) { + clearTimers(); + + if (val) { + // 鼠标进入 + const enterDelay = normalizedOptions.enterDelay ?? DEFAULT_ENTER_DELAY; + const delayTime = isFunction(enterDelay) ? enterDelay() : enterDelay; + + if (delayTime <= 0) { + value.value = true; + } else { + enterTimer.value = setTimeout(() => { + value.value = true; + enterTimer.value = undefined; + }, delayTime); + } + } else { + // 鼠标离开 + const leaveDelay = normalizedOptions.leaveDelay ?? DEFAULT_LEAVE_DELAY; + const delayTime = isFunction(leaveDelay) ? leaveDelay() : leaveDelay; + + if (delayTime <= 0) { + value.value = false; + } else { + leaveTimer.value = setTimeout(() => { + value.value = false; + leaveTimer.value = undefined; + }, delayTime); + } + } + } + + const hoverWatcher = watch( + isOutsideAll, + (val) => { + setValueDelay(!val); + }, + { immediate: true }, + ); + + const controller = { + enable() { + hoverWatcher.resume(); + }, + disable() { + hoverWatcher.pause(); + }, + }; + + onUnmounted(() => { + clearTimers(); + // 停止监听器 + stopWatcher(); + // 停止所有剩余的作用域 + hoverScopes.value.forEach((scope) => scope.stop()); + }); + + return [value, controller] as [typeof value, typeof controller]; +} diff --git a/packages/effects/hooks/src/use-pagination.ts b/packages/effects/hooks/src/use-pagination.ts new file mode 100644 index 0000000..0115606 --- /dev/null +++ b/packages/effects/hooks/src/use-pagination.ts @@ -0,0 +1,72 @@ +import type { Ref } from 'vue'; + +import { computed, ref, unref, watch } from 'vue'; + +/** + * Paginates an array of items + * @param list The array to paginate + * @param pageNo The current page number (1-based) + * @param pageSize Number of items per page + * @returns Paginated array slice + * @throws {Error} If pageNo or pageSize are invalid + */ +function pagination(list: T[], pageNo: number, pageSize: number): T[] { + if (pageNo < 1) throw new Error('Page number must be positive'); + if (pageSize < 1) throw new Error('Page size must be positive'); + + const offset = (pageNo - 1) * Number(pageSize); + const ret = + offset + pageSize >= list.length + ? list.slice(offset) + : list.slice(offset, offset + pageSize); + return ret; +} + +export function usePagination( + list: Ref, + pageSize: number, + totalChangeToFirstPage = true, +) { + const currentPage = ref(1); + const pageSizeRef = ref(pageSize); + + const totalPages = computed(() => + Math.ceil(unref(list).length / unref(pageSizeRef)), + ); + + const paginationList = computed(() => { + return pagination(unref(list), unref(currentPage), unref(pageSizeRef)); + }); + + const total = computed(() => { + return unref(list).length; + }); + + if (totalChangeToFirstPage) { + watch(total, () => { + setCurrentPage(1); + }); + } + + function setCurrentPage(page: number) { + if (page === 1 && unref(totalPages) === 0) { + currentPage.value = 1; + } else { + if (page < 1 || page > unref(totalPages)) { + throw new Error('Invalid page number'); + } + currentPage.value = page; + } + } + + function setPageSize(pageSize: number) { + if (pageSize < 1) { + throw new Error('Page size must be positive'); + } + pageSizeRef.value = pageSize; + // Reset to first page to prevent invalid state + currentPage.value = 1; + } + + return { setCurrentPage, total, setPageSize, paginationList, currentPage }; +} diff --git a/packages/effects/hooks/src/use-refresh.ts b/packages/effects/hooks/src/use-refresh.ts new file mode 100644 index 0000000..b3a5cae --- /dev/null +++ b/packages/effects/hooks/src/use-refresh.ts @@ -0,0 +1,16 @@ +import { useRouter } from 'vue-router'; + +import { useTabbarStore } from '@vben/stores'; + +export function useRefresh() { + const router = useRouter(); + const tabbarStore = useTabbarStore(); + + async function refresh() { + await tabbarStore.refresh(router); + } + + return { + refresh, + }; +} diff --git a/packages/effects/hooks/src/use-tabs.ts b/packages/effects/hooks/src/use-tabs.ts new file mode 100644 index 0000000..5267211 --- /dev/null +++ b/packages/effects/hooks/src/use-tabs.ts @@ -0,0 +1,133 @@ +import type { ComputedRef } from 'vue'; +import type { RouteLocationNormalized } from 'vue-router'; + +import { useRoute, useRouter } from 'vue-router'; + +import { useTabbarStore } from '@vben/stores'; + +export function useTabs() { + const router = useRouter(); + const route = useRoute(); + const tabbarStore = useTabbarStore(); + + async function closeLeftTabs(tab?: RouteLocationNormalized) { + await tabbarStore.closeLeftTabs(tab || route); + } + + async function closeAllTabs() { + await tabbarStore.closeAllTabs(router); + } + + async function closeRightTabs(tab?: RouteLocationNormalized) { + await tabbarStore.closeRightTabs(tab || route); + } + + async function closeOtherTabs(tab?: RouteLocationNormalized) { + await tabbarStore.closeOtherTabs(tab || route); + } + + async function closeCurrentTab(tab?: RouteLocationNormalized) { + await tabbarStore.closeTab(tab || route, router); + } + + async function pinTab(tab?: RouteLocationNormalized) { + await tabbarStore.pinTab(tab || route); + } + + async function unpinTab(tab?: RouteLocationNormalized) { + await tabbarStore.unpinTab(tab || route); + } + + async function toggleTabPin(tab?: RouteLocationNormalized) { + await tabbarStore.toggleTabPin(tab || route); + } + + async function refreshTab(name?: string) { + await tabbarStore.refresh(name || router); + } + + async function openTabInNewWindow(tab?: RouteLocationNormalized) { + await tabbarStore.openTabInNewWindow(tab || route); + } + + async function closeTabByKey(key: string) { + await tabbarStore.closeTabByKey(key, router); + } + + /** + * 设置当前标签页的标题 + * + * @description 支持设置静态标题字符串或动态计算标题 + * @description 动态标题会在每次渲染时重新计算,适用于多语言或状态相关的标题 + * + * @param title - 标题内容 + * - 静态标题: 直接传入字符串 + * - 动态标题: 传入 ComputedRef + * + * @example + * // 静态标题 + * setTabTitle('标签页') + * + * // 动态标题(多语言) + * setTabTitle(computed(() => t('page.title'))) + */ + async function setTabTitle(title: ComputedRef | string) { + tabbarStore.setUpdateTime(); + await tabbarStore.setTabTitle(route, title); + } + + async function resetTabTitle() { + tabbarStore.setUpdateTime(); + await tabbarStore.resetTabTitle(route); + } + + /** + * 获取操作是否禁用 + * @param tab + */ + function getTabDisableState(tab: RouteLocationNormalized = route) { + const tabs = tabbarStore.getTabs; + const affixTabs = tabbarStore.affixTabs; + const index = tabs.findIndex((item) => item.path === tab.path); + + const disabled = tabs.length <= 1; + + const { meta } = tab; + const affixTab = meta?.affixTab ?? false; + const isCurrentTab = route.path === tab.path; + + // 当前处于最左侧或者减去固定标签页的数量等于0 + const disabledCloseLeft = + index === 0 || index - affixTabs.length <= 0 || !isCurrentTab; + + const disabledCloseRight = !isCurrentTab || index === tabs.length - 1; + + const disabledCloseOther = + disabled || !isCurrentTab || tabs.length - affixTabs.length <= 1; + return { + disabledCloseAll: disabled, + disabledCloseCurrent: !!affixTab || disabled, + disabledCloseLeft, + disabledCloseOther, + disabledCloseRight, + disabledRefresh: !isCurrentTab, + }; + } + + return { + closeAllTabs, + closeCurrentTab, + closeLeftTabs, + closeOtherTabs, + closeRightTabs, + closeTabByKey, + getTabDisableState, + openTabInNewWindow, + pinTab, + refreshTab, + resetTabTitle, + setTabTitle, + toggleTabPin, + unpinTab, + }; +} diff --git a/packages/effects/hooks/src/use-watermark.ts b/packages/effects/hooks/src/use-watermark.ts new file mode 100644 index 0000000..8484a08 --- /dev/null +++ b/packages/effects/hooks/src/use-watermark.ts @@ -0,0 +1,84 @@ +import type { Watermark, WatermarkOptions } from 'watermark-js-plus'; + +import { nextTick, onUnmounted, readonly, ref } from 'vue'; + +const watermark = ref(); +const unmountedHooked = ref(false); +const cachedOptions = ref>({ + advancedStyle: { + colorStops: [ + { + color: 'gray', + offset: 0, + }, + { + color: 'gray', + offset: 1, + }, + ], + type: 'linear', + }, + // fontSize: '20px', + content: '', + contentType: 'multi-line-text', + globalAlpha: 0.25, + gridLayoutOptions: { + cols: 2, + gap: [20, 20], + matrix: [ + [1, 0], + [0, 1], + ], + rows: 2, + }, + height: 200, + layout: 'grid', + rotate: 30, + width: 160, +}); + +export function useWatermark() { + async function initWatermark(options: Partial) { + const { Watermark } = await import('watermark-js-plus'); + + cachedOptions.value = { + ...cachedOptions.value, + ...options, + }; + watermark.value = new Watermark(cachedOptions.value); + await watermark.value?.create(); + } + + async function updateWatermark(options: Partial) { + if (watermark.value) { + await nextTick(); + await watermark.value?.changeOptions({ + ...cachedOptions.value, + ...options, + }); + } else { + await initWatermark(options); + } + } + + function destroyWatermark() { + if (watermark.value) { + watermark.value.destroy(); + watermark.value = undefined; + } + } + + // 只在第一次调用时注册卸载钩子,防止重复注册以致于在路由切换时销毁了水印 + if (!unmountedHooked.value) { + unmountedHooked.value = true; + onUnmounted(() => { + destroyWatermark(); + }); + } + + return { + destroyWatermark, + updateWatermark, + watermark: readonly(watermark), + }; +} diff --git a/packages/effects/hooks/tsconfig.json b/packages/effects/hooks/tsconfig.json new file mode 100644 index 0000000..b13aa7a --- /dev/null +++ b/packages/effects/hooks/tsconfig.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "compilerOptions": { + "types": ["vite/client", "@vben/types/global"] + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/effects/layouts/package.json b/packages/effects/layouts/package.json new file mode 100644 index 0000000..58fc6f4 --- /dev/null +++ b/packages/effects/layouts/package.json @@ -0,0 +1,43 @@ +{ + "name": "@vben/layouts", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/effects/layouts" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "dependencies": { + "@vben-core/composables": "workspace:*", + "@vben-core/form-ui": "workspace:*", + "@vben-core/layout-ui": "workspace:*", + "@vben-core/menu-ui": "workspace:*", + "@vben-core/popup-ui": "workspace:*", + "@vben-core/shadcn-ui": "workspace:*", + "@vben-core/shared": "workspace:*", + "@vben-core/tabs-ui": "workspace:*", + "@vben/constants": "workspace:*", + "@vben/hooks": "workspace:*", + "@vben/icons": "workspace:*", + "@vben/locales": "workspace:*", + "@vben/preferences": "workspace:*", + "@vben/stores": "workspace:*", + "@vben/types": "workspace:*", + "@vben/utils": "workspace:*", + "@vueuse/core": "catalog:", + "vue": "catalog:", + "vue-router": "catalog:" + } +} diff --git a/packages/effects/layouts/src/authentication/authentication.vue b/packages/effects/layouts/src/authentication/authentication.vue new file mode 100644 index 0000000..6d3bf8c --- /dev/null +++ b/packages/effects/layouts/src/authentication/authentication.vue @@ -0,0 +1,196 @@ + + + + + diff --git a/packages/effects/layouts/src/authentication/form.vue b/packages/effects/layouts/src/authentication/form.vue new file mode 100644 index 0000000..fa73e12 --- /dev/null +++ b/packages/effects/layouts/src/authentication/form.vue @@ -0,0 +1,38 @@ + + + diff --git a/packages/effects/layouts/src/authentication/icons/slogan.vue b/packages/effects/layouts/src/authentication/icons/slogan.vue new file mode 100644 index 0000000..82cc119 --- /dev/null +++ b/packages/effects/layouts/src/authentication/icons/slogan.vue @@ -0,0 +1,4568 @@ + diff --git a/packages/effects/layouts/src/authentication/index.ts b/packages/effects/layouts/src/authentication/index.ts new file mode 100644 index 0000000..d7c1c29 --- /dev/null +++ b/packages/effects/layouts/src/authentication/index.ts @@ -0,0 +1,2 @@ +export { default as AuthPageLayout } from './authentication.vue'; +export * from './types'; diff --git a/packages/effects/layouts/src/authentication/toolbar.vue b/packages/effects/layouts/src/authentication/toolbar.vue new file mode 100644 index 0000000..94d321a --- /dev/null +++ b/packages/effects/layouts/src/authentication/toolbar.vue @@ -0,0 +1,49 @@ + + + diff --git a/packages/effects/layouts/src/authentication/types.ts b/packages/effects/layouts/src/authentication/types.ts new file mode 100644 index 0000000..c4c1c7f --- /dev/null +++ b/packages/effects/layouts/src/authentication/types.ts @@ -0,0 +1 @@ +export type ToolbarType = 'color' | 'language' | 'layout' | 'theme'; diff --git a/packages/effects/layouts/src/basic/README.md b/packages/effects/layouts/src/basic/README.md new file mode 100644 index 0000000..b1266ea --- /dev/null +++ b/packages/effects/layouts/src/basic/README.md @@ -0,0 +1,7 @@ +## layout + +### header + +- 支持N个自定义插槽,命名方式:header-right-n,header-left-n +- header-left-n ,排序方式:0-19 ,breadcrumb 21-x +- header-right-n ,排序方式:0-49,global-search,51-59,theme-toggle,61-69,language-toggle,71-79,fullscreen,81-89,notification,91-149,user-dropdown,151-x diff --git a/packages/effects/layouts/src/basic/content/content-spinner.vue b/packages/effects/layouts/src/basic/content/content-spinner.vue new file mode 100644 index 0000000..e97e4b6 --- /dev/null +++ b/packages/effects/layouts/src/basic/content/content-spinner.vue @@ -0,0 +1,12 @@ + + diff --git a/packages/effects/layouts/src/basic/content/content.vue b/packages/effects/layouts/src/basic/content/content.vue new file mode 100644 index 0000000..8b8a639 --- /dev/null +++ b/packages/effects/layouts/src/basic/content/content.vue @@ -0,0 +1,148 @@ + + + diff --git a/packages/effects/layouts/src/basic/content/index.ts b/packages/effects/layouts/src/basic/content/index.ts new file mode 100644 index 0000000..8372b20 --- /dev/null +++ b/packages/effects/layouts/src/basic/content/index.ts @@ -0,0 +1,2 @@ +export { default as LayoutContentSpinner } from './content-spinner.vue'; +export { default as LayoutContent } from './content.vue'; diff --git a/packages/effects/layouts/src/basic/content/use-content-spinner.ts b/packages/effects/layouts/src/basic/content/use-content-spinner.ts new file mode 100644 index 0000000..dfe3c53 --- /dev/null +++ b/packages/effects/layouts/src/basic/content/use-content-spinner.ts @@ -0,0 +1,50 @@ +import { computed, ref } from 'vue'; +import { useRouter } from 'vue-router'; + +import { preferences } from '@vben/preferences'; + +function useContentSpinner() { + const spinning = ref(false); + const startTime = ref(0); + const router = useRouter(); + const minShowTime = 500; // 最小显示时间 + const enableLoading = computed(() => preferences.transition.loading); + + // 结束加载动画 + const onEnd = () => { + if (!enableLoading.value) { + return; + } + const processTime = performance.now() - startTime.value; + if (processTime < minShowTime) { + setTimeout(() => { + spinning.value = false; + }, minShowTime - processTime); + } else { + spinning.value = false; + } + }; + + // 路由前置守卫 + router.beforeEach((to) => { + if (to.meta.loaded || !enableLoading.value || to.meta.iframeSrc) { + return true; + } + startTime.value = performance.now(); + spinning.value = true; + return true; + }); + + // 路由后置守卫 + router.afterEach((to) => { + if (to.meta.loaded || !enableLoading.value || to.meta.iframeSrc) { + return true; + } + onEnd(); + return true; + }); + + return { spinning }; +} + +export { useContentSpinner }; diff --git a/packages/effects/layouts/src/basic/copyright/copyright.vue b/packages/effects/layouts/src/basic/copyright/copyright.vue new file mode 100644 index 0000000..de49c7c --- /dev/null +++ b/packages/effects/layouts/src/basic/copyright/copyright.vue @@ -0,0 +1,48 @@ + + + diff --git a/packages/effects/layouts/src/basic/copyright/index.ts b/packages/effects/layouts/src/basic/copyright/index.ts new file mode 100644 index 0000000..e0620da --- /dev/null +++ b/packages/effects/layouts/src/basic/copyright/index.ts @@ -0,0 +1 @@ +export { default as Copyright } from './copyright.vue'; diff --git a/packages/effects/layouts/src/basic/footer/footer.vue b/packages/effects/layouts/src/basic/footer/footer.vue new file mode 100644 index 0000000..6fc256d --- /dev/null +++ b/packages/effects/layouts/src/basic/footer/footer.vue @@ -0,0 +1,11 @@ + + + diff --git a/packages/effects/layouts/src/basic/footer/index.ts b/packages/effects/layouts/src/basic/footer/index.ts new file mode 100644 index 0000000..7e149a2 --- /dev/null +++ b/packages/effects/layouts/src/basic/footer/index.ts @@ -0,0 +1 @@ +export { default as LayoutFooter } from './footer.vue'; diff --git a/packages/effects/layouts/src/basic/header/header.vue b/packages/effects/layouts/src/basic/header/header.vue new file mode 100644 index 0000000..44ec671 --- /dev/null +++ b/packages/effects/layouts/src/basic/header/header.vue @@ -0,0 +1,195 @@ + + + + diff --git a/packages/effects/layouts/src/basic/header/index.ts b/packages/effects/layouts/src/basic/header/index.ts new file mode 100644 index 0000000..44f0729 --- /dev/null +++ b/packages/effects/layouts/src/basic/header/index.ts @@ -0,0 +1 @@ +export { default as LayoutHeader } from './header.vue'; diff --git a/packages/effects/layouts/src/basic/index.ts b/packages/effects/layouts/src/basic/index.ts new file mode 100644 index 0000000..b3a01cd --- /dev/null +++ b/packages/effects/layouts/src/basic/index.ts @@ -0,0 +1 @@ +export { default as BasicLayout } from './layout.vue'; diff --git a/packages/effects/layouts/src/basic/layout.vue b/packages/effects/layouts/src/basic/layout.vue new file mode 100644 index 0000000..b8912c0 --- /dev/null +++ b/packages/effects/layouts/src/basic/layout.vue @@ -0,0 +1,421 @@ + + + diff --git a/packages/effects/layouts/src/basic/menu/extra-menu.vue b/packages/effects/layouts/src/basic/menu/extra-menu.vue new file mode 100644 index 0000000..5f194a7 --- /dev/null +++ b/packages/effects/layouts/src/basic/menu/extra-menu.vue @@ -0,0 +1,41 @@ + + + diff --git a/packages/effects/layouts/src/basic/menu/index.ts b/packages/effects/layouts/src/basic/menu/index.ts new file mode 100644 index 0000000..72b87ad --- /dev/null +++ b/packages/effects/layouts/src/basic/menu/index.ts @@ -0,0 +1,5 @@ +export { default as LayoutExtraMenu } from './extra-menu.vue'; +export { default as LayoutMenu } from './menu.vue'; +export { default as LayoutMixedMenu } from './mixed-menu.vue'; +export * from './use-extra-menu'; +export * from './use-mixed-menu'; diff --git a/packages/effects/layouts/src/basic/menu/menu.vue b/packages/effects/layouts/src/basic/menu/menu.vue new file mode 100644 index 0000000..cbb5cfb --- /dev/null +++ b/packages/effects/layouts/src/basic/menu/menu.vue @@ -0,0 +1,45 @@ + + + diff --git a/packages/effects/layouts/src/basic/menu/mixed-menu.vue b/packages/effects/layouts/src/basic/menu/mixed-menu.vue new file mode 100644 index 0000000..ae12cc9 --- /dev/null +++ b/packages/effects/layouts/src/basic/menu/mixed-menu.vue @@ -0,0 +1,46 @@ + + + diff --git a/packages/effects/layouts/src/basic/menu/use-extra-menu.ts b/packages/effects/layouts/src/basic/menu/use-extra-menu.ts new file mode 100644 index 0000000..e2afb74 --- /dev/null +++ b/packages/effects/layouts/src/basic/menu/use-extra-menu.ts @@ -0,0 +1,133 @@ +import type { ComputedRef } from 'vue'; + +import type { MenuRecordRaw } from '@vben/types'; + +import { computed, ref, watch } from 'vue'; +import { useRoute } from 'vue-router'; + +import { preferences } from '@vben/preferences'; +import { useAccessStore } from '@vben/stores'; +import { findRootMenuByPath } from '@vben/utils'; + +import { useNavigation } from './use-navigation'; + +function useExtraMenu(useRootMenus?: ComputedRef) { + const accessStore = useAccessStore(); + const { navigation, willOpenedByWindow } = useNavigation(); + + const menus = computed(() => useRootMenus?.value ?? accessStore.accessMenus); + + /** 记录当前顶级菜单下哪个子菜单最后激活 */ + const defaultSubMap = new Map(); + const extraRootMenus = ref([]); + const route = useRoute(); + const extraMenus = ref([]); + const sidebarExtraVisible = ref(false); + const extraActiveMenu = ref(''); + const parentLevel = computed(() => + preferences.app.layout === 'header-mixed-nav' ? 1 : 0, + ); + + /** + * 选择混合菜单事件 + * @param menu + */ + const handleMixedMenuSelect = async (menu: MenuRecordRaw) => { + const _extraMenus = menu?.children ?? []; + const hasChildren = _extraMenus.length > 0; + + if (!willOpenedByWindow(menu.path)) { + extraMenus.value = _extraMenus ?? []; + extraActiveMenu.value = menu.parents?.[parentLevel.value] ?? menu.path; + sidebarExtraVisible.value = hasChildren; + } + + if (!hasChildren) { + await navigation(menu.path); + } else if (preferences.sidebar.autoActivateChild) { + await navigation( + defaultSubMap.has(menu.path) + ? (defaultSubMap.get(menu.path) as string) + : menu.path, + ); + } + }; + + /** + * 选择默认菜单事件 + * @param menu + * @param rootMenu + */ + const handleDefaultSelect = async ( + menu: MenuRecordRaw, + rootMenu?: MenuRecordRaw, + ) => { + extraMenus.value = rootMenu?.children ?? extraRootMenus.value ?? []; + extraActiveMenu.value = menu.parents?.[parentLevel.value] ?? menu.path; + + if (preferences.sidebar.expandOnHover) { + sidebarExtraVisible.value = extraMenus.value.length > 0; + } + }; + + /** + * 侧边菜单鼠标移出事件 + */ + const handleSideMouseLeave = () => { + if (preferences.sidebar.expandOnHover) { + return; + } + + const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath( + menus.value, + route.path, + ); + extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? ''; + extraMenus.value = rootMenu?.children ?? []; + }; + + const handleMenuMouseEnter = (menu: MenuRecordRaw) => { + if (!preferences.sidebar.expandOnHover) { + const { findMenu } = findRootMenuByPath(menus.value, menu.path); + extraMenus.value = findMenu?.children ?? []; + extraActiveMenu.value = menu.parents?.[parentLevel.value] ?? menu.path; + sidebarExtraVisible.value = extraMenus.value.length > 0; + } + }; + + function calcExtraMenus(path: string) { + const currentPath = route.meta?.activePath || path; + const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath( + menus.value, + currentPath, + parentLevel.value, + ); + extraRootMenus.value = rootMenu?.children ?? []; + if (rootMenuPath) defaultSubMap.set(rootMenuPath, currentPath); + extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? ''; + extraMenus.value = rootMenu?.children ?? []; + if (preferences.sidebar.expandOnHover) { + sidebarExtraVisible.value = extraMenus.value.length > 0; + } + } + + watch( + () => [route.path, preferences.app.layout], + ([path]) => { + calcExtraMenus(path || ''); + }, + { immediate: true }, + ); + + return { + extraActiveMenu, + extraMenus, + handleDefaultSelect, + handleMenuMouseEnter, + handleMixedMenuSelect, + handleSideMouseLeave, + sidebarExtraVisible, + }; +} + +export { useExtraMenu }; diff --git a/packages/effects/layouts/src/basic/menu/use-mixed-menu.ts b/packages/effects/layouts/src/basic/menu/use-mixed-menu.ts new file mode 100644 index 0000000..8424c38 --- /dev/null +++ b/packages/effects/layouts/src/basic/menu/use-mixed-menu.ts @@ -0,0 +1,172 @@ +import type { MenuRecordRaw } from '@vben/types'; + +import { computed, onBeforeMount, ref, watch } from 'vue'; +import { useRoute } from 'vue-router'; + +import { preferences, usePreferences } from '@vben/preferences'; +import { useAccessStore } from '@vben/stores'; +import { findRootMenuByPath } from '@vben/utils'; + +import { useNavigation } from './use-navigation'; + +function useMixedMenu() { + const { navigation, willOpenedByWindow } = useNavigation(); + const accessStore = useAccessStore(); + const route = useRoute(); + const splitSideMenus = ref([]); + const rootMenuPath = ref(''); + const mixedRootMenuPath = ref(''); + const mixExtraMenus = ref([]); + /** 记录当前顶级菜单下哪个子菜单最后激活 */ + const defaultSubMap = new Map(); + const { isMixedNav, isHeaderMixedNav } = usePreferences(); + + const needSplit = computed( + () => + (preferences.navigation.split && isMixedNav.value) || + isHeaderMixedNav.value, + ); + + const sidebarVisible = computed(() => { + const enableSidebar = preferences.sidebar.enable; + if (needSplit.value) { + return enableSidebar && splitSideMenus.value.length > 0; + } + return enableSidebar; + }); + const menus = computed(() => accessStore.accessMenus); + + /** + * 头部菜单 + */ + const headerMenus = computed(() => { + if (!needSplit.value) { + return menus.value; + } + return menus.value.map((item) => { + return { + ...item, + children: [], + }; + }); + }); + + /** + * 侧边菜单 + */ + const sidebarMenus = computed(() => { + return needSplit.value ? splitSideMenus.value : menus.value; + }); + + const mixHeaderMenus = computed(() => { + return isHeaderMixedNav.value ? sidebarMenus.value : headerMenus.value; + }); + + /** + * 侧边菜单激活路径 + */ + const sidebarActive = computed(() => { + return (route?.meta?.activePath as string) ?? route.path; + }); + + /** + * 头部菜单激活路径 + */ + const headerActive = computed(() => { + if (!needSplit.value) { + return route.meta?.activePath ?? route.path; + } + return rootMenuPath.value; + }); + + /** + * 菜单点击事件处理 + * @param key 菜单路径 + * @param mode 菜单模式 + */ + const handleMenuSelect = (key: string, mode?: string) => { + if (!needSplit.value || mode === 'vertical') { + navigation(key); + return; + } + const rootMenu = menus.value.find((item) => item.path === key); + const _splitSideMenus = rootMenu?.children ?? []; + + if (!willOpenedByWindow(key)) { + rootMenuPath.value = rootMenu?.path ?? ''; + splitSideMenus.value = _splitSideMenus; + } + + if (_splitSideMenus.length === 0) { + navigation(key); + } else if (rootMenu && preferences.sidebar.autoActivateChild) { + navigation( + defaultSubMap.has(rootMenu.path) + ? (defaultSubMap.get(rootMenu.path) as string) + : rootMenu.path, + ); + } + }; + + /** + * 侧边菜单展开事件 + * @param key 路由路径 + * @param parentsPath 父级路径 + */ + const handleMenuOpen = (key: string, parentsPath: string[]) => { + if (parentsPath.length <= 1 && preferences.sidebar.autoActivateChild) { + navigation( + defaultSubMap.has(key) ? (defaultSubMap.get(key) as string) : key, + ); + } + }; + + /** + * 计算侧边菜单 + * @param path 路由路径 + */ + function calcSideMenus(path: string = route.path) { + let { rootMenu } = findRootMenuByPath(menus.value, path); + if (!rootMenu) { + rootMenu = menus.value.find((item) => item.path === path); + } + const result = findRootMenuByPath(rootMenu?.children || [], path, 1); + mixedRootMenuPath.value = result.rootMenuPath ?? ''; + mixExtraMenus.value = result.rootMenu?.children ?? []; + rootMenuPath.value = rootMenu?.path ?? ''; + splitSideMenus.value = rootMenu?.children ?? []; + } + + watch( + () => route.path, + (path) => { + const currentPath = route?.meta?.activePath ?? route?.meta?.link ?? path; + if (willOpenedByWindow(currentPath)) { + return; + } + calcSideMenus(currentPath); + if (rootMenuPath.value) + defaultSubMap.set(rootMenuPath.value, currentPath); + }, + { immediate: true }, + ); + + // 初始化计算侧边菜单 + onBeforeMount(() => { + calcSideMenus(route.meta?.activePath || route.path); + }); + + return { + handleMenuSelect, + handleMenuOpen, + headerActive, + headerMenus, + sidebarActive, + sidebarMenus, + mixHeaderMenus, + mixExtraMenus, + sidebarVisible, + }; +} + +export { useMixedMenu }; diff --git a/packages/effects/layouts/src/basic/menu/use-navigation.ts b/packages/effects/layouts/src/basic/menu/use-navigation.ts new file mode 100644 index 0000000..daa6dc7 --- /dev/null +++ b/packages/effects/layouts/src/basic/menu/use-navigation.ts @@ -0,0 +1,74 @@ +import type { RouteRecordNormalized } from 'vue-router'; + +import { useRouter } from 'vue-router'; + +import { isHttpUrl, openRouteInNewWindow, openWindow } from '@vben/utils'; + +function useNavigation() { + const router = useRouter(); + const routeMetaMap = new Map(); + + // 初始化路由映射 + const initRouteMetaMap = () => { + const routes = router.getRoutes(); + routes.forEach((route) => { + routeMetaMap.set(route.path, route); + }); + }; + + initRouteMetaMap(); + + // 监听路由变化 + router.afterEach(() => { + initRouteMetaMap(); + }); + + // 检查是否应该在新窗口打开 + const shouldOpenInNewWindow = (path: string): boolean => { + if (isHttpUrl(path)) { + return true; + } + const route = routeMetaMap.get(path); + // 如果有外链或者设置了在新窗口打开,返回 true + return !!(route?.meta?.link || route?.meta?.openInNewWindow); + }; + + const resolveHref = (path: string): string => { + return router.resolve(path).href; + }; + + const navigation = async (path: string) => { + try { + const route = routeMetaMap.get(path); + const { openInNewWindow = false, query = {}, link } = route?.meta ?? {}; + + // 检查是否有外链 + if (link && typeof link === 'string') { + openWindow(link, { target: '_blank' }); + return; + } + + if (isHttpUrl(path)) { + openWindow(path, { target: '_blank' }); + } else if (openInNewWindow) { + openRouteInNewWindow(resolveHref(path)); + } else { + await router.push({ + path, + query, + }); + } + } catch (error) { + console.error('Navigation failed:', error); + throw error; + } + }; + + const willOpenedByWindow = (path: string) => { + return shouldOpenInNewWindow(path); + }; + + return { navigation, willOpenedByWindow }; +} + +export { useNavigation }; diff --git a/packages/effects/layouts/src/basic/tabbar/index.ts b/packages/effects/layouts/src/basic/tabbar/index.ts new file mode 100644 index 0000000..5cc2479 --- /dev/null +++ b/packages/effects/layouts/src/basic/tabbar/index.ts @@ -0,0 +1,2 @@ +export { default as LayoutTabbar } from './tabbar.vue'; +export * from './use-tabbar'; diff --git a/packages/effects/layouts/src/basic/tabbar/tabbar.vue b/packages/effects/layouts/src/basic/tabbar/tabbar.vue new file mode 100644 index 0000000..367604e --- /dev/null +++ b/packages/effects/layouts/src/basic/tabbar/tabbar.vue @@ -0,0 +1,84 @@ + + + diff --git a/packages/effects/layouts/src/basic/tabbar/use-tabbar.ts b/packages/effects/layouts/src/basic/tabbar/use-tabbar.ts new file mode 100644 index 0000000..0f0ef34 --- /dev/null +++ b/packages/effects/layouts/src/basic/tabbar/use-tabbar.ts @@ -0,0 +1,227 @@ +import type { RouteLocationNormalizedGeneric } from 'vue-router'; + +import type { TabDefinition } from '@vben/types'; + +import type { IContextMenuItem } from '@vben-core/tabs-ui'; + +import { computed, ref, watch } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; + +import { useContentMaximize, useTabs } from '@vben/hooks'; +import { + ArrowLeftToLine, + ArrowRightLeft, + ArrowRightToLine, + ExternalLink, + FoldHorizontal, + Fullscreen, + Minimize2, + Pin, + PinOff, + RotateCw, + X, +} from '@vben/icons'; +import { $t, useI18n } from '@vben/locales'; +import { getTabKey, useAccessStore, useTabbarStore } from '@vben/stores'; +import { filterTree } from '@vben/utils'; + +export function useTabbar() { + const router = useRouter(); + const route = useRoute(); + const accessStore = useAccessStore(); + const tabbarStore = useTabbarStore(); + const { contentIsMaximize, toggleMaximize } = useContentMaximize(); + const { + closeAllTabs, + closeCurrentTab, + closeLeftTabs, + closeOtherTabs, + closeRightTabs, + closeTabByKey, + getTabDisableState, + openTabInNewWindow, + refreshTab, + toggleTabPin, + } = useTabs(); + + /** + * 当前路径对应的tab的key + */ + const currentActive = computed(() => { + return getTabKey(route); + }); + + const { locale } = useI18n(); + const currentTabs = ref(); + watch( + [ + () => tabbarStore.getTabs, + () => tabbarStore.updateTime, + () => locale.value, + ], + ([tabs]) => { + currentTabs.value = tabs.map((item) => wrapperTabLocale(item)); + }, + ); + + /** + * 初始化固定标签页 + */ + const initAffixTabs = () => { + const affixTabs = filterTree(router.getRoutes(), (route) => { + return !!route.meta?.affixTab; + }); + tabbarStore.setAffixTabs(affixTabs); + }; + + // 点击tab,跳转路由 + const handleClick = (key: string) => { + const { fullPath, path } = tabbarStore.getTabByKey(key); + router.push(fullPath || path); + }; + + // 关闭tab + const handleClose = async (key: string) => { + await closeTabByKey(key); + }; + + function wrapperTabLocale(tab: RouteLocationNormalizedGeneric) { + return { + ...tab, + meta: { + ...tab?.meta, + title: $t(tab?.meta?.title as string), + }, + }; + } + + watch( + () => accessStore.accessMenus, + () => { + initAffixTabs(); + }, + { immediate: true }, + ); + + watch( + () => route.fullPath, + () => { + const meta = route.matched?.[route.matched.length - 1]?.meta; + tabbarStore.addTab({ + ...route, + meta: meta || route.meta, + }); + }, + { immediate: true }, + ); + + const createContextMenus = (tab: TabDefinition) => { + const { + disabledCloseAll, + disabledCloseCurrent, + disabledCloseLeft, + disabledCloseOther, + disabledCloseRight, + disabledRefresh, + } = getTabDisableState(tab); + + const affixTab = tab?.meta?.affixTab ?? false; + + const menus: IContextMenuItem[] = [ + { + disabled: disabledCloseCurrent, + handler: async () => { + await closeCurrentTab(tab); + }, + icon: X, + key: 'close', + text: $t('preferences.tabbar.contextMenu.close'), + }, + { + handler: async () => { + await toggleTabPin(tab); + }, + icon: affixTab ? PinOff : Pin, + key: 'affix', + text: affixTab + ? $t('preferences.tabbar.contextMenu.unpin') + : $t('preferences.tabbar.contextMenu.pin'), + }, + { + handler: async () => { + if (!contentIsMaximize.value) { + await router.push(tab.fullPath); + } + toggleMaximize(); + }, + icon: contentIsMaximize.value ? Minimize2 : Fullscreen, + key: contentIsMaximize.value ? 'restore-maximize' : 'maximize', + text: contentIsMaximize.value + ? $t('preferences.tabbar.contextMenu.restoreMaximize') + : $t('preferences.tabbar.contextMenu.maximize'), + }, + { + disabled: disabledRefresh, + handler: () => refreshTab(), + icon: RotateCw, + key: 'reload', + text: $t('preferences.tabbar.contextMenu.reload'), + }, + { + handler: async () => { + await openTabInNewWindow(tab); + }, + icon: ExternalLink, + key: 'open-in-new-window', + separator: true, + text: $t('preferences.tabbar.contextMenu.openInNewWindow'), + }, + + { + disabled: disabledCloseLeft, + handler: async () => { + await closeLeftTabs(tab); + }, + icon: ArrowLeftToLine, + key: 'close-left', + text: $t('preferences.tabbar.contextMenu.closeLeft'), + }, + { + disabled: disabledCloseRight, + handler: async () => { + await closeRightTabs(tab); + }, + icon: ArrowRightToLine, + key: 'close-right', + separator: true, + text: $t('preferences.tabbar.contextMenu.closeRight'), + }, + { + disabled: disabledCloseOther, + handler: async () => { + await closeOtherTabs(tab); + }, + icon: FoldHorizontal, + key: 'close-other', + text: $t('preferences.tabbar.contextMenu.closeOther'), + }, + { + disabled: disabledCloseAll, + handler: closeAllTabs, + icon: ArrowRightLeft, + key: 'close-all', + text: $t('preferences.tabbar.contextMenu.closeAll'), + }, + ]; + + return menus.filter((item) => tabbarStore.getMenuList.includes(item.key)); + }; + + return { + createContextMenus, + currentActive, + currentTabs, + handleClick, + handleClose, + }; +} diff --git a/packages/effects/layouts/src/iframe/iframe-router-view.vue b/packages/effects/layouts/src/iframe/iframe-router-view.vue new file mode 100644 index 0000000..3f1f952 --- /dev/null +++ b/packages/effects/layouts/src/iframe/iframe-router-view.vue @@ -0,0 +1,86 @@ + + diff --git a/packages/effects/layouts/src/iframe/iframe-view.vue b/packages/effects/layouts/src/iframe/iframe-view.vue new file mode 100644 index 0000000..7b8b46c --- /dev/null +++ b/packages/effects/layouts/src/iframe/iframe-view.vue @@ -0,0 +1,3 @@ + diff --git a/packages/effects/layouts/src/iframe/index.ts b/packages/effects/layouts/src/iframe/index.ts new file mode 100644 index 0000000..1b8c131 --- /dev/null +++ b/packages/effects/layouts/src/iframe/index.ts @@ -0,0 +1,2 @@ +export { default as IFrameRouterView } from './iframe-router-view.vue'; +export { default as IFrameView } from './iframe-view.vue'; diff --git a/packages/effects/layouts/src/index.ts b/packages/effects/layouts/src/index.ts new file mode 100644 index 0000000..124a44a --- /dev/null +++ b/packages/effects/layouts/src/index.ts @@ -0,0 +1,4 @@ +export * from './authentication'; +export * from './basic'; +export * from './iframe'; +export * from './widgets'; diff --git a/packages/effects/layouts/src/widgets/breadcrumb.vue b/packages/effects/layouts/src/widgets/breadcrumb.vue new file mode 100644 index 0000000..c041960 --- /dev/null +++ b/packages/effects/layouts/src/widgets/breadcrumb.vue @@ -0,0 +1,74 @@ + + diff --git a/packages/effects/layouts/src/widgets/check-updates/check-updates.vue b/packages/effects/layouts/src/widgets/check-updates/check-updates.vue new file mode 100644 index 0000000..4f3082f --- /dev/null +++ b/packages/effects/layouts/src/widgets/check-updates/check-updates.vue @@ -0,0 +1,136 @@ + + diff --git a/packages/effects/layouts/src/widgets/check-updates/index.ts b/packages/effects/layouts/src/widgets/check-updates/index.ts new file mode 100644 index 0000000..fc20c66 --- /dev/null +++ b/packages/effects/layouts/src/widgets/check-updates/index.ts @@ -0,0 +1 @@ +export { default as CheckUpdates } from './check-updates.vue'; diff --git a/packages/effects/layouts/src/widgets/color-toggle.vue b/packages/effects/layouts/src/widgets/color-toggle.vue new file mode 100644 index 0000000..ae15cb8 --- /dev/null +++ b/packages/effects/layouts/src/widgets/color-toggle.vue @@ -0,0 +1,64 @@ + + + diff --git a/packages/effects/layouts/src/widgets/global-search/global-search.vue b/packages/effects/layouts/src/widgets/global-search/global-search.vue new file mode 100644 index 0000000..bd8b334 --- /dev/null +++ b/packages/effects/layouts/src/widgets/global-search/global-search.vue @@ -0,0 +1,157 @@ + + + diff --git a/packages/effects/layouts/src/widgets/global-search/index.ts b/packages/effects/layouts/src/widgets/global-search/index.ts new file mode 100644 index 0000000..cd490ae --- /dev/null +++ b/packages/effects/layouts/src/widgets/global-search/index.ts @@ -0,0 +1 @@ +export { default as GlobalSearch } from './global-search.vue'; diff --git a/packages/effects/layouts/src/widgets/global-search/search-panel.vue b/packages/effects/layouts/src/widgets/global-search/search-panel.vue new file mode 100644 index 0000000..6e94049 --- /dev/null +++ b/packages/effects/layouts/src/widgets/global-search/search-panel.vue @@ -0,0 +1,288 @@ + + + diff --git a/packages/effects/layouts/src/widgets/help/help.vue b/packages/effects/layouts/src/widgets/help/help.vue new file mode 100644 index 0000000..7ca8527 --- /dev/null +++ b/packages/effects/layouts/src/widgets/help/help.vue @@ -0,0 +1,106 @@ + + diff --git a/packages/effects/layouts/src/widgets/help/index.ts b/packages/effects/layouts/src/widgets/help/index.ts new file mode 100644 index 0000000..2d470b4 --- /dev/null +++ b/packages/effects/layouts/src/widgets/help/index.ts @@ -0,0 +1 @@ +export { default as Help } from './help.vue'; diff --git a/packages/effects/layouts/src/widgets/index.ts b/packages/effects/layouts/src/widgets/index.ts new file mode 100644 index 0000000..665cdb9 --- /dev/null +++ b/packages/effects/layouts/src/widgets/index.ts @@ -0,0 +1,14 @@ +export { default as Breadcrumb } from './breadcrumb.vue'; +export * from './check-updates'; +export { default as AuthenticationColorToggle } from './color-toggle.vue'; +export * from './global-search'; +export * from './help'; +export { default as LanguageToggle } from './language-toggle.vue'; +export { default as AuthenticationLayoutToggle } from './layout-toggle.vue'; +export * from './lock-screen'; +export * from './notification'; +export * from './preferences'; +export * from './tenant-dropdown'; +export * from './theme-toggle'; +export * from './timezone'; +export * from './user-dropdown'; diff --git a/packages/effects/layouts/src/widgets/language-toggle.vue b/packages/effects/layouts/src/widgets/language-toggle.vue new file mode 100644 index 0000000..f92432f --- /dev/null +++ b/packages/effects/layouts/src/widgets/language-toggle.vue @@ -0,0 +1,39 @@ + + + diff --git a/packages/effects/layouts/src/widgets/layout-toggle.vue b/packages/effects/layouts/src/widgets/layout-toggle.vue new file mode 100644 index 0000000..ae4eecb --- /dev/null +++ b/packages/effects/layouts/src/widgets/layout-toggle.vue @@ -0,0 +1,64 @@ + + + diff --git a/packages/effects/layouts/src/widgets/lock-screen/index.ts b/packages/effects/layouts/src/widgets/lock-screen/index.ts new file mode 100644 index 0000000..8ba1f16 --- /dev/null +++ b/packages/effects/layouts/src/widgets/lock-screen/index.ts @@ -0,0 +1,2 @@ +export { default as LockScreenModal } from './lock-screen-modal.vue'; +export { default as LockScreen } from './lock-screen.vue'; diff --git a/packages/effects/layouts/src/widgets/lock-screen/lock-screen-modal.vue b/packages/effects/layouts/src/widgets/lock-screen/lock-screen-modal.vue new file mode 100644 index 0000000..908e670 --- /dev/null +++ b/packages/effects/layouts/src/widgets/lock-screen/lock-screen-modal.vue @@ -0,0 +1,110 @@ + + + diff --git a/packages/effects/layouts/src/widgets/lock-screen/lock-screen.vue b/packages/effects/layouts/src/widgets/lock-screen/lock-screen.vue new file mode 100644 index 0000000..3f70033 --- /dev/null +++ b/packages/effects/layouts/src/widgets/lock-screen/lock-screen.vue @@ -0,0 +1,167 @@ + + + diff --git a/packages/effects/layouts/src/widgets/notification/index.ts b/packages/effects/layouts/src/widgets/notification/index.ts new file mode 100644 index 0000000..e219b71 --- /dev/null +++ b/packages/effects/layouts/src/widgets/notification/index.ts @@ -0,0 +1,3 @@ +export { default as Notification } from './notification.vue'; + +export type * from './types'; diff --git a/packages/effects/layouts/src/widgets/notification/notification.vue b/packages/effects/layouts/src/widgets/notification/notification.vue new file mode 100644 index 0000000..4135ea9 --- /dev/null +++ b/packages/effects/layouts/src/widgets/notification/notification.vue @@ -0,0 +1,241 @@ + + + + diff --git a/packages/effects/layouts/src/widgets/notification/types.ts b/packages/effects/layouts/src/widgets/notification/types.ts new file mode 100644 index 0000000..3f015ce --- /dev/null +++ b/packages/effects/layouts/src/widgets/notification/types.ts @@ -0,0 +1,17 @@ +interface NotificationItem { + id: any; + avatar: string; + date: string; + isRead?: boolean; + message: string; + title: string; + /** + * 跳转链接,可以是路由路径或完整 URL + * @example '/dashboard' 或 'https://example.com' + */ + link?: string; + query?: Record; + state?: Record; +} + +export type { NotificationItem }; diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/block.vue b/packages/effects/layouts/src/widgets/preferences/blocks/block.vue new file mode 100644 index 0000000..c8cc9e6 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/block.vue @@ -0,0 +1,22 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/checkbox-item.vue b/packages/effects/layouts/src/widgets/preferences/blocks/checkbox-item.vue new file mode 100644 index 0000000..99940c6 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/checkbox-item.vue @@ -0,0 +1,63 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/general/animation.vue b/packages/effects/layouts/src/widgets/preferences/blocks/general/animation.vue new file mode 100644 index 0000000..b27d074 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/general/animation.vue @@ -0,0 +1,51 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/general/general.vue b/packages/effects/layouts/src/widgets/preferences/blocks/general/general.vue new file mode 100644 index 0000000..c69cd3a --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/general/general.vue @@ -0,0 +1,47 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/index.ts b/packages/effects/layouts/src/widgets/preferences/blocks/index.ts new file mode 100644 index 0000000..cdd6bb1 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/index.ts @@ -0,0 +1,20 @@ +export { default as Block } from './block.vue'; +export { default as Animation } from './general/animation.vue'; +export { default as General } from './general/general.vue'; +export { default as Breadcrumb } from './layout/breadcrumb.vue'; +export { default as Content } from './layout/content.vue'; +export { default as Copyright } from './layout/copyright.vue'; +export { default as Footer } from './layout/footer.vue'; +export { default as Header } from './layout/header.vue'; +export { default as Layout } from './layout/layout.vue'; +export { default as Navigation } from './layout/navigation.vue'; +export { default as Sidebar } from './layout/sidebar.vue'; +export { default as Tabbar } from './layout/tabbar.vue'; +export { default as Widget } from './layout/widget.vue'; +export { default as GlobalShortcutKeys } from './shortcut-keys/global.vue'; +export { default as SwitchItem } from './switch-item.vue'; +export { default as BuiltinTheme } from './theme/builtin.vue'; +export { default as ColorMode } from './theme/color-mode.vue'; +export { default as FontSize } from './theme/font-size.vue'; +export { default as Radius } from './theme/radius.vue'; +export { default as Theme } from './theme/theme.vue'; diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/input-item.vue b/packages/effects/layouts/src/widgets/preferences/blocks/input-item.vue new file mode 100644 index 0000000..8e9f09e --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/input-item.vue @@ -0,0 +1,63 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/layout/breadcrumb.vue b/packages/effects/layouts/src/widgets/preferences/blocks/layout/breadcrumb.vue new file mode 100644 index 0000000..51f1a40 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/layout/breadcrumb.vue @@ -0,0 +1,56 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/layout/content.vue b/packages/effects/layouts/src/widgets/preferences/blocks/layout/content.vue new file mode 100644 index 0000000..75af1c3 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/layout/content.vue @@ -0,0 +1,53 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/layout/copyright.vue b/packages/effects/layouts/src/widgets/preferences/blocks/layout/copyright.vue new file mode 100644 index 0000000..9389029 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/layout/copyright.vue @@ -0,0 +1,44 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/layout/footer.vue b/packages/effects/layouts/src/widgets/preferences/blocks/layout/footer.vue new file mode 100644 index 0000000..8a77920 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/layout/footer.vue @@ -0,0 +1,17 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/layout/header.vue b/packages/effects/layouts/src/widgets/preferences/blocks/layout/header.vue new file mode 100644 index 0000000..ee04ee2 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/layout/header.vue @@ -0,0 +1,74 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/layout/layout.vue b/packages/effects/layouts/src/widgets/preferences/blocks/layout/layout.vue new file mode 100644 index 0000000..a46650b --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/layout/layout.vue @@ -0,0 +1,112 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/layout/navigation.vue b/packages/effects/layouts/src/widgets/preferences/blocks/layout/navigation.vue new file mode 100644 index 0000000..23acb1f --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/layout/navigation.vue @@ -0,0 +1,45 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/layout/sidebar.vue b/packages/effects/layouts/src/widgets/preferences/blocks/layout/sidebar.vue new file mode 100644 index 0000000..e8d84af --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/layout/sidebar.vue @@ -0,0 +1,100 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/layout/tabbar.vue b/packages/effects/layouts/src/widgets/preferences/blocks/layout/tabbar.vue new file mode 100644 index 0000000..885c30c --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/layout/tabbar.vue @@ -0,0 +1,102 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/layout/widget.vue b/packages/effects/layouts/src/widgets/preferences/blocks/layout/widget.vue new file mode 100644 index 0000000..82addb3 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/layout/widget.vue @@ -0,0 +1,71 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/number-field-item.vue b/packages/effects/layouts/src/widgets/preferences/blocks/number-field-item.vue new file mode 100644 index 0000000..3878f81 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/number-field-item.vue @@ -0,0 +1,74 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/select-item.vue b/packages/effects/layouts/src/widgets/preferences/blocks/select-item.vue new file mode 100644 index 0000000..fabc371 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/select-item.vue @@ -0,0 +1,68 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/shortcut-keys/global.vue b/packages/effects/layouts/src/widgets/preferences/blocks/shortcut-keys/global.vue new file mode 100644 index 0000000..f71a1f6 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/shortcut-keys/global.vue @@ -0,0 +1,50 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/switch-item.vue b/packages/effects/layouts/src/widgets/preferences/blocks/switch-item.vue new file mode 100644 index 0000000..33d99e9 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/switch-item.vue @@ -0,0 +1,55 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/theme/builtin.vue b/packages/effects/layouts/src/widgets/preferences/blocks/theme/builtin.vue new file mode 100644 index 0000000..b31a1a9 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/theme/builtin.vue @@ -0,0 +1,162 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/theme/color-mode.vue b/packages/effects/layouts/src/widgets/preferences/blocks/theme/color-mode.vue new file mode 100644 index 0000000..9a41d4e --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/theme/color-mode.vue @@ -0,0 +1,26 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/theme/font-size.vue b/packages/effects/layouts/src/widgets/preferences/blocks/theme/font-size.vue new file mode 100644 index 0000000..b1aaa2d --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/theme/font-size.vue @@ -0,0 +1,62 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/theme/radius.vue b/packages/effects/layouts/src/widgets/preferences/blocks/theme/radius.vue new file mode 100644 index 0000000..4201ed6 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/theme/radius.vue @@ -0,0 +1,38 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/theme/theme.vue b/packages/effects/layouts/src/widgets/preferences/blocks/theme/theme.vue new file mode 100644 index 0000000..1a5ca4b --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/theme/theme.vue @@ -0,0 +1,83 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/toggle-item.vue b/packages/effects/layouts/src/widgets/preferences/blocks/toggle-item.vue new file mode 100644 index 0000000..3f2a4a2 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/blocks/toggle-item.vue @@ -0,0 +1,46 @@ + + + diff --git a/packages/effects/layouts/src/widgets/preferences/icons/content-compact.vue b/packages/effects/layouts/src/widgets/preferences/icons/content-compact.vue new file mode 100644 index 0000000..a1bcefd --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/icons/content-compact.vue @@ -0,0 +1,119 @@ + diff --git a/packages/effects/layouts/src/widgets/preferences/icons/full-content.vue b/packages/effects/layouts/src/widgets/preferences/icons/full-content.vue new file mode 100644 index 0000000..5cbcaca --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/icons/full-content.vue @@ -0,0 +1,50 @@ + diff --git a/packages/effects/layouts/src/widgets/preferences/icons/header-mixed-nav.vue b/packages/effects/layouts/src/widgets/preferences/icons/header-mixed-nav.vue new file mode 100644 index 0000000..d5c9367 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/icons/header-mixed-nav.vue @@ -0,0 +1,202 @@ + diff --git a/packages/effects/layouts/src/widgets/preferences/icons/header-nav.vue b/packages/effects/layouts/src/widgets/preferences/icons/header-nav.vue new file mode 100644 index 0000000..18158b3 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/icons/header-nav.vue @@ -0,0 +1,119 @@ + diff --git a/packages/effects/layouts/src/widgets/preferences/icons/header-sidebar-nav.vue b/packages/effects/layouts/src/widgets/preferences/icons/header-sidebar-nav.vue new file mode 100644 index 0000000..b44e249 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/icons/header-sidebar-nav.vue @@ -0,0 +1,177 @@ + diff --git a/packages/effects/layouts/src/widgets/preferences/icons/index.ts b/packages/effects/layouts/src/widgets/preferences/icons/index.ts new file mode 100644 index 0000000..7eec1b4 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/icons/index.ts @@ -0,0 +1,12 @@ +import HeaderNav from './header-nav.vue'; + +export { default as ContentCompact } from './content-compact.vue'; +export { default as FullContent } from './full-content.vue'; +export { default as HeaderMixedNav } from './header-mixed-nav.vue'; +export { default as HeaderSidebarNav } from './header-sidebar-nav.vue'; +export { default as MixedNav } from './mixed-nav.vue'; +export { default as SidebarMixedNav } from './sidebar-mixed-nav.vue'; +export { default as SidebarNav } from './sidebar-nav.vue'; + +const ContentWide = HeaderNav; +export { ContentWide, HeaderNav }; diff --git a/packages/effects/layouts/src/widgets/preferences/icons/mixed-nav.vue b/packages/effects/layouts/src/widgets/preferences/icons/mixed-nav.vue new file mode 100644 index 0000000..d194383 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/icons/mixed-nav.vue @@ -0,0 +1,161 @@ + diff --git a/packages/effects/layouts/src/widgets/preferences/icons/setting.vue b/packages/effects/layouts/src/widgets/preferences/icons/setting.vue new file mode 100644 index 0000000..d824e11 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/icons/setting.vue @@ -0,0 +1,12 @@ + diff --git a/packages/effects/layouts/src/widgets/preferences/icons/sidebar-mixed-nav.vue b/packages/effects/layouts/src/widgets/preferences/icons/sidebar-mixed-nav.vue new file mode 100644 index 0000000..8fc0ba4 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/icons/sidebar-mixed-nav.vue @@ -0,0 +1,173 @@ + diff --git a/packages/effects/layouts/src/widgets/preferences/icons/sidebar-nav.vue b/packages/effects/layouts/src/widgets/preferences/icons/sidebar-nav.vue new file mode 100644 index 0000000..83ff399 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/icons/sidebar-nav.vue @@ -0,0 +1,153 @@ + diff --git a/packages/effects/layouts/src/widgets/preferences/index.ts b/packages/effects/layouts/src/widgets/preferences/index.ts new file mode 100644 index 0000000..2c737d5 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/index.ts @@ -0,0 +1,3 @@ +export { default as PreferencesButton } from './preferences-button.vue'; +export { default as Preferences } from './preferences.vue'; +export * from './use-open-preferences'; diff --git a/packages/effects/layouts/src/widgets/preferences/preferences-button.vue b/packages/effects/layouts/src/widgets/preferences/preferences-button.vue new file mode 100644 index 0000000..8598bb2 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/preferences-button.vue @@ -0,0 +1,20 @@ + + diff --git a/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue b/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue new file mode 100644 index 0000000..aaf7125 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue @@ -0,0 +1,495 @@ + + + + + diff --git a/packages/effects/layouts/src/widgets/preferences/preferences.vue b/packages/effects/layouts/src/widgets/preferences/preferences.vue new file mode 100644 index 0000000..8bf91eb --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/preferences.vue @@ -0,0 +1,72 @@ + + diff --git a/packages/effects/layouts/src/widgets/preferences/use-open-preferences.ts b/packages/effects/layouts/src/widgets/preferences/use-open-preferences.ts new file mode 100644 index 0000000..eb9d847 --- /dev/null +++ b/packages/effects/layouts/src/widgets/preferences/use-open-preferences.ts @@ -0,0 +1,16 @@ +import { ref } from 'vue'; + +const openPreferences = ref(false); + +function useOpenPreferences() { + function handleOpenPreference() { + openPreferences.value = true; + } + + return { + handleOpenPreference, + openPreferences, + }; +} + +export { useOpenPreferences }; diff --git a/packages/effects/layouts/src/widgets/tenant-dropdown/index.ts b/packages/effects/layouts/src/widgets/tenant-dropdown/index.ts new file mode 100644 index 0000000..c71b0a9 --- /dev/null +++ b/packages/effects/layouts/src/widgets/tenant-dropdown/index.ts @@ -0,0 +1 @@ +export { default as TenantDropdown } from './tenant-dropdown.vue'; diff --git a/packages/effects/layouts/src/widgets/tenant-dropdown/tenant-dropdown.vue b/packages/effects/layouts/src/widgets/tenant-dropdown/tenant-dropdown.vue new file mode 100644 index 0000000..76e2b2f --- /dev/null +++ b/packages/effects/layouts/src/widgets/tenant-dropdown/tenant-dropdown.vue @@ -0,0 +1,85 @@ + + diff --git a/packages/effects/layouts/src/widgets/theme-toggle/index.ts b/packages/effects/layouts/src/widgets/theme-toggle/index.ts new file mode 100644 index 0000000..0673d21 --- /dev/null +++ b/packages/effects/layouts/src/widgets/theme-toggle/index.ts @@ -0,0 +1 @@ +export { default as ThemeToggle } from './theme-toggle.vue'; diff --git a/packages/effects/layouts/src/widgets/theme-toggle/theme-button.vue b/packages/effects/layouts/src/widgets/theme-toggle/theme-button.vue new file mode 100644 index 0000000..8d24b53 --- /dev/null +++ b/packages/effects/layouts/src/widgets/theme-toggle/theme-button.vue @@ -0,0 +1,188 @@ + + + + + diff --git a/packages/effects/layouts/src/widgets/theme-toggle/theme-toggle.vue b/packages/effects/layouts/src/widgets/theme-toggle/theme-toggle.vue new file mode 100644 index 0000000..19c132e --- /dev/null +++ b/packages/effects/layouts/src/widgets/theme-toggle/theme-toggle.vue @@ -0,0 +1,83 @@ + + diff --git a/packages/effects/layouts/src/widgets/timezone/index.ts b/packages/effects/layouts/src/widgets/timezone/index.ts new file mode 100644 index 0000000..eef486d --- /dev/null +++ b/packages/effects/layouts/src/widgets/timezone/index.ts @@ -0,0 +1 @@ +export { default as TimezoneButton } from './timezone-button.vue'; diff --git a/packages/effects/layouts/src/widgets/timezone/timezone-button.vue b/packages/effects/layouts/src/widgets/timezone/timezone-button.vue new file mode 100644 index 0000000..f426b94 --- /dev/null +++ b/packages/effects/layouts/src/widgets/timezone/timezone-button.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/packages/effects/layouts/src/widgets/user-dropdown/index.ts b/packages/effects/layouts/src/widgets/user-dropdown/index.ts new file mode 100644 index 0000000..86429e9 --- /dev/null +++ b/packages/effects/layouts/src/widgets/user-dropdown/index.ts @@ -0,0 +1 @@ +export { default as UserDropdown } from './user-dropdown.vue'; diff --git a/packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue b/packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue new file mode 100644 index 0000000..8156324 --- /dev/null +++ b/packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue @@ -0,0 +1,262 @@ + + + diff --git a/packages/effects/layouts/tsconfig.json b/packages/effects/layouts/tsconfig.json new file mode 100644 index 0000000..ce1a891 --- /dev/null +++ b/packages/effects/layouts/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/effects/plugins/README.md b/packages/effects/plugins/README.md new file mode 100644 index 0000000..c394c9c --- /dev/null +++ b/packages/effects/plugins/README.md @@ -0,0 +1,28 @@ +# @vben/plugins + +该目录用于存放项目中集成的第三方库及其相关插件。每个插件都包含了可重用的逻辑、配置和组件,方便在项目中进行统一管理和调用。 + +## 注意 + +所有的第三方插件都必须以 `subpath` 形式引入,例: + +以 `echarts` 为例,引入方式如下: + +**packages.json** + +```json +"exports": { + "./echarts": { + "types": "./src/echarts/index.ts", + "default": "./src/echarts/index.ts" + } + } +``` + +**使用方式** + +```ts +import { useEcharts } from '@vben/plugins/echarts'; +``` + +这样做的好处是,应用可以自行选择是否使用插件,而不会因为插件的引入及副作用而导致打包体积增大,只引入需要的插件即可。 diff --git a/packages/effects/plugins/package.json b/packages/effects/plugins/package.json new file mode 100644 index 0000000..7c58ab8 --- /dev/null +++ b/packages/effects/plugins/package.json @@ -0,0 +1,70 @@ +{ + "name": "@vben/plugins", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/effects/plugins" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + "./code-editor": { + "types": "./src/code-editor/index.ts", + "default": "./src/code-editor/index.ts" + }, + "./echarts": { + "types": "./src/echarts/index.ts", + "default": "./src/echarts/index.ts" + }, + "./vxe-table": { + "types": "./src/vxe-table/index.ts", + "default": "./src/vxe-table/index.ts" + }, + "./motion": { + "types": "./src/motion/index.ts", + "default": "./src/motion/index.ts" + }, + "./markmap": { + "types": "./src/markmap/index.ts", + "default": "./src/markmap/index.ts" + }, + "./tinyflow": { + "types": "./src/tinyflow/index.ts", + "default": "./src/tinyflow/index.ts" + } + }, + "dependencies": { + "@tinyflow-ai/vue": "catalog:", + "@vben-core/form-ui": "workspace:*", + "@vben-core/shadcn-ui": "workspace:*", + "@vben-core/shared": "workspace:*", + "@vben/hooks": "workspace:*", + "@vben/icons": "workspace:*", + "@vben/locales": "workspace:*", + "@vben/preferences": "workspace:*", + "@vben/types": "workspace:*", + "@vben/utils": "workspace:*", + "@vueuse/core": "catalog:", + "@vueuse/motion": "catalog:", + "codemirror": "catalog:", + "echarts": "catalog:", + "markdown-it": "catalog:", + "markmap-common": "catalog:", + "markmap-lib": "catalog:", + "markmap-toolbar": "catalog:", + "markmap-view": "catalog:", + "vue": "catalog:", + "vxe-pc-ui": "catalog:", + "vxe-table": "catalog:" + }, + "devDependencies": { + "@types/codemirror": "catalog:", + "@types/markdown-it": "catalog:" + } +} diff --git a/packages/effects/plugins/src/code-editor/code-editor.vue b/packages/effects/plugins/src/code-editor/code-editor.vue new file mode 100644 index 0000000..7062ac0 --- /dev/null +++ b/packages/effects/plugins/src/code-editor/code-editor.vue @@ -0,0 +1,54 @@ + + + diff --git a/packages/effects/plugins/src/code-editor/code-mirror.ts b/packages/effects/plugins/src/code-editor/code-mirror.ts new file mode 100644 index 0000000..a4a9f8e --- /dev/null +++ b/packages/effects/plugins/src/code-editor/code-mirror.ts @@ -0,0 +1,23 @@ +// modes +import 'codemirror/mode/javascript/javascript'; +import 'codemirror/mode/css/css'; +import 'codemirror/mode/htmlmixed/htmlmixed'; +import 'codemirror/mode/vue/vue'; + +// import 'codemirror/addon/lint/lint.css'; +import './codemirror.css'; +import 'codemirror/theme/idea.css'; +import 'codemirror/theme/material-palenight.css'; + +// addons +// import 'codemirror/addon/edit/closebrackets'; +// import 'codemirror/addon/edit/closetag'; +// import 'codemirror/addon/comment/comment'; +// import 'codemirror/addon/fold/foldcode'; +// import 'codemirror/addon/fold/foldgutter'; +// import 'codemirror/addon/fold/brace-fold'; +// import 'codemirror/addon/fold/indent-fold'; +// import 'codemirror/addon/lint/json-lint'; +// import 'codemirror/addon/fold/comment-fold'; + +export { default as CodeMirror } from 'codemirror'; diff --git a/packages/effects/plugins/src/code-editor/code-mirror.vue b/packages/effects/plugins/src/code-editor/code-mirror.vue new file mode 100644 index 0000000..42d58ef --- /dev/null +++ b/packages/effects/plugins/src/code-editor/code-mirror.vue @@ -0,0 +1,137 @@ + + + diff --git a/packages/effects/plugins/src/code-editor/codemirror.css b/packages/effects/plugins/src/code-editor/codemirror.css new file mode 100644 index 0000000..09b3b8f --- /dev/null +++ b/packages/effects/plugins/src/code-editor/codemirror.css @@ -0,0 +1,524 @@ +/* BASICS */ + +.CodeMirror { + --base: #545281; + --comment: hsl(210deg 25% 60%); + --keyword: #af4ab1; + --variable: #0055d1; + --function: #c25205; + --string: #2ba46d; + --number: #c25205; + --tags: #d00; + --qualifier: #ff6032; + --important: var(--string); + + position: relative; + height: auto; + height: 100%; + overflow: hidden; + font-family: var(--font-code); + background: white; + direction: ltr; +} + +/* PADDING */ + +.CodeMirror-lines { + min-height: 1px; /* prevents collapsing before first draw */ + padding: 4px 0; /* Vertical padding around content */ + cursor: text; +} + +.CodeMirror-scrollbar-filler, +.CodeMirror-gutter-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + position: absolute; + top: 0; + left: 0; + z-index: 3; + min-height: 100%; + white-space: nowrap; + background-color: transparent; + border-right: 1px solid #ddd; +} + +.CodeMirror-linenumber { + min-width: 20px; + padding: 0 3px 0 5px; + color: var(--comment); + text-align: right; + white-space: nowrap; + opacity: 0.6; +} + +.CodeMirror-guttermarker { + color: black; +} + +.CodeMirror-guttermarker-subtle { + color: #999; +} + +/* FOLD GUTTER */ + +.CodeMirror-foldmarker { + font-family: arial; + line-height: 0.3; + color: #414141; + text-shadow: + #f96 1px 1px 2px, + #f96 -1px -1px 2px, + #f96 1px -1px 2px, + #f96 -1px 1px 2px; + cursor: pointer; +} + +.CodeMirror-foldgutter { + width: 0.7em; +} + +.CodeMirror-foldgutter-open, +.CodeMirror-foldgutter-folded { + cursor: pointer; +} + +.CodeMirror-foldgutter-open::after, +.CodeMirror-foldgutter-folded::after { + position: relative; + top: -0.1em; + display: inline-block; + font-size: 0.8em; + content: '>'; + opacity: 0.8; + transform: rotate(90deg); + transition: transform 0.2s; +} + +.CodeMirror-foldgutter-folded::after { + transform: none; +} + +/* CURSOR */ + +.CodeMirror-cursor { + position: absolute; + width: 0; + pointer-events: none; + border-right: none; + border-left: 1px solid black; +} + +/* Shown when moving in bi-directional text */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} + +.cm-fat-cursor .CodeMirror-cursor { + width: auto; + background: #7e7; + border: 0 !important; +} + +.cm-fat-cursor div.CodeMirror-cursors { + z-index: 1; +} + +.cm-fat-cursor-mark { + background-color: rgb(20 255 20 / 50%); + animation: blink 1.06s steps(1) infinite; +} + +.cm-animate-fat-cursor { + width: auto; + background-color: #7e7; + border: 0; + animation: blink 1.06s steps(1) infinite; +} + +@keyframes blink { + 50% { + background-color: transparent; + } +} + +@keyframes blink { + 50% { + background-color: transparent; + } +} + +@keyframes blink { + 50% { + background-color: transparent; + } +} + +.cm-tab { + display: inline-block; + text-decoration: inherit; +} + +.CodeMirror-rulers { + position: absolute; + inset: -50px 0 -20px; + overflow: hidden; +} + +.CodeMirror-ruler { + position: absolute; + top: 0; + bottom: 0; + border-left: 1px solid #ccc; +} + +/* DEFAULT THEME */ +.cm-s-default.CodeMirror { + background-color: transparent; +} + +.cm-s-default .cm-header { + color: blue; +} + +.cm-s-default .cm-quote { + color: #090; +} + +.cm-negative { + color: #d44; +} + +.cm-positive { + color: #292; +} + +.cm-header, +.cm-strong { + font-weight: bold; +} + +.cm-em { + font-style: italic; +} + +.cm-link { + text-decoration: underline; +} + +.cm-strikethrough { + text-decoration: line-through; +} + +.cm-s-default .cm-atom, +.cm-s-default .cm-def, +.cm-s-default .cm-property, +.cm-s-default .cm-variable-2, +.cm-s-default .cm-variable-3, +.cm-s-default .cm-punctuation { + color: var(--base); +} + +.cm-s-default .cm-hr, +.cm-s-default .cm-comment { + color: var(--comment); +} + +.cm-s-default .cm-attribute, +.cm-s-default .cm-keyword { + color: var(--keyword); +} + +.cm-s-default .cm-variable { + color: var(--variable); +} + +.cm-s-default .cm-bracket, +.cm-s-default .cm-tag { + color: var(--tags); +} + +.cm-s-default .cm-number { + color: var(--number); +} + +.cm-s-default .cm-string, +.cm-s-default .cm-string-2 { + color: var(--string); +} + +.cm-s-default .cm-type { + color: #085; +} + +.cm-s-default .cm-meta { + color: #555; +} + +.cm-s-default .cm-qualifier { + color: var(--qualifier); +} + +.cm-s-default .cm-builtin { + color: #7539ff; +} + +.cm-s-default .cm-link { + color: var(--flash); +} + +.cm-s-default .cm-error { + color: #ff008c; +} + +.cm-invalidchar { + color: #ff008c; +} + +.CodeMirror-composing { + border-bottom: 2px solid; +} + +/* Default styles for common addons */ + +div.CodeMirror span.CodeMirror-matchingbracket { + color: #0b0; +} + +div.CodeMirror span.CodeMirror-nonmatchingbracket { + color: #a22; +} + +.CodeMirror-matchingtag { + background: rgb(255 150 0 / 30%); +} + +.CodeMirror-activeline-background { + background: #e8f2ff; +} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror-scroll { + position: relative; + height: 100%; + padding-bottom: 30px; + margin-right: -30px; + + /* 30px is the magic margin used to hide the element's real scrollbars */ + + /* See overflow: hidden in .CodeMirror */ + margin-bottom: -30px; + overflow: scroll !important; /* Things will break if this is overridden */ + outline: none; /* Prevent dragging from highlighting the element */ +} + +.CodeMirror-sizer { + position: relative; + margin-bottom: 20px !important; + border-right: 30px solid transparent; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actual scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, +.CodeMirror-hscrollbar, +.CodeMirror-scrollbar-filler, +.CodeMirror-gutter-filler { + position: absolute; + z-index: 6; + display: none; +} + +.CodeMirror-vscrollbar { + top: 0; + right: 0; + overflow: hidden scroll; +} + +.CodeMirror-hscrollbar { + bottom: 0; + left: 0; + overflow: scroll hidden; +} + +.CodeMirror-scrollbar-filler { + right: 0; + bottom: 0; +} + +.CodeMirror-gutter-filler { + bottom: 0; + left: 0; +} + +.CodeMirror-gutter { + display: inline-block; + height: 100%; + margin-bottom: -30px; + vertical-align: top; + white-space: normal; +} + +.CodeMirror-gutter-wrapper { + position: absolute; + z-index: 4; + background: none !important; + border: none !important; +} + +.CodeMirror-gutter-background { + position: absolute; + top: 0; + bottom: 0; + z-index: 4; +} + +.CodeMirror-gutter-elt { + position: absolute; + z-index: 4; + cursor: default; +} + +.CodeMirror-gutter-wrapper ::selection { + background-color: transparent; +} + +.CodeMirrorwrapper ::selection { + background-color: transparent; +} + +.CodeMirror pre { + position: relative; + z-index: 2; + padding: 0 4px; /* Horizontal padding of content */ + margin: 0; + overflow: visible; + font-family: inherit; + font-size: inherit; + font-variant-ligatures: contextual; + line-height: inherit; + color: inherit; + overflow-wrap: normal; + white-space: pre; + background: transparent; + border-width: 0; + + /* Reset some styles that the rest of the page might have set */ + border-radius: 0; + -webkit-tap-highlight-color: transparent; +} + +.CodeMirror-wrap pre { + word-break: normal; + overflow-wrap: break-word; + white-space: pre-wrap; +} + +.CodeMirror-linebackground { + position: absolute; + inset: 0; + z-index: 0; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; + padding: 0.1px; /* Force widget margins to stay inside of the container */ +} + +.CodeMirror-rtl pre { + direction: rtl; +} + +.CodeMirror-code { + outline: none; +} + +/* Force content-box sizing for the elements where we expect it */ +.CodeMirror-scroll, +.CodeMirror-sizer, +.CodeMirror-gutter, +.CodeMirror-gutters, +.CodeMirror-linenumber { + box-sizing: content-box; +} + +.CodeMirror-measure { + position: absolute; + visibility: hidden; + width: 100%; + height: 0; + overflow: hidden; +} + +.CodeMirror-measure pre { + position: static; +} + +div.CodeMirror-cursors { + position: relative; + z-index: 3; + visibility: hidden; +} + +div.CodeMirror-dragcursors { + visibility: visible; +} + +.CodeMirror-focused div.CodeMirror-cursors { + visibility: visible; +} + +.CodeMirror-selected { + background: #d9d9d9; +} + +.CodeMirror-focused .CodeMirror-selected { + background: #d7d4f0; +} + +.CodeMirror-crosshair { + cursor: crosshair; +} + +.CodeMirror-line::selection, +.CodeMirror-line > span::selection, +.CodeMirror-line > span > span::selection { + background: #d7d4f0; +} + +.cm-searching { + background-color: #ffa; + background-color: rgb(255 255 0 / 40%); +} + +/* Used to force a border model for a node */ +.cm-force-border { + padding-right: 0.1px; +} + +@media print { + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursors { + visibility: hidden; + } +} + +/* See issue #2901 */ +.cm-tab-wrap-hack::after { + content: ''; +} + +/* Help users use markselection to safely style text background */ +span.CodeMirror-selectedtext { + background: none; +} diff --git a/packages/effects/plugins/src/code-editor/index.ts b/packages/effects/plugins/src/code-editor/index.ts new file mode 100644 index 0000000..d19a3b4 --- /dev/null +++ b/packages/effects/plugins/src/code-editor/index.ts @@ -0,0 +1,2 @@ +export { default as CodeEditor } from './code-editor.vue'; +export * from './types'; diff --git a/packages/effects/plugins/src/code-editor/types.ts b/packages/effects/plugins/src/code-editor/types.ts new file mode 100644 index 0000000..c1d490d --- /dev/null +++ b/packages/effects/plugins/src/code-editor/types.ts @@ -0,0 +1,14 @@ +export enum MODE { + HTML = 'htmlmixed', + JS = 'javascript', + JSON = 'application/json', + VUE = 'vue', +} + +export interface CodeEditorProps { + mode?: string; + value?: string; + readonly?: boolean; + bordered?: boolean; + autoFormat?: boolean; +} diff --git a/packages/effects/plugins/src/echarts/echarts-ui.vue b/packages/effects/plugins/src/echarts/echarts-ui.vue new file mode 100644 index 0000000..70d1f20 --- /dev/null +++ b/packages/effects/plugins/src/echarts/echarts-ui.vue @@ -0,0 +1,15 @@ + + + diff --git a/packages/effects/plugins/src/echarts/echarts.ts b/packages/effects/plugins/src/echarts/echarts.ts new file mode 100644 index 0000000..216d883 --- /dev/null +++ b/packages/effects/plugins/src/echarts/echarts.ts @@ -0,0 +1,90 @@ +import type { + // 系列类型的定义后缀都为 SeriesOption + BarSeriesOption, + GaugeSeriesOption, + LineSeriesOption, + MapSeriesOption, +} from 'echarts/charts'; +import type { + DatasetComponentOption, + DataZoomComponentOption, + GeoComponentOption, + GridComponentOption, + // 组件类型的定义后缀都为 ComponentOption + TitleComponentOption, + TooltipComponentOption, + VisualMapComponentOption, +} from 'echarts/components'; +import type { ComposeOption } from 'echarts/core'; + +import { + BarChart, + FunnelChart, + GaugeChart, + LineChart, + MapChart, + PieChart, + RadarChart, +} from 'echarts/charts'; +import { + // 数据集组件 + DatasetComponent, + DataZoomComponent, + DataZoomInsideComponent, + DataZoomSliderComponent, + GeoComponent, + GridComponent, + LegendComponent, + TitleComponent, + ToolboxComponent, + TooltipComponent, + // 内置数据转换器组件 (filter, sort) + TransformComponent, + VisualMapComponent, +} from 'echarts/components'; +import * as echarts from 'echarts/core'; +import { LabelLayout, UniversalTransition } from 'echarts/features'; +import { CanvasRenderer } from 'echarts/renderers'; + +// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型 +export type ECOption = ComposeOption< + | BarSeriesOption + | DatasetComponentOption + | DataZoomComponentOption + | GaugeSeriesOption + | GeoComponentOption + | GridComponentOption + | LineSeriesOption + | MapSeriesOption + | TitleComponentOption + | TooltipComponentOption + | VisualMapComponentOption +>; + +// 注册必须的组件 +echarts.use([ + TitleComponent, + PieChart, + RadarChart, + TooltipComponent, + GridComponent, + DatasetComponent, + DataZoomComponent, + DataZoomInsideComponent, + DataZoomSliderComponent, + TransformComponent, + BarChart, + LineChart, + FunnelChart, + GaugeChart, + LabelLayout, + UniversalTransition, + CanvasRenderer, + LegendComponent, + ToolboxComponent, + VisualMapComponent, + MapChart, + GeoComponent, +]); + +export default echarts; diff --git a/packages/effects/plugins/src/echarts/index.ts b/packages/effects/plugins/src/echarts/index.ts new file mode 100644 index 0000000..80f36a1 --- /dev/null +++ b/packages/effects/plugins/src/echarts/index.ts @@ -0,0 +1,3 @@ +export * from './echarts'; +export { default as EchartsUI } from './echarts-ui.vue'; +export * from './use-echarts'; diff --git a/packages/effects/plugins/src/echarts/map/china.json b/packages/effects/plugins/src/echarts/map/china.json new file mode 100644 index 0000000..222a970 --- /dev/null +++ b/packages/effects/plugins/src/echarts/map/china.json @@ -0,0 +1,27252 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "adcode": 110000, + "name": "北京市", + "center": [116.405285, 39.904989], + "centroid": [116.41995, 40.18994], + "childrenNum": 16, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 0, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [117.348611, 40.581141], + [117.389879, 40.561593], + [117.429915, 40.576141], + [117.412669, 40.605226], + [117.467487, 40.649738], + [117.467487, 40.649738], + [117.501364, 40.636569], + [117.514914, 40.660181], + [117.493973, 40.675161], + [117.408973, 40.686961], + [117.342451, 40.673799], + [117.319662, 40.657911], + [117.278394, 40.664267], + [117.208177, 40.694675], + [117.117018, 40.70012], + [117.11209, 40.707379], + [117.012308, 40.693767], + [116.964881, 40.709647], + [116.926692, 40.745022], + [116.924229, 40.773581], + [116.848468, 40.839264], + [116.81336, 40.848319], + [116.759773, 40.889954], + [116.713577, 40.909858], + [116.722201, 40.927495], + [116.677853, 40.970888], + [116.698795, 41.021477], + [116.688324, 41.044501], + [116.647672, 41.059394], + [116.615643, 41.053076], + [116.623034, 41.021026], + [116.598397, 40.974503], + [116.5676, 40.992574], + [116.519557, 40.98128], + [116.519557, 40.98128], + [116.455499, 40.980828], + [116.447492, 40.953715], + [116.477057, 40.899907], + [116.398216, 40.90624], + [116.370499, 40.94377], + [116.339702, 40.929303], + [116.334159, 40.90443], + [116.438253, 40.81934], + [116.46597, 40.774487], + [116.453651, 40.765876], + [116.316912, 40.772221], + [116.311369, 40.754996], + [116.273181, 40.762703], + [116.247311, 40.791707], + [116.22021, 40.744115], + [116.204812, 40.740035], + [116.171551, 40.695582], + [116.162928, 40.662451], + [116.133979, 40.666536], + [116.09887, 40.630665], + [116.005247, 40.583868], + [115.982457, 40.578868], + [115.971986, 40.6025], + [115.907929, 40.617493], + [115.885139, 40.595229], + [115.827857, 40.587504], + [115.819849, 40.55932], + [115.784741, 40.55841], + [115.755176, 40.540221], + [115.736082, 40.503372], + [115.781045, 40.49336], + [115.771806, 40.443734], + [115.864197, 40.359422], + [115.917784, 40.354405], + [115.95166, 40.281852], + [115.968907, 40.264045], + [115.89869, 40.234354], + [115.870356, 40.185909], + [115.855574, 40.188652], + [115.847567, 40.147036], + [115.806299, 40.15344], + [115.773654, 40.176307], + [115.75456, 40.145663], + [115.75456, 40.145663], + [115.599959, 40.119583], + [115.59072, 40.096239], + [115.527278, 40.076092], + [115.485394, 40.040364], + [115.454597, 40.029825], + [115.450286, 39.992697], + [115.428728, 39.984443], + [115.426264, 39.950502], + [115.481083, 39.935819], + [115.522967, 39.899099], + [115.515575, 39.892212], + [115.515575, 39.892212], + [115.526046, 39.87568], + [115.514344, 39.837549], + [115.567314, 39.816407], + [115.552532, 39.794799], + [115.50572, 39.784222], + [115.483547, 39.798477], + [115.483547, 39.798477], + [115.443511, 39.785601], + [115.439815, 39.752022], + [115.486626, 39.741899], + [115.491554, 39.670074], + [115.478619, 39.650723], + [115.478619, 39.650723], + [115.522351, 39.640124], + [115.518039, 39.597252], + [115.545756, 39.618922], + [115.587024, 39.589873], + [115.633836, 39.599557], + [115.633836, 39.599557], + [115.667712, 39.615234], + [115.698509, 39.577881], + [115.698509, 39.577881], + [115.699125, 39.570039], + [115.699125, 39.570039], + [115.716988, 39.56035], + [115.716988, 39.56035], + [115.718835, 39.553891], + [115.718835, 39.553891], + [115.720683, 39.551122], + [115.720683, 39.551122], + [115.722531, 39.5442], + [115.721299, 39.543738], + [115.722531, 39.5442], + [115.722531, 39.543738], + [115.721299, 39.543738], + [115.722531, 39.543738], + [115.724995, 39.5442], + [115.724995, 39.5442], + [115.738545, 39.540046], + [115.738545, 39.539585], + [115.738545, 39.540046], + [115.738545, 39.539585], + [115.752712, 39.515581], + [115.806299, 39.510041], + [115.806299, 39.510041], + [115.821081, 39.522968], + [115.821081, 39.522968], + [115.828473, 39.541431], + [115.867893, 39.546507], + [115.867893, 39.546507], + [115.91532, 39.582955], + [115.91532, 39.582955], + [115.910393, 39.600479], + [115.910393, 39.600479], + [115.957204, 39.560812], + [115.978146, 39.595868], + [115.995392, 39.576958], + [116.026189, 39.587567], + [116.036044, 39.571884], + [116.09887, 39.575113], + [116.130283, 39.567732], + [116.151841, 39.583416], + [116.198652, 39.589412], + [116.240536, 39.564041], + [116.257782, 39.500344], + [116.307057, 39.488337], + [116.337854, 39.455536], + [116.361876, 39.455074], + [116.361876, 39.455074], + [116.434557, 39.442597], + [116.454883, 39.453226], + [116.444412, 39.482332], + [116.411767, 39.482794], + [116.401912, 39.528046], + [116.443796, 39.510041], + [116.437637, 39.526661], + [116.478289, 39.535431], + [116.473361, 39.552968], + [116.50847, 39.551122], + [116.524484, 39.596329], + [116.592237, 39.621227], + [116.592237, 39.621227], + [116.620571, 39.601863], + [116.664918, 39.605552], + [116.723432, 39.59264], + [116.724048, 39.59264], + [116.723432, 39.59264], + [116.724048, 39.59264], + [116.726512, 39.595407], + [116.726512, 39.595407], + [116.709266, 39.618], + [116.748686, 39.619844], + [116.79057, 39.595868], + [116.812128, 39.615695], + [116.8497, 39.66777], + [116.906366, 39.677444], + [116.90575, 39.688037], + [116.889736, 39.687576], + [116.887272, 39.72533], + [116.916837, 39.731314], + [116.902055, 39.763523], + [116.949482, 39.778703], + [116.918069, 39.84628], + [116.907598, 39.832494], + [116.865714, 39.843982], + [116.812128, 39.889916], + [116.78441, 39.891294], + [116.782563, 39.947749], + [116.757925, 39.967934], + [116.781331, 40.034866], + [116.820135, 40.02845], + [116.831222, 40.051359], + [116.867562, 40.041739], + [116.927924, 40.055024], + [116.945171, 40.04128], + [117.025243, 40.030283], + [117.051728, 40.059605], + [117.105315, 40.074261], + [117.105315, 40.074261], + [117.140423, 40.064185], + [117.159517, 40.077008], + [117.204481, 40.069681], + [117.210024, 40.082045], + [117.224191, 40.094865], + [117.224191, 40.094865], + [117.254988, 40.114548], + [117.254988, 40.114548], + [117.254988, 40.114548], + [117.274082, 40.105852], + [117.307343, 40.136971], + [117.349227, 40.136513], + [117.367089, 40.172649], + [117.367089, 40.173106], + [117.367089, 40.173106], + [117.367089, 40.172649], + [117.383719, 40.188195], + [117.389879, 40.227958], + [117.351075, 40.229786], + [117.331365, 40.289613], + [117.295024, 40.2782], + [117.271618, 40.325211], + [117.271618, 40.325211], + [117.243285, 40.369453], + [117.226039, 40.368997], + [117.234046, 40.417312], + [117.263611, 40.442367], + [117.208793, 40.501552], + [117.262995, 40.512927], + [117.247597, 40.539766], + [117.269771, 40.560684], + [117.348611, 40.581141], + [117.348611, 40.581141] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 120000, + "name": "天津市", + "center": [117.190182, 39.125596], + "centroid": [117.347043, 39.288036], + "childrenNum": 16, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 1, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [117.765602, 39.400527], + [117.846906, 39.407926], + [117.871543, 39.411625], + [117.870311, 39.455074], + [117.899877, 39.474479], + [117.912195, 39.517428], + [117.912195, 39.517428], + [117.904804, 39.533585], + [117.933753, 39.574191], + [117.868464, 39.59679], + [117.829659, 39.589873], + [117.766834, 39.598635], + [117.753899, 39.579726], + [117.753899, 39.579726], + [117.745276, 39.547892], + [117.715711, 39.529892], + [117.707088, 39.576036], + [117.684914, 39.58895], + [117.654117, 39.575113], + [117.637486, 39.603246], + [117.66274, 39.636437], + [117.668899, 39.666849], + [117.627015, 39.703693], + [117.57774, 39.726711], + [117.595603, 39.74604], + [117.56111, 39.754782], + [117.546327, 39.775943], + [117.561726, 39.799856], + [117.529081, 39.859144], + [117.529081, 39.859144], + [117.508139, 39.901854], + [117.508139, 39.901854], + [117.512451, 39.90874], + [117.512451, 39.90874], + [117.513067, 39.910576], + [117.513067, 39.910576], + [117.514914, 39.946832], + [117.534625, 39.954631], + [117.546327, 39.999116], + [117.594987, 39.994531], + [117.594987, 39.994531], + [117.614697, 39.97252], + [117.671363, 39.973896], + [117.691073, 39.984902], + [117.756363, 39.965181], + [117.781616, 39.966558], + [117.781616, 39.966558], + [117.795167, 39.996823], + [117.795167, 39.996823], + [117.793319, 40.005534], + [117.793319, 40.005534], + [117.768681, 40.022034], + [117.768681, 40.022034], + [117.744044, 40.018368], + [117.74774, 40.047236], + [117.776073, 40.059605], + [117.752667, 40.081588], + [117.71879, 40.082045], + [117.71879, 40.082045], + [117.675059, 40.082045], + [117.655965, 40.109514], + [117.655965, 40.109514], + [117.654117, 40.114548], + [117.654117, 40.114548], + [117.651653, 40.122786], + [117.651653, 40.122786], + [117.613465, 40.158014], + [117.613465, 40.158014], + [117.609769, 40.160301], + [117.609769, 40.160301], + [117.576508, 40.178593], + [117.571581, 40.219276], + [117.548791, 40.232527], + [117.505059, 40.227044], + [117.450241, 40.252627], + [117.415748, 40.248973], + [117.389879, 40.227958], + [117.383719, 40.188195], + [117.367089, 40.172649], + [117.367089, 40.173106], + [117.367089, 40.173106], + [117.367089, 40.172649], + [117.349227, 40.136513], + [117.307343, 40.136971], + [117.274082, 40.105852], + [117.254988, 40.114548], + [117.254988, 40.114548], + [117.254988, 40.114548], + [117.224191, 40.094865], + [117.224191, 40.094865], + [117.210024, 40.082045], + [117.192162, 40.066475], + [117.198322, 39.992697], + [117.150894, 39.944996], + [117.162597, 39.876598], + [117.162597, 39.876598], + [117.227887, 39.852712], + [117.247597, 39.860981], + [117.251908, 39.834332], + [117.192162, 39.832953], + [117.156438, 39.817326], + [117.15767, 39.796638], + [117.205713, 39.763984], + [117.161981, 39.748801], + [117.165061, 39.718886], + [117.165061, 39.718886], + [117.177996, 39.645194], + [117.152742, 39.623532], + [117.10901, 39.625375], + [117.10901, 39.625375], + [117.016004, 39.653949], + [116.983359, 39.638742], + [116.983359, 39.638742], + [116.964265, 39.64335], + [116.948866, 39.680668], + [116.948866, 39.680668], + [116.944555, 39.695405], + [116.944555, 39.695405], + [116.932236, 39.706456], + [116.932236, 39.706456], + [116.90575, 39.688037], + [116.906366, 39.677444], + [116.8497, 39.66777], + [116.812128, 39.615695], + [116.808432, 39.576497], + [116.78749, 39.554352], + [116.819519, 39.528507], + [116.820751, 39.482332], + [116.785026, 39.465702], + [116.832454, 39.435664], + [116.876185, 39.43474], + [116.839845, 39.413474], + [116.840461, 39.378326], + [116.818287, 39.3737], + [116.829374, 39.338994], + [116.870642, 39.357506], + [116.889736, 39.338068], + [116.87249, 39.291304], + [116.881729, 39.225966], + [116.881729, 39.225966], + [116.855859, 39.215766], + [116.870026, 39.153607], + [116.909446, 39.150822], + [116.912526, 39.110898], + [116.91191, 39.111362], + [116.91191, 39.111362], + [116.912526, 39.110898], + [116.871874, 39.054688], + [116.812744, 39.05097], + [116.812744, 39.05097], + [116.783179, 39.05097], + [116.783179, 39.05097], + [116.754229, 39.034701], + [116.754229, 39.034701], + [116.754845, 39.003084], + [116.72836, 38.975174], + [116.708034, 38.931892], + [116.722201, 38.896968], + [116.723432, 38.852706], + [116.75115, 38.831264], + [116.737599, 38.784629], + [116.746222, 38.754299], + [116.794265, 38.744498], + [116.794265, 38.744498], + [116.858939, 38.741231], + [116.877417, 38.680522], + [116.948866, 38.689398], + [116.950714, 38.689398], + [116.95133, 38.689398], + [116.950714, 38.689398], + [116.948866, 38.689398], + [116.95133, 38.689398], + [117.038793, 38.688464], + [117.068358, 38.680522], + [117.055424, 38.639398], + [117.070822, 38.608072], + [117.109626, 38.584685], + [117.150894, 38.617892], + [117.183539, 38.61836], + [117.183539, 38.61836], + [117.213104, 38.639866], + [117.213104, 38.639866], + [117.258684, 38.608072], + [117.258684, 38.608072], + [117.238358, 38.580943], + [117.25314, 38.556143], + [117.368937, 38.564566], + [117.432379, 38.601524], + [117.47919, 38.616489], + [117.55803, 38.613683], + [117.639334, 38.626776], + [117.65658, 38.66043], + [117.729261, 38.680055], + [117.740964, 38.700141], + [117.740964, 38.753833], + [117.671363, 38.772032], + [117.646725, 38.788827], + [117.64611, 38.828933], + [117.752051, 38.847579], + [117.778536, 38.869016], + [117.847522, 38.855502], + [117.875855, 38.920252], + [117.898029, 38.948649], + [117.855529, 38.957492], + [117.837667, 39.057011], + [117.871543, 39.122506], + [117.96455, 39.172631], + [117.977485, 39.206028], + [118.032919, 39.219939], + [118.034767, 39.218548], + [118.064948, 39.231065], + [118.064948, 39.256094], + [118.036615, 39.264898], + [118.024296, 39.289451], + [118.024296, 39.289451], + [117.982412, 39.298714], + [117.982412, 39.298714], + [117.979333, 39.300566], + [117.979333, 39.300566], + [117.973173, 39.312143], + [117.973173, 39.312143], + [117.965782, 39.314921], + [117.965782, 39.314921], + [117.919587, 39.318162], + [117.919587, 39.318162], + [117.88879, 39.332051], + [117.854913, 39.328348], + [117.854297, 39.328348], + [117.854913, 39.328348], + [117.854297, 39.328348], + [117.850601, 39.363984], + [117.850601, 39.363984], + [117.810565, 39.354729], + [117.805022, 39.373237], + [117.784696, 39.376938], + [117.74466, 39.354729], + [117.670747, 39.357969], + [117.669515, 39.322792], + [117.594987, 39.349176], + [117.536472, 39.338068], + [117.521074, 39.357043], + [117.570965, 39.404689], + [117.601146, 39.419485], + [117.614081, 39.407001], + [117.668899, 39.412087], + [117.673211, 39.386652], + [117.699696, 39.407463], + [117.765602, 39.400527] + ] + ], + [ + [ + [117.805022, 39.373237], + [117.852449, 39.380639], + [117.846906, 39.407926], + [117.765602, 39.400527], + [117.784696, 39.376938], + [117.805022, 39.373237] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 130000, + "name": "河北省", + "center": [114.502461, 38.045474], + "childrenNum": 11, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 2, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [117.467487, 40.649738], + [117.412669, 40.605226], + [117.429915, 40.576141], + [117.389879, 40.561593], + [117.348611, 40.581141], + [117.348611, 40.581141], + [117.269771, 40.560684], + [117.247597, 40.539766], + [117.262995, 40.512927], + [117.208793, 40.501552], + [117.263611, 40.442367], + [117.234046, 40.417312], + [117.226039, 40.368997], + [117.243285, 40.369453], + [117.271618, 40.325211], + [117.271618, 40.325211], + [117.295024, 40.2782], + [117.331365, 40.289613], + [117.351075, 40.229786], + [117.389879, 40.227958], + [117.415748, 40.248973], + [117.450241, 40.252627], + [117.505059, 40.227044], + [117.548791, 40.232527], + [117.571581, 40.219276], + [117.576508, 40.178593], + [117.609769, 40.160301], + [117.609769, 40.160301], + [117.613465, 40.158014], + [117.613465, 40.158014], + [117.651653, 40.122786], + [117.651653, 40.122786], + [117.654117, 40.114548], + [117.654117, 40.114548], + [117.655965, 40.109514], + [117.655965, 40.109514], + [117.675059, 40.082045], + [117.71879, 40.082045], + [117.71879, 40.082045], + [117.752667, 40.081588], + [117.776073, 40.059605], + [117.74774, 40.047236], + [117.744044, 40.018368], + [117.768681, 40.022034], + [117.768681, 40.022034], + [117.793319, 40.005534], + [117.793319, 40.005534], + [117.795167, 39.996823], + [117.795167, 39.996823], + [117.781616, 39.966558], + [117.781616, 39.966558], + [117.756363, 39.965181], + [117.691073, 39.984902], + [117.671363, 39.973896], + [117.614697, 39.97252], + [117.594987, 39.994531], + [117.594987, 39.994531], + [117.546327, 39.999116], + [117.534625, 39.954631], + [117.514914, 39.946832], + [117.513067, 39.910576], + [117.513067, 39.910576], + [117.512451, 39.90874], + [117.512451, 39.90874], + [117.508139, 39.901854], + [117.508139, 39.901854], + [117.529081, 39.859144], + [117.529081, 39.859144], + [117.561726, 39.799856], + [117.546327, 39.775943], + [117.56111, 39.754782], + [117.595603, 39.74604], + [117.57774, 39.726711], + [117.627015, 39.703693], + [117.668899, 39.666849], + [117.66274, 39.636437], + [117.637486, 39.603246], + [117.654117, 39.575113], + [117.684914, 39.58895], + [117.707088, 39.576036], + [117.715711, 39.529892], + [117.745276, 39.547892], + [117.753899, 39.579726], + [117.753899, 39.579726], + [117.766834, 39.598635], + [117.829659, 39.589873], + [117.868464, 39.59679], + [117.933753, 39.574191], + [117.904804, 39.533585], + [117.912195, 39.517428], + [117.912195, 39.517428], + [117.899877, 39.474479], + [117.870311, 39.455074], + [117.871543, 39.411625], + [117.846906, 39.407926], + [117.852449, 39.380639], + [117.805022, 39.373237], + [117.810565, 39.354729], + [117.850601, 39.363984], + [117.850601, 39.363984], + [117.854297, 39.328348], + [117.854913, 39.328348], + [117.854297, 39.328348], + [117.854913, 39.328348], + [117.88879, 39.332051], + [117.919587, 39.318162], + [117.919587, 39.318162], + [117.965782, 39.314921], + [117.965782, 39.314921], + [117.973173, 39.312143], + [117.973173, 39.312143], + [117.979333, 39.300566], + [117.979333, 39.300566], + [117.982412, 39.298714], + [117.982412, 39.298714], + [118.024296, 39.289451], + [118.024296, 39.289451], + [118.036615, 39.264898], + [118.064948, 39.256094], + [118.064948, 39.231065], + [118.034767, 39.218548], + [118.026144, 39.201854], + [118.070492, 39.213911], + [118.077883, 39.201854], + [118.12531, 39.182838], + [118.162883, 39.136433], + [118.1906, 39.080708], + [118.225092, 39.034701], + [118.319331, 39.009594], + [118.366143, 39.016104], + [118.377845, 38.971917], + [118.491178, 38.909077], + [118.539837, 38.910008], + [118.604511, 38.971452], + [118.570634, 38.999363], + [118.533062, 39.090928], + [118.588497, 39.107648], + [118.578642, 39.130863], + [118.637156, 39.157319], + [118.76096, 39.133648], + [118.814546, 39.138754], + [118.857662, 39.162888], + [118.897082, 39.151286], + [118.920488, 39.171703], + [118.951285, 39.178662], + [118.896466, 39.139683], + [118.890307, 39.118792], + [118.926031, 39.123435], + [118.97777, 39.163352], + [119.023966, 39.187012], + [119.038132, 39.211593], + [119.096031, 39.24219], + [119.121284, 39.281576], + [119.185342, 39.342234], + [119.272805, 39.363521], + [119.317153, 39.4107], + [119.316537, 39.437051], + [119.269726, 39.498497], + [119.366428, 39.734996], + [119.474217, 39.813189], + [119.536427, 39.809052], + [119.520413, 39.840306], + [119.540739, 39.888079], + [119.588166, 39.910576], + [119.620195, 39.904609], + [119.642369, 39.925264], + [119.681789, 39.922511], + [119.726137, 39.940867], + [119.787115, 39.950502], + [119.820375, 39.979399], + [119.842549, 39.956007], + [119.872114, 39.960594], + [119.854252, 39.98857], + [119.845629, 40.000949], + [119.845629, 40.000949], + [119.854252, 40.033033], + [119.81668, 40.050443], + [119.81668, 40.050443], + [119.787115, 40.041739], + [119.787115, 40.041739], + [119.783419, 40.046778], + [119.783419, 40.046778], + [119.772332, 40.08113], + [119.736608, 40.104936], + [119.760629, 40.136056], + [119.745847, 40.207851], + [119.716898, 40.195966], + [119.671934, 40.23938], + [119.639289, 40.231613], + [119.639289, 40.231613], + [119.651608, 40.271808], + [119.598021, 40.334335], + [119.586934, 40.375381], + [119.604797, 40.455119], + [119.553674, 40.502007], + [119.572152, 40.523846], + [119.559217, 40.547952], + [119.503783, 40.553864], + [119.477913, 40.533399], + [119.429254, 40.540221], + [119.30237, 40.530215], + [119.256175, 40.543404], + [119.22045, 40.569322], + [119.230921, 40.603863], + [119.177951, 40.609315], + [119.162552, 40.600228], + [119.14469, 40.632482], + [119.184726, 40.680153], + [119.165632, 40.69286], + [119.115125, 40.666536], + [119.054763, 40.664721], + [119.028277, 40.692406], + [119.011031, 40.687414], + [118.96114, 40.72008], + [118.950053, 40.747743], + [118.895234, 40.75409], + [118.907553, 40.775394], + [118.878604, 40.783098], + [118.845959, 40.822057], + [118.873061, 40.847866], + [118.90201, 40.960946], + [118.916792, 40.969984], + [118.977154, 40.959138], + [118.977154, 40.959138], + [119.00056, 40.967273], + [119.013495, 41.007479], + [118.951901, 41.018317], + [118.937118, 41.052625], + [118.964836, 41.079246], + [119.037516, 41.067516], + [119.080632, 41.095936], + [119.081248, 41.131555], + [119.126212, 41.138767], + [119.189038, 41.198234], + [119.169943, 41.222996], + [119.204436, 41.222546], + [119.209364, 41.244599], + [119.2494, 41.279689], + [119.239545, 41.31431], + [119.211827, 41.308016], + [119.197661, 41.282837], + [119.168712, 41.294978], + [119.092951, 41.293629], + [118.980234, 41.305769], + [118.949437, 41.317906], + [118.890923, 41.300823], + [118.844727, 41.342622], + [118.843496, 41.374516], + [118.770199, 41.352956], + [118.741866, 41.324198], + [118.677192, 41.35026], + [118.629765, 41.346666], + [118.528135, 41.355202], + [118.412338, 41.331838], + [118.380309, 41.312062], + [118.348896, 41.342622], + [118.361215, 41.384844], + [118.348896, 41.428384], + [118.327338, 41.450816], + [118.271904, 41.471446], + [118.315636, 41.512688], + [118.302701, 41.55256], + [118.215237, 41.59554], + [118.206614, 41.650566], + [118.159187, 41.67605], + [118.155491, 41.712694], + [118.132702, 41.733241], + [118.140093, 41.784134], + [118.178281, 41.814917], + [118.236179, 41.80778], + [118.247266, 41.773869], + [118.29223, 41.772976], + [118.335346, 41.845241], + [118.340273, 41.87243], + [118.268824, 41.930336], + [118.306396, 41.940131], + [118.313788, 41.98819], + [118.291614, 42.007759], + [118.239875, 42.024655], + [118.286686, 42.033991], + [118.296541, 42.057545], + [118.27252, 42.083312], + [118.239259, 42.092639], + [118.212774, 42.081091], + [118.220165, 42.058434], + [118.194296, 42.031324], + [118.116687, 42.037102], + [118.155491, 42.081091], + [118.097593, 42.105072], + [118.089586, 42.12283], + [118.106216, 42.172082], + [118.033535, 42.199132], + [117.977485, 42.229716], + [117.974405, 42.25054], + [118.047702, 42.280656], + [118.060021, 42.298364], + [118.008898, 42.346595], + [118.024296, 42.385064], + [117.997811, 42.416884], + [117.874007, 42.510038], + [117.856761, 42.539148], + [117.797631, 42.585431], + [117.801326, 42.612744], + [117.779768, 42.61847], + [117.708935, 42.588515], + [117.667051, 42.582347], + [117.60053, 42.603054], + [117.537088, 42.603054], + [117.530313, 42.590278], + [117.475494, 42.602613], + [117.435458, 42.585431], + [117.434226, 42.557224], + [117.387415, 42.517537], + [117.387415, 42.517537], + [117.410205, 42.519743], + [117.413284, 42.471645], + [117.390495, 42.461933], + [117.332596, 42.46105], + [117.332596, 42.46105], + [117.275314, 42.481797], + [117.275314, 42.481797], + [117.188467, 42.468114], + [117.188467, 42.468114], + [117.135496, 42.468996], + [117.09546, 42.484004], + [117.080061, 42.463699], + [117.080061, 42.463699], + [117.01662, 42.456193], + [117.01662, 42.456193], + [117.009228, 42.44957], + [117.009228, 42.44957], + [117.005533, 42.43367], + [117.005533, 42.43367], + [116.99075, 42.425719], + [116.99075, 42.425719], + [116.974736, 42.426603], + [116.974736, 42.426603], + [116.97104, 42.427486], + [116.97104, 42.427486], + [116.944555, 42.415116], + [116.944555, 42.415116], + [116.936547, 42.410256], + [116.936547, 42.410256], + [116.921765, 42.403628], + [116.921765, 42.403628], + [116.910062, 42.395231], + [116.910062, 42.395231], + [116.910678, 42.394789], + [116.910678, 42.394789], + [116.886656, 42.366496], + [116.897743, 42.297479], + [116.918685, 42.229716], + [116.903287, 42.190708], + [116.789338, 42.200462], + [116.825062, 42.155669], + [116.850316, 42.156556], + [116.890352, 42.092639], + [116.879881, 42.018431], + [116.796113, 41.977958], + [116.748686, 41.984186], + [116.727744, 41.951259], + [116.66923, 41.947698], + [116.639049, 41.929891], + [116.597165, 41.935679], + [116.553433, 41.928555], + [116.510933, 41.974399], + [116.4826, 41.975734], + [116.453651, 41.945917], + [116.393289, 41.942802], + [116.414231, 41.982407], + [116.373579, 42.009983], + [116.310137, 41.997086], + [116.298434, 41.96817], + [116.223906, 41.932562], + [116.212819, 41.885352], + [116.194341, 41.861734], + [116.122892, 41.861734], + [116.106877, 41.831419], + [116.129051, 41.805996], + [116.09887, 41.776547], + [116.034196, 41.782795], + [116.007095, 41.79752], + [116.007095, 41.797966], + [116.007095, 41.79752], + [116.007095, 41.797966], + [115.994776, 41.828743], + [115.954124, 41.874213], + [115.916552, 41.945027], + [115.85311, 41.927665], + [115.834632, 41.93835], + [115.811226, 41.912525], + [115.726227, 41.870202], + [115.688038, 41.867528], + [115.654162, 41.829189], + [115.57409, 41.80555], + [115.519887, 41.76762], + [115.488474, 41.760924], + [115.42996, 41.728775], + [115.346808, 41.712247], + [115.319091, 41.691693], + [115.360975, 41.661297], + [115.345576, 41.635807], + [115.377605, 41.603148], + [115.310468, 41.592854], + [115.290142, 41.622835], + [115.26612, 41.616124], + [115.256881, 41.580768], + [115.20391, 41.571367], + [115.195287, 41.602253], + [115.0992, 41.62373], + [115.056085, 41.602253], + [115.016049, 41.615229], + [114.860832, 41.60091], + [114.895325, 41.636255], + [114.902716, 41.695715], + [114.89594, 41.76762], + [114.868839, 41.813579], + [114.922426, 41.825175], + [114.939056, 41.846132], + [114.923658, 41.871093], + [114.915035, 41.960605], + [114.9021, 42.015763], + [114.860832, 42.054879], + [114.86268, 42.097967], + [114.825723, 42.139695], + [114.79431, 42.149457], + [114.789383, 42.130819], + [114.75489, 42.115727], + [114.675434, 42.12061], + [114.647717, 42.109512], + [114.560254, 42.132595], + [114.510978, 42.110844], + [114.502355, 42.06732], + [114.480181, 42.064654], + [114.467863, 42.025989], + [114.511594, 41.981962], + [114.478334, 41.951704], + [114.419203, 41.942356], + [114.352066, 41.953484], + [114.343443, 41.926774], + [114.282465, 41.863517], + [114.200545, 41.789934], + [114.215328, 41.75646], + [114.206704, 41.7386], + [114.237501, 41.698843], + [114.215328, 41.68499], + [114.259059, 41.623282], + [114.226414, 41.616572], + [114.221487, 41.582111], + [114.230726, 41.513584], + [114.101379, 41.537779], + [114.032394, 41.529715], + [113.976959, 41.505966], + [113.953553, 41.483553], + [113.933227, 41.487139], + [113.919677, 41.454404], + [113.877793, 41.431076], + [113.871017, 41.413126], + [113.94493, 41.392477], + [113.92522, 41.325546], + [113.899351, 41.316108], + [113.914749, 41.294529], + [113.95109, 41.282837], + [113.971416, 41.239649], + [113.992357, 41.269794], + [114.016379, 41.231999], + [113.996669, 41.19238], + [113.960945, 41.171211], + [113.920293, 41.172112], + [113.877793, 41.115777], + [113.819279, 41.09774], + [113.868554, 41.06887], + [113.973263, 40.983087], + [113.994821, 40.938798], + [114.057647, 40.925234], + [114.041633, 40.917546], + [114.055183, 40.867782], + [114.073661, 40.857372], + [114.044712, 40.830661], + [114.080437, 40.790348], + [114.104458, 40.797597], + [114.103227, 40.770861], + [114.134639, 40.737314], + [114.162357, 40.71373], + [114.183299, 40.67153], + [114.236269, 40.607043], + [114.283081, 40.590685], + [114.273842, 40.552954], + [114.293552, 40.55159], + [114.282465, 40.494725], + [114.267066, 40.474242], + [114.299711, 40.44009], + [114.286161, 40.425057], + [114.31203, 40.372645], + [114.381015, 40.36307], + [114.390254, 40.351213], + [114.438914, 40.371733], + [114.481413, 40.34802], + [114.530688, 40.345283], + [114.510978, 40.302851], + [114.46971, 40.268155], + [114.406269, 40.246232], + [114.362537, 40.249886], + [114.292936, 40.230242], + [114.255364, 40.236182], + [114.235654, 40.198252], + [114.180219, 40.191395], + [114.135871, 40.175392], + [114.097683, 40.193681], + [114.073046, 40.168533], + [114.073046, 40.168533], + [114.101995, 40.099901], + [114.086596, 40.071513], + [114.045944, 40.056856], + [114.018227, 40.103563], + [113.989278, 40.11226], + [113.959097, 40.033491], + [113.910438, 40.015618], + [114.029314, 39.985819], + [114.028082, 39.959218], + [114.047176, 39.916085], + [114.067502, 39.922511], + [114.17406, 39.897722], + [114.212248, 39.918839], + [114.229494, 39.899558], + [114.204241, 39.885324], + [114.215943, 39.8619], + [114.286776, 39.871087], + [114.285545, 39.858225], + [114.395182, 39.867412], + [114.406885, 39.833413], + [114.390254, 39.819165], + [114.41674, 39.775943], + [114.409964, 39.761683], + [114.408117, 39.652106], + [114.431522, 39.613851], + [114.49558, 39.608318], + [114.51529, 39.564964], + [114.568877, 39.573729], + [114.532536, 39.486027], + [114.501739, 39.476789], + [114.496812, 39.438437], + [114.469095, 39.400989], + [114.466631, 39.329736], + [114.430906, 39.307513], + [114.437066, 39.259337], + [114.416124, 39.242654], + [114.47587, 39.21623], + [114.443841, 39.174023], + [114.388406, 39.176807], + [114.360689, 39.134112], + [114.369928, 39.107648], + [114.345907, 39.075133], + [114.252284, 39.073739], + [114.180835, 39.049111], + [114.157429, 39.061194], + [114.10877, 39.052364], + [114.082901, 39.09325], + [114.082901, 39.09325], + [114.064422, 39.094179], + [114.050872, 39.135969], + [114.006524, 39.122971], + [113.994821, 39.095572], + [113.961561, 39.100681], + [113.930148, 39.063517], + [113.898119, 39.067699], + [113.80696, 38.989595], + [113.776779, 38.986804], + [113.76754, 38.959819], + [113.776163, 38.885788], + [113.795257, 38.860628], + [113.855619, 38.828933], + [113.836525, 38.795824], + [113.839605, 38.7585], + [113.802648, 38.763166], + [113.775547, 38.709949], + [113.720728, 38.713218], + [113.70225, 38.651551], + [113.612939, 38.645942], + [113.603084, 38.587024], + [113.561816, 38.558483], + [113.546417, 38.492936], + [113.583374, 38.459671], + [113.537794, 38.417952], + [113.525475, 38.383245], + [113.557504, 38.343359], + [113.54457, 38.270569], + [113.570439, 38.237202], + [113.598772, 38.22733], + [113.64312, 38.232031], + [113.678844, 38.20523], + [113.711489, 38.213695], + [113.720728, 38.174656], + [113.797105, 38.162894], + [113.831597, 38.16854], + [113.811271, 38.117707], + [113.876561, 38.055059], + [113.872249, 37.990471], + [113.901198, 37.984811], + [113.936307, 37.922993], + [113.959097, 37.906468], + [113.976959, 37.816696], + [114.006524, 37.813386], + [114.044712, 37.761834], + [113.996669, 37.730128], + [113.993589, 37.706932], + [114.068118, 37.721608], + [114.12848, 37.698409], + [114.139567, 37.675676], + [114.115545, 37.619761], + [114.118625, 37.59084], + [114.036705, 37.494037], + [114.014531, 37.42468], + [113.973879, 37.40329], + [113.962792, 37.355734], + [113.90243, 37.310052], + [113.886416, 37.239095], + [113.853155, 37.215269], + [113.832213, 37.167594], + [113.773083, 37.151855], + [113.773699, 37.107004], + [113.758301, 37.075497], + [113.788482, 37.059739], + [113.771851, 37.016745], + [113.791561, 36.98759], + [113.76138, 36.956034], + [113.792793, 36.894796], + [113.773083, 36.85506], + [113.731815, 36.858891], + [113.731815, 36.878521], + [113.696707, 36.882351], + [113.676381, 36.855539], + [113.680692, 36.789907], + [113.600004, 36.752995], + [113.549497, 36.752515], + [113.535946, 36.732373], + [113.499606, 36.740527], + [113.465113, 36.707908], + [113.506997, 36.705029], + [113.476816, 36.655114], + [113.486671, 36.635427], + [113.54457, 36.62342], + [113.539642, 36.594116], + [113.569823, 36.585947], + [113.588917, 36.547974], + [113.559968, 36.528741], + [113.554425, 36.494589], + [113.587069, 36.460904], + [113.635729, 36.451277], + [113.670221, 36.425278], + [113.708409, 36.423352], + [113.731199, 36.363135], + [113.755221, 36.366026], + [113.813119, 36.332285], + [113.856851, 36.329392], + [113.84946, 36.347711], + [113.882104, 36.353977], + [113.911054, 36.314927], + [113.962792, 36.353977], + [113.981887, 36.31782], + [114.002828, 36.334214], + [114.056415, 36.329392], + [114.04348, 36.303353], + [114.080437, 36.269585], + [114.129096, 36.280199], + [114.175907, 36.264759], + [114.170364, 36.245938], + [114.170364, 36.245938], + [114.203009, 36.245456], + [114.2104, 36.272962], + [114.241197, 36.251247], + [114.257827, 36.263794], + [114.299095, 36.245938], + [114.345291, 36.255591], + [114.356378, 36.230492], + [114.408117, 36.224699], + [114.417356, 36.205868], + [114.466015, 36.197658], + [114.480181, 36.177855], + [114.533152, 36.171575], + [114.586739, 36.141133], + [114.588587, 36.118414], + [114.640326, 36.137266], + [114.720398, 36.140166], + [114.734564, 36.15563], + [114.771521, 36.124699], + [114.857752, 36.127599], + [114.858368, 36.144516], + [114.912571, 36.140649], + [114.926737, 36.089403], + [114.914419, 36.052155], + [114.998186, 36.069572], + [115.04623, 36.112613], + [115.048693, 36.161912], + [115.06286, 36.178338], + [115.104744, 36.172058], + [115.12507, 36.209731], + [115.1842, 36.193312], + [115.201446, 36.210214], + [115.201446, 36.210214], + [115.202678, 36.209248], + [115.202678, 36.209248], + [115.202678, 36.208765], + [115.202678, 36.208765], + [115.242098, 36.19138], + [115.279055, 36.13775], + [115.30246, 36.127599], + [115.312931, 36.088436], + [115.365902, 36.099074], + [115.376989, 36.128083], + [115.450902, 36.152248], + [115.465068, 36.170125], + [115.483547, 36.148865], + [115.474923, 36.248352], + [115.466916, 36.258969], + [115.466916, 36.258969], + [115.462605, 36.276339], + [115.417025, 36.292742], + [115.423185, 36.32216], + [115.366518, 36.30914], + [115.368982, 36.342409], + [115.340033, 36.398307], + [115.297533, 36.413239], + [115.317243, 36.454166], + [115.291374, 36.460423], + [115.272895, 36.497476], + [115.33141, 36.550378], + [115.355431, 36.627262], + [115.365902, 36.621979], + [115.420105, 36.686795], + [115.451518, 36.702151], + [115.479851, 36.760187], + [115.524815, 36.763543], + [115.683727, 36.808117], + [115.71206, 36.883308], + [115.75764, 36.902453], + [115.79706, 36.968945], + [115.776734, 36.992848], + [115.85619, 37.060694], + [115.888219, 37.112254], + [115.879596, 37.150901], + [115.91224, 37.177132], + [115.909777, 37.20669], + [115.969523, 37.239572], + [115.975682, 37.337179], + [116.024341, 37.360015], + [116.085935, 37.373809], + [116.106261, 37.368577], + [116.169087, 37.384271], + [116.193109, 37.365723], + [116.236224, 37.361442], + [116.2855, 37.404241], + [116.226369, 37.428007], + [116.243, 37.447965], + [116.224522, 37.479791], + [116.240536, 37.489764], + [116.240536, 37.489764], + [116.27626, 37.466967], + [116.290427, 37.484065], + [116.278724, 37.524895], + [116.295355, 37.554316], + [116.336007, 37.581355], + [116.36742, 37.566177], + [116.379738, 37.522047], + [116.38097, 37.522522], + [116.379738, 37.522047], + [116.38097, 37.522522], + [116.433941, 37.473142], + [116.448108, 37.503059], + [116.4826, 37.521573], + [116.575607, 37.610754], + [116.604556, 37.624975], + [116.66307, 37.686096], + [116.679085, 37.728708], + [116.724664, 37.744327], + [116.753613, 37.77035], + [116.753613, 37.793054], + [116.804736, 37.848837], + [116.837997, 37.835132], + [116.919301, 37.846002], + [117.027091, 37.832296], + [117.074518, 37.848837], + [117.150278, 37.839385], + [117.185387, 37.849783], + [117.271618, 37.839858], + [117.320278, 37.861596], + [117.400966, 37.844584], + [117.438538, 37.854035], + [117.481038, 37.914967], + [117.513067, 37.94329], + [117.524154, 37.989527], + [117.557414, 38.046105], + [117.557414, 38.046105], + [117.586979, 38.071551], + [117.704624, 38.076262], + [117.746508, 38.12524], + [117.771145, 38.134655], + [117.766834, 38.158658], + [117.789007, 38.180772], + [117.808718, 38.22827], + [117.848754, 38.255062], + [117.895565, 38.301572], + [117.948536, 38.346644], + [117.957775, 38.376208], + [117.937449, 38.387936], + [117.84629, 38.368232], + [117.781, 38.373862], + [117.730493, 38.424985], + [117.72495, 38.457328], + [117.678754, 38.477008], + [117.644878, 38.52759], + [117.68553, 38.539293], + [117.638102, 38.54491], + [117.639334, 38.626776], + [117.55803, 38.613683], + [117.47919, 38.616489], + [117.432379, 38.601524], + [117.368937, 38.564566], + [117.25314, 38.556143], + [117.238358, 38.580943], + [117.258684, 38.608072], + [117.258684, 38.608072], + [117.213104, 38.639866], + [117.213104, 38.639866], + [117.183539, 38.61836], + [117.183539, 38.61836], + [117.150894, 38.617892], + [117.109626, 38.584685], + [117.070822, 38.608072], + [117.055424, 38.639398], + [117.068358, 38.680522], + [117.038793, 38.688464], + [116.95133, 38.689398], + [116.948866, 38.689398], + [116.950714, 38.689398], + [116.95133, 38.689398], + [116.950714, 38.689398], + [116.948866, 38.689398], + [116.877417, 38.680522], + [116.858939, 38.741231], + [116.794265, 38.744498], + [116.794265, 38.744498], + [116.746222, 38.754299], + [116.737599, 38.784629], + [116.75115, 38.831264], + [116.723432, 38.852706], + [116.722201, 38.896968], + [116.708034, 38.931892], + [116.72836, 38.975174], + [116.754845, 39.003084], + [116.754229, 39.034701], + [116.754229, 39.034701], + [116.783179, 39.05097], + [116.783179, 39.05097], + [116.812744, 39.05097], + [116.812744, 39.05097], + [116.871874, 39.054688], + [116.912526, 39.110898], + [116.91191, 39.111362], + [116.91191, 39.111362], + [116.912526, 39.110898], + [116.909446, 39.150822], + [116.870026, 39.153607], + [116.855859, 39.215766], + [116.881729, 39.225966], + [116.881729, 39.225966], + [116.87249, 39.291304], + [116.889736, 39.338068], + [116.870642, 39.357506], + [116.829374, 39.338994], + [116.818287, 39.3737], + [116.840461, 39.378326], + [116.839845, 39.413474], + [116.876185, 39.43474], + [116.832454, 39.435664], + [116.785026, 39.465702], + [116.820751, 39.482332], + [116.819519, 39.528507], + [116.78749, 39.554352], + [116.808432, 39.576497], + [116.812128, 39.615695], + [116.79057, 39.595868], + [116.748686, 39.619844], + [116.709266, 39.618], + [116.726512, 39.595407], + [116.726512, 39.595407], + [116.724048, 39.59264], + [116.723432, 39.59264], + [116.724048, 39.59264], + [116.723432, 39.59264], + [116.664918, 39.605552], + [116.620571, 39.601863], + [116.592237, 39.621227], + [116.592237, 39.621227], + [116.524484, 39.596329], + [116.50847, 39.551122], + [116.473361, 39.552968], + [116.478289, 39.535431], + [116.437637, 39.526661], + [116.443796, 39.510041], + [116.401912, 39.528046], + [116.411767, 39.482794], + [116.444412, 39.482332], + [116.454883, 39.453226], + [116.434557, 39.442597], + [116.361876, 39.455074], + [116.361876, 39.455074], + [116.337854, 39.455536], + [116.307057, 39.488337], + [116.257782, 39.500344], + [116.240536, 39.564041], + [116.198652, 39.589412], + [116.151841, 39.583416], + [116.130283, 39.567732], + [116.09887, 39.575113], + [116.036044, 39.571884], + [116.026189, 39.587567], + [115.995392, 39.576958], + [115.978146, 39.595868], + [115.957204, 39.560812], + [115.910393, 39.600479], + [115.910393, 39.600479], + [115.91532, 39.582955], + [115.91532, 39.582955], + [115.867893, 39.546507], + [115.867893, 39.546507], + [115.828473, 39.541431], + [115.821081, 39.522968], + [115.821081, 39.522968], + [115.806299, 39.510041], + [115.806299, 39.510041], + [115.752712, 39.515581], + [115.738545, 39.539585], + [115.738545, 39.540046], + [115.738545, 39.539585], + [115.738545, 39.540046], + [115.724995, 39.5442], + [115.724995, 39.5442], + [115.722531, 39.543738], + [115.721299, 39.543738], + [115.722531, 39.543738], + [115.722531, 39.5442], + [115.721299, 39.543738], + [115.722531, 39.5442], + [115.720683, 39.551122], + [115.720683, 39.551122], + [115.718835, 39.553891], + [115.718835, 39.553891], + [115.716988, 39.56035], + [115.716988, 39.56035], + [115.699125, 39.570039], + [115.699125, 39.570039], + [115.698509, 39.577881], + [115.698509, 39.577881], + [115.667712, 39.615234], + [115.633836, 39.599557], + [115.633836, 39.599557], + [115.587024, 39.589873], + [115.545756, 39.618922], + [115.518039, 39.597252], + [115.522351, 39.640124], + [115.478619, 39.650723], + [115.478619, 39.650723], + [115.491554, 39.670074], + [115.486626, 39.741899], + [115.439815, 39.752022], + [115.443511, 39.785601], + [115.483547, 39.798477], + [115.483547, 39.798477], + [115.50572, 39.784222], + [115.552532, 39.794799], + [115.567314, 39.816407], + [115.514344, 39.837549], + [115.526046, 39.87568], + [115.515575, 39.892212], + [115.515575, 39.892212], + [115.522967, 39.899099], + [115.481083, 39.935819], + [115.426264, 39.950502], + [115.428728, 39.984443], + [115.450286, 39.992697], + [115.454597, 40.029825], + [115.485394, 40.040364], + [115.527278, 40.076092], + [115.59072, 40.096239], + [115.599959, 40.119583], + [115.75456, 40.145663], + [115.75456, 40.145663], + [115.773654, 40.176307], + [115.806299, 40.15344], + [115.847567, 40.147036], + [115.855574, 40.188652], + [115.870356, 40.185909], + [115.89869, 40.234354], + [115.968907, 40.264045], + [115.95166, 40.281852], + [115.917784, 40.354405], + [115.864197, 40.359422], + [115.771806, 40.443734], + [115.781045, 40.49336], + [115.736082, 40.503372], + [115.755176, 40.540221], + [115.784741, 40.55841], + [115.819849, 40.55932], + [115.827857, 40.587504], + [115.885139, 40.595229], + [115.907929, 40.617493], + [115.971986, 40.6025], + [115.982457, 40.578868], + [116.005247, 40.583868], + [116.09887, 40.630665], + [116.133979, 40.666536], + [116.162928, 40.662451], + [116.171551, 40.695582], + [116.204812, 40.740035], + [116.22021, 40.744115], + [116.247311, 40.791707], + [116.273181, 40.762703], + [116.311369, 40.754996], + [116.316912, 40.772221], + [116.453651, 40.765876], + [116.46597, 40.774487], + [116.438253, 40.81934], + [116.334159, 40.90443], + [116.339702, 40.929303], + [116.370499, 40.94377], + [116.398216, 40.90624], + [116.477057, 40.899907], + [116.447492, 40.953715], + [116.455499, 40.980828], + [116.519557, 40.98128], + [116.519557, 40.98128], + [116.5676, 40.992574], + [116.598397, 40.974503], + [116.623034, 41.021026], + [116.615643, 41.053076], + [116.647672, 41.059394], + [116.688324, 41.044501], + [116.698795, 41.021477], + [116.677853, 40.970888], + [116.722201, 40.927495], + [116.713577, 40.909858], + [116.759773, 40.889954], + [116.81336, 40.848319], + [116.848468, 40.839264], + [116.924229, 40.773581], + [116.926692, 40.745022], + [116.964881, 40.709647], + [117.012308, 40.693767], + [117.11209, 40.707379], + [117.117018, 40.70012], + [117.208177, 40.694675], + [117.278394, 40.664267], + [117.319662, 40.657911], + [117.342451, 40.673799], + [117.408973, 40.686961], + [117.493973, 40.675161], + [117.514914, 40.660181], + [117.501364, 40.636569], + [117.467487, 40.649738], + [117.467487, 40.649738] + ] + ], + [ + [ + [117.210024, 40.082045], + [117.204481, 40.069681], + [117.159517, 40.077008], + [117.140423, 40.064185], + [117.105315, 40.074261], + [117.105315, 40.074261], + [117.051728, 40.059605], + [117.025243, 40.030283], + [116.945171, 40.04128], + [116.927924, 40.055024], + [116.867562, 40.041739], + [116.831222, 40.051359], + [116.820135, 40.02845], + [116.781331, 40.034866], + [116.757925, 39.967934], + [116.782563, 39.947749], + [116.78441, 39.891294], + [116.812128, 39.889916], + [116.865714, 39.843982], + [116.907598, 39.832494], + [116.918069, 39.84628], + [116.949482, 39.778703], + [116.902055, 39.763523], + [116.916837, 39.731314], + [116.887272, 39.72533], + [116.889736, 39.687576], + [116.90575, 39.688037], + [116.932236, 39.706456], + [116.932236, 39.706456], + [116.944555, 39.695405], + [116.944555, 39.695405], + [116.948866, 39.680668], + [116.948866, 39.680668], + [116.964265, 39.64335], + [116.983359, 39.638742], + [116.983359, 39.638742], + [117.016004, 39.653949], + [117.10901, 39.625375], + [117.10901, 39.625375], + [117.152742, 39.623532], + [117.177996, 39.645194], + [117.165061, 39.718886], + [117.165061, 39.718886], + [117.161981, 39.748801], + [117.205713, 39.763984], + [117.15767, 39.796638], + [117.156438, 39.817326], + [117.192162, 39.832953], + [117.251908, 39.834332], + [117.247597, 39.860981], + [117.227887, 39.852712], + [117.162597, 39.876598], + [117.162597, 39.876598], + [117.150894, 39.944996], + [117.198322, 39.992697], + [117.192162, 40.066475], + [117.210024, 40.082045] + ] + ], + [ + [ + [117.784696, 39.376938], + [117.765602, 39.400527], + [117.699696, 39.407463], + [117.673211, 39.386652], + [117.668899, 39.412087], + [117.614081, 39.407001], + [117.601146, 39.419485], + [117.570965, 39.404689], + [117.521074, 39.357043], + [117.536472, 39.338068], + [117.594987, 39.349176], + [117.669515, 39.322792], + [117.670747, 39.357969], + [117.74466, 39.354729], + [117.784696, 39.376938] + ] + ], + [ + [ + [118.869365, 39.142932], + [118.82009, 39.108576], + [118.857662, 39.098824], + [118.869365, 39.142932] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 140000, + "name": "山西省", + "center": [112.549248, 37.857014], + "centroid": [112.304436, 37.618179], + "childrenNum": 11, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 3, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [110.379257, 34.600612], + [110.424837, 34.588295], + [110.488279, 34.610956], + [110.533242, 34.583368], + [110.610851, 34.607508], + [110.710017, 34.605045], + [110.749437, 34.65232], + [110.791937, 34.649858], + [110.824582, 34.615881], + [110.883712, 34.64395], + [110.903422, 34.669056], + [110.920052, 34.730068], + [110.976103, 34.706456], + [111.035233, 34.740887], + [111.118385, 34.756623], + [111.148566, 34.807742], + [111.232949, 34.789559], + [111.255123, 34.819535], + [111.29208, 34.806759], + [111.345666, 34.831816], + [111.389398, 34.815113], + [111.439289, 34.838202], + [111.502731, 34.829851], + [111.543999, 34.853428], + [111.570484, 34.843114], + [111.592042, 34.881416], + [111.617911, 34.894671], + [111.646861, 34.938836], + [111.681969, 34.9511], + [111.664107, 34.984449], + [111.740483, 35.00455], + [111.807005, 35.032977], + [111.810084, 35.062374], + [111.933272, 35.083435], + [111.97762, 35.067272], + [112.018888, 35.068742], + [112.039214, 35.045717], + [112.062004, 35.056005], + [112.05646, 35.098615], + [112.066315, 35.153437], + [112.03983, 35.194039], + [112.078634, 35.219467], + [112.058924, 35.280069], + [112.13838, 35.271275], + [112.21722, 35.253195], + [112.242474, 35.234622], + [112.304684, 35.251728], + [112.288053, 35.219956], + [112.36751, 35.219956], + [112.390915, 35.239021], + [112.513487, 35.218489], + [112.637291, 35.225822], + [112.628052, 35.263457], + [112.720443, 35.206265], + [112.772798, 35.207732], + [112.822073, 35.258082], + [112.884283, 35.243909], + [112.934174, 35.262968], + [112.936022, 35.284466], + [112.992072, 35.29619], + [112.985913, 35.33965], + [112.996384, 35.362104], + [113.067217, 35.353806], + [113.126347, 35.332327], + [113.149137, 35.350878], + [113.165151, 35.412845], + [113.185477, 35.409431], + [113.189789, 35.44893], + [113.243375, 35.449418], + [113.304353, 35.426989], + [113.31236, 35.481101], + [113.348085, 35.468429], + [113.391817, 35.506925], + [113.439244, 35.507412], + [113.49899, 35.532254], + [113.513773, 35.57364], + [113.55812, 35.621816], + [113.547649, 35.656835], + [113.578446, 35.633491], + [113.625258, 35.632518], + [113.622794, 35.674825], + [113.592613, 35.691838], + [113.587685, 35.736542], + [113.604932, 35.797727], + [113.582758, 35.818111], + [113.660982, 35.837035], + [113.637576, 35.870019], + [113.654207, 35.931586], + [113.648663, 35.994073], + [113.678844, 35.985841], + [113.694859, 36.026991], + [113.660366, 36.034735], + [113.68562, 36.056026], + [113.671453, 36.115514], + [113.655439, 36.125182], + [113.712721, 36.129533], + [113.705946, 36.148865], + [113.651127, 36.174473], + [113.697939, 36.181719], + [113.681924, 36.216491], + [113.716417, 36.262347], + [113.712105, 36.303353], + [113.736127, 36.324571], + [113.731199, 36.363135], + [113.708409, 36.423352], + [113.670221, 36.425278], + [113.635729, 36.451277], + [113.587069, 36.460904], + [113.554425, 36.494589], + [113.559968, 36.528741], + [113.588917, 36.547974], + [113.569823, 36.585947], + [113.539642, 36.594116], + [113.54457, 36.62342], + [113.486671, 36.635427], + [113.476816, 36.655114], + [113.506997, 36.705029], + [113.465113, 36.707908], + [113.499606, 36.740527], + [113.535946, 36.732373], + [113.549497, 36.752515], + [113.600004, 36.752995], + [113.680692, 36.789907], + [113.676381, 36.855539], + [113.696707, 36.882351], + [113.731815, 36.878521], + [113.731815, 36.858891], + [113.773083, 36.85506], + [113.792793, 36.894796], + [113.76138, 36.956034], + [113.791561, 36.98759], + [113.771851, 37.016745], + [113.788482, 37.059739], + [113.758301, 37.075497], + [113.773699, 37.107004], + [113.773083, 37.151855], + [113.832213, 37.167594], + [113.853155, 37.215269], + [113.886416, 37.239095], + [113.90243, 37.310052], + [113.962792, 37.355734], + [113.973879, 37.40329], + [114.014531, 37.42468], + [114.036705, 37.494037], + [114.118625, 37.59084], + [114.115545, 37.619761], + [114.139567, 37.675676], + [114.12848, 37.698409], + [114.068118, 37.721608], + [113.993589, 37.706932], + [113.996669, 37.730128], + [114.044712, 37.761834], + [114.006524, 37.813386], + [113.976959, 37.816696], + [113.959097, 37.906468], + [113.936307, 37.922993], + [113.901198, 37.984811], + [113.872249, 37.990471], + [113.876561, 38.055059], + [113.811271, 38.117707], + [113.831597, 38.16854], + [113.797105, 38.162894], + [113.720728, 38.174656], + [113.711489, 38.213695], + [113.678844, 38.20523], + [113.64312, 38.232031], + [113.598772, 38.22733], + [113.570439, 38.237202], + [113.54457, 38.270569], + [113.557504, 38.343359], + [113.525475, 38.383245], + [113.537794, 38.417952], + [113.583374, 38.459671], + [113.546417, 38.492936], + [113.561816, 38.558483], + [113.603084, 38.587024], + [113.612939, 38.645942], + [113.70225, 38.651551], + [113.720728, 38.713218], + [113.775547, 38.709949], + [113.802648, 38.763166], + [113.839605, 38.7585], + [113.836525, 38.795824], + [113.855619, 38.828933], + [113.795257, 38.860628], + [113.776163, 38.885788], + [113.76754, 38.959819], + [113.776779, 38.986804], + [113.80696, 38.989595], + [113.898119, 39.067699], + [113.930148, 39.063517], + [113.961561, 39.100681], + [113.994821, 39.095572], + [114.006524, 39.122971], + [114.050872, 39.135969], + [114.064422, 39.094179], + [114.082901, 39.09325], + [114.082901, 39.09325], + [114.10877, 39.052364], + [114.157429, 39.061194], + [114.180835, 39.049111], + [114.252284, 39.073739], + [114.345907, 39.075133], + [114.369928, 39.107648], + [114.360689, 39.134112], + [114.388406, 39.176807], + [114.443841, 39.174023], + [114.47587, 39.21623], + [114.416124, 39.242654], + [114.437066, 39.259337], + [114.430906, 39.307513], + [114.466631, 39.329736], + [114.469095, 39.400989], + [114.496812, 39.438437], + [114.501739, 39.476789], + [114.532536, 39.486027], + [114.568877, 39.573729], + [114.51529, 39.564964], + [114.49558, 39.608318], + [114.431522, 39.613851], + [114.408117, 39.652106], + [114.409964, 39.761683], + [114.41674, 39.775943], + [114.390254, 39.819165], + [114.406885, 39.833413], + [114.395182, 39.867412], + [114.285545, 39.858225], + [114.286776, 39.871087], + [114.215943, 39.8619], + [114.204241, 39.885324], + [114.229494, 39.899558], + [114.212248, 39.918839], + [114.17406, 39.897722], + [114.067502, 39.922511], + [114.047176, 39.916085], + [114.028082, 39.959218], + [114.029314, 39.985819], + [113.910438, 40.015618], + [113.959097, 40.033491], + [113.989278, 40.11226], + [114.018227, 40.103563], + [114.045944, 40.056856], + [114.086596, 40.071513], + [114.101995, 40.099901], + [114.073046, 40.168533], + [114.073046, 40.168533], + [114.097683, 40.193681], + [114.135871, 40.175392], + [114.180219, 40.191395], + [114.235654, 40.198252], + [114.255364, 40.236182], + [114.292936, 40.230242], + [114.362537, 40.249886], + [114.406269, 40.246232], + [114.46971, 40.268155], + [114.510978, 40.302851], + [114.530688, 40.345283], + [114.481413, 40.34802], + [114.438914, 40.371733], + [114.390254, 40.351213], + [114.381015, 40.36307], + [114.31203, 40.372645], + [114.286161, 40.425057], + [114.299711, 40.44009], + [114.267066, 40.474242], + [114.282465, 40.494725], + [114.293552, 40.55159], + [114.273842, 40.552954], + [114.283081, 40.590685], + [114.236269, 40.607043], + [114.183299, 40.67153], + [114.162357, 40.71373], + [114.134639, 40.737314], + [114.084748, 40.729605], + [114.063806, 40.706925], + [114.07243, 40.679246], + [114.041633, 40.608861], + [114.076741, 40.575686], + [114.080437, 40.547952], + [114.061959, 40.52885], + [114.011452, 40.515657], + [113.948626, 40.514747], + [113.890112, 40.466503], + [113.850691, 40.460583], + [113.794641, 40.517932], + [113.763228, 40.473787], + [113.688699, 40.448288], + [113.559968, 40.348476], + [113.500222, 40.334335], + [113.387505, 40.319279], + [113.316672, 40.319736], + [113.27602, 40.388601], + [113.251382, 40.413211], + [113.083231, 40.374925], + [113.03334, 40.368997], + [112.898449, 40.329317], + [112.848558, 40.206937], + [112.744464, 40.167161], + [112.712436, 40.178593], + [112.6299, 40.235725], + [112.511639, 40.269068], + [112.456205, 40.300112], + [112.418017, 40.295091], + [112.349031, 40.257194], + [112.310227, 40.256281], + [112.299756, 40.21105], + [112.232619, 40.169905], + [112.232003, 40.133311], + [112.183344, 40.083877], + [112.182112, 40.061437], + [112.142076, 40.027076], + [112.133453, 40.001866], + [112.07617, 39.919298], + [112.042294, 39.886243], + [112.012729, 39.827438], + [111.970229, 39.796638], + [111.959758, 39.692642], + [111.925265, 39.66731], + [111.9382, 39.623071], + [111.87907, 39.606013], + [111.842729, 39.620305], + [111.783599, 39.58895], + [111.722621, 39.606013], + [111.659179, 39.641507], + [111.625303, 39.633672], + [111.525521, 39.662242], + [111.497187, 39.661781], + [111.445448, 39.640124], + [111.460847, 39.606935], + [111.441137, 39.59679], + [111.422043, 39.539123], + [111.431282, 39.508656], + [111.372152, 39.479099], + [111.358601, 39.432428], + [111.337043, 39.420872], + [111.171971, 39.423183], + [111.143022, 39.407926], + [111.125776, 39.366297], + [111.159037, 39.362596], + [111.155341, 39.338531], + [111.186138, 39.35149], + [111.179363, 39.326959], + [111.202152, 39.305197], + [111.247732, 39.302419], + [111.213239, 39.257021], + [111.219399, 39.244044], + [111.163348, 39.152678], + [111.173819, 39.135041], + [111.147334, 39.100681], + [111.138095, 39.064447], + [111.094363, 39.030053], + [111.038313, 39.020289], + [110.998276, 38.998433], + [110.980414, 38.970056], + [111.009979, 38.932823], + [111.016755, 38.889981], + [110.995813, 38.868084], + [111.009363, 38.847579], + [110.965016, 38.755699], + [110.915125, 38.704345], + [110.916357, 38.673981], + [110.880632, 38.626776], + [110.898494, 38.587024], + [110.920052, 38.581878], + [110.907733, 38.521035], + [110.870777, 38.510265], + [110.874473, 38.453579], + [110.840596, 38.439986], + [110.796864, 38.453579], + [110.77777, 38.440924], + [110.746973, 38.366355], + [110.701394, 38.353215], + [110.661358, 38.308617], + [110.601612, 38.308147], + [110.57759, 38.297345], + [110.565887, 38.215105], + [110.528315, 38.211814], + [110.509221, 38.192061], + [110.519692, 38.130889], + [110.501829, 38.097929], + [110.507989, 38.013107], + [110.528315, 37.990471], + [110.522771, 37.955088], + [110.59422, 37.922049], + [110.680452, 37.790216], + [110.735886, 37.77035], + [110.750669, 37.736281], + [110.716792, 37.728708], + [110.706321, 37.705511], + [110.775306, 37.680886], + [110.793169, 37.650567], + [110.763604, 37.639668], + [110.771611, 37.594634], + [110.795017, 37.558586], + [110.770995, 37.538184], + [110.759292, 37.474567], + [110.740198, 37.44939], + [110.644111, 37.435135], + [110.630561, 37.372858], + [110.641648, 37.360015], + [110.695234, 37.34955], + [110.678604, 37.317668], + [110.690307, 37.287201], + [110.661974, 37.281963], + [110.651503, 37.256722], + [110.590525, 37.187145], + [110.53509, 37.138021], + [110.535706, 37.115118], + [110.49567, 37.086956], + [110.460561, 37.044932], + [110.417446, 37.027257], + [110.426685, 37.008621], + [110.382953, 37.022001], + [110.381721, 37.002408], + [110.424221, 36.963685], + [110.408823, 36.892403], + [110.376178, 36.882351], + [110.424221, 36.855539], + [110.406975, 36.824886], + [110.423605, 36.818179], + [110.407591, 36.776007], + [110.447011, 36.737649], + [110.438388, 36.685835], + [110.402663, 36.697352], + [110.394656, 36.676716], + [110.426685, 36.657514], + [110.447627, 36.621018], + [110.496902, 36.582102], + [110.488895, 36.556628], + [110.503677, 36.488335], + [110.47288, 36.453203], + [110.489511, 36.430094], + [110.487047, 36.393972], + [110.459946, 36.327946], + [110.474112, 36.306729], + [110.474112, 36.248352], + [110.45625, 36.22663], + [110.447011, 36.164328], + [110.467953, 36.074893], + [110.491974, 36.034735], + [110.49259, 35.994073], + [110.516612, 35.971796], + [110.502445, 35.947575], + [110.516612, 35.918501], + [110.511684, 35.879718], + [110.549257, 35.877778], + [110.550489, 35.838005], + [110.571431, 35.800639], + [110.57759, 35.701559], + [110.609619, 35.632031], + [110.589293, 35.602355], + [110.567735, 35.539559], + [110.531394, 35.511309], + [110.477808, 35.413821], + [110.45009, 35.327933], + [110.374946, 35.251728], + [110.378642, 35.210666], + [110.364475, 35.197952], + [110.373714, 35.134351], + [110.320743, 35.00504], + [110.262229, 34.944233], + [110.230816, 34.880925], + [110.246831, 34.789068], + [110.243135, 34.725641], + [110.229584, 34.692679], + [110.269004, 34.629671], + [110.29549, 34.610956], + [110.379257, 34.600612] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 150000, + "name": "内蒙古自治区", + "center": [111.670801, 40.818311], + "centroid": [114.077429, 44.331087], + "childrenNum": 12, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 4, + "acroutes": [100000] + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [97.172903, 42.795257], + [97.371235, 42.457076], + [97.500582, 42.243894], + [97.653335, 41.986856], + [97.84674, 41.656379], + [97.613915, 41.477276], + [97.629314, 41.440498], + [97.903407, 41.168057], + [97.971776, 41.09774], + [98.142391, 41.001607], + [98.184891, 40.988056], + [98.25018, 40.93925], + [98.333332, 40.918903], + [98.344419, 40.568413], + [98.627751, 40.677884], + [98.569853, 40.746836], + [98.668403, 40.773128], + [98.689345, 40.691952], + [98.72199, 40.657911], + [98.762642, 40.639748], + [98.802678, 40.607043], + [98.80699, 40.660181], + [98.790975, 40.705564], + [98.984996, 40.782644], + [99.041662, 40.693767], + [99.102025, 40.676522], + [99.12543, 40.715091], + [99.172858, 40.747289], + [99.174705, 40.858278], + [99.565827, 40.846961], + [99.673, 40.93292], + [99.985897, 40.909858], + [100.057346, 40.908049], + [100.107853, 40.875475], + [100.224882, 40.727337], + [100.237201, 40.716905], + [100.242744, 40.618855], + [100.169447, 40.541131], + [100.169447, 40.277743], + [100.007455, 40.20008], + [99.955716, 40.150695], + [99.927383, 40.063727], + [99.841152, 40.013326], + [99.751225, 40.006909], + [99.714268, 39.972061], + [99.533182, 39.891753], + [99.491298, 39.884406], + [99.459885, 39.898181], + [99.440791, 39.885783], + [99.469124, 39.875221], + [99.672384, 39.888079], + [99.822058, 39.860063], + [99.904593, 39.785601], + [99.958796, 39.769504], + [100.040716, 39.757083], + [100.128179, 39.702312], + [100.250135, 39.685274], + [100.314193, 39.606935], + [100.301258, 39.572345], + [100.326512, 39.509118], + [100.44354, 39.485565], + [100.500823, 39.481408], + [100.498975, 39.400527], + [100.606764, 39.387577], + [100.707778, 39.404689], + [100.842053, 39.405614], + [100.842669, 39.199999], + [100.864227, 39.106719], + [100.829118, 39.075133], + [100.835278, 39.025869], + [100.875314, 39.002619], + [100.901799, 39.030053], + [100.961545, 39.005874], + [100.969553, 38.946788], + [101.117378, 38.975174], + [101.228863, 39.020754], + [101.198682, 38.943064], + [101.237486, 38.907214], + [101.24303, 38.860628], + [101.33542, 38.847113], + [101.34158, 38.822406], + [101.307087, 38.80282], + [101.331109, 38.777164], + [101.412413, 38.764099], + [101.562702, 38.713218], + [101.601506, 38.65529], + [101.672955, 38.6908], + [101.777049, 38.66043], + [101.873751, 38.733761], + [101.941505, 38.808883], + [102.075164, 38.891378], + [102.045599, 38.904885], + [101.955055, 38.985874], + [101.926106, 39.000758], + [101.833715, 39.08907], + [101.902701, 39.111827], + [102.012338, 39.127149], + [102.050526, 39.141075], + [102.276576, 39.188868], + [102.3548, 39.231993], + [102.45335, 39.255167], + [102.579002, 39.183301], + [102.616574, 39.171703], + [102.883892, 39.120649], + [103.007696, 39.099753], + [103.133347, 39.192579], + [103.188166, 39.215302], + [103.259615, 39.263971], + [103.344615, 39.331588], + [103.428998, 39.353341], + [103.595302, 39.386652], + [103.728961, 39.430117], + [103.85338, 39.461543], + [103.955626, 39.456923], + [104.089901, 39.419947], + [104.073271, 39.351953], + [104.047401, 39.297788], + [104.171205, 39.160567], + [104.207546, 39.083495], + [104.190915, 39.042139], + [104.196459, 38.9882], + [104.173053, 38.94446], + [104.044322, 38.895105], + [104.011677, 38.85923], + [103.85954, 38.64454], + [103.416063, 38.404821], + [103.465339, 38.353215], + [103.507838, 38.280905], + [103.53494, 38.156776], + [103.368636, 38.08898], + [103.362477, 38.037621], + [103.40744, 37.860651], + [103.627947, 37.797783], + [103.683381, 37.777919], + [103.841062, 37.64725], + [103.874938, 37.604117], + [103.935916, 37.572818], + [104.089285, 37.465067], + [104.183524, 37.406618], + [104.237727, 37.411847], + [104.287002, 37.428007], + [104.322726, 37.44844], + [104.407726, 37.464592], + [104.419429, 37.511604], + [104.433595, 37.515402], + [104.623305, 37.522522], + [104.805007, 37.539133], + [104.866601, 37.566651], + [105.027977, 37.580881], + [105.111128, 37.633981], + [105.187505, 37.657674], + [105.221998, 37.677097], + [105.315004, 37.702197], + [105.4037, 37.710246], + [105.467141, 37.695094], + [105.598952, 37.699356], + [105.616199, 37.722555], + [105.622358, 37.777919], + [105.677177, 37.771769], + [105.760944, 37.799674], + [105.80406, 37.862068], + [105.799749, 37.939986], + [105.840401, 38.004147], + [105.780655, 38.084741], + [105.76772, 38.121474], + [105.775111, 38.186887], + [105.802828, 38.220277], + [105.842248, 38.240962], + [105.86627, 38.296406], + [105.821307, 38.366824], + [105.835473, 38.387467], + [105.827466, 38.432486], + [105.850872, 38.443736], + [105.836705, 38.476071], + [105.863806, 38.53508], + [105.856415, 38.569714], + [105.874277, 38.593105], + [105.852719, 38.641735], + [105.894603, 38.696405], + [105.88598, 38.716953], + [105.908154, 38.737496], + [105.909386, 38.791159], + [105.992538, 38.857366], + [105.97098, 38.909077], + [106.021487, 38.953769], + [106.060907, 38.96866], + [106.087392, 39.006339], + [106.078153, 39.026333], + [106.096631, 39.084889], + [106.145907, 39.153142], + [106.170544, 39.163352], + [106.192718, 39.142932], + [106.251232, 39.131327], + [106.285109, 39.146181], + [106.29558, 39.167992], + [106.280181, 39.262118], + [106.402753, 39.291767], + [106.511774, 39.272311], + [106.525325, 39.308439], + [106.556122, 39.322329], + [106.602318, 39.37555], + [106.643586, 39.357969], + [106.683622, 39.357506], + [106.751375, 39.381564], + [106.781556, 39.371849], + [106.806809, 39.318625], + [106.806193, 39.277407], + [106.790795, 39.241263], + [106.795723, 39.214375], + [106.825288, 39.19397], + [106.859164, 39.107648], + [106.878874, 39.091392], + [106.933693, 39.076527], + [106.96757, 39.054688], + [106.971881, 39.026333], + [106.954019, 38.941202], + [106.837606, 38.847579], + [106.756302, 38.748699], + [106.709491, 38.718821], + [106.66268, 38.601524], + [106.647897, 38.470917], + [106.599854, 38.389812], + [106.482209, 38.319417], + [106.555506, 38.263521], + [106.627571, 38.232501], + [106.654672, 38.22921], + [106.737824, 38.197706], + [106.779092, 38.171833], + [106.858548, 38.156306], + [106.942316, 38.132302], + [107.010069, 38.120532], + [107.051337, 38.122886], + [107.071047, 38.138892], + [107.119091, 38.134185], + [107.138801, 38.161011], + [107.19054, 38.153953], + [107.240431, 38.111586], + [107.33159, 38.086625], + [107.3938, 38.014993], + [107.440611, 37.995659], + [107.411662, 37.948009], + [107.448618, 37.933378], + [107.49235, 37.944706], + [107.560719, 37.893717], + [107.65003, 37.86443], + [107.684523, 37.888522], + [107.732566, 37.84931], + [107.842819, 37.828987], + [107.884703, 37.808186], + [107.982022, 37.787378], + [107.993109, 37.735335], + [108.025753, 37.696041], + [108.012819, 37.66857], + [108.025137, 37.649619], + [108.055318, 37.652462], + [108.134159, 37.622131], + [108.193905, 37.638246], + [108.205608, 37.655779], + [108.24626, 37.665728], + [108.293071, 37.656726], + [108.301078, 37.640616], + [108.422418, 37.648672], + [108.485244, 37.678044], + [108.532671, 37.690832], + [108.628142, 37.651988], + [108.699591, 37.669518], + [108.720533, 37.683728], + [108.777815, 37.683728], + [108.791982, 37.700303], + [108.784591, 37.764673], + [108.799989, 37.784068], + [108.791982, 37.872934], + [108.798141, 37.93385], + [108.82709, 37.989056], + [108.797525, 38.04799], + [108.830786, 38.049875], + [108.883141, 38.01405], + [108.893612, 37.978207], + [108.93488, 37.922521], + [108.9743, 37.931962], + [108.982923, 37.964053], + [109.018648, 37.971602], + [109.037742, 38.021593], + [109.06977, 38.023008], + [109.050676, 38.055059], + [109.069155, 38.091336], + [108.964445, 38.154894], + [108.938575, 38.207582], + [108.976148, 38.245192], + [108.961981, 38.26493], + [109.007561, 38.359316], + [109.051292, 38.385122], + [109.054372, 38.433892], + [109.128901, 38.480288], + [109.175712, 38.518694], + [109.196654, 38.552867], + [109.276726, 38.623035], + [109.331545, 38.597783], + [109.367269, 38.627711], + [109.329081, 38.66043], + [109.338936, 38.701542], + [109.404226, 38.720689], + [109.444262, 38.782763], + [109.511399, 38.833595], + [109.549587, 38.805618], + [109.624116, 38.85457], + [109.672159, 38.928167], + [109.685094, 38.968195], + [109.665384, 38.981687], + [109.72513, 39.018429], + [109.762086, 39.057476], + [109.793499, 39.074204], + [109.851397, 39.122971], + [109.890818, 39.103932], + [109.92223, 39.107183], + [109.893897, 39.141075], + [109.961035, 39.191651], + [109.871723, 39.243581], + [109.90252, 39.271848], + [109.962267, 39.212056], + [110.041107, 39.21623], + [110.109476, 39.249606], + [110.217881, 39.281113], + [110.184005, 39.355192], + [110.161831, 39.387115], + [110.136577, 39.39174], + [110.12549, 39.432891], + [110.152592, 39.45415], + [110.243751, 39.423645], + [110.257917, 39.407001], + [110.385417, 39.310291], + [110.429764, 39.341308], + [110.434692, 39.381101], + [110.482735, 39.360745], + [110.524003, 39.382952], + [110.559728, 39.351027], + [110.566503, 39.320014], + [110.596684, 39.282966], + [110.626249, 39.266751], + [110.702626, 39.273701], + [110.731575, 39.30705], + [110.73835, 39.348713], + [110.782698, 39.38804], + [110.869545, 39.494341], + [110.891103, 39.509118], + [110.958856, 39.519275], + [111.017371, 39.552045], + [111.101138, 39.559428], + [111.136863, 39.587106], + [111.154725, 39.569116], + [111.148566, 39.531277], + [111.10545, 39.497573], + [111.10545, 39.472631], + [111.058639, 39.447681], + [111.064182, 39.400989], + [111.098059, 39.401914], + [111.087588, 39.376013], + [111.125776, 39.366297], + [111.143022, 39.407926], + [111.171971, 39.423183], + [111.337043, 39.420872], + [111.358601, 39.432428], + [111.372152, 39.479099], + [111.431282, 39.508656], + [111.422043, 39.539123], + [111.441137, 39.59679], + [111.460847, 39.606935], + [111.445448, 39.640124], + [111.497187, 39.661781], + [111.525521, 39.662242], + [111.625303, 39.633672], + [111.659179, 39.641507], + [111.722621, 39.606013], + [111.783599, 39.58895], + [111.842729, 39.620305], + [111.87907, 39.606013], + [111.9382, 39.623071], + [111.925265, 39.66731], + [111.959758, 39.692642], + [111.970229, 39.796638], + [112.012729, 39.827438], + [112.042294, 39.886243], + [112.07617, 39.919298], + [112.133453, 40.001866], + [112.142076, 40.027076], + [112.182112, 40.061437], + [112.183344, 40.083877], + [112.232003, 40.133311], + [112.232619, 40.169905], + [112.299756, 40.21105], + [112.310227, 40.256281], + [112.349031, 40.257194], + [112.418017, 40.295091], + [112.456205, 40.300112], + [112.511639, 40.269068], + [112.6299, 40.235725], + [112.712436, 40.178593], + [112.744464, 40.167161], + [112.848558, 40.206937], + [112.898449, 40.329317], + [113.03334, 40.368997], + [113.083231, 40.374925], + [113.251382, 40.413211], + [113.27602, 40.388601], + [113.316672, 40.319736], + [113.387505, 40.319279], + [113.500222, 40.334335], + [113.559968, 40.348476], + [113.688699, 40.448288], + [113.763228, 40.473787], + [113.794641, 40.517932], + [113.850691, 40.460583], + [113.890112, 40.466503], + [113.948626, 40.514747], + [114.011452, 40.515657], + [114.061959, 40.52885], + [114.080437, 40.547952], + [114.076741, 40.575686], + [114.041633, 40.608861], + [114.07243, 40.679246], + [114.063806, 40.706925], + [114.084748, 40.729605], + [114.134639, 40.737314], + [114.103227, 40.770861], + [114.104458, 40.797597], + [114.080437, 40.790348], + [114.044712, 40.830661], + [114.073661, 40.857372], + [114.055183, 40.867782], + [114.041633, 40.917546], + [114.057647, 40.925234], + [113.994821, 40.938798], + [113.973263, 40.983087], + [113.868554, 41.06887], + [113.819279, 41.09774], + [113.877793, 41.115777], + [113.920293, 41.172112], + [113.960945, 41.171211], + [113.996669, 41.19238], + [114.016379, 41.231999], + [113.992357, 41.269794], + [113.971416, 41.239649], + [113.95109, 41.282837], + [113.914749, 41.294529], + [113.899351, 41.316108], + [113.92522, 41.325546], + [113.94493, 41.392477], + [113.871017, 41.413126], + [113.877793, 41.431076], + [113.919677, 41.454404], + [113.933227, 41.487139], + [113.953553, 41.483553], + [113.976959, 41.505966], + [114.032394, 41.529715], + [114.101379, 41.537779], + [114.230726, 41.513584], + [114.221487, 41.582111], + [114.226414, 41.616572], + [114.259059, 41.623282], + [114.215328, 41.68499], + [114.237501, 41.698843], + [114.206704, 41.7386], + [114.215328, 41.75646], + [114.200545, 41.789934], + [114.282465, 41.863517], + [114.343443, 41.926774], + [114.352066, 41.953484], + [114.419203, 41.942356], + [114.478334, 41.951704], + [114.511594, 41.981962], + [114.467863, 42.025989], + [114.480181, 42.064654], + [114.502355, 42.06732], + [114.510978, 42.110844], + [114.560254, 42.132595], + [114.647717, 42.109512], + [114.675434, 42.12061], + [114.75489, 42.115727], + [114.789383, 42.130819], + [114.79431, 42.149457], + [114.825723, 42.139695], + [114.86268, 42.097967], + [114.860832, 42.054879], + [114.9021, 42.015763], + [114.915035, 41.960605], + [114.923658, 41.871093], + [114.939056, 41.846132], + [114.922426, 41.825175], + [114.868839, 41.813579], + [114.89594, 41.76762], + [114.902716, 41.695715], + [114.895325, 41.636255], + [114.860832, 41.60091], + [115.016049, 41.615229], + [115.056085, 41.602253], + [115.0992, 41.62373], + [115.195287, 41.602253], + [115.20391, 41.571367], + [115.256881, 41.580768], + [115.26612, 41.616124], + [115.290142, 41.622835], + [115.310468, 41.592854], + [115.377605, 41.603148], + [115.345576, 41.635807], + [115.360975, 41.661297], + [115.319091, 41.691693], + [115.346808, 41.712247], + [115.42996, 41.728775], + [115.488474, 41.760924], + [115.519887, 41.76762], + [115.57409, 41.80555], + [115.654162, 41.829189], + [115.688038, 41.867528], + [115.726227, 41.870202], + [115.811226, 41.912525], + [115.834632, 41.93835], + [115.85311, 41.927665], + [115.916552, 41.945027], + [115.954124, 41.874213], + [115.994776, 41.828743], + [116.007095, 41.797966], + [116.007095, 41.79752], + [116.034196, 41.782795], + [116.09887, 41.776547], + [116.129051, 41.805996], + [116.106877, 41.831419], + [116.122892, 41.861734], + [116.194341, 41.861734], + [116.212819, 41.885352], + [116.223906, 41.932562], + [116.298434, 41.96817], + [116.310137, 41.997086], + [116.373579, 42.009983], + [116.414231, 41.982407], + [116.393289, 41.942802], + [116.453651, 41.945917], + [116.4826, 41.975734], + [116.510933, 41.974399], + [116.553433, 41.928555], + [116.597165, 41.935679], + [116.639049, 41.929891], + [116.66923, 41.947698], + [116.727744, 41.951259], + [116.748686, 41.984186], + [116.796113, 41.977958], + [116.879881, 42.018431], + [116.890352, 42.092639], + [116.850316, 42.156556], + [116.825062, 42.155669], + [116.789338, 42.200462], + [116.903287, 42.190708], + [116.918685, 42.229716], + [116.897743, 42.297479], + [116.886656, 42.366496], + [116.910678, 42.394789], + [116.910062, 42.395231], + [116.921765, 42.403628], + [116.936547, 42.410256], + [116.944555, 42.415116], + [116.97104, 42.427486], + [116.974736, 42.426603], + [116.99075, 42.425719], + [117.005533, 42.43367], + [117.009228, 42.44957], + [117.01662, 42.456193], + [117.080061, 42.463699], + [117.09546, 42.484004], + [117.135496, 42.468996], + [117.188467, 42.468114], + [117.275314, 42.481797], + [117.332596, 42.46105], + [117.390495, 42.461933], + [117.413284, 42.471645], + [117.410205, 42.519743], + [117.387415, 42.517537], + [117.434226, 42.557224], + [117.435458, 42.585431], + [117.475494, 42.602613], + [117.530313, 42.590278], + [117.537088, 42.603054], + [117.60053, 42.603054], + [117.667051, 42.582347], + [117.708935, 42.588515], + [117.779768, 42.61847], + [117.801326, 42.612744], + [117.797631, 42.585431], + [117.856761, 42.539148], + [117.874007, 42.510038], + [117.997811, 42.416884], + [118.024296, 42.385064], + [118.008898, 42.346595], + [118.060021, 42.298364], + [118.047702, 42.280656], + [117.974405, 42.25054], + [117.977485, 42.229716], + [118.033535, 42.199132], + [118.106216, 42.172082], + [118.089586, 42.12283], + [118.097593, 42.105072], + [118.155491, 42.081091], + [118.116687, 42.037102], + [118.194296, 42.031324], + [118.220165, 42.058434], + [118.212774, 42.081091], + [118.239259, 42.092639], + [118.27252, 42.083312], + [118.296541, 42.057545], + [118.286686, 42.033991], + [118.239875, 42.024655], + [118.291614, 42.007759], + [118.313788, 41.98819], + [118.306396, 41.940131], + [118.268824, 41.930336], + [118.340273, 41.87243], + [118.335346, 41.845241], + [118.29223, 41.772976], + [118.247266, 41.773869], + [118.236179, 41.80778], + [118.178281, 41.814917], + [118.140093, 41.784134], + [118.132702, 41.733241], + [118.155491, 41.712694], + [118.159187, 41.67605], + [118.206614, 41.650566], + [118.215237, 41.59554], + [118.302701, 41.55256], + [118.315636, 41.512688], + [118.271904, 41.471446], + [118.327338, 41.450816], + [118.348896, 41.428384], + [118.361215, 41.384844], + [118.348896, 41.342622], + [118.380309, 41.312062], + [118.412338, 41.331838], + [118.528135, 41.355202], + [118.629765, 41.346666], + [118.677192, 41.35026], + [118.741866, 41.324198], + [118.770199, 41.352956], + [118.843496, 41.374516], + [118.844727, 41.342622], + [118.890923, 41.300823], + [118.949437, 41.317906], + [118.980234, 41.305769], + [119.092951, 41.293629], + [119.168712, 41.294978], + [119.197661, 41.282837], + [119.211827, 41.308016], + [119.239545, 41.31431], + [119.296211, 41.325097], + [119.330704, 41.385293], + [119.309762, 41.405944], + [119.376283, 41.422102], + [119.378131, 41.459787], + [119.401537, 41.472343], + [119.406464, 41.503276], + [119.361501, 41.545841], + [119.362116, 41.566442], + [119.420015, 41.567785], + [119.415703, 41.590169], + [119.342406, 41.617914], + [119.307914, 41.657273], + [119.299907, 41.705545], + [119.319001, 41.727435], + [119.317769, 41.764049], + [119.292515, 41.790827], + [119.312841, 41.80555], + [119.334399, 41.871539], + [119.323312, 41.889807], + [119.340559, 41.926774], + [119.323928, 41.937014], + [119.324544, 41.969505], + [119.375667, 42.023322], + [119.384906, 42.08953], + [119.352261, 42.118391], + [119.314689, 42.119723], + [119.30853, 42.147239], + [119.286972, 42.154781], + [119.277733, 42.185387], + [119.237697, 42.200905], + [119.274037, 42.239021], + [119.280197, 42.260728], + [119.34795, 42.300578], + [119.432949, 42.317396], + [119.482841, 42.347037], + [119.502551, 42.388159], + [119.540123, 42.363401], + [119.572152, 42.359421], + [119.571536, 42.335536], + [119.539507, 42.297922], + [119.557985, 42.289068], + [119.609108, 42.276671], + [119.617115, 42.252755], + [119.679941, 42.240793], + [119.744615, 42.211545], + [119.841933, 42.215534], + [119.854868, 42.170308], + [119.837622, 42.135257], + [119.845629, 42.097079], + [119.87581, 42.077982], + [119.897368, 42.030879], + [119.921389, 42.014429], + [119.924469, 41.98908], + [119.950954, 41.974399], + [119.954034, 41.923212], + [119.989759, 41.899163], + [120.023019, 41.816701], + [120.041498, 41.818932], + [120.050737, 41.776101], + [120.024867, 41.737707], + [120.035954, 41.708226], + [120.096316, 41.697056], + [120.1382, 41.729221], + [120.127113, 41.77253], + [120.183164, 41.826513], + [120.188707, 41.848361], + [120.215808, 41.853265], + [120.251533, 41.884016], + [120.286641, 41.880005], + [120.290337, 41.897381], + [120.260156, 41.904062], + [120.271859, 41.925439], + [120.318054, 41.93746], + [120.309431, 41.951704], + [120.373489, 41.994862], + [120.399358, 41.984631], + [120.456641, 42.016208], + [120.450481, 42.057101], + [120.493597, 42.073539], + [120.466496, 42.105516], + [120.56751, 42.152119], + [120.58414, 42.167203], + [120.624792, 42.154338], + [120.72211, 42.203565], + [120.745516, 42.223512], + [120.79048, 42.218636], + [120.820661, 42.227943], + [120.8299, 42.252755], + [120.883487, 42.242565], + [120.883487, 42.269585], + [120.933994, 42.27977], + [120.992508, 42.264714], + [121.028848, 42.242565], + [121.070732, 42.254083], + [121.087978, 42.278885], + [121.120623, 42.280656], + [121.133558, 42.300135], + [121.184681, 42.333324], + [121.218558, 42.371802], + [121.285079, 42.387717], + [121.314644, 42.42837], + [121.304789, 42.435879], + [121.386093, 42.474294], + [121.434752, 42.475176], + [121.4791, 42.49636], + [121.506201, 42.482239], + [121.570875, 42.487093], + [121.607831, 42.516214], + [121.604136, 42.495037], + [121.66573, 42.437204], + [121.69899, 42.438529], + [121.747649, 42.484887], + [121.803084, 42.514891], + [121.817867, 42.504303], + [121.831417, 42.533856], + [121.844352, 42.522389], + [121.889931, 42.556784], + [121.921344, 42.605697], + [121.915801, 42.656332], + [121.94167, 42.666014], + [121.939207, 42.688453], + [122.018663, 42.69901], + [122.062394, 42.723635], + [122.072865, 42.710444], + [122.160945, 42.684934], + [122.204676, 42.685374], + [122.204676, 42.732867], + [122.261343, 42.695931], + [122.324785, 42.684934], + [122.338951, 42.669975], + [122.396234, 42.684054], + [122.396234, 42.707366], + [122.460907, 42.755282], + [122.439349, 42.770221], + [122.371596, 42.776371], + [122.35127, 42.830378], + [122.436886, 42.843105], + [122.556378, 42.827745], + [122.576088, 42.819405], + [122.580399, 42.789987], + [122.624747, 42.773296], + [122.653696, 42.78252], + [122.733152, 42.786034], + [122.73808, 42.77066], + [122.786123, 42.757479], + [122.848949, 42.712203], + [122.883442, 42.751766], + [122.887137, 42.770221], + [122.925941, 42.772417], + [122.945651, 42.753524], + [122.980144, 42.777689], + [123.058368, 42.768903], + [123.118114, 42.801405], + [123.227752, 42.831695], + [123.169853, 42.859777], + [123.188947, 42.895739], + [123.18402, 42.925983], + [123.259165, 42.993431], + [123.323222, 43.000872], + [123.434707, 43.027565], + [123.474743, 43.042438], + [123.536337, 43.007], + [123.572678, 43.003498], + [123.580685, 43.036314], + [123.631192, 43.088346], + [123.636119, 43.141644], + [123.666916, 43.179623], + [123.645974, 43.208855], + [123.676771, 43.223684], + [123.664453, 43.264663], + [123.698329, 43.272071], + [123.703873, 43.37047], + [123.608402, 43.366119], + [123.54496, 43.415262], + [123.519707, 43.402219], + [123.486446, 43.44525], + [123.442098, 43.437863], + [123.419925, 43.410046], + [123.382968, 43.469143], + [123.36449, 43.483475], + [123.315831, 43.492159], + [123.329998, 43.519071], + [123.304744, 43.550742], + [123.360179, 43.567223], + [123.452569, 43.545971], + [123.461193, 43.568523], + [123.434091, 43.575461], + [123.421157, 43.598435], + [123.5117, 43.592801], + [123.510468, 43.624867], + [123.536953, 43.633964], + [123.518475, 43.682024], + [123.520323, 43.708419], + [123.48275, 43.737396], + [123.498149, 43.771114], + [123.461809, 43.822518], + [123.467968, 43.853599], + [123.397135, 43.954929], + [123.37065, 43.970006], + [123.400831, 43.979481], + [123.365722, 44.013922], + [123.331229, 44.028984], + [123.32815, 44.084035], + [123.350939, 44.092633], + [123.362642, 44.133452], + [123.386664, 44.161794], + [123.323838, 44.179823], + [123.286882, 44.211574], + [123.277027, 44.25274], + [123.196955, 44.34483], + [123.128585, 44.367081], + [123.114419, 44.40258], + [123.142136, 44.428228], + [123.125506, 44.455147], + [123.137209, 44.486322], + [123.12489, 44.5098], + [123.06576, 44.505959], + [123.025108, 44.493153], + [122.85634, 44.398304], + [122.76087, 44.369648], + [122.702971, 44.319145], + [122.675254, 44.285738], + [122.641993, 44.283595], + [122.515726, 44.251025], + [122.483081, 44.236877], + [122.319241, 44.233018], + [122.271198, 44.255741], + [122.291524, 44.310152], + [122.294604, 44.41113], + [122.28598, 44.477783], + [122.228082, 44.480345], + [122.224386, 44.526016], + [122.196053, 44.559712], + [122.13138, 44.577619], + [122.113517, 44.615546], + [122.103046, 44.67388], + [122.117213, 44.701961], + [122.161561, 44.728328], + [122.152322, 44.744057], + [122.10243, 44.736406], + [122.110438, 44.767856], + [122.142467, 44.753833], + [122.168952, 44.770405], + [122.099967, 44.7823], + [122.098119, 44.81882], + [122.04946, 44.912985], + [122.079025, 44.914256], + [122.087032, 44.95281], + [122.074713, 45.006573], + [122.098735, 45.02138], + [122.119677, 45.068739], + [122.109822, 45.142236], + [122.143082, 45.183167], + [122.192358, 45.180636], + [122.22993, 45.206784], + [122.239169, 45.276313], + [122.147394, 45.295682], + [122.146778, 45.374352], + [122.180039, 45.409655], + [122.168336, 45.439897], + [122.064242, 45.472641], + [122.002648, 45.507882], + [121.993409, 45.552741], + [121.966308, 45.596308], + [121.995873, 45.59882], + [122.003264, 45.623102], + [121.970004, 45.692956], + [121.934279, 45.71051], + [121.867142, 45.719703], + [121.812323, 45.704659], + [121.811091, 45.687103], + [121.713773, 45.701734], + [121.666345, 45.727641], + [121.644172, 45.752284], + [121.657106, 45.770238], + [121.697142, 45.76314], + [121.754425, 45.794862], + [121.766744, 45.830318], + [121.769823, 45.84366], + [121.817251, 45.875336], + [121.805548, 45.900746], + [121.821562, 45.918235], + [121.809243, 45.961102], + [121.761816, 45.998947], + [121.819098, 46.023054], + [121.843736, 46.024301], + [121.864062, 46.002272], + [121.923808, 46.004767], + [121.92812, 45.988552], + [122.040221, 45.959022], + [122.085184, 45.912406], + [122.091344, 45.882002], + [122.200981, 45.857], + [122.236705, 45.831569], + [122.253952, 45.7982], + [122.301379, 45.813218], + [122.337719, 45.859917], + [122.372828, 45.856166], + [122.362357, 45.917403], + [122.446125, 45.916986], + [122.496016, 45.85825], + [122.504639, 45.786933], + [122.522501, 45.786933], + [122.556378, 45.82156], + [122.603189, 45.778169], + [122.640761, 45.771072], + [122.650001, 45.731401], + [122.671558, 45.70048], + [122.741775, 45.705077], + [122.751015, 45.735996], + [122.792283, 45.766063], + [122.752246, 45.834905], + [122.772572, 45.856583], + [122.80029, 45.856583], + [122.828623, 45.912406], + [122.792898, 46.073313], + [123.04605, 46.099878], + [123.070071, 46.123527], + [123.112571, 46.130163], + [123.102716, 46.172037], + [123.127354, 46.174523], + [123.128585, 46.210565], + [123.178476, 46.248239], + [123.142136, 46.298293], + [123.089781, 46.347888], + [123.011557, 46.434984], + [123.010325, 46.524823], + [123.002318, 46.574624], + [123.052825, 46.579972], + [123.04605, 46.617803], + [123.077462, 46.622324], + [123.098404, 46.603002], + [123.18094, 46.614103], + [123.228368, 46.588198], + [123.279491, 46.616981], + [123.276411, 46.660947], + [123.318295, 46.662179], + [123.366338, 46.677784], + [123.474743, 46.686817], + [123.603475, 46.68928], + [123.631808, 46.728675], + [123.629344, 46.813524], + [123.580069, 46.827447], + [123.625648, 46.847508], + [123.599163, 46.868378], + [123.605322, 46.891286], + [123.576989, 46.891286], + [123.575757, 46.845461], + [123.562823, 46.82581], + [123.506772, 46.827038], + [123.483366, 46.84587], + [123.52833, 46.944836], + [123.487678, 46.959951], + [123.42362, 46.934212], + [123.337389, 46.988943], + [123.301664, 46.999965], + [123.304128, 46.964852], + [123.360179, 46.970978], + [123.404526, 46.935438], + [123.40699, 46.906416], + [123.374345, 46.837683], + [123.341084, 46.826628], + [123.295505, 46.865105], + [123.221592, 46.850373], + [123.22344, 46.821305], + [123.198802, 46.803283], + [123.163694, 46.74016], + [123.103332, 46.734828], + [123.076846, 46.745082], + [123.026339, 46.718829], + [123.00355, 46.730726], + [122.996774, 46.761483], + [122.906847, 46.80738], + [122.893913, 46.895376], + [122.895144, 46.960359], + [122.83971, 46.937072], + [122.791051, 46.941567], + [122.798442, 46.9575], + [122.77442, 46.973837], + [122.778116, 47.002822], + [122.845869, 47.046881], + [122.852645, 47.072158], + [122.821232, 47.065636], + [122.710363, 47.093349], + [122.679566, 47.094164], + [122.615508, 47.124306], + [122.582863, 47.158092], + [122.531124, 47.198771], + [122.498479, 47.255262], + [122.462755, 47.27841], + [122.441197, 47.310476], + [122.418407, 47.350632], + [122.507103, 47.401291], + [122.543443, 47.495589], + [122.59395, 47.54732], + [122.765181, 47.614333], + [122.848949, 47.67441], + [122.926557, 47.697777], + [123.041122, 47.746492], + [123.161846, 47.781892], + [123.214201, 47.824502], + [123.256085, 47.876711], + [123.300432, 47.953723], + [123.537569, 48.021816], + [123.579453, 48.045427], + [123.705105, 48.152142], + [123.746373, 48.197638], + [123.862785, 48.271782], + [124.019234, 48.39313], + [124.07898, 48.43603], + [124.136878, 48.463023], + [124.25945, 48.536385], + [124.314269, 48.503881], + [124.302566, 48.456673], + [124.330283, 48.435633], + [124.309957, 48.413393], + [124.331515, 48.380015], + [124.317964, 48.35099], + [124.353689, 48.315978], + [124.365392, 48.283731], + [124.422058, 48.245884], + [124.412819, 48.219175], + [124.418978, 48.181679], + [124.475029, 48.173698], + [124.471333, 48.133373], + [124.430065, 48.12099], + [124.415899, 48.08782], + [124.46579, 48.098213], + [124.478108, 48.123387], + [124.505826, 48.124985], + [124.529847, 48.146951], + [124.512601, 48.164518], + [124.547094, 48.200829], + [124.579122, 48.262221], + [124.558796, 48.268197], + [124.579738, 48.297269], + [124.540934, 48.335476], + [124.547094, 48.35775], + [124.51876, 48.378027], + [124.52492, 48.426897], + [124.507674, 48.445558], + [124.555717, 48.467784], + [124.533543, 48.515379], + [124.548941, 48.535593], + [124.520608, 48.556195], + [124.579122, 48.596582], + [124.601912, 48.632587], + [124.624702, 48.701755], + [124.612383, 48.747945], + [124.656115, 48.783842], + [124.644412, 48.80789], + [124.654267, 48.83429], + [124.697383, 48.841775], + [124.715861, 48.885475], + [124.709086, 48.920487], + [124.744194, 48.920487], + [124.756513, 48.967262], + [124.808252, 49.020666], + [124.828578, 49.077933], + [124.809484, 49.115943], + [124.847672, 49.129651], + [124.860607, 49.166448], + [124.906802, 49.184054], + [124.983179, 49.162535], + [125.039845, 49.17623], + [125.034302, 49.157056], + [125.117453, 49.126127], + [125.158721, 49.144921], + [125.187671, 49.186792], + [125.219699, 49.189139], + [125.227707, 49.248947], + [125.214772, 49.277066], + [125.261583, 49.322336], + [125.256656, 49.359769], + [125.277598, 49.379644], + [125.25604, 49.395227], + [125.256656, 49.437275], + [125.270822, 49.454395], + [125.228323, 49.487063], + [125.211076, 49.539908], + [125.233866, 49.536801], + [125.23017, 49.595411], + [125.205533, 49.593859], + [125.16796, 49.629923], + [125.15441, 49.616741], + [125.127308, 49.655113], + [125.132236, 49.672157], + [125.164881, 49.669446], + [125.189518, 49.652401], + [125.185207, 49.634574], + [125.219699, 49.669058], + [125.225243, 49.726349], + [125.204301, 49.734086], + [125.221547, 49.754969], + [125.222779, 49.799026], + [125.177815, 49.829533], + [125.239409, 49.844587], + [125.225243, 49.867351], + [125.245569, 49.87198], + [125.212924, 49.907452], + [125.225859, 49.922481], + [125.199373, 49.935194], + [125.190134, 49.959841], + [125.231402, 49.957531], + [125.241873, 49.987938], + [125.278214, 49.996402], + [125.297924, 50.014481], + [125.283757, 50.036012], + [125.25296, 50.041393], + [125.289916, 50.057917], + [125.315786, 50.04562], + [125.328105, 50.065985], + [125.283757, 50.070211], + [125.287453, 50.093636], + [125.258504, 50.103618], + [125.27883, 50.127411], + [125.311474, 50.140453], + [125.376148, 50.137385], + [125.335496, 50.161161], + [125.382923, 50.172278], + [125.39093, 50.199868], + [125.417416, 50.195654], + [125.448829, 50.216338], + [125.442053, 50.260357], + [125.466075, 50.266861], + [125.463611, 50.295925], + [125.530749, 50.331085], + [125.520278, 50.3498], + [125.546763, 50.358965], + [125.522126, 50.404759], + [125.536292, 50.420014], + [125.567089, 50.402852], + [125.583104, 50.409717], + [125.562162, 50.438314], + [125.580024, 50.449366], + [125.627451, 50.443268], + [125.654553, 50.471082], + [125.699516, 50.487078], + [125.740784, 50.523237], + [125.754335, 50.506874], + [125.770349, 50.531227], + [125.794987, 50.532748], + [125.829479, 50.56165], + [125.807921, 50.60383], + [125.814697, 50.62092], + [125.793139, 50.643316], + [125.804226, 50.658874], + [125.789443, 50.679735], + [125.825784, 50.70362], + [125.78082, 50.725598], + [125.795603, 50.738856], + [125.758646, 50.746809], + [125.804226, 50.773309], + [125.828863, 50.756654], + [125.846726, 50.769524], + [125.836255, 50.793363], + [125.890457, 50.805845], + [125.878138, 50.816812], + [125.913247, 50.825885], + [125.939732, 50.85423], + [125.961906, 50.901054], + [125.997631, 50.872738], + [125.996399, 50.906715], + [126.02042, 50.927466], + [126.042594, 50.92558], + [126.068464, 50.967434], + [126.041978, 50.981753], + [126.033971, 51.011132], + [126.059225, 51.043503], + [125.976073, 51.084498], + [125.993935, 51.119072], + [125.970529, 51.123955], + [125.946508, 51.108176], + [125.909551, 51.138977], + [125.864588, 51.146487], + [125.850421, 51.21364], + [125.819008, 51.227134], + [125.761726, 51.226385], + [125.76111, 51.261976], + [125.740784, 51.27583], + [125.700132, 51.327465], + [125.626219, 51.380163], + [125.623756, 51.387633], + [125.62314, 51.398089], + [125.600966, 51.410409], + [125.60035, 51.413396], + [125.595422, 51.416755], + [125.559082, 51.461521], + [125.528285, 51.488359], + [125.424807, 51.562827], + [125.38046, 51.585516], + [125.35151, 51.623801], + [125.316402, 51.610052], + [125.289301, 51.633831], + [125.228938, 51.640517], + [125.214772, 51.627888], + [125.175968, 51.639403], + [125.130388, 51.635317], + [125.12854, 51.659083], + [125.098975, 51.658341], + [125.060171, 51.59667], + [125.073106, 51.553526], + [125.047236, 51.529704], + [125.004737, 51.529332], + [124.983795, 51.508478], + [124.928976, 51.498419], + [124.917889, 51.474196], + [124.942527, 51.447349], + [124.885244, 51.40817], + [124.864302, 51.37979], + [124.783614, 51.392115], + [124.76452, 51.38726], + [124.752817, 51.35812], + [124.693687, 51.3327], + [124.62655, 51.327465], + [124.58713, 51.363725], + [124.555717, 51.375307], + [124.490427, 51.380537], + [124.478108, 51.36223], + [124.443616, 51.35812], + [124.426985, 51.331953], + [124.430065, 51.301281], + [124.406659, 51.272086], + [124.339522, 51.293422], + [124.297638, 51.298661], + [124.271769, 51.308389], + [124.239124, 51.344664], + [124.192313, 51.33943], + [124.128255, 51.347281], + [124.090067, 51.3413], + [124.071588, 51.320734], + [123.994596, 51.322604], + [123.939777, 51.313253], + [123.926227, 51.300532], + [123.887423, 51.320734], + [123.842459, 51.367462], + [123.794416, 51.361109], + [123.711264, 51.398089], + [123.660141, 51.342795], + [123.661989, 51.319237], + [123.582533, 51.306893], + [123.582533, 51.294545], + [123.46304, 51.286686], + [123.440251, 51.270963], + [123.414381, 51.278825], + [123.376809, 51.266844], + [123.339853, 51.27246], + [123.294273, 51.254111], + [123.231447, 51.268716], + [123.231447, 51.279199], + [123.127969, 51.297913], + [123.069455, 51.321108], + [123.002934, 51.31213], + [122.965977, 51.345786], + [122.965977, 51.386886], + [122.946267, 51.405183], + [122.903768, 51.415262], + [122.900072, 51.445112], + [122.871123, 51.455181], + [122.854492, 51.477551], + [122.880362, 51.511085], + [122.858804, 51.524864], + [122.880362, 51.537894], + [122.874202, 51.561339], + [122.832935, 51.581797], + [122.85634, 51.606707], + [122.820616, 51.633088], + [122.816304, 51.655371], + [122.778732, 51.698048], + [122.749167, 51.746613], + [122.771957, 51.779579], + [122.732536, 51.832495], + [122.725761, 51.87833], + [122.706051, 51.890151], + [122.729457, 51.919321], + [122.726377, 51.978709], + [122.683877, 51.974654], + [122.664783, 51.99861], + [122.650616, 52.058997], + [122.625363, 52.067459], + [122.643841, 52.111585], + [122.629059, 52.13657], + [122.690653, 52.140243], + [122.73808, 52.153464], + [122.769493, 52.179893], + [122.766413, 52.232705], + [122.787355, 52.252494], + [122.76087, 52.26678], + [122.710979, 52.256157], + [122.67895, 52.276667], + [122.585943, 52.266413], + [122.560689, 52.282526], + [122.478153, 52.29607], + [122.484313, 52.341432], + [122.447356, 52.394052], + [122.419023, 52.375057], + [122.378987, 52.395512], + [122.367284, 52.413768], + [122.342031, 52.414133], + [122.326016, 52.459374], + [122.310618, 52.475416], + [122.207756, 52.469218], + [122.178191, 52.48963], + [122.168952, 52.513674], + [122.140003, 52.510032], + [122.142467, 52.495096], + [122.107358, 52.452445], + [122.080873, 52.440407], + [122.091344, 52.427272], + [122.040837, 52.413038], + [122.035909, 52.377615], + [121.976779, 52.343626], + [121.94783, 52.298266], + [121.901018, 52.280695], + [121.841272, 52.282526], + [121.769207, 52.308147], + [121.714389, 52.318025], + [121.715621, 52.342894], + [121.658338, 52.3904], + [121.678664, 52.419973], + [121.63986, 52.44442], + [121.590585, 52.443326], + [121.565331, 52.460468], + [121.519136, 52.456821], + [121.495114, 52.484892], + [121.474172, 52.482706], + [121.416274, 52.499468], + [121.411963, 52.52205], + [121.353448, 52.534793], + [121.323883, 52.573727], + [121.280151, 52.586819], + [121.225333, 52.577364], + [121.182217, 52.59918], + [121.237036, 52.619167], + [121.29247, 52.651855], + [121.309717, 52.676173], + [121.373158, 52.683067], + [121.455078, 52.73528], + [121.476636, 52.772225], + [121.511129, 52.779104], + [121.537614, 52.801542], + [121.591201, 52.824693], + [121.620766, 52.853251], + [121.604136, 52.872401], + [121.610295, 52.892264], + [121.66265, 52.912478], + [121.677432, 52.948192], + [121.715621, 52.997926], + [121.785838, 53.018451], + [121.817867, 53.061631], + [121.775367, 53.089674], + [121.784606, 53.104408], + [121.753193, 53.147501], + [121.722396, 53.145706], + [121.665114, 53.170467], + [121.660186, 53.195213], + [121.67928, 53.199515], + [121.679896, 53.240722], + [121.642324, 53.262564], + [121.615222, 53.258984], + [121.575802, 53.29155], + [121.504969, 53.323018], + [121.499426, 53.337314], + [121.416274, 53.319443], + [121.336818, 53.325877], + [121.308485, 53.301565], + [121.227797, 53.280459], + [121.155732, 53.285468], + [121.129246, 53.277238], + [121.098449, 53.306929], + [121.055334, 53.29155], + [120.950624, 53.29763], + [120.936457, 53.28833], + [120.882871, 53.294411], + [120.867472, 53.278669], + [120.820661, 53.269007], + [120.838523, 53.239648], + [120.821893, 53.241797], + [120.736277, 53.204892], + [120.690698, 53.174771], + [120.687002, 53.142476], + [120.659901, 53.137091], + [120.643886, 53.106923], + [120.562582, 53.082845], + [120.529321, 53.045803], + [120.452945, 53.01017], + [120.411061, 52.957927], + [120.363018, 52.94134], + [120.350699, 52.906343], + [120.295265, 52.891542], + [120.297112, 52.869872], + [120.222584, 52.84277], + [120.181316, 52.806969], + [120.14128, 52.813119], + [120.101244, 52.788877], + [120.031642, 52.773674], + [120.071063, 52.70628], + [120.035338, 52.646409], + [120.049505, 52.598453], + [120.07599, 52.586092], + [120.125265, 52.586819], + [120.194866, 52.578819], + [120.289721, 52.623527], + [120.396895, 52.616261], + [120.462184, 52.64532], + [120.483742, 52.630066], + [120.56135, 52.595544], + [120.605082, 52.589364], + [120.62664, 52.570818], + [120.658669, 52.56718], + [120.690698, 52.547532], + [120.734429, 52.536977], + [120.687002, 52.511489], + [120.706712, 52.492909], + [120.68269, 52.464479], + [120.688234, 52.427637], + [120.64943, 52.3904], + [120.653741, 52.371038], + [120.62356, 52.361172], + [120.627256, 52.323878], + [120.653741, 52.302658], + [120.695625, 52.290214], + [120.715951, 52.261286], + [120.755371, 52.258355], + [120.745516, 52.20594], + [120.786784, 52.15787], + [120.760299, 52.136937], + [120.76769, 52.10938], + [120.753523, 52.085483], + [120.717183, 52.072978], + [120.690698, 52.047221], + [120.691929, 52.026973], + [120.717799, 52.015556], + [120.704864, 51.983501], + [120.66298, 51.958061], + [120.656821, 51.926333], + [120.548416, 51.907877], + [120.549032, 51.882394], + [120.481278, 51.885719], + [120.480046, 51.855049], + [120.40059, 51.833605], + [120.40675, 51.81659], + [120.363634, 51.789945], + [120.317438, 51.785873], + [120.294649, 51.752171], + [120.226279, 51.717703], + [120.172693, 51.679868], + [120.087077, 51.678013], + [120.100628, 51.649058], + [120.05936, 51.634203], + [120.035954, 51.583657], + [120.052584, 51.560967], + [120.017476, 51.52114], + [119.985447, 51.505125], + [119.982367, 51.482396], + [120.002693, 51.459283], + [119.982983, 51.445112], + [119.97128, 51.40033], + [119.910918, 51.390994], + [119.914614, 51.374187], + [119.946643, 51.360736], + [119.883817, 51.336813], + [119.885049, 51.302777], + [119.811136, 51.281071], + [119.828383, 51.263099], + [119.797586, 51.243622], + [119.821607, 51.21439], + [119.784035, 51.22601], + [119.760629, 51.212516], + [119.788346, 51.174636], + [119.771716, 51.124331], + [119.752622, 51.117193], + [119.764325, 51.092017], + [119.719361, 51.075099], + [119.726753, 51.051028], + [119.678093, 51.016404], + [119.630666, 51.00925], + [119.598637, 50.984767], + [119.569688, 50.933879], + [119.491464, 50.87878], + [119.498855, 50.827776], + [119.515485, 50.814165], + [119.496391, 50.771795], + [119.506862, 50.763846], + [119.450196, 50.695281], + [119.430486, 50.684286], + [119.385522, 50.682769], + [119.394145, 50.667219], + [119.361501, 50.632689], + [119.298059, 50.616743], + [119.281428, 50.601551], + [119.295595, 50.573814], + [119.264182, 50.536933], + [119.262334, 50.490124], + [119.250631, 50.448604], + [119.22353, 50.441363], + [119.217371, 50.414675], + [119.165016, 50.422683], + [119.125596, 50.389118], + [119.176719, 50.378814], + [119.155777, 50.364691], + [119.188422, 50.347509], + [119.232153, 50.365455], + [119.259871, 50.345218], + [119.277117, 50.366218], + [119.322696, 50.352474], + [119.358421, 50.358965], + [119.381827, 50.324208], + [119.35103, 50.303953], + [119.339943, 50.244668], + [119.319001, 50.220933], + [119.358421, 50.197953], + [119.339327, 50.192206], + [119.350414, 50.166145], + [119.309762, 50.161161], + [119.290052, 50.121655], + [119.236465, 50.075204], + [119.190269, 50.087877], + [119.193965, 50.069826], + [119.163168, 50.027554], + [119.12498, 50.019095], + [119.090487, 49.985629], + [118.982082, 49.979087], + [118.964836, 49.988708], + [118.791757, 49.955606], + [118.761576, 49.959456], + [118.739402, 49.946364], + [118.672264, 49.955991], + [118.605127, 49.926719], + [118.574946, 49.931342], + [118.531214, 49.887791], + [118.485019, 49.866194], + [118.483787, 49.830691], + [118.443751, 49.835709], + [118.385853, 49.827217], + [118.398787, 49.802502], + [118.384005, 49.783958], + [118.315636, 49.766953], + [118.284223, 49.743755], + [118.220781, 49.729831], + [118.211542, 49.690744], + [118.156723, 49.660149], + [118.129622, 49.669446], + [118.082811, 49.616741], + [118.011362, 49.614803], + [117.995963, 49.623332], + [117.950999, 49.596187], + [117.866, 49.591532], + [117.849369, 49.551557], + [117.809333, 49.521263], + [117.638102, 49.574847], + [117.485349, 49.633024], + [117.278394, 49.636512], + [117.068974, 49.695389], + [116.736367, 49.847674], + [116.717889, 49.847288], + [116.428397, 49.430659], + [116.048363, 48.873274], + [116.077928, 48.822471], + [116.069305, 48.811437], + [115.83032, 48.560156], + [115.799523, 48.514982], + [115.822929, 48.259432], + [115.81061, 48.257042], + [115.529126, 48.155336], + [115.545141, 48.134971], + [115.539597, 48.104607], + [115.580249, 47.921649], + [115.939342, 47.683275], + [115.968291, 47.689721], + [116.111189, 47.811642], + [116.130283, 47.823296], + [116.26579, 47.876711], + [116.453035, 47.837358], + [116.669846, 47.890758], + [116.791186, 47.89758], + [116.879265, 47.893968], + [117.094844, 47.8241], + [117.384335, 47.641356], + [117.493357, 47.758563], + [117.519226, 47.761782], + [117.529081, 47.782697], + [117.813645, 48.016212], + [117.886942, 48.025418], + [117.96147, 48.011007], + [118.052014, 48.01421], + [118.107448, 48.031021], + [118.124694, 48.047427], + [118.150564, 48.036224], + [118.238643, 48.041826], + [118.238027, 48.031422], + [118.284839, 48.011007], + [118.351976, 48.006203], + [118.37415, 48.016612], + [118.422193, 48.01461], + [118.441903, 47.995791], + [118.568171, 47.992187], + [118.773278, 47.771034], + [119.134219, 47.664335], + [119.152081, 47.540453], + [119.205052, 47.520249], + [119.365812, 47.47739], + [119.32208, 47.42721], + [119.365812, 47.423161], + [119.386138, 47.397645], + [119.437877, 47.378602], + [119.450812, 47.353065], + [119.559217, 47.303172], + [119.56784, 47.248357], + [119.627586, 47.247544], + [119.716282, 47.195518], + [119.763093, 47.13082], + [119.806825, 47.055037], + [119.79081, 47.04525], + [119.795122, 47.013024], + [119.845013, 46.964852], + [119.859795, 46.917046], + [119.926933, 46.903963], + [119.920157, 46.853238], + [119.936172, 46.790173], + [119.917078, 46.758203], + [119.93494, 46.712674], + [119.911534, 46.669572], + [119.859179, 46.669572], + [119.804361, 46.68189], + [119.8136, 46.66834], + [119.783419, 46.626023], + [119.739687, 46.615336], + [119.677477, 46.584908], + [119.682405, 46.605058], + [119.656535, 46.625612], + [119.598637, 46.618214], + [119.557985, 46.633832], + [119.491464, 46.629311], + [119.431718, 46.638763], + [119.374435, 46.603414], + [119.357805, 46.619447], + [119.325776, 46.608759], + [119.26295, 46.649034], + [119.20074, 46.648213], + [119.152081, 46.658072], + [119.123132, 46.642872], + [119.073857, 46.676552], + [119.011647, 46.745902], + [118.951285, 46.722111], + [118.912481, 46.733188], + [118.914329, 46.77501], + [118.845343, 46.771731], + [118.788061, 46.717598], + [118.788061, 46.687227], + [118.677192, 46.6979], + [118.639004, 46.721291], + [118.586033, 46.692975], + [118.446831, 46.704467], + [118.41049, 46.728265], + [118.316252, 46.73934], + [118.274984, 46.715957], + [118.238643, 46.709392], + [118.192448, 46.682711], + [118.124078, 46.678195], + [118.04647, 46.631366], + [117.992883, 46.631366], + [117.982412, 46.614925], + [117.914659, 46.607936], + [117.868464, 46.575447], + [117.870927, 46.549935], + [117.813645, 46.530588], + [117.769913, 46.537586], + [117.748355, 46.521941], + [117.704008, 46.516587], + [117.641182, 46.558166], + [117.622704, 46.596012], + [117.596218, 46.603414], + [117.49582, 46.600535], + [117.42006, 46.582029], + [117.447777, 46.528117], + [117.392343, 46.463023], + [117.375712, 46.416421], + [117.383719, 46.394962], + [117.372017, 46.36028], + [117.247597, 46.366888], + [117.097308, 46.356976], + [116.876801, 46.375559], + [116.834302, 46.384229], + [116.81336, 46.355737], + [116.745606, 46.327642], + [116.673541, 46.325163], + [116.585462, 46.292504], + [116.573143, 46.258998], + [116.536187, 46.23251], + [116.439484, 46.137628], + [116.414231, 46.133896], + [116.271949, 45.966926], + [116.243, 45.876169], + [116.288579, 45.839074], + [116.278108, 45.831152], + [116.286731, 45.775247], + [116.260862, 45.776082], + [116.22329, 45.747273], + [116.217746, 45.72221], + [116.17463, 45.688775], + [116.1155, 45.679577], + [116.035428, 45.685013], + [116.026805, 45.661177], + [115.936878, 45.632727], + [115.864197, 45.572853], + [115.699741, 45.45963], + [115.586408, 45.440317], + [115.36467, 45.392427], + [115.178041, 45.396209], + [114.983404, 45.379397], + [114.920578, 45.386122], + [114.745035, 45.438217], + [114.600906, 45.403773], + [114.551014, 45.387383], + [114.539928, 45.325985], + [114.519602, 45.283893], + [114.459855, 45.21353], + [114.409348, 45.179371], + [114.347139, 45.119436], + [114.313262, 45.107189], + [114.19069, 45.036607], + [114.158045, 44.994301], + [114.116777, 44.957045], + [114.065038, 44.931206], + [113.907358, 44.915104], + [113.861778, 44.863377], + [113.798953, 44.849377], + [113.712105, 44.788247], + [113.631417, 44.745333], + [113.540874, 44.759358], + [113.503918, 44.777628], + [113.11526, 44.799714], + [113.037652, 44.822641], + [112.937869, 44.840042], + [112.850406, 44.840466], + [112.712436, 44.879494], + [112.599719, 44.930783], + [112.540589, 45.001072], + [112.438959, 45.071697], + [112.396459, 45.064512], + [112.113743, 45.072965], + [112.071243, 45.096206], + [112.002874, 45.090713], + [111.903707, 45.052252], + [111.764505, 44.969325], + [111.69244, 44.859983], + [111.624687, 44.778477], + [111.585267, 44.705789], + [111.560629, 44.647062], + [111.569868, 44.57634], + [111.530448, 44.55033], + [111.514434, 44.507666], + [111.478709, 44.488884], + [111.427586, 44.394455], + [111.415883, 44.35724], + [111.428818, 44.319573], + [111.507042, 44.294305], + [111.534144, 44.26217], + [111.541535, 44.206855], + [111.559397, 44.171238], + [111.662875, 44.061247], + [111.702295, 44.034147], + [111.773128, 44.010479], + [111.870447, 43.940279], + [111.959758, 43.823382], + [111.970845, 43.748205], + [111.951135, 43.693275], + [111.891388, 43.6738], + [111.79407, 43.672068], + [111.606209, 43.513863], + [111.564325, 43.490422], + [111.456535, 43.494329], + [111.400485, 43.472618], + [111.354289, 43.436125], + [111.183674, 43.396132], + [111.151029, 43.38004], + [111.069725, 43.357852], + [111.02045, 43.329998], + [110.82027, 43.149067], + [110.769763, 43.099272], + [110.736502, 43.089657], + [110.687227, 43.036314], + [110.689691, 43.02144], + [110.631177, 42.936061], + [110.469801, 42.839156], + [110.437156, 42.781203], + [110.34846, 42.742098], + [110.139657, 42.674815], + [110.108244, 42.642687], + [109.906216, 42.635643], + [109.733753, 42.579262], + [109.683862, 42.558988], + [109.544044, 42.472528], + [109.486761, 42.458842], + [109.291509, 42.435879], + [109.026039, 42.458401], + [108.983539, 42.449128], + [108.845569, 42.395673], + [108.798757, 42.415116], + [108.705134, 42.413349], + [108.532671, 42.442945], + [108.298614, 42.438529], + [108.238252, 42.460167], + [108.089195, 42.436321], + [108.022058, 42.433229], + [107.986949, 42.413349], + [107.939522, 42.403628], + [107.736262, 42.415116], + [107.57427, 42.412907], + [107.501589, 42.456635], + [107.46648, 42.458842], + [107.303872, 42.412465], + [107.271844, 42.364285], + [107.051337, 42.319166], + [106.785867, 42.291281], + [106.612789, 42.241679], + [106.372572, 42.161436], + [106.344855, 42.149457], + [106.01348, 42.032213], + [105.74185, 41.949033], + [105.589713, 41.888471], + [105.385221, 41.797073], + [105.291599, 41.749763], + [105.230621, 41.751103], + [105.009498, 41.583007], + [104.923267, 41.654143], + [104.803775, 41.652355], + [104.68921, 41.6452], + [104.524138, 41.661745], + [104.530298, 41.875104], + [104.418813, 41.860397], + [104.30856, 41.840782], + [104.080046, 41.805104], + [103.868779, 41.802427], + [103.454868, 41.877332], + [103.418527, 41.882233], + [103.20726, 41.96283], + [103.021862, 42.028212], + [102.712045, 42.153007], + [102.621502, 42.154338], + [102.540814, 42.162323], + [102.449039, 42.144133], + [102.093642, 42.223512], + [102.070236, 42.232374], + [101.877447, 42.432345], + [101.803534, 42.503861], + [101.770274, 42.509597], + [101.557775, 42.529887], + [101.291689, 42.586312], + [100.862995, 42.671295], + [100.826655, 42.675255], + [100.32528, 42.690213], + [100.272309, 42.636523], + [100.004376, 42.648849], + [99.969267, 42.647969], + [99.51224, 42.568244], + [98.962822, 42.607018], + [98.546447, 42.638284], + [98.195362, 42.653251], + [97.831958, 42.706047], + [97.28254, 42.782081], + [97.172903, 42.795257] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 210000, + "name": "辽宁省", + "center": [123.429096, 41.796767], + "centroid": [122.604994, 41.299712], + "childrenNum": 14, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 5, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [123.534489, 39.788361], + [123.546808, 39.756163], + [123.579453, 39.781002], + [123.612714, 39.775023], + [123.642279, 39.796178], + [123.645358, 39.823761], + [123.674924, 39.826979], + [123.687858, 39.808132], + [123.795032, 39.822842], + [123.812278, 39.831115], + [123.95148, 39.817786], + [124.002603, 39.800316], + [124.103001, 39.823302], + [124.099306, 39.777323], + [124.151045, 39.74558], + [124.173218, 39.841225], + [124.214486, 39.865116], + [124.215102, 39.883487], + [124.21695, 39.894049], + [124.218182, 39.895885], + [124.219414, 39.899099], + [124.241588, 39.928477], + [124.286551, 39.931689], + [124.288399, 39.962888], + [124.349377, 39.989029], + [124.372167, 40.021576], + [124.336442, 40.049985], + [124.346913, 40.079756], + [124.428217, 40.144291], + [124.457782, 40.177679], + [124.490427, 40.18408], + [124.513833, 40.218362], + [124.515065, 40.22019], + [124.62655, 40.291896], + [124.722636, 40.321561], + [124.739267, 40.371733], + [124.834121, 40.423235], + [124.913578, 40.481981], + [124.945606, 40.45603], + [124.985642, 40.475153], + [125.044157, 40.466503], + [125.042925, 40.483802], + [125.004737, 40.496091], + [125.015823, 40.533853], + [125.076801, 40.562048], + [125.113758, 40.569322], + [125.181511, 40.611132], + [125.262815, 40.620218], + [125.279445, 40.655187], + [125.305315, 40.661089], + [125.329337, 40.643835], + [125.375532, 40.658365], + [125.422343, 40.635661], + [125.418648, 40.673345], + [125.453756, 40.676522], + [125.459916, 40.707379], + [125.49564, 40.728697], + [125.544915, 40.729605], + [125.551075, 40.761796], + [125.585567, 40.788535], + [125.61698, 40.763609], + [125.685349, 40.769048], + [125.67611, 40.788082], + [125.641002, 40.798503], + [125.648393, 40.826133], + [125.707523, 40.866877], + [125.687813, 40.897645], + [125.652089, 40.91619], + [125.584335, 40.891764], + [125.589263, 40.931112], + [125.635458, 40.94151], + [125.650241, 40.970888], + [125.674879, 40.974503], + [125.684118, 41.021929], + [125.726617, 41.055332], + [125.739552, 41.08917], + [125.712451, 41.095485], + [125.734009, 41.125695], + [125.759878, 41.132908], + [125.791291, 41.167607], + [125.73832, 41.178418], + [125.758646, 41.232449], + [125.749407, 41.245499], + [125.695205, 41.244599], + [125.685349, 41.273842], + [125.646545, 41.264396], + [125.642234, 41.296327], + [125.62006, 41.318355], + [125.637306, 41.34442], + [125.610205, 41.365084], + [125.589879, 41.359245], + [125.581256, 41.396517], + [125.547995, 41.401006], + [125.534444, 41.428833], + [125.533212, 41.479069], + [125.493176, 41.509103], + [125.507343, 41.534195], + [125.479626, 41.544946], + [125.450061, 41.597777], + [125.461148, 41.642516], + [125.446981, 41.67605], + [125.412488, 41.691246], + [125.344119, 41.672474], + [125.317018, 41.676944], + [125.332416, 41.711354], + [125.336112, 41.768067], + [125.336112, 41.768067], + [125.323177, 41.771191], + [125.323177, 41.771191], + [125.319482, 41.776993], + [125.319482, 41.776993], + [125.294844, 41.822945], + [125.307779, 41.924548], + [125.35151, 41.92811], + [125.291764, 41.958825], + [125.29854, 41.974399], + [125.369989, 42.002868], + [125.363213, 42.017097], + [125.416184, 42.063766], + [125.414336, 42.101964], + [125.446365, 42.098411], + [125.490097, 42.136145], + [125.458068, 42.160105], + [125.458068, 42.160105], + [125.41372, 42.156112], + [125.368141, 42.182726], + [125.357054, 42.145464], + [125.305931, 42.146351], + [125.312706, 42.197359], + [125.280677, 42.175187], + [125.312706, 42.219966], + [125.27575, 42.231045], + [125.27575, 42.266928], + [125.299156, 42.289953], + [125.264047, 42.312528], + [125.224011, 42.30102], + [125.175352, 42.308102], + [125.167345, 42.351903], + [125.203685, 42.366938], + [125.185823, 42.38197], + [125.186439, 42.427928], + [125.140243, 42.44692], + [125.150098, 42.458842], + [125.105135, 42.490624], + [125.068794, 42.499449], + [125.090968, 42.515773], + [125.066946, 42.534738], + [125.089736, 42.567803], + [125.082961, 42.591159], + [125.097127, 42.622433], + [125.038613, 42.615387], + [125.010896, 42.63212], + [125.014592, 42.666014], + [124.99057, 42.677455], + [124.968396, 42.722756], + [124.996729, 42.745174], + [124.975171, 42.802722], + [124.92836, 42.819844], + [124.897563, 42.787791], + [124.874157, 42.789987], + [124.856911, 42.824234], + [124.84952, 42.882585], + [124.87231, 42.962344], + [124.869846, 42.988178], + [124.840897, 43.032377], + [124.88894, 43.074796], + [124.882781, 43.13422], + [124.785462, 43.117185], + [124.755281, 43.074359], + [124.719557, 43.069987], + [124.686912, 43.051185], + [124.677673, 43.002185], + [124.658579, 42.972854], + [124.635173, 42.972854], + [124.632093, 42.949642], + [124.607456, 42.937376], + [124.586514, 42.905384], + [124.466406, 42.847054], + [124.435609, 42.880831], + [124.371551, 42.880831], + [124.38079, 42.912835], + [124.431913, 42.930803], + [124.442384, 42.958841], + [124.42329, 42.975482], + [124.369703, 42.972854], + [124.333363, 42.997371], + [124.425754, 43.076107], + [124.366007, 43.121554], + [124.273617, 43.17875], + [124.287167, 43.207983], + [124.27608, 43.233278], + [124.228653, 43.235022], + [124.215102, 43.255947], + [124.168291, 43.244177], + [124.114088, 43.247229], + [124.117168, 43.2773], + [124.099306, 43.292983], + [124.032784, 43.280786], + [123.964415, 43.34088], + [123.896046, 43.361333], + [123.881263, 43.392218], + [123.881263, 43.392218], + [123.852314, 43.406133], + [123.857858, 43.459153], + [123.857858, 43.459153], + [123.79688, 43.489988], + [123.747604, 43.472184], + [123.749452, 43.439167], + [123.710032, 43.417001], + [123.703873, 43.37047], + [123.698329, 43.272071], + [123.664453, 43.264663], + [123.676771, 43.223684], + [123.645974, 43.208855], + [123.666916, 43.179623], + [123.636119, 43.141644], + [123.631192, 43.088346], + [123.580685, 43.036314], + [123.572678, 43.003498], + [123.536337, 43.007], + [123.474743, 43.042438], + [123.434707, 43.027565], + [123.323222, 43.000872], + [123.259165, 42.993431], + [123.18402, 42.925983], + [123.188947, 42.895739], + [123.169853, 42.859777], + [123.227752, 42.831695], + [123.118114, 42.801405], + [123.058368, 42.768903], + [122.980144, 42.777689], + [122.945651, 42.753524], + [122.925941, 42.772417], + [122.887137, 42.770221], + [122.883442, 42.751766], + [122.883442, 42.751766], + [122.848949, 42.712203], + [122.848949, 42.712203], + [122.786123, 42.757479], + [122.73808, 42.77066], + [122.733152, 42.786034], + [122.653696, 42.78252], + [122.624747, 42.773296], + [122.580399, 42.789987], + [122.576088, 42.819405], + [122.556378, 42.827745], + [122.436886, 42.843105], + [122.35127, 42.830378], + [122.371596, 42.776371], + [122.439349, 42.770221], + [122.460907, 42.755282], + [122.396234, 42.707366], + [122.396234, 42.684054], + [122.338951, 42.669975], + [122.324785, 42.684934], + [122.261343, 42.695931], + [122.204676, 42.732867], + [122.204676, 42.685374], + [122.160945, 42.684934], + [122.072865, 42.710444], + [122.062394, 42.723635], + [122.018663, 42.69901], + [121.939207, 42.688453], + [121.94167, 42.666014], + [121.915801, 42.656332], + [121.921344, 42.605697], + [121.889931, 42.556784], + [121.844352, 42.522389], + [121.831417, 42.533856], + [121.817867, 42.504303], + [121.803084, 42.514891], + [121.747649, 42.484887], + [121.69899, 42.438529], + [121.66573, 42.437204], + [121.604136, 42.495037], + [121.607831, 42.516214], + [121.570875, 42.487093], + [121.506201, 42.482239], + [121.4791, 42.49636], + [121.434752, 42.475176], + [121.386093, 42.474294], + [121.304789, 42.435879], + [121.314644, 42.42837], + [121.285079, 42.387717], + [121.218558, 42.371802], + [121.184681, 42.333324], + [121.133558, 42.300135], + [121.120623, 42.280656], + [121.087978, 42.278885], + [121.070732, 42.254083], + [121.028848, 42.242565], + [120.992508, 42.264714], + [120.933994, 42.27977], + [120.883487, 42.269585], + [120.883487, 42.269585], + [120.883487, 42.242565], + [120.8299, 42.252755], + [120.820661, 42.227943], + [120.79048, 42.218636], + [120.745516, 42.223512], + [120.72211, 42.203565], + [120.624792, 42.154338], + [120.58414, 42.167203], + [120.56751, 42.152119], + [120.466496, 42.105516], + [120.493597, 42.073539], + [120.450481, 42.057101], + [120.456641, 42.016208], + [120.399358, 41.984631], + [120.373489, 41.994862], + [120.309431, 41.951704], + [120.318054, 41.93746], + [120.271859, 41.925439], + [120.260156, 41.904062], + [120.290337, 41.897381], + [120.286641, 41.880005], + [120.251533, 41.884016], + [120.215808, 41.853265], + [120.188707, 41.848361], + [120.183164, 41.826513], + [120.127113, 41.77253], + [120.1382, 41.729221], + [120.096316, 41.697056], + [120.035954, 41.708226], + [120.024867, 41.737707], + [120.050737, 41.776101], + [120.041498, 41.818932], + [120.023019, 41.816701], + [119.989759, 41.899163], + [119.954034, 41.923212], + [119.950954, 41.974399], + [119.924469, 41.98908], + [119.921389, 42.014429], + [119.897368, 42.030879], + [119.87581, 42.077982], + [119.845629, 42.097079], + [119.837622, 42.135257], + [119.854868, 42.170308], + [119.841933, 42.215534], + [119.744615, 42.211545], + [119.679941, 42.240793], + [119.617115, 42.252755], + [119.609108, 42.276671], + [119.557985, 42.289068], + [119.557985, 42.289068], + [119.539507, 42.297922], + [119.571536, 42.335536], + [119.572152, 42.359421], + [119.540123, 42.363401], + [119.502551, 42.388159], + [119.482841, 42.347037], + [119.432949, 42.317396], + [119.34795, 42.300578], + [119.280197, 42.260728], + [119.274037, 42.239021], + [119.237697, 42.200905], + [119.277733, 42.185387], + [119.286972, 42.154781], + [119.30853, 42.147239], + [119.314689, 42.119723], + [119.352261, 42.118391], + [119.384906, 42.08953], + [119.375667, 42.023322], + [119.324544, 41.969505], + [119.323928, 41.937014], + [119.340559, 41.926774], + [119.323312, 41.889807], + [119.334399, 41.871539], + [119.312841, 41.80555], + [119.292515, 41.790827], + [119.317769, 41.764049], + [119.319001, 41.727435], + [119.299907, 41.705545], + [119.307914, 41.657273], + [119.342406, 41.617914], + [119.415703, 41.590169], + [119.420015, 41.567785], + [119.362116, 41.566442], + [119.361501, 41.545841], + [119.406464, 41.503276], + [119.401537, 41.472343], + [119.378131, 41.459787], + [119.376283, 41.422102], + [119.309762, 41.405944], + [119.330704, 41.385293], + [119.296211, 41.325097], + [119.239545, 41.31431], + [119.2494, 41.279689], + [119.209364, 41.244599], + [119.204436, 41.222546], + [119.169943, 41.222996], + [119.189038, 41.198234], + [119.126212, 41.138767], + [119.081248, 41.131555], + [119.080632, 41.095936], + [119.037516, 41.067516], + [118.964836, 41.079246], + [118.937118, 41.052625], + [118.951901, 41.018317], + [119.013495, 41.007479], + [119.00056, 40.967273], + [118.977154, 40.959138], + [118.977154, 40.959138], + [118.916792, 40.969984], + [118.90201, 40.960946], + [118.873061, 40.847866], + [118.845959, 40.822057], + [118.878604, 40.783098], + [118.907553, 40.775394], + [118.895234, 40.75409], + [118.950053, 40.747743], + [118.96114, 40.72008], + [119.011031, 40.687414], + [119.028277, 40.692406], + [119.054763, 40.664721], + [119.115125, 40.666536], + [119.165632, 40.69286], + [119.184726, 40.680153], + [119.14469, 40.632482], + [119.162552, 40.600228], + [119.177951, 40.609315], + [119.230921, 40.603863], + [119.22045, 40.569322], + [119.256175, 40.543404], + [119.30237, 40.530215], + [119.429254, 40.540221], + [119.477913, 40.533399], + [119.503783, 40.553864], + [119.559217, 40.547952], + [119.572152, 40.523846], + [119.553674, 40.502007], + [119.604797, 40.455119], + [119.586934, 40.375381], + [119.598021, 40.334335], + [119.651608, 40.271808], + [119.639289, 40.231613], + [119.639289, 40.231613], + [119.671934, 40.23938], + [119.716898, 40.195966], + [119.745847, 40.207851], + [119.760629, 40.136056], + [119.736608, 40.104936], + [119.772332, 40.08113], + [119.783419, 40.046778], + [119.783419, 40.046778], + [119.787115, 40.041739], + [119.787115, 40.041739], + [119.81668, 40.050443], + [119.81668, 40.050443], + [119.854252, 40.033033], + [119.845629, 40.000949], + [119.845629, 40.000949], + [119.854252, 39.98857], + [119.91831, 39.989946], + [119.941715, 40.009659], + [119.947259, 40.040364], + [120.092005, 40.077466], + [120.134504, 40.074719], + [120.161606, 40.096239], + [120.273091, 40.127362], + [120.371641, 40.174478], + [120.451097, 40.177679], + [120.491749, 40.20008], + [120.523778, 40.256737], + [120.52193, 40.304676], + [120.537329, 40.325211], + [120.602618, 40.36079], + [120.596459, 40.399084], + [120.617401, 40.41959], + [120.616169, 40.444645], + [120.619249, 40.460128], + [120.666676, 40.467413], + [120.693777, 40.505647], + [120.72211, 40.515657], + [120.72827, 40.539311], + [120.822509, 40.59432], + [120.837291, 40.644289], + [120.8299, 40.671076], + [120.861313, 40.684692], + [120.939537, 40.686507], + [120.983269, 40.712822], + [121.032544, 40.709193], + [121.028848, 40.746382], + [120.991276, 40.744115], + [120.980189, 40.766329], + [120.994356, 40.790801], + [120.971566, 40.805751], + [121.00729, 40.807563], + [121.010986, 40.784457], + [121.086747, 40.79805], + [121.076892, 40.815716], + [121.096602, 40.839717], + [121.126167, 40.86914], + [121.177906, 40.873665], + [121.23642, 40.851035], + [121.290622, 40.851488], + [121.439064, 40.830208], + [121.440296, 40.88181], + [121.499426, 40.880001], + [121.526527, 40.85194], + [121.55486, 40.849677], + [121.553013, 40.817528], + [121.576418, 40.837906], + [121.626309, 40.844244], + [121.682976, 40.829755], + [121.732251, 40.846961], + [121.735331, 40.862351], + [121.778446, 40.886787], + [121.816019, 40.894931], + [121.84312, 40.831567], + [121.883772, 40.802127], + [121.934279, 40.79805], + [121.936127, 40.711462], + [121.951525, 40.680607], + [122.025438, 40.674253], + [122.06609, 40.64883], + [122.122141, 40.657457], + [122.148626, 40.671983], + [122.133843, 40.614313], + [122.150474, 40.588413], + [122.245944, 40.519752], + [122.231162, 40.505192], + [122.265038, 40.48016], + [122.221923, 40.481071], + [122.240401, 40.461039], + [122.250872, 40.445555], + [122.229314, 40.424146], + [122.186814, 40.422779], + [122.198517, 40.382219], + [122.152322, 40.357597], + [122.135691, 40.374925], + [122.111054, 40.348932], + [122.138155, 40.338897], + [122.110438, 40.315629], + [122.079641, 40.332967], + [122.040221, 40.322017], + [122.039605, 40.260391], + [122.02667, 40.244862], + [121.940438, 40.242121], + [121.950293, 40.204194], + [121.98109, 40.173106], + [122.003264, 40.172191], + [121.995257, 40.128277], + [121.956453, 40.133311], + [121.910257, 40.072887], + [121.824642, 40.025701], + [121.796309, 39.999116], + [121.779062, 39.942702], + [121.76428, 39.933525], + [121.699606, 39.937196], + [121.626925, 39.882569], + [121.572107, 39.865116], + [121.541926, 39.874302], + [121.530223, 39.851334], + [121.472325, 39.802155], + [121.487107, 39.760303], + [121.45939, 39.747881], + [121.502506, 39.703233], + [121.482796, 39.659478], + [121.451999, 39.658095], + [121.450151, 39.624914], + [121.325731, 39.601402], + [121.299246, 39.606013], + [121.263521, 39.589873], + [121.226565, 39.554814], + [121.224717, 39.519275], + [121.268449, 39.482794], + [121.286927, 39.507271], + [121.301709, 39.476327], + [121.245659, 39.456923], + [121.270296, 39.434277], + [121.246891, 39.421334], + [121.245659, 39.389427], + [121.270296, 39.374162], + [121.307869, 39.391277], + [121.324499, 39.371386], + [121.35468, 39.377863], + [121.432904, 39.357506], + [121.435984, 39.329736], + [121.466781, 39.320014], + [121.474788, 39.296398], + [121.508665, 39.29223], + [121.51544, 39.286672], + [121.562252, 39.322792], + [121.621382, 39.326033], + [121.72486, 39.364447], + [121.711925, 39.33992], + [121.7187, 39.320477], + [121.667577, 39.310754], + [121.672505, 39.275554], + [121.623846, 39.285745], + [121.589353, 39.263044], + [121.631237, 39.22643], + [121.591201, 39.228748], + [121.586889, 39.193506], + [121.604136, 39.166136], + [121.639244, 39.166136], + [121.68236, 39.117863], + [121.631853, 39.077921], + [121.605983, 39.080708], + [121.642324, 39.11972], + [121.590585, 39.154999], + [121.562252, 39.127149], + [121.599208, 39.098824], + [121.581962, 39.075598], + [121.508049, 39.034237], + [121.431057, 39.027263], + [121.370695, 39.060264], + [121.317108, 39.012384], + [121.341129, 38.980757], + [121.275224, 38.971917], + [121.204391, 38.941202], + [121.180369, 38.959819], + [121.128014, 38.958888], + [121.08921, 38.922115], + [121.094138, 38.894173], + [121.129862, 38.879266], + [121.110768, 38.862026], + [121.12863, 38.799089], + [121.112, 38.776231], + [121.13787, 38.723023], + [121.198848, 38.721623], + [121.259825, 38.786495], + [121.280767, 38.786961], + [121.288775, 38.78976], + [121.315876, 38.793958], + [121.359608, 38.822406], + [121.399028, 38.812613], + [121.509897, 38.817743], + [121.564715, 38.874607], + [121.618302, 38.862492], + [121.675585, 38.86156], + [121.708845, 38.872744], + [121.719316, 38.920252], + [121.655874, 38.946788], + [121.618918, 38.950046], + [121.66265, 38.966333], + [121.671273, 39.010059], + [121.73841, 38.998898], + [121.756889, 39.025869], + [121.790149, 39.022614], + [121.804932, 38.970986], + [121.863446, 38.942598], + [121.920728, 38.969591], + [121.905946, 38.997503], + [121.852975, 39.035631], + [121.8887, 39.027263], + [121.929352, 39.024939], + [121.907178, 39.055617], + [121.923192, 39.053758], + [121.963228, 39.030053], + [122.013735, 39.073275], + [122.061778, 39.060264], + [122.071634, 39.074204], + [122.048228, 39.101146], + [122.088264, 39.112291], + [122.127684, 39.144788], + [122.167104, 39.158711], + [122.123988, 39.172631], + [122.117213, 39.213911], + [122.160329, 39.238019], + [122.242865, 39.267678], + [122.274893, 39.322329], + [122.30877, 39.346399], + [122.366053, 39.370461], + [122.412864, 39.411625], + [122.455364, 39.408388], + [122.467682, 39.403301], + [122.51203, 39.413474], + [122.532972, 39.419947], + [122.581631, 39.464316], + [122.637066, 39.488799], + [122.649385, 39.516505], + [122.682645, 39.514658], + [122.808913, 39.559889], + [122.847101, 39.581571], + [122.860652, 39.604629], + [122.941956, 39.604629], + [122.972753, 39.594946], + [122.978912, 39.616156], + [123.021412, 39.64335], + [123.010941, 39.655331], + [123.103332, 39.676983], + [123.146448, 39.647037], + [123.166774, 39.674219], + [123.212969, 39.665928], + [123.215433, 39.696786], + [123.253005, 39.689879], + [123.286882, 39.704154], + [123.270251, 39.714743], + [123.274563, 39.753862], + [123.350939, 39.750641], + [123.388512, 39.74742], + [123.392823, 39.723949], + [123.477823, 39.74696], + [123.521555, 39.772724], + [123.534489, 39.788361] + ] + ], + [ + [ + [122.63953, 39.286209], + [122.593334, 39.278334], + [122.539131, 39.308439], + [122.50895, 39.290377], + [122.57732, 39.269994], + [122.67895, 39.268605], + [122.673406, 39.269531], + [122.662935, 39.273701], + [122.655544, 39.277407], + [122.640761, 39.288061], + [122.63953, 39.286209] + ] + ], + [ + [ + [122.318625, 39.170775], + [122.345111, 39.144788], + [122.366053, 39.174951], + [122.398697, 39.16196], + [122.383299, 39.190723], + [122.393154, 39.213448], + [122.343263, 39.203246], + [122.322321, 39.177271], + [122.322937, 39.174487], + [122.319241, 39.172167], + [122.318625, 39.170775] + ] + ], + [ + [ + [122.691884, 39.23292], + [122.696812, 39.206492], + [122.751631, 39.229675], + [122.740544, 39.248679], + [122.635834, 39.241727], + [122.628443, 39.231993], + [122.690037, 39.234774], + [122.691268, 39.23431], + [122.691884, 39.23292] + ] + ], + [ + [ + [122.738696, 39.034701], + [122.704819, 39.044463], + [122.733152, 39.014244], + [122.75779, 39.009594], + [122.739312, 39.036561], + [122.738696, 39.034701] + ] + ], + [ + [ + [123.022644, 39.546507], + [122.96105, 39.551122], + [122.945035, 39.520198], + [122.995542, 39.495264], + [123.036194, 39.533123], + [123.022644, 39.546507] + ] + ], + [ + [ + [122.503407, 39.241263], + [122.502175, 39.224112], + [122.547755, 39.229211], + [122.503407, 39.241263] + ] + ], + [ + [ + [120.786784, 40.473787], + [120.83298, 40.491995], + [120.8299, 40.516112], + [120.805262, 40.525666], + [120.774465, 40.48016], + [120.786784, 40.473787] + ] + ], + [ + [ + [123.086702, 39.426881], + [123.090397, 39.450915], + [123.054057, 39.457847], + [123.086702, 39.426881] + ] + ], + [ + [ + [123.160614, 39.025404], + [123.205578, 39.057011], + [123.20065, 39.077921], + [123.145832, 39.091857], + [123.143984, 39.038885], + [123.160614, 39.025404] + ] + ], + [ + [ + [123.716807, 39.74512], + [123.756843, 39.754322], + [123.719887, 39.763063], + [123.716807, 39.74512] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 220000, + "name": "吉林省", + "center": [125.3245, 43.886841], + "centroid": [126.171208, 43.703954], + "childrenNum": 9, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 6, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [129.601492, 42.415116], + [129.601492, 42.422627], + [129.591021, 42.447803], + [129.627361, 42.462816], + [129.651999, 42.426603], + [129.704354, 42.427045], + [129.748701, 42.471204], + [129.738846, 42.500332], + [129.749933, 42.546644], + [129.746237, 42.58455], + [129.786889, 42.615387], + [129.754245, 42.645768], + [129.796744, 42.681854], + [129.767179, 42.707806], + [129.78381, 42.762752], + [129.810911, 42.795257], + [129.816454, 42.851003], + [129.835549, 42.866796], + [129.846636, 42.918533], + [129.874969, 42.923792], + [129.856491, 42.951833], + [129.868193, 42.97373], + [129.903918, 42.968475], + [129.897143, 43.001748], + [129.954425, 43.010938], + [129.963664, 42.978547], + [130.002468, 42.981174], + [130.027106, 42.9676], + [130.072685, 42.971541], + [130.10841, 42.989929], + [130.144134, 42.976357], + [130.120729, 42.954461], + [130.127504, 42.932556], + [130.10225, 42.922916], + [130.136127, 42.90363], + [130.17062, 42.912397], + [130.21004, 42.902315], + [130.258083, 42.90626], + [130.277793, 42.892232], + [130.258083, 42.860655], + [130.245148, 42.799209], + [130.242069, 42.738582], + [130.257467, 42.710884], + [130.290112, 42.702968], + [130.333228, 42.64973], + [130.373264, 42.630799], + [130.388046, 42.603054], + [130.420691, 42.617148], + [130.44656, 42.607459], + [130.423771, 42.574855], + [130.435474, 42.553257], + [130.476125, 42.570007], + [130.459495, 42.588075], + [130.482285, 42.626837], + [130.522937, 42.622433], + [130.520473, 42.593362], + [130.558661, 42.495919], + [130.585763, 42.485328], + [130.581451, 42.435437], + [130.645509, 42.426603], + [130.600545, 42.450453], + [130.599929, 42.486211], + [130.565437, 42.506509], + [130.570364, 42.557224], + [130.622719, 42.573092], + [130.633806, 42.603494], + [130.592538, 42.671295], + [130.521089, 42.702089], + [130.464423, 42.688453], + [130.425003, 42.706926], + [130.40714, 42.731548], + [130.46627, 42.772417], + [130.532792, 42.787352], + [130.562357, 42.815015], + [130.603625, 42.819405], + [130.665835, 42.847932], + [130.708335, 42.846615], + [130.719422, 42.831695], + [130.75453, 42.845738], + [130.784095, 42.842227], + [130.801957, 42.879515], + [130.845073, 42.881269], + [130.890653, 42.852758], + [130.912826, 42.870744], + [130.949783, 42.876884], + [130.981812, 42.857145], + [131.043406, 42.862848], + [131.017536, 42.915027], + [131.034167, 42.929051], + [131.114855, 42.915027], + [131.145652, 42.9365], + [131.151195, 42.968475], + [131.115471, 42.975482], + [131.11855, 43.007875], + [131.102536, 43.021002], + [131.120398, 43.068238], + [131.171521, 43.06955], + [131.173985, 43.111506], + [131.207861, 43.1316], + [131.218948, 43.191405], + [131.201086, 43.203185], + [131.206014, 43.237202], + [131.255289, 43.265099], + [131.269455, 43.297775], + [131.275615, 43.369165], + [131.314419, 43.392653], + [131.295941, 43.441774], + [131.314419, 43.461325], + [131.31873, 43.499539], + [131.304564, 43.502144], + [131.294093, 43.470012], + [131.234963, 43.475224], + [131.201086, 43.442209], + [131.175217, 43.444816], + [131.142572, 43.425695], + [131.026775, 43.508655], + [130.959638, 43.48608], + [130.907283, 43.434387], + [130.864167, 43.437863], + [130.841378, 43.454374], + [130.822899, 43.503446], + [130.776704, 43.52341], + [130.727429, 43.560284], + [130.671378, 43.565054], + [130.665835, 43.583698], + [130.623335, 43.589767], + [130.630726, 43.622268], + [130.57098, 43.626167], + [130.57098, 43.626167], + [130.501995, 43.636563], + [130.488444, 43.65605], + [130.437937, 43.646091], + [130.412684, 43.652586], + [130.394206, 43.703227], + [130.423155, 43.745179], + [130.382503, 43.777164], + [130.381887, 43.817768], + [130.362793, 43.844967], + [130.386198, 43.85403], + [130.368336, 43.894151], + [130.381887, 43.910106], + [130.338155, 43.963975], + [130.364025, 43.992399], + [130.365256, 44.044042], + [130.319061, 44.03974], + [130.307358, 44.002731], + [130.27225, 43.981634], + [130.262395, 43.949328], + [130.208192, 43.948466], + [130.153373, 43.915711], + [130.143518, 43.878624], + [130.116417, 43.878192], + [130.110873, 43.852735], + [130.079461, 43.835039], + [130.027722, 43.851872], + [130.009243, 43.889407], + [130.022794, 43.917866], + [130.017867, 43.961821], + [129.979062, 44.015644], + [129.951345, 44.027263], + [129.907614, 44.023821], + [129.881128, 44.000148], + [129.868193, 44.012631], + [129.802904, 43.964837], + [129.780114, 43.892857], + [129.739462, 43.895876], + [129.743158, 43.876035], + [129.699426, 43.8838], + [129.650767, 43.873016], + [129.529427, 43.870427], + [129.467833, 43.874741], + [129.449971, 43.850578], + [129.417942, 43.843672], + [129.406855, 43.819496], + [129.348341, 43.798333], + [129.30892, 43.812155], + [129.289826, 43.797038], + [129.254718, 43.819496], + [129.211602, 43.784509], + [129.232544, 43.709284], + [129.214066, 43.695006], + [129.217146, 43.648689], + [129.232544, 43.635263], + [129.23008, 43.593234], + [129.169102, 43.561585], + [129.145081, 43.570258], + [129.093958, 43.547706], + [129.037907, 43.540332], + [129.013886, 43.522976], + [128.962763, 43.53903], + [128.949828, 43.553779], + [128.878379, 43.539898], + [128.834647, 43.587599], + [128.821097, 43.637429], + [128.78722, 43.686784], + [128.768126, 43.732207], + [128.729322, 43.736964], + [128.760119, 43.755554], + [128.739177, 43.806972], + [128.719467, 43.816905], + [128.760734, 43.857482], + [128.729938, 43.889838], + [128.696061, 43.903207], + [128.636315, 43.891132], + [128.64001, 43.948035], + [128.610445, 43.960529], + [128.584576, 43.990246], + [128.574721, 44.047914], + [128.529141, 44.112401], + [128.471859, 44.157501], + [128.450301, 44.203423], + [128.471859, 44.247596], + [128.453997, 44.257884], + [128.472475, 44.320001], + [128.446605, 44.339694], + [128.475555, 44.346114], + [128.481714, 44.375637], + [128.457076, 44.409848], + [128.463236, 44.431647], + [128.427511, 44.473512], + [128.397946, 44.483761], + [128.372693, 44.514495], + [128.295084, 44.480772], + [128.293237, 44.467961], + [128.228563, 44.445748], + [128.211317, 44.431647], + [128.172512, 44.34697], + [128.137404, 44.357668], + [128.094904, 44.354673], + [128.074578, 44.370075], + [128.049941, 44.349965], + [128.065339, 44.307155], + [128.101679, 44.293449], + [128.064107, 44.251454], + [128.104143, 44.230017], + [128.09244, 44.181539], + [128.060411, 44.168663], + [128.088129, 44.158359], + [128.091208, 44.133022], + [128.042549, 44.103807], + [127.950158, 44.088334], + [127.912586, 44.064687], + [127.862695, 44.062967], + [127.846065, 44.081886], + [127.808492, 44.086615], + [127.783239, 44.071997], + [127.729036, 44.09908], + [127.735811, 44.11412], + [127.712406, 44.199133], + [127.681609, 44.166946], + [127.641573, 44.193555], + [127.626174, 44.187977], + [127.59045, 44.227872], + [127.623711, 44.278025], + [127.579363, 44.310581], + [127.486356, 44.410275], + [127.50853, 44.437202], + [127.463566, 44.484615], + [127.465414, 44.516628], + [127.485124, 44.528576], + [127.536247, 44.522176], + [127.570124, 44.55033], + [127.557189, 44.575488], + [127.392733, 44.632158], + [127.275705, 44.640249], + [127.261538, 44.61299], + [127.214111, 44.624917], + [127.228893, 44.642804], + [127.182082, 44.644507], + [127.138966, 44.607451], + [127.094619, 44.615972], + [127.089691, 44.593816], + [127.049655, 44.566961], + [127.041648, 44.591258], + [127.044112, 44.653874], + [127.030561, 44.673454], + [127.041032, 44.712169], + [126.9973, 44.764882], + [126.984366, 44.823914], + [126.999764, 44.87398], + [127.021938, 44.898997], + [127.073061, 44.907051], + [127.092771, 44.94688], + [127.050271, 45.004034], + [127.018242, 45.024341], + [126.984981, 45.067893], + [126.970815, 45.070852], + [126.96404, 45.132104], + [126.85625, 45.145613], + [126.792808, 45.135481], + [126.787265, 45.159118], + [126.732446, 45.187385], + [126.685635, 45.187807], + [126.640055, 45.214373], + [126.644983, 45.225334], + [126.569222, 45.252725], + [126.540273, 45.23882], + [126.519331, 45.248091], + [126.402919, 45.222805], + [126.356107, 45.185698], + [126.293282, 45.180214], + [126.285274, 45.162494], + [126.235383, 45.140125], + [126.225528, 45.154054], + [126.166398, 45.13337], + [126.142992, 45.147723], + [126.091869, 45.149411], + [126.047522, 45.170933], + [125.998247, 45.162072], + [125.992703, 45.192447], + [125.957595, 45.201303], + [125.915095, 45.196664], + [125.849805, 45.23882], + [125.823936, 45.237978], + [125.815929, 45.264942], + [125.761726, 45.291472], + [125.726001, 45.336503], + [125.695205, 45.352066], + [125.712451, 45.389485], + [125.711835, 45.477677], + [125.687813, 45.514173], + [125.660096, 45.507043], + [125.61698, 45.517947], + [125.583104, 45.491942], + [125.497488, 45.469283], + [125.480242, 45.486488], + [125.424807, 45.485649], + [125.434662, 45.462988], + [125.398322, 45.416797], + [125.361981, 45.392847], + [125.319482, 45.422678], + [125.301619, 45.402092], + [125.248649, 45.417637], + [125.189518, 45.39915], + [125.137779, 45.409655], + [125.097127, 45.38276], + [125.06633, 45.39915], + [125.08912, 45.420998], + [125.0497, 45.428558], + [125.025678, 45.493201], + [124.961005, 45.495299], + [124.936983, 45.53388], + [124.911114, 45.535976], + [124.884628, 45.495299], + [124.886476, 45.442836], + [124.839665, 45.455852], + [124.792853, 45.436958], + [124.776223, 45.468024], + [124.729412, 45.444096], + [124.690607, 45.452493], + [124.625318, 45.437377], + [124.575427, 45.451234], + [124.579738, 45.424358], + [124.544014, 45.411756], + [124.507058, 45.424778], + [124.480572, 45.456271], + [124.398652, 45.440737], + [124.374015, 45.45795], + [124.352457, 45.496557], + [124.369087, 45.512915], + [124.348761, 45.546874], + [124.287783, 45.539329], + [124.264377, 45.555256], + [124.273001, 45.584163], + [124.238508, 45.591702], + [124.226805, 45.633564], + [124.162132, 45.616404], + [124.128255, 45.641933], + [124.147349, 45.665359], + [124.122096, 45.669123], + [124.13503, 45.690448], + [124.10177, 45.700898], + [124.098074, 45.722628], + [124.054342, 45.751449], + [124.014922, 45.749779], + [124.001987, 45.770655], + [124.064197, 45.802372], + [124.03648, 45.83824], + [124.067277, 45.840325], + [124.061118, 45.886168], + [123.996444, 45.906993], + [123.968727, 45.936551], + [123.973654, 45.973997], + [124.011842, 45.981899], + [123.989053, 46.011833], + [124.040176, 46.01973], + [124.034016, 46.045074], + [124.009995, 46.057534], + [124.015538, 46.088257], + [123.99398, 46.101123], + [124.01677, 46.118549], + [123.991516, 46.143019], + [124.001987, 46.166649], + [123.971806, 46.170379], + [123.956408, 46.206009], + [123.979814, 46.228784], + [123.952096, 46.256516], + [123.960103, 46.288369], + [123.936082, 46.286715], + [123.917604, 46.25693], + [123.896046, 46.303668], + [123.84985, 46.302428], + [123.775938, 46.263136], + [123.726047, 46.255688], + [123.673692, 46.258585], + [123.604706, 46.251964], + [123.569598, 46.223816], + [123.569598, 46.223816], + [123.499381, 46.259826], + [123.452569, 46.233338], + [123.430396, 46.243687], + [123.357099, 46.232096], + [123.357099, 46.232096], + [123.320758, 46.254447], + [123.286266, 46.250308], + [123.248078, 46.273065], + [123.178476, 46.248239], + [123.128585, 46.210565], + [123.127354, 46.174523], + [123.102716, 46.172037], + [123.112571, 46.130163], + [123.070071, 46.123527], + [123.04605, 46.099878], + [122.792898, 46.073313], + [122.828623, 45.912406], + [122.80029, 45.856583], + [122.772572, 45.856583], + [122.752246, 45.834905], + [122.792283, 45.766063], + [122.751015, 45.735996], + [122.741775, 45.705077], + [122.671558, 45.70048], + [122.650001, 45.731401], + [122.640761, 45.771072], + [122.603189, 45.778169], + [122.556378, 45.82156], + [122.522501, 45.786933], + [122.504639, 45.786933], + [122.496016, 45.85825], + [122.446125, 45.916986], + [122.362357, 45.917403], + [122.372828, 45.856166], + [122.337719, 45.859917], + [122.301379, 45.813218], + [122.253952, 45.7982], + [122.236705, 45.831569], + [122.200981, 45.857], + [122.091344, 45.882002], + [122.085184, 45.912406], + [122.040221, 45.959022], + [121.92812, 45.988552], + [121.923808, 46.004767], + [121.864062, 46.002272], + [121.843736, 46.024301], + [121.819098, 46.023054], + [121.761816, 45.998947], + [121.809243, 45.961102], + [121.821562, 45.918235], + [121.805548, 45.900746], + [121.817251, 45.875336], + [121.769823, 45.84366], + [121.766744, 45.830318], + [121.766744, 45.830318], + [121.754425, 45.794862], + [121.697142, 45.76314], + [121.657106, 45.770238], + [121.644172, 45.752284], + [121.666345, 45.727641], + [121.713773, 45.701734], + [121.811091, 45.687103], + [121.812323, 45.704659], + [121.867142, 45.719703], + [121.934279, 45.71051], + [121.970004, 45.692956], + [122.003264, 45.623102], + [121.995873, 45.59882], + [121.966308, 45.596308], + [121.993409, 45.552741], + [122.002648, 45.507882], + [122.064242, 45.472641], + [122.168336, 45.439897], + [122.180039, 45.409655], + [122.146778, 45.374352], + [122.147394, 45.295682], + [122.239169, 45.276313], + [122.22993, 45.206784], + [122.192358, 45.180636], + [122.143082, 45.183167], + [122.109822, 45.142236], + [122.119677, 45.068739], + [122.098735, 45.02138], + [122.074713, 45.006573], + [122.087032, 44.95281], + [122.079025, 44.914256], + [122.04946, 44.912985], + [122.098119, 44.81882], + [122.099967, 44.7823], + [122.168952, 44.770405], + [122.142467, 44.753833], + [122.110438, 44.767856], + [122.10243, 44.736406], + [122.152322, 44.744057], + [122.161561, 44.728328], + [122.117213, 44.701961], + [122.103046, 44.67388], + [122.113517, 44.615546], + [122.13138, 44.577619], + [122.196053, 44.559712], + [122.224386, 44.526016], + [122.228082, 44.480345], + [122.28598, 44.477783], + [122.294604, 44.41113], + [122.291524, 44.310152], + [122.271198, 44.255741], + [122.319241, 44.233018], + [122.483081, 44.236877], + [122.515726, 44.251025], + [122.641993, 44.283595], + [122.675254, 44.285738], + [122.702971, 44.319145], + [122.76087, 44.369648], + [122.85634, 44.398304], + [123.025108, 44.493153], + [123.06576, 44.505959], + [123.12489, 44.5098], + [123.137209, 44.486322], + [123.125506, 44.455147], + [123.142136, 44.428228], + [123.114419, 44.40258], + [123.128585, 44.367081], + [123.196955, 44.34483], + [123.277027, 44.25274], + [123.286882, 44.211574], + [123.323838, 44.179823], + [123.386664, 44.161794], + [123.362642, 44.133452], + [123.350939, 44.092633], + [123.32815, 44.084035], + [123.331229, 44.028984], + [123.365722, 44.013922], + [123.400831, 43.979481], + [123.37065, 43.970006], + [123.397135, 43.954929], + [123.467968, 43.853599], + [123.461809, 43.822518], + [123.498149, 43.771114], + [123.48275, 43.737396], + [123.520323, 43.708419], + [123.518475, 43.682024], + [123.536953, 43.633964], + [123.510468, 43.624867], + [123.5117, 43.592801], + [123.421157, 43.598435], + [123.434091, 43.575461], + [123.461193, 43.568523], + [123.452569, 43.545971], + [123.452569, 43.545971], + [123.360179, 43.567223], + [123.304744, 43.550742], + [123.329998, 43.519071], + [123.315831, 43.492159], + [123.36449, 43.483475], + [123.382968, 43.469143], + [123.419925, 43.410046], + [123.442098, 43.437863], + [123.486446, 43.44525], + [123.519707, 43.402219], + [123.54496, 43.415262], + [123.608402, 43.366119], + [123.703873, 43.37047], + [123.710032, 43.417001], + [123.749452, 43.439167], + [123.747604, 43.472184], + [123.79688, 43.489988], + [123.857858, 43.459153], + [123.857858, 43.459153], + [123.852314, 43.406133], + [123.881263, 43.392218], + [123.881263, 43.392218], + [123.896046, 43.361333], + [123.964415, 43.34088], + [124.032784, 43.280786], + [124.099306, 43.292983], + [124.117168, 43.2773], + [124.114088, 43.247229], + [124.168291, 43.244177], + [124.215102, 43.255947], + [124.228653, 43.235022], + [124.27608, 43.233278], + [124.287167, 43.207983], + [124.273617, 43.17875], + [124.366007, 43.121554], + [124.425754, 43.076107], + [124.333363, 42.997371], + [124.369703, 42.972854], + [124.42329, 42.975482], + [124.442384, 42.958841], + [124.431913, 42.930803], + [124.38079, 42.912835], + [124.371551, 42.880831], + [124.435609, 42.880831], + [124.466406, 42.847054], + [124.586514, 42.905384], + [124.607456, 42.937376], + [124.632093, 42.949642], + [124.635173, 42.972854], + [124.658579, 42.972854], + [124.677673, 43.002185], + [124.686912, 43.051185], + [124.719557, 43.069987], + [124.755281, 43.074359], + [124.785462, 43.117185], + [124.882781, 43.13422], + [124.88894, 43.074796], + [124.840897, 43.032377], + [124.869846, 42.988178], + [124.87231, 42.962344], + [124.84952, 42.882585], + [124.856911, 42.824234], + [124.874157, 42.789987], + [124.897563, 42.787791], + [124.92836, 42.819844], + [124.975171, 42.802722], + [124.996729, 42.745174], + [124.968396, 42.722756], + [124.99057, 42.677455], + [125.014592, 42.666014], + [125.010896, 42.63212], + [125.038613, 42.615387], + [125.097127, 42.622433], + [125.082961, 42.591159], + [125.089736, 42.567803], + [125.066946, 42.534738], + [125.090968, 42.515773], + [125.068794, 42.499449], + [125.105135, 42.490624], + [125.150098, 42.458842], + [125.140243, 42.44692], + [125.186439, 42.427928], + [125.185823, 42.38197], + [125.203685, 42.366938], + [125.167345, 42.351903], + [125.175352, 42.308102], + [125.224011, 42.30102], + [125.264047, 42.312528], + [125.299156, 42.289953], + [125.27575, 42.266928], + [125.27575, 42.231045], + [125.312706, 42.219966], + [125.280677, 42.175187], + [125.312706, 42.197359], + [125.305931, 42.146351], + [125.357054, 42.145464], + [125.368141, 42.182726], + [125.41372, 42.156112], + [125.458068, 42.160105], + [125.458068, 42.160105], + [125.490097, 42.136145], + [125.446365, 42.098411], + [125.414336, 42.101964], + [125.416184, 42.063766], + [125.363213, 42.017097], + [125.369989, 42.002868], + [125.29854, 41.974399], + [125.291764, 41.958825], + [125.35151, 41.92811], + [125.307779, 41.924548], + [125.294844, 41.822945], + [125.319482, 41.776993], + [125.319482, 41.776993], + [125.323177, 41.771191], + [125.323177, 41.771191], + [125.336112, 41.768067], + [125.336112, 41.768067], + [125.332416, 41.711354], + [125.317018, 41.676944], + [125.344119, 41.672474], + [125.412488, 41.691246], + [125.446981, 41.67605], + [125.461148, 41.642516], + [125.450061, 41.597777], + [125.479626, 41.544946], + [125.507343, 41.534195], + [125.493176, 41.509103], + [125.533212, 41.479069], + [125.534444, 41.428833], + [125.547995, 41.401006], + [125.581256, 41.396517], + [125.589879, 41.359245], + [125.610205, 41.365084], + [125.637306, 41.34442], + [125.62006, 41.318355], + [125.642234, 41.296327], + [125.646545, 41.264396], + [125.685349, 41.273842], + [125.695205, 41.244599], + [125.749407, 41.245499], + [125.758646, 41.232449], + [125.73832, 41.178418], + [125.791291, 41.167607], + [125.759878, 41.132908], + [125.734009, 41.125695], + [125.712451, 41.095485], + [125.739552, 41.08917], + [125.726617, 41.055332], + [125.684118, 41.021929], + [125.674879, 40.974503], + [125.650241, 40.970888], + [125.635458, 40.94151], + [125.589263, 40.931112], + [125.584335, 40.891764], + [125.652089, 40.91619], + [125.687813, 40.897645], + [125.707523, 40.866877], + [125.778356, 40.897645], + [125.817161, 40.866877], + [125.860892, 40.888597], + [125.875059, 40.908501], + [125.921254, 40.882715], + [125.959442, 40.88181], + [126.008102, 40.936537], + [126.041362, 40.928851], + [126.051833, 40.96185], + [126.08263, 40.976762], + [126.066, 40.997542], + [126.1085, 41.011995], + [126.099877, 41.036376], + [126.133753, 41.063906], + [126.124514, 41.092327], + [126.16763, 41.094583], + [126.187956, 41.113072], + [126.188572, 41.114875], + [126.295129, 41.171661], + [126.332086, 41.236949], + [126.35426, 41.244599], + [126.373354, 41.289133], + [126.437411, 41.353405], + [126.497158, 41.374965], + [126.524259, 41.349362], + [126.539041, 41.366881], + [126.497158, 41.406842], + [126.559983, 41.548081], + [126.582773, 41.563307], + [126.564295, 41.608965], + [126.592628, 41.624624], + [126.608027, 41.669345], + [126.644983, 41.661297], + [126.688099, 41.674262], + [126.724439, 41.710907], + [126.690562, 41.728328], + [126.694874, 41.751103], + [126.723207, 41.753335], + [126.8002, 41.702865], + [126.809439, 41.749317], + [126.848243, 41.734134], + [126.85625, 41.760031], + [126.887047, 41.791719], + [126.931395, 41.812687], + [126.952953, 41.804212], + [126.940018, 41.773423], + [126.979438, 41.776993], + [127.005923, 41.749317], + [127.050887, 41.744852], + [127.057662, 41.703758], + [127.037952, 41.676944], + [127.103242, 41.647883], + [127.093387, 41.629993], + [127.127263, 41.622388], + [127.135887, 41.600463], + [127.178386, 41.600015], + [127.125416, 41.566442], + [127.11864, 41.540018], + [127.164836, 41.542706], + [127.188241, 41.527475], + [127.241212, 41.520754], + [127.28864, 41.501932], + [127.253531, 41.486691], + [127.296031, 41.486243], + [127.360704, 41.466065], + [127.360088, 41.479518], + [127.405668, 41.478621], + [127.419835, 41.460235], + [127.459255, 41.461581], + [127.465414, 41.479069], + [127.526392, 41.467859], + [127.547334, 41.477276], + [127.563964, 41.432871], + [127.618783, 41.432871], + [127.636645, 41.413575], + [127.684073, 41.422999], + [127.780159, 41.427038], + [127.854688, 41.420755], + [127.86947, 41.4037], + [127.882405, 41.448124], + [127.909506, 41.42973], + [127.93168, 41.444984], + [127.970484, 41.438704], + [127.991426, 41.421204], + [128.000049, 41.442741], + [128.040085, 41.393375], + [128.110919, 41.393375], + [128.090593, 41.374516], + [128.114614, 41.364186], + [128.169433, 41.404149], + [128.203925, 41.410882], + [128.243345, 41.477276], + [128.238418, 41.497898], + [128.301244, 41.540018], + [128.317874, 41.575844], + [128.30186, 41.627756], + [128.248889, 41.681414], + [128.208853, 41.688565], + [128.163889, 41.721628], + [128.147875, 41.78101], + [128.112766, 41.793504], + [128.104143, 41.843457], + [128.115846, 41.896935], + [128.106607, 41.949923], + [128.033926, 42.000199], + [128.090593, 42.022877], + [128.294468, 42.026434], + [128.405338, 42.018876], + [128.466316, 42.020654], + [128.49896, 42.000644], + [128.598127, 42.007315], + [128.60675, 42.02999], + [128.637547, 42.035324], + [128.658489, 42.018876], + [128.70222, 42.02021], + [128.737945, 42.050435], + [128.779213, 42.033546], + [128.795227, 42.042436], + [128.898089, 42.016653], + [128.952908, 42.025545], + [128.954755, 42.083756], + [128.971386, 42.097079], + [129.008958, 42.09175], + [129.039139, 42.107736], + [129.048378, 42.137476], + [129.113668, 42.140583], + [129.166639, 42.188047], + [129.215914, 42.208442], + [129.209138, 42.237692], + [129.181421, 42.242122], + [129.183269, 42.262056], + [129.215914, 42.265157], + [129.231312, 42.283755], + [129.208522, 42.293052], + [129.260261, 42.335536], + [129.231312, 42.356325], + [129.240551, 42.376223], + [129.326167, 42.389927], + [129.30892, 42.403628], + [129.331094, 42.429695], + [129.356348, 42.427045], + [129.342181, 42.441179], + [129.368051, 42.459284], + [129.366203, 42.428811], + [129.392688, 42.42837], + [129.400695, 42.449128], + [129.452434, 42.441179], + [129.49863, 42.412023], + [129.546057, 42.361632], + [129.578086, 42.380202], + [129.569463, 42.399208], + [129.601492, 42.415116] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 230000, + "name": "黑龙江省", + "center": [126.642464, 45.756967], + "centroid": [127.693027, 48.040465], + "childrenNum": 13, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 7, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [123.569598, 46.223816], + [123.604706, 46.251964], + [123.673692, 46.258585], + [123.726047, 46.255688], + [123.775938, 46.263136], + [123.84985, 46.302428], + [123.896046, 46.303668], + [123.917604, 46.25693], + [123.936082, 46.286715], + [123.960103, 46.288369], + [123.952096, 46.256516], + [123.979814, 46.228784], + [123.956408, 46.206009], + [123.971806, 46.170379], + [124.001987, 46.166649], + [123.991516, 46.143019], + [124.01677, 46.118549], + [123.99398, 46.101123], + [124.015538, 46.088257], + [124.009995, 46.057534], + [124.034016, 46.045074], + [124.040176, 46.01973], + [123.989053, 46.011833], + [124.011842, 45.981899], + [123.973654, 45.973997], + [123.968727, 45.936551], + [123.996444, 45.906993], + [124.061118, 45.886168], + [124.067277, 45.840325], + [124.03648, 45.83824], + [124.064197, 45.802372], + [124.001987, 45.770655], + [124.014922, 45.749779], + [124.054342, 45.751449], + [124.098074, 45.722628], + [124.10177, 45.700898], + [124.13503, 45.690448], + [124.122096, 45.669123], + [124.147349, 45.665359], + [124.128255, 45.641933], + [124.162132, 45.616404], + [124.226805, 45.633564], + [124.238508, 45.591702], + [124.273001, 45.584163], + [124.264377, 45.555256], + [124.287783, 45.539329], + [124.348761, 45.546874], + [124.369087, 45.512915], + [124.352457, 45.496557], + [124.374015, 45.45795], + [124.398652, 45.440737], + [124.480572, 45.456271], + [124.507058, 45.424778], + [124.544014, 45.411756], + [124.579738, 45.424358], + [124.575427, 45.451234], + [124.625318, 45.437377], + [124.690607, 45.452493], + [124.729412, 45.444096], + [124.776223, 45.468024], + [124.792853, 45.436958], + [124.839665, 45.455852], + [124.886476, 45.442836], + [124.884628, 45.495299], + [124.911114, 45.535976], + [124.936983, 45.53388], + [124.961005, 45.495299], + [125.025678, 45.493201], + [125.0497, 45.428558], + [125.08912, 45.420998], + [125.06633, 45.39915], + [125.097127, 45.38276], + [125.137779, 45.409655], + [125.189518, 45.39915], + [125.248649, 45.417637], + [125.301619, 45.402092], + [125.319482, 45.422678], + [125.361981, 45.392847], + [125.398322, 45.416797], + [125.434662, 45.462988], + [125.424807, 45.485649], + [125.480242, 45.486488], + [125.497488, 45.469283], + [125.583104, 45.491942], + [125.61698, 45.517947], + [125.660096, 45.507043], + [125.687813, 45.514173], + [125.711835, 45.477677], + [125.712451, 45.389485], + [125.695205, 45.352066], + [125.726001, 45.336503], + [125.761726, 45.291472], + [125.815929, 45.264942], + [125.823936, 45.237978], + [125.849805, 45.23882], + [125.915095, 45.196664], + [125.957595, 45.201303], + [125.992703, 45.192447], + [125.998247, 45.162072], + [126.047522, 45.170933], + [126.091869, 45.149411], + [126.142992, 45.147723], + [126.166398, 45.13337], + [126.225528, 45.154054], + [126.235383, 45.140125], + [126.285274, 45.162494], + [126.293282, 45.180214], + [126.356107, 45.185698], + [126.402919, 45.222805], + [126.519331, 45.248091], + [126.540273, 45.23882], + [126.569222, 45.252725], + [126.644983, 45.225334], + [126.640055, 45.214373], + [126.685635, 45.187807], + [126.732446, 45.187385], + [126.787265, 45.159118], + [126.792808, 45.135481], + [126.85625, 45.145613], + [126.96404, 45.132104], + [126.970815, 45.070852], + [126.984981, 45.067893], + [127.018242, 45.024341], + [127.050271, 45.004034], + [127.092771, 44.94688], + [127.073061, 44.907051], + [127.021938, 44.898997], + [126.999764, 44.87398], + [126.984366, 44.823914], + [126.9973, 44.764882], + [127.041032, 44.712169], + [127.030561, 44.673454], + [127.044112, 44.653874], + [127.041648, 44.591258], + [127.049655, 44.566961], + [127.089691, 44.593816], + [127.094619, 44.615972], + [127.138966, 44.607451], + [127.182082, 44.644507], + [127.228893, 44.642804], + [127.214111, 44.624917], + [127.261538, 44.61299], + [127.275705, 44.640249], + [127.392733, 44.632158], + [127.557189, 44.575488], + [127.570124, 44.55033], + [127.536247, 44.522176], + [127.485124, 44.528576], + [127.465414, 44.516628], + [127.463566, 44.484615], + [127.50853, 44.437202], + [127.486356, 44.410275], + [127.579363, 44.310581], + [127.623711, 44.278025], + [127.59045, 44.227872], + [127.626174, 44.187977], + [127.641573, 44.193555], + [127.681609, 44.166946], + [127.712406, 44.199133], + [127.735811, 44.11412], + [127.729036, 44.09908], + [127.783239, 44.071997], + [127.808492, 44.086615], + [127.846065, 44.081886], + [127.862695, 44.062967], + [127.912586, 44.064687], + [127.950158, 44.088334], + [128.042549, 44.103807], + [128.091208, 44.133022], + [128.088129, 44.158359], + [128.060411, 44.168663], + [128.09244, 44.181539], + [128.104143, 44.230017], + [128.064107, 44.251454], + [128.101679, 44.293449], + [128.065339, 44.307155], + [128.049941, 44.349965], + [128.074578, 44.370075], + [128.094904, 44.354673], + [128.137404, 44.357668], + [128.172512, 44.34697], + [128.211317, 44.431647], + [128.228563, 44.445748], + [128.293237, 44.467961], + [128.295084, 44.480772], + [128.372693, 44.514495], + [128.397946, 44.483761], + [128.427511, 44.473512], + [128.463236, 44.431647], + [128.457076, 44.409848], + [128.481714, 44.375637], + [128.475555, 44.346114], + [128.446605, 44.339694], + [128.472475, 44.320001], + [128.453997, 44.257884], + [128.471859, 44.247596], + [128.450301, 44.203423], + [128.471859, 44.157501], + [128.529141, 44.112401], + [128.574721, 44.047914], + [128.584576, 43.990246], + [128.610445, 43.960529], + [128.64001, 43.948035], + [128.636315, 43.891132], + [128.696061, 43.903207], + [128.729938, 43.889838], + [128.760734, 43.857482], + [128.719467, 43.816905], + [128.739177, 43.806972], + [128.760119, 43.755554], + [128.729322, 43.736964], + [128.768126, 43.732207], + [128.78722, 43.686784], + [128.821097, 43.637429], + [128.834647, 43.587599], + [128.878379, 43.539898], + [128.949828, 43.553779], + [128.962763, 43.53903], + [129.013886, 43.522976], + [129.037907, 43.540332], + [129.093958, 43.547706], + [129.145081, 43.570258], + [129.169102, 43.561585], + [129.23008, 43.593234], + [129.232544, 43.635263], + [129.217146, 43.648689], + [129.214066, 43.695006], + [129.232544, 43.709284], + [129.211602, 43.784509], + [129.254718, 43.819496], + [129.289826, 43.797038], + [129.30892, 43.812155], + [129.348341, 43.798333], + [129.406855, 43.819496], + [129.417942, 43.843672], + [129.449971, 43.850578], + [129.467833, 43.874741], + [129.529427, 43.870427], + [129.650767, 43.873016], + [129.699426, 43.8838], + [129.743158, 43.876035], + [129.739462, 43.895876], + [129.780114, 43.892857], + [129.802904, 43.964837], + [129.868193, 44.012631], + [129.881128, 44.000148], + [129.907614, 44.023821], + [129.951345, 44.027263], + [129.979062, 44.015644], + [130.017867, 43.961821], + [130.022794, 43.917866], + [130.009243, 43.889407], + [130.027722, 43.851872], + [130.079461, 43.835039], + [130.110873, 43.852735], + [130.116417, 43.878192], + [130.143518, 43.878624], + [130.153373, 43.915711], + [130.208192, 43.948466], + [130.262395, 43.949328], + [130.27225, 43.981634], + [130.307358, 44.002731], + [130.319061, 44.03974], + [130.365256, 44.044042], + [130.364025, 43.992399], + [130.338155, 43.963975], + [130.381887, 43.910106], + [130.368336, 43.894151], + [130.386198, 43.85403], + [130.362793, 43.844967], + [130.381887, 43.817768], + [130.382503, 43.777164], + [130.423155, 43.745179], + [130.394206, 43.703227], + [130.412684, 43.652586], + [130.437937, 43.646091], + [130.488444, 43.65605], + [130.501995, 43.636563], + [130.57098, 43.626167], + [130.57098, 43.626167], + [130.630726, 43.622268], + [130.623335, 43.589767], + [130.665835, 43.583698], + [130.671378, 43.565054], + [130.727429, 43.560284], + [130.776704, 43.52341], + [130.822899, 43.503446], + [130.841378, 43.454374], + [130.864167, 43.437863], + [130.907283, 43.434387], + [130.959638, 43.48608], + [131.026775, 43.508655], + [131.142572, 43.425695], + [131.175217, 43.444816], + [131.201086, 43.442209], + [131.234963, 43.475224], + [131.294093, 43.470012], + [131.304564, 43.502144], + [131.276847, 43.495632], + [131.20047, 43.532089], + [131.222028, 43.593234], + [131.216485, 43.613169], + [131.239274, 43.670337], + [131.221412, 43.682024], + [131.215869, 43.72745], + [131.232499, 43.742585], + [131.213405, 43.801357], + [131.2171, 43.836334], + [131.254057, 43.893289], + [131.26268, 43.948897], + [131.245434, 43.95579], + [131.26576, 44.034578], + [131.28239, 44.035868], + [131.287318, 44.03802], + [131.293477, 44.043182], + [131.310723, 44.046623], + [131.111775, 44.710042], + [131.090833, 44.717272], + [131.093297, 44.746183], + [131.069275, 44.759783], + [131.064348, 44.786973], + [131.016304, 44.789521], + [131.015688, 44.814999], + [130.972573, 44.820094], + [130.965181, 44.85065], + [131.07913, 44.881614], + [131.10192, 44.898997], + [131.090217, 44.924427], + [131.16105, 44.948151], + [131.20355, 44.932901], + [131.207861, 44.913833], + [131.263296, 44.929935], + [131.274999, 44.919766], + [131.313803, 44.950692], + [131.313803, 44.965938], + [131.355071, 44.990068], + [131.380324, 44.978216], + [131.409889, 44.985836], + [131.464708, 44.963397], + [131.501664, 44.977793], + [131.484418, 44.99557], + [131.529382, 45.012073], + [131.566338, 45.045487], + [131.63286, 45.075078], + [131.695685, 45.132104], + [131.687678, 45.1511], + [131.650722, 45.159962], + [131.681519, 45.215217], + [131.721555, 45.234606], + [131.759127, 45.213952], + [131.79362, 45.211844], + [131.788692, 45.245984], + [131.825649, 45.291472], + [131.82996, 45.311677], + [131.887858, 45.342393], + [131.917423, 45.339448], + [131.93159, 45.287683], + [131.976554, 45.277156], + [132.003655, 45.25441], + [132.17427, 45.216903], + [132.394161, 45.16376], + [132.76434, 45.081417], + [132.867202, 45.061976], + [132.916477, 45.031109], + [132.954049, 45.023072], + [132.98731, 45.043373], + [133.035969, 45.054366], + [133.070462, 45.097051], + [133.089556, 45.097473], + [133.107418, 45.124504], + [133.139447, 45.127459], + [133.129592, 45.211422], + [133.095715, 45.246827], + [133.110498, 45.266627], + [133.097563, 45.284735], + [133.128976, 45.336924], + [133.119121, 45.352908], + [133.144991, 45.367205], + [133.143759, 45.430658], + [133.164701, 45.437377], + [133.170244, 45.465506], + [133.203505, 45.516689], + [133.246005, 45.517528], + [133.333468, 45.562379], + [133.342707, 45.554836], + [133.393214, 45.580393], + [133.423395, 45.584163], + [133.412924, 45.618079], + [133.471438, 45.631053], + [133.448649, 45.647372], + [133.485605, 45.658667], + [133.484989, 45.691702], + [133.445569, 45.705077], + [133.454192, 45.731819], + [133.486837, 45.740173], + [133.469591, 45.777751], + [133.505315, 45.785681], + [133.469591, 45.799451], + [133.467743, 45.834905], + [133.494228, 45.840325], + [133.491764, 45.867002], + [133.51209, 45.887001], + [133.55459, 45.893249], + [133.583539, 45.868669], + [133.618032, 45.903662], + [133.614952, 45.942794], + [133.676546, 45.94321], + [133.681474, 45.986473], + [133.740604, 46.048812], + [133.745531, 46.075389], + [133.690713, 46.133896], + [133.706111, 46.163333], + [133.764626, 46.17328], + [133.794807, 46.193583], + [133.814517, 46.230854], + [133.849625, 46.203939], + [133.87919, 46.233752], + [133.867487, 46.250722], + [133.909987, 46.254447], + [133.91861, 46.280924], + [133.908139, 46.308216], + [133.922922, 46.330948], + [133.869335, 46.338386], + [133.876726, 46.362345], + [133.940784, 46.38134], + [133.948791, 46.401153], + [133.902596, 46.446119], + [133.852089, 46.450242], + [133.849625, 46.475389], + [133.890893, 46.525235], + [133.919842, 46.596012], + [134.011001, 46.637941], + [134.030711, 46.708981], + [134.033175, 46.759023], + [134.052885, 46.779928], + [134.025168, 46.810657], + [134.041182, 46.848326], + [134.042414, 46.886787], + [134.076291, 46.938298], + [134.063972, 46.979962], + [134.10216, 47.005678], + [134.118175, 47.061968], + [134.142812, 47.093349], + [134.222268, 47.105164], + [134.232739, 47.134892], + [134.230276, 47.182097], + [134.210566, 47.210155], + [134.156979, 47.248357], + [134.177305, 47.326299], + [134.203174, 47.347389], + [134.263536, 47.371307], + [134.266616, 47.391974], + [134.307268, 47.428829], + [134.339297, 47.439759], + [134.490202, 47.446235], + [134.522847, 47.468086], + [134.568426, 47.478199], + [134.576434, 47.519036], + [134.627556, 47.546512], + [134.678064, 47.588507], + [134.689766, 47.63813], + [134.779694, 47.7159], + [134.772918, 47.763391], + [134.678679, 47.819278], + [134.670056, 47.864667], + [134.677448, 47.884738], + [134.658969, 47.901191], + [134.607846, 47.909214], + [134.599839, 47.947711], + [134.55426, 47.982173], + [134.551796, 48.032622], + [134.632484, 48.099412], + [134.67252, 48.170505], + [134.679295, 48.256245], + [134.77107, 48.288908], + [134.864077, 48.332293], + [135.009439, 48.365703], + [135.090743, 48.403461], + [135.09567, 48.437618], + [135.068569, 48.459451], + [135.035924, 48.440795], + [134.996504, 48.439603], + [134.927519, 48.451513], + [134.886867, 48.437618], + [134.848679, 48.393925], + [134.820961, 48.37604], + [134.764295, 48.370076], + [134.704549, 48.405448], + [134.640491, 48.409818], + [134.578281, 48.405448], + [134.501905, 48.418954], + [134.438463, 48.405448], + [134.369478, 48.382797], + [134.20379, 48.3824], + [134.150819, 48.346217], + [134.116327, 48.333089], + [134.0689, 48.338659], + [134.029479, 48.327519], + [133.995603, 48.303639], + [133.940784, 48.302047], + [133.876111, 48.282536], + [133.824372, 48.277359], + [133.791111, 48.261026], + [133.740604, 48.254651], + [133.693177, 48.186866], + [133.667307, 48.183275], + [133.59709, 48.194846], + [133.573068, 48.182078], + [133.545967, 48.121389], + [133.451728, 48.112999], + [133.407997, 48.124585], + [133.302055, 48.103009], + [133.239845, 48.126583], + [133.182563, 48.135769], + [133.130208, 48.134971], + [133.053216, 48.110202], + [133.02673, 48.085421], + [133.016259, 48.054228], + [132.992238, 48.035424], + [132.883216, 48.002599], + [132.819159, 47.936887], + [132.769268, 47.93849], + [132.723072, 47.962941], + [132.691043, 47.962941], + [132.661478, 47.944905], + [132.662094, 47.922451], + [132.687348, 47.88514], + [132.662094, 47.854227], + [132.621442, 47.82852], + [132.599268, 47.792347], + [132.6005, 47.740858], + [132.558, 47.718316], + [132.469305, 47.726368], + [132.371987, 47.765402], + [132.325175, 47.762184], + [132.288835, 47.742065], + [132.272205, 47.718718], + [132.242639, 47.70986], + [132.19706, 47.714289], + [132.157024, 47.70543], + [132.086191, 47.703013], + [132.000575, 47.712276], + [131.976554, 47.673201], + [131.900793, 47.685692], + [131.825649, 47.677231], + [131.741881, 47.706638], + [131.690142, 47.707041], + [131.641483, 47.663932], + [131.59036, 47.660707], + [131.568186, 47.682469], + [131.559563, 47.724757], + [131.543548, 47.736028], + [131.456085, 47.747297], + [131.359998, 47.730796], + [131.273767, 47.738846], + [131.236811, 47.733211], + [131.183224, 47.702611], + [131.115471, 47.689721], + [131.029855, 47.694555], + [130.983659, 47.713081], + [130.966413, 47.733211], + [130.961486, 47.828118], + [130.891269, 47.927263], + [130.870943, 47.943301], + [130.770544, 47.998194], + [130.737284, 48.034223], + [130.699711, 48.044227], + [130.666451, 48.105007], + [130.673842, 48.12818], + [130.765617, 48.18926], + [130.769313, 48.231136], + [130.787791, 48.256643], + [130.817972, 48.265409], + [130.845073, 48.296473], + [130.81982, 48.341444], + [130.785327, 48.357353], + [130.747755, 48.404256], + [130.745907, 48.449131], + [130.776704, 48.480084], + [130.767465, 48.507846], + [130.711414, 48.511414], + [130.647357, 48.484844], + [130.620871, 48.49595], + [130.615944, 48.575601], + [130.605473, 48.594207], + [130.538335, 48.612016], + [130.538951, 48.635751], + [130.576524, 48.688719], + [130.622103, 48.783842], + [130.689856, 48.849651], + [130.680617, 48.881146], + [130.609168, 48.881146], + [130.559277, 48.861071], + [130.501995, 48.865795], + [130.471198, 48.905541], + [130.412068, 48.905148], + [130.279641, 48.866976], + [130.237757, 48.868551], + [130.219895, 48.893739], + [130.113337, 48.956653], + [130.059135, 48.979047], + [130.020946, 49.021058], + [129.937179, 49.040285], + [129.9187, 49.060681], + [129.934715, 49.078717], + [129.913157, 49.1085], + [129.866962, 49.113985], + [129.855259, 49.133567], + [129.864498, 49.158621], + [129.847867, 49.181316], + [129.784426, 49.184054], + [129.753629, 49.208692], + [129.761636, 49.25754], + [129.730223, 49.288387], + [129.696962, 49.298535], + [129.604571, 49.279018], + [129.562687, 49.299706], + [129.546057, 49.395227], + [129.51834, 49.423652], + [129.448739, 49.441167], + [129.390224, 49.432605], + [129.374826, 49.414309], + [129.379138, 49.367175], + [129.358196, 49.355871], + [129.320623, 49.3586], + [129.266421, 49.396006], + [129.215298, 49.399122], + [129.180805, 49.386657], + [129.143849, 49.357431], + [129.084719, 49.359769], + [129.061929, 49.374189], + [129.013886, 49.457119], + [128.932582, 49.46801], + [128.871604, 49.492506], + [128.792147, 49.473065], + [128.76135, 49.482009], + [128.763198, 49.515824], + [128.813089, 49.558157], + [128.802618, 49.58222], + [128.744104, 49.595023], + [128.715155, 49.564756], + [128.656025, 49.577564], + [128.619684, 49.593471], + [128.537764, 49.604332], + [128.500192, 49.593859], + [128.389939, 49.58998], + [128.343128, 49.544956], + [128.287077, 49.566309], + [128.243345, 49.563203], + [128.185447, 49.53952], + [128.122005, 49.55311], + [128.070882, 49.556604], + [128.001281, 49.592307], + [127.949542, 49.596187], + [127.897804, 49.579116], + [127.815268, 49.593859], + [127.782007, 49.630698], + [127.705015, 49.665185], + [127.677913, 49.697712], + [127.674833, 49.764247], + [127.653892, 49.780094], + [127.583059, 49.786277], + [127.531936, 49.826059], + [127.529472, 49.864265], + [127.547334, 49.928645], + [127.543638, 49.944438], + [127.495595, 49.994479], + [127.501755, 50.056764], + [127.58737, 50.137768], + [127.60708, 50.178794], + [127.603385, 50.239309], + [127.44632, 50.270686], + [127.371791, 50.29669], + [127.332371, 50.340634], + [127.369944, 50.403996], + [127.3644, 50.438314], + [127.30527, 50.45432], + [127.293567, 50.46575], + [127.323132, 50.52552], + [127.36132, 50.547582], + [127.370559, 50.581415], + [127.294799, 50.663426], + [127.28864, 50.699451], + [127.305886, 50.733932], + [127.295415, 50.755139], + [127.236285, 50.781256], + [127.143894, 50.910111], + [127.113713, 50.93765], + [127.052119, 50.962911], + [126.985597, 51.029202], + [126.922772, 51.061937], + [126.917844, 51.138977], + [126.899982, 51.200518], + [126.926467, 51.246244], + [126.976358, 51.291551], + [126.98375, 51.318863], + [126.970815, 51.332327], + [126.887047, 51.321856], + [126.877808, 51.300906], + [126.908605, 51.283691], + [126.92154, 51.259729], + [126.908605, 51.246619], + [126.863025, 51.248492], + [126.820526, 51.281071], + [126.813134, 51.311756], + [126.837156, 51.345038], + [126.904293, 51.340552], + [126.930163, 51.359241], + [126.908605, 51.407423], + [126.835308, 51.413769], + [126.791577, 51.432428], + [126.784185, 51.448095], + [126.812518, 51.493948], + [126.843931, 51.521885], + [126.837156, 51.536033], + [126.69549, 51.57845], + [126.67886, 51.602246], + [126.741069, 51.642374], + [126.723823, 51.679126], + [126.734294, 51.711399], + [126.724439, 51.7266], + [126.6727, 51.73179], + [126.658534, 51.762544], + [126.622809, 51.777357], + [126.580925, 51.824728], + [126.555056, 51.874266], + [126.510092, 51.922274], + [126.462665, 51.948471], + [126.468208, 51.982395], + [126.447882, 52.009294], + [126.450962, 52.027709], + [126.487918, 52.041699], + [126.514404, 52.037282], + [126.563679, 52.119302], + [126.556288, 52.136203], + [126.499005, 52.16044], + [126.457121, 52.165212], + [126.403535, 52.185031], + [126.34502, 52.192002], + [126.306832, 52.205574], + [126.312992, 52.235271], + [126.357955, 52.264216], + [126.401071, 52.279597], + [126.436795, 52.277034], + [126.4331, 52.298632], + [126.327774, 52.310342], + [126.320999, 52.342163], + [126.348716, 52.357882], + [126.353644, 52.389304], + [126.326542, 52.424353], + [126.268644, 52.475051], + [126.205202, 52.466302], + [126.192883, 52.492181], + [126.213209, 52.525327], + [126.147304, 52.573], + [126.066616, 52.603905], + [126.055529, 52.582455], + [126.030891, 52.576273], + [125.989008, 52.603178], + [125.968682, 52.630429], + [125.971145, 52.654033], + [125.995783, 52.675085], + [126.061688, 52.673271], + [126.072775, 52.691048], + [126.044442, 52.739628], + [126.112195, 52.757016], + [126.116507, 52.768243], + [126.052449, 52.800095], + [126.02042, 52.795753], + [125.985312, 52.758465], + [125.966834, 52.759914], + [125.937269, 52.786705], + [125.923718, 52.815651], + [125.855349, 52.866259], + [125.854117, 52.891542], + [125.827631, 52.899123], + [125.772197, 52.89804], + [125.751255, 52.88143], + [125.722306, 52.880347], + [125.678574, 52.86084], + [125.666871, 52.869872], + [125.665023, 52.913561], + [125.737088, 52.943504], + [125.742632, 52.993964], + [125.684118, 53.00801], + [125.643466, 53.039686], + [125.640386, 53.06199], + [125.613901, 53.083564], + [125.588647, 53.081047], + [125.530749, 53.0512], + [125.504263, 53.061271], + [125.503647, 53.095424], + [125.452524, 53.107641], + [125.343503, 53.14463], + [125.315786, 53.144989], + [125.252344, 53.18051], + [125.195062, 53.198439], + [125.142091, 53.204175], + [125.038613, 53.202741], + [124.970244, 53.194137], + [124.887708, 53.164368], + [124.909266, 53.118059], + [124.87231, 53.099018], + [124.832889, 53.145347], + [124.787926, 53.140681], + [124.734339, 53.146783], + [124.712165, 53.162574], + [124.720789, 53.192344], + [124.678905, 53.207043], + [124.590209, 53.208476], + [124.563108, 53.201666], + [124.496587, 53.207759], + [124.487348, 53.217436], + [124.435609, 53.223886], + [124.412203, 53.248601], + [124.375863, 53.258984], + [124.327819, 53.331954], + [124.239124, 53.379817], + [124.19416, 53.37339], + [124.125791, 53.348033], + [124.058038, 53.404085], + [124.01369, 53.403371], + [123.985973, 53.434401], + [123.865249, 53.489627], + [123.797495, 53.489983], + [123.746373, 53.500308], + [123.698329, 53.498528], + [123.668764, 53.533756], + [123.620721, 53.550115], + [123.58746, 53.546915], + [123.569598, 53.505291], + [123.53141, 53.507071], + [123.557895, 53.531978], + [123.546808, 53.551537], + [123.517243, 53.558292], + [123.490758, 53.542648], + [123.510468, 53.509206], + [123.499381, 53.497816], + [123.47228, 53.509206], + [123.454417, 53.536602], + [123.394055, 53.538024], + [123.309672, 53.56078], + [123.274563, 53.563269], + [123.231447, 53.549404], + [123.179092, 53.509918], + [123.137209, 53.498172], + [123.093477, 53.508138], + [123.052209, 53.506715], + [122.943804, 53.483929], + [122.894528, 53.462914], + [122.826775, 53.457213], + [122.763949, 53.463626], + [122.673406, 53.459351], + [122.608117, 53.465408], + [122.5379, 53.453293], + [122.496016, 53.458638], + [122.435038, 53.444739], + [122.37406, 53.47467], + [122.350038, 53.505647], + [122.266886, 53.470039], + [122.227466, 53.461845], + [122.161561, 53.468614], + [122.111054, 53.426913], + [122.077177, 53.422277], + [122.026054, 53.428339], + [121.875765, 53.426556], + [121.816019, 53.41336], + [121.754425, 53.389454], + [121.697758, 53.392666], + [121.589969, 53.350891], + [121.499426, 53.337314], + [121.504969, 53.323018], + [121.575802, 53.29155], + [121.615222, 53.258984], + [121.642324, 53.262564], + [121.679896, 53.240722], + [121.67928, 53.199515], + [121.660186, 53.195213], + [121.665114, 53.170467], + [121.722396, 53.145706], + [121.753193, 53.147501], + [121.784606, 53.104408], + [121.775367, 53.089674], + [121.817867, 53.061631], + [121.785838, 53.018451], + [121.715621, 52.997926], + [121.677432, 52.948192], + [121.66265, 52.912478], + [121.610295, 52.892264], + [121.604136, 52.872401], + [121.620766, 52.853251], + [121.591201, 52.824693], + [121.537614, 52.801542], + [121.511129, 52.779104], + [121.476636, 52.772225], + [121.455078, 52.73528], + [121.373158, 52.683067], + [121.309717, 52.676173], + [121.29247, 52.651855], + [121.237036, 52.619167], + [121.182217, 52.59918], + [121.225333, 52.577364], + [121.280151, 52.586819], + [121.323883, 52.573727], + [121.353448, 52.534793], + [121.411963, 52.52205], + [121.416274, 52.499468], + [121.474172, 52.482706], + [121.495114, 52.484892], + [121.519136, 52.456821], + [121.565331, 52.460468], + [121.590585, 52.443326], + [121.63986, 52.44442], + [121.678664, 52.419973], + [121.658338, 52.3904], + [121.715621, 52.342894], + [121.714389, 52.318025], + [121.769207, 52.308147], + [121.841272, 52.282526], + [121.901018, 52.280695], + [121.94783, 52.298266], + [121.976779, 52.343626], + [122.035909, 52.377615], + [122.040837, 52.413038], + [122.091344, 52.427272], + [122.080873, 52.440407], + [122.107358, 52.452445], + [122.142467, 52.495096], + [122.140003, 52.510032], + [122.168952, 52.513674], + [122.178191, 52.48963], + [122.207756, 52.469218], + [122.310618, 52.475416], + [122.326016, 52.459374], + [122.342031, 52.414133], + [122.367284, 52.413768], + [122.378987, 52.395512], + [122.419023, 52.375057], + [122.447356, 52.394052], + [122.484313, 52.341432], + [122.478153, 52.29607], + [122.560689, 52.282526], + [122.585943, 52.266413], + [122.67895, 52.276667], + [122.710979, 52.256157], + [122.76087, 52.26678], + [122.787355, 52.252494], + [122.766413, 52.232705], + [122.769493, 52.179893], + [122.73808, 52.153464], + [122.690653, 52.140243], + [122.629059, 52.13657], + [122.643841, 52.111585], + [122.625363, 52.067459], + [122.650616, 52.058997], + [122.664783, 51.99861], + [122.683877, 51.974654], + [122.726377, 51.978709], + [122.729457, 51.919321], + [122.706051, 51.890151], + [122.725761, 51.87833], + [122.732536, 51.832495], + [122.771957, 51.779579], + [122.749167, 51.746613], + [122.778732, 51.698048], + [122.816304, 51.655371], + [122.820616, 51.633088], + [122.85634, 51.606707], + [122.832935, 51.581797], + [122.874202, 51.561339], + [122.880362, 51.537894], + [122.858804, 51.524864], + [122.880362, 51.511085], + [122.854492, 51.477551], + [122.871123, 51.455181], + [122.900072, 51.445112], + [122.903768, 51.415262], + [122.946267, 51.405183], + [122.965977, 51.386886], + [122.965977, 51.345786], + [123.002934, 51.31213], + [123.069455, 51.321108], + [123.127969, 51.297913], + [123.231447, 51.279199], + [123.231447, 51.268716], + [123.294273, 51.254111], + [123.339853, 51.27246], + [123.376809, 51.266844], + [123.414381, 51.278825], + [123.440251, 51.270963], + [123.46304, 51.286686], + [123.582533, 51.294545], + [123.582533, 51.306893], + [123.661989, 51.319237], + [123.660141, 51.342795], + [123.711264, 51.398089], + [123.794416, 51.361109], + [123.842459, 51.367462], + [123.887423, 51.320734], + [123.926227, 51.300532], + [123.939777, 51.313253], + [123.994596, 51.322604], + [124.071588, 51.320734], + [124.090067, 51.3413], + [124.128255, 51.347281], + [124.192313, 51.33943], + [124.239124, 51.344664], + [124.271769, 51.308389], + [124.297638, 51.298661], + [124.339522, 51.293422], + [124.406659, 51.272086], + [124.430065, 51.301281], + [124.426985, 51.331953], + [124.443616, 51.35812], + [124.478108, 51.36223], + [124.490427, 51.380537], + [124.555717, 51.375307], + [124.58713, 51.363725], + [124.62655, 51.327465], + [124.693687, 51.3327], + [124.752817, 51.35812], + [124.76452, 51.38726], + [124.783614, 51.392115], + [124.864302, 51.37979], + [124.885244, 51.40817], + [124.942527, 51.447349], + [124.917889, 51.474196], + [124.928976, 51.498419], + [124.983795, 51.508478], + [125.004737, 51.529332], + [125.047236, 51.529704], + [125.073106, 51.553526], + [125.060171, 51.59667], + [125.098975, 51.658341], + [125.12854, 51.659083], + [125.130388, 51.635317], + [125.175968, 51.639403], + [125.214772, 51.627888], + [125.228938, 51.640517], + [125.289301, 51.633831], + [125.316402, 51.610052], + [125.35151, 51.623801], + [125.38046, 51.585516], + [125.424807, 51.562827], + [125.528285, 51.488359], + [125.559082, 51.461521], + [125.559082, 51.461521], + [125.595422, 51.416755], + [125.595422, 51.416755], + [125.60035, 51.413396], + [125.60035, 51.413396], + [125.600966, 51.410409], + [125.600966, 51.410409], + [125.62314, 51.398089], + [125.62314, 51.398089], + [125.623756, 51.387633], + [125.623756, 51.387633], + [125.626219, 51.380163], + [125.626219, 51.380163], + [125.700132, 51.327465], + [125.700132, 51.327465], + [125.740784, 51.27583], + [125.740784, 51.27583], + [125.76111, 51.261976], + [125.76111, 51.261976], + [125.761726, 51.226385], + [125.819008, 51.227134], + [125.850421, 51.21364], + [125.864588, 51.146487], + [125.909551, 51.138977], + [125.946508, 51.108176], + [125.970529, 51.123955], + [125.993935, 51.119072], + [125.976073, 51.084498], + [126.059225, 51.043503], + [126.033971, 51.011132], + [126.041978, 50.981753], + [126.068464, 50.967434], + [126.042594, 50.92558], + [126.02042, 50.927466], + [125.996399, 50.906715], + [125.997631, 50.872738], + [125.961906, 50.901054], + [125.939732, 50.85423], + [125.913247, 50.825885], + [125.878138, 50.816812], + [125.890457, 50.805845], + [125.836255, 50.793363], + [125.846726, 50.769524], + [125.828863, 50.756654], + [125.804226, 50.773309], + [125.758646, 50.746809], + [125.795603, 50.738856], + [125.78082, 50.725598], + [125.825784, 50.70362], + [125.789443, 50.679735], + [125.804226, 50.658874], + [125.793139, 50.643316], + [125.814697, 50.62092], + [125.807921, 50.60383], + [125.829479, 50.56165], + [125.794987, 50.532748], + [125.770349, 50.531227], + [125.754335, 50.506874], + [125.740784, 50.523237], + [125.699516, 50.487078], + [125.654553, 50.471082], + [125.627451, 50.443268], + [125.580024, 50.449366], + [125.562162, 50.438314], + [125.583104, 50.409717], + [125.567089, 50.402852], + [125.536292, 50.420014], + [125.522126, 50.404759], + [125.546763, 50.358965], + [125.520278, 50.3498], + [125.530749, 50.331085], + [125.463611, 50.295925], + [125.466075, 50.266861], + [125.442053, 50.260357], + [125.448829, 50.216338], + [125.417416, 50.195654], + [125.39093, 50.199868], + [125.382923, 50.172278], + [125.335496, 50.161161], + [125.376148, 50.137385], + [125.311474, 50.140453], + [125.27883, 50.127411], + [125.258504, 50.103618], + [125.287453, 50.093636], + [125.283757, 50.070211], + [125.328105, 50.065985], + [125.315786, 50.04562], + [125.289916, 50.057917], + [125.25296, 50.041393], + [125.283757, 50.036012], + [125.297924, 50.014481], + [125.278214, 49.996402], + [125.241873, 49.987938], + [125.231402, 49.957531], + [125.190134, 49.959841], + [125.199373, 49.935194], + [125.225859, 49.922481], + [125.212924, 49.907452], + [125.245569, 49.87198], + [125.225243, 49.867351], + [125.239409, 49.844587], + [125.177815, 49.829533], + [125.222779, 49.799026], + [125.221547, 49.754969], + [125.204301, 49.734086], + [125.225243, 49.726349], + [125.219699, 49.669058], + [125.185207, 49.634574], + [125.189518, 49.652401], + [125.164881, 49.669446], + [125.132236, 49.672157], + [125.127308, 49.655113], + [125.15441, 49.616741], + [125.16796, 49.629923], + [125.205533, 49.593859], + [125.23017, 49.595411], + [125.233866, 49.536801], + [125.211076, 49.539908], + [125.228323, 49.487063], + [125.270822, 49.454395], + [125.256656, 49.437275], + [125.25604, 49.395227], + [125.277598, 49.379644], + [125.256656, 49.359769], + [125.261583, 49.322336], + [125.214772, 49.277066], + [125.227707, 49.248947], + [125.219699, 49.189139], + [125.187671, 49.186792], + [125.158721, 49.144921], + [125.117453, 49.126127], + [125.034302, 49.157056], + [125.039845, 49.17623], + [124.983179, 49.162535], + [124.906802, 49.184054], + [124.860607, 49.166448], + [124.847672, 49.129651], + [124.809484, 49.115943], + [124.828578, 49.077933], + [124.808252, 49.020666], + [124.756513, 48.967262], + [124.744194, 48.920487], + [124.709086, 48.920487], + [124.715861, 48.885475], + [124.697383, 48.841775], + [124.654267, 48.83429], + [124.644412, 48.80789], + [124.656115, 48.783842], + [124.612383, 48.747945], + [124.624702, 48.701755], + [124.601912, 48.632587], + [124.579122, 48.596582], + [124.520608, 48.556195], + [124.548941, 48.535593], + [124.533543, 48.515379], + [124.555717, 48.467784], + [124.507674, 48.445558], + [124.52492, 48.426897], + [124.51876, 48.378027], + [124.547094, 48.35775], + [124.540934, 48.335476], + [124.579738, 48.297269], + [124.558796, 48.268197], + [124.579122, 48.262221], + [124.547094, 48.200829], + [124.512601, 48.164518], + [124.529847, 48.146951], + [124.505826, 48.124985], + [124.478108, 48.123387], + [124.46579, 48.098213], + [124.415899, 48.08782], + [124.430065, 48.12099], + [124.471333, 48.133373], + [124.475029, 48.173698], + [124.418978, 48.181679], + [124.412819, 48.219175], + [124.422058, 48.245884], + [124.365392, 48.283731], + [124.353689, 48.315978], + [124.317964, 48.35099], + [124.331515, 48.380015], + [124.309957, 48.413393], + [124.330283, 48.435633], + [124.302566, 48.456673], + [124.314269, 48.503881], + [124.25945, 48.536385], + [124.25945, 48.536385], + [124.136878, 48.463023], + [124.07898, 48.43603], + [124.019234, 48.39313], + [123.862785, 48.271782], + [123.746373, 48.197638], + [123.705105, 48.152142], + [123.579453, 48.045427], + [123.537569, 48.021816], + [123.300432, 47.953723], + [123.256085, 47.876711], + [123.214201, 47.824502], + [123.161846, 47.781892], + [123.041122, 47.746492], + [122.926557, 47.697777], + [122.848949, 47.67441], + [122.765181, 47.614333], + [122.59395, 47.54732], + [122.543443, 47.495589], + [122.507103, 47.401291], + [122.418407, 47.350632], + [122.441197, 47.310476], + [122.441197, 47.310476], + [122.462755, 47.27841], + [122.498479, 47.255262], + [122.531124, 47.198771], + [122.582863, 47.158092], + [122.582863, 47.158092], + [122.615508, 47.124306], + [122.679566, 47.094164], + [122.710363, 47.093349], + [122.710363, 47.093349], + [122.821232, 47.065636], + [122.852645, 47.072158], + [122.845869, 47.046881], + [122.778116, 47.002822], + [122.77442, 46.973837], + [122.798442, 46.9575], + [122.791051, 46.941567], + [122.83971, 46.937072], + [122.895144, 46.960359], + [122.893913, 46.895376], + [122.906847, 46.80738], + [122.996774, 46.761483], + [123.00355, 46.730726], + [123.026339, 46.718829], + [123.076846, 46.745082], + [123.103332, 46.734828], + [123.163694, 46.74016], + [123.198802, 46.803283], + [123.22344, 46.821305], + [123.221592, 46.850373], + [123.295505, 46.865105], + [123.341084, 46.826628], + [123.374345, 46.837683], + [123.40699, 46.906416], + [123.404526, 46.935438], + [123.360179, 46.970978], + [123.304128, 46.964852], + [123.301664, 46.999965], + [123.337389, 46.988943], + [123.42362, 46.934212], + [123.487678, 46.959951], + [123.52833, 46.944836], + [123.483366, 46.84587], + [123.506772, 46.827038], + [123.562823, 46.82581], + [123.575757, 46.845461], + [123.576989, 46.891286], + [123.605322, 46.891286], + [123.599163, 46.868378], + [123.625648, 46.847508], + [123.580069, 46.827447], + [123.629344, 46.813524], + [123.631808, 46.728675], + [123.603475, 46.68928], + [123.474743, 46.686817], + [123.366338, 46.677784], + [123.318295, 46.662179], + [123.276411, 46.660947], + [123.279491, 46.616981], + [123.228368, 46.588198], + [123.18094, 46.614103], + [123.098404, 46.603002], + [123.077462, 46.622324], + [123.04605, 46.617803], + [123.052825, 46.579972], + [123.002318, 46.574624], + [123.010325, 46.524823], + [123.011557, 46.434984], + [123.089781, 46.347888], + [123.142136, 46.298293], + [123.178476, 46.248239], + [123.248078, 46.273065], + [123.286266, 46.250308], + [123.320758, 46.254447], + [123.357099, 46.232096], + [123.357099, 46.232096], + [123.430396, 46.243687], + [123.452569, 46.233338], + [123.499381, 46.259826], + [123.569598, 46.223816], + [123.569598, 46.223816] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 310000, + "name": "上海市", + "center": [121.472644, 31.231706], + "centroid": [121.438737, 31.072559], + "childrenNum": 16, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 8, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [120.901349, 31.017327], + [120.940153, 31.010146], + [120.949392, 31.030148], + [120.989428, 31.01425], + [121.000515, 30.938309], + [120.993124, 30.889532], + [121.020225, 30.872069], + [120.991892, 30.837133], + [121.038087, 30.814007], + [121.060261, 30.845354], + [121.097833, 30.857171], + [121.13787, 30.826342], + [121.123087, 30.77905], + [121.174826, 30.771851], + [121.21671, 30.785734], + [121.232108, 30.755909], + [121.272144, 30.723504], + [121.274608, 30.677191], + [121.362071, 30.679764], + [121.426129, 30.730192], + [121.517288, 30.775451], + [121.601056, 30.805269], + [121.681128, 30.818633], + [121.904714, 30.814007], + [121.943518, 30.776993], + [121.970004, 30.789333], + [121.954605, 30.825828], + [121.994025, 30.862823], + [121.990945, 30.96859], + [121.977395, 31.016301], + [121.946598, 31.066039], + [121.809859, 31.196669], + [121.722396, 31.3036], + [121.599208, 31.37465], + [121.520984, 31.394575], + [121.404571, 31.479337], + [121.343593, 31.511996], + [121.301093, 31.49873], + [121.301093, 31.49873], + [121.247507, 31.476785], + [121.241963, 31.493117], + [121.174826, 31.44922], + [121.143413, 31.392021], + [121.113848, 31.37465], + [121.130478, 31.343987], + [121.142797, 31.275472], + [121.090442, 31.291838], + [121.060261, 31.245289], + [121.076892, 31.158267], + [121.018377, 31.134194], + [120.930298, 31.141365], + [120.881023, 31.134706], + [120.859465, 31.100379], + [120.890878, 31.094229], + [120.901349, 31.017327] + ] + ], + [ + [ + [121.974931, 31.61704], + [121.715005, 31.673592], + [121.64294, 31.697527], + [121.599824, 31.703128], + [121.49881, 31.753012], + [121.431673, 31.769295], + [121.384861, 31.833382], + [121.323267, 31.868458], + [121.265369, 31.863883], + [121.200079, 31.834907], + [121.118775, 31.759119], + [121.145261, 31.75403], + [121.289391, 31.61653], + [121.371926, 31.553314], + [121.395332, 31.585437], + [121.434136, 31.590535], + [121.547469, 31.531382], + [121.625693, 31.501792], + [121.682976, 31.491075], + [121.819098, 31.437987], + [121.890547, 31.428795], + [121.981706, 31.464024], + [121.995873, 31.493117], + [121.974931, 31.61704] + ] + ], + [ + [ + [121.795693, 31.330186], + [121.792613, 31.363408], + [121.742106, 31.407345], + [121.585657, 31.454836], + [121.567179, 31.48342], + [121.520984, 31.494137], + [121.509897, 31.4824], + [121.572107, 31.435944], + [121.727939, 31.35472], + [121.76428, 31.31536], + [121.785222, 31.31127], + [121.795693, 31.330186] + ] + ], + [ + [ + [121.801852, 31.356765], + [121.8037, 31.328652], + [121.840656, 31.295418], + [121.932431, 31.283144], + [122.016199, 31.282121], + [122.097503, 31.255522], + [122.122756, 31.307179], + [122.116597, 31.320984], + [122.040837, 31.324051], + [121.951525, 31.337343], + [121.845584, 31.37465], + [121.792613, 31.377715], + [121.801852, 31.356765] + ] + ], + [ + [ + [121.626925, 31.445135], + [121.631853, 31.456878], + [121.579498, 31.479848], + [121.626925, 31.445135] + ] + ], + [ + [ + [121.943518, 31.215608], + [121.959533, 31.159291], + [121.995873, 31.160828], + [122.008808, 31.221238], + [121.950909, 31.228915], + [121.943518, 31.215608] + ] + ], + [ + [ + [121.88254, 31.240684], + [121.909026, 31.195133], + [121.923808, 31.234032], + [121.88254, 31.240684] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 320000, + "name": "江苏省", + "center": [118.767413, 32.041544], + "centroid": [119.486506, 32.983991], + "childrenNum": 13, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 9, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [117.311654, 34.561686], + [117.27285, 34.556757], + [117.303647, 34.542463], + [117.267923, 34.532603], + [117.27285, 34.499565], + [117.252524, 34.48674], + [117.248213, 34.451216], + [117.166293, 34.434435], + [117.139191, 34.526687], + [117.15151, 34.559222], + [117.104083, 34.648874], + [117.073286, 34.639026], + [117.061583, 34.675947], + [117.070206, 34.713835], + [117.022163, 34.759081], + [116.969192, 34.771864], + [116.95133, 34.81069], + [116.979047, 34.815113], + [116.966113, 34.844588], + [116.929156, 34.843114], + [116.922381, 34.894671], + [116.858323, 34.928533], + [116.821983, 34.929515], + [116.815823, 34.965324], + [116.789338, 34.975133], + [116.781331, 34.916757], + [116.677853, 34.939327], + [116.622418, 34.939818], + [116.613795, 34.922645], + [116.557745, 34.908905], + [116.445028, 34.895652], + [116.408071, 34.850972], + [116.403144, 34.756131], + [116.369267, 34.749247], + [116.363724, 34.715311], + [116.392057, 34.710391], + [116.374195, 34.640011], + [116.430245, 34.650843], + [116.432709, 34.630163], + [116.477057, 34.614896], + [116.490607, 34.573513], + [116.594085, 34.511894], + [116.592237, 34.493646], + [116.662454, 34.472927], + [116.722816, 34.472434], + [116.773939, 34.453683], + [116.782563, 34.429993], + [116.828142, 34.389012], + [116.909446, 34.408271], + [116.969192, 34.389012], + [116.960569, 34.363821], + [116.983359, 34.348011], + [116.969192, 34.283753], + [117.051112, 34.221425], + [117.025243, 34.167469], + [117.046801, 34.151622], + [117.123793, 34.128342], + [117.130568, 34.101586], + [117.192162, 34.068873], + [117.257452, 34.065899], + [117.277162, 34.078787], + [117.311654, 34.067882], + [117.357234, 34.088205], + [117.404045, 34.03218], + [117.435458, 34.028212], + [117.514914, 34.060941], + [117.543248, 34.038627], + [117.569117, 33.985051], + [117.612849, 34.000433], + [117.629479, 34.028708], + [117.671363, 33.992494], + [117.672595, 33.934916], + [117.715095, 33.879287], + [117.753899, 33.891211], + [117.759442, 33.874318], + [117.739732, 33.758467], + [117.72495, 33.74951], + [117.750203, 33.710688], + [117.791471, 33.733585], + [117.843826, 33.736074], + [117.901724, 33.720146], + [117.972557, 33.74951], + [118.019985, 33.738562], + [118.065564, 33.76593], + [118.117919, 33.766427], + [118.161035, 33.735576], + [118.16781, 33.663381], + [118.112376, 33.617045], + [118.117919, 33.594615], + [118.107448, 33.475391], + [118.050782, 33.491863], + [118.027376, 33.455421], + [118.016905, 33.402978], + [118.029224, 33.374995], + [117.992883, 33.333005], + [117.974405, 33.279487], + [117.939297, 33.262475], + [117.942376, 33.224936], + [117.977485, 33.226437], + [117.988572, 33.180869], + [118.037231, 33.152314], + [118.038463, 33.134776], + [118.149332, 33.169348], + [118.178281, 33.217926], + [118.217085, 33.191888], + [118.219549, 33.114227], + [118.243571, 33.027967], + [118.244803, 32.998359], + [118.26944, 32.969242], + [118.303933, 32.96874], + [118.291614, 32.946143], + [118.252194, 32.936601], + [118.2331, 32.914498], + [118.250346, 32.848157], + [118.301469, 32.846145], + [118.300237, 32.783275], + [118.334114, 32.761637], + [118.363063, 32.770695], + [118.375382, 32.718849], + [118.411106, 32.715828], + [118.450526, 32.743518], + [118.483787, 32.721367], + [118.560163, 32.729926], + [118.572482, 32.719856], + [118.642699, 32.744525], + [118.707373, 32.72036], + [118.756648, 32.737477], + [118.73817, 32.772708], + [118.743097, 32.853184], + [118.743097, 32.853184], + [118.810235, 32.853687], + [118.821322, 32.920527], + [118.846575, 32.922034], + [118.849039, 32.956689], + [118.89585, 32.957694], + [118.89585, 32.957694], + [118.892771, 32.941121], + [118.934039, 32.93861], + [118.993169, 32.958196], + [119.020886, 32.955685], + [119.054763, 32.8748], + [119.113277, 32.823014], + [119.184726, 32.825529], + [119.211827, 32.708275], + [119.208748, 32.641276], + [119.230921, 32.607001], + [119.22045, 32.576748], + [119.152697, 32.557582], + [119.168096, 32.536394], + [119.142226, 32.499556], + [119.084944, 32.452602], + [119.041212, 32.515201], + [118.975923, 32.505108], + [118.922336, 32.557078], + [118.92172, 32.557078], + [118.922336, 32.557078], + [118.92172, 32.557078], + [118.890923, 32.553042], + [118.908169, 32.59238], + [118.84288, 32.56767], + [118.820706, 32.60448], + [118.784981, 32.582295], + [118.757264, 32.603976], + [118.73509, 32.58885], + [118.719076, 32.614059], + [118.719076, 32.614059], + [118.688895, 32.588346], + [118.658714, 32.594397], + [118.632844, 32.578261], + [118.59712, 32.600951], + [118.568787, 32.585825], + [118.564475, 32.562122], + [118.608823, 32.536899], + [118.592192, 32.481383], + [118.628533, 32.467751], + [118.691359, 32.472295], + [118.685199, 32.403604], + [118.703061, 32.328792], + [118.657482, 32.30148], + [118.674728, 32.250375], + [118.643931, 32.209875], + [118.510888, 32.194176], + [118.49549, 32.165304], + [118.501033, 32.121726], + [118.433896, 32.086746], + [118.394476, 32.076098], + [118.389548, 31.985281], + [118.363679, 31.930443], + [118.472084, 31.879639], + [118.466541, 31.857784], + [118.504729, 31.841516], + [118.481939, 31.778453], + [118.533678, 31.76726], + [118.521975, 31.743343], + [118.5577, 31.73011], + [118.571866, 31.746397], + [118.641467, 31.75861], + [118.653786, 31.73011], + [118.697518, 31.709747], + [118.643315, 31.671555], + [118.643315, 31.649651], + [118.736322, 31.633347], + [118.748025, 31.675629], + [118.773894, 31.682759], + [118.802844, 31.619078], + [118.858894, 31.623665], + [118.881684, 31.564023], + [118.885995, 31.519139], + [118.883532, 31.500261], + [118.852119, 31.393553], + [118.824401, 31.375672], + [118.767735, 31.363919], + [118.745561, 31.372606], + [118.720924, 31.322518], + [118.726467, 31.282121], + [118.756648, 31.279564], + [118.794836, 31.229426], + [118.870597, 31.242219], + [118.984546, 31.237102], + [119.014727, 31.241707], + [119.10527, 31.235055], + [119.107118, 31.250917], + [119.158241, 31.294907], + [119.197661, 31.295418], + [119.198277, 31.270357], + [119.266646, 31.250405], + [119.294363, 31.263195], + [119.338095, 31.259103], + [119.350414, 31.301043], + [119.374435, 31.258591], + [119.360269, 31.213049], + [119.391682, 31.174142], + [119.439109, 31.177214], + [119.461283, 31.156219], + [119.532732, 31.159291], + [119.599869, 31.10909], + [119.623891, 31.130096], + [119.678093, 31.167997], + [119.705811, 31.152634], + [119.715666, 31.169533], + [119.779723, 31.17875], + [119.809904, 31.148536], + [119.827151, 31.174142], + [119.878274, 31.160828], + [119.921389, 31.170045], + [119.946027, 31.106016], + [119.988527, 31.059375], + [120.001461, 31.027071], + [120.052584, 31.00553], + [120.111099, 30.955761], + [120.149903, 30.937283], + [120.223816, 30.926502], + [120.316206, 30.933689], + [120.371025, 30.948575], + [120.35809, 30.886964], + [120.42338, 30.902884], + [120.435083, 30.920855], + [120.441858, 30.860768], + [120.460336, 30.839702], + [120.489285, 30.763624], + [120.504684, 30.757967], + [120.563814, 30.835592], + [120.589684, 30.854089], + [120.654973, 30.846896], + [120.68269, 30.882342], + [120.713487, 30.88491], + [120.709176, 30.933176], + [120.684538, 30.955247], + [120.698089, 30.970643], + [120.746132, 30.962432], + [120.770154, 30.996809], + [120.820661, 31.006556], + [120.865624, 30.989627], + [120.901349, 31.017327], + [120.890878, 31.094229], + [120.859465, 31.100379], + [120.881023, 31.134706], + [120.930298, 31.141365], + [121.018377, 31.134194], + [121.076892, 31.158267], + [121.060261, 31.245289], + [121.090442, 31.291838], + [121.142797, 31.275472], + [121.130478, 31.343987], + [121.113848, 31.37465], + [121.143413, 31.392021], + [121.174826, 31.44922], + [121.241963, 31.493117], + [121.247507, 31.476785], + [121.301093, 31.49873], + [121.301093, 31.49873], + [121.343593, 31.511996], + [121.371926, 31.553314], + [121.289391, 31.61653], + [121.145261, 31.75403], + [121.118775, 31.759119], + [121.200079, 31.834907], + [121.265369, 31.863883], + [121.323267, 31.868458], + [121.384861, 31.833382], + [121.431673, 31.769295], + [121.49881, 31.753012], + [121.599824, 31.703128], + [121.64294, 31.697527], + [121.715005, 31.673592], + [121.974931, 31.61704], + [121.970004, 31.718911], + [121.889315, 31.866425], + [121.856055, 31.955328], + [121.772287, 32.032984], + [121.759352, 32.059362], + [121.525295, 32.136423], + [121.542542, 32.152132], + [121.458774, 32.177462], + [121.499426, 32.211394], + [121.493882, 32.263533], + [121.450151, 32.282256], + [121.425513, 32.430885], + [121.390405, 32.460682], + [121.352216, 32.474315], + [121.269681, 32.483402], + [121.153268, 32.52933], + [121.121855, 32.569183], + [121.076892, 32.576243], + [121.020225, 32.605489], + [120.961711, 32.612042], + [120.979573, 32.636236], + [120.963559, 32.68259], + [120.916131, 32.701225], + [120.953088, 32.714318], + [120.972182, 32.761134], + [120.981421, 32.85972], + [120.957399, 32.893395], + [120.932762, 33.005887], + [120.917979, 33.02596], + [120.871784, 33.047032], + [120.874247, 33.093672], + [120.843451, 33.209915], + [120.819429, 33.237951], + [120.833595, 33.274984], + [120.813885, 33.303499], + [120.769538, 33.307], + [120.741205, 33.337505], + [120.717183, 33.436945], + [120.680227, 33.520306], + [120.622944, 33.615051], + [120.611241, 33.627012], + [120.583524, 33.668362], + [120.534249, 33.782346], + [120.48559, 33.859411], + [120.367329, 34.091674], + [120.347619, 34.179352], + [120.314359, 34.255563], + [120.311895, 34.306991], + [120.103707, 34.391481], + [119.962657, 34.459112], + [119.811752, 34.485754], + [119.781571, 34.515839], + [119.641137, 34.569078], + [119.610956, 34.592729], + [119.569072, 34.615389], + [119.465594, 34.672994], + [119.525956, 34.73351], + [119.456971, 34.748264], + [119.381827, 34.752198], + [119.494543, 34.754656], + [119.497007, 34.754164], + [119.439725, 34.785136], + [119.440957, 34.769406], + [119.378747, 34.764489], + [119.312841, 34.774813], + [119.272189, 34.797914], + [119.238313, 34.799388], + [119.217371, 34.827886], + [119.202588, 34.890253], + [119.214907, 34.925589], + [119.211211, 34.981507], + [119.238313, 35.048657], + [119.285124, 35.068252], + [119.291899, 35.028567], + [119.307298, 35.032977], + [119.292515, 35.068742], + [119.306066, 35.076578], + [119.286972, 35.115261], + [119.250016, 35.124562], + [119.217371, 35.106939], + [119.137915, 35.096167], + [119.114509, 35.055026], + [119.027045, 35.055516], + [118.942662, 35.040817], + [118.928495, 35.051106], + [118.86259, 35.025626], + [118.860742, 34.944233], + [118.805307, 34.87307], + [118.80038, 34.843114], + [118.772047, 34.794474], + [118.739402, 34.792508], + [118.719076, 34.745313], + [118.764039, 34.740396], + [118.783749, 34.723181], + [118.739402, 34.693663], + [118.690127, 34.678408], + [118.664257, 34.693663], + [118.607591, 34.694155], + [118.601431, 34.714327], + [118.545997, 34.705964], + [118.460997, 34.656258], + [118.473932, 34.623269], + [118.439439, 34.626223], + [118.424657, 34.595193], + [118.439439, 34.507949], + [118.416034, 34.473914], + [118.404947, 34.427525], + [118.379693, 34.415183], + [118.290382, 34.424563], + [118.277447, 34.404814], + [118.220165, 34.405802], + [118.217701, 34.379134], + [118.179513, 34.379628], + [118.177665, 34.45319], + [118.132702, 34.483287], + [118.16473, 34.50499], + [118.185056, 34.543942], + [118.079115, 34.569571], + [118.114839, 34.614404], + [118.084042, 34.655766], + [118.053861, 34.650843], + [117.951615, 34.678408], + [117.909732, 34.670533], + [117.902956, 34.644443], + [117.793935, 34.651827], + [117.791471, 34.583368], + [117.801942, 34.518798], + [117.684298, 34.547392], + [117.659044, 34.501044], + [117.609769, 34.490686], + [117.592523, 34.462566], + [117.53832, 34.467006], + [117.465023, 34.484767], + [117.402813, 34.550843], + [117.402813, 34.569571], + [117.370785, 34.584846], + [117.325205, 34.573021], + [117.325205, 34.573021], + [117.32151, 34.566614], + [117.32151, 34.566614], + [117.311654, 34.561686], + [117.311654, 34.561686] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 330000, + "name": "浙江省", + "center": [120.153576, 30.287459], + "centroid": [120.109913, 29.181466], + "childrenNum": 11, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 10, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [118.433896, 28.288335], + [118.444367, 28.253548], + [118.490562, 28.238259], + [118.493026, 28.262509], + [118.588497, 28.282538], + [118.595272, 28.258292], + [118.651322, 28.277267], + [118.674728, 28.27147], + [118.699366, 28.309939], + [118.719692, 28.312047], + [118.756032, 28.252493], + [118.802228, 28.240368], + [118.804075, 28.207675], + [118.771431, 28.188687], + [118.805923, 28.154923], + [118.802228, 28.117453], + [118.767735, 28.10584], + [118.719076, 28.063601], + [118.733858, 28.027684], + [118.730163, 27.970615], + [118.753568, 27.947885], + [118.818242, 27.916689], + [118.829329, 27.847921], + [118.873677, 27.733563], + [118.879836, 27.667859], + [118.913713, 27.619616], + [118.909401, 27.568168], + [118.869365, 27.540047], + [118.907553, 27.460952], + [118.955597, 27.4498], + [118.986393, 27.47582], + [118.983314, 27.498649], + [119.020886, 27.498118], + [119.03998, 27.478475], + [119.092335, 27.466262], + [119.129907, 27.475289], + [119.121284, 27.438115], + [119.14777, 27.424836], + [119.224146, 27.416868], + [119.26911, 27.42218], + [119.285124, 27.457766], + [119.334399, 27.480067], + [119.360269, 27.524657], + [119.416935, 27.539517], + [119.438493, 27.508734], + [119.466826, 27.526249], + [119.501935, 27.610601], + [119.501319, 27.649837], + [119.541971, 27.666799], + [119.606028, 27.674749], + [119.644217, 27.663619], + [119.626354, 27.620676], + [119.630666, 27.582491], + [119.675014, 27.574534], + [119.659615, 27.540578], + [119.690412, 27.537394], + [119.70889, 27.514042], + [119.703347, 27.446613], + [119.685485, 27.438646], + [119.711354, 27.403054], + [119.750774, 27.373829], + [119.739687, 27.362668], + [119.782187, 27.330241], + [119.768636, 27.307909], + [119.843165, 27.300464], + [119.938636, 27.329709], + [119.960194, 27.365857], + [120.008237, 27.375423], + [120.026099, 27.344063], + [120.052584, 27.338747], + [120.096316, 27.390302], + [120.136968, 27.402523], + [120.134504, 27.420055], + [120.221352, 27.420055], + [120.26262, 27.432804], + [120.273091, 27.38924], + [120.340844, 27.399867], + [120.343924, 27.363199], + [120.430155, 27.258976], + [120.401822, 27.250996], + [120.404286, 27.204166], + [120.461568, 27.142407], + [120.492365, 27.136016], + [120.545952, 27.156785], + [120.574901, 27.234501], + [120.554575, 27.25206], + [120.580444, 27.321203], + [120.665444, 27.357884], + [120.673451, 27.420055], + [120.703016, 27.478475], + [120.637111, 27.561271], + [120.634647, 27.577186], + [120.685154, 27.622797], + [120.709176, 27.682699], + [120.771386, 27.734623], + [120.777545, 27.774873], + [120.809574, 27.775402], + [120.840371, 27.758986], + [120.910588, 27.864852], + [120.942001, 27.896592], + [120.97403, 27.887071], + [121.027616, 27.832574], + [121.070116, 27.834162], + [121.107688, 27.81352], + [121.152036, 27.815638], + [121.134174, 27.787051], + [121.13479, 27.787051], + [121.149572, 27.801345], + [121.149572, 27.801875], + [121.153268, 27.809815], + [121.152652, 27.810344], + [121.192072, 27.822518], + [121.193304, 27.872259], + [121.162507, 27.879136], + [121.162507, 27.90717], + [121.099681, 27.895005], + [121.05595, 27.900294], + [120.991892, 27.95], + [121.015298, 27.981714], + [121.059029, 28.096338], + [121.108304, 28.139092], + [121.121239, 28.12537], + [121.140949, 28.031382], + [121.176058, 28.022401], + [121.261057, 28.034551], + [121.299862, 28.067297], + [121.328195, 28.134343], + [121.373774, 28.133287], + [121.402107, 28.197127], + [121.45631, 28.250385], + [121.488955, 28.301509], + [121.538846, 28.299401], + [121.571491, 28.279376], + [121.580114, 28.240368], + [121.627541, 28.251966], + [121.669425, 28.33312], + [121.660186, 28.355768], + [121.634317, 28.347868], + [121.658954, 28.392628], + [121.692831, 28.407368], + [121.671273, 28.472621], + [121.646019, 28.511544], + [121.634317, 28.562542], + [121.596128, 28.575156], + [121.557324, 28.645033], + [121.540694, 28.655537], + [121.646019, 28.682842], + [121.689135, 28.719062], + [121.704534, 28.804577], + [121.687287, 28.863294], + [121.774751, 28.863818], + [121.772287, 28.898404], + [121.743338, 28.954451], + [121.711309, 28.985865], + [121.712541, 29.028783], + [121.658954, 29.058606], + [121.660186, 29.118226], + [121.616454, 29.143318], + [121.608447, 29.168927], + [121.715621, 29.125022], + [121.750113, 29.136523], + [121.767975, 29.166837], + [121.780294, 29.10986], + [121.811091, 29.10986], + [121.85975, 29.086328], + [121.884388, 29.105677], + [121.966308, 29.052852], + [121.970004, 29.092604], + [121.988482, 29.110906], + [121.986634, 29.154817], + [121.948446, 29.193485], + [121.971851, 29.193485], + [121.966924, 29.249894], + [122.002032, 29.260336], + [122.000185, 29.278608], + [121.94475, 29.28435], + [121.958301, 29.334448], + [121.936127, 29.348012], + [121.937975, 29.384], + [121.975547, 29.411113], + [121.993409, 29.45229], + [121.973083, 29.477821], + [121.968772, 29.515846], + [121.995257, 29.545007], + [122.000185, 29.582486], + [121.966308, 29.636078], + [121.909641, 29.650122], + [121.872685, 29.632437], + [121.833265, 29.653242], + [121.937359, 29.748373], + [122.003264, 29.762401], + [122.043916, 29.822647], + [122.10243, 29.859504], + [122.143082, 29.877668], + [122.140003, 29.901535], + [122.00696, 29.891678], + [122.00388, 29.92021], + [121.971235, 29.955476], + [121.919497, 29.920729], + [121.835113, 29.958068], + [121.78399, 29.99332], + [121.721164, 29.992802], + [121.699606, 30.007832], + [121.652795, 30.071037], + [121.635548, 30.070002], + [121.561636, 30.184395], + [121.497578, 30.258861], + [121.395332, 30.338435], + [121.371926, 30.37097], + [121.328195, 30.397299], + [121.225333, 30.404526], + [121.183449, 30.434458], + [121.092906, 30.515952], + [121.058413, 30.563888], + [121.148956, 30.599953], + [121.188992, 30.632916], + [121.239499, 30.648878], + [121.274608, 30.677191], + [121.272144, 30.723504], + [121.232108, 30.755909], + [121.21671, 30.785734], + [121.174826, 30.771851], + [121.123087, 30.77905], + [121.13787, 30.826342], + [121.097833, 30.857171], + [121.060261, 30.845354], + [121.038087, 30.814007], + [120.991892, 30.837133], + [121.020225, 30.872069], + [120.993124, 30.889532], + [121.000515, 30.938309], + [120.989428, 31.01425], + [120.949392, 31.030148], + [120.940153, 31.010146], + [120.901349, 31.017327], + [120.865624, 30.989627], + [120.820661, 31.006556], + [120.770154, 30.996809], + [120.746132, 30.962432], + [120.698089, 30.970643], + [120.684538, 30.955247], + [120.709176, 30.933176], + [120.713487, 30.88491], + [120.68269, 30.882342], + [120.654973, 30.846896], + [120.589684, 30.854089], + [120.563814, 30.835592], + [120.504684, 30.757967], + [120.489285, 30.763624], + [120.460336, 30.839702], + [120.441858, 30.860768], + [120.435083, 30.920855], + [120.42338, 30.902884], + [120.35809, 30.886964], + [120.371025, 30.948575], + [120.316206, 30.933689], + [120.223816, 30.926502], + [120.149903, 30.937283], + [120.111099, 30.955761], + [120.052584, 31.00553], + [120.001461, 31.027071], + [119.988527, 31.059375], + [119.946027, 31.106016], + [119.921389, 31.170045], + [119.878274, 31.160828], + [119.827151, 31.174142], + [119.809904, 31.148536], + [119.779723, 31.17875], + [119.715666, 31.169533], + [119.705811, 31.152634], + [119.678093, 31.167997], + [119.623891, 31.130096], + [119.649144, 31.104991], + [119.629434, 31.085517], + [119.633746, 31.019379], + [119.580159, 30.967051], + [119.582007, 30.932149], + [119.563529, 30.919315], + [119.557369, 30.874124], + [119.575847, 30.829939], + [119.55429, 30.825828], + [119.527188, 30.77905], + [119.479761, 30.772365], + [119.482841, 30.704467], + [119.444652, 30.650422], + [119.408312, 30.645274], + [119.39045, 30.685941], + [119.343022, 30.664322], + [119.323312, 30.630341], + [119.238929, 30.609225], + [119.265414, 30.574709], + [119.237081, 30.546881], + [119.272189, 30.510281], + [119.326392, 30.532964], + [119.336247, 30.508734], + [119.335015, 30.448389], + [119.36766, 30.38491], + [119.402768, 30.374584], + [119.349182, 30.349281], + [119.326392, 30.372002], + [119.277117, 30.341018], + [119.246936, 30.341018], + [119.236465, 30.297106], + [119.201356, 30.290905], + [119.126828, 30.304856], + [119.091719, 30.323972], + [119.06277, 30.304856], + [118.988857, 30.332237], + [118.954365, 30.360126], + [118.880452, 30.31519], + [118.877988, 30.282637], + [118.905089, 30.216464], + [118.929727, 30.2025], + [118.852735, 30.166805], + [118.852119, 30.149729], + [118.895234, 30.148694], + [118.873677, 30.11505], + [118.878604, 30.064822], + [118.902626, 30.029078], + [118.894619, 29.937845], + [118.838568, 29.934733], + [118.841032, 29.891159], + [118.740634, 29.814859], + [118.744945, 29.73902], + [118.700598, 29.706277], + [118.647011, 29.64336], + [118.61991, 29.654282], + [118.573714, 29.638159], + [118.532446, 29.588731], + [118.500417, 29.57572], + [118.496106, 29.519492], + [118.381541, 29.504909], + [118.347664, 29.474174], + [118.329802, 29.495012], + [118.306396, 29.479384], + [118.316252, 29.422581], + [118.248498, 29.431443], + [118.193064, 29.395472], + [118.205382, 29.343839], + [118.166578, 29.314099], + [118.178281, 29.297921], + [118.138861, 29.283828], + [118.077883, 29.290614], + [118.073571, 29.216993], + [118.042159, 29.210202], + [118.027992, 29.167882], + [118.045238, 29.149068], + [118.037847, 29.102017], + [118.076035, 29.074822], + [118.066796, 29.053898], + [118.097593, 28.998952], + [118.115455, 29.009944], + [118.115455, 29.009944], + [118.133933, 28.983771], + [118.165346, 28.986912], + [118.227556, 28.942406], + [118.195527, 28.904167], + [118.270056, 28.918836], + [118.300237, 28.826075], + [118.364295, 28.813491], + [118.403099, 28.702791], + [118.428352, 28.681267], + [118.428352, 28.617193], + [118.428352, 28.617193], + [118.412338, 28.55676], + [118.4302, 28.515225], + [118.414802, 28.497344], + [118.474548, 28.478934], + [118.456686, 28.424738], + [118.432048, 28.402104], + [118.455454, 28.384204], + [118.480091, 28.327325], + [118.433896, 28.288335] + ] + ], + [ + [ + [122.163408, 29.988137], + [122.239785, 29.962735], + [122.279205, 29.937326], + [122.322321, 29.940438], + [122.341415, 29.976733], + [122.343879, 30.020269], + [122.310002, 30.039958], + [122.290908, 30.074663], + [122.301379, 30.086574], + [122.293988, 30.100554], + [122.152938, 30.113497], + [122.095655, 30.158008], + [122.048844, 30.147141], + [121.955221, 30.183878], + [121.934895, 30.161631], + [121.983554, 30.100554], + [121.989714, 30.077252], + [121.978011, 30.059125], + [122.027902, 29.991247], + [122.106742, 30.005759], + [122.118445, 29.986582], + [122.163408, 29.988137] + ] + ], + [ + [ + [122.213915, 30.186464], + [122.178807, 30.199396], + [122.152938, 30.19112], + [122.143698, 30.163183], + [122.168336, 30.138343], + [122.213915, 30.186464] + ] + ], + [ + [ + [122.229314, 29.711995], + [122.210836, 29.700559], + [122.269966, 29.685482], + [122.231162, 29.710435], + [122.229314, 29.711995] + ] + ], + [ + [ + [122.427646, 30.738422], + [122.427031, 30.697777], + [122.532972, 30.696748], + [122.528045, 30.725047], + [122.475074, 30.714243], + [122.445509, 30.745109], + [122.427646, 30.738422] + ] + ], + [ + [ + [122.162793, 30.329654], + [122.058083, 30.291938], + [122.154169, 30.244903], + [122.231778, 30.234562], + [122.247176, 30.30124], + [122.228082, 30.329654], + [122.191126, 30.329654], + [122.176343, 30.351863], + [122.162793, 30.329654] + ] + ], + [ + [ + [122.317393, 30.249556], + [122.277973, 30.242835], + [122.358661, 30.236113], + [122.365437, 30.255242], + [122.417175, 30.238699], + [122.40732, 30.272817], + [122.333408, 30.272817], + [122.317393, 30.249556] + ] + ], + [ + [ + [122.026054, 29.178333], + [122.013119, 29.151681], + [122.056851, 29.158476], + [122.075945, 29.176243], + [122.036525, 29.20759], + [122.026054, 29.178333] + ] + ], + [ + [ + [122.372212, 29.893234], + [122.386379, 29.834069], + [122.415944, 29.828877], + [122.401777, 29.869884], + [122.433806, 29.883376], + [122.43319, 29.919173], + [122.411632, 29.951846], + [122.398081, 29.9394], + [122.351886, 29.959105], + [122.330944, 29.937845], + [122.338951, 29.911911], + [122.353734, 29.89946], + [122.362973, 29.894272], + [122.372212, 29.893234] + ] + ], + [ + [ + [122.43011, 30.408655], + [122.432574, 30.445294], + [122.37406, 30.461802], + [122.277973, 30.471603], + [122.281669, 30.418461], + [122.318625, 30.407106], + [122.352502, 30.422074], + [122.43011, 30.408655] + ] + ], + [ + [ + [121.837577, 28.770484], + [121.86283, 28.782024], + [121.861598, 28.814016], + [121.837577, 28.770484] + ] + ], + [ + [ + [122.265038, 29.84549], + [122.221307, 29.832512], + [122.248408, 29.804473], + [122.310002, 29.766557], + [122.325401, 29.781621], + [122.299531, 29.819532], + [122.319241, 29.829397], + [122.265038, 29.84549] + ] + ], + [ + [ + [121.790765, 29.082144], + [121.832649, 29.050236], + [121.84312, 29.082144], + [121.82033, 29.099402], + [121.790765, 29.082144] + ] + ], + [ + [ + [121.201311, 27.623328], + [121.197616, 27.618025], + [121.198848, 27.616964], + [121.203775, 27.625979], + [121.201311, 27.623328] + ] + ], + [ + [ + [121.943518, 30.776993], + [121.968156, 30.688514], + [121.997105, 30.658659], + [122.087032, 30.602014], + [122.133227, 30.595317], + [122.075329, 30.647848], + [122.011271, 30.66947], + [121.992793, 30.695204], + [121.987866, 30.753338], + [121.970004, 30.789333], + [121.943518, 30.776993] + ] + ], + [ + [ + [121.889315, 28.471569], + [121.918881, 28.497344], + [121.881924, 28.502603], + [121.889315, 28.471569] + ] + ], + [ + [ + [122.182503, 29.650642], + [122.211452, 29.692241], + [122.200365, 29.712515], + [122.146778, 29.749412], + [122.13138, 29.788893], + [122.083952, 29.78318], + [122.047612, 29.719791], + [122.074097, 29.701599], + [122.095655, 29.716673], + [122.138155, 29.662083], + [122.182503, 29.650642] + ] + ], + [ + [ + [122.461523, 29.944068], + [122.459675, 29.944586], + [122.460291, 29.947179], + [122.451668, 29.943031], + [122.451052, 29.940956], + [122.450436, 29.940956], + [122.449204, 29.9394], + [122.4529, 29.936807], + [122.452284, 29.935252], + [122.45598, 29.926435], + [122.457827, 29.927472], + [122.462755, 29.927991], + [122.467067, 29.928509], + [122.459059, 29.938882], + [122.461523, 29.944068] + ] + ], + [ + [ + [122.570544, 30.644244], + [122.559457, 30.679764], + [122.546523, 30.651967], + [122.570544, 30.644244] + ] + ], + [ + [ + [121.869605, 28.423685], + [121.910873, 28.44], + [121.889931, 28.45105], + [121.869605, 28.423685] + ] + ], + [ + [ + [122.065474, 30.179739], + [122.055619, 30.200431], + [122.017431, 30.186464], + [122.025438, 30.161631], + [122.065474, 30.179739] + ] + ], + [ + [ + [122.391306, 29.970512], + [122.411632, 30.025969], + [122.378371, 30.023896], + [122.3679, 29.980361], + [122.391306, 29.970512] + ] + ], + [ + [ + [121.850511, 29.977251], + [121.874533, 29.964809], + [121.933047, 29.994875], + [121.924424, 30.052391], + [121.88562, 30.094859], + [121.848663, 30.101072], + [121.84004, 30.047211], + [121.844968, 29.982953], + [121.850511, 29.977251] + ] + ], + [ + [ + [121.066421, 27.478475], + [121.066421, 27.461483], + [121.107073, 27.443958], + [121.067036, 27.478475], + [121.066421, 27.478475] + ] + ], + [ + [ + [121.952141, 29.187738], + [121.979243, 29.160043], + [121.976779, 29.191918], + [121.952141, 29.187738] + ] + ], + [ + [ + [122.038373, 29.759284], + [122.011271, 29.746294], + [122.02975, 29.716673], + [122.038373, 29.759284] + ] + ], + [ + [ + [121.940438, 30.114533], + [121.910257, 30.089163], + [121.945982, 30.064304], + [121.962612, 30.106249], + [121.940438, 30.114533] + ] + ], + [ + [ + [121.957685, 30.287804], + [122.0008, 30.308473], + [121.989098, 30.339985], + [121.94167, 30.33327], + [121.921344, 30.30744], + [121.957685, 30.287804] + ] + ], + [ + [ + [122.192974, 29.965327], + [122.163408, 29.988137], + [122.152322, 29.97103], + [122.154169, 29.97103], + [122.155401, 29.970512], + [122.18435, 29.955476], + [122.192974, 29.965327] + ] + ], + [ + [ + [122.287828, 29.723949], + [122.301379, 29.748373], + [122.258263, 29.753569], + [122.241633, 29.784738], + [122.2133, 29.771752], + [122.251488, 29.731225], + [122.287828, 29.723949] + ] + ], + [ + [ + [121.134174, 27.787051], + [121.134174, 27.785992], + [121.13479, 27.787051], + [121.134174, 27.787051] + ] + ], + [ + [ + [122.760254, 30.141966], + [122.784275, 30.130062], + [122.781196, 30.13265], + [122.778116, 30.13679], + [122.770725, 30.138861], + [122.763333, 30.141966], + [122.762101, 30.142484], + [122.760254, 30.141966] + ] + ], + [ + [ + [122.264423, 30.269716], + [122.253952, 30.237147], + [122.315545, 30.250073], + [122.300147, 30.271266], + [122.264423, 30.269716] + ] + ], + [ + [ + [122.282901, 29.860542], + [122.30877, 29.849642], + [122.343263, 29.860542], + [122.343263, 29.882857], + [122.301379, 29.883895], + [122.282901, 29.860542] + ] + ], + [ + [ + [122.781196, 30.694175], + [122.799674, 30.716301], + [122.778732, 30.729677], + [122.757174, 30.713728], + [122.781196, 30.694175] + ] + ], + [ + [ + [121.098449, 27.937311], + [121.152652, 27.961629], + [121.120623, 27.986471], + [121.0695, 27.984357], + [121.038087, 27.948942], + [121.098449, 27.937311] + ] + ], + [ + [ + [121.185913, 27.963215], + [121.237652, 27.988056], + [121.197616, 28.000739], + [121.17113, 27.978543], + [121.185913, 27.963215] + ] + ], + [ + [ + [122.454132, 29.956513], + [122.447972, 29.955994], + [122.445509, 29.952365], + [122.446741, 29.951327], + [122.447972, 29.947698], + [122.459059, 29.950809], + [122.458443, 29.951846], + [122.455364, 29.955994], + [122.454132, 29.956513] + ] + ], + [ + [ + [122.836014, 30.698806], + [122.831087, 30.728648], + [122.807681, 30.714243], + [122.836014, 30.698806] + ] + ], + [ + [ + [122.200365, 29.969475], + [122.233626, 29.946661], + [122.273662, 29.93214], + [122.239785, 29.960142], + [122.200365, 29.969475] + ] + ], + [ + [ + [122.029134, 29.954957], + [122.043916, 29.930584], + [122.058699, 29.955994], + [122.029134, 29.954957] + ] + ], + [ + [ + [121.044247, 27.979072], + [121.089826, 27.998625], + [121.073812, 28.007608], + [121.044247, 27.979072] + ] + ], + [ + [ + [122.471378, 29.927472], + [122.470762, 29.925916], + [122.473226, 29.925397], + [122.47261, 29.927472], + [122.471378, 29.927472] + ] + ], + [ + [ + [122.152322, 29.97103], + [122.155401, 29.970512], + [122.154169, 29.97103], + [122.152322, 29.97103] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 340000, + "name": "安徽省", + "center": [117.283042, 31.86119], + "centroid": [117.226884, 31.849254], + "childrenNum": 16, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 11, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [116.599629, 34.014324], + [116.641512, 33.978103], + [116.64336, 33.896675], + [116.631042, 33.887733], + [116.566984, 33.9081], + [116.558361, 33.881274], + [116.486296, 33.869846], + [116.437637, 33.846489], + [116.437021, 33.801246], + [116.408071, 33.805721], + [116.393905, 33.782843], + [116.316912, 33.771402], + [116.263326, 33.730101], + [116.230065, 33.735078], + [116.155536, 33.709693], + [116.132747, 33.751501], + [116.100102, 33.782843], + [116.074232, 33.781351], + [116.055754, 33.804727], + [116.05945, 33.860902], + [115.982457, 33.917039], + [116.00032, 33.965199], + [115.95782, 34.007875], + [115.904233, 34.009859], + [115.876516, 34.028708], + [115.877132, 34.002913], + [115.85003, 34.004898], + [115.846335, 34.028708], + [115.809378, 34.062428], + [115.768726, 34.061932], + [115.736082, 34.076805], + [115.705901, 34.059949], + [115.658473, 34.061437], + [115.642459, 34.03218], + [115.60735, 34.030196], + [115.579017, 33.974133], + [115.577785, 33.950307], + [115.547604, 33.874815], + [115.631988, 33.869846], + [115.614126, 33.775879], + [115.576553, 33.787817], + [115.563003, 33.772895], + [115.601807, 33.718653], + [115.601191, 33.658898], + [115.639995, 33.585143], + [115.564851, 33.576169], + [115.511264, 33.55323], + [115.463837, 33.567193], + [115.422569, 33.557219], + [115.394851, 33.506335], + [115.366518, 33.5233], + [115.345576, 33.502842], + [115.345576, 33.449928], + [115.324634, 33.457418], + [115.315395, 33.431451], + [115.328946, 33.403477], + [115.313547, 33.376994], + [115.341881, 33.370997], + [115.365286, 33.336005], + [115.361591, 33.298497], + [115.335105, 33.297997], + [115.340033, 33.260973], + [115.300613, 33.204407], + [115.303692, 33.149809], + [115.289526, 33.131769], + [115.245178, 33.135778], + [115.194671, 33.120743], + [115.168186, 33.088658], + [115.041302, 33.086653], + [114.990795, 33.102195], + [114.966158, 33.147304], + [114.932897, 33.153817], + [114.902716, 33.129764], + [114.897172, 33.086653], + [114.913187, 33.083143], + [114.925506, 33.016928], + [114.891629, 33.020441], + [114.883006, 32.990328], + [114.916266, 32.971251], + [114.943368, 32.935094], + [115.009273, 32.940117], + [115.035143, 32.932582], + [115.029599, 32.906962], + [115.139237, 32.897917], + [115.155867, 32.864747], + [115.197135, 32.856201], + [115.189744, 32.812452], + [115.211301, 32.785791], + [115.189744, 32.770695], + [115.179273, 32.726402], + [115.182968, 32.666973], + [115.20083, 32.591876], + [115.24333, 32.593388], + [115.267352, 32.578261], + [115.30554, 32.583303], + [115.304924, 32.553042], + [115.411482, 32.575235], + [115.409018, 32.549007], + [115.497713, 32.492489], + [115.5088, 32.468761], + [115.510648, 32.468761], + [115.510648, 32.468256], + [115.510648, 32.467751], + [115.509416, 32.466741], + [115.522967, 32.441997], + [115.57101, 32.419266], + [115.604271, 32.425833], + [115.626445, 32.40512], + [115.657857, 32.428864], + [115.667712, 32.409667], + [115.704669, 32.495013], + [115.742241, 32.476335], + [115.771806, 32.505108], + [115.789052, 32.468761], + [115.861117, 32.537403], + [115.891298, 32.576243], + [115.910393, 32.567165], + [115.8759, 32.542448], + [115.845719, 32.501575], + [115.883291, 32.487946], + [115.865429, 32.458662], + [115.899306, 32.390971], + [115.912856, 32.227596], + [115.941805, 32.166318], + [115.922095, 32.049725], + [115.928871, 32.003046], + [115.909161, 31.94314], + [115.920248, 31.920285], + [115.894994, 31.8649], + [115.893762, 31.832365], + [115.914704, 31.814567], + [115.886371, 31.776418], + [115.851878, 31.786593], + [115.808147, 31.770313], + [115.808147, 31.770313], + [115.767495, 31.78761], + [115.731154, 31.76726], + [115.676336, 31.778453], + [115.553764, 31.69549], + [115.534054, 31.698545], + [115.495249, 31.673083], + [115.476771, 31.643028], + [115.485394, 31.608885], + [115.439815, 31.588496], + [115.415793, 31.525771], + [115.371446, 31.495668], + [115.389924, 31.450241], + [115.373909, 31.405813], + [115.393004, 31.389977], + [115.372062, 31.349098], + [115.40717, 31.337854], + [115.443511, 31.344498], + [115.473076, 31.265242], + [115.507568, 31.267799], + [115.539597, 31.231985], + [115.540213, 31.194621], + [115.585793, 31.143926], + [115.603655, 31.17363], + [115.655394, 31.211002], + [115.700973, 31.201276], + [115.778582, 31.112164], + [115.797676, 31.128047], + [115.837712, 31.127022], + [115.867277, 31.147512], + [115.887603, 31.10909], + [115.939958, 31.071678], + [115.938726, 31.04707], + [116.006479, 31.034764], + [116.015102, 31.011685], + [116.058834, 31.012711], + [116.071769, 30.956787], + [116.03974, 30.957813], + [115.976298, 30.931636], + [115.932566, 30.889532], + [115.865429, 30.864364], + [115.848799, 30.828397], + [115.863581, 30.815549], + [115.851262, 30.756938], + [115.782893, 30.751795], + [115.762567, 30.685426], + [115.81369, 30.637035], + [115.819234, 30.597893], + [115.848799, 30.602014], + [115.876516, 30.582438], + [115.887603, 30.542758], + [115.910393, 30.519046], + [115.894994, 30.452517], + [115.921479, 30.416397], + [115.885139, 30.379747], + [115.91532, 30.337919], + [115.903001, 30.31364], + [115.985537, 30.290905], + [115.997856, 30.252657], + [116.065609, 30.204569], + [116.055754, 30.180774], + [116.088399, 30.110391], + [116.078544, 30.062233], + [116.091479, 30.036331], + [116.073616, 29.969993], + [116.128435, 29.897904], + [116.13521, 29.819532], + [116.172783, 29.828358], + [116.227601, 29.816936], + [116.250391, 29.785777], + [116.280572, 29.788893], + [116.342782, 29.835626], + [116.467818, 29.896347], + [116.525716, 29.897385], + [116.552201, 29.909836], + [116.585462, 30.045657], + [116.620571, 30.073109], + [116.666766, 30.076734], + [116.720353, 30.053945], + [116.747454, 30.057053], + [116.783794, 30.030632], + [116.802889, 29.99643], + [116.830606, 30.004723], + [116.83307, 29.95755], + [116.868794, 29.980361], + [116.900207, 29.949253], + [116.882961, 29.893753], + [116.780715, 29.792529], + [116.762237, 29.802396], + [116.673541, 29.709916], + [116.698795, 29.707836], + [116.70557, 29.69692], + [116.706802, 29.6964], + [116.704954, 29.688602], + [116.680317, 29.681323], + [116.651983, 29.637118], + [116.716657, 29.590813], + [116.721585, 29.564789], + [116.760389, 29.599139], + [116.780715, 29.569994], + [116.849084, 29.57624], + [116.873722, 29.609546], + [116.939627, 29.648561], + [116.974736, 29.657403], + [116.996294, 29.683403], + [117.041873, 29.680803], + [117.112706, 29.711995], + [117.108395, 29.75201], + [117.136728, 29.775388], + [117.123177, 29.798761], + [117.073286, 29.831992], + [117.127489, 29.86158], + [117.129952, 29.89946], + [117.171836, 29.920729], + [117.2168, 29.926953], + [117.246365, 29.915023], + [117.261763, 29.880781], + [117.25314, 29.834588], + [117.29256, 29.822647], + [117.338756, 29.848085], + [117.359082, 29.812782], + [117.382487, 29.840818], + [117.415132, 29.85068], + [117.408973, 29.802396], + [117.455168, 29.749412], + [117.453936, 29.688082], + [117.490277, 29.660003], + [117.530313, 29.654282], + [117.523538, 29.630356], + [117.543248, 29.588731], + [117.608537, 29.591333], + [117.647957, 29.614749], + [117.678754, 29.595496], + [117.690457, 29.555939], + [117.729877, 29.550213], + [117.795167, 29.570515], + [117.872775, 29.54761], + [117.933753, 29.549172], + [118.00397, 29.578322], + [118.042774, 29.566351], + [118.050782, 29.542924], + [118.095129, 29.534072], + [118.143788, 29.489803], + [118.127774, 29.47209], + [118.136397, 29.418932], + [118.193064, 29.395472], + [118.248498, 29.431443], + [118.316252, 29.422581], + [118.306396, 29.479384], + [118.329802, 29.495012], + [118.347664, 29.474174], + [118.381541, 29.504909], + [118.496106, 29.519492], + [118.500417, 29.57572], + [118.532446, 29.588731], + [118.573714, 29.638159], + [118.61991, 29.654282], + [118.647011, 29.64336], + [118.700598, 29.706277], + [118.744945, 29.73902], + [118.740634, 29.814859], + [118.841032, 29.891159], + [118.838568, 29.934733], + [118.894619, 29.937845], + [118.902626, 30.029078], + [118.878604, 30.064822], + [118.873677, 30.11505], + [118.895234, 30.148694], + [118.852119, 30.149729], + [118.852735, 30.166805], + [118.929727, 30.2025], + [118.905089, 30.216464], + [118.877988, 30.282637], + [118.880452, 30.31519], + [118.954365, 30.360126], + [118.988857, 30.332237], + [119.06277, 30.304856], + [119.091719, 30.323972], + [119.126828, 30.304856], + [119.201356, 30.290905], + [119.236465, 30.297106], + [119.246936, 30.341018], + [119.277117, 30.341018], + [119.326392, 30.372002], + [119.349182, 30.349281], + [119.402768, 30.374584], + [119.36766, 30.38491], + [119.335015, 30.448389], + [119.336247, 30.508734], + [119.326392, 30.532964], + [119.272189, 30.510281], + [119.237081, 30.546881], + [119.265414, 30.574709], + [119.238929, 30.609225], + [119.323312, 30.630341], + [119.343022, 30.664322], + [119.39045, 30.685941], + [119.408312, 30.645274], + [119.444652, 30.650422], + [119.482841, 30.704467], + [119.479761, 30.772365], + [119.527188, 30.77905], + [119.55429, 30.825828], + [119.575847, 30.829939], + [119.557369, 30.874124], + [119.563529, 30.919315], + [119.582007, 30.932149], + [119.580159, 30.967051], + [119.633746, 31.019379], + [119.629434, 31.085517], + [119.649144, 31.104991], + [119.623891, 31.130096], + [119.599869, 31.10909], + [119.532732, 31.159291], + [119.461283, 31.156219], + [119.439109, 31.177214], + [119.391682, 31.174142], + [119.360269, 31.213049], + [119.374435, 31.258591], + [119.350414, 31.301043], + [119.338095, 31.259103], + [119.294363, 31.263195], + [119.266646, 31.250405], + [119.198277, 31.270357], + [119.197661, 31.295418], + [119.158241, 31.294907], + [119.107118, 31.250917], + [119.10527, 31.235055], + [119.014727, 31.241707], + [118.984546, 31.237102], + [118.870597, 31.242219], + [118.794836, 31.229426], + [118.756648, 31.279564], + [118.726467, 31.282121], + [118.720924, 31.322518], + [118.745561, 31.372606], + [118.767735, 31.363919], + [118.824401, 31.375672], + [118.852119, 31.393553], + [118.883532, 31.500261], + [118.857046, 31.506384], + [118.865669, 31.519139], + [118.885995, 31.519139], + [118.881684, 31.564023], + [118.858894, 31.623665], + [118.802844, 31.619078], + [118.773894, 31.682759], + [118.748025, 31.675629], + [118.736322, 31.633347], + [118.643315, 31.649651], + [118.643315, 31.671555], + [118.697518, 31.709747], + [118.653786, 31.73011], + [118.641467, 31.75861], + [118.571866, 31.746397], + [118.5577, 31.73011], + [118.521975, 31.743343], + [118.533678, 31.76726], + [118.481939, 31.778453], + [118.504729, 31.841516], + [118.466541, 31.857784], + [118.472084, 31.879639], + [118.363679, 31.930443], + [118.389548, 31.985281], + [118.394476, 32.076098], + [118.433896, 32.086746], + [118.501033, 32.121726], + [118.49549, 32.165304], + [118.510888, 32.194176], + [118.643931, 32.209875], + [118.674728, 32.250375], + [118.657482, 32.30148], + [118.703061, 32.328792], + [118.685199, 32.403604], + [118.691359, 32.472295], + [118.628533, 32.467751], + [118.592192, 32.481383], + [118.608823, 32.536899], + [118.564475, 32.562122], + [118.568787, 32.585825], + [118.59712, 32.600951], + [118.632844, 32.578261], + [118.658714, 32.594397], + [118.688895, 32.588346], + [118.719076, 32.614059], + [118.719076, 32.614059], + [118.73509, 32.58885], + [118.757264, 32.603976], + [118.784981, 32.582295], + [118.820706, 32.60448], + [118.84288, 32.56767], + [118.908169, 32.59238], + [118.890923, 32.553042], + [118.92172, 32.557078], + [118.922336, 32.557078], + [118.92172, 32.557078], + [118.922336, 32.557078], + [118.975923, 32.505108], + [119.041212, 32.515201], + [119.084944, 32.452602], + [119.142226, 32.499556], + [119.168096, 32.536394], + [119.152697, 32.557582], + [119.22045, 32.576748], + [119.230921, 32.607001], + [119.208748, 32.641276], + [119.211827, 32.708275], + [119.184726, 32.825529], + [119.113277, 32.823014], + [119.054763, 32.8748], + [119.020886, 32.955685], + [118.993169, 32.958196], + [118.934039, 32.93861], + [118.892771, 32.941121], + [118.89585, 32.957694], + [118.89585, 32.957694], + [118.849039, 32.956689], + [118.846575, 32.922034], + [118.821322, 32.920527], + [118.810235, 32.853687], + [118.743097, 32.853184], + [118.743097, 32.853184], + [118.73817, 32.772708], + [118.756648, 32.737477], + [118.707373, 32.72036], + [118.642699, 32.744525], + [118.572482, 32.719856], + [118.560163, 32.729926], + [118.483787, 32.721367], + [118.450526, 32.743518], + [118.411106, 32.715828], + [118.375382, 32.718849], + [118.363063, 32.770695], + [118.334114, 32.761637], + [118.300237, 32.783275], + [118.301469, 32.846145], + [118.250346, 32.848157], + [118.2331, 32.914498], + [118.252194, 32.936601], + [118.291614, 32.946143], + [118.303933, 32.96874], + [118.26944, 32.969242], + [118.244803, 32.998359], + [118.243571, 33.027967], + [118.219549, 33.114227], + [118.217085, 33.191888], + [118.178281, 33.217926], + [118.149332, 33.169348], + [118.038463, 33.134776], + [118.037231, 33.152314], + [117.988572, 33.180869], + [117.977485, 33.226437], + [117.942376, 33.224936], + [117.939297, 33.262475], + [117.974405, 33.279487], + [117.992883, 33.333005], + [118.029224, 33.374995], + [118.016905, 33.402978], + [118.027376, 33.455421], + [118.050782, 33.491863], + [118.107448, 33.475391], + [118.117919, 33.594615], + [118.112376, 33.617045], + [118.16781, 33.663381], + [118.161035, 33.735576], + [118.117919, 33.766427], + [118.065564, 33.76593], + [118.019985, 33.738562], + [117.972557, 33.74951], + [117.901724, 33.720146], + [117.843826, 33.736074], + [117.791471, 33.733585], + [117.750203, 33.710688], + [117.72495, 33.74951], + [117.739732, 33.758467], + [117.759442, 33.874318], + [117.753899, 33.891211], + [117.715095, 33.879287], + [117.672595, 33.934916], + [117.671363, 33.992494], + [117.629479, 34.028708], + [117.612849, 34.000433], + [117.569117, 33.985051], + [117.543248, 34.038627], + [117.514914, 34.060941], + [117.435458, 34.028212], + [117.404045, 34.03218], + [117.357234, 34.088205], + [117.311654, 34.067882], + [117.277162, 34.078787], + [117.257452, 34.065899], + [117.192162, 34.068873], + [117.130568, 34.101586], + [117.123793, 34.128342], + [117.046801, 34.151622], + [117.025243, 34.167469], + [117.051112, 34.221425], + [116.969192, 34.283753], + [116.983359, 34.348011], + [116.960569, 34.363821], + [116.969192, 34.389012], + [116.909446, 34.408271], + [116.828142, 34.389012], + [116.782563, 34.429993], + [116.773939, 34.453683], + [116.722816, 34.472434], + [116.662454, 34.472927], + [116.592237, 34.493646], + [116.594085, 34.511894], + [116.490607, 34.573513], + [116.477057, 34.614896], + [116.432709, 34.630163], + [116.430245, 34.650843], + [116.374195, 34.640011], + [116.334159, 34.620806], + [116.32492, 34.601104], + [116.286116, 34.608986], + [116.247927, 34.551829], + [116.196804, 34.575977], + [116.191261, 34.535561], + [116.204196, 34.508442], + [116.178326, 34.496112], + [116.162312, 34.459605], + [116.178942, 34.430487], + [116.215898, 34.403333], + [116.213435, 34.382098], + [116.255934, 34.376665], + [116.301514, 34.342082], + [116.357564, 34.319843], + [116.372347, 34.26595], + [116.409303, 34.273863], + [116.409303, 34.273863], + [116.456731, 34.268917], + [116.516477, 34.296114], + [116.562056, 34.285731], + [116.582382, 34.266444], + [116.545426, 34.241711], + [116.542962, 34.203608], + [116.565752, 34.16945], + [116.536187, 34.151127], + [116.52818, 34.122892], + [116.576223, 34.068873], + [116.576223, 34.068873], + [116.599629, 34.014324], + [116.599629, 34.014324] + ] + ], + [ + [ + [118.865669, 31.519139], + [118.857046, 31.506384], + [118.883532, 31.500261], + [118.885995, 31.519139], + [118.865669, 31.519139] + ] + ], + [ + [ + [116.698795, 29.707836], + [116.673541, 29.709916], + [116.653831, 29.694841], + [116.680317, 29.681323], + [116.704954, 29.688602], + [116.706802, 29.6964], + [116.70557, 29.69692], + [116.698795, 29.707836] + ] + ], + [ + [ + [115.5088, 32.468761], + [115.509416, 32.466741], + [115.510648, 32.467751], + [115.510648, 32.468256], + [115.510648, 32.468761], + [115.5088, 32.468761] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 350000, + "name": "福建省", + "center": [119.306239, 26.075302], + "centroid": [118.006468, 26.069925], + "childrenNum": 9, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 12, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [119.004872, 24.970009], + [118.989473, 24.973807], + [119.023966, 25.04377], + [119.016575, 25.058409], + [118.974691, 25.024792], + [118.945126, 25.028588], + [118.892155, 25.092558], + [118.974691, 25.115319], + [118.951901, 25.15162], + [118.985162, 25.168954], + [118.985162, 25.19495], + [118.942046, 25.211195], + [118.940198, 25.21715], + [118.943278, 25.221482], + [118.903242, 25.239347], + [118.900162, 25.242595], + [118.919256, 25.248008], + [118.91556, 25.256668], + [118.918024, 25.25721], + [118.956212, 25.272905], + [118.996864, 25.266411], + [118.975307, 25.237723], + [118.990089, 25.20199], + [119.055379, 25.219316], + [119.074473, 25.211195], + [119.054147, 25.168412], + [119.032589, 25.17437], + [119.028893, 25.139702], + [119.06585, 25.102855], + [119.075705, 25.099604], + [119.134219, 25.106107], + [119.107118, 25.075214], + [119.119436, 25.012861], + [119.146538, 25.056782], + [119.165632, 25.145661], + [119.137299, 25.15487], + [119.108349, 25.193867], + [119.131755, 25.223106], + [119.190269, 25.175995], + [119.231537, 25.188993], + [119.26911, 25.159746], + [119.314689, 25.190076], + [119.294979, 25.237182], + [119.331935, 25.230685], + [119.380595, 25.250173], + [119.333167, 25.287516], + [119.299291, 25.328634], + [119.247552, 25.333502], + [119.240776, 25.316733], + [119.218603, 25.368115], + [119.14469, 25.388121], + [119.151465, 25.426503], + [119.191501, 25.424341], + [119.232153, 25.442176], + [119.219834, 25.468654], + [119.256175, 25.488643], + [119.275269, 25.476758], + [119.26295, 25.428124], + [119.288204, 25.410827], + [119.353493, 25.411908], + [119.343638, 25.472436], + [119.359037, 25.521592], + [119.400921, 25.493505], + [119.45266, 25.493505], + [119.438493, 25.412449], + [119.463131, 25.448661], + [119.491464, 25.443257], + [119.48592, 25.418935], + [119.507478, 25.396231], + [119.486536, 25.369737], + [119.548746, 25.365952], + [119.578927, 25.400556], + [119.555521, 25.429205], + [119.577695, 25.445959], + [119.59063, 25.398394], + [119.582623, 25.374063], + [119.597405, 25.334584], + [119.649144, 25.342697], + [119.665159, 25.3719], + [119.656535, 25.396772], + [119.670086, 25.435691], + [119.622659, 25.434069], + [119.675014, 25.468113], + [119.682405, 25.445959], + [119.688564, 25.441095], + [119.773564, 25.395691], + [119.764325, 25.433529], + [119.804977, 25.457847], + [119.866571, 25.455145], + [119.864107, 25.469734], + [119.862875, 25.474597], + [119.811136, 25.507009], + [119.81668, 25.532393], + [119.861027, 25.531313], + [119.883817, 25.546432], + [119.831462, 25.579905], + [119.843165, 25.597717], + [119.790194, 25.614447], + [119.785883, 25.66786], + [119.700267, 25.616606], + [119.683637, 25.592859], + [119.716898, 25.551292], + [119.715666, 25.51187], + [119.680557, 25.497827], + [119.675014, 25.475137], + [119.634362, 25.475137], + [119.611572, 25.519972], + [119.616499, 25.556691], + [119.586934, 25.59232], + [119.534579, 25.585303], + [119.541355, 25.6247], + [119.478529, 25.631715], + [119.472986, 25.662466], + [119.543819, 25.684581], + [119.602949, 25.68512], + [119.602949, 25.714779], + [119.626354, 25.723406], + [119.628202, 25.87212], + [119.638057, 25.889888], + [119.69534, 25.904424], + [119.723673, 26.011503], + [119.700267, 26.032477], + [119.668854, 26.026024], + [119.654688, 26.090002], + [119.618963, 26.11956], + [119.604181, 26.168985], + [119.664543, 26.202282], + [119.676246, 26.262943], + [119.7711, 26.285481], + [119.802513, 26.268846], + [119.806825, 26.307479], + [119.845013, 26.323036], + [119.862875, 26.307479], + [119.904143, 26.308552], + [119.95465, 26.352534], + [119.946027, 26.374519], + [119.893672, 26.355752], + [119.835774, 26.434019], + [119.83639, 26.454381], + [119.788346, 26.583435], + [119.740303, 26.610727], + [119.670086, 26.618218], + [119.605412, 26.595744], + [119.577695, 26.622498], + [119.619579, 26.649246], + [119.637441, 26.703256], + [119.664543, 26.726243], + [119.711354, 26.686681], + [119.833926, 26.690959], + [119.864107, 26.671174], + [119.873962, 26.642827], + [119.908455, 26.661547], + [119.899216, 26.693098], + [119.938636, 26.747088], + [119.942947, 26.784492], + [120.052584, 26.786629], + [120.061824, 26.768997], + [119.99407, 26.720363], + [119.969433, 26.686681], + [119.972512, 26.654594], + [119.949107, 26.624638], + [119.901679, 26.624638], + [119.851788, 26.595209], + [119.828383, 26.524013], + [119.867187, 26.509019], + [119.947875, 26.56042], + [119.93802, 26.576478], + [119.967585, 26.597885], + [120.007621, 26.595744], + [120.063671, 26.627848], + [120.093852, 26.613938], + [120.1382, 26.638012], + [120.110483, 26.692563], + [120.162222, 26.717691], + [120.151135, 26.750829], + [120.106787, 26.752966], + [120.136352, 26.797847], + [120.103707, 26.794642], + [120.102476, 26.82669], + [120.073526, 26.823485], + [120.054432, 26.863533], + [120.117874, 26.882751], + [120.126497, 26.920644], + [120.130193, 26.917976], + [120.1807, 26.920644], + [120.233055, 26.907837], + [120.25954, 26.982526], + [120.279866, 26.987326], + [120.275554, 27.027315], + [120.29588, 27.035845], + [120.282946, 27.089671], + [120.391967, 27.081146], + [120.403054, 27.10086], + [120.461568, 27.142407], + [120.404286, 27.204166], + [120.401822, 27.250996], + [120.430155, 27.258976], + [120.343924, 27.363199], + [120.340844, 27.399867], + [120.273091, 27.38924], + [120.26262, 27.432804], + [120.221352, 27.420055], + [120.134504, 27.420055], + [120.136968, 27.402523], + [120.096316, 27.390302], + [120.052584, 27.338747], + [120.026099, 27.344063], + [120.008237, 27.375423], + [119.960194, 27.365857], + [119.938636, 27.329709], + [119.843165, 27.300464], + [119.768636, 27.307909], + [119.782187, 27.330241], + [119.739687, 27.362668], + [119.750774, 27.373829], + [119.711354, 27.403054], + [119.685485, 27.438646], + [119.703347, 27.446613], + [119.70889, 27.514042], + [119.690412, 27.537394], + [119.659615, 27.540578], + [119.675014, 27.574534], + [119.630666, 27.582491], + [119.626354, 27.620676], + [119.644217, 27.663619], + [119.606028, 27.674749], + [119.541971, 27.666799], + [119.501319, 27.649837], + [119.501935, 27.610601], + [119.466826, 27.526249], + [119.438493, 27.508734], + [119.416935, 27.539517], + [119.360269, 27.524657], + [119.334399, 27.480067], + [119.285124, 27.457766], + [119.26911, 27.42218], + [119.224146, 27.416868], + [119.14777, 27.424836], + [119.121284, 27.438115], + [119.129907, 27.475289], + [119.092335, 27.466262], + [119.03998, 27.478475], + [119.020886, 27.498118], + [118.983314, 27.498649], + [118.986393, 27.47582], + [118.955597, 27.4498], + [118.907553, 27.460952], + [118.869365, 27.540047], + [118.909401, 27.568168], + [118.913713, 27.619616], + [118.879836, 27.667859], + [118.873677, 27.733563], + [118.829329, 27.847921], + [118.818242, 27.916689], + [118.753568, 27.947885], + [118.730163, 27.970615], + [118.733858, 28.027684], + [118.719076, 28.063601], + [118.767735, 28.10584], + [118.802228, 28.117453], + [118.805923, 28.154923], + [118.771431, 28.188687], + [118.804075, 28.207675], + [118.802228, 28.240368], + [118.756032, 28.252493], + [118.719692, 28.312047], + [118.699366, 28.309939], + [118.674728, 28.27147], + [118.651322, 28.277267], + [118.595272, 28.258292], + [118.588497, 28.282538], + [118.493026, 28.262509], + [118.490562, 28.238259], + [118.444367, 28.253548], + [118.433896, 28.288335], + [118.424041, 28.291497], + [118.314404, 28.221913], + [118.339041, 28.193962], + [118.375382, 28.186577], + [118.361215, 28.155978], + [118.356288, 28.091586], + [118.242339, 28.075746], + [118.199839, 28.049869], + [118.153644, 28.062016], + [118.120999, 28.041946], + [118.129006, 28.017118], + [118.094513, 28.003909], + [118.096977, 27.970615], + [117.999043, 27.991227], + [117.965166, 27.962687], + [117.942992, 27.974315], + [117.910963, 27.949471], + [117.856145, 27.94577], + [117.78716, 27.896063], + [117.788392, 27.855858], + [117.740348, 27.800286], + [117.704624, 27.834162], + [117.68245, 27.823577], + [117.649805, 27.851625], + [117.609769, 27.863265], + [117.556182, 27.966387], + [117.52169, 27.982243], + [117.477958, 27.930966], + [117.453936, 27.939955], + [117.407741, 27.893948], + [117.366473, 27.88231], + [117.341836, 27.855858], + [117.334444, 27.8876], + [117.280242, 27.871201], + [117.276546, 27.847921], + [117.303031, 27.833103], + [117.296256, 27.764282], + [117.245133, 27.71926], + [117.205097, 27.714492], + [117.204481, 27.683759], + [117.174916, 27.677399], + [117.114554, 27.692238], + [117.096076, 27.667329], + [117.11209, 27.645596], + [117.094228, 27.627569], + [117.065279, 27.665739], + [117.040641, 27.669979], + [117.003685, 27.625449], + [117.024627, 27.592569], + [117.01662, 27.563393], + [117.054808, 27.5427], + [117.076982, 27.566046], + [117.103467, 27.533149], + [117.110242, 27.458828], + [117.133032, 27.42218], + [117.107163, 27.393491], + [117.104699, 27.330773], + [117.140423, 27.322798], + [117.136728, 27.303123], + [117.171836, 27.29036], + [117.149662, 27.241419], + [117.044953, 27.146667], + [117.05296, 27.100327], + [116.967344, 27.061962], + [116.936547, 27.019319], + [116.910062, 27.034779], + [116.851548, 27.009188], + [116.817671, 27.018252], + [116.679085, 26.978259], + [116.632889, 26.933984], + [116.602092, 26.888623], + [116.548506, 26.84004], + [116.543578, 26.803723], + [116.557745, 26.773806], + [116.515245, 26.720898], + [116.520172, 26.684543], + [116.566368, 26.650315], + [116.553433, 26.575942], + [116.539267, 26.559349], + [116.597165, 26.512768], + [116.610716, 26.476882], + [116.638433, 26.477418], + [116.608252, 26.429732], + [116.601476, 26.372911], + [116.553433, 26.365404], + [116.553433, 26.400253], + [116.519557, 26.410437], + [116.499846, 26.361651], + [116.459194, 26.345026], + [116.437021, 26.308016], + [116.412999, 26.297822], + [116.385282, 26.238253], + [116.400064, 26.202819], + [116.392057, 26.171133], + [116.435789, 26.159854], + [116.476441, 26.172745], + [116.489375, 26.113649], + [116.384666, 26.030864], + [116.360028, 25.991601], + [116.369883, 25.963088], + [116.326152, 25.956631], + [116.303362, 25.924341], + [116.258398, 25.902809], + [116.225138, 25.908731], + [116.17771, 25.894195], + [116.132131, 25.860273], + [116.131515, 25.824185], + [116.18079, 25.778926], + [116.129667, 25.758985], + [116.106877, 25.701299], + [116.067457, 25.703995], + [116.068689, 25.646282], + [116.041588, 25.62416], + [116.063145, 25.56317], + [116.040356, 25.548052], + [116.03666, 25.514571], + [116.005247, 25.490264], + [116.023109, 25.435691], + [115.992928, 25.374063], + [116.008327, 25.319437], + [115.987385, 25.290221], + [115.949813, 25.292386], + [115.930719, 25.236099], + [115.855574, 25.20957], + [115.860501, 25.165704], + [115.888219, 25.128866], + [115.880212, 25.092016], + [115.908545, 25.084428], + [115.928255, 25.050276], + [115.873436, 25.019911], + [115.925175, 24.960786], + [115.870356, 24.959701], + [115.89253, 24.936911], + [115.907929, 24.923343], + [115.985537, 24.899461], + [116.015102, 24.905975], + [116.068073, 24.850053], + [116.153073, 24.846795], + [116.191877, 24.877203], + [116.221442, 24.829959], + [116.251007, 24.82507], + [116.244232, 24.793563], + [116.297202, 24.801712], + [116.345862, 24.828872], + [116.363724, 24.87123], + [116.395137, 24.877746], + [116.417927, 24.840821], + [116.381586, 24.82507], + [116.375427, 24.803885], + [116.419158, 24.767482], + [116.416079, 24.744113], + [116.44626, 24.714216], + [116.485064, 24.720196], + [116.517709, 24.652225], + [116.506622, 24.621218], + [116.530027, 24.604895], + [116.570679, 24.621762], + [116.600861, 24.654401], + [116.623034, 24.64189], + [116.667382, 24.658752], + [116.777635, 24.679418], + [116.815207, 24.654944], + [116.761005, 24.583128], + [116.759157, 24.545572], + [116.796729, 24.502014], + [116.83307, 24.496568], + [116.860787, 24.460075], + [116.839229, 24.442097], + [116.903903, 24.369614], + [116.895895, 24.350533], + [116.919301, 24.321087], + [116.914374, 24.287817], + [116.938395, 24.28127], + [116.933468, 24.220157], + [116.956257, 24.216883], + [116.998757, 24.179217], + [116.9347, 24.126794], + [116.930388, 24.064514], + [116.953178, 24.008218], + [116.981511, 23.999471], + [116.976583, 23.931659], + [116.955642, 23.922359], + [116.981511, 23.855602], + [117.012308, 23.855054], + [117.019083, 23.801952], + [117.048032, 23.758687], + [117.055424, 23.694038], + [117.123793, 23.647448], + [117.147199, 23.654027], + [117.192778, 23.629356], + [117.192778, 23.5619], + [117.291328, 23.571225], + [117.302415, 23.550379], + [117.387415, 23.555317], + [117.463791, 23.584937], + [117.454552, 23.628259], + [117.493357, 23.642514], + [117.501364, 23.70445], + [117.54448, 23.715956], + [117.601762, 23.70171], + [117.660276, 23.789357], + [117.651653, 23.815093], + [117.671979, 23.878041], + [117.691073, 23.888985], + [117.762522, 23.886796], + [117.792703, 23.906494], + [117.807486, 23.947521], + [117.864768, 24.004938], + [117.910347, 24.012045], + [117.927594, 24.039922], + [117.936217, 24.100029], + [118.000275, 24.152462], + [118.019369, 24.197232], + [118.074803, 24.225615], + [118.115455, 24.229435], + [118.158571, 24.269814], + [118.112376, 24.357075], + [118.081579, 24.35653], + [118.088354, 24.408858], + [118.048934, 24.418122], + [118.084042, 24.528695], + [118.121615, 24.570067], + [118.150564, 24.583673], + [118.169042, 24.559725], + [118.242955, 24.51236], + [118.375382, 24.536317], + [118.363679, 24.567889], + [118.444367, 24.614689], + [118.512736, 24.60816], + [118.557084, 24.572788], + [118.558316, 24.51236], + [118.614366, 24.521617], + [118.680272, 24.58204], + [118.687047, 24.63373], + [118.661178, 24.622306], + [118.652554, 24.653857], + [118.670417, 24.679962], + [118.703677, 24.665278], + [118.778822, 24.743569], + [118.786213, 24.77672], + [118.650707, 24.808774], + [118.647627, 24.843536], + [118.702445, 24.865258], + [118.69875, 24.848967], + [118.748641, 24.84245], + [118.807771, 24.870687], + [118.834256, 24.854397], + [118.864437, 24.887518], + [118.933423, 24.870687], + [118.988857, 24.878831], + [118.987009, 24.898375], + [118.932807, 24.906518], + [118.91864, 24.932569], + [118.945741, 24.954275], + [119.014111, 24.941252], + [119.032589, 24.961328], + [119.032589, 24.961871], + [119.007335, 24.963499], + [119.004872, 24.970009] + ] + ], + [ + [ + [118.412338, 24.514538], + [118.374766, 24.458986], + [118.318715, 24.486765], + [118.298389, 24.477506], + [118.31194, 24.424661], + [118.282375, 24.413218], + [118.329802, 24.382152], + [118.353208, 24.415398], + [118.405563, 24.427931], + [118.457918, 24.412128], + [118.477012, 24.437738], + [118.451758, 24.506915], + [118.412338, 24.514538] + ] + ], + [ + [ + [119.471138, 25.197116], + [119.507478, 25.183036], + [119.52534, 25.157579], + [119.549362, 25.161912], + [119.566608, 25.210112], + [119.540739, 25.20199], + [119.501319, 25.21715], + [119.473601, 25.259916], + [119.44342, 25.238806], + [119.444036, 25.20199], + [119.471138, 25.197116] + ] + ], + [ + [ + [119.580159, 25.627398], + [119.611572, 25.669479], + [119.580775, 25.650059], + [119.580159, 25.627398] + ] + ], + [ + [ + [119.976824, 26.191005], + [120.016244, 26.217316], + [119.998998, 26.235569], + [119.970665, 26.217852], + [119.976824, 26.191005] + ] + ], + [ + [ + [118.230636, 24.401228], + [118.273752, 24.441007], + [118.233716, 24.445911], + [118.230636, 24.401228] + ] + ], + [ + [ + [119.906607, 26.68989], + [119.926933, 26.664756], + [119.950954, 26.692563], + [119.906607, 26.68989] + ] + ], + [ + [ + [118.204151, 24.504737], + [118.191832, 24.536861], + [118.14502, 24.560814], + [118.093281, 24.540672], + [118.068644, 24.463344], + [118.084042, 24.435559], + [118.143173, 24.420847], + [118.19368, 24.463344], + [118.204151, 24.504737] + ] + ], + [ + [ + [119.929397, 26.134067], + [119.960194, 26.146961], + [119.919542, 26.172208], + [119.929397, 26.134067] + ] + ], + [ + [ + [119.642985, 26.129231], + [119.665159, 26.155556], + [119.62697, 26.173282], + [119.606028, 26.15287], + [119.642985, 26.129231] + ] + ], + [ + [ + [120.034106, 26.488667], + [120.066751, 26.498308], + [120.071679, 26.521336], + [120.035954, 26.515981], + [120.034106, 26.488667] + ] + ], + [ + [ + [119.662079, 25.646822], + [119.673782, 25.632794], + [119.718745, 25.634952], + [119.716898, 25.664624], + [119.662079, 25.646822] + ] + ], + [ + [ + [119.760629, 26.613402], + [119.776644, 26.600025], + [119.818527, 26.616613], + [119.796354, 26.630523], + [119.760629, 26.613402] + ] + ], + [ + [ + [120.135736, 26.550784], + [120.167149, 26.571661], + [120.153598, 26.604841], + [120.117874, 26.568984], + [120.135736, 26.550784] + ] + ], + [ + [ + [120.360554, 26.916909], + [120.394431, 26.933984], + [120.363018, 26.967592], + [120.327909, 26.963858], + [120.319286, 26.944654], + [120.360554, 26.916909] + ] + ], + [ + [ + [120.150519, 26.798916], + [120.140048, 26.795176], + [120.163454, 26.798381], + [120.161606, 26.803189], + [120.150519, 26.798916] + ] + ], + [ + [ + [119.668238, 26.628383], + [119.720593, 26.635873], + [119.758781, 26.659408], + [119.748926, 26.681334], + [119.712586, 26.6685], + [119.673782, 26.680799], + [119.651608, 26.657269], + [119.668238, 26.628383] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 360000, + "name": "江西省", + "center": [115.892151, 28.676493], + "centroid": [115.732975, 27.636112], + "childrenNum": 11, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 13, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [118.193064, 29.395472], + [118.136397, 29.418932], + [118.127774, 29.47209], + [118.143788, 29.489803], + [118.095129, 29.534072], + [118.050782, 29.542924], + [118.042774, 29.566351], + [118.00397, 29.578322], + [117.933753, 29.549172], + [117.872775, 29.54761], + [117.795167, 29.570515], + [117.729877, 29.550213], + [117.690457, 29.555939], + [117.678754, 29.595496], + [117.647957, 29.614749], + [117.608537, 29.591333], + [117.543248, 29.588731], + [117.523538, 29.630356], + [117.530313, 29.654282], + [117.490277, 29.660003], + [117.453936, 29.688082], + [117.455168, 29.749412], + [117.408973, 29.802396], + [117.415132, 29.85068], + [117.382487, 29.840818], + [117.359082, 29.812782], + [117.338756, 29.848085], + [117.29256, 29.822647], + [117.25314, 29.834588], + [117.261763, 29.880781], + [117.246365, 29.915023], + [117.2168, 29.926953], + [117.171836, 29.920729], + [117.129952, 29.89946], + [117.127489, 29.86158], + [117.073286, 29.831992], + [117.123177, 29.798761], + [117.136728, 29.775388], + [117.108395, 29.75201], + [117.112706, 29.711995], + [117.041873, 29.680803], + [116.996294, 29.683403], + [116.974736, 29.657403], + [116.939627, 29.648561], + [116.873722, 29.609546], + [116.849084, 29.57624], + [116.780715, 29.569994], + [116.760389, 29.599139], + [116.721585, 29.564789], + [116.716657, 29.590813], + [116.651983, 29.637118], + [116.680317, 29.681323], + [116.653831, 29.694841], + [116.673541, 29.709916], + [116.762237, 29.802396], + [116.780715, 29.792529], + [116.882961, 29.893753], + [116.900207, 29.949253], + [116.868794, 29.980361], + [116.83307, 29.95755], + [116.830606, 30.004723], + [116.802889, 29.99643], + [116.783794, 30.030632], + [116.747454, 30.057053], + [116.720353, 30.053945], + [116.666766, 30.076734], + [116.620571, 30.073109], + [116.585462, 30.045657], + [116.552201, 29.909836], + [116.525716, 29.897385], + [116.467818, 29.896347], + [116.342782, 29.835626], + [116.280572, 29.788893], + [116.250391, 29.785777], + [116.227601, 29.816936], + [116.172783, 29.828358], + [116.13521, 29.819532], + [116.087167, 29.795125], + [116.049595, 29.761881], + [115.965827, 29.724469], + [115.909777, 29.723949], + [115.837096, 29.748373], + [115.762567, 29.793048], + [115.706517, 29.837703], + [115.667712, 29.850161], + [115.611662, 29.841337], + [115.51188, 29.840299], + [115.479235, 29.811224], + [115.470612, 29.739539], + [115.412714, 29.688602], + [115.355431, 29.649602], + [115.304924, 29.637118], + [115.28583, 29.618391], + [115.250722, 29.660003], + [115.176809, 29.654803], + [115.113367, 29.684963], + [115.117679, 29.655843], + [115.143548, 29.645961], + [115.120142, 29.597578], + [115.157099, 29.584568], + [115.154019, 29.510117], + [115.086266, 29.525741], + [115.087498, 29.560104], + [115.033295, 29.546568], + [115.00065, 29.572076], + [114.947679, 29.542924], + [114.966773, 29.522096], + [114.940288, 29.493971], + [114.900868, 29.505951], + [114.860216, 29.476258], + [114.888549, 29.436134], + [114.918114, 29.454374], + [114.90518, 29.473132], + [114.935977, 29.486678], + [114.947063, 29.465317], + [114.931049, 29.422581], + [114.895325, 29.397557], + [114.866375, 29.404335], + [114.812173, 29.383478], + [114.784455, 29.386086], + [114.759818, 29.363139], + [114.740724, 29.386607], + [114.67297, 29.395993], + [114.621847, 29.379828], + [114.589819, 29.352707], + [114.519602, 29.325578], + [114.466015, 29.324013], + [114.440145, 29.341752], + [114.376088, 29.322969], + [114.341595, 29.327665], + [114.307102, 29.365225], + [114.259059, 29.343839], + [114.252284, 29.23475], + [114.169748, 29.216993], + [114.063191, 29.204978], + [114.034857, 29.152204], + [113.98743, 29.126068], + [113.952321, 29.092604], + [113.94185, 29.047097], + [113.961561, 28.999476], + [113.955401, 28.978536], + [113.973879, 28.937692], + [114.008988, 28.955498], + [114.005292, 28.917788], + [114.028082, 28.891069], + [114.060111, 28.902596], + [114.056415, 28.872204], + [114.076741, 28.834464], + [114.124784, 28.843376], + [114.153734, 28.829221], + [114.137719, 28.779926], + [114.157429, 28.761566], + [114.122321, 28.623497], + [114.132176, 28.607211], + [114.08598, 28.558337], + [114.138335, 28.533629], + [114.15435, 28.507337], + [114.218407, 28.48472], + [114.217175, 28.466308], + [114.172212, 28.432632], + [114.214712, 28.403157], + [114.252284, 28.395787], + [114.2529, 28.319423], + [114.198081, 28.29097], + [114.182067, 28.249858], + [114.143879, 28.246694], + [114.109386, 28.205038], + [114.107538, 28.182885], + [114.068734, 28.171806], + [114.012068, 28.174972], + [113.992357, 28.161255], + [114.025002, 28.080499], + [114.047176, 28.057263], + [114.025618, 28.031382], + [113.970184, 28.041418], + [113.966488, 28.017646], + [113.936307, 28.018703], + [113.914133, 27.991227], + [113.864242, 28.004966], + [113.845148, 27.971672], + [113.822974, 27.982243], + [113.752141, 27.93361], + [113.72812, 27.874904], + [113.756453, 27.860091], + [113.763228, 27.799228], + [113.69917, 27.740979], + [113.696707, 27.71979], + [113.652359, 27.663619], + [113.607395, 27.625449], + [113.608627, 27.585143], + [113.579062, 27.545354], + [113.583374, 27.524657], + [113.627105, 27.49971], + [113.591381, 27.467855], + [113.59754, 27.428554], + [113.632033, 27.40518], + [113.605548, 27.38924], + [113.616635, 27.345658], + [113.657902, 27.347253], + [113.699786, 27.331836], + [113.72812, 27.350442], + [113.872865, 27.384988], + [113.872865, 27.346721], + [113.854387, 27.30525], + [113.872865, 27.289828], + [113.846996, 27.222262], + [113.779242, 27.137081], + [113.771851, 27.096598], + [113.803264, 27.099261], + [113.824206, 27.036378], + [113.86301, 27.018252], + [113.892575, 26.964925], + [113.927068, 26.948922], + [113.890112, 26.895562], + [113.877177, 26.859262], + [113.835909, 26.806394], + [113.853771, 26.769532], + [113.860546, 26.664221], + [113.912901, 26.613938], + [113.996669, 26.615543], + [114.019459, 26.587182], + [114.10877, 26.56952], + [114.07243, 26.480096], + [114.110002, 26.482775], + [114.090292, 26.455988], + [114.085364, 26.406149], + [114.062575, 26.406149], + [114.030546, 26.376664], + [114.047792, 26.337518], + [114.021307, 26.288701], + [114.029314, 26.266163], + [113.978807, 26.237716], + [113.972647, 26.20604], + [113.949242, 26.192616], + [113.962792, 26.150722], + [114.013299, 26.184023], + [114.088444, 26.168448], + [114.102611, 26.187783], + [114.181451, 26.214631], + [114.216559, 26.203355], + [114.237501, 26.152333], + [114.188842, 26.121172], + [114.10569, 26.097526], + [114.121089, 26.085702], + [114.087828, 26.06635], + [114.044096, 26.076564], + [114.008372, 26.015806], + [114.028082, 25.98138], + [114.028082, 25.893119], + [113.971416, 25.836036], + [113.961561, 25.77731], + [113.920293, 25.741197], + [113.913517, 25.701299], + [113.957249, 25.611749], + [113.983118, 25.599336], + [113.986198, 25.529153], + [113.962792, 25.528072], + [113.94493, 25.441635], + [114.003444, 25.442716], + [113.983118, 25.415152], + [114.050256, 25.36433], + [114.029314, 25.328093], + [114.017611, 25.273987], + [114.039785, 25.250714], + [114.055799, 25.277775], + [114.083517, 25.275611], + [114.115545, 25.302125], + [114.190074, 25.316733], + [114.204857, 25.29942], + [114.260291, 25.291845], + [114.2954, 25.299961], + [114.31511, 25.33837], + [114.382863, 25.317274], + [114.43029, 25.343779], + [114.438914, 25.376226], + [114.477718, 25.37136], + [114.541159, 25.416773], + [114.599674, 25.385959], + [114.63663, 25.324306], + [114.714238, 25.315651], + [114.743188, 25.274528], + [114.73518, 25.225813], + [114.693912, 25.213902], + [114.685905, 25.173287], + [114.73518, 25.155954], + [114.735796, 25.121822], + [114.664963, 25.10123], + [114.640326, 25.074129], + [114.604601, 25.083886], + [114.561485, 25.077382], + [114.532536, 25.022623], + [114.506051, 24.999844], + [114.45616, 24.99659], + [114.454928, 24.977062], + [114.395798, 24.951019], + [114.403189, 24.877746], + [114.378551, 24.861457], + [114.342211, 24.807145], + [114.336052, 24.749004], + [114.281849, 24.724001], + [114.27261, 24.700624], + [114.169132, 24.689749], + [114.19069, 24.656576], + [114.258443, 24.641346], + [114.289856, 24.619042], + [114.300943, 24.578775], + [114.363769, 24.582584], + [114.391486, 24.563535], + [114.403189, 24.497657], + [114.429058, 24.48622], + [114.534384, 24.559181], + [114.589819, 24.537406], + [114.627391, 24.576598], + [114.664963, 24.583673], + [114.704999, 24.525973], + [114.73826, 24.565168], + [114.729637, 24.608704], + [114.781376, 24.613057], + [114.827571, 24.588026], + [114.846665, 24.602719], + [114.868839, 24.562446], + [114.893477, 24.582584], + [114.909491, 24.661471], + [114.940288, 24.650049], + [115.00373, 24.679418], + [115.024672, 24.669085], + [115.057317, 24.703343], + [115.083802, 24.699537], + [115.104744, 24.667997], + [115.1842, 24.711498], + [115.258729, 24.728894], + [115.269816, 24.749548], + [115.306772, 24.758787], + [115.358511, 24.735416], + [115.372678, 24.774546], + [115.412714, 24.79302], + [115.476771, 24.762591], + [115.522967, 24.702799], + [115.555611, 24.683768], + [115.569778, 24.622306], + [115.605503, 24.62557], + [115.671408, 24.604895], + [115.68927, 24.545027], + [115.752712, 24.546116], + [115.785357, 24.567345], + [115.843871, 24.562446], + [115.840791, 24.584217], + [115.797676, 24.628834], + [115.780429, 24.663103], + [115.801371, 24.705517], + [115.769342, 24.708236], + [115.756408, 24.749004], + [115.776734, 24.774546], + [115.764415, 24.791933], + [115.790284, 24.856027], + [115.807531, 24.862543], + [115.824161, 24.909232], + [115.863581, 24.891318], + [115.861733, 24.863629], + [115.907313, 24.879917], + [115.885139, 24.898918], + [115.89253, 24.936911], + [115.870356, 24.959701], + [115.925175, 24.960786], + [115.873436, 25.019911], + [115.928255, 25.050276], + [115.908545, 25.084428], + [115.880212, 25.092016], + [115.888219, 25.128866], + [115.860501, 25.165704], + [115.855574, 25.20957], + [115.930719, 25.236099], + [115.949813, 25.292386], + [115.987385, 25.290221], + [116.008327, 25.319437], + [115.992928, 25.374063], + [116.023109, 25.435691], + [116.005247, 25.490264], + [116.03666, 25.514571], + [116.040356, 25.548052], + [116.063145, 25.56317], + [116.041588, 25.62416], + [116.068689, 25.646282], + [116.067457, 25.703995], + [116.106877, 25.701299], + [116.129667, 25.758985], + [116.18079, 25.778926], + [116.131515, 25.824185], + [116.132131, 25.860273], + [116.17771, 25.894195], + [116.225138, 25.908731], + [116.258398, 25.902809], + [116.303362, 25.924341], + [116.326152, 25.956631], + [116.369883, 25.963088], + [116.360028, 25.991601], + [116.384666, 26.030864], + [116.489375, 26.113649], + [116.476441, 26.172745], + [116.435789, 26.159854], + [116.392057, 26.171133], + [116.400064, 26.202819], + [116.385282, 26.238253], + [116.412999, 26.297822], + [116.437021, 26.308016], + [116.459194, 26.345026], + [116.499846, 26.361651], + [116.519557, 26.410437], + [116.553433, 26.400253], + [116.553433, 26.365404], + [116.601476, 26.372911], + [116.608252, 26.429732], + [116.638433, 26.477418], + [116.610716, 26.476882], + [116.597165, 26.512768], + [116.539267, 26.559349], + [116.553433, 26.575942], + [116.566368, 26.650315], + [116.520172, 26.684543], + [116.515245, 26.720898], + [116.557745, 26.773806], + [116.543578, 26.803723], + [116.548506, 26.84004], + [116.602092, 26.888623], + [116.632889, 26.933984], + [116.679085, 26.978259], + [116.817671, 27.018252], + [116.851548, 27.009188], + [116.910062, 27.034779], + [116.936547, 27.019319], + [116.967344, 27.061962], + [117.05296, 27.100327], + [117.044953, 27.146667], + [117.149662, 27.241419], + [117.171836, 27.29036], + [117.136728, 27.303123], + [117.140423, 27.322798], + [117.104699, 27.330773], + [117.107163, 27.393491], + [117.133032, 27.42218], + [117.110242, 27.458828], + [117.103467, 27.533149], + [117.076982, 27.566046], + [117.054808, 27.5427], + [117.01662, 27.563393], + [117.024627, 27.592569], + [117.003685, 27.625449], + [117.040641, 27.669979], + [117.065279, 27.665739], + [117.094228, 27.627569], + [117.11209, 27.645596], + [117.096076, 27.667329], + [117.114554, 27.692238], + [117.174916, 27.677399], + [117.204481, 27.683759], + [117.205097, 27.714492], + [117.245133, 27.71926], + [117.296256, 27.764282], + [117.303031, 27.833103], + [117.276546, 27.847921], + [117.280242, 27.871201], + [117.334444, 27.8876], + [117.341836, 27.855858], + [117.366473, 27.88231], + [117.407741, 27.893948], + [117.453936, 27.939955], + [117.477958, 27.930966], + [117.52169, 27.982243], + [117.556182, 27.966387], + [117.609769, 27.863265], + [117.649805, 27.851625], + [117.68245, 27.823577], + [117.704624, 27.834162], + [117.740348, 27.800286], + [117.788392, 27.855858], + [117.78716, 27.896063], + [117.856145, 27.94577], + [117.910963, 27.949471], + [117.942992, 27.974315], + [117.965166, 27.962687], + [117.999043, 27.991227], + [118.096977, 27.970615], + [118.094513, 28.003909], + [118.129006, 28.017118], + [118.120999, 28.041946], + [118.153644, 28.062016], + [118.199839, 28.049869], + [118.242339, 28.075746], + [118.356288, 28.091586], + [118.361215, 28.155978], + [118.375382, 28.186577], + [118.339041, 28.193962], + [118.314404, 28.221913], + [118.424041, 28.291497], + [118.433896, 28.288335], + [118.480091, 28.327325], + [118.455454, 28.384204], + [118.432048, 28.402104], + [118.456686, 28.424738], + [118.474548, 28.478934], + [118.414802, 28.497344], + [118.4302, 28.515225], + [118.412338, 28.55676], + [118.428352, 28.617193], + [118.428352, 28.617193], + [118.428352, 28.681267], + [118.403099, 28.702791], + [118.364295, 28.813491], + [118.300237, 28.826075], + [118.270056, 28.918836], + [118.195527, 28.904167], + [118.227556, 28.942406], + [118.165346, 28.986912], + [118.133933, 28.983771], + [118.115455, 29.009944], + [118.115455, 29.009944], + [118.097593, 28.998952], + [118.066796, 29.053898], + [118.076035, 29.074822], + [118.037847, 29.102017], + [118.045238, 29.149068], + [118.027992, 29.167882], + [118.042159, 29.210202], + [118.073571, 29.216993], + [118.077883, 29.290614], + [118.138861, 29.283828], + [118.178281, 29.297921], + [118.166578, 29.314099], + [118.205382, 29.343839], + [118.193064, 29.395472] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 370000, + "name": "山东省", + "center": [117.000923, 36.675807], + "centroid": [118.187759, 36.376092], + "childrenNum": 16, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 14, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [116.374195, 34.640011], + [116.392057, 34.710391], + [116.363724, 34.715311], + [116.369267, 34.749247], + [116.403144, 34.756131], + [116.408071, 34.850972], + [116.445028, 34.895652], + [116.557745, 34.908905], + [116.613795, 34.922645], + [116.622418, 34.939818], + [116.677853, 34.939327], + [116.781331, 34.916757], + [116.789338, 34.975133], + [116.815823, 34.965324], + [116.821983, 34.929515], + [116.858323, 34.928533], + [116.922381, 34.894671], + [116.929156, 34.843114], + [116.966113, 34.844588], + [116.979047, 34.815113], + [116.95133, 34.81069], + [116.969192, 34.771864], + [117.022163, 34.759081], + [117.070206, 34.713835], + [117.061583, 34.675947], + [117.073286, 34.639026], + [117.104083, 34.648874], + [117.15151, 34.559222], + [117.139191, 34.526687], + [117.166293, 34.434435], + [117.248213, 34.451216], + [117.252524, 34.48674], + [117.27285, 34.499565], + [117.267923, 34.532603], + [117.303647, 34.542463], + [117.27285, 34.556757], + [117.311654, 34.561686], + [117.311654, 34.561686], + [117.32151, 34.566614], + [117.32151, 34.566614], + [117.325205, 34.573021], + [117.325205, 34.573021], + [117.370785, 34.584846], + [117.402813, 34.569571], + [117.402813, 34.550843], + [117.465023, 34.484767], + [117.53832, 34.467006], + [117.592523, 34.462566], + [117.609769, 34.490686], + [117.659044, 34.501044], + [117.684298, 34.547392], + [117.801942, 34.518798], + [117.791471, 34.583368], + [117.793935, 34.651827], + [117.902956, 34.644443], + [117.909732, 34.670533], + [117.951615, 34.678408], + [118.053861, 34.650843], + [118.084042, 34.655766], + [118.114839, 34.614404], + [118.079115, 34.569571], + [118.185056, 34.543942], + [118.16473, 34.50499], + [118.132702, 34.483287], + [118.177665, 34.45319], + [118.179513, 34.379628], + [118.217701, 34.379134], + [118.220165, 34.405802], + [118.277447, 34.404814], + [118.290382, 34.424563], + [118.379693, 34.415183], + [118.404947, 34.427525], + [118.416034, 34.473914], + [118.439439, 34.507949], + [118.424657, 34.595193], + [118.439439, 34.626223], + [118.473932, 34.623269], + [118.460997, 34.656258], + [118.545997, 34.705964], + [118.601431, 34.714327], + [118.607591, 34.694155], + [118.664257, 34.693663], + [118.690127, 34.678408], + [118.739402, 34.693663], + [118.783749, 34.723181], + [118.764039, 34.740396], + [118.719076, 34.745313], + [118.739402, 34.792508], + [118.772047, 34.794474], + [118.80038, 34.843114], + [118.805307, 34.87307], + [118.860742, 34.944233], + [118.86259, 35.025626], + [118.928495, 35.051106], + [118.942662, 35.040817], + [119.027045, 35.055516], + [119.114509, 35.055026], + [119.137915, 35.096167], + [119.217371, 35.106939], + [119.250016, 35.124562], + [119.286972, 35.115261], + [119.306066, 35.076578], + [119.354109, 35.080007], + [119.373819, 35.078538], + [119.428022, 35.121136], + [119.397841, 35.137777], + [119.411392, 35.231689], + [119.450812, 35.285443], + [119.493312, 35.318655], + [119.538275, 35.296678], + [119.543819, 35.347949], + [119.590014, 35.37284], + [119.579543, 35.406504], + [119.618963, 35.459655], + [119.663311, 35.562931], + [119.662079, 35.589215], + [119.718129, 35.615492], + [119.75139, 35.617924], + [119.772332, 35.578995], + [119.780339, 35.584835], + [119.792658, 35.615492], + [119.824071, 35.646136], + [119.83023, 35.620357], + [119.868419, 35.60868], + [119.925085, 35.637382], + [119.91215, 35.660725], + [119.950339, 35.729741], + [119.920157, 35.739943], + [119.926317, 35.759856], + [119.958346, 35.760342], + [120.01378, 35.714193], + [120.049505, 35.786562], + [120.032258, 35.812288], + [120.064287, 35.873414], + [120.112331, 35.885052], + [120.125265, 35.906868], + [120.152983, 35.907353], + [120.207801, 35.947575], + [120.169613, 35.888446], + [120.202258, 35.89184], + [120.209033, 35.917531], + [120.265699, 35.966468], + [120.30512, 35.971796], + [120.316206, 36.002304], + [120.289721, 36.017311], + [120.285409, 36.01247], + [120.249069, 35.992136], + [120.257076, 36.025055], + [120.198562, 35.995525], + [120.234902, 36.030863], + [120.239214, 36.062316], + [120.181316, 36.066669], + [120.152367, 36.095206], + [120.116642, 36.102943], + [120.108635, 36.127599], + [120.142512, 36.143549], + [120.140664, 36.173507], + [120.181316, 36.203936], + [120.22012, 36.209248], + [120.224432, 36.19138], + [120.260772, 36.198624], + [120.263236, 36.182202], + [120.310047, 36.185101], + [120.297112, 36.225664], + [120.319902, 36.232423], + [120.362402, 36.196209], + [120.35809, 36.174956], + [120.286025, 36.047317], + [120.337764, 36.055058], + [120.429539, 36.056994], + [120.468959, 36.087952], + [120.546568, 36.091821], + [120.546568, 36.107778], + [120.593995, 36.100525], + [120.615553, 36.120348], + [120.64327, 36.114547], + [120.672835, 36.130016], + [120.712255, 36.126632], + [120.696857, 36.15563], + [120.696857, 36.203936], + [120.680843, 36.238698], + [120.686386, 36.279234], + [120.657437, 36.276339], + [120.66298, 36.331803], + [120.744284, 36.327946], + [120.694393, 36.390118], + [120.759683, 36.46283], + [120.828668, 36.46668], + [120.837291, 36.459942], + [120.858849, 36.424797], + [120.848994, 36.403124], + [120.871784, 36.36699], + [120.911204, 36.412276], + [120.917979, 36.417573], + [120.90874, 36.450315], + [120.938305, 36.447908], + [120.965407, 36.466199], + [120.95432, 36.507578], + [120.983269, 36.546051], + [120.962327, 36.562877], + [120.909972, 36.568645], + [120.884718, 36.601323], + [120.847146, 36.618617], + [120.882255, 36.627262], + [120.926602, 36.611892], + [120.955551, 36.575855], + [121.028848, 36.572971], + [121.078123, 36.607568], + [121.161275, 36.651273], + [121.251818, 36.671436], + [121.29863, 36.702151], + [121.31218, 36.702151], + [121.35776, 36.713186], + [121.400876, 36.701191], + [121.3941, 36.738129], + [121.454462, 36.752515], + [121.496962, 36.795179], + [121.506817, 36.803805], + [121.565331, 36.830635], + [121.548701, 36.807638], + [121.485259, 36.786073], + [121.532071, 36.73621], + [121.575186, 36.740047], + [121.556092, 36.764502], + [121.651563, 36.723739], + [121.631853, 36.80093], + [121.6762, 36.819137], + [121.726092, 36.826323], + [121.762432, 36.84644], + [121.767975, 36.874691], + [121.927504, 36.932597], + [121.965076, 36.938337], + [122.008808, 36.96225], + [122.042684, 36.871819], + [122.051923, 36.904846], + [122.093191, 36.913938], + [122.115981, 36.94025], + [122.124604, 36.944077], + [122.141235, 36.938337], + [122.119677, 36.891924], + [122.175727, 36.894317], + [122.188662, 36.866073], + [122.174495, 36.842609], + [122.220691, 36.848835], + [122.275509, 36.83734], + [122.280437, 36.835904], + [122.344495, 36.828239], + [122.378371, 36.844525], + [122.383915, 36.865595], + [122.415944, 36.85937], + [122.454748, 36.879], + [122.452284, 36.88618], + [122.434422, 36.914416], + [122.483081, 36.913938], + [122.48924, 36.886659], + [122.532356, 36.901496], + [122.55761, 36.968467], + [122.544675, 37.004797], + [122.583479, 37.037289], + [122.575472, 37.054485], + [122.494168, 37.033945], + [122.467067, 37.037289], + [122.478769, 37.058784], + [122.484313, 37.128956], + [122.533588, 37.153286], + [122.581015, 37.147562], + [122.573624, 37.176178], + [122.624131, 37.190959], + [122.592718, 37.261485], + [122.567465, 37.25958], + [122.573624, 37.296247], + [122.611196, 37.339558], + [122.607501, 37.364296], + [122.650616, 37.388551], + [122.6925, 37.373809], + [122.714058, 37.392355], + [122.701739, 37.418501], + [122.67587, 37.413273], + [122.641377, 37.428482], + [122.553914, 37.407093], + [122.4954, 37.413748], + [122.487393, 37.43466], + [122.41656, 37.414699], + [122.337103, 37.414223], + [122.281053, 37.430858], + [122.287212, 37.445114], + [122.25272, 37.467917], + [122.194205, 37.456041], + [122.166488, 37.438937], + [122.131996, 37.49926], + [122.163408, 37.519199], + [122.150474, 37.557163], + [122.08888, 37.554316], + [122.075329, 37.540556], + [122.017431, 37.531065], + [121.997721, 37.494512], + [121.923808, 37.473142], + [121.772903, 37.466492], + [121.66573, 37.473617], + [121.635548, 37.494037], + [121.575802, 37.460317], + [121.571491, 37.441313], + [121.477252, 37.475992], + [121.460006, 37.522522], + [121.400876, 37.557638], + [121.395948, 37.589891], + [121.435368, 37.592737], + [121.391021, 37.625449], + [121.349137, 37.635403], + [121.358376, 37.597479], + [121.304789, 37.582778], + [121.217326, 37.582778], + [121.17421, 37.597479], + [121.148956, 37.626397], + [121.161891, 37.646302], + [121.142797, 37.661464], + [121.160043, 37.698882], + [121.136022, 37.723501], + [121.037471, 37.718767], + [120.994356, 37.759468], + [120.943233, 37.785486], + [120.940769, 37.819533], + [120.874863, 37.833241], + [120.845298, 37.826623], + [120.839139, 37.82426], + [120.733197, 37.833714], + [120.656821, 37.793054], + [120.634031, 37.796364], + [120.590915, 37.7642], + [120.517619, 37.750005], + [120.454793, 37.757576], + [120.367945, 37.697935], + [120.227511, 37.693673], + [120.22012, 37.671886], + [120.269395, 37.658622], + [120.272475, 37.636824], + [120.215192, 37.621183], + [120.208417, 37.588469], + [120.246605, 37.556689], + [120.222584, 37.532963], + [120.144359, 37.481691], + [120.086461, 37.465067], + [120.064903, 37.448915], + [120.010085, 37.442263], + [119.949723, 37.419927], + [119.926933, 37.386649], + [119.843781, 37.376662], + [119.837006, 37.346695], + [119.883201, 37.311004], + [119.89244, 37.263866], + [119.865339, 37.233854], + [119.83023, 37.225754], + [119.808057, 37.196203], + [119.740303, 37.133727], + [119.687332, 37.143746], + [119.678709, 37.158056], + [119.576463, 37.127524], + [119.489616, 37.134681], + [119.428022, 37.125616], + [119.361501, 37.125616], + [119.327624, 37.115595], + [119.301138, 37.139452], + [119.298675, 37.197156], + [119.2069, 37.223371], + [119.190885, 37.25958], + [119.204436, 37.280058], + [119.136683, 37.230995], + [119.12806, 37.254816], + [119.091103, 37.257674], + [119.084328, 37.239572], + [119.054147, 37.254816], + [119.03998, 37.30434], + [119.001176, 37.31862], + [118.942662, 37.497361], + [118.939582, 37.527268], + [118.988857, 37.620709], + [119.023966, 37.642037], + [119.153313, 37.655305], + [119.236465, 37.651988], + [119.262334, 37.660517], + [119.280197, 37.692726], + [119.309146, 37.805349], + [119.291899, 37.869627], + [119.24016, 37.878131], + [119.212443, 37.838913], + [119.16132, 37.81906], + [119.12806, 37.847892], + [119.110813, 37.921577], + [119.001792, 37.99613], + [118.974075, 38.094162], + [118.908169, 38.139362], + [118.811467, 38.157717], + [118.703677, 38.151129], + [118.626069, 38.138421], + [118.607591, 38.129006], + [118.597736, 38.079088], + [118.552156, 38.05553], + [118.534294, 38.063541], + [118.517048, 38.088509], + [118.504729, 38.11394], + [118.44991, 38.124299], + [118.431432, 38.106406], + [118.404331, 38.121003], + [118.331034, 38.12524], + [118.217085, 38.146893], + [118.177665, 38.186417], + [118.112376, 38.210403], + [118.045238, 38.214165], + [118.018753, 38.202409], + [117.896797, 38.279495], + [117.895565, 38.301572], + [117.848754, 38.255062], + [117.808718, 38.22827], + [117.789007, 38.180772], + [117.766834, 38.158658], + [117.771145, 38.134655], + [117.746508, 38.12524], + [117.704624, 38.076262], + [117.586979, 38.071551], + [117.557414, 38.046105], + [117.557414, 38.046105], + [117.524154, 37.989527], + [117.513067, 37.94329], + [117.481038, 37.914967], + [117.438538, 37.854035], + [117.400966, 37.844584], + [117.320278, 37.861596], + [117.271618, 37.839858], + [117.185387, 37.849783], + [117.150278, 37.839385], + [117.074518, 37.848837], + [117.027091, 37.832296], + [116.919301, 37.846002], + [116.837997, 37.835132], + [116.804736, 37.848837], + [116.753613, 37.793054], + [116.753613, 37.77035], + [116.724664, 37.744327], + [116.679085, 37.728708], + [116.66307, 37.686096], + [116.604556, 37.624975], + [116.575607, 37.610754], + [116.4826, 37.521573], + [116.448108, 37.503059], + [116.433941, 37.473142], + [116.38097, 37.522522], + [116.379738, 37.522047], + [116.38097, 37.522522], + [116.379738, 37.522047], + [116.36742, 37.566177], + [116.336007, 37.581355], + [116.295355, 37.554316], + [116.278724, 37.524895], + [116.290427, 37.484065], + [116.27626, 37.466967], + [116.240536, 37.489764], + [116.240536, 37.489764], + [116.224522, 37.479791], + [116.243, 37.447965], + [116.226369, 37.428007], + [116.2855, 37.404241], + [116.236224, 37.361442], + [116.193109, 37.365723], + [116.169087, 37.384271], + [116.106261, 37.368577], + [116.085935, 37.373809], + [116.024341, 37.360015], + [115.975682, 37.337179], + [115.969523, 37.239572], + [115.909777, 37.20669], + [115.91224, 37.177132], + [115.879596, 37.150901], + [115.888219, 37.112254], + [115.85619, 37.060694], + [115.776734, 36.992848], + [115.79706, 36.968945], + [115.75764, 36.902453], + [115.71206, 36.883308], + [115.683727, 36.808117], + [115.524815, 36.763543], + [115.479851, 36.760187], + [115.451518, 36.702151], + [115.420105, 36.686795], + [115.365902, 36.621979], + [115.355431, 36.627262], + [115.33141, 36.550378], + [115.272895, 36.497476], + [115.291374, 36.460423], + [115.317243, 36.454166], + [115.297533, 36.413239], + [115.340033, 36.398307], + [115.368982, 36.342409], + [115.366518, 36.30914], + [115.423185, 36.32216], + [115.417025, 36.292742], + [115.462605, 36.276339], + [115.466916, 36.258969], + [115.466916, 36.258969], + [115.474923, 36.248352], + [115.483547, 36.148865], + [115.484163, 36.125666], + [115.449054, 36.047317], + [115.447822, 36.01247], + [115.362822, 35.971796], + [115.353583, 35.938854], + [115.364054, 35.894264], + [115.335105, 35.796756], + [115.363438, 35.779765], + [115.407786, 35.80889], + [115.460141, 35.867594], + [115.487858, 35.880688], + [115.495249, 35.896203], + [115.505104, 35.899112], + [115.513112, 35.890385], + [115.583945, 35.921893], + [115.648618, 35.922863], + [115.699125, 35.966468], + [115.774886, 35.974702], + [115.779813, 35.993588], + [115.817386, 36.012954], + [115.859886, 36.003756], + [115.89869, 36.026507], + [115.989849, 36.045381], + [116.057602, 36.104877], + [116.099486, 36.112129], + [116.063145, 36.028927], + [116.048979, 35.970343], + [115.984921, 35.974218], + [115.911624, 35.960171], + [115.907929, 35.92674], + [115.873436, 35.918985], + [115.882675, 35.879718], + [115.859886, 35.857894], + [115.81677, 35.844312], + [115.773654, 35.854014], + [115.73485, 35.833154], + [115.696046, 35.788989], + [115.693582, 35.754028], + [115.622749, 35.739457], + [115.52851, 35.733628], + [115.48601, 35.710306], + [115.383148, 35.568772], + [115.34496, 35.55368], + [115.356047, 35.490359], + [115.307388, 35.480126], + [115.237171, 35.423087], + [115.172497, 35.426501], + [115.126302, 35.41821], + [115.117679, 35.400163], + [115.091809, 35.416259], + [115.073947, 35.374304], + [115.04315, 35.376744], + [114.957534, 35.261014], + [114.929201, 35.244886], + [114.932281, 35.198441], + [114.861448, 35.182301], + [114.841738, 35.15099], + [114.883006, 35.098615], + [114.835578, 35.076578], + [114.818948, 35.051596], + [114.852209, 35.041797], + [114.824492, 35.012393], + [114.880542, 35.00357], + [114.923658, 34.968757], + [114.950759, 34.989843], + [115.008041, 34.988372], + [115.028983, 34.9717], + [115.075179, 35.000628], + [115.12815, 35.00455], + [115.157099, 34.957968], + [115.219309, 34.96042], + [115.205142, 34.914303], + [115.251953, 34.906451], + [115.239019, 34.87798], + [115.256265, 34.845079], + [115.317243, 34.859321], + [115.42688, 34.805285], + [115.449054, 34.74433], + [115.433655, 34.725149], + [115.461373, 34.637057], + [115.515575, 34.582383], + [115.553148, 34.568586], + [115.622749, 34.574499], + [115.685575, 34.556265], + [115.697278, 34.594207], + [115.787821, 34.580905], + [115.827241, 34.558236], + [115.838328, 34.5676], + [115.984305, 34.589281], + [115.991081, 34.615389], + [116.037276, 34.593222], + [116.101334, 34.60603], + [116.134594, 34.559715], + [116.156768, 34.5538], + [116.196804, 34.575977], + [116.247927, 34.551829], + [116.286116, 34.608986], + [116.32492, 34.601104], + [116.334159, 34.620806], + [116.374195, 34.640011] + ] + ], + [ + [ + [120.729502, 37.947065], + [120.721495, 37.917328], + [120.76461, 37.895134], + [120.76461, 37.923937], + [120.729502, 37.947065] + ] + ], + [ + [ + [120.692545, 37.983867], + [120.732581, 37.961694], + [120.724574, 37.987641], + [120.692545, 37.983867] + ] + ], + [ + [ + [120.990044, 36.413239], + [120.978341, 36.428649], + [120.950624, 36.414684], + [120.990044, 36.413239] + ] + ], + [ + [ + [120.750444, 38.150188], + [120.7874, 38.158658], + [120.742436, 38.199116], + [120.750444, 38.150188] + ] + ], + [ + [ + [120.918595, 38.345236], + [120.914899, 38.373393], + [120.895189, 38.36307], + [120.918595, 38.345236] + ] + ], + [ + [ + [120.159142, 35.765198], + [120.169613, 35.740428], + [120.193019, 35.756942], + [120.172077, 35.785591], + [120.159142, 35.765198] + ] + ], + [ + [ + [120.62664, 37.94565], + [120.631567, 37.981037], + [120.602002, 37.978678], + [120.62664, 37.94565] + ] + ], + [ + [ + [120.802183, 38.284193], + [120.848378, 38.305799], + [120.816349, 38.318008], + [120.802183, 38.284193] + ] + ], + [ + [ + [121.489571, 37.577086], + [121.489571, 37.577561], + [121.489571, 37.578509], + [121.488955, 37.578035], + [121.489571, 37.577086] + ] + ], + [ + [ + [121.485875, 37.578509], + [121.487723, 37.578035], + [121.487723, 37.578509], + [121.485875, 37.578509] + ] + ], + [ + [ + [121.487723, 37.578509], + [121.487723, 37.577561], + [121.488955, 37.578035], + [121.488955, 37.578509], + [121.488339, 37.578509], + [121.487723, 37.578509] + ] + ], + [ + [ + [115.495249, 35.896203], + [115.487858, 35.880688], + [115.513112, 35.890385], + [115.505104, 35.899112], + [115.495249, 35.896203] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 410000, + "name": "河南省", + "center": [113.665412, 34.757975], + "centroid": [113.619717, 33.902648], + "childrenNum": 18, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 15, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [112.716747, 32.357612], + [112.735841, 32.356095], + [112.776493, 32.358623], + [112.860877, 32.396024], + [112.888594, 32.37682], + [112.912, 32.390971], + [112.992072, 32.378336], + [113.000695, 32.41674], + [113.025949, 32.425328], + [113.078919, 32.394508], + [113.107869, 32.398551], + [113.118956, 32.375809], + [113.155912, 32.380863], + [113.158992, 32.410677], + [113.211962, 32.431895], + [113.2366, 32.407141], + [113.333918, 32.336377], + [113.317904, 32.327275], + [113.353628, 32.294904], + [113.376418, 32.298445], + [113.428773, 32.270618], + [113.511925, 32.316654], + [113.624642, 32.36115], + [113.650511, 32.412698], + [113.700402, 32.420782], + [113.735511, 32.410677], + [113.76754, 32.370249], + [113.753989, 32.328286], + [113.768772, 32.30148], + [113.768156, 32.284279], + [113.758301, 32.27669], + [113.749061, 32.272642], + [113.73859, 32.255942], + [113.752757, 32.215951], + [113.782322, 32.184553], + [113.750293, 32.11615], + [113.722576, 32.12426], + [113.728735, 32.083197], + [113.791561, 32.036028], + [113.757685, 31.98985], + [113.817431, 31.964467], + [113.805728, 31.929428], + [113.832213, 31.918761], + [113.830981, 31.87913], + [113.854387, 31.843042], + [113.893807, 31.847109], + [113.914749, 31.877098], + [113.957865, 31.852701], + [113.952321, 31.793714], + [113.988662, 31.749959], + [114.017611, 31.770822], + [114.086596, 31.782014], + [114.121705, 31.809482], + [114.134024, 31.843042], + [114.191922, 31.852192], + [114.235654, 31.833382], + [114.292936, 31.752503], + [114.350218, 31.755557], + [114.403189, 31.746906], + [114.443841, 31.728074], + [114.530688, 31.742834], + [114.549783, 31.766751], + [114.586123, 31.762172], + [114.57134, 31.660858], + [114.547935, 31.623665], + [114.560869, 31.560963], + [114.572572, 31.553824], + [114.61692, 31.585437], + [114.641558, 31.582378], + [114.696376, 31.525771], + [114.778912, 31.520669], + [114.789383, 31.480358], + [114.830035, 31.45892], + [114.870071, 31.479337], + [114.884238, 31.469129], + [114.962462, 31.494648], + [114.995107, 31.471171], + [115.022824, 31.527811], + [115.096121, 31.508425], + [115.114599, 31.530362], + [115.106592, 31.567592], + [115.12507, 31.599201], + [115.16449, 31.604808], + [115.212533, 31.555354], + [115.235939, 31.555354], + [115.218077, 31.515057], + [115.211301, 31.442072], + [115.252569, 31.421646], + [115.250722, 31.392021], + [115.301229, 31.383846], + [115.338801, 31.40428], + [115.373909, 31.405813], + [115.389924, 31.450241], + [115.371446, 31.495668], + [115.415793, 31.525771], + [115.439815, 31.588496], + [115.485394, 31.608885], + [115.476771, 31.643028], + [115.495249, 31.673083], + [115.534054, 31.698545], + [115.553764, 31.69549], + [115.676336, 31.778453], + [115.731154, 31.76726], + [115.767495, 31.78761], + [115.808147, 31.770313], + [115.808147, 31.770313], + [115.851878, 31.786593], + [115.886371, 31.776418], + [115.914704, 31.814567], + [115.893762, 31.832365], + [115.894994, 31.8649], + [115.920248, 31.920285], + [115.909161, 31.94314], + [115.928871, 32.003046], + [115.922095, 32.049725], + [115.941805, 32.166318], + [115.912856, 32.227596], + [115.899306, 32.390971], + [115.865429, 32.458662], + [115.883291, 32.487946], + [115.845719, 32.501575], + [115.8759, 32.542448], + [115.910393, 32.567165], + [115.891298, 32.576243], + [115.861117, 32.537403], + [115.789052, 32.468761], + [115.771806, 32.505108], + [115.742241, 32.476335], + [115.704669, 32.495013], + [115.667712, 32.409667], + [115.657857, 32.428864], + [115.626445, 32.40512], + [115.604271, 32.425833], + [115.57101, 32.419266], + [115.522967, 32.441997], + [115.509416, 32.466741], + [115.5088, 32.468761], + [115.497713, 32.492489], + [115.409018, 32.549007], + [115.411482, 32.575235], + [115.304924, 32.553042], + [115.30554, 32.583303], + [115.267352, 32.578261], + [115.24333, 32.593388], + [115.20083, 32.591876], + [115.182968, 32.666973], + [115.179273, 32.726402], + [115.189744, 32.770695], + [115.211301, 32.785791], + [115.189744, 32.812452], + [115.197135, 32.856201], + [115.155867, 32.864747], + [115.139237, 32.897917], + [115.029599, 32.906962], + [115.035143, 32.932582], + [115.009273, 32.940117], + [114.943368, 32.935094], + [114.916266, 32.971251], + [114.883006, 32.990328], + [114.891629, 33.020441], + [114.925506, 33.016928], + [114.913187, 33.083143], + [114.897172, 33.086653], + [114.902716, 33.129764], + [114.932897, 33.153817], + [114.966158, 33.147304], + [114.990795, 33.102195], + [115.041302, 33.086653], + [115.168186, 33.088658], + [115.194671, 33.120743], + [115.245178, 33.135778], + [115.289526, 33.131769], + [115.303692, 33.149809], + [115.300613, 33.204407], + [115.340033, 33.260973], + [115.335105, 33.297997], + [115.361591, 33.298497], + [115.365286, 33.336005], + [115.341881, 33.370997], + [115.313547, 33.376994], + [115.328946, 33.403477], + [115.315395, 33.431451], + [115.324634, 33.457418], + [115.345576, 33.449928], + [115.345576, 33.502842], + [115.366518, 33.5233], + [115.394851, 33.506335], + [115.422569, 33.557219], + [115.463837, 33.567193], + [115.511264, 33.55323], + [115.564851, 33.576169], + [115.639995, 33.585143], + [115.601191, 33.658898], + [115.601807, 33.718653], + [115.563003, 33.772895], + [115.576553, 33.787817], + [115.614126, 33.775879], + [115.631988, 33.869846], + [115.547604, 33.874815], + [115.577785, 33.950307], + [115.579017, 33.974133], + [115.60735, 34.030196], + [115.642459, 34.03218], + [115.658473, 34.061437], + [115.705901, 34.059949], + [115.736082, 34.076805], + [115.768726, 34.061932], + [115.809378, 34.062428], + [115.846335, 34.028708], + [115.85003, 34.004898], + [115.877132, 34.002913], + [115.876516, 34.028708], + [115.904233, 34.009859], + [115.95782, 34.007875], + [116.00032, 33.965199], + [115.982457, 33.917039], + [116.05945, 33.860902], + [116.055754, 33.804727], + [116.074232, 33.781351], + [116.100102, 33.782843], + [116.132747, 33.751501], + [116.155536, 33.709693], + [116.230065, 33.735078], + [116.263326, 33.730101], + [116.316912, 33.771402], + [116.393905, 33.782843], + [116.408071, 33.805721], + [116.437021, 33.801246], + [116.437637, 33.846489], + [116.486296, 33.869846], + [116.558361, 33.881274], + [116.566984, 33.9081], + [116.631042, 33.887733], + [116.64336, 33.896675], + [116.641512, 33.978103], + [116.599629, 34.014324], + [116.599629, 34.014324], + [116.576223, 34.068873], + [116.576223, 34.068873], + [116.52818, 34.122892], + [116.536187, 34.151127], + [116.565752, 34.16945], + [116.542962, 34.203608], + [116.545426, 34.241711], + [116.582382, 34.266444], + [116.562056, 34.285731], + [116.516477, 34.296114], + [116.456731, 34.268917], + [116.409303, 34.273863], + [116.409303, 34.273863], + [116.372347, 34.26595], + [116.357564, 34.319843], + [116.301514, 34.342082], + [116.255934, 34.376665], + [116.213435, 34.382098], + [116.215898, 34.403333], + [116.178942, 34.430487], + [116.162312, 34.459605], + [116.178326, 34.496112], + [116.204196, 34.508442], + [116.191261, 34.535561], + [116.196804, 34.575977], + [116.156768, 34.5538], + [116.134594, 34.559715], + [116.101334, 34.60603], + [116.037276, 34.593222], + [115.991081, 34.615389], + [115.984305, 34.589281], + [115.838328, 34.5676], + [115.827241, 34.558236], + [115.787821, 34.580905], + [115.697278, 34.594207], + [115.685575, 34.556265], + [115.622749, 34.574499], + [115.553148, 34.568586], + [115.515575, 34.582383], + [115.461373, 34.637057], + [115.433655, 34.725149], + [115.449054, 34.74433], + [115.42688, 34.805285], + [115.317243, 34.859321], + [115.256265, 34.845079], + [115.239019, 34.87798], + [115.251953, 34.906451], + [115.205142, 34.914303], + [115.219309, 34.96042], + [115.157099, 34.957968], + [115.12815, 35.00455], + [115.075179, 35.000628], + [115.028983, 34.9717], + [115.008041, 34.988372], + [114.950759, 34.989843], + [114.923658, 34.968757], + [114.880542, 35.00357], + [114.824492, 35.012393], + [114.852209, 35.041797], + [114.818948, 35.051596], + [114.835578, 35.076578], + [114.883006, 35.098615], + [114.841738, 35.15099], + [114.861448, 35.182301], + [114.932281, 35.198441], + [114.929201, 35.244886], + [114.957534, 35.261014], + [115.04315, 35.376744], + [115.073947, 35.374304], + [115.091809, 35.416259], + [115.117679, 35.400163], + [115.126302, 35.41821], + [115.172497, 35.426501], + [115.237171, 35.423087], + [115.307388, 35.480126], + [115.356047, 35.490359], + [115.34496, 35.55368], + [115.383148, 35.568772], + [115.48601, 35.710306], + [115.52851, 35.733628], + [115.622749, 35.739457], + [115.693582, 35.754028], + [115.696046, 35.788989], + [115.73485, 35.833154], + [115.773654, 35.854014], + [115.81677, 35.844312], + [115.859886, 35.857894], + [115.882675, 35.879718], + [115.873436, 35.918985], + [115.907929, 35.92674], + [115.911624, 35.960171], + [115.984921, 35.974218], + [116.048979, 35.970343], + [116.063145, 36.028927], + [116.099486, 36.112129], + [116.057602, 36.104877], + [115.989849, 36.045381], + [115.89869, 36.026507], + [115.859886, 36.003756], + [115.817386, 36.012954], + [115.779813, 35.993588], + [115.774886, 35.974702], + [115.699125, 35.966468], + [115.648618, 35.922863], + [115.583945, 35.921893], + [115.513112, 35.890385], + [115.487858, 35.880688], + [115.460141, 35.867594], + [115.407786, 35.80889], + [115.363438, 35.779765], + [115.335105, 35.796756], + [115.364054, 35.894264], + [115.353583, 35.938854], + [115.362822, 35.971796], + [115.447822, 36.01247], + [115.449054, 36.047317], + [115.484163, 36.125666], + [115.483547, 36.148865], + [115.465068, 36.170125], + [115.450902, 36.152248], + [115.376989, 36.128083], + [115.365902, 36.099074], + [115.312931, 36.088436], + [115.30246, 36.127599], + [115.279055, 36.13775], + [115.242098, 36.19138], + [115.202678, 36.208765], + [115.202678, 36.208765], + [115.202678, 36.209248], + [115.202678, 36.209248], + [115.201446, 36.210214], + [115.201446, 36.210214], + [115.1842, 36.193312], + [115.12507, 36.209731], + [115.104744, 36.172058], + [115.06286, 36.178338], + [115.048693, 36.161912], + [115.04623, 36.112613], + [114.998186, 36.069572], + [114.914419, 36.052155], + [114.926737, 36.089403], + [114.912571, 36.140649], + [114.858368, 36.144516], + [114.857752, 36.127599], + [114.771521, 36.124699], + [114.734564, 36.15563], + [114.720398, 36.140166], + [114.640326, 36.137266], + [114.588587, 36.118414], + [114.586739, 36.141133], + [114.533152, 36.171575], + [114.480181, 36.177855], + [114.466015, 36.197658], + [114.417356, 36.205868], + [114.408117, 36.224699], + [114.356378, 36.230492], + [114.345291, 36.255591], + [114.299095, 36.245938], + [114.257827, 36.263794], + [114.241197, 36.251247], + [114.2104, 36.272962], + [114.203009, 36.245456], + [114.170364, 36.245938], + [114.170364, 36.245938], + [114.175907, 36.264759], + [114.129096, 36.280199], + [114.080437, 36.269585], + [114.04348, 36.303353], + [114.056415, 36.329392], + [114.002828, 36.334214], + [113.981887, 36.31782], + [113.962792, 36.353977], + [113.911054, 36.314927], + [113.882104, 36.353977], + [113.84946, 36.347711], + [113.856851, 36.329392], + [113.813119, 36.332285], + [113.755221, 36.366026], + [113.731199, 36.363135], + [113.736127, 36.324571], + [113.712105, 36.303353], + [113.716417, 36.262347], + [113.681924, 36.216491], + [113.697939, 36.181719], + [113.651127, 36.174473], + [113.705946, 36.148865], + [113.712721, 36.129533], + [113.655439, 36.125182], + [113.671453, 36.115514], + [113.68562, 36.056026], + [113.660366, 36.034735], + [113.694859, 36.026991], + [113.678844, 35.985841], + [113.648663, 35.994073], + [113.654207, 35.931586], + [113.637576, 35.870019], + [113.660982, 35.837035], + [113.582758, 35.818111], + [113.604932, 35.797727], + [113.587685, 35.736542], + [113.592613, 35.691838], + [113.622794, 35.674825], + [113.625258, 35.632518], + [113.578446, 35.633491], + [113.547649, 35.656835], + [113.55812, 35.621816], + [113.513773, 35.57364], + [113.49899, 35.532254], + [113.439244, 35.507412], + [113.391817, 35.506925], + [113.348085, 35.468429], + [113.31236, 35.481101], + [113.304353, 35.426989], + [113.243375, 35.449418], + [113.189789, 35.44893], + [113.185477, 35.409431], + [113.165151, 35.412845], + [113.149137, 35.350878], + [113.126347, 35.332327], + [113.067217, 35.353806], + [112.996384, 35.362104], + [112.985913, 35.33965], + [112.992072, 35.29619], + [112.936022, 35.284466], + [112.934174, 35.262968], + [112.884283, 35.243909], + [112.822073, 35.258082], + [112.772798, 35.207732], + [112.720443, 35.206265], + [112.628052, 35.263457], + [112.637291, 35.225822], + [112.513487, 35.218489], + [112.390915, 35.239021], + [112.36751, 35.219956], + [112.288053, 35.219956], + [112.304684, 35.251728], + [112.242474, 35.234622], + [112.21722, 35.253195], + [112.13838, 35.271275], + [112.058924, 35.280069], + [112.078634, 35.219467], + [112.03983, 35.194039], + [112.066315, 35.153437], + [112.05646, 35.098615], + [112.062004, 35.056005], + [112.039214, 35.045717], + [112.018888, 35.068742], + [111.97762, 35.067272], + [111.933272, 35.083435], + [111.810084, 35.062374], + [111.807005, 35.032977], + [111.740483, 35.00455], + [111.664107, 34.984449], + [111.681969, 34.9511], + [111.646861, 34.938836], + [111.617911, 34.894671], + [111.592042, 34.881416], + [111.570484, 34.843114], + [111.543999, 34.853428], + [111.502731, 34.829851], + [111.439289, 34.838202], + [111.389398, 34.815113], + [111.345666, 34.831816], + [111.29208, 34.806759], + [111.255123, 34.819535], + [111.232949, 34.789559], + [111.148566, 34.807742], + [111.118385, 34.756623], + [111.035233, 34.740887], + [110.976103, 34.706456], + [110.920052, 34.730068], + [110.903422, 34.669056], + [110.883712, 34.64395], + [110.824582, 34.615881], + [110.791937, 34.649858], + [110.749437, 34.65232], + [110.710017, 34.605045], + [110.610851, 34.607508], + [110.533242, 34.583368], + [110.488279, 34.610956], + [110.424837, 34.588295], + [110.379257, 34.600612], + [110.366939, 34.566614], + [110.404511, 34.557743], + [110.372482, 34.544435], + [110.360779, 34.516825], + [110.403279, 34.433448], + [110.403279, 34.433448], + [110.473496, 34.393457], + [110.503677, 34.33714], + [110.451938, 34.292653], + [110.428533, 34.288203], + [110.43962, 34.243196], + [110.507989, 34.217466], + [110.55172, 34.213012], + [110.55788, 34.193214], + [110.621938, 34.177372], + [110.642264, 34.161032], + [110.61393, 34.113478], + [110.591757, 34.101586], + [110.587445, 34.023252], + [110.620706, 34.035652], + [110.671213, 33.966192], + [110.665669, 33.937895], + [110.627481, 33.925482], + [110.628713, 33.910086], + [110.587445, 33.887733], + [110.612083, 33.852453], + [110.66259, 33.85295], + [110.712481, 33.833564], + [110.74143, 33.798759], + [110.782082, 33.796272], + [110.81719, 33.751003], + [110.831973, 33.713675], + [110.823966, 33.685793], + [110.878784, 33.634486], + [110.966864, 33.609071], + [111.00382, 33.578662], + [111.002588, 33.535772], + [111.02661, 33.478386], + [111.02661, 33.467903], + [110.996429, 33.435946], + [111.025994, 33.375495], + [111.025994, 33.330504], + [110.984726, 33.255469], + [111.046936, 33.202905], + [111.045704, 33.169849], + [111.08882, 33.181871], + [111.12824, 33.15532], + [111.146102, 33.12375], + [111.179363, 33.115229], + [111.192913, 33.071609], + [111.152877, 33.039507], + [111.221862, 33.042517], + [111.258819, 33.006389], + [111.273601, 32.971753], + [111.242804, 32.930573], + [111.255123, 32.883846], + [111.276065, 32.903445], + [111.293311, 32.859217], + [111.380159, 32.829049], + [111.41342, 32.757108], + [111.475629, 32.760127], + [111.458383, 32.726402], + [111.513202, 32.674026], + [111.530448, 32.628172], + [111.577875, 32.593388], + [111.640701, 32.634724], + [111.646245, 32.605993], + [111.713382, 32.606497], + [111.808853, 32.536899], + [111.858128, 32.528826], + [111.890157, 32.503089], + [111.948671, 32.51722], + [111.975772, 32.471791], + [112.014576, 32.450077], + [112.063851, 32.474315], + [112.081098, 32.425833], + [112.155626, 32.377326], + [112.150083, 32.411688], + [112.172873, 32.385412], + [112.206133, 32.392992], + [112.328089, 32.321712], + [112.360118, 32.3657], + [112.390915, 32.37126], + [112.448814, 32.34295], + [112.477147, 32.380863], + [112.530733, 32.37682], + [112.545516, 32.404109], + [112.589248, 32.381369], + [112.612037, 32.386928], + [112.645298, 32.368227], + [112.716747, 32.357612] + ] + ], + [ + [ + [113.768156, 32.284279], + [113.768772, 32.30148], + [113.749061, 32.272642], + [113.758301, 32.27669], + [113.768156, 32.284279] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 420000, + "name": "湖北省", + "center": [114.298572, 30.584355], + "centroid": [112.271301, 30.987527], + "childrenNum": 17, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 16, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [111.045704, 33.169849], + [111.034001, 33.177864], + [111.035849, 33.187881], + [111.046936, 33.202905], + [110.984726, 33.255469], + [110.960704, 33.253967], + [110.9219, 33.203907], + [110.865234, 33.213921], + [110.828893, 33.201403], + [110.824582, 33.158327], + [110.753133, 33.15031], + [110.702626, 33.097182], + [110.650887, 33.157324], + [110.623785, 33.143796], + [110.59422, 33.168346], + [110.57759, 33.250464], + [110.54125, 33.255469], + [110.471032, 33.171352], + [110.398352, 33.176862], + [110.398352, 33.176862], + [110.372482, 33.186379], + [110.33799, 33.160331], + [110.285635, 33.171352], + [110.218497, 33.163336], + [110.164911, 33.209415], + [110.031252, 33.191888], + [109.999223, 33.212419], + [109.973353, 33.203907], + [109.916687, 33.229942], + [109.852013, 33.247961], + [109.813209, 33.236449], + [109.732521, 33.231443], + [109.693101, 33.254468], + [109.649985, 33.251465], + [109.619804, 33.275484], + [109.60687, 33.235949], + [109.514479, 33.237951], + [109.498464, 33.207412], + [109.438718, 33.152314], + [109.468283, 33.140288], + [109.522486, 33.138785], + [109.576073, 33.110216], + [109.688174, 33.116733], + [109.704188, 33.101694], + [109.794731, 33.067095], + [109.785492, 32.987316], + [109.76455, 32.909474], + [109.789804, 32.882339], + [109.847702, 32.893395], + [109.856941, 32.910479], + [109.907448, 32.903947], + [109.927158, 32.887364], + [109.988752, 32.886359], + [110.051578, 32.851676], + [110.105164, 32.832569], + [110.142121, 32.802895], + [110.127338, 32.77774], + [110.159367, 32.767173], + [110.156903, 32.683093], + [110.206179, 32.633212], + [110.153824, 32.593388], + [110.124259, 32.616579], + [110.090382, 32.617083], + [110.084223, 32.580782], + [110.017701, 32.546989], + [109.97089, 32.577756], + [109.910528, 32.592884], + [109.816905, 32.577252], + [109.746072, 32.594901], + [109.726978, 32.608513], + [109.631507, 32.599943], + [109.619804, 32.56767], + [109.637051, 32.540935], + [109.575457, 32.506622], + [109.526797, 32.43341], + [109.529877, 32.405625], + [109.502776, 32.38895], + [109.513247, 32.342444], + [109.495385, 32.300468], + [109.528645, 32.270112], + [109.550203, 32.225065], + [109.592703, 32.219495], + [109.604406, 32.199241], + [109.58716, 32.161251], + [109.621652, 32.106519], + [109.590855, 32.047696], + [109.590855, 32.012688], + [109.631507, 31.962436], + [109.62042, 31.928412], + [109.584696, 31.900472], + [109.60379, 31.885737], + [109.633971, 31.824738], + [109.633971, 31.804396], + [109.592087, 31.789136], + [109.585928, 31.726546], + [109.622268, 31.711783], + [109.683246, 31.719929], + [109.731289, 31.700582], + [109.737449, 31.628761], + [109.76455, 31.602769], + [109.745456, 31.598182], + [109.727594, 31.548214], + [109.837847, 31.555354], + [109.894513, 31.519139], + [109.969658, 31.508935], + [109.94502, 31.47066], + [109.98752, 31.474744], + [110.036795, 31.436966], + [110.054042, 31.410921], + [110.118715, 31.409899], + [110.161831, 31.314338], + [110.155671, 31.279564], + [110.180309, 31.179774], + [110.200019, 31.158779], + [110.180309, 31.121899], + [110.147048, 31.116776], + [110.119947, 31.088592], + [110.120563, 31.0322], + [110.140273, 31.030661], + [110.140889, 30.987062], + [110.172918, 30.978853], + [110.153824, 30.953708], + [110.151976, 30.911613], + [110.082375, 30.799614], + [110.048498, 30.800642], + [110.019549, 30.829425], + [110.008462, 30.883369], + [109.943788, 30.878746], + [109.894513, 30.899803], + [109.828608, 30.864364], + [109.780564, 30.848437], + [109.701724, 30.783677], + [109.656761, 30.760538], + [109.661072, 30.738936], + [109.625348, 30.702923], + [109.590855, 30.69366], + [109.574225, 30.646818], + [109.543428, 30.63961], + [109.535421, 30.664837], + [109.435638, 30.595832], + [109.418392, 30.559766], + [109.35495, 30.487076], + [109.337088, 30.521623], + [109.36111, 30.551004], + [109.314298, 30.599953], + [109.299516, 30.630341], + [109.245313, 30.580892], + [109.191726, 30.545851], + [109.191726, 30.545851], + [109.143683, 30.521108], + [109.103647, 30.565949], + [109.09256, 30.578831], + [109.106111, 30.61077], + [109.111654, 30.646303], + [109.071002, 30.640125], + [109.042669, 30.655571], + [109.006329, 30.626736], + [108.971836, 30.627766], + [108.893612, 30.565434], + [108.838793, 30.503062], + [108.808612, 30.491202], + [108.789518, 30.513374], + [108.743939, 30.494812], + [108.698975, 30.54482], + [108.688504, 30.58759], + [108.642925, 30.578831], + [108.6497, 30.53915], + [108.56778, 30.468508], + [108.556077, 30.487592], + [108.512961, 30.501515], + [108.472925, 30.487076], + [108.42673, 30.492233], + [108.411331, 30.438586], + [108.430425, 30.416397], + [108.402092, 30.376649], + [108.431041, 30.354446], + [108.460606, 30.35961], + [108.501258, 30.314673], + [108.524048, 30.309506], + [108.54499, 30.269716], + [108.581947, 30.255759], + [108.551766, 30.1637], + [108.56778, 30.157491], + [108.546222, 30.104178], + [108.513577, 30.057571], + [108.532055, 30.051873], + [108.536367, 29.983472], + [108.517889, 29.9394], + [108.516041, 29.885451], + [108.467998, 29.864175], + [108.433505, 29.880262], + [108.371295, 29.841337], + [108.424266, 29.815897], + [108.422418, 29.772791], + [108.442744, 29.778505], + [108.437201, 29.741098], + [108.460606, 29.741098], + [108.504338, 29.707836], + [108.504954, 29.728626], + [108.548686, 29.749412], + [108.52528, 29.770713], + [108.556077, 29.818493], + [108.601041, 29.863656], + [108.658939, 29.854833], + [108.680497, 29.800319], + [108.676801, 29.749412], + [108.690968, 29.689642], + [108.752562, 29.649082], + [108.786438, 29.691721], + [108.797525, 29.660003], + [108.781511, 29.635558], + [108.844337, 29.658443], + [108.888068, 29.628795], + [108.870206, 29.596537], + [108.901003, 29.604863], + [108.913322, 29.574679], + [108.878213, 29.539279], + [108.888684, 29.502305], + [108.866511, 29.470527], + [108.884373, 29.440824], + [108.927488, 29.435612], + [108.934264, 29.399643], + [108.919481, 29.3261], + [108.983539, 29.332883], + [108.999553, 29.36366], + [109.034662, 29.360531], + [109.060531, 29.403292], + [109.11227, 29.361053], + [109.106727, 29.288526], + [109.141835, 29.270256], + [109.110422, 29.21647], + [109.139372, 29.168927], + [109.162777, 29.180946], + [109.215748, 29.145409], + [109.232378, 29.119271], + [109.274262, 29.121885], + [109.261328, 29.161089], + [109.275494, 29.202366], + [109.257632, 29.222738], + [109.312451, 29.25146], + [109.352487, 29.284872], + [109.343863, 29.369398], + [109.391291, 29.372005], + [109.368501, 29.413719], + [109.418392, 29.453332], + [109.415928, 29.497617], + [109.436254, 29.488761], + [109.433791, 29.530948], + [109.458428, 29.513242], + [109.467051, 29.560104], + [109.488609, 29.553336], + [109.516326, 29.626194], + [109.558826, 29.606944], + [109.578536, 29.629836], + [109.651833, 29.625674], + [109.664768, 29.599659], + [109.717739, 29.615269], + [109.701108, 29.636078], + [109.714659, 29.673524], + [109.760238, 29.689122], + [109.755311, 29.733304], + [109.779333, 29.757725], + [109.869876, 29.774869], + [109.908064, 29.763959], + [109.941325, 29.774349], + [110.02386, 29.769674], + [110.113788, 29.789932], + [110.160599, 29.753569], + [110.219729, 29.746814], + [110.289946, 29.6964], + [110.302265, 29.661563], + [110.339221, 29.668324], + [110.372482, 29.633477], + [110.447011, 29.664684], + [110.467337, 29.713034], + [110.507373, 29.692241], + [110.562807, 29.712515], + [110.642879, 29.775907], + [110.60038, 29.839779], + [110.549873, 29.848085], + [110.538786, 29.895828], + [110.49875, 29.91243], + [110.517228, 29.961179], + [110.557264, 29.988137], + [110.491358, 30.019751], + [110.497518, 30.055499], + [110.531394, 30.061197], + [110.600996, 30.054463], + [110.650887, 30.07777], + [110.712481, 30.033223], + [110.756212, 30.054463], + [110.746973, 30.112979], + [110.851067, 30.126439], + [110.924364, 30.111426], + [110.929907, 30.063268], + [111.031537, 30.048765], + [111.242188, 30.040476], + [111.266826, 30.01146], + [111.3315, 29.970512], + [111.342587, 29.944586], + [111.382623, 29.95029], + [111.394325, 29.912948], + [111.436825, 29.930065], + [111.475629, 29.918654], + [111.527368, 29.925916], + [111.553854, 29.894272], + [111.669034, 29.888565], + [111.669034, 29.888565], + [111.705375, 29.890121], + [111.723853, 29.909317], + [111.723853, 29.909317], + [111.75773, 29.92021], + [111.8107, 29.901017], + [111.861207, 29.856909], + [111.899396, 29.855871], + [111.899396, 29.855871], + [111.925881, 29.836665], + [111.965917, 29.832512], + [111.95483, 29.796683], + [112.008417, 29.778505], + [112.07617, 29.743696], + [112.065699, 29.681323], + [112.089721, 29.685482], + [112.111279, 29.659483], + [112.178416, 29.656883], + [112.202438, 29.633997], + [112.244322, 29.659483], + [112.233851, 29.61631], + [112.303452, 29.585609], + [112.281278, 29.536676], + [112.291133, 29.517409], + [112.333017, 29.545007], + [112.368741, 29.541362], + [112.424792, 29.598619], + [112.439574, 29.633997], + [112.499321, 29.629316], + [112.54182, 29.60122], + [112.572001, 29.624113], + [112.640371, 29.607985], + [112.650842, 29.592374], + [112.693957, 29.601741], + [112.714283, 29.648561], + [112.733378, 29.645441], + [112.788812, 29.681323], + [112.79374, 29.735902], + [112.861493, 29.78318], + [112.894138, 29.783699], + [112.902145, 29.79149], + [112.929246, 29.77383], + [112.923703, 29.766557], + [112.926782, 29.692241], + [112.944645, 29.682883], + [112.974826, 29.732784], + [113.025949, 29.772791], + [113.005007, 29.693801], + [112.915696, 29.620992], + [112.912, 29.606944], + [112.950188, 29.473132], + [113.034572, 29.523658], + [113.057362, 29.522616], + [113.078304, 29.438218], + [113.099861, 29.459585], + [113.145441, 29.449163], + [113.181781, 29.485636], + [113.222433, 29.543965], + [113.277252, 29.594976], + [113.37765, 29.703158], + [113.571671, 29.849123], + [113.575367, 29.809147], + [113.550729, 29.768115], + [113.558736, 29.727067], + [113.540258, 29.699519], + [113.547033, 29.675603], + [113.606164, 29.666764], + [113.663446, 29.684443], + [113.680692, 29.64336], + [113.704098, 29.634518], + [113.73859, 29.579363], + [113.710257, 29.555419], + [113.630801, 29.523137], + [113.677613, 29.513763], + [113.755221, 29.446557], + [113.731199, 29.393907], + [113.674533, 29.388172], + [113.660982, 29.333405], + [113.632033, 29.316186], + [113.609859, 29.25146], + [113.651743, 29.225872], + [113.693011, 29.226394], + [113.691779, 29.19662], + [113.66283, 29.16945], + [113.690547, 29.114566], + [113.696091, 29.077437], + [113.722576, 29.104631], + [113.749677, 29.060699], + [113.775547, 29.095219], + [113.816199, 29.105154], + [113.852539, 29.058606], + [113.882104, 29.065407], + [113.876561, 29.038202], + [113.898119, 29.029307], + [113.94185, 29.047097], + [113.952321, 29.092604], + [113.98743, 29.126068], + [114.034857, 29.152204], + [114.063191, 29.204978], + [114.169748, 29.216993], + [114.252284, 29.23475], + [114.259059, 29.343839], + [114.307102, 29.365225], + [114.341595, 29.327665], + [114.376088, 29.322969], + [114.440145, 29.341752], + [114.466015, 29.324013], + [114.519602, 29.325578], + [114.589819, 29.352707], + [114.621847, 29.379828], + [114.67297, 29.395993], + [114.740724, 29.386607], + [114.759818, 29.363139], + [114.784455, 29.386086], + [114.812173, 29.383478], + [114.866375, 29.404335], + [114.895325, 29.397557], + [114.931049, 29.422581], + [114.947063, 29.465317], + [114.935977, 29.486678], + [114.90518, 29.473132], + [114.918114, 29.454374], + [114.888549, 29.436134], + [114.860216, 29.476258], + [114.900868, 29.505951], + [114.940288, 29.493971], + [114.966773, 29.522096], + [114.947679, 29.542924], + [115.00065, 29.572076], + [115.033295, 29.546568], + [115.087498, 29.560104], + [115.086266, 29.525741], + [115.154019, 29.510117], + [115.157099, 29.584568], + [115.120142, 29.597578], + [115.143548, 29.645961], + [115.117679, 29.655843], + [115.113367, 29.684963], + [115.176809, 29.654803], + [115.250722, 29.660003], + [115.28583, 29.618391], + [115.304924, 29.637118], + [115.355431, 29.649602], + [115.412714, 29.688602], + [115.470612, 29.739539], + [115.479235, 29.811224], + [115.51188, 29.840299], + [115.611662, 29.841337], + [115.667712, 29.850161], + [115.706517, 29.837703], + [115.762567, 29.793048], + [115.837096, 29.748373], + [115.909777, 29.723949], + [115.965827, 29.724469], + [116.049595, 29.761881], + [116.087167, 29.795125], + [116.13521, 29.819532], + [116.128435, 29.897904], + [116.073616, 29.969993], + [116.091479, 30.036331], + [116.078544, 30.062233], + [116.088399, 30.110391], + [116.055754, 30.180774], + [116.065609, 30.204569], + [115.997856, 30.252657], + [115.985537, 30.290905], + [115.903001, 30.31364], + [115.91532, 30.337919], + [115.885139, 30.379747], + [115.921479, 30.416397], + [115.894994, 30.452517], + [115.910393, 30.519046], + [115.887603, 30.542758], + [115.876516, 30.582438], + [115.848799, 30.602014], + [115.819234, 30.597893], + [115.81369, 30.637035], + [115.762567, 30.685426], + [115.782893, 30.751795], + [115.851262, 30.756938], + [115.863581, 30.815549], + [115.848799, 30.828397], + [115.865429, 30.864364], + [115.932566, 30.889532], + [115.976298, 30.931636], + [116.03974, 30.957813], + [116.071769, 30.956787], + [116.058834, 31.012711], + [116.015102, 31.011685], + [116.006479, 31.034764], + [115.938726, 31.04707], + [115.939958, 31.071678], + [115.887603, 31.10909], + [115.867277, 31.147512], + [115.837712, 31.127022], + [115.797676, 31.128047], + [115.778582, 31.112164], + [115.700973, 31.201276], + [115.655394, 31.211002], + [115.603655, 31.17363], + [115.585793, 31.143926], + [115.540213, 31.194621], + [115.539597, 31.231985], + [115.507568, 31.267799], + [115.473076, 31.265242], + [115.443511, 31.344498], + [115.40717, 31.337854], + [115.372062, 31.349098], + [115.393004, 31.389977], + [115.373909, 31.405813], + [115.338801, 31.40428], + [115.301229, 31.383846], + [115.250722, 31.392021], + [115.252569, 31.421646], + [115.211301, 31.442072], + [115.218077, 31.515057], + [115.235939, 31.555354], + [115.212533, 31.555354], + [115.16449, 31.604808], + [115.12507, 31.599201], + [115.106592, 31.567592], + [115.114599, 31.530362], + [115.096121, 31.508425], + [115.022824, 31.527811], + [114.995107, 31.471171], + [114.962462, 31.494648], + [114.884238, 31.469129], + [114.870071, 31.479337], + [114.830035, 31.45892], + [114.789383, 31.480358], + [114.778912, 31.520669], + [114.696376, 31.525771], + [114.641558, 31.582378], + [114.61692, 31.585437], + [114.572572, 31.553824], + [114.560869, 31.560963], + [114.547935, 31.623665], + [114.57134, 31.660858], + [114.586123, 31.762172], + [114.549783, 31.766751], + [114.530688, 31.742834], + [114.443841, 31.728074], + [114.403189, 31.746906], + [114.350218, 31.755557], + [114.292936, 31.752503], + [114.235654, 31.833382], + [114.191922, 31.852192], + [114.134024, 31.843042], + [114.121705, 31.809482], + [114.086596, 31.782014], + [114.017611, 31.770822], + [113.988662, 31.749959], + [113.952321, 31.793714], + [113.957865, 31.852701], + [113.914749, 31.877098], + [113.893807, 31.847109], + [113.854387, 31.843042], + [113.830981, 31.87913], + [113.832213, 31.918761], + [113.805728, 31.929428], + [113.817431, 31.964467], + [113.757685, 31.98985], + [113.791561, 32.036028], + [113.728735, 32.083197], + [113.722576, 32.12426], + [113.750293, 32.11615], + [113.782322, 32.184553], + [113.752757, 32.215951], + [113.73859, 32.255942], + [113.749061, 32.272642], + [113.768772, 32.30148], + [113.753989, 32.328286], + [113.76754, 32.370249], + [113.735511, 32.410677], + [113.700402, 32.420782], + [113.650511, 32.412698], + [113.624642, 32.36115], + [113.511925, 32.316654], + [113.428773, 32.270618], + [113.376418, 32.298445], + [113.353628, 32.294904], + [113.317904, 32.327275], + [113.333918, 32.336377], + [113.2366, 32.407141], + [113.211962, 32.431895], + [113.158992, 32.410677], + [113.155912, 32.380863], + [113.118956, 32.375809], + [113.107869, 32.398551], + [113.078919, 32.394508], + [113.025949, 32.425328], + [113.000695, 32.41674], + [112.992072, 32.378336], + [112.912, 32.390971], + [112.888594, 32.37682], + [112.860877, 32.396024], + [112.776493, 32.358623], + [112.735841, 32.356095], + [112.733993, 32.356601], + [112.724138, 32.358623], + [112.716747, 32.357612], + [112.645298, 32.368227], + [112.612037, 32.386928], + [112.589248, 32.381369], + [112.545516, 32.404109], + [112.530733, 32.37682], + [112.477147, 32.380863], + [112.448814, 32.34295], + [112.390915, 32.37126], + [112.360118, 32.3657], + [112.328089, 32.321712], + [112.206133, 32.392992], + [112.172873, 32.385412], + [112.150083, 32.411688], + [112.155626, 32.377326], + [112.081098, 32.425833], + [112.063851, 32.474315], + [112.014576, 32.450077], + [111.975772, 32.471791], + [111.948671, 32.51722], + [111.890157, 32.503089], + [111.858128, 32.528826], + [111.808853, 32.536899], + [111.713382, 32.606497], + [111.646245, 32.605993], + [111.640701, 32.634724], + [111.577875, 32.593388], + [111.530448, 32.628172], + [111.513202, 32.674026], + [111.458383, 32.726402], + [111.475629, 32.760127], + [111.41342, 32.757108], + [111.380159, 32.829049], + [111.293311, 32.859217], + [111.276065, 32.903445], + [111.255123, 32.883846], + [111.242804, 32.930573], + [111.273601, 32.971753], + [111.258819, 33.006389], + [111.221862, 33.042517], + [111.152877, 33.039507], + [111.192913, 33.071609], + [111.179363, 33.115229], + [111.146102, 33.12375], + [111.12824, 33.15532], + [111.08882, 33.181871], + [111.045704, 33.169849] + ] + ], + [ + [ + [109.106111, 30.570587], + [109.101183, 30.579346], + [109.09872, 30.579346], + [109.106111, 30.570587] + ] + ], + [ + [ + [111.046936, 33.202905], + [111.035849, 33.187881], + [111.034001, 33.177864], + [111.045704, 33.169849], + [111.046936, 33.202905] + ] + ], + [ + [ + [112.716747, 32.357612], + [112.735841, 32.356095], + [112.733993, 32.356601], + [112.724138, 32.358623], + [112.716747, 32.357612] + ] + ], + [ + [ + [112.902145, 29.79149], + [112.894138, 29.783699], + [112.923703, 29.766557], + [112.929246, 29.77383], + [112.902145, 29.79149] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 430000, + "name": "湖南省", + "center": [112.982279, 28.19409], + "centroid": [111.711649, 27.629216], + "childrenNum": 14, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 17, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [112.024431, 24.740308], + [112.03367, 24.771286], + [112.124214, 24.841364], + [112.149467, 24.837019], + [112.167329, 24.859828], + [112.175337, 24.927685], + [112.119902, 24.963499], + [112.12175, 24.989538], + [112.155626, 25.026419], + [112.151931, 25.055698], + [112.177184, 25.106649], + [112.187039, 25.182494], + [112.246785, 25.185202], + [112.256025, 25.159204], + [112.302836, 25.157037], + [112.315771, 25.175453], + [112.365046, 25.191701], + [112.414937, 25.14241], + [112.44327, 25.185744], + [112.458053, 25.152162], + [112.562762, 25.124531], + [112.628052, 25.140785], + [112.660081, 25.132658], + [112.712436, 25.083344], + [112.714899, 25.025876], + [112.742001, 24.99876], + [112.743233, 24.959701], + [112.778341, 24.947764], + [112.780805, 24.896747], + [112.873812, 24.896747], + [112.904609, 24.921715], + [112.941565, 24.915745], + [112.994536, 24.927142], + [113.009934, 24.977604], + [112.979137, 25.03401], + [113.004391, 25.089306], + [112.96805, 25.141869], + [112.97421, 25.168412], + [113.034572, 25.198199], + [112.992688, 25.247467], + [112.958195, 25.254503], + [112.897833, 25.238264], + [112.867036, 25.249632], + [112.854718, 25.337829], + [112.891058, 25.339993], + [112.924319, 25.296714], + [112.93479, 25.325929], + [112.969898, 25.350269], + [113.013014, 25.352432], + [113.078304, 25.382174], + [113.096782, 25.412449], + [113.131274, 25.414611], + [113.11834, 25.445418], + [113.176854, 25.471355], + [113.226129, 25.50971], + [113.248919, 25.514031], + [113.311129, 25.490264], + [113.314208, 25.442716], + [113.341926, 25.448661], + [113.373338, 25.402719], + [113.407215, 25.401637], + [113.449715, 25.359463], + [113.479896, 25.375145], + [113.535946, 25.368656], + [113.579062, 25.34432], + [113.584606, 25.306453], + [113.611707, 25.327552], + [113.680076, 25.334584], + [113.686852, 25.351891], + [113.753373, 25.362707], + [113.76446, 25.333502], + [113.814967, 25.328634], + [113.839605, 25.363248], + [113.877177, 25.380552], + [113.887032, 25.436772], + [113.94493, 25.441635], + [113.962792, 25.528072], + [113.986198, 25.529153], + [113.983118, 25.599336], + [113.957249, 25.611749], + [113.913517, 25.701299], + [113.920293, 25.741197], + [113.961561, 25.77731], + [113.971416, 25.836036], + [114.028082, 25.893119], + [114.028082, 25.98138], + [114.008372, 26.015806], + [114.044096, 26.076564], + [114.087828, 26.06635], + [114.121089, 26.085702], + [114.10569, 26.097526], + [114.188842, 26.121172], + [114.237501, 26.152333], + [114.216559, 26.203355], + [114.181451, 26.214631], + [114.102611, 26.187783], + [114.088444, 26.168448], + [114.013299, 26.184023], + [113.962792, 26.150722], + [113.949242, 26.192616], + [113.972647, 26.20604], + [113.978807, 26.237716], + [114.029314, 26.266163], + [114.021307, 26.288701], + [114.047792, 26.337518], + [114.030546, 26.376664], + [114.062575, 26.406149], + [114.085364, 26.406149], + [114.090292, 26.455988], + [114.110002, 26.482775], + [114.07243, 26.480096], + [114.10877, 26.56952], + [114.019459, 26.587182], + [113.996669, 26.615543], + [113.912901, 26.613938], + [113.860546, 26.664221], + [113.853771, 26.769532], + [113.835909, 26.806394], + [113.877177, 26.859262], + [113.890112, 26.895562], + [113.927068, 26.948922], + [113.892575, 26.964925], + [113.86301, 27.018252], + [113.824206, 27.036378], + [113.803264, 27.099261], + [113.771851, 27.096598], + [113.779242, 27.137081], + [113.846996, 27.222262], + [113.872865, 27.289828], + [113.854387, 27.30525], + [113.872865, 27.346721], + [113.872865, 27.384988], + [113.72812, 27.350442], + [113.699786, 27.331836], + [113.657902, 27.347253], + [113.616635, 27.345658], + [113.605548, 27.38924], + [113.632033, 27.40518], + [113.59754, 27.428554], + [113.591381, 27.467855], + [113.627105, 27.49971], + [113.583374, 27.524657], + [113.579062, 27.545354], + [113.608627, 27.585143], + [113.607395, 27.625449], + [113.652359, 27.663619], + [113.696707, 27.71979], + [113.69917, 27.740979], + [113.763228, 27.799228], + [113.756453, 27.860091], + [113.72812, 27.874904], + [113.752141, 27.93361], + [113.822974, 27.982243], + [113.845148, 27.971672], + [113.864242, 28.004966], + [113.914133, 27.991227], + [113.936307, 28.018703], + [113.966488, 28.017646], + [113.970184, 28.041418], + [114.025618, 28.031382], + [114.047176, 28.057263], + [114.025002, 28.080499], + [113.992357, 28.161255], + [114.012068, 28.174972], + [114.068734, 28.171806], + [114.107538, 28.182885], + [114.109386, 28.205038], + [114.143879, 28.246694], + [114.182067, 28.249858], + [114.198081, 28.29097], + [114.2529, 28.319423], + [114.252284, 28.395787], + [114.214712, 28.403157], + [114.172212, 28.432632], + [114.217175, 28.466308], + [114.218407, 28.48472], + [114.15435, 28.507337], + [114.138335, 28.533629], + [114.08598, 28.558337], + [114.132176, 28.607211], + [114.122321, 28.623497], + [114.157429, 28.761566], + [114.137719, 28.779926], + [114.153734, 28.829221], + [114.124784, 28.843376], + [114.076741, 28.834464], + [114.056415, 28.872204], + [114.060111, 28.902596], + [114.028082, 28.891069], + [114.005292, 28.917788], + [114.008988, 28.955498], + [113.973879, 28.937692], + [113.955401, 28.978536], + [113.961561, 28.999476], + [113.94185, 29.047097], + [113.898119, 29.029307], + [113.876561, 29.038202], + [113.882104, 29.065407], + [113.852539, 29.058606], + [113.816199, 29.105154], + [113.775547, 29.095219], + [113.749677, 29.060699], + [113.722576, 29.104631], + [113.696091, 29.077437], + [113.690547, 29.114566], + [113.66283, 29.16945], + [113.691779, 29.19662], + [113.693011, 29.226394], + [113.651743, 29.225872], + [113.609859, 29.25146], + [113.632033, 29.316186], + [113.660982, 29.333405], + [113.674533, 29.388172], + [113.731199, 29.393907], + [113.755221, 29.446557], + [113.677613, 29.513763], + [113.630801, 29.523137], + [113.710257, 29.555419], + [113.73859, 29.579363], + [113.704098, 29.634518], + [113.680692, 29.64336], + [113.663446, 29.684443], + [113.606164, 29.666764], + [113.547033, 29.675603], + [113.540258, 29.699519], + [113.558736, 29.727067], + [113.550729, 29.768115], + [113.575367, 29.809147], + [113.571671, 29.849123], + [113.37765, 29.703158], + [113.277252, 29.594976], + [113.222433, 29.543965], + [113.181781, 29.485636], + [113.145441, 29.449163], + [113.099861, 29.459585], + [113.078304, 29.438218], + [113.057362, 29.522616], + [113.034572, 29.523658], + [112.950188, 29.473132], + [112.912, 29.606944], + [112.915696, 29.620992], + [113.005007, 29.693801], + [113.025949, 29.772791], + [112.974826, 29.732784], + [112.944645, 29.682883], + [112.926782, 29.692241], + [112.923703, 29.766557], + [112.894138, 29.783699], + [112.861493, 29.78318], + [112.79374, 29.735902], + [112.788812, 29.681323], + [112.733378, 29.645441], + [112.714283, 29.648561], + [112.693957, 29.601741], + [112.650842, 29.592374], + [112.640371, 29.607985], + [112.572001, 29.624113], + [112.54182, 29.60122], + [112.499321, 29.629316], + [112.439574, 29.633997], + [112.424792, 29.598619], + [112.368741, 29.541362], + [112.333017, 29.545007], + [112.291133, 29.517409], + [112.281278, 29.536676], + [112.303452, 29.585609], + [112.233851, 29.61631], + [112.244322, 29.659483], + [112.202438, 29.633997], + [112.178416, 29.656883], + [112.111279, 29.659483], + [112.089721, 29.685482], + [112.065699, 29.681323], + [112.07617, 29.743696], + [112.008417, 29.778505], + [111.95483, 29.796683], + [111.965917, 29.832512], + [111.925881, 29.836665], + [111.899396, 29.855871], + [111.899396, 29.855871], + [111.861207, 29.856909], + [111.8107, 29.901017], + [111.75773, 29.92021], + [111.723853, 29.909317], + [111.723853, 29.909317], + [111.705375, 29.890121], + [111.669034, 29.888565], + [111.669034, 29.888565], + [111.553854, 29.894272], + [111.527368, 29.925916], + [111.475629, 29.918654], + [111.436825, 29.930065], + [111.394325, 29.912948], + [111.382623, 29.95029], + [111.342587, 29.944586], + [111.3315, 29.970512], + [111.266826, 30.01146], + [111.242188, 30.040476], + [111.031537, 30.048765], + [110.929907, 30.063268], + [110.924364, 30.111426], + [110.851067, 30.126439], + [110.746973, 30.112979], + [110.756212, 30.054463], + [110.712481, 30.033223], + [110.650887, 30.07777], + [110.600996, 30.054463], + [110.531394, 30.061197], + [110.497518, 30.055499], + [110.491358, 30.019751], + [110.557264, 29.988137], + [110.517228, 29.961179], + [110.49875, 29.91243], + [110.538786, 29.895828], + [110.549873, 29.848085], + [110.60038, 29.839779], + [110.642879, 29.775907], + [110.562807, 29.712515], + [110.507373, 29.692241], + [110.467337, 29.713034], + [110.447011, 29.664684], + [110.372482, 29.633477], + [110.339221, 29.668324], + [110.302265, 29.661563], + [110.289946, 29.6964], + [110.219729, 29.746814], + [110.160599, 29.753569], + [110.113788, 29.789932], + [110.02386, 29.769674], + [109.941325, 29.774349], + [109.908064, 29.763959], + [109.869876, 29.774869], + [109.779333, 29.757725], + [109.755311, 29.733304], + [109.760238, 29.689122], + [109.714659, 29.673524], + [109.701108, 29.636078], + [109.717739, 29.615269], + [109.664768, 29.599659], + [109.651833, 29.625674], + [109.578536, 29.629836], + [109.558826, 29.606944], + [109.516326, 29.626194], + [109.488609, 29.553336], + [109.467051, 29.560104], + [109.458428, 29.513242], + [109.433791, 29.530948], + [109.436254, 29.488761], + [109.415928, 29.497617], + [109.418392, 29.453332], + [109.368501, 29.413719], + [109.391291, 29.372005], + [109.343863, 29.369398], + [109.352487, 29.284872], + [109.312451, 29.25146], + [109.257632, 29.222738], + [109.275494, 29.202366], + [109.261328, 29.161089], + [109.274262, 29.121885], + [109.232378, 29.119271], + [109.240386, 29.086328], + [109.312451, 29.066453], + [109.319842, 29.042388], + [109.294588, 29.015177], + [109.292741, 28.987436], + [109.261328, 28.952356], + [109.235458, 28.882161], + [109.246545, 28.80143], + [109.241002, 28.776779], + [109.2989, 28.7474], + [109.294588, 28.722211], + [109.252704, 28.691767], + [109.271183, 28.671816], + [109.192958, 28.636104], + [109.201581, 28.597753], + [109.235458, 28.61982], + [109.252089, 28.606685], + [109.306907, 28.62087], + [109.319842, 28.579886], + [109.273646, 28.53836], + [109.274262, 28.494714], + [109.260712, 28.46473], + [109.264407, 28.392628], + [109.289045, 28.373673], + [109.268719, 28.33786], + [109.275494, 28.313101], + [109.317994, 28.277795], + [109.33524, 28.293605], + [109.388211, 28.268307], + [109.367885, 28.254602], + [109.340168, 28.19027], + [109.33832, 28.141731], + [109.314298, 28.103729], + [109.298284, 28.036136], + [109.335856, 28.063073], + [109.378972, 28.034551], + [109.362342, 28.007608], + [109.319842, 27.988585], + [109.30198, 27.956343], + [109.32169, 27.868027], + [109.346943, 27.838396], + [109.332777, 27.782815], + [109.37774, 27.736741], + [109.366653, 27.721909], + [109.414081, 27.725087], + [109.470747, 27.680049], + [109.45658, 27.673689], + [109.470131, 27.62863], + [109.451037, 27.586204], + [109.461508, 27.567637], + [109.404841, 27.55066], + [109.303211, 27.47582], + [109.300132, 27.423774], + [109.245313, 27.41793], + [109.202197, 27.450331], + [109.167089, 27.41793], + [109.141835, 27.448207], + [109.142451, 27.418461], + [109.103647, 27.336621], + [109.044517, 27.331304], + [109.053756, 27.293551], + [108.983539, 27.26802], + [108.963213, 27.235565], + [108.907778, 27.204699], + [108.926873, 27.160512], + [108.878829, 27.106187], + [108.79075, 27.084343], + [108.877597, 27.01612], + [108.942887, 27.017186], + [108.942887, 27.017186], + [108.940423, 27.044907], + [109.007561, 27.08008], + [109.032814, 27.104056], + [109.128901, 27.122701], + [109.101183, 27.06889], + [109.165857, 27.066758], + [109.21698, 27.114711], + [109.239154, 27.14933], + [109.264407, 27.131755], + [109.33524, 27.139212], + [109.358646, 27.153058], + [109.415312, 27.154123], + [109.441182, 27.117907], + [109.472595, 27.134951], + [109.454733, 27.069423], + [109.486761, 27.053968], + [109.497848, 27.079548], + [109.520022, 27.058764], + [109.555131, 26.946788], + [109.436254, 26.892359], + [109.452885, 26.861932], + [109.486761, 26.895562], + [109.509551, 26.877947], + [109.513247, 26.84004], + [109.497232, 26.815474], + [109.522486, 26.749226], + [109.528645, 26.743881], + [109.554515, 26.73533], + [109.597015, 26.756173], + [109.568065, 26.726243], + [109.528645, 26.743881], + [109.52187, 26.749226], + [109.486761, 26.759913], + [109.447957, 26.759913], + [109.407305, 26.719829], + [109.35495, 26.693098], + [109.283501, 26.698445], + [109.306291, 26.661012], + [109.334008, 26.646036], + [109.35495, 26.658873], + [109.390675, 26.598955], + [109.407305, 26.533116], + [109.381436, 26.518659], + [109.385747, 26.493487], + [109.362342, 26.472061], + [109.38082, 26.454381], + [109.319842, 26.418477], + [109.29582, 26.350389], + [109.271183, 26.327863], + [109.285965, 26.295676], + [109.325385, 26.29031], + [109.351255, 26.264016], + [109.369733, 26.277432], + [109.442414, 26.289774], + [109.467051, 26.313917], + [109.439334, 26.238789], + [109.47629, 26.148035], + [109.513863, 26.128157], + [109.502776, 26.096451], + [109.449805, 26.101826], + [109.452885, 26.055598], + [109.48245, 26.029788], + [109.513247, 25.998056], + [109.560058, 26.021184], + [109.588391, 26.019571], + [109.635203, 26.047533], + [109.649369, 26.016882], + [109.730057, 25.989988], + [109.710963, 25.954478], + [109.693717, 25.959321], + [109.67955, 25.921649], + [109.685094, 25.880197], + [109.768246, 25.890427], + [109.779333, 25.866196], + [109.811361, 25.877504], + [109.826144, 25.911422], + [109.806434, 25.973848], + [109.782412, 25.996981], + [109.814441, 26.041081], + [109.864332, 26.027637], + [109.898825, 26.095377], + [109.904368, 26.135679], + [109.970274, 26.195301], + [110.03002, 26.166299], + [110.099005, 26.168985], + [110.100853, 26.132455], + [110.065128, 26.050221], + [110.100853, 26.020108], + [110.168606, 26.028713], + [110.181541, 26.060437], + [110.24991, 26.010965], + [110.257301, 25.961473], + [110.325671, 25.975462], + [110.373098, 26.088927], + [110.437772, 26.153945], + [110.477808, 26.179727], + [110.495054, 26.166299], + [110.546793, 26.233421], + [110.552952, 26.283335], + [110.584365, 26.296749], + [110.612083, 26.333764], + [110.643495, 26.308552], + [110.673676, 26.317135], + [110.721104, 26.294066], + [110.742046, 26.313917], + [110.73527, 26.270993], + [110.759292, 26.248451], + [110.836284, 26.255966], + [110.939762, 26.286554], + [110.926212, 26.320354], + [110.944074, 26.326791], + [110.94469, 26.373447], + [110.974255, 26.385778], + [111.008747, 26.35897], + [111.008132, 26.336982], + [111.090667, 26.308016], + [111.208928, 26.30426], + [111.204616, 26.276359], + [111.228022, 26.261333], + [111.277913, 26.272066], + [111.293311, 26.222148], + [111.271754, 26.217316], + [111.274833, 26.183486], + [111.258203, 26.151796], + [111.26621, 26.095914], + [111.244652, 26.078177], + [111.267442, 26.058824], + [111.235413, 26.048071], + [111.189834, 25.953402], + [111.230486, 25.916267], + [111.251428, 25.864581], + [111.29208, 25.854349], + [111.297007, 25.874274], + [111.346282, 25.906577], + [111.376463, 25.906039], + [111.383239, 25.881812], + [111.460231, 25.885042], + [111.4861, 25.859196], + [111.43313, 25.84627], + [111.442369, 25.77192], + [111.399869, 25.744431], + [111.30871, 25.720171], + [111.309942, 25.645203], + [111.343202, 25.602574], + [111.324724, 25.564249], + [111.32842, 25.521592], + [111.279145, 25.42326], + [111.210776, 25.363248], + [111.184906, 25.367034], + [111.138711, 25.303748], + [111.103602, 25.285351], + [111.112841, 25.21715], + [110.998892, 25.161371], + [110.98411, 25.101772], + [110.951465, 25.04377], + [110.968711, 24.975434], + [111.009363, 24.921172], + [111.100522, 24.945593], + [111.101754, 25.035095], + [111.139943, 25.042144], + [111.200921, 25.074672], + [111.221862, 25.106649], + [111.274833, 25.151078], + [111.321645, 25.105023], + [111.36784, 25.108817], + [111.375231, 25.128324], + [111.435593, 25.093642], + [111.416499, 25.047566], + [111.467622, 25.02208], + [111.460231, 24.992793], + [111.43313, 24.979774], + [111.434977, 24.951562], + [111.470086, 24.92877], + [111.447296, 24.892947], + [111.449144, 24.857113], + [111.479325, 24.797366], + [111.461463, 24.728894], + [111.431282, 24.687574], + [111.451608, 24.665822], + [111.499035, 24.667997], + [111.526752, 24.637538], + [111.570484, 24.64461], + [111.588962, 24.690837], + [111.641933, 24.684856], + [111.637621, 24.715303], + [111.666571, 24.760961], + [111.708455, 24.788673], + [111.783599, 24.785957], + [111.814396, 24.770199], + [111.868599, 24.771829], + [111.875374, 24.756613], + [111.929577, 24.75607], + [111.951135, 24.769655], + [112.024431, 24.740308] + ] + ], + [ + [ + [109.528645, 26.743881], + [109.522486, 26.749226], + [109.52187, 26.749226], + [109.528645, 26.743881] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 440000, + "name": "广东省", + "center": [113.280637, 23.125178], + "centroid": [113.429919, 23.334643], + "childrenNum": 21, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 18, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [113.558736, 22.212244], + [113.594461, 22.228864], + [113.595693, 22.304186], + [113.617866, 22.315259], + [113.604932, 22.339617], + [113.627721, 22.349027], + [113.669605, 22.416539], + [113.66591, 22.438667], + [113.624642, 22.443092], + [113.608627, 22.408793], + [113.573519, 22.41156], + [113.631417, 22.475723], + [113.668373, 22.4807], + [113.691779, 22.514981], + [113.740438, 22.534329], + [113.717033, 22.645391], + [113.678228, 22.726007], + [113.733663, 22.736494], + [113.758301, 22.683496], + [113.765692, 22.665825], + [113.803264, 22.593463], + [113.856851, 22.539857], + [113.869786, 22.459685], + [113.893807, 22.442539], + [113.952937, 22.486783], + [113.954785, 22.491206], + [113.976343, 22.510558], + [114.031778, 22.503923], + [114.082285, 22.512216], + [114.095219, 22.534329], + [114.156813, 22.543726], + [114.166052, 22.559201], + [114.222719, 22.553122], + [114.232574, 22.539857], + [114.294784, 22.563623], + [114.321885, 22.587385], + [114.381631, 22.60175], + [114.427211, 22.589042], + [114.472174, 22.522168], + [114.476486, 22.459132], + [114.506667, 22.438667], + [114.549167, 22.465769], + [114.611377, 22.481806], + [114.628623, 22.513875], + [114.614456, 22.545384], + [114.568261, 22.560859], + [114.559022, 22.583517], + [114.603369, 22.638763], + [114.579964, 22.661407], + [114.51529, 22.655332], + [114.567029, 22.685705], + [114.591666, 22.690122], + [114.601521, 22.730975], + [114.689601, 22.7674], + [114.709927, 22.787817], + [114.749963, 22.764089], + [114.73518, 22.724351], + [114.728405, 22.651466], + [114.743803, 22.632687], + [114.746267, 22.581859], + [114.866375, 22.591805], + [114.88547, 22.538751], + [114.922426, 22.549253], + [114.927969, 22.621639], + [114.945216, 22.645391], + [115.039454, 22.713862], + [115.02344, 22.726007], + [115.053621, 22.747533], + [115.076411, 22.788368], + [115.154635, 22.80161], + [115.190975, 22.77347], + [115.190359, 22.818711], + [115.236555, 22.82533], + [115.230396, 22.776781], + [115.319091, 22.783402], + [115.338185, 22.776781], + [115.349272, 22.712206], + [115.381301, 22.684048], + [115.430576, 22.684048], + [115.471844, 22.697852], + [115.575322, 22.650914], + [115.565467, 22.684048], + [115.609198, 22.753052], + [115.541445, 22.755259], + [115.570394, 22.786713], + [115.583945, 22.82864], + [115.654162, 22.865591], + [115.696046, 22.84298], + [115.760103, 22.834707], + [115.788437, 22.809885], + [115.796444, 22.739254], + [115.829089, 22.734838], + [115.883291, 22.78561], + [115.931334, 22.802713], + [115.965211, 22.800506], + [115.99724, 22.826985], + [116.05637, 22.844635], + [116.104413, 22.816505], + [116.14137, 22.835259], + [116.239304, 22.921275], + [116.259014, 22.932298], + [116.302746, 22.951588], + [116.382818, 22.91907], + [116.449955, 22.936707], + [116.50539, 22.930645], + [116.544194, 22.996769], + [116.576839, 23.014397], + [116.557129, 23.056253], + [116.566368, 23.088738], + [116.550969, 23.109656], + [116.566368, 23.134424], + [116.665534, 23.158086], + [116.701259, 23.198248], + [116.74499, 23.215299], + [116.806584, 23.200998], + [116.821367, 23.240597], + [116.798577, 23.244996], + [116.782563, 23.313714], + [116.871874, 23.4159], + [116.871258, 23.416449], + [116.874338, 23.447199], + [116.874953, 23.447748], + [116.895895, 23.476295], + [116.888504, 23.501543], + [116.92854, 23.530079], + [116.963649, 23.507031], + [117.01046, 23.502641], + [117.044953, 23.539955], + [117.085605, 23.536663], + [117.192778, 23.5619], + [117.192778, 23.629356], + [117.147199, 23.654027], + [117.123793, 23.647448], + [117.055424, 23.694038], + [117.048032, 23.758687], + [117.019083, 23.801952], + [117.012308, 23.855054], + [116.981511, 23.855602], + [116.955642, 23.922359], + [116.976583, 23.931659], + [116.981511, 23.999471], + [116.953178, 24.008218], + [116.930388, 24.064514], + [116.9347, 24.126794], + [116.998757, 24.179217], + [116.956257, 24.216883], + [116.933468, 24.220157], + [116.938395, 24.28127], + [116.914374, 24.287817], + [116.919301, 24.321087], + [116.895895, 24.350533], + [116.903903, 24.369614], + [116.839229, 24.442097], + [116.860787, 24.460075], + [116.83307, 24.496568], + [116.796729, 24.502014], + [116.759157, 24.545572], + [116.761005, 24.583128], + [116.815207, 24.654944], + [116.777635, 24.679418], + [116.667382, 24.658752], + [116.623034, 24.64189], + [116.600861, 24.654401], + [116.570679, 24.621762], + [116.530027, 24.604895], + [116.506622, 24.621218], + [116.517709, 24.652225], + [116.485064, 24.720196], + [116.44626, 24.714216], + [116.416079, 24.744113], + [116.419158, 24.767482], + [116.375427, 24.803885], + [116.381586, 24.82507], + [116.417927, 24.840821], + [116.395137, 24.877746], + [116.363724, 24.87123], + [116.345862, 24.828872], + [116.297202, 24.801712], + [116.244232, 24.793563], + [116.251007, 24.82507], + [116.221442, 24.829959], + [116.191877, 24.877203], + [116.153073, 24.846795], + [116.068073, 24.850053], + [116.015102, 24.905975], + [115.985537, 24.899461], + [115.907929, 24.923343], + [115.89253, 24.936911], + [115.885139, 24.898918], + [115.907313, 24.879917], + [115.861733, 24.863629], + [115.863581, 24.891318], + [115.824161, 24.909232], + [115.807531, 24.862543], + [115.790284, 24.856027], + [115.764415, 24.791933], + [115.776734, 24.774546], + [115.756408, 24.749004], + [115.769342, 24.708236], + [115.801371, 24.705517], + [115.780429, 24.663103], + [115.797676, 24.628834], + [115.840791, 24.584217], + [115.843871, 24.562446], + [115.785357, 24.567345], + [115.752712, 24.546116], + [115.68927, 24.545027], + [115.671408, 24.604895], + [115.605503, 24.62557], + [115.569778, 24.622306], + [115.555611, 24.683768], + [115.522967, 24.702799], + [115.476771, 24.762591], + [115.412714, 24.79302], + [115.372678, 24.774546], + [115.358511, 24.735416], + [115.306772, 24.758787], + [115.269816, 24.749548], + [115.258729, 24.728894], + [115.1842, 24.711498], + [115.104744, 24.667997], + [115.083802, 24.699537], + [115.057317, 24.703343], + [115.024672, 24.669085], + [115.00373, 24.679418], + [114.940288, 24.650049], + [114.909491, 24.661471], + [114.893477, 24.582584], + [114.868839, 24.562446], + [114.846665, 24.602719], + [114.827571, 24.588026], + [114.781376, 24.613057], + [114.729637, 24.608704], + [114.73826, 24.565168], + [114.704999, 24.525973], + [114.664963, 24.583673], + [114.627391, 24.576598], + [114.589819, 24.537406], + [114.534384, 24.559181], + [114.429058, 24.48622], + [114.403189, 24.497657], + [114.391486, 24.563535], + [114.363769, 24.582584], + [114.300943, 24.578775], + [114.289856, 24.619042], + [114.258443, 24.641346], + [114.19069, 24.656576], + [114.169132, 24.689749], + [114.27261, 24.700624], + [114.281849, 24.724001], + [114.336052, 24.749004], + [114.342211, 24.807145], + [114.378551, 24.861457], + [114.403189, 24.877746], + [114.395798, 24.951019], + [114.454928, 24.977062], + [114.45616, 24.99659], + [114.506051, 24.999844], + [114.532536, 25.022623], + [114.561485, 25.077382], + [114.604601, 25.083886], + [114.640326, 25.074129], + [114.664963, 25.10123], + [114.735796, 25.121822], + [114.73518, 25.155954], + [114.685905, 25.173287], + [114.693912, 25.213902], + [114.73518, 25.225813], + [114.743188, 25.274528], + [114.714238, 25.315651], + [114.63663, 25.324306], + [114.599674, 25.385959], + [114.541159, 25.416773], + [114.477718, 25.37136], + [114.438914, 25.376226], + [114.43029, 25.343779], + [114.382863, 25.317274], + [114.31511, 25.33837], + [114.2954, 25.299961], + [114.260291, 25.291845], + [114.204857, 25.29942], + [114.190074, 25.316733], + [114.115545, 25.302125], + [114.083517, 25.275611], + [114.055799, 25.277775], + [114.039785, 25.250714], + [114.017611, 25.273987], + [114.029314, 25.328093], + [114.050256, 25.36433], + [113.983118, 25.415152], + [114.003444, 25.442716], + [113.94493, 25.441635], + [113.887032, 25.436772], + [113.877177, 25.380552], + [113.839605, 25.363248], + [113.814967, 25.328634], + [113.76446, 25.333502], + [113.753373, 25.362707], + [113.686852, 25.351891], + [113.680076, 25.334584], + [113.611707, 25.327552], + [113.584606, 25.306453], + [113.579062, 25.34432], + [113.535946, 25.368656], + [113.479896, 25.375145], + [113.449715, 25.359463], + [113.407215, 25.401637], + [113.373338, 25.402719], + [113.341926, 25.448661], + [113.314208, 25.442716], + [113.311129, 25.490264], + [113.248919, 25.514031], + [113.226129, 25.50971], + [113.176854, 25.471355], + [113.11834, 25.445418], + [113.131274, 25.414611], + [113.096782, 25.412449], + [113.078304, 25.382174], + [113.013014, 25.352432], + [112.969898, 25.350269], + [112.93479, 25.325929], + [112.924319, 25.296714], + [112.891058, 25.339993], + [112.854718, 25.337829], + [112.867036, 25.249632], + [112.897833, 25.238264], + [112.958195, 25.254503], + [112.992688, 25.247467], + [113.034572, 25.198199], + [112.97421, 25.168412], + [112.96805, 25.141869], + [113.004391, 25.089306], + [112.979137, 25.03401], + [113.009934, 24.977604], + [112.994536, 24.927142], + [112.941565, 24.915745], + [112.904609, 24.921715], + [112.873812, 24.896747], + [112.780805, 24.896747], + [112.778341, 24.947764], + [112.743233, 24.959701], + [112.742001, 24.99876], + [112.714899, 25.025876], + [112.712436, 25.083344], + [112.660081, 25.132658], + [112.628052, 25.140785], + [112.562762, 25.124531], + [112.458053, 25.152162], + [112.44327, 25.185744], + [112.414937, 25.14241], + [112.365046, 25.191701], + [112.315771, 25.175453], + [112.302836, 25.157037], + [112.256025, 25.159204], + [112.246785, 25.185202], + [112.187039, 25.182494], + [112.177184, 25.106649], + [112.151931, 25.055698], + [112.155626, 25.026419], + [112.12175, 24.989538], + [112.119902, 24.963499], + [112.175337, 24.927685], + [112.167329, 24.859828], + [112.149467, 24.837019], + [112.124214, 24.841364], + [112.03367, 24.771286], + [112.024431, 24.740308], + [111.961606, 24.721283], + [111.939432, 24.686487], + [111.953598, 24.64733], + [111.927729, 24.629378], + [111.936968, 24.595645], + [111.972077, 24.578775], + [112.007185, 24.534684], + [112.009649, 24.503103], + [111.985011, 24.467701], + [112.025047, 24.438828], + [112.057692, 24.387057], + [112.05954, 24.339628], + [112.026279, 24.294908], + [111.990555, 24.279634], + [111.986243, 24.25672], + [111.958526, 24.263813], + [111.912946, 24.221795], + [111.877222, 24.227252], + [111.871062, 24.176487], + [111.886461, 24.163929], + [111.878454, 24.109862], + [111.92157, 24.012045], + [111.940664, 23.987989], + [111.911714, 23.943693], + [111.854432, 23.947521], + [111.845809, 23.904305], + [111.812548, 23.887343], + [111.824867, 23.832612], + [111.8107, 23.80688], + [111.722621, 23.823305], + [111.683201, 23.822758], + [111.683201, 23.822758], + [111.654868, 23.833159], + [111.627766, 23.78881], + [111.621607, 23.725819], + [111.666571, 23.718696], + [111.614832, 23.65896], + [111.615448, 23.639225], + [111.555702, 23.64087], + [111.487332, 23.626615], + [111.479941, 23.532822], + [111.428818, 23.466414], + [111.399869, 23.469159], + [111.383239, 23.399423], + [111.389398, 23.375804], + [111.363528, 23.340641], + [111.376463, 23.30437], + [111.353058, 23.284582], + [111.36476, 23.240047], + [111.388782, 23.210349], + [111.38447, 23.16744], + [111.365992, 23.14488], + [111.377695, 23.082132], + [111.402333, 23.066165], + [111.43313, 23.073322], + [111.433746, 23.036428], + [111.389398, 23.005583], + [111.403565, 22.99126], + [111.362913, 22.967568], + [111.374615, 22.938361], + [111.358601, 22.889301], + [111.218167, 22.748085], + [111.185522, 22.735942], + [111.118385, 22.744773], + [111.058023, 22.729871], + [111.089435, 22.695643], + [111.055559, 22.648705], + [110.997045, 22.631582], + [110.958856, 22.636553], + [110.950233, 22.61059], + [110.896031, 22.613352], + [110.897878, 22.591805], + [110.812263, 22.576333], + [110.778386, 22.585174], + [110.749437, 22.556991], + [110.762988, 22.518298], + [110.740198, 22.498947], + [110.74143, 22.464109], + [110.688459, 22.477935], + [110.712481, 22.440879], + [110.711249, 22.369506], + [110.74143, 22.361757], + [110.749437, 22.329653], + [110.787009, 22.28259], + [110.759292, 22.274837], + [110.725415, 22.29588], + [110.687843, 22.249914], + [110.646575, 22.220554], + [110.678604, 22.172901], + [110.629329, 22.149068], + [110.598532, 22.162924], + [110.602843, 22.18343], + [110.55788, 22.196175], + [110.505525, 22.14297], + [110.456866, 22.189526], + [110.414366, 22.208365], + [110.378026, 22.164587], + [110.34846, 22.195621], + [110.326287, 22.152393], + [110.364475, 22.125785], + [110.35154, 22.097508], + [110.359547, 22.015973], + [110.352772, 21.97602], + [110.374946, 21.967695], + [110.374946, 21.967695], + [110.378642, 21.939942], + [110.378642, 21.939942], + [110.391576, 21.89386], + [110.337374, 21.887751], + [110.290562, 21.917736], + [110.283787, 21.892194], + [110.224041, 21.882198], + [110.224041, 21.882198], + [110.212338, 21.886085], + [110.212338, 21.886085], + [110.196323, 21.899968], + [110.12857, 21.902744], + [110.101469, 21.86998], + [110.050962, 21.857205], + [109.999839, 21.881643], + [109.94502, 21.84443], + [109.940093, 21.769419], + [109.916071, 21.668787], + [109.888354, 21.652101], + [109.888354, 21.652101], + [109.839695, 21.636525], + [109.786108, 21.637638], + [109.778101, 21.670455], + [109.742992, 21.616497], + [109.754695, 21.556396], + [109.788572, 21.490702], + [109.785492, 21.45673], + [109.819369, 21.445033], + [109.894513, 21.442248], + [109.904368, 21.429992], + [109.868644, 21.365913], + [109.770709, 21.359783], + [109.757775, 21.346963], + [109.763934, 21.226514], + [109.674623, 21.136671], + [109.674007, 21.067997], + [109.655529, 20.929435], + [109.664768, 20.862343], + [109.711579, 20.774519], + [109.730057, 20.719673], + [109.74484, 20.621124], + [109.793499, 20.615522], + [109.813825, 20.574627], + [109.811977, 20.541566], + [109.839695, 20.489439], + [109.888354, 20.475423], + [109.895745, 20.42776], + [109.864948, 20.40196], + [109.861252, 20.376717], + [109.916071, 20.316677], + [109.909296, 20.236961], + [109.929006, 20.211691], + [109.993679, 20.254368], + [110.082375, 20.258859], + [110.118099, 20.219553], + [110.168606, 20.219553], + [110.220345, 20.25156], + [110.296722, 20.249314], + [110.349076, 20.258859], + [110.384185, 20.293103], + [110.425453, 20.291419], + [110.452554, 20.311064], + [110.491358, 20.373912], + [110.54125, 20.42047], + [110.550489, 20.47262], + [110.499982, 20.572386], + [110.487047, 20.640167], + [110.466105, 20.680485], + [110.411286, 20.670966], + [110.392192, 20.682724], + [110.407591, 20.731987], + [110.393424, 20.816479], + [110.350924, 20.84165], + [110.327519, 20.847802], + [110.269004, 20.839972], + [110.209874, 20.860106], + [110.184005, 20.891979], + [110.180925, 20.98197], + [110.204947, 21.003202], + [110.208642, 21.050684], + [110.241903, 21.016051], + [110.24991, 21.045098], + [110.296722, 21.093684], + [110.39096, 21.124949], + [110.422373, 21.190807], + [110.451322, 21.186343], + [110.501213, 21.217588], + [110.534474, 21.204198], + [110.626249, 21.215915], + [110.65951, 21.239902], + [110.713097, 21.3124], + [110.768531, 21.364799], + [110.796248, 21.37483], + [110.888639, 21.367585], + [110.929291, 21.375945], + [111.034617, 21.438906], + [111.103602, 21.455616], + [111.171355, 21.458401], + [111.28284, 21.485691], + [111.276065, 21.443362], + [111.250196, 21.45116], + [111.257587, 21.41495], + [111.28592, 21.41885], + [111.353058, 21.464528], + [111.382623, 21.495714], + [111.444217, 21.514088], + [111.494724, 21.501282], + [111.521825, 21.517429], + [111.560629, 21.50518], + [111.609904, 21.530234], + [111.650556, 21.512418], + [111.677658, 21.529677], + [111.693672, 21.590345], + [111.736788, 21.609821], + [111.794686, 21.61149], + [111.832258, 21.578659], + [111.810084, 21.555283], + [111.887693, 21.578659], + [111.941896, 21.607039], + [111.972692, 21.603144], + [112.026895, 21.633744], + [111.997946, 21.657107], + [111.954214, 21.667674], + [111.956062, 21.710494], + [112.036134, 21.761637], + [112.136532, 21.793871], + [112.192583, 21.789425], + [112.196894, 21.736624], + [112.236315, 21.727173], + [112.238778, 21.702153], + [112.353343, 21.707157], + [112.415553, 21.734956], + [112.427256, 21.789981], + [112.445734, 21.803317], + [112.497473, 21.785535], + [112.535661, 21.753856], + [112.647146, 21.758302], + [112.68595, 21.810541], + [112.792508, 21.921067], + [112.841167, 21.920512], + [112.893522, 21.84443], + [112.929862, 21.838875], + [112.989608, 21.869424], + [113.047507, 21.956595], + [113.053666, 22.012089], + [113.032108, 22.04593], + [113.045659, 22.088636], + [113.086927, 22.12634], + [113.091854, 22.065344], + [113.142977, 22.012089], + [113.1516, 21.979905], + [113.235368, 21.887751], + [113.266781, 21.871646], + [113.319752, 21.909407], + [113.330223, 21.96159], + [113.442324, 22.009315], + [113.45957, 22.043711], + [113.527939, 22.073663], + [113.567359, 22.075327], + [113.554425, 22.107489], + [113.554425, 22.142416], + [113.534715, 22.174009], + [113.53841, 22.209473], + [113.558736, 22.212244] + ] + ], + [ + [ + [117.024627, 23.437865], + [116.982743, 23.460924], + [116.944555, 23.440061], + [116.951946, 23.419744], + [117.027091, 23.41535], + [117.050496, 23.400522], + [117.081909, 23.409309], + [117.124409, 23.389537], + [117.142887, 23.400522], + [117.142887, 23.459826], + [117.129336, 23.483431], + [117.093612, 23.459277], + [117.058503, 23.47355], + [117.029554, 23.443356], + [117.024627, 23.437865] + ] + ], + [ + [ + [112.853486, 21.740515], + [112.876275, 21.772753], + [112.840551, 21.776644], + [112.782653, 21.739959], + [112.724138, 21.719945], + [112.70566, 21.679354], + [112.734609, 21.666562], + [112.780189, 21.671568], + [112.730914, 21.613715], + [112.775261, 21.564189], + [112.817145, 21.590345], + [112.798667, 21.610933], + [112.821457, 21.655994], + [112.804826, 21.686583], + [112.83316, 21.736624], + [112.853486, 21.740515] + ] + ], + [ + [ + [112.530733, 21.583667], + [112.563378, 21.591458], + [112.571385, 21.619835], + [112.621277, 21.606482], + [112.665624, 21.642644], + [112.639139, 21.67268], + [112.66624, 21.683803], + [112.663776, 21.714386], + [112.592327, 21.693256], + [112.560299, 21.666562], + [112.57077, 21.645982], + [112.535045, 21.628737], + [112.530733, 21.583667] + ] + ], + [ + [ + [114.231342, 22.016528], + [114.311414, 22.041493], + [114.302791, 22.050368], + [114.239965, 22.03539], + [114.231342, 22.016528] + ] + ], + [ + [ + [110.43346, 21.171276], + [110.489511, 21.138904], + [110.508605, 21.140579], + [110.544945, 21.083633], + [110.582517, 21.094801], + [110.632409, 21.210893], + [110.589293, 21.194713], + [110.525235, 21.190249], + [110.499366, 21.213125], + [110.445163, 21.184669], + [110.431612, 21.180763], + [110.43346, 21.171276] + ] + ], + [ + [ + [112.435263, 21.663781], + [112.456205, 21.648763], + [112.458669, 21.68992], + [112.435263, 21.663781] + ] + ], + [ + [ + [110.517844, 21.079166], + [110.459946, 21.062971], + [110.398352, 21.096476], + [110.352772, 21.079724], + [110.305961, 21.0881], + [110.27578, 21.033369], + [110.211106, 20.986999], + [110.201251, 20.938378], + [110.309656, 20.963529], + [110.347845, 20.984763], + [110.407591, 20.990351], + [110.47288, 20.983087], + [110.511684, 20.916578], + [110.535706, 20.922727], + [110.539402, 20.987557], + [110.560344, 21.061295], + [110.517844, 21.079166] + ] + ], + [ + [ + [113.765076, 21.962145], + [113.774315, 21.998218], + [113.74167, 21.991559], + [113.765076, 21.962145] + ] + ], + [ + [ + [113.723192, 21.922177], + [113.742902, 21.950489], + [113.71888, 21.951599], + [113.723192, 21.922177] + ] + ], + [ + [ + [113.142977, 21.831653], + [113.162071, 21.853873], + [113.203955, 21.861093], + [113.167615, 21.876644], + [113.136818, 21.868869], + [113.142977, 21.831653] + ] + ], + [ + [ + [113.819894, 22.396068], + [113.813735, 22.419858], + [113.786634, 22.413773], + [113.819894, 22.396068] + ] + ], + [ + [ + [114.190074, 21.986564], + [114.229494, 21.995443], + [114.180835, 22.00987], + [114.190074, 21.986564] + ] + ], + [ + [ + [114.153734, 21.97491], + [114.171596, 22.000437], + [114.124169, 21.985455], + [114.153734, 21.97491] + ] + ], + [ + [ + [116.769628, 20.771721], + [116.761005, 20.750456], + [116.87249, 20.738143], + [116.889736, 20.683284], + [116.849084, 20.628405], + [116.749302, 20.600958], + [116.796113, 20.582471], + [116.862635, 20.588633], + [116.905135, 20.619443], + [116.934084, 20.676565], + [116.925461, 20.726949], + [116.88604, 20.775638], + [116.820135, 20.780674], + [116.769628, 20.771721] + ] + ], + [ + [ + [113.025333, 21.847762], + [113.045659, 21.882753], + [113.007471, 21.869424], + [113.025333, 21.847762] + ] + ], + [ + [ + [110.405127, 20.678245], + [110.437772, 20.677685], + [110.414366, 20.710157], + [110.405127, 20.678245] + ] + ], + [ + [ + [110.644727, 20.935584], + [110.584365, 20.948998], + [110.548641, 20.908752], + [110.562807, 20.861224], + [110.611467, 20.860106], + [110.646575, 20.917137], + [110.644727, 20.935584] + ] + ], + [ + [ + [110.556648, 20.32734], + [110.593604, 20.360447], + [110.586213, 20.381205], + [110.556648, 20.32734] + ] + ], + [ + [ + [115.943037, 21.097592], + [115.953508, 21.064088], + [115.989233, 21.035603], + [116.040356, 21.02052], + [116.067457, 21.04063], + [116.044051, 21.110434], + [116.024341, 21.12439], + [115.965211, 21.123832], + [115.943037, 21.097592] + ] + ], + [ + [ + [115.926407, 20.981411], + [115.939342, 20.945644], + [115.970139, 20.919373], + [115.999088, 20.922727], + [116.000936, 20.948439], + [115.954124, 20.99985], + [115.926407, 20.981411] + ] + ], + [ + [ + [115.834632, 22.722695], + [115.834632, 22.722143], + [115.835248, 22.722695], + [115.834632, 22.722695] + ] + ], + [ + [ + [115.834632, 22.723247], + [115.834632, 22.722695], + [115.835248, 22.722695], + [115.834632, 22.723247] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 450000, + "name": "广西壮族自治区", + "center": [108.320004, 22.82402], + "centroid": [108.7944, 23.833381], + "childrenNum": 14, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 19, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [109.48245, 26.029788], + [109.473211, 26.006663], + [109.408537, 25.967392], + [109.435022, 25.93349], + [109.396834, 25.900117], + [109.359262, 25.836036], + [109.339552, 25.83442], + [109.327849, 25.76168], + [109.340168, 25.731493], + [109.296436, 25.71424], + [109.207125, 25.740119], + [109.206509, 25.788087], + [109.147995, 25.741736], + [109.13198, 25.762758], + [109.143683, 25.795092], + [109.095024, 25.80533], + [109.077778, 25.776771], + [109.048213, 25.790781], + [108.989698, 25.778926], + [108.999553, 25.765453], + [108.963829, 25.732572], + [108.940423, 25.740119], + [108.896076, 25.71424], + [108.900387, 25.682423], + [108.953974, 25.686738], + [108.953974, 25.686738], + [109.007561, 25.734728], + [109.043285, 25.738502], + [109.07901, 25.72071], + [109.075314, 25.693749], + [109.030966, 25.629556], + [109.051908, 25.566949], + [109.088249, 25.550752], + [109.024807, 25.51241], + [108.949046, 25.557231], + [108.8893, 25.543193], + [108.890532, 25.556151], + [108.826474, 25.550212], + [108.814772, 25.526992], + [108.781511, 25.554531], + [108.799989, 25.576666], + [108.783975, 25.628477], + [108.724844, 25.634952], + [108.68912, 25.623081], + [108.68604, 25.587462], + [108.660787, 25.584763], + [108.658323, 25.550212], + [108.68912, 25.533473], + [108.634917, 25.520512], + [108.6072, 25.491885], + [108.600425, 25.432448], + [108.62999, 25.335666], + [108.625062, 25.308076], + [108.589338, 25.335125], + [108.585642, 25.365952], + [108.471693, 25.458928], + [108.418723, 25.443257], + [108.400244, 25.491344], + [108.359592, 25.513491], + [108.348506, 25.536173], + [108.308469, 25.525912], + [108.280752, 25.48], + [108.241332, 25.46217], + [108.251803, 25.430286], + [108.192673, 25.458928], + [108.162492, 25.444878], + [108.193289, 25.405421], + [108.142782, 25.390825], + [108.152021, 25.324306], + [108.143398, 25.269658], + [108.115065, 25.210112], + [108.080572, 25.193867], + [108.001732, 25.196574], + [107.928435, 25.155954], + [107.872384, 25.141327], + [107.839124, 25.115861], + [107.762747, 25.125073], + [107.789233, 25.15487], + [107.760283, 25.188451], + [107.762131, 25.229061], + [107.741805, 25.24043], + [107.700537, 25.194408], + [107.696226, 25.219858], + [107.661733, 25.258833], + [107.659885, 25.316192], + [107.632168, 25.310241], + [107.599523, 25.250714], + [107.576734, 25.256668], + [107.512676, 25.209029], + [107.472024, 25.213902], + [107.489886, 25.276693], + [107.481263, 25.299961], + [107.432604, 25.289139], + [107.409198, 25.347024], + [107.420901, 25.392987], + [107.375937, 25.411908], + [107.358691, 25.393528], + [107.318039, 25.401637], + [107.308184, 25.432988], + [107.336517, 25.461089], + [107.263836, 25.543193], + [107.232423, 25.556691], + [107.228728, 25.604733], + [107.205322, 25.607971], + [107.185612, 25.578825], + [107.064272, 25.559391], + [107.066736, 25.50917], + [107.015613, 25.495666], + [106.996519, 25.442716], + [106.963874, 25.437852], + [106.987896, 25.358922], + [107.012533, 25.352973], + [107.013765, 25.275611], + [106.975577, 25.232851], + [106.933077, 25.250714], + [106.904128, 25.231768], + [106.888113, 25.181953], + [106.853005, 25.186827], + [106.787715, 25.17112], + [106.764926, 25.183036], + [106.732281, 25.162454], + [106.691013, 25.179245], + [106.644817, 25.164621], + [106.63989, 25.132658], + [106.590615, 25.08768], + [106.551195, 25.082802], + [106.519782, 25.054072], + [106.450181, 25.033468], + [106.442173, 25.019369], + [106.332536, 24.988454], + [106.304819, 24.973807], + [106.253696, 24.971094], + [106.215508, 24.981944], + [106.191486, 24.95319], + [106.145291, 24.954275], + [106.197645, 24.885889], + [106.206269, 24.851139], + [106.173008, 24.760417], + [106.150218, 24.762591], + [106.113878, 24.714216], + [106.047356, 24.684312], + [106.024566, 24.633186], + [105.961741, 24.677786], + [105.942031, 24.725088], + [105.863806, 24.729437], + [105.827466, 24.702799], + [105.767104, 24.719109], + [105.70551, 24.768569], + [105.617431, 24.78161], + [105.607576, 24.803885], + [105.573083, 24.797366], + [105.497322, 24.809318], + [105.493011, 24.833217], + [105.457286, 24.87123], + [105.428337, 24.930941], + [105.365511, 24.943423], + [105.334099, 24.9266], + [105.267577, 24.929313], + [105.251563, 24.967296], + [105.212758, 24.995505], + [105.178266, 24.985199], + [105.157324, 24.958616], + [105.131454, 24.959701], + [105.09573, 24.92877], + [105.096346, 24.928228], + [105.082179, 24.915745], + [105.077868, 24.918459], + [105.039064, 24.872859], + [105.026745, 24.815836], + [105.03352, 24.787586], + [104.899245, 24.752809], + [104.865985, 24.730524], + [104.841963, 24.676155], + [104.771746, 24.659839], + [104.729246, 24.617953], + [104.703377, 24.645698], + [104.628848, 24.660927], + [104.595587, 24.709323], + [104.529682, 24.731611], + [104.489646, 24.653313], + [104.520443, 24.535228], + [104.550008, 24.518894], + [104.575877, 24.424661], + [104.616529, 24.421937], + [104.63008, 24.397958], + [104.610986, 24.377246], + [104.641783, 24.367979], + [104.70892, 24.321087], + [104.721239, 24.340173], + [104.703377, 24.419757], + [104.715695, 24.441552], + [104.74834, 24.435559], + [104.765587, 24.45953], + [104.784681, 24.443732], + [104.83642, 24.446456], + [104.914028, 24.426296], + [104.930042, 24.411038], + [104.979933, 24.412673], + [105.042759, 24.442097], + [105.106817, 24.414853], + [105.111744, 24.37234], + [105.138846, 24.376701], + [105.188121, 24.347261], + [105.196744, 24.326541], + [105.164715, 24.288362], + [105.215222, 24.214699], + [105.24294, 24.208695], + [105.229389, 24.165567], + [105.182577, 24.167205], + [105.20044, 24.105491], + [105.260186, 24.061236], + [105.292831, 24.074896], + [105.273121, 24.092927], + [105.320548, 24.116416], + [105.334099, 24.094566], + [105.395692, 24.065607], + [105.406163, 24.043748], + [105.493011, 24.016965], + [105.533663, 24.130071], + [105.594641, 24.137718], + [105.628518, 24.126794], + [105.649459, 24.032816], + [105.704278, 24.0667], + [105.739387, 24.059596], + [105.765256, 24.073804], + [105.802212, 24.051945], + [105.796669, 24.023524], + [105.841633, 24.03063], + [105.859495, 24.056864], + [105.89214, 24.040468], + [105.908154, 24.069432], + [105.901995, 24.099482], + [105.919241, 24.122425], + [105.963589, 24.110954], + [105.998081, 24.120786], + [106.011632, 24.099482], + [106.04982, 24.089649], + [106.053516, 24.051399], + [106.096631, 24.018058], + [106.091088, 23.998924], + [106.128044, 23.956819], + [106.157609, 23.891174], + [106.192718, 23.879135], + [106.173008, 23.861622], + [106.192102, 23.824947], + [106.136667, 23.795381], + [106.157609, 23.724175], + [106.149602, 23.665538], + [106.120653, 23.605229], + [106.141595, 23.569579], + [106.08616, 23.524043], + [106.071994, 23.495506], + [106.039965, 23.484529], + [105.999929, 23.447748], + [105.986378, 23.489469], + [105.935871, 23.508678], + [105.913081, 23.499348], + [105.89214, 23.52514], + [105.852103, 23.526786], + [105.815763, 23.507031], + [105.805908, 23.467512], + [105.758481, 23.459826], + [105.699966, 23.40162], + [105.637757, 23.404366], + [105.694423, 23.363168], + [105.699966, 23.327453], + [105.649459, 23.346136], + [105.593409, 23.312614], + [105.560148, 23.257093], + [105.526272, 23.234548], + [105.542902, 23.184495], + [105.558916, 23.177893], + [105.574931, 23.066165], + [105.625438, 23.064513], + [105.648844, 23.078828], + [105.724604, 23.06231], + [105.74185, 23.030921], + [105.780039, 23.022659], + [105.805908, 22.994565], + [105.839169, 22.987403], + [105.879205, 22.916865], + [105.893987, 22.936707], + [105.959277, 22.948832], + [105.994385, 22.93781], + [106.019639, 22.990709], + [106.08616, 22.996218], + [106.106486, 22.980792], + [106.153914, 22.988505], + [106.206885, 22.978588], + [106.270326, 22.907494], + [106.258007, 22.889852], + [106.286957, 22.867245], + [106.366413, 22.857871], + [106.37134, 22.878273], + [106.41384, 22.877171], + [106.504383, 22.91025], + [106.525941, 22.946628], + [106.562282, 22.923479], + [106.606013, 22.925684], + [106.631267, 22.88103], + [106.657136, 22.863385], + [106.674998, 22.891506], + [106.716882, 22.881582], + [106.709491, 22.866142], + [106.774781, 22.812643], + [106.776012, 22.813746], + [106.778476, 22.814298], + [106.779092, 22.813746], + [106.779708, 22.813195], + [106.78094, 22.813195], + [106.784636, 22.812643], + [106.796338, 22.812091], + [106.801882, 22.815401], + [106.804346, 22.816505], + [106.808657, 22.817608], + [106.813585, 22.817608], + [106.838838, 22.803265], + [106.820976, 22.768504], + [106.768621, 22.739254], + [106.780324, 22.708894], + [106.756302, 22.68957], + [106.711955, 22.575228], + [106.650361, 22.575228], + [106.61402, 22.602303], + [106.585071, 22.517192], + [106.588151, 22.472958], + [106.560434, 22.455813], + [106.588767, 22.374486], + [106.562897, 22.345706], + [106.663296, 22.33076], + [106.670071, 22.283144], + [106.688549, 22.260438], + [106.7021, 22.207257], + [106.673151, 22.182322], + [106.706411, 22.160707], + [106.691629, 22.13521], + [106.71565, 22.089745], + [106.706411, 22.021521], + [106.683006, 21.999882], + [106.698404, 21.959925], + [106.73844, 22.008205], + [106.790179, 22.004876], + [106.802498, 21.98157], + [106.859164, 21.986009], + [106.926302, 21.967695], + [106.935541, 21.933836], + [106.974345, 21.923288], + [106.999598, 21.947714], + [107.05996, 21.914959], + [107.058729, 21.887196], + [107.018693, 21.859427], + [107.018077, 21.81943], + [107.093837, 21.803317], + [107.148656, 21.758858], + [107.194851, 21.736624], + [107.199163, 21.718833], + [107.242279, 21.703265], + [107.271844, 21.727173], + [107.310648, 21.733844], + [107.356843, 21.667674], + [107.363619, 21.602031], + [107.388256, 21.594241], + [107.431372, 21.642088], + [107.477567, 21.659888], + [107.500973, 21.613715], + [107.486806, 21.59591], + [107.547168, 21.58645], + [107.584741, 21.614828], + [107.603219, 21.597579], + [107.712856, 21.616497], + [107.807711, 21.655438], + [107.837892, 21.640419], + [107.863761, 21.650988], + [107.892095, 21.622617], + [107.893942, 21.596466], + [107.929051, 21.585893], + [107.958, 21.534131], + [108.034376, 21.545821], + [108.108289, 21.508521], + [108.193905, 21.519656], + [108.156332, 21.55083], + [108.205608, 21.597579], + [108.241332, 21.599805], + [108.249955, 21.561406], + [108.210535, 21.505737], + [108.230245, 21.491259], + [108.330027, 21.540254], + [108.397781, 21.533017], + [108.492635, 21.554727], + [108.591802, 21.677129], + [108.626294, 21.67991], + [108.658939, 21.643757], + [108.678033, 21.659331], + [108.735931, 21.628181], + [108.734084, 21.626512], + [108.745786, 21.602587], + [108.801837, 21.626512], + [108.83325, 21.610933], + [108.881293, 21.627068], + [108.937959, 21.589789], + [109.093792, 21.579215], + [109.09872, 21.571424], + [109.110422, 21.568085], + [109.138756, 21.567528], + [109.142451, 21.511861], + [109.074698, 21.489589], + [109.039589, 21.457844], + [109.046365, 21.424421], + [109.095024, 21.419407], + [109.138756, 21.388762], + [109.186183, 21.390991], + [109.245929, 21.425536], + [109.41716, 21.438906], + [109.484914, 21.453388], + [109.529877, 21.437234], + [109.540964, 21.466199], + [109.576689, 21.493487], + [109.604406, 21.523553], + [109.612413, 21.556953], + [109.654913, 21.493487], + [109.704188, 21.462857], + [109.785492, 21.45673], + [109.788572, 21.490702], + [109.754695, 21.556396], + [109.742992, 21.616497], + [109.778101, 21.670455], + [109.786108, 21.637638], + [109.839695, 21.636525], + [109.888354, 21.652101], + [109.888354, 21.652101], + [109.916071, 21.668787], + [109.940093, 21.769419], + [109.94502, 21.84443], + [109.999839, 21.881643], + [110.050962, 21.857205], + [110.101469, 21.86998], + [110.12857, 21.902744], + [110.196323, 21.899968], + [110.212338, 21.886085], + [110.212338, 21.886085], + [110.224041, 21.882198], + [110.224041, 21.882198], + [110.283787, 21.892194], + [110.290562, 21.917736], + [110.337374, 21.887751], + [110.391576, 21.89386], + [110.378642, 21.939942], + [110.378642, 21.939942], + [110.374946, 21.967695], + [110.374946, 21.967695], + [110.352772, 21.97602], + [110.359547, 22.015973], + [110.35154, 22.097508], + [110.364475, 22.125785], + [110.326287, 22.152393], + [110.34846, 22.195621], + [110.378026, 22.164587], + [110.414366, 22.208365], + [110.456866, 22.189526], + [110.505525, 22.14297], + [110.55788, 22.196175], + [110.602843, 22.18343], + [110.598532, 22.162924], + [110.629329, 22.149068], + [110.678604, 22.172901], + [110.646575, 22.220554], + [110.687843, 22.249914], + [110.725415, 22.29588], + [110.759292, 22.274837], + [110.787009, 22.28259], + [110.749437, 22.329653], + [110.74143, 22.361757], + [110.711249, 22.369506], + [110.712481, 22.440879], + [110.688459, 22.477935], + [110.74143, 22.464109], + [110.740198, 22.498947], + [110.762988, 22.518298], + [110.749437, 22.556991], + [110.778386, 22.585174], + [110.812263, 22.576333], + [110.897878, 22.591805], + [110.896031, 22.613352], + [110.950233, 22.61059], + [110.958856, 22.636553], + [110.997045, 22.631582], + [111.055559, 22.648705], + [111.089435, 22.695643], + [111.058023, 22.729871], + [111.118385, 22.744773], + [111.185522, 22.735942], + [111.218167, 22.748085], + [111.358601, 22.889301], + [111.374615, 22.938361], + [111.362913, 22.967568], + [111.403565, 22.99126], + [111.389398, 23.005583], + [111.433746, 23.036428], + [111.43313, 23.073322], + [111.402333, 23.066165], + [111.377695, 23.082132], + [111.365992, 23.14488], + [111.38447, 23.16744], + [111.388782, 23.210349], + [111.36476, 23.240047], + [111.353058, 23.284582], + [111.376463, 23.30437], + [111.363528, 23.340641], + [111.389398, 23.375804], + [111.383239, 23.399423], + [111.399869, 23.469159], + [111.428818, 23.466414], + [111.479941, 23.532822], + [111.487332, 23.626615], + [111.555702, 23.64087], + [111.615448, 23.639225], + [111.614832, 23.65896], + [111.666571, 23.718696], + [111.621607, 23.725819], + [111.627766, 23.78881], + [111.654868, 23.833159], + [111.683201, 23.822758], + [111.683201, 23.822758], + [111.722621, 23.823305], + [111.8107, 23.80688], + [111.824867, 23.832612], + [111.812548, 23.887343], + [111.845809, 23.904305], + [111.854432, 23.947521], + [111.911714, 23.943693], + [111.940664, 23.987989], + [111.92157, 24.012045], + [111.878454, 24.109862], + [111.886461, 24.163929], + [111.871062, 24.176487], + [111.877222, 24.227252], + [111.912946, 24.221795], + [111.958526, 24.263813], + [111.986243, 24.25672], + [111.990555, 24.279634], + [112.026279, 24.294908], + [112.05954, 24.339628], + [112.057692, 24.387057], + [112.025047, 24.438828], + [111.985011, 24.467701], + [112.009649, 24.503103], + [112.007185, 24.534684], + [111.972077, 24.578775], + [111.936968, 24.595645], + [111.927729, 24.629378], + [111.953598, 24.64733], + [111.939432, 24.686487], + [111.961606, 24.721283], + [112.024431, 24.740308], + [111.951135, 24.769655], + [111.929577, 24.75607], + [111.875374, 24.756613], + [111.868599, 24.771829], + [111.814396, 24.770199], + [111.783599, 24.785957], + [111.708455, 24.788673], + [111.666571, 24.760961], + [111.637621, 24.715303], + [111.641933, 24.684856], + [111.588962, 24.690837], + [111.570484, 24.64461], + [111.526752, 24.637538], + [111.499035, 24.667997], + [111.451608, 24.665822], + [111.431282, 24.687574], + [111.461463, 24.728894], + [111.479325, 24.797366], + [111.449144, 24.857113], + [111.447296, 24.892947], + [111.470086, 24.92877], + [111.434977, 24.951562], + [111.43313, 24.979774], + [111.460231, 24.992793], + [111.467622, 25.02208], + [111.416499, 25.047566], + [111.435593, 25.093642], + [111.375231, 25.128324], + [111.36784, 25.108817], + [111.321645, 25.105023], + [111.274833, 25.151078], + [111.221862, 25.106649], + [111.200921, 25.074672], + [111.139943, 25.042144], + [111.101754, 25.035095], + [111.100522, 24.945593], + [111.009363, 24.921172], + [110.968711, 24.975434], + [110.951465, 25.04377], + [110.98411, 25.101772], + [110.998892, 25.161371], + [111.112841, 25.21715], + [111.103602, 25.285351], + [111.138711, 25.303748], + [111.184906, 25.367034], + [111.210776, 25.363248], + [111.279145, 25.42326], + [111.32842, 25.521592], + [111.324724, 25.564249], + [111.343202, 25.602574], + [111.309942, 25.645203], + [111.30871, 25.720171], + [111.399869, 25.744431], + [111.442369, 25.77192], + [111.43313, 25.84627], + [111.4861, 25.859196], + [111.460231, 25.885042], + [111.383239, 25.881812], + [111.376463, 25.906039], + [111.346282, 25.906577], + [111.297007, 25.874274], + [111.29208, 25.854349], + [111.251428, 25.864581], + [111.230486, 25.916267], + [111.189834, 25.953402], + [111.235413, 26.048071], + [111.267442, 26.058824], + [111.244652, 26.078177], + [111.26621, 26.095914], + [111.258203, 26.151796], + [111.274833, 26.183486], + [111.271754, 26.217316], + [111.293311, 26.222148], + [111.277913, 26.272066], + [111.228022, 26.261333], + [111.204616, 26.276359], + [111.208928, 26.30426], + [111.090667, 26.308016], + [111.008132, 26.336982], + [111.008747, 26.35897], + [110.974255, 26.385778], + [110.94469, 26.373447], + [110.944074, 26.326791], + [110.926212, 26.320354], + [110.939762, 26.286554], + [110.836284, 26.255966], + [110.759292, 26.248451], + [110.73527, 26.270993], + [110.742046, 26.313917], + [110.721104, 26.294066], + [110.673676, 26.317135], + [110.643495, 26.308552], + [110.612083, 26.333764], + [110.584365, 26.296749], + [110.552952, 26.283335], + [110.546793, 26.233421], + [110.495054, 26.166299], + [110.477808, 26.179727], + [110.437772, 26.153945], + [110.373098, 26.088927], + [110.325671, 25.975462], + [110.257301, 25.961473], + [110.24991, 26.010965], + [110.181541, 26.060437], + [110.168606, 26.028713], + [110.100853, 26.020108], + [110.065128, 26.050221], + [110.100853, 26.132455], + [110.099005, 26.168985], + [110.03002, 26.166299], + [109.970274, 26.195301], + [109.904368, 26.135679], + [109.898825, 26.095377], + [109.864332, 26.027637], + [109.814441, 26.041081], + [109.782412, 25.996981], + [109.806434, 25.973848], + [109.826144, 25.911422], + [109.811361, 25.877504], + [109.779333, 25.866196], + [109.768246, 25.890427], + [109.685094, 25.880197], + [109.67955, 25.921649], + [109.693717, 25.959321], + [109.710963, 25.954478], + [109.730057, 25.989988], + [109.649369, 26.016882], + [109.635203, 26.047533], + [109.588391, 26.019571], + [109.560058, 26.021184], + [109.513247, 25.998056], + [109.48245, 26.029788] + ] + ], + [ + [ + [105.096346, 24.928228], + [105.09573, 24.92877], + [105.077868, 24.918459], + [105.082179, 24.915745], + [105.096346, 24.928228] + ] + ], + [ + [ + [109.088249, 21.014934], + [109.11227, 21.02499], + [109.117814, 21.017727], + [109.144299, 21.041189], + [109.138756, 21.067439], + [109.09256, 21.057386], + [109.088865, 21.031134], + [109.088249, 21.014934] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 460000, + "name": "海南省", + "center": [110.33119, 20.031971], + "centroid": [109.754859, 19.189767], + "childrenNum": 19, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 20, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [110.106396, 20.026812], + [110.042339, 19.991384], + [109.997375, 19.980136], + [109.965346, 19.993634], + [109.898825, 19.994196], + [109.855093, 19.984073], + [109.814441, 19.993072], + [109.76147, 19.981261], + [109.712195, 20.017253], + [109.657993, 20.01163], + [109.585312, 19.98801], + [109.526797, 19.943573], + [109.498464, 19.873236], + [109.411001, 19.895184], + [109.349407, 19.898561], + [109.300748, 19.917693], + [109.25948, 19.898561], + [109.255784, 19.867045], + [109.231147, 19.863105], + [109.159082, 19.79048], + [109.169553, 19.736411], + [109.147379, 19.704863], + [109.093792, 19.68965], + [109.048829, 19.619764], + [108.993394, 19.587065], + [108.92872, 19.524468], + [108.855424, 19.469182], + [108.806148, 19.450561], + [108.765496, 19.400894], + [108.694047, 19.387346], + [108.644772, 19.349518], + [108.609048, 19.276661], + [108.591186, 19.141592], + [108.598577, 19.055633], + [108.630606, 19.003017], + [108.637997, 18.924346], + [108.595497, 18.872256], + [108.593033, 18.809386], + [108.65278, 18.740258], + [108.663866, 18.67337], + [108.641077, 18.565614], + [108.644772, 18.486738], + [108.68912, 18.447571], + [108.776583, 18.441894], + [108.881293, 18.416344], + [108.905315, 18.389087], + [108.944735, 18.314107], + [109.006329, 18.323198], + [109.108575, 18.323766], + [109.138756, 18.268081], + [109.17448, 18.260125], + [109.287813, 18.264671], + [109.355566, 18.215221], + [109.441182, 18.199303], + [109.467051, 18.173718], + [109.527413, 18.169169], + [109.584696, 18.143579], + [109.661688, 18.175424], + [109.726362, 18.177698], + [109.749767, 18.193618], + [109.785492, 18.339672], + [109.919767, 18.375457], + [110.022629, 18.360121], + [110.070672, 18.376025], + [110.090382, 18.399309], + [110.116867, 18.506602], + [110.214186, 18.578662], + [110.246215, 18.609859], + [110.329366, 18.642185], + [110.367555, 18.631977], + [110.499366, 18.651824], + [110.499366, 18.751592], + [110.578206, 18.784458], + [110.590525, 18.838841], + [110.585597, 18.88075], + [110.619474, 19.152334], + [110.676756, 19.286264], + [110.706321, 19.320153], + [110.729727, 19.378878], + [110.787009, 19.399765], + [110.844292, 19.449996], + [110.888023, 19.518827], + [110.920668, 19.552668], + [111.008747, 19.60398], + [111.061718, 19.612436], + [111.071573, 19.628784], + [111.043856, 19.763448], + [111.013675, 19.850159], + [110.966248, 20.018377], + [110.940994, 20.028499], + [110.871393, 20.01163], + [110.808567, 20.035808], + [110.778386, 20.068415], + [110.744509, 20.074036], + [110.717408, 20.148778], + [110.687843, 20.163947], + [110.655814, 20.134169], + [110.562191, 20.110006], + [110.526467, 20.07516], + [110.495054, 20.077408], + [110.387265, 20.113378], + [110.318279, 20.108882], + [110.28933, 20.056047], + [110.243135, 20.077408], + [110.144585, 20.074598], + [110.106396, 20.026812] + ] + ], + [ + [ + [112.208597, 3.876129], + [112.241858, 3.845677], + [112.280046, 3.86777], + [112.260336, 3.917925], + [112.219068, 3.908969], + [112.208597, 3.876129] + ] + ], + [ + [ + [113.266165, 8.125929], + [113.311129, 8.177469], + [113.343157, 8.193463], + [113.288955, 8.119412], + [113.349933, 8.172137], + [113.386273, 8.238479], + [113.386273, 8.289412], + [113.354244, 8.304217], + [113.353628, 8.237887], + [113.293882, 8.176284], + [113.266165, 8.125929] + ] + ], + [ + [ + [111.99733, 3.848065], + [112.015192, 3.823583], + [112.064467, 3.830152], + [112.073707, 3.865979], + [112.03367, 3.892251], + [111.99733, 3.848065] + ] + ], + [ + [ + [111.463311, 17.077491], + [111.536607, 17.104949], + [111.4861, 17.058039], + [111.559397, 17.087788], + [111.542151, 17.11982], + [111.452224, 17.092936], + [111.463311, 17.077491] + ] + ], + [ + [ + [117.708319, 15.182712], + [117.712631, 15.118592], + [117.726798, 15.105303], + [117.827812, 15.111659], + [117.72495, 15.131302], + [117.720638, 15.195418], + [117.74466, 15.217941], + [117.784696, 15.16885], + [117.838899, 15.15903], + [117.782848, 15.187333], + [117.748355, 15.230068], + [117.715095, 15.222561], + [117.708319, 15.182712] + ] + ], + [ + [ + [112.241858, 3.942404], + [112.292365, 3.946583], + [112.288053, 3.97345], + [112.254177, 3.97942], + [112.241858, 3.942404] + ] + ], + [ + [ + [111.734324, 16.19732], + [111.779903, 16.19732], + [111.81686, 16.224329], + [111.813164, 16.261676], + [111.782367, 16.273741], + [111.716462, 16.249036], + [111.789758, 16.250186], + [111.790374, 16.220307], + [111.734324, 16.19732] + ] + ], + [ + [ + [111.649324, 16.255931], + [111.577875, 16.208239], + [111.56802, 16.162834], + [111.611136, 16.156511], + [111.690592, 16.211112], + [111.606825, 16.177779], + [111.598817, 16.198469], + [111.681353, 16.262251], + [111.649324, 16.255931] + ] + ], + [ + [ + [113.896887, 7.607204], + [113.919677, 7.566865], + [113.98743, 7.536014], + [114.058879, 7.537794], + [114.157429, 7.561525], + [114.289856, 7.617288], + [114.368696, 7.638642], + [114.407501, 7.683126], + [114.419819, 7.765557], + [114.464167, 7.814771], + [114.540543, 7.862201], + [114.555326, 7.891249], + [114.540543, 7.945783], + [114.511594, 7.966527], + [114.47279, 7.968898], + [114.414892, 7.952895], + [114.268298, 7.870501], + [114.211632, 7.786904], + [114.095219, 7.721082], + [114.029314, 7.670078], + [113.921524, 7.639235], + [113.896887, 7.607204] + ] + ], + [ + [ + [113.976959, 8.872888], + [114.013299, 8.836817], + [114.035473, 8.783591], + [114.060111, 8.816119], + [114.041017, 8.843913], + [113.989894, 8.878801], + [113.976959, 8.872888] + ] + ], + [ + [ + [113.956017, 8.840365], + [113.975111, 8.793054], + [114.012068, 8.798376], + [113.977575, 8.841548], + [113.956017, 8.840365] + ] + ], + [ + [ + [111.97454, 16.323715], + [112.002258, 16.306484], + [112.07617, 16.323715], + [112.074938, 16.349558], + [112.047221, 16.360469], + [112.002874, 16.350707], + [111.97454, 16.323715] + ] + ], + [ + [ + [111.739251, 16.452898], + [111.766969, 16.470116], + [111.786679, 16.520039], + [111.759577, 16.545857], + [111.765737, 16.495366], + [111.739251, 16.452898] + ] + ], + [ + [ + [112.216604, 8.866383], + [112.206133, 8.88767], + [112.180264, 8.862244], + [112.216604, 8.866383] + ] + ], + [ + [ + [113.792177, 7.373422], + [113.828518, 7.362145], + [113.829134, 7.383511], + [113.792177, 7.373422] + ] + ], + [ + [ + [114.194386, 8.764664], + [114.201161, 8.727991], + [114.248588, 8.724442], + [114.222103, 8.784773], + [114.194386, 8.764664] + ] + ], + [ + [ + [112.232619, 16.996239], + [112.207981, 16.987081], + [112.222764, 16.960751], + [112.292981, 16.96762], + [112.266496, 16.993949], + [112.232619, 16.996239] + ] + ], + [ + [ + [114.689601, 10.345648], + [114.702536, 10.312677], + [114.725941, 10.319154], + [114.747499, 10.37214], + [114.717318, 10.380381], + [114.689601, 10.345648] + ] + ], + [ + [ + [115.837712, 9.709775], + [115.861117, 9.694438], + [115.867277, 9.650191], + [115.901153, 9.67084], + [115.925791, 9.781734], + [115.901153, 9.795888], + [115.870972, 9.778785], + [115.837712, 9.709775] + ] + ], + [ + [ + [114.617536, 9.965688], + [114.642173, 9.917351], + [114.672355, 9.927963], + [114.685905, 9.979245], + [114.617536, 9.965688] + ] + ], + [ + [ + [113.769387, 7.636862], + [113.773699, 7.601865], + [113.814967, 7.603051], + [113.831597, 7.644573], + [113.769387, 7.636862] + ] + ], + [ + [ + [109.463972, 7.344339], + [109.463972, 7.315254], + [109.513247, 7.320002], + [109.571761, 7.373422], + [109.654297, 7.479648], + [109.709115, 7.511095], + [109.791651, 7.524742], + [109.938861, 7.504569], + [109.948716, 7.522962], + [109.904984, 7.55144], + [109.816289, 7.572797], + [109.72205, 7.575763], + [109.653065, 7.559745], + [109.536037, 7.448792], + [109.463972, 7.344339] + ] + ], + [ + [ + [116.273181, 8.879392], + [116.294123, 8.858105], + [116.332311, 8.901269], + [116.305826, 8.917233], + [116.273181, 8.879392] + ] + ], + [ + [ + [112.476531, 16.001247], + [112.570154, 16.011027], + [112.612037, 16.039212], + [112.588016, 16.070844], + [112.462364, 16.043813], + [112.448814, 16.005274], + [112.476531, 16.001247] + ] + ], + [ + [ + [112.537509, 8.846278], + [112.57077, 8.815527], + [112.639755, 8.818484], + [112.598487, 8.859288], + [112.537509, 8.846278] + ] + ], + [ + [ + [114.469095, 10.836261], + [114.475254, 10.814512], + [114.513442, 10.848605], + [114.565181, 10.836261], + [114.593514, 10.856245], + [114.587355, 10.909138], + [114.55471, 10.900911], + [114.469095, 10.836261] + ] + ], + [ + [ + [112.409393, 16.294996], + [112.383524, 16.265698], + [112.411241, 16.2634], + [112.475915, 16.288677], + [112.531349, 16.285805], + [112.536893, 16.312228], + [112.509176, 16.317397], + [112.409393, 16.294996] + ] + ], + [ + [ + [116.48876, 10.395686], + [116.461658, 10.34918], + [116.467202, 10.309144], + [116.511549, 10.297957], + [116.566368, 10.304434], + [116.644592, 10.335051], + [116.637817, 10.365076], + [116.514629, 10.34918], + [116.542346, 10.41982], + [116.526332, 10.426883], + [116.48876, 10.395686] + ] + ], + [ + [ + [112.349031, 16.912088], + [112.360734, 16.925257], + [112.334249, 16.962469], + [112.30222, 16.963041], + [112.349031, 16.912088] + ] + ], + [ + [ + [111.500267, 16.45175], + [111.49534, 16.4374], + [111.545847, 16.43453], + [111.538455, 16.461507], + [111.500267, 16.45175] + ] + ], + [ + [ + [115.500177, 9.897897], + [115.54822, 9.869007], + [115.585177, 9.896128], + [115.581481, 9.917351], + [115.518039, 9.933857], + [115.500177, 9.897897] + ] + ], + [ + [ + [114.669891, 8.210048], + [114.691449, 8.18517], + [114.74134, 8.189316], + [114.726557, 8.21064], + [114.669891, 8.210048] + ] + ], + [ + [ + [114.507899, 8.120004], + [114.530073, 8.103415], + [114.595978, 8.120596], + [114.624311, 8.149626], + [114.595978, 8.15792], + [114.507899, 8.120004] + ] + ], + [ + [ + [115.16757, 8.386523], + [115.18112, 8.345668], + [115.235939, 8.321982], + [115.285214, 8.314876], + [115.315395, 8.356326], + [115.299381, 8.370537], + [115.202678, 8.395403], + [115.16757, 8.386523] + ] + ], + [ + [ + [113.895039, 8.00505], + [113.904894, 7.963564], + [113.9708, 7.944597], + [113.969568, 7.974825], + [113.940003, 8.018088], + [113.895039, 8.00505] + ] + ], + [ + [ + [115.436119, 9.393447], + [115.450286, 9.345028], + [115.469996, 9.3592], + [115.456445, 9.417064], + [115.436119, 9.393447] + ] + ], + [ + [ + [116.457347, 9.174326], + [116.477057, 9.137103], + [116.500462, 9.164282], + [116.457347, 9.174326] + ] + ], + [ + [ + [113.638192, 8.976942], + [113.654823, 8.962163], + [113.730583, 9.004133], + [113.719496, 9.020092], + [113.644968, 8.989355], + [113.638192, 8.976942] + ] + ], + [ + [ + [114.696992, 11.004322], + [114.710543, 11.001972], + [114.793079, 11.07657], + [114.799854, 11.10476], + [114.766593, 11.110045], + [114.710543, 11.039567], + [114.696992, 11.004322] + ] + ], + [ + [ + [114.62, 11.432264], + [114.652644, 11.436957], + [114.661884, 11.522584], + [114.621232, 11.518479], + [114.62, 11.432264] + ] + ], + [ + [ + [114.910723, 10.863298], + [114.931049, 10.841551], + [114.959998, 10.902087], + [114.934129, 10.902674], + [114.910723, 10.863298] + ] + ], + [ + [ + [111.572948, 16.470116], + [111.578491, 16.447158], + [111.614216, 16.44027], + [111.592658, 16.490775], + [111.572948, 16.470116] + ] + ], + [ + [ + [113.939387, 8.875253], + [113.912285, 8.888853], + [113.893807, 8.862836], + [113.916597, 8.837999], + [113.939387, 8.875253] + ] + ], + [ + [ + [109.936397, 7.848566], + [109.936397, 7.823665], + [109.988136, 7.8124], + [110.050346, 7.846194], + [110.082991, 7.896584], + [110.078063, 7.949339], + [110.0331, 7.944597], + [109.953027, 7.888878], + [109.936397, 7.848566] + ] + ], + [ + [ + [116.727128, 11.501473], + [116.765316, 11.430504], + [116.772092, 11.445755], + [116.738215, 11.514961], + [116.727128, 11.501473] + ] + ], + [ + [ + [111.690592, 16.587731], + [111.724469, 16.560198], + [111.717078, 16.59404], + [111.690592, 16.587731] + ] + ], + [ + [ + [112.507328, 16.466098], + [112.586784, 16.525777], + [112.575081, 16.537251], + [112.499321, 16.493645], + [112.507328, 16.466098] + ] + ], + [ + [ + [111.761425, 16.061642], + [111.791606, 16.028859], + [111.828563, 16.049565], + [111.829795, 16.070844], + [111.761425, 16.061642] + ] + ], + [ + [ + [113.845764, 10.018733], + [113.865474, 10.00341], + [113.872249, 10.123029], + [113.856851, 10.12185], + [113.845764, 10.018733] + ] + ], + [ + [ + [114.791847, 8.160882], + [114.777064, 8.114079], + [114.812173, 8.110524], + [114.818332, 8.141332], + [114.791847, 8.160882] + ] + ], + [ + [ + [116.557129, 9.745167], + [116.566368, 9.718623], + [116.593469, 9.723932], + [116.557129, 9.745167] + ] + ], + [ + [ + [115.28275, 10.191951], + [115.288294, 10.172513], + [115.333257, 10.200198], + [115.28891, 10.211388], + [115.28275, 10.191951] + ] + ], + [ + [ + [116.832454, 10.476908], + [116.855243, 10.468669], + [116.868794, 10.495739], + [116.832454, 10.476908] + ] + ], + [ + [ + [114.703151, 16.170307], + [114.816484, 16.198469], + [114.802934, 16.215135], + [114.704383, 16.199044], + [114.703151, 16.170307] + ] + ], + [ + [ + [115.97753, 9.321997], + [115.926407, 9.311366], + [115.943037, 9.269433], + [115.976298, 9.268252], + [115.999088, 9.293649], + [115.97753, 9.321997] + ] + ], + [ + [ + [113.660366, 9.231039], + [113.676997, 9.202683], + [113.697323, 9.225722], + [113.660366, 9.231039] + ] + ], + [ + [ + [114.665579, 7.590001], + [114.671739, 7.563898], + [114.72163, 7.59178], + [114.703767, 7.614915], + [114.665579, 7.590001] + ] + ], + [ + [ + [114.493116, 10.717504], + [114.513442, 10.722208], + [114.562717, 10.778064], + [114.539312, 10.793349], + [114.493116, 10.717504] + ] + ], + [ + [ + [117.770529, 10.773361], + [117.798862, 10.753371], + [117.835819, 10.803931], + [117.831507, 10.838612], + [117.801942, 10.839788], + [117.775457, 10.809222], + [117.770529, 10.773361] + ] + ], + [ + [ + [114.242429, 10.242014], + [114.263371, 10.239658], + [114.326197, 10.284414], + [114.312646, 10.300901], + [114.265219, 10.275581], + [114.242429, 10.242014] + ] + ], + [ + [ + [114.688985, 11.469217], + [114.722246, 11.429331], + [114.737644, 11.463938], + [114.720398, 11.49209], + [114.688985, 11.469217] + ] + ], + [ + [ + [116.638433, 10.503977], + [116.653215, 10.491031], + [116.70865, 10.492797], + [116.699411, 10.517511], + [116.638433, 10.503977] + ] + ], + [ + [ + [110.459946, 8.116449], + [110.471032, 8.072012], + [110.554184, 8.093935], + [110.599764, 8.156735], + [110.568351, 8.17273], + [110.461793, 8.128298], + [110.459946, 8.116449] + ] + ], + [ + [ + [111.463311, 8.52504], + [111.497187, 8.523857], + [111.509506, 8.550489], + [111.463311, 8.52504] + ] + ], + [ + [ + [115.258113, 8.509652], + [115.271048, 8.477098], + [115.296301, 8.510836], + [115.258113, 8.509652] + ] + ], + [ + [ + [113.221817, 8.073789], + [113.235984, 8.068456], + [113.283411, 8.111117], + [113.269861, 8.120004], + [113.221817, 8.073789] + ] + ], + [ + [ + [114.074893, 10.929118], + [114.064422, 10.904437], + [114.110002, 10.918541], + [114.096451, 10.947921], + [114.074893, 10.929118] + ] + ], + [ + [ + [117.258068, 10.320331], + [117.299336, 10.313855], + [117.299952, 10.343293], + [117.274698, 10.358011], + [117.258068, 10.320331] + ] + ], + [ + [ + [114.212864, 16.040937], + [114.31203, 16.034611], + [114.306487, 16.057616], + [114.268914, 16.059342], + [114.212864, 16.040937] + ] + ], + [ + [ + [110.609003, 8.010976], + [110.642879, 7.989049], + [110.641648, 8.031125], + [110.622553, 8.041199], + [110.609003, 8.010976] + ] + ], + [ + [ + [115.509416, 8.490712], + [115.521735, 8.460523], + [115.55438, 8.461115], + [115.569162, 8.49012], + [115.558691, 8.523265], + [115.514344, 8.519122], + [115.509416, 8.490712] + ] + ], + [ + [ + [111.539071, 7.54432], + [111.542767, 7.524742], + [111.583419, 7.543134], + [111.612368, 7.592374], + [111.566788, 7.606017], + [111.539071, 7.54432] + ] + ], + [ + [ + [111.657947, 8.672974], + [111.665955, 8.622683], + [111.717694, 8.6499], + [111.697368, 8.67889], + [111.657947, 8.672974] + ] + ], + [ + [ + [110.460561, 7.799948], + [110.487663, 7.783346], + [110.511684, 7.805878], + [110.485199, 7.827815], + [110.460561, 7.799948] + ] + ], + [ + [ + [112.345952, 8.926101], + [112.392763, 8.919598], + [112.384756, 8.946793], + [112.345952, 8.926101] + ] + ], + [ + [ + [116.469665, 9.810041], + [116.47952, 9.785272], + [116.50847, 9.79117], + [116.490607, 9.821246], + [116.469665, 9.810041] + ] + ], + [ + [ + [111.925265, 8.070827], + [111.949287, 8.05068], + [111.994866, 8.047125], + [112.018888, 8.065494], + [112.013344, 8.093342], + [111.95483, 8.106377], + [111.925265, 8.070827] + ] + ], + [ + [ + [114.457392, 15.599305], + [114.466631, 15.576823], + [114.491884, 15.59354], + [114.457392, 15.599305] + ] + ], + [ + [ + [114.985252, 11.078332], + [115.013585, 11.063062], + [115.021592, 11.085967], + [114.985252, 11.078332] + ] + ], + [ + [ + [114.10569, 16.004124], + [114.110618, 15.978235], + [114.132176, 16.007575], + [114.10569, 16.004124] + ] + ], + [ + [ + [116.045283, 10.095338], + [116.067457, 10.065876], + [116.09579, 10.09357], + [116.070537, 10.12892], + [116.045283, 10.095338] + ] + ], + [ + [ + [117.266691, 10.69163], + [117.348611, 10.672811], + [117.404661, 10.671047], + [117.418212, 10.702803], + [117.369553, 10.7422], + [117.293176, 10.735144], + [117.266691, 10.69163] + ] + ], + [ + [ + [114.854057, 7.244611], + [114.819564, 7.192957], + [114.869455, 7.198895], + [114.854057, 7.244611] + ] + ], + [ + [ + [112.823305, 8.910729], + [112.859645, 8.889444], + [112.873196, 8.908364], + [112.823305, 8.910729] + ] + ], + [ + [ + [111.670266, 7.651098], + [111.707223, 7.648725], + [111.749722, 7.703884], + [111.726317, 7.729977], + [111.691208, 7.711593], + [111.670266, 7.651098] + ] + ], + [ + [ + [112.207981, 8.835634], + [112.235699, 8.827355], + [112.241242, 8.852783], + [112.207981, 8.835634] + ] + ], + [ + [ + [112.527654, 5.79444], + [112.531965, 5.766455], + [112.562762, 5.75931], + [112.562146, 5.820637], + [112.527654, 5.79444] + ] + ], + [ + [ + [114.599058, 8.846278], + [114.645869, 8.844504], + [114.68221, 8.881166], + [114.665579, 8.900087], + [114.61692, 8.881166], + [114.599058, 8.846278] + ] + ], + [ + [ + [114.868223, 7.983715], + [114.907643, 7.951117], + [114.914419, 8.00742], + [114.883006, 8.011569], + [114.868223, 7.983715] + ] + ], + [ + [ + [112.945261, 8.410204], + [112.985297, 8.429149], + [112.949572, 8.432701], + [112.945261, 8.410204] + ] + ], + [ + [ + [113.600004, 6.961929], + [113.580294, 6.920344], + [113.62341, 6.942325], + [113.600004, 6.961929] + ] + ], + [ + [ + [116.695099, 16.345538], + [116.708034, 16.299591], + [116.738831, 16.303612], + [116.747454, 16.360469], + [116.717889, 16.373676], + [116.695099, 16.345538] + ] + ], + [ + [ + [117.347995, 10.090624], + [117.354154, 10.06293], + [117.385567, 10.063519], + [117.373864, 10.106532], + [117.347995, 10.090624] + ] + ], + [ + [ + [112.993304, 19.472003], + [113.038883, 19.480466], + [113.048123, 19.506417], + [113.029028, 19.52898], + [112.993304, 19.52616], + [112.980369, 19.496263], + [112.993304, 19.472003] + ] + ], + [ + [ + [114.448153, 16.034035], + [114.485109, 16.034611], + [114.521449, 16.056466], + [114.465399, 16.067393], + [114.448153, 16.034035] + ] + ], + [ + [ + [113.832213, 19.158552], + [113.874097, 19.151203], + [113.914749, 19.172119], + [113.920293, 19.223551], + [113.875945, 19.237113], + [113.80696, 19.222986], + [113.799568, 19.19925], + [113.832213, 19.158552] + ] + ], + [ + [ + [112.650842, 5.106941], + [112.655769, 5.055676], + [112.682871, 5.048522], + [112.719211, 5.075944], + [112.678559, 5.121247], + [112.650842, 5.106941] + ] + ], + [ + [ + [111.638853, 7.907254], + [111.665339, 7.887099], + [111.712766, 7.887099], + [111.713382, 7.927408], + [111.651788, 7.932743], + [111.638853, 7.907254] + ] + ], + [ + [ + [112.244322, 8.874662], + [112.281278, 8.855148], + [112.288669, 8.885896], + [112.244322, 8.874662] + ] + ], + [ + [ + [112.89229, 7.844416], + [112.929862, 7.827815], + [112.93171, 7.867537], + [112.89229, 7.844416] + ] + ], + [ + [ + [112.583088, 5.56159], + [112.606494, 5.51751], + [112.614501, 5.465683], + [112.642834, 5.489512], + [112.616349, 5.568737], + [112.583088, 5.56159] + ] + ], + [ + [ + [112.523342, 5.656289], + [112.5449, 5.616386], + [112.565842, 5.63068], + [112.56153, 5.677133], + [112.528886, 5.687257], + [112.523342, 5.656289] + ] + ], + [ + [ + [115.361591, 13.948985], + [115.397315, 13.92517], + [115.438583, 13.943757], + [115.423185, 13.977443], + [115.377605, 13.968732], + [115.361591, 13.948985] + ] + ], + [ + [ + [113.596924, 10.240836], + [113.617866, 10.22199], + [113.638192, 10.243192], + [113.596924, 10.240836] + ] + ], + [ + [ + [113.860546, 15.477068], + [113.893807, 15.463802], + [113.890112, 15.490909], + [113.860546, 15.477068] + ] + ], + [ + [ + [112.907072, 4.993079], + [112.943413, 4.991887], + [112.952652, 5.047926], + [112.910768, 5.038388], + [112.907072, 4.993079] + ] + ], + [ + [ + [112.557219, 5.109326], + [112.568922, 5.071771], + [112.610806, 5.091443], + [112.601567, 5.120055], + [112.557219, 5.109326] + ] + ], + [ + [ + [112.350263, 5.621747], + [112.385988, 5.615791], + [112.385372, 5.643187], + [112.350263, 5.621747] + ] + ], + [ + [ + [112.226459, 16.759147], + [112.254177, 16.751698], + [112.262184, 16.778057], + [112.211061, 16.795819], + [112.226459, 16.759147] + ] + ], + [ + [ + [112.233851, 15.69612], + [112.25972, 15.734718], + [112.240626, 15.741055], + [112.20367, 15.71398], + [112.233851, 15.69612] + ] + ], + [ + [ + [112.612037, 5.367973], + [112.640371, 5.347715], + [112.685334, 5.371548], + [112.690878, 5.406702], + [112.62374, 5.401935], + [112.612037, 5.367973] + ] + ], + [ + [ + [112.472219, 5.73966], + [112.496857, 5.736683], + [112.498089, 5.775387], + [112.472219, 5.73966] + ] + ], + [ + [ + [113.217506, 6.306249], + [113.230441, 6.285429], + [113.243991, 6.325878], + [113.217506, 6.306249] + ] + ], + [ + [ + [116.152457, 9.579384], + [116.189413, 9.565221], + [116.187565, 9.595317], + [116.152457, 9.579384] + ] + ], + [ + [ + [114.948911, 7.508722], + [114.960614, 7.484988], + [115.012353, 7.484988], + [115.013585, 7.525928], + [114.948911, 7.508722] + ] + ], + [ + [ + [111.553854, 7.807656], + [111.585267, 7.771487], + [111.619759, 7.840265], + [111.603745, 7.861608], + [111.553854, 7.807656] + ] + ], + [ + [ + [113.938771, 15.8355], + [113.973263, 15.805558], + [113.9708, 15.83953], + [113.938771, 15.8355] + ] + ], + [ + [ + [114.926122, 16.036911], + [114.895325, 16.036336], + [114.910723, 16.001823], + [114.926122, 16.036911] + ] + ], + [ + [ + [116.749302, 9.056736], + [116.699411, 9.049053], + [116.70865, 9.024229], + [116.740679, 9.028367], + [116.749302, 9.056736] + ] + ], + [ + [ + [112.64653, 16.385733], + [112.681639, 16.400661], + [112.660081, 16.426494], + [112.64653, 16.385733] + ] + ], + [ + [ + [111.203384, 19.92557], + [111.203384, 19.925007], + [111.204, 19.92557], + [111.204, 19.926132], + [111.203384, 19.92557] + ] + ], + [ + [ + [115.758256, 10.461018], + [115.776118, 10.434534], + [115.801987, 10.463372], + [115.758256, 10.461018] + ] + ], + [ + [ + [117.21372, 10.735144], + [117.187235, 10.741612], + [117.206945, 10.707507], + [117.21372, 10.735144] + ] + ], + [ + [ + [112.671784, 16.331755], + [112.701349, 16.331755], + [112.677943, 16.35932], + [112.671784, 16.331755] + ] + ], + [ + [ + [115.782277, 10.541046], + [115.795212, 10.499858], + [115.805067, 10.524571], + [115.782277, 10.541046] + ] + ], + [ + [ + [112.512255, 9.544566], + [112.50856, 9.525679], + [112.568922, 9.516826], + [112.567074, 9.554008], + [112.512255, 9.544566] + ] + ], + [ + [ + [114.610145, 15.649447], + [114.581195, 15.625242], + [114.610761, 15.615444], + [114.610145, 15.649447] + ] + ], + [ + [ + [117.299336, 11.077745], + [117.264227, 11.063062], + [117.284553, 11.02547], + [117.304263, 11.027232], + [117.299336, 11.077745] + ] + ], + [ + [ + [117.691073, 11.048965], + [117.653501, 11.046029], + [117.655965, 11.024882], + [117.690457, 11.016658], + [117.691073, 11.048965] + ] + ], + [ + [ + [114.166668, 9.38459], + [114.175291, 9.342075], + [114.195617, 9.350933], + [114.194386, 9.391676], + [114.166668, 9.38459] + ] + ], + [ + [ + [114.714854, 9.736909], + [114.693296, 9.741038], + [114.680978, 9.707416], + [114.704999, 9.700337], + [114.714854, 9.736909] + ] + ], + [ + [ + [112.554139, 5.97839], + [112.553523, 5.942676], + [112.575697, 5.971247], + [112.554139, 5.97839] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 500000, + "name": "重庆市", + "center": [106.504962, 29.533155], + "centroid": [107.8839, 30.067297], + "childrenNum": 38, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 21, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [106.37442, 28.525742], + [106.403369, 28.569901], + [106.477282, 28.530474], + [106.504999, 28.544669], + [106.466811, 28.586193], + [106.49268, 28.591448], + [106.502535, 28.661313], + [106.528405, 28.677591], + [106.492064, 28.742153], + [106.461883, 28.761041], + [106.45326, 28.817162], + [106.474202, 28.832891], + [106.561666, 28.756319], + [106.56105, 28.719062], + [106.587535, 28.691767], + [106.6171, 28.691242], + [106.617716, 28.66709], + [106.651593, 28.649235], + [106.618332, 28.645033], + [106.63681, 28.622972], + [106.606629, 28.593024], + [106.615252, 28.549401], + [106.567825, 28.523638], + [106.564745, 28.485247], + [106.632499, 28.503655], + [106.697788, 28.47683], + [106.708259, 28.450524], + [106.747063, 28.467361], + [106.726121, 28.51838], + [106.73844, 28.554657], + [106.77786, 28.563068], + [106.756918, 28.607211], + [106.784636, 28.626649], + [106.807425, 28.589346], + [106.830831, 28.623497], + [106.866556, 28.624548], + [106.889345, 28.695966], + [106.86594, 28.690192], + [106.824056, 28.756319], + [106.845614, 28.780975], + [106.872099, 28.777304], + [106.923222, 28.809821], + [106.951555, 28.766812], + [106.988512, 28.776254], + [106.983584, 28.851239], + [107.019308, 28.861722], + [107.016229, 28.882685], + [107.14188, 28.887925], + [107.206554, 28.868535], + [107.194851, 28.838134], + [107.227496, 28.836037], + [107.210866, 28.817686], + [107.219489, 28.772582], + [107.24659, 28.76209], + [107.261373, 28.792514], + [107.327894, 28.810869], + [107.339597, 28.845997], + [107.383945, 28.848618], + [107.41351, 28.911502], + [107.441227, 28.943977], + [107.412894, 28.960211], + [107.396879, 28.993718], + [107.364235, 29.00942], + [107.395647, 29.041341], + [107.369778, 29.091558], + [107.412278, 29.094696], + [107.427676, 29.128682], + [107.408582, 29.138091], + [107.401807, 29.184603], + [107.441227, 29.203934], + [107.486806, 29.174153], + [107.570574, 29.218037], + [107.589052, 29.150113], + [107.605683, 29.164747], + [107.659885, 29.162656], + [107.700537, 29.141228], + [107.749197, 29.199754], + [107.810791, 29.139137], + [107.784921, 29.048143], + [107.823725, 29.034016], + [107.810175, 28.984295], + [107.867457, 28.960211], + [107.882855, 29.00628], + [107.908725, 29.007327], + [107.925971, 29.032446], + [108.026369, 29.039772], + [108.070717, 29.086328], + [108.150173, 29.053375], + [108.193289, 29.072207], + [108.256115, 29.040295], + [108.277673, 29.091558], + [108.306622, 29.079006], + [108.297999, 29.045527], + [108.319556, 28.961258], + [108.345426, 28.943453], + [108.357745, 28.893165], + [108.346658, 28.859625], + [108.352817, 28.815589], + [108.386078, 28.803003], + [108.385462, 28.772058], + [108.347274, 28.736381], + [108.332491, 28.679166], + [108.439049, 28.634003], + [108.501258, 28.626649], + [108.50249, 28.63768], + [108.575787, 28.659738], + [108.636149, 28.621396], + [108.604736, 28.590922], + [108.610896, 28.539412], + [108.573939, 28.531], + [108.586874, 28.463678], + [108.609664, 28.43579], + [108.609048, 28.407368], + [108.576403, 28.38631], + [108.580099, 28.343128], + [108.611512, 28.324691], + [108.667562, 28.334173], + [108.656475, 28.359981], + [108.697127, 28.401051], + [108.688504, 28.422106], + [108.640461, 28.456838], + [108.657091, 28.47683], + [108.700207, 28.48209], + [108.709446, 28.501026], + [108.746402, 28.45105], + [108.780279, 28.42579], + [108.759953, 28.389995], + [108.783359, 28.380518], + [108.761801, 28.304143], + [108.726692, 28.282011], + [108.738395, 28.228241], + [108.772888, 28.212949], + [108.821547, 28.245113], + [108.855424, 28.199764], + [108.89546, 28.219804], + [108.923793, 28.217167], + [108.929952, 28.19027], + [109.005713, 28.162837], + [109.026655, 28.220331], + [109.086401, 28.184467], + [109.101799, 28.202401], + [109.081473, 28.247749], + [109.117198, 28.277795], + [109.152306, 28.349975], + [109.153538, 28.417369], + [109.191726, 28.471043], + [109.23361, 28.474726], + [109.274262, 28.494714], + [109.273646, 28.53836], + [109.319842, 28.579886], + [109.306907, 28.62087], + [109.252089, 28.606685], + [109.235458, 28.61982], + [109.201581, 28.597753], + [109.192958, 28.636104], + [109.271183, 28.671816], + [109.252704, 28.691767], + [109.294588, 28.722211], + [109.2989, 28.7474], + [109.241002, 28.776779], + [109.246545, 28.80143], + [109.235458, 28.882161], + [109.261328, 28.952356], + [109.292741, 28.987436], + [109.294588, 29.015177], + [109.319842, 29.042388], + [109.312451, 29.066453], + [109.240386, 29.086328], + [109.232378, 29.119271], + [109.215748, 29.145409], + [109.162777, 29.180946], + [109.139372, 29.168927], + [109.110422, 29.21647], + [109.141835, 29.270256], + [109.106727, 29.288526], + [109.11227, 29.361053], + [109.060531, 29.403292], + [109.034662, 29.360531], + [108.999553, 29.36366], + [108.983539, 29.332883], + [108.919481, 29.3261], + [108.934264, 29.399643], + [108.927488, 29.435612], + [108.884373, 29.440824], + [108.866511, 29.470527], + [108.888684, 29.502305], + [108.878213, 29.539279], + [108.913322, 29.574679], + [108.901003, 29.604863], + [108.870206, 29.596537], + [108.888068, 29.628795], + [108.844337, 29.658443], + [108.781511, 29.635558], + [108.797525, 29.660003], + [108.786438, 29.691721], + [108.752562, 29.649082], + [108.690968, 29.689642], + [108.676801, 29.749412], + [108.680497, 29.800319], + [108.658939, 29.854833], + [108.601041, 29.863656], + [108.556077, 29.818493], + [108.52528, 29.770713], + [108.548686, 29.749412], + [108.504954, 29.728626], + [108.504338, 29.707836], + [108.460606, 29.741098], + [108.437201, 29.741098], + [108.442744, 29.778505], + [108.422418, 29.772791], + [108.424266, 29.815897], + [108.371295, 29.841337], + [108.433505, 29.880262], + [108.467998, 29.864175], + [108.516041, 29.885451], + [108.517889, 29.9394], + [108.536367, 29.983472], + [108.532055, 30.051873], + [108.513577, 30.057571], + [108.546222, 30.104178], + [108.56778, 30.157491], + [108.551766, 30.1637], + [108.581947, 30.255759], + [108.54499, 30.269716], + [108.524048, 30.309506], + [108.501258, 30.314673], + [108.460606, 30.35961], + [108.431041, 30.354446], + [108.402092, 30.376649], + [108.430425, 30.416397], + [108.411331, 30.438586], + [108.42673, 30.492233], + [108.472925, 30.487076], + [108.512961, 30.501515], + [108.556077, 30.487592], + [108.56778, 30.468508], + [108.6497, 30.53915], + [108.642925, 30.578831], + [108.688504, 30.58759], + [108.698975, 30.54482], + [108.743939, 30.494812], + [108.789518, 30.513374], + [108.808612, 30.491202], + [108.838793, 30.503062], + [108.893612, 30.565434], + [108.971836, 30.627766], + [109.006329, 30.626736], + [109.042669, 30.655571], + [109.071002, 30.640125], + [109.111654, 30.646303], + [109.106111, 30.61077], + [109.105495, 30.585529], + [109.102415, 30.580377], + [109.101183, 30.579346], + [109.106111, 30.570587], + [109.103647, 30.565949], + [109.143683, 30.521108], + [109.191726, 30.545851], + [109.191726, 30.545851], + [109.245313, 30.580892], + [109.299516, 30.630341], + [109.314298, 30.599953], + [109.36111, 30.551004], + [109.337088, 30.521623], + [109.35495, 30.487076], + [109.418392, 30.559766], + [109.435638, 30.595832], + [109.535421, 30.664837], + [109.543428, 30.63961], + [109.574225, 30.646818], + [109.590855, 30.69366], + [109.625348, 30.702923], + [109.661072, 30.738936], + [109.656761, 30.760538], + [109.701724, 30.783677], + [109.780564, 30.848437], + [109.828608, 30.864364], + [109.894513, 30.899803], + [109.943788, 30.878746], + [110.008462, 30.883369], + [110.019549, 30.829425], + [110.048498, 30.800642], + [110.082375, 30.799614], + [110.151976, 30.911613], + [110.153824, 30.953708], + [110.172918, 30.978853], + [110.140889, 30.987062], + [110.140273, 31.030661], + [110.120563, 31.0322], + [110.119947, 31.088592], + [110.147048, 31.116776], + [110.180309, 31.121899], + [110.200019, 31.158779], + [110.180309, 31.179774], + [110.155671, 31.279564], + [110.161831, 31.314338], + [110.118715, 31.409899], + [110.054042, 31.410921], + [110.036795, 31.436966], + [109.98752, 31.474744], + [109.94502, 31.47066], + [109.969658, 31.508935], + [109.894513, 31.519139], + [109.837847, 31.555354], + [109.727594, 31.548214], + [109.745456, 31.598182], + [109.76455, 31.602769], + [109.737449, 31.628761], + [109.731289, 31.700582], + [109.683246, 31.719929], + [109.622268, 31.711783], + [109.585928, 31.726546], + [109.549587, 31.73011], + [109.502776, 31.716365], + [109.446109, 31.722983], + [109.381436, 31.705165], + [109.281654, 31.716874], + [109.282885, 31.743343], + [109.253936, 31.759628], + [109.279806, 31.776418], + [109.27611, 31.79931], + [109.195422, 31.817618], + [109.191111, 31.85575], + [109.123357, 31.892851], + [109.085785, 31.929428], + [108.986619, 31.980205], + [108.902235, 31.984774], + [108.837561, 32.039072], + [108.78767, 32.04871], + [108.75133, 32.076098], + [108.734084, 32.106519], + [108.676801, 32.10297], + [108.585026, 32.17189], + [108.543758, 32.177969], + [108.509882, 32.201266], + [108.480317, 32.182527], + [108.399013, 32.194176], + [108.370063, 32.172397], + [108.379918, 32.154158], + [108.379918, 32.154158], + [108.379303, 32.153652], + [108.379303, 32.153652], + [108.399628, 32.147065], + [108.452599, 32.090296], + [108.42981, 32.061391], + [108.372527, 32.077112], + [108.344194, 32.067477], + [108.362056, 32.035521], + [108.329411, 32.020299], + [108.370063, 31.988835], + [108.351585, 31.971575], + [108.307238, 31.997463], + [108.259194, 31.967006], + [108.343578, 31.860834], + [108.386078, 31.854226], + [108.391005, 31.829822], + [108.429194, 31.809482], + [108.455063, 31.814059], + [108.462454, 31.780488], + [108.535135, 31.757592], + [108.50557, 31.734182], + [108.514809, 31.693963], + [108.546838, 31.665442], + [108.519121, 31.665952], + [108.468614, 31.636404], + [108.442744, 31.633856], + [108.390389, 31.591555], + [108.386078, 31.544134], + [108.339266, 31.539033], + [108.344194, 31.512506], + [108.254883, 31.49873], + [108.233941, 31.506894], + [108.191441, 31.492096], + [108.193289, 31.467598], + [108.224086, 31.464024], + [108.216079, 31.41041], + [108.153869, 31.371073], + [108.185898, 31.336831], + [108.095354, 31.268311], + [108.038688, 31.252964], + [108.031297, 31.217144], + [108.07626, 31.231985], + [108.089811, 31.204859], + [108.025753, 31.116263], + [108.009123, 31.109602], + [108.026985, 31.061938], + [108.060246, 31.052197], + [108.00358, 31.025533], + [107.983254, 30.983983], + [107.942602, 30.989114], + [107.948145, 30.918802], + [107.994956, 30.908533], + [107.956152, 30.882855], + [107.851443, 30.792931], + [107.788001, 30.81966], + [107.763979, 30.817091], + [107.760899, 30.862823], + [107.739957, 30.884396], + [107.693146, 30.875665], + [107.645103, 30.821202], + [107.57735, 30.847924], + [107.515756, 30.854603], + [107.483111, 30.838675], + [107.498509, 30.809381], + [107.454162, 30.771851], + [107.454162, 30.771851], + [107.424597, 30.74048], + [107.458473, 30.704981], + [107.477567, 30.664837], + [107.516987, 30.644759], + [107.485575, 30.598408], + [107.427676, 30.547397], + [107.443075, 30.53348], + [107.408582, 30.521623], + [107.368546, 30.468508], + [107.338981, 30.386459], + [107.288474, 30.337402], + [107.257677, 30.267131], + [107.221337, 30.213878], + [107.103076, 30.090198], + [107.080286, 30.094341], + [107.084598, 30.063786], + [107.058113, 30.043066], + [107.055649, 30.040476], + [107.054417, 30.040994], + [107.053801, 30.043584], + [107.02054, 30.036849], + [106.981736, 30.08502], + [106.976193, 30.083467], + [106.94478, 30.037367], + [106.913367, 30.025451], + [106.862244, 30.033223], + [106.83699, 30.049801], + [106.825904, 30.03115], + [106.825904, 30.03115], + [106.785252, 30.01716], + [106.732281, 30.027005], + [106.724274, 30.058607], + [106.699636, 30.074145], + [106.700252, 30.111944], + [106.672535, 30.122297], + [106.677462, 30.156974], + [106.631883, 30.186464], + [106.611557, 30.235596], + [106.612173, 30.235596], + [106.611557, 30.235596], + [106.612173, 30.235596], + [106.612173, 30.235596], + [106.612789, 30.235596], + [106.612789, 30.235596], + [106.642354, 30.246454], + [106.611557, 30.292455], + [106.560434, 30.31519], + [106.545035, 30.296589], + [106.49884, 30.295556], + [106.43971, 30.308473], + [106.428623, 30.254725], + [106.401521, 30.242318], + [106.349167, 30.24542], + [106.334384, 30.225772], + [106.306667, 30.238182], + [106.296196, 30.205603], + [106.264167, 30.20974], + [106.260471, 30.19681], + [106.232754, 30.185947], + [106.180399, 30.233011], + [106.168696, 30.303823], + [106.132356, 30.323972], + [106.132972, 30.30279], + [106.07261, 30.333786], + [106.031958, 30.373551], + [105.943263, 30.372002], + [105.900763, 30.405042], + [105.84656, 30.410203], + [105.825618, 30.436006], + [105.792357, 30.427234], + [105.760329, 30.384393], + [105.754785, 30.342567], + [105.714749, 30.322939], + [105.720292, 30.252657], + [105.720292, 30.252657], + [105.670401, 30.254208], + [105.624822, 30.275918], + [105.619894, 30.234045], + [105.662394, 30.210258], + [105.642684, 30.186464], + [105.56138, 30.183878], + [105.550909, 30.179222], + [105.536127, 30.152834], + [105.596489, 30.159043], + [105.574315, 30.130579], + [105.580474, 30.129544], + [105.582938, 30.127474], + [105.582938, 30.12385], + [105.642068, 30.101072], + [105.638988, 30.076216], + [105.676561, 30.06793], + [105.687032, 30.038922], + [105.719677, 30.042548], + [105.753553, 30.018196], + [105.723372, 29.975177], + [105.730763, 29.95755], + [105.70243, 29.924879], + [105.717213, 29.893753], + [105.738771, 29.891159], + [105.707974, 29.840818], + [105.610655, 29.837184], + [105.582938, 29.819013], + [105.574931, 29.744216], + [105.529351, 29.707836], + [105.481924, 29.718232], + [105.476996, 29.674564], + [105.419714, 29.688082], + [105.38091, 29.628275], + [105.347649, 29.621512], + [105.332867, 29.592374], + [105.296526, 29.571035], + [105.305149, 29.53199], + [105.337794, 29.459064], + [105.334099, 29.441345], + [105.387069, 29.455416], + [105.387069, 29.455416], + [105.399388, 29.43874], + [105.372903, 29.421018], + [105.426489, 29.419454], + [105.441888, 29.400686], + [105.418482, 29.352185], + [105.42033, 29.31149], + [105.465294, 29.322969], + [105.459134, 29.288526], + [105.513337, 29.283306], + [105.521344, 29.264513], + [105.557684, 29.278608], + [105.631597, 29.280174], + [105.647612, 29.253027], + [105.695039, 29.287482], + [105.712285, 29.219082], + [105.703662, 29.176766], + [105.728916, 29.134432], + [105.752321, 29.129727], + [105.728916, 29.1062], + [105.757865, 29.069068], + [105.74185, 29.039249], + [105.766488, 29.013607], + [105.762176, 28.9911], + [105.801596, 28.958116], + [105.797285, 28.936121], + [105.830546, 28.944501], + [105.852719, 28.927217], + [105.910002, 28.920407], + [105.969132, 28.965971], + [106.001161, 28.973824], + [106.040581, 28.955498], + [106.049204, 28.906263], + [106.070762, 28.919884], + [106.101559, 28.898928], + [106.14837, 28.901548], + [106.173008, 28.920407], + [106.206885, 28.904691], + [106.264783, 28.845997], + [106.245689, 28.817686], + [106.267863, 28.779402], + [106.274022, 28.739004], + [106.305435, 28.704365], + [106.304203, 28.64976], + [106.346703, 28.583565], + [106.33192, 28.55308], + [106.37442, 28.525742] + ] + ], + [ + [ + [109.105495, 30.585529], + [109.106111, 30.61077], + [109.09256, 30.578831], + [109.09872, 30.579346], + [109.101183, 30.579346], + [109.102415, 30.580377], + [109.105495, 30.585529] + ] + ], + [ + [ + [105.582938, 30.12385], + [105.582938, 30.127474], + [105.580474, 30.129544], + [105.574315, 30.130579], + [105.582938, 30.12385] + ] + ], + [ + [ + [109.09872, 30.579346], + [109.09256, 30.578831], + [109.103647, 30.565949], + [109.106111, 30.570587], + [109.09872, 30.579346] + ] + ], + [ + [ + [107.058113, 30.043066], + [107.053801, 30.043584], + [107.054417, 30.040994], + [107.055649, 30.040476], + [107.058113, 30.043066] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 510000, + "name": "四川省", + "center": [104.065735, 30.659462], + "centroid": [102.693453, 30.674545], + "childrenNum": 21, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 22, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [101.167885, 27.198311], + [101.170349, 27.175421], + [101.145095, 27.103523], + [101.157414, 27.094999], + [101.136472, 27.023584], + [101.228863, 26.981992], + [101.227015, 26.959057], + [101.264587, 26.955323], + [101.267667, 26.903034], + [101.311399, 26.903034], + [101.365602, 26.883819], + [101.399478, 26.841642], + [101.358826, 26.771669], + [101.387159, 26.753501], + [101.389623, 26.723036], + [101.435819, 26.740675], + [101.458608, 26.731054], + [101.445674, 26.77434], + [101.466, 26.786629], + [101.513427, 26.768463], + [101.453065, 26.692563], + [101.481398, 26.673313], + [101.461072, 26.640687], + [101.461688, 26.606447], + [101.402558, 26.604841], + [101.395783, 26.591998], + [101.422884, 26.53151], + [101.458608, 26.49563], + [101.506652, 26.499915], + [101.530057, 26.467239], + [101.565782, 26.454381], + [101.637847, 26.388995], + [101.635383, 26.357361], + [101.660636, 26.346635], + [101.64031, 26.318745], + [101.597195, 26.303187], + [101.586108, 26.279579], + [101.630455, 26.224832], + [101.690202, 26.241473], + [101.737013, 26.219463], + [101.773353, 26.168448], + [101.807846, 26.156093], + [101.796759, 26.114723], + [101.839875, 26.082477], + [101.835563, 26.04592], + [101.857737, 26.049146], + [101.899621, 26.099139], + [101.929186, 26.105588], + [101.954439, 26.084627], + [102.020961, 26.096451], + [102.080091, 26.065275], + [102.107808, 26.068501], + [102.152156, 26.10935], + [102.174946, 26.146961], + [102.242699, 26.190468], + [102.245163, 26.212483], + [102.349257, 26.244694], + [102.392372, 26.296749], + [102.440416, 26.300505], + [102.542046, 26.338591], + [102.570995, 26.362723], + [102.629509, 26.336982], + [102.638748, 26.307479], + [102.60056, 26.250598], + [102.659074, 26.221611], + [102.709581, 26.210336], + [102.739762, 26.268846], + [102.785342, 26.298895], + [102.833385, 26.306406], + [102.878964, 26.364332], + [102.893131, 26.338591], + [102.975667, 26.340736], + [102.998457, 26.371839], + [102.988602, 26.413117], + [102.989833, 26.482775], + [103.030485, 26.485989], + [103.052659, 26.514374], + [103.052659, 26.555602], + [103.035413, 26.556673], + [103.026174, 26.664221], + [103.005232, 26.679195], + [103.008312, 26.710741], + [102.983674, 26.76686], + [102.991681, 26.775409], + [102.966428, 26.837904], + [102.949181, 26.843244], + [102.896211, 26.91264], + [102.894979, 27.001724], + [102.870957, 27.026782], + [102.913457, 27.133886], + [102.904218, 27.227584], + [102.883276, 27.258444], + [102.883892, 27.299401], + [102.899906, 27.317481], + [102.941174, 27.405711], + [102.989833, 27.367983], + [103.055739, 27.40943], + [103.080992, 27.396679], + [103.141355, 27.420586], + [103.144434, 27.450331], + [103.19063, 27.523596], + [103.232514, 27.56976], + [103.2861, 27.561802], + [103.29226, 27.632872], + [103.349542, 27.678459], + [103.369868, 27.708664], + [103.393274, 27.709194], + [103.461027, 27.779638], + [103.487512, 27.794992], + [103.509686, 27.843687], + [103.502295, 27.910343], + [103.55465, 27.978543], + [103.515846, 27.965329], + [103.486281, 28.033495], + [103.459179, 28.021345], + [103.430846, 28.044587], + [103.470266, 28.122204], + [103.533092, 28.168641], + [103.573128, 28.230877], + [103.643961, 28.260401], + [103.692004, 28.232459], + [103.701859, 28.198709], + [103.740048, 28.23615], + [103.770845, 28.233514], + [103.828743, 28.285173], + [103.877402, 28.316262], + [103.85338, 28.356822], + [103.860156, 28.383677], + [103.828743, 28.44], + [103.829975, 28.459995], + [103.781931, 28.525216], + [103.802873, 28.563068], + [103.838598, 28.587244], + [103.833054, 28.605109], + [103.850917, 28.66709], + [103.887873, 28.61982], + [103.910047, 28.631377], + [103.953779, 28.600906], + [104.05972, 28.6277], + [104.09606, 28.603533], + [104.117618, 28.634003], + [104.170589, 28.642932], + [104.230951, 28.635579], + [104.252509, 28.660788], + [104.277147, 28.631902], + [104.314719, 28.615617], + [104.372617, 28.649235], + [104.425588, 28.626649], + [104.417581, 28.598279], + [104.375697, 28.5946], + [104.355987, 28.555183], + [104.323342, 28.540989], + [104.260516, 28.536257], + [104.267908, 28.499448], + [104.254357, 28.403683], + [104.282074, 28.343128], + [104.314103, 28.306778], + [104.343052, 28.334173], + [104.384936, 28.329959], + [104.392943, 28.291497], + [104.420045, 28.269889], + [104.44961, 28.269889], + [104.462544, 28.241422], + [104.442834, 28.211366], + [104.402182, 28.202928], + [104.406494, 28.173389], + [104.444682, 28.16231], + [104.448994, 28.113758], + [104.40095, 28.091586], + [104.373233, 28.051454], + [104.304248, 28.050926], + [104.30856, 28.036136], + [104.362762, 28.012891], + [104.40095, 27.952114], + [104.44961, 27.927794], + [104.508124, 27.878078], + [104.52537, 27.889187], + [104.573413, 27.840512], + [104.607906, 27.857974], + [104.63316, 27.850567], + [104.676275, 27.880723], + [104.743413, 27.901881], + [104.761891, 27.884426], + [104.796999, 27.901352], + [104.842579, 27.900294], + [104.888158, 27.914574], + [104.918339, 27.938897], + [104.903557, 27.962158], + [104.975006, 28.020816], + [104.980549, 28.063073], + [105.002107, 28.064129], + [105.061853, 28.096866], + [105.119752, 28.07205], + [105.168411, 28.071522], + [105.186889, 28.054623], + [105.167795, 28.021345], + [105.186273, 27.995454], + [105.218302, 27.990698], + [105.247867, 28.009193], + [105.270657, 27.99704], + [105.284823, 27.935725], + [105.233084, 27.895534], + [105.25957, 27.827811], + [105.313157, 27.810874], + [105.273736, 27.794992], + [105.293447, 27.770637], + [105.290367, 27.712373], + [105.308229, 27.704955], + [105.353809, 27.748924], + [105.44004, 27.775402], + [105.508409, 27.769048], + [105.560148, 27.71979], + [105.605112, 27.715552], + [105.62359, 27.666269], + [105.664242, 27.683759], + [105.720292, 27.683759], + [105.722756, 27.706015], + [105.76772, 27.7182], + [105.848408, 27.707074], + [105.868118, 27.732504], + [105.922937, 27.746805], + [105.92848, 27.729855], + [105.985146, 27.749983], + [106.023335, 27.746805], + [106.063987, 27.776991], + [106.120653, 27.779638], + [106.193334, 27.75422], + [106.242609, 27.767459], + [106.306667, 27.808756], + [106.337464, 27.859033], + [106.325145, 27.898708], + [106.304819, 27.899237], + [106.307899, 27.936782], + [106.328225, 27.952643], + [106.286341, 28.007079], + [106.246305, 28.011835], + [106.266631, 28.066769], + [106.206885, 28.134343], + [106.145291, 28.162837], + [106.093552, 28.162837], + [105.975907, 28.107952], + [105.943878, 28.143314], + [105.895219, 28.119565], + [105.860727, 28.159672], + [105.889676, 28.237732], + [105.848408, 28.255656], + [105.824386, 28.306251], + [105.78743, 28.335753], + [105.76464, 28.308359], + [105.76464, 28.308359], + [105.737539, 28.30309], + [105.730147, 28.271997], + [105.68888, 28.284119], + [105.639604, 28.324164], + [105.655003, 28.362615], + [105.643916, 28.431053], + [105.612503, 28.438947], + [105.62359, 28.517854], + [105.68272, 28.534154], + [105.693191, 28.58882], + [105.712901, 28.586718], + [105.74493, 28.616668], + [105.757249, 28.590397], + [105.78435, 28.610889], + [105.808372, 28.599855], + [105.884748, 28.595126], + [105.889676, 28.670765], + [105.937719, 28.686517], + [105.966668, 28.761041], + [106.001161, 28.743727], + [106.030726, 28.694917], + [106.085544, 28.681792], + [106.103407, 28.636104], + [106.14837, 28.642932], + [106.17116, 28.629275], + [106.184711, 28.58882], + [106.254928, 28.539412], + [106.2925, 28.537309], + [106.304819, 28.505233], + [106.349167, 28.473674], + [106.379348, 28.479986], + [106.37442, 28.525742], + [106.33192, 28.55308], + [106.346703, 28.583565], + [106.304203, 28.64976], + [106.305435, 28.704365], + [106.274022, 28.739004], + [106.267863, 28.779402], + [106.245689, 28.817686], + [106.264783, 28.845997], + [106.206885, 28.904691], + [106.173008, 28.920407], + [106.14837, 28.901548], + [106.101559, 28.898928], + [106.070762, 28.919884], + [106.049204, 28.906263], + [106.040581, 28.955498], + [106.001161, 28.973824], + [105.969132, 28.965971], + [105.910002, 28.920407], + [105.852719, 28.927217], + [105.830546, 28.944501], + [105.797285, 28.936121], + [105.801596, 28.958116], + [105.762176, 28.9911], + [105.766488, 29.013607], + [105.74185, 29.039249], + [105.757865, 29.069068], + [105.728916, 29.1062], + [105.752321, 29.129727], + [105.728916, 29.134432], + [105.703662, 29.176766], + [105.712285, 29.219082], + [105.695039, 29.287482], + [105.647612, 29.253027], + [105.631597, 29.280174], + [105.557684, 29.278608], + [105.521344, 29.264513], + [105.513337, 29.283306], + [105.459134, 29.288526], + [105.465294, 29.322969], + [105.42033, 29.31149], + [105.418482, 29.352185], + [105.441888, 29.400686], + [105.426489, 29.419454], + [105.372903, 29.421018], + [105.399388, 29.43874], + [105.387069, 29.455416], + [105.387069, 29.455416], + [105.334099, 29.441345], + [105.337794, 29.459064], + [105.305149, 29.53199], + [105.296526, 29.571035], + [105.332867, 29.592374], + [105.347649, 29.621512], + [105.38091, 29.628275], + [105.419714, 29.688082], + [105.476996, 29.674564], + [105.481924, 29.718232], + [105.529351, 29.707836], + [105.574931, 29.744216], + [105.582938, 29.819013], + [105.610655, 29.837184], + [105.707974, 29.840818], + [105.738771, 29.891159], + [105.717213, 29.893753], + [105.70243, 29.924879], + [105.730763, 29.95755], + [105.723372, 29.975177], + [105.753553, 30.018196], + [105.719677, 30.042548], + [105.687032, 30.038922], + [105.676561, 30.06793], + [105.638988, 30.076216], + [105.642068, 30.101072], + [105.582938, 30.12385], + [105.574315, 30.130579], + [105.596489, 30.159043], + [105.536127, 30.152834], + [105.550909, 30.179222], + [105.556453, 30.187499], + [105.558916, 30.18543], + [105.56138, 30.183878], + [105.642684, 30.186464], + [105.662394, 30.210258], + [105.619894, 30.234045], + [105.624822, 30.275918], + [105.670401, 30.254208], + [105.720292, 30.252657], + [105.720292, 30.252657], + [105.714749, 30.322939], + [105.754785, 30.342567], + [105.760329, 30.384393], + [105.792357, 30.427234], + [105.825618, 30.436006], + [105.84656, 30.410203], + [105.900763, 30.405042], + [105.943263, 30.372002], + [106.031958, 30.373551], + [106.07261, 30.333786], + [106.132972, 30.30279], + [106.132356, 30.323972], + [106.168696, 30.303823], + [106.180399, 30.233011], + [106.232754, 30.185947], + [106.260471, 30.19681], + [106.260471, 30.204051], + [106.260471, 30.207672], + [106.264167, 30.20974], + [106.296196, 30.205603], + [106.306667, 30.238182], + [106.334384, 30.225772], + [106.349167, 30.24542], + [106.401521, 30.242318], + [106.428623, 30.254725], + [106.43971, 30.308473], + [106.49884, 30.295556], + [106.545035, 30.296589], + [106.560434, 30.31519], + [106.611557, 30.292455], + [106.642354, 30.246454], + [106.612789, 30.235596], + [106.612789, 30.235596], + [106.612173, 30.235596], + [106.612173, 30.235596], + [106.611557, 30.235596], + [106.612173, 30.235596], + [106.611557, 30.235596], + [106.631883, 30.186464], + [106.677462, 30.156974], + [106.672535, 30.122297], + [106.700252, 30.111944], + [106.699636, 30.074145], + [106.724274, 30.058607], + [106.732281, 30.027005], + [106.785252, 30.01716], + [106.825904, 30.03115], + [106.825904, 30.03115], + [106.83699, 30.049801], + [106.862244, 30.033223], + [106.913367, 30.025451], + [106.94478, 30.037367], + [106.976193, 30.083467], + [106.975577, 30.088127], + [106.976809, 30.088127], + [106.977425, 30.087609], + [106.978656, 30.087609], + [106.979888, 30.088127], + [106.980504, 30.087609], + [106.981736, 30.08502], + [107.02054, 30.036849], + [107.053801, 30.043584], + [107.058113, 30.043066], + [107.084598, 30.063786], + [107.080286, 30.094341], + [107.103076, 30.090198], + [107.221337, 30.213878], + [107.257677, 30.267131], + [107.288474, 30.337402], + [107.338981, 30.386459], + [107.368546, 30.468508], + [107.408582, 30.521623], + [107.443075, 30.53348], + [107.427676, 30.547397], + [107.485575, 30.598408], + [107.516987, 30.644759], + [107.477567, 30.664837], + [107.458473, 30.704981], + [107.424597, 30.74048], + [107.454162, 30.771851], + [107.454162, 30.771851], + [107.498509, 30.809381], + [107.483111, 30.838675], + [107.515756, 30.854603], + [107.57735, 30.847924], + [107.645103, 30.821202], + [107.693146, 30.875665], + [107.739957, 30.884396], + [107.760899, 30.862823], + [107.763979, 30.817091], + [107.788001, 30.81966], + [107.851443, 30.792931], + [107.956152, 30.882855], + [107.994956, 30.908533], + [107.948145, 30.918802], + [107.942602, 30.989114], + [107.983254, 30.983983], + [108.00358, 31.025533], + [108.060246, 31.052197], + [108.026985, 31.061938], + [108.009123, 31.109602], + [108.025753, 31.116263], + [108.089811, 31.204859], + [108.07626, 31.231985], + [108.031297, 31.217144], + [108.038688, 31.252964], + [108.095354, 31.268311], + [108.185898, 31.336831], + [108.153869, 31.371073], + [108.216079, 31.41041], + [108.224086, 31.464024], + [108.193289, 31.467598], + [108.191441, 31.492096], + [108.233941, 31.506894], + [108.254883, 31.49873], + [108.344194, 31.512506], + [108.339266, 31.539033], + [108.386078, 31.544134], + [108.390389, 31.591555], + [108.442744, 31.633856], + [108.468614, 31.636404], + [108.519121, 31.665952], + [108.546838, 31.665442], + [108.514809, 31.693963], + [108.50557, 31.734182], + [108.535135, 31.757592], + [108.462454, 31.780488], + [108.455063, 31.814059], + [108.429194, 31.809482], + [108.391005, 31.829822], + [108.386078, 31.854226], + [108.343578, 31.860834], + [108.259194, 31.967006], + [108.307238, 31.997463], + [108.351585, 31.971575], + [108.370063, 31.988835], + [108.329411, 32.020299], + [108.362056, 32.035521], + [108.344194, 32.067477], + [108.372527, 32.077112], + [108.42981, 32.061391], + [108.452599, 32.090296], + [108.399628, 32.147065], + [108.379303, 32.153652], + [108.379303, 32.153652], + [108.379918, 32.154158], + [108.379918, 32.154158], + [108.370063, 32.172397], + [108.399013, 32.194176], + [108.480317, 32.182527], + [108.509882, 32.201266], + [108.507418, 32.245819], + [108.469846, 32.270618], + [108.414411, 32.252399], + [108.389773, 32.263533], + [108.310933, 32.232152], + [108.240716, 32.274666], + [108.179738, 32.221521], + [108.156948, 32.239239], + [108.143398, 32.219495], + [108.086731, 32.233165], + [108.018362, 32.2119], + [108.024521, 32.177462], + [107.979558, 32.146051], + [107.924739, 32.197215], + [107.890247, 32.214432], + [107.864377, 32.201266], + [107.812022, 32.247844], + [107.753508, 32.338399], + [107.707929, 32.331826], + [107.680827, 32.397035], + [107.648183, 32.413709], + [107.598291, 32.411688], + [107.527458, 32.38238], + [107.489886, 32.425328], + [107.456625, 32.41775], + [107.460937, 32.453612], + [107.438763, 32.465732], + [107.436299, 32.529835], + [107.382097, 32.54043], + [107.356843, 32.506622], + [107.313727, 32.489965], + [107.287858, 32.457147], + [107.263836, 32.403099], + [107.212097, 32.428864], + [107.189924, 32.468256], + [107.127098, 32.482393], + [107.080286, 32.542448], + [107.108004, 32.600951], + [107.098765, 32.649338], + [107.05996, 32.686115], + [107.066736, 32.708779], + [107.012533, 32.721367], + [106.912751, 32.704247], + [106.903512, 32.721367], + [106.854853, 32.724388], + [106.82344, 32.705254], + [106.793259, 32.712807], + [106.783404, 32.735967], + [106.733513, 32.739491], + [106.670071, 32.694678], + [106.626955, 32.682086], + [106.585687, 32.68813], + [106.517934, 32.668485], + [106.498224, 32.649338], + [106.451412, 32.65992], + [106.421231, 32.616579], + [106.389203, 32.62666], + [106.347935, 32.671003], + [106.301123, 32.680071], + [106.267863, 32.673522], + [106.254928, 32.693671], + [106.17424, 32.6977], + [106.120037, 32.719856], + [106.071378, 32.758114], + [106.07261, 32.76365], + [106.093552, 32.82402], + [106.071378, 32.828546], + [106.044277, 32.864747], + [106.011632, 32.829552], + [105.969132, 32.849162], + [105.93156, 32.826032], + [105.893371, 32.838603], + [105.849024, 32.817985], + [105.825002, 32.824523], + [105.822538, 32.770192], + [105.779423, 32.750061], + [105.768952, 32.767676], + [105.719061, 32.759624], + [105.677793, 32.726402], + [105.596489, 32.69921], + [105.585402, 32.728919], + [105.563844, 32.724891], + [105.555221, 32.794343], + [105.534279, 32.790822], + [105.524424, 32.847654], + [105.495475, 32.873292], + [105.49917, 32.911986], + [105.467757, 32.930071], + [105.414171, 32.922034], + [105.408011, 32.885857], + [105.38091, 32.876307], + [105.396308, 32.85067], + [105.396308, 32.85067], + [105.427721, 32.784281], + [105.454207, 32.767173], + [105.448663, 32.732946], + [105.368591, 32.712807], + [105.347033, 32.68259], + [105.297758, 32.656897], + [105.263265, 32.652362], + [105.219534, 32.666469], + [105.215222, 32.63674], + [105.185041, 32.617587], + [105.111128, 32.593893], + [105.0791, 32.637244], + [105.026745, 32.650346], + [104.925115, 32.607505], + [104.881999, 32.600951], + [104.845659, 32.653873], + [104.820405, 32.662943], + [104.795768, 32.643292], + [104.739717, 32.635228], + [104.696601, 32.673522], + [104.643015, 32.661935], + [104.592508, 32.695685], + [104.582653, 32.722374], + [104.526602, 32.728416], + [104.51182, 32.753585], + [104.458849, 32.748551], + [104.363994, 32.822511], + [104.294393, 32.835586], + [104.277147, 32.90244], + [104.288234, 32.942628], + [104.345516, 32.940117], + [104.378161, 32.953174], + [104.383704, 32.994343], + [104.426204, 33.010906], + [104.391711, 33.035493], + [104.337509, 33.038002], + [104.378161, 33.109214], + [104.351059, 33.158828], + [104.32827, 33.223934], + [104.323958, 33.26898], + [104.303632, 33.304499], + [104.333813, 33.315502], + [104.386168, 33.298497], + [104.420045, 33.327004], + [104.373849, 33.345004], + [104.292545, 33.336505], + [104.272219, 33.391486], + [104.22048, 33.404477], + [104.213089, 33.446932], + [104.180444, 33.472895], + [104.155191, 33.542755], + [104.176749, 33.5996], + [104.103452, 33.663381], + [104.046169, 33.686291], + [103.980264, 33.670852], + [103.861388, 33.682307], + [103.778236, 33.658898], + [103.690772, 33.69376], + [103.667983, 33.685793], + [103.645809, 33.708697], + [103.593454, 33.716164], + [103.563889, 33.699735], + [103.552186, 33.671351], + [103.520157, 33.678323], + [103.545411, 33.719649], + [103.518309, 33.807213], + [103.464723, 33.80224], + [103.434542, 33.752993], + [103.35447, 33.743539], + [103.278709, 33.774387], + [103.284868, 33.80224], + [103.24976, 33.814175], + [103.228202, 33.79478], + [103.165376, 33.805721], + [103.153673, 33.819147], + [103.181391, 33.900649], + [103.16476, 33.929454], + [103.1315, 33.931937], + [103.120413, 33.953286], + [103.157369, 33.998944], + [103.147514, 34.036644], + [103.119797, 34.03466], + [103.129652, 34.065899], + [103.178927, 34.079779], + [103.121644, 34.112487], + [103.124108, 34.162022], + [103.100087, 34.181828], + [103.052043, 34.195194], + [103.005848, 34.184798], + [102.973203, 34.205588], + [102.977515, 34.252595], + [102.949181, 34.292159], + [102.911609, 34.312923], + [102.85987, 34.301058], + [102.856791, 34.270895], + [102.798276, 34.272874], + [102.779798, 34.236764], + [102.728675, 34.235774], + [102.694799, 34.198659], + [102.664002, 34.192719], + [102.651067, 34.165983], + [102.598712, 34.14766], + [102.655994, 34.113478], + [102.649219, 34.080275], + [102.615958, 34.099604], + [102.511865, 34.086222], + [102.471213, 34.072839], + [102.437336, 34.087214], + [102.406539, 34.033172], + [102.392372, 33.971651], + [102.345561, 33.969666], + [102.315996, 33.993983], + [102.287047, 33.977607], + [102.248858, 33.98654], + [102.226069, 33.963214], + [102.16817, 33.983066], + [102.136142, 33.965199], + [102.25317, 33.861399], + [102.261177, 33.821136], + [102.243315, 33.786823], + [102.296286, 33.783838], + [102.324619, 33.754486], + [102.284583, 33.719151], + [102.342481, 33.725622], + [102.31538, 33.665374], + [102.346793, 33.605582], + [102.440416, 33.574673], + [102.477988, 33.543254], + [102.446575, 33.53228], + [102.461358, 33.501345], + [102.462589, 33.449429], + [102.447807, 33.454922], + [102.392988, 33.404477], + [102.368967, 33.41247], + [102.310452, 33.397982], + [102.296286, 33.413969], + [102.258098, 33.409472], + [102.218062, 33.349503], + [102.192192, 33.337005], + [102.217446, 33.247961], + [102.200815, 33.223434], + [102.160163, 33.242956], + [102.144765, 33.273983], + [102.117047, 33.288492], + [102.08933, 33.227439], + [102.08933, 33.204908], + [102.054838, 33.189884], + [101.99386, 33.1999], + [101.935345, 33.186879], + [101.921795, 33.153817], + [101.887302, 33.135778], + [101.865744, 33.103198], + [101.825708, 33.119239], + [101.841723, 33.184876], + [101.83002, 33.213921], + [101.770274, 33.248962], + [101.769658, 33.26898], + [101.877447, 33.314502], + [101.887302, 33.383991], + [101.915635, 33.425957], + [101.946432, 33.442937], + [101.906396, 33.48188], + [101.907012, 33.539264], + [101.884222, 33.578163], + [101.844186, 33.602591], + [101.831252, 33.554726], + [101.783208, 33.556721], + [101.769042, 33.538765], + [101.777665, 33.533776], + [101.769042, 33.45592], + [101.695745, 33.433948], + [101.663716, 33.383991], + [101.64955, 33.323004], + [101.677883, 33.297497], + [101.735781, 33.279987], + [101.709912, 33.21292], + [101.653861, 33.162835], + [101.661252, 33.135778], + [101.633535, 33.101193], + [101.557775, 33.167344], + [101.515275, 33.192889], + [101.487557, 33.226938], + [101.403174, 33.225436], + [101.386543, 33.207412], + [101.393935, 33.157826], + [101.381616, 33.153316], + [101.297232, 33.262475], + [101.217776, 33.256469], + [101.182668, 33.26948], + [101.156798, 33.236449], + [101.124769, 33.221431], + [101.11553, 33.194893], + [101.169733, 33.10019], + [101.143863, 33.086151], + [101.146327, 33.056563], + [101.184515, 33.041514], + [101.171581, 33.009902], + [101.183899, 32.984304], + [101.129081, 32.989324], + [101.134624, 32.95217], + [101.124153, 32.909976], + [101.178356, 32.892892], + [101.223935, 32.855698], + [101.237486, 32.825026], + [101.22332, 32.725898], + [101.157414, 32.661431], + [101.124769, 32.658408], + [101.077342, 32.68259], + [101.030531, 32.660424], + [100.99727, 32.627668], + [100.956618, 32.621116], + [100.93198, 32.600447], + [100.887633, 32.632708], + [100.834046, 32.648835], + [100.77122, 32.643795], + [100.690532, 32.678056], + [100.71209, 32.645307], + [100.710242, 32.610026], + [100.673286, 32.628172], + [100.661583, 32.616075], + [100.657887, 32.546484], + [100.645568, 32.526303], + [100.603069, 32.553547], + [100.54517, 32.569687], + [100.516837, 32.632204], + [100.470026, 32.694678], + [100.450932, 32.694678], + [100.420135, 32.73194], + [100.378251, 32.698707], + [100.399193, 32.756101], + [100.339447, 32.719353], + [100.258759, 32.742511], + [100.231041, 32.696189], + [100.229809, 32.650346], + [100.208252, 32.606497], + [100.189773, 32.630692], + [100.109701, 32.640268], + [100.088143, 32.668988], + [100.139266, 32.724388], + [100.117093, 32.802392], + [100.123252, 32.837095], + [100.064738, 32.895907], + [100.029629, 32.895907], + [100.038252, 32.929066], + [99.956332, 32.948152], + [99.947709, 32.986814], + [99.877492, 33.045527], + [99.877492, 32.993339], + [99.851007, 32.941623], + [99.805427, 32.940619], + [99.788181, 32.956689], + [99.764159, 32.924545], + [99.791877, 32.883344], + [99.766623, 32.826032], + [99.760464, 32.769689], + [99.717964, 32.732443], + [99.700718, 32.76667], + [99.646515, 32.774721], + [99.640355, 32.790822], + [99.589233, 32.789312], + [99.558436, 32.839106], + [99.45311, 32.862233], + [99.376118, 32.899927], + [99.353944, 32.885354], + [99.268944, 32.878318], + [99.24677, 32.924043], + [99.235067, 32.982296], + [99.214741, 32.991332], + [99.196263, 33.035493], + [99.124814, 33.046028], + [99.090322, 33.079131], + [99.024416, 33.094675], + [99.014561, 33.081137], + [98.971445, 33.098185], + [98.967134, 33.115229], + [98.92217, 33.118738], + [98.858728, 33.150811], + [98.804526, 33.219428], + [98.802062, 33.270481], + [98.759562, 33.276985], + [98.779888, 33.370497], + [98.736157, 33.406975], + [98.742316, 33.477887], + [98.725686, 33.503341], + [98.678258, 33.522801], + [98.648077, 33.548741], + [98.652389, 33.595114], + [98.622824, 33.610067], + [98.61728, 33.637476], + [98.6567, 33.64744], + [98.610505, 33.682805], + [98.582788, 33.731595], + [98.539672, 33.746525], + [98.51873, 33.77389], + [98.494092, 33.768915], + [98.492861, 33.796272], + [98.463295, 33.848477], + [98.434962, 33.843009], + [98.407245, 33.867362], + [98.425723, 33.913066], + [98.415252, 33.956761], + [98.440506, 33.981577], + [98.428187, 34.029204], + [98.396774, 34.053008], + [98.399854, 34.085231], + [98.344419, 34.094648], + [98.258188, 34.083249], + [98.206449, 34.08424], + [98.158405, 34.107037], + [98.098043, 34.122892], + [98.028442, 34.122892], + [97.95453, 34.190739], + [97.898479, 34.209548], + [97.8104, 34.207568], + [97.796849, 34.199154], + [97.796849, 34.199154], + [97.789458, 34.182818], + [97.789458, 34.182818], + [97.766668, 34.158555], + [97.665654, 34.126855], + [97.70261, 34.036644], + [97.652719, 33.998448], + [97.660111, 33.956264], + [97.629314, 33.919523], + [97.601596, 33.929951], + [97.52214, 33.903133], + [97.503662, 33.912073], + [97.460546, 33.887236], + [97.395257, 33.889224], + [97.398336, 33.848477], + [97.371851, 33.842015], + [97.373083, 33.817655], + [97.406344, 33.795278], + [97.422974, 33.754984], + [97.418046, 33.728608], + [97.435293, 33.682307], + [97.415583, 33.605582], + [97.450075, 33.582152], + [97.523372, 33.577166], + [97.511669, 33.520805], + [97.552321, 33.465906], + [97.625618, 33.461412], + [97.674893, 33.432949], + [97.754349, 33.409972], + [97.676125, 33.341004], + [97.622538, 33.337005], + [97.607756, 33.263976], + [97.548626, 33.203907], + [97.487648, 33.168346], + [97.498119, 33.137783], + [97.487032, 33.107209], + [97.517213, 33.097683], + [97.542466, 33.035995], + [97.499966, 33.011408], + [97.523988, 32.988822], + [97.438372, 32.976271], + [97.375547, 32.956689], + [97.347829, 32.895907], + [97.376163, 32.886359], + [97.392793, 32.828546], + [97.386018, 32.77925], + [97.429133, 32.714318], + [97.42359, 32.70475], + [97.48272, 32.654377], + [97.535075, 32.638252], + [97.543698, 32.62162], + [97.607756, 32.614059], + [97.616995, 32.586329], + [97.700763, 32.53488], + [97.730944, 32.527312], + [97.795617, 32.521257], + [97.80732, 32.50006], + [97.863986, 32.499051], + [97.880001, 32.486431], + [97.940363, 32.482393], + [98.079565, 32.415224], + [98.107283, 32.391476], + [98.125145, 32.401077], + [98.218768, 32.342444], + [98.208913, 32.318171], + [98.23047, 32.262521], + [98.218768, 32.234683], + [98.260035, 32.208862], + [98.303151, 32.121726], + [98.357354, 32.087253], + [98.404781, 32.045159], + [98.402933, 32.026896], + [98.434962, 32.007613], + [98.432498, 31.922825], + [98.399238, 31.895899], + [98.426339, 31.856767], + [98.414636, 31.832365], + [98.461448, 31.800327], + [98.508875, 31.751995], + [98.516882, 31.717383], + [98.545831, 31.717383], + [98.553839, 31.660349], + [98.619128, 31.591555], + [98.651157, 31.57881], + [98.696736, 31.538523], + [98.714599, 31.508935], + [98.844562, 31.429817], + [98.84333, 31.416028], + [98.887062, 31.37465], + [98.810685, 31.306668], + [98.805758, 31.279052], + [98.773113, 31.249382], + [98.691809, 31.333253], + [98.643766, 31.338876], + [98.616048, 31.3036], + [98.60373, 31.257568], + [98.62344, 31.221238], + [98.602498, 31.192062], + [98.675179, 31.15417], + [98.710287, 31.1178], + [98.712135, 31.082954], + [98.736772, 31.049121], + [98.774961, 31.031174], + [98.806374, 30.995783], + [98.797135, 30.948575], + [98.774345, 30.908019], + [98.797135, 30.87926], + [98.850105, 30.849465], + [98.904924, 30.782649], + [98.957895, 30.765166], + [98.963438, 30.728134], + [98.907388, 30.698292], + [98.92217, 30.609225], + [98.939417, 30.598923], + [98.926482, 30.569556], + [98.932025, 30.521623], + [98.965286, 30.449937], + [98.967134, 30.33482], + [98.986844, 30.280569], + [98.970829, 30.260928], + [98.993003, 30.215429], + [98.9813, 30.182843], + [98.989308, 30.151799], + [99.044742, 30.079842], + [99.036735, 30.053945], + [99.055213, 29.958587], + [99.068148, 29.931621], + [99.0238, 29.846009], + [99.018873, 29.792009], + [98.992387, 29.677163], + [99.014561, 29.607464], + [99.052133, 29.563748], + [99.044742, 29.520013], + [99.066916, 29.421018], + [99.058909, 29.417368], + [99.075539, 29.316186], + [99.114343, 29.243628], + [99.113727, 29.221171], + [99.105104, 29.162656], + [99.118039, 29.100971], + [99.113727, 29.07273], + [99.132206, 28.94869], + [99.123582, 28.890021], + [99.103872, 28.841803], + [99.114343, 28.765763], + [99.134053, 28.734806], + [99.126662, 28.698066], + [99.147604, 28.640831], + [99.183944, 28.58882], + [99.170394, 28.566221], + [99.191952, 28.494714], + [99.187024, 28.44], + [99.16485, 28.425264], + [99.200575, 28.365774], + [99.229524, 28.350502], + [99.237531, 28.317842], + [99.28927, 28.286227], + [99.306516, 28.227714], + [99.374886, 28.18183], + [99.412458, 28.295186], + [99.392748, 28.318369], + [99.437095, 28.398419], + [99.404451, 28.44421], + [99.426625, 28.454207], + [99.396444, 28.491032], + [99.403219, 28.546246], + [99.463581, 28.549401], + [99.466045, 28.579886], + [99.504233, 28.619294], + [99.540573, 28.623497], + [99.53195, 28.677591], + [99.553508, 28.710664], + [99.614486, 28.740054], + [99.609559, 28.784122], + [99.625573, 28.81454], + [99.676696, 28.810345], + [99.717964, 28.846521], + [99.722275, 28.757369], + [99.755536, 28.701216], + [99.79434, 28.699116], + [99.834992, 28.660788], + [99.834376, 28.628225], + [99.873181, 28.631902], + [99.875644, 28.611939], + [99.91876, 28.599329], + [99.985281, 28.529422], + [99.990209, 28.47683], + [100.073977, 28.426317], + [100.057346, 28.368934], + [100.136803, 28.349975], + [100.176223, 28.325218], + [100.147274, 28.288862], + [100.188541, 28.252493], + [100.153433, 28.208202], + [100.102926, 28.201873], + [100.091223, 28.181302], + [100.062274, 28.193962], + [100.033325, 28.184467], + [100.021006, 28.147008], + [100.05673, 28.097922], + [100.088759, 28.029269], + [100.120788, 28.018703], + [100.196549, 27.936254], + [100.170063, 27.907699], + [100.210715, 27.87702], + [100.30865, 27.861149], + [100.30865, 27.830457], + [100.28586, 27.80611], + [100.304954, 27.788639], + [100.311729, 27.724028], + [100.327744, 27.72032], + [100.350534, 27.755809], + [100.412127, 27.816167], + [100.442924, 27.86644], + [100.504518, 27.852154], + [100.511294, 27.827811], + [100.54517, 27.809286], + [100.609228, 27.859033], + [100.634482, 27.915631], + [100.681293, 27.923035], + [100.719481, 27.858503], + [100.707162, 27.800816], + [100.757053, 27.770107], + [100.775532, 27.743098], + [100.782307, 27.691708], + [100.848212, 27.672099], + [100.827886, 27.615904], + [100.854988, 27.623858], + [100.91227, 27.521473], + [100.901183, 27.453517], + [100.936908, 27.469448], + [100.95169, 27.426961], + [101.021907, 27.332899], + [101.026219, 27.270679], + [101.042233, 27.22173], + [101.071798, 27.194585], + [101.119226, 27.208957], + [101.167885, 27.198311], + [101.167885, 27.198311] + ] + ], + [ + [ + [106.264167, 30.20974], + [106.260471, 30.207672], + [106.260471, 30.204051], + [106.260471, 30.19681], + [106.264167, 30.20974] + ] + ], + [ + [ + [106.976809, 30.088127], + [106.975577, 30.088127], + [106.976193, 30.083467], + [106.981736, 30.08502], + [106.980504, 30.087609], + [106.979888, 30.088127], + [106.978656, 30.087609], + [106.977425, 30.087609], + [106.976809, 30.088127] + ] + ], + [ + [ + [105.558916, 30.18543], + [105.556453, 30.187499], + [105.550909, 30.179222], + [105.56138, 30.183878], + [105.558916, 30.18543] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 520000, + "name": "贵州省", + "center": [106.713478, 26.578343], + "centroid": [106.880455, 26.826368], + "childrenNum": 9, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 23, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [109.274262, 28.494714], + [109.23361, 28.474726], + [109.191726, 28.471043], + [109.153538, 28.417369], + [109.152306, 28.349975], + [109.117198, 28.277795], + [109.081473, 28.247749], + [109.101799, 28.202401], + [109.086401, 28.184467], + [109.026655, 28.220331], + [109.005713, 28.162837], + [108.929952, 28.19027], + [108.923793, 28.217167], + [108.89546, 28.219804], + [108.855424, 28.199764], + [108.821547, 28.245113], + [108.772888, 28.212949], + [108.738395, 28.228241], + [108.726692, 28.282011], + [108.761801, 28.304143], + [108.783359, 28.380518], + [108.759953, 28.389995], + [108.780279, 28.42579], + [108.746402, 28.45105], + [108.709446, 28.501026], + [108.700207, 28.48209], + [108.657091, 28.47683], + [108.640461, 28.456838], + [108.688504, 28.422106], + [108.697127, 28.401051], + [108.656475, 28.359981], + [108.667562, 28.334173], + [108.611512, 28.324691], + [108.580099, 28.343128], + [108.576403, 28.38631], + [108.609048, 28.407368], + [108.609664, 28.43579], + [108.586874, 28.463678], + [108.573939, 28.531], + [108.610896, 28.539412], + [108.604736, 28.590922], + [108.636149, 28.621396], + [108.575787, 28.659738], + [108.50249, 28.63768], + [108.501258, 28.626649], + [108.439049, 28.634003], + [108.332491, 28.679166], + [108.347274, 28.736381], + [108.385462, 28.772058], + [108.386078, 28.803003], + [108.352817, 28.815589], + [108.346658, 28.859625], + [108.357745, 28.893165], + [108.345426, 28.943453], + [108.319556, 28.961258], + [108.297999, 29.045527], + [108.306622, 29.079006], + [108.277673, 29.091558], + [108.256115, 29.040295], + [108.193289, 29.072207], + [108.150173, 29.053375], + [108.070717, 29.086328], + [108.026369, 29.039772], + [107.925971, 29.032446], + [107.908725, 29.007327], + [107.882855, 29.00628], + [107.867457, 28.960211], + [107.810175, 28.984295], + [107.823725, 29.034016], + [107.784921, 29.048143], + [107.810791, 29.139137], + [107.749197, 29.199754], + [107.700537, 29.141228], + [107.659885, 29.162656], + [107.605683, 29.164747], + [107.589052, 29.150113], + [107.570574, 29.218037], + [107.486806, 29.174153], + [107.441227, 29.203934], + [107.401807, 29.184603], + [107.408582, 29.138091], + [107.427676, 29.128682], + [107.412278, 29.094696], + [107.369778, 29.091558], + [107.395647, 29.041341], + [107.364235, 29.00942], + [107.396879, 28.993718], + [107.412894, 28.960211], + [107.441227, 28.943977], + [107.41351, 28.911502], + [107.383945, 28.848618], + [107.339597, 28.845997], + [107.327894, 28.810869], + [107.261373, 28.792514], + [107.24659, 28.76209], + [107.219489, 28.772582], + [107.210866, 28.817686], + [107.227496, 28.836037], + [107.194851, 28.838134], + [107.206554, 28.868535], + [107.14188, 28.887925], + [107.016229, 28.882685], + [107.019308, 28.861722], + [106.983584, 28.851239], + [106.988512, 28.776254], + [106.951555, 28.766812], + [106.923222, 28.809821], + [106.872099, 28.777304], + [106.845614, 28.780975], + [106.824056, 28.756319], + [106.86594, 28.690192], + [106.889345, 28.695966], + [106.866556, 28.624548], + [106.830831, 28.623497], + [106.807425, 28.589346], + [106.784636, 28.626649], + [106.756918, 28.607211], + [106.77786, 28.563068], + [106.73844, 28.554657], + [106.726121, 28.51838], + [106.747063, 28.467361], + [106.708259, 28.450524], + [106.697788, 28.47683], + [106.632499, 28.503655], + [106.564745, 28.485247], + [106.567825, 28.523638], + [106.615252, 28.549401], + [106.606629, 28.593024], + [106.63681, 28.622972], + [106.618332, 28.645033], + [106.651593, 28.649235], + [106.617716, 28.66709], + [106.6171, 28.691242], + [106.587535, 28.691767], + [106.56105, 28.719062], + [106.561666, 28.756319], + [106.474202, 28.832891], + [106.45326, 28.817162], + [106.461883, 28.761041], + [106.492064, 28.742153], + [106.528405, 28.677591], + [106.502535, 28.661313], + [106.49268, 28.591448], + [106.466811, 28.586193], + [106.504999, 28.544669], + [106.477282, 28.530474], + [106.403369, 28.569901], + [106.37442, 28.525742], + [106.379348, 28.479986], + [106.349167, 28.473674], + [106.304819, 28.505233], + [106.2925, 28.537309], + [106.254928, 28.539412], + [106.184711, 28.58882], + [106.17116, 28.629275], + [106.14837, 28.642932], + [106.103407, 28.636104], + [106.085544, 28.681792], + [106.030726, 28.694917], + [106.001161, 28.743727], + [105.966668, 28.761041], + [105.937719, 28.686517], + [105.889676, 28.670765], + [105.884748, 28.595126], + [105.808372, 28.599855], + [105.78435, 28.610889], + [105.757249, 28.590397], + [105.74493, 28.616668], + [105.712901, 28.586718], + [105.693191, 28.58882], + [105.68272, 28.534154], + [105.62359, 28.517854], + [105.612503, 28.438947], + [105.643916, 28.431053], + [105.655003, 28.362615], + [105.639604, 28.324164], + [105.68888, 28.284119], + [105.730147, 28.271997], + [105.737539, 28.30309], + [105.76464, 28.308359], + [105.76464, 28.308359], + [105.78743, 28.335753], + [105.824386, 28.306251], + [105.848408, 28.255656], + [105.889676, 28.237732], + [105.860727, 28.159672], + [105.895219, 28.119565], + [105.943878, 28.143314], + [105.975907, 28.107952], + [106.093552, 28.162837], + [106.145291, 28.162837], + [106.206885, 28.134343], + [106.266631, 28.066769], + [106.246305, 28.011835], + [106.286341, 28.007079], + [106.328225, 27.952643], + [106.307899, 27.936782], + [106.304819, 27.899237], + [106.325145, 27.898708], + [106.337464, 27.859033], + [106.306667, 27.808756], + [106.242609, 27.767459], + [106.193334, 27.75422], + [106.120653, 27.779638], + [106.063987, 27.776991], + [106.023335, 27.746805], + [105.985146, 27.749983], + [105.92848, 27.729855], + [105.922937, 27.746805], + [105.868118, 27.732504], + [105.848408, 27.707074], + [105.76772, 27.7182], + [105.722756, 27.706015], + [105.720292, 27.683759], + [105.664242, 27.683759], + [105.62359, 27.666269], + [105.605112, 27.715552], + [105.560148, 27.71979], + [105.508409, 27.769048], + [105.44004, 27.775402], + [105.353809, 27.748924], + [105.308229, 27.704955], + [105.29591, 27.631811], + [105.304533, 27.611661], + [105.25649, 27.582491], + [105.232469, 27.546945], + [105.260186, 27.514573], + [105.234316, 27.489093], + [105.233084, 27.436522], + [105.182577, 27.367451], + [105.184425, 27.392959], + [105.120984, 27.418461], + [105.068013, 27.418461], + [105.01073, 27.379143], + [104.913412, 27.327051], + [104.871528, 27.290891], + [104.851818, 27.299401], + [104.856746, 27.332368], + [104.824717, 27.3531], + [104.77113, 27.317481], + [104.7545, 27.345658], + [104.611602, 27.306846], + [104.570334, 27.331836], + [104.539537, 27.327583], + [104.497037, 27.414743], + [104.467472, 27.414211], + [104.363378, 27.467855], + [104.30856, 27.407305], + [104.295625, 27.37436], + [104.247582, 27.336621], + [104.248813, 27.291955], + [104.210625, 27.297273], + [104.173053, 27.263232], + [104.113923, 27.338216], + [104.084358, 27.330773], + [104.01722, 27.383926], + [104.015372, 27.429086], + [103.956242, 27.425367], + [103.932221, 27.443958], + [103.905119, 27.38552], + [103.903271, 27.347785], + [103.874322, 27.331304], + [103.865699, 27.28185], + [103.80041, 27.26536], + [103.801641, 27.250464], + [103.748671, 27.210021], + [103.696316, 27.126429], + [103.63349, 27.12057], + [103.620555, 27.096598], + [103.652584, 27.092868], + [103.659975, 27.065692], + [103.614396, 27.079548], + [103.601461, 27.061962], + [103.623635, 27.035312], + [103.623019, 27.007056], + [103.675374, 27.051836], + [103.704939, 27.049171], + [103.73204, 27.018785], + [103.753598, 26.963858], + [103.775156, 26.951056], + [103.763453, 26.905702], + [103.779468, 26.87421], + [103.722185, 26.851253], + [103.705555, 26.794642], + [103.725265, 26.742812], + [103.773308, 26.716621], + [103.759142, 26.689355], + [103.748671, 26.623568], + [103.763453, 26.585041], + [103.815808, 26.55239], + [103.819504, 26.529903], + [103.865699, 26.512232], + [103.953163, 26.521336], + [104.008597, 26.511697], + [104.067727, 26.51491], + [104.068343, 26.573266], + [104.121314, 26.638012], + [104.160734, 26.646571], + [104.222328, 26.620358], + [104.268524, 26.617683], + [104.274683, 26.633733], + [104.313487, 26.612867], + [104.353523, 26.620893], + [104.398487, 26.686147], + [104.424356, 26.709137], + [104.468088, 26.644431], + [104.459465, 26.602701], + [104.488414, 26.579689], + [104.556783, 26.590393], + [104.579573, 26.568449], + [104.57095, 26.524549], + [104.598667, 26.520801], + [104.638703, 26.477954], + [104.631928, 26.451702], + [104.665804, 26.434019], + [104.664572, 26.397572], + [104.684283, 26.3772], + [104.659645, 26.335373], + [104.592508, 26.317672], + [104.542616, 26.253282], + [104.548776, 26.226979], + [104.518595, 26.165762], + [104.52845, 26.114186], + [104.499501, 26.070651], + [104.460081, 26.085702], + [104.470552, 26.009352], + [104.438523, 25.92757], + [104.414501, 25.909807], + [104.441602, 25.868889], + [104.42374, 25.841961], + [104.397871, 25.76168], + [104.370769, 25.730415], + [104.328886, 25.760602], + [104.310407, 25.647901], + [104.332581, 25.598796], + [104.389248, 25.595558], + [104.428668, 25.576126], + [104.436059, 25.520512], + [104.418813, 25.499447], + [104.434827, 25.472436], + [104.44961, 25.495126], + [104.483486, 25.494585], + [104.524138, 25.526992], + [104.556783, 25.524832], + [104.543232, 25.400556], + [104.566638, 25.402719], + [104.615913, 25.364871], + [104.646094, 25.356759], + [104.639935, 25.295632], + [104.689826, 25.296173], + [104.736021, 25.268034], + [104.816094, 25.262622], + [104.826565, 25.235558], + [104.806854, 25.224189], + [104.822869, 25.170037], + [104.801927, 25.163537], + [104.753884, 25.214443], + [104.724319, 25.195491], + [104.732326, 25.167871], + [104.695369, 25.122364], + [104.685514, 25.078466], + [104.619609, 25.060577], + [104.684898, 25.054072], + [104.713232, 24.996048], + [104.663957, 24.964584], + [104.635623, 24.903803], + [104.586964, 24.872859], + [104.539537, 24.813663], + [104.542616, 24.75607], + [104.529682, 24.731611], + [104.595587, 24.709323], + [104.628848, 24.660927], + [104.703377, 24.645698], + [104.729246, 24.617953], + [104.771746, 24.659839], + [104.841963, 24.676155], + [104.865985, 24.730524], + [104.899245, 24.752809], + [105.03352, 24.787586], + [105.026745, 24.815836], + [105.039064, 24.872859], + [105.077868, 24.918459], + [105.09573, 24.92877], + [105.131454, 24.959701], + [105.157324, 24.958616], + [105.178266, 24.985199], + [105.212758, 24.995505], + [105.251563, 24.967296], + [105.267577, 24.929313], + [105.334099, 24.9266], + [105.365511, 24.943423], + [105.428337, 24.930941], + [105.457286, 24.87123], + [105.493011, 24.833217], + [105.497322, 24.809318], + [105.573083, 24.797366], + [105.607576, 24.803885], + [105.617431, 24.78161], + [105.70551, 24.768569], + [105.767104, 24.719109], + [105.827466, 24.702799], + [105.863806, 24.729437], + [105.942031, 24.725088], + [105.961741, 24.677786], + [106.024566, 24.633186], + [106.047356, 24.684312], + [106.113878, 24.714216], + [106.150218, 24.762591], + [106.173008, 24.760417], + [106.206269, 24.851139], + [106.197645, 24.885889], + [106.145291, 24.954275], + [106.191486, 24.95319], + [106.215508, 24.981944], + [106.253696, 24.971094], + [106.304819, 24.973807], + [106.332536, 24.988454], + [106.442173, 25.019369], + [106.450181, 25.033468], + [106.519782, 25.054072], + [106.551195, 25.082802], + [106.590615, 25.08768], + [106.63989, 25.132658], + [106.644817, 25.164621], + [106.691013, 25.179245], + [106.732281, 25.162454], + [106.764926, 25.183036], + [106.787715, 25.17112], + [106.853005, 25.186827], + [106.888113, 25.181953], + [106.904128, 25.231768], + [106.933077, 25.250714], + [106.975577, 25.232851], + [107.013765, 25.275611], + [107.012533, 25.352973], + [106.987896, 25.358922], + [106.963874, 25.437852], + [106.996519, 25.442716], + [107.015613, 25.495666], + [107.066736, 25.50917], + [107.064272, 25.559391], + [107.185612, 25.578825], + [107.205322, 25.607971], + [107.228728, 25.604733], + [107.232423, 25.556691], + [107.263836, 25.543193], + [107.336517, 25.461089], + [107.308184, 25.432988], + [107.318039, 25.401637], + [107.358691, 25.393528], + [107.375937, 25.411908], + [107.420901, 25.392987], + [107.409198, 25.347024], + [107.432604, 25.289139], + [107.481263, 25.299961], + [107.489886, 25.276693], + [107.472024, 25.213902], + [107.512676, 25.209029], + [107.576734, 25.256668], + [107.599523, 25.250714], + [107.632168, 25.310241], + [107.659885, 25.316192], + [107.661733, 25.258833], + [107.696226, 25.219858], + [107.700537, 25.194408], + [107.741805, 25.24043], + [107.762131, 25.229061], + [107.760283, 25.188451], + [107.789233, 25.15487], + [107.762747, 25.125073], + [107.839124, 25.115861], + [107.872384, 25.141327], + [107.928435, 25.155954], + [108.001732, 25.196574], + [108.080572, 25.193867], + [108.115065, 25.210112], + [108.143398, 25.269658], + [108.152021, 25.324306], + [108.142782, 25.390825], + [108.193289, 25.405421], + [108.162492, 25.444878], + [108.192673, 25.458928], + [108.251803, 25.430286], + [108.241332, 25.46217], + [108.280752, 25.48], + [108.308469, 25.525912], + [108.348506, 25.536173], + [108.359592, 25.513491], + [108.400244, 25.491344], + [108.418723, 25.443257], + [108.471693, 25.458928], + [108.585642, 25.365952], + [108.589338, 25.335125], + [108.625062, 25.308076], + [108.62999, 25.335666], + [108.600425, 25.432448], + [108.6072, 25.491885], + [108.634917, 25.520512], + [108.68912, 25.533473], + [108.658323, 25.550212], + [108.660787, 25.584763], + [108.68604, 25.587462], + [108.68912, 25.623081], + [108.724844, 25.634952], + [108.783975, 25.628477], + [108.799989, 25.576666], + [108.781511, 25.554531], + [108.814772, 25.526992], + [108.826474, 25.550212], + [108.890532, 25.556151], + [108.8893, 25.543193], + [108.949046, 25.557231], + [109.024807, 25.51241], + [109.088249, 25.550752], + [109.051908, 25.566949], + [109.030966, 25.629556], + [109.075314, 25.693749], + [109.07901, 25.72071], + [109.043285, 25.738502], + [109.007561, 25.734728], + [108.953974, 25.686738], + [108.953974, 25.686738], + [108.900387, 25.682423], + [108.896076, 25.71424], + [108.940423, 25.740119], + [108.963829, 25.732572], + [108.999553, 25.765453], + [108.989698, 25.778926], + [109.048213, 25.790781], + [109.077778, 25.776771], + [109.095024, 25.80533], + [109.143683, 25.795092], + [109.13198, 25.762758], + [109.147995, 25.741736], + [109.206509, 25.788087], + [109.207125, 25.740119], + [109.296436, 25.71424], + [109.340168, 25.731493], + [109.327849, 25.76168], + [109.339552, 25.83442], + [109.359262, 25.836036], + [109.396834, 25.900117], + [109.435022, 25.93349], + [109.408537, 25.967392], + [109.473211, 26.006663], + [109.48245, 26.029788], + [109.452885, 26.055598], + [109.449805, 26.101826], + [109.502776, 26.096451], + [109.513863, 26.128157], + [109.47629, 26.148035], + [109.439334, 26.238789], + [109.467051, 26.313917], + [109.442414, 26.289774], + [109.369733, 26.277432], + [109.351255, 26.264016], + [109.325385, 26.29031], + [109.285965, 26.295676], + [109.271183, 26.327863], + [109.29582, 26.350389], + [109.319842, 26.418477], + [109.38082, 26.454381], + [109.362342, 26.472061], + [109.385747, 26.493487], + [109.381436, 26.518659], + [109.407305, 26.533116], + [109.390675, 26.598955], + [109.35495, 26.658873], + [109.334008, 26.646036], + [109.306291, 26.661012], + [109.283501, 26.698445], + [109.35495, 26.693098], + [109.407305, 26.719829], + [109.447957, 26.759913], + [109.486761, 26.759913], + [109.47629, 26.829894], + [109.467051, 26.83203], + [109.452885, 26.861932], + [109.436254, 26.892359], + [109.555131, 26.946788], + [109.520022, 27.058764], + [109.497848, 27.079548], + [109.486761, 27.053968], + [109.454733, 27.069423], + [109.472595, 27.134951], + [109.441182, 27.117907], + [109.415312, 27.154123], + [109.358646, 27.153058], + [109.33524, 27.139212], + [109.264407, 27.131755], + [109.239154, 27.14933], + [109.21698, 27.114711], + [109.165857, 27.066758], + [109.101183, 27.06889], + [109.128901, 27.122701], + [109.032814, 27.104056], + [109.007561, 27.08008], + [108.940423, 27.044907], + [108.942887, 27.017186], + [108.942887, 27.017186], + [108.877597, 27.01612], + [108.79075, 27.084343], + [108.878829, 27.106187], + [108.926873, 27.160512], + [108.907778, 27.204699], + [108.963213, 27.235565], + [108.983539, 27.26802], + [109.053756, 27.293551], + [109.044517, 27.331304], + [109.103647, 27.336621], + [109.142451, 27.418461], + [109.141835, 27.448207], + [109.167089, 27.41793], + [109.202197, 27.450331], + [109.245313, 27.41793], + [109.300132, 27.423774], + [109.303211, 27.47582], + [109.404841, 27.55066], + [109.461508, 27.567637], + [109.451037, 27.586204], + [109.470131, 27.62863], + [109.45658, 27.673689], + [109.470747, 27.680049], + [109.414081, 27.725087], + [109.366653, 27.721909], + [109.37774, 27.736741], + [109.332777, 27.782815], + [109.346943, 27.838396], + [109.32169, 27.868027], + [109.30198, 27.956343], + [109.319842, 27.988585], + [109.362342, 28.007608], + [109.378972, 28.034551], + [109.335856, 28.063073], + [109.298284, 28.036136], + [109.314298, 28.103729], + [109.33832, 28.141731], + [109.340168, 28.19027], + [109.367885, 28.254602], + [109.388211, 28.268307], + [109.33524, 28.293605], + [109.317994, 28.277795], + [109.275494, 28.313101], + [109.268719, 28.33786], + [109.289045, 28.373673], + [109.264407, 28.392628], + [109.260712, 28.46473], + [109.274262, 28.494714] + ] + ], + [ + [ + [109.47629, 26.829894], + [109.486761, 26.759913], + [109.52187, 26.749226], + [109.522486, 26.749226], + [109.497232, 26.815474], + [109.513247, 26.84004], + [109.509551, 26.877947], + [109.486761, 26.895562], + [109.452885, 26.861932], + [109.467051, 26.83203], + [109.47629, 26.829894] + ] + ], + [ + [ + [109.528645, 26.743881], + [109.568065, 26.726243], + [109.597015, 26.756173], + [109.554515, 26.73533], + [109.528645, 26.743881] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 530000, + "name": "云南省", + "center": [102.712251, 25.040609], + "centroid": [101.485106, 25.008643], + "childrenNum": 16, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 24, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [105.308229, 27.704955], + [105.290367, 27.712373], + [105.293447, 27.770637], + [105.273736, 27.794992], + [105.313157, 27.810874], + [105.25957, 27.827811], + [105.233084, 27.895534], + [105.284823, 27.935725], + [105.270657, 27.99704], + [105.247867, 28.009193], + [105.218302, 27.990698], + [105.186273, 27.995454], + [105.167795, 28.021345], + [105.186889, 28.054623], + [105.168411, 28.071522], + [105.119752, 28.07205], + [105.061853, 28.096866], + [105.002107, 28.064129], + [104.980549, 28.063073], + [104.975006, 28.020816], + [104.903557, 27.962158], + [104.918339, 27.938897], + [104.888158, 27.914574], + [104.842579, 27.900294], + [104.796999, 27.901352], + [104.761891, 27.884426], + [104.743413, 27.901881], + [104.676275, 27.880723], + [104.63316, 27.850567], + [104.607906, 27.857974], + [104.573413, 27.840512], + [104.52537, 27.889187], + [104.508124, 27.878078], + [104.44961, 27.927794], + [104.40095, 27.952114], + [104.362762, 28.012891], + [104.30856, 28.036136], + [104.304248, 28.050926], + [104.373233, 28.051454], + [104.40095, 28.091586], + [104.448994, 28.113758], + [104.444682, 28.16231], + [104.406494, 28.173389], + [104.402182, 28.202928], + [104.442834, 28.211366], + [104.462544, 28.241422], + [104.44961, 28.269889], + [104.420045, 28.269889], + [104.392943, 28.291497], + [104.384936, 28.329959], + [104.343052, 28.334173], + [104.314103, 28.306778], + [104.282074, 28.343128], + [104.254357, 28.403683], + [104.267908, 28.499448], + [104.260516, 28.536257], + [104.323342, 28.540989], + [104.355987, 28.555183], + [104.375697, 28.5946], + [104.417581, 28.598279], + [104.425588, 28.626649], + [104.372617, 28.649235], + [104.314719, 28.615617], + [104.277147, 28.631902], + [104.252509, 28.660788], + [104.230951, 28.635579], + [104.170589, 28.642932], + [104.117618, 28.634003], + [104.09606, 28.603533], + [104.05972, 28.6277], + [103.953779, 28.600906], + [103.910047, 28.631377], + [103.887873, 28.61982], + [103.850917, 28.66709], + [103.833054, 28.605109], + [103.838598, 28.587244], + [103.802873, 28.563068], + [103.781931, 28.525216], + [103.829975, 28.459995], + [103.828743, 28.44], + [103.860156, 28.383677], + [103.85338, 28.356822], + [103.877402, 28.316262], + [103.828743, 28.285173], + [103.770845, 28.233514], + [103.740048, 28.23615], + [103.701859, 28.198709], + [103.692004, 28.232459], + [103.643961, 28.260401], + [103.573128, 28.230877], + [103.533092, 28.168641], + [103.470266, 28.122204], + [103.430846, 28.044587], + [103.459179, 28.021345], + [103.486281, 28.033495], + [103.515846, 27.965329], + [103.55465, 27.978543], + [103.502295, 27.910343], + [103.509686, 27.843687], + [103.487512, 27.794992], + [103.461027, 27.779638], + [103.393274, 27.709194], + [103.369868, 27.708664], + [103.349542, 27.678459], + [103.29226, 27.632872], + [103.2861, 27.561802], + [103.232514, 27.56976], + [103.19063, 27.523596], + [103.144434, 27.450331], + [103.141355, 27.420586], + [103.080992, 27.396679], + [103.055739, 27.40943], + [102.989833, 27.367983], + [102.941174, 27.405711], + [102.899906, 27.317481], + [102.883892, 27.299401], + [102.883276, 27.258444], + [102.904218, 27.227584], + [102.913457, 27.133886], + [102.870957, 27.026782], + [102.894979, 27.001724], + [102.896211, 26.91264], + [102.949181, 26.843244], + [102.966428, 26.837904], + [102.991681, 26.775409], + [102.983674, 26.76686], + [103.008312, 26.710741], + [103.005232, 26.679195], + [103.026174, 26.664221], + [103.035413, 26.556673], + [103.052659, 26.555602], + [103.052659, 26.514374], + [103.030485, 26.485989], + [102.989833, 26.482775], + [102.988602, 26.413117], + [102.998457, 26.371839], + [102.975667, 26.340736], + [102.893131, 26.338591], + [102.878964, 26.364332], + [102.833385, 26.306406], + [102.785342, 26.298895], + [102.739762, 26.268846], + [102.709581, 26.210336], + [102.659074, 26.221611], + [102.60056, 26.250598], + [102.638748, 26.307479], + [102.629509, 26.336982], + [102.570995, 26.362723], + [102.542046, 26.338591], + [102.440416, 26.300505], + [102.392372, 26.296749], + [102.349257, 26.244694], + [102.245163, 26.212483], + [102.242699, 26.190468], + [102.174946, 26.146961], + [102.152156, 26.10935], + [102.107808, 26.068501], + [102.080091, 26.065275], + [102.020961, 26.096451], + [101.954439, 26.084627], + [101.929186, 26.105588], + [101.899621, 26.099139], + [101.857737, 26.049146], + [101.835563, 26.04592], + [101.839875, 26.082477], + [101.796759, 26.114723], + [101.807846, 26.156093], + [101.773353, 26.168448], + [101.737013, 26.219463], + [101.690202, 26.241473], + [101.630455, 26.224832], + [101.586108, 26.279579], + [101.597195, 26.303187], + [101.64031, 26.318745], + [101.660636, 26.346635], + [101.635383, 26.357361], + [101.637847, 26.388995], + [101.565782, 26.454381], + [101.530057, 26.467239], + [101.506652, 26.499915], + [101.458608, 26.49563], + [101.422884, 26.53151], + [101.395783, 26.591998], + [101.402558, 26.604841], + [101.461688, 26.606447], + [101.461072, 26.640687], + [101.481398, 26.673313], + [101.453065, 26.692563], + [101.513427, 26.768463], + [101.466, 26.786629], + [101.445674, 26.77434], + [101.458608, 26.731054], + [101.435819, 26.740675], + [101.389623, 26.723036], + [101.387159, 26.753501], + [101.358826, 26.771669], + [101.399478, 26.841642], + [101.365602, 26.883819], + [101.311399, 26.903034], + [101.267667, 26.903034], + [101.264587, 26.955323], + [101.227015, 26.959057], + [101.228863, 26.981992], + [101.136472, 27.023584], + [101.157414, 27.094999], + [101.145095, 27.103523], + [101.170349, 27.175421], + [101.167885, 27.198311], + [101.167885, 27.198311], + [101.119226, 27.208957], + [101.071798, 27.194585], + [101.042233, 27.22173], + [101.026219, 27.270679], + [101.021907, 27.332899], + [100.95169, 27.426961], + [100.936908, 27.469448], + [100.901183, 27.453517], + [100.91227, 27.521473], + [100.854988, 27.623858], + [100.827886, 27.615904], + [100.848212, 27.672099], + [100.782307, 27.691708], + [100.775532, 27.743098], + [100.757053, 27.770107], + [100.707162, 27.800816], + [100.719481, 27.858503], + [100.681293, 27.923035], + [100.634482, 27.915631], + [100.609228, 27.859033], + [100.54517, 27.809286], + [100.511294, 27.827811], + [100.504518, 27.852154], + [100.442924, 27.86644], + [100.412127, 27.816167], + [100.350534, 27.755809], + [100.327744, 27.72032], + [100.311729, 27.724028], + [100.304954, 27.788639], + [100.28586, 27.80611], + [100.30865, 27.830457], + [100.30865, 27.861149], + [100.210715, 27.87702], + [100.170063, 27.907699], + [100.196549, 27.936254], + [100.120788, 28.018703], + [100.088759, 28.029269], + [100.05673, 28.097922], + [100.021006, 28.147008], + [100.033325, 28.184467], + [100.062274, 28.193962], + [100.091223, 28.181302], + [100.102926, 28.201873], + [100.153433, 28.208202], + [100.188541, 28.252493], + [100.147274, 28.288862], + [100.176223, 28.325218], + [100.136803, 28.349975], + [100.057346, 28.368934], + [100.073977, 28.426317], + [99.990209, 28.47683], + [99.985281, 28.529422], + [99.91876, 28.599329], + [99.875644, 28.611939], + [99.873181, 28.631902], + [99.834376, 28.628225], + [99.834992, 28.660788], + [99.79434, 28.699116], + [99.755536, 28.701216], + [99.722275, 28.757369], + [99.717964, 28.846521], + [99.676696, 28.810345], + [99.625573, 28.81454], + [99.609559, 28.784122], + [99.614486, 28.740054], + [99.553508, 28.710664], + [99.53195, 28.677591], + [99.540573, 28.623497], + [99.504233, 28.619294], + [99.466045, 28.579886], + [99.463581, 28.549401], + [99.403219, 28.546246], + [99.396444, 28.491032], + [99.426625, 28.454207], + [99.404451, 28.44421], + [99.437095, 28.398419], + [99.392748, 28.318369], + [99.412458, 28.295186], + [99.374886, 28.18183], + [99.306516, 28.227714], + [99.28927, 28.286227], + [99.237531, 28.317842], + [99.229524, 28.350502], + [99.200575, 28.365774], + [99.16485, 28.425264], + [99.187024, 28.44], + [99.191952, 28.494714], + [99.170394, 28.566221], + [99.183944, 28.58882], + [99.147604, 28.640831], + [99.126662, 28.698066], + [99.134053, 28.734806], + [99.114343, 28.765763], + [99.103872, 28.841803], + [99.123582, 28.890021], + [99.132206, 28.94869], + [99.113727, 29.07273], + [99.118039, 29.100971], + [99.105104, 29.162656], + [99.113727, 29.221171], + [99.037351, 29.20759], + [99.024416, 29.188783], + [98.9813, 29.204978], + [98.960974, 29.165792], + [98.967134, 29.128159], + [98.991771, 29.105677], + [99.013329, 29.036632], + [98.925866, 28.978536], + [98.917859, 28.886877], + [98.973909, 28.864867], + [98.972677, 28.832367], + [98.922786, 28.823978], + [98.912931, 28.800906], + [98.852569, 28.798283], + [98.827932, 28.821356], + [98.821772, 28.920931], + [98.786048, 28.998952], + [98.757714, 29.004186], + [98.70228, 28.9644], + [98.655469, 28.976966], + [98.624056, 28.95864], + [98.6567, 28.910454], + [98.643766, 28.895261], + [98.668403, 28.843376], + [98.652389, 28.817162], + [98.683802, 28.740054], + [98.666555, 28.712239], + [98.594491, 28.667615], + [98.637606, 28.552029], + [98.619128, 28.50944], + [98.625903, 28.489455], + [98.673947, 28.478934], + [98.693041, 28.43158], + [98.740468, 28.348395], + [98.746628, 28.321003], + [98.710287, 28.288862], + [98.712135, 28.229296], + [98.649925, 28.200291], + [98.625903, 28.165475], + [98.559382, 28.182885], + [98.494092, 28.141203], + [98.464527, 28.151229], + [98.428803, 28.104785], + [98.389383, 28.114814], + [98.389999, 28.16442], + [98.370289, 28.18394], + [98.37768, 28.246167], + [98.353042, 28.293078], + [98.317934, 28.324691], + [98.301303, 28.384204], + [98.208913, 28.358401], + [98.207681, 28.330486], + [98.231702, 28.314681], + [98.266811, 28.242477], + [98.21692, 28.212949], + [98.169492, 28.206093], + [98.17442, 28.163365], + [98.139311, 28.142259], + [98.160253, 28.101089], + [98.133152, 27.990698], + [98.143007, 27.948942], + [98.187355, 27.939426], + [98.205217, 27.889716], + [98.169492, 27.851096], + [98.215688, 27.810874], + [98.234166, 27.690648], + [98.283441, 27.654608], + [98.310542, 27.583552], + [98.317318, 27.51935], + [98.337644, 27.508734], + [98.388767, 27.515104], + [98.429419, 27.549068], + [98.430035, 27.653547], + [98.444201, 27.665209], + [98.474998, 27.634462], + [98.53536, 27.620676], + [98.554454, 27.646126], + [98.587099, 27.587265], + [98.583404, 27.571351], + [98.650541, 27.567637], + [98.662244, 27.586734], + [98.706591, 27.553313], + [98.685034, 27.484315], + [98.704744, 27.462014], + [98.686881, 27.425367], + [98.702896, 27.412618], + [98.706591, 27.362136], + [98.741084, 27.330241], + [98.734925, 27.287168], + [98.717062, 27.271211], + [98.723222, 27.221198], + [98.696121, 27.211086], + [98.713983, 27.139744], + [98.712751, 27.075817], + [98.765722, 27.05077], + [98.762642, 27.018252], + [98.732461, 27.002257], + [98.757098, 26.877947], + [98.730613, 26.851253], + [98.762026, 26.798916], + [98.746012, 26.696841], + [98.770033, 26.690424], + [98.762642, 26.660478], + [98.781736, 26.620893], + [98.773113, 26.578083], + [98.753403, 26.559349], + [98.757098, 26.491881], + [98.741084, 26.432947], + [98.750323, 26.424372], + [98.733693, 26.350926], + [98.681338, 26.308016], + [98.672715, 26.239863], + [98.713367, 26.231274], + [98.735541, 26.185097], + [98.712751, 26.156093], + [98.720142, 26.127082], + [98.661012, 26.087852], + [98.656084, 26.139977], + [98.632679, 26.145887], + [98.575396, 26.118485], + [98.602498, 26.054523], + [98.614201, 25.968468], + [98.637606, 25.971696], + [98.686881, 25.925955], + [98.705976, 25.855426], + [98.677642, 25.816105], + [98.640686, 25.798864], + [98.553839, 25.845731], + [98.529201, 25.840884], + [98.476846, 25.77731], + [98.461448, 25.735267], + [98.457752, 25.682963], + [98.409709, 25.664084], + [98.402317, 25.593939], + [98.326557, 25.566409], + [98.314854, 25.543193], + [98.247717, 25.607971], + [98.170724, 25.620383], + [98.189818, 25.569108], + [98.163949, 25.524292], + [98.131304, 25.51025], + [98.15779, 25.457307], + [98.137464, 25.381633], + [98.101123, 25.388662], + [98.099891, 25.354055], + [98.06971, 25.311864], + [98.006884, 25.298338], + [98.0075, 25.279399], + [97.940363, 25.214985], + [97.904023, 25.216609], + [97.875689, 25.25721], + [97.839349, 25.27074], + [97.796233, 25.155954], + [97.743262, 25.078466], + [97.719857, 25.080634], + [97.727864, 25.04377], + [97.716777, 24.978147], + [97.729712, 24.908689], + [97.785762, 24.876117], + [97.797465, 24.845709], + [97.765436, 24.823984], + [97.680437, 24.827243], + [97.652103, 24.790846], + [97.569567, 24.765852], + [97.547394, 24.739221], + [97.569567, 24.708236], + [97.570799, 24.602719], + [97.554785, 24.490577], + [97.530147, 24.443187], + [97.588662, 24.435559], + [97.669966, 24.452993], + [97.679821, 24.401228], + [97.716161, 24.358711], + [97.662574, 24.339083], + [97.665038, 24.296544], + [97.721089, 24.295999], + [97.767284, 24.258357], + [97.729712, 24.227252], + [97.72848, 24.183585], + [97.754349, 24.163929], + [97.748806, 24.160653], + [97.743262, 24.159561], + [97.730944, 24.113685], + [97.700763, 24.093473], + [97.697067, 24.092927], + [97.637321, 24.04812], + [97.628698, 24.004938], + [97.572647, 23.983068], + [97.529531, 23.943146], + [97.5283, 23.926736], + [97.618227, 23.888438], + [97.640401, 23.866001], + [97.647176, 23.840823], + [97.684132, 23.876946], + [97.718009, 23.867643], + [97.72848, 23.895551], + [97.763588, 23.907041], + [97.795617, 23.951897], + [97.8104, 23.943146], + [97.863371, 23.978693], + [97.896015, 23.974319], + [97.902175, 24.014231], + [97.984095, 24.031177], + [97.995182, 24.04648], + [98.091268, 24.085824], + [98.096196, 24.08637], + [98.123297, 24.092927], + [98.125761, 24.092927], + [98.132536, 24.09238], + [98.19721, 24.09839], + [98.219999, 24.113685], + [98.343187, 24.098936], + [98.37768, 24.114232], + [98.48239, 24.122425], + [98.487933, 24.123517], + [98.547063, 24.128433], + [98.593875, 24.08036], + [98.646229, 24.106038], + [98.681954, 24.100029], + [98.71891, 24.127887], + [98.818692, 24.133348], + [98.841482, 24.126794], + [98.876591, 24.15137], + [98.895069, 24.098936], + [98.807606, 24.025164], + [98.773729, 24.022431], + [98.727533, 23.970491], + [98.701048, 23.981427], + [98.673331, 23.960647], + [98.701048, 23.946427], + [98.68565, 23.90157], + [98.701664, 23.834254], + [98.669019, 23.800857], + [98.696121, 23.784429], + [98.784816, 23.781691], + [98.824236, 23.727462], + [98.811917, 23.703354], + [98.835939, 23.683625], + [98.847026, 23.632097], + [98.882134, 23.620035], + [98.882134, 23.595358], + [98.844562, 23.578904], + [98.80391, 23.540504], + [98.826084, 23.470257], + [98.874743, 23.483431], + [98.912315, 23.426333], + [98.920938, 23.360971], + [98.872895, 23.329651], + [98.906772, 23.331849], + [98.936953, 23.309866], + [98.928946, 23.26589], + [98.889525, 23.209249], + [98.906772, 23.185595], + [99.002242, 23.160287], + [99.057677, 23.164689], + [99.048438, 23.11461], + [99.106336, 23.086536], + [99.187024, 23.100299], + [99.255393, 23.077727], + [99.281879, 23.101399], + [99.3484, 23.12892], + [99.380429, 23.099748], + [99.440791, 23.079379], + [99.477747, 23.083233], + [99.528255, 23.065614], + [99.517168, 23.006685], + [99.533798, 22.961507], + [99.563363, 22.925684], + [99.531334, 22.897019], + [99.446951, 22.934503], + [99.43648, 22.913557], + [99.462965, 22.844635], + [99.401371, 22.826434], + [99.385357, 22.761882], + [99.326842, 22.751396], + [99.31514, 22.737598], + [99.339777, 22.708894], + [99.385973, 22.57136], + [99.359487, 22.535435], + [99.382277, 22.493418], + [99.297277, 22.41156], + [99.251698, 22.393301], + [99.278183, 22.34626], + [99.233836, 22.296434], + [99.235683, 22.250468], + [99.207966, 22.232188], + [99.175321, 22.185647], + [99.188256, 22.162924], + [99.156227, 22.159599], + [99.219669, 22.110816], + [99.294814, 22.109152], + [99.35456, 22.095845], + [99.400139, 22.100281], + [99.486987, 22.128557], + [99.516552, 22.099726], + [99.562747, 22.113034], + [99.578762, 22.098617], + [99.581841, 22.103053], + [99.648979, 22.100835], + [99.696406, 22.067562], + [99.762927, 22.068117], + [99.870101, 22.029288], + [99.871333, 22.067007], + [99.972347, 22.053141], + [99.965571, 22.014309], + [100.000064, 21.973245], + [99.982202, 21.919401], + [99.960028, 21.907186], + [99.944014, 21.821097], + [99.991441, 21.703821], + [100.049339, 21.669899], + [100.094303, 21.702709], + [100.131875, 21.699929], + [100.169447, 21.663225], + [100.107853, 21.585337], + [100.123252, 21.565302], + [100.131259, 21.504066], + [100.168831, 21.482906], + [100.184846, 21.516315], + [100.206404, 21.509634], + [100.235353, 21.466756], + [100.298795, 21.477894], + [100.349302, 21.528564], + [100.437381, 21.533017], + [100.48296, 21.458958], + [100.526692, 21.471211], + [100.579047, 21.451717], + [100.691764, 21.510748], + [100.730568, 21.518542], + [100.753358, 21.555283], + [100.789082, 21.570867], + [100.804481, 21.609821], + [100.847597, 21.634856], + [100.870386, 21.67268], + [100.896872, 21.68269], + [100.899335, 21.684915], + [100.936292, 21.694368], + [100.937524, 21.693812], + [101.015132, 21.707157], + [101.089661, 21.773865], + [101.123537, 21.771642], + [101.111835, 21.746074], + [101.116762, 21.691032], + [101.153102, 21.669343], + [101.169117, 21.590345], + [101.146943, 21.560293], + [101.209153, 21.55751], + [101.210385, 21.509077], + [101.225167, 21.499055], + [101.193138, 21.473996], + [101.194986, 21.424979], + [101.142631, 21.409379], + [101.183899, 21.334699], + [101.244877, 21.302364], + [101.246725, 21.275598], + [101.222088, 21.234324], + [101.290457, 21.17853], + [101.387775, 21.225956], + [101.439514, 21.227072], + [101.532521, 21.252174], + [101.601506, 21.233208], + [101.588572, 21.191365], + [101.605818, 21.172392], + [101.672339, 21.194713], + [101.703136, 21.14616], + [101.76473, 21.147835], + [101.794911, 21.208104], + [101.834331, 21.204756], + [101.833715, 21.252731], + [101.791832, 21.285636], + [101.745636, 21.297345], + [101.730238, 21.336929], + [101.749948, 21.409379], + [101.741324, 21.482906], + [101.772737, 21.512975], + [101.755491, 21.538027], + [101.754875, 21.58478], + [101.804766, 21.577546], + [101.828788, 21.617054], + [101.807846, 21.644313], + [101.780129, 21.640975], + [101.76781, 21.716054], + [101.747484, 21.729953], + [101.771506, 21.833319], + [101.740093, 21.845541], + [101.735165, 21.875534], + [101.700057, 21.897191], + [101.701288, 21.938832], + [101.666796, 21.934391], + [101.606434, 21.967695], + [101.626144, 22.005986], + [101.573789, 22.115251], + [101.602738, 22.131883], + [101.596579, 22.161262], + [101.547304, 22.238282], + [101.56455, 22.269299], + [101.625528, 22.28259], + [101.671723, 22.372826], + [101.648318, 22.400494], + [101.672339, 22.47517], + [101.715455, 22.477935], + [101.774585, 22.506135], + [101.824476, 22.45692], + [101.823244, 22.42705], + [101.862665, 22.389427], + [101.901469, 22.384447], + [101.907628, 22.437007], + [101.978461, 22.427603], + [102.046214, 22.458026], + [102.131214, 22.430922], + [102.145381, 22.397727], + [102.179257, 22.430369], + [102.270416, 22.419858], + [102.25625, 22.457473], + [102.322771, 22.554227], + [102.356648, 22.563623], + [102.404691, 22.629925], + [102.384365, 22.679631], + [102.43672, 22.699508], + [102.45951, 22.762986], + [102.510633, 22.774574], + [102.551285, 22.743669], + [102.569763, 22.701164], + [102.607335, 22.730975], + [102.657226, 22.687913], + [102.688639, 22.70006], + [102.80074, 22.620534], + [102.82353, 22.623296], + [102.880196, 22.586832], + [102.892515, 22.533223], + [102.930703, 22.482359], + [102.986754, 22.477935], + [103.030485, 22.441432], + [103.081608, 22.454154], + [103.071753, 22.488441], + [103.183238, 22.558649], + [103.161065, 22.590147], + [103.195557, 22.648153], + [103.220195, 22.643734], + [103.283021, 22.678526], + [103.288564, 22.732078], + [103.321209, 22.777885], + [103.323057, 22.807678], + [103.375411, 22.794989], + [103.441317, 22.753052], + [103.436389, 22.6973], + [103.457947, 22.658646], + [103.50907, 22.601198], + [103.529396, 22.59291], + [103.580519, 22.66693], + [103.567585, 22.701164], + [103.642113, 22.794989], + [103.740048, 22.709446], + [103.743127, 22.697852], + [103.766533, 22.688465], + [103.825047, 22.615562], + [103.863851, 22.584069], + [103.875554, 22.565833], + [103.894032, 22.564728], + [103.964865, 22.502265], + [104.009213, 22.517745], + [104.009213, 22.575228], + [104.022148, 22.593463], + [104.04309, 22.67687], + [104.045553, 22.728215], + [104.089901, 22.768504], + [104.117618, 22.808781], + [104.224176, 22.826434], + [104.261748, 22.841877], + [104.274067, 22.828088], + [104.256821, 22.77347], + [104.272835, 22.73815], + [104.323342, 22.728767], + [104.375697, 22.690122], + [104.422508, 22.734838], + [104.498885, 22.774574], + [104.527834, 22.814298], + [104.596203, 22.846289], + [104.674428, 22.817056], + [104.737869, 22.825882], + [104.732942, 22.852356], + [104.760659, 22.862282], + [104.772362, 22.893711], + [104.846275, 22.926235], + [104.860441, 22.970874], + [104.821021, 23.032022], + [104.804391, 23.110207], + [104.874608, 23.123417], + [104.882615, 23.163589], + [104.912796, 23.175693], + [104.949136, 23.152033], + [104.958991, 23.188896], + [105.093266, 23.260942], + [105.122215, 23.247745], + [105.181962, 23.279084], + [105.238012, 23.26424], + [105.260186, 23.31811], + [105.325475, 23.390086], + [105.353809, 23.362069], + [105.372903, 23.317561], + [105.416018, 23.283482], + [105.445584, 23.292827], + [105.50225, 23.202648], + [105.542902, 23.184495], + [105.526272, 23.234548], + [105.560148, 23.257093], + [105.593409, 23.312614], + [105.649459, 23.346136], + [105.699966, 23.327453], + [105.694423, 23.363168], + [105.637757, 23.404366], + [105.699966, 23.40162], + [105.758481, 23.459826], + [105.805908, 23.467512], + [105.815763, 23.507031], + [105.852103, 23.526786], + [105.89214, 23.52514], + [105.913081, 23.499348], + [105.935871, 23.508678], + [105.986378, 23.489469], + [105.999929, 23.447748], + [106.039965, 23.484529], + [106.071994, 23.495506], + [106.08616, 23.524043], + [106.141595, 23.569579], + [106.120653, 23.605229], + [106.149602, 23.665538], + [106.157609, 23.724175], + [106.136667, 23.795381], + [106.192102, 23.824947], + [106.173008, 23.861622], + [106.192718, 23.879135], + [106.157609, 23.891174], + [106.128044, 23.956819], + [106.091088, 23.998924], + [106.096631, 24.018058], + [106.053516, 24.051399], + [106.04982, 24.089649], + [106.011632, 24.099482], + [105.998081, 24.120786], + [105.963589, 24.110954], + [105.919241, 24.122425], + [105.901995, 24.099482], + [105.908154, 24.069432], + [105.89214, 24.040468], + [105.859495, 24.056864], + [105.841633, 24.03063], + [105.796669, 24.023524], + [105.802212, 24.051945], + [105.765256, 24.073804], + [105.739387, 24.059596], + [105.704278, 24.0667], + [105.649459, 24.032816], + [105.628518, 24.126794], + [105.594641, 24.137718], + [105.533663, 24.130071], + [105.493011, 24.016965], + [105.406163, 24.043748], + [105.395692, 24.065607], + [105.334099, 24.094566], + [105.320548, 24.116416], + [105.273121, 24.092927], + [105.292831, 24.074896], + [105.260186, 24.061236], + [105.20044, 24.105491], + [105.182577, 24.167205], + [105.229389, 24.165567], + [105.24294, 24.208695], + [105.215222, 24.214699], + [105.164715, 24.288362], + [105.196744, 24.326541], + [105.188121, 24.347261], + [105.138846, 24.376701], + [105.111744, 24.37234], + [105.106817, 24.414853], + [105.042759, 24.442097], + [104.979933, 24.412673], + [104.930042, 24.411038], + [104.914028, 24.426296], + [104.83642, 24.446456], + [104.784681, 24.443732], + [104.765587, 24.45953], + [104.74834, 24.435559], + [104.715695, 24.441552], + [104.703377, 24.419757], + [104.721239, 24.340173], + [104.70892, 24.321087], + [104.641783, 24.367979], + [104.610986, 24.377246], + [104.63008, 24.397958], + [104.616529, 24.421937], + [104.575877, 24.424661], + [104.550008, 24.518894], + [104.520443, 24.535228], + [104.489646, 24.653313], + [104.529682, 24.731611], + [104.542616, 24.75607], + [104.539537, 24.813663], + [104.586964, 24.872859], + [104.635623, 24.903803], + [104.663957, 24.964584], + [104.713232, 24.996048], + [104.684898, 25.054072], + [104.619609, 25.060577], + [104.685514, 25.078466], + [104.695369, 25.122364], + [104.732326, 25.167871], + [104.724319, 25.195491], + [104.753884, 25.214443], + [104.801927, 25.163537], + [104.822869, 25.170037], + [104.806854, 25.224189], + [104.826565, 25.235558], + [104.816094, 25.262622], + [104.736021, 25.268034], + [104.689826, 25.296173], + [104.639935, 25.295632], + [104.646094, 25.356759], + [104.615913, 25.364871], + [104.566638, 25.402719], + [104.543232, 25.400556], + [104.556783, 25.524832], + [104.524138, 25.526992], + [104.483486, 25.494585], + [104.44961, 25.495126], + [104.434827, 25.472436], + [104.418813, 25.499447], + [104.436059, 25.520512], + [104.428668, 25.576126], + [104.389248, 25.595558], + [104.332581, 25.598796], + [104.310407, 25.647901], + [104.328886, 25.760602], + [104.370769, 25.730415], + [104.397871, 25.76168], + [104.42374, 25.841961], + [104.441602, 25.868889], + [104.414501, 25.909807], + [104.438523, 25.92757], + [104.470552, 26.009352], + [104.460081, 26.085702], + [104.499501, 26.070651], + [104.52845, 26.114186], + [104.518595, 26.165762], + [104.548776, 26.226979], + [104.542616, 26.253282], + [104.592508, 26.317672], + [104.659645, 26.335373], + [104.684283, 26.3772], + [104.664572, 26.397572], + [104.665804, 26.434019], + [104.631928, 26.451702], + [104.638703, 26.477954], + [104.598667, 26.520801], + [104.57095, 26.524549], + [104.579573, 26.568449], + [104.556783, 26.590393], + [104.488414, 26.579689], + [104.459465, 26.602701], + [104.468088, 26.644431], + [104.424356, 26.709137], + [104.398487, 26.686147], + [104.353523, 26.620893], + [104.313487, 26.612867], + [104.274683, 26.633733], + [104.268524, 26.617683], + [104.222328, 26.620358], + [104.160734, 26.646571], + [104.121314, 26.638012], + [104.068343, 26.573266], + [104.067727, 26.51491], + [104.008597, 26.511697], + [103.953163, 26.521336], + [103.865699, 26.512232], + [103.819504, 26.529903], + [103.815808, 26.55239], + [103.763453, 26.585041], + [103.748671, 26.623568], + [103.759142, 26.689355], + [103.773308, 26.716621], + [103.725265, 26.742812], + [103.705555, 26.794642], + [103.722185, 26.851253], + [103.779468, 26.87421], + [103.763453, 26.905702], + [103.775156, 26.951056], + [103.753598, 26.963858], + [103.73204, 27.018785], + [103.704939, 27.049171], + [103.675374, 27.051836], + [103.623019, 27.007056], + [103.623635, 27.035312], + [103.601461, 27.061962], + [103.614396, 27.079548], + [103.659975, 27.065692], + [103.652584, 27.092868], + [103.620555, 27.096598], + [103.63349, 27.12057], + [103.696316, 27.126429], + [103.748671, 27.210021], + [103.801641, 27.250464], + [103.80041, 27.26536], + [103.865699, 27.28185], + [103.874322, 27.331304], + [103.903271, 27.347785], + [103.905119, 27.38552], + [103.932221, 27.443958], + [103.956242, 27.425367], + [104.015372, 27.429086], + [104.01722, 27.383926], + [104.084358, 27.330773], + [104.113923, 27.338216], + [104.173053, 27.263232], + [104.210625, 27.297273], + [104.248813, 27.291955], + [104.247582, 27.336621], + [104.295625, 27.37436], + [104.30856, 27.407305], + [104.363378, 27.467855], + [104.467472, 27.414211], + [104.497037, 27.414743], + [104.539537, 27.327583], + [104.570334, 27.331836], + [104.611602, 27.306846], + [104.7545, 27.345658], + [104.77113, 27.317481], + [104.824717, 27.3531], + [104.856746, 27.332368], + [104.851818, 27.299401], + [104.871528, 27.290891], + [104.913412, 27.327051], + [105.01073, 27.379143], + [105.068013, 27.418461], + [105.120984, 27.418461], + [105.184425, 27.392959], + [105.182577, 27.367451], + [105.233084, 27.436522], + [105.234316, 27.489093], + [105.260186, 27.514573], + [105.232469, 27.546945], + [105.25649, 27.582491], + [105.304533, 27.611661], + [105.29591, 27.631811], + [105.308229, 27.704955] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 540000, + "name": "西藏自治区", + "center": [91.132212, 29.660361], + "centroid": [88.388277, 31.56375], + "childrenNum": 7, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 25, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [89.711414, 36.093272], + [89.614711, 36.109712], + [89.594385, 36.126632], + [89.490291, 36.151281], + [89.375727, 36.228078], + [89.335075, 36.23725], + [89.292575, 36.231457], + [89.232213, 36.295636], + [89.198952, 36.260417], + [89.126887, 36.254626], + [89.10225, 36.281164], + [89.054822, 36.291777], + [89.013554, 36.315409], + [88.964279, 36.318785], + [88.926091, 36.36458], + [88.870657, 36.348193], + [88.838628, 36.353496], + [88.802903, 36.33807], + [88.783809, 36.291777], + [88.766563, 36.292259], + [88.690186, 36.367954], + [88.623665, 36.389636], + [88.618121, 36.428168], + [88.573158, 36.461386], + [88.498629, 36.446463], + [88.470912, 36.48208], + [88.41055, 36.473418], + [88.356963, 36.477268], + [88.366202, 36.458016], + [88.282434, 36.470049], + [88.241782, 36.468605], + [88.222688, 36.447426], + [88.182652, 36.452721], + [88.134609, 36.427205], + [88.092109, 36.43539], + [88.006494, 36.430575], + [87.983088, 36.437797], + [87.95845, 36.408423], + [87.919646, 36.39349], + [87.838342, 36.383855], + [87.826023, 36.391563], + [87.767509, 36.3747], + [87.731785, 36.384818], + [87.6203, 36.360243], + [87.570409, 36.342409], + [87.470626, 36.354459], + [87.460155, 36.409868], + [87.426895, 36.42576], + [87.386859, 36.412757], + [87.363453, 36.420463], + [87.348055, 36.393008], + [87.292004, 36.358797], + [87.193454, 36.349158], + [87.161425, 36.325535], + [87.149106, 36.297565], + [87.08628, 36.310587], + [87.051788, 36.2966], + [86.996353, 36.308658], + [86.943998, 36.284058], + [86.931064, 36.265242], + [86.887332, 36.262829], + [86.86331, 36.299977], + [86.836209, 36.291294], + [86.746282, 36.291777], + [86.69947, 36.24449], + [86.599072, 36.222285], + [86.531935, 36.227113], + [86.515305, 36.205385], + [86.454943, 36.221319], + [86.392733, 36.206834], + [86.35824, 36.168676], + [86.2794, 36.170608], + [86.248603, 36.141616], + [86.187625, 36.130983], + [86.182081, 36.064734], + [86.199944, 36.047801], + [86.173458, 36.008113], + [86.150668, 36.00424], + [86.129111, 35.941761], + [86.093386, 35.906868], + [86.090306, 35.876809], + [86.05335, 35.842857], + [86.035488, 35.846738], + [85.949256, 35.778794], + [85.903677, 35.78462], + [85.835308, 35.771996], + [85.811286, 35.778794], + [85.691178, 35.751114], + [85.65299, 35.731199], + [85.612953, 35.651486], + [85.566142, 35.6403], + [85.518715, 35.680658], + [85.373969, 35.700101], + [85.341324, 35.753543], + [85.271107, 35.788989], + [85.146071, 35.742371], + [85.053065, 35.752086], + [84.99455, 35.737028], + [84.973608, 35.709334], + [84.920022, 35.696213], + [84.798066, 35.647595], + [84.729081, 35.613546], + [84.704443, 35.616951], + [84.628067, 35.595055], + [84.570168, 35.588242], + [84.513502, 35.564391], + [84.448828, 35.550272], + [84.475929, 35.516181], + [84.45314, 35.473303], + [84.424191, 35.466479], + [84.333032, 35.413821], + [84.274517, 35.404065], + [84.200605, 35.381135], + [84.160569, 35.359663], + [84.140859, 35.379184], + [84.095895, 35.362592], + [84.077417, 35.400163], + [84.005968, 35.422599], + [83.906186, 35.40309], + [83.885244, 35.367472], + [83.79778, 35.354783], + [83.785462, 35.36308], + [83.677672, 35.361128], + [83.622238, 35.335256], + [83.599448, 35.351366], + [83.54155, 35.341603], + [83.540318, 35.364056], + [83.502745, 35.360639], + [83.449159, 35.382111], + [83.405427, 35.380648], + [83.333978, 35.397236], + [83.280391, 35.401138], + [83.251442, 35.417722], + [83.178145, 35.38943], + [83.127022, 35.398699], + [83.088834, 35.425526], + [83.067892, 35.46258], + [82.998907, 35.484512], + [82.971806, 35.548324], + [82.981661, 35.599922], + [82.956407, 35.636409], + [82.967494, 35.667532], + [82.894813, 35.673852], + [82.873871, 35.688922], + [82.795031, 35.688436], + [82.780249, 35.666073], + [82.731589, 35.637868], + [82.652133, 35.67288], + [82.628727, 35.692324], + [82.546192, 35.708362], + [82.501844, 35.701073], + [82.468583, 35.717595], + [82.424852, 35.712736], + [82.392823, 35.656349], + [82.336156, 35.651486], + [82.350323, 35.611113], + [82.328149, 35.559523], + [82.2992, 35.544916], + [82.263475, 35.547837], + [82.234526, 35.520565], + [82.189563, 35.513258], + [82.164925, 35.495719], + [82.086701, 35.467454], + [82.071302, 35.450393], + [82.034346, 35.451855], + [82.029419, 35.426013], + [82.05344, 35.35039], + [82.030034, 35.321585], + [81.99123, 35.30547], + [81.955506, 35.307423], + [81.927789, 35.271275], + [81.853876, 35.25857], + [81.804601, 35.270786], + [81.736847, 35.26248], + [81.68634, 35.235599], + [81.513261, 35.23511], + [81.504638, 35.279092], + [81.447972, 35.318167], + [81.441196, 35.333303], + [81.385762, 35.335256], + [81.363588, 35.354783], + [81.314313, 35.337209], + [81.285364, 35.345508], + [81.26627, 35.322562], + [81.219458, 35.319144], + [81.191741, 35.36552], + [81.142466, 35.365032], + [81.103662, 35.386015], + [81.09935, 35.40748], + [81.054387, 35.402602], + [81.031597, 35.380648], + [81.030981, 35.337209], + [81.002648, 35.334768], + [81.026053, 35.31133], + [80.963844, 35.310842], + [80.924423, 35.330862], + [80.894242, 35.324027], + [80.844351, 35.345508], + [80.759968, 35.334768], + [80.689135, 35.339162], + [80.690982, 35.364544], + [80.65649, 35.393821], + [80.599823, 35.409431], + [80.56841, 35.391381], + [80.532686, 35.404553], + [80.514824, 35.391869], + [80.444607, 35.417235], + [80.432904, 35.449418], + [80.375006, 35.387966], + [80.321419, 35.38699], + [80.286926, 35.35283], + [80.267832, 35.295701], + [80.362687, 35.20871], + [80.257977, 35.203331], + [80.223484, 35.177409], + [80.23026, 35.147565], + [80.118159, 35.066293], + [80.078123, 35.076578], + [80.031311, 35.034447], + [80.04363, 35.022196], + [80.02392, 34.971209], + [80.041782, 34.943252], + [80.034391, 34.902033], + [80.003594, 34.895162], + [79.996819, 34.856375], + [79.961094, 34.862759], + [79.926602, 34.849499], + [79.947544, 34.821008], + [79.898268, 34.732035], + [79.906892, 34.683821], + [79.866856, 34.671517], + [79.88595, 34.642965], + [79.84345, 34.55725], + [79.861312, 34.528166], + [79.801566, 34.478847], + [79.735661, 34.471447], + [79.699936, 34.477861], + [79.675914, 34.451216], + [79.58106, 34.456151], + [79.545335, 34.476381], + [79.504683, 34.45467], + [79.435082, 34.447761], + [79.363017, 34.428018], + [79.326677, 34.44332], + [79.274322, 34.435916], + [79.241677, 34.415183], + [79.179467, 34.422588], + [79.161605, 34.441345], + [79.072294, 34.412714], + [79.039033, 34.421601], + [79.0107, 34.399877], + [79.048888, 34.348506], + [79.039649, 34.33467], + [79.019939, 34.313417], + [78.981751, 34.31836], + [78.958345, 34.230827], + [78.941099, 34.212022], + [78.9257, 34.155584], + [78.910302, 34.143202], + [78.878273, 34.163012], + [78.828998, 34.125369], + [78.801897, 34.137258], + [78.737223, 34.089692], + [78.661462, 34.086718], + [78.656535, 34.030196], + [78.736607, 33.999937], + [78.744614, 33.980585], + [78.734143, 33.918529], + [78.762476, 33.90959], + [78.756317, 33.8773], + [78.766172, 33.823124], + [78.758165, 33.790802], + [78.779723, 33.73259], + [78.692259, 33.676331], + [78.684868, 33.654415], + [78.713201, 33.623025], + [78.755085, 33.623025], + [78.74215, 33.55323], + [78.816679, 33.480882], + [78.84994, 33.419963], + [78.896751, 33.41247], + [78.949722, 33.376495], + [78.9682, 33.334505], + [79.022403, 33.323504], + [79.041497, 33.268479], + [79.083997, 33.245459], + [79.072294, 33.22844], + [79.10925, 33.200401], + [79.152366, 33.184375], + [79.162221, 33.165841], + [79.139431, 33.117735], + [79.162837, 33.01191], + [79.204721, 32.964724], + [79.255844, 32.942628], + [79.227511, 32.89038], + [79.237982, 32.846145], + [79.225047, 32.784281], + [79.275554, 32.778746], + [79.301423, 32.728919], + [79.27309, 32.678056], + [79.299575, 32.637244], + [79.308199, 32.596918], + [79.272474, 32.561113], + [79.252148, 32.516715], + [79.190554, 32.511669], + [79.180083, 32.492994], + [79.135736, 32.472295], + [79.124649, 32.416235], + [79.103091, 32.369744], + [79.067982, 32.380863], + [79.005772, 32.375304], + [78.970664, 32.331826], + [78.904142, 32.374798], + [78.87273, 32.40512], + [78.81052, 32.436441], + [78.782186, 32.480373], + [78.760629, 32.563635], + [78.781571, 32.608009], + [78.74215, 32.654881], + [78.741534, 32.703743], + [78.6861, 32.680071], + [78.675013, 32.658408], + [78.628202, 32.630188], + [78.588782, 32.637748], + [78.577695, 32.615067], + [78.518564, 32.605993], + [78.500086, 32.580782], + [78.424942, 32.565652], + [78.395377, 32.530339], + [78.426174, 32.502584], + [78.472985, 32.435431], + [78.458818, 32.379853], + [78.483456, 32.357106], + [78.480992, 32.329297], + [78.508709, 32.297939], + [78.475449, 32.236708], + [78.430485, 32.212407], + [78.429869, 32.194683], + [78.469905, 32.127808], + [78.509941, 32.147065], + [78.527188, 32.11463], + [78.609107, 32.052768], + [78.60726, 32.023851], + [78.705194, 31.988835], + [78.762476, 31.947203], + [78.768636, 31.92638], + [78.739687, 31.885228], + [78.665158, 31.851684], + [78.654687, 31.819144], + [78.706426, 31.778453], + [78.763092, 31.668499], + [78.798817, 31.675629], + [78.806824, 31.64099], + [78.845628, 31.609905], + [78.833925, 31.584927], + [78.779723, 31.545154], + [78.740303, 31.532912], + [78.729832, 31.478316], + [78.755701, 31.478316], + [78.792041, 31.435944], + [78.760013, 31.392531], + [78.755085, 31.355742], + [78.795121, 31.301043], + [78.859179, 31.289281], + [78.865338, 31.312804], + [78.884432, 31.277006], + [78.923852, 31.246824], + [78.930628, 31.220726], + [78.997765, 31.158779], + [78.97436, 31.115751], + [79.010084, 31.043994], + [79.059359, 31.028097], + [79.096931, 30.992192], + [79.181931, 31.015788], + [79.205953, 31.0004], + [79.227511, 30.949088], + [79.33222, 30.969103], + [79.316206, 31.01784], + [79.35809, 31.031174], + [79.404901, 31.071678], + [79.424611, 31.061425], + [79.427075, 31.018353], + [79.505915, 31.027584], + [79.550879, 30.957813], + [79.59769, 30.925989], + [79.660516, 30.956787], + [79.668523, 30.980392], + [79.729501, 30.941389], + [79.75845, 30.936769], + [79.835443, 30.851006], + [79.890877, 30.855116], + [79.913051, 30.833022], + [79.900732, 30.7991], + [79.961094, 30.771337], + [79.955551, 30.738422], + [79.970333, 30.685941], + [80.014065, 30.661748], + [80.04363, 30.603559], + [80.143412, 30.55822], + [80.214245, 30.586044], + [80.261673, 30.566465], + [80.322035, 30.564403], + [80.357759, 30.520592], + [80.43044, 30.515952], + [80.446454, 30.495327], + [80.504969, 30.483466], + [80.549316, 30.448905], + [80.585041, 30.463866], + [80.633084, 30.458707], + [80.692214, 30.416913], + [80.719316, 30.414848], + [80.81725, 30.321389], + [80.910873, 30.30279], + [80.933662, 30.266614], + [80.996488, 30.267648], + [81.034677, 30.246971], + [81.038372, 30.205086], + [81.082104, 30.151281], + [81.085799, 30.100554], + [81.110437, 30.085538], + [81.09627, 30.052909], + [81.131995, 30.016124], + [81.225618, 30.005759], + [81.256415, 30.011978], + [81.247792, 30.032705], + [81.2829, 30.061197], + [81.293371, 30.094859], + [81.269349, 30.153351], + [81.335871, 30.149729], + [81.393769, 30.199396], + [81.397465, 30.240767], + [81.419023, 30.270232], + [81.406088, 30.291938], + [81.427646, 30.305373], + [81.399929, 30.319323], + [81.406088, 30.369421], + [81.432573, 30.379231], + [81.406704, 30.40401], + [81.418407, 30.420525], + [81.454131, 30.412268], + [81.494783, 30.381296], + [81.555761, 30.369421], + [81.566232, 30.428782], + [81.613044, 30.412784], + [81.63029, 30.446842], + [81.723913, 30.407623], + [81.759021, 30.385426], + [81.872354, 30.373035], + [81.939491, 30.344633], + [81.954274, 30.355995], + [81.99123, 30.322939], + [82.022027, 30.339468], + [82.060215, 30.332237], + [82.104563, 30.346182], + [82.132896, 30.30434], + [82.11873, 30.279019], + [82.114418, 30.226806], + [82.142135, 30.200948], + [82.188947, 30.18543], + [82.207425, 30.143519], + [82.183403, 30.12178], + [82.17786, 30.06793], + [82.246845, 30.071555], + [82.311519, 30.035813], + [82.333693, 30.045138], + [82.368185, 30.014051], + [82.412533, 30.011978], + [82.431011, 29.989692], + [82.474743, 29.973622], + [82.498148, 29.947698], + [82.560974, 29.955476], + [82.609017, 29.886489], + [82.64351, 29.868846], + [82.6238, 29.834588], + [82.703872, 29.847566], + [82.737749, 29.80655], + [82.691553, 29.766037], + [82.757459, 29.761881], + [82.774089, 29.726548], + [82.816589, 29.717192], + [82.830756, 29.687562], + [82.885574, 29.689122], + [82.9484, 29.704718], + [82.966878, 29.658963], + [83.011226, 29.667804], + [83.088834, 29.604863], + [83.12887, 29.623593], + [83.159667, 29.61735], + [83.164595, 29.595496], + [83.217565, 29.60018], + [83.266841, 29.571035], + [83.27608, 29.505951], + [83.325355, 29.502826], + [83.383253, 29.42206], + [83.415898, 29.420496], + [83.423289, 29.361053], + [83.450391, 29.332883], + [83.463941, 29.285916], + [83.492274, 29.280174], + [83.548941, 29.201322], + [83.57789, 29.203934], + [83.596368, 29.174153], + [83.656114, 29.16736], + [83.667201, 29.200277], + [83.727563, 29.244672], + [83.800244, 29.249372], + [83.82057, 29.294267], + [83.851367, 29.294789], + [83.911729, 29.323491], + [83.949301, 29.312533], + [83.986874, 29.325057], + [84.002272, 29.291658], + [84.052163, 29.296877], + [84.116837, 29.286438], + [84.130388, 29.239972], + [84.203068, 29.239972], + [84.197525, 29.210202], + [84.17104, 29.19453], + [84.176583, 29.133909], + [84.20738, 29.118749], + [84.192597, 29.084236], + [84.194445, 29.045004], + [84.224626, 29.049189], + [84.248648, 29.030353], + [84.228322, 28.949738], + [84.234481, 28.889497], + [84.268358, 28.895261], + [84.330568, 28.859101], + [84.340423, 28.866963], + [84.408176, 28.85386], + [84.404481, 28.828173], + [84.434046, 28.823978], + [84.445133, 28.764189], + [84.483321, 28.735331], + [84.557233, 28.74635], + [84.620059, 28.732182], + [84.650856, 28.714338], + [84.669334, 28.680742], + [84.699515, 28.671816], + [84.698284, 28.633478], + [84.773428, 28.610363], + [84.857196, 28.567798], + [84.896616, 28.587244], + [84.981616, 28.586193], + [84.995782, 28.611414], + [85.05676, 28.674441], + [85.126361, 28.676016], + [85.155926, 28.643983], + [85.195963, 28.624022], + [85.18426, 28.587244], + [85.189803, 28.544669], + [85.160238, 28.49261], + [85.108499, 28.461047], + [85.129441, 28.377885], + [85.113427, 28.344708], + [85.179948, 28.324164], + [85.209513, 28.338914], + [85.272339, 28.282538], + [85.349947, 28.298347], + [85.379512, 28.274105], + [85.415853, 28.321003], + [85.458969, 28.332593], + [85.520563, 28.326798], + [85.602483, 28.295712], + [85.601251, 28.254075], + [85.650526, 28.283592], + [85.682555, 28.375779], + [85.720743, 28.372093], + [85.753388, 28.227714], + [85.791576, 28.195544], + [85.854402, 28.172334], + [85.871648, 28.124843], + [85.898749, 28.101617], + [85.901213, 28.053566], + [85.980053, 27.984357], + [85.949256, 27.937311], + [86.002227, 27.90717], + [86.053966, 27.900823], + [86.125415, 27.923035], + [86.082915, 28.018175], + [86.086611, 28.090002], + [86.128495, 28.086835], + [86.140198, 28.114814], + [86.19132, 28.167058], + [86.223965, 28.092642], + [86.206103, 28.084195], + [86.231972, 27.974315], + [86.27324, 27.976958], + [86.308965, 27.950528], + [86.393349, 27.926736], + [86.414906, 27.904526], + [86.450015, 27.908757], + [86.475884, 27.944713], + [86.514689, 27.954757], + [86.513457, 27.996511], + [86.537478, 28.044587], + [86.55842, 28.047757], + [86.568891, 28.103201], + [86.60092, 28.097922], + [86.611391, 28.069938], + [86.647732, 28.06941], + [86.662514, 28.092114], + [86.700086, 28.101617], + [86.74813, 28.089474], + [86.768456, 28.06941], + [86.756753, 28.032967], + [86.827586, 28.012363], + [86.864542, 28.022401], + [86.885484, 27.995983], + [86.926752, 27.985942], + [86.935375, 27.955286], + [87.035157, 27.946299], + [87.080737, 27.910872], + [87.118309, 27.840512], + [87.173744, 27.818284], + [87.227946, 27.812991], + [87.249504, 27.839454], + [87.280917, 27.845275], + [87.317258, 27.826753], + [87.364069, 27.824106], + [87.421967, 27.856916], + [87.418272, 27.825694], + [87.45954, 27.820931], + [87.58088, 27.859562], + [87.598126, 27.814579], + [87.670191, 27.832045], + [87.668343, 27.809815], + [87.727473, 27.802933], + [87.77798, 27.860091], + [87.782292, 27.890774], + [87.826639, 27.927794], + [87.930733, 27.909285], + [87.982472, 27.884426], + [88.037291, 27.901881], + [88.090877, 27.885484], + [88.111819, 27.864852], + [88.137689, 27.878607], + [88.120442, 27.915103], + [88.156783, 27.957929], + [88.203594, 27.943127], + [88.242398, 27.967444], + [88.254101, 27.939426], + [88.357579, 27.986471], + [88.401311, 27.976958], + [88.43334, 28.002852], + [88.469064, 28.009721], + [88.498013, 28.04089], + [88.554064, 28.027684], + [88.565151, 28.083139], + [88.620585, 28.091586], + [88.645223, 28.111119], + [88.67602, 28.068353], + [88.764099, 28.068353], + [88.812142, 28.018175], + [88.842939, 28.006023], + [88.846635, 27.921448], + [88.864497, 27.921448], + [88.888519, 27.846863], + [88.863265, 27.811932], + [88.870657, 27.743098], + [88.850331, 27.710783], + [88.852178, 27.671039], + [88.816454, 27.641354], + [88.813374, 27.606889], + [88.770874, 27.563924], + [88.797976, 27.521473], + [88.783193, 27.467324], + [88.809063, 27.405711], + [88.838012, 27.37808], + [88.867577, 27.3818], + [88.901453, 27.327583], + [88.920548, 27.325456], + [88.911924, 27.272807], + [88.942105, 27.261636], + [88.984605, 27.208957], + [89.067757, 27.240354], + [89.077612, 27.287168], + [89.152757, 27.319076], + [89.182938, 27.373829], + [89.132431, 27.441302], + [89.095474, 27.471572], + [89.109025, 27.537925], + [89.163228, 27.574534], + [89.128735, 27.611131], + [89.131815, 27.633402], + [89.184786, 27.673689], + [89.238988, 27.796581], + [89.295655, 27.84845], + [89.375727, 27.875962], + [89.44348, 27.968501], + [89.461958, 28.03191], + [89.511233, 28.086307], + [89.541414, 28.088418], + [89.605472, 28.161782], + [89.720037, 28.170224], + [89.779167, 28.197127], + [89.789638, 28.240895], + [89.869094, 28.221386], + [89.901739, 28.18183], + [89.976268, 28.189215], + [90.017536, 28.162837], + [90.03355, 28.136981], + [90.07297, 28.155451], + [90.103151, 28.141731], + [90.124709, 28.190797], + [90.166593, 28.187632], + [90.189999, 28.161782], + [90.231882, 28.144897], + [90.297172, 28.153868], + [90.367389, 28.088946], + [90.384019, 28.06096], + [90.43699, 28.063073], + [90.47949, 28.044587], + [90.513983, 28.062016], + [90.569417, 28.044059], + [90.591591, 28.021345], + [90.701844, 28.076274], + [90.741264, 28.053038], + [90.802242, 28.040362], + [90.806554, 28.015005], + [90.853365, 27.969029], + [90.896481, 27.946299], + [90.96177, 27.9537], + [90.976553, 27.935725], + [90.96485, 27.900294], + [91.025828, 27.857445], + [91.113292, 27.846333], + [91.155175, 27.894476], + [91.147784, 27.927794], + [91.162567, 27.968501], + [91.216153, 27.989113], + [91.251878, 27.970615], + [91.309776, 28.057791], + [91.464993, 28.002852], + [91.490246, 27.971672], + [91.486551, 27.937311], + [91.552456, 27.90717], + [91.611586, 27.891303], + [91.618978, 27.856916], + [91.561079, 27.855329], + [91.544449, 27.820401], + [91.610355, 27.819343], + [91.642383, 27.7664], + [91.622673, 27.692238], + [91.570934, 27.650897], + [91.562311, 27.627569], + [91.582637, 27.598933], + [91.564775, 27.58196], + [91.585101, 27.540578], + [91.626985, 27.509265], + [91.663325, 27.507142], + [91.71876, 27.467324], + [91.753868, 27.462545], + [91.839484, 27.489624], + [91.946657, 27.464138], + [92.010715, 27.474758], + [92.021802, 27.444489], + [92.064918, 27.391365], + [92.125896, 27.273339], + [92.091403, 27.264296], + [92.071077, 27.237694], + [92.061222, 27.190327], + [92.032273, 27.167967], + [92.02673, 27.108318], + [92.043976, 27.052902], + [92.076005, 27.041175], + [92.124664, 26.960124], + [92.109265, 26.854991], + [92.197961, 26.86994], + [92.28604, 26.892359], + [92.404916, 26.9025], + [92.496691, 26.921711], + [92.549046, 26.941453], + [92.64698, 26.952656], + [92.682089, 26.947855], + [92.802813, 26.895028], + [92.909371, 26.914241], + [93.050421, 26.883819], + [93.111399, 26.880082], + [93.232739, 26.906769], + [93.56781, 26.938252], + [93.625092, 26.955323], + [93.747048, 27.015587], + [93.817265, 27.025183], + [93.841903, 27.045973], + [93.849294, 27.168499], + [93.970634, 27.30525], + [94.056866, 27.375423], + [94.147409, 27.458297], + [94.220705, 27.536333], + [94.277372, 27.58143], + [94.353132, 27.578778], + [94.399944, 27.589386], + [94.443675, 27.585143], + [94.478168, 27.602116], + [94.524979, 27.596282], + [94.660486, 27.650367], + [94.722696, 27.683759], + [94.78121, 27.699127], + [94.836645, 27.728796], + [94.88592, 27.743098], + [94.947514, 27.792345], + [95.015267, 27.82887], + [95.067006, 27.840512], + [95.28628, 27.939955], + [95.32878, 28.017646], + [95.352802, 28.04089], + [95.371896, 28.110063], + [95.39715, 28.142259], + [95.437802, 28.161782], + [95.528345, 28.182885], + [95.674322, 28.254075], + [95.740228, 28.275159], + [95.787655, 28.270416], + [95.832003, 28.295186], + [95.874502, 28.29782], + [95.899756, 28.278322], + [95.907763, 28.241422], + [95.936096, 28.240368], + [95.989067, 28.198181], + [96.074683, 28.193434], + [96.098088, 28.212421], + [96.194175, 28.212949], + [96.275479, 28.228241], + [96.298269, 28.140148], + [96.367254, 28.118509], + [96.398667, 28.118509], + [96.395587, 28.143842], + [96.426384, 28.161782], + [96.46334, 28.143314], + [96.499681, 28.067297], + [96.538485, 28.075218], + [96.623485, 28.024514], + [96.635188, 27.994926], + [96.690622, 27.948942], + [96.711564, 27.9574], + [96.784245, 27.931495], + [96.810114, 27.890245], + [96.849534, 27.874375], + [96.908049, 27.884426], + [96.972722, 27.861149], + [97.008447, 27.807698], + [97.049099, 27.81405], + [97.062649, 27.742568], + [97.097758, 27.740979], + [97.103301, 27.780697], + [97.167975, 27.811932], + [97.253591, 27.891832], + [97.303482, 27.913516], + [97.324424, 27.880723], + [97.386634, 27.882839], + [97.372467, 27.907699], + [97.379242, 27.970087], + [97.413119, 28.01342], + [97.378626, 28.031382], + [97.375547, 28.062545], + [97.320728, 28.054095], + [97.305945, 28.071522], + [97.340438, 28.104785], + [97.326887, 28.132759], + [97.352757, 28.149646], + [97.362612, 28.199236], + [97.349677, 28.235623], + [97.398336, 28.238786], + [97.402032, 28.279903], + [97.422358, 28.297293], + [97.461162, 28.26778], + [97.469169, 28.30309], + [97.518445, 28.327852], + [97.488879, 28.347341], + [97.485184, 28.38631], + [97.499966, 28.428948], + [97.521524, 28.444736], + [97.507974, 28.46473], + [97.521524, 28.495766], + [97.569567, 28.541515], + [97.60406, 28.515225], + [97.634857, 28.532051], + [97.68598, 28.519958], + [97.737103, 28.465782], + [97.738335, 28.396313], + [97.769748, 28.3742], + [97.801161, 28.326798], + [97.842429, 28.326798], + [97.871378, 28.361561], + [97.907718, 28.363141], + [98.020435, 28.253548], + [98.008116, 28.214003], + [98.03337, 28.187105], + [98.056775, 28.202401], + [98.090036, 28.195544], + [98.097427, 28.166531], + [98.139311, 28.142259], + [98.17442, 28.163365], + [98.169492, 28.206093], + [98.21692, 28.212949], + [98.266811, 28.242477], + [98.231702, 28.314681], + [98.207681, 28.330486], + [98.208913, 28.358401], + [98.301303, 28.384204], + [98.317934, 28.324691], + [98.353042, 28.293078], + [98.37768, 28.246167], + [98.370289, 28.18394], + [98.389999, 28.16442], + [98.389383, 28.114814], + [98.428803, 28.104785], + [98.464527, 28.151229], + [98.494092, 28.141203], + [98.559382, 28.182885], + [98.625903, 28.165475], + [98.649925, 28.200291], + [98.712135, 28.229296], + [98.710287, 28.288862], + [98.746628, 28.321003], + [98.740468, 28.348395], + [98.693041, 28.43158], + [98.673947, 28.478934], + [98.625903, 28.489455], + [98.619128, 28.50944], + [98.637606, 28.552029], + [98.594491, 28.667615], + [98.666555, 28.712239], + [98.683802, 28.740054], + [98.652389, 28.817162], + [98.668403, 28.843376], + [98.643766, 28.895261], + [98.6567, 28.910454], + [98.624056, 28.95864], + [98.655469, 28.976966], + [98.70228, 28.9644], + [98.757714, 29.004186], + [98.786048, 28.998952], + [98.821772, 28.920931], + [98.827932, 28.821356], + [98.852569, 28.798283], + [98.912931, 28.800906], + [98.922786, 28.823978], + [98.972677, 28.832367], + [98.973909, 28.864867], + [98.917859, 28.886877], + [98.925866, 28.978536], + [99.013329, 29.036632], + [98.991771, 29.105677], + [98.967134, 29.128159], + [98.960974, 29.165792], + [98.9813, 29.204978], + [99.024416, 29.188783], + [99.037351, 29.20759], + [99.113727, 29.221171], + [99.114343, 29.243628], + [99.075539, 29.316186], + [99.058909, 29.417368], + [99.066916, 29.421018], + [99.044742, 29.520013], + [99.052133, 29.563748], + [99.014561, 29.607464], + [98.992387, 29.677163], + [99.018873, 29.792009], + [99.0238, 29.846009], + [99.068148, 29.931621], + [99.055213, 29.958587], + [99.036735, 30.053945], + [99.044742, 30.079842], + [98.989308, 30.151799], + [98.9813, 30.182843], + [98.993003, 30.215429], + [98.970829, 30.260928], + [98.986844, 30.280569], + [98.967134, 30.33482], + [98.965286, 30.449937], + [98.932025, 30.521623], + [98.926482, 30.569556], + [98.939417, 30.598923], + [98.92217, 30.609225], + [98.907388, 30.698292], + [98.963438, 30.728134], + [98.957895, 30.765166], + [98.904924, 30.782649], + [98.850105, 30.849465], + [98.797135, 30.87926], + [98.774345, 30.908019], + [98.797135, 30.948575], + [98.806374, 30.995783], + [98.774961, 31.031174], + [98.736772, 31.049121], + [98.712135, 31.082954], + [98.710287, 31.1178], + [98.675179, 31.15417], + [98.602498, 31.192062], + [98.62344, 31.221238], + [98.60373, 31.257568], + [98.616048, 31.3036], + [98.643766, 31.338876], + [98.691809, 31.333253], + [98.773113, 31.249382], + [98.805758, 31.279052], + [98.810685, 31.306668], + [98.887062, 31.37465], + [98.84333, 31.416028], + [98.844562, 31.429817], + [98.714599, 31.508935], + [98.696736, 31.538523], + [98.651157, 31.57881], + [98.619128, 31.591555], + [98.553839, 31.660349], + [98.545831, 31.717383], + [98.516882, 31.717383], + [98.508875, 31.751995], + [98.461448, 31.800327], + [98.414636, 31.832365], + [98.426339, 31.856767], + [98.399238, 31.895899], + [98.432498, 31.922825], + [98.434962, 32.007613], + [98.402933, 32.026896], + [98.404781, 32.045159], + [98.357354, 32.087253], + [98.303151, 32.121726], + [98.260035, 32.208862], + [98.218768, 32.234683], + [98.23047, 32.262521], + [98.208913, 32.318171], + [98.218768, 32.342444], + [98.125145, 32.401077], + [98.107283, 32.391476], + [98.079565, 32.415224], + [97.940363, 32.482393], + [97.880001, 32.486431], + [97.863986, 32.499051], + [97.80732, 32.50006], + [97.795617, 32.521257], + [97.730944, 32.527312], + [97.684132, 32.530339], + [97.670582, 32.51722], + [97.540618, 32.536899], + [97.50243, 32.530844], + [97.463626, 32.55506], + [97.448843, 32.586833], + [97.411887, 32.575235], + [97.374315, 32.546484], + [97.3583, 32.563635], + [97.332431, 32.542448], + [97.334895, 32.514192], + [97.388481, 32.501575], + [97.341054, 32.440987], + [97.387865, 32.427349], + [97.424822, 32.322723], + [97.415583, 32.296421], + [97.371235, 32.273148], + [97.32196, 32.303503], + [97.299786, 32.294904], + [97.264062, 32.182527], + [97.271453, 32.139971], + [97.313953, 32.130342], + [97.293011, 32.096887], + [97.308409, 32.076605], + [97.258518, 32.072041], + [97.219714, 32.109054], + [97.201852, 32.090296], + [97.233881, 32.063927], + [97.214786, 32.042623], + [97.188301, 32.055304], + [97.169823, 32.032984], + [97.127323, 32.044145], + [97.028773, 32.04871], + [97.006599, 32.067984], + [96.935766, 32.048203], + [96.965947, 32.008628], + [96.941925, 31.986297], + [96.894498, 32.013703], + [96.863085, 31.996448], + [96.868629, 31.964975], + [96.824281, 32.007613], + [96.722651, 32.013195], + [96.742977, 32.001016], + [96.753448, 31.944156], + [96.776238, 31.935015], + [96.81073, 31.894375], + [96.794716, 31.869474], + [96.760223, 31.860325], + [96.765767, 31.819144], + [96.799027, 31.792188], + [96.840295, 31.720438], + [96.790404, 31.698545], + [96.778701, 31.675629], + [96.722651, 31.686833], + [96.691854, 31.722474], + [96.661057, 31.705674], + [96.615477, 31.737236], + [96.56805, 31.711783], + [96.519391, 31.74945], + [96.468884, 31.769804], + [96.435623, 31.796258], + [96.407906, 31.845583], + [96.389428, 31.919777], + [96.288414, 31.919777], + [96.253305, 31.929936], + [96.220044, 31.905553], + [96.188632, 31.904028], + [96.214501, 31.876589], + [96.202798, 31.841008], + [96.183088, 31.835924], + [96.178161, 31.775401], + [96.231131, 31.749959], + [96.222508, 31.733164], + [96.252073, 31.697527], + [96.245298, 31.657802], + [96.221892, 31.647613], + [96.207726, 31.598691], + [96.156603, 31.602769], + [96.148595, 31.686324], + [96.135661, 31.70211], + [96.064828, 31.720438], + [95.989067, 31.78761], + [95.983524, 31.816601], + [95.89914, 31.81711], + [95.846169, 31.736218], + [95.853561, 31.714329], + [95.823995, 31.68225], + [95.779648, 31.748941], + [95.634286, 31.782523], + [95.580083, 31.76726], + [95.546823, 31.73978], + [95.511714, 31.750468], + [95.480301, 31.795749], + [95.456896, 31.801853], + [95.406389, 31.896915], + [95.408852, 31.918761], + [95.3682, 31.92892], + [95.360809, 31.95939], + [95.395918, 32.001523], + [95.454432, 32.007613], + [95.421171, 32.033999], + [95.454432, 32.061898], + [95.440265, 32.157705], + [95.406389, 32.182021], + [95.367584, 32.178982], + [95.366968, 32.151118], + [95.31523, 32.148585], + [95.270266, 32.194683], + [95.270266, 32.194683], + [95.239469, 32.287315], + [95.241317, 32.3207], + [95.214216, 32.321712], + [95.20744, 32.297433], + [95.10581, 32.258979], + [95.079325, 32.279726], + [95.096571, 32.322217], + [95.193274, 32.332331], + [95.261643, 32.348006], + [95.228382, 32.363678], + [95.218527, 32.397035], + [95.153853, 32.386423], + [95.081789, 32.384907], + [95.075013, 32.376315], + [95.075013, 32.376315], + [95.057151, 32.395014], + [94.988166, 32.422802], + [94.944434, 32.404109], + [94.912405, 32.41573], + [94.889616, 32.472295], + [94.852043, 32.463712], + [94.80708, 32.486431], + [94.78737, 32.522266], + [94.762116, 32.526303], + [94.737479, 32.587338], + [94.638312, 32.645307], + [94.614291, 32.673522], + [94.591501, 32.640772], + [94.522516, 32.595909], + [94.459074, 32.599439], + [94.463386, 32.572209], + [94.435052, 32.562626], + [94.395016, 32.594397], + [94.371611, 32.524789], + [94.350053, 32.533871], + [94.294002, 32.519743], + [94.292154, 32.502584], + [94.250886, 32.51722], + [94.196684, 32.51621], + [94.176974, 32.454117], + [94.137554, 32.433915], + [94.091974, 32.463207], + [94.049474, 32.469771], + [94.03038, 32.448057], + [93.978641, 32.459672], + [93.960163, 32.484917], + [93.90904, 32.463207], + [93.861613, 32.466237], + [93.851142, 32.50965], + [93.820345, 32.549511], + [93.75136, 32.56313], + [93.721795, 32.578261], + [93.651577, 32.571705], + [93.618933, 32.522771], + [93.516687, 32.47583], + [93.501904, 32.503593], + [93.476651, 32.504603], + [93.4631, 32.556069], + [93.411977, 32.558086], + [93.385492, 32.525294], + [93.33868, 32.5712], + [93.308499, 32.580278], + [93.300492, 32.619604], + [93.260456, 32.62666], + [93.239514, 32.662439], + [93.210565, 32.655385], + [93.176688, 32.6705], + [93.159442, 32.644803], + [93.087993, 32.63674], + [93.069515, 32.626156], + [93.023935, 32.703239], + [93.019624, 32.737477], + [93.00053, 32.741001], + [92.964189, 32.714821], + [92.933392, 32.719353], + [92.866871, 32.698203], + [92.822523, 32.729926], + [92.789262, 32.719856], + [92.756618, 32.743014], + [92.686401, 32.76516], + [92.667922, 32.73194], + [92.634662, 32.720863], + [92.574916, 32.741001], + [92.56814, 32.73194], + [92.484372, 32.745028], + [92.459119, 32.76365], + [92.411076, 32.748048], + [92.355641, 32.764657], + [92.343938, 32.738484], + [92.310062, 32.751571], + [92.255243, 32.720863], + [92.198577, 32.754591], + [92.211511, 32.788306], + [92.193649, 32.801889], + [92.227526, 32.821003], + [92.205352, 32.866255], + [92.145606, 32.885857], + [92.101874, 32.860222], + [92.038432, 32.860725], + [92.018722, 32.829552], + [91.955897, 32.8205], + [91.896766, 32.907967], + [91.857962, 32.90244], + [91.839484, 32.948152], + [91.799448, 32.942126], + [91.752637, 32.969242], + [91.685499, 32.989324], + [91.664557, 33.012913], + [91.583253, 33.0375], + [91.55492, 33.060074], + [91.535826, 33.10019], + [91.49579, 33.109214], + [91.436044, 33.066092], + [91.370138, 33.100691], + [91.311624, 33.108211], + [91.261733, 33.141291], + [91.226624, 33.141792], + [91.18782, 33.106206], + [91.161335, 33.108712], + [91.147784, 33.07211], + [91.072024, 33.113224], + [91.037531, 33.098686], + [91.001807, 33.11573], + [90.927894, 33.120241], + [90.902024, 33.083143], + [90.88293, 33.120241], + [90.803474, 33.114227], + [90.740032, 33.142293], + [90.704308, 33.135778], + [90.627315, 33.180368], + [90.562642, 33.229441], + [90.490577, 33.264977], + [90.405577, 33.260473], + [90.363077, 33.279487], + [90.332896, 33.310501], + [90.246665, 33.423959], + [90.22018, 33.437943], + [90.107463, 33.460913], + [90.088984, 33.478885], + [90.083441, 33.525295], + [90.01076, 33.553728], + [89.984275, 33.612061], + [90.008296, 33.687785], + [89.981195, 33.70322], + [89.983659, 33.725622], + [89.907282, 33.741051], + [89.902355, 33.758467], + [89.942391, 33.801246], + [89.899891, 33.80771], + [89.837065, 33.868853], + [89.795181, 33.865374], + [89.73174, 33.921509], + [89.718805, 33.946832], + [89.688008, 33.959739], + [89.684928, 33.990013], + [89.635037, 34.049537], + [89.656595, 34.057966], + [89.655979, 34.097126], + [89.71203, 34.131809], + [89.756993, 34.124874], + [89.760073, 34.152613], + [89.789638, 34.150632], + [89.816739, 34.16945], + [89.838297, 34.263477], + [89.825362, 34.293642], + [89.86663, 34.324785], + [89.858623, 34.359375], + [89.820435, 34.369255], + [89.799493, 34.39642], + [89.819819, 34.420614], + [89.823515, 34.455657], + [89.814891, 34.548871], + [89.777935, 34.574499], + [89.798877, 34.628686], + [89.74837, 34.641981], + [89.72558, 34.660689], + [89.732356, 34.732035], + [89.799493, 34.743838], + [89.825978, 34.796931], + [89.867862, 34.81069], + [89.838913, 34.865705], + [89.814891, 34.86816], + [89.821051, 34.902033], + [89.78779, 34.921664], + [89.747138, 34.903506], + [89.707102, 34.919701], + [89.670146, 34.887798], + [89.578987, 34.895162], + [89.560509, 34.938836], + [89.59069, 35.057965], + [89.593153, 35.104491], + [89.579603, 35.118688], + [89.519241, 35.133862], + [89.46935, 35.214577], + [89.450255, 35.223867], + [89.48598, 35.256616], + [89.531559, 35.276161], + [89.494603, 35.298632], + [89.516161, 35.330862], + [89.497067, 35.361128], + [89.58761, 35.383575], + [89.619639, 35.412357], + [89.658443, 35.425526], + [89.685544, 35.416259], + [89.739131, 35.468429], + [89.765, 35.482563], + [89.740979, 35.507412], + [89.720037, 35.501566], + [89.699711, 35.544916], + [89.71203, 35.581915], + [89.75145, 35.580942], + [89.765616, 35.599922], + [89.726196, 35.648082], + [89.748986, 35.66267], + [89.747138, 35.7516], + [89.782863, 35.773453], + [89.767464, 35.799183], + [89.801957, 35.848193], + [89.778551, 35.861775], + [89.707718, 35.849163], + [89.654747, 35.848193], + [89.62395, 35.859349], + [89.550654, 35.856924], + [89.554965, 35.873414], + [89.489676, 35.903475], + [89.428082, 35.917531], + [89.434857, 35.992136], + [89.404676, 36.016827], + [89.417611, 36.044897], + [89.474893, 36.022151], + [89.605472, 36.038123], + [89.688624, 36.091337], + [89.711414, 36.093272] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 610000, + "name": "陕西省", + "center": [108.948024, 34.263161], + "centroid": [108.887114, 35.263661], + "childrenNum": 10, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 26, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [110.379257, 34.600612], + [110.29549, 34.610956], + [110.269004, 34.629671], + [110.229584, 34.692679], + [110.243135, 34.725641], + [110.246831, 34.789068], + [110.230816, 34.880925], + [110.262229, 34.944233], + [110.320743, 35.00504], + [110.373714, 35.134351], + [110.364475, 35.197952], + [110.378642, 35.210666], + [110.374946, 35.251728], + [110.45009, 35.327933], + [110.477808, 35.413821], + [110.531394, 35.511309], + [110.567735, 35.539559], + [110.589293, 35.602355], + [110.609619, 35.632031], + [110.57759, 35.701559], + [110.571431, 35.800639], + [110.550489, 35.838005], + [110.549257, 35.877778], + [110.511684, 35.879718], + [110.516612, 35.918501], + [110.502445, 35.947575], + [110.516612, 35.971796], + [110.49259, 35.994073], + [110.491974, 36.034735], + [110.467953, 36.074893], + [110.447011, 36.164328], + [110.45625, 36.22663], + [110.474112, 36.248352], + [110.474112, 36.306729], + [110.459946, 36.327946], + [110.487047, 36.393972], + [110.489511, 36.430094], + [110.47288, 36.453203], + [110.503677, 36.488335], + [110.488895, 36.556628], + [110.496902, 36.582102], + [110.447627, 36.621018], + [110.426685, 36.657514], + [110.394656, 36.676716], + [110.402663, 36.697352], + [110.438388, 36.685835], + [110.447011, 36.737649], + [110.407591, 36.776007], + [110.423605, 36.818179], + [110.406975, 36.824886], + [110.424221, 36.855539], + [110.376178, 36.882351], + [110.408823, 36.892403], + [110.424221, 36.963685], + [110.381721, 37.002408], + [110.382953, 37.022001], + [110.426685, 37.008621], + [110.417446, 37.027257], + [110.460561, 37.044932], + [110.49567, 37.086956], + [110.535706, 37.115118], + [110.53509, 37.138021], + [110.590525, 37.187145], + [110.651503, 37.256722], + [110.661974, 37.281963], + [110.690307, 37.287201], + [110.678604, 37.317668], + [110.695234, 37.34955], + [110.641648, 37.360015], + [110.630561, 37.372858], + [110.644111, 37.435135], + [110.740198, 37.44939], + [110.759292, 37.474567], + [110.770995, 37.538184], + [110.795017, 37.558586], + [110.771611, 37.594634], + [110.763604, 37.639668], + [110.793169, 37.650567], + [110.775306, 37.680886], + [110.706321, 37.705511], + [110.716792, 37.728708], + [110.750669, 37.736281], + [110.735886, 37.77035], + [110.680452, 37.790216], + [110.59422, 37.922049], + [110.522771, 37.955088], + [110.528315, 37.990471], + [110.507989, 38.013107], + [110.501829, 38.097929], + [110.519692, 38.130889], + [110.509221, 38.192061], + [110.528315, 38.211814], + [110.565887, 38.215105], + [110.57759, 38.297345], + [110.601612, 38.308147], + [110.661358, 38.308617], + [110.701394, 38.353215], + [110.746973, 38.366355], + [110.77777, 38.440924], + [110.796864, 38.453579], + [110.840596, 38.439986], + [110.874473, 38.453579], + [110.870777, 38.510265], + [110.907733, 38.521035], + [110.920052, 38.581878], + [110.898494, 38.587024], + [110.880632, 38.626776], + [110.916357, 38.673981], + [110.915125, 38.704345], + [110.965016, 38.755699], + [111.009363, 38.847579], + [110.995813, 38.868084], + [111.016755, 38.889981], + [111.009979, 38.932823], + [110.980414, 38.970056], + [110.998276, 38.998433], + [111.038313, 39.020289], + [111.094363, 39.030053], + [111.138095, 39.064447], + [111.147334, 39.100681], + [111.173819, 39.135041], + [111.163348, 39.152678], + [111.219399, 39.244044], + [111.213239, 39.257021], + [111.247732, 39.302419], + [111.202152, 39.305197], + [111.179363, 39.326959], + [111.186138, 39.35149], + [111.155341, 39.338531], + [111.159037, 39.362596], + [111.125776, 39.366297], + [111.087588, 39.376013], + [111.098059, 39.401914], + [111.064182, 39.400989], + [111.058639, 39.447681], + [111.10545, 39.472631], + [111.10545, 39.497573], + [111.148566, 39.531277], + [111.154725, 39.569116], + [111.136863, 39.587106], + [111.101138, 39.559428], + [111.017371, 39.552045], + [110.958856, 39.519275], + [110.891103, 39.509118], + [110.869545, 39.494341], + [110.782698, 39.38804], + [110.73835, 39.348713], + [110.731575, 39.30705], + [110.702626, 39.273701], + [110.626249, 39.266751], + [110.596684, 39.282966], + [110.566503, 39.320014], + [110.559728, 39.351027], + [110.524003, 39.382952], + [110.482735, 39.360745], + [110.434692, 39.381101], + [110.429764, 39.341308], + [110.385417, 39.310291], + [110.257917, 39.407001], + [110.243751, 39.423645], + [110.152592, 39.45415], + [110.12549, 39.432891], + [110.136577, 39.39174], + [110.161831, 39.387115], + [110.184005, 39.355192], + [110.217881, 39.281113], + [110.109476, 39.249606], + [110.041107, 39.21623], + [109.962267, 39.212056], + [109.90252, 39.271848], + [109.871723, 39.243581], + [109.961035, 39.191651], + [109.893897, 39.141075], + [109.92223, 39.107183], + [109.890818, 39.103932], + [109.851397, 39.122971], + [109.793499, 39.074204], + [109.762086, 39.057476], + [109.72513, 39.018429], + [109.665384, 38.981687], + [109.685094, 38.968195], + [109.672159, 38.928167], + [109.624116, 38.85457], + [109.549587, 38.805618], + [109.511399, 38.833595], + [109.444262, 38.782763], + [109.404226, 38.720689], + [109.338936, 38.701542], + [109.329081, 38.66043], + [109.367269, 38.627711], + [109.331545, 38.597783], + [109.276726, 38.623035], + [109.196654, 38.552867], + [109.175712, 38.518694], + [109.128901, 38.480288], + [109.054372, 38.433892], + [109.051292, 38.385122], + [109.007561, 38.359316], + [108.961981, 38.26493], + [108.976148, 38.245192], + [108.938575, 38.207582], + [108.964445, 38.154894], + [109.069155, 38.091336], + [109.050676, 38.055059], + [109.06977, 38.023008], + [109.037742, 38.021593], + [109.018648, 37.971602], + [108.982923, 37.964053], + [108.9743, 37.931962], + [108.93488, 37.922521], + [108.893612, 37.978207], + [108.883141, 38.01405], + [108.830786, 38.049875], + [108.797525, 38.04799], + [108.82709, 37.989056], + [108.798141, 37.93385], + [108.791982, 37.872934], + [108.799989, 37.784068], + [108.784591, 37.764673], + [108.791982, 37.700303], + [108.777815, 37.683728], + [108.720533, 37.683728], + [108.699591, 37.669518], + [108.628142, 37.651988], + [108.532671, 37.690832], + [108.485244, 37.678044], + [108.422418, 37.648672], + [108.301078, 37.640616], + [108.293071, 37.656726], + [108.24626, 37.665728], + [108.205608, 37.655779], + [108.193905, 37.638246], + [108.134159, 37.622131], + [108.055318, 37.652462], + [108.025137, 37.649619], + [108.012819, 37.66857], + [108.025753, 37.696041], + [107.993109, 37.735335], + [107.982022, 37.787378], + [107.884703, 37.808186], + [107.842819, 37.828987], + [107.732566, 37.84931], + [107.684523, 37.888522], + [107.65003, 37.86443], + [107.659269, 37.844112], + [107.646335, 37.805349], + [107.620465, 37.776026], + [107.599523, 37.791162], + [107.57119, 37.776499], + [107.499125, 37.765619], + [107.484959, 37.706458], + [107.425828, 37.684201], + [107.387024, 37.691305], + [107.389488, 37.671413], + [107.422133, 37.665254], + [107.361155, 37.613125], + [107.311264, 37.609806], + [107.330358, 37.584201], + [107.369162, 37.58752], + [107.345756, 37.518725], + [107.284162, 37.481691], + [107.282931, 37.437036], + [107.257677, 37.337179], + [107.273075, 37.29101], + [107.309416, 37.239095], + [107.270612, 37.229089], + [107.317423, 37.200017], + [107.336517, 37.165687], + [107.334669, 37.138975], + [107.306952, 37.100799], + [107.281083, 37.127047], + [107.268764, 37.099367], + [107.28601, 37.054963], + [107.288474, 37.008143], + [107.288474, 37.008143], + [107.291554, 36.979463], + [107.291554, 36.979463], + [107.310032, 36.912502], + [107.336517, 36.925899], + [107.365466, 36.905324], + [107.478183, 36.908196], + [107.533618, 36.867031], + [107.540393, 36.828718], + [107.5909, 36.836382], + [107.642023, 36.819137], + [107.670356, 36.83303], + [107.722095, 36.802367], + [107.742421, 36.811951], + [107.768291, 36.792783], + [107.866841, 36.766899], + [107.907493, 36.750118], + [107.914268, 36.720861], + [107.940754, 36.694953], + [107.938906, 36.655594], + [108.006659, 36.683435], + [108.02329, 36.647912], + [108.001732, 36.639269], + [108.060862, 36.592194], + [108.079956, 36.614294], + [108.092891, 36.587388], + [108.163724, 36.563839], + [108.1976, 36.630144], + [108.222854, 36.631105], + [108.204992, 36.606607], + [108.204992, 36.606607], + [108.210535, 36.577296], + [108.245644, 36.571048], + [108.262274, 36.549417], + [108.340498, 36.559032], + [108.365136, 36.519603], + [108.391621, 36.505654], + [108.408252, 36.45946], + [108.460606, 36.422871], + [108.495099, 36.422389], + [108.514809, 36.445501], + [108.510498, 36.47438], + [108.562852, 36.43876], + [108.618903, 36.433946], + [108.651548, 36.384818], + [108.641693, 36.359279], + [108.646004, 36.254143], + [108.712526, 36.138716], + [108.682345, 36.062316], + [108.688504, 36.021183], + [108.659555, 35.990683], + [108.652164, 35.94806], + [108.593649, 35.950967], + [108.562852, 35.921409], + [108.518505, 35.905414], + [108.499411, 35.872444], + [108.527744, 35.82442], + [108.533903, 35.746257], + [108.517889, 35.699615], + [108.539447, 35.605761], + [108.618287, 35.557088], + [108.625678, 35.537124], + [108.605968, 35.503028], + [108.631222, 35.418698], + [108.61028, 35.355271], + [108.614591, 35.328909], + [108.583178, 35.294724], + [108.547454, 35.304981], + [108.48894, 35.275184], + [108.36144, 35.279581], + [108.345426, 35.300586], + [108.296767, 35.267855], + [108.239484, 35.256127], + [108.221622, 35.296678], + [108.174811, 35.304981], + [108.094739, 35.280069], + [108.049159, 35.253683], + [107.949993, 35.245375], + [107.960464, 35.263457], + [107.867457, 35.256127], + [107.841587, 35.276649], + [107.745501, 35.311819], + [107.737494, 35.267366], + [107.667277, 35.257104], + [107.652494, 35.244886], + [107.686371, 35.218], + [107.715936, 35.168114], + [107.727639, 35.120157], + [107.769523, 35.064333], + [107.769523, 35.064333], + [107.773218, 35.060904], + [107.773218, 35.060904], + [107.814486, 35.024646], + [107.846515, 35.024646], + [107.863145, 34.999158], + [107.842203, 34.979056], + [107.741805, 34.953553], + [107.675284, 34.9511], + [107.638943, 34.935402], + [107.619849, 34.964834], + [107.564415, 34.968757], + [107.523763, 34.909886], + [107.455394, 34.916757], + [107.400575, 34.932949], + [107.369162, 34.917738], + [107.350068, 34.93393], + [107.286626, 34.931968], + [107.252749, 34.880925], + [107.189308, 34.893198], + [107.162206, 34.944233], + [107.119707, 34.950119], + [107.089526, 34.976604], + [107.08275, 35.024156], + [107.012533, 35.029547], + [106.990975, 35.068252], + [106.950323, 35.066782], + [106.901664, 35.094698], + [106.838222, 35.080007], + [106.710723, 35.100574], + [106.706411, 35.081966], + [106.615252, 35.071191], + [106.577064, 35.089312], + [106.541956, 35.083925], + [106.52163, 35.027587], + [106.494528, 35.006021], + [106.494528, 35.006021], + [106.484673, 34.983959], + [106.493296, 34.941289], + [106.527789, 34.876507], + [106.556122, 34.861285], + [106.550579, 34.82936], + [106.575216, 34.769897], + [106.539492, 34.745805], + [106.505615, 34.746789], + [106.487137, 34.715311], + [106.456956, 34.703996], + [106.442173, 34.675455], + [106.471122, 34.634102], + [106.419384, 34.643458], + [106.314058, 34.578934], + [106.341159, 34.568093], + [106.334384, 34.517811], + [106.455108, 34.531617], + [106.514238, 34.511894], + [106.513622, 34.498085], + [106.558586, 34.48822], + [106.610941, 34.454177], + [106.638042, 34.391481], + [106.717498, 34.369255], + [106.691013, 34.337635], + [106.705179, 34.299575], + [106.68239, 34.256057], + [106.652825, 34.24369], + [106.63373, 34.260014], + [106.589383, 34.253584], + [106.577064, 34.280786], + [106.526557, 34.292159], + [106.496376, 34.238248], + [106.5321, 34.254079], + [106.55797, 34.229837], + [106.585071, 34.149641], + [106.560434, 34.109514], + [106.501919, 34.105055], + [106.505615, 34.056479], + [106.471738, 34.024244], + [106.474202, 33.970659], + [106.41076, 33.909093], + [106.428007, 33.866368], + [106.475434, 33.875809], + [106.491448, 33.834559], + [106.461883, 33.789807], + [106.488369, 33.757969], + [106.482825, 33.707203], + [106.534564, 33.695254], + [106.575832, 33.631497], + [106.58076, 33.576169], + [106.540108, 33.512822], + [106.456956, 33.532779], + [106.447101, 33.613058], + [106.384891, 33.612061], + [106.35163, 33.587137], + [106.303587, 33.604585], + [106.237681, 33.564201], + [106.187174, 33.546746], + [106.108334, 33.569686], + [106.117573, 33.602591], + [106.086776, 33.617045], + [106.047356, 33.610067], + [105.971596, 33.613058], + [105.940183, 33.570684], + [105.902611, 33.556222], + [105.871198, 33.511325], + [105.842248, 33.489866], + [105.831162, 33.451926], + [105.837937, 33.410971], + [105.827466, 33.379993], + [105.709822, 33.382991], + [105.755401, 33.329004], + [105.752937, 33.291994], + [105.791741, 33.278486], + [105.799133, 33.258471], + [105.862574, 33.234447], + [105.917393, 33.237951], + [105.965436, 33.204407], + [105.968516, 33.154318], + [105.93156, 33.178365], + [105.897067, 33.146803], + [105.923552, 33.147805], + [105.934639, 33.112221], + [105.914929, 33.066092], + [105.926632, 33.042517], + [105.917393, 32.993841], + [105.861959, 32.939112], + [105.82685, 32.950663], + [105.735691, 32.905454], + [105.656851, 32.895405], + [105.638373, 32.879323], + [105.590329, 32.87681], + [105.565692, 32.906962], + [105.528119, 32.919019], + [105.49917, 32.911986], + [105.495475, 32.873292], + [105.524424, 32.847654], + [105.534279, 32.790822], + [105.555221, 32.794343], + [105.563844, 32.724891], + [105.585402, 32.728919], + [105.596489, 32.69921], + [105.677793, 32.726402], + [105.719061, 32.759624], + [105.768952, 32.767676], + [105.779423, 32.750061], + [105.822538, 32.770192], + [105.825002, 32.824523], + [105.849024, 32.817985], + [105.893371, 32.838603], + [105.93156, 32.826032], + [105.969132, 32.849162], + [106.011632, 32.829552], + [106.044277, 32.864747], + [106.071378, 32.828546], + [106.093552, 32.82402], + [106.07261, 32.76365], + [106.076921, 32.76365], + [106.076305, 32.759121], + [106.071378, 32.758114], + [106.120037, 32.719856], + [106.17424, 32.6977], + [106.254928, 32.693671], + [106.267863, 32.673522], + [106.301123, 32.680071], + [106.347935, 32.671003], + [106.389203, 32.62666], + [106.421231, 32.616579], + [106.451412, 32.65992], + [106.498224, 32.649338], + [106.517934, 32.668485], + [106.585687, 32.68813], + [106.626955, 32.682086], + [106.670071, 32.694678], + [106.733513, 32.739491], + [106.783404, 32.735967], + [106.793259, 32.712807], + [106.82344, 32.705254], + [106.854853, 32.724388], + [106.903512, 32.721367], + [106.912751, 32.704247], + [107.012533, 32.721367], + [107.066736, 32.708779], + [107.05996, 32.686115], + [107.098765, 32.649338], + [107.108004, 32.600951], + [107.080286, 32.542448], + [107.127098, 32.482393], + [107.189924, 32.468256], + [107.212097, 32.428864], + [107.263836, 32.403099], + [107.287858, 32.457147], + [107.313727, 32.489965], + [107.356843, 32.506622], + [107.382097, 32.54043], + [107.436299, 32.529835], + [107.438763, 32.465732], + [107.460937, 32.453612], + [107.456625, 32.41775], + [107.489886, 32.425328], + [107.527458, 32.38238], + [107.598291, 32.411688], + [107.648183, 32.413709], + [107.680827, 32.397035], + [107.707929, 32.331826], + [107.753508, 32.338399], + [107.812022, 32.247844], + [107.864377, 32.201266], + [107.890247, 32.214432], + [107.924739, 32.197215], + [107.979558, 32.146051], + [108.024521, 32.177462], + [108.018362, 32.2119], + [108.086731, 32.233165], + [108.143398, 32.219495], + [108.156948, 32.239239], + [108.179738, 32.221521], + [108.240716, 32.274666], + [108.310933, 32.232152], + [108.389773, 32.263533], + [108.414411, 32.252399], + [108.469846, 32.270618], + [108.507418, 32.245819], + [108.509882, 32.201266], + [108.543758, 32.177969], + [108.585026, 32.17189], + [108.676801, 32.10297], + [108.734084, 32.106519], + [108.75133, 32.076098], + [108.78767, 32.04871], + [108.837561, 32.039072], + [108.902235, 31.984774], + [108.986619, 31.980205], + [109.085785, 31.929428], + [109.123357, 31.892851], + [109.191111, 31.85575], + [109.195422, 31.817618], + [109.27611, 31.79931], + [109.279806, 31.776418], + [109.253936, 31.759628], + [109.282885, 31.743343], + [109.281654, 31.716874], + [109.381436, 31.705165], + [109.446109, 31.722983], + [109.502776, 31.716365], + [109.549587, 31.73011], + [109.585928, 31.726546], + [109.592087, 31.789136], + [109.633971, 31.804396], + [109.633971, 31.824738], + [109.60379, 31.885737], + [109.584696, 31.900472], + [109.62042, 31.928412], + [109.631507, 31.962436], + [109.590855, 32.012688], + [109.590855, 32.047696], + [109.621652, 32.106519], + [109.58716, 32.161251], + [109.604406, 32.199241], + [109.592703, 32.219495], + [109.550203, 32.225065], + [109.528645, 32.270112], + [109.495385, 32.300468], + [109.513247, 32.342444], + [109.502776, 32.38895], + [109.529877, 32.405625], + [109.526797, 32.43341], + [109.575457, 32.506622], + [109.637051, 32.540935], + [109.619804, 32.56767], + [109.631507, 32.599943], + [109.726978, 32.608513], + [109.746072, 32.594901], + [109.816905, 32.577252], + [109.910528, 32.592884], + [109.97089, 32.577756], + [110.017701, 32.546989], + [110.084223, 32.580782], + [110.090382, 32.617083], + [110.124259, 32.616579], + [110.153824, 32.593388], + [110.206179, 32.633212], + [110.156903, 32.683093], + [110.159367, 32.767173], + [110.127338, 32.77774], + [110.142121, 32.802895], + [110.105164, 32.832569], + [110.051578, 32.851676], + [109.988752, 32.886359], + [109.927158, 32.887364], + [109.907448, 32.903947], + [109.856941, 32.910479], + [109.847702, 32.893395], + [109.789804, 32.882339], + [109.76455, 32.909474], + [109.785492, 32.987316], + [109.794731, 33.067095], + [109.704188, 33.101694], + [109.688174, 33.116733], + [109.576073, 33.110216], + [109.522486, 33.138785], + [109.468283, 33.140288], + [109.438718, 33.152314], + [109.498464, 33.207412], + [109.514479, 33.237951], + [109.60687, 33.235949], + [109.619804, 33.275484], + [109.649985, 33.251465], + [109.693101, 33.254468], + [109.732521, 33.231443], + [109.813209, 33.236449], + [109.852013, 33.247961], + [109.916687, 33.229942], + [109.973353, 33.203907], + [109.999223, 33.212419], + [110.031252, 33.191888], + [110.164911, 33.209415], + [110.218497, 33.163336], + [110.285635, 33.171352], + [110.33799, 33.160331], + [110.372482, 33.186379], + [110.398352, 33.176862], + [110.398352, 33.176862], + [110.471032, 33.171352], + [110.54125, 33.255469], + [110.57759, 33.250464], + [110.59422, 33.168346], + [110.623785, 33.143796], + [110.650887, 33.157324], + [110.702626, 33.097182], + [110.753133, 33.15031], + [110.824582, 33.158327], + [110.828893, 33.201403], + [110.865234, 33.213921], + [110.9219, 33.203907], + [110.960704, 33.253967], + [110.984726, 33.255469], + [111.025994, 33.330504], + [111.025994, 33.375495], + [110.996429, 33.435946], + [111.02661, 33.467903], + [111.021066, 33.471397], + [111.021682, 33.476389], + [111.02661, 33.478386], + [111.002588, 33.535772], + [111.00382, 33.578662], + [110.966864, 33.609071], + [110.878784, 33.634486], + [110.823966, 33.685793], + [110.831973, 33.713675], + [110.81719, 33.751003], + [110.782082, 33.796272], + [110.74143, 33.798759], + [110.712481, 33.833564], + [110.66259, 33.85295], + [110.612083, 33.852453], + [110.587445, 33.887733], + [110.628713, 33.910086], + [110.627481, 33.925482], + [110.665669, 33.937895], + [110.671213, 33.966192], + [110.620706, 34.035652], + [110.587445, 34.023252], + [110.591757, 34.101586], + [110.61393, 34.113478], + [110.642264, 34.161032], + [110.621938, 34.177372], + [110.55788, 34.193214], + [110.55172, 34.213012], + [110.507989, 34.217466], + [110.43962, 34.243196], + [110.428533, 34.288203], + [110.451938, 34.292653], + [110.503677, 34.33714], + [110.473496, 34.393457], + [110.403279, 34.433448], + [110.403279, 34.433448], + [110.360779, 34.516825], + [110.372482, 34.544435], + [110.404511, 34.557743], + [110.366939, 34.566614], + [110.379257, 34.600612] + ] + ], + [ + [ + [111.02661, 33.478386], + [111.021682, 33.476389], + [111.021066, 33.471397], + [111.02661, 33.467903], + [111.02661, 33.478386] + ] + ], + [ + [ + [106.076921, 32.76365], + [106.07261, 32.76365], + [106.071378, 32.758114], + [106.076305, 32.759121], + [106.076921, 32.76365] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 620000, + "name": "甘肃省", + "center": [103.823557, 36.058039], + "childrenNum": 14, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 27, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [106.506231, 35.737514], + [106.504383, 35.736057], + [106.498224, 35.732656], + [106.49268, 35.732656], + [106.434782, 35.688436], + [106.460036, 35.643705], + [106.47913, 35.575101], + [106.460036, 35.578995], + [106.440941, 35.52641], + [106.465579, 35.481101], + [106.490217, 35.480613], + [106.483441, 35.450393], + [106.503767, 35.415284], + [106.501304, 35.364056], + [106.472354, 35.310842], + [106.415688, 35.276161], + [106.368261, 35.273718], + [106.363333, 35.238532], + [106.319601, 35.265411], + [106.241377, 35.358687], + [106.237681, 35.409431], + [106.196414, 35.409919], + [106.173008, 35.437716], + [106.129892, 35.393333], + [106.113262, 35.361616], + [106.083081, 35.421624], + [106.073226, 35.420649], + [106.067682, 35.436254], + [106.073226, 35.447468], + [106.071378, 35.449418], + [106.06953, 35.458193], + [106.071994, 35.463555], + [106.054132, 35.45478], + [106.034422, 35.469404], + [106.002393, 35.438692], + [105.894603, 35.413821], + [105.897683, 35.451368], + [106.048588, 35.488898], + [106.047356, 35.498155], + [106.023335, 35.49377], + [106.017175, 35.519103], + [105.900147, 35.54735], + [105.868734, 35.540046], + [105.847176, 35.490359], + [105.816379, 35.575101], + [105.800365, 35.564878], + [105.762176, 35.602841], + [105.759097, 35.634464], + [105.713517, 35.650513], + [105.722756, 35.673366], + [105.690727, 35.698643], + [105.723988, 35.725854], + [105.740618, 35.698643], + [105.759097, 35.724883], + [105.70243, 35.733142], + [105.667322, 35.749657], + [105.595873, 35.715651], + [105.481924, 35.727312], + [105.457286, 35.771511], + [105.432033, 35.787533], + [105.428953, 35.819082], + [105.408627, 35.822479], + [105.38091, 35.792873], + [105.371055, 35.844312], + [105.39754, 35.857409], + [105.350113, 35.875839], + [105.324859, 35.941761], + [105.343954, 36.033767], + [105.406163, 36.074409], + [105.430801, 36.10391], + [105.491163, 36.101009], + [105.515185, 36.147415], + [105.478844, 36.213111], + [105.460366, 36.223733], + [105.45975, 36.268137], + [105.476381, 36.293224], + [105.455439, 36.321678], + [105.425873, 36.330357], + [105.401236, 36.369881], + [105.398156, 36.430575], + [105.363048, 36.443093], + [105.362432, 36.496514], + [105.322396, 36.535954], + [105.281744, 36.522489], + [105.252179, 36.553263], + [105.2762, 36.563358], + [105.261418, 36.602764], + [105.22015, 36.631105], + [105.225693, 36.664716], + [105.201056, 36.700711], + [105.218302, 36.730455], + [105.272505, 36.739567], + [105.275584, 36.752515], + [105.319932, 36.742924], + [105.340874, 36.764502], + [105.334714, 36.80093], + [105.303302, 36.820575], + [105.279896, 36.86751], + [105.244787, 36.894796], + [105.178882, 36.892403], + [105.185657, 36.942164], + [105.165331, 36.99476], + [105.128991, 36.996194], + [105.05939, 37.022956], + [105.03968, 37.007187], + [105.004571, 37.035378], + [104.95468, 37.040156], + [104.954064, 37.077407], + [104.914644, 37.097935], + [104.888158, 37.15901], + [104.864753, 37.17284], + [104.85613, 37.211933], + [104.776673, 37.246718], + [104.717543, 37.208597], + [104.638087, 37.201923], + [104.600515, 37.242907], + [104.624536, 37.298627], + [104.651022, 37.290534], + [104.673812, 37.317668], + [104.713848, 37.329566], + [104.662109, 37.367626], + [104.679971, 37.408044], + [104.521059, 37.43466], + [104.499501, 37.421353], + [104.448994, 37.42468], + [104.437907, 37.445589], + [104.365226, 37.418026], + [104.298705, 37.414223], + [104.287002, 37.428007], + [104.237727, 37.411847], + [104.183524, 37.406618], + [104.089285, 37.465067], + [103.935916, 37.572818], + [103.874938, 37.604117], + [103.841062, 37.64725], + [103.683381, 37.777919], + [103.627947, 37.797783], + [103.40744, 37.860651], + [103.362477, 38.037621], + [103.368636, 38.08898], + [103.53494, 38.156776], + [103.507838, 38.280905], + [103.465339, 38.353215], + [103.416063, 38.404821], + [103.85954, 38.64454], + [104.011677, 38.85923], + [104.044322, 38.895105], + [104.173053, 38.94446], + [104.196459, 38.9882], + [104.190915, 39.042139], + [104.207546, 39.083495], + [104.171205, 39.160567], + [104.047401, 39.297788], + [104.073271, 39.351953], + [104.089901, 39.419947], + [103.955626, 39.456923], + [103.85338, 39.461543], + [103.728961, 39.430117], + [103.595302, 39.386652], + [103.428998, 39.353341], + [103.344615, 39.331588], + [103.259615, 39.263971], + [103.188166, 39.215302], + [103.133347, 39.192579], + [103.007696, 39.099753], + [102.883892, 39.120649], + [102.616574, 39.171703], + [102.579002, 39.183301], + [102.45335, 39.255167], + [102.3548, 39.231993], + [102.276576, 39.188868], + [102.050526, 39.141075], + [102.012338, 39.127149], + [101.902701, 39.111827], + [101.833715, 39.08907], + [101.926106, 39.000758], + [101.955055, 38.985874], + [102.045599, 38.904885], + [102.075164, 38.891378], + [101.941505, 38.808883], + [101.873751, 38.733761], + [101.777049, 38.66043], + [101.672955, 38.6908], + [101.601506, 38.65529], + [101.562702, 38.713218], + [101.412413, 38.764099], + [101.331109, 38.777164], + [101.307087, 38.80282], + [101.34158, 38.822406], + [101.33542, 38.847113], + [101.24303, 38.860628], + [101.237486, 38.907214], + [101.198682, 38.943064], + [101.228863, 39.020754], + [101.117378, 38.975174], + [100.969553, 38.946788], + [100.961545, 39.005874], + [100.901799, 39.030053], + [100.875314, 39.002619], + [100.835278, 39.025869], + [100.829118, 39.075133], + [100.864227, 39.106719], + [100.842669, 39.199999], + [100.842053, 39.405614], + [100.707778, 39.404689], + [100.606764, 39.387577], + [100.498975, 39.400527], + [100.500823, 39.481408], + [100.44354, 39.485565], + [100.326512, 39.509118], + [100.301258, 39.572345], + [100.314193, 39.606935], + [100.250135, 39.685274], + [100.128179, 39.702312], + [100.040716, 39.757083], + [99.958796, 39.769504], + [99.904593, 39.785601], + [99.822058, 39.860063], + [99.672384, 39.888079], + [99.469124, 39.875221], + [99.440791, 39.885783], + [99.459885, 39.898181], + [99.491298, 39.884406], + [99.533182, 39.891753], + [99.714268, 39.972061], + [99.751225, 40.006909], + [99.841152, 40.013326], + [99.927383, 40.063727], + [99.955716, 40.150695], + [100.007455, 40.20008], + [100.169447, 40.277743], + [100.169447, 40.541131], + [100.242744, 40.618855], + [100.237201, 40.716905], + [100.224882, 40.727337], + [100.107853, 40.875475], + [100.057346, 40.908049], + [99.985897, 40.909858], + [99.673, 40.93292], + [99.565827, 40.846961], + [99.174705, 40.858278], + [99.172858, 40.747289], + [99.12543, 40.715091], + [99.102025, 40.676522], + [99.041662, 40.693767], + [98.984996, 40.782644], + [98.790975, 40.705564], + [98.80699, 40.660181], + [98.802678, 40.607043], + [98.762642, 40.639748], + [98.72199, 40.657911], + [98.689345, 40.691952], + [98.668403, 40.773128], + [98.569853, 40.746836], + [98.627751, 40.677884], + [98.344419, 40.568413], + [98.333332, 40.918903], + [98.25018, 40.93925], + [98.184891, 40.988056], + [98.142391, 41.001607], + [97.971776, 41.09774], + [97.903407, 41.168057], + [97.629314, 41.440498], + [97.613915, 41.477276], + [97.84674, 41.656379], + [97.653335, 41.986856], + [97.500582, 42.243894], + [97.371235, 42.457076], + [97.172903, 42.795257], + [96.968411, 42.756161], + [96.742361, 42.75704], + [96.386348, 42.727592], + [96.166458, 42.623314], + [96.103632, 42.604375], + [96.072219, 42.569566], + [96.02356, 42.542675], + [96.0174, 42.482239], + [95.978596, 42.436762], + [96.06606, 42.414674], + [96.042038, 42.352787], + [96.040806, 42.326688], + [96.178161, 42.21775], + [96.077147, 42.149457], + [96.13874, 42.05399], + [96.137509, 42.019765], + [96.117183, 41.985966], + [96.054973, 41.936124], + [95.998306, 41.906289], + [95.855408, 41.849699], + [95.801206, 41.848361], + [95.759322, 41.835878], + [95.65646, 41.826067], + [95.57146, 41.796181], + [95.445193, 41.719841], + [95.39407, 41.693481], + [95.335556, 41.644305], + [95.299831, 41.565994], + [95.247476, 41.61344], + [95.194505, 41.694821], + [95.199433, 41.719395], + [95.16494, 41.735474], + [95.135991, 41.772976], + [95.110738, 41.768513], + [95.011572, 41.726541], + [94.969072, 41.718948], + [94.861898, 41.668451], + [94.809543, 41.619256], + [94.750413, 41.538227], + [94.534219, 41.505966], + [94.184365, 41.268444], + [94.01067, 41.114875], + [93.908424, 40.983539], + [93.809874, 40.879548], + [93.820961, 40.793519], + [93.760599, 40.664721], + [93.506216, 40.648376], + [92.928465, 40.572504], + [92.920458, 40.391792], + [92.906907, 40.310609], + [92.796654, 40.153897], + [92.745531, 39.868331], + [92.687632, 39.657174], + [92.639589, 39.514196], + [92.52564, 39.368611], + [92.378431, 39.258411], + [92.339011, 39.236628], + [92.343938, 39.146181], + [92.366112, 39.096037], + [92.366728, 39.059335], + [92.41046, 39.03842], + [92.459119, 39.042604], + [92.459119, 39.063982], + [92.489916, 39.099753], + [92.545966, 39.111362], + [92.659299, 39.109969], + [92.765857, 39.136898], + [92.866871, 39.138754], + [92.889045, 39.160103], + [92.938936, 39.169848], + [92.978356, 39.143396], + [93.043029, 39.146645], + [93.115094, 39.17959], + [93.142196, 39.160567], + [93.131725, 39.108112], + [93.165601, 39.090928], + [93.198246, 39.045857], + [93.179152, 38.923977], + [93.237666, 38.916062], + [93.274007, 38.896036], + [93.453245, 38.915596], + [93.729186, 38.924443], + [93.834511, 38.867618], + [93.884403, 38.867618], + [93.884403, 38.826136], + [93.769838, 38.821007], + [93.756287, 38.807484], + [93.773533, 38.771099], + [93.800019, 38.750566], + [93.885018, 38.720689], + [93.95154, 38.715086], + [93.973098, 38.724891], + [94.281067, 38.7599], + [94.370379, 38.7627], + [94.511429, 38.445142], + [94.527443, 38.425922], + [94.527443, 38.365416], + [94.56132, 38.351807], + [94.582878, 38.36917], + [94.672805, 38.386998], + [94.812623, 38.385591], + [94.861282, 38.393565], + [94.884072, 38.414669], + [94.973999, 38.430142], + [95.045448, 38.418889], + [95.072549, 38.402476], + [95.122441, 38.417014], + [95.140919, 38.392158], + [95.185266, 38.379492], + [95.209904, 38.327868], + [95.229614, 38.330685], + [95.259179, 38.302981], + [95.315846, 38.318947], + [95.408236, 38.300163], + [95.440881, 38.310965], + [95.455664, 38.291709], + [95.487693, 38.314721], + [95.51849, 38.294997], + [95.585011, 38.343359], + [95.608417, 38.339134], + [95.671858, 38.388405], + [95.703887, 38.400131], + [95.723597, 38.378554], + [95.775952, 38.356031], + [95.83693, 38.344298], + [95.852945, 38.287481], + [95.89606, 38.2903], + [95.932401, 38.259291], + [95.93856, 38.237202], + [96.006929, 38.207582], + [96.06606, 38.173245], + [96.109175, 38.187358], + [96.221892, 38.149246], + [96.252689, 38.167599], + [96.264392, 38.145952], + [96.313051, 38.161952], + [96.301964, 38.183124], + [96.335841, 38.246132], + [96.378341, 38.277146], + [96.46334, 38.277616], + [96.665369, 38.23015], + [96.655514, 38.295936], + [96.638883, 38.307208], + [96.626564, 38.356031], + [96.698013, 38.422172], + [96.707868, 38.459203], + [96.6666, 38.483567], + [96.706637, 38.505582], + [96.780549, 38.504177], + [96.800259, 38.52759], + [96.767614, 38.552399], + [96.808882, 38.582346], + [96.7941, 38.608072], + [96.847071, 38.599186], + [96.876636, 38.580475], + [96.961019, 38.558015], + [97.055874, 38.594508], + [97.047251, 38.653888], + [97.057722, 38.67258], + [97.009063, 38.702477], + [97.023229, 38.755699], + [97.00044, 38.7613], + [96.987505, 38.793025], + [96.993664, 38.834993], + [96.983809, 38.869016], + [96.940693, 38.90768], + [96.938846, 38.95563], + [96.965331, 39.017034], + [96.95794, 39.041674], + [96.969643, 39.097895], + [97.012142, 39.142004], + [96.962251, 39.198144], + [97.017686, 39.208347], + [97.060186, 39.19768], + [97.14149, 39.199999], + [97.220946, 39.193042], + [97.315185, 39.164744], + [97.347213, 39.167528], + [97.371235, 39.140611], + [97.401416, 39.146645], + [97.458698, 39.117863], + [97.504894, 39.076527], + [97.58127, 39.052364], + [97.679205, 39.010524], + [97.701379, 38.963076], + [97.828878, 38.93003], + [97.875689, 38.898365], + [98.009348, 38.85923], + [98.029058, 38.834061], + [98.068478, 38.816344], + [98.091884, 38.786495], + [98.167645, 38.840121], + [98.242173, 38.880664], + [98.235398, 38.918855], + [98.276666, 38.963541], + [98.287753, 38.992386], + [98.280977, 39.027263], + [98.316702, 39.040744], + [98.383839, 39.029588], + [98.401086, 39.001688], + [98.432498, 38.996107], + [98.428187, 38.976104], + [98.457752, 38.952838], + [98.526737, 38.95563], + [98.584635, 38.93003], + [98.624056, 38.959353], + [98.612353, 38.977035], + [98.661628, 38.993782], + [98.70536, 39.043533], + [98.730613, 39.057011], + [98.743548, 39.086747], + [98.816845, 39.085818], + [98.818076, 39.064911], + [98.886446, 39.040744], + [98.903076, 39.012384], + [98.951735, 38.987735], + [99.054597, 38.97657], + [99.107568, 38.951907], + [99.071843, 38.921184], + [99.068764, 38.896968], + [99.141445, 38.852706], + [99.222133, 38.788827], + [99.291118, 38.765966], + [99.361951, 38.718354], + [99.375502, 38.684727], + [99.412458, 38.665571], + [99.450646, 38.60433], + [99.501769, 38.612281], + [99.52887, 38.546314], + [99.585537, 38.498556], + [99.63974, 38.474666], + [99.65945, 38.449361], + [99.727203, 38.415607], + [99.758, 38.410449], + [99.826985, 38.370109], + [99.960028, 38.320825], + [100.001912, 38.315191], + [100.049955, 38.283254], + [100.071513, 38.284663], + [100.117093, 38.253652], + [100.126332, 38.231561], + [100.182998, 38.222158], + [100.159592, 38.291239], + [100.163904, 38.328337], + [100.136803, 38.33444], + [100.093071, 38.407166], + [100.022238, 38.432017], + [100.001296, 38.467169], + [100.025933, 38.507923], + [100.064122, 38.518694], + [100.086911, 38.492936], + [100.113397, 38.497151], + [100.163288, 38.461546], + [100.24028, 38.441861], + [100.259374, 38.366355], + [100.301874, 38.388405], + [100.331439, 38.337257], + [100.318505, 38.329276], + [100.396729, 38.293118], + [100.424446, 38.307208], + [100.432453, 38.275267], + [100.459555, 38.2654], + [100.474953, 38.288891], + [100.516837, 38.272448], + [100.545786, 38.247072], + [100.595061, 38.242372], + [100.619083, 38.26587], + [100.71517, 38.253652], + [100.752126, 38.238612], + [100.825423, 38.158658], + [100.860531, 38.148305], + [100.913502, 38.17889], + [100.93814, 38.16007], + [100.91843, 38.129006], + [100.922125, 38.084741], + [100.888864, 38.056001], + [100.895024, 38.013107], + [100.91843, 37.999432], + [100.964009, 38.011221], + [101.077342, 37.941874], + [101.103211, 37.946593], + [101.114298, 37.92016], + [101.152486, 37.891356], + [101.159262, 37.86821], + [101.202994, 37.84742], + [101.276906, 37.83655], + [101.362522, 37.791162], + [101.382848, 37.822369], + [101.459224, 37.86632], + [101.551615, 37.835604], + [101.598427, 37.827569], + [101.670491, 37.754264], + [101.659405, 37.733441], + [101.791832, 37.696041], + [101.815853, 37.654357], + [101.854657, 37.664781], + [101.873135, 37.686569], + [101.946432, 37.728235], + [101.998787, 37.724921], + [102.036359, 37.685149], + [102.048678, 37.651515], + [102.035128, 37.627819], + [102.102265, 37.582304], + [102.131214, 37.54625], + [102.103497, 37.482641], + [102.125055, 37.48549], + [102.176794, 37.458892], + [102.19712, 37.420403], + [102.299981, 37.391404], + [102.29875, 37.370004], + [102.368351, 37.327662], + [102.428097, 37.308624], + [102.419474, 37.294343], + [102.45335, 37.271487], + [102.457662, 37.248147], + [102.490307, 37.223371], + [102.533422, 37.217176], + [102.578386, 37.17284], + [102.599944, 37.174748], + [102.642444, 37.099845], + [102.583314, 37.104618], + [102.488459, 37.078362], + [102.506321, 37.019134], + [102.450271, 36.968467], + [102.499546, 36.954599], + [102.526031, 36.928291], + [102.56114, 36.91968], + [102.587009, 36.869904], + [102.639364, 36.852666], + [102.720052, 36.767858], + [102.692335, 36.775528], + [102.639364, 36.732853], + [102.612879, 36.738129], + [102.601176, 36.710307], + [102.630741, 36.650793], + [102.684328, 36.619097], + [102.724364, 36.613813], + [102.714509, 36.599401], + [102.761936, 36.568645], + [102.734219, 36.562396], + [102.753313, 36.525855], + [102.793349, 36.497957], + [102.771791, 36.47438], + [102.829689, 36.365544], + [102.831537, 36.365544], + [102.838928, 36.345783], + [102.836465, 36.344819], + [102.845704, 36.331803], + [102.896827, 36.331803], + [102.922696, 36.298047], + [103.024942, 36.256556], + [103.021246, 36.232906], + [103.066826, 36.216974], + [103.048964, 36.199107], + [102.986754, 36.193312], + [102.965812, 36.151765], + [102.948566, 36.150798], + [102.941174, 36.104877], + [102.882044, 36.082632], + [102.932551, 36.048285], + [102.968276, 36.044414], + [102.951645, 36.021667], + [102.971971, 35.995525], + [102.942406, 35.92674], + [102.954725, 35.858864], + [102.94487, 35.829757], + [102.914073, 35.845282], + [102.81737, 35.850133], + [102.787189, 35.862745], + [102.739146, 35.821023], + [102.715125, 35.815685], + [102.686175, 35.771996], + [102.707733, 35.70496], + [102.744074, 35.657807], + [102.7644, 35.653431], + [102.763168, 35.612086], + [102.808747, 35.560496], + [102.746537, 35.545403], + [102.729291, 35.523487], + [102.782878, 35.527871], + [102.743458, 35.494745], + [102.695414, 35.528358], + [102.570995, 35.548324], + [102.531575, 35.580455], + [102.503241, 35.585322], + [102.49893, 35.545403], + [102.437952, 35.455268], + [102.447807, 35.437229], + [102.408387, 35.409431], + [102.314764, 35.434303], + [102.293822, 35.424063], + [102.287663, 35.36552], + [102.317844, 35.343067], + [102.311684, 35.31426], + [102.280887, 35.303028], + [102.3123, 35.282512], + [102.370199, 35.263946], + [102.365887, 35.235599], + [102.404075, 35.179366], + [102.346793, 35.164201], + [102.310452, 35.128967], + [102.29567, 35.071681], + [102.252554, 35.048657], + [102.218062, 35.057475], + [102.211286, 35.034937], + [102.176178, 35.032977], + [102.157699, 35.010923], + [102.133678, 35.014844], + [102.094874, 34.986901], + [102.048062, 34.910868], + [102.068388, 34.887798], + [101.985852, 34.90007], + [101.916867, 34.873561], + [101.923027, 34.835746], + [101.917483, 34.705964], + [101.919947, 34.621791], + [101.934729, 34.58731], + [101.956287, 34.582876], + [101.97415, 34.548871], + [102.001867, 34.538519], + [102.093026, 34.536547], + [102.139837, 34.50351], + [102.155852, 34.507456], + [102.169402, 34.457631], + [102.205743, 34.407777], + [102.259329, 34.355917], + [102.237156, 34.34307], + [102.237156, 34.34307], + [102.186649, 34.352952], + [102.149692, 34.271885], + [102.067772, 34.293642], + [102.062229, 34.227858], + [102.01357, 34.218456], + [102.030816, 34.190739], + [102.003099, 34.162022], + [101.965526, 34.167469], + [101.955055, 34.109514], + [101.897773, 34.133791], + [101.874367, 34.130323], + [101.851578, 34.153108], + [101.836795, 34.124378], + [101.788136, 34.131809], + [101.764114, 34.122892], + [101.736397, 34.080275], + [101.718535, 34.083249], + [101.703136, 34.119424], + [101.674187, 34.110506], + [101.6206, 34.178857], + [101.53868, 34.212022], + [101.492485, 34.195689], + [101.482014, 34.218951], + [101.417956, 34.227858], + [101.369913, 34.248143], + [101.327413, 34.24468], + [101.325565, 34.268423], + [101.268899, 34.278808], + [101.228863, 34.298586], + [101.235022, 34.325279], + [101.193754, 34.336646], + [101.178356, 34.320831], + [101.098284, 34.329233], + [101.054552, 34.322808], + [100.986799, 34.374689], + [100.951074, 34.38358], + [100.895024, 34.375183], + [100.868538, 34.332693], + [100.821727, 34.317371], + [100.798321, 34.260014], + [100.809408, 34.247153], + [100.764445, 34.178857], + [100.806329, 34.155584], + [100.848828, 34.089692], + [100.870386, 34.083744], + [100.880857, 34.036644], + [100.93506, 33.990013], + [100.927669, 33.975126], + [100.965857, 33.946832], + [100.994806, 33.891707], + [101.023139, 33.896178], + [101.054552, 33.863386], + [101.153718, 33.8445], + [101.153102, 33.823124], + [101.190675, 33.791796], + [101.186363, 33.741051], + [101.162957, 33.719649], + [101.177124, 33.685295], + [101.166653, 33.659894], + [101.217776, 33.669856], + [101.23687, 33.685793], + [101.302776, 33.657902], + [101.385312, 33.644949], + [101.424732, 33.655411], + [101.428427, 33.680315], + [101.501724, 33.702723], + [101.58426, 33.674339], + [101.585492, 33.645448], + [101.616905, 33.598603], + [101.611977, 33.565199], + [101.622448, 33.502343], + [101.718535, 33.494857], + [101.748716, 33.505337], + [101.769042, 33.538765], + [101.783208, 33.556721], + [101.831252, 33.554726], + [101.844186, 33.602591], + [101.884222, 33.578163], + [101.907012, 33.539264], + [101.906396, 33.48188], + [101.946432, 33.442937], + [101.915635, 33.425957], + [101.887302, 33.383991], + [101.877447, 33.314502], + [101.769658, 33.26898], + [101.770274, 33.248962], + [101.83002, 33.213921], + [101.841723, 33.184876], + [101.825708, 33.119239], + [101.865744, 33.103198], + [101.887302, 33.135778], + [101.921795, 33.153817], + [101.935345, 33.186879], + [101.99386, 33.1999], + [102.054838, 33.189884], + [102.08933, 33.204908], + [102.08933, 33.227439], + [102.117047, 33.288492], + [102.144765, 33.273983], + [102.160163, 33.242956], + [102.200815, 33.223434], + [102.217446, 33.247961], + [102.192192, 33.337005], + [102.218062, 33.349503], + [102.258098, 33.409472], + [102.296286, 33.413969], + [102.310452, 33.397982], + [102.368967, 33.41247], + [102.392988, 33.404477], + [102.447807, 33.454922], + [102.462589, 33.449429], + [102.461358, 33.501345], + [102.446575, 33.53228], + [102.477988, 33.543254], + [102.440416, 33.574673], + [102.346793, 33.605582], + [102.31538, 33.665374], + [102.342481, 33.725622], + [102.284583, 33.719151], + [102.324619, 33.754486], + [102.296286, 33.783838], + [102.243315, 33.786823], + [102.261177, 33.821136], + [102.25317, 33.861399], + [102.136142, 33.965199], + [102.16817, 33.983066], + [102.226069, 33.963214], + [102.248858, 33.98654], + [102.287047, 33.977607], + [102.315996, 33.993983], + [102.345561, 33.969666], + [102.392372, 33.971651], + [102.406539, 34.033172], + [102.437336, 34.087214], + [102.471213, 34.072839], + [102.511865, 34.086222], + [102.615958, 34.099604], + [102.649219, 34.080275], + [102.655994, 34.113478], + [102.598712, 34.14766], + [102.651067, 34.165983], + [102.664002, 34.192719], + [102.694799, 34.198659], + [102.728675, 34.235774], + [102.779798, 34.236764], + [102.798276, 34.272874], + [102.856791, 34.270895], + [102.85987, 34.301058], + [102.911609, 34.312923], + [102.949181, 34.292159], + [102.977515, 34.252595], + [102.973203, 34.205588], + [103.005848, 34.184798], + [103.052043, 34.195194], + [103.100087, 34.181828], + [103.124108, 34.162022], + [103.121644, 34.112487], + [103.178927, 34.079779], + [103.129652, 34.065899], + [103.119797, 34.03466], + [103.147514, 34.036644], + [103.157369, 33.998944], + [103.120413, 33.953286], + [103.1315, 33.931937], + [103.16476, 33.929454], + [103.181391, 33.900649], + [103.153673, 33.819147], + [103.165376, 33.805721], + [103.228202, 33.79478], + [103.24976, 33.814175], + [103.284868, 33.80224], + [103.278709, 33.774387], + [103.35447, 33.743539], + [103.434542, 33.752993], + [103.464723, 33.80224], + [103.518309, 33.807213], + [103.545411, 33.719649], + [103.520157, 33.678323], + [103.552186, 33.671351], + [103.563889, 33.699735], + [103.593454, 33.716164], + [103.645809, 33.708697], + [103.667983, 33.685793], + [103.690772, 33.69376], + [103.778236, 33.658898], + [103.861388, 33.682307], + [103.980264, 33.670852], + [104.046169, 33.686291], + [104.103452, 33.663381], + [104.176749, 33.5996], + [104.155191, 33.542755], + [104.180444, 33.472895], + [104.213089, 33.446932], + [104.22048, 33.404477], + [104.272219, 33.391486], + [104.292545, 33.336505], + [104.373849, 33.345004], + [104.420045, 33.327004], + [104.386168, 33.298497], + [104.333813, 33.315502], + [104.303632, 33.304499], + [104.323958, 33.26898], + [104.32827, 33.223934], + [104.351059, 33.158828], + [104.378161, 33.109214], + [104.337509, 33.038002], + [104.391711, 33.035493], + [104.426204, 33.010906], + [104.383704, 32.994343], + [104.378161, 32.953174], + [104.345516, 32.940117], + [104.288234, 32.942628], + [104.277147, 32.90244], + [104.294393, 32.835586], + [104.363994, 32.822511], + [104.458849, 32.748551], + [104.51182, 32.753585], + [104.526602, 32.728416], + [104.582653, 32.722374], + [104.592508, 32.695685], + [104.643015, 32.661935], + [104.696601, 32.673522], + [104.739717, 32.635228], + [104.795768, 32.643292], + [104.820405, 32.662943], + [104.845659, 32.653873], + [104.881999, 32.600951], + [104.925115, 32.607505], + [105.026745, 32.650346], + [105.0791, 32.637244], + [105.111128, 32.593893], + [105.185041, 32.617587], + [105.215222, 32.63674], + [105.219534, 32.666469], + [105.263265, 32.652362], + [105.297758, 32.656897], + [105.347033, 32.68259], + [105.368591, 32.712807], + [105.448663, 32.732946], + [105.454207, 32.767173], + [105.427721, 32.784281], + [105.396308, 32.85067], + [105.396308, 32.85067], + [105.38091, 32.876307], + [105.408011, 32.885857], + [105.414171, 32.922034], + [105.467757, 32.930071], + [105.49917, 32.911986], + [105.528119, 32.919019], + [105.565692, 32.906962], + [105.590329, 32.87681], + [105.638373, 32.879323], + [105.656851, 32.895405], + [105.735691, 32.905454], + [105.82685, 32.950663], + [105.861959, 32.939112], + [105.917393, 32.993841], + [105.926632, 33.042517], + [105.914929, 33.066092], + [105.934639, 33.112221], + [105.923552, 33.147805], + [105.897067, 33.146803], + [105.93156, 33.178365], + [105.968516, 33.154318], + [105.965436, 33.204407], + [105.917393, 33.237951], + [105.862574, 33.234447], + [105.799133, 33.258471], + [105.791741, 33.278486], + [105.752937, 33.291994], + [105.755401, 33.329004], + [105.709822, 33.382991], + [105.827466, 33.379993], + [105.837937, 33.410971], + [105.831162, 33.451926], + [105.842248, 33.489866], + [105.871198, 33.511325], + [105.902611, 33.556222], + [105.940183, 33.570684], + [105.971596, 33.613058], + [106.047356, 33.610067], + [106.086776, 33.617045], + [106.117573, 33.602591], + [106.108334, 33.569686], + [106.187174, 33.546746], + [106.237681, 33.564201], + [106.303587, 33.604585], + [106.35163, 33.587137], + [106.384891, 33.612061], + [106.447101, 33.613058], + [106.456956, 33.532779], + [106.540108, 33.512822], + [106.58076, 33.576169], + [106.575832, 33.631497], + [106.534564, 33.695254], + [106.482825, 33.707203], + [106.488369, 33.757969], + [106.461883, 33.789807], + [106.491448, 33.834559], + [106.475434, 33.875809], + [106.428007, 33.866368], + [106.41076, 33.909093], + [106.474202, 33.970659], + [106.471738, 34.024244], + [106.505615, 34.056479], + [106.501919, 34.105055], + [106.560434, 34.109514], + [106.585071, 34.149641], + [106.55797, 34.229837], + [106.5321, 34.254079], + [106.496376, 34.238248], + [106.526557, 34.292159], + [106.577064, 34.280786], + [106.589383, 34.253584], + [106.63373, 34.260014], + [106.652825, 34.24369], + [106.68239, 34.256057], + [106.705179, 34.299575], + [106.691013, 34.337635], + [106.717498, 34.369255], + [106.638042, 34.391481], + [106.610941, 34.454177], + [106.558586, 34.48822], + [106.513622, 34.498085], + [106.514238, 34.511894], + [106.455108, 34.531617], + [106.334384, 34.517811], + [106.341159, 34.568093], + [106.314058, 34.578934], + [106.419384, 34.643458], + [106.471122, 34.634102], + [106.442173, 34.675455], + [106.456956, 34.703996], + [106.487137, 34.715311], + [106.505615, 34.746789], + [106.539492, 34.745805], + [106.575216, 34.769897], + [106.550579, 34.82936], + [106.556122, 34.861285], + [106.527789, 34.876507], + [106.493296, 34.941289], + [106.484673, 34.983959], + [106.494528, 35.006021], + [106.494528, 35.006021], + [106.52163, 35.027587], + [106.541956, 35.083925], + [106.577064, 35.089312], + [106.615252, 35.071191], + [106.706411, 35.081966], + [106.710723, 35.100574], + [106.838222, 35.080007], + [106.901664, 35.094698], + [106.950323, 35.066782], + [106.990975, 35.068252], + [107.012533, 35.029547], + [107.08275, 35.024156], + [107.089526, 34.976604], + [107.119707, 34.950119], + [107.162206, 34.944233], + [107.189308, 34.893198], + [107.252749, 34.880925], + [107.286626, 34.931968], + [107.350068, 34.93393], + [107.369162, 34.917738], + [107.400575, 34.932949], + [107.455394, 34.916757], + [107.523763, 34.909886], + [107.564415, 34.968757], + [107.619849, 34.964834], + [107.638943, 34.935402], + [107.675284, 34.9511], + [107.741805, 34.953553], + [107.842203, 34.979056], + [107.863145, 34.999158], + [107.846515, 35.024646], + [107.814486, 35.024646], + [107.773218, 35.060904], + [107.773218, 35.060904], + [107.769523, 35.064333], + [107.769523, 35.064333], + [107.727639, 35.120157], + [107.715936, 35.168114], + [107.686371, 35.218], + [107.652494, 35.244886], + [107.667277, 35.257104], + [107.737494, 35.267366], + [107.745501, 35.311819], + [107.841587, 35.276649], + [107.867457, 35.256127], + [107.960464, 35.263457], + [107.949993, 35.245375], + [108.049159, 35.253683], + [108.094739, 35.280069], + [108.174811, 35.304981], + [108.221622, 35.296678], + [108.239484, 35.256127], + [108.296767, 35.267855], + [108.345426, 35.300586], + [108.36144, 35.279581], + [108.48894, 35.275184], + [108.547454, 35.304981], + [108.583178, 35.294724], + [108.614591, 35.328909], + [108.61028, 35.355271], + [108.631222, 35.418698], + [108.605968, 35.503028], + [108.625678, 35.537124], + [108.618287, 35.557088], + [108.539447, 35.605761], + [108.517889, 35.699615], + [108.533903, 35.746257], + [108.527744, 35.82442], + [108.499411, 35.872444], + [108.518505, 35.905414], + [108.562852, 35.921409], + [108.593649, 35.950967], + [108.652164, 35.94806], + [108.659555, 35.990683], + [108.688504, 36.021183], + [108.682345, 36.062316], + [108.712526, 36.138716], + [108.646004, 36.254143], + [108.641693, 36.359279], + [108.651548, 36.384818], + [108.618903, 36.433946], + [108.562852, 36.43876], + [108.510498, 36.47438], + [108.514809, 36.445501], + [108.495099, 36.422389], + [108.460606, 36.422871], + [108.408252, 36.45946], + [108.391621, 36.505654], + [108.365136, 36.519603], + [108.340498, 36.559032], + [108.262274, 36.549417], + [108.245644, 36.571048], + [108.210535, 36.577296], + [108.204992, 36.606607], + [108.204992, 36.606607], + [108.222854, 36.631105], + [108.1976, 36.630144], + [108.163724, 36.563839], + [108.092891, 36.587388], + [108.079956, 36.614294], + [108.060862, 36.592194], + [108.001732, 36.639269], + [108.02329, 36.647912], + [108.006659, 36.683435], + [107.938906, 36.655594], + [107.940754, 36.694953], + [107.914268, 36.720861], + [107.907493, 36.750118], + [107.866841, 36.766899], + [107.768291, 36.792783], + [107.742421, 36.811951], + [107.722095, 36.802367], + [107.670356, 36.83303], + [107.642023, 36.819137], + [107.5909, 36.836382], + [107.540393, 36.828718], + [107.533618, 36.867031], + [107.478183, 36.908196], + [107.365466, 36.905324], + [107.336517, 36.925899], + [107.310032, 36.912502], + [107.291554, 36.979463], + [107.291554, 36.979463], + [107.288474, 37.008143], + [107.288474, 37.008143], + [107.28601, 37.054963], + [107.268764, 37.099367], + [107.234887, 37.096503], + [107.181916, 37.143269], + [107.133873, 37.134681], + [107.095685, 37.115595], + [107.030395, 37.140883], + [107.031011, 37.108436], + [106.998367, 37.106527], + [106.905976, 37.151378], + [106.912135, 37.110345], + [106.891193, 37.098413], + [106.818512, 37.141838], + [106.776012, 37.158056], + [106.772933, 37.120367], + [106.750143, 37.09889], + [106.728585, 37.121321], + [106.687933, 37.12991], + [106.673151, 37.1113], + [106.6171, 37.135158], + [106.605397, 37.127524], + [106.645433, 37.064992], + [106.666991, 37.016745], + [106.646665, 37.000496], + [106.64297, 36.962729], + [106.594926, 36.967988], + [106.595542, 36.94025], + [106.540108, 36.984244], + [106.549347, 36.941685], + [106.601702, 36.918244], + [106.609709, 36.878521], + [106.609709, 36.878521], + [106.626955, 36.892403], + [106.637426, 36.867031], + [106.637426, 36.867031], + [106.657752, 36.820575], + [106.627571, 36.752995], + [106.644817, 36.72278], + [106.59431, 36.750118], + [106.514238, 36.715584], + [106.519782, 36.708868], + [106.519782, 36.708868], + [106.530869, 36.690154], + [106.490833, 36.685835], + [106.491448, 36.628703], + [106.444637, 36.624861], + [106.465579, 36.583063], + [106.444637, 36.557109], + [106.397826, 36.576816], + [106.392282, 36.556628], + [106.363949, 36.577296], + [106.37134, 36.549417], + [106.39721, 36.548455], + [106.455724, 36.496995], + [106.494528, 36.494589], + [106.523477, 36.468605], + [106.492064, 36.422389], + [106.510543, 36.379037], + [106.497608, 36.31348], + [106.470507, 36.306246], + [106.504383, 36.266207], + [106.54134, 36.25366], + [106.559202, 36.292259], + [106.647897, 36.259451], + [106.685469, 36.273445], + [106.698404, 36.244008], + [106.735976, 36.23725], + [106.772933, 36.212628], + [106.808657, 36.21118], + [106.833295, 36.229044], + [106.858548, 36.206834], + [106.858548, 36.206834], + [106.873947, 36.178338], + [106.873947, 36.178338], + [106.930613, 36.138716], + [106.925686, 36.115997], + [106.957715, 36.091337], + [106.940468, 36.064734], + [106.928149, 36.011502], + [106.94786, 35.988262], + [106.90228, 35.943699], + [106.93862, 35.952905], + [106.940468, 35.931101], + [106.912751, 35.93207], + [106.849925, 35.887476], + [106.927534, 35.810346], + [106.897353, 35.759856], + [106.868403, 35.771996], + [106.867171, 35.738485], + [106.819128, 35.7448], + [106.806193, 35.70982], + [106.750759, 35.725369], + [106.750759, 35.689408], + [106.674998, 35.728284], + [106.66268, 35.70739], + [106.633115, 35.714679], + [106.620796, 35.743829], + [106.595542, 35.727312], + [106.566593, 35.738971], + [106.506231, 35.737514] + ] + ], + [ + [ + [106.047356, 35.498155], + [106.048588, 35.488898], + [106.054132, 35.45478], + [106.071994, 35.463555], + [106.078769, 35.509848], + [106.047356, 35.498155] + ] + ], + [ + [ + [102.831537, 36.365544], + [102.829689, 36.365544], + [102.836465, 36.344819], + [102.838928, 36.345783], + [102.831537, 36.365544] + ] + ], + [ + [ + [106.073226, 35.447468], + [106.067682, 35.436254], + [106.073226, 35.420649], + [106.083081, 35.421624], + [106.073226, 35.447468] + ] + ], + [ + [ + [106.504383, 35.736057], + [106.506231, 35.737514], + [106.49268, 35.732656], + [106.498224, 35.732656], + [106.504383, 35.736057] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 630000, + "name": "青海省", + "center": [101.778916, 36.623178], + "centroid": [96.043533, 35.726403], + "childrenNum": 8, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 28, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [102.829689, 36.365544], + [102.771791, 36.47438], + [102.793349, 36.497957], + [102.753313, 36.525855], + [102.734219, 36.562396], + [102.761936, 36.568645], + [102.714509, 36.599401], + [102.724364, 36.613813], + [102.684328, 36.619097], + [102.630741, 36.650793], + [102.601176, 36.710307], + [102.612879, 36.738129], + [102.639364, 36.732853], + [102.692335, 36.775528], + [102.720052, 36.767858], + [102.639364, 36.852666], + [102.587009, 36.869904], + [102.56114, 36.91968], + [102.526031, 36.928291], + [102.499546, 36.954599], + [102.450271, 36.968467], + [102.506321, 37.019134], + [102.488459, 37.078362], + [102.583314, 37.104618], + [102.642444, 37.099845], + [102.599944, 37.174748], + [102.578386, 37.17284], + [102.533422, 37.217176], + [102.490307, 37.223371], + [102.457662, 37.248147], + [102.45335, 37.271487], + [102.419474, 37.294343], + [102.428097, 37.308624], + [102.368351, 37.327662], + [102.29875, 37.370004], + [102.299981, 37.391404], + [102.19712, 37.420403], + [102.176794, 37.458892], + [102.125055, 37.48549], + [102.103497, 37.482641], + [102.131214, 37.54625], + [102.102265, 37.582304], + [102.035128, 37.627819], + [102.048678, 37.651515], + [102.036359, 37.685149], + [101.998787, 37.724921], + [101.946432, 37.728235], + [101.873135, 37.686569], + [101.854657, 37.664781], + [101.815853, 37.654357], + [101.791832, 37.696041], + [101.659405, 37.733441], + [101.670491, 37.754264], + [101.598427, 37.827569], + [101.551615, 37.835604], + [101.459224, 37.86632], + [101.382848, 37.822369], + [101.362522, 37.791162], + [101.276906, 37.83655], + [101.202994, 37.84742], + [101.159262, 37.86821], + [101.152486, 37.891356], + [101.114298, 37.92016], + [101.103211, 37.946593], + [101.077342, 37.941874], + [100.964009, 38.011221], + [100.91843, 37.999432], + [100.895024, 38.013107], + [100.888864, 38.056001], + [100.922125, 38.084741], + [100.91843, 38.129006], + [100.93814, 38.16007], + [100.913502, 38.17889], + [100.860531, 38.148305], + [100.825423, 38.158658], + [100.752126, 38.238612], + [100.71517, 38.253652], + [100.619083, 38.26587], + [100.595061, 38.242372], + [100.545786, 38.247072], + [100.516837, 38.272448], + [100.474953, 38.288891], + [100.459555, 38.2654], + [100.432453, 38.275267], + [100.424446, 38.307208], + [100.396729, 38.293118], + [100.318505, 38.329276], + [100.331439, 38.337257], + [100.301874, 38.388405], + [100.259374, 38.366355], + [100.24028, 38.441861], + [100.163288, 38.461546], + [100.113397, 38.497151], + [100.086911, 38.492936], + [100.064122, 38.518694], + [100.025933, 38.507923], + [100.001296, 38.467169], + [100.022238, 38.432017], + [100.093071, 38.407166], + [100.136803, 38.33444], + [100.163904, 38.328337], + [100.159592, 38.291239], + [100.182998, 38.222158], + [100.126332, 38.231561], + [100.117093, 38.253652], + [100.071513, 38.284663], + [100.049955, 38.283254], + [100.001912, 38.315191], + [99.960028, 38.320825], + [99.826985, 38.370109], + [99.758, 38.410449], + [99.727203, 38.415607], + [99.65945, 38.449361], + [99.63974, 38.474666], + [99.585537, 38.498556], + [99.52887, 38.546314], + [99.501769, 38.612281], + [99.450646, 38.60433], + [99.412458, 38.665571], + [99.375502, 38.684727], + [99.361951, 38.718354], + [99.291118, 38.765966], + [99.222133, 38.788827], + [99.141445, 38.852706], + [99.068764, 38.896968], + [99.071843, 38.921184], + [99.107568, 38.951907], + [99.054597, 38.97657], + [98.951735, 38.987735], + [98.903076, 39.012384], + [98.886446, 39.040744], + [98.818076, 39.064911], + [98.816845, 39.085818], + [98.743548, 39.086747], + [98.730613, 39.057011], + [98.70536, 39.043533], + [98.661628, 38.993782], + [98.612353, 38.977035], + [98.624056, 38.959353], + [98.584635, 38.93003], + [98.526737, 38.95563], + [98.457752, 38.952838], + [98.428187, 38.976104], + [98.432498, 38.996107], + [98.401086, 39.001688], + [98.383839, 39.029588], + [98.316702, 39.040744], + [98.280977, 39.027263], + [98.287753, 38.992386], + [98.276666, 38.963541], + [98.235398, 38.918855], + [98.242173, 38.880664], + [98.167645, 38.840121], + [98.091884, 38.786495], + [98.068478, 38.816344], + [98.029058, 38.834061], + [98.009348, 38.85923], + [97.875689, 38.898365], + [97.828878, 38.93003], + [97.701379, 38.963076], + [97.679205, 39.010524], + [97.58127, 39.052364], + [97.504894, 39.076527], + [97.458698, 39.117863], + [97.401416, 39.146645], + [97.371235, 39.140611], + [97.347213, 39.167528], + [97.315185, 39.164744], + [97.220946, 39.193042], + [97.14149, 39.199999], + [97.060186, 39.19768], + [97.017686, 39.208347], + [96.962251, 39.198144], + [97.012142, 39.142004], + [96.969643, 39.097895], + [96.95794, 39.041674], + [96.965331, 39.017034], + [96.938846, 38.95563], + [96.940693, 38.90768], + [96.983809, 38.869016], + [96.993664, 38.834993], + [96.987505, 38.793025], + [97.00044, 38.7613], + [97.023229, 38.755699], + [97.009063, 38.702477], + [97.057722, 38.67258], + [97.047251, 38.653888], + [97.055874, 38.594508], + [96.961019, 38.558015], + [96.876636, 38.580475], + [96.847071, 38.599186], + [96.7941, 38.608072], + [96.808882, 38.582346], + [96.767614, 38.552399], + [96.800259, 38.52759], + [96.780549, 38.504177], + [96.706637, 38.505582], + [96.6666, 38.483567], + [96.707868, 38.459203], + [96.698013, 38.422172], + [96.626564, 38.356031], + [96.638883, 38.307208], + [96.655514, 38.295936], + [96.665369, 38.23015], + [96.46334, 38.277616], + [96.378341, 38.277146], + [96.335841, 38.246132], + [96.301964, 38.183124], + [96.313051, 38.161952], + [96.264392, 38.145952], + [96.252689, 38.167599], + [96.221892, 38.149246], + [96.109175, 38.187358], + [96.06606, 38.173245], + [96.006929, 38.207582], + [95.93856, 38.237202], + [95.932401, 38.259291], + [95.89606, 38.2903], + [95.852945, 38.287481], + [95.83693, 38.344298], + [95.775952, 38.356031], + [95.723597, 38.378554], + [95.703887, 38.400131], + [95.671858, 38.388405], + [95.608417, 38.339134], + [95.585011, 38.343359], + [95.51849, 38.294997], + [95.487693, 38.314721], + [95.455664, 38.291709], + [95.440881, 38.310965], + [95.408236, 38.300163], + [95.315846, 38.318947], + [95.259179, 38.302981], + [95.229614, 38.330685], + [95.209904, 38.327868], + [95.185266, 38.379492], + [95.140919, 38.392158], + [95.122441, 38.417014], + [95.072549, 38.402476], + [95.045448, 38.418889], + [94.973999, 38.430142], + [94.884072, 38.414669], + [94.861282, 38.393565], + [94.812623, 38.385591], + [94.672805, 38.386998], + [94.582878, 38.36917], + [94.56132, 38.351807], + [94.527443, 38.365416], + [94.527443, 38.425922], + [94.511429, 38.445142], + [94.370379, 38.7627], + [94.281067, 38.7599], + [93.973098, 38.724891], + [93.95154, 38.715086], + [93.885018, 38.720689], + [93.800019, 38.750566], + [93.773533, 38.771099], + [93.756287, 38.807484], + [93.769838, 38.821007], + [93.884403, 38.826136], + [93.884403, 38.867618], + [93.834511, 38.867618], + [93.729186, 38.924443], + [93.453245, 38.915596], + [93.274007, 38.896036], + [93.237666, 38.916062], + [93.179152, 38.923977], + [93.198246, 39.045857], + [93.165601, 39.090928], + [93.131725, 39.108112], + [93.142196, 39.160567], + [93.115094, 39.17959], + [93.043029, 39.146645], + [92.978356, 39.143396], + [92.938936, 39.169848], + [92.889045, 39.160103], + [92.866871, 39.138754], + [92.765857, 39.136898], + [92.659299, 39.109969], + [92.545966, 39.111362], + [92.489916, 39.099753], + [92.459119, 39.063982], + [92.459119, 39.042604], + [92.41046, 39.03842], + [92.416003, 39.010524], + [92.380279, 38.999828], + [92.263866, 39.002153], + [92.197961, 38.983548], + [92.173323, 38.960749], + [92.10865, 38.963541], + [91.966368, 38.930961], + [91.880752, 38.899297], + [91.87952, 38.884391], + [91.806223, 38.872744], + [91.694738, 38.86622], + [91.681188, 38.852706], + [91.501333, 38.815411], + [91.446515, 38.813546], + [91.298689, 38.746365], + [91.242639, 38.752433], + [91.188436, 38.73096], + [90.992567, 38.695003], + [90.970394, 38.697806], + [90.899561, 38.679588], + [90.724634, 38.658094], + [90.65996, 38.674449], + [90.619308, 38.664636], + [90.645794, 38.635191], + [90.606374, 38.610878], + [90.608837, 38.594508], + [90.560794, 38.593573], + [90.525685, 38.561291], + [90.463476, 38.556611], + [90.465323, 38.521971], + [90.427135, 38.493873], + [90.353222, 38.482162], + [90.315034, 38.501835], + [90.248513, 38.491531], + [90.130868, 38.494341], + [90.111774, 38.477945], + [90.111774, 38.418889], + [90.129636, 38.400131], + [90.179528, 38.396848], + [90.137644, 38.340543], + [90.280542, 38.238142], + [90.352607, 38.233441], + [90.361846, 38.300163], + [90.401882, 38.311434], + [90.531229, 38.319886], + [90.516446, 38.207111], + [90.519526, 37.730601], + [90.579272, 37.720661], + [90.586663, 37.703144], + [90.643946, 37.696988], + [90.777605, 37.648672], + [90.820104, 37.613599], + [90.854597, 37.604117], + [90.882314, 37.575664], + [90.865684, 37.53059], + [90.911879, 37.519674], + [90.958075, 37.477891], + [91.019669, 37.493088], + [91.073256, 37.475992], + [91.099741, 37.447965], + [91.113292, 37.387124], + [91.136081, 37.355734], + [91.134849, 37.324331], + [91.194596, 37.273868], + [91.1909, 37.205737], + [91.280211, 37.163779], + [91.286371, 37.105095], + [91.303617, 37.083136], + [91.291298, 37.042544], + [91.303617, 37.012444], + [91.216153, 37.010054], + [91.181045, 37.025345], + [91.133618, 37.007665], + [91.126842, 36.978507], + [91.051698, 36.96751], + [91.036915, 36.929727], + [90.983944, 36.913459], + [90.924198, 36.921115], + [90.853981, 36.915373], + [90.758511, 36.825844], + [90.732025, 36.825844], + [90.727098, 36.755872], + [90.754815, 36.721341], + [90.720938, 36.708868], + [90.706156, 36.658955], + [90.730793, 36.655594], + [90.72217, 36.620058], + [90.741264, 36.585947], + [90.810865, 36.585466], + [90.831191, 36.55807], + [90.905104, 36.560474], + [91.011662, 36.539801], + [91.035683, 36.529703], + [91.039995, 36.474861], + [91.028292, 36.443093], + [91.051698, 36.433946], + [91.026444, 36.323607], + [91.07264, 36.299012], + [91.051698, 36.238215], + [91.096045, 36.219871], + [91.09235, 36.163844], + [91.124994, 36.115514], + [91.081263, 36.088436], + [90.979017, 36.106811], + [90.922966, 36.028927], + [90.850285, 36.016827], + [90.815793, 36.035703], + [90.776373, 36.086501], + [90.659344, 36.13485], + [90.613149, 36.126632], + [90.534925, 36.147899], + [90.478258, 36.13195], + [90.424055, 36.133883], + [90.325505, 36.159496], + [90.23681, 36.160462], + [90.198006, 36.187516], + [90.130252, 36.2078], + [90.145651, 36.239181], + [90.058188, 36.255591], + [90.043405, 36.276822], + [90.003369, 36.278752], + [90.028006, 36.258486], + [90.019999, 36.213594], + [89.997825, 36.168193], + [89.944855, 36.140649], + [89.941159, 36.067637], + [89.914058, 36.079246], + [89.819819, 36.080697], + [89.766848, 36.073925], + [89.711414, 36.093272], + [89.688624, 36.091337], + [89.605472, 36.038123], + [89.474893, 36.022151], + [89.417611, 36.044897], + [89.404676, 36.016827], + [89.434857, 35.992136], + [89.428082, 35.917531], + [89.489676, 35.903475], + [89.554965, 35.873414], + [89.550654, 35.856924], + [89.62395, 35.859349], + [89.654747, 35.848193], + [89.707718, 35.849163], + [89.778551, 35.861775], + [89.801957, 35.848193], + [89.767464, 35.799183], + [89.782863, 35.773453], + [89.747138, 35.7516], + [89.748986, 35.66267], + [89.726196, 35.648082], + [89.765616, 35.599922], + [89.75145, 35.580942], + [89.71203, 35.581915], + [89.699711, 35.544916], + [89.720037, 35.501566], + [89.740979, 35.507412], + [89.765, 35.482563], + [89.739131, 35.468429], + [89.685544, 35.416259], + [89.658443, 35.425526], + [89.619639, 35.412357], + [89.58761, 35.383575], + [89.497067, 35.361128], + [89.516161, 35.330862], + [89.494603, 35.298632], + [89.531559, 35.276161], + [89.48598, 35.256616], + [89.450255, 35.223867], + [89.46935, 35.214577], + [89.519241, 35.133862], + [89.579603, 35.118688], + [89.593153, 35.104491], + [89.59069, 35.057965], + [89.560509, 34.938836], + [89.578987, 34.895162], + [89.670146, 34.887798], + [89.707102, 34.919701], + [89.747138, 34.903506], + [89.78779, 34.921664], + [89.821051, 34.902033], + [89.814891, 34.86816], + [89.838913, 34.865705], + [89.867862, 34.81069], + [89.825978, 34.796931], + [89.799493, 34.743838], + [89.732356, 34.732035], + [89.72558, 34.660689], + [89.74837, 34.641981], + [89.798877, 34.628686], + [89.777935, 34.574499], + [89.814891, 34.548871], + [89.823515, 34.455657], + [89.819819, 34.420614], + [89.799493, 34.39642], + [89.820435, 34.369255], + [89.858623, 34.359375], + [89.86663, 34.324785], + [89.825362, 34.293642], + [89.838297, 34.263477], + [89.816739, 34.16945], + [89.789638, 34.150632], + [89.760073, 34.152613], + [89.756993, 34.124874], + [89.71203, 34.131809], + [89.655979, 34.097126], + [89.656595, 34.057966], + [89.635037, 34.049537], + [89.684928, 33.990013], + [89.688008, 33.959739], + [89.718805, 33.946832], + [89.73174, 33.921509], + [89.795181, 33.865374], + [89.837065, 33.868853], + [89.899891, 33.80771], + [89.942391, 33.801246], + [89.902355, 33.758467], + [89.907282, 33.741051], + [89.983659, 33.725622], + [89.981195, 33.70322], + [90.008296, 33.687785], + [89.984275, 33.612061], + [90.01076, 33.553728], + [90.083441, 33.525295], + [90.088984, 33.478885], + [90.107463, 33.460913], + [90.22018, 33.437943], + [90.246665, 33.423959], + [90.332896, 33.310501], + [90.363077, 33.279487], + [90.405577, 33.260473], + [90.490577, 33.264977], + [90.562642, 33.229441], + [90.627315, 33.180368], + [90.704308, 33.135778], + [90.740032, 33.142293], + [90.803474, 33.114227], + [90.88293, 33.120241], + [90.902024, 33.083143], + [90.927894, 33.120241], + [91.001807, 33.11573], + [91.037531, 33.098686], + [91.072024, 33.113224], + [91.147784, 33.07211], + [91.161335, 33.108712], + [91.18782, 33.106206], + [91.226624, 33.141792], + [91.261733, 33.141291], + [91.311624, 33.108211], + [91.370138, 33.100691], + [91.436044, 33.066092], + [91.49579, 33.109214], + [91.535826, 33.10019], + [91.55492, 33.060074], + [91.583253, 33.0375], + [91.664557, 33.012913], + [91.685499, 32.989324], + [91.752637, 32.969242], + [91.799448, 32.942126], + [91.839484, 32.948152], + [91.857962, 32.90244], + [91.896766, 32.907967], + [91.955897, 32.8205], + [92.018722, 32.829552], + [92.038432, 32.860725], + [92.101874, 32.860222], + [92.145606, 32.885857], + [92.205352, 32.866255], + [92.227526, 32.821003], + [92.193649, 32.801889], + [92.211511, 32.788306], + [92.198577, 32.754591], + [92.255243, 32.720863], + [92.310062, 32.751571], + [92.343938, 32.738484], + [92.355641, 32.764657], + [92.411076, 32.748048], + [92.459119, 32.76365], + [92.484372, 32.745028], + [92.56814, 32.73194], + [92.574916, 32.741001], + [92.634662, 32.720863], + [92.667922, 32.73194], + [92.686401, 32.76516], + [92.756618, 32.743014], + [92.789262, 32.719856], + [92.822523, 32.729926], + [92.866871, 32.698203], + [92.933392, 32.719353], + [92.964189, 32.714821], + [93.00053, 32.741001], + [93.019624, 32.737477], + [93.023935, 32.703239], + [93.069515, 32.626156], + [93.087993, 32.63674], + [93.159442, 32.644803], + [93.176688, 32.6705], + [93.210565, 32.655385], + [93.239514, 32.662439], + [93.260456, 32.62666], + [93.300492, 32.619604], + [93.308499, 32.580278], + [93.33868, 32.5712], + [93.385492, 32.525294], + [93.411977, 32.558086], + [93.4631, 32.556069], + [93.476651, 32.504603], + [93.501904, 32.503593], + [93.516687, 32.47583], + [93.618933, 32.522771], + [93.651577, 32.571705], + [93.721795, 32.578261], + [93.75136, 32.56313], + [93.820345, 32.549511], + [93.851142, 32.50965], + [93.861613, 32.466237], + [93.90904, 32.463207], + [93.960163, 32.484917], + [93.978641, 32.459672], + [94.03038, 32.448057], + [94.049474, 32.469771], + [94.091974, 32.463207], + [94.137554, 32.433915], + [94.176974, 32.454117], + [94.196684, 32.51621], + [94.250886, 32.51722], + [94.292154, 32.502584], + [94.294002, 32.519743], + [94.350053, 32.533871], + [94.371611, 32.524789], + [94.395016, 32.594397], + [94.435052, 32.562626], + [94.463386, 32.572209], + [94.459074, 32.599439], + [94.522516, 32.595909], + [94.591501, 32.640772], + [94.614291, 32.673522], + [94.638312, 32.645307], + [94.737479, 32.587338], + [94.762116, 32.526303], + [94.78737, 32.522266], + [94.80708, 32.486431], + [94.852043, 32.463712], + [94.889616, 32.472295], + [94.912405, 32.41573], + [94.944434, 32.404109], + [94.988166, 32.422802], + [95.057151, 32.395014], + [95.075013, 32.376315], + [95.075013, 32.376315], + [95.081789, 32.384907], + [95.153853, 32.386423], + [95.218527, 32.397035], + [95.228382, 32.363678], + [95.261643, 32.348006], + [95.193274, 32.332331], + [95.096571, 32.322217], + [95.079325, 32.279726], + [95.10581, 32.258979], + [95.20744, 32.297433], + [95.214216, 32.321712], + [95.241317, 32.3207], + [95.239469, 32.287315], + [95.270266, 32.194683], + [95.270266, 32.194683], + [95.31523, 32.148585], + [95.366968, 32.151118], + [95.367584, 32.178982], + [95.406389, 32.182021], + [95.440265, 32.157705], + [95.454432, 32.061898], + [95.421171, 32.033999], + [95.454432, 32.007613], + [95.395918, 32.001523], + [95.360809, 31.95939], + [95.3682, 31.92892], + [95.408852, 31.918761], + [95.406389, 31.896915], + [95.456896, 31.801853], + [95.480301, 31.795749], + [95.511714, 31.750468], + [95.546823, 31.73978], + [95.580083, 31.76726], + [95.634286, 31.782523], + [95.779648, 31.748941], + [95.823995, 31.68225], + [95.853561, 31.714329], + [95.846169, 31.736218], + [95.89914, 31.81711], + [95.983524, 31.816601], + [95.989067, 31.78761], + [96.064828, 31.720438], + [96.135661, 31.70211], + [96.148595, 31.686324], + [96.156603, 31.602769], + [96.207726, 31.598691], + [96.221892, 31.647613], + [96.245298, 31.657802], + [96.252073, 31.697527], + [96.222508, 31.733164], + [96.231131, 31.749959], + [96.178161, 31.775401], + [96.183088, 31.835924], + [96.202798, 31.841008], + [96.214501, 31.876589], + [96.188632, 31.904028], + [96.220044, 31.905553], + [96.253305, 31.929936], + [96.288414, 31.919777], + [96.389428, 31.919777], + [96.407906, 31.845583], + [96.435623, 31.796258], + [96.468884, 31.769804], + [96.519391, 31.74945], + [96.56805, 31.711783], + [96.615477, 31.737236], + [96.661057, 31.705674], + [96.691854, 31.722474], + [96.722651, 31.686833], + [96.778701, 31.675629], + [96.790404, 31.698545], + [96.840295, 31.720438], + [96.799027, 31.792188], + [96.765767, 31.819144], + [96.760223, 31.860325], + [96.794716, 31.869474], + [96.81073, 31.894375], + [96.776238, 31.935015], + [96.753448, 31.944156], + [96.742977, 32.001016], + [96.722651, 32.013195], + [96.824281, 32.007613], + [96.868629, 31.964975], + [96.863085, 31.996448], + [96.894498, 32.013703], + [96.941925, 31.986297], + [96.965947, 32.008628], + [96.935766, 32.048203], + [97.006599, 32.067984], + [97.028773, 32.04871], + [97.127323, 32.044145], + [97.169823, 32.032984], + [97.188301, 32.055304], + [97.214786, 32.042623], + [97.233881, 32.063927], + [97.201852, 32.090296], + [97.219714, 32.109054], + [97.258518, 32.072041], + [97.308409, 32.076605], + [97.293011, 32.096887], + [97.313953, 32.130342], + [97.271453, 32.139971], + [97.264062, 32.182527], + [97.299786, 32.294904], + [97.32196, 32.303503], + [97.371235, 32.273148], + [97.415583, 32.296421], + [97.424822, 32.322723], + [97.387865, 32.427349], + [97.341054, 32.440987], + [97.388481, 32.501575], + [97.334895, 32.514192], + [97.332431, 32.542448], + [97.3583, 32.563635], + [97.374315, 32.546484], + [97.411887, 32.575235], + [97.448843, 32.586833], + [97.463626, 32.55506], + [97.50243, 32.530844], + [97.540618, 32.536899], + [97.670582, 32.51722], + [97.684132, 32.530339], + [97.730944, 32.527312], + [97.700763, 32.53488], + [97.616995, 32.586329], + [97.607756, 32.614059], + [97.543698, 32.62162], + [97.535075, 32.638252], + [97.48272, 32.654377], + [97.42359, 32.70475], + [97.429133, 32.714318], + [97.386018, 32.77925], + [97.392793, 32.828546], + [97.376163, 32.886359], + [97.347829, 32.895907], + [97.375547, 32.956689], + [97.438372, 32.976271], + [97.523988, 32.988822], + [97.499966, 33.011408], + [97.542466, 33.035995], + [97.517213, 33.097683], + [97.487032, 33.107209], + [97.498119, 33.137783], + [97.487648, 33.168346], + [97.548626, 33.203907], + [97.607756, 33.263976], + [97.622538, 33.337005], + [97.676125, 33.341004], + [97.754349, 33.409972], + [97.674893, 33.432949], + [97.625618, 33.461412], + [97.552321, 33.465906], + [97.511669, 33.520805], + [97.523372, 33.577166], + [97.450075, 33.582152], + [97.415583, 33.605582], + [97.435293, 33.682307], + [97.418046, 33.728608], + [97.422974, 33.754984], + [97.406344, 33.795278], + [97.373083, 33.817655], + [97.371851, 33.842015], + [97.398336, 33.848477], + [97.395257, 33.889224], + [97.460546, 33.887236], + [97.503662, 33.912073], + [97.52214, 33.903133], + [97.601596, 33.929951], + [97.629314, 33.919523], + [97.660111, 33.956264], + [97.652719, 33.998448], + [97.70261, 34.036644], + [97.665654, 34.126855], + [97.766668, 34.158555], + [97.789458, 34.182818], + [97.789458, 34.182818], + [97.796849, 34.199154], + [97.796849, 34.199154], + [97.8104, 34.207568], + [97.898479, 34.209548], + [97.95453, 34.190739], + [98.028442, 34.122892], + [98.098043, 34.122892], + [98.158405, 34.107037], + [98.206449, 34.08424], + [98.258188, 34.083249], + [98.344419, 34.094648], + [98.399854, 34.085231], + [98.396774, 34.053008], + [98.428187, 34.029204], + [98.440506, 33.981577], + [98.415252, 33.956761], + [98.425723, 33.913066], + [98.407245, 33.867362], + [98.434962, 33.843009], + [98.463295, 33.848477], + [98.492861, 33.796272], + [98.494092, 33.768915], + [98.51873, 33.77389], + [98.539672, 33.746525], + [98.582788, 33.731595], + [98.610505, 33.682805], + [98.6567, 33.64744], + [98.61728, 33.637476], + [98.622824, 33.610067], + [98.652389, 33.595114], + [98.648077, 33.548741], + [98.678258, 33.522801], + [98.725686, 33.503341], + [98.742316, 33.477887], + [98.736157, 33.406975], + [98.779888, 33.370497], + [98.759562, 33.276985], + [98.802062, 33.270481], + [98.804526, 33.219428], + [98.858728, 33.150811], + [98.92217, 33.118738], + [98.967134, 33.115229], + [98.971445, 33.098185], + [99.014561, 33.081137], + [99.024416, 33.094675], + [99.090322, 33.079131], + [99.124814, 33.046028], + [99.196263, 33.035493], + [99.214741, 32.991332], + [99.235067, 32.982296], + [99.24677, 32.924043], + [99.268944, 32.878318], + [99.353944, 32.885354], + [99.376118, 32.899927], + [99.45311, 32.862233], + [99.558436, 32.839106], + [99.589233, 32.789312], + [99.640355, 32.790822], + [99.646515, 32.774721], + [99.700718, 32.76667], + [99.717964, 32.732443], + [99.760464, 32.769689], + [99.766623, 32.826032], + [99.791877, 32.883344], + [99.764159, 32.924545], + [99.788181, 32.956689], + [99.805427, 32.940619], + [99.851007, 32.941623], + [99.877492, 32.993339], + [99.877492, 33.045527], + [99.947709, 32.986814], + [99.956332, 32.948152], + [100.038252, 32.929066], + [100.029629, 32.895907], + [100.064738, 32.895907], + [100.123252, 32.837095], + [100.117093, 32.802392], + [100.139266, 32.724388], + [100.088143, 32.668988], + [100.109701, 32.640268], + [100.189773, 32.630692], + [100.208252, 32.606497], + [100.229809, 32.650346], + [100.231041, 32.696189], + [100.258759, 32.742511], + [100.339447, 32.719353], + [100.399193, 32.756101], + [100.378251, 32.698707], + [100.420135, 32.73194], + [100.450932, 32.694678], + [100.470026, 32.694678], + [100.516837, 32.632204], + [100.54517, 32.569687], + [100.603069, 32.553547], + [100.645568, 32.526303], + [100.657887, 32.546484], + [100.661583, 32.616075], + [100.673286, 32.628172], + [100.710242, 32.610026], + [100.71209, 32.645307], + [100.690532, 32.678056], + [100.77122, 32.643795], + [100.834046, 32.648835], + [100.887633, 32.632708], + [100.93198, 32.600447], + [100.956618, 32.621116], + [100.99727, 32.627668], + [101.030531, 32.660424], + [101.077342, 32.68259], + [101.124769, 32.658408], + [101.157414, 32.661431], + [101.22332, 32.725898], + [101.237486, 32.825026], + [101.223935, 32.855698], + [101.178356, 32.892892], + [101.124153, 32.909976], + [101.134624, 32.95217], + [101.129081, 32.989324], + [101.183899, 32.984304], + [101.171581, 33.009902], + [101.184515, 33.041514], + [101.146327, 33.056563], + [101.143863, 33.086151], + [101.169733, 33.10019], + [101.11553, 33.194893], + [101.124769, 33.221431], + [101.156798, 33.236449], + [101.182668, 33.26948], + [101.217776, 33.256469], + [101.297232, 33.262475], + [101.381616, 33.153316], + [101.393935, 33.157826], + [101.386543, 33.207412], + [101.403174, 33.225436], + [101.487557, 33.226938], + [101.515275, 33.192889], + [101.557775, 33.167344], + [101.633535, 33.101193], + [101.661252, 33.135778], + [101.653861, 33.162835], + [101.709912, 33.21292], + [101.735781, 33.279987], + [101.677883, 33.297497], + [101.64955, 33.323004], + [101.663716, 33.383991], + [101.695745, 33.433948], + [101.769042, 33.45592], + [101.777665, 33.533776], + [101.769042, 33.538765], + [101.748716, 33.505337], + [101.718535, 33.494857], + [101.622448, 33.502343], + [101.611977, 33.565199], + [101.616905, 33.598603], + [101.585492, 33.645448], + [101.58426, 33.674339], + [101.501724, 33.702723], + [101.428427, 33.680315], + [101.424732, 33.655411], + [101.385312, 33.644949], + [101.302776, 33.657902], + [101.23687, 33.685793], + [101.217776, 33.669856], + [101.166653, 33.659894], + [101.177124, 33.685295], + [101.162957, 33.719649], + [101.186363, 33.741051], + [101.190675, 33.791796], + [101.153102, 33.823124], + [101.153718, 33.8445], + [101.054552, 33.863386], + [101.023139, 33.896178], + [100.994806, 33.891707], + [100.965857, 33.946832], + [100.927669, 33.975126], + [100.93506, 33.990013], + [100.880857, 34.036644], + [100.870386, 34.083744], + [100.848828, 34.089692], + [100.806329, 34.155584], + [100.764445, 34.178857], + [100.809408, 34.247153], + [100.798321, 34.260014], + [100.821727, 34.317371], + [100.868538, 34.332693], + [100.895024, 34.375183], + [100.951074, 34.38358], + [100.986799, 34.374689], + [101.054552, 34.322808], + [101.098284, 34.329233], + [101.178356, 34.320831], + [101.193754, 34.336646], + [101.235022, 34.325279], + [101.228863, 34.298586], + [101.268899, 34.278808], + [101.325565, 34.268423], + [101.327413, 34.24468], + [101.369913, 34.248143], + [101.417956, 34.227858], + [101.482014, 34.218951], + [101.492485, 34.195689], + [101.53868, 34.212022], + [101.6206, 34.178857], + [101.674187, 34.110506], + [101.703136, 34.119424], + [101.718535, 34.083249], + [101.736397, 34.080275], + [101.764114, 34.122892], + [101.788136, 34.131809], + [101.836795, 34.124378], + [101.851578, 34.153108], + [101.874367, 34.130323], + [101.897773, 34.133791], + [101.955055, 34.109514], + [101.965526, 34.167469], + [102.003099, 34.162022], + [102.030816, 34.190739], + [102.01357, 34.218456], + [102.062229, 34.227858], + [102.067772, 34.293642], + [102.149692, 34.271885], + [102.186649, 34.352952], + [102.237156, 34.34307], + [102.237156, 34.34307], + [102.259329, 34.355917], + [102.205743, 34.407777], + [102.169402, 34.457631], + [102.155852, 34.507456], + [102.139837, 34.50351], + [102.093026, 34.536547], + [102.001867, 34.538519], + [101.97415, 34.548871], + [101.956287, 34.582876], + [101.934729, 34.58731], + [101.919947, 34.621791], + [101.917483, 34.705964], + [101.923027, 34.835746], + [101.916867, 34.873561], + [101.985852, 34.90007], + [102.068388, 34.887798], + [102.048062, 34.910868], + [102.094874, 34.986901], + [102.133678, 35.014844], + [102.157699, 35.010923], + [102.176178, 35.032977], + [102.211286, 35.034937], + [102.218062, 35.057475], + [102.252554, 35.048657], + [102.29567, 35.071681], + [102.310452, 35.128967], + [102.346793, 35.164201], + [102.404075, 35.179366], + [102.365887, 35.235599], + [102.370199, 35.263946], + [102.3123, 35.282512], + [102.280887, 35.303028], + [102.311684, 35.31426], + [102.317844, 35.343067], + [102.287663, 35.36552], + [102.293822, 35.424063], + [102.314764, 35.434303], + [102.408387, 35.409431], + [102.447807, 35.437229], + [102.437952, 35.455268], + [102.49893, 35.545403], + [102.503241, 35.585322], + [102.531575, 35.580455], + [102.570995, 35.548324], + [102.695414, 35.528358], + [102.743458, 35.494745], + [102.782878, 35.527871], + [102.729291, 35.523487], + [102.746537, 35.545403], + [102.808747, 35.560496], + [102.763168, 35.612086], + [102.7644, 35.653431], + [102.744074, 35.657807], + [102.707733, 35.70496], + [102.686175, 35.771996], + [102.715125, 35.815685], + [102.739146, 35.821023], + [102.787189, 35.862745], + [102.81737, 35.850133], + [102.914073, 35.845282], + [102.94487, 35.829757], + [102.954725, 35.858864], + [102.942406, 35.92674], + [102.971971, 35.995525], + [102.951645, 36.021667], + [102.968276, 36.044414], + [102.932551, 36.048285], + [102.882044, 36.082632], + [102.941174, 36.104877], + [102.948566, 36.150798], + [102.965812, 36.151765], + [102.986754, 36.193312], + [103.048964, 36.199107], + [103.066826, 36.216974], + [103.021246, 36.232906], + [103.024942, 36.256556], + [102.922696, 36.298047], + [102.896827, 36.331803], + [102.845704, 36.331803], + [102.836465, 36.344819], + [102.829689, 36.365544] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 640000, + "name": "宁夏回族自治区", + "center": [106.278179, 38.46637], + "centroid": [106.169866, 37.291332], + "childrenNum": 5, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 29, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [107.268764, 37.099367], + [107.281083, 37.127047], + [107.306952, 37.100799], + [107.334669, 37.138975], + [107.336517, 37.165687], + [107.317423, 37.200017], + [107.270612, 37.229089], + [107.309416, 37.239095], + [107.273075, 37.29101], + [107.257677, 37.337179], + [107.282931, 37.437036], + [107.284162, 37.481691], + [107.345756, 37.518725], + [107.369162, 37.58752], + [107.330358, 37.584201], + [107.311264, 37.609806], + [107.361155, 37.613125], + [107.422133, 37.665254], + [107.389488, 37.671413], + [107.387024, 37.691305], + [107.425828, 37.684201], + [107.484959, 37.706458], + [107.499125, 37.765619], + [107.57119, 37.776499], + [107.599523, 37.791162], + [107.620465, 37.776026], + [107.646335, 37.805349], + [107.659269, 37.844112], + [107.65003, 37.86443], + [107.560719, 37.893717], + [107.49235, 37.944706], + [107.448618, 37.933378], + [107.411662, 37.948009], + [107.440611, 37.995659], + [107.3938, 38.014993], + [107.33159, 38.086625], + [107.240431, 38.111586], + [107.19054, 38.153953], + [107.138801, 38.161011], + [107.119091, 38.134185], + [107.071047, 38.138892], + [107.051337, 38.122886], + [107.010069, 38.120532], + [106.942316, 38.132302], + [106.858548, 38.156306], + [106.779092, 38.171833], + [106.737824, 38.197706], + [106.654672, 38.22921], + [106.627571, 38.232501], + [106.555506, 38.263521], + [106.482209, 38.319417], + [106.599854, 38.389812], + [106.647897, 38.470917], + [106.66268, 38.601524], + [106.709491, 38.718821], + [106.756302, 38.748699], + [106.837606, 38.847579], + [106.954019, 38.941202], + [106.971881, 39.026333], + [106.96757, 39.054688], + [106.933693, 39.076527], + [106.878874, 39.091392], + [106.859164, 39.107648], + [106.825288, 39.19397], + [106.795723, 39.214375], + [106.790795, 39.241263], + [106.806193, 39.277407], + [106.806809, 39.318625], + [106.781556, 39.371849], + [106.751375, 39.381564], + [106.683622, 39.357506], + [106.643586, 39.357969], + [106.602318, 39.37555], + [106.556122, 39.322329], + [106.525325, 39.308439], + [106.511774, 39.272311], + [106.402753, 39.291767], + [106.280181, 39.262118], + [106.29558, 39.167992], + [106.285109, 39.146181], + [106.251232, 39.131327], + [106.192718, 39.142932], + [106.170544, 39.163352], + [106.145907, 39.153142], + [106.096631, 39.084889], + [106.078153, 39.026333], + [106.087392, 39.006339], + [106.060907, 38.96866], + [106.021487, 38.953769], + [105.97098, 38.909077], + [105.992538, 38.857366], + [105.909386, 38.791159], + [105.908154, 38.737496], + [105.88598, 38.716953], + [105.894603, 38.696405], + [105.852719, 38.641735], + [105.874277, 38.593105], + [105.856415, 38.569714], + [105.863806, 38.53508], + [105.836705, 38.476071], + [105.850872, 38.443736], + [105.827466, 38.432486], + [105.835473, 38.387467], + [105.821307, 38.366824], + [105.86627, 38.296406], + [105.842248, 38.240962], + [105.802828, 38.220277], + [105.775111, 38.186887], + [105.76772, 38.121474], + [105.780655, 38.084741], + [105.840401, 38.004147], + [105.799749, 37.939986], + [105.80406, 37.862068], + [105.760944, 37.799674], + [105.677177, 37.771769], + [105.622358, 37.777919], + [105.616199, 37.722555], + [105.598952, 37.699356], + [105.467141, 37.695094], + [105.4037, 37.710246], + [105.315004, 37.702197], + [105.221998, 37.677097], + [105.187505, 37.657674], + [105.111128, 37.633981], + [105.027977, 37.580881], + [104.866601, 37.566651], + [104.805007, 37.539133], + [104.623305, 37.522522], + [104.433595, 37.515402], + [104.419429, 37.511604], + [104.407726, 37.464592], + [104.322726, 37.44844], + [104.287002, 37.428007], + [104.298705, 37.414223], + [104.365226, 37.418026], + [104.437907, 37.445589], + [104.448994, 37.42468], + [104.499501, 37.421353], + [104.521059, 37.43466], + [104.679971, 37.408044], + [104.662109, 37.367626], + [104.713848, 37.329566], + [104.673812, 37.317668], + [104.651022, 37.290534], + [104.624536, 37.298627], + [104.600515, 37.242907], + [104.638087, 37.201923], + [104.717543, 37.208597], + [104.776673, 37.246718], + [104.85613, 37.211933], + [104.864753, 37.17284], + [104.888158, 37.15901], + [104.914644, 37.097935], + [104.954064, 37.077407], + [104.95468, 37.040156], + [105.004571, 37.035378], + [105.03968, 37.007187], + [105.05939, 37.022956], + [105.128991, 36.996194], + [105.165331, 36.99476], + [105.185657, 36.942164], + [105.178882, 36.892403], + [105.244787, 36.894796], + [105.279896, 36.86751], + [105.303302, 36.820575], + [105.334714, 36.80093], + [105.340874, 36.764502], + [105.319932, 36.742924], + [105.275584, 36.752515], + [105.272505, 36.739567], + [105.218302, 36.730455], + [105.201056, 36.700711], + [105.225693, 36.664716], + [105.22015, 36.631105], + [105.261418, 36.602764], + [105.2762, 36.563358], + [105.252179, 36.553263], + [105.281744, 36.522489], + [105.322396, 36.535954], + [105.362432, 36.496514], + [105.363048, 36.443093], + [105.398156, 36.430575], + [105.401236, 36.369881], + [105.425873, 36.330357], + [105.455439, 36.321678], + [105.476381, 36.293224], + [105.45975, 36.268137], + [105.460366, 36.223733], + [105.478844, 36.213111], + [105.515185, 36.147415], + [105.491163, 36.101009], + [105.430801, 36.10391], + [105.406163, 36.074409], + [105.343954, 36.033767], + [105.324859, 35.941761], + [105.350113, 35.875839], + [105.39754, 35.857409], + [105.371055, 35.844312], + [105.38091, 35.792873], + [105.408627, 35.822479], + [105.428953, 35.819082], + [105.432033, 35.787533], + [105.457286, 35.771511], + [105.481924, 35.727312], + [105.595873, 35.715651], + [105.667322, 35.749657], + [105.70243, 35.733142], + [105.759097, 35.724883], + [105.740618, 35.698643], + [105.723988, 35.725854], + [105.690727, 35.698643], + [105.722756, 35.673366], + [105.713517, 35.650513], + [105.759097, 35.634464], + [105.762176, 35.602841], + [105.800365, 35.564878], + [105.816379, 35.575101], + [105.847176, 35.490359], + [105.868734, 35.540046], + [105.900147, 35.54735], + [106.017175, 35.519103], + [106.023335, 35.49377], + [106.047356, 35.498155], + [106.078769, 35.509848], + [106.071994, 35.463555], + [106.06953, 35.458193], + [106.073842, 35.45478], + [106.073226, 35.450393], + [106.071378, 35.449418], + [106.073226, 35.447468], + [106.083081, 35.421624], + [106.113262, 35.361616], + [106.129892, 35.393333], + [106.173008, 35.437716], + [106.196414, 35.409919], + [106.237681, 35.409431], + [106.241377, 35.358687], + [106.319601, 35.265411], + [106.363333, 35.238532], + [106.368261, 35.273718], + [106.415688, 35.276161], + [106.472354, 35.310842], + [106.501304, 35.364056], + [106.503767, 35.415284], + [106.483441, 35.450393], + [106.490217, 35.480613], + [106.465579, 35.481101], + [106.440941, 35.52641], + [106.460036, 35.578995], + [106.47913, 35.575101], + [106.460036, 35.643705], + [106.434782, 35.688436], + [106.49268, 35.732656], + [106.506231, 35.737514], + [106.566593, 35.738971], + [106.595542, 35.727312], + [106.620796, 35.743829], + [106.633115, 35.714679], + [106.66268, 35.70739], + [106.674998, 35.728284], + [106.750759, 35.689408], + [106.750759, 35.725369], + [106.806193, 35.70982], + [106.819128, 35.7448], + [106.867171, 35.738485], + [106.868403, 35.771996], + [106.897353, 35.759856], + [106.927534, 35.810346], + [106.849925, 35.887476], + [106.912751, 35.93207], + [106.940468, 35.931101], + [106.93862, 35.952905], + [106.90228, 35.943699], + [106.94786, 35.988262], + [106.928149, 36.011502], + [106.940468, 36.064734], + [106.957715, 36.091337], + [106.925686, 36.115997], + [106.930613, 36.138716], + [106.873947, 36.178338], + [106.873947, 36.178338], + [106.858548, 36.206834], + [106.858548, 36.206834], + [106.833295, 36.229044], + [106.808657, 36.21118], + [106.772933, 36.212628], + [106.735976, 36.23725], + [106.698404, 36.244008], + [106.685469, 36.273445], + [106.647897, 36.259451], + [106.559202, 36.292259], + [106.54134, 36.25366], + [106.504383, 36.266207], + [106.470507, 36.306246], + [106.497608, 36.31348], + [106.510543, 36.379037], + [106.492064, 36.422389], + [106.523477, 36.468605], + [106.494528, 36.494589], + [106.455724, 36.496995], + [106.39721, 36.548455], + [106.37134, 36.549417], + [106.363949, 36.577296], + [106.392282, 36.556628], + [106.397826, 36.576816], + [106.444637, 36.557109], + [106.465579, 36.583063], + [106.444637, 36.624861], + [106.491448, 36.628703], + [106.490833, 36.685835], + [106.530869, 36.690154], + [106.519782, 36.708868], + [106.519782, 36.708868], + [106.514238, 36.715584], + [106.59431, 36.750118], + [106.644817, 36.72278], + [106.627571, 36.752995], + [106.657752, 36.820575], + [106.637426, 36.867031], + [106.637426, 36.867031], + [106.626955, 36.892403], + [106.609709, 36.878521], + [106.609709, 36.878521], + [106.601702, 36.918244], + [106.549347, 36.941685], + [106.540108, 36.984244], + [106.595542, 36.94025], + [106.594926, 36.967988], + [106.64297, 36.962729], + [106.646665, 37.000496], + [106.666991, 37.016745], + [106.645433, 37.064992], + [106.605397, 37.127524], + [106.6171, 37.135158], + [106.673151, 37.1113], + [106.687933, 37.12991], + [106.728585, 37.121321], + [106.750143, 37.09889], + [106.772933, 37.120367], + [106.776012, 37.158056], + [106.818512, 37.141838], + [106.891193, 37.098413], + [106.912135, 37.110345], + [106.905976, 37.151378], + [106.998367, 37.106527], + [107.031011, 37.108436], + [107.030395, 37.140883], + [107.095685, 37.115595], + [107.133873, 37.134681], + [107.181916, 37.143269], + [107.234887, 37.096503], + [107.268764, 37.099367] + ] + ], + [ + [ + [106.048588, 35.488898], + [105.897683, 35.451368], + [105.894603, 35.413821], + [106.002393, 35.438692], + [106.034422, 35.469404], + [106.054132, 35.45478], + [106.048588, 35.488898] + ] + ], + [ + [ + [106.073842, 35.45478], + [106.06953, 35.458193], + [106.071378, 35.449418], + [106.073226, 35.450393], + [106.073842, 35.45478] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 650000, + "name": "新疆维吾尔自治区", + "center": [87.617733, 43.792818], + "centroid": [85.294711, 41.371801], + "childrenNum": 24, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 30, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [96.386348, 42.727592], + [96.363558, 42.900562], + [95.921314, 43.229789], + [95.880046, 43.28035], + [95.857872, 43.417436], + [95.735916, 43.597569], + [95.705735, 43.67077], + [95.645373, 43.787966], + [95.623199, 43.855756], + [95.527113, 44.007466], + [95.426099, 44.009618], + [95.377439, 44.025972], + [95.326932, 44.028554], + [95.35157, 44.090054], + [95.355882, 44.166087], + [95.376208, 44.227444], + [95.4107, 44.245024], + [95.43041, 44.281882], + [95.41378, 44.298589], + [95.238853, 44.277169], + [95.1286, 44.269884], + [94.998637, 44.253169], + [94.945666, 44.292592], + [94.826174, 44.320001], + [94.768275, 44.34055], + [94.722696, 44.34055], + [94.673421, 44.397021], + [94.606283, 44.448311], + [94.557008, 44.462408], + [94.470777, 44.509373], + [94.390705, 44.521749], + [94.359292, 44.515775], + [94.329727, 44.582734], + [94.279836, 44.603617], + [94.227481, 44.645785], + [94.215162, 44.667921], + [94.152336, 44.684944], + [94.066105, 44.732154], + [93.723642, 44.865498], + [93.716251, 44.894334], + [93.613389, 44.926546], + [93.509296, 44.968055], + [93.434767, 44.955351], + [93.376869, 44.985412], + [93.314659, 44.995147], + [93.314043, 44.980333], + [93.252449, 44.991761], + [93.174225, 45.015458], + [93.100312, 45.007419], + [93.062124, 45.018419], + [93.002377, 45.009958], + [92.932776, 45.017573], + [92.922921, 45.03703], + [92.884117, 45.046756], + [92.847777, 45.038721], + [92.779407, 45.050561], + [92.683937, 45.02561], + [92.547814, 45.018419], + [92.501003, 45.001072], + [92.414155, 45.018419], + [92.348866, 45.014188], + [92.315605, 45.028994], + [92.240461, 45.015881], + [92.100026, 45.081417], + [92.056911, 45.086911], + [91.885679, 45.078882], + [91.803144, 45.082685], + [91.694738, 45.065357], + [91.561695, 45.075501], + [91.500101, 45.103809], + [91.448978, 45.156586], + [91.429268, 45.156586], + [91.37753, 45.11099], + [91.33503, 45.129571], + [91.242023, 45.13717], + [91.230936, 45.153632], + [91.195827, 45.159118], + [91.17119, 45.199616], + [91.129922, 45.21606], + [91.050466, 45.208892], + [91.007966, 45.218589], + [90.96177, 45.201303], + [90.881698, 45.192025], + [90.866916, 45.209314], + [90.897713, 45.249776], + [90.877387, 45.280946], + [90.831807, 45.300313], + [90.804706, 45.29484], + [90.813329, 45.32851], + [90.773909, 45.405874], + [90.772677, 45.432338], + [90.723402, 45.464667], + [90.671047, 45.487747], + [90.676591, 45.582488], + [90.714779, 45.728895], + [90.799778, 45.834905], + [90.890937, 45.921566], + [91.028292, 46.023054], + [91.014741, 46.06667], + [91.021517, 46.121038], + [90.98456, 46.160431], + [90.94822, 46.219262], + [90.955611, 46.233752], + [90.900177, 46.31235], + [90.983328, 46.374734], + [90.996263, 46.419309], + [91.025828, 46.444057], + [91.038147, 46.500936], + [91.060937, 46.516999], + [91.079415, 46.558989], + [91.068328, 46.579149], + [91.017821, 46.58244], + [91.036299, 46.670393], + [91.054161, 46.717598], + [91.019053, 46.766402], + [90.992567, 46.769682], + [90.992567, 46.790583], + [90.942676, 46.82581], + [90.958075, 46.879425], + [90.929742, 46.893331], + [90.92235, 46.938707], + [90.901408, 46.960768], + [90.830575, 46.995883], + [90.767134, 46.992617], + [90.691989, 47.080717], + [90.653801, 47.111681], + [90.579888, 47.198364], + [90.56141, 47.206903], + [90.521374, 47.2845], + [90.488113, 47.317374], + [90.526301, 47.379007], + [90.507823, 47.400076], + [90.468403, 47.404937], + [90.459164, 47.43895], + [90.474562, 47.462422], + [90.468403, 47.497611], + [90.398186, 47.547724], + [90.376012, 47.603036], + [90.346447, 47.637324], + [90.384635, 47.644179], + [90.331665, 47.681663], + [90.216484, 47.70543], + [90.180144, 47.72516], + [90.13518, 47.723147], + [90.07605, 47.777469], + [90.070506, 47.820483], + [90.086521, 47.86547], + [90.066195, 47.883534], + [90.040941, 47.874704], + [89.960253, 47.885942], + [89.957789, 47.842982], + [89.86971, 47.834144], + [89.761921, 47.835751], + [89.735435, 47.89758], + [89.651052, 47.913627], + [89.645508, 47.947711], + [89.595617, 47.973359], + [89.599313, 48.015811], + [89.569132, 48.037825], + [89.498299, 48.02822], + [89.38127, 48.046227], + [89.359712, 48.026219], + [89.308589, 48.021816], + [89.282104, 47.994189], + [89.231597, 47.98017], + [89.156452, 47.996992], + [89.078228, 47.98698], + [89.044967, 48.009806], + [89.027105, 48.051028], + [88.953808, 48.090618], + [88.939026, 48.115396], + [88.824461, 48.107005], + [88.79736, 48.133772], + [88.721599, 48.160526], + [88.700657, 48.180881], + [88.668628, 48.171303], + [88.638447, 48.183674], + [88.601491, 48.221567], + [88.594716, 48.259831], + [88.575006, 48.277757], + [88.605803, 48.337863], + [88.573774, 48.351785], + [88.573158, 48.369679], + [88.535586, 48.368884], + [88.523267, 48.403461], + [88.503557, 48.412996], + [88.462289, 48.392335], + [88.438267, 48.393528], + [88.360659, 48.433251], + [88.363123, 48.460641], + [88.318159, 48.478497], + [88.229464, 48.498329], + [88.196819, 48.493967], + [88.151855, 48.526478], + [88.130297, 48.521721], + [88.10874, 48.545895], + [88.041602, 48.548272], + [87.973233, 48.575997], + [87.96153, 48.599353], + [88.010805, 48.618742], + [88.02682, 48.65315], + [88.089645, 48.69504], + [88.090877, 48.71992], + [88.064392, 48.712813], + [88.029283, 48.750313], + [87.96153, 48.773588], + [87.93874, 48.757809], + [87.872219, 48.799612], + [87.826639, 48.800795], + [87.803234, 48.824835], + [87.829103, 48.825623], + [87.792147, 48.849258], + [87.78106, 48.872094], + [87.742256, 48.881146], + [87.760118, 48.925992], + [87.793995, 48.927565], + [87.814321, 48.945256], + [87.87653, 48.949186], + [87.871603, 48.963726], + [87.911639, 48.979833], + [87.883922, 48.993971], + [87.883306, 49.023806], + [87.835263, 49.054406], + [87.858052, 49.07362], + [87.844502, 49.090084], + [87.867291, 49.108892], + [87.845733, 49.146096], + [87.82048, 49.148445], + [87.821096, 49.173883], + [87.793379, 49.18249], + [87.762582, 49.172709], + [87.700372, 49.175839], + [87.67635, 49.15549], + [87.602437, 49.152359], + [87.563017, 49.142572], + [87.517438, 49.145704], + [87.49588, 49.132001], + [87.511894, 49.10184], + [87.43675, 49.075188], + [87.388707, 49.097921], + [87.304939, 49.112418], + [87.239033, 49.114376], + [87.211932, 49.140615], + [87.112766, 49.15549], + [87.088128, 49.133567], + [87.000049, 49.142572], + [86.953853, 49.131218], + [86.887948, 49.132001], + [86.854071, 49.109284], + [86.84976, 49.066563], + [86.836209, 49.051269], + [86.772151, 49.02773], + [86.732115, 48.994757], + [86.730267, 48.959797], + [86.757985, 48.894919], + [86.782006, 48.887049], + [86.821426, 48.850439], + [86.818963, 48.831139], + [86.770303, 48.810255], + [86.754289, 48.78463], + [86.780774, 48.731369], + [86.771535, 48.717156], + [86.70255, 48.666195], + [86.693311, 48.64366], + [86.640956, 48.629027], + [86.635413, 48.612016], + [86.594761, 48.576789], + [86.579978, 48.538763], + [86.416138, 48.481671], + [86.38103, 48.49357], + [86.305269, 48.491984], + [86.270161, 48.452307], + [86.225813, 48.432456], + [86.053966, 48.441192], + [85.916612, 48.438015], + [85.791576, 48.418954], + [85.758315, 48.403064], + [85.695489, 48.335078], + [85.695489, 48.302445], + [85.678243, 48.266205], + [85.633895, 48.232731], + [85.622193, 48.202824], + [85.587084, 48.191654], + [85.576613, 48.15853], + [85.55136, 48.127781], + [85.551975, 48.081423], + [85.531649, 48.046227], + [85.547048, 48.008205], + [85.617881, 47.550552], + [85.614801, 47.498015], + [85.685018, 47.428829], + [85.701649, 47.384275], + [85.675779, 47.321837], + [85.701033, 47.28856], + [85.682555, 47.249982], + [85.682555, 47.222757], + [85.641903, 47.18413], + [85.582772, 47.142626], + [85.547048, 47.096609], + [85.545816, 47.057891], + [85.441106, 47.063191], + [85.355491, 47.054629], + [85.325926, 47.044842], + [85.276651, 47.068898], + [85.213825, 47.041172], + [85.175637, 46.997924], + [85.102956, 46.968936], + [85.082014, 46.939933], + [84.987159, 46.918272], + [84.979768, 46.883106], + [84.95513, 46.861013], + [84.934188, 46.863878], + [84.867051, 46.927673], + [84.849189, 46.957092], + [84.781435, 46.979962], + [84.748175, 47.009759], + [84.699515, 47.008535], + [84.668718, 46.995067], + [84.563393, 46.991801], + [84.506726, 46.97302], + [84.425422, 47.008943], + [84.37122, 46.993434], + [84.336727, 47.00527], + [84.2893, 46.994658], + [84.195061, 47.003638], + [84.150098, 46.977512], + [84.086656, 46.965261], + [84.038613, 46.973428], + [84.002888, 46.990576], + [83.951765, 46.98731], + [83.932671, 46.970161], + [83.88586, 46.982003], + [83.766367, 47.026896], + [83.69923, 47.015472], + [83.700462, 47.032199], + [83.576042, 47.059114], + [83.566803, 47.080717], + [83.53847, 47.083977], + [83.463325, 47.132042], + [83.418978, 47.119012], + [83.370318, 47.178436], + [83.324739, 47.167858], + [83.306261, 47.179656], + [83.257602, 47.173147], + [83.221877, 47.186977], + [83.207094, 47.213814], + [83.17445, 47.218286], + [83.15474, 47.236168], + [83.108544, 47.221944], + [83.02724, 47.21544], + [83.031552, 47.168265], + [82.993364, 47.065229], + [82.937929, 47.014248], + [82.923762, 46.932169], + [82.876335, 46.823762], + [82.878183, 46.797138], + [82.829524, 46.772551], + [82.788872, 46.677784], + [82.774089, 46.600124], + [82.726662, 46.494756], + [82.609017, 46.294985], + [82.518474, 46.153798], + [82.461808, 45.97982], + [82.401446, 45.972333], + [82.342932, 45.935303], + [82.336156, 45.882418], + [82.349707, 45.822811], + [82.340468, 45.772742], + [82.289961, 45.71636], + [82.288729, 45.655321], + [82.266555, 45.620172], + [82.281954, 45.53891], + [82.448257, 45.461309], + [82.546808, 45.426038], + [82.60101, 45.346178], + [82.58746, 45.224069], + [82.562822, 45.204676], + [82.487061, 45.181058], + [82.344779, 45.219011], + [82.294272, 45.247669], + [82.206809, 45.236713], + [82.109491, 45.211422], + [82.091012, 45.222383], + [82.09594, 45.249776], + [82.052824, 45.255674], + [81.993078, 45.237978], + [81.921013, 45.233342], + [81.879745, 45.284314], + [81.832318, 45.319673], + [81.78797, 45.3836], + [81.677101, 45.35459], + [81.645072, 45.359216], + [81.582863, 45.336503], + [81.575471, 45.30789], + [81.536667, 45.304101], + [81.52866, 45.285999], + [81.462754, 45.264099], + [81.437501, 45.28263], + [81.398697, 45.275471], + [81.382066, 45.257781], + [81.327864, 45.260729], + [81.284748, 45.23882], + [81.236705, 45.247248], + [81.175111, 45.227863], + [81.170183, 45.211001], + [81.111669, 45.218168], + [81.080872, 45.182745], + [81.024821, 45.162916], + [80.966307, 45.168402], + [80.93551, 45.160384], + [80.897938, 45.127459], + [80.862214, 45.127037], + [80.816634, 45.152788], + [80.731634, 45.156164], + [80.686055, 45.129148], + [80.599207, 45.105921], + [80.519135, 45.108878], + [80.493882, 45.127037], + [80.445839, 45.097895], + [80.443991, 45.077614], + [80.404571, 45.049293], + [80.358375, 45.040836], + [80.328194, 45.070007], + [80.291854, 45.06578], + [80.24381, 45.031532], + [80.195767, 45.030686], + [80.144644, 45.059017], + [80.136021, 45.041259], + [80.111999, 45.052675], + [80.060876, 45.026033], + [80.056565, 45.011227], + [79.98142, 44.964244], + [79.951855, 44.957892], + [79.944464, 44.937985], + [79.887798, 44.90917], + [79.969102, 44.877797], + [79.953703, 44.849377], + [79.991891, 44.830281], + [79.999283, 44.793768], + [80.087978, 44.817122], + [80.115695, 44.815424], + [80.169898, 44.84471], + [80.18776, 44.825612], + [80.178521, 44.796741], + [80.200695, 44.756808], + [80.238883, 44.7228], + [80.313412, 44.704938], + [80.400259, 44.628751], + [80.411962, 44.605321], + [80.350368, 44.484615], + [80.383013, 44.401297], + [80.399027, 44.30587], + [80.413194, 44.264741], + [80.400875, 44.198704], + [80.407034, 44.149772], + [80.3941, 44.127009], + [80.449534, 44.078017], + [80.458773, 44.047054], + [80.457541, 43.981203], + [80.485259, 43.95579], + [80.475404, 43.938124], + [80.511128, 43.906657], + [80.522215, 43.816473], + [80.75504, 43.494329], + [80.761199, 43.446554], + [80.746417, 43.439167], + [80.735946, 43.389609], + [80.686055, 43.333916], + [80.69283, 43.32042], + [80.777214, 43.308227], + [80.769207, 43.265535], + [80.788917, 43.242433], + [80.789533, 43.201876], + [80.804315, 43.178314], + [80.79446, 43.137277], + [80.752576, 43.148194], + [80.73225, 43.131163], + [80.706997, 43.143828], + [80.650946, 43.147321], + [80.593048, 43.133347], + [80.556092, 43.104515], + [80.482795, 43.06955], + [80.416889, 43.05687], + [80.378701, 43.031502], + [80.397795, 42.996933], + [80.487106, 42.948766], + [80.5912, 42.923354], + [80.602903, 42.894424], + [80.503737, 42.882146], + [80.450766, 42.861971], + [80.407034, 42.834767], + [80.338049, 42.831695], + [80.280151, 42.838278], + [80.262289, 42.828623], + [80.259209, 42.790865], + [80.225948, 42.713083], + [80.228412, 42.692852], + [80.179753, 42.670415], + [80.163738, 42.629919], + [80.180985, 42.590718], + [80.221637, 42.533415], + [80.265368, 42.502097], + [80.225948, 42.485769], + [80.206238, 42.431462], + [80.239499, 42.389927], + [80.229028, 42.358536], + [80.283847, 42.320493], + [80.272144, 42.281984], + [80.29247, 42.259842], + [80.28631, 42.233261], + [80.233339, 42.210215], + [80.168666, 42.200462], + [80.163738, 42.152563], + [80.139717, 42.151232], + [80.16805, 42.096635], + [80.193303, 42.081535], + [80.14218, 42.03488], + [80.089826, 42.047325], + [79.923522, 42.042436], + [79.852689, 42.015319], + [79.854537, 41.984186], + [79.822508, 41.963275], + [79.776313, 41.89248], + [79.724574, 41.896935], + [79.640806, 41.884907], + [79.616784, 41.856385], + [79.550879, 41.834094], + [79.500988, 41.835432], + [79.457256, 41.847915], + [79.415372, 41.836769], + [79.356242, 41.795735], + [79.326061, 41.809565], + [79.276786, 41.78101], + [79.271858, 41.767174], + [79.21704, 41.725648], + [79.138199, 41.722968], + [79.10925, 41.697503], + [79.043345, 41.681414], + [79.021787, 41.657273], + [78.99407, 41.664427], + [78.957729, 41.65146], + [78.891824, 41.597777], + [78.86657, 41.593749], + [78.825302, 41.560173], + [78.739071, 41.555695], + [78.696571, 41.54181], + [78.707042, 41.522098], + [78.675629, 41.50238], + [78.650375, 41.467411], + [78.580774, 41.481759], + [78.527188, 41.440947], + [78.454507, 41.412228], + [78.391681, 41.408189], + [78.385522, 41.394721], + [78.338094, 41.397415], + [78.324544, 41.384395], + [78.235232, 41.399211], + [78.163783, 41.383497], + [78.149617, 41.368228], + [78.165015, 41.340825], + [78.136682, 41.279239], + [78.129291, 41.228398], + [78.094798, 41.224347], + [77.972842, 41.173013], + [77.905089, 41.185174], + [77.836104, 41.153189], + [77.814546, 41.13426], + [77.807155, 41.091876], + [77.829328, 41.059394], + [77.796068, 41.049014], + [77.780669, 41.022832], + [77.737553, 41.032313], + [77.684583, 41.00793], + [77.654402, 41.016059], + [77.597119, 41.005221], + [77.591576, 40.992122], + [77.540453, 41.006575], + [77.476395, 40.999349], + [77.473931, 41.022832], + [77.415417, 41.038633], + [77.363062, 41.04089], + [77.296541, 41.004769], + [77.236795, 41.027798], + [77.169041, 41.009285], + [77.108063, 41.038181], + [77.091433, 41.062553], + [77.023064, 41.059394], + [77.002122, 41.073381], + [76.940528, 41.028701], + [76.885709, 41.027347], + [76.85368, 40.97631], + [76.817956, 40.975406], + [76.761905, 40.954167], + [76.741579, 40.912119], + [76.731724, 40.818887], + [76.693536, 40.779472], + [76.646725, 40.759983], + [76.646725, 40.73686], + [76.676906, 40.696036], + [76.654732, 40.652917], + [76.657196, 40.620218], + [76.611, 40.601591], + [76.601145, 40.578868], + [76.556798, 40.542495], + [76.543247, 40.513837], + [76.539551, 40.464226], + [76.508754, 40.429613], + [76.470566, 40.422779], + [76.442233, 40.391336], + [76.390494, 40.37766], + [76.381871, 40.39088], + [76.333212, 40.343459], + [76.327668, 40.391336], + [76.283321, 40.415034], + [76.279625, 40.439179], + [76.22419, 40.401819], + [76.176147, 40.381307], + [76.144118, 40.393615], + [76.081293, 40.39635], + [76.048648, 40.388601], + [76.048648, 40.357141], + [76.026474, 40.355317], + [75.986438, 40.381763], + [75.932235, 40.339353], + [75.921764, 40.291439], + [75.890351, 40.30924], + [75.84046, 40.312434], + [75.831221, 40.327492], + [75.785642, 40.301025], + [75.739446, 40.299199], + [75.709265, 40.280939], + [75.688323, 40.343915], + [75.669845, 40.363982], + [75.686475, 40.418223], + [75.717272, 40.443278], + [75.733287, 40.474242], + [75.646439, 40.516567], + [75.631041, 40.548862], + [75.627345, 40.605226], + [75.636584, 40.624306], + [75.599628, 40.659727], + [75.550353, 40.64883], + [75.467817, 40.599773], + [75.432093, 40.563412], + [75.355716, 40.537947], + [75.292274, 40.483802], + [75.268869, 40.483802], + [75.242383, 40.448743], + [75.206659, 40.447833], + [75.13521, 40.463315], + [75.102565, 40.44009], + [75.051442, 40.449654], + [75.021877, 40.466958], + [74.995392, 40.455119], + [74.963363, 40.464681], + [74.891914, 40.507467], + [74.844486, 40.521117], + [74.819233, 40.505647], + [74.814921, 40.461039], + [74.795211, 40.443278], + [74.908544, 40.338897], + [74.862965, 40.32658], + [74.824776, 40.344371], + [74.700357, 40.346195], + [74.697893, 40.310153], + [74.673255, 40.278656], + [74.618437, 40.27957], + [74.577169, 40.260391], + [74.534669, 40.207851], + [74.485394, 40.182251], + [74.433039, 40.13148], + [74.356662, 40.089371], + [74.316626, 40.106767], + [74.280902, 40.09807], + [74.26304, 40.125074], + [74.126301, 40.104479], + [74.113366, 40.086624], + [74.023439, 40.085251], + [74.008041, 40.050901], + [73.943367, 40.016076], + [73.980324, 40.004617], + [73.910722, 39.934443], + [73.907027, 39.873843], + [73.845433, 39.831115], + [73.841737, 39.756163], + [73.905795, 39.741899], + [73.924273, 39.722108], + [73.953838, 39.600018], + [73.916266, 39.586644], + [73.914418, 39.564041], + [73.883621, 39.540969], + [73.893476, 39.528046], + [73.868223, 39.482794], + [73.836194, 39.472169], + [73.745651, 39.462005], + [73.6471, 39.474479], + [73.61076, 39.465702], + [73.592898, 39.412087], + [73.502355, 39.383877], + [73.554094, 39.350102], + [73.554709, 39.295935], + [73.542391, 39.269531], + [73.564564, 39.266288], + [73.580579, 39.237555], + [73.623079, 39.235237], + [73.639709, 39.220402], + [73.657571, 39.166136], + [73.688368, 39.154999], + [73.719781, 39.108112], + [73.720397, 39.071881], + [73.743187, 39.029588], + [73.780143, 39.026798], + [73.820179, 39.041674], + [73.839889, 39.008199], + [73.846665, 38.962145], + [73.826339, 38.916993], + [73.767824, 38.941202], + [73.742571, 38.933754], + [73.70931, 38.893241], + [73.699455, 38.857832], + [73.729636, 38.837324], + [73.769056, 38.775765], + [73.757353, 38.719755], + [73.809092, 38.634256], + [73.799237, 38.610878], + [73.852208, 38.584217], + [73.89902, 38.579071], + [73.926121, 38.536016], + [74.011736, 38.52478], + [74.034526, 38.541634], + [74.090577, 38.542102], + [74.068403, 38.585621], + [74.088113, 38.610878], + [74.11275, 38.611345], + [74.147859, 38.676785], + [74.229779, 38.656224], + [74.353583, 38.655757], + [74.421952, 38.647812], + [74.455829, 38.632853], + [74.506336, 38.637528], + [74.546988, 38.607604], + [74.613509, 38.593105], + [74.639995, 38.599653], + [74.717603, 38.542102], + [74.78474, 38.538357], + [74.821697, 38.491062], + [74.862965, 38.484035], + [74.868508, 38.403883], + [74.834015, 38.361193], + [74.789668, 38.324581], + [74.806914, 38.285602], + [74.793363, 38.271039], + [74.816769, 38.215576], + [74.80445, 38.167128], + [74.821697, 38.10311], + [74.879595, 38.021122], + [74.92579, 38.01735], + [74.911008, 37.966884], + [74.919015, 37.908357], + [74.936877, 37.876241], + [74.917167, 37.845057], + [74.989848, 37.797783], + [75.006478, 37.770823], + [74.949196, 37.725395], + [74.923327, 37.717347], + [74.920863, 37.684675], + [74.891914, 37.668097], + [74.940573, 37.559061], + [75.000935, 37.53059], + [75.002167, 37.511604], + [75.035428, 37.500685], + [75.078543, 37.511129], + [75.090862, 37.486915], + [75.129666, 37.459367], + [75.153072, 37.414223], + [75.125971, 37.388075], + [75.140137, 37.355258], + [75.125971, 37.322427], + [75.078543, 37.318144], + [75.018181, 37.293867], + [74.927022, 37.277678], + [74.911008, 37.233378], + [74.816153, 37.216699], + [74.800139, 37.248147], + [74.753943, 37.281011], + [74.727458, 37.282916], + [74.665864, 37.23576], + [74.642458, 37.261485], + [74.598727, 37.258151], + [74.578401, 37.231472], + [74.54514, 37.2491], + [74.511263, 37.240048], + [74.477387, 37.19954], + [74.487858, 37.161871], + [74.465068, 37.147085], + [74.496481, 37.116072], + [74.498944, 37.072155], + [74.530357, 37.082182], + [74.56793, 37.032512], + [74.617205, 37.043499], + [74.632603, 37.066425], + [74.70898, 37.084569], + [74.739161, 37.028212], + [74.792747, 37.027257], + [74.806914, 37.054485], + [74.84695, 37.056873], + [74.84387, 37.0134], + [74.86974, 36.990458], + [74.893762, 36.939772], + [74.938725, 36.94312], + [74.927638, 36.978029], + [75.005862, 36.99476], + [75.032348, 37.016745], + [75.063145, 37.006231], + [75.172166, 37.013877], + [75.16847, 36.991892], + [75.244847, 36.963207], + [75.288579, 36.974682], + [75.345861, 36.960816], + [75.413614, 36.954599], + [75.396368, 36.904367], + [75.430245, 36.873255], + [75.434556, 36.83303], + [75.425933, 36.778883], + [75.458578, 36.720861], + [75.504773, 36.743404], + [75.536802, 36.729975], + [75.537418, 36.773131], + [75.588541, 36.762584], + [75.634121, 36.771693], + [75.724048, 36.750597], + [75.8072, 36.707908], + [75.871257, 36.666636], + [75.947018, 36.590752], + [75.924228, 36.566242], + [75.991981, 36.505654], + [76.035097, 36.409386], + [75.991365, 36.35205], + [75.998757, 36.312034], + [76.055423, 36.252695], + [76.060967, 36.225182], + [76.011691, 36.229044], + [76.016619, 36.165294], + [75.96796, 36.159013], + [75.936547, 36.13485], + [75.949482, 36.070056], + [75.982742, 36.031347], + [76.028322, 36.016827], + [76.044336, 36.026991], + [76.097307, 36.022635], + [76.117017, 35.975186], + [76.16506, 35.908807], + [76.146582, 35.839946], + [76.160133, 35.82442], + [76.221727, 35.823449], + [76.228502, 35.837035], + [76.298719, 35.841401], + [76.365857, 35.82442], + [76.369552, 35.86323], + [76.431762, 35.851589], + [76.471798, 35.886021], + [76.51553, 35.881173], + [76.55803, 35.923347], + [76.59745, 35.895718], + [76.579587, 35.866625], + [76.587595, 35.840431], + [76.566037, 35.819082], + [76.593754, 35.771996], + [76.69292, 35.747714], + [76.769297, 35.653917], + [76.848753, 35.668018], + [76.906651, 35.615005], + [76.967013, 35.591649], + [76.99781, 35.611113], + [77.072339, 35.591162], + [77.093281, 35.569746], + [77.195527, 35.519103], + [77.307628, 35.540533], + [77.331649, 35.530793], + [77.355055, 35.494257], + [77.396939, 35.467942], + [77.451758, 35.46063], + [77.518895, 35.482075], + [77.578025, 35.47574], + [77.590344, 35.460143], + [77.639619, 35.45478], + [77.657481, 35.477689], + [77.690742, 35.448443], + [77.735706, 35.461605], + [77.757879, 35.497181], + [77.797299, 35.491334], + [77.816394, 35.518616], + [77.85643, 35.487436], + [77.870596, 35.495232], + [77.914944, 35.465017], + [77.917408, 35.490847], + [77.951284, 35.478664], + [78.009799, 35.491821], + [78.029509, 35.469404], + [78.048603, 35.491334], + [78.140378, 35.494745], + [78.113892, 35.466967], + [78.107117, 35.437229], + [78.046755, 35.384063], + [78.013494, 35.366008], + [78.020885, 35.315237], + [78.01719, 35.228267], + [78.060306, 35.180344], + [78.062769, 35.114772], + [78.078784, 35.100084], + [78.124979, 35.108407], + [78.150849, 35.069721], + [78.123131, 35.036897], + [78.160704, 34.990823], + [78.201972, 34.974642], + [78.182262, 34.936874], + [78.206283, 34.891726], + [78.237696, 34.882398], + [78.230921, 34.776288], + [78.21429, 34.760556], + [78.213059, 34.717771], + [78.267261, 34.705472], + [78.265413, 34.651335], + [78.280812, 34.623269], + [78.346101, 34.60406], + [78.397224, 34.605538], + [78.427405, 34.594207], + [78.436029, 34.543942], + [78.492695, 34.578441], + [78.542586, 34.574499], + [78.559832, 34.55725], + [78.562912, 34.51288], + [78.58139, 34.505483], + [78.634977, 34.538026], + [78.708274, 34.522249], + [78.715049, 34.502031], + [78.758781, 34.481807], + [78.742766, 34.45467], + [78.809288, 34.432955], + [78.878273, 34.391481], + [78.899831, 34.354929], + [78.958961, 34.386049], + [78.973128, 34.362833], + [79.039649, 34.33467], + [79.048888, 34.348506], + [79.0107, 34.399877], + [79.039033, 34.421601], + [79.072294, 34.412714], + [79.161605, 34.441345], + [79.179467, 34.422588], + [79.241677, 34.415183], + [79.274322, 34.435916], + [79.326677, 34.44332], + [79.363017, 34.428018], + [79.435082, 34.447761], + [79.504683, 34.45467], + [79.545335, 34.476381], + [79.58106, 34.456151], + [79.675914, 34.451216], + [79.699936, 34.477861], + [79.735661, 34.471447], + [79.801566, 34.478847], + [79.861312, 34.528166], + [79.84345, 34.55725], + [79.88595, 34.642965], + [79.866856, 34.671517], + [79.906892, 34.683821], + [79.898268, 34.732035], + [79.947544, 34.821008], + [79.926602, 34.849499], + [79.961094, 34.862759], + [79.996819, 34.856375], + [80.003594, 34.895162], + [80.034391, 34.902033], + [80.041782, 34.943252], + [80.02392, 34.971209], + [80.04363, 35.022196], + [80.031311, 35.034447], + [80.078123, 35.076578], + [80.118159, 35.066293], + [80.23026, 35.147565], + [80.223484, 35.177409], + [80.257977, 35.203331], + [80.362687, 35.20871], + [80.267832, 35.295701], + [80.286926, 35.35283], + [80.321419, 35.38699], + [80.375006, 35.387966], + [80.432904, 35.449418], + [80.444607, 35.417235], + [80.514824, 35.391869], + [80.532686, 35.404553], + [80.56841, 35.391381], + [80.599823, 35.409431], + [80.65649, 35.393821], + [80.690982, 35.364544], + [80.689135, 35.339162], + [80.759968, 35.334768], + [80.844351, 35.345508], + [80.894242, 35.324027], + [80.924423, 35.330862], + [80.963844, 35.310842], + [81.026053, 35.31133], + [81.002648, 35.334768], + [81.030981, 35.337209], + [81.031597, 35.380648], + [81.054387, 35.402602], + [81.09935, 35.40748], + [81.103662, 35.386015], + [81.142466, 35.365032], + [81.191741, 35.36552], + [81.219458, 35.319144], + [81.26627, 35.322562], + [81.285364, 35.345508], + [81.314313, 35.337209], + [81.363588, 35.354783], + [81.385762, 35.335256], + [81.441196, 35.333303], + [81.447972, 35.318167], + [81.504638, 35.279092], + [81.513261, 35.23511], + [81.68634, 35.235599], + [81.736847, 35.26248], + [81.804601, 35.270786], + [81.853876, 35.25857], + [81.927789, 35.271275], + [81.955506, 35.307423], + [81.99123, 35.30547], + [82.030034, 35.321585], + [82.05344, 35.35039], + [82.029419, 35.426013], + [82.034346, 35.451855], + [82.071302, 35.450393], + [82.086701, 35.467454], + [82.164925, 35.495719], + [82.189563, 35.513258], + [82.234526, 35.520565], + [82.263475, 35.547837], + [82.2992, 35.544916], + [82.328149, 35.559523], + [82.350323, 35.611113], + [82.336156, 35.651486], + [82.392823, 35.656349], + [82.424852, 35.712736], + [82.468583, 35.717595], + [82.501844, 35.701073], + [82.546192, 35.708362], + [82.628727, 35.692324], + [82.652133, 35.67288], + [82.731589, 35.637868], + [82.780249, 35.666073], + [82.795031, 35.688436], + [82.873871, 35.688922], + [82.894813, 35.673852], + [82.967494, 35.667532], + [82.956407, 35.636409], + [82.981661, 35.599922], + [82.971806, 35.548324], + [82.998907, 35.484512], + [83.067892, 35.46258], + [83.088834, 35.425526], + [83.127022, 35.398699], + [83.178145, 35.38943], + [83.251442, 35.417722], + [83.280391, 35.401138], + [83.333978, 35.397236], + [83.405427, 35.380648], + [83.449159, 35.382111], + [83.502745, 35.360639], + [83.540318, 35.364056], + [83.54155, 35.341603], + [83.599448, 35.351366], + [83.622238, 35.335256], + [83.677672, 35.361128], + [83.785462, 35.36308], + [83.79778, 35.354783], + [83.885244, 35.367472], + [83.906186, 35.40309], + [84.005968, 35.422599], + [84.077417, 35.400163], + [84.095895, 35.362592], + [84.140859, 35.379184], + [84.160569, 35.359663], + [84.200605, 35.381135], + [84.274517, 35.404065], + [84.333032, 35.413821], + [84.424191, 35.466479], + [84.45314, 35.473303], + [84.475929, 35.516181], + [84.448828, 35.550272], + [84.513502, 35.564391], + [84.570168, 35.588242], + [84.628067, 35.595055], + [84.704443, 35.616951], + [84.729081, 35.613546], + [84.798066, 35.647595], + [84.920022, 35.696213], + [84.973608, 35.709334], + [84.99455, 35.737028], + [85.053065, 35.752086], + [85.146071, 35.742371], + [85.271107, 35.788989], + [85.341324, 35.753543], + [85.373969, 35.700101], + [85.518715, 35.680658], + [85.566142, 35.6403], + [85.612953, 35.651486], + [85.65299, 35.731199], + [85.691178, 35.751114], + [85.811286, 35.778794], + [85.835308, 35.771996], + [85.903677, 35.78462], + [85.949256, 35.778794], + [86.035488, 35.846738], + [86.05335, 35.842857], + [86.090306, 35.876809], + [86.093386, 35.906868], + [86.129111, 35.941761], + [86.150668, 36.00424], + [86.173458, 36.008113], + [86.199944, 36.047801], + [86.182081, 36.064734], + [86.187625, 36.130983], + [86.248603, 36.141616], + [86.2794, 36.170608], + [86.35824, 36.168676], + [86.392733, 36.206834], + [86.454943, 36.221319], + [86.515305, 36.205385], + [86.531935, 36.227113], + [86.599072, 36.222285], + [86.69947, 36.24449], + [86.746282, 36.291777], + [86.836209, 36.291294], + [86.86331, 36.299977], + [86.887332, 36.262829], + [86.931064, 36.265242], + [86.943998, 36.284058], + [86.996353, 36.308658], + [87.051788, 36.2966], + [87.08628, 36.310587], + [87.149106, 36.297565], + [87.161425, 36.325535], + [87.193454, 36.349158], + [87.292004, 36.358797], + [87.348055, 36.393008], + [87.363453, 36.420463], + [87.386859, 36.412757], + [87.426895, 36.42576], + [87.460155, 36.409868], + [87.470626, 36.354459], + [87.570409, 36.342409], + [87.6203, 36.360243], + [87.731785, 36.384818], + [87.767509, 36.3747], + [87.826023, 36.391563], + [87.838342, 36.383855], + [87.919646, 36.39349], + [87.95845, 36.408423], + [87.983088, 36.437797], + [88.006494, 36.430575], + [88.092109, 36.43539], + [88.134609, 36.427205], + [88.182652, 36.452721], + [88.222688, 36.447426], + [88.241782, 36.468605], + [88.282434, 36.470049], + [88.366202, 36.458016], + [88.356963, 36.477268], + [88.41055, 36.473418], + [88.470912, 36.48208], + [88.498629, 36.446463], + [88.573158, 36.461386], + [88.618121, 36.428168], + [88.623665, 36.389636], + [88.690186, 36.367954], + [88.766563, 36.292259], + [88.783809, 36.291777], + [88.802903, 36.33807], + [88.838628, 36.353496], + [88.870657, 36.348193], + [88.926091, 36.36458], + [88.964279, 36.318785], + [89.013554, 36.315409], + [89.054822, 36.291777], + [89.10225, 36.281164], + [89.126887, 36.254626], + [89.198952, 36.260417], + [89.232213, 36.295636], + [89.292575, 36.231457], + [89.335075, 36.23725], + [89.375727, 36.228078], + [89.490291, 36.151281], + [89.594385, 36.126632], + [89.614711, 36.109712], + [89.711414, 36.093272], + [89.766848, 36.073925], + [89.819819, 36.080697], + [89.914058, 36.079246], + [89.941159, 36.067637], + [89.944855, 36.140649], + [89.997825, 36.168193], + [90.019999, 36.213594], + [90.028006, 36.258486], + [90.003369, 36.278752], + [90.043405, 36.276822], + [90.058188, 36.255591], + [90.145651, 36.239181], + [90.130252, 36.2078], + [90.198006, 36.187516], + [90.23681, 36.160462], + [90.325505, 36.159496], + [90.424055, 36.133883], + [90.478258, 36.13195], + [90.534925, 36.147899], + [90.613149, 36.126632], + [90.659344, 36.13485], + [90.776373, 36.086501], + [90.815793, 36.035703], + [90.850285, 36.016827], + [90.922966, 36.028927], + [90.979017, 36.106811], + [91.081263, 36.088436], + [91.124994, 36.115514], + [91.09235, 36.163844], + [91.096045, 36.219871], + [91.051698, 36.238215], + [91.07264, 36.299012], + [91.026444, 36.323607], + [91.051698, 36.433946], + [91.028292, 36.443093], + [91.039995, 36.474861], + [91.035683, 36.529703], + [91.011662, 36.539801], + [90.905104, 36.560474], + [90.831191, 36.55807], + [90.810865, 36.585466], + [90.741264, 36.585947], + [90.72217, 36.620058], + [90.730793, 36.655594], + [90.706156, 36.658955], + [90.720938, 36.708868], + [90.754815, 36.721341], + [90.727098, 36.755872], + [90.732025, 36.825844], + [90.758511, 36.825844], + [90.853981, 36.915373], + [90.924198, 36.921115], + [90.983944, 36.913459], + [91.036915, 36.929727], + [91.051698, 36.96751], + [91.126842, 36.978507], + [91.133618, 37.007665], + [91.181045, 37.025345], + [91.216153, 37.010054], + [91.303617, 37.012444], + [91.291298, 37.042544], + [91.303617, 37.083136], + [91.286371, 37.105095], + [91.280211, 37.163779], + [91.1909, 37.205737], + [91.194596, 37.273868], + [91.134849, 37.324331], + [91.136081, 37.355734], + [91.113292, 37.387124], + [91.099741, 37.447965], + [91.073256, 37.475992], + [91.019669, 37.493088], + [90.958075, 37.477891], + [90.911879, 37.519674], + [90.865684, 37.53059], + [90.882314, 37.575664], + [90.854597, 37.604117], + [90.820104, 37.613599], + [90.777605, 37.648672], + [90.643946, 37.696988], + [90.586663, 37.703144], + [90.579272, 37.720661], + [90.519526, 37.730601], + [90.516446, 38.207111], + [90.531229, 38.319886], + [90.401882, 38.311434], + [90.361846, 38.300163], + [90.352607, 38.233441], + [90.280542, 38.238142], + [90.137644, 38.340543], + [90.179528, 38.396848], + [90.129636, 38.400131], + [90.111774, 38.418889], + [90.111774, 38.477945], + [90.130868, 38.494341], + [90.248513, 38.491531], + [90.315034, 38.501835], + [90.353222, 38.482162], + [90.427135, 38.493873], + [90.465323, 38.521971], + [90.463476, 38.556611], + [90.525685, 38.561291], + [90.560794, 38.593573], + [90.608837, 38.594508], + [90.606374, 38.610878], + [90.645794, 38.635191], + [90.619308, 38.664636], + [90.65996, 38.674449], + [90.724634, 38.658094], + [90.899561, 38.679588], + [90.970394, 38.697806], + [90.992567, 38.695003], + [91.188436, 38.73096], + [91.242639, 38.752433], + [91.298689, 38.746365], + [91.446515, 38.813546], + [91.501333, 38.815411], + [91.681188, 38.852706], + [91.694738, 38.86622], + [91.806223, 38.872744], + [91.87952, 38.884391], + [91.880752, 38.899297], + [91.966368, 38.930961], + [92.10865, 38.963541], + [92.173323, 38.960749], + [92.197961, 38.983548], + [92.263866, 39.002153], + [92.380279, 38.999828], + [92.416003, 39.010524], + [92.41046, 39.03842], + [92.366728, 39.059335], + [92.366112, 39.096037], + [92.343938, 39.146181], + [92.339011, 39.236628], + [92.378431, 39.258411], + [92.52564, 39.368611], + [92.639589, 39.514196], + [92.687632, 39.657174], + [92.745531, 39.868331], + [92.796654, 40.153897], + [92.906907, 40.310609], + [92.920458, 40.391792], + [92.928465, 40.572504], + [93.506216, 40.648376], + [93.760599, 40.664721], + [93.820961, 40.793519], + [93.809874, 40.879548], + [93.908424, 40.983539], + [94.01067, 41.114875], + [94.184365, 41.268444], + [94.534219, 41.505966], + [94.750413, 41.538227], + [94.809543, 41.619256], + [94.861898, 41.668451], + [94.969072, 41.718948], + [95.011572, 41.726541], + [95.110738, 41.768513], + [95.135991, 41.772976], + [95.16494, 41.735474], + [95.199433, 41.719395], + [95.194505, 41.694821], + [95.247476, 41.61344], + [95.299831, 41.565994], + [95.335556, 41.644305], + [95.39407, 41.693481], + [95.445193, 41.719841], + [95.57146, 41.796181], + [95.65646, 41.826067], + [95.759322, 41.835878], + [95.801206, 41.848361], + [95.855408, 41.849699], + [95.998306, 41.906289], + [96.054973, 41.936124], + [96.117183, 41.985966], + [96.137509, 42.019765], + [96.13874, 42.05399], + [96.077147, 42.149457], + [96.178161, 42.21775], + [96.040806, 42.326688], + [96.042038, 42.352787], + [96.06606, 42.414674], + [95.978596, 42.436762], + [96.0174, 42.482239], + [96.02356, 42.542675], + [96.072219, 42.569566], + [96.103632, 42.604375], + [96.166458, 42.623314], + [96.386348, 42.727592] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 710000, + "name": "台湾省", + "center": [121.509062, 25.044332], + "centroid": [120.971485, 23.749452], + "childrenNum": 0, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 31, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [120.443706, 22.441432], + [120.517619, 22.408793], + [120.569973, 22.361757], + [120.640806, 22.241605], + [120.659285, 22.154056], + [120.661748, 22.067007], + [120.651277, 22.033171], + [120.667908, 21.983235], + [120.701784, 21.927174], + [120.743052, 21.915515], + [120.781857, 21.923843], + [120.854537, 21.883309], + [120.873016, 21.897191], + [120.86624, 21.984345], + [120.907508, 22.033171], + [120.912436, 22.086418], + [120.903197, 22.12634], + [120.914899, 22.302525], + [120.981421, 22.528248], + [121.014682, 22.584069], + [121.03316, 22.650914], + [121.078739, 22.669691], + [121.170514, 22.723247], + [121.21055, 22.770711], + [121.237652, 22.836362], + [121.276456, 22.877171], + [121.324499, 22.945526], + [121.35468, 23.00999], + [121.370695, 23.084334], + [121.409499, 23.1025], + [121.430441, 23.137175], + [121.415042, 23.196047], + [121.440296, 23.271937], + [121.479716, 23.322507], + [121.497578, 23.419744], + [121.5216, 23.483431], + [121.522832, 23.538858], + [121.587505, 23.760878], + [121.621382, 23.920718], + [121.65957, 24.007125], + [121.63986, 24.064514], + [121.643556, 24.097843], + [121.678048, 24.133895], + [121.689135, 24.174303], + [121.809243, 24.339083], + [121.82649, 24.423572], + [121.867758, 24.47914], + [121.88562, 24.529784], + [121.892395, 24.617953], + [121.86283, 24.671261], + [121.841272, 24.734329], + [121.844968, 24.836476], + [121.933047, 24.938539], + [122.012503, 25.001471], + [121.98109, 25.030757], + [121.947214, 25.031841], + [121.917033, 25.138076], + [121.841888, 25.135367], + [121.782142, 25.160287], + [121.745186, 25.161912], + [121.707613, 25.191701], + [121.700222, 25.226896], + [121.655259, 25.242054], + [121.62323, 25.29455], + [121.585041, 25.309159], + [121.53515, 25.307535], + [121.444607, 25.27074], + [121.413194, 25.238806], + [121.371926, 25.159746], + [121.319572, 25.140785], + [121.209318, 25.12724], + [121.132942, 25.078466], + [121.102145, 25.075214], + [121.024537, 25.040517], + [121.009754, 24.993878], + [120.961095, 24.940167], + [120.914899, 24.864715], + [120.89211, 24.767482], + [120.82374, 24.688118], + [120.762147, 24.658208], + [120.68885, 24.600542], + [120.642654, 24.490033], + [120.589068, 24.43229], + [120.546568, 24.370159], + [120.520698, 24.311816], + [120.470807, 24.242533], + [120.451713, 24.182493], + [120.391967, 24.118055], + [120.316206, 23.984708], + [120.278018, 23.92783], + [120.245989, 23.840276], + [120.175156, 23.807427], + [120.102476, 23.701162], + [120.095084, 23.58768], + [120.12157, 23.504836], + [120.108019, 23.341191], + [120.081534, 23.291728], + [120.018708, 23.073322], + [120.029795, 23.048544], + [120.133272, 23.000625], + [120.149287, 22.896468], + [120.20041, 22.721039], + [120.274323, 22.560307], + [120.297112, 22.531565], + [120.443706, 22.441432] + ] + ], + [ + [ + [124.542782, 25.903886], + [124.584666, 25.908731], + [124.566804, 25.941563], + [124.542782, 25.903886] + ] + ], + [ + [ + [123.445178, 25.726102], + [123.469816, 25.712623], + [123.50862, 25.722867], + [123.512316, 25.755212], + [123.479055, 25.768687], + [123.445794, 25.749822], + [123.445178, 25.726102] + ] + ], + [ + [ + [119.646064, 23.550928], + [119.691028, 23.547087], + [119.678093, 23.600294], + [119.61034, 23.604132], + [119.601717, 23.575613], + [119.566608, 23.584937], + [119.562297, 23.530627], + [119.578927, 23.502641], + [119.609108, 23.503738], + [119.646064, 23.550928] + ] + ], + [ + [ + [123.666916, 25.914114], + [123.706952, 25.91519], + [123.689706, 25.939949], + [123.666916, 25.914114] + ] + ], + [ + [ + [119.506246, 23.625518], + [119.506246, 23.577259], + [119.47237, 23.556962], + [119.519181, 23.559705], + [119.52534, 23.62497], + [119.506246, 23.625518] + ] + ], + [ + [ + [119.497623, 23.38679], + [119.495159, 23.349982], + [119.516717, 23.349982], + [119.497623, 23.38679] + ] + ], + [ + [ + [119.557369, 23.666634], + [119.608492, 23.620035], + [119.615268, 23.661153], + [119.586318, 23.675952], + [119.557369, 23.666634] + ] + ], + [ + [ + [122.066706, 25.6247], + [122.087032, 25.61067], + [122.092575, 25.639268], + [122.066706, 25.6247] + ] + ], + [ + [ + [121.468013, 22.67687], + [121.474788, 22.643734], + [121.513592, 22.631582], + [121.514824, 22.676318], + [121.468013, 22.67687] + ] + ], + [ + [ + [121.510513, 22.086972], + [121.507433, 22.048704], + [121.533918, 22.022076], + [121.594281, 21.995443], + [121.604752, 22.022631], + [121.575186, 22.037055], + [121.575802, 22.0842], + [121.510513, 22.086972] + ] + ], + [ + [ + [122.097503, 25.499987], + [122.110438, 25.465952], + [122.122141, 25.495666], + [122.097503, 25.499987] + ] + ], + [ + [ + [119.421247, 23.216949], + [119.436029, 23.186146], + [119.453275, 23.216399], + [119.421247, 23.216949] + ] + ], + [ + [ + [120.355011, 22.327439], + [120.395663, 22.342385], + [120.383344, 22.355669], + [120.355011, 22.327439] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 810000, + "name": "香港特别行政区", + "center": [114.173355, 22.320048], + "centroid": [114.134357, 22.377366], + "childrenNum": 18, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 32, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [114.031778, 22.503923], + [114.000981, 22.491206], + [113.977575, 22.45692], + [113.918445, 22.418199], + [113.920293, 22.367845], + [113.951706, 22.355116], + [113.956633, 22.359543], + [113.980039, 22.366185], + [114.026234, 22.34792], + [113.955401, 22.298649], + [113.969568, 22.321349], + [113.898119, 22.308615], + [113.889496, 22.271514], + [113.8433, 22.229418], + [113.84946, 22.191188], + [113.899351, 22.215568], + [113.935691, 22.205041], + [113.981271, 22.229972], + [113.996669, 22.206149], + [114.026234, 22.229418], + [114.004676, 22.239389], + [114.02993, 22.263207], + [114.034857, 22.300864], + [114.069966, 22.326885], + [114.121089, 22.320795], + [114.145726, 22.300864], + [114.120473, 22.272068], + [114.164821, 22.226648], + [114.200545, 22.232188], + [114.203009, 22.206703], + [114.265835, 22.200608], + [114.248588, 22.274837], + [114.262139, 22.294773], + [114.284929, 22.263761], + [114.313262, 22.264315], + [114.315726, 22.299203], + [114.315726, 22.299756], + [114.278153, 22.328546], + [114.283081, 22.386661], + [114.322501, 22.385554], + [114.323117, 22.385554], + [114.323733, 22.385001], + [114.323733, 22.384447], + [114.356994, 22.340171], + [114.394566, 22.361757], + [114.385327, 22.41156], + [114.406269, 22.432582], + [114.406269, 22.433688], + [114.376088, 22.436454], + [114.325581, 22.479041], + [114.278769, 22.435901], + [114.220255, 22.427603], + [114.205473, 22.449729], + [114.23319, 22.466875], + [114.2529, 22.445304], + [114.340979, 22.50337], + [114.309566, 22.497288], + [114.28924, 22.52272], + [114.263987, 22.541515], + [114.263371, 22.541515], + [114.260291, 22.547595], + [114.232574, 22.528801], + [114.232574, 22.539857], + [114.222719, 22.553122], + [114.166052, 22.559201], + [114.156813, 22.543726], + [114.095219, 22.534329], + [114.082285, 22.512216], + [114.031778, 22.503923] + ] + ], + [ + [ + [114.142647, 22.213906], + [114.123553, 22.238836], + [114.120473, 22.177888], + [114.154965, 22.177888], + [114.166668, 22.205041], + [114.142647, 22.213906] + ] + ], + [ + [ + [114.305871, 22.372273], + [114.313878, 22.340724], + [114.332972, 22.353455], + [114.305255, 22.372826], + [114.305871, 22.372273] + ] + ], + [ + [ + [114.320037, 22.381127], + [114.323733, 22.384447], + [114.323733, 22.385001], + [114.323117, 22.385554], + [114.322501, 22.385554], + [114.319421, 22.382234], + [114.320037, 22.38168], + [114.320037, 22.381127] + ] + ], + [ + [ + [114.305871, 22.369506], + [114.305871, 22.372273], + [114.305255, 22.372826], + [114.305871, 22.369506] + ] + ], + [ + [ + [114.315726, 22.299203], + [114.316958, 22.298649], + [114.316342, 22.30031], + [114.315726, 22.299756], + [114.315726, 22.299203] + ] + ], + [ + [ + [114.319421, 22.382234], + [114.320037, 22.381127], + [114.320037, 22.38168], + [114.319421, 22.382234] + ] + ], + [ + [ + [114.372392, 22.32301], + [114.373008, 22.323564], + [114.372392, 22.323564], + [114.372392, 22.32301] + ] + ], + [ + [ + [114.323733, 22.297541], + [114.324349, 22.297541], + [114.323733, 22.298095], + [114.323733, 22.297541] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "adcode": 820000, + "name": "澳门特别行政区", + "center": [113.54909, 22.198951], + "centroid": [113.566988, 22.159307], + "childrenNum": 8, + "level": "province", + "parent": { "adcode": 100000 }, + "subFeatureIndex": 33, + "acroutes": [100000] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [113.554425, 22.107489], + [113.6037, 22.132438], + [113.575983, 22.194513], + [113.558736, 22.212244], + [113.53841, 22.209473], + [113.534715, 22.174009], + [113.554425, 22.142416], + [113.554425, 22.107489] + ] + ], + [ + [ + [113.586453, 22.201162], + [113.575983, 22.201162], + [113.575983, 22.194513], + [113.586453, 22.201162] + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "name": "", "adchar": "JD", "adcode": "100000_JD" }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [122.51865306, 23.46078502], + [122.79861399, 24.57367379], + [122.79889322, 24.57678999], + [122.79819583, 24.57983997], + [122.79659008, 24.58252516], + [122.79423315, 24.58458272], + [122.79135575, 24.58581125], + [122.78823955, 24.58609049], + [122.78518957, 24.5853931], + [122.78250438, 24.58378734], + [122.78044682, 24.58143041], + [122.77921829, 24.57855302], + [122.49925737, 23.46566424], + [122.49897813, 23.46254804], + [122.49967552, 23.45949807], + [122.50128127, 23.45681287], + [122.5036382, 23.45475531], + [122.5065156, 23.45352678], + [122.50963181, 23.45324755], + [122.51268178, 23.45394494], + [122.51536697, 23.45555069], + [122.51742454, 23.45790762], + [122.51865306, 23.46078502] + ] + ], + [ + [ + [121.17202617, 20.8054593], + [121.90938804, 21.68743347], + [121.9109946, 21.69011818], + [121.91169291, 21.69316794], + [121.91141462, 21.69628423], + [121.91018696, 21.699162], + [121.9081301, 21.70151955], + [121.9054454, 21.70312611], + [121.90239563, 21.70382443], + [121.89927934, 21.70354613], + [121.89640158, 21.70231847], + [121.89404403, 21.70026162], + [121.15668216, 20.81828744], + [121.1550756, 20.81560273], + [121.15437729, 20.81255297], + [121.15465558, 20.80943668], + [121.15588324, 20.80655891], + [121.1579401, 20.80420136], + [121.1606248, 20.8025948], + [121.16367457, 20.80189649], + [121.16679085, 20.80217478], + [121.16966862, 20.80340244], + [121.17202617, 20.8054593] + ] + ], + [ + [ + [119.47366172, 18.00707291], + [120.02569734, 19.02403788], + [120.02674143, 19.02698721], + [120.02682302, 19.03011484], + [120.02593412, 19.0331146], + [120.02416175, 19.03569286], + [120.02167941, 19.03759723], + [120.01873007, 19.03864132], + [120.01560245, 19.03872291], + [120.01260269, 19.03783401], + [120.01002443, 19.03606165], + [120.00812005, 19.0335793], + [119.45608443, 18.01661433], + [119.45504035, 18.01366499], + [119.45495876, 18.01053737], + [119.45584765, 18.00753761], + [119.45762002, 18.00495935], + [119.46010237, 18.00305497], + [119.4630517, 18.00201089], + [119.46617933, 18.0019293], + [119.46917909, 18.0028182], + [119.47175735, 18.00459056], + [119.47366172, 18.00707291] + ] + ], + [ + [ + [119.0726757, 15.04098494], + [119.0726757, 16.04388528], + [119.07218626, 16.04697545], + [119.07076587, 16.04976313], + [119.06855355, 16.05197545], + [119.06576587, 16.05339584], + [119.0626757, 16.05388528], + [119.05958553, 16.05339584], + [119.05679784, 16.05197545], + [119.05458553, 16.04976313], + [119.05316513, 16.04697545], + [119.0526757, 16.04388528], + [119.0526757, 15.04105889], + [119.0521839, 15.00781004], + [119.05262758, 15.00471297], + [119.05400659, 15.00190458], + [119.05618595, 14.99965979], + [119.05895232, 14.99819832], + [119.06203491, 14.99766324], + [119.06513198, 14.99810691], + [119.06794036, 14.99948592], + [119.07018516, 15.00166528], + [119.07164663, 15.00443165], + [119.07218171, 15.00751424], + [119.0726746, 15.04083704], + [119.0726757, 15.04098494] + ] + ], + [ + [ + [118.68646749, 11.18959191], + [118.52518702, 10.91547751], + [118.52404181, 10.91256595], + [118.52385237, 10.909443], + [118.52463726, 10.90641436], + [118.52631962, 10.9037765], + [118.5287348, 10.90178762], + [118.53164636, 10.90064241], + [118.53476931, 10.90045298], + [118.53779795, 10.90123786], + [118.54043581, 10.90292022], + [118.54242469, 10.9053354], + [118.70409227, 11.18010771], + [118.70476212, 11.18147468], + [118.87431591, 11.606662], + [118.87459939, 11.60747236], + [118.98894963, 11.98573108], + [118.98937534, 11.98883067], + [118.9888224, 11.99191011], + [118.98734492, 11.99466796], + [118.98508753, 11.99683427], + [118.98227119, 11.99819697], + [118.9791716, 11.99862269], + [118.97609216, 11.99806975], + [118.97333431, 11.99659227], + [118.97116801, 11.99433487], + [118.9698053, 11.99151854], + [118.85557939, 11.6136711], + [118.68646749, 11.18959191] + ] + ], + [ + [ + [115.54466883, 7.14672265], + [116.2504858, 7.979279], + [116.25211077, 7.98195261], + [116.25283001, 7.9849975], + [116.25257312, 7.98811563], + [116.25136525, 7.99100176], + [116.24932463, 7.99337338], + [116.24665102, 7.99499834], + [116.24360613, 7.99571758], + [116.240488, 7.99546069], + [116.23760187, 7.99425282], + [116.23523025, 7.99221221], + [115.52941328, 7.15965587], + [115.52778832, 7.15698226], + [115.52706908, 7.15393736], + [115.52732596, 7.15081924], + [115.52853383, 7.1479331], + [115.53057445, 7.14556148], + [115.53324806, 7.14393652], + [115.53629295, 7.14321728], + [115.53941108, 7.14347417], + [115.54229721, 7.14468204], + [115.54466883, 7.14672265] + ] + ], + [ + [ + [112.30705249, 3.53487257], + [111.78690114, 3.41687263], + [111.78399583, 3.41571167], + [111.78159146, 3.41370973], + [111.77992341, 3.41106279], + [111.77915495, 3.40802995], + [111.77936129, 3.40490807], + [111.78052226, 3.40200275], + [111.78252419, 3.39959839], + [111.78517113, 3.39793033], + [111.78820398, 3.39716187], + [111.79132585, 3.39736822], + [112.31181658, 3.51544515], + [112.31248917, 3.51562254], + [112.52147408, 3.5785908], + [112.52281386, 3.57910186], + [112.85206367, 3.73256867], + [112.85465776, 3.7343178], + [112.85658437, 3.73678292], + [112.85765492, 3.73972276], + [112.85776462, 3.74284952], + [112.85690272, 3.74585715], + [112.8551536, 3.74845124], + [112.85268847, 3.75037785], + [112.84974864, 3.7514484], + [112.84662187, 3.75155809], + [112.84361424, 3.7506962], + [112.51501594, 3.59753306], + [112.30705249, 3.53487257] + ] + ], + [ + [ + [108.26055972, 6.08912451], + [108.29013305, 6.01266273], + [108.29170425, 6.00995718], + [108.29403462, 6.00786957], + [108.29689603, 6.00660426], + [108.3000084, 6.00628511], + [108.30306706, 6.00694335], + [108.30577262, 6.00851455], + [108.30786022, 6.01084492], + [108.30912553, 6.01370633], + [108.30944469, 6.0168187], + [108.30878645, 6.01987736], + [108.279563, 6.09543449], + [108.25611734, 6.22752625], + [108.21679964, 6.53816468], + [108.21876335, 6.94964057], + [108.24419535, 7.07390742], + [108.24433543, 7.07703297], + [108.24350281, 7.08004883], + [108.24177899, 7.0826598], + [108.2393327, 7.08461028], + [108.23640341, 7.08570936], + [108.23327786, 7.08584944], + [108.230262, 7.08501682], + [108.22765103, 7.083293], + [108.22570055, 7.08084671], + [108.22460147, 7.07791743], + [108.19897125, 6.95268198], + [108.1987683, 6.95072469], + [108.19679674, 6.53760583], + [108.19687578, 6.53630242], + [108.23630689, 6.22476797], + [108.23638164, 6.22427602], + [108.26004031, 6.09098419], + [108.26055972, 6.08912451] + ] + ], + [ + [ + [110.12822847, 11.36894451], + [110.05553696, 11.25335394], + [110.05430621, 11.25047749], + [110.05402458, 11.2473615], + [110.05471962, 11.24431099], + [110.05632331, 11.24162456], + [110.05867865, 11.23956519], + [110.0615551, 11.23833444], + [110.06467109, 11.23805281], + [110.0677216, 11.23874785], + [110.07040803, 11.24035153], + [110.07246741, 11.24270688], + [110.14541497, 11.35870461], + [110.14588682, 11.35954163], + [110.20700505, 11.48128846], + [110.20728377, 11.48189306], + [110.25854422, 11.60358735], + [110.25901765, 11.60499559], + [110.30436343, 11.7826124], + [110.30456934, 11.78364161], + [110.32822801, 11.94571326], + [110.32832827, 11.94685414], + [110.33424294, 12.14159753], + [110.33424553, 12.14210167], + [110.33227398, 12.24038351], + [110.33172267, 12.24346324], + [110.33024665, 12.24622187], + [110.3279904, 12.24838938], + [110.32517479, 12.24975358], + [110.32207543, 12.25018094], + [110.3189957, 12.24962962], + [110.31623706, 12.2481536], + [110.31406956, 12.24589736], + [110.31270536, 12.24308175], + [110.312278, 12.23998238], + [110.3142445, 12.14195265], + [110.3083549, 11.94803461], + [110.28485499, 11.78705054], + [110.23982347, 11.61066468], + [110.18898148, 11.48996382], + [110.12822847, 11.36894451] + ] + ], + [ + [ + [109.82951587, 15.22896754], + [109.84522534, 15.15316562], + [109.84633168, 15.15023907], + [109.84828823, 15.14779763], + [109.85090347, 15.14608029], + [109.85392139, 15.14525516], + [109.85704658, 15.145403], + [109.85997314, 15.14650935], + [109.86241457, 15.1484659], + [109.86413191, 15.15108113], + [109.86495704, 15.15409906], + [109.8648092, 15.15722425], + [109.84903675, 15.23333003], + [109.84889209, 15.23393326], + [109.78974541, 15.45068337], + [109.7892391, 15.45210582], + [109.69066131, 15.67432448], + [109.6900529, 15.67548445], + [109.59147511, 15.83677407], + [109.59116145, 15.8372556], + [109.53201478, 15.92259221], + [109.53166592, 15.92306523], + [109.30888011, 16.20725797], + [109.30658844, 16.20938798], + [109.30375073, 16.21070558], + [109.30064474, 16.21108179], + [109.29757451, 16.21047978], + [109.29484059, 16.20895848], + [109.29271057, 16.20666681], + [109.29139298, 16.2038291], + [109.29101677, 16.20072311], + [109.29161878, 16.19765288], + [109.29314007, 16.19491896], + [109.51574449, 15.91095759], + [109.57455994, 15.82609887], + [109.67264555, 15.66561455], + [109.77065019, 15.44468789], + [109.82951587, 15.22896754] + ] + ] + ] + } + } + ] +} diff --git a/packages/effects/plugins/src/echarts/use-echarts.ts b/packages/effects/plugins/src/echarts/use-echarts.ts new file mode 100644 index 0000000..dd87b5b --- /dev/null +++ b/packages/effects/plugins/src/echarts/use-echarts.ts @@ -0,0 +1,194 @@ +import type { EChartsOption } from 'echarts'; + +import type { Ref } from 'vue'; + +import type { Nullable } from '@vben/types'; + +import type EchartsUI from './echarts-ui.vue'; + +import { computed, nextTick, watch } from 'vue'; + +import { usePreferences } from '@vben/preferences'; + +import { + tryOnUnmounted, + useDebounceFn, + useResizeObserver, + useTimeoutFn, + useWindowSize, +} from '@vueuse/core'; + +import echarts from './echarts'; +// TODO @xingyu:有 500kb,china.json 会影响打包么? +import chinaMap from './map/china.json'; + +type EchartsUIType = typeof EchartsUI | undefined; + +type EchartsThemeType = 'dark' | 'light' | null; + +function useEcharts(chartRef: Ref) { + let chartInstance: echarts.ECharts | null = null; + let cacheOptions: EChartsOption = {}; + + const { isDark } = usePreferences(); + const { height, width } = useWindowSize(); + const resizeHandler: () => void = useDebounceFn(resize, 200); + + echarts.registerMap('china', { + geoJSON: chinaMap as any, + specialAreas: { + china: { + left: 500, + top: 500, + width: 1000, + height: 1000, + }, + }, + }); + + const getChartEl = (): HTMLElement | null => { + const refValue = chartRef?.value as unknown; + if (!refValue) return null; + if (refValue instanceof HTMLElement) { + return refValue; + } + const maybeComponent = refValue as { $el?: HTMLElement }; + return maybeComponent.$el ?? null; + }; + + const isElHidden = (el: HTMLElement | null): boolean => { + if (!el) return true; + return el.offsetHeight === 0 || el.offsetWidth === 0; + }; + + const getOptions = computed((): EChartsOption => { + if (!isDark.value) { + return {}; + } + + return { + backgroundColor: 'transparent', + }; + }); + + const initCharts = (t?: EchartsThemeType) => { + const el = chartRef?.value?.$el; + if (!el) { + return; + } + chartInstance = echarts.init(el, t || isDark.value ? 'dark' : null); + + return chartInstance; + }; + + const renderEcharts = ( + options: EChartsOption, + clear = true, + ): Promise> => { + cacheOptions = options; + const currentOptions = { + ...options, + ...getOptions.value, + }; + return new Promise((resolve) => { + if (chartRef.value?.offsetHeight === 0) { + useTimeoutFn(async () => { + resolve(await renderEcharts(currentOptions)); + }, 30); + return; + } + nextTick(() => { + const el = getChartEl(); + if (isElHidden(el)) { + useTimeoutFn(async () => { + resolve(await renderEcharts(currentOptions)); + }, 30); + return; + } + useTimeoutFn(() => { + if (!chartInstance || chartInstance?.getDom() !== el) { + chartInstance?.dispose(); + const instance = initCharts(); + if (!instance) return; + } + clear && chartInstance?.clear(); + chartInstance?.setOption(currentOptions); + resolve(chartInstance); + }, 30); + }); + }); + }; + + const updateData = ( + option: EChartsOption, + notMerge = false, // false = 合并(保留动画),true = 完全替换 + lazyUpdate = false, // true 时不立即重绘,适合短时间内多次调用 + ): Promise => { + return new Promise((resolve) => { + nextTick(() => { + if (!chartInstance) { + // 还没初始化 → 当作首次渲染 + renderEcharts(option).then(resolve); + return; + } + + // 合并你原有的全局配置(比如 backgroundColor) + const finalOption = { + ...option, + ...getOptions.value, + }; + + chartInstance.setOption(finalOption, { + notMerge, + lazyUpdate, + // silent: true, // 如果追求极致性能可开启(关闭所有事件) + }); + + resolve(chartInstance); + }); + }); + }; + + function resize() { + const el = getChartEl(); + if (isElHidden(el)) { + return; + } + chartInstance?.resize({ + animation: { + duration: 300, + easing: 'quadraticIn', + }, + }); + } + + watch([width, height], () => { + resizeHandler?.(); + }); + + useResizeObserver(chartRef as never, resizeHandler); + + watch(isDark, () => { + if (chartInstance) { + chartInstance.dispose(); + initCharts(); + renderEcharts(cacheOptions); + resize(); + } + }); + + tryOnUnmounted(() => { + // 销毁实例,释放资源 + chartInstance?.dispose(); + }); + return { + renderEcharts, + resize, + updateData, + getChartInstance: () => chartInstance, + }; +} + +export { useEcharts }; + +export type { EchartsUIType }; diff --git a/packages/effects/plugins/src/markmap/index.ts b/packages/effects/plugins/src/markmap/index.ts new file mode 100644 index 0000000..72a4923 --- /dev/null +++ b/packages/effects/plugins/src/markmap/index.ts @@ -0,0 +1,5 @@ +export { default as MarkdownIt } from 'markdown-it'; +export { Transformer } from 'markmap-lib'; +export { Toolbar } from 'markmap-toolbar'; + +export * from 'markmap-view'; diff --git a/packages/effects/plugins/src/motion/index.ts b/packages/effects/plugins/src/motion/index.ts new file mode 100644 index 0000000..021465a --- /dev/null +++ b/packages/effects/plugins/src/motion/index.ts @@ -0,0 +1,8 @@ +export * from './types'; + +export { + MotionComponent as Motion, + MotionDirective, + MotionGroupComponent as MotionGroup, + MotionPlugin, +} from '@vueuse/motion'; diff --git a/packages/effects/plugins/src/motion/types.ts b/packages/effects/plugins/src/motion/types.ts new file mode 100644 index 0000000..f08bf21 --- /dev/null +++ b/packages/effects/plugins/src/motion/types.ts @@ -0,0 +1,26 @@ +export const MotionPresets = [ + 'fade', + 'fadeVisible', + 'fadeVisibleOnce', + 'rollBottom', + 'rollLeft', + 'rollRight', + 'rollTop', + 'rollVisibleBottom', + 'rollVisibleLeft', + 'rollVisibleRight', + 'rollVisibleTop', + 'pop', + 'popVisible', + 'popVisibleOnce', + 'slideBottom', + 'slideLeft', + 'slideRight', + 'slideTop', + 'slideVisibleBottom', + 'slideVisibleLeft', + 'slideVisibleRight', + 'slideVisibleTop', +] as const; + +export type MotionPreset = (typeof MotionPresets)[number]; diff --git a/packages/effects/plugins/src/tinyflow/index.ts b/packages/effects/plugins/src/tinyflow/index.ts new file mode 100644 index 0000000..f21bd14 --- /dev/null +++ b/packages/effects/plugins/src/tinyflow/index.ts @@ -0,0 +1 @@ +export { default as Tinyflow } from './tinyflow.vue'; diff --git a/packages/effects/plugins/src/tinyflow/tinyflow.vue b/packages/effects/plugins/src/tinyflow/tinyflow.vue new file mode 100644 index 0000000..256f8a0 --- /dev/null +++ b/packages/effects/plugins/src/tinyflow/tinyflow.vue @@ -0,0 +1,74 @@ + + + diff --git a/packages/effects/plugins/src/vxe-table/api.ts b/packages/effects/plugins/src/vxe-table/api.ts new file mode 100644 index 0000000..2b60d60 --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/api.ts @@ -0,0 +1,128 @@ +import type { VxeGridInstance } from 'vxe-table'; + +import type { ExtendedFormApi } from '@vben-core/form-ui'; + +import type { VxeGridProps } from './types'; + +import { toRaw } from 'vue'; + +import { Store } from '@vben-core/shared/store'; +import { + bindMethods, + isBoolean, + isFunction, + mergeWithArrayOverride, + StateHandler, +} from '@vben-core/shared/utils'; + +function getDefaultState(): VxeGridProps { + return { + class: '', + gridClass: '', + gridOptions: {}, + gridEvents: {}, + formOptions: undefined, + showSearchForm: true, + }; +} + +export class VxeGridApi = any> { + public formApi = {} as ExtendedFormApi; + + // private prevState: null | VxeGridProps = null; + public grid = {} as VxeGridInstance; + public state: null | VxeGridProps = null; + + public store: Store>; + + private isMounted = false; + + private stateHandler: StateHandler; + + constructor(options: VxeGridProps = {}) { + const storeState = { ...options }; + + const defaultState = getDefaultState(); + this.store = new Store( + mergeWithArrayOverride(storeState, defaultState), + { + onUpdate: () => { + // this.prevState = this.state; + this.state = this.store.state; + }, + }, + ); + + this.state = this.store.state; + this.stateHandler = new StateHandler(); + bindMethods(this); + } + + mount(instance: null | VxeGridInstance, formApi: ExtendedFormApi) { + if (!this.isMounted && instance) { + this.grid = instance; + this.formApi = formApi; + this.stateHandler.setConditionTrue(); + this.isMounted = true; + } + } + + async query(params: Record = {}) { + try { + await this.grid.commitProxy('query', toRaw(params)); + } catch (error) { + console.error('Error occurred while querying:', error); + } + } + + async reload(params: Record = {}) { + try { + await this.grid.commitProxy('reload', toRaw(params)); + } catch (error) { + console.error('Error occurred while reloading:', error); + } + } + + setGridOptions(options: Partial) { + this.setState({ + gridOptions: options, + }); + } + + setLoading(isLoading: boolean) { + this.setState({ + gridOptions: { + loading: isLoading, + }, + }); + } + + setState( + stateOrFn: + | ((prev: VxeGridProps) => Partial>) + | Partial>, + ) { + if (isFunction(stateOrFn)) { + this.store.setState((prev) => { + return mergeWithArrayOverride(stateOrFn(prev), prev); + }); + } else { + this.store.setState((prev) => mergeWithArrayOverride(stateOrFn, prev)); + } + } + + toggleSearchForm(show?: boolean) { + this.setState({ + showSearchForm: isBoolean(show) ? show : !this.state?.showSearchForm, + }); + // nextTick(() => { + // this.grid.recalculate(); + // }); + return this.state?.showSearchForm; + } + + unmount() { + this.isMounted = false; + this.stateHandler.reset(); + } +} diff --git a/packages/effects/plugins/src/vxe-table/extends.ts b/packages/effects/plugins/src/vxe-table/extends.ts new file mode 100644 index 0000000..ff5fe27 --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/extends.ts @@ -0,0 +1,81 @@ +import type { VxeGridProps, VxeUIExport } from 'vxe-table'; + +import type { Recordable } from '@vben/types'; + +import type { VxeGridApi } from './api'; + +import { formatDate, formatDateTime, isFunction } from '@vben/utils'; + +export function extendProxyOptions( + api: VxeGridApi, + options: VxeGridProps, + getFormValues: () => Recordable, +) { + [ + 'query', + 'querySuccess', + 'queryError', + 'queryAll', + 'queryAllSuccess', + 'queryAllError', + ].forEach((key) => { + extendProxyOption(key, api, options, getFormValues); + }); +} + +function extendProxyOption( + key: string, + api: VxeGridApi, + options: VxeGridProps, + getFormValues: () => Recordable, +) { + const { proxyConfig } = options; + const configFn = (proxyConfig?.ajax as Recordable)?.[key]; + if (!isFunction(configFn)) { + return options; + } + + const wrapperFn = async ( + params: Recordable, + customValues: Recordable, + ...args: Recordable[] + ) => { + const formValues = getFormValues(); + const data = await configFn( + params, + { + /** + * 开启toolbarConfig.refresh功能 + * 点击刷新按钮 这里的值为PointerEvent 会携带错误参数 + */ + ...(customValues instanceof PointerEvent ? {} : customValues), + ...formValues, + }, + ...args, + ); + return data; + }; + api.setState({ + gridOptions: { + proxyConfig: { + ajax: { + [key]: wrapperFn, + }, + }, + }, + }); +} + +export function extendsDefaultFormatter(vxeUI: VxeUIExport) { + vxeUI.formats.add('formatDate', { + tableCellFormatMethod({ cellValue }) { + return formatDate(cellValue) as string; + }, + }); + + vxeUI.formats.add('formatDateTime', { + tableCellFormatMethod({ cellValue }) { + return formatDateTime(cellValue) as string; + }, + }); +} diff --git a/packages/effects/plugins/src/vxe-table/index.ts b/packages/effects/plugins/src/vxe-table/index.ts new file mode 100644 index 0000000..66196d7 --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/index.ts @@ -0,0 +1,27 @@ +import { defineAsyncComponent } from 'vue'; + +export { setupVbenVxeTable } from './init'; +export { default as VbenVxeTableToolbar } from './table-toolbar.vue'; +export type { VxeTableGridOptions } from './types'; +export * from './use-vxe-grid'; +export { default as VbenVxeGrid } from './use-vxe-grid.vue'; +export { useTableToolbar } from './use-vxe-toolbar'; +export * from './validation'; + +export type { + VxeGridListeners, + VxeGridProps, + VxeGridPropTypes, + VxeTableInstance, +} from 'vxe-table'; + +// 异步导出 vxe-table 相关组件提供给需要单独使用 vxe-table 的场景 +export const AsyncVxeTable = defineAsyncComponent(() => + import('vxe-table').then((mod) => mod.VxeTable), +); +export const AsyncVxeColumn = defineAsyncComponent(() => + import('vxe-table').then((mod) => mod.VxeColumn), +); +export const AsyncVxeToolbar = defineAsyncComponent(() => + import('vxe-table').then((mod) => mod.VxeToolbar), +); diff --git a/packages/effects/plugins/src/vxe-table/init.ts b/packages/effects/plugins/src/vxe-table/init.ts new file mode 100644 index 0000000..0a1e8ba --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/init.ts @@ -0,0 +1,131 @@ +import type { SetupVxeTable } from './types'; + +import { defineComponent, watch } from 'vue'; + +import { usePreferences } from '@vben/preferences'; + +import { useVbenForm } from '@vben-core/form-ui'; + +import { + VxeButton, + VxeCheckbox, + + // VxeFormGather, + // VxeForm, + // VxeFormItem, + VxeIcon, + VxeInput, + VxeLoading, + VxeModal, + VxeNumberInput, + VxePager, + // VxeList, + // VxeModal, + // VxeOptgroup, + // VxeOption, + // VxePulldown, + VxeRadio, + VxeRadioButton, + VxeRadioGroup, + VxeSelect, + VxeTooltip, + VxeUI, + VxeUpload, + // VxeSwitch, + // VxeTextarea, +} from 'vxe-pc-ui'; +import enUS from 'vxe-pc-ui/lib/language/en-US'; +// 导入默认的语言 +import zhCN from 'vxe-pc-ui/lib/language/zh-CN'; +import { + VxeColgroup, + VxeColumn, + VxeGrid, + VxeTable, + VxeToolbar, +} from 'vxe-table'; + +import { extendsDefaultFormatter } from './extends'; + +// 是否加载过 +let isInit = false; + +// eslint-disable-next-line import/no-mutable-exports +export let useTableForm: typeof useVbenForm; + +// 部分组件,如果没注册,vxe-table 会报错,这里实际没用组件,只是为了不报错,同时可以减少打包体积 +const createVirtualComponent = (name = '') => { + return defineComponent({ + name, + }); +}; + +export function initVxeTable() { + if (isInit) { + return; + } + + VxeUI.component(VxeTable); + VxeUI.component(VxeColumn); + VxeUI.component(VxeColgroup); + VxeUI.component(VxeGrid); + VxeUI.component(VxeToolbar); + + VxeUI.component(VxeButton); + // VxeUI.component(VxeButtonGroup); + VxeUI.component(VxeCheckbox); + // VxeUI.component(VxeCheckboxGroup); + VxeUI.component(createVirtualComponent('VxeForm')); + // VxeUI.component(VxeFormGather); + // VxeUI.component(VxeFormItem); + VxeUI.component(VxeIcon); + VxeUI.component(VxeInput); + // VxeUI.component(VxeList); + VxeUI.component(VxeLoading); + VxeUI.component(VxeModal); + VxeUI.component(VxeNumberInput); + // VxeUI.component(VxeOptgroup); + // VxeUI.component(VxeOption); + VxeUI.component(VxePager); + // VxeUI.component(VxePulldown); + VxeUI.component(VxeRadio); + VxeUI.component(VxeRadioButton); + VxeUI.component(VxeRadioGroup); + VxeUI.component(VxeSelect); + // VxeUI.component(VxeSwitch); + // VxeUI.component(VxeTextarea); + VxeUI.component(VxeTooltip); + VxeUI.component(VxeUpload); + + isInit = true; +} + +export function setupVbenVxeTable(setupOptions: SetupVxeTable) { + const { configVxeTable, useVbenForm } = setupOptions; + + initVxeTable(); + useTableForm = useVbenForm; + + const { isDark, locale } = usePreferences(); + + const localMap = { + 'zh-CN': zhCN, + 'en-US': enUS, + }; + + watch( + [() => isDark.value, () => locale.value], + ([isDarkValue, localeValue]) => { + VxeUI.setTheme(isDarkValue ? 'dark' : 'light'); + VxeUI.setI18n(localeValue, localMap[localeValue]); + VxeUI.setLanguage(localeValue); + }, + { + immediate: true, + }, + ); + + extendsDefaultFormatter(VxeUI); + + configVxeTable(VxeUI); +} diff --git a/packages/effects/plugins/src/vxe-table/style.css b/packages/effects/plugins/src/vxe-table/style.css new file mode 100644 index 0000000..152fcf2 --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/style.css @@ -0,0 +1,143 @@ +:root .vxe-grid { + --vxe-ui-font-color: hsl(var(--foreground)); + --vxe-ui-font-primary-color: hsl(var(--primary)); + + /* --vxe-ui-font-lighten-color: #babdc0; + --vxe-ui-font-darken-color: #86898e; */ + --vxe-ui-font-disabled-color: hsl(var(--foreground) / 50%); + + /* base */ + --vxe-ui-base-popup-border-color: hsl(var(--border)); + --vxe-ui-input-disabled-color: hsl(var(--border) / 60%); + + /* --vxe-ui-base-popup-box-shadow: 0px 12px 30px 8px rgb(0 0 0 / 50%); */ + + /* layout */ + --vxe-ui-layout-background-color: hsl(var(--background)); + --vxe-ui-table-resizable-line-color: hsl(var(--heavy)); + + /* --vxe-ui-table-fixed-left-scrolling-box-shadow: 8px 0px 10px -5px hsl(var(--accent)); + --vxe-ui-table-fixed-right-scrolling-box-shadow: -8px 0px 10px -5px hsl(var(--accent)); */ + + /* input */ + --vxe-ui-input-border-color: hsl(var(--border)); + + /* --vxe-ui-input-placeholder-color: #8d9095; */ + + /* --vxe-ui-input-disabled-background-color: #262727; */ + + /* loading */ + --vxe-ui-loading-background-color: hsl(var(--overlay-content)); + + /* table */ + --vxe-ui-table-header-background-color: hsl(var(--accent)); + --vxe-ui-table-border-color: hsl(var(--border)); + --vxe-ui-table-row-hover-background-color: hsl(var(--accent-hover)); + --vxe-ui-table-row-striped-background-color: hsl(var(--accent) / 60%); + --vxe-ui-table-row-hover-striped-background-color: hsl(var(--accent)); + --vxe-ui-table-row-radio-checked-background-color: hsl(var(--accent)); + --vxe-ui-table-row-hover-radio-checked-background-color: hsl( + var(--accent-hover) + ); + --vxe-ui-table-row-checkbox-checked-background-color: hsl(var(--accent)); + --vxe-ui-table-row-hover-checkbox-checked-background-color: hsl( + var(--accent-hover) + ); + --vxe-ui-table-row-current-background-color: hsl(var(--accent)); + --vxe-ui-table-row-hover-current-background-color: hsl(var(--accent-hover)); + --vxe-ui-font-primary-tinge-color: hsl(var(--primary)); + --vxe-ui-font-primary-lighten-color: hsl(var(--primary) / 60%); + --vxe-ui-font-primary-darken-color: hsl(var(--primary)); + + height: auto !important; + + /* --vxe-ui-table-fixed-scrolling-box-shadow-color: rgb(0 0 0 / 80%); */ +} + +.vxe-pager { + .vxe-pager--prev-btn:not(.is--disabled):active, + .vxe-pager--next-btn:not(.is--disabled):active, + .vxe-pager--num-btn:not(.is--disabled):active, + .vxe-pager--jump-prev:not(.is--disabled):active, + .vxe-pager--jump-next:not(.is--disabled):active, + .vxe-pager--prev-btn:not(.is--disabled):focus, + .vxe-pager--next-btn:not(.is--disabled):focus, + .vxe-pager--num-btn:not(.is--disabled):focus, + .vxe-pager--jump-prev:not(.is--disabled):focus, + .vxe-pager--jump-next:not(.is--disabled):focus { + color: hsl(var(--accent-foreground)); + background-color: hsl(var(--accent)); + border: 1px solid hsl(var(--border)); + box-shadow: 0 0 0 1px hsl(var(--border)); + } + + .vxe-pager--wrapper { + display: flex; + align-items: center; + } + + .vxe-pager--sizes { + margin-right: auto; + } +} + +.vxe-pager--wrapper { + @apply justify-center md:justify-end; +} + +.vxe-tools--operate { + margin-right: 0.25rem; + margin-left: 0.75rem; +} + +.vxe-table-custom--checkbox-option:hover { + background: none !important; +} + +.vxe-toolbar { + padding: 0; +} + +.vxe-buttons--wrapper:not(:empty), +.vxe-tools--operate:not(:empty), +.vxe-tools--wrapper:not(:empty) { + padding: 0.6em 0; +} + +.vxe-tools--operate:not(:has(button)) { + margin-left: 0; +} + +.vxe-grid--layout-header-wrapper { + overflow: visible; +} + +.vxe-grid--layout-body-content-wrapper { + overflow: hidden; +} + +/* 必填字段错误样式 */ +.vxe-table .required-field-error::after { + position: absolute; + top: -1px; + right: -1px; + z-index: 10; + padding: 1px 4px; + font-size: 10px; + line-height: 1; + color: white; + content: '必填'; + background-color: #ff4d4f; + border-radius: 0 0 0 4px; +} + +/* 必填字段内的输入框样式 */ +.vxe-table .required-field-error .ant-select, +.vxe-table .required-field-error .ant-input-number, +.vxe-table .required-field-error .ant-input { + border-color: #ff4d4f !important; +} + +.vxe-table .required-field-error .ant-select .ant-select-selector { + border-color: #ff4d4f !important; +} diff --git a/packages/effects/plugins/src/vxe-table/table-toolbar.vue b/packages/effects/plugins/src/vxe-table/table-toolbar.vue new file mode 100644 index 0000000..6e93324 --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/table-toolbar.vue @@ -0,0 +1,74 @@ + + + + diff --git a/packages/effects/plugins/src/vxe-table/types.ts b/packages/effects/plugins/src/vxe-table/types.ts new file mode 100644 index 0000000..8b9aea4 --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/types.ts @@ -0,0 +1,93 @@ +import type { + VxeGridListeners, + VxeGridPropTypes, + VxeGridProps as VxeTableGridProps, + VxeUIExport, +} from 'vxe-table'; + +import type { Ref } from 'vue'; + +import type { ClassType, DeepPartial } from '@vben/types'; + +import type { BaseFormComponentType, VbenFormProps } from '@vben-core/form-ui'; + +import type { VxeGridApi } from './api'; + +import { useVbenForm } from '@vben-core/form-ui'; + +export interface VxePaginationInfo { + currentPage: number; + pageSize: number; + total: number; +} + +interface ToolbarConfigOptions extends VxeGridPropTypes.ToolbarConfig { + /** 是否显示切换搜索表单的按钮 */ + search?: boolean; +} + +export interface VxeTableGridOptions extends VxeTableGridProps { + /** 工具栏配置 */ + toolbarConfig?: ToolbarConfigOptions; +} + +export interface SeparatorOptions { + show?: boolean; + backgroundColor?: string; +} + +export interface VxeGridProps< + T extends Record = any, + D extends BaseFormComponentType = BaseFormComponentType, +> { + /** + * 标题 + */ + tableTitle?: string; + /** + * 标题帮助 + */ + tableTitleHelp?: string; + /** + * 组件class + */ + class?: ClassType; + /** + * vxe-grid class + */ + gridClass?: ClassType; + /** + * vxe-grid 配置 + */ + gridOptions?: DeepPartial>; + /** + * vxe-grid 事件 + */ + gridEvents?: DeepPartial>; + /** + * 表单配置 + */ + formOptions?: VbenFormProps; + /** + * 显示搜索表单 + */ + showSearchForm?: boolean; + /** + * 搜索表单与表格主体之间的分隔条 + */ + separator?: boolean | SeparatorOptions; +} + +export type ExtendedVxeGridApi< + D extends Record = any, + F extends BaseFormComponentType = BaseFormComponentType, +> = VxeGridApi & { + useStore: >>( + selector?: (state: NoInfer>) => T, + ) => Readonly>; +}; + +export interface SetupVxeTable { + configVxeTable: (ui: VxeUIExport) => void; + useVbenForm: typeof useVbenForm; +} diff --git a/packages/effects/plugins/src/vxe-table/use-vxe-grid.ts b/packages/effects/plugins/src/vxe-table/use-vxe-grid.ts new file mode 100644 index 0000000..6ab8769 --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/use-vxe-grid.ts @@ -0,0 +1,70 @@ +import type { VxeGridSlots, VxeGridSlotTypes } from 'vxe-table'; + +import type { SlotsType } from 'vue'; + +import type { BaseFormComponentType } from '@vben-core/form-ui'; + +import type { ExtendedVxeGridApi, VxeGridProps } from './types'; + +import { defineComponent, h, onBeforeUnmount } from 'vue'; + +import { useStore } from '@vben-core/shared/store'; + +import { VxeGridApi } from './api'; +import VxeGrid from './use-vxe-grid.vue'; + +type FilteredSlots = { + [K in keyof VxeGridSlots as K extends 'form' + ? never + : K]: VxeGridSlots[K]; +}; + +export function useVbenVxeGrid< + T extends Record = any, + D extends BaseFormComponentType = BaseFormComponentType, +>(options: VxeGridProps) { + // const IS_REACTIVE = isReactive(options); + const api = new VxeGridApi(options); + const extendedApi: ExtendedVxeGridApi = api as ExtendedVxeGridApi; + extendedApi.useStore = (selector) => { + return useStore(api.store, selector); + }; + + const Grid = defineComponent( + (props: VxeGridProps, { attrs, slots }) => { + onBeforeUnmount(() => { + api.unmount(); + }); + api.setState({ ...props, ...attrs }); + return () => h(VxeGrid, { ...props, ...attrs, api: extendedApi }, slots); + }, + { + name: 'VbenVxeGrid', + inheritAttrs: false, + slots: Object as SlotsType< + { + // 表格标题 + 'table-title': undefined; + // 工具栏左侧部分 + 'toolbar-actions': VxeGridSlotTypes.DefaultSlotParams; + // 工具栏右侧部分 + 'toolbar-tools': VxeGridSlotTypes.DefaultSlotParams; + } & FilteredSlots + >, + }, + ); + // Add reactivity support + // if (IS_REACTIVE) { + // watch( + // () => options, + // () => { + // api.setState(options); + // }, + // { immediate: true }, + // ); + // } + + return [Grid, extendedApi] as const; +} + +export type UseVbenVxeGrid = typeof useVbenVxeGrid; diff --git a/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue b/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue new file mode 100644 index 0000000..ac71f06 --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue @@ -0,0 +1,483 @@ + + + diff --git a/packages/effects/plugins/src/vxe-table/use-vxe-toolbar.ts b/packages/effects/plugins/src/vxe-table/use-vxe-toolbar.ts new file mode 100644 index 0000000..773b20f --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/use-vxe-toolbar.ts @@ -0,0 +1,48 @@ +import type { VxeTableInstance, VxeToolbarInstance } from 'vxe-table'; + +import { ref, watch } from 'vue'; + +import VbenVxeTableToolbar from './table-toolbar.vue'; + +/** + * vxe 原生工具栏挂载封装 + * 解决每个组件使用 vxe-table 组件时都需要写一遍的问题 + */ +export function useTableToolbar() { + const hiddenSearchBar = ref(false); // 隐藏搜索栏 + const tableToolbarRef = ref>(); + const tableRef = ref(); + const isBound = ref(false); + + /** 挂载 toolbar 工具栏 */ + async function bindTableToolbar() { + const table = tableRef.value; + const tableToolbar = tableToolbarRef.value; + if (table && tableToolbar) { + // 延迟 1 秒,确保 toolbar 组件已经挂载 + setTimeout(async () => { + const toolbar = tableToolbar.getToolbarRef(); + if (!toolbar) { + console.error('[toolbar 挂载失败] Table toolbar not found'); + } + await table.connectToolbar(toolbar as VxeToolbarInstance); + isBound.value = true; + }, 1000); // 延迟挂载确保 toolbar 正确挂载 + } + } + + watch( + () => tableRef.value, + async (val) => { + if (!val || isBound.value) return; + await bindTableToolbar(); + }, + { immediate: true }, + ); + + return { + hiddenSearchBar, + tableToolbarRef, + tableRef, + }; +} diff --git a/packages/effects/plugins/src/vxe-table/validation.ts b/packages/effects/plugins/src/vxe-table/validation.ts new file mode 100644 index 0000000..487f241 --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/validation.ts @@ -0,0 +1,61 @@ +/** + * 创建验证类名的工具函数 + * @param isValidating 验证状态 + * @param fieldName 字段名 + * @param validationRules 验证规则,可以是字符串或自定义函数 + * @returns 返回 className 函数 + */ +function createValidationClassName( + isValidating: any, + fieldName: string, + validationRules: ((row: any) => boolean) | string, +) { + return ({ row }: { row: any }) => { + if (!isValidating?.value) return ''; + + let isValid = true; + if (typeof validationRules === 'string') { + // 处理简单的验证规则 + if (validationRules === 'required') { + isValid = + fieldName === 'count' + ? row[fieldName] && row[fieldName] > 0 + : !!row[fieldName]; + } + } else if (typeof validationRules === 'function') { + // 处理自定义验证函数 + isValid = validationRules(row); + } + + return isValid ? '' : 'required-field-error'; + }; +} + +/** + * 创建必填字段验证 + * @param isValidating 验证状态 + * @param fieldName 字段名 + * @returns 返回 className 函数 + */ +function createRequiredValidation(isValidating: any, fieldName: string) { + return createValidationClassName(isValidating, fieldName, 'required'); +} + +/** + * 创建自定义验证 + * @param isValidating 验证状态 + * @param validationFn 自定义验证函数 + * @returns 返回 className 函数 + */ +function createCustomValidation( + isValidating: any, + validationFn: (row: any) => boolean, +) { + return createValidationClassName(isValidating, '', validationFn); +} + +export { + createCustomValidation, + createRequiredValidation, + createValidationClassName, +}; diff --git a/packages/effects/plugins/tsconfig.json b/packages/effects/plugins/tsconfig.json new file mode 100644 index 0000000..ce1a891 --- /dev/null +++ b/packages/effects/plugins/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/effects/request/package.json b/packages/effects/request/package.json new file mode 100644 index 0000000..294d422 --- /dev/null +++ b/packages/effects/request/package.json @@ -0,0 +1,33 @@ +{ + "name": "@vben/request", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/effects/request" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "dependencies": { + "@microsoft/fetch-event-source": "catalog:", + "@vben/locales": "workspace:*", + "@vben/utils": "workspace:*", + "axios": "catalog:", + "qs": "catalog:" + }, + "devDependencies": { + "@types/qs": "catalog:", + "axios-mock-adapter": "catalog:" + } +} diff --git a/packages/effects/request/src/index.ts b/packages/effects/request/src/index.ts new file mode 100644 index 0000000..d4a3ed1 --- /dev/null +++ b/packages/effects/request/src/index.ts @@ -0,0 +1,3 @@ +export * from './request-client'; +export * from '@microsoft/fetch-event-source'; +export * from 'axios'; diff --git a/packages/effects/request/src/request-client/index.ts b/packages/effects/request/src/request-client/index.ts new file mode 100644 index 0000000..a44cd15 --- /dev/null +++ b/packages/effects/request/src/request-client/index.ts @@ -0,0 +1,3 @@ +export * from './preset-interceptors'; +export * from './request-client'; +export type * from './types'; diff --git a/packages/effects/request/src/request-client/modules/downloader.test.ts b/packages/effects/request/src/request-client/modules/downloader.test.ts new file mode 100644 index 0000000..27e8a30 --- /dev/null +++ b/packages/effects/request/src/request-client/modules/downloader.test.ts @@ -0,0 +1,157 @@ +import type { AxiosRequestConfig } from 'axios'; + +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { FileDownloader } from './downloader'; + +describe('fileDownloader', () => { + let fileDownloader: FileDownloader; + const mockAxiosInstance = { + get: vi.fn(), + } as any; + + beforeEach(() => { + fileDownloader = new FileDownloader(mockAxiosInstance); + }); + + it('should create an instance of FileDownloader', () => { + expect(fileDownloader).toBeInstanceOf(FileDownloader); + }); + + it('should download a file and return a Blob', async () => { + const url = 'https://example.com/file'; + const mockBlob = new Blob(['file content'], { type: 'text/plain' }); + const mockResponse: Blob = mockBlob; + + mockAxiosInstance.get.mockResolvedValueOnce(mockResponse); + + const result = await fileDownloader.download(url); + + expect(result).toBeInstanceOf(Blob); + expect(result).toEqual(mockBlob); + expect(mockAxiosInstance.get).toHaveBeenCalledWith(url, { + method: 'GET', + responseType: 'blob', + responseReturn: 'body', + }); + }); + + it('should merge provided config with default config', async () => { + const url = 'https://example.com/file'; + const mockBlob = new Blob(['file content'], { type: 'text/plain' }); + const mockResponse: Blob = mockBlob; + + mockAxiosInstance.get.mockResolvedValueOnce(mockResponse); + + const customConfig: AxiosRequestConfig = { + headers: { 'Custom-Header': 'value' }, + }; + + const result = await fileDownloader.download(url, customConfig); + expect(result).toBeInstanceOf(Blob); + expect(result).toEqual(mockBlob); + expect(mockAxiosInstance.get).toHaveBeenCalledWith(url, { + ...customConfig, + method: 'GET', + responseType: 'blob', + responseReturn: 'body', + }); + }); + + it('should handle errors gracefully', async () => { + const url = 'https://example.com/file'; + mockAxiosInstance.get.mockRejectedValueOnce(new Error('Network Error')); + await expect(fileDownloader.download(url)).rejects.toThrow('Network Error'); + }); + + it('should handle empty URL gracefully', async () => { + const url = ''; + mockAxiosInstance.get.mockRejectedValueOnce( + new Error('Request failed with status code 404'), + ); + + await expect(fileDownloader.download(url)).rejects.toThrow( + 'Request failed with status code 404', + ); + }); + + it('should handle null URL gracefully', async () => { + const url = null as unknown as string; + mockAxiosInstance.get.mockRejectedValueOnce( + new Error('Request failed with status code 404'), + ); + + await expect(fileDownloader.download(url)).rejects.toThrow( + 'Request failed with status code 404', + ); + }); +}); + +describe('fileDownloader use other method', () => { + let fileDownloader: FileDownloader; + + it('should call request using get', async () => { + const url = 'https://example.com/file'; + const mockBlob = new Blob(['file content'], { type: 'text/plain' }); + const mockResponse: Blob = mockBlob; + + const mockAxiosInstance = { + request: vi.fn(), + } as any; + + fileDownloader = new FileDownloader(mockAxiosInstance); + + mockAxiosInstance.request.mockResolvedValueOnce(mockResponse); + + const result = await fileDownloader.download(url); + + expect(result).toBeInstanceOf(Blob); + expect(result).toEqual(mockBlob); + expect(mockAxiosInstance.request).toHaveBeenCalledWith(url, { + method: 'GET', + responseType: 'blob', + responseReturn: 'body', + }); + }); + + it('should call post', async () => { + const url = 'https://example.com/file'; + + const mockAxiosInstance = { + post: vi.fn(), + } as any; + + fileDownloader = new FileDownloader(mockAxiosInstance); + + const customConfig: AxiosRequestConfig = { + method: 'POST', + data: { name: 'aa' }, + }; + + await fileDownloader.download(url, customConfig); + + expect(mockAxiosInstance.post).toHaveBeenCalledWith( + url, + { name: 'aa' }, + { + method: 'POST', + responseType: 'blob', + responseReturn: 'body', + }, + ); + }); + + it('should handle errors gracefully', async () => { + const url = 'https://example.com/file'; + const mockAxiosInstance = { + post: vi.fn(), + } as any; + + fileDownloader = new FileDownloader(mockAxiosInstance); + await expect(() => + fileDownloader.download(url, { method: 'postt' }), + ).rejects.toThrow( + 'RequestClient does not support method "POSTT". Please ensure the method is properly implemented in your RequestClient instance.', + ); + }); +}); diff --git a/packages/effects/request/src/request-client/modules/downloader.ts b/packages/effects/request/src/request-client/modules/downloader.ts new file mode 100644 index 0000000..6c30005 --- /dev/null +++ b/packages/effects/request/src/request-client/modules/downloader.ts @@ -0,0 +1,60 @@ +import type { RequestClient } from '../request-client'; +import type { RequestClientConfig } from '../types'; + +type DownloadRequestConfig = { + /** + * 定义期望获得的数据类型。 + * raw: 原始的AxiosResponse,包括headers、status等。 + * body: 只返回响应数据的BODY部分(Blob) + */ + responseReturn?: 'body' | 'raw'; +} & Omit; + +class FileDownloader { + private client: RequestClient; + + constructor(client: RequestClient) { + this.client = client; + } + /** + * 下载文件 + * @param url 文件的完整链接 + * @param config 配置信息,可选。 + * @returns 如果config.responseReturn为'body',则返回Blob(默认),否则返回RequestResponse + */ + public async download( + url: string, + config?: DownloadRequestConfig, + ): Promise { + const finalConfig: DownloadRequestConfig = { + responseReturn: 'body', + method: 'GET', + ...config, + responseType: 'blob', + }; + + // Prefer a generic request if available; otherwise, dispatch to method-specific calls. + const method = (finalConfig.method || 'GET').toUpperCase(); + const clientAny = this.client as any; + + if (typeof clientAny.request === 'function') { + return await clientAny.request(url, finalConfig); + } + const lower = method.toLowerCase(); + + if (typeof clientAny[lower] === 'function') { + if (['POST', 'PUT'].includes(method)) { + const { data, ...rest } = finalConfig as Record; + return await clientAny[lower](url, data, rest); + } + + return await clientAny[lower](url, finalConfig); + } + + throw new Error( + `RequestClient does not support method "${method}". Please ensure the method is properly implemented in your RequestClient instance.`, + ); + } +} + +export { FileDownloader }; diff --git a/packages/effects/request/src/request-client/modules/interceptor.ts b/packages/effects/request/src/request-client/modules/interceptor.ts new file mode 100644 index 0000000..f6d2ad8 --- /dev/null +++ b/packages/effects/request/src/request-client/modules/interceptor.ts @@ -0,0 +1,40 @@ +import type { AxiosInstance, AxiosResponse } from 'axios'; + +import type { + RequestInterceptorConfig, + ResponseInterceptorConfig, +} from '../types'; + +const defaultRequestInterceptorConfig: RequestInterceptorConfig = { + fulfilled: (response) => response, + rejected: (error) => Promise.reject(error), +}; + +const defaultResponseInterceptorConfig: ResponseInterceptorConfig = { + fulfilled: (response: AxiosResponse) => response, + rejected: (error) => Promise.reject(error), +}; + +class InterceptorManager { + private axiosInstance: AxiosInstance; + + constructor(instance: AxiosInstance) { + this.axiosInstance = instance; + } + + addRequestInterceptor({ + fulfilled, + rejected, + }: RequestInterceptorConfig = defaultRequestInterceptorConfig) { + this.axiosInstance.interceptors.request.use(fulfilled, rejected); + } + + addResponseInterceptor({ + fulfilled, + rejected, + }: ResponseInterceptorConfig = defaultResponseInterceptorConfig) { + this.axiosInstance.interceptors.response.use(fulfilled, rejected); + } +} + +export { InterceptorManager }; diff --git a/packages/effects/request/src/request-client/modules/sse.test.ts b/packages/effects/request/src/request-client/modules/sse.test.ts new file mode 100644 index 0000000..4e8c6a9 --- /dev/null +++ b/packages/effects/request/src/request-client/modules/sse.test.ts @@ -0,0 +1,142 @@ +import type { RequestClient } from '../request-client'; + +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { SSE } from './sse'; + +// 模拟 TextDecoder +const OriginalTextDecoder = globalThis.TextDecoder; + +beforeEach(() => { + vi.stubGlobal( + 'TextDecoder', + class { + private decoder = new OriginalTextDecoder(); + decode(value: Uint8Array, opts?: any) { + return this.decoder.decode(value, opts); + } + }, + ); +}); + +// 创建 fetch mock +const createFetchMock = (chunks: string[], ok = true) => { + const encoder = new TextEncoder(); + let index = 0; + return vi.fn().mockResolvedValue({ + ok, + status: ok ? 200 : 500, + body: { + getReader: () => ({ + read: async () => { + if (index < chunks.length) { + return { done: false, value: encoder.encode(chunks[index++]) }; + } + return { done: true, value: undefined }; + }, + }), + }, + }); +}; + +describe('sSE', () => { + let client: RequestClient; + let sse: SSE; + + beforeEach(() => { + vi.restoreAllMocks(); + client = { + getBaseUrl: () => 'http://localhost', + instance: { + interceptors: { + request: { + handlers: [], + }, + }, + }, + } as unknown as RequestClient; + sse = new SSE(client); + }); + + it('should call requestSSE when postSSE is used', async () => { + const spy = vi.spyOn(sse, 'requestSSE').mockResolvedValue(undefined); + await sse.postSSE('/test', { foo: 'bar' }, { headers: { a: '1' } }); + expect(spy).toHaveBeenCalledWith( + '/test', + { foo: 'bar' }, + { + headers: { a: '1' }, + method: 'POST', + }, + ); + }); + + it('should throw error if fetch response not ok', async () => { + vi.stubGlobal('fetch', createFetchMock([], false)); + await expect(sse.requestSSE('/bad')).rejects.toThrow( + 'HTTP error! status: 500', + ); + }); + + it('should trigger onMessage and onEnd callbacks', async () => { + const messages: string[] = []; + const onMessage = vi.fn((msg: string) => messages.push(msg)); + const onEnd = vi.fn(); + + vi.stubGlobal('fetch', createFetchMock(['hello', ' world'])); + + await sse.requestSSE('/sse', undefined, { onMessage, onEnd }); + + expect(onMessage).toHaveBeenCalledTimes(2); + expect(messages.join('')).toBe('hello world'); + // onEnd 不再带参数 + expect(onEnd).toHaveBeenCalled(); + }); + + it('should apply request interceptors', async () => { + const interceptor = vi.fn(async (config) => { + config.headers['x-test'] = 'intercepted'; + return config; + }); + (client.instance.interceptors.request as any).handlers.push({ + fulfilled: interceptor, + }); + + // 创建 fetch mock,并挂到全局 + const fetchMock = createFetchMock(['data']); + vi.stubGlobal('fetch', fetchMock); + + await sse.requestSSE('/sse', undefined, {}); + + expect(interceptor).toHaveBeenCalled(); + expect(fetchMock).toHaveBeenCalledWith( + 'http://localhost/sse', + expect.objectContaining({ + headers: expect.any(Headers), + }), + ); + + const calls = fetchMock.mock?.calls; + expect(calls).toBeDefined(); + expect(calls?.length).toBeGreaterThan(0); + + const init = calls?.[0]?.[1] as RequestInit; + expect(init).toBeDefined(); + + const headers = init?.headers as Headers; + expect(headers?.get('x-test')).toBe('intercepted'); + expect(headers?.get('accept')).toBe('text/event-stream'); + }); + + it('should throw error when no reader', async () => { + vi.stubGlobal( + 'fetch', + vi.fn().mockResolvedValue({ + ok: true, + status: 200, + body: null, + }), + ); + await expect(sse.requestSSE('/sse')).rejects.toThrow('No reader'); + }); +}); diff --git a/packages/effects/request/src/request-client/modules/sse.ts b/packages/effects/request/src/request-client/modules/sse.ts new file mode 100644 index 0000000..09d1301 --- /dev/null +++ b/packages/effects/request/src/request-client/modules/sse.ts @@ -0,0 +1,136 @@ +import type { AxiosRequestHeaders, InternalAxiosRequestConfig } from 'axios'; + +import type { RequestClient } from '../request-client'; +import type { SseRequestOptions } from '../types'; + +/** + * SSE模块 + */ +class SSE { + private client: RequestClient; + + constructor(client: RequestClient) { + this.client = client; + } + + public async postSSE( + url: string, + data?: any, + requestOptions?: SseRequestOptions, + ) { + return this.requestSSE(url, data, { + ...requestOptions, + method: 'POST', + }); + } + + /** + * SSE请求方法 + * @param url - 请求URL + * @param data - 请求数据 + * @param requestOptions - SSE请求选项 + */ + public async requestSSE( + url: string, + data?: any, + requestOptions?: SseRequestOptions, + ) { + const baseUrl = this.client.getBaseUrl() || ''; + + let axiosConfig: InternalAxiosRequestConfig = { + url, + method: (requestOptions?.method as any) ?? 'GET', + headers: {} as AxiosRequestHeaders, + }; + const requestInterceptors = this.client.instance.interceptors + .request as any; + if ( + requestInterceptors.handlers && + requestInterceptors.handlers.length > 0 + ) { + for (const handler of requestInterceptors.handlers) { + if (typeof handler?.fulfilled === 'function') { + const next = await handler.fulfilled(axiosConfig as any); + if (next) axiosConfig = next as InternalAxiosRequestConfig; + } + } + } + + const merged = new Headers(); + Object.entries( + (axiosConfig.headers ?? {}) as Record, + ).forEach(([k, v]) => merged.set(k, String(v))); + if (requestOptions?.headers) { + new Headers(requestOptions.headers).forEach((v, k) => merged.set(k, v)); + } + if (!merged.has('accept')) { + merged.set('accept', 'text/event-stream'); + } + + let bodyInit = requestOptions?.body ?? data; + const ct = (merged.get('content-type') || '').toLowerCase(); + if ( + bodyInit && + typeof bodyInit === 'object' && + !ArrayBuffer.isView(bodyInit as any) && + !(bodyInit instanceof ArrayBuffer) && + !(bodyInit instanceof Blob) && + !(bodyInit instanceof FormData) && + ct.includes('application/json') + ) { + bodyInit = JSON.stringify(bodyInit); + } + const requestInit: RequestInit = { + ...requestOptions, + method: axiosConfig.method, + headers: merged, + body: bodyInit, + }; + + const response = await fetch(safeJoinUrl(baseUrl, url), requestInit); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const reader = response.body?.getReader(); + const decoder = new TextDecoder(); + + if (!reader) { + throw new Error('No reader'); + } + let isEnd = false; + while (!isEnd) { + const { done, value } = await reader.read(); + if (done) { + isEnd = true; + decoder.decode(new Uint8Array(0), { stream: false }); + requestOptions?.onEnd?.(); + reader.releaseLock?.(); + break; + } + const content = decoder.decode(value, { stream: true }); + requestOptions?.onMessage?.(content); + } + } +} + +function safeJoinUrl(baseUrl: string | undefined, url: string): string { + if (!baseUrl) { + return url; // 没有 baseUrl,直接返回 url + } + + // 如果 url 本身就是绝对地址,直接返回 + if (/^https?:\/\//i.test(url)) { + return url; + } + + // 如果 baseUrl 是完整 URL,就用 new URL + if (/^https?:\/\//i.test(baseUrl)) { + return new URL(url, baseUrl).toString(); + } + + // 否则,当作路径拼接 + return `${baseUrl.replace(/\/+$/, '')}/${url.replace(/^\/+/, '')}`; +} + +export { SSE }; diff --git a/packages/effects/request/src/request-client/modules/uploader.test.ts b/packages/effects/request/src/request-client/modules/uploader.test.ts new file mode 100644 index 0000000..8306656 --- /dev/null +++ b/packages/effects/request/src/request-client/modules/uploader.test.ts @@ -0,0 +1,118 @@ +import type { AxiosRequestConfig, AxiosResponse } from 'axios'; + +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { FileUploader } from './uploader'; + +describe('fileUploader', () => { + let fileUploader: FileUploader; + // Mock the AxiosInstance + const mockAxiosInstance = { + post: vi.fn(), + } as any; + + beforeEach(() => { + fileUploader = new FileUploader(mockAxiosInstance); + }); + + it('should create an instance of FileUploader', () => { + expect(fileUploader).toBeInstanceOf(FileUploader); + }); + + it('should upload a file and return the response', async () => { + const url = 'https://example.com/upload'; + const file = new File(['file content'], 'test.txt', { type: 'text/plain' }); + const mockResponse: AxiosResponse = { + config: {} as any, + data: { success: true }, + headers: {}, + status: 200, + statusText: 'OK', + }; + + ( + mockAxiosInstance.post as unknown as ReturnType + ).mockResolvedValueOnce(mockResponse); + + const result = await fileUploader.upload(url, { file }); + expect(result).toEqual(mockResponse); + expect(mockAxiosInstance.post).toHaveBeenCalledWith( + url, + expect.any(FormData), + { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }, + ); + }); + + it('should merge provided config with default config', async () => { + const url = 'https://example.com/upload'; + const file = new File(['file content'], 'test.txt', { type: 'text/plain' }); + const mockResponse: AxiosResponse = { + config: {} as any, + data: { success: true }, + headers: {}, + status: 200, + statusText: 'OK', + }; + + ( + mockAxiosInstance.post as unknown as ReturnType + ).mockResolvedValueOnce(mockResponse); + + const customConfig: AxiosRequestConfig = { + headers: { 'Custom-Header': 'value' }, + }; + + const result = await fileUploader.upload(url, { file }, customConfig); + expect(result).toEqual(mockResponse); + expect(mockAxiosInstance.post).toHaveBeenCalledWith( + url, + expect.any(FormData), + { + headers: { + 'Content-Type': 'multipart/form-data', + 'Custom-Header': 'value', + }, + }, + ); + }); + + it('should handle errors gracefully', async () => { + const url = 'https://example.com/upload'; + const file = new File(['file content'], 'test.txt', { type: 'text/plain' }); + ( + mockAxiosInstance.post as unknown as ReturnType + ).mockRejectedValueOnce(new Error('Network Error')); + + await expect(fileUploader.upload(url, { file })).rejects.toThrow( + 'Network Error', + ); + }); + + it('should handle empty URL gracefully', async () => { + const url = ''; + const file = new File(['file content'], 'test.txt', { type: 'text/plain' }); + ( + mockAxiosInstance.post as unknown as ReturnType + ).mockRejectedValueOnce(new Error('Request failed with status code 404')); + + await expect(fileUploader.upload(url, { file })).rejects.toThrow( + 'Request failed with status code 404', + ); + }); + + it('should handle null URL gracefully', async () => { + const url = null as unknown as string; + const file = new File(['file content'], 'test.txt', { type: 'text/plain' }); + ( + mockAxiosInstance.post as unknown as ReturnType + ).mockRejectedValueOnce(new Error('Request failed with status code 404')); + + await expect(fileUploader.upload(url, { file })).rejects.toThrow( + 'Request failed with status code 404', + ); + }); +}); diff --git a/packages/effects/request/src/request-client/modules/uploader.ts b/packages/effects/request/src/request-client/modules/uploader.ts new file mode 100644 index 0000000..1353222 --- /dev/null +++ b/packages/effects/request/src/request-client/modules/uploader.ts @@ -0,0 +1,42 @@ +import type { RequestClient } from '../request-client'; +import type { RequestClientConfig } from '../types'; + +import { isUndefined } from '@vben/utils'; + +class FileUploader { + private client: RequestClient; + + constructor(client: RequestClient) { + this.client = client; + } + + public async upload( + url: string, + data: Record & { file: Blob | File }, + config?: RequestClientConfig, + ): Promise { + const formData = new FormData(); + + Object.entries(data).forEach(([key, value]) => { + if (Array.isArray(value)) { + value.forEach((item, index) => { + !isUndefined(item) && formData.append(`${key}[${index}]`, item); + }); + } else { + !isUndefined(value) && formData.append(key, value); + } + }); + + const finalConfig: RequestClientConfig = { + ...config, + headers: { + 'Content-Type': 'multipart/form-data', + ...config?.headers, + }, + }; + + return this.client.post(url, formData, finalConfig); + } +} + +export { FileUploader }; diff --git a/packages/effects/request/src/request-client/preset-interceptors.ts b/packages/effects/request/src/request-client/preset-interceptors.ts new file mode 100644 index 0000000..de0f5bd --- /dev/null +++ b/packages/effects/request/src/request-client/preset-interceptors.ts @@ -0,0 +1,166 @@ +import type { RequestClient } from './request-client'; +import type { MakeErrorMessageFn, ResponseInterceptorConfig } from './types'; + +import { $t } from '@vben/locales'; +import { isFunction } from '@vben/utils'; + +import axios from 'axios'; + +export const defaultResponseInterceptor = ({ + codeField = 'code', + dataField = 'data', + successCode = 0, +}: { + /** 响应数据中代表访问结果的字段名 */ + codeField: string; + /** 响应数据中装载实际数据的字段名,或者提供一个函数从响应数据中解析需要返回的数据 */ + dataField: ((response: any) => any) | string; + /** 当codeField所指定的字段值与successCode相同时,代表接口访问成功。如果提供一个函数,则返回true代表接口访问成功 */ + successCode: ((code: any) => boolean) | number | string; +}): ResponseInterceptorConfig => { + return { + fulfilled: (response) => { + const { config, data: responseData, status } = response; + + if (config.responseReturn === 'raw') { + return response; + } + + if (status >= 200 && status < 400) { + if (config.responseReturn === 'body') { + return responseData; + } else if ( + isFunction(successCode) + ? successCode(responseData[codeField]) + : responseData[codeField] === successCode + ) { + return isFunction(dataField) + ? dataField(responseData) + : responseData[dataField]; + } + } + throw Object.assign({}, response, { response }); + }, + }; +}; + +export const authenticateResponseInterceptor = ({ + client, + doReAuthenticate, + doRefreshToken, + enableRefreshToken, + formatToken, +}: { + client: RequestClient; + doReAuthenticate: () => Promise; + doRefreshToken: () => Promise; + enableRefreshToken: boolean; + formatToken: (token: string) => null | string; +}): ResponseInterceptorConfig => { + return { + rejected: async (error) => { + const { config, response, data: responseData } = error; + // 如果不是 401 错误,直接抛出异常 + if (response?.status !== 401 && responseData?.code !== 401) { + throw error; + } + // 判断是否启用了 refreshToken 功能 + // 如果没有启用或者已经是重试请求了,直接跳转到重新登录 + if (!enableRefreshToken || config.__isRetryRequest) { + await doReAuthenticate(); + throw error; + } + // 如果正在刷新 token,则将请求加入队列,等待刷新完成 + if (client.isRefreshing) { + return new Promise((resolve) => { + client.refreshTokenQueue.push((newToken: string) => { + config.headers.Authorization = formatToken(newToken); + resolve(client.request(config.url, { ...config })); + }); + }); + } + + // 标记开始刷新 token + client.isRefreshing = true; + // 标记当前请求为重试请求,避免无限循环 + config.__isRetryRequest = true; + + try { + const newToken = await doRefreshToken(); + + // 处理队列中的请求 + client.refreshTokenQueue.forEach((callback) => callback(newToken)); + // 清空队列 + client.refreshTokenQueue = []; + + return client.request(error.config.url, { ...error.config }); + } catch (refreshError) { + // 如果刷新 token 失败,处理错误(如强制登出或跳转登录页面) + client.refreshTokenQueue.forEach((callback) => callback('')); + client.refreshTokenQueue = []; + console.error('Refresh token failed, please login again.'); + await doReAuthenticate(); + + throw refreshError; + } finally { + client.isRefreshing = false; + } + }, + }; +}; + +export const errorMessageResponseInterceptor = ( + makeErrorMessage?: MakeErrorMessageFn, +): ResponseInterceptorConfig => { + return { + rejected: (error: any) => { + if (axios.isCancel(error)) { + return Promise.reject(error); + } + + const err: string = error?.toString?.() ?? ''; + let errMsg = ''; + if (err?.includes('Network Error')) { + errMsg = $t('ui.fallback.http.networkError'); + } else if (error?.message?.includes?.('timeout')) { + errMsg = $t('ui.fallback.http.requestTimeout'); + } + if (errMsg) { + makeErrorMessage?.(errMsg, error); + return Promise.reject(error); + } + + let errorMessage = ''; + const status = + error?.code || error?.response?.data?.code || error?.response?.status; + + switch (status) { + case 400: { + errorMessage = $t('ui.fallback.http.badRequest'); + break; + } + case 401: { + errorMessage = $t('ui.fallback.http.unauthorized'); + break; + } + case 403: { + errorMessage = $t('ui.fallback.http.forbidden'); + break; + } + case 404: { + errorMessage = $t('ui.fallback.http.notFound'); + break; + } + case 408: { + errorMessage = $t('ui.fallback.http.requestTimeout'); + break; + } + default: { + errorMessage = $t('ui.fallback.http.internalServerError'); + } + } + makeErrorMessage?.(errorMessage, error); + return Promise.reject(error); + }, + }; +}; diff --git a/packages/effects/request/src/request-client/request-client.test.ts b/packages/effects/request/src/request-client/request-client.test.ts new file mode 100644 index 0000000..2d94525 --- /dev/null +++ b/packages/effects/request/src/request-client/request-client.test.ts @@ -0,0 +1,99 @@ +import axios from 'axios'; +import MockAdapter from 'axios-mock-adapter'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; + +import { RequestClient } from './request-client'; + +describe('requestClient', () => { + let mock: MockAdapter; + let requestClient: RequestClient; + + beforeEach(() => { + mock = new MockAdapter(axios); + requestClient = new RequestClient(); + }); + + afterEach(() => { + mock.reset(); + }); + + it('should successfully make a GET request', async () => { + mock.onGet('test/url').reply(200, { data: 'response' }); + + const response = await requestClient.get('test/url'); + + expect(response.data).toEqual({ data: 'response' }); + }); + + it('should successfully make a POST request', async () => { + const postData = { key: 'value' }; + const mockData = { data: 'response' }; + mock.onPost('/test/post', postData).reply(200, mockData); + const response = await requestClient.post('/test/post', postData); + expect(response.data).toEqual(mockData); + }); + + it('should successfully make a PUT request', async () => { + const putData = { key: 'updatedValue' }; + const mockData = { data: 'updated response' }; + mock.onPut('/test/put', putData).reply(200, mockData); + const response = await requestClient.put('/test/put', putData); + expect(response.data).toEqual(mockData); + }); + + it('should successfully make a DELETE request', async () => { + const mockData = { data: 'delete response' }; + mock.onDelete('/test/delete').reply(200, mockData); + const response = await requestClient.delete('/test/delete'); + expect(response.data).toEqual(mockData); + }); + + it('should handle network errors', async () => { + mock.onGet('/test/error').networkError(); + try { + await requestClient.get('/test/error'); + expect(true).toBe(false); + } catch (error: any) { + expect(error.isAxiosError).toBe(true); + expect(error.message).toBe('Network Error'); + } + }); + + it('should handle timeout', async () => { + mock.onGet('/test/timeout').timeout(); + try { + await requestClient.get('/test/timeout'); + expect(true).toBe(false); + } catch (error: any) { + expect(error.isAxiosError).toBe(true); + expect(error.code).toBe('ECONNABORTED'); + } + }); + + it('should successfully upload a file', async () => { + const fileData = new Blob(['file contents'], { type: 'text/plain' }); + + mock.onPost('/test/upload').reply((config) => { + return config.data instanceof FormData && config.data.has('file') + ? [200, { data: 'file uploaded' }] + : [400, { error: 'Bad Request' }]; + }); + + const response = await requestClient.upload('/test/upload', { + file: fileData, + }); + expect(response.data).toEqual({ data: 'file uploaded' }); + }); + + it('should successfully download a file as a blob', async () => { + const mockFileContent = new Blob(['mock file content'], { + type: 'text/plain', + }); + + mock.onGet('/test/download').reply(200, mockFileContent); + + const res = await requestClient.download('/test/download'); + + expect(res.data).toBeInstanceOf(Blob); + }); +}); diff --git a/packages/effects/request/src/request-client/request-client.ts b/packages/effects/request/src/request-client/request-client.ts new file mode 100644 index 0000000..c764dda --- /dev/null +++ b/packages/effects/request/src/request-client/request-client.ts @@ -0,0 +1,182 @@ +import type { AxiosInstance, AxiosResponse } from 'axios'; + +import type { RequestClientConfig, RequestClientOptions } from './types'; + +import { bindMethods, isString, merge } from '@vben/utils'; + +import axios from 'axios'; +import qs from 'qs'; + +import { FileDownloader } from './modules/downloader'; +import { InterceptorManager } from './modules/interceptor'; +import { SSE } from './modules/sse'; +import { FileUploader } from './modules/uploader'; + +function getParamsSerializer( + paramsSerializer: RequestClientOptions['paramsSerializer'], +) { + if (isString(paramsSerializer)) { + switch (paramsSerializer) { + case 'brackets': { + return (params: any) => + qs.stringify(params, { arrayFormat: 'brackets' }); + } + case 'comma': { + return (params: any) => qs.stringify(params, { arrayFormat: 'comma' }); + } + case 'indices': { + return (params: any) => + qs.stringify(params, { arrayFormat: 'indices' }); + } + case 'repeat': { + return (params: any) => qs.stringify(params, { arrayFormat: 'repeat' }); + } + } + } + return paramsSerializer; +} + +class RequestClient { + public addRequestInterceptor: InterceptorManager['addRequestInterceptor']; + + public addResponseInterceptor: InterceptorManager['addResponseInterceptor']; + public download: FileDownloader['download']; + + public readonly instance: AxiosInstance; + // 是否正在刷新token + public isRefreshing = false; + public postSSE: SSE['postSSE']; + // 刷新token队列 + public refreshTokenQueue: ((token: string) => void)[] = []; + public requestSSE: SSE['requestSSE']; + public upload: FileUploader['upload']; + + /** + * 构造函数,用于创建Axios实例 + * @param options - Axios请求配置,可选 + */ + constructor(options: RequestClientOptions = {}) { + // 合并默认配置和传入的配置 + const defaultConfig: RequestClientOptions = { + headers: { + 'Content-Type': 'application/json;charset=utf-8', + }, + responseReturn: 'raw', + // 默认超时时间 + timeout: 10_000, + paramsSerializer: 'repeat', + }; + const { ...axiosConfig } = options; + const requestConfig = merge(axiosConfig, defaultConfig); + requestConfig.paramsSerializer = getParamsSerializer( + requestConfig.paramsSerializer, + ); + this.instance = axios.create(requestConfig); + + bindMethods(this); + + // 实例化拦截器管理器 + const interceptorManager = new InterceptorManager(this.instance); + this.addRequestInterceptor = + interceptorManager.addRequestInterceptor.bind(interceptorManager); + this.addResponseInterceptor = + interceptorManager.addResponseInterceptor.bind(interceptorManager); + + // 实例化文件上传器 + const fileUploader = new FileUploader(this); + this.upload = fileUploader.upload.bind(fileUploader); + // 实例化文件下载器 + const fileDownloader = new FileDownloader(this); + this.download = fileDownloader.download.bind(fileDownloader); + // 实例化SSE模块 + const sse = new SSE(this); + this.postSSE = sse.postSSE.bind(sse); + this.requestSSE = sse.requestSSE.bind(sse); + } + + /** + * DELETE请求方法 + */ + public delete( + url: string, + config?: RequestClientConfig, + ): Promise { + return this.request(url, { ...config, method: 'DELETE' }); + } + + /** + * GET请求方法 + */ + public get(url: string, config?: RequestClientConfig): Promise { + return this.request(url, { ...config, method: 'GET' }); + } + + /** + * 获取基础URL + */ + public getBaseUrl() { + return this.instance.defaults.baseURL; + } + + /** + * POST请求方法 + */ + public post( + url: string, + data?: any, + config?: RequestClientConfig, + ): Promise { + return this.request(url, { ...config, data, method: 'POST' }); + } + + /** + * PUT请求方法 + */ + public put( + url: string, + data?: any, + config?: RequestClientConfig, + ): Promise { + return this.request(url, { ...config, data, method: 'PUT' }); + } + + /** + * 通用的请求方法 + */ + public async request( + url: string, + config: RequestClientConfig, + ): Promise { + try { + const response: AxiosResponse = await this.instance({ + url, + ...config, + ...(config.paramsSerializer + ? { paramsSerializer: getParamsSerializer(config.paramsSerializer) } + : {}), + }); + return response as T; + } catch (error: any) { + throw error.response ? error.response.data : error; + } + } +} + +/** + * 构建排序字段,处理 vxe 排序条件 + * + * add by 芋艿 + */ +export const buildSortingField = (sorts: any[]) => { + if (!sorts || sorts.length === 0) { + return {}; + } + const result: Record = {}; + sorts.forEach((sort: any, index: number) => { + result[`sortingFields[${index}].field`] = sort.field; + result[`sortingFields[${index}].order`] = sort.order; + }); + return result; +}; + +export { RequestClient }; diff --git a/packages/effects/request/src/request-client/types.ts b/packages/effects/request/src/request-client/types.ts new file mode 100644 index 0000000..c1722b8 --- /dev/null +++ b/packages/effects/request/src/request-client/types.ts @@ -0,0 +1,103 @@ +import type { + AxiosRequestConfig, + AxiosResponse, + CreateAxiosDefaults, + InternalAxiosRequestConfig, +} from 'axios'; + +type ExtendOptions = { + /** + * 参数序列化方式。预置的有 + * - brackets: ids[]=1&ids[]=2&ids[]=3 + * - comma: ids=1,2,3 + * - indices: ids[0]=1&ids[1]=2&ids[2]=3 + * - repeat: ids=1&ids=2&ids=3 + */ + paramsSerializer?: + | 'brackets' + | 'comma' + | 'indices' + | 'repeat' + | AxiosRequestConfig['paramsSerializer']; + /** + * 响应数据的返回方式。 + * - raw: 原始的AxiosResponse,包括headers、status等,不做是否成功请求的检查。 + * - body: 返回响应数据的BODY部分(只会根据status检查请求是否成功,忽略对code的判断,这种情况下应由调用方检查请求是否成功)。 + * - data: 解构响应的BODY数据,只返回其中的data节点数据(会检查status和code是否为成功状态)。 + */ + responseReturn?: 'body' | 'data' | 'raw'; +}; +type RequestClientConfig = AxiosRequestConfig & ExtendOptions; + +type RequestResponse = AxiosResponse & { + config: RequestClientConfig; +}; + +type RequestContentType = + | 'application/json;charset=utf-8' + | 'application/octet-stream;charset=utf-8' + | 'application/x-www-form-urlencoded;charset=utf-8' + | 'multipart/form-data;charset=utf-8'; + +type RequestClientOptions = CreateAxiosDefaults & ExtendOptions; + +/** + * SSE 请求选项 + */ +interface SseRequestOptions extends RequestInit { + onMessage?: (message: string) => void; + onEnd?: () => void; +} + +interface RequestInterceptorConfig { + fulfilled?: ( + config: ExtendOptions & InternalAxiosRequestConfig, + ) => + | (ExtendOptions & InternalAxiosRequestConfig) + | Promise>; + rejected?: (error: any) => any; +} + +interface ResponseInterceptorConfig { + fulfilled?: ( + response: RequestResponse, + ) => Promise | RequestResponse; + rejected?: (error: any) => any; +} + +type MakeErrorMessageFn = (message: string, error: any) => void; + +interface HttpResponse { + /** + * 0 表示成功 其他表示失败 + * 0 means success, others means fail + */ + code: number; + data: T; + msg: string; +} + +interface PageParam { + [key: string]: any; + pageNo: number; + pageSize: number; +} + +interface PageResult { + list: T[]; + total: number; +} + +export type { + HttpResponse, + MakeErrorMessageFn, + PageParam, + PageResult, + RequestClientConfig, + RequestClientOptions, + RequestContentType, + RequestInterceptorConfig, + RequestResponse, + ResponseInterceptorConfig, + SseRequestOptions, +}; diff --git a/packages/effects/request/tsconfig.json b/packages/effects/request/tsconfig.json new file mode 100644 index 0000000..ce1a891 --- /dev/null +++ b/packages/effects/request/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/icons/README.md b/packages/icons/README.md new file mode 100644 index 0000000..bc50d25 --- /dev/null +++ b/packages/icons/README.md @@ -0,0 +1,19 @@ +# @vben/icons + +用于多个 `app` 公用的图标文件,继承了 `@vben-core/icons` 的所有能力。业务上有通用图标可以放在这里。 + +## 用法 + +### 添加依赖 + +```bash +# 进入目标应用目录,例如 apps/xxxx-app +# cd apps/xxxx-app +pnpm add @vben/icons +``` + +### 使用 + +```ts +import { X } from '@vben/icons'; +``` diff --git a/packages/icons/package.json b/packages/icons/package.json new file mode 100644 index 0000000..d959286 --- /dev/null +++ b/packages/icons/package.json @@ -0,0 +1,22 @@ +{ + "name": "@vben/icons", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/icons" + }, + "license": "MIT", + "type": "module", + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "dependencies": { + "@vben-core/icons": "workspace:*" + } +} diff --git a/packages/icons/src/iconify/index.ts b/packages/icons/src/iconify/index.ts new file mode 100644 index 0000000..f4f2222 --- /dev/null +++ b/packages/icons/src/iconify/index.ts @@ -0,0 +1,67 @@ +import { createIconifyIcon } from '@vben-core/icons'; + +export * from '@vben-core/icons'; + +export const MdiKeyboardEsc = createIconifyIcon('mdi:keyboard-esc'); + +export const MdiWechat = createIconifyIcon('mdi:wechat'); + +export const MdiGithub = createIconifyIcon('mdi:github'); + +export const MdiGoogle = createIconifyIcon('mdi:google'); + +export const MdiQqchat = createIconifyIcon('mdi:qqchat'); + +export const MdiCheckboxMarkedCircleOutline = createIconifyIcon( + 'mdi:checkbox-marked-circle-outline', +); + +export const MsRefresh = createIconifyIcon('material-symbols:refresh-rounded'); + +export const TMinimize = createIconifyIcon('tabler:arrows-minimize'); + +export const AntdProfileOutlined = createIconifyIcon( + 'ant-design:profile-outlined', +); + +export const FolderOpenOutlined = createIconifyIcon( + 'ant-design:folder-open-outlined', +); + +export const DownloadOutlined = createIconifyIcon( + 'ant-design:download-outlined', +); + +export const EyeOutlined = createIconifyIcon('ant-design:eye-outlined'); + +export const ApiOutlined = createIconifyIcon('ant-design:api-outlined'); + +export const ZoomOutOutlined = createIconifyIcon( + 'ant-design:zoom-out-outlined', +); + +export const ZoomInOutlined = createIconifyIcon('ant-design:zoom-in-outlined'); + +export const UndoOutlined = createIconifyIcon('ant-design:undo-outlined'); + +export const RedoOutlined = createIconifyIcon('ant-design:redo-outlined'); + +export const ReloadOutlined = createIconifyIcon('ant-design:reload-outlined'); + +export const AlignLeftOutlined = createIconifyIcon( + 'ant-design:align-left-outlined', +); + +export const WarningOutlined = createIconifyIcon('ant-design:warning-outlined'); + +export const RiDingding = createIconifyIcon('ri:dingding-fill'); + +export const MenuOutlined = createIconifyIcon('ant-design:menu-outlined'); + +export const PlusOutlined = createIconifyIcon('ant-design:plus-outlined'); + +export const CloseCircleFilled = createIconifyIcon( + 'ant-design:close-circle-filled', +); + +export const SelectOutlined = createIconifyIcon('ant-design:select-outlined'); diff --git a/packages/icons/src/icons/empty-icon.vue b/packages/icons/src/icons/empty-icon.vue new file mode 100644 index 0000000..444a765 --- /dev/null +++ b/packages/icons/src/icons/empty-icon.vue @@ -0,0 +1,27 @@ + diff --git a/packages/icons/src/index.ts b/packages/icons/src/index.ts new file mode 100644 index 0000000..f69f28e --- /dev/null +++ b/packages/icons/src/index.ts @@ -0,0 +1,3 @@ +export * from './iconify'; +export { default as EmptyIcon } from './icons/empty-icon.vue'; +export * from './svg'; diff --git a/packages/icons/src/svg/icons/ai/gpt.svg b/packages/icons/src/svg/icons/ai/gpt.svg new file mode 100644 index 0000000..2625ec0 --- /dev/null +++ b/packages/icons/src/svg/icons/ai/gpt.svg @@ -0,0 +1 @@ + diff --git a/packages/icons/src/svg/icons/antdv-logo.svg b/packages/icons/src/svg/icons/antdv-logo.svg new file mode 100644 index 0000000..dbfcee7 --- /dev/null +++ b/packages/icons/src/svg/icons/antdv-logo.svg @@ -0,0 +1,29 @@ + + + + Vue + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/antdv-next-logo.svg b/packages/icons/src/svg/icons/antdv-next-logo.svg new file mode 100644 index 0000000..b335be1 --- /dev/null +++ b/packages/icons/src/svg/icons/antdv-next-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/avatar-1.svg b/packages/icons/src/svg/icons/avatar-1.svg new file mode 100644 index 0000000..b05970d --- /dev/null +++ b/packages/icons/src/svg/icons/avatar-1.svg @@ -0,0 +1 @@ +Asset 15 diff --git a/packages/icons/src/svg/icons/avatar-2.svg b/packages/icons/src/svg/icons/avatar-2.svg new file mode 100644 index 0000000..8e17b0b --- /dev/null +++ b/packages/icons/src/svg/icons/avatar-2.svg @@ -0,0 +1 @@ +Asset 16 diff --git a/packages/icons/src/svg/icons/avatar-3.svg b/packages/icons/src/svg/icons/avatar-3.svg new file mode 100644 index 0000000..ca79178 --- /dev/null +++ b/packages/icons/src/svg/icons/avatar-3.svg @@ -0,0 +1 @@ +Asset 17 diff --git a/packages/icons/src/svg/icons/avatar-4.svg b/packages/icons/src/svg/icons/avatar-4.svg new file mode 100644 index 0000000..d9138df --- /dev/null +++ b/packages/icons/src/svg/icons/avatar-4.svg @@ -0,0 +1 @@ +Asset 120 diff --git a/packages/icons/src/svg/icons/bell.svg b/packages/icons/src/svg/icons/bell.svg new file mode 100644 index 0000000..90c34e1 --- /dev/null +++ b/packages/icons/src/svg/icons/bell.svg @@ -0,0 +1 @@ +Asset 510 diff --git a/packages/icons/src/svg/icons/bpm/bpm-approve.svg b/packages/icons/src/svg/icons/bpm/bpm-approve.svg new file mode 100644 index 0000000..06aa09d --- /dev/null +++ b/packages/icons/src/svg/icons/bpm/bpm-approve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/bpm/bpm-cancel.svg b/packages/icons/src/svg/icons/bpm/bpm-cancel.svg new file mode 100644 index 0000000..ab9b155 --- /dev/null +++ b/packages/icons/src/svg/icons/bpm/bpm-cancel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/bpm/bpm-reject.svg b/packages/icons/src/svg/icons/bpm/bpm-reject.svg new file mode 100644 index 0000000..21fd5f6 --- /dev/null +++ b/packages/icons/src/svg/icons/bpm/bpm-reject.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/bpm/bpm-running.svg b/packages/icons/src/svg/icons/bpm/bpm-running.svg new file mode 100644 index 0000000..5908c13 --- /dev/null +++ b/packages/icons/src/svg/icons/bpm/bpm-running.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/cake.svg b/packages/icons/src/svg/icons/cake.svg new file mode 100644 index 0000000..43901fb --- /dev/null +++ b/packages/icons/src/svg/icons/cake.svg @@ -0,0 +1 @@ +Asset 480% diff --git a/packages/icons/src/svg/icons/card.svg b/packages/icons/src/svg/icons/card.svg new file mode 100644 index 0000000..40ff3e3 --- /dev/null +++ b/packages/icons/src/svg/icons/card.svg @@ -0,0 +1 @@ + diff --git a/packages/icons/src/svg/icons/dingding.svg b/packages/icons/src/svg/icons/dingding.svg new file mode 100644 index 0000000..c2fc786 --- /dev/null +++ b/packages/icons/src/svg/icons/dingding.svg @@ -0,0 +1 @@ + diff --git a/packages/icons/src/svg/icons/download.svg b/packages/icons/src/svg/icons/download.svg new file mode 100644 index 0000000..af9ff15 --- /dev/null +++ b/packages/icons/src/svg/icons/download.svg @@ -0,0 +1 @@ + diff --git a/packages/icons/src/svg/icons/github.svg b/packages/icons/src/svg/icons/github.svg new file mode 100644 index 0000000..39d092d --- /dev/null +++ b/packages/icons/src/svg/icons/github.svg @@ -0,0 +1 @@ + diff --git a/packages/icons/src/svg/icons/google.svg b/packages/icons/src/svg/icons/google.svg new file mode 100644 index 0000000..f2ad0a4 --- /dev/null +++ b/packages/icons/src/svg/icons/google.svg @@ -0,0 +1 @@ + diff --git a/packages/icons/src/svg/icons/pay/alipay-app.svg b/packages/icons/src/svg/icons/pay/alipay-app.svg new file mode 100644 index 0000000..ebf1188 --- /dev/null +++ b/packages/icons/src/svg/icons/pay/alipay-app.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/pay/alipay-bar.svg b/packages/icons/src/svg/icons/pay/alipay-bar.svg new file mode 100644 index 0000000..eb1e1e8 --- /dev/null +++ b/packages/icons/src/svg/icons/pay/alipay-bar.svg @@ -0,0 +1,2 @@ + diff --git a/packages/icons/src/svg/icons/pay/alipay-pc.svg b/packages/icons/src/svg/icons/pay/alipay-pc.svg new file mode 100644 index 0000000..2a75277 --- /dev/null +++ b/packages/icons/src/svg/icons/pay/alipay-pc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/pay/alipay-qr.svg b/packages/icons/src/svg/icons/pay/alipay-qr.svg new file mode 100644 index 0000000..4833750 --- /dev/null +++ b/packages/icons/src/svg/icons/pay/alipay-qr.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/pay/alipay-wap.svg b/packages/icons/src/svg/icons/pay/alipay-wap.svg new file mode 100644 index 0000000..87075db --- /dev/null +++ b/packages/icons/src/svg/icons/pay/alipay-wap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/pay/mock.svg b/packages/icons/src/svg/icons/pay/mock.svg new file mode 100644 index 0000000..e0a6857 --- /dev/null +++ b/packages/icons/src/svg/icons/pay/mock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/pay/wallet.svg b/packages/icons/src/svg/icons/pay/wallet.svg new file mode 100644 index 0000000..27b09ea --- /dev/null +++ b/packages/icons/src/svg/icons/pay/wallet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/pay/wx-app.svg b/packages/icons/src/svg/icons/pay/wx-app.svg new file mode 100644 index 0000000..ad40b2a --- /dev/null +++ b/packages/icons/src/svg/icons/pay/wx-app.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/pay/wx-bar.svg b/packages/icons/src/svg/icons/pay/wx-bar.svg new file mode 100644 index 0000000..11292e6 --- /dev/null +++ b/packages/icons/src/svg/icons/pay/wx-bar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/pay/wx-lite.svg b/packages/icons/src/svg/icons/pay/wx-lite.svg new file mode 100644 index 0000000..0c925cf --- /dev/null +++ b/packages/icons/src/svg/icons/pay/wx-lite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/pay/wx-native.svg b/packages/icons/src/svg/icons/pay/wx-native.svg new file mode 100644 index 0000000..bf3ba2b --- /dev/null +++ b/packages/icons/src/svg/icons/pay/wx-native.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/pay/wx-pub.svg b/packages/icons/src/svg/icons/pay/wx-pub.svg new file mode 100644 index 0000000..3a6d15b --- /dev/null +++ b/packages/icons/src/svg/icons/pay/wx-pub.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/packages/icons/src/svg/icons/qqchat.svg b/packages/icons/src/svg/icons/qqchat.svg new file mode 100644 index 0000000..ac9a7f0 --- /dev/null +++ b/packages/icons/src/svg/icons/qqchat.svg @@ -0,0 +1 @@ + diff --git a/packages/icons/src/svg/icons/tdesign-logo.svg b/packages/icons/src/svg/icons/tdesign-logo.svg new file mode 100644 index 0000000..bdbba5c --- /dev/null +++ b/packages/icons/src/svg/icons/tdesign-logo.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/icons/src/svg/icons/wechat.svg b/packages/icons/src/svg/icons/wechat.svg new file mode 100644 index 0000000..346b037 --- /dev/null +++ b/packages/icons/src/svg/icons/wechat.svg @@ -0,0 +1 @@ + diff --git a/packages/icons/src/svg/index.ts b/packages/icons/src/svg/index.ts new file mode 100644 index 0000000..01d16ac --- /dev/null +++ b/packages/icons/src/svg/index.ts @@ -0,0 +1,79 @@ +import { createIconifyIcon } from '@vben-core/icons'; + +import './load.js'; + +const SvgAvatar1Icon = createIconifyIcon('svg:avatar-1'); +const SvgAvatar2Icon = createIconifyIcon('svg:avatar-2'); +const SvgAvatar3Icon = createIconifyIcon('svg:avatar-3'); +const SvgAvatar4Icon = createIconifyIcon('svg:avatar-4'); +const SvgDownloadIcon = createIconifyIcon('svg:download'); +const SvgCardIcon = createIconifyIcon('svg:card'); +const SvgBellIcon = createIconifyIcon('svg:bell'); +const SvgCakeIcon = createIconifyIcon('svg:cake'); +const SvgAntdvLogoIcon = createIconifyIcon('svg:antdv-logo'); +const SvgGithubIcon = createIconifyIcon('svg:github'); +const SvgGoogleIcon = createIconifyIcon('svg:google'); +const SvgQQChatIcon = createIconifyIcon('svg:qqchat'); +const SvgWeChatIcon = createIconifyIcon('svg:wechat'); +const SvgDingDingIcon = createIconifyIcon('svg:dingding'); +const SvgTDesignIcon = createIconifyIcon('svg:tdesign-logo'); +const SvgAntdvNextLogoIcon = createIconifyIcon('svg:antdv-next-logo'); + +/** AI */ +const SvgGptIcon = createIconifyIcon('svg:gpt'); + +/** 支付 */ +const SvgAlipayPcIcon = createIconifyIcon('svg:alipay-pc'); +const SvgAlipayWapIcon = createIconifyIcon('svg:alipay-wap'); +const SvgAlipayAppIcon = createIconifyIcon('svg:alipay-app'); +const SvgAlipayQrIcon = createIconifyIcon('svg:alipay-qr'); +const SvgAlipayBarIcon = createIconifyIcon('svg:alipay-bar'); +const SvgWxPubIcon = createIconifyIcon('svg:wx-pub'); +const SvgWxLiteIcon = createIconifyIcon('svg:wx-lite'); +const SvgWxAppIcon = createIconifyIcon('svg:wx-app'); +const SvgWxNativeIcon = createIconifyIcon('svg:wx-native'); +const SvgWxBarIcon = createIconifyIcon('svg:wx-bar'); +const SvgWalletIcon = createIconifyIcon('svg:wallet'); +const SvgMockIcon = createIconifyIcon('svg:mock'); + +/** BPM */ +const SvgBpmRunningIcon = createIconifyIcon('svg:bpm-running'); +const SvgBpmApproveIcon = createIconifyIcon('svg:bpm-approve'); +const SvgBpmRejectIcon = createIconifyIcon('svg:bpm-reject'); +const SvgBpmCancelIcon = createIconifyIcon('svg:bpm-cancel'); + +export { + SvgAlipayAppIcon, + SvgAlipayBarIcon, + SvgAlipayPcIcon, + SvgAlipayQrIcon, + SvgAlipayWapIcon, + SvgAntdvLogoIcon, + SvgAntdvNextLogoIcon, + SvgAvatar1Icon, + SvgAvatar2Icon, + SvgAvatar3Icon, + SvgAvatar4Icon, + SvgBellIcon, + SvgBpmApproveIcon, + SvgBpmCancelIcon, + SvgBpmRejectIcon, + SvgBpmRunningIcon, + SvgCakeIcon, + SvgCardIcon, + SvgDingDingIcon, + SvgDownloadIcon, + SvgGithubIcon, + SvgGoogleIcon, + SvgGptIcon, + SvgMockIcon, + SvgQQChatIcon, + SvgTDesignIcon, + SvgWalletIcon, + SvgWeChatIcon, + SvgWxAppIcon, + SvgWxBarIcon, + SvgWxLiteIcon, + SvgWxNativeIcon, + SvgWxPubIcon, +}; diff --git a/packages/icons/src/svg/load.ts b/packages/icons/src/svg/load.ts new file mode 100644 index 0000000..59098bd --- /dev/null +++ b/packages/icons/src/svg/load.ts @@ -0,0 +1,79 @@ +import type { IconifyIconStructure } from '@vben-core/icons'; + +import { addIcon } from '@vben-core/icons'; + +let loaded = false; +if (!loaded) { + loadSvgIcons(); + loaded = true; +} + +function parseSvg(svgData: string): IconifyIconStructure { + const parser = new DOMParser(); + const xmlDoc = parser.parseFromString(svgData, 'image/svg+xml'); + const svgElement = xmlDoc.documentElement; + + // 提取 SVG 根元素的关键样式属性 + const getAttrs = (el: Element, attrs: string[]) => + attrs + .map((attr) => + el.hasAttribute(attr) ? `${attr}="${el.getAttribute(attr)}"` : '', + ) + .filter(Boolean) + .join(' '); + + const rootAttrs = getAttrs(svgElement, [ + 'fill', + 'stroke', + 'fill-rule', + 'stroke-width', + ]); + + const svgContent = [...svgElement.childNodes] + .filter((node) => node.nodeType === Node.ELEMENT_NODE) + .map((node) => new XMLSerializer().serializeToString(node)) + .join(''); + // 若根有属性,用一个 g 标签包裹内容并继承属性 + const body = rootAttrs ? `${svgContent}` : svgContent; + + const viewBoxValue = svgElement.getAttribute('viewBox') || ''; + const [left, top, width, height] = viewBoxValue.split(' ').map((val) => { + const num = Number(val); + return Number.isNaN(num) ? undefined : num; + }); + + return { + body, + height, + left, + top, + width, + }; +} + +/** + * 自定义的svg图片转化为组件 + * @example ./svg/avatar.svg + * + */ +async function loadSvgIcons() { + const svgEagers = import.meta.glob('./icons/**', { + eager: true, + query: '?raw', + }); + + await Promise.all( + Object.entries(svgEagers).map((svg) => { + const [key, body] = svg as [string, string | { default: string }]; + + // ./icons/xxxx.svg => xxxxxx + const start = key.lastIndexOf('/') + 1; + const end = key.lastIndexOf('.'); + const iconName = key.slice(start, end); + + return addIcon(`svg:${iconName}`, { + ...parseSvg(typeof body === 'object' ? body.default : body), + }); + }), + ); +} diff --git a/packages/icons/tsconfig.json b/packages/icons/tsconfig.json new file mode 100644 index 0000000..ce1a891 --- /dev/null +++ b/packages/icons/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/locales/package.json b/packages/locales/package.json new file mode 100644 index 0000000..ce75b3c --- /dev/null +++ b/packages/locales/package.json @@ -0,0 +1,28 @@ +{ + "name": "@vben/locales", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/locales" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "dependencies": { + "@intlify/core-base": "catalog:", + "@vben-core/composables": "workspace:*", + "vue": "catalog:", + "vue-i18n": "catalog:" + } +} diff --git a/packages/locales/src/i18n.ts b/packages/locales/src/i18n.ts new file mode 100644 index 0000000..6378f2c --- /dev/null +++ b/packages/locales/src/i18n.ts @@ -0,0 +1,147 @@ +import type { App } from 'vue'; +import type { Locale } from 'vue-i18n'; + +import type { + ImportLocaleFn, + LoadMessageFn, + LocaleSetupOptions, + SupportedLanguagesType, +} from './typing'; + +import { unref } from 'vue'; +import { createI18n } from 'vue-i18n'; + +import { useSimpleLocale } from '@vben-core/composables'; + +const i18n = createI18n({ + globalInjection: true, + legacy: false, + locale: '', + messages: {}, +}); + +const modules = import.meta.glob('./langs/**/*.json'); + +const { setSimpleLocale } = useSimpleLocale(); + +const localesMap = loadLocalesMapFromDir( + /\.\/langs\/([^/]+)\/(.*)\.json$/, + modules, +); +let loadMessages: LoadMessageFn; + +/** + * Load locale modules + * @param modules + */ +function loadLocalesMap(modules: Record Promise>) { + const localesMap: Record = {}; + + for (const [path, loadLocale] of Object.entries(modules)) { + const key = path.match(/([\w-]*)\.(json)/)?.[1]; + if (key) { + localesMap[key] = loadLocale as ImportLocaleFn; + } + } + return localesMap; +} + +/** + * Load locale modules with directory structure + * @param regexp - Regular expression to match language and file names + * @param modules - The modules object containing paths and import functions + * @returns A map of locales to their corresponding import functions + */ +function loadLocalesMapFromDir( + regexp: RegExp, + modules: Record Promise>, +): Record { + const localesRaw: Record Promise>> = {}; + const localesMap: Record = {}; + + // Iterate over the modules to extract language and file names + for (const path in modules) { + const match = path.match(regexp); + if (match) { + const [_, locale, fileName] = match; + if (locale && fileName) { + if (!localesRaw[locale]) { + localesRaw[locale] = {}; + } + if (modules[path]) { + localesRaw[locale][fileName] = modules[path]; + } + } + } + } + + // Convert raw locale data into async import functions + for (const [locale, files] of Object.entries(localesRaw)) { + localesMap[locale] = async () => { + const messages: Record = {}; + for (const [fileName, importFn] of Object.entries(files)) { + messages[fileName] = ((await importFn()) as any)?.default; + } + return { default: messages }; + }; + } + + return localesMap; +} + +/** + * Set i18n language + * @param locale + */ +function setI18nLanguage(locale: Locale) { + i18n.global.locale.value = locale; + + document?.querySelector('html')?.setAttribute('lang', locale); +} + +async function setupI18n(app: App, options: LocaleSetupOptions = {}) { + const { defaultLocale = 'zh-CN' } = options; + // app可以自行扩展一些第三方库和组件库的国际化 + loadMessages = options.loadMessages || (async () => ({})); + app.use(i18n); + await loadLocaleMessages(defaultLocale); + + // 在控制台打印警告 + i18n.global.setMissingHandler((locale, key) => { + if (options.missingWarn && key !== 'OAuth 2.0' && key.includes('.')) { + console.warn( + `[intlify] Not found '${key}' key in '${locale}' locale messages.`, + ); + } + }); +} + +/** + * Load locale messages + * @param lang + */ +async function loadLocaleMessages(lang: SupportedLanguagesType) { + if (unref(i18n.global.locale) === lang) { + return setI18nLanguage(lang); + } + setSimpleLocale(lang); + + const message = await localesMap[lang]?.(); + + if (message?.default) { + i18n.global.setLocaleMessage(lang, message.default); + } + + const mergeMessage = await loadMessages(lang); + i18n.global.mergeLocaleMessage(lang, mergeMessage); + + return setI18nLanguage(lang); +} + +export { + i18n, + loadLocaleMessages, + loadLocalesMap, + loadLocalesMapFromDir, + setupI18n, +}; diff --git a/packages/locales/src/index.ts b/packages/locales/src/index.ts new file mode 100644 index 0000000..d4bfd81 --- /dev/null +++ b/packages/locales/src/index.ts @@ -0,0 +1,30 @@ +import { + i18n, + loadLocaleMessages, + loadLocalesMap, + loadLocalesMapFromDir, + setupI18n, +} from './i18n'; + +const $t = i18n.global.t; +const $te = i18n.global.te; + +export { + $t, + $te, + i18n, + loadLocaleMessages, + loadLocalesMap, + loadLocalesMapFromDir, + setupI18n, +}; +export { + type ImportLocaleFn, + type LocaleSetupOptions, + type SupportedLanguagesType, +} from './typing'; +export type { CompileError } from '@intlify/core-base'; + +export { useI18n } from 'vue-i18n'; + +export type { Locale } from 'vue-i18n'; diff --git a/packages/locales/src/langs/en-US/authentication.json b/packages/locales/src/langs/en-US/authentication.json new file mode 100644 index 0000000..d1fd9b7 --- /dev/null +++ b/packages/locales/src/langs/en-US/authentication.json @@ -0,0 +1,70 @@ +{ + "welcomeBack": "Welcome Back", + "pageTitle": "Plug-and-play Admin system", + "pageDesc": "Efficient, versatile frontend template", + "loginSuccess": "Login Successful", + "loginSuccessDesc": "Welcome Back", + "loginSubtitle": "Enter your account details to manage your projects", + "selectAccount": "Quick Select Account", + "username": "Username", + "password": "Password", + "nickname": "Nickname", + "tenant": "Tenant", + "usernameTip": "Please enter username", + "passwordErrorTip": "Password is incorrect", + "passwordTip": "Please enter password", + "nicknameTip": "Please enter nickname", + "tenantTip": "Please select tenant", + "verifyRequiredTip": "Please complete the verification first", + "rememberMe": "Remember Me", + "createAnAccount": "Create an Account", + "createAccount": "Create Account", + "alreadyHaveAccount": "Already have an account?", + "accountTip": "Don't have an account?", + "signUp": "Sign Up", + "signUpSubtitle": "Make managing your applications simple and fun", + "confirmPassword": "Confirm Password", + "confirmPasswordTip": "The passwords do not match", + "agree": "I agree to", + "privacyPolicy": "Privacy-policy", + "terms": "Terms", + "agreeTip": "Please agree to the Privacy Policy and Terms", + "goToLogin": "Login instead", + "passwordStrength": "Use 8 or more characters with a mix of letters, numbers & symbols", + "forgetPassword": "Forget Password?", + "forgetPasswordSubtitle": "Enter your email and we'll send you instructions to reset your password", + "resetPasswordSuccess": "Reset password success", + "emailTip": "Please enter email", + "emailValidErrorTip": "The email format you entered is incorrect", + "resetPassword": "Reset Password", + "email": "Email", + "qrcodeSubtitle": "Scan the QR code with your phone to login", + "qrcodePrompt": "Click 'Confirm' after scanning to complete login", + "qrcodeLogin": "QR Code Login", + "wechatLogin": "Wechat Login", + "qqLogin": "QQ Login", + "githubLogin": "Github Login", + "googleLogin": "Google Login", + "dingdingLogin": "Dingding Login", + "codeSubtitle": "Enter your phone number to start managing your project", + "code": "Security code", + "codeTip": "Security code required {0} characters", + "mobile": "Mobile", + "mobileLogin": "Mobile Login", + "mobileTip": "Please enter mobile number", + "mobileErrortip": "The phone number format is incorrect", + "sendCode": "Get Security code", + "sendText": "Resend in {0}s", + "thirdPartyLogin": "Or continue with", + "weChat": "WeChat", + "qq": "QQ", + "gitHub": "GitHub", + "google": "Google", + "loginAgainTitle": "Please Log In Again", + "loginAgainSubTitle": "Your login session has expired. Please log in again to continue.", + "layout": { + "center": "Align Center", + "alignLeft": "Align Left", + "alignRight": "Align Right" + } +} diff --git a/packages/locales/src/langs/en-US/common.json b/packages/locales/src/langs/en-US/common.json new file mode 100644 index 0000000..0d289b3 --- /dev/null +++ b/packages/locales/src/langs/en-US/common.json @@ -0,0 +1,26 @@ +{ + "back": "Back", + "backToHome": "Back To Home", + "login": "Login", + "logout": "Logout", + "prompt": "Prompt", + "cancel": "Cancel", + "confirm": "Confirm", + "reset": "Reset", + "noData": "No Data", + "refresh": "Refresh", + "loadingMenu": "Loading Menu", + "query": "Search", + "search": "Search", + "enabled": "Enabled", + "disabled": "Disabled", + "edit": "Edit", + "delete": "Delete", + "deleteBatch": "Delete Batch", + "create": "Create", + "detail": "Detail", + "yes": "Yes", + "no": "No", + "showSearchPanel": "Show search panel", + "hideSearchPanel": "Hide search panel" +} diff --git a/packages/locales/src/langs/en-US/preferences.json b/packages/locales/src/langs/en-US/preferences.json new file mode 100644 index 0000000..f32d0b6 --- /dev/null +++ b/packages/locales/src/langs/en-US/preferences.json @@ -0,0 +1,196 @@ +{ + "title": "Preferences", + "subtitle": "Customize Preferences & Preview in Real Time", + "enableStickyPreferencesNavigationBar": "Enable sticky preferences navigation bar", + "disableStickyPreferencesNavigationBar": "Disable sticky preferences navigation bar", + "resetTip": "Data has changed, click to reset", + "resetTitle": "Reset Preferences", + "resetSuccess": "Preferences reset successfully", + "appearance": "Appearance", + "layout": "Layout", + "content": "Content", + "other": "Other", + "wide": "Wide", + "compact": "Fixed", + "followSystem": "Follow System", + "vertical": "Vertical", + "verticalTip": "Side vertical menu mode", + "horizontal": "Horizontal", + "horizontalTip": "Horizontal menu mode, all menus displayed at the top", + "twoColumn": "Two Column", + "twoColumnTip": "Vertical Two Column Menu Mode", + "headerSidebarNav": "Header Vertical", + "headerSidebarNavTip": "Header Full Width, Sidebar Navigation Mode", + "headerTwoColumn": "Header Two Column", + "headerTwoColumnTip": "Header Navigation & Sidebar Two Column co-exists", + "mixedMenu": "Mixed Menu", + "mixedMenuTip": "Vertical & Horizontal Menu Co-exists", + "fullContent": "Full Content", + "fullContentTip": "Only display content body, hide all menus", + "normal": "Normal", + "plain": "Plain", + "rounded": "Rounded", + "copyPreferences": "Copy Preferences", + "copyPreferencesSuccessTitle": "Copy successful", + "copyPreferencesSuccess": "Copy successful, please override in `src/preferences.ts` under app", + "clearAndLogout": "Clear Cache & Logout", + "mode": "Mode", + "general": "General", + "language": "Language", + "dynamicTitle": "Dynamic Title", + "watermark": "Watermark", + "watermarkContent": "Please input Watermark content", + "checkUpdates": "Periodic update check", + "position": { + "title": "Preferences Postion", + "header": "Header", + "auto": "Auto", + "fixed": "Fixed" + }, + "sidebar": { + "buttons": "Show Buttons", + "buttonFixed": "Fixed", + "buttonCollapsed": "Collapsed", + "title": "Sidebar", + "width": "Width", + "visible": "Show Sidebar", + "collapsed": "Collpase Menu", + "collapsedShowTitle": "Show Menu Title", + "autoActivateChild": "Auto Activate SubMenu", + "autoActivateChildTip": "`Enabled` to automatically activate the submenu while click menu.", + "expandOnHover": "Expand On Hover", + "expandOnHoverTip": "When the mouse hovers over menu, \n `Enabled` to expand children menus \n `Disabled` to expand whole sidebar." + }, + "tabbar": { + "title": "Tabbar", + "enable": "Enable Tab Bar", + "icon": "Show Tabbar Icon", + "showMore": "Show More Button", + "showMaximize": "Show Maximize Button", + "persist": "Persist Tabs", + "visitHistory": "Visit History", + "visitHistoryTip": "When enabled, the tab bar records tab visit history. \nClosing the current tab will automatically select the last opened tab.", + "maxCount": "Max Count of Tabs", + "maxCountTip": "When the number of tabs exceeds the maximum,\nthe oldest tab will be closed.\n Set to 0 to disable count checking.", + "draggable": "Enable Draggable Sort", + "wheelable": "Support Mouse Wheel", + "middleClickClose": "Close Tab when Mouse Middle Button Click", + "wheelableTip": "When enabled, the Tabbar area responds to vertical scrolling events of the scroll wheel.", + "styleType": { + "title": "Tabs Style", + "chrome": "Chrome", + "card": "Card", + "plain": "Plain", + "brisk": "Brisk" + }, + "contextMenu": { + "reload": "Reload", + "close": "Close", + "pin": "Pin", + "unpin": "Unpin", + "closeLeft": "Close Left Tabs", + "closeRight": "Close Right Tabs", + "closeOther": "Close Other Tabs", + "closeAll": "Close All Tabs", + "openInNewWindow": "Open in New Window", + "maximize": "Maximize", + "restoreMaximize": "Restore" + } + }, + "navigationMenu": { + "title": "Navigation Menu", + "style": "Navigation Menu Style", + "accordion": "Sidebar Accordion Menu", + "split": "Navigation Menu Separation", + "splitTip": "When enabled, the sidebar displays the top bar's submenu" + }, + "breadcrumb": { + "title": "Breadcrumb", + "home": "Show Home Button", + "enable": "Enable Breadcrumb", + "icon": "Show Breadcrumb Icon", + "background": "background", + "style": "Breadcrumb Style", + "hideOnlyOne": "Hidden when only one" + }, + "animation": { + "title": "Animation", + "loading": "Page Loading", + "transition": "Page Transition", + "progress": "Page Progress" + }, + "theme": { + "title": "Theme", + "radius": "Radius", + "fontSize": "Font Size", + "fontSizeTip": "Adjust global font size with real-time preview", + "light": "Light", + "dark": "Dark", + "darkSidebar": "Semi Dark Sidebar", + "darkHeader": "Semi Dark Header", + "weakMode": "Weak Mode", + "grayMode": "Gray Mode", + "builtin": { + "title": "Built-in", + "default": "Default", + "violet": "Violet", + "pink": "Pink", + "rose": "Rose", + "skyBlue": "Sky Blue", + "deepBlue": "Deep Blue", + "green": "Green", + "deepGreen": "Deep Green", + "orange": "Orange", + "yellow": "Yellow", + "zinc": "Zinc", + "neutral": "Neutral", + "slate": "Slate", + "gray": "Gray", + "custom": "Custom" + } + }, + "header": { + "title": "Header", + "visible": "Show Header", + "modeStatic": "Static", + "modeFixed": "Fixed", + "modeAuto": "Auto hide & Show", + "modeAutoScroll": "Scroll to Hide & Show", + "menuAlign": "Menu Align", + "menuAlignStart": "Start", + "menuAlignEnd": "End", + "menuAlignCenter": "Center" + }, + "footer": { + "title": "Footer", + "visible": "Show Footer", + "fixed": "Fixed at Bottom" + }, + "copyright": { + "title": "Copyright", + "enable": "Enable Copyright", + "companyName": "Company Name", + "companySiteLink": "Company Site Link", + "date": "Date", + "icp": "ICP License Number", + "icpLink": "ICP Site Link" + }, + "shortcutKeys": { + "title": "Shortcut Keys", + "global": "Global", + "search": "Global Search", + "logout": "Logout", + "preferences": "Preferences" + }, + "widget": { + "title": "Widget", + "globalSearch": "Enable Global Search", + "fullscreen": "Enable Fullscreen", + "themeToggle": "Enable Theme Toggle", + "languageToggle": "Enable Language Toggle", + "notification": "Enable Notification", + "sidebarToggle": "Enable Sidebar Toggle", + "lockScreen": "Enable Lock Screen", + "refresh": "Enable Refresh" + } +} diff --git a/packages/locales/src/langs/en-US/profile.json b/packages/locales/src/langs/en-US/profile.json new file mode 100644 index 0000000..1c17e2e --- /dev/null +++ b/packages/locales/src/langs/en-US/profile.json @@ -0,0 +1,4 @@ +{ + "updatePassword": "Update Password", + "updateBasicProfile": "Update Basic Profile" +} diff --git a/packages/locales/src/langs/en-US/ui.json b/packages/locales/src/langs/en-US/ui.json new file mode 100644 index 0000000..58ccce2 --- /dev/null +++ b/packages/locales/src/langs/en-US/ui.json @@ -0,0 +1,167 @@ +{ + "formRules": { + "required": "Please enter {0}", + "selectRequired": "Please select {0}", + "minLength": "{0} must be at least {1} characters", + "maxLength": "{0} can be at most {1} characters", + "length": "{0} must be {1} characters long", + "alreadyExists": "{0} `{1}` already exists", + "startWith": "{0} must start with `{1}`", + "invalidURL": "Please input a valid URL", + "mobile": "Please input a valid {0}", + "sizeLimit": "The file size cannot exceed {0}MB", + "previewWarning": "Unable to open the file, there is no available URL or preview address" + }, + "actionTitle": { + "copy": "Copy {0}", + "cancel": "Cancel {0}", + "edit": "Modify {0}", + "create": "Create {0}", + "delete": "Delete {0}", + "deleteBatch": "Delete Batch", + "detail": "Detail {0}", + "view": "View {0}", + "import": "Import", + "export": "Export" + }, + "actionMessage": { + "deleteConfirm": "Are you sure to delete {0}?", + "deleteBatchConfirm": "Are you sure to delete selected items?", + "deleting": "Deleting {0} ...", + "deletingBatch": "Deleting selected ...", + "deleteSuccess": "{0} deleted successfully", + "deleteFailed": "{0} deleted failed", + "operationSuccess": "Operation succeeded", + "operationFailed": "Operation failed", + "importSuccess": "Import succeeded", + "importFail": "Import failed", + "downloadTemplateFail": "Download template failed", + "updating": "Updating {0}...", + "updateSuccess": "Update {0} successfully", + "updateFailed": "Update {0} failed", + "closing": "Closing {0} ...", + "closeSuccess": "{0} closed successfully" + }, + "placeholder": { + "input": "Please enter", + "select": "Please select", + "upload": "Click to upload" + }, + "captcha": { + "title": "Please complete the security verification", + "sliderSuccessText": "Passed", + "sliderDefaultText": "Slider and drag", + "alt": "Supports img tag src attribute value", + "sliderRotateDefaultTip": "Click picture to refresh", + "sliderTranslateDefaultTip": "Click picture to refresh", + "sliderRotateFailTip": "Validation failed", + "sliderRotateSuccessTip": "Validation successful, time {0} seconds", + "sliderTranslateFailTip": "Validation failed", + "sliderTranslateSuccessTip": "Validation successful, time {0} seconds", + "refreshAriaLabel": "Refresh captcha", + "confirmAriaLabel": "Confirm selection", + "confirm": "Confirm", + "pointAriaLabel": "Click point", + "clickInOrder": "Please click in order" + }, + "iconPicker": { + "placeholder": "Select an icon", + "search": "Search icon..." + }, + "jsonViewer": { + "copy": "Copy", + "copied": "Copied" + }, + "crop": { + "title": "Image Cropping", + "titleTip": "Cropping Ratio {0}", + "confirm": "Crop", + "cancel": "Cancel cropping", + "errorTip": "Cropping error" + }, + "fallback": { + "pageNotFound": "Oops! Page Not Found", + "pageNotFoundDesc": "Sorry, we couldn't find the page you were looking for.", + "forbidden": "Oops! Access Denied", + "forbiddenDesc": "Sorry, but you don't have permission to access this page.", + "internalError": "Oops! Something Went Wrong", + "internalErrorDesc": "Sorry, but the server encountered an error.", + "offline": "Offline Page", + "offlineError": "Oops! Network Error", + "offlineErrorDesc": "Sorry, can't connect to the internet. Check your connection.", + "comingSoon": "Coming Soon", + "http": { + "requestTimeout": "The request timed out. Please try again later.", + "networkError": "A network error occurred. Please check your internet connection and try again.", + "badRequest": "Bad Request. Please check your input and try again.", + "unauthorized": "Unauthorized. Please log in to continue.", + "forbidden": "Forbidden. You do not have permission to access this resource.", + "notFound": "Not Found. The requested resource could not be found.", + "internalServerError": "Internal Server Error. Something went wrong on our end. Please try again later." + } + }, + "widgets": { + "document": "Document", + "profile": "Profile", + "qa": "Q&A", + "setting": "Settings", + "logoutTip": "Do you want to logout?", + "viewAll": "View All Messages", + "notifications": "Notifications", + "markAllAsRead": "Make All as Read", + "clearNotifications": "Clear", + "checkUpdatesTitle": "New Version Available", + "checkUpdatesDescription": "Click to refresh and get the latest version", + "search": { + "title": "Search", + "searchNavigate": "Search Navigation", + "select": "Select", + "navigate": "Navigate", + "close": "Close", + "noResults": "No Search Results Found", + "noRecent": "No Search History", + "recent": "Search History" + }, + "lockScreen": { + "title": "Lock Screen", + "screenButton": "Locking", + "password": "Password", + "placeholder": "Please enter password", + "unlock": "Click to unlock", + "errorPasswordTip": "Password error, please re-enter", + "backToLogin": "Back to login", + "entry": "Enter the system" + }, + "timezone": { + "setTimezone": "Set Timezone", + "setSuccess": "Timezone set successfully" + } + }, + "upload": { + "upload": "Upload", + "imgUpload": "ImageUpload", + "accept": "Support {0} format", + "acceptUpload": "Only upload files in {0} format", + "maxSize": "A single file does not exceed {0}MB", + "maxSizeMultiple": "Only upload files up to {0}MB!", + "maxNumber": "Only upload up to {0} files", + "uploadSuccess": "Upload successfully", + "uploadError": "Upload failed", + "imgUploading": "Image sending, please wait..." + }, + "cropper": { + "selectImage": "Select Image", + "uploadSuccess": "Uploaded success!", + "imageTooBig": "Image too big", + "modalTitle": "Avatar upload", + "okText": "Confirm and upload", + "btn_reset": "Reset", + "btn_rotate_left": "Counterclockwise rotation", + "btn_rotate_right": "Clockwise rotation", + "btn_scale_x": "Flip horizontal", + "btn_scale_y": "Flip vertical", + "btn_zoom_in": "Zoom in", + "btn_zoom_out": "Zoom out", + "preview": "Preview" + } +} diff --git a/packages/locales/src/langs/zh-CN/authentication.json b/packages/locales/src/langs/zh-CN/authentication.json new file mode 100644 index 0000000..1eb61ae --- /dev/null +++ b/packages/locales/src/langs/zh-CN/authentication.json @@ -0,0 +1,70 @@ +{ + "welcomeBack": "欢迎回来", + "pageTitle": "开箱即用的大型中后台管理系统", + "pageDesc": "工程化、高性能、跨组件库的前端模版", + "loginSuccess": "登录成功", + "loginSuccessDesc": "欢迎回来", + "loginSubtitle": "请输入您的帐户信息以开始管理您的项目", + "selectAccount": "快速选择账号", + "username": "账号", + "password": "密码", + "nickname": "昵称", + "tenant": "租户", + "usernameTip": "请输入用户名", + "passwordTip": "请输入密码", + "nicknameTip": "请输入昵称", + "tenantTip": "请选择租户", + "verifyRequiredTip": "请先完成验证", + "passwordErrorTip": "密码错误", + "rememberMe": "记住账号", + "createAnAccount": "创建一个账号", + "createAccount": "创建账号", + "alreadyHaveAccount": "已经有账号了?", + "accountTip": "还没有账号?", + "signUp": "注册", + "signUpSubtitle": "让您的应用程序管理变得简单而有趣", + "confirmPassword": "确认密码", + "confirmPasswordTip": "两次输入的密码不一致", + "agree": "我同意", + "privacyPolicy": "隐私政策", + "terms": "条款", + "agreeTip": "请同意隐私政策和条款", + "goToLogin": "去登录", + "passwordStrength": "使用 8 个或更多字符,混合字母、数字和符号", + "forgetPassword": "忘记密码?", + "forgetPasswordSubtitle": "输入您的电子邮件,我们将向您发送重置密码的连接", + "resetPasswordSuccess": "重置密码成功", + "emailTip": "请输入邮箱", + "emailValidErrorTip": "你输入的邮箱格式不正确", + "resetPassword": "重置密码", + "email": "邮箱", + "qrcodeSubtitle": "请用手机扫描二维码登录", + "qrcodePrompt": "扫码后点击 '确认',即可完成登录", + "qrcodeLogin": "扫码登录", + "wechatLogin": "微信登录", + "qqLogin": "QQ登录", + "githubLogin": "Github登录", + "googleLogin": "Google登录", + "dingdingLogin": "钉钉登录", + "codeSubtitle": "请输入您的手机号码以开始管理您的项目", + "code": "验证码", + "codeTip": "请输入{0}位验证码", + "mobile": "手机号码", + "mobileTip": "请输入手机号", + "mobileErrortip": "手机号码格式错误", + "mobileLogin": "手机号登录", + "sendCode": "获取验证码", + "sendText": "{0}秒后重新获取", + "thirdPartyLogin": "其他登录方式", + "weChat": "微信", + "qq": "QQ", + "gitHub": "GitHub", + "google": "Google", + "loginAgainTitle": "重新登录", + "loginAgainSubTitle": "您的登录状态已过期,请重新登录以继续。", + "layout": { + "center": "居中", + "alignLeft": "居左", + "alignRight": "居右" + } +} diff --git a/packages/locales/src/langs/zh-CN/common.json b/packages/locales/src/langs/zh-CN/common.json new file mode 100644 index 0000000..b90087f --- /dev/null +++ b/packages/locales/src/langs/zh-CN/common.json @@ -0,0 +1,26 @@ +{ + "back": "返回", + "backToHome": "返回首页", + "login": "登录", + "logout": "退出登录", + "prompt": "提示", + "cancel": "取消", + "confirm": "确认", + "reset": "重置", + "noData": "暂无数据", + "refresh": "刷新", + "loadingMenu": "加载菜单中", + "query": "查询", + "search": "搜索", + "enabled": "已启用", + "disabled": "已禁用", + "edit": "修改", + "delete": "删除", + "deleteBatch": "批量删除", + "create": "新增", + "detail": "详情", + "yes": "是", + "no": "否", + "showSearchPanel": "显示搜索面板", + "hideSearchPanel": "隐藏搜索面板" +} diff --git a/packages/locales/src/langs/zh-CN/preferences.json b/packages/locales/src/langs/zh-CN/preferences.json new file mode 100644 index 0000000..a36a9db --- /dev/null +++ b/packages/locales/src/langs/zh-CN/preferences.json @@ -0,0 +1,196 @@ +{ + "title": "偏好设置", + "subtitle": "自定义偏好设置 & 实时预览", + "enableStickyPreferencesNavigationBar": "开启首选项导航栏吸顶效果", + "disableStickyPreferencesNavigationBar": "关闭首选项导航栏吸顶效果", + "resetTitle": "重置偏好设置", + "resetTip": "数据有变化,点击可进行重置", + "resetSuccess": "重置偏好设置成功", + "appearance": "外观", + "layout": "布局", + "content": "内容", + "other": "其它", + "wide": "流式", + "compact": "定宽", + "followSystem": "跟随系统", + "vertical": "垂直", + "verticalTip": "侧边垂直菜单模式", + "horizontal": "水平", + "horizontalTip": "水平菜单模式,菜单全部显示在顶部", + "twoColumn": "双列菜单", + "twoColumnTip": "垂直双列菜单模式", + "headerSidebarNav": "侧边导航", + "headerSidebarNavTip": "顶部通栏,侧边导航模式", + "headerTwoColumn": "混合双列", + "headerTwoColumnTip": "双列、水平菜单共存模式", + "mixedMenu": "混合垂直", + "mixedMenuTip": "垂直水平菜单共存", + "fullContent": "内容全屏", + "fullContentTip": "不显示任何菜单,只显示内容主体", + "normal": "常规", + "plain": "朴素", + "rounded": "圆润", + "copyPreferences": "复制偏好设置", + "copyPreferencesSuccessTitle": "复制成功", + "copyPreferencesSuccess": "复制成功,请在 app 下的 `src/preferences.ts`内进行覆盖", + "clearAndLogout": "清空缓存 & 退出登录", + "mode": "模式", + "general": "通用", + "language": "语言", + "dynamicTitle": "动态标题", + "watermark": "水印", + "watermarkContent": "请输入水印文案", + "checkUpdates": "定时检查更新", + "position": { + "title": "偏好设置位置", + "header": "顶栏", + "auto": "自动", + "fixed": "固定" + }, + "sidebar": { + "buttons": "显示按钮", + "buttonFixed": "固定按钮", + "buttonCollapsed": "折叠按钮", + "title": "侧边栏", + "width": "宽度", + "visible": "显示侧边栏", + "collapsed": "折叠菜单", + "collapsedShowTitle": "折叠显示菜单名", + "autoActivateChild": "自动激活子菜单", + "autoActivateChildTip": "点击顶层菜单时,自动激活第一个子菜单或者上一次激活的子菜单", + "expandOnHover": "鼠标悬停展开", + "expandOnHoverTip": "鼠标在折叠区域悬浮时,`启用`则展开当前子菜单,`禁用`则展开整个侧边栏" + }, + "tabbar": { + "title": "标签栏", + "enable": "启用标签栏", + "icon": "显示标签栏图标", + "showMore": "显示更多按钮", + "showMaximize": "显示最大化按钮", + "persist": "持久化标签页", + "visitHistory": "访问历史记录", + "visitHistoryTip": "开启后,标签栏会记录标签访问历史\n关闭当前标签,会自动选中上一个打开的标签", + "maxCount": "最大标签数", + "maxCountTip": "每次打开新的标签时如果超过最大标签数,\n会自动关闭一个最先打开的标签\n设置为 0 则不限制", + "draggable": "启动拖拽排序", + "wheelable": "启用纵向滚轮响应", + "middleClickClose": "点击鼠标中键关闭标签页", + "wheelableTip": "开启后,标签栏区域可以响应滚轮的纵向滚动事件。\n关闭时,只能响应系统的横向滚动事件(需要按下Shift再滚动滚轮)", + "styleType": { + "title": "标签页风格", + "chrome": "谷歌", + "card": "卡片", + "plain": "朴素", + "brisk": "轻快" + }, + "contextMenu": { + "reload": "重新加载", + "close": "关闭", + "pin": "固定", + "unpin": "取消固定", + "closeLeft": "关闭左侧标签页", + "closeRight": "关闭右侧标签页", + "closeOther": "关闭其它标签页", + "closeAll": "关闭全部标签页", + "openInNewWindow": "在新窗口打开", + "maximize": "最大化", + "restoreMaximize": "还原" + } + }, + "navigationMenu": { + "title": "导航菜单", + "style": "导航菜单风格", + "accordion": "侧边导航菜单手风琴模式", + "split": "导航菜单分离", + "splitTip": "开启时,侧边栏显示顶栏对应菜单的子菜单" + }, + "breadcrumb": { + "title": "面包屑导航", + "enable": "开启面包屑导航", + "icon": "显示面包屑图标", + "home": "显示首页按钮", + "style": "面包屑风格", + "hideOnlyOne": "仅有一个时隐藏", + "background": "背景" + }, + "animation": { + "title": "动画", + "loading": "页面切换 Loading", + "transition": "页面切换动画", + "progress": "页面切换进度条" + }, + "theme": { + "title": "主题", + "radius": "圆角", + "fontSize": "字体大小", + "fontSizeTip": "调整全局字体大小,实时预览效果", + "light": "浅色", + "dark": "深色", + "darkSidebar": "深色侧边栏", + "darkHeader": "深色顶栏", + "weakMode": "色弱模式", + "grayMode": "灰色模式", + "builtin": { + "title": "内置主题", + "default": "默认", + "violet": "紫罗兰", + "pink": "樱花粉", + "rose": "玫瑰红", + "skyBlue": "天蓝色", + "deepBlue": "深蓝色", + "green": "浅绿色", + "deepGreen": "深绿色", + "orange": "橙黄色", + "yellow": "柠檬黄", + "zinc": "锌色灰", + "neutral": "中性色", + "slate": "石板灰", + "gray": "中灰色", + "custom": "自定义" + } + }, + "header": { + "title": "顶栏", + "modeStatic": "静止", + "modeFixed": "固定", + "modeAuto": "自动隐藏和显示", + "modeAutoScroll": "滚动隐藏和显示", + "visible": "显示顶栏", + "menuAlign": "菜单位置", + "menuAlignStart": "左侧", + "menuAlignEnd": "右侧", + "menuAlignCenter": "居中" + }, + "footer": { + "title": "底栏", + "visible": "显示底栏", + "fixed": "固定在底部" + }, + "copyright": { + "title": "版权", + "enable": "启用版权", + "companyName": "公司名", + "companySiteLink": "公司主页", + "date": "日期", + "icp": "ICP 备案号", + "icpLink": "ICP 网站链接" + }, + "shortcutKeys": { + "title": "快捷键", + "global": "全局", + "search": "全局搜索", + "logout": "退出登录", + "preferences": "偏好设置" + }, + "widget": { + "title": "小部件", + "globalSearch": "启用全局搜索", + "fullscreen": "启用全屏", + "themeToggle": "启用主题切换", + "languageToggle": "启用语言切换", + "notification": "启用通知", + "sidebarToggle": "启用侧边栏切换", + "lockScreen": "启用锁屏", + "refresh": "启用刷新" + } +} diff --git a/packages/locales/src/langs/zh-CN/profile.json b/packages/locales/src/langs/zh-CN/profile.json new file mode 100644 index 0000000..a38908c --- /dev/null +++ b/packages/locales/src/langs/zh-CN/profile.json @@ -0,0 +1,4 @@ +{ + "updatePassword": "更新密码", + "updateBasicProfile": "更新基本信息" +} diff --git a/packages/locales/src/langs/zh-CN/ui.json b/packages/locales/src/langs/zh-CN/ui.json new file mode 100644 index 0000000..f69b17d --- /dev/null +++ b/packages/locales/src/langs/zh-CN/ui.json @@ -0,0 +1,167 @@ +{ + "formRules": { + "required": "请输入{0}", + "selectRequired": "请选择{0}", + "minLength": "{0}至少{1}个字符", + "maxLength": "{0}最多{1}个字符", + "length": "{0}长度必须为{1}个字符", + "alreadyExists": "{0} `{1}` 已存在", + "startWith": "{0}必须以 {1} 开头", + "invalidURL": "请输入有效的链接", + "mobile": "请输入正确的{0}", + "sizeLimit": "文件大小不能超过 {0}MB", + "previewWarning": "无法打开文件,没有可用的URL或预览地址" + }, + "actionTitle": { + "copy": "复制{0}", + "cancel": "取消{0}", + "edit": "修改{0}", + "create": "新增{0}", + "delete": "删除{0}", + "deleteBatch": "批量删除", + "detail": "详情{0}", + "view": "查看{0}", + "import": "导入", + "export": "导出" + }, + "actionMessage": { + "deleteConfirm": "确定删除 {0} 吗?", + "deleteBatchConfirm": "确定删除所选项吗?", + "deleting": "正在删除 {0} ...", + "deletingBatch": "正在删除所选项 ...", + "deleteSuccess": "{0} 删除成功", + "deleteFailed": "{0} 删除失败", + "operationSuccess": "操作成功", + "operationFailed": "操作失败", + "importSuccess": "导入成功", + "importFail": "导入失败", + "downloadTemplateFail": "下载模板失败", + "updating": "正在更新 {0}...", + "updateSuccess": "更新 {0} 成功", + "updateFailed": "更新 {0} 失败", + "closing": "正在关闭 {0} ...", + "closeSuccess": "{0} 关闭成功" + }, + "placeholder": { + "input": "请输入", + "select": "请选择", + "upload": "点击上传" + }, + "captcha": { + "title": "请完成安全验证", + "sliderSuccessText": "验证通过", + "sliderDefaultText": "请按住滑块拖动", + "sliderRotateDefaultTip": "点击图片可刷新", + "sliderTranslateDefaultTip": "点击图片可刷新", + "sliderRotateFailTip": "验证失败", + "sliderRotateSuccessTip": "验证成功,耗时{0}秒", + "sliderTranslateFailTip": "验证失败", + "sliderTranslateSuccessTip": "验证成功,耗时{0}秒", + "alt": "支持img标签src属性值", + "refreshAriaLabel": "刷新验证码", + "confirmAriaLabel": "确认选择", + "confirm": "确认", + "pointAriaLabel": "点击点", + "clickInOrder": "请依次点击" + }, + "iconPicker": { + "placeholder": "选择一个图标", + "search": "搜索图标..." + }, + "jsonViewer": { + "copy": "复制", + "copied": "已复制" + }, + "crop": { + "title": "图片裁剪", + "titleTip": "裁剪比例 {0}", + "confirm": "裁剪", + "cancel": "取消裁剪", + "errorTip": "裁剪错误" + }, + "fallback": { + "pageNotFound": "哎呀!未找到页面", + "pageNotFoundDesc": "抱歉,我们无法找到您要找的页面。", + "forbidden": "哎呀!访问被拒绝", + "forbiddenDesc": "抱歉,您没有权限访问此页面。", + "internalError": "哎呀!出错了", + "internalErrorDesc": "抱歉,服务器遇到错误。", + "offline": "离线页面", + "offlineError": "哎呀!网络错误", + "offlineErrorDesc": "抱歉,无法连接到互联网,请检查您的网络连接并重试。", + "comingSoon": "即将推出", + "http": { + "requestTimeout": "请求超时,请稍后再试。", + "networkError": "网络异常,请检查您的网络连接后重试。", + "badRequest": "请求错误。请检查您的输入并重试。", + "unauthorized": "登录认证过期,请重新登录后继续。", + "forbidden": "禁止访问, 您没有权限访问此资源。", + "notFound": "未找到, 请求的资源不存在。", + "internalServerError": "内部服务器错误,请稍后再试。" + } + }, + "widgets": { + "document": "文档", + "profile": "个人中心", + "qa": "问题 & 帮助", + "setting": "设置", + "logoutTip": "是否退出登录?", + "viewAll": "查看所有消息", + "notifications": "通知", + "markAllAsRead": "全部标记为已读", + "clearNotifications": "清空", + "checkUpdatesTitle": "新版本可用", + "checkUpdatesDescription": "点击刷新以获取最新版本", + "search": { + "title": "搜索", + "searchNavigate": "搜索导航菜单", + "select": "选择", + "navigate": "导航", + "close": "关闭", + "noResults": "未找到搜索结果", + "noRecent": "没有搜索历史", + "recent": "搜索历史" + }, + "lockScreen": { + "title": "锁定屏幕", + "screenButton": "锁定", + "password": "密码", + "placeholder": "请输入锁屏密码", + "unlock": "点击解锁", + "errorPasswordTip": "密码错误,请重新输入", + "backToLogin": "返回登录", + "entry": "进入系统" + }, + "timezone": { + "setTimezone": "设置时区", + "setSuccess": "时区设置成功" + } + }, + "upload": { + "upload": "上传", + "imgUpload": "图片上传", + "accept": "支持{0}格式", + "acceptUpload": "只能上传{0}格式文件", + "maxSize": "单个文件不超过{0}MB", + "maxSizeMultiple": "只能上传不超过{0}MB的文件!", + "maxNumber": "最多只能上传{0}个文件", + "uploadSuccess": "上传成功", + "uploadError": "上传失败", + "imgUploading": "图片发送中,请稍等。。。" + }, + "cropper": { + "selectImage": "选择图片", + "uploadSuccess": "上传成功", + "imageTooBig": "图片超限", + "modalTitle": "头像上传", + "okText": "确认并上传", + "btn_reset": "重置", + "btn_rotate_left": "逆时针旋转", + "btn_rotate_right": "顺时针旋转", + "btn_scale_x": "水平翻转", + "btn_scale_y": "垂直翻转", + "btn_zoom_in": "放大", + "btn_zoom_out": "缩小", + "preview": "预览" + } +} diff --git a/packages/locales/src/typing.ts b/packages/locales/src/typing.ts new file mode 100644 index 0000000..fdebac2 --- /dev/null +++ b/packages/locales/src/typing.ts @@ -0,0 +1,25 @@ +export type SupportedLanguagesType = 'en-US' | 'zh-CN'; + +export type ImportLocaleFn = () => Promise<{ default: Record }>; + +export type LoadMessageFn = ( + lang: SupportedLanguagesType, +) => Promise | undefined>; + +export interface LocaleSetupOptions { + /** + * Default language + * @default zh-CN + */ + defaultLocale?: SupportedLanguagesType; + /** + * Load message function + * @param lang + * @returns + */ + loadMessages?: LoadMessageFn; + /** + * Whether to warn when the key is not found + */ + missingWarn?: boolean; +} diff --git a/packages/locales/tsconfig.json b/packages/locales/tsconfig.json new file mode 100644 index 0000000..ce1a891 --- /dev/null +++ b/packages/locales/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/preferences/package.json b/packages/preferences/package.json new file mode 100644 index 0000000..84a5a01 --- /dev/null +++ b/packages/preferences/package.json @@ -0,0 +1,26 @@ +{ + "name": "@vben/preferences", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/preferences" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "dependencies": { + "@vben-core/preferences": "workspace:*", + "@vben-core/typings": "workspace:*" + } +} diff --git a/packages/preferences/src/index.ts b/packages/preferences/src/index.ts new file mode 100644 index 0000000..75fab43 --- /dev/null +++ b/packages/preferences/src/index.ts @@ -0,0 +1,17 @@ +import type { Preferences } from '@vben-core/preferences'; +import type { DeepPartial } from '@vben-core/typings'; + +/** + * 如果你想所有的app都使用相同的默认偏好设置,你可以在这里定义 + * 而不是去修改 @vben-core/preferences 中的默认偏好设置 + * @param preferences + * @returns + */ + +function defineOverridesPreferences(preferences: DeepPartial) { + return preferences; +} + +export { defineOverridesPreferences }; + +export * from '@vben-core/preferences'; diff --git a/packages/preferences/tsconfig.json b/packages/preferences/tsconfig.json new file mode 100644 index 0000000..ce1a891 --- /dev/null +++ b/packages/preferences/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/stores/package.json b/packages/stores/package.json new file mode 100644 index 0000000..d91761a --- /dev/null +++ b/packages/stores/package.json @@ -0,0 +1,32 @@ +{ + "name": "@vben/stores", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/stores" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "dependencies": { + "@vben-core/preferences": "workspace:*", + "@vben-core/shared": "workspace:*", + "@vben-core/typings": "workspace:*", + "pinia": "catalog:", + "pinia-plugin-persistedstate": "catalog:", + "secure-ls": "catalog:", + "vue": "catalog:", + "vue-router": "catalog:" + } +} diff --git a/packages/stores/shim-pinia.d.ts b/packages/stores/shim-pinia.d.ts new file mode 100644 index 0000000..558d0ba --- /dev/null +++ b/packages/stores/shim-pinia.d.ts @@ -0,0 +1,9 @@ +// https://github.com/vuejs/pinia/issues/2098 +declare module 'pinia' { + export function acceptHMRUpdate( + initialUseStore: any | StoreDefinition, + hot: any, + ): (newModule: any) => any; +} + +export { acceptHMRUpdate }; diff --git a/packages/stores/src/index.ts b/packages/stores/src/index.ts new file mode 100644 index 0000000..41b3662 --- /dev/null +++ b/packages/stores/src/index.ts @@ -0,0 +1,3 @@ +export * from './modules'; +export * from './setup'; +export { defineStore, storeToRefs } from 'pinia'; diff --git a/packages/stores/src/modules/access.test.ts b/packages/stores/src/modules/access.test.ts new file mode 100644 index 0000000..211e256 --- /dev/null +++ b/packages/stores/src/modules/access.test.ts @@ -0,0 +1,46 @@ +import { createPinia, setActivePinia } from 'pinia'; +import { beforeEach, describe, expect, it } from 'vitest'; + +import { useAccessStore } from './access'; + +describe('useAccessStore', () => { + beforeEach(() => { + setActivePinia(createPinia()); + }); + + it('updates accessMenus state', () => { + const store = useAccessStore(); + expect(store.accessMenus).toEqual([]); + store.setAccessMenus([{ name: 'Dashboard', path: '/dashboard' }]); + expect(store.accessMenus).toEqual([ + { name: 'Dashboard', path: '/dashboard' }, + ]); + }); + + it('updates accessToken state correctly', () => { + const store = useAccessStore(); + expect(store.accessToken).toBeNull(); // 初始状态 + store.setAccessToken('abc123'); + expect(store.accessToken).toBe('abc123'); + }); + + it('returns the correct accessToken', () => { + const store = useAccessStore(); + store.setAccessToken('xyz789'); + expect(store.accessToken).toBe('xyz789'); + }); + + // 测试设置空的访问菜单列表 + it('handles empty accessMenus correctly', () => { + const store = useAccessStore(); + store.setAccessMenus([]); + expect(store.accessMenus).toEqual([]); + }); + + // 测试设置空的访问路由列表 + it('handles empty accessRoutes correctly', () => { + const store = useAccessStore(); + store.setAccessRoutes([]); + expect(store.accessRoutes).toEqual([]); + }); +}); diff --git a/packages/stores/src/modules/access.ts b/packages/stores/src/modules/access.ts new file mode 100644 index 0000000..785fffd --- /dev/null +++ b/packages/stores/src/modules/access.ts @@ -0,0 +1,147 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import type { MenuRecordRaw } from '@vben-core/typings'; + +import { acceptHMRUpdate, defineStore } from 'pinia'; + +type AccessToken = null | string; + +interface AccessState { + /** + * 权限码 + */ + accessCodes: string[]; + /** + * 可访问的菜单列表 + */ + accessMenus: MenuRecordRaw[]; + /** + * 可访问的路由列表 + */ + accessRoutes: RouteRecordRaw[]; + /** + * 登录 accessToken + */ + accessToken: AccessToken; + /** + * 是否已经检查过权限 + */ + isAccessChecked: boolean; + /** + * 是否锁屏状态 + */ + isLockScreen: boolean; + /** + * 锁屏密码 + */ + lockScreenPassword?: string; + /** + * 登录是否过期 + */ + loginExpired: boolean; + /** + * 登录 accessToken + */ + refreshToken: AccessToken; + /** + * 登录租户编号 + */ + tenantId: null | number; + /** + * 访问租户编号 + */ + visitTenantId: null | number; +} + +/** + * @zh_CN 访问权限相关 + */ +export const useAccessStore = defineStore('core-access', { + actions: { + getMenuByPath(path: string) { + function findMenu( + menus: MenuRecordRaw[], + path: string, + ): MenuRecordRaw | undefined { + for (const menu of menus) { + if (menu.path === path) { + return menu; + } + if (menu.children) { + const matched = findMenu(menu.children, path); + if (matched) { + return matched; + } + } + } + } + return findMenu(this.accessMenus, path); + }, + lockScreen(password: string) { + this.isLockScreen = true; + this.lockScreenPassword = password; + }, + setAccessCodes(codes: string[]) { + this.accessCodes = codes; + }, + setAccessMenus(menus: MenuRecordRaw[]) { + this.accessMenus = menus; + }, + setAccessRoutes(routes: RouteRecordRaw[]) { + this.accessRoutes = routes; + }, + setAccessToken(token: AccessToken) { + this.accessToken = token; + }, + setIsAccessChecked(isAccessChecked: boolean) { + this.isAccessChecked = isAccessChecked; + }, + setLoginExpired(loginExpired: boolean) { + this.loginExpired = loginExpired; + }, + setRefreshToken(token: AccessToken) { + this.refreshToken = token; + }, + setTenantId(tenantId: null | number) { + this.tenantId = tenantId; + }, + setVisitTenantId(visitTenantId: number) { + this.visitTenantId = visitTenantId; + }, + unlockScreen() { + this.isLockScreen = false; + this.lockScreenPassword = undefined; + }, + }, + persist: { + // 持久化 + pick: [ + 'accessToken', + 'refreshToken', + 'accessCodes', + 'tenantId', + 'visitTenantId', + 'isLockScreen', + 'lockScreenPassword', + ], + }, + state: (): AccessState => ({ + accessCodes: [], + accessMenus: [], + accessRoutes: [], + accessToken: null, + isAccessChecked: false, + isLockScreen: false, + lockScreenPassword: undefined, + loginExpired: false, + refreshToken: null, + tenantId: null, + visitTenantId: null, + }), +}); + +// 解决热更新问题 +const hot = import.meta.hot; +if (hot) { + hot.accept(acceptHMRUpdate(useAccessStore, hot)); +} diff --git a/packages/stores/src/modules/dict.ts b/packages/stores/src/modules/dict.ts new file mode 100644 index 0000000..6d80c4b --- /dev/null +++ b/packages/stores/src/modules/dict.ts @@ -0,0 +1,73 @@ +import { acceptHMRUpdate, defineStore } from 'pinia'; + +export interface DictItem { + colorType?: string; + cssClass?: string; + label: string; + value: string; +} + +export type Dict = Record; + +interface DictState { + dictCache: Dict; +} + +export const useDictStore = defineStore('core-dict', { + actions: { + getDictData(dictType: string, value: any) { + const dict = this.dictCache[dictType]; + if (!dict) { + return undefined; + } + return ( + dict.find((d) => d.value === value || d.value === value.toString()) ?? + undefined + ); + }, + getDictOptions(dictType: string) { + const dictOptions = this.dictCache[dictType]; + if (!dictOptions) { + return []; + } + return dictOptions; + }, + setDictCache(dicts: Dict) { + this.dictCache = dicts; + }, + setDictCacheByApi( + api: (params: Record) => Promise[]>, + params: Record = {}, + labelField: string = 'label', + valueField: string = 'value', + ) { + api(params).then((dicts) => { + const dictCacheData: Dict = {}; + dicts.forEach((dict) => { + dictCacheData[dict.dictType] = dicts + .filter((d) => d.dictType === dict.dictType) + .map((d) => ({ + colorType: d.colorType, + cssClass: d.cssClass, + label: d[labelField], + value: d[valueField], + })); + }); + this.setDictCache(dictCacheData); + }); + }, + }, + persist: { + // 持久化 + pick: ['dictCache'], + }, + state: (): DictState => ({ + dictCache: {}, + }), +}); + +// 解决热更新问题 +const hot = import.meta.hot; +if (hot) { + hot.accept(acceptHMRUpdate(useDictStore, hot)); +} diff --git a/packages/stores/src/modules/index.ts b/packages/stores/src/modules/index.ts new file mode 100644 index 0000000..6048fec --- /dev/null +++ b/packages/stores/src/modules/index.ts @@ -0,0 +1,5 @@ +export * from './access'; +export * from './dict'; +export * from './tabbar'; +export * from './timezone'; +export * from './user'; diff --git a/packages/stores/src/modules/tabbar.test.ts b/packages/stores/src/modules/tabbar.test.ts new file mode 100644 index 0000000..7c0fe7a --- /dev/null +++ b/packages/stores/src/modules/tabbar.test.ts @@ -0,0 +1,300 @@ +import { createRouter, createWebHistory } from 'vue-router'; + +import { createPinia, setActivePinia } from 'pinia'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { useTabbarStore } from './tabbar'; + +describe('useAccessStore', () => { + const router = createRouter({ + history: createWebHistory(), + routes: [], + }); + router.push = vi.fn(); + router.replace = vi.fn(); + beforeEach(() => { + setActivePinia(createPinia()); + vi.clearAllMocks(); + }); + + it('adds a new tab', () => { + const store = useTabbarStore(); + const tab: any = { + fullPath: '/home', + meta: {}, + key: '/home', + name: 'Home', + path: '/home', + }; + const addNewTab = store.addTab(tab); + expect(store.tabs.length).toBe(1); + expect(store.tabs[0]).toEqual(addNewTab); + }); + + it('adds a new tab if it does not exist', () => { + const store = useTabbarStore(); + const newTab: any = { + fullPath: '/new', + meta: {}, + name: 'New', + path: '/new', + }; + const addNewTab = store.addTab(newTab); + expect(store.tabs).toContainEqual(addNewTab); + }); + + it('updates an existing tab instead of adding a new one', () => { + const store = useTabbarStore(); + const initialTab: any = { + fullPath: '/existing', + meta: { + fullPathKey: false, + }, + name: 'Existing', + path: '/existing', + query: {}, + }; + store.addTab(initialTab); + const updatedTab = { ...initialTab, query: { id: '1' } }; + store.addTab(updatedTab); + expect(store.tabs.length).toBe(1); + expect(store.tabs[0]?.query).toEqual({ id: '1' }); + }); + + it('closes all tabs', async () => { + const store = useTabbarStore(); + store.addTab({ + fullPath: '/home', + meta: {}, + name: 'Home', + path: '/home', + } as any); + router.replace = vi.fn(); + + await store.closeAllTabs(router); + + expect(store.tabs.length).toBe(1); + }); + + it('closes a non-affix tab', () => { + const store = useTabbarStore(); + const tab: any = { + fullPath: '/closable', + meta: {}, + name: 'Closable', + path: '/closable', + }; + store.tabs.push(tab); + store._close(tab); + expect(store.tabs.length).toBe(0); + }); + + it('does not close an affix tab', () => { + const store = useTabbarStore(); + const affixTab: any = { + fullPath: '/affix', + meta: { affixTab: true }, + name: 'Affix', + path: '/affix', + }; + store.tabs.push(affixTab); + store._close(affixTab); + expect(store.tabs.length).toBe(1); // Affix tab should not be closed + }); + + it('returns all cache tabs', () => { + const store = useTabbarStore(); + store.cachedTabs.add('Home'); + store.cachedTabs.add('About'); + expect(store.getCachedTabs).toEqual(['Home', 'About']); + }); + + it('returns all tabs, including affix tabs', () => { + const store = useTabbarStore(); + const normalTab: any = { + fullPath: '/normal', + meta: {}, + name: 'Normal', + path: '/normal', + }; + const affixTab: any = { + fullPath: '/affix', + meta: { affixTab: true }, + name: 'Affix', + path: '/affix', + }; + store.tabs.push(normalTab); + store.affixTabs.push(affixTab); + expect(store.getTabs).toContainEqual(normalTab); + expect(store.affixTabs).toContainEqual(affixTab); + }); + + it('navigates to a specific tab', async () => { + const store = useTabbarStore(); + const tab: any = { meta: {}, name: 'Dashboard', path: '/dashboard' }; + + await store._goToTab(tab, router); + + expect(router.replace).toHaveBeenCalledWith({ + params: {}, + path: '/dashboard', + query: {}, + }); + }); + + it('closes multiple tabs by paths', async () => { + const store = useTabbarStore(); + store.addTab({ + fullPath: '/home', + meta: {}, + name: 'Home', + path: '/home', + } as any); + store.addTab({ + fullPath: '/about', + meta: {}, + name: 'About', + path: '/about', + } as any); + store.addTab({ + fullPath: '/contact', + meta: {}, + name: 'Contact', + path: '/contact', + } as any); + + await store._bulkCloseByKeys(['/home', '/contact']); + + expect(store.tabs).toHaveLength(1); + expect(store.tabs[0]?.name).toBe('About'); + }); + + it('closes all tabs to the left of the specified tab', async () => { + const store = useTabbarStore(); + store.addTab({ + fullPath: '/home', + meta: {}, + name: 'Home', + path: '/home', + } as any); + store.addTab({ + fullPath: '/about', + meta: {}, + name: 'About', + path: '/about', + } as any); + const targetTab: any = { + fullPath: '/contact', + meta: {}, + name: 'Contact', + path: '/contact', + }; + const addTargetTab = store.addTab(targetTab); + await store.closeLeftTabs(addTargetTab); + + expect(store.tabs).toHaveLength(1); + expect(store.tabs[0]?.name).toBe('Contact'); + }); + + it('closes all tabs except the specified tab', async () => { + const store = useTabbarStore(); + store.addTab({ + fullPath: '/home', + meta: {}, + name: 'Home', + path: '/home', + } as any); + const targetTab: any = { + fullPath: '/about', + meta: {}, + name: 'About', + path: '/about', + }; + const addTargetTab = store.addTab(targetTab); + store.addTab({ + fullPath: '/contact', + meta: {}, + name: 'Contact', + path: '/contact', + } as any); + + await store.closeOtherTabs(addTargetTab); + + expect(store.tabs).toHaveLength(1); + expect(store.tabs[0]?.name).toBe('About'); + }); + + it('closes all tabs to the right of the specified tab', async () => { + const store = useTabbarStore(); + const targetTab: any = { + fullPath: '/home', + meta: {}, + name: 'Home', + path: '/home', + }; + const addTargetTab = store.addTab(targetTab); + store.addTab({ + fullPath: '/about', + meta: {}, + name: 'About', + path: '/about', + } as any); + store.addTab({ + fullPath: '/contact', + meta: {}, + name: 'Contact', + path: '/contact', + } as any); + + await store.closeRightTabs(addTargetTab); + + expect(store.tabs).toHaveLength(1); + expect(store.tabs[0]?.name).toBe('Home'); + }); + + it('closes the tab with the specified key', async () => { + const store = useTabbarStore(); + const keyToClose = '/about'; + store.addTab({ + fullPath: '/home', + meta: {}, + name: 'Home', + path: '/home', + } as any); + store.addTab({ + fullPath: keyToClose, + meta: {}, + name: 'About', + path: '/about', + } as any); + store.addTab({ + fullPath: '/contact', + meta: {}, + name: 'Contact', + path: '/contact', + } as any); + + await store.closeTabByKey(keyToClose, router); + + expect(store.tabs).toHaveLength(2); + expect( + store.tabs.find((tab) => tab.fullPath === keyToClose), + ).toBeUndefined(); + }); + + it('refreshes the current tab', async () => { + const store = useTabbarStore(); + const currentTab: any = { + fullPath: '/dashboard', + meta: { name: 'Dashboard' }, + name: 'Dashboard', + path: '/dashboard', + }; + router.currentRoute.value = currentTab; + + await store.refresh(router); + + expect(store.excludeCachedTabs.has('Dashboard')).toBe(false); + expect(store.renderRouteView).toBe(true); + }); +}); diff --git a/packages/stores/src/modules/tabbar.ts b/packages/stores/src/modules/tabbar.ts new file mode 100644 index 0000000..6b18c26 --- /dev/null +++ b/packages/stores/src/modules/tabbar.ts @@ -0,0 +1,720 @@ +import type { ComputedRef } from 'vue'; +import type { + RouteLocationNormalized, + Router, + RouteRecordNormalized, +} from 'vue-router'; + +import type { TabDefinition } from '@vben-core/typings'; + +import { toRaw } from 'vue'; + +import { preferences } from '@vben-core/preferences'; +import { + createStack, + openRouteInNewWindow, + Stack, + startProgress, + stopProgress, +} from '@vben-core/shared/utils'; + +import { acceptHMRUpdate, defineStore } from 'pinia'; + +interface TabbarState { + /** + * @zh_CN 当前打开的标签页列表缓存 + */ + cachedTabs: Set; + /** + * @zh_CN 拖拽结束的索引 + */ + dragEndIndex: number; + /** + * @zh_CN 需要排除缓存的标签页 + */ + excludeCachedTabs: Set; + /** + * @zh_CN 标签右键菜单列表 + */ + menuList: string[]; + /** + * @zh_CN 是否刷新 + */ + renderRouteView?: boolean; + /** + * @zh_CN 当前打开的标签页列表 + */ + tabs: TabDefinition[]; + /** + * @zh_CN 更新时间,用于一些更新场景,使用watch深度监听的话,会损耗性能 + */ + updateTime?: number; + /** + * @zh_CN 上一个标签页打开的标签 + */ + visitHistory: Stack; +} + +/** + * @zh_CN 访问历史记录最大数量 + */ +const MAX_VISIT_HISTORY = 50; + +/** + * @zh_CN 访问权限相关 + */ +export const useTabbarStore = defineStore('core-tabbar', { + actions: { + /** + * Close tabs in bulk + */ + async _bulkCloseByKeys(keys: string[]) { + const keySet = new Set(keys); + this.tabs = this.tabs.filter( + (item) => !keySet.has(getTabKeyFromTab(item)), + ); + if (isVisitHistory()) { + this.visitHistory.remove(...keys); + } + + await this.updateCacheTabs(); + }, + /** + * @zh_CN 关闭标签页 + * @param tab + */ + _close(tab: TabDefinition) { + if (isAffixTab(tab)) { + return; + } + const index = this.tabs.findIndex((item) => equalTab(item, tab)); + index !== -1 && this.tabs.splice(index, 1); + }, + /** + * @zh_CN 跳转到默认标签页 + */ + async _goToDefaultTab(router: Router) { + if (this.getTabs.length <= 0) { + return; + } + const firstTab = this.getTabs[0]; + if (firstTab) { + await this._goToTab(firstTab, router); + } + }, + /** + * @zh_CN 跳转到标签页 + * @param tab + * @param router + */ + async _goToTab(tab: TabDefinition, router: Router) { + const { params, path, query } = tab; + const toParams = { + params: params || {}, + path, + query: query || {}, + }; + await router.replace(toParams); + }, + /** + * @zh_CN 添加标签页 + * @param routeTab + */ + addTab(routeTab: TabDefinition): TabDefinition { + let tab = cloneTab(routeTab); + if (!tab.key) { + tab.key = getTabKey(routeTab); + } + if (!isTabShown(tab)) { + return tab; + } + + const tabIndex = this.tabs.findIndex((item) => { + return equalTab(item, tab); + }); + + if (tabIndex === -1) { + const maxCount = preferences.tabbar.maxCount; + // 获取动态路由打开数,超过 0 即代表需要控制打开数 + const maxNumOfOpenTab = (routeTab?.meta?.maxNumOfOpenTab ?? + -1) as number; + // 如果动态路由层级大于 0 了,那么就要限制该路由的打开数限制了 + // 获取到已经打开的动态路由数, 判断是否大于某一个值 + if ( + maxNumOfOpenTab > 0 && + this.tabs.filter((tab) => tab.name === routeTab.name).length >= + maxNumOfOpenTab + ) { + // 关闭第一个 + const index = this.tabs.findIndex( + (item) => item.name === routeTab.name, + ); + index !== -1 && this.tabs.splice(index, 1); + } else if (maxCount > 0 && this.tabs.length >= maxCount) { + // 关闭第一个 + const index = this.tabs.findIndex( + (item) => + !Reflect.has(item.meta, 'affixTab') || !item.meta.affixTab, + ); + index !== -1 && this.tabs.splice(index, 1); + } + this.tabs.push(tab); + } else { + // 页面已经存在,不重复添加选项卡,只更新选项卡参数 + const currentTab = toRaw(this.tabs)[tabIndex]; + const mergedTab = { + ...currentTab, + ...tab, + meta: { ...currentTab?.meta, ...tab.meta }, + }; + if (currentTab) { + const curMeta = currentTab.meta; + if (Reflect.has(curMeta, 'affixTab')) { + mergedTab.meta.affixTab = curMeta.affixTab; + } + if (Reflect.has(curMeta, 'newTabTitle')) { + mergedTab.meta.newTabTitle = curMeta.newTabTitle; + } + } + tab = mergedTab; + this.tabs.splice(tabIndex, 1, mergedTab); + } + this.updateCacheTabs(); + // 添加访问历史记录 + if (isVisitHistory()) { + this.visitHistory.push(tab.key as string); + } + return tab; + }, + /** + * @zh_CN 关闭所有标签页 + */ + async closeAllTabs(router: Router) { + const newTabs = this.tabs.filter((tab) => isAffixTab(tab)); + this.tabs = newTabs.length > 0 ? newTabs : [...this.tabs].splice(0, 1); + // 设置访问历史记录 + if (isVisitHistory()) { + this.visitHistory.retain( + this.tabs.map((item) => getTabKeyFromTab(item)), + ); + } + await this._goToDefaultTab(router); + this.updateCacheTabs(); + }, + /** + * @zh_CN 关闭左侧标签页 + * @param tab + */ + async closeLeftTabs(tab: TabDefinition) { + const index = this.tabs.findIndex((item) => equalTab(item, tab)); + + if (index < 1) { + return; + } + + const leftTabs = this.tabs.slice(0, index); + const keys: string[] = []; + + for (const item of leftTabs) { + if (!isAffixTab(item)) { + keys.push(item.key as string); + } + } + await this._bulkCloseByKeys(keys); + }, + /** + * @zh_CN 关闭其他标签页 + * @param tab + */ + async closeOtherTabs(tab: TabDefinition) { + const closeKeys = this.tabs.map((item) => getTabKeyFromTab(item)); + + const keys: string[] = []; + + for (const key of closeKeys) { + if (key !== getTabKeyFromTab(tab)) { + const closeTab = this.tabs.find( + (item) => getTabKeyFromTab(item) === key, + ); + if (!closeTab) { + continue; + } + if (!isAffixTab(closeTab)) { + keys.push(closeTab.key as string); + } + } + } + await this._bulkCloseByKeys(keys); + }, + /** + * @zh_CN 关闭右侧标签页 + * @param tab + */ + async closeRightTabs(tab: TabDefinition) { + const index = this.tabs.findIndex((item) => equalTab(item, tab)); + + if (index !== -1 && index < this.tabs.length - 1) { + const rightTabs = this.tabs.slice(index + 1); + + const keys: string[] = []; + for (const item of rightTabs) { + if (!isAffixTab(item)) { + keys.push(item.key as string); + } + } + await this._bulkCloseByKeys(keys); + } + }, + + /** + * @zh_CN 关闭标签页 + * @param tab + * @param router + */ + async closeTab(tab: TabDefinition, router: Router) { + const { currentRoute } = router; + const currentTabKey = getTabKey(currentRoute.value); + // 关闭不是激活选项卡 + if (currentTabKey !== getTabKeyFromTab(tab)) { + this._close(tab); + this.updateCacheTabs(); + // 移除访问历史记录 + if (isVisitHistory()) { + this.visitHistory.remove(getTabKeyFromTab(tab)); + } + return; + } + if (this.getTabs.length <= 1) { + console.error('Failed to close the tab; only one tab remains open.'); + return; + } + // 从访问历史记录中移除当前关闭的tab + if (isVisitHistory()) { + this.visitHistory.remove(currentTabKey); + this._close(tab); + + let previousTab: TabDefinition | undefined; + let previousTabKey: string | undefined; + while (true) { + previousTabKey = this.visitHistory.pop(); + if (!previousTabKey) { + break; + } + previousTab = this.getTabByKey(previousTabKey); + if (previousTab) { + break; + } + } + await (previousTab + ? this._goToTab(previousTab, router) + : this._goToDefaultTab(router)); + return; + } + // 未开启访问历史记录,直接跳转下一个或上一个tab + const index = this.getTabs.findIndex( + (item) => getTabKeyFromTab(item) === getTabKey(currentRoute.value), + ); + + const before = this.getTabs[index - 1]; + const after = this.getTabs[index + 1]; + + // 下一个tab存在,跳转到下一个 + if (after) { + this._close(tab); + await this._goToTab(after, router); + // 上一个tab存在,跳转到上一个 + } else if (before) { + this._close(tab); + await this._goToTab(before, router); + } + }, + + /** + * @zh_CN 通过key关闭标签页 + * @param key + * @param router + */ + async closeTabByKey(key: string, router: Router) { + const originKey = decodeURIComponent(key); + const index = this.tabs.findIndex( + (item) => getTabKeyFromTab(item) === originKey, + ); + if (index === -1) { + return; + } + + const tab = this.tabs[index]; + if (tab) { + await this.closeTab(tab, router); + } + }, + + /** + * 根据tab的key获取tab + * @param key + */ + getTabByKey(key: string) { + return this.getTabs.find( + (item) => getTabKeyFromTab(item) === key, + ) as TabDefinition; + }, + /** + * @zh_CN 新窗口打开标签页 + * @param tab + */ + async openTabInNewWindow(tab: TabDefinition) { + openRouteInNewWindow(tab.fullPath || tab.path); + }, + + /** + * @zh_CN 固定标签页 + * @param tab + */ + async pinTab(tab: TabDefinition) { + const index = this.tabs.findIndex((item) => equalTab(item, tab)); + if (index === -1) { + return; + } + const oldTab = this.tabs[index]; + tab.meta.affixTab = true; + tab.meta.title = oldTab?.meta?.title as string; + // this.addTab(tab); + this.tabs.splice(index, 1, tab); + // 过滤固定tabs,后面更改affixTabOrder的值的话可能会有问题,目前行464排序affixTabs没有设置值 + const affixTabs = this.tabs.filter((tab) => isAffixTab(tab)); + // 获得固定tabs的index + const newIndex = affixTabs.findIndex((item) => equalTab(item, tab)); + // 交换位置重新排序 + await this.sortTabs(index, newIndex); + }, + + /** + * 刷新标签页 + */ + async refresh(router: Router | string) { + // 如果是Router路由,那么就根据当前路由刷新 + // 如果是string字符串,为路由名称,则定向刷新指定标签页,不能是当前路由名称,否则不会刷新 + if (typeof router === 'string') { + return await this.refreshByName(router); + } + + const { currentRoute } = router; + const { name } = currentRoute.value; + + this.excludeCachedTabs.add(name as string); + this.renderRouteView = false; + startProgress(); + + await new Promise((resolve) => setTimeout(resolve, 200)); + + this.excludeCachedTabs.delete(name as string); + this.renderRouteView = true; + stopProgress(); + }, + + /** + * 根据路由名称刷新指定标签页 + */ + async refreshByName(name: string) { + this.excludeCachedTabs.add(name); + await new Promise((resolve) => setTimeout(resolve, 200)); + this.excludeCachedTabs.delete(name); + }, + + /** + * @zh_CN 重置标签页标题 + */ + async resetTabTitle(tab: TabDefinition) { + if (tab?.meta?.newTabTitle) { + return; + } + const findTab = this.tabs.find((item) => equalTab(item, tab)); + if (findTab) { + findTab.meta.newTabTitle = undefined; + await this.updateCacheTabs(); + } + }, + + /** + * 设置固定标签页 + * @param tabs + */ + setAffixTabs(tabs: RouteRecordNormalized[]) { + for (const tab of tabs) { + tab.meta.affixTab = true; + this.addTab(routeToTab(tab)); + } + }, + + /** + * @zh_CN 更新菜单列表 + * @param list + */ + setMenuList(list: string[]) { + this.menuList = list; + }, + + /** + * @zh_CN 设置标签页标题 + * + * @zh_CN 支持设置静态标题字符串或计算属性作为动态标题 + * @zh_CN 当标题为计算属性时,标题会随计算属性值变化而自动更新 + * @zh_CN 适用于需要根据状态或多语言动态更新标题的场景 + * + * @param {TabDefinition} tab - 标签页对象 + * @param {ComputedRef | string} title - 标题内容,支持静态字符串或计算属性 + * + * @example + * // 设置静态标题 + * setTabTitle(tab, '新标签页'); + * + * @example + * // 设置动态标题 + * setTabTitle(tab, computed(() => t('common.dashboard'))); + */ + async setTabTitle(tab: TabDefinition, title: ComputedRef | string) { + const findTab = this.tabs.find((item) => equalTab(item, tab)); + + if (findTab) { + findTab.meta.newTabTitle = title; + + await this.updateCacheTabs(); + } + }, + setUpdateTime() { + this.updateTime = Date.now(); + }, + /** + * @zh_CN 设置标签页顺序 + * @param oldIndex + * @param newIndex + */ + async sortTabs(oldIndex: number, newIndex: number) { + const currentTab = this.tabs[oldIndex]; + if (!currentTab) { + return; + } + this.tabs.splice(oldIndex, 1); + this.tabs.splice(newIndex, 0, currentTab); + this.dragEndIndex = this.dragEndIndex + 1; + }, + + /** + * @zh_CN 切换固定标签页 + * @param tab + */ + async toggleTabPin(tab: TabDefinition) { + const affixTab = tab?.meta?.affixTab ?? false; + + await (affixTab ? this.unpinTab(tab) : this.pinTab(tab)); + }, + + /** + * @zh_CN 取消固定标签页 + * @param tab + */ + async unpinTab(tab: TabDefinition) { + const index = this.tabs.findIndex((item) => equalTab(item, tab)); + if (index === -1) { + return; + } + const oldTab = this.tabs[index]; + tab.meta.affixTab = false; + tab.meta.title = oldTab?.meta?.title as string; + // this.addTab(tab); + this.tabs.splice(index, 1, tab); + // 过滤固定tabs,后面更改affixTabOrder的值的话可能会有问题,目前行464排序affixTabs没有设置值 + const affixTabs = this.tabs.filter((tab) => isAffixTab(tab)); + // 获得固定tabs的index,使用固定tabs的下一个位置也就是活动tabs的第一个位置 + const newIndex = affixTabs.length; + // 交换位置重新排序 + await this.sortTabs(index, newIndex); + }, + /** + * 根据当前打开的选项卡更新缓存 + */ + async updateCacheTabs() { + const cacheMap = new Set(); + + for (const tab of this.tabs) { + // 跳过不需要持久化的标签页 + const keepAlive = tab.meta?.keepAlive; + if (!keepAlive) { + continue; + } + (tab.matched || []).forEach((t, i) => { + if (i > 0) { + cacheMap.add(t.name as string); + } + }); + + const name = tab.name as string; + cacheMap.add(name); + } + this.cachedTabs = cacheMap; + }, + }, + getters: { + affixTabs(): TabDefinition[] { + const affixTabs = this.tabs.filter((tab) => isAffixTab(tab)); + + return affixTabs.toSorted((a, b) => { + const orderA = (a.meta?.affixTabOrder ?? 0) as number; + const orderB = (b.meta?.affixTabOrder ?? 0) as number; + return orderA - orderB; + }); + }, + getCachedTabs(): string[] { + return [...this.cachedTabs]; + }, + getExcludeCachedTabs(): string[] { + return [...this.excludeCachedTabs]; + }, + getMenuList(): string[] { + return this.menuList; + }, + getTabs(): TabDefinition[] { + const normalTabs = this.tabs.filter((tab) => !isAffixTab(tab)); + return [...this.affixTabs, ...normalTabs].filter(Boolean); + }, + }, + persist: [ + // tabs不需要保存在localStorage + { + pick: ['tabs', 'visitHistory'], + storage: sessionStorage, + }, + ], + state: (): TabbarState => ({ + visitHistory: createStack(true, MAX_VISIT_HISTORY), + cachedTabs: new Set(), + dragEndIndex: 0, + excludeCachedTabs: new Set(), + menuList: [ + 'close', + 'affix', + 'maximize', + 'reload', + 'open-in-new-window', + 'close-left', + 'close-right', + 'close-other', + 'close-all', + ], + renderRouteView: true, + tabs: [], + updateTime: Date.now(), + }), +}); + +// 解决热更新问题 +const hot = import.meta.hot; +if (hot) { + hot.accept(acceptHMRUpdate(useTabbarStore, hot)); +} + +/** + * @zh_CN 克隆路由,防止路由被修改 + * @param route + */ +function cloneTab(route: TabDefinition): TabDefinition { + if (!route) { + return route; + } + const { matched, meta, ...opt } = route; + return { + ...opt, + matched: (matched + ? matched.map((item) => ({ + meta: item.meta, + name: item.name, + path: item.path, + })) + : undefined) as RouteRecordNormalized[], + meta: { + ...meta, + newTabTitle: meta.newTabTitle, + }, + }; +} + +/** + * @zh_CN 是否是固定标签页 + * @param tab + */ +function isAffixTab(tab: TabDefinition) { + return tab?.meta?.affixTab ?? false; +} + +/** + * @zh_CN 是否显示标签 + * @param tab + */ +function isTabShown(tab: TabDefinition) { + const matched = tab?.matched ?? []; + return !tab.meta.hideInTab && matched.every((item) => !item.meta.hideInTab); +} + +/** + * 从route获取tab页的key + * @param tab + */ +function getTabKey(tab: RouteLocationNormalized | RouteRecordNormalized) { + const { + fullPath, + path, + meta: { fullPathKey } = {}, + query = {}, + } = tab as RouteLocationNormalized; + // pageKey可能是数组(查询参数重复时可能出现) + const pageKey = Array.isArray(query.pageKey) + ? query.pageKey[0] + : query.pageKey; + let rawKey; + if (pageKey) { + rawKey = pageKey; + } else { + rawKey = fullPathKey === false ? path : (fullPath ?? path); + } + try { + return decodeURIComponent(rawKey); + } catch { + return rawKey; + } +} + +/** + * @zh_CN 是否开启访问历史记录 + */ +function isVisitHistory() { + return preferences.tabbar.visitHistory; +} + +/** + * 从tab获取tab页的key + * 如果tab没有key,那么就从route获取key + * @param tab + */ +function getTabKeyFromTab(tab: TabDefinition): string { + return tab.key ?? getTabKey(tab); +} + +/** + * 比较两个tab是否相等 + * @param a + * @param b + */ +function equalTab(a: TabDefinition, b: TabDefinition) { + return getTabKeyFromTab(a) === getTabKeyFromTab(b); +} + +function routeToTab(route: RouteRecordNormalized) { + return { + meta: route.meta, + name: route.name, + path: route.path, + key: getTabKey(route), + } as TabDefinition; +} + +export { getTabKey }; diff --git a/packages/stores/src/modules/timezone.ts b/packages/stores/src/modules/timezone.ts new file mode 100644 index 0000000..24180c6 --- /dev/null +++ b/packages/stores/src/modules/timezone.ts @@ -0,0 +1,132 @@ +import { ref, unref } from 'vue'; + +import { DEFAULT_TIME_ZONE_OPTIONS } from '@vben-core/preferences'; +import { + getCurrentTimezone, + setCurrentTimezone, +} from '@vben-core/shared/utils'; + +import { acceptHMRUpdate, defineStore } from 'pinia'; + +interface TimezoneHandler { + getTimezone?: () => Promise; + getTimezoneOptions?: () => Promise< + { + label: string; + value: string; + }[] + >; + setTimezone?: (timezone: string) => Promise; +} + +/** + * 默认时区处理模块 + * 时区存储基于pinia存储插件 + */ +const getDefaultTimezoneHandler = (): TimezoneHandler => { + return { + getTimezoneOptions: () => { + return Promise.resolve( + DEFAULT_TIME_ZONE_OPTIONS.map((item) => { + return { + label: item.label, + value: item.timezone, + }; + }), + ); + }, + }; +}; + +/** + * 自定义时区处理模块 + */ +let customTimezoneHandler: null | Partial = null; +const setTimezoneHandler = (handler: Partial) => { + customTimezoneHandler = handler; +}; + +/** + * 获取时区处理模块 + */ +const getTimezoneHandler = () => { + return { + ...getDefaultTimezoneHandler(), + ...customTimezoneHandler, + }; +}; + +/** + * timezone支持模块 + */ +const useTimezoneStore = defineStore( + 'core-timezone', + () => { + const timezoneRef = ref(getCurrentTimezone()); + + /** + * 初始化时区 + * Initialize the timezone + */ + async function initTimezone() { + const timezoneHandler = getTimezoneHandler(); + const timezone = await timezoneHandler.getTimezone?.(); + if (timezone) { + timezoneRef.value = timezone; + } + // 设置dayjs默认时区 + setCurrentTimezone(unref(timezoneRef)); + } + + /** + * 设置时区 + * Set the timezone + * @param timezone 时区字符串 + */ + async function setTimezone(timezone: string) { + const timezoneHandler = getTimezoneHandler(); + await timezoneHandler.setTimezone?.(timezone); + timezoneRef.value = timezone; + // 设置dayjs默认时区 + setCurrentTimezone(timezone); + } + + /** + * 获取时区选项 + * Get the timezone options + */ + async function getTimezoneOptions() { + const timezoneHandler = getTimezoneHandler(); + return (await timezoneHandler.getTimezoneOptions?.()) || []; + } + + initTimezone().catch((error) => { + console.error('Failed to initialize timezone during store setup:', error); + }); + + function $reset() { + timezoneRef.value = getCurrentTimezone(); + } + + return { + timezone: timezoneRef, + setTimezone, + getTimezoneOptions, + $reset, + }; + }, + { + persist: { + // 持久化 + pick: ['timezone'], + }, + }, +); + +export { setTimezoneHandler, useTimezoneStore }; + +// 解决热更新问题 +const hot = import.meta.hot; +if (hot) { + hot.accept(acceptHMRUpdate(useTimezoneStore, hot)); +} diff --git a/packages/stores/src/modules/user.test.ts b/packages/stores/src/modules/user.test.ts new file mode 100644 index 0000000..3d8a22c --- /dev/null +++ b/packages/stores/src/modules/user.test.ts @@ -0,0 +1,37 @@ +import { createPinia, setActivePinia } from 'pinia'; +import { beforeEach, describe, expect, it } from 'vitest'; + +import { useUserStore } from './user'; + +describe('useUserStore', () => { + beforeEach(() => { + setActivePinia(createPinia()); + }); + + it('returns correct userInfo', () => { + const store = useUserStore(); + const userInfo: any = { name: 'Jane Doe', roles: [{ value: 'user' }] }; + store.setUserInfo(userInfo); + expect(store.userInfo).toEqual(userInfo); + }); + + // 测试重置用户信息时的行为 + it('clears userInfo and userRoles when setting null userInfo', () => { + const store = useUserStore(); + store.setUserInfo({ + roles: [{ roleName: 'User', value: 'user' }], + } as any); + expect(store.userInfo).not.toBeNull(); + expect(store.userRoles.length).toBeGreaterThan(0); + + store.setUserInfo(null as any); + expect(store.userInfo).toBeNull(); + expect(store.userRoles).toEqual([]); + }); + + // 测试在没有用户角色时返回空数组 + it('returns an empty array for userRoles if not set', () => { + const store = useUserStore(); + expect(store.userRoles).toEqual([]); + }); +}); diff --git a/packages/stores/src/modules/user.ts b/packages/stores/src/modules/user.ts new file mode 100644 index 0000000..14a4f6f --- /dev/null +++ b/packages/stores/src/modules/user.ts @@ -0,0 +1,60 @@ +import { acceptHMRUpdate, defineStore } from 'pinia'; + +interface BasicUserInfo { + [key: string]: any; + /** + * 头像 + */ + avatar: string; + /** + * 用户邮箱 + */ + email?: string; + /** + * 用户昵称 + */ + nickname: string; + /** + * 用户 id + */ + userId: string; + /** + * 用户名 + */ + username: string; +} + +interface AccessState { + /** + * 用户信息 + */ + userInfo: BasicUserInfo | null; + /** + * 用户角色 + */ + userRoles: string[]; +} + +/** + * @zh_CN 用户信息相关 + */ +export const useUserStore = defineStore('core-user', { + actions: { + setUserInfo(userInfo: BasicUserInfo | null) { + this.userInfo = userInfo; + }, + setUserRoles(roles: string[]) { + this.userRoles = roles; + }, + }, + state: (): AccessState => ({ + userInfo: null, + userRoles: [], + }), +}); + +// 解决热更新问题 +const hot = import.meta.hot; +if (hot) { + hot.accept(acceptHMRUpdate(useUserStore, hot)); +} diff --git a/packages/stores/src/setup.ts b/packages/stores/src/setup.ts new file mode 100644 index 0000000..b18c27e --- /dev/null +++ b/packages/stores/src/setup.ts @@ -0,0 +1,60 @@ +import type { Pinia } from 'pinia'; + +import type { App } from 'vue'; + +import { createPinia } from 'pinia'; +import SecureLS from 'secure-ls'; + +let pinia: Pinia; + +export interface InitStoreOptions { + /** + * @zh_CN 应用名,由于 @vben/stores 是公用的,后续可能有多个app,为了防止多个app缓存冲突,可在这里配置应用名,应用名将被用于持久化的前缀 + */ + namespace: string; +} + +/** + * @zh_CN 初始化pinia + */ +export async function initStores(app: App, options: InitStoreOptions) { + const { createPersistedState } = await import('pinia-plugin-persistedstate'); + pinia = createPinia(); + const { namespace } = options; + const ls = new SecureLS({ + encodingType: 'aes', + encryptionSecret: import.meta.env.VITE_APP_STORE_SECURE_KEY, + isCompression: true, + // @ts-ignore secure-ls does not have a type definition for this + metaKey: `${namespace}-secure-meta`, + }); + pinia.use( + createPersistedState({ + // key $appName-$store.id + key: (storeKey) => `${namespace}-${storeKey}`, + storage: import.meta.env.DEV + ? localStorage + : { + getItem(key) { + return ls.get(key); + }, + setItem(key, value) { + ls.set(key, value); + }, + }, + }), + ); + app.use(pinia); + return pinia; +} + +export function resetAllStores() { + if (!pinia) { + console.error('Pinia is not installed'); + return; + } + const allStores = (pinia as any)._s; + for (const [_key, store] of allStores) { + store.$reset(); + } +} diff --git a/packages/stores/tsconfig.json b/packages/stores/tsconfig.json new file mode 100644 index 0000000..3057820 --- /dev/null +++ b/packages/stores/tsconfig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src", "shim-pinia.d.ts"] +} diff --git a/packages/styles/README.md b/packages/styles/README.md new file mode 100644 index 0000000..4826446 --- /dev/null +++ b/packages/styles/README.md @@ -0,0 +1,19 @@ +# @vben/styles + +用于多个 `app` 公用的样式文件,继承了 `@vben-core/design` 的所有能力。业务上有通用的样式文件可以放在这里。 + +## 用法 + +### 添加依赖 + +```bash +# 进入目标应用目录,例如 apps/xxxx-app +# cd apps/xxxx-app +pnpm add @vben/styles +``` + +### 使用 + +```ts +import '@vben/styles'; +``` diff --git a/packages/styles/package.json b/packages/styles/package.json new file mode 100644 index 0000000..79125f1 --- /dev/null +++ b/packages/styles/package.json @@ -0,0 +1,37 @@ +{ + "name": "@vben/styles", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/styles" + }, + "license": "MIT", + "type": "module", + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + }, + "./antd": { + "default": "./src/antd/index.css" + }, + "./antdv-next": { + "default": "./src/antdv-next/index.css" + }, + "./ele": { + "default": "./src/ele/index.css" + }, + "./naive": { + "default": "./src/naive/index.css" + }, + "./global": { + "default": "./src/global/index.scss" + } + }, + "dependencies": { + "@vben-core/design": "workspace:*" + } +} diff --git a/packages/styles/src/antd/index.css b/packages/styles/src/antd/index.css new file mode 100644 index 0000000..4dec637 --- /dev/null +++ b/packages/styles/src/antd/index.css @@ -0,0 +1,75 @@ +/* ant-design-vue 组件库的一些样式重置 */ + +.ant-app { + width: 100%; + height: 100%; + overscroll-behavior: none; + color: inherit; +} + +.ant-btn { + .anticon { + display: inline-flex; + } + + /* * 修复按钮添加图标时的位置问题 */ + > svg { + display: inline-block; + } + + > svg + span { + margin-inline-start: 6px; + } +} + +.ant-tag { + > svg { + display: inline-block; + } + + > svg + span { + margin-inline-start: 4px; + } +} + +.ant-message-notice-content, +.ant-notification-notice { + @apply dark:border-border/60 dark:border; +} + +.form-valid-error { + /** select 选择器的样式 */ + + .ant-select:not(.valid-success) .ant-select-selector:not(.valid-success) { + border-color: hsl(var(--destructive)) !important; + } + + .ant-select-focused .ant-select-selector { + box-shadow: 0 0 0 2px rgb(255 38 5 / 6%) !important; + } + + /** 数字输入框样式 */ + .ant-input-number-focused { + box-shadow: 0 0 0 2px rgb(255 38 5 / 6%); + } + + /** 密码输入框样式 */ + .ant-input-affix-wrapper:hover { + border-color: hsl(var(--destructive)); + box-shadow: 0 0 0 2px rgb(255 38 5 / 6%); + } + + .ant-input:not(.valid-success) { + border-color: hsl(var(--destructive)) !important; + } +} + +/** 区间选择器下面来回切换时的样式 */ +.ant-app .form-valid-error .ant-picker-active-bar { + background-color: hsl(var(--destructive)); +} + +/** 时间选择器的样式 */ +.ant-app .form-valid-error .ant-picker-focused { + box-shadow: 0 0 0 2px rgb(255 38 5 / 6%); +} diff --git a/packages/styles/src/antdv-next/index.css b/packages/styles/src/antdv-next/index.css new file mode 100644 index 0000000..420dfe9 --- /dev/null +++ b/packages/styles/src/antdv-next/index.css @@ -0,0 +1,77 @@ +/* antdv-next 组件库的一些样式重置 */ + +.ant-app { + width: 100%; + height: 100%; + overscroll-behavior: none; + color: inherit; +} + +.ant-btn { + .anticon { + display: inline-flex; + } + + /* * 修复按钮添加图标时的位置问题 */ + > .ant-btn-icon { + svg { + display: inline-block; + } + + svg + span { + margin-inline-start: 6px; + } + } +} + +.ant-tag { + > svg { + display: inline-block; + } + + > svg + span { + margin-inline-start: 4px; + } +} + +.ant-message-notice-content, +.ant-notification-notice { + @apply dark:border-border/60 dark:border; +} + +.form-valid-error { + /** select 选择器的样式 */ + + .ant-select:not(.valid-success) { + border-color: hsl(var(--destructive)) !important; + } + + .ant-select-focused { + box-shadow: 0 0 0 2px rgb(255 38 5 / 6%) !important; + } + + /** 数字输入框样式 */ + .ant-input-number-focused { + box-shadow: 0 0 0 2px rgb(255 38 5 / 6%); + } + + /** 密码输入框样式 */ + .ant-input-affix-wrapper:hover { + border-color: hsl(var(--destructive)); + box-shadow: 0 0 0 2px rgb(255 38 5 / 6%); + } + + .ant-input:not(.valid-success) { + border-color: hsl(var(--destructive)) !important; + } +} + +/** 区间选择器下面来回切换时的样式 */ +.ant-app .form-valid-error .ant-picker-active-bar { + background-color: hsl(var(--destructive)); +} + +/** 时间选择器的样式 */ +.ant-app .form-valid-error .ant-picker-focused { + box-shadow: 0 0 0 2px rgb(255 38 5 / 6%); +} diff --git a/packages/styles/src/ele/index.css b/packages/styles/src/ele/index.css new file mode 100644 index 0000000..4ee8f7b --- /dev/null +++ b/packages/styles/src/ele/index.css @@ -0,0 +1,44 @@ +.el-card { + --el-card-border-radius: var(--radius) !important; +} + +.form-valid-error { + /** select 选择器的样式 */ + .el-select .el-select__wrapper { + box-shadow: 0 0 0 1px var(--el-color-danger) inset; + } + + /** input 选择器的样式 */ + .el-input .el-input__wrapper { + box-shadow: 0 0 0 1px var(--el-color-danger) inset; + } + + /** radio和checkbox 选择器的样式 */ + .el-radio .el-radio__inner, + .el-checkbox .el-checkbox__inner { + border: 1px solid var(--el-color-danger); + } + + .el-checkbox-button .el-checkbox-button__inner, + .el-radio-button .el-radio-button__inner { + border: 1px solid var(--el-color-danger); + } + + .el-checkbox-button:first-child .el-checkbox-button__inner, + .el-radio-button:first-child .el-radio-button__inner { + border-left: 1px solid var(--el-color-danger); + } + + .el-checkbox-button:not(:first-child) .el-checkbox-button__inner, + .el-radio-button:not(:first-child) .el-radio-button__inner { + border-left: none; + } + + .el-textarea .el-textarea__inner { + border: 1px solid var(--el-color-danger); + } +} + +html .el-loading-mask { + z-index: 1000; +} diff --git a/packages/styles/src/global/index.scss b/packages/styles/src/global/index.scss new file mode 100644 index 0000000..c7af9bb --- /dev/null +++ b/packages/styles/src/global/index.scss @@ -0,0 +1 @@ +@use '@vben-core/design/bem' as *; diff --git a/packages/styles/src/index.ts b/packages/styles/src/index.ts new file mode 100644 index 0000000..b375456 --- /dev/null +++ b/packages/styles/src/index.ts @@ -0,0 +1 @@ +import '@vben-core/design'; diff --git a/packages/styles/src/naive/index.css b/packages/styles/src/naive/index.css new file mode 100644 index 0000000..a775116 --- /dev/null +++ b/packages/styles/src/naive/index.css @@ -0,0 +1,20 @@ +.form-valid-error { + .n-base-selection__state-border, + .n-input__state-border, + .n-radio-group__splitor { + border: var(--n-border-error); + } + + .n-radio-group .n-radio-button, + .n-radio-group .n-radio-group__splitor { + --n-button-border-color: rgb(255 56 96); + } + + .n-radio__dot { + --n-box-shadow: inset 0 0 0 1px rgb(255 56 96); + } + + .n-checkbox-box__border { + --n-border: 1px solid rgb(255 56 96); + } +} diff --git a/packages/styles/tsconfig.json b/packages/styles/tsconfig.json new file mode 100644 index 0000000..ce1a891 --- /dev/null +++ b/packages/styles/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/types/README.md b/packages/types/README.md new file mode 100644 index 0000000..f796f31 --- /dev/null +++ b/packages/types/README.md @@ -0,0 +1,20 @@ +# @vben/types + +用于多个 `app` 公用的工具类型,继承了 `@vben-core/typings` 的所有能力。业务上有通用的类型定义可以放在这里。 + +## 用法 + +### 添加依赖 + +```bash +# 进入目标应用目录,例如 apps/xxxx-app +# cd apps/xxxx-app +pnpm add @vben/types +``` + +### 使用 + +```ts +// 推荐加上 type +import type { SelectOption } from '@vben/types'; +``` diff --git a/packages/types/global.d.ts b/packages/types/global.d.ts new file mode 100644 index 0000000..36e546a --- /dev/null +++ b/packages/types/global.d.ts @@ -0,0 +1,38 @@ +import type { RouteMeta as IRouteMeta } from '@vben-core/typings'; + +import 'vue-router'; + +declare module 'vue-router' { + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + interface RouteMeta extends IRouteMeta {} +} + +export interface VbenAdminProAppConfigRaw { + VITE_GLOB_API_URL: string; + VITE_GLOB_AUTH_DINGDING_CLIENT_ID: string; + VITE_GLOB_AUTH_DINGDING_CORP_ID: string; + // API 加解密相关配置 + VITE_APP_API_ENCRYPT_ENABLE: string; + VITE_APP_API_ENCRYPT_HEADER: string; + VITE_APP_API_ENCRYPT_ALGORITHM: string; + VITE_APP_API_ENCRYPT_REQUEST_KEY: string; + VITE_APP_API_ENCRYPT_RESPONSE_KEY: string; +} + +interface AuthConfig { + dingding?: { + clientId: string; + corpId: string; + }; +} + +export interface ApplicationConfig { + apiURL: string; + auth: AuthConfig; +} + +declare global { + interface Window { + _VBEN_ADMIN_PRO_APP_CONF_: VbenAdminProAppConfigRaw; + } +} diff --git a/packages/types/package.json b/packages/types/package.json new file mode 100644 index 0000000..249f64c --- /dev/null +++ b/packages/types/package.json @@ -0,0 +1,27 @@ +{ + "name": "@vben/types", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/types" + }, + "license": "MIT", + "type": "module", + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + }, + "./global": { + "types": "./global.d.ts" + } + }, + "dependencies": { + "@vben-core/typings": "workspace:*", + "vue": "catalog:", + "vue-router": "catalog:" + } +} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts new file mode 100644 index 0000000..1e266c4 --- /dev/null +++ b/packages/types/src/index.ts @@ -0,0 +1,2 @@ +export type * from './user'; +export type * from '@vben-core/typings'; diff --git a/packages/types/src/user.ts b/packages/types/src/user.ts new file mode 100644 index 0000000..46d08ab --- /dev/null +++ b/packages/types/src/user.ts @@ -0,0 +1,19 @@ +import type { AppRouteRecordRaw, BasicUserInfo } from '@vben-core/typings'; + +/** 用户信息 */ +interface UserInfo extends BasicUserInfo { + /** + * 首页地址 + */ + homePath: string; +} + +/** 权限信息 */ +interface AuthPermissionInfo { + user: UserInfo; + roles: string[]; + permissions: string[]; + menus: AppRouteRecordRaw[]; +} + +export type { AuthPermissionInfo, UserInfo }; diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json new file mode 100644 index 0000000..ce1a891 --- /dev/null +++ b/packages/types/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/packages/utils/README.md b/packages/utils/README.md new file mode 100644 index 0000000..f06068a --- /dev/null +++ b/packages/utils/README.md @@ -0,0 +1,19 @@ +# @vben/utils + +用于多个 `app` 公用的工具包,继承了 `@vben-core/shared/utils` 的所有能力。业务上有通用的工具函数可以放在这里。 + +## 用法 + +### 添加依赖 + +```bash +# 进入目标应用目录,例如 apps/xxxx-app +# cd apps/xxxx-app +pnpm add @vben/utils +``` + +### 使用 + +```ts +import { isString } from '@vben/utils'; +``` diff --git a/packages/utils/package.json b/packages/utils/package.json new file mode 100644 index 0000000..5fe93f6 --- /dev/null +++ b/packages/utils/package.json @@ -0,0 +1,27 @@ +{ + "name": "@vben/utils", + "version": "5.6.0", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/utils" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "dependencies": { + "@vben-core/shared": "workspace:*", + "@vben-core/typings": "workspace:*", + "vue-router": "catalog:" + } +} diff --git a/packages/utils/src/helpers/__tests__/find-menu-by-path.test.ts b/packages/utils/src/helpers/__tests__/find-menu-by-path.test.ts new file mode 100644 index 0000000..fc0d76b --- /dev/null +++ b/packages/utils/src/helpers/__tests__/find-menu-by-path.test.ts @@ -0,0 +1,88 @@ +import { describe, expect, it } from 'vitest'; + +import { findMenuByPath, findRootMenuByPath } from '../find-menu-by-path'; + +// 示例菜单数据 +const menus: any[] = [ + { path: '/', children: [] }, + { path: '/about', children: [] }, + { + path: '/contact', + children: [ + { path: '/contact/email', children: [] }, + { path: '/contact/phone', children: [] }, + ], + }, + { + path: '/services', + children: [ + { path: '/services/design', children: [] }, + { + path: '/services/development', + children: [{ path: '/services/development/web', children: [] }], + }, + ], + }, +]; + +describe('menu Finder Tests', () => { + it('finds a top-level menu', () => { + const menu = findMenuByPath(menus, '/about'); + expect(menu).toBeDefined(); + expect(menu?.path).toBe('/about'); + }); + + it('finds a nested menu', () => { + const menu = findMenuByPath(menus, '/services/development/web'); + expect(menu).toBeDefined(); + expect(menu?.path).toBe('/services/development/web'); + }); + + it('returns null for a non-existent path', () => { + const menu = findMenuByPath(menus, '/non-existent'); + expect(menu).toBeNull(); + }); + + it('handles empty menus list', () => { + const menu = findMenuByPath([], '/about'); + expect(menu).toBeNull(); + }); + + it('handles menu items without children', () => { + const menu = findMenuByPath( + [{ path: '/only', children: undefined }] as any[], + '/only', + ); + expect(menu).toBeDefined(); + expect(menu?.path).toBe('/only'); + }); + + it('finds root menu by path', () => { + const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath( + menus, + '/services/development/web', + ); + + expect(findMenu).toBeDefined(); + expect(rootMenu).toBeUndefined(); + expect(rootMenuPath).toBeUndefined(); + expect(findMenu?.path).toBe('/services/development/web'); + }); + + it('returns null for undefined or empty path', () => { + const menuUndefinedPath = findMenuByPath(menus); + const menuEmptyPath = findMenuByPath(menus, ''); + expect(menuUndefinedPath).toBeNull(); + expect(menuEmptyPath).toBeNull(); + }); + + it('checks for root menu when path does not exist', () => { + const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath( + menus, + '/non-existent', + ); + expect(findMenu).toBeNull(); + expect(rootMenu).toBeUndefined(); + expect(rootMenuPath).toBeUndefined(); + }); +}); diff --git a/packages/utils/src/helpers/__tests__/generate-menus.test.ts b/packages/utils/src/helpers/__tests__/generate-menus.test.ts new file mode 100644 index 0000000..c02cc9d --- /dev/null +++ b/packages/utils/src/helpers/__tests__/generate-menus.test.ts @@ -0,0 +1,233 @@ +import type { Router, RouteRecordRaw } from 'vue-router'; + +import { createRouter, createWebHistory } from 'vue-router'; + +import { describe, expect, it, vi } from 'vitest'; + +import { generateMenus } from '../generate-menus'; + +// Nested route setup to test child inclusion and hideChildrenInMenu functionality + +describe('generateMenus', () => { + // 模拟路由数据 + const mockRoutes = [ + { + meta: { icon: 'home-icon', title: '首页' }, + name: 'home', + path: '/home', + }, + { + meta: { hideChildrenInMenu: true, icon: 'about-icon', title: '关于' }, + name: 'about', + path: '/about', + children: [ + { + path: 'team', + name: 'team', + meta: { icon: 'team-icon', title: '团队' }, + }, + ], + }, + ] as RouteRecordRaw[]; + + // 模拟 Vue 路由器实例 + const mockRouter = { + getRoutes: vi.fn(() => [ + { name: 'home', path: '/home' }, + { name: 'about', path: '/about' }, + { name: 'team', path: '/about/team' }, + ]), + }; + + it('the correct menu list should be generated according to the route', async () => { + const expectedMenus = [ + { + badge: undefined, + badgeType: undefined, + badgeVariants: undefined, + icon: 'home-icon', + name: '首页', + order: undefined, + parent: undefined, + parents: undefined, + path: '/home', + show: true, + children: [], + }, + { + badge: undefined, + badgeType: undefined, + badgeVariants: undefined, + icon: 'about-icon', + name: '关于', + order: undefined, + parent: undefined, + parents: undefined, + path: '/about', + show: true, + children: [], + }, + ]; + + const menus = generateMenus(mockRoutes, mockRouter as any); + expect(menus).toEqual(expectedMenus); + }); + + it('includes additional meta properties in menu items', async () => { + const mockRoutesWithMeta = [ + { + meta: { icon: 'user-icon', order: 1, title: 'Profile' }, + name: 'profile', + path: '/profile', + }, + ] as RouteRecordRaw[]; + + const menus = generateMenus(mockRoutesWithMeta, mockRouter as any); + expect(menus).toEqual([ + { + badge: undefined, + badgeType: undefined, + badgeVariants: undefined, + icon: 'user-icon', + name: 'Profile', + order: 1, + parent: undefined, + parents: undefined, + path: '/profile', + show: true, + children: [], + }, + ]); + }); + + it('handles dynamic route parameters correctly', async () => { + const mockRoutesWithParams = [ + { + meta: { icon: 'details-icon', title: 'User Details' }, + name: 'userDetails', + path: '/users/:userId', + }, + ] as RouteRecordRaw[]; + + const menus = generateMenus(mockRoutesWithParams, mockRouter as any); + expect(menus).toEqual([ + { + badge: undefined, + badgeType: undefined, + badgeVariants: undefined, + icon: 'details-icon', + name: 'User Details', + order: undefined, + parent: undefined, + parents: undefined, + path: '/users/:userId', + show: true, + children: [], + }, + ]); + }); + + it('processes routes with redirects correctly', async () => { + const mockRoutesWithRedirect = [ + { + name: 'redirectedRoute', + path: '/old-path', + redirect: '/new-path', + }, + { + meta: { icon: 'path-icon', title: 'New Path' }, + name: 'newPath', + path: '/new-path', + }, + ] as RouteRecordRaw[]; + + const menus = generateMenus(mockRoutesWithRedirect, mockRouter as any); + expect(menus).toEqual([ + // Assuming your generateMenus function excludes redirect routes from the menu + { + badge: undefined, + badgeType: undefined, + badgeVariants: undefined, + icon: undefined, + name: 'redirectedRoute', + order: undefined, + parent: undefined, + parents: undefined, + path: '/old-path', + show: true, + children: [], + }, + { + badge: undefined, + badgeType: undefined, + badgeVariants: undefined, + icon: 'path-icon', + name: 'New Path', + order: undefined, + parent: undefined, + parents: undefined, + path: '/new-path', + show: true, + children: [], + }, + ]); + }); + + const routes: any = [ + { + meta: { order: 2, title: 'Home' }, + name: 'home', + path: '/', + }, + { + meta: { order: 1, title: 'About' }, + name: 'about', + path: '/about', + }, + ]; + + const router: Router = createRouter({ + history: createWebHistory(), + routes, + }); + + it('should generate menu list with correct order', async () => { + const menus = generateMenus(routes, router); + const expectedMenus = [ + { + badge: undefined, + badgeType: undefined, + badgeVariants: undefined, + icon: undefined, + name: 'About', + order: 1, + parent: undefined, + parents: undefined, + path: '/about', + show: true, + children: [], + }, + { + badge: undefined, + badgeType: undefined, + badgeVariants: undefined, + icon: undefined, + name: 'Home', + order: 2, + parent: undefined, + parents: undefined, + path: '/', + show: true, + children: [], + }, + ]; + + expect(menus).toEqual(expectedMenus); + }); + + it('should handle empty routes', async () => { + const emptyRoutes: any[] = []; + const menus = generateMenus(emptyRoutes, router); + expect(menus).toEqual([]); + }); +}); diff --git a/packages/utils/src/helpers/__tests__/generate-routes-frontend.test.ts b/packages/utils/src/helpers/__tests__/generate-routes-frontend.test.ts new file mode 100644 index 0000000..8e01853 --- /dev/null +++ b/packages/utils/src/helpers/__tests__/generate-routes-frontend.test.ts @@ -0,0 +1,105 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { describe, expect, it } from 'vitest'; + +import { + generateRoutesByFrontend, + hasAuthority, +} from '../generate-routes-frontend'; + +// Mock 路由数据 +const mockRoutes = [ + { + meta: { + authority: ['admin', 'user'], + hideInMenu: false, + }, + path: '/dashboard', + children: [ + { + path: '/dashboard/overview', + meta: { authority: ['admin'], hideInMenu: false }, + }, + { + path: '/dashboard/stats', + meta: { authority: ['user'], hideInMenu: true }, + }, + ], + }, + { + meta: { authority: ['admin'], hideInMenu: false }, + path: '/settings', + }, + { + meta: { hideInMenu: false }, + path: '/profile', + }, +] as RouteRecordRaw[]; + +describe('hasAuthority', () => { + it('should return true if there is no authority defined', () => { + expect(hasAuthority(mockRoutes[2], ['admin'])).toBe(true); + }); + + it('should return true if the user has the required authority', () => { + expect(hasAuthority(mockRoutes[0], ['admin'])).toBe(true); + }); + + it('should return false if the user does not have the required authority', () => { + expect(hasAuthority(mockRoutes[1], ['user'])).toBe(false); + }); +}); + +describe('generateRoutesByFrontend', () => { + it('should handle routes without children', async () => { + const generatedRoutes = await generateRoutesByFrontend(mockRoutes, [ + 'user', + ]); + expect(generatedRoutes).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + path: '/profile', // This route has no children and should be included + }), + ]), + ); + }); + + it('should handle empty roles array', async () => { + const generatedRoutes = await generateRoutesByFrontend(mockRoutes, []); + expect(generatedRoutes).toEqual( + expect.arrayContaining([ + // Only routes without authority should be included + expect.objectContaining({ + path: '/profile', + }), + ]), + ); + expect(generatedRoutes).not.toEqual( + expect.arrayContaining([ + expect.objectContaining({ + path: '/dashboard', + }), + expect.objectContaining({ + path: '/settings', + }), + ]), + ); + }); + + it('should handle missing meta fields', async () => { + const routesWithMissingMeta = [ + { path: '/path1' }, // No meta + { meta: {}, path: '/path2' }, // Empty meta + { meta: { authority: ['admin'] }, path: '/path3' }, // Only authority + ]; + const generatedRoutes = await generateRoutesByFrontend( + routesWithMissingMeta as RouteRecordRaw[], + ['admin'], + ); + expect(generatedRoutes).toEqual([ + { path: '/path1' }, + { meta: {}, path: '/path2' }, + { meta: { authority: ['admin'] }, path: '/path3' }, + ]); + }); +}); diff --git a/packages/utils/src/helpers/__tests__/merge-route-modules.test.ts b/packages/utils/src/helpers/__tests__/merge-route-modules.test.ts new file mode 100644 index 0000000..3615556 --- /dev/null +++ b/packages/utils/src/helpers/__tests__/merge-route-modules.test.ts @@ -0,0 +1,68 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import type { RouteModuleType } from '../merge-route-modules'; + +import { describe, expect, it } from 'vitest'; + +import { mergeRouteModules } from '../merge-route-modules'; + +describe('mergeRouteModules', () => { + it('should merge route modules correctly', () => { + const routeModules: Record = { + './dynamic-routes/about.ts': { + default: [ + { + component: () => Promise.resolve({ template: '
    About
    ' }), + name: 'About', + path: '/about', + }, + ], + }, + './dynamic-routes/home.ts': { + default: [ + { + component: () => Promise.resolve({ template: '
    Home
    ' }), + name: 'Home', + path: '/', + }, + ], + }, + }; + + const expectedRoutes: RouteRecordRaw[] = [ + { + component: expect.any(Function), + name: 'About', + path: '/about', + }, + { + component: expect.any(Function), + name: 'Home', + path: '/', + }, + ]; + + const mergedRoutes = mergeRouteModules(routeModules); + expect(mergedRoutes).toEqual(expectedRoutes); + }); + + it('should handle empty modules', () => { + const routeModules: Record = {}; + const expectedRoutes: RouteRecordRaw[] = []; + + const mergedRoutes = mergeRouteModules(routeModules); + expect(mergedRoutes).toEqual(expectedRoutes); + }); + + it('should handle modules with no default export', () => { + const routeModules: Record = { + './dynamic-routes/empty.ts': { + default: [], + }, + }; + const expectedRoutes: RouteRecordRaw[] = []; + + const mergedRoutes = mergeRouteModules(routeModules); + expect(mergedRoutes).toEqual(expectedRoutes); + }); +}); diff --git a/packages/utils/src/helpers/find-menu-by-path.ts b/packages/utils/src/helpers/find-menu-by-path.ts new file mode 100644 index 0000000..747cc7f --- /dev/null +++ b/packages/utils/src/helpers/find-menu-by-path.ts @@ -0,0 +1,37 @@ +import type { MenuRecordRaw } from '@vben-core/typings'; + +function findMenuByPath( + list: MenuRecordRaw[], + path?: string, +): MenuRecordRaw | null { + for (const menu of list) { + if (menu.path === path) { + return menu; + } + const findMenu = menu.children && findMenuByPath(menu.children, path); + if (findMenu) { + return findMenu; + } + } + return null; +} + +/** + * 查找根菜单 + * @param menus + * @param path + */ +function findRootMenuByPath(menus: MenuRecordRaw[], path?: string, level = 0) { + const findMenu = findMenuByPath(menus, path); + const rootMenuPath = findMenu?.parents?.[level]; + const rootMenu = rootMenuPath + ? menus.find((item) => item.path === rootMenuPath) + : undefined; + return { + findMenu, + rootMenu, + rootMenuPath, + }; +} + +export { findMenuByPath, findRootMenuByPath }; diff --git a/packages/utils/src/helpers/generate-menus.ts b/packages/utils/src/helpers/generate-menus.ts new file mode 100644 index 0000000..697bf4b --- /dev/null +++ b/packages/utils/src/helpers/generate-menus.ts @@ -0,0 +1,213 @@ +import type { Router, RouteRecordRaw } from 'vue-router'; + +import type { + AppRouteRecordRaw, + ExRouteRecordRaw, + MenuRecordRaw, + RouteMeta, + RouteRecordStringComponent, +} from '@vben-core/typings'; + +import { + filterTree, + isHttpUrl, + mapTree, + sortTree, +} from '@vben-core/shared/utils'; + +/** + * 根据 routes 生成菜单列表 + * @param routes - 路由配置列表 + * @param router - Vue Router 实例 + * @returns 生成的菜单列表 + */ +function generateMenus( + routes: RouteRecordRaw[], + router: Router, +): MenuRecordRaw[] { + // 将路由列表转换为一个以 name 为键的对象映射 + const finalRoutesMap: { [key: string]: string } = Object.fromEntries( + router.getRoutes().map(({ name, path }) => [name, path]), + ); + + let menus = mapTree(routes, (route) => { + // 获取最终的路由路径 + const path = finalRoutesMap[route.name as string] ?? route.path ?? ''; + + const { + meta = {} as RouteMeta, + name: routeName, + redirect, + children = [], + } = route; + const { + activeIcon, + badge, + badgeType, + badgeVariants, + hideChildrenInMenu = false, + icon, + link, + order, + title = '', + } = meta; + + // 确保菜单名称不为空 + const name = (title || routeName || '') as string; + + // 处理子菜单 + const resultChildren = hideChildrenInMenu + ? [] + : ((children as MenuRecordRaw[]) ?? []); + + // 设置子菜单的父子关系 + if (resultChildren.length > 0) { + resultChildren.forEach((child) => { + child.parents = [...(route.parents ?? []), path]; + child.parent = path; + }); + } + + // 确定最终路径 + const resultPath = hideChildrenInMenu ? redirect || path : link || path; + + return { + activeIcon, + badge, + badgeType, + badgeVariants, + icon, + name, + order, + parent: route.parent, + parents: route.parents, + path: resultPath, + show: !meta.hideInMenu, + children: resultChildren, + }; + }); + + // 对菜单进行排序,避免order=0时被替换成999的问题 + menus = sortTree(menus, (a, b) => (a?.order ?? 999) - (b?.order ?? 999)); + + // 过滤掉隐藏的菜单项 + return filterTree(menus, (menu) => !!menu.show); +} + +/** + * 转换后端菜单数据为路由数据 + * @param menuList 后端菜单数据 + * @param parent 父级菜单 + * @param nameSet 用于跟踪已使用的 name,防止重复 + * @returns 路由数据 + */ +function convertServerMenuToRouteRecordStringComponent( + menuList: AppRouteRecordRaw[], + parent = '', + nameSet: Set = new Set(), +): RouteRecordStringComponent[] { + const menus: RouteRecordStringComponent[] = []; + menuList.forEach((menu) => { + // 处理外链菜单(顶级或子级) + if (isHttpUrl(menu.path)) { + // add by 芋艿:如果有 ?_iframe 参数,则作为内嵌页面处理 + // 如果有 _iframe 参数,则使用 iframeSrc;如果没有,则使用 link + const url = new URL(menu.path); + let link: string | undefined; + let iframeSrc: string | undefined; + if (url.searchParams.has('_iframe')) { + url.searchParams.delete('_iframe'); + iframeSrc = url.toString(); + } else { + link = menu.path; + } + + const urlMenu: RouteRecordStringComponent = { + component: 'IFrameView', + meta: { + hideInMenu: !menu.visible, + icon: menu.icon, + iframeSrc, + link, + order: menu.sort, + title: menu.name, + }, + name: menu.name, + path: `${menu.id}`, + }; + menus.push(urlMenu); + return; + } else if (menu.children && menu.parentId === 0) { + menu.component = 'BasicLayout'; + } else if (!menu.children) { + menu.component = menu.component as string; + } + if (menu.component === 'Layout') { + menu.component = 'BasicLayout'; + } + + if (menu.children && menu.parentId !== 0) { + menu.component = ''; + } + + // path + if (parent) { + menu.path = `${parent}/${menu.path}`; + } + + if (!menu.path.startsWith('/')) { + menu.path = `/${menu.path}`; + } + + // add by 芋艿:防止 name 重复,只有在 name 重复时,才自动添加 id + let finalName = menu.componentName || menu.name; + if (nameSet.has(finalName)) { + finalName = menu.name + menu.id; + console.error(`menu name duplicate: ${menu.name}, id: ${menu.id}`, menu); + } + nameSet.add(finalName); + + // add by 芋艿:处理 menu.component 中的 query 参数 + // https://doc.vben.pro/guide/essentials/route.html#query + let query: Record | undefined; + // add by 芋艿:防止 component 为 null 时,调用 indexOf 报错;关联 + if (!menu.component) { + menu.component = ''; + } + const queryIndex = menu.component.indexOf('?'); + if (queryIndex !== -1) { + // 提取 query 字符串并解析为对象 + const queryString = menu.component.slice(queryIndex + 1); + query = Object.fromEntries(new URLSearchParams(queryString).entries()); + // 移除 component 中的 query 部分 + menu.component = menu.component.slice(0, queryIndex); + } + + const buildMenu: RouteRecordStringComponent = { + component: menu.component, + meta: { + hideInMenu: !menu.visible, + icon: menu.icon, + keepAlive: menu.keepAlive, + order: menu.sort, + title: menu.name, + ...(query && { query }), + }, + name: finalName, + path: menu.path, + }; + + if (menu.children && menu.children.length > 0) { + buildMenu.children = convertServerMenuToRouteRecordStringComponent( + menu.children, + menu.path, + nameSet, + ); + } + + menus.push(buildMenu); + }); + return menus; +} + +export { convertServerMenuToRouteRecordStringComponent, generateMenus }; diff --git a/packages/utils/src/helpers/generate-routes-backend.ts b/packages/utils/src/helpers/generate-routes-backend.ts new file mode 100644 index 0000000..2715457 --- /dev/null +++ b/packages/utils/src/helpers/generate-routes-backend.ts @@ -0,0 +1,109 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import type { + ComponentRecordType, + GenerateMenuAndRoutesOptions, + RouteRecordStringComponent, +} from '@vben-core/typings'; + +import { mapTree } from '@vben-core/shared/utils'; + +/** + * 判断路由是否在菜单中显示但访问时展示 403(让用户知悉功能并申请权限) + */ +function menuHasVisibleWithForbidden(route: RouteRecordRaw): boolean { + return !!route.meta?.menuVisibleWithForbidden; +} + +/** + * 动态生成路由 - 后端方式 + * 对 meta.menuVisibleWithForbidden 为 true 的项直接替换为 403 组件,让用户知悉功能并申请权限。 + */ +async function generateRoutesByBackend( + options: GenerateMenuAndRoutesOptions, +): Promise { + const { + fetchMenuListAsync, + layoutMap = {}, + pageMap = {}, + forbiddenComponent, + } = options; + + try { + const menuRoutes = await fetchMenuListAsync?.(); + if (!menuRoutes) { + return []; + } + + const normalizePageMap: ComponentRecordType = {}; + + for (const [key, value] of Object.entries(pageMap)) { + normalizePageMap[normalizeViewPath(key)] = value; + } + + let routes = convertRoutes(menuRoutes, layoutMap, normalizePageMap); + + if (forbiddenComponent) { + routes = mapTree(routes, (route) => { + if (menuHasVisibleWithForbidden(route)) { + route.component = forbiddenComponent; + } + return route; + }); + } + + // add by 芋艿:合并静态路由和动态路由 + return [...options.routes, ...routes]; + } catch (error) { + console.error(error); + throw error; + } +} + +function convertRoutes( + routes: RouteRecordStringComponent[], + layoutMap: ComponentRecordType, + pageMap: ComponentRecordType, +): RouteRecordRaw[] { + return mapTree(routes, (node) => { + const route = node as unknown as RouteRecordRaw; + const { component, name } = node; + + if (!name) { + console.error('route name is required', route); + } + + // layout转换 + if (component && layoutMap[component]) { + route.component = layoutMap[component]; + // 页面组件转换 + } else if (component) { + const normalizePath = normalizeViewPath(component); + const pageKey = normalizePath.endsWith('.vue') + ? normalizePath + : `${normalizePath}.vue`; + if (pageMap[pageKey]) { + route.component = pageMap[pageKey]; + } else { + console.error(`route component is invalid: ${pageKey}`, route); + route.component = pageMap['/_core/fallback/not-found.vue']; + } + } + + return route; + }); +} + +function normalizeViewPath(path: string): string { + // 去除相对路径前缀 + const normalizedPath = path.replace(/^(\.\/|\.\.\/)+/, ''); + + // 确保路径以 '/' 开头 + const viewPath = normalizedPath.startsWith('/') + ? normalizedPath + : `/${normalizedPath}`; + + // 这里耦合了vben-admin的目录结构 + return viewPath.replace(/^\/views/, ''); +} +export { generateRoutesByBackend }; diff --git a/packages/utils/src/helpers/generate-routes-frontend.ts b/packages/utils/src/helpers/generate-routes-frontend.ts new file mode 100644 index 0000000..dafc8a7 --- /dev/null +++ b/packages/utils/src/helpers/generate-routes-frontend.ts @@ -0,0 +1,58 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { filterTree, mapTree } from '@vben-core/shared/utils'; + +/** + * 动态生成路由 - 前端方式 + */ +async function generateRoutesByFrontend( + routes: RouteRecordRaw[], + roles: string[], + forbiddenComponent?: RouteRecordRaw['component'], +): Promise { + // 根据角色标识过滤路由表,判断当前用户是否拥有指定权限 + const finalRoutes = filterTree(routes, (route) => { + return hasAuthority(route, roles); + }); + + if (!forbiddenComponent) { + return finalRoutes; + } + + // 如果有禁止访问的页面,将禁止访问的页面替换为403页面 + return mapTree(finalRoutes, (route) => { + if (menuHasVisibleWithForbidden(route)) { + route.component = forbiddenComponent; + } + return route; + }); +} + +/** + * 判断路由是否有权限访问 + * @param route + * @param access + */ +function hasAuthority(route: RouteRecordRaw, access: string[]) { + const authority = route.meta?.authority; + if (!authority) { + return true; + } + const canAccess = access.some((value) => authority.includes(value)); + + return canAccess || (!canAccess && menuHasVisibleWithForbidden(route)); +} + +/** + * 判断路由是否在菜单中显示,但是访问会被重定向到403 + * @param route + */ +function menuHasVisibleWithForbidden(route: RouteRecordRaw) { + return ( + !!route.meta?.authority && + Reflect.has(route.meta || {}, 'menuVisibleWithForbidden') && + !!route.meta?.menuVisibleWithForbidden + ); +} + +export { generateRoutesByFrontend, hasAuthority }; diff --git a/packages/utils/src/helpers/get-popup-container.ts b/packages/utils/src/helpers/get-popup-container.ts new file mode 100644 index 0000000..5ebb6f2 --- /dev/null +++ b/packages/utils/src/helpers/get-popup-container.ts @@ -0,0 +1,39 @@ +/** + * If the node is holding inside a form, return the form element, + * otherwise return the parent node of the given element or + * the document body if the element is not provided. + */ +export function getPopupContainer(node?: HTMLElement): HTMLElement { + return ( + node?.closest('form') ?? (node?.parentNode as HTMLElement) ?? document.body + ); +} + +// TODO @xingyu:这个需要 pr 给 vben 官方么?体感上,这个是全局性的哈; +/** + * VxeTable专用弹窗层 + * 解决问题: https://gitee.com/dapppp/ruoyi-plus-vben5/issues/IB1DM3 + * 单表格用法跟上面getPopupContainer一样 + * 一个页面(body下)有多个表格元素 必须先指定ID & ID参数传入该函数 + * + * getVxePopupContainer="(node) => getVxePopupContainer(node, 'xxx')" + * @param _node 触发的元素 + * @param id 表格唯一id 当页面(该窗口)有>=两个表格 必须提供ID + * @returns 挂载节点 + */ +export function getVxePopupContainer( + _node?: HTMLElement, + id?: string, +): HTMLElement { + let selector = 'div.vxe-table--body-wrapper.body--wrapper'; + if (id) { + selector = `div#${id} ${selector}`; + } + // 挂载到vxe-table的滚动区域 + const vxeTableContainerNode = document.querySelector(selector); + if (!vxeTableContainerNode) { + console.warn('无法找到vxe-table元素, 将会挂载到body.'); + return document.body; + } + return vxeTableContainerNode as HTMLElement; +} diff --git a/packages/utils/src/helpers/index.ts b/packages/utils/src/helpers/index.ts new file mode 100644 index 0000000..da2cd8d --- /dev/null +++ b/packages/utils/src/helpers/index.ts @@ -0,0 +1,8 @@ +export * from './find-menu-by-path'; +export * from './generate-menus'; +export * from './generate-routes-backend'; +export * from './generate-routes-frontend'; +export * from './get-popup-container'; +export * from './merge-route-modules'; +export * from './reset-routes'; +export * from './unmount-global-loading'; diff --git a/packages/utils/src/helpers/merge-route-modules.ts b/packages/utils/src/helpers/merge-route-modules.ts new file mode 100644 index 0000000..53e21f3 --- /dev/null +++ b/packages/utils/src/helpers/merge-route-modules.ts @@ -0,0 +1,28 @@ +import type { RouteRecordRaw } from 'vue-router'; + +// 定义模块类型 +interface RouteModuleType { + default: RouteRecordRaw[]; +} + +/** + * 合并动态路由模块的默认导出 + * @param routeModules 动态导入的路由模块对象 + * @returns 合并后的路由配置数组 + */ +function mergeRouteModules( + routeModules: Record, +): RouteRecordRaw[] { + const mergedRoutes: RouteRecordRaw[] = []; + + for (const routeModule of Object.values(routeModules)) { + const moduleRoutes = (routeModule as RouteModuleType)?.default ?? []; + mergedRoutes.push(...moduleRoutes); + } + + return mergedRoutes; +} + +export { mergeRouteModules }; + +export type { RouteModuleType }; diff --git a/packages/utils/src/helpers/reset-routes.ts b/packages/utils/src/helpers/reset-routes.ts new file mode 100644 index 0000000..0d53a00 --- /dev/null +++ b/packages/utils/src/helpers/reset-routes.ts @@ -0,0 +1,31 @@ +import type { Router, RouteRecordName, RouteRecordRaw } from 'vue-router'; + +import { traverseTreeValues } from '@vben-core/shared/utils'; + +/** + * @zh_CN 重置所有路由,如有指定白名单除外 + */ +export function resetStaticRoutes(router: Router, routes: RouteRecordRaw[]) { + // 获取静态路由所有节点包含子节点的 name,并排除不存在 name 字段的路由 + const staticRouteNames = traverseTreeValues< + RouteRecordRaw, + RouteRecordName | undefined + >(routes, (route) => { + // 这些路由需要指定 name,防止在路由重置时,不能删除没有指定 name 的路由 + if (!route.name) { + console.warn( + `The route with the path ${route.path} needs to have the field name specified.`, + ); + } + return route.name; + }); + + const { getRoutes, hasRoute, removeRoute } = router; + const allRoutes = getRoutes(); + allRoutes.forEach(({ name }) => { + // 存在于路由表且非白名单才需要删除 + if (name && !staticRouteNames.includes(name) && hasRoute(name)) { + removeRoute(name); + } + }); +} diff --git a/packages/utils/src/helpers/unmount-global-loading.ts b/packages/utils/src/helpers/unmount-global-loading.ts new file mode 100644 index 0000000..10b88ea --- /dev/null +++ b/packages/utils/src/helpers/unmount-global-loading.ts @@ -0,0 +1,31 @@ +/** + * 移除并销毁loading + * 放在这里是而不是放在 index.html 的app标签内,是因为这样比较不会生硬,渲染过快可能会有闪烁 + * 通过先添加css动画隐藏,在动画结束后在移除loading节点来改善体验 + * 不好的地方是会增加一些代码量 + * 自定义loading可以见:https://doc.vben.pro/guide/in-depth/loading.html + */ +export function unmountGlobalLoading() { + // 查找全局 loading 元素 + const loadingElement = document.querySelector('#__app-loading__'); + + if (loadingElement) { + // 添加隐藏类,触发过渡动画 + loadingElement.classList.add('hidden'); + + // 查找所有需要移除的注入 loading 元素 + const injectLoadingElements = document.querySelectorAll( + '[data-app-loading^="inject"]', + ); + + // 当过渡动画结束时,移除 loading 元素和所有注入的 loading 元素 + loadingElement.addEventListener( + 'transitionend', + () => { + loadingElement.remove(); // 移除 loading 元素 + injectLoadingElements.forEach((el) => el.remove()); // 移除所有注入的 loading 元素 + }, + { once: true }, + ); // 确保事件只触发一次 + } +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts new file mode 100644 index 0000000..eb9bef1 --- /dev/null +++ b/packages/utils/src/index.ts @@ -0,0 +1,5 @@ +export * from './helpers'; +export * from './validator'; +export * from '@vben-core/shared/cache'; +export * from '@vben-core/shared/color'; +export * from '@vben-core/shared/utils'; diff --git a/packages/utils/src/validator/index.ts b/packages/utils/src/validator/index.ts new file mode 100644 index 0000000..0d7fc29 --- /dev/null +++ b/packages/utils/src/validator/index.ts @@ -0,0 +1,2 @@ +export * from './regex'; +export * from './validator'; diff --git a/packages/utils/src/validator/regex.ts b/packages/utils/src/validator/regex.ts new file mode 100644 index 0000000..9d1e7c4 --- /dev/null +++ b/packages/utils/src/validator/regex.ts @@ -0,0 +1,18 @@ +/** 手机号正则表达式(中国) */ +const MOBILE_REGEX = /(?:0|86|\+86)?1[3-9]\d{9}/; +/** 身份证号正则表达式 */ +const ID_CARD_REGEX = /^\d{15}|\d{18}$/; +/** 邮箱正则表达式 */ +const EMAIL_REGEX = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/; +/** 密码正则表达式 以字母开头,长度在6~18之间,只能包含字母、数字和下划线 */ +const PASSWORD_REGEX = /^[a-z]\w{5,17}$/i; +/** 强密码 必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间 */ +const STRONG_PASSWORD_REGEX = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$/; + +export { + EMAIL_REGEX, + ID_CARD_REGEX, + MOBILE_REGEX, + PASSWORD_REGEX, + STRONG_PASSWORD_REGEX, +}; diff --git a/packages/utils/src/validator/validator.ts b/packages/utils/src/validator/validator.ts new file mode 100644 index 0000000..862f330 --- /dev/null +++ b/packages/utils/src/validator/validator.ts @@ -0,0 +1,16 @@ +import { MOBILE_REGEX } from './regex'; + +/** + * 验证是否为手机号码(中国) + * + * @param value 值 + * @returns 是否为手机号码(中国) + */ +function isMobile(value?: null | string): boolean { + if (!value) { + return false; + } + return MOBILE_REGEX.test(value); +} + +export { isMobile }; diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json new file mode 100644 index 0000000..255148a --- /dev/null +++ b/packages/utils/tsconfig.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/library.json", + "compilerOptions": { + "types": ["@vben-core/typings/vue-router"] + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..a78d45d --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,23527 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +catalogs: + default: + '@changesets/changelog-github': + specifier: ^0.5.2 + version: 0.5.2 + '@changesets/cli': + specifier: ^2.29.8 + version: 2.29.8 + '@changesets/git': + specifier: ^3.0.4 + version: 3.0.4 + '@clack/prompts': + specifier: ^0.11.0 + version: 0.11.0 + '@commitlint/cli': + specifier: ^19.8.1 + version: 19.8.1 + '@commitlint/config-conventional': + specifier: ^19.8.1 + version: 19.8.1 + '@eslint/js': + specifier: ^9.39.2 + version: 9.39.2 + '@form-create/ant-design-vue': + specifier: ^3.2.37 + version: 3.2.37 + '@form-create/antd-designer': + specifier: ^3.4.0 + version: 3.4.0 + '@form-create/designer': + specifier: ^3.4.0 + version: 3.4.0 + '@form-create/element-ui': + specifier: ^3.2.37 + version: 3.2.37 + '@form-create/naive-ui': + specifier: ^3.2.37 + version: 3.2.37 + '@iconify/json': + specifier: ^2.2.432 + version: 2.2.438 + '@iconify/tailwind': + specifier: ^1.2.0 + version: 1.2.0 + '@iconify/vue': + specifier: ^5.0.0 + version: 5.0.0 + '@intlify/core-base': + specifier: ^11.2.8 + version: 11.2.8 + '@intlify/unplugin-vue-i18n': + specifier: ^6.0.8 + version: 6.0.8 + '@jspm/generator': + specifier: ^2.9.0 + version: 2.10.0 + '@manypkg/get-packages': + specifier: ^3.1.0 + version: 3.1.0 + '@microsoft/fetch-event-source': + specifier: ^2.0.1 + version: 2.0.1 + '@nolebase/vitepress-plugin-git-changelog': + specifier: ^2.18.2 + version: 2.18.2 + '@playwright/test': + specifier: ^1.58.2 + version: 1.58.2 + '@pnpm/workspace.read-manifest': + specifier: ^1000.2.10 + version: 1000.2.10 + '@stylistic/stylelint-plugin': + specifier: ^4.0.1 + version: 4.0.1 + '@tailwindcss/nesting': + specifier: 0.0.0-insiders.565cd3e + version: 0.0.0-insiders.565cd3e + '@tailwindcss/typography': + specifier: ^0.5.19 + version: 0.5.19 + '@tanstack/vue-store': + specifier: ^0.8.0 + version: 0.8.0 + '@tinyflow-ai/vue': + specifier: ~1.1.10 + version: 1.1.10 + '@tinymce/tinymce-vue': + specifier: ^6.3.0 + version: 6.3.0 + '@types/archiver': + specifier: ^6.0.4 + version: 6.0.4 + '@types/codemirror': + specifier: ^5.60.17 + version: 5.60.17 + '@types/crypto-js': + specifier: ^4.2.2 + version: 4.2.2 + '@types/eslint': + specifier: ^9.6.1 + version: 9.6.1 + '@types/html-minifier-terser': + specifier: ^7.0.2 + version: 7.0.2 + '@types/lodash.clonedeep': + specifier: ^4.5.9 + version: 4.5.9 + '@types/markdown-it': + specifier: ^14.1.2 + version: 14.1.2 + '@types/node': + specifier: ^24.10.12 + version: 24.10.13 + '@types/nprogress': + specifier: ^0.2.3 + version: 0.2.3 + '@types/postcss-import': + specifier: ^14.0.3 + version: 14.0.3 + '@types/qrcode': + specifier: ^1.5.6 + version: 1.5.6 + '@types/qs': + specifier: ^6.14.0 + version: 6.14.0 + '@types/sortablejs': + specifier: ^1.15.9 + version: 1.15.9 + '@typescript-eslint/eslint-plugin': + specifier: ^8.54.0 + version: 8.55.0 + '@typescript-eslint/parser': + specifier: ^8.54.0 + version: 8.55.0 + '@vee-validate/zod': + specifier: ^4.15.1 + version: 4.15.1 + '@videojs-player/vue': + specifier: ^1.0.0 + version: 1.0.0 + '@vite-pwa/vitepress': + specifier: ^1.1.0 + version: 1.1.0 + '@vitejs/plugin-vue': + specifier: ^6.0.4 + version: 6.0.4 + '@vitejs/plugin-vue-jsx': + specifier: ^5.1.4 + version: 5.1.4 + '@vue/shared': + specifier: ^3.5.27 + version: 3.5.28 + '@vue/test-utils': + specifier: ^2.4.6 + version: 2.4.6 + '@vueuse/core': + specifier: ^14.1.0 + version: 14.2.1 + '@vueuse/integrations': + specifier: ^14.1.0 + version: 14.2.1 + '@vueuse/motion': + specifier: ^3.0.3 + version: 3.0.3 + ant-design-vue: + specifier: ^4.2.6 + version: 4.2.6 + antdv-next: + specifier: ^1.0.2 + version: 1.0.2 + archiver: + specifier: ^7.0.1 + version: 7.0.1 + autoprefixer: + specifier: ^10.4.24 + version: 10.4.24 + axios: + specifier: ^1.13.4 + version: 1.13.5 + axios-mock-adapter: + specifier: ^2.1.0 + version: 2.1.0 + benz-amr-recorder: + specifier: ^1.1.5 + version: 1.1.5 + bpmn-js: + specifier: ^17.11.1 + version: 17.11.1 + bpmn-js-properties-panel: + specifier: 5.23.0 + version: 5.23.0 + bpmn-js-token-simulation: + specifier: ^0.36.3 + version: 0.36.3 + cac: + specifier: ^6.7.14 + version: 6.7.14 + camunda-bpmn-moddle: + specifier: ^7.0.1 + version: 7.0.1 + chalk: + specifier: ^5.6.2 + version: 5.6.2 + cheerio: + specifier: ^1.2.0 + version: 1.2.0 + circular-dependency-scanner: + specifier: ^2.3.0 + version: 2.3.0 + class-variance-authority: + specifier: ^0.7.1 + version: 0.7.1 + codemirror: + specifier: ^5.65.20 + version: 5.65.21 + commitlint-plugin-function-rules: + specifier: ^4.3.1 + version: 4.3.1 + consola: + specifier: ^3.4.2 + version: 3.4.2 + cropperjs: + specifier: ^1.6.2 + version: 1.6.2 + cross-env: + specifier: ^10.1.0 + version: 10.1.0 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + cspell: + specifier: ^9.6.4 + version: 9.6.4 + cssnano: + specifier: ^7.1.2 + version: 7.1.2 + cz-git: + specifier: ^1.12.0 + version: 1.12.0 + czg: + specifier: ^1.12.0 + version: 1.12.0 + dayjs: + specifier: ^1.11.19 + version: 1.11.19 + defu: + specifier: ^6.1.4 + version: 6.1.4 + depcheck: + specifier: ^1.4.7 + version: 1.4.7 + diagram-js: + specifier: ^12.8.1 + version: 12.8.1 + dotenv: + specifier: ^16.6.1 + version: 16.6.1 + echarts: + specifier: ^6.0.0 + version: 6.0.0 + element-plus: + specifier: ^2.13.1 + version: 2.13.2 + es-toolkit: + specifier: ^1.44.0 + version: 1.44.0 + eslint: + specifier: ^9.39.2 + version: 9.39.2 + eslint-config-turbo: + specifier: ^2.7.6 + version: 2.8.5 + eslint-plugin-command: + specifier: ^3.4.0 + version: 3.4.0 + eslint-plugin-eslint-comments: + specifier: ^3.2.0 + version: 3.2.0 + eslint-plugin-import-x: + specifier: ^4.16.1 + version: 4.16.1 + eslint-plugin-jsdoc: + specifier: ^61.7.1 + version: 61.7.1 + eslint-plugin-jsonc: + specifier: ^2.21.0 + version: 2.21.1 + eslint-plugin-n: + specifier: ^17.23.2 + version: 17.23.2 + eslint-plugin-no-only-tests: + specifier: ^3.3.0 + version: 3.3.0 + eslint-plugin-perfectionist: + specifier: ^4.15.1 + version: 4.15.1 + eslint-plugin-pnpm: + specifier: ^1.5.0 + version: 1.5.0 + eslint-plugin-prettier: + specifier: ^5.5.5 + version: 5.5.5 + eslint-plugin-regexp: + specifier: ^2.10.0 + version: 2.10.0 + eslint-plugin-unicorn: + specifier: ^62.0.0 + version: 62.0.0 + eslint-plugin-unused-imports: + specifier: ^4.3.0 + version: 4.4.1 + eslint-plugin-vitest: + specifier: ^0.5.4 + version: 0.5.4 + eslint-plugin-vue: + specifier: ^10.7.0 + version: 10.7.0 + eslint-plugin-yml: + specifier: ^1.19.1 + version: 1.19.1 + execa: + specifier: ^9.6.1 + version: 9.6.1 + fast-xml-parser: + specifier: ^4.5.3 + version: 4.5.3 + find-up: + specifier: ^7.0.0 + version: 7.0.0 + get-port: + specifier: ^7.1.0 + version: 7.1.0 + globals: + specifier: ^16.5.0 + version: 16.5.0 + happy-dom: + specifier: ^17.6.3 + version: 17.6.3 + highlight.js: + specifier: ^11.11.1 + version: 11.11.1 + html-minifier-terser: + specifier: ^7.2.0 + version: 7.2.0 + is-ci: + specifier: ^4.1.0 + version: 4.1.0 + jsencrypt: + specifier: ^3.5.4 + version: 3.5.4 + json-bigint: + specifier: ^1.0.0 + version: 1.0.0 + jsonc-eslint-parser: + specifier: ^2.4.2 + version: 2.4.2 + lefthook: + specifier: ^2.1.0 + version: 2.1.0 + lodash.clonedeep: + specifier: ^4.5.0 + version: 4.5.0 + lucide-vue-next: + specifier: ^0.553.0 + version: 0.553.0 + markdown-it: + specifier: ^14.1.0 + version: 14.1.0 + markmap-common: + specifier: ^0.16.0 + version: 0.16.0 + markmap-lib: + specifier: ^0.16.1 + version: 0.16.1 + markmap-toolbar: + specifier: ^0.17.2 + version: 0.17.2 + markmap-view: + specifier: ^0.16.0 + version: 0.16.0 + medium-zoom: + specifier: ^1.1.0 + version: 1.1.0 + naive-ui: + specifier: ^2.43.2 + version: 2.43.2 + nitropack: + specifier: ^2.13.1 + version: 2.13.1 + nprogress: + specifier: ^0.2.0 + version: 0.2.0 + ora: + specifier: ^8.2.0 + version: 8.2.0 + pinia-plugin-persistedstate: + specifier: ^4.7.1 + version: 4.7.1 + pkg-types: + specifier: ^2.3.0 + version: 2.3.0 + playwright: + specifier: ^1.58.2 + version: 1.58.2 + postcss: + specifier: ^8.5.6 + version: 8.5.6 + postcss-antd-fixes: + specifier: ^0.2.0 + version: 0.2.0 + postcss-html: + specifier: ^1.8.1 + version: 1.8.1 + postcss-import: + specifier: ^16.1.1 + version: 16.1.1 + postcss-preset-env: + specifier: ^10.6.1 + version: 10.6.1 + postcss-scss: + specifier: ^4.0.9 + version: 4.0.9 + prettier: + specifier: ^3.8.1 + version: 3.8.1 + prettier-plugin-tailwindcss: + specifier: ^0.7.2 + version: 0.7.2 + publint: + specifier: ^0.3.17 + version: 0.3.17 + qrcode: + specifier: ^1.5.4 + version: 1.5.4 + qs: + specifier: ^6.14.1 + version: 6.14.1 + reka-ui: + specifier: ^2.7.0 + version: 2.8.0 + resolve.exports: + specifier: ^2.0.3 + version: 2.0.3 + rimraf: + specifier: ^6.1.2 + version: 6.1.2 + rollup: + specifier: ^4.57.0 + version: 4.57.1 + rollup-plugin-visualizer: + specifier: ^5.14.0 + version: 5.14.0 + sass: + specifier: ^1.97.3 + version: 1.97.3 + secure-ls: + specifier: ^2.0.0 + version: 2.0.0 + sortablejs: + specifier: ^1.15.6 + version: 1.15.6 + steady-xml: + specifier: ^0.1.0 + version: 0.1.0 + stylelint: + specifier: ^16.26.1 + version: 16.26.1 + stylelint-config-recess-order: + specifier: ^7.6.0 + version: 7.6.1 + stylelint-config-recommended: + specifier: ^17.0.0 + version: 17.0.0 + stylelint-config-recommended-scss: + specifier: ^16.0.2 + version: 16.0.2 + stylelint-config-recommended-vue: + specifier: ^1.6.1 + version: 1.6.1 + stylelint-config-standard: + specifier: ^39.0.1 + version: 39.0.1 + stylelint-order: + specifier: ^7.0.1 + version: 7.0.1 + stylelint-prettier: + specifier: ^5.0.3 + version: 5.0.3 + stylelint-scss: + specifier: ^6.14.0 + version: 6.14.0 + tailwind-merge: + specifier: ^2.6.0 + version: 2.6.1 + tailwindcss: + specifier: ^3.4.19 + version: 3.4.19 + tailwindcss-animate: + specifier: ^1.0.7 + version: 1.0.7 + tdesign-vue-next: + specifier: ^1.18.0 + version: 1.18.2 + theme-colors: + specifier: ^0.1.0 + version: 0.1.0 + tinymce: + specifier: ^7.3.0 + version: 7.9.1 + tippy.js: + specifier: ^6.3.7 + version: 6.3.7 + turbo: + specifier: ^2.8.3 + version: 2.8.5 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + unbuild: + specifier: ^3.6.1 + version: 3.6.1 + unplugin-element-plus: + specifier: ^0.11.2 + version: 0.11.2 + vee-validate: + specifier: ^4.15.1 + version: 4.15.1 + video.js: + specifier: ^7.21.7 + version: 7.21.7 + vite: + specifier: ^7.3.1 + version: 7.3.1 + vite-plugin-compression: + specifier: ^0.5.1 + version: 0.5.1 + vite-plugin-dts: + specifier: ^4.5.4 + version: 4.5.4 + vite-plugin-html: + specifier: ^3.2.2 + version: 3.2.2 + vite-plugin-lazy-import: + specifier: ^1.0.7 + version: 1.0.7 + vite-plugin-pwa: + specifier: ^1.2.0 + version: 1.2.0 + vite-plugin-vue-devtools: + specifier: ^8.0.5 + version: 8.0.6 + vitepress: + specifier: ^1.6.4 + version: 1.6.4 + vitepress-plugin-group-icons: + specifier: ^1.7.1 + version: 1.7.1 + vitest: + specifier: ^3.2.4 + version: 3.2.4 + vue-dompurify-html: + specifier: ^5.3.0 + version: 5.3.0 + vue-eslint-parser: + specifier: ^10.2.0 + version: 10.2.0 + vue-i18n: + specifier: ^11.2.8 + version: 11.2.8 + vue-json-viewer: + specifier: ^3.0.4 + version: 3.0.4 + vue-router: + specifier: ^4.6.4 + version: 4.6.4 + vue-tippy: + specifier: ^6.7.1 + version: 6.7.1 + vue-tsc: + specifier: ^3.2.4 + version: 3.2.4 + vue3-print-nb: + specifier: ^0.1.4 + version: 0.1.4 + vue3-signature: + specifier: ^0.2.4 + version: 0.2.4 + vuedraggable: + specifier: ^4.1.0 + version: 4.1.0 + vxe-pc-ui: + specifier: ^4.12.16 + version: 4.12.36 + vxe-table: + specifier: ^4.17.46 + version: 4.17.48 + watermark-js-plus: + specifier: ^1.6.3 + version: 1.6.3 + yaml-eslint-parser: + specifier: ^1.3.2 + version: 1.3.2 + zod: + specifier: ^3.25.76 + version: 3.25.76 + zod-defaults: + specifier: 0.1.3 + version: 0.1.3 + +overrides: + '@ast-grep/napi': ^0.39.9 + '@ctrl/tinycolor': ^4.2.0 + clsx: ^2.1.1 + esbuild: ^0.25.12 + jiti: ^2.6.1 + pinia: ^3.0.4 + vue: ^3.5.27 + +importers: + + .: + devDependencies: + '@changesets/changelog-github': + specifier: 'catalog:' + version: 0.5.2 + '@changesets/cli': + specifier: 'catalog:' + version: 2.29.8(@types/node@24.10.13) + '@playwright/test': + specifier: 'catalog:' + version: 1.58.2 + '@types/node': + specifier: 'catalog:' + version: 24.10.13 + '@vben/commitlint-config': + specifier: workspace:* + version: link:internal/lint-configs/commitlint-config + '@vben/eslint-config': + specifier: workspace:* + version: link:internal/lint-configs/eslint-config + '@vben/prettier-config': + specifier: workspace:* + version: link:internal/lint-configs/prettier-config + '@vben/stylelint-config': + specifier: workspace:* + version: link:internal/lint-configs/stylelint-config + '@vben/tailwind-config': + specifier: workspace:* + version: link:internal/tailwind-config + '@vben/tsconfig': + specifier: workspace:* + version: link:internal/tsconfig + '@vben/turbo-run': + specifier: workspace:* + version: link:scripts/turbo-run + '@vben/vite-config': + specifier: workspace:* + version: link:internal/vite-config + '@vben/vsh': + specifier: workspace:* + version: link:scripts/vsh + '@vitejs/plugin-vue': + specifier: 'catalog:' + version: 6.0.4(vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3)) + '@vitejs/plugin-vue-jsx': + specifier: 'catalog:' + version: 5.1.4(vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3)) + '@vue/test-utils': + specifier: 'catalog:' + version: 2.4.6 + autoprefixer: + specifier: 'catalog:' + version: 10.4.24(postcss@8.5.6) + cross-env: + specifier: 'catalog:' + version: 10.1.0 + cspell: + specifier: 'catalog:' + version: 9.6.4 + happy-dom: + specifier: 'catalog:' + version: 17.6.3 + is-ci: + specifier: 'catalog:' + version: 4.1.0 + lefthook: + specifier: 'catalog:' + version: 2.1.0 + playwright: + specifier: 'catalog:' + version: 1.58.2 + rimraf: + specifier: 'catalog:' + version: 6.1.2 + tailwindcss: + specifier: 'catalog:' + version: 3.4.19(yaml@2.8.2) + turbo: + specifier: 'catalog:' + version: 2.8.5 + typescript: + specifier: 'catalog:' + version: 5.9.3 + unbuild: + specifier: 'catalog:' + version: 3.6.1(sass@1.97.3)(typescript@5.9.3)(vue-tsc@3.2.4(typescript@5.9.3))(vue@3.5.28(typescript@5.9.3)) + vite: + specifier: 'catalog:' + version: 7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vitest: + specifier: 'catalog:' + version: 3.2.4(@types/node@24.10.13)(happy-dom@17.6.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-tsc: + specifier: 'catalog:' + version: 3.2.4(typescript@5.9.3) + + apps/web-antd: + dependencies: + '@form-create/ant-design-vue': + specifier: 'catalog:' + version: 3.2.37(vue@3.5.28(typescript@5.9.3)) + '@form-create/antd-designer': + specifier: 'catalog:' + version: 3.4.0(vue@3.5.28(typescript@5.9.3)) + '@tinymce/tinymce-vue': + specifier: 'catalog:' + version: 6.3.0(tinymce@7.9.1)(vue@3.5.28(typescript@5.9.3)) + '@vben/access': + specifier: workspace:* + version: link:../../packages/effects/access + '@vben/common-ui': + specifier: workspace:* + version: link:../../packages/effects/common-ui + '@vben/constants': + specifier: workspace:* + version: link:../../packages/constants + '@vben/hooks': + specifier: workspace:* + version: link:../../packages/effects/hooks + '@vben/icons': + specifier: workspace:* + version: link:../../packages/icons + '@vben/layouts': + specifier: workspace:* + version: link:../../packages/effects/layouts + '@vben/locales': + specifier: workspace:* + version: link:../../packages/locales + '@vben/plugins': + specifier: workspace:* + version: link:../../packages/effects/plugins + '@vben/preferences': + specifier: workspace:* + version: link:../../packages/preferences + '@vben/request': + specifier: workspace:* + version: link:../../packages/effects/request + '@vben/stores': + specifier: workspace:* + version: link:../../packages/stores + '@vben/styles': + specifier: workspace:* + version: link:../../packages/styles + '@vben/types': + specifier: workspace:* + version: link:../../packages/types + '@vben/utils': + specifier: workspace:* + version: link:../../packages/utils + '@videojs-player/vue': + specifier: 'catalog:' + version: 1.0.0(@types/video.js@7.3.58)(video.js@7.21.7)(vue@3.5.28(typescript@5.9.3)) + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + '@vueuse/integrations': + specifier: 'catalog:' + version: 14.2.1(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(focus-trap@7.8.0)(nprogress@0.2.0)(qrcode@1.5.4)(sortablejs@1.15.6)(vue@3.5.28(typescript@5.9.3)) + ant-design-vue: + specifier: 'catalog:' + version: 4.2.6(vue@3.5.28(typescript@5.9.3)) + benz-amr-recorder: + specifier: 'catalog:' + version: 1.1.5 + bpmn-js: + specifier: 'catalog:' + version: 17.11.1 + bpmn-js-properties-panel: + specifier: 'catalog:' + version: 5.23.0(@bpmn-io/properties-panel@3.38.0)(bpmn-js@17.11.1)(camunda-bpmn-js-behaviors@1.14.0(bpmn-js@17.11.1)(camunda-bpmn-moddle@7.0.1)(zeebe-bpmn-moddle@1.12.0))(diagram-js@12.8.1) + bpmn-js-token-simulation: + specifier: 'catalog:' + version: 0.36.3 + camunda-bpmn-moddle: + specifier: 'catalog:' + version: 7.0.1 + cropperjs: + specifier: 'catalog:' + version: 1.6.2 + dayjs: + specifier: 'catalog:' + version: 1.11.19 + diagram-js: + specifier: 'catalog:' + version: 12.8.1 + fast-xml-parser: + specifier: 'catalog:' + version: 4.5.3 + highlight.js: + specifier: 'catalog:' + version: 11.11.1 + pinia: + specifier: ^3.0.4 + version: 3.0.4(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)) + steady-xml: + specifier: 'catalog:' + version: 0.1.0 + tinymce: + specifier: 'catalog:' + version: 7.9.1 + video.js: + specifier: 'catalog:' + version: 7.21.7 + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-dompurify-html: + specifier: 'catalog:' + version: 5.3.0(vue@3.5.28(typescript@5.9.3)) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + vue3-print-nb: + specifier: 'catalog:' + version: 0.1.4(typescript@5.9.3) + vue3-signature: + specifier: 'catalog:' + version: 0.2.4(vue@3.5.28(typescript@5.9.3)) + vuedraggable: + specifier: 'catalog:' + version: 4.1.0(vue@3.5.28(typescript@5.9.3)) + + apps/web-antdv-next: + dependencies: + '@vben/access': + specifier: workspace:* + version: link:../../packages/effects/access + '@vben/common-ui': + specifier: workspace:* + version: link:../../packages/effects/common-ui + '@vben/constants': + specifier: workspace:* + version: link:../../packages/constants + '@vben/hooks': + specifier: workspace:* + version: link:../../packages/effects/hooks + '@vben/icons': + specifier: workspace:* + version: link:../../packages/icons + '@vben/layouts': + specifier: workspace:* + version: link:../../packages/effects/layouts + '@vben/locales': + specifier: workspace:* + version: link:../../packages/locales + '@vben/plugins': + specifier: workspace:* + version: link:../../packages/effects/plugins + '@vben/preferences': + specifier: workspace:* + version: link:../../packages/preferences + '@vben/request': + specifier: workspace:* + version: link:../../packages/effects/request + '@vben/stores': + specifier: workspace:* + version: link:../../packages/stores + '@vben/styles': + specifier: workspace:* + version: link:../../packages/styles + '@vben/types': + specifier: workspace:* + version: link:../../packages/types + '@vben/utils': + specifier: workspace:* + version: link:../../packages/utils + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + antdv-next: + specifier: 'catalog:' + version: 1.0.2(date-fns@4.1.0)(luxon@3.7.2)(vue@3.5.28(typescript@5.9.3)) + dayjs: + specifier: 'catalog:' + version: 1.11.19 + pinia: + specifier: ^3.0.4 + version: 3.0.4(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + + apps/web-ele: + dependencies: + '@form-create/designer': + specifier: 'catalog:' + version: 3.4.0(vue@3.5.28(typescript@5.9.3)) + '@form-create/element-ui': + specifier: 'catalog:' + version: 3.2.37(vue@3.5.28(typescript@5.9.3)) + '@tinymce/tinymce-vue': + specifier: 'catalog:' + version: 6.3.0(tinymce@7.9.1)(vue@3.5.28(typescript@5.9.3)) + '@vben/access': + specifier: workspace:* + version: link:../../packages/effects/access + '@vben/common-ui': + specifier: workspace:* + version: link:../../packages/effects/common-ui + '@vben/constants': + specifier: workspace:* + version: link:../../packages/constants + '@vben/hooks': + specifier: workspace:* + version: link:../../packages/effects/hooks + '@vben/icons': + specifier: workspace:* + version: link:../../packages/icons + '@vben/layouts': + specifier: workspace:* + version: link:../../packages/effects/layouts + '@vben/locales': + specifier: workspace:* + version: link:../../packages/locales + '@vben/plugins': + specifier: workspace:* + version: link:../../packages/effects/plugins + '@vben/preferences': + specifier: workspace:* + version: link:../../packages/preferences + '@vben/request': + specifier: workspace:* + version: link:../../packages/effects/request + '@vben/stores': + specifier: workspace:* + version: link:../../packages/stores + '@vben/styles': + specifier: workspace:* + version: link:../../packages/styles + '@vben/types': + specifier: workspace:* + version: link:../../packages/types + '@vben/utils': + specifier: workspace:* + version: link:../../packages/utils + '@videojs-player/vue': + specifier: 'catalog:' + version: 1.0.0(@types/video.js@7.3.58)(video.js@7.21.7)(vue@3.5.28(typescript@5.9.3)) + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + '@vueuse/integrations': + specifier: 'catalog:' + version: 14.2.1(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(focus-trap@7.8.0)(nprogress@0.2.0)(qrcode@1.5.4)(sortablejs@1.15.6)(vue@3.5.28(typescript@5.9.3)) + benz-amr-recorder: + specifier: 'catalog:' + version: 1.1.5 + bpmn-js: + specifier: 'catalog:' + version: 17.11.1 + bpmn-js-properties-panel: + specifier: 'catalog:' + version: 5.23.0(@bpmn-io/properties-panel@3.38.0)(bpmn-js@17.11.1)(camunda-bpmn-js-behaviors@1.14.0(bpmn-js@17.11.1)(camunda-bpmn-moddle@7.0.1)(zeebe-bpmn-moddle@1.12.0))(diagram-js@12.8.1) + bpmn-js-token-simulation: + specifier: 'catalog:' + version: 0.36.3 + camunda-bpmn-moddle: + specifier: 'catalog:' + version: 7.0.1 + cropperjs: + specifier: 'catalog:' + version: 1.6.2 + dayjs: + specifier: 'catalog:' + version: 1.11.19 + diagram-js: + specifier: 'catalog:' + version: 12.8.1 + element-plus: + specifier: 'catalog:' + version: 2.13.2(vue@3.5.28(typescript@5.9.3)) + fast-xml-parser: + specifier: 'catalog:' + version: 4.5.3 + highlight.js: + specifier: 'catalog:' + version: 11.11.1 + pinia: + specifier: ^3.0.4 + version: 3.0.4(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)) + steady-xml: + specifier: 'catalog:' + version: 0.1.0 + tinymce: + specifier: 'catalog:' + version: 7.9.1 + video.js: + specifier: 'catalog:' + version: 7.21.7 + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-dompurify-html: + specifier: 'catalog:' + version: 5.3.0(vue@3.5.28(typescript@5.9.3)) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + vue3-print-nb: + specifier: 'catalog:' + version: 0.1.4(typescript@5.9.3) + vue3-signature: + specifier: 'catalog:' + version: 0.2.4(vue@3.5.28(typescript@5.9.3)) + vuedraggable: + specifier: 'catalog:' + version: 4.1.0(vue@3.5.28(typescript@5.9.3)) + devDependencies: + unplugin-element-plus: + specifier: 'catalog:' + version: 0.11.2(magicast@0.5.2) + + apps/web-naive: + dependencies: + '@form-create/naive-ui': + specifier: 'catalog:' + version: 3.2.37(vue@3.5.28(typescript@5.9.3)) + '@vben/access': + specifier: workspace:* + version: link:../../packages/effects/access + '@vben/common-ui': + specifier: workspace:* + version: link:../../packages/effects/common-ui + '@vben/constants': + specifier: workspace:* + version: link:../../packages/constants + '@vben/hooks': + specifier: workspace:* + version: link:../../packages/effects/hooks + '@vben/icons': + specifier: workspace:* + version: link:../../packages/icons + '@vben/layouts': + specifier: workspace:* + version: link:../../packages/effects/layouts + '@vben/locales': + specifier: workspace:* + version: link:../../packages/locales + '@vben/plugins': + specifier: workspace:* + version: link:../../packages/effects/plugins + '@vben/preferences': + specifier: workspace:* + version: link:../../packages/preferences + '@vben/request': + specifier: workspace:* + version: link:../../packages/effects/request + '@vben/stores': + specifier: workspace:* + version: link:../../packages/stores + '@vben/styles': + specifier: workspace:* + version: link:../../packages/styles + '@vben/types': + specifier: workspace:* + version: link:../../packages/types + '@vben/utils': + specifier: workspace:* + version: link:../../packages/utils + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + dayjs: + specifier: 'catalog:' + version: 1.11.19 + naive-ui: + specifier: 'catalog:' + version: 2.43.2(vue@3.5.28(typescript@5.9.3)) + pinia: + specifier: ^3.0.4 + version: 3.0.4(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + + apps/web-tdesign: + dependencies: + '@tinymce/tinymce-vue': + specifier: 'catalog:' + version: 6.3.0(tinymce@7.9.1)(vue@3.5.28(typescript@5.9.3)) + '@vben/access': + specifier: workspace:* + version: link:../../packages/effects/access + '@vben/common-ui': + specifier: workspace:* + version: link:../../packages/effects/common-ui + '@vben/constants': + specifier: workspace:* + version: link:../../packages/constants + '@vben/hooks': + specifier: workspace:* + version: link:../../packages/effects/hooks + '@vben/icons': + specifier: workspace:* + version: link:../../packages/icons + '@vben/layouts': + specifier: workspace:* + version: link:../../packages/effects/layouts + '@vben/locales': + specifier: workspace:* + version: link:../../packages/locales + '@vben/plugins': + specifier: workspace:* + version: link:../../packages/effects/plugins + '@vben/preferences': + specifier: workspace:* + version: link:../../packages/preferences + '@vben/request': + specifier: workspace:* + version: link:../../packages/effects/request + '@vben/stores': + specifier: workspace:* + version: link:../../packages/stores + '@vben/styles': + specifier: workspace:* + version: link:../../packages/styles + '@vben/types': + specifier: workspace:* + version: link:../../packages/types + '@vben/utils': + specifier: workspace:* + version: link:../../packages/utils + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + cropperjs: + specifier: 'catalog:' + version: 1.6.2 + dayjs: + specifier: 'catalog:' + version: 1.11.19 + es-toolkit: + specifier: 'catalog:' + version: 1.44.0 + pinia: + specifier: ^3.0.4 + version: 3.0.4(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)) + tdesign-vue-next: + specifier: 'catalog:' + version: 1.18.2(vue@3.5.28(typescript@5.9.3)) + tinymce: + specifier: 'catalog:' + version: 7.9.1 + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + + docs: + dependencies: + '@vben-core/shadcn-ui': + specifier: workspace:* + version: link:../packages/@core/ui-kit/shadcn-ui + '@vben/common-ui': + specifier: workspace:* + version: link:../packages/effects/common-ui + '@vben/locales': + specifier: workspace:* + version: link:../packages/locales + '@vben/plugins': + specifier: workspace:* + version: link:../packages/effects/plugins + '@vben/styles': + specifier: workspace:* + version: link:../packages/styles + ant-design-vue: + specifier: 'catalog:' + version: 4.2.6(vue@3.5.28(typescript@5.9.3)) + lucide-vue-next: + specifier: 'catalog:' + version: 0.553.0(vue@3.5.28(typescript@5.9.3)) + medium-zoom: + specifier: 'catalog:' + version: 1.1.0 + reka-ui: + specifier: 'catalog:' + version: 2.8.0(vue@3.5.28(typescript@5.9.3)) + vitepress-plugin-group-icons: + specifier: 'catalog:' + version: 1.7.1(vite@5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)) + devDependencies: + '@nolebase/vitepress-plugin-git-changelog': + specifier: 'catalog:' + version: 2.18.2(vitepress@1.6.4(@algolia/client-search@5.48.0)(@types/node@25.2.3)(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(less@4.5.1)(nprogress@0.2.0)(postcss@8.5.6)(qrcode@1.5.4)(sass@1.97.3)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.46.0)(typescript@5.9.3))(vue@3.5.28(typescript@5.9.3)) + '@vben/vite-config': + specifier: workspace:* + version: link:../internal/vite-config + '@vite-pwa/vitepress': + specifier: 'catalog:' + version: 1.1.0(vite-plugin-pwa@1.2.0(vite@5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0))(workbox-build@7.4.0)(workbox-window@7.4.0)) + vitepress: + specifier: 'catalog:' + version: 1.6.4(@algolia/client-search@5.48.0)(@types/node@25.2.3)(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(less@4.5.1)(nprogress@0.2.0)(postcss@8.5.6)(qrcode@1.5.4)(sass@1.97.3)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.46.0)(typescript@5.9.3) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + + internal/lint-configs/commitlint-config: + dependencies: + '@commitlint/cli': + specifier: 'catalog:' + version: 19.8.1(@types/node@24.10.13)(typescript@5.9.3) + '@commitlint/config-conventional': + specifier: 'catalog:' + version: 19.8.1 + '@vben/node-utils': + specifier: workspace:* + version: link:../../node-utils + commitlint-plugin-function-rules: + specifier: 'catalog:' + version: 4.3.1(@commitlint/lint@19.8.1) + cz-git: + specifier: 'catalog:' + version: 1.12.0 + czg: + specifier: 'catalog:' + version: 1.12.0 + + internal/lint-configs/eslint-config: + dependencies: + eslint-config-turbo: + specifier: 'catalog:' + version: 2.8.5(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.5) + eslint-plugin-command: + specifier: 'catalog:' + version: 3.4.0(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-import-x: + specifier: 'catalog:' + version: 4.16.1(@typescript-eslint/utils@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)) + devDependencies: + '@eslint/js': + specifier: 'catalog:' + version: 9.39.2 + '@types/eslint': + specifier: 'catalog:' + version: 9.6.1 + '@typescript-eslint/eslint-plugin': + specifier: 'catalog:' + version: 8.55.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': + specifier: 'catalog:' + version: 8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint: + specifier: 'catalog:' + version: 9.39.2(jiti@2.6.1) + eslint-plugin-eslint-comments: + specifier: 'catalog:' + version: 3.2.0(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-jsdoc: + specifier: 'catalog:' + version: 61.7.1(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-jsonc: + specifier: 'catalog:' + version: 2.21.1(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-n: + specifier: 'catalog:' + version: 17.23.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint-plugin-no-only-tests: + specifier: 'catalog:' + version: 3.3.0 + eslint-plugin-perfectionist: + specifier: 'catalog:' + version: 4.15.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint-plugin-pnpm: + specifier: 'catalog:' + version: 1.5.0(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-prettier: + specifier: 'catalog:' + version: 5.5.5(@types/eslint@9.6.1)(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1) + eslint-plugin-regexp: + specifier: 'catalog:' + version: 2.10.0(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-unicorn: + specifier: 'catalog:' + version: 62.0.0(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-unused-imports: + specifier: 'catalog:' + version: 4.4.1(@typescript-eslint/eslint-plugin@8.55.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-vitest: + specifier: 'catalog:' + version: 0.5.4(@typescript-eslint/eslint-plugin@8.55.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/node@25.2.3)(happy-dom@17.6.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + eslint-plugin-vue: + specifier: 'catalog:' + version: 10.7.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.39.2(jiti@2.6.1))) + eslint-plugin-yml: + specifier: 'catalog:' + version: 1.19.1(eslint@9.39.2(jiti@2.6.1)) + globals: + specifier: 'catalog:' + version: 16.5.0 + jsonc-eslint-parser: + specifier: 'catalog:' + version: 2.4.2 + vue-eslint-parser: + specifier: 'catalog:' + version: 10.2.0(eslint@9.39.2(jiti@2.6.1)) + yaml-eslint-parser: + specifier: 'catalog:' + version: 1.3.2 + + internal/lint-configs/prettier-config: + dependencies: + prettier: + specifier: 'catalog:' + version: 3.8.1 + prettier-plugin-tailwindcss: + specifier: 'catalog:' + version: 0.7.2(prettier@3.8.1) + + internal/lint-configs/stylelint-config: + dependencies: + '@stylistic/stylelint-plugin': + specifier: 'catalog:' + version: 4.0.1(stylelint@16.26.1(typescript@5.9.3)) + stylelint-config-recess-order: + specifier: 'catalog:' + version: 7.6.1(stylelint-order@7.0.1(stylelint@16.26.1(typescript@5.9.3)))(stylelint@16.26.1(typescript@5.9.3)) + stylelint-scss: + specifier: 'catalog:' + version: 6.14.0(stylelint@16.26.1(typescript@5.9.3)) + devDependencies: + postcss: + specifier: 'catalog:' + version: 8.5.6 + postcss-html: + specifier: 'catalog:' + version: 1.8.1 + postcss-scss: + specifier: 'catalog:' + version: 4.0.9(postcss@8.5.6) + prettier: + specifier: 'catalog:' + version: 3.8.1 + stylelint: + specifier: 'catalog:' + version: 16.26.1(typescript@5.9.3) + stylelint-config-recommended: + specifier: 'catalog:' + version: 17.0.0(stylelint@16.26.1(typescript@5.9.3)) + stylelint-config-recommended-scss: + specifier: 'catalog:' + version: 16.0.2(postcss@8.5.6)(stylelint@16.26.1(typescript@5.9.3)) + stylelint-config-recommended-vue: + specifier: 'catalog:' + version: 1.6.1(postcss-html@1.8.1)(stylelint@16.26.1(typescript@5.9.3)) + stylelint-config-standard: + specifier: 'catalog:' + version: 39.0.1(stylelint@16.26.1(typescript@5.9.3)) + stylelint-order: + specifier: 'catalog:' + version: 7.0.1(stylelint@16.26.1(typescript@5.9.3)) + stylelint-prettier: + specifier: 'catalog:' + version: 5.0.3(prettier@3.8.1)(stylelint@16.26.1(typescript@5.9.3)) + + internal/node-utils: + dependencies: + '@changesets/git': + specifier: 'catalog:' + version: 3.0.4 + '@manypkg/get-packages': + specifier: 'catalog:' + version: 3.1.0 + chalk: + specifier: 'catalog:' + version: 5.6.2 + consola: + specifier: 'catalog:' + version: 3.4.2 + dayjs: + specifier: 'catalog:' + version: 1.11.19 + execa: + specifier: 'catalog:' + version: 9.6.1 + find-up: + specifier: 'catalog:' + version: 7.0.0 + ora: + specifier: 'catalog:' + version: 8.2.0 + pkg-types: + specifier: 'catalog:' + version: 2.3.0 + prettier: + specifier: 'catalog:' + version: 3.8.1 + rimraf: + specifier: 'catalog:' + version: 6.1.2 + + internal/tailwind-config: + dependencies: + '@iconify/json': + specifier: 'catalog:' + version: 2.2.438 + '@iconify/tailwind': + specifier: 'catalog:' + version: 1.2.0 + '@manypkg/get-packages': + specifier: 'catalog:' + version: 3.1.0 + '@tailwindcss/nesting': + specifier: 'catalog:' + version: 0.0.0-insiders.565cd3e(postcss@8.5.6) + '@tailwindcss/typography': + specifier: 'catalog:' + version: 0.5.19(tailwindcss@3.4.19(yaml@2.8.2)) + autoprefixer: + specifier: 'catalog:' + version: 10.4.24(postcss@8.5.6) + cssnano: + specifier: 'catalog:' + version: 7.1.2(postcss@8.5.6) + jiti: + specifier: ^2.6.1 + version: 2.6.1 + postcss: + specifier: 'catalog:' + version: 8.5.6 + postcss-antd-fixes: + specifier: 'catalog:' + version: 0.2.0(postcss@8.5.6) + postcss-import: + specifier: 'catalog:' + version: 16.1.1(postcss@8.5.6) + postcss-preset-env: + specifier: 'catalog:' + version: 10.6.1(postcss@8.5.6) + tailwindcss: + specifier: 'catalog:' + version: 3.4.19(yaml@2.8.2) + tailwindcss-animate: + specifier: 'catalog:' + version: 1.0.7(tailwindcss@3.4.19(yaml@2.8.2)) + devDependencies: + '@types/postcss-import': + specifier: 'catalog:' + version: 14.0.3 + + internal/tsconfig: + dependencies: + '@vben/types': + specifier: workspace:* + version: link:../../packages/types + vite: + specifier: 'catalog:' + version: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + + internal/vite-config: + dependencies: + '@intlify/unplugin-vue-i18n': + specifier: 'catalog:' + version: 6.0.8(@vue/compiler-dom@3.5.28)(eslint@9.39.2(jiti@2.6.1))(rollup@4.57.1)(typescript@5.9.3)(vue-i18n@11.2.8(vue@3.5.28(typescript@5.9.3)))(vue@3.5.28(typescript@5.9.3)) + '@jspm/generator': + specifier: 'catalog:' + version: 2.10.0 + archiver: + specifier: 'catalog:' + version: 7.0.1 + cheerio: + specifier: 'catalog:' + version: 1.2.0 + get-port: + specifier: 'catalog:' + version: 7.1.0 + html-minifier-terser: + specifier: 'catalog:' + version: 7.2.0 + nitropack: + specifier: 'catalog:' + version: 2.13.1 + resolve.exports: + specifier: 'catalog:' + version: 2.0.3 + vite-plugin-pwa: + specifier: 'catalog:' + version: 1.2.0(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(workbox-build@7.4.0)(workbox-window@7.4.0) + vite-plugin-vue-devtools: + specifier: 'catalog:' + version: 8.0.6(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3)) + devDependencies: + '@pnpm/workspace.read-manifest': + specifier: 'catalog:' + version: 1000.2.10 + '@types/archiver': + specifier: 'catalog:' + version: 6.0.4 + '@types/html-minifier-terser': + specifier: 'catalog:' + version: 7.0.2 + '@vben/node-utils': + specifier: workspace:* + version: link:../node-utils + '@vitejs/plugin-vue': + specifier: 'catalog:' + version: 6.0.4(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3)) + '@vitejs/plugin-vue-jsx': + specifier: 'catalog:' + version: 5.1.4(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3)) + dayjs: + specifier: 'catalog:' + version: 1.11.19 + dotenv: + specifier: 'catalog:' + version: 16.6.1 + rollup: + specifier: 'catalog:' + version: 4.57.1 + rollup-plugin-visualizer: + specifier: 'catalog:' + version: 5.14.0(rollup@4.57.1) + sass: + specifier: 'catalog:' + version: 1.97.3 + vite: + specifier: 'catalog:' + version: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite-plugin-compression: + specifier: 'catalog:' + version: 0.5.1(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + vite-plugin-dts: + specifier: 'catalog:' + version: 4.5.4(@types/node@25.2.3)(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + vite-plugin-html: + specifier: 'catalog:' + version: 3.2.2(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + vite-plugin-lazy-import: + specifier: 'catalog:' + version: 1.0.7 + + packages/@core/base/design: {} + + packages/@core/base/icons: + dependencies: + '@iconify/vue': + specifier: 'catalog:' + version: 5.0.0(vue@3.5.28(typescript@5.9.3)) + lucide-vue-next: + specifier: 'catalog:' + version: 0.553.0(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + + packages/@core/base/shared: + dependencies: + '@ctrl/tinycolor': + specifier: ^4.2.0 + version: 4.2.0 + '@tanstack/vue-store': + specifier: 'catalog:' + version: 0.8.0(vue@3.5.28(typescript@5.9.3)) + '@vue/shared': + specifier: 'catalog:' + version: 3.5.28 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + crypto-js: + specifier: 'catalog:' + version: 4.2.0 + dayjs: + specifier: 'catalog:' + version: 1.11.19 + defu: + specifier: 'catalog:' + version: 6.1.4 + es-toolkit: + specifier: 'catalog:' + version: 1.44.0 + jsencrypt: + specifier: 'catalog:' + version: 3.5.4 + lodash.clonedeep: + specifier: 'catalog:' + version: 4.5.0 + nprogress: + specifier: 'catalog:' + version: 0.2.0 + tailwind-merge: + specifier: 'catalog:' + version: 2.6.1 + theme-colors: + specifier: 'catalog:' + version: 0.1.0 + devDependencies: + '@types/crypto-js': + specifier: 'catalog:' + version: 4.2.2 + '@types/lodash.clonedeep': + specifier: 'catalog:' + version: 4.5.9 + '@types/nprogress': + specifier: 'catalog:' + version: 0.2.3 + + packages/@core/base/typings: + dependencies: + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + + packages/@core/composables: + dependencies: + '@vben-core/shared': + specifier: workspace:* + version: link:../base/shared + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + reka-ui: + specifier: 'catalog:' + version: 2.8.0(vue@3.5.28(typescript@5.9.3)) + sortablejs: + specifier: 'catalog:' + version: 1.15.6 + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + devDependencies: + '@types/sortablejs': + specifier: 'catalog:' + version: 1.15.9 + + packages/@core/preferences: + dependencies: + '@vben-core/shared': + specifier: workspace:* + version: link:../base/shared + '@vben-core/typings': + specifier: workspace:* + version: link:../base/typings + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + + packages/@core/ui-kit/form-ui: + dependencies: + '@vben-core/composables': + specifier: workspace:* + version: link:../../composables + '@vben-core/icons': + specifier: workspace:* + version: link:../../base/icons + '@vben-core/shadcn-ui': + specifier: workspace:* + version: link:../shadcn-ui + '@vben-core/shared': + specifier: workspace:* + version: link:../../base/shared + '@vben-core/typings': + specifier: workspace:* + version: link:../../base/typings + '@vee-validate/zod': + specifier: 'catalog:' + version: 4.15.1(vue@3.5.28(typescript@5.9.3))(zod@3.25.76) + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + vee-validate: + specifier: 'catalog:' + version: 4.15.1(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + zod: + specifier: 'catalog:' + version: 3.25.76 + zod-defaults: + specifier: 'catalog:' + version: 0.1.3(zod@3.25.76) + + packages/@core/ui-kit/layout-ui: + dependencies: + '@vben-core/composables': + specifier: workspace:* + version: link:../../composables + '@vben-core/icons': + specifier: workspace:* + version: link:../../base/icons + '@vben-core/shadcn-ui': + specifier: workspace:* + version: link:../shadcn-ui + '@vben-core/shared': + specifier: workspace:* + version: link:../../base/shared + '@vben-core/typings': + specifier: workspace:* + version: link:../../base/typings + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + + packages/@core/ui-kit/menu-ui: + dependencies: + '@vben-core/composables': + specifier: workspace:* + version: link:../../composables + '@vben-core/icons': + specifier: workspace:* + version: link:../../base/icons + '@vben-core/shadcn-ui': + specifier: workspace:* + version: link:../shadcn-ui + '@vben-core/shared': + specifier: workspace:* + version: link:../../base/shared + '@vben-core/typings': + specifier: workspace:* + version: link:../../base/typings + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + + packages/@core/ui-kit/popup-ui: + dependencies: + '@vben-core/composables': + specifier: workspace:* + version: link:../../composables + '@vben-core/icons': + specifier: workspace:* + version: link:../../base/icons + '@vben-core/shadcn-ui': + specifier: workspace:* + version: link:../shadcn-ui + '@vben-core/shared': + specifier: workspace:* + version: link:../../base/shared + '@vben-core/typings': + specifier: workspace:* + version: link:../../base/typings + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + + packages/@core/ui-kit/shadcn-ui: + dependencies: + '@vben-core/composables': + specifier: workspace:* + version: link:../../composables + '@vben-core/icons': + specifier: workspace:* + version: link:../../base/icons + '@vben-core/shared': + specifier: workspace:* + version: link:../../base/shared + '@vben-core/typings': + specifier: workspace:* + version: link:../../base/typings + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + class-variance-authority: + specifier: 'catalog:' + version: 0.7.1 + lucide-vue-next: + specifier: 'catalog:' + version: 0.553.0(vue@3.5.28(typescript@5.9.3)) + reka-ui: + specifier: 'catalog:' + version: 2.8.0(vue@3.5.28(typescript@5.9.3)) + vee-validate: + specifier: 'catalog:' + version: 4.15.1(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + + packages/@core/ui-kit/tabs-ui: + dependencies: + '@vben-core/composables': + specifier: workspace:* + version: link:../../composables + '@vben-core/icons': + specifier: workspace:* + version: link:../../base/icons + '@vben-core/shadcn-ui': + specifier: workspace:* + version: link:../shadcn-ui + '@vben-core/typings': + specifier: workspace:* + version: link:../../base/typings + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + + packages/constants: + dependencies: + '@vben-core/shared': + specifier: workspace:* + version: link:../@core/base/shared + + packages/effects/access: + dependencies: + '@vben/preferences': + specifier: workspace:* + version: link:../../preferences + '@vben/stores': + specifier: workspace:* + version: link:../../stores + '@vben/types': + specifier: workspace:* + version: link:../../types + '@vben/utils': + specifier: workspace:* + version: link:../../utils + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + + packages/effects/common-ui: + dependencies: + '@vben-core/form-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/form-ui + '@vben-core/popup-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/popup-ui + '@vben-core/preferences': + specifier: workspace:* + version: link:../../@core/preferences + '@vben-core/shadcn-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/shadcn-ui + '@vben-core/shared': + specifier: workspace:* + version: link:../../@core/base/shared + '@vben/constants': + specifier: workspace:* + version: link:../../constants + '@vben/hooks': + specifier: workspace:* + version: link:../hooks + '@vben/icons': + specifier: workspace:* + version: link:../../icons + '@vben/locales': + specifier: workspace:* + version: link:../../locales + '@vben/types': + specifier: workspace:* + version: link:../../types + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + '@vueuse/integrations': + specifier: 'catalog:' + version: 14.2.1(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(focus-trap@7.8.0)(nprogress@0.2.0)(qrcode@1.5.4)(sortablejs@1.15.6)(vue@3.5.28(typescript@5.9.3)) + json-bigint: + specifier: 'catalog:' + version: 1.0.0 + qrcode: + specifier: 'catalog:' + version: 1.5.4 + tippy.js: + specifier: 'catalog:' + version: 6.3.7 + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-json-viewer: + specifier: 'catalog:' + version: 3.0.4(vue@3.5.28(typescript@5.9.3)) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + vue-tippy: + specifier: 'catalog:' + version: 6.7.1(vue@3.5.28(typescript@5.9.3)) + devDependencies: + '@types/qrcode': + specifier: 'catalog:' + version: 1.5.6 + + packages/effects/hooks: + dependencies: + '@vben-core/composables': + specifier: workspace:* + version: link:../../@core/composables + '@vben/preferences': + specifier: workspace:* + version: link:../../preferences + '@vben/stores': + specifier: workspace:* + version: link:../../stores + '@vben/types': + specifier: workspace:* + version: link:../../types + '@vben/utils': + specifier: workspace:* + version: link:../../utils + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + watermark-js-plus: + specifier: 'catalog:' + version: 1.6.3 + + packages/effects/layouts: + dependencies: + '@vben-core/composables': + specifier: workspace:* + version: link:../../@core/composables + '@vben-core/form-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/form-ui + '@vben-core/layout-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/layout-ui + '@vben-core/menu-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/menu-ui + '@vben-core/popup-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/popup-ui + '@vben-core/shadcn-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/shadcn-ui + '@vben-core/shared': + specifier: workspace:* + version: link:../../@core/base/shared + '@vben-core/tabs-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/tabs-ui + '@vben/constants': + specifier: workspace:* + version: link:../../constants + '@vben/hooks': + specifier: workspace:* + version: link:../hooks + '@vben/icons': + specifier: workspace:* + version: link:../../icons + '@vben/locales': + specifier: workspace:* + version: link:../../locales + '@vben/preferences': + specifier: workspace:* + version: link:../../preferences + '@vben/stores': + specifier: workspace:* + version: link:../../stores + '@vben/types': + specifier: workspace:* + version: link:../../types + '@vben/utils': + specifier: workspace:* + version: link:../../utils + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + + packages/effects/plugins: + dependencies: + '@tinyflow-ai/vue': + specifier: 'catalog:' + version: 1.1.10(svelte@5.50.1)(vue@3.5.28(typescript@5.9.3)) + '@vben-core/form-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/form-ui + '@vben-core/shadcn-ui': + specifier: workspace:* + version: link:../../@core/ui-kit/shadcn-ui + '@vben-core/shared': + specifier: workspace:* + version: link:../../@core/base/shared + '@vben/hooks': + specifier: workspace:* + version: link:../hooks + '@vben/icons': + specifier: workspace:* + version: link:../../icons + '@vben/locales': + specifier: workspace:* + version: link:../../locales + '@vben/preferences': + specifier: workspace:* + version: link:../../preferences + '@vben/types': + specifier: workspace:* + version: link:../../types + '@vben/utils': + specifier: workspace:* + version: link:../../utils + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.28(typescript@5.9.3)) + '@vueuse/motion': + specifier: 'catalog:' + version: 3.0.3(magicast@0.5.2)(vue@3.5.28(typescript@5.9.3)) + codemirror: + specifier: 'catalog:' + version: 5.65.21 + echarts: + specifier: 'catalog:' + version: 6.0.0 + markdown-it: + specifier: 'catalog:' + version: 14.1.0 + markmap-common: + specifier: 'catalog:' + version: 0.16.0 + markmap-lib: + specifier: 'catalog:' + version: 0.16.1(markmap-common@0.16.0) + markmap-toolbar: + specifier: 'catalog:' + version: 0.17.2(markmap-common@0.16.0) + markmap-view: + specifier: 'catalog:' + version: 0.16.0(markmap-common@0.16.0) + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vxe-pc-ui: + specifier: 'catalog:' + version: 4.12.36(vue@3.5.28(typescript@5.9.3)) + vxe-table: + specifier: 'catalog:' + version: 4.17.48(vue@3.5.28(typescript@5.9.3)) + devDependencies: + '@types/codemirror': + specifier: 'catalog:' + version: 5.60.17 + '@types/markdown-it': + specifier: 'catalog:' + version: 14.1.2 + + packages/effects/request: + dependencies: + '@microsoft/fetch-event-source': + specifier: 'catalog:' + version: 2.0.1 + '@vben/locales': + specifier: workspace:* + version: link:../../locales + '@vben/utils': + specifier: workspace:* + version: link:../../utils + axios: + specifier: 'catalog:' + version: 1.13.5 + qs: + specifier: 'catalog:' + version: 6.14.1 + devDependencies: + '@types/qs': + specifier: 'catalog:' + version: 6.14.0 + axios-mock-adapter: + specifier: 'catalog:' + version: 2.1.0(axios@1.13.5) + + packages/icons: + dependencies: + '@vben-core/icons': + specifier: workspace:* + version: link:../@core/base/icons + + packages/locales: + dependencies: + '@intlify/core-base': + specifier: 'catalog:' + version: 11.2.8 + '@vben-core/composables': + specifier: workspace:* + version: link:../@core/composables + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-i18n: + specifier: 'catalog:' + version: 11.2.8(vue@3.5.28(typescript@5.9.3)) + + packages/preferences: + dependencies: + '@vben-core/preferences': + specifier: workspace:* + version: link:../@core/preferences + '@vben-core/typings': + specifier: workspace:* + version: link:../@core/base/typings + + packages/stores: + dependencies: + '@vben-core/preferences': + specifier: workspace:* + version: link:../@core/preferences + '@vben-core/shared': + specifier: workspace:* + version: link:../@core/base/shared + '@vben-core/typings': + specifier: workspace:* + version: link:../@core/base/typings + pinia: + specifier: ^3.0.4 + version: 3.0.4(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)) + pinia-plugin-persistedstate: + specifier: 'catalog:' + version: 4.7.1(@nuxt/kit@4.3.1(magicast@0.5.2))(pinia@3.0.4(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3))) + secure-ls: + specifier: 'catalog:' + version: 2.0.0 + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + + packages/styles: + dependencies: + '@vben-core/design': + specifier: workspace:* + version: link:../@core/base/design + + packages/types: + dependencies: + '@vben-core/typings': + specifier: workspace:* + version: link:../@core/base/typings + vue: + specifier: ^3.5.27 + version: 3.5.28(typescript@5.9.3) + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + + packages/utils: + dependencies: + '@vben-core/shared': + specifier: workspace:* + version: link:../@core/base/shared + '@vben-core/typings': + specifier: workspace:* + version: link:../@core/base/typings + vue-router: + specifier: 'catalog:' + version: 4.6.4(vue@3.5.28(typescript@5.9.3)) + + scripts/turbo-run: + dependencies: + '@clack/prompts': + specifier: 'catalog:' + version: 0.11.0 + '@vben/node-utils': + specifier: workspace:* + version: link:../../internal/node-utils + cac: + specifier: 'catalog:' + version: 6.7.14 + + scripts/vsh: + dependencies: + '@vben/node-utils': + specifier: workspace:* + version: link:../../internal/node-utils + cac: + specifier: 'catalog:' + version: 6.7.14 + circular-dependency-scanner: + specifier: 'catalog:' + version: 2.3.0 + depcheck: + specifier: 'catalog:' + version: 1.4.7 + publint: + specifier: 'catalog:' + version: 0.3.17 + +packages: + + '@algolia/abtesting@1.14.0': + resolution: {integrity: sha512-cZfj+1Z1dgrk3YPtNQNt0H9Rr67P8b4M79JjUKGS0d7/EbFbGxGgSu6zby5f22KXo3LT0LZa4O2c6VVbupJuDg==} + engines: {node: '>= 14.0.0'} + + '@algolia/autocomplete-core@1.17.7': + resolution: {integrity: sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==} + + '@algolia/autocomplete-plugin-algolia-insights@1.17.7': + resolution: {integrity: sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==} + peerDependencies: + search-insights: '>= 1 < 3' + + '@algolia/autocomplete-preset-algolia@1.17.7': + resolution: {integrity: sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' + + '@algolia/autocomplete-shared@1.17.7': + resolution: {integrity: sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' + + '@algolia/client-abtesting@5.48.0': + resolution: {integrity: sha512-n17WSJ7vazmM6yDkWBAjY12J8ERkW9toOqNgQ1GEZu/Kc4dJDJod1iy+QP5T/UlR3WICgZDi/7a/VX5TY5LAPQ==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-analytics@5.48.0': + resolution: {integrity: sha512-v5bMZMEqW9U2l40/tTAaRyn4AKrYLio7KcRuHmLaJtxuJAhvZiE7Y62XIsF070juz4MN3eyvfQmI+y5+OVbZuA==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-common@5.48.0': + resolution: {integrity: sha512-7H3DgRyi7UByScc0wz7EMrhgNl7fKPDjKX9OcWixLwCj7yrRXDSIzwunykuYUUO7V7HD4s319e15FlJ9CQIIFQ==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-insights@5.48.0': + resolution: {integrity: sha512-tXmkB6qrIGAXrtRYHQNpfW0ekru/qymV02bjT0w5QGaGw0W91yT+53WB6dTtRRsIrgS30Al6efBvyaEosjZ5uw==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-personalization@5.48.0': + resolution: {integrity: sha512-4tXEsrdtcBZbDF73u14Kb3otN+xUdTVGop1tBjict+Rc/FhsJQVIwJIcTrOJqmvhtBfc56Bu65FiVOnpAZCxcw==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-query-suggestions@5.48.0': + resolution: {integrity: sha512-unzSUwWFpsDrO8935RhMAlyK0Ttua/5XveVIwzfjs5w+GVBsHgIkbOe8VbBJccMU/z1LCwvu1AY3kffuSLAR5Q==} + engines: {node: '>= 14.0.0'} + + '@algolia/client-search@5.48.0': + resolution: {integrity: sha512-RB9bKgYTVUiOcEb5bOcZ169jiiVW811dCsJoLT19DcbbFmU4QaK0ghSTssij35QBQ3SCOitXOUrHcGgNVwS7sQ==} + engines: {node: '>= 14.0.0'} + + '@algolia/ingestion@1.48.0': + resolution: {integrity: sha512-rhoSoPu+TDzDpvpk3cY/pYgbeWXr23DxnAIH/AkN0dUC+GCnVIeNSQkLaJ+CL4NZ51cjLIjksrzb4KC5Xu+ktw==} + engines: {node: '>= 14.0.0'} + + '@algolia/monitoring@1.48.0': + resolution: {integrity: sha512-aSe6jKvWt+8VdjOaq2ERtsXp9+qMXNJ3mTyTc1VMhNfgPl7ArOhRMRSQ8QBnY8ZL4yV5Xpezb7lAg8pdGrrulg==} + engines: {node: '>= 14.0.0'} + + '@algolia/recommend@5.48.0': + resolution: {integrity: sha512-p9tfI1bimAaZrdiVExL/dDyGUZ8gyiSHsktP1ZWGzt5hXpM3nhv4tSjyHtXjEKtA0UvsaHKwSfFE8aAAm1eIQA==} + engines: {node: '>= 14.0.0'} + + '@algolia/requester-browser-xhr@5.48.0': + resolution: {integrity: sha512-XshyfpsQB7BLnHseMinp3fVHOGlTv6uEHOzNK/3XrEF9mjxoZAcdVfY1OCXObfwRWX5qXZOq8FnrndFd44iVsQ==} + engines: {node: '>= 14.0.0'} + + '@algolia/requester-fetch@5.48.0': + resolution: {integrity: sha512-Q4XNSVQU89bKNAPuvzSYqTH9AcbOOiIo6AeYMQTxgSJ2+uvT78CLPMG89RIIloYuAtSfE07s40OLV50++l1Bbw==} + engines: {node: '>= 14.0.0'} + + '@algolia/requester-node-http@5.48.0': + resolution: {integrity: sha512-ZgxV2+5qt3NLeUYBTsi6PLyHcENQWC0iFppFZekHSEDA2wcLdTUjnaJzimTEULHIvJuLRCkUs4JABdhuJktEag==} + engines: {node: '>= 14.0.0'} + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@ant-design/colors@6.0.0': + resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==} + + '@ant-design/colors@7.2.1': + resolution: {integrity: sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==} + + '@ant-design/fast-color@2.0.6': + resolution: {integrity: sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==} + engines: {node: '>=8.x'} + + '@ant-design/fast-color@3.0.1': + resolution: {integrity: sha512-esKJegpW4nckh0o6kV3Tkb7NPIZYbPnnFxmQDUmL08ukXZAvV85TZBr70eGuke/CIArLaP6aw8lt9KILjnWuOw==} + engines: {node: '>=8.x'} + + '@ant-design/icons-svg@4.4.2': + resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==} + + '@ant-design/icons-vue@7.0.1': + resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==} + peerDependencies: + vue: ^3.5.27 + + '@antdv-next/cssinjs@1.0.1': + resolution: {integrity: sha512-9C7f2dZ7seDLuRU7dy23dmyxsWGZyHl9OriDQvamYHjqpKf6WdJhdUkQpTZ7q63t6h5JXrDgX4VYZH3JD6hX3g==} + peerDependencies: + vue: ^3.5.27 + + '@antdv-next/icons@1.0.0': + resolution: {integrity: sha512-O3gxRGEYOYsNbyPuhEqZ+HIDTakl6v3ukBDQwZ3ZvbzOPBorgdhMhHQ1WFjlLBCo72bdx5/wKyjz6oFRhk0G+g==} + peerDependencies: + vue: ^3.5.27 + + '@antfu/install-pkg@1.1.0': + resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} + + '@apideck/better-ajv-errors@0.3.6': + resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==} + engines: {node: '>=10'} + peerDependencies: + ajv: '>=8' + + '@ast-grep/napi-darwin-arm64@0.39.9': + resolution: {integrity: sha512-0gdBC2oPBkIBsh89yUXxJeK37QYRbp1qNZVuRGizT666ljgCw+2NIxHeQGNjwWuI0+g3exrd8FyqD3gMixRx3w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@ast-grep/napi-darwin-x64@0.39.9': + resolution: {integrity: sha512-7QuQNFwcVj71hDAMBErF+mVq2h92vUdHLKa/vq58HdRpix5G3DZqcTKoFjwhCNzc2wsNRAjV+BiIR01znQSxLA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@ast-grep/napi-linux-arm64-gnu@0.39.9': + resolution: {integrity: sha512-qXTjhagRYkPyHNACEzGi5q26OMRdSvLRRqi799oZaSDf96Xj+8tcB5+tFlH0NpqaP84GsZoQ15SfDXeoP4qdmQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@ast-grep/napi-linux-arm64-musl@0.39.9': + resolution: {integrity: sha512-U9KVohyburVGEWiiREFq+iTxdMdSbRyXL+yzCVvGPmLPW4Ca4zpX9Cret4jCJBp8dljSIK0C7txXAc7fM+6rag==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@ast-grep/napi-linux-x64-gnu@0.39.9': + resolution: {integrity: sha512-C5WwiNr/eE7lS0vl9bNdSXrsGIUAga2SaqV3G+ogVl9HeRU2jtGhv+3AgzGvYWj+PtnbtuZ2Nxkm10gEVPhv1A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@ast-grep/napi-linux-x64-musl@0.39.9': + resolution: {integrity: sha512-KutzZSMhHP3P43nQ+kNSbuiDaqkCcdqOcXLnq28MRvS+qwvW+01dJ8eWRlpMJC9vCJmaJAZfI7xkNSp74WkdxA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@ast-grep/napi-win32-arm64-msvc@0.39.9': + resolution: {integrity: sha512-S2kC6K9I7e70oMVn2FDICzVlz7SPZVWNCRKCBD+Dgy1OTn0byzmMLaGpjth3pqN93UCssEC03ooP3tuclS0JSA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@ast-grep/napi-win32-ia32-msvc@0.39.9': + resolution: {integrity: sha512-n18Dqtc7O5q8ZM9gBNkvLd+ajdjLNraw4ZoIcHelI7TnTvh1m6zR3tUuHNxPhL+IJfdKx3ne7ATKlEeiSlMn4g==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@ast-grep/napi-win32-x64-msvc@0.39.9': + resolution: {integrity: sha512-YOF7mO+6nvyRtMC179u82Vr1qIGOmoE1yjwr4cmAf7DVNd+vs42y9tbQGYwLmVY8M3Hg1PviB8XX7FQKewuOGQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@ast-grep/napi@0.39.9': + resolution: {integrity: sha512-qtLLQq1a3isK0iaq0Drl7Qt4PqeyjTrpFxNdA/20O/jYkGiA/oJA8DLMn1bzczsfjlUohe4dg39bpeAqG02uvA==} + engines: {node: '>= 10'} + + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.28.6': + resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.28.5': + resolution: {integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.6': + resolution: {integrity: sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.28.5': + resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.27.1': + resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.28.6': + resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.28.6': + resolution: {integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.6': + resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.0': + resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': + resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': + resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': + resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': + resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6': + resolution: {integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-decorators@7.29.0': + resolution: {integrity: sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.28.6': + resolution: {integrity: sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.28.6': + resolution: {integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.28.6': + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.28.6': + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.28.6': + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.27.1': + resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.29.0': + resolution: {integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.28.6': + resolution: {integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.27.1': + resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.28.6': + resolution: {integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.28.6': + resolution: {integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.28.6': + resolution: {integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.28.6': + resolution: {integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.28.6': + resolution: {integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.28.5': + resolution: {integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.28.6': + resolution: {integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.27.1': + resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.27.1': + resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-explicit-resource-management@7.28.6': + resolution: {integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.28.6': + resolution: {integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.27.1': + resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.27.1': + resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.27.1': + resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.28.6': + resolution: {integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.27.1': + resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.28.6': + resolution: {integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.27.1': + resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.27.1': + resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.28.6': + resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.29.0': + resolution: {integrity: sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.27.1': + resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.27.1': + resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6': + resolution: {integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.28.6': + resolution: {integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.28.6': + resolution: {integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.27.1': + resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.28.6': + resolution: {integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.28.6': + resolution: {integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.27.7': + resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.28.6': + resolution: {integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.28.6': + resolution: {integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.27.1': + resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.29.0': + resolution: {integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.28.6': + resolution: {integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.27.1': + resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.27.1': + resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.28.6': + resolution: {integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.27.1': + resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.27.1': + resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.27.1': + resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.28.6': + resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.27.1': + resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.28.6': + resolution: {integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.27.1': + resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.28.6': + resolution: {integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.29.0': + resolution: {integrity: sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/preset-typescript@7.28.5': + resolution: {integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime-corejs3@7.29.0': + resolution: {integrity: sha512-TgUkdp71C9pIbBcHudc+gXZnihEDOjUAmXO1VO4HHGES7QLZcShR0stfKIxLSNIYx2fqhmJChOjm/wkF8wv4gA==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@bpmn-io/cm-theme@0.1.0-alpha.2': + resolution: {integrity: sha512-ZILgiYzxk3KMvxplUXmdRFQo45/JehDPg5k9tWfehmzUOSE13ssyLPil8uCloMQnb3yyzyOWTjb/wzKXTHlFQw==} + + '@bpmn-io/diagram-js-ui@0.2.3': + resolution: {integrity: sha512-OGyjZKvGK8tHSZ0l7RfeKhilGoOGtFDcoqSGYkX0uhFlo99OVZ9Jn1K7TJGzcE9BdKwvA5Y5kGqHEhdTxHvFfw==} + + '@bpmn-io/extract-process-variables@0.8.0': + resolution: {integrity: sha512-yAS7ZYX+D56K+luC36u96eRMLb4VHcPUwTUqMZ/Z/Je2gou2DJLRbuBTHAB4jjKt4wFCHSG4B8Y+TrBciEYf4w==} + + '@bpmn-io/feel-editor@2.4.0': + resolution: {integrity: sha512-/2fRDDEYb07zacdsFn1nn0W3gV/XkT2YSpHfa9HpyeyYzHWT2bCeU5YkIPxtROrJdScqGuCcCQV2IuxAfgjjhw==} + engines: {node: '>= 20'} + + '@bpmn-io/feel-lint@3.1.0': + resolution: {integrity: sha512-nOCYWMXgwR0joU4XKhu4f3P5f4/AsmuyiV1e+fzcXTCh7iMLU8VYdHXSIzZuJ0zxz3Gsnp7A8S8lt+HJ43H6IA==} + + '@bpmn-io/feelin@6.1.0': + resolution: {integrity: sha512-nqmmlHRD9tl0ZcpYTEkZdpc/rAMoYc+ct0SOg9fFIFWRaEApme3DuXC7v9AMA5g+upGCKd6cUc3t97y+unpfMw==} + engines: {node: '>= 20.12.0'} + + '@bpmn-io/lang-feel@3.0.0': + resolution: {integrity: sha512-t/k0z5AW18J7Qz2i/bIFAlvlcS63RuyQB9OQ0YiC1WyMosxXRAnv98LHnVbwirx9vje1DLll85tkBT2B8KLjmQ==} + engines: {node: '>= 20.12.0'} + + '@bpmn-io/lezer-feel@2.2.1': + resolution: {integrity: sha512-X/8DIoTIW+F9dI2Pr2M66tGT8q83ZXLAwVYqHVUWw9STXbbCs7Aluy6CxW8EpXD1rur15pbP1ZkXQDIFkx55rA==} + engines: {node: '>= 20.12.0'} + + '@bpmn-io/properties-panel@3.38.0': + resolution: {integrity: sha512-o8Oih4ILK93cMyD1FO1rnLL5GvWqbzFM8R14RhEheNUXvfd8/VnwOHpMlXvqlJ5zX8GTN9VBks3jmt7HQf0slg==} + + '@cacheable/memory@2.0.7': + resolution: {integrity: sha512-RbxnxAMf89Tp1dLhXMS7ceft/PGsDl1Ip7T20z5nZ+pwIAsQ1p2izPjVG69oCLv/jfQ7HDPHTWK0c9rcAWXN3A==} + + '@cacheable/utils@2.3.4': + resolution: {integrity: sha512-knwKUJEYgIfwShABS1BX6JyJJTglAFcEU7EXqzTdiGCXur4voqkiJkdgZIQtWNFhynzDWERcTYv/sETMu3uJWA==} + + '@camunda/feel-builtins@0.3.0': + resolution: {integrity: sha512-pLz9GC2aXyWOk7fYnimnXZZh75X4TGmy//4FQW9yp+9I2voyUZAg+7vBOo+FzAeIiBMU9aEjrYfX8hBpzIkc+A==} + + '@carbon/icons@11.74.0': + resolution: {integrity: sha512-tKAUXSgzLvov2gidRb3/U1NvUWKqxfG3anmWMz7WnTj/W3aK6PXpvgfspqPMOnBsnuF5q5H3Csq6XJ99dUZ5ig==} + + '@changesets/apply-release-plan@7.0.14': + resolution: {integrity: sha512-ddBvf9PHdy2YY0OUiEl3TV78mH9sckndJR14QAt87KLEbIov81XO0q0QAmvooBxXlqRRP8I9B7XOzZwQG7JkWA==} + + '@changesets/assemble-release-plan@6.0.9': + resolution: {integrity: sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==} + + '@changesets/changelog-git@0.2.1': + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} + + '@changesets/changelog-github@0.5.2': + resolution: {integrity: sha512-HeGeDl8HaIGj9fQHo/tv5XKQ2SNEi9+9yl1Bss1jttPqeiASRXhfi0A2wv8yFKCp07kR1gpOI5ge6+CWNm1jPw==} + + '@changesets/cli@2.29.8': + resolution: {integrity: sha512-1weuGZpP63YWUYjay/E84qqwcnt5yJMM0tep10Up7Q5cS/DGe2IZ0Uj3HNMxGhCINZuR7aO9WBMdKnPit5ZDPA==} + hasBin: true + + '@changesets/config@3.1.2': + resolution: {integrity: sha512-CYiRhA4bWKemdYi/uwImjPxqWNpqGPNbEBdX1BdONALFIDK7MCUj6FPkzD+z9gJcvDFUQJn9aDVf4UG7OT6Kog==} + + '@changesets/errors@0.2.0': + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + + '@changesets/get-dependents-graph@2.1.3': + resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} + + '@changesets/get-github-info@0.7.0': + resolution: {integrity: sha512-+i67Bmhfj9V4KfDeS1+Tz3iF32btKZB2AAx+cYMqDSRFP7r3/ZdGbjCo+c6qkyViN9ygDuBjzageuPGJtKGe5A==} + + '@changesets/get-release-plan@4.0.14': + resolution: {integrity: sha512-yjZMHpUHgl4Xl5gRlolVuxDkm4HgSJqT93Ri1Uz8kGrQb+5iJ8dkXJ20M2j/Y4iV5QzS2c5SeTxVSKX+2eMI0g==} + + '@changesets/get-version-range-type@0.4.0': + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + + '@changesets/git@3.0.4': + resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} + + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} + + '@changesets/parse@0.4.2': + resolution: {integrity: sha512-Uo5MC5mfg4OM0jU3up66fmSn6/NE9INK+8/Vn/7sMVcdWg46zfbvvUSjD9EMonVqPi9fbrJH9SXHn48Tr1f2yA==} + + '@changesets/pre@2.0.2': + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} + + '@changesets/read@0.6.6': + resolution: {integrity: sha512-P5QaN9hJSQQKJShzzpBT13FzOSPyHbqdoIBUd2DJdgvnECCyO6LmAOWSV+O8se2TaZJVwSXjL+v9yhb+a9JeJg==} + + '@changesets/should-skip-package@0.1.2': + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} + + '@changesets/types@4.1.0': + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + + '@changesets/types@6.1.0': + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} + + '@changesets/write@0.4.0': + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + + '@clack/core@0.5.0': + resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==} + + '@clack/prompts@0.11.0': + resolution: {integrity: sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw==} + + '@cloudflare/kv-asset-handler@0.4.2': + resolution: {integrity: sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==} + engines: {node: '>=18.0.0'} + + '@codemirror/autocomplete@6.20.0': + resolution: {integrity: sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==} + + '@codemirror/commands@6.10.2': + resolution: {integrity: sha512-vvX1fsih9HledO1c9zdotZYUZnE4xV0m6i3m25s5DIfXofuprk6cRcLUZvSk3CASUbwjQX21tOGbkY2BH8TpnQ==} + + '@codemirror/language@6.12.1': + resolution: {integrity: sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ==} + + '@codemirror/lint@6.9.3': + resolution: {integrity: sha512-y3YkYhdnhjDBAe0VIA0c4wVoFOvnp8CnAvfLqi0TqotIv92wIlAAP7HELOpLBsKwjAX6W92rSflA6an/2zBvXw==} + + '@codemirror/state@6.5.4': + resolution: {integrity: sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw==} + + '@codemirror/view@6.39.13': + resolution: {integrity: sha512-QBO8ZsgJLCbI28KdY0/oDy5NQLqOQVZCozBknxc2/7L98V+TVYFHnfaCsnGh1U+alpd2LOkStVwYY7nW2R1xbw==} + + '@commitlint/cli@19.8.1': + resolution: {integrity: sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA==} + engines: {node: '>=v18'} + hasBin: true + + '@commitlint/config-conventional@19.8.1': + resolution: {integrity: sha512-/AZHJL6F6B/G959CsMAzrPKKZjeEiAVifRyEwXxcT6qtqbPwGw+iQxmNS+Bu+i09OCtdNRW6pNpBvgPrtMr9EQ==} + engines: {node: '>=v18'} + + '@commitlint/config-validator@19.8.1': + resolution: {integrity: sha512-0jvJ4u+eqGPBIzzSdqKNX1rvdbSU1lPNYlfQQRIFnBgLy26BtC0cFnr7c/AyuzExMxWsMOte6MkTi9I3SQ3iGQ==} + engines: {node: '>=v18'} + + '@commitlint/ensure@19.8.1': + resolution: {integrity: sha512-mXDnlJdvDzSObafjYrOSvZBwkD01cqB4gbnnFuVyNpGUM5ijwU/r/6uqUmBXAAOKRfyEjpkGVZxaDsCVnHAgyw==} + engines: {node: '>=v18'} + + '@commitlint/execute-rule@19.8.1': + resolution: {integrity: sha512-YfJyIqIKWI64Mgvn/sE7FXvVMQER/Cd+s3hZke6cI1xgNT/f6ZAz5heND0QtffH+KbcqAwXDEE1/5niYayYaQA==} + engines: {node: '>=v18'} + + '@commitlint/format@19.8.1': + resolution: {integrity: sha512-kSJj34Rp10ItP+Eh9oCItiuN/HwGQMXBnIRk69jdOwEW9llW9FlyqcWYbHPSGofmjsqeoxa38UaEA5tsbm2JWw==} + engines: {node: '>=v18'} + + '@commitlint/is-ignored@19.8.1': + resolution: {integrity: sha512-AceOhEhekBUQ5dzrVhDDsbMaY5LqtN8s1mqSnT2Kz1ERvVZkNihrs3Sfk1Je/rxRNbXYFzKZSHaPsEJJDJV8dg==} + engines: {node: '>=v18'} + + '@commitlint/lint@19.8.1': + resolution: {integrity: sha512-52PFbsl+1EvMuokZXLRlOsdcLHf10isTPlWwoY1FQIidTsTvjKXVXYb7AvtpWkDzRO2ZsqIgPK7bI98x8LRUEw==} + engines: {node: '>=v18'} + + '@commitlint/load@19.8.1': + resolution: {integrity: sha512-9V99EKG3u7z+FEoe4ikgq7YGRCSukAcvmKQuTtUyiYPnOd9a2/H9Ak1J9nJA1HChRQp9OA/sIKPugGS+FK/k1A==} + engines: {node: '>=v18'} + + '@commitlint/message@19.8.1': + resolution: {integrity: sha512-+PMLQvjRXiU+Ae0Wc+p99EoGEutzSXFVwQfa3jRNUZLNW5odZAyseb92OSBTKCu+9gGZiJASt76Cj3dLTtcTdg==} + engines: {node: '>=v18'} + + '@commitlint/parse@19.8.1': + resolution: {integrity: sha512-mmAHYcMBmAgJDKWdkjIGq50X4yB0pSGpxyOODwYmoexxxiUCy5JJT99t1+PEMK7KtsCtzuWYIAXYAiKR+k+/Jw==} + engines: {node: '>=v18'} + + '@commitlint/read@19.8.1': + resolution: {integrity: sha512-03Jbjb1MqluaVXKHKRuGhcKWtSgh3Jizqy2lJCRbRrnWpcM06MYm8th59Xcns8EqBYvo0Xqb+2DoZFlga97uXQ==} + engines: {node: '>=v18'} + + '@commitlint/resolve-extends@19.8.1': + resolution: {integrity: sha512-GM0mAhFk49I+T/5UCYns5ayGStkTt4XFFrjjf0L4S26xoMTSkdCf9ZRO8en1kuopC4isDFuEm7ZOm/WRVeElVg==} + engines: {node: '>=v18'} + + '@commitlint/rules@19.8.1': + resolution: {integrity: sha512-Hnlhd9DyvGiGwjfjfToMi1dsnw1EXKGJNLTcsuGORHz6SS9swRgkBsou33MQ2n51/boIDrbsg4tIBbRpEWK2kw==} + engines: {node: '>=v18'} + + '@commitlint/to-lines@19.8.1': + resolution: {integrity: sha512-98Mm5inzbWTKuZQr2aW4SReY6WUukdWXuZhrqf1QdKPZBCCsXuG87c+iP0bwtD6DBnmVVQjgp4whoHRVixyPBg==} + engines: {node: '>=v18'} + + '@commitlint/top-level@19.8.1': + resolution: {integrity: sha512-Ph8IN1IOHPSDhURCSXBz44+CIu+60duFwRsg6HqaISFHQHbmBtxVw4ZrFNIYUzEP7WwrNPxa2/5qJ//NK1FGcw==} + engines: {node: '>=v18'} + + '@commitlint/types@19.8.1': + resolution: {integrity: sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==} + engines: {node: '>=v18'} + + '@cspell/cspell-bundled-dicts@9.6.4': + resolution: {integrity: sha512-OIiPQuB7XQ6rnUv4KaCwHr9vNwbh6VZ4GfgQjcThT0oz0hkL6E5Ar3tq54K9jyqE9ylcHqpRuXUgnKgio6Hlig==} + engines: {node: '>=20'} + + '@cspell/cspell-json-reporter@9.6.4': + resolution: {integrity: sha512-rGYSDnDWACrUyovfN8M/LM8CCFSKjYd2kehbNS7YMPk0Jk+rLk6sgt5WYu3ty45otXCkiO07bjUo/81wBLet7A==} + engines: {node: '>=20'} + + '@cspell/cspell-performance-monitor@9.6.4': + resolution: {integrity: sha512-exuqxV1IVfZkasg57ZjUbaHeZDd6Mdbsbe5FBT3+XaVnRij+wpY2oEW9+kIOL5MOQE3bgQKgu37iMtA1NlCrGA==} + engines: {node: '>=20.18'} + + '@cspell/cspell-pipe@9.6.4': + resolution: {integrity: sha512-vVxajTG9Ko01oHk8HPsMLajcLrd9AfkOk6vdgFI4FD7ZPq1CY0hfTmfmJ8bzZ4/QkqXglTvePdSgHQVJeltwWw==} + engines: {node: '>=20'} + + '@cspell/cspell-resolver@9.6.4': + resolution: {integrity: sha512-3xsgZEqqH9Uj8ZYLBnWbnsHz8wphgaeuWKcNDqgwoMjvwTMQLGoXjHht8Jx5yxd2e080lB7fJax8TaBdCzmFFA==} + engines: {node: '>=20'} + + '@cspell/cspell-service-bus@9.6.4': + resolution: {integrity: sha512-oGNEzP1gJ43rLklJQjOk5PsfX0mZkLjV19djGptb9xZQeC2qAUxnaAbZtWt5CE8ni2iiTaRmgNRbUqAhRCnjew==} + engines: {node: '>=20'} + + '@cspell/cspell-types@9.6.4': + resolution: {integrity: sha512-lf6d+BdMkJIFCxx2FpajLpqVGGyaGUNFU6jhEM6QUPeGuoA5et2kJXrL0NSY2uWLOVyYYc/FPjzlbe8trA9tBQ==} + engines: {node: '>=20'} + + '@cspell/cspell-worker@9.6.4': + resolution: {integrity: sha512-anacKDOZzDfPzuDeFOXGI2tFBYiRRCSnIZP/AOyJ9zTvEQcqq5p/ak18nJ5OQyDr2NG7ovJiCDT5YNiH2Vdg/g==} + engines: {node: '>=20.18'} + + '@cspell/dict-ada@4.1.1': + resolution: {integrity: sha512-E+0YW9RhZod/9Qy2gxfNZiHJjCYFlCdI69br1eviQQWB8yOTJX0JHXLs79kOYhSW0kINPVUdvddEBe6Lu6CjGQ==} + + '@cspell/dict-al@1.1.1': + resolution: {integrity: sha512-sD8GCaZetgQL4+MaJLXqbzWcRjfKVp8x+px3HuCaaiATAAtvjwUQ5/Iubiqwfd1boIh2Y1/3EgM3TLQ7Q8e0wQ==} + + '@cspell/dict-aws@4.0.17': + resolution: {integrity: sha512-ORcblTWcdlGjIbWrgKF+8CNEBQiLVKdUOFoTn0KPNkAYnFcdPP0muT4892h7H4Xafh3j72wqB4/loQ6Nti9E/w==} + + '@cspell/dict-bash@4.2.2': + resolution: {integrity: sha512-kyWbwtX3TsCf5l49gGQIZkRLaB/P8g73GDRm41Zu8Mv51kjl2H7Au0TsEvHv7jzcsRLS6aUYaZv6Zsvk1fOz+Q==} + + '@cspell/dict-companies@3.2.10': + resolution: {integrity: sha512-bJ1qnO1DkTn7JYGXvxp8FRQc4yq6tRXnrII+jbP8hHmq5TX5o1Wu+rdfpoUQaMWTl6balRvcMYiINDesnpR9Bw==} + + '@cspell/dict-cpp@7.0.2': + resolution: {integrity: sha512-dfbeERiVNeqmo/npivdR6rDiBCqZi3QtjH2Z0HFcXwpdj6i97dX1xaKyK2GUsO/p4u1TOv63Dmj5Vm48haDpuA==} + + '@cspell/dict-cryptocurrencies@5.0.5': + resolution: {integrity: sha512-R68hYYF/rtlE6T/dsObStzN5QZw+0aQBinAXuWCVqwdS7YZo0X33vGMfChkHaiCo3Z2+bkegqHlqxZF4TD3rUA==} + + '@cspell/dict-csharp@4.0.8': + resolution: {integrity: sha512-qmk45pKFHSxckl5mSlbHxmDitSsGMlk/XzFgt7emeTJWLNSTUK//MbYAkBNRtfzB4uD7pAFiKgpKgtJrTMRnrQ==} + + '@cspell/dict-css@4.0.19': + resolution: {integrity: sha512-VYHtPnZt/Zd/ATbW3rtexWpBnHUohUrQOHff/2JBhsVgxOrksAxJnLAO43Q1ayLJBJUUwNVo+RU0sx0aaysZfg==} + + '@cspell/dict-dart@2.3.2': + resolution: {integrity: sha512-sUiLW56t9gfZcu8iR/5EUg+KYyRD83Cjl3yjDEA2ApVuJvK1HhX+vn4e4k4YfjpUQMag8XO2AaRhARE09+/rqw==} + + '@cspell/dict-data-science@2.0.13': + resolution: {integrity: sha512-l1HMEhBJkPmw4I2YGVu2eBSKM89K9pVF+N6qIr5Uo5H3O979jVodtuwP8I7LyPrJnC6nz28oxeGRCLh9xC5CVA==} + + '@cspell/dict-django@4.1.6': + resolution: {integrity: sha512-SdbSFDGy9ulETqNz15oWv2+kpWLlk8DJYd573xhIkeRdcXOjskRuxjSZPKfW7O3NxN/KEf3gm3IevVOiNuFS+w==} + + '@cspell/dict-docker@1.1.17': + resolution: {integrity: sha512-OcnVTIpHIYYKhztNTyK8ShAnXTfnqs43hVH6p0py0wlcwRIXe5uj4f12n7zPf2CeBI7JAlPjEsV0Rlf4hbz/xQ==} + + '@cspell/dict-dotnet@5.0.11': + resolution: {integrity: sha512-LSVKhpFf/ASTWJcfYeS0Sykcl1gVMsv2Z5Eo0TnTMSTLV3738HH+66pIsjUTChqU6SF3gKPuCe6EOaRYqb/evA==} + + '@cspell/dict-elixir@4.0.8': + resolution: {integrity: sha512-CyfphrbMyl4Ms55Vzuj+mNmd693HjBFr9hvU+B2YbFEZprE5AG+EXLYTMRWrXbpds4AuZcvN3deM2XVB80BN/Q==} + + '@cspell/dict-en-common-misspellings@2.1.12': + resolution: {integrity: sha512-14Eu6QGqyksqOd4fYPuRb58lK1Va7FQK9XxFsRKnZU8LhL3N+kj7YKDW+7aIaAN/0WGEqslGP6lGbQzNti8Akw==} + + '@cspell/dict-en-gb-mit@3.1.18': + resolution: {integrity: sha512-AXaMzbaxhSc32MSzKX0cpwT+Thv1vPfxQz1nTly1VHw3wQcwPqVFSqrLOYwa8VNqAPR45583nnhD6iqJ9YESoQ==} + + '@cspell/dict-en_us@4.4.29': + resolution: {integrity: sha512-G3B27++9ziRdgbrY/G/QZdFAnMzzx17u8nCb2Xyd4q6luLpzViRM/CW3jA+Mb/cGT5zR/9N+Yz9SrGu1s0bq7g==} + + '@cspell/dict-filetypes@3.0.15': + resolution: {integrity: sha512-uDMeqYlLlK476w/muEFQGBy9BdQWS0mQ7BJiy/iQv5XUWZxE2O54ZQd9nW8GyQMzAgoyg5SG4hf9l039Qt66oA==} + + '@cspell/dict-flutter@1.1.1': + resolution: {integrity: sha512-UlOzRcH2tNbFhZmHJN48Za/2/MEdRHl2BMkCWZBYs+30b91mWvBfzaN4IJQU7dUZtowKayVIF9FzvLZtZokc5A==} + + '@cspell/dict-fonts@4.0.5': + resolution: {integrity: sha512-BbpkX10DUX/xzHs6lb7yzDf/LPjwYIBJHJlUXSBXDtK/1HaeS+Wqol4Mlm2+NAgZ7ikIE5DQMViTgBUY3ezNoQ==} + + '@cspell/dict-fsharp@1.1.1': + resolution: {integrity: sha512-imhs0u87wEA4/cYjgzS0tAyaJpwG7vwtC8UyMFbwpmtw+/bgss+osNfyqhYRyS/ehVCWL17Ewx2UPkexjKyaBA==} + + '@cspell/dict-fullstack@3.2.8': + resolution: {integrity: sha512-J6EeoeThvx/DFrcA2rJiCA6vfqwJMbkG0IcXhlsmRZmasIpanmxgt90OEaUazbZahFiuJT8wrhgQ1QgD1MsqBw==} + + '@cspell/dict-gaming-terms@1.1.2': + resolution: {integrity: sha512-9XnOvaoTBscq0xuD6KTEIkk9hhdfBkkvJAIsvw3JMcnp1214OCGW8+kako5RqQ2vTZR3Tnf3pc57o7VgkM0q1Q==} + + '@cspell/dict-git@3.1.0': + resolution: {integrity: sha512-KEt9zGkxqGy2q1nwH4CbyqTSv5nadpn8BAlDnzlRcnL0Xb3LX9xTgSGShKvzb0bw35lHoYyLWN2ZKAqbC4pgGQ==} + + '@cspell/dict-golang@6.0.26': + resolution: {integrity: sha512-YKA7Xm5KeOd14v5SQ4ll6afe9VSy3a2DWM7L9uBq4u3lXToRBQ1W5PRa+/Q9udd+DTURyVVnQ+7b9cnOlNxaRg==} + + '@cspell/dict-google@1.0.9': + resolution: {integrity: sha512-biL65POqialY0i4g6crj7pR6JnBkbsPovB2WDYkj3H4TuC/QXv7Pu5pdPxeUJA6TSCHI7T5twsO4VSVyRxD9CA==} + + '@cspell/dict-haskell@4.0.6': + resolution: {integrity: sha512-ib8SA5qgftExpYNjWhpYIgvDsZ/0wvKKxSP+kuSkkak520iPvTJumEpIE+qPcmJQo4NzdKMN8nEfaeci4OcFAQ==} + + '@cspell/dict-html-symbol-entities@4.0.5': + resolution: {integrity: sha512-429alTD4cE0FIwpMucvSN35Ld87HCyuM8mF731KU5Rm4Je2SG6hmVx7nkBsLyrmH3sQukTcr1GaiZsiEg8svPA==} + + '@cspell/dict-html@4.0.14': + resolution: {integrity: sha512-2bf7n+kS92g+cMKV0wr9o/Oq9n8JzU7CcrB96gIh2GHgnF+0xDOqO2W/1KeFAqOfqosoOVE48t+4dnEMkkoJ2Q==} + + '@cspell/dict-java@5.0.12': + resolution: {integrity: sha512-qPSNhTcl7LGJ5Qp6VN71H8zqvRQK04S08T67knMq9hTA8U7G1sTKzLmBaDOFhq17vNX/+rT+rbRYp+B5Nwza1A==} + + '@cspell/dict-julia@1.1.1': + resolution: {integrity: sha512-WylJR9TQ2cgwd5BWEOfdO3zvDB+L7kYFm0I9u0s9jKHWQ6yKmfKeMjU9oXxTBxIufhCXm92SKwwVNAC7gjv+yA==} + + '@cspell/dict-k8s@1.0.12': + resolution: {integrity: sha512-2LcllTWgaTfYC7DmkMPOn9GsBWsA4DZdlun4po8s2ysTP7CPEnZc1ZfK6pZ2eI4TsZemlUQQ+NZxMe9/QutQxg==} + + '@cspell/dict-kotlin@1.1.1': + resolution: {integrity: sha512-J3NzzfgmxRvEeOe3qUXnSJQCd38i/dpF9/t3quuWh6gXM+krsAXP75dY1CzDmS8mrJAlBdVBeAW5eAZTD8g86Q==} + + '@cspell/dict-latex@5.0.0': + resolution: {integrity: sha512-HUrIqUVohM6P0+5b7BsdAdb0STIv0aaFBvguI7pLcreljlcX3FSPUxea7ticzNlCNeVrEaiEn/ws9m6rYUeuNw==} + + '@cspell/dict-lorem-ipsum@4.0.5': + resolution: {integrity: sha512-9a4TJYRcPWPBKkQAJ/whCu4uCAEgv/O2xAaZEI0n4y1/l18Yyx8pBKoIX5QuVXjjmKEkK7hi5SxyIsH7pFEK9Q==} + + '@cspell/dict-lua@4.0.8': + resolution: {integrity: sha512-N4PkgNDMu9JVsRu7JBS/3E/dvfItRgk9w5ga2dKq+JupP2Y3lojNaAVFhXISh4Y0a6qXDn2clA6nvnavQ/jjLA==} + + '@cspell/dict-makefile@1.0.5': + resolution: {integrity: sha512-4vrVt7bGiK8Rx98tfRbYo42Xo2IstJkAF4tLLDMNQLkQ86msDlYSKG1ZCk8Abg+EdNcFAjNhXIiNO+w4KflGAQ==} + + '@cspell/dict-markdown@2.0.14': + resolution: {integrity: sha512-uLKPNJsUcumMQTsZZgAK9RgDLyQhUz/uvbQTEkvF/Q4XfC1i/BnA8XrOrd0+Vp6+tPOKyA+omI5LRWfMu5K/Lw==} + peerDependencies: + '@cspell/dict-css': ^4.0.19 + '@cspell/dict-html': ^4.0.14 + '@cspell/dict-html-symbol-entities': ^4.0.5 + '@cspell/dict-typescript': ^3.2.3 + + '@cspell/dict-monkeyc@1.0.12': + resolution: {integrity: sha512-MN7Vs11TdP5mbdNFQP5x2Ac8zOBm97ARg6zM5Sb53YQt/eMvXOMvrep7+/+8NJXs0jkp70bBzjqU4APcqBFNAw==} + + '@cspell/dict-node@5.0.9': + resolution: {integrity: sha512-hO+ga+uYZ/WA4OtiMEyKt5rDUlUyu3nXMf8KVEeqq2msYvAPdldKBGH7lGONg6R/rPhv53Rb+0Y1SLdoK1+7wQ==} + + '@cspell/dict-npm@5.2.33': + resolution: {integrity: sha512-U1gfDxdFR6nnojvtdkF2Ati3jfIlnW5nJkFb2jS1JunlhrSYdZXwz/4bI//h1W3aaeYQoSlvTIqk3vlnIDrNng==} + + '@cspell/dict-php@4.1.1': + resolution: {integrity: sha512-EXelI+4AftmdIGtA8HL8kr4WlUE11OqCSVlnIgZekmTkEGSZdYnkFdiJ5IANSALtlQ1mghKjz+OFqVs6yowgWA==} + + '@cspell/dict-powershell@5.0.15': + resolution: {integrity: sha512-l4S5PAcvCFcVDMJShrYD0X6Huv9dcsQPlsVsBGbH38wvuN7gS7+GxZFAjTNxDmTY1wrNi1cCatSg6Pu2BW4rgg==} + + '@cspell/dict-public-licenses@2.0.15': + resolution: {integrity: sha512-cJEOs901H13Pfy0fl4dCD1U+xpWIMaEPq8MeYU83FfDZvellAuSo4GqWCripfIqlhns/L6+UZEIJSOZnjgy7Wg==} + + '@cspell/dict-python@4.2.25': + resolution: {integrity: sha512-hDdN0YhKgpbtZVRjQ2c8jk+n0wQdidAKj1Fk8w7KEHb3YlY5uPJ0mAKJk7AJKPNLOlILoUmN+HAVJz+cfSbWYg==} + + '@cspell/dict-r@2.1.1': + resolution: {integrity: sha512-71Ka+yKfG4ZHEMEmDxc6+blFkeTTvgKbKAbwiwQAuKl3zpqs1Y0vUtwW2N4b3LgmSPhV3ODVY0y4m5ofqDuKMw==} + + '@cspell/dict-ruby@5.1.0': + resolution: {integrity: sha512-9PJQB3cfkBULrMLp5kSAcFPpzf8oz9vFN+QYZABhQwWkGbuzCIXSorHrmWSASlx4yejt3brjaWS57zZ/YL5ZQQ==} + + '@cspell/dict-rust@4.1.2': + resolution: {integrity: sha512-O1FHrumYcO+HZti3dHfBPUdnDFkI+nbYK3pxYmiM1sr+G0ebOd6qchmswS0Wsc6ZdEVNiPYJY/gZQR6jfW3uOg==} + + '@cspell/dict-scala@5.0.9': + resolution: {integrity: sha512-AjVcVAELgllybr1zk93CJ5wSUNu/Zb5kIubymR/GAYkMyBdYFCZ3Zbwn4Zz8GJlFFAbazABGOu0JPVbeY59vGg==} + + '@cspell/dict-shell@1.1.2': + resolution: {integrity: sha512-WqOUvnwcHK1X61wAfwyXq04cn7KYyskg90j4lLg3sGGKMW9Sq13hs91pqrjC44Q+lQLgCobrTkMDw9Wyl9nRFA==} + + '@cspell/dict-software-terms@5.1.20': + resolution: {integrity: sha512-TEk1xHvetTI4pv7Vzje1D322m6QEjaH2P6ucOOf6q7EJCppQIdC0lZSXkgHJAFU5HGSvEXSzvnVeW2RHW86ziQ==} + + '@cspell/dict-sql@2.2.1': + resolution: {integrity: sha512-qDHF8MpAYCf4pWU8NKbnVGzkoxMNrFqBHyG/dgrlic5EQiKANCLELYtGlX5auIMDLmTf1inA0eNtv74tyRJ/vg==} + + '@cspell/dict-svelte@1.0.7': + resolution: {integrity: sha512-hGZsGqP0WdzKkdpeVLBivRuSNzOTvN036EBmpOwxH+FTY2DuUH7ecW+cSaMwOgmq5JFSdTcbTNFlNC8HN8lhaQ==} + + '@cspell/dict-swift@2.0.6': + resolution: {integrity: sha512-PnpNbrIbex2aqU1kMgwEKvCzgbkHtj3dlFLPMqW1vSniop7YxaDTtvTUO4zA++ugYAEL+UK8vYrBwDPTjjvSnA==} + + '@cspell/dict-terraform@1.1.3': + resolution: {integrity: sha512-gr6wxCydwSFyyBKhBA2xkENXtVFToheqYYGFvlMZXWjviynXmh+NK/JTvTCk/VHk3+lzbO9EEQKee6VjrAUSbA==} + + '@cspell/dict-typescript@3.2.3': + resolution: {integrity: sha512-zXh1wYsNljQZfWWdSPYwQhpwiuW0KPW1dSd8idjMRvSD0aSvWWHoWlrMsmZeRl4qM4QCEAjua8+cjflm41cQBg==} + + '@cspell/dict-vue@3.0.5': + resolution: {integrity: sha512-Mqutb8jbM+kIcywuPQCCaK5qQHTdaByoEO2J9LKFy3sqAdiBogNkrplqUK0HyyRFgCfbJUgjz3N85iCMcWH0JA==} + + '@cspell/dict-zig@1.0.0': + resolution: {integrity: sha512-XibBIxBlVosU06+M6uHWkFeT0/pW5WajDRYdXG2CgHnq85b0TI/Ks0FuBJykmsgi2CAD3Qtx8UHFEtl/DSFnAQ==} + + '@cspell/dynamic-import@9.6.4': + resolution: {integrity: sha512-1VnL9ahT3s17DLWl4MeO1pYg7zcVT3X9cKynI2/U86zNK5xMGS5icvjp7X65tsCAVNcWOtkqVFfrxi7kWxn67g==} + engines: {node: '>=20'} + + '@cspell/filetypes@9.6.4': + resolution: {integrity: sha512-a1aZ/8vGnhTknxTukjzo3m8CISyHW2MWnbedywg5SDEl5RMJitmzX90QZiQdSvEcqzqmtoAgSEZNBT2LX2gIKg==} + engines: {node: '>=20'} + + '@cspell/rpc@9.6.4': + resolution: {integrity: sha512-vGI1788Rx5Yml9N1/pD4zGd8Vrchi2Y01ADf9NiiOaNVVdf4PU1GCssLCsiIzhYQneErpQ8pJi/mS2F/QMZbRA==} + engines: {node: '>=20.18'} + + '@cspell/strong-weak-map@9.6.4': + resolution: {integrity: sha512-AQrUbA0JUOEQgwItnfUQ6Ydk0hWY/uV3VhLwZWyrnT9eiQynmTnRTHtOCkkSl9+M4P0N4Raa2eGFRLcPAFksaw==} + engines: {node: '>=20'} + + '@cspell/url@9.6.4': + resolution: {integrity: sha512-h6VMlb7bDyGJfwLtipxxtHlT+ojzUXZz14AqZ/NEzY3LfOhfJTGpRcWLYFsgG/L0Ma4qjsYbPJt/Sj1C14j0VA==} + engines: {node: '>=20'} + + '@css-render/plugin-bem@0.15.14': + resolution: {integrity: sha512-QK513CJ7yEQxm/P3EwsI+d+ha8kSOcjGvD6SevM41neEMxdULE+18iuQK6tEChAWMOQNQPLG/Rw3Khb69r5neg==} + peerDependencies: + css-render: ~0.15.14 + + '@css-render/vue3-ssr@0.15.14': + resolution: {integrity: sha512-//8027GSbxE9n3QlD73xFY6z4ZbHbvrOVB7AO6hsmrEzGbg+h2A09HboUyDgu+xsmj7JnvJD39Irt+2D0+iV8g==} + peerDependencies: + vue: ^3.5.27 + + '@csstools/cascade-layer-name-parser@2.0.5': + resolution: {integrity: sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-syntax-patches-for-csstree@1.0.27': + resolution: {integrity: sha512-sxP33Jwg1bviSUXAV43cVYdmjt2TLnLXNqCWl9xmxHawWVjGz/kEbdkr7F9pxJNBN2Mh+dq0crgItbW6tQvyow==} + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + + '@csstools/media-query-list-parser@4.0.3': + resolution: {integrity: sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/postcss-alpha-function@1.0.1': + resolution: {integrity: sha512-isfLLwksH3yHkFXfCI2Gcaqg7wGGHZZwunoJzEZk0yKYIokgre6hYVFibKL3SYAoR1kBXova8LB+JoO5vZzi9w==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-cascade-layers@5.0.2': + resolution: {integrity: sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-color-function-display-p3-linear@1.0.1': + resolution: {integrity: sha512-E5qusdzhlmO1TztYzDIi8XPdPoYOjoTY6HBYBCYSj+Gn4gQRBlvjgPQXzfzuPQqt8EhkC/SzPKObg4Mbn8/xMg==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-color-function@4.0.12': + resolution: {integrity: sha512-yx3cljQKRaSBc2hfh8rMZFZzChaFgwmO2JfFgFr1vMcF3C/uyy5I4RFIBOIWGq1D+XbKCG789CGkG6zzkLpagA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-color-mix-function@3.0.12': + resolution: {integrity: sha512-4STERZfCP5Jcs13P1U5pTvI9SkgLgfMUMhdXW8IlJWkzOOOqhZIjcNhWtNJZes2nkBDsIKJ0CJtFtuaZ00moag==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-color-mix-variadic-function-arguments@1.0.2': + resolution: {integrity: sha512-rM67Gp9lRAkTo+X31DUqMEq+iK+EFqsidfecmhrteErxJZb6tUoJBVQca1Vn1GpDql1s1rD1pKcuYzMsg7Z1KQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-content-alt-text@2.0.8': + resolution: {integrity: sha512-9SfEW9QCxEpTlNMnpSqFaHyzsiRpZ5J5+KqCu1u5/eEJAWsMhzT40qf0FIbeeglEvrGRMdDzAxMIz3wqoGSb+Q==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-contrast-color-function@2.0.12': + resolution: {integrity: sha512-YbwWckjK3qwKjeYz/CijgcS7WDUCtKTd8ShLztm3/i5dhh4NaqzsbYnhm4bjrpFpnLZ31jVcbK8YL77z3GBPzA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-exponential-functions@2.0.9': + resolution: {integrity: sha512-abg2W/PI3HXwS/CZshSa79kNWNZHdJPMBXeZNyPQFbbj8sKO3jXxOt/wF7juJVjyDTc6JrvaUZYFcSBZBhaxjw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-font-format-keywords@4.0.0': + resolution: {integrity: sha512-usBzw9aCRDvchpok6C+4TXC57btc4bJtmKQWOHQxOVKen1ZfVqBUuCZ/wuqdX5GHsD0NRSr9XTP+5ID1ZZQBXw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-gamut-mapping@2.0.11': + resolution: {integrity: sha512-fCpCUgZNE2piVJKC76zFsgVW1apF6dpYsqGyH8SIeCcM4pTEsRTWTLCaJIMKFEundsCKwY1rwfhtrio04RJ4Dw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-gradients-interpolation-method@5.0.12': + resolution: {integrity: sha512-jugzjwkUY0wtNrZlFeyXzimUL3hN4xMvoPnIXxoZqxDvjZRiSh+itgHcVUWzJ2VwD/VAMEgCLvtaJHX+4Vj3Ow==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-hwb-function@4.0.12': + resolution: {integrity: sha512-mL/+88Z53KrE4JdePYFJAQWFrcADEqsLprExCM04GDNgHIztwFzj0Mbhd/yxMBngq0NIlz58VVxjt5abNs1VhA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-ic-unit@4.0.4': + resolution: {integrity: sha512-yQ4VmossuOAql65sCPppVO1yfb7hDscf4GseF0VCA/DTDaBc0Wtf8MTqVPfjGYlT5+2buokG0Gp7y0atYZpwjg==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-initial@2.0.1': + resolution: {integrity: sha512-L1wLVMSAZ4wovznquK0xmC7QSctzO4D0Is590bxpGqhqjboLXYA16dWZpfwImkdOgACdQ9PqXsuRroW6qPlEsg==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-is-pseudo-class@5.0.3': + resolution: {integrity: sha512-jS/TY4SpG4gszAtIg7Qnf3AS2pjcUM5SzxpApOrlndMeGhIbaTzWBzzP/IApXoNWEW7OhcjkRT48jnAUIFXhAQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-light-dark-function@2.0.11': + resolution: {integrity: sha512-fNJcKXJdPM3Lyrbmgw2OBbaioU7yuKZtiXClf4sGdQttitijYlZMD5K7HrC/eF83VRWRrYq6OZ0Lx92leV2LFA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-logical-float-and-clear@3.0.0': + resolution: {integrity: sha512-SEmaHMszwakI2rqKRJgE+8rpotFfne1ZS6bZqBoQIicFyV+xT1UF42eORPxJkVJVrH9C0ctUgwMSn3BLOIZldQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-logical-overflow@2.0.0': + resolution: {integrity: sha512-spzR1MInxPuXKEX2csMamshR4LRaSZ3UXVaRGjeQxl70ySxOhMpP2252RAFsg8QyyBXBzuVOOdx1+bVO5bPIzA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-logical-overscroll-behavior@2.0.0': + resolution: {integrity: sha512-e/webMjoGOSYfqLunyzByZj5KKe5oyVg/YSbie99VEaSDE2kimFm0q1f6t/6Jo+VVCQ/jbe2Xy+uX+C4xzWs4w==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-logical-resize@3.0.0': + resolution: {integrity: sha512-DFbHQOFW/+I+MY4Ycd/QN6Dg4Hcbb50elIJCfnwkRTCX05G11SwViI5BbBlg9iHRl4ytB7pmY5ieAFk3ws7yyg==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-logical-viewport-units@3.0.4': + resolution: {integrity: sha512-q+eHV1haXA4w9xBwZLKjVKAWn3W2CMqmpNpZUk5kRprvSiBEGMgrNH3/sJZ8UA3JgyHaOt3jwT9uFa4wLX4EqQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-media-minmax@2.0.9': + resolution: {integrity: sha512-af9Qw3uS3JhYLnCbqtZ9crTvvkR+0Se+bBqSr7ykAnl9yKhk6895z9rf+2F4dClIDJWxgn0iZZ1PSdkhrbs2ig==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5': + resolution: {integrity: sha512-zhAe31xaaXOY2Px8IYfoVTB3wglbJUVigGphFLj6exb7cjZRH9A6adyE22XfFK3P2PzwRk0VDeTJmaxpluyrDg==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-nested-calc@4.0.0': + resolution: {integrity: sha512-jMYDdqrQQxE7k9+KjstC3NbsmC063n1FTPLCgCRS2/qHUbHM0mNy9pIn4QIiQGs9I/Bg98vMqw7mJXBxa0N88A==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-normalize-display-values@4.0.1': + resolution: {integrity: sha512-TQUGBuRvxdc7TgNSTevYqrL8oItxiwPDixk20qCB5me/W8uF7BPbhRrAvFuhEoywQp/woRsUZ6SJ+sU5idZAIA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-oklab-function@4.0.12': + resolution: {integrity: sha512-HhlSmnE1NKBhXsTnNGjxvhryKtO7tJd1w42DKOGFD6jSHtYOrsJTQDKPMwvOfrzUAk8t7GcpIfRyM7ssqHpFjg==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-position-area-property@1.0.0': + resolution: {integrity: sha512-fUP6KR8qV2NuUZV3Cw8itx0Ep90aRjAZxAEzC3vrl6yjFv+pFsQbR18UuQctEKmA72K9O27CoYiKEgXxkqjg8Q==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-progressive-custom-properties@4.2.1': + resolution: {integrity: sha512-uPiiXf7IEKtUQXsxu6uWtOlRMXd2QWWy5fhxHDnPdXKCQckPP3E34ZgDoZ62r2iT+UOgWsSbM4NvHE5m3mAEdw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-property-rule-prelude-list@1.0.0': + resolution: {integrity: sha512-IxuQjUXq19fobgmSSvUDO7fVwijDJaZMvWQugxfEUxmjBeDCVaDuMpsZ31MsTm5xbnhA+ElDi0+rQ7sQQGisFA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-random-function@2.0.1': + resolution: {integrity: sha512-q+FQaNiRBhnoSNo+GzqGOIBKoHQ43lYz0ICrV+UudfWnEF6ksS6DsBIJSISKQT2Bvu3g4k6r7t0zYrk5pDlo8w==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-relative-color-syntax@3.0.12': + resolution: {integrity: sha512-0RLIeONxu/mtxRtf3o41Lq2ghLimw0w9ByLWnnEVuy89exmEEq8bynveBxNW3nyHqLAFEeNtVEmC1QK9MZ8Huw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-scope-pseudo-class@4.0.1': + resolution: {integrity: sha512-IMi9FwtH6LMNuLea1bjVMQAsUhFxJnyLSgOp/cpv5hrzWmrUYU5fm0EguNDIIOHUqzXode8F/1qkC/tEo/qN8Q==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-sign-functions@1.1.4': + resolution: {integrity: sha512-P97h1XqRPcfcJndFdG95Gv/6ZzxUBBISem0IDqPZ7WMvc/wlO+yU0c5D/OCpZ5TJoTt63Ok3knGk64N+o6L2Pg==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-stepped-value-functions@4.0.9': + resolution: {integrity: sha512-h9btycWrsex4dNLeQfyU3y3w40LMQooJWFMm/SK9lrKguHDcFl4VMkncKKoXi2z5rM9YGWbUQABI8BT2UydIcA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-syntax-descriptor-syntax-production@1.0.1': + resolution: {integrity: sha512-GneqQWefjM//f4hJ/Kbox0C6f2T7+pi4/fqTqOFGTL3EjnvOReTqO1qUQ30CaUjkwjYq9qZ41hzarrAxCc4gow==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-system-ui-font-family@1.0.0': + resolution: {integrity: sha512-s3xdBvfWYfoPSBsikDXbuorcMG1nN1M6GdU0qBsGfcmNR0A/qhloQZpTxjA3Xsyrk1VJvwb2pOfiOT3at/DuIQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-text-decoration-shorthand@4.0.3': + resolution: {integrity: sha512-KSkGgZfx0kQjRIYnpsD7X2Om9BUXX/Kii77VBifQW9Ih929hK0KNjVngHDH0bFB9GmfWcR9vJYJJRvw/NQjkrA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-trigonometric-functions@4.0.9': + resolution: {integrity: sha512-Hnh5zJUdpNrJqK9v1/E3BbrQhaDTj5YiX7P61TOvUhoDHnUmsNNxcDAgkQ32RrcWx9GVUvfUNPcUkn8R3vIX6A==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/postcss-unset-value@4.0.0': + resolution: {integrity: sha512-cBz3tOCI5Fw6NIFEwU3RiwK6mn3nKegjpJuzCndoGq3BZPkUjnsq7uQmIeMNeMbMk7YD2MfKcgCpZwX5jyXqCA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@csstools/selector-resolve-nested@3.1.0': + resolution: {integrity: sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==} + engines: {node: '>=18'} + peerDependencies: + postcss-selector-parser: ^7.0.0 + + '@csstools/selector-specificity@5.0.0': + resolution: {integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==} + engines: {node: '>=18'} + peerDependencies: + postcss-selector-parser: ^7.0.0 + + '@csstools/utilities@2.0.0': + resolution: {integrity: sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + '@ctrl/tinycolor@4.2.0': + resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} + engines: {node: '>=14'} + + '@docsearch/css@3.8.2': + resolution: {integrity: sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==} + + '@docsearch/js@3.8.2': + resolution: {integrity: sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==} + + '@docsearch/react@3.8.2': + resolution: {integrity: sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==} + peerDependencies: + '@types/react': '>= 16.8.0 < 19.0.0' + react: '>= 16.8.0 < 19.0.0' + react-dom: '>= 16.8.0 < 19.0.0' + search-insights: '>= 1 < 3' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + react-dom: + optional: true + search-insights: + optional: true + + '@dual-bundle/import-meta-resolve@4.2.1': + resolution: {integrity: sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==} + + '@element-plus/icons-vue@2.3.2': + resolution: {integrity: sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==} + peerDependencies: + vue: ^3.5.27 + + '@emnapi/core@1.8.1': + resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} + + '@emnapi/runtime@1.8.1': + resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + + '@emotion/hash@0.8.0': + resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} + + '@emotion/hash@0.9.2': + resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + + '@emotion/unitless@0.7.5': + resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} + + '@emotion/unitless@0.8.1': + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + + '@epic-web/invariant@1.0.0': + resolution: {integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==} + + '@es-joy/jsdoccomment@0.78.0': + resolution: {integrity: sha512-rQkU5u8hNAq2NVRzHnIUUvR6arbO0b6AOlvpTNS48CkiKSn/xtNfOzBK23JE4SiW89DgvU7GtxLVgV4Vn2HBAw==} + engines: {node: '>=20.11.0'} + + '@es-joy/resolve.exports@1.2.0': + resolution: {integrity: sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==} + engines: {node: '>=10'} + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.2': + resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@floating-ui/core@1.7.4': + resolution: {integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==} + + '@floating-ui/dom@1.7.5': + resolution: {integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==} + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + + '@floating-ui/vue@1.1.10': + resolution: {integrity: sha512-vdf8f6rHnFPPLRsmL4p12wYl+Ux4mOJOkjzKEMYVnwdf7UFdvBtHlLvQyx8iKG5vhPRbDRgZxdtpmyigDPjzYg==} + + '@form-create/ant-design-vue@3.2.37': + resolution: {integrity: sha512-BrdsQ3+G556u75ff3srCCKWDXeZpJ9Yr+AoeI36MLX+eRIkg9p4Xgxoy6eQ3jb0ohEKuh8kKNKF5H5lJVTIvPw==} + peerDependencies: + vue: ^3.5.27 + + '@form-create/antd-designer@3.4.0': + resolution: {integrity: sha512-55wFRbsLJ02Fj4+CLJK2HJ628xsQRafzlmz2yhHFk99O8eMl523QpxD/0O4yH7e+azqakxW6H5WoFexG78qSgA==} + peerDependencies: + vue: ^3.5.27 + + '@form-create/component-antdv-frame@3.2.31': + resolution: {integrity: sha512-1pg+OsmZLnhIZJvg4dC14R0KNaRVGGN1pxZkY2hf0iFeoKViEMnhsRKAqJzjAf3uGE/2jSyXpjRpRPZi8Egwww==} + + '@form-create/component-antdv-group@3.2.34': + resolution: {integrity: sha512-7m4WLRkvVyOZ8ADQyWON9RIhJ/1aOb+dN2xUsxH+S1reGPlnKL9bRoCY5XNsPf/iitbWLRistSSi1r1Q0XFK/g==} + + '@form-create/component-antdv-upload@3.2.31': + resolution: {integrity: sha512-pTaYM31LnEocHYCrBNqp2qE67NbhjNEG0qO4OJgLjsf8i66Pd47BTB3SLkay2daAH1o1ziRNkoilsQrcHTV3og==} + + '@form-create/component-elm-checkbox@3.2.31': + resolution: {integrity: sha512-XQT66E+nRXA2KGZwU1TujSGtICevDUUwks8K+79xs214lofva+rMaRFtrpZYXFgt0+molMUSOl/wc9dOrNr+1Q==} + + '@form-create/component-elm-frame@3.2.31': + resolution: {integrity: sha512-8ub7SnIRVV6YVIBXHps1A7hi7ivrjm8v1qNIcUOndUliXjP90PZ02YUZkVNh12aX8LNhGtuq8kLZqtdSdh78uA==} + + '@form-create/component-elm-group@3.2.34': + resolution: {integrity: sha512-/067dB7Ss9UNLCKfTKpazYwVlpIeuAPGfhO4kcVx+bqr38fMuh2zuQNAqqRk5hsNC/Y8wOnPshT/bU1L8AQOGA==} + + '@form-create/component-elm-radio@3.2.31': + resolution: {integrity: sha512-hm/+tuBPf6bH1iw1xP80JXGe9rhUTovMcQpDfLMNkrdXrLZJ618sKXzID1nId03QKYcocnOHvkbX0NuNPila+A==} + + '@form-create/component-elm-select@3.2.37': + resolution: {integrity: sha512-kbxYHdA5KOVmvD9HIBJZWntjpRXFf8uO2+uSjolamCmKh+St0RDttdUMRNjXDxroHHrdtJMIP9K778/BCHYk4g==} + + '@form-create/component-elm-tree@3.2.31': + resolution: {integrity: sha512-cLWwqT+3ES5FSRywQ7HIh05jvEeMPhoQnIxcSbLnzB24tS2eM2x5DhbhjJ02wsZGPvfcO4m3BBp0fgv1RKww1g==} + + '@form-create/component-elm-upload@3.2.31': + resolution: {integrity: sha512-2XJr7x8gPf+U0FnPYLyPt0+qLG9+lZSO7tlInT0fw7TJF9pWzrtxicnX6sWvd4EoWCNzYU13HXL33Aq1zP2IeA==} + + '@form-create/component-naive-checkbox@3.2.31': + resolution: {integrity: sha512-MLIVLg2A6mHjKnwgrohVX6AtyKJyQ58G3DD6zpS30nPvyaFJNgrL5N1bU5vQ9IwC4YsO8dbBiR1epxRJ+53l2g==} + + '@form-create/component-naive-frame@3.2.31': + resolution: {integrity: sha512-XmQ0ywyULRUPyyn0bSKMijRsWIIg1U3Ytju+kQfclOb6gSzSQ0ULJqEQQRXHhIhDMC5g8QsBbq4S/bZgiHWUNA==} + + '@form-create/component-naive-group@3.2.34': + resolution: {integrity: sha512-P+6Rsm9yNIkdKQZ/byJoo9ygvOJEZEFqNVh6e1gu70dJGd9HhmiFukIcx/N1tdmQYhM3MUedEgbsvko8XtBD1g==} + + '@form-create/component-naive-radio@3.2.31': + resolution: {integrity: sha512-0XRQvtDAz25BDAuBARW2Ds0J5jCCTKgaVlv4/o7A8Ck16PF2rXdwU8XHaKEFQNb8Q8VMAFZjJgsQk5r+xZxCuw==} + + '@form-create/component-naive-upload@3.2.31': + resolution: {integrity: sha512-qYAZxtC09AJw8BaN913Gt22H0vymPfAFQMGhLP0gyJQv74dUa3caFrGAZkf5ie+/YbQEGqPnF5ckXGt5yS4VFg==} + + '@form-create/component-subform@3.2.34': + resolution: {integrity: sha512-h1AiMdpHfMr3s1AuX3L5BChc6Na5Megp/UU/FOCbAqt6+XEEEAKWt+2p6X1MMOJRLT+EI8ZRBcUfVbcw4/dHSQ==} + + '@form-create/component-wangeditor@3.2.14': + resolution: {integrity: sha512-N/U/hFBdBu2OIguxoKe1Kslq5fW6XmtyhKDImLfKLn1xI6X5WUtt3r7QTaUPcVUl2vntpM9wJ/FBdG17RzF/Dg==} + + '@form-create/core@3.2.37': + resolution: {integrity: sha512-1Wwr+6xMrL/6XfeeZJtlhMIKOWjwdUxuTiOJEApk+Q+Stsaz15LtKqsffyZTs7mN5DajUGnDxW8MP/myYgABXw==} + peerDependencies: + vue: ^3.5.27 + + '@form-create/designer@3.4.0': + resolution: {integrity: sha512-g1vUqX977lIHuWtAIhgLKZGZw87YClA1sJnLOFkweGA5CBJDhqNhvC4N0M1idkuKmCJtS+aweCYmrL2FapjDsw==} + peerDependencies: + vue: ^3.5.27 + + '@form-create/element-ui@3.2.37': + resolution: {integrity: sha512-KfC+a1zE1SfEpiZR3i+C95GPsoXajrT/b76bvToI6Nxk4SKSG+cqNyrS4FnRU0WbJlxjF9lzPJ+oejOLmqPjmQ==} + peerDependencies: + vue: ^3.5.27 + + '@form-create/naive-ui@3.2.37': + resolution: {integrity: sha512-8TuSIWg2DhAq/VV3TVe4kW0RM3lO2tIMNpwdZRciZKIPLI7ePjrZvA+H7ztc160C6DRgNDm+fRGh4H2COX44ig==} + peerDependencies: + vue: ^3.5.27 + + '@form-create/utils@3.2.31': + resolution: {integrity: sha512-YcisHXuQEF0r9y2VKS2CB2nMQ2q8EkKvQXp4nPR9sjbsCabPZOXq2n2MrkWDMhwQNwep08/0NCf7z0wslHzyWQ==} + + '@gera2ld/jsx-dom@2.2.2': + resolution: {integrity: sha512-EOqf31IATRE6zS1W1EoWmXZhGfLAoO9FIlwTtHduSrBdud4npYBxYAkv8dZ5hudDPwJeeSjn40kbCL4wAzr8dA==} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@ibm/telemetry-js@1.11.0': + resolution: {integrity: sha512-RO/9j+URJnSfseWg9ZkEX9p+a3Ousd33DBU7rOafoZB08RqdzxFVYJ2/iM50dkBuD0o7WX7GYt1sLbNgCoE+pA==} + hasBin: true + + '@iconify-json/logos@1.2.10': + resolution: {integrity: sha512-qxaXKJ6fu8jzTMPQdHtNxlfx6tBQ0jXRbHZIYy5Ilh8Lx9US9FsAdzZWUR8MXV8PnWTKGDFO4ZZee9VwerCyMA==} + + '@iconify-json/octicon@1.2.20': + resolution: {integrity: sha512-BCIWoh06jlOKMY3JCDx547g+4a0TOj96cdrtD1N4gz3oNlWF7yXdrK9WbqYN4ykmDl+KdJYRtOYIFP1AvGXgVA==} + + '@iconify-json/simple-icons@1.2.70': + resolution: {integrity: sha512-CYNRCgN6nBTjN4dNkrBCjHXNR2e4hQihdsZUs/afUNFOWLSYjfihca4EFN05rRvDk4Xoy2n8tym6IxBZmcn+Qg==} + + '@iconify-json/vscode-icons@1.2.41': + resolution: {integrity: sha512-2qMotu+RBsom/sqiInfZQGCeVm7KmSrZdjK0b4oGbOcOLL0vECSUuAuvrsCZIkYloqzY6EBg2lkaSfnByVebpg==} + + '@iconify/json@2.2.438': + resolution: {integrity: sha512-vDZEuUxqO9b29GBNQrblIH/sE4e1fwNuwZjm3q22w8sKv6bJnqtMw0nCDAf0RVlp+7IPPCRVkFnk6L78cXZ6cg==} + + '@iconify/tailwind@1.2.0': + resolution: {integrity: sha512-KgpIHWOTcRYw1XcoUqyNSrmYyfLLqZYu3AmP8zdfLk0F5TqRO8YerhlvlQmGfn7rJXgPeZN569xPAJnJ53zZxA==} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@3.1.0': + resolution: {integrity: sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==} + + '@iconify/vue@5.0.0': + resolution: {integrity: sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg==} + peerDependencies: + vue: ^3.5.27 + + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@internationalized/date@3.11.0': + resolution: {integrity: sha512-BOx5huLAWhicM9/ZFs84CzP+V3gBW6vlpM02yzsdYC7TGlZJX1OJiEEHcSayF00Z+3jLlm4w79amvSt6RqKN3Q==} + + '@internationalized/number@3.6.5': + resolution: {integrity: sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==} + + '@intlify/bundle-utils@10.0.1': + resolution: {integrity: sha512-WkaXfSevtpgtUR4t8K2M6lbR7g03mtOxFeh+vXp5KExvPqS12ppaRj1QxzwRuRI5VUto54A22BjKoBMLyHILWQ==} + engines: {node: '>= 18'} + peerDependencies: + petite-vue-i18n: '*' + vue-i18n: '*' + peerDependenciesMeta: + petite-vue-i18n: + optional: true + vue-i18n: + optional: true + + '@intlify/core-base@11.2.8': + resolution: {integrity: sha512-nBq6Y1tVkjIUsLsdOjDSJj4AsjvD0UG3zsg9Fyc+OivwlA/oMHSKooUy9tpKj0HqZ+NWFifweHavdljlBLTwdA==} + engines: {node: '>= 16'} + + '@intlify/message-compiler@11.2.8': + resolution: {integrity: sha512-A5n33doOjmHsBtCN421386cG1tWp5rpOjOYPNsnpjIJbQ4POF0QY2ezhZR9kr0boKwaHjbOifvyQvHj2UTrDFQ==} + engines: {node: '>= 16'} + + '@intlify/shared@11.2.8': + resolution: {integrity: sha512-l6e4NZyUgv8VyXXH4DbuucFOBmxLF56C/mqh2tvApbzl2Hrhi1aTDcuv5TKdxzfHYmpO3UB0Cz04fgDT9vszfw==} + engines: {node: '>= 16'} + + '@intlify/unplugin-vue-i18n@6.0.8': + resolution: {integrity: sha512-Vvm3KhjE6TIBVUQAk37rBiaYy2M5OcWH0ZcI1XKEsOTeN1o0bErk+zeuXmcrcMc/73YggfI8RoxOUz9EB/69JQ==} + engines: {node: '>= 18'} + peerDependencies: + petite-vue-i18n: '*' + vue: ^3.5.27 + vue-i18n: '*' + peerDependenciesMeta: + petite-vue-i18n: + optional: true + vue-i18n: + optional: true + + '@intlify/vue-i18n-extensions@8.0.0': + resolution: {integrity: sha512-w0+70CvTmuqbskWfzeYhn0IXxllr6mU+IeM2MU0M+j9OW64jkrvqY+pYFWrUnIIC9bEdij3NICruicwd5EgUuQ==} + engines: {node: '>= 18'} + peerDependencies: + '@intlify/shared': ^9.0.0 || ^10.0.0 || ^11.0.0 + '@vue/compiler-dom': ^3.0.0 + vue: ^3.5.27 + vue-i18n: ^9.0.0 || ^10.0.0 || ^11.0.0 + peerDependenciesMeta: + '@intlify/shared': + optional: true + '@vue/compiler-dom': + optional: true + vue: + optional: true + vue-i18n: + optional: true + + '@ioredis/commands@1.5.0': + resolution: {integrity: sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow==} + + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.1': + resolution: {integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==} + engines: {node: 20 || >=22} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@isaacs/cliui@9.0.0': + resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==} + engines: {node: '>=18'} + + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@jspm/generator@2.10.0': + resolution: {integrity: sha512-uP4qx/bh7eu7NVyEU5V0jjRUXmVtIiM1tsO9YwVFOlOkMUob5TRZfGac5bEo2qb+1AvSUN6IfFJP94iDnvSV1g==} + + '@jspm/import-map@1.2.2': + resolution: {integrity: sha512-QrM7+lkgVE8t9NZSm9fDSzheguEOVCOxueKxSwgoOt7yUWesWKDFmmL9bQFURl4IqMcpPz7VV2Tvw9s9emaJzQ==} + + '@juggle/resize-observer@3.4.0': + resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} + + '@keyv/bigmap@1.3.1': + resolution: {integrity: sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==} + engines: {node: '>= 18'} + peerDependencies: + keyv: ^5.6.0 + + '@keyv/serialize@1.1.1': + resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} + + '@lezer/common@1.5.1': + resolution: {integrity: sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==} + + '@lezer/highlight@1.2.3': + resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} + + '@lezer/lr@1.4.8': + resolution: {integrity: sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==} + + '@lezer/markdown@1.6.3': + resolution: {integrity: sha512-jpGm5Ps+XErS+xA4urw7ogEGkeZOahVQF21Z6oECF0sj+2liwZopd2+I8uH5I/vZsRuuze3OxBREIANLf6KKUw==} + + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/find-root@3.1.0': + resolution: {integrity: sha512-BcSqCyKhBVZ5YkSzOiheMCV41kqAFptW6xGqYSTjkVTl9XQpr+pqHhwgGCOHQtjDCv7Is6EFyA14Sm5GVbVABA==} + engines: {node: '>=20.0.0'} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + + '@manypkg/get-packages@3.1.0': + resolution: {integrity: sha512-0TbBVyvPrP7xGYBI/cP8UP+yl/z+HtbTttAD7FMAJgn/kXOTwh5/60TsqP9ZYY710forNfyV0N8P/IE/ujGZJg==} + engines: {node: '>=20.0.0'} + + '@manypkg/tools@2.1.0': + resolution: {integrity: sha512-0FOIepYR4ugPYaHwK7hDeHDkfPOBVvayt9QpvRbi2LT/h2b0GaE/gM9Gag7fsnyYyNaTZ2IGyOuVg07IYepvYQ==} + engines: {node: '>=20.0.0'} + + '@mapbox/node-pre-gyp@2.0.3': + resolution: {integrity: sha512-uwPAhccfFJlsfCxMYTwOdVfOz3xqyj8xYL3zJj8f0pb30tLohnnFPhLuqp4/qoEz8sNxe4SESZedcBojRefIzg==} + engines: {node: '>=18'} + hasBin: true + + '@marijn/find-cluster-break@1.0.2': + resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} + + '@microsoft/api-extractor-model@7.32.2': + resolution: {integrity: sha512-Ussc25rAalc+4JJs9HNQE7TuO9y6jpYQX9nWD1DhqUzYPBr3Lr7O9intf+ZY8kD5HnIqeIRJX7ccCT0QyBy2Ww==} + + '@microsoft/api-extractor@7.56.3': + resolution: {integrity: sha512-fRqok4aRNq5GpgGBv2fKlSSKbirPKTJ75vQefthB5x9dwt4Zz+AezUzdc1p/AG4wUBIgmhjcEwn/Rj+N4Wh4Mw==} + hasBin: true + + '@microsoft/fetch-event-source@2.0.1': + resolution: {integrity: sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==} + + '@microsoft/tsdoc-config@0.18.0': + resolution: {integrity: sha512-8N/vClYyfOH+l4fLkkr9+myAoR6M7akc8ntBJ4DJdWH2b09uVfr71+LTMpNyG19fNqWDg8KEDZhx5wxuqHyGjw==} + + '@microsoft/tsdoc@0.16.0': + resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} + + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nolebase/ui@2.18.2': + resolution: {integrity: sha512-xxfRacF9cqQ5/umMhvhr0y2W4SkhzTmrrAHJ0UAAu/pIWfV/JPE9Hj0buH06bK7ZEUur+036gxkKlStI6UtDBw==} + peerDependencies: + vitepress: ^1.5.0 || ^2.0.0-alpha.1 + vue: ^3.5.27 + + '@nolebase/vitepress-plugin-git-changelog@2.18.2': + resolution: {integrity: sha512-TT1nxP+iS+5K8OLtkEr1EZ4bhCa4iqggly0JTD7TsO01hcwzMovr0lRaxPTo/4i/0bwMiPcaKxpKJ2zJIiu4Kw==} + peerDependencies: + vitepress: ^1.5.0 || ^2.0.0-alpha.1 + + '@npmcli/fs@5.0.0': + resolution: {integrity: sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==} + engines: {node: ^20.17.0 || >=22.9.0} + + '@nuxt/kit@3.21.1': + resolution: {integrity: sha512-QORZRjcuTKgo++XP1Pc2c2gqwRydkaExrIRfRI9vFsPA3AzuHVn5Gfmbv1ic8y34e78mr5DMBvJlelUaeOuajg==} + engines: {node: '>=18.12.0'} + + '@nuxt/kit@4.3.1': + resolution: {integrity: sha512-UjBFt72dnpc+83BV3OIbCT0YHLevJtgJCHpxMX0YRKWLDhhbcDdUse87GtsQBrjvOzK7WUNUYLDS/hQLYev5rA==} + engines: {node: '>=18.12.0'} + + '@one-ini/wasm@0.1.1': + resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + + '@parcel/watcher-android-arm64@2.5.6': + resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.6': + resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.6': + resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.6': + resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.6': + resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm-musl@2.5.6': + resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-arm64-glibc@2.5.6': + resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm64-musl@2.5.6': + resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-x64-glibc@2.5.6': + resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-x64-musl@2.5.6': + resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@parcel/watcher-wasm@2.5.6': + resolution: {integrity: sha512-byAiBZ1t3tXQvc8dMD/eoyE7lTXYorhn+6uVW5AC+JGI1KtJC/LvDche5cfUE+qiefH+Ybq0bUCJU0aB1cSHUA==} + engines: {node: '>= 10.0.0'} + bundledDependencies: + - napi-wasm + + '@parcel/watcher-win32-arm64@2.5.6': + resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.6': + resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.6': + resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.6': + resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} + engines: {node: '>= 10.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.2.9': + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@playwright/test@1.58.2': + resolution: {integrity: sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==} + engines: {node: '>=18'} + hasBin: true + + '@pnpm/config.env-replace@1.1.0': + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + + '@pnpm/constants@1001.3.1': + resolution: {integrity: sha512-2hf0s4pVrVEH8RvdJJ7YRKjQdiG8m0iAT26TTqXnCbK30kKwJW69VLmP5tED5zstmDRXcOeH5eRcrpkdwczQ9g==} + engines: {node: '>=18.12'} + + '@pnpm/error@1000.0.5': + resolution: {integrity: sha512-GjH0TPjbVNrPnl/BAGoFuBLJ2sFfXNKbS33lll/Ehe9yw0fyc8Kdw7kO9if37yQqn6vaa4dAHKkPllum7f/IPQ==} + engines: {node: '>=18.12'} + + '@pnpm/network.ca-file@1.0.2': + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} + + '@pnpm/npm-conf@3.0.2': + resolution: {integrity: sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==} + engines: {node: '>=12'} + + '@pnpm/types@1001.3.0': + resolution: {integrity: sha512-NLTXheat/u7OEGg5M5vF6Z85zx8uKUZE0+whtX/sbFV2XL48RdnOWGPTKYuVVkv8M+launaLUTgGEXNs/ess2w==} + engines: {node: '>=18.12'} + + '@pnpm/workspace.read-manifest@1000.2.10': + resolution: {integrity: sha512-SnKM53rRYwpgrNI/LQ/4wa0BP9hkc29kQt2c9bBE1daDQP89z61v3LCkchnthgdE1s530JmaJRAf9tHtqRQ0jA==} + engines: {node: '>=18.12'} + + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + + '@poppinss/colors@4.1.6': + resolution: {integrity: sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==} + + '@poppinss/dumper@0.6.5': + resolution: {integrity: sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==} + + '@poppinss/exception@1.2.3': + resolution: {integrity: sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==} + + '@publint/pack@0.1.4': + resolution: {integrity: sha512-HDVTWq3H0uTXiU0eeSQntcVUTPP3GamzeXI41+x7uU9J65JgWQh3qWZHblR1i0npXfFtF+mxBiU2nJH8znxWnQ==} + engines: {node: '>=18'} + + '@rolldown/pluginutils@1.0.0-rc.2': + resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} + + '@rolldown/pluginutils@1.0.0-rc.3': + resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} + + '@rollup/plugin-alias@5.1.1': + resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-alias@6.0.0': + resolution: {integrity: sha512-tPCzJOtS7uuVZd+xPhoy5W4vThe6KWXNmsFCNktaAh5RTqcLiSfT4huPQIXkgJ6YCOjJHvecOAzQxLFhPxKr+g==} + engines: {node: '>=20.19.0'} + peerDependencies: + rollup: '>=4.0.0' + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-babel@5.3.1': + resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} + engines: {node: '>= 10.0.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@types/babel__core': ^7.1.9 + rollup: ^1.20.0||^2.0.0 + peerDependenciesMeta: + '@types/babel__core': + optional: true + + '@rollup/plugin-commonjs@28.0.9': + resolution: {integrity: sha512-PIR4/OHZ79romx0BVVll/PkwWpJ7e5lsqFa3gFfcrFPWwLXLV39JVUzQV9RKjWerE7B845Hqjj9VYlQeieZ2dA==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-commonjs@29.0.0': + resolution: {integrity: sha512-U2YHaxR2cU/yAiwKJtJRhnyLk7cifnQw0zUpISsocBDoHDJn+HTV74ABqnwr5bEgWUwFZC9oFL6wLe21lHu5eQ==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-inject@5.0.5': + resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-json@6.1.0': + resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@15.3.1': + resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@16.0.3': + resolution: {integrity: sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-replace@2.4.2': + resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + + '@rollup/plugin-replace@6.0.3': + resolution: {integrity: sha512-J4RZarRvQAm5IF0/LwUUg+obsm+xZhYnbMXmXROyoSE1ATJe3oXSb9L5MMppdxP2ylNSjv6zFBwKYjcKMucVfA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-terser@0.4.4': + resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/pluginutils@3.1.0': + resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + + '@rollup/pluginutils@4.2.1': + resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} + engines: {node: '>= 8.0.0'} + + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.57.1': + resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.57.1': + resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.57.1': + resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.57.1': + resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.57.1': + resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.57.1': + resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.57.1': + resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.57.1': + resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.57.1': + resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.57.1': + resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.57.1': + resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.57.1': + resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.57.1': + resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.57.1': + resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.57.1': + resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.57.1': + resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.57.1': + resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.57.1': + resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.57.1': + resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.57.1': + resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.57.1': + resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.57.1': + resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.57.1': + resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.57.1': + resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} + cpu: [x64] + os: [win32] + + '@rushstack/node-core-library@5.19.1': + resolution: {integrity: sha512-ESpb2Tajlatgbmzzukg6zyAhH+sICqJR2CNXNhXcEbz6UGCQfrKCtkxOpJTftWc8RGouroHG0Nud1SJAszvpmA==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/problem-matcher@0.1.1': + resolution: {integrity: sha512-Fm5XtS7+G8HLcJHCWpES5VmeMyjAKaWeyZU5qPzZC+22mPlJzAsOxymHiWIfuirtPckX3aptWws+K2d0BzniJA==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/rig-package@0.6.0': + resolution: {integrity: sha512-ZQmfzsLE2+Y91GF15c65L/slMRVhF6Hycq04D4TwtdGaUAbIXXg9c5pKA5KFU7M4QMaihoobp9JJYpYcaY3zOw==} + + '@rushstack/terminal@0.21.0': + resolution: {integrity: sha512-cLaI4HwCNYmknM5ns4G+drqdEB6q3dCPV423+d3TZeBusYSSm09+nR7CnhzJMjJqeRcdMAaLnrA4M/3xDz4R3w==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/ts-command-line@5.2.0': + resolution: {integrity: sha512-lYxCX0nDdkDtCkVpvF0m25ymf66SaMWuppbD6b7MdkIzvGXKBXNIVZlwBH/C0YfkanrupnICWf2n4z3AKSfaHw==} + + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@shikijs/core@2.5.0': + resolution: {integrity: sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==} + + '@shikijs/engine-javascript@2.5.0': + resolution: {integrity: sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==} + + '@shikijs/engine-oniguruma@2.5.0': + resolution: {integrity: sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==} + + '@shikijs/langs@2.5.0': + resolution: {integrity: sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==} + + '@shikijs/themes@2.5.0': + resolution: {integrity: sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==} + + '@shikijs/transformers@2.5.0': + resolution: {integrity: sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==} + + '@shikijs/types@2.5.0': + resolution: {integrity: sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@simonwep/pickr@1.8.2': + resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==} + + '@sindresorhus/base62@1.0.0': + resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==} + engines: {node: '>=18'} + + '@sindresorhus/is@7.2.0': + resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} + engines: {node: '>=18'} + + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@speed-highlight/core@1.2.14': + resolution: {integrity: sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA==} + + '@stylistic/stylelint-plugin@4.0.1': + resolution: {integrity: sha512-jKZSZr/S/NehfgayNJI3O/JEq+W5lSeHUJNvdOebRPNFP2ZylTbAx/p5qR8scQFpiVzy1VQM9R+G0kIB62r1Pw==} + engines: {node: ^18.12 || >=20.9} + peerDependencies: + stylelint: ^16.22.0 + + '@surma/rollup-plugin-off-main-thread@2.2.3': + resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} + + '@svelte-put/shortcut@4.1.0': + resolution: {integrity: sha512-wImNEIkbxAIWFqlfuhcbC+jRPDeRa/uJGIXHMEVVD+jqL9xCwWNnkGQJ6Qb2XVszuRLHlb8SGZDL3Io/h3vs8w==} + peerDependencies: + svelte: ^5.1.0 + + '@sveltejs/acorn-typescript@1.0.8': + resolution: {integrity: sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==} + peerDependencies: + acorn: ^8.9.0 + + '@swc/helpers@0.5.18': + resolution: {integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==} + + '@sxzz/popperjs-es@2.11.8': + resolution: {integrity: sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==} + + '@tailwindcss/nesting@0.0.0-insiders.565cd3e': + resolution: {integrity: sha512-WhHoFBx19TnH/c+xLwT/sxei6+4RpdfiyG3MYXfmLaMsADmVqBkF7B6lDalgZD9YdM459MF7DtxVbWkOrV7IaQ==} + peerDependencies: + postcss: ^8.2.15 + + '@tailwindcss/typography@0.5.19': + resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' + + '@tanstack/store@0.8.0': + resolution: {integrity: sha512-Om+BO0YfMZe//X2z0uLF2j+75nQga6TpTJgLJQBiq85aOyZNIhkCgleNcud2KQg4k4v9Y9l+Uhru3qWMPGTOzQ==} + + '@tanstack/virtual-core@3.13.18': + resolution: {integrity: sha512-Mx86Hqu1k39icq2Zusq+Ey2J6dDWTjDvEv43PJtRCoEYTLyfaPnxIQ6iy7YAOK0NV/qOEmZQ/uCufrppZxTgcg==} + + '@tanstack/vue-store@0.8.0': + resolution: {integrity: sha512-YLsinYboBLIjNkxDpAn1ydaMS35dKq3M3a788JRCJi4/stWcN7Swp0pxxJ+p0IwKSY4tBXx7vMz22OYWQ1QsUQ==} + peerDependencies: + '@vue/composition-api': ^1.2.1 + vue: ^3.5.27 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + '@tanstack/vue-virtual@3.13.18': + resolution: {integrity: sha512-6pT8HdHtTU5Z+t906cGdCroUNA5wHjFXsNss9gwk7QAr1VNZtz9IQCs2Nhx0gABK48c+OocHl2As+TMg8+Hy4A==} + peerDependencies: + vue: ^3.5.27 + + '@tinyflow-ai/ui@1.1.10': + resolution: {integrity: sha512-l3kIYNq3K7LPKdcR6Dl60qwE039O4bdl7vRNnc1gqL0Rnzh6KTwYiwGvnwU8v96aoqCbRdPfvuvaaSrJomGf3Q==} + + '@tinyflow-ai/vue@1.1.10': + resolution: {integrity: sha512-wK27NL3V00eFYDPRSioYCrmEsk5mvRFNooJR2bEgdYGmYWXSRkwYzPQy4dn1MrmGDMsqNYK3XjKRRvN7g+lofg==} + peerDependencies: + vue: ^3.5.27 + + '@tinymce/tinymce-vue@6.3.0': + resolution: {integrity: sha512-DSP8Jhd3XqCCliTnusfbmz3D8GqQ4iRzkc4aadYHDcJPVjkaqopJ61McOdH82CSy599vGLkPjGzqJYWJkRMiUA==} + peerDependencies: + tinymce: ^8.0.0 || ^7.0.0 || ^6.0.0 || ^5.5.1 + vue: ^3.5.27 + peerDependenciesMeta: + tinymce: + optional: true + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/archiver@6.0.4': + resolution: {integrity: sha512-ULdQpARQ3sz9WH4nb98mJDYA0ft2A8C4f4fovvUcFwINa1cgGjY36JCAYuP5YypRq4mco1lJp1/7jEMS2oR0Hg==} + + '@types/argparse@1.0.38': + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + + '@types/bintrees@1.0.6': + resolution: {integrity: sha512-pZWT4Bz+tWwxlDspSjdoIza4PE5lbGI4Xvs3FZV/2v5m5SDA8LwNpU8AXxlndmARO7OaQ1Vf3zFenOsNMzaRkQ==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/codemirror@5.60.17': + resolution: {integrity: sha512-AZq2FIsUHVMlp7VSe2hTfl5w4pcUkoFkM3zVsRKsn1ca8CXRDYvnin04+HP2REkwsxemuHqvDofdlhUWNpbwfw==} + + '@types/conventional-commits-parser@5.0.2': + resolution: {integrity: sha512-BgT2szDXnVypgpNxOK8aL5SGjUdaQbC++WZNjF1Qge3Og2+zhHj+RWhmehLhYyvQwqAmvezruVfOf8+3m74W+g==} + + '@types/crypto-js@4.2.2': + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} + + '@types/d3-array@3.2.2': + resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} + + '@types/d3-axis@3.0.6': + resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} + + '@types/d3-brush@3.0.6': + resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} + + '@types/d3-chord@3.0.6': + resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} + + '@types/d3-color@3.1.3': + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + + '@types/d3-contour@3.0.6': + resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} + + '@types/d3-delaunay@6.0.4': + resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} + + '@types/d3-dispatch@3.0.7': + resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==} + + '@types/d3-drag@3.0.7': + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} + + '@types/d3-dsv@3.0.7': + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} + + '@types/d3-ease@3.0.2': + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + + '@types/d3-fetch@3.0.7': + resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} + + '@types/d3-force@3.0.10': + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} + + '@types/d3-format@3.0.4': + resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} + + '@types/d3-geo@3.1.0': + resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} + + '@types/d3-hierarchy@3.1.7': + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} + + '@types/d3-interpolate@3.0.4': + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + + '@types/d3-path@3.1.1': + resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==} + + '@types/d3-polygon@3.0.2': + resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} + + '@types/d3-quadtree@3.0.6': + resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} + + '@types/d3-random@3.0.3': + resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==} + + '@types/d3-scale-chromatic@3.1.0': + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} + + '@types/d3-scale@4.0.9': + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} + + '@types/d3-selection@3.0.11': + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} + + '@types/d3-shape@3.1.8': + resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + + '@types/d3-time-format@4.0.3': + resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} + + '@types/d3-time@3.0.4': + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + + '@types/d3-timer@3.0.2': + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + + '@types/d3-transition@3.0.9': + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} + + '@types/d3-zoom@3.0.8': + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} + + '@types/d3@7.4.3': + resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/estree@0.0.39': + resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/geojson@7946.0.16': + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/html-minifier-terser@7.0.2': + resolution: {integrity: sha512-mm2HqV22l8lFQh4r2oSsOEVea+m0qqxEmwpc9kC1p/XzmjLWrReR9D/GRs8Pex2NX/imyEH9c5IU/7tMBQCHOA==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/katex@0.16.8': + resolution: {integrity: sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==} + + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash.clonedeep@4.5.9': + resolution: {integrity: sha512-19429mWC+FyaAhOLzsS8kZUsI+/GmBAQ0HFiCPsKGU+7pBXOQWhyrY6xNNDwUSX8SMZMJvuFVMF9O5dQOlQK9Q==} + + '@types/lodash@4.17.23': + resolution: {integrity: sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==} + + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + + '@types/minimatch@3.0.5': + resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} + + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + + '@types/node@24.10.13': + resolution: {integrity: sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==} + + '@types/node@25.2.3': + resolution: {integrity: sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==} + + '@types/nprogress@0.2.3': + resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} + + '@types/parse-json@4.0.2': + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + + '@types/postcss-import@14.0.3': + resolution: {integrity: sha512-raZhRVTf6Vw5+QbmQ7LOHSDML71A5rj4+EqDzAbrZPfxfoGzFxMHRCq16VlddGIZpHELw0BG4G0YE2ANkdZiIQ==} + + '@types/qrcode@1.5.6': + resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==} + + '@types/qs@6.14.0': + resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + + '@types/readdir-glob@1.1.5': + resolution: {integrity: sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==} + + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + + '@types/sortablejs@1.15.9': + resolution: {integrity: sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ==} + + '@types/tern@0.23.9': + resolution: {integrity: sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==} + + '@types/tinycolor2@1.4.6': + resolution: {integrity: sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/validator@13.15.10': + resolution: {integrity: sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==} + + '@types/video.js@7.3.58': + resolution: {integrity: sha512-1CQjuSrgbv1/dhmcfQ83eVyYbvGyqhTvb2Opxr0QCV+iJ4J6/J+XWQ3Om59WiwCd1MN3rDUHasx5XRrpUtewYQ==} + + '@types/web-bluetooth@0.0.20': + resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + + '@typescript-eslint/eslint-plugin@8.55.0': + resolution: {integrity: sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.55.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.55.0': + resolution: {integrity: sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.55.0': + resolution: {integrity: sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@7.18.0': + resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/scope-manager@8.55.0': + resolution: {integrity: sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.55.0': + resolution: {integrity: sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.55.0': + resolution: {integrity: sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@7.18.0': + resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/types@8.55.0': + resolution: {integrity: sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@7.18.0': + resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/typescript-estree@8.55.0': + resolution: {integrity: sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@7.18.0': + resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + + '@typescript-eslint/utils@8.55.0': + resolution: {integrity: sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@7.18.0': + resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/visitor-keys@8.55.0': + resolution: {integrity: sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + cpu: [x64] + os: [win32] + + '@v-c/async-validator@1.0.0': + resolution: {integrity: sha512-nwi4hW/V3L5M4qY8cwScEuUonGfm1KRmN6aPwGpG9zhy7UDTEXKA3Tv4pdfjY9ryXKQc5TYo78TLSX9EjAPLUA==} + + '@v-c/cascader@1.0.0': + resolution: {integrity: sha512-GoDcocPUnIgJOVknk96nxzx7Jkf9kFKJ+sjcZPT45pBynZvaMOFJ9ZLGMB2ZMOYtRr0SfXeqZ09lLy9c8PtwZw==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/checkbox@1.0.1': + resolution: {integrity: sha512-+QsE/0VfU6oeglwuHWYxRNTn3+eV08iG0uN/upDmqSGznezInzfUClh+t4acd/OxyJVtuob0WKsg/vPlT6WRWw==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/collapse@1.0.0': + resolution: {integrity: sha512-y4NAl3j4mka193ZMDLHdISA8to61qoROG6/kTQ0myM2ZuEsonnEK1QWlqoEw3gveMsa6a4RdyoXLxdGdcJyp0Q==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/color-picker@1.0.5': + resolution: {integrity: sha512-n8wydSJExOwvPR4mqW/xmQb9FUFIaA87u0PlcZoJnW8craJtU2+iYm9BlgzGhSm+Nu3Dx9TYypO+xJ4pwhnuPg==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/dialog@1.0.1': + resolution: {integrity: sha512-8+HqvlDXGcgie4Z+sQB3HnMkkFN0N1zfIxdQwtpXTl+gWu9ue8tz+zI7pNXMq7XdM3DU6A+x+qeNRstJ2poCbw==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/drawer@1.0.0': + resolution: {integrity: sha512-1FhalqOqDmdvEfXGmlEZtwbeZBMKeK3+LIeDfXfqUiLy38QMMDTxMARmnHCxUGhuj20zFxrZUl0sxNEaTjTkEA==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/dropdown@1.0.2': + resolution: {integrity: sha512-D6TACf3jUiRWx4xW5h2+wVT9SMYxUasFlAHESYJr4ZMjLTLLM1Q8iBjkjhGF+vA0eYR5zqRTwlaacN0DNDZBPw==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/image@1.0.2': + resolution: {integrity: sha512-uTAhX+SRWjQHIUPJ0DAYUSzOEVnVDAmZazJNP5OqCqLuncrS7hUN37CQ1XgNKaF2Dt8b1aPFZlpXYb/zXfQdXw==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/input-number@1.0.2': + resolution: {integrity: sha512-9wbAmdC0Nt18XlLLgfVbmulY50K7tc5RZsNeZuWnmqluTK3JTgZRSbPdRkzl308x8vtGyCOufnepsMrFei1NoQ==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/input@1.0.2': + resolution: {integrity: sha512-NzBor6XbUYP42zRrcaBUgWtQI1aIaN3oylmMdvSZ5UMcWsAXRNC8XKsedkFF/LLOEJBJ2NaTbomHRwkIjmtQAA==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/mentions@1.0.0': + resolution: {integrity: sha512-trkG1lvfiaIY7UnHn0gx6B01o3rFLEMin3KGp1q4oU6zOCRWde4ejZ+EHSvmXzOz2N+FlRMTE4EMJFi4w0oOlQ==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/menu@1.0.10': + resolution: {integrity: sha512-iKXuPpZteVjPlg3nQ+4YbAlYa3/I21N/5RswKLai61IRO/8IcfRLc+YBEoG3n5xV+I5b2Yby2iJjsA8lU1En/w==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/mini-decimal@1.0.1': + resolution: {integrity: sha512-76wZLdlkI017iDlaZMNOWZyDCv29YVabUJn5urQgIKtW4dnI5AkNXWtmLyhl/mu/OS7ZGisRi5ai/558QhLQxQ==} + + '@v-c/mutate-observer@1.0.1': + resolution: {integrity: sha512-84+9KGORX8LY9u+K0DEGyRwRCJaky0sjRkXxBC7X/jahHJl8NQGQ0Gxve5IVwaxRTfZ9eftlRmHs90JD6Utfqg==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/notification@1.0.0': + resolution: {integrity: sha512-aU5g+ZiYxp0KVdKuho067wJRF38Mv7MrQS95dwSJLsbDmVFBpjO3Lo3ptakfPkwn+7uwRytHKIf39t9QVGk+sg==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/overflow@1.0.3': + resolution: {integrity: sha512-GVWxd2gk9T0t9kO7EH1fMy2DgYULle/D+GBXiEeB5j/V1b9Gj39pvFLA1EHuiiyJW56Lr/P/uJ/ZM38WFh755w==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/pagination@1.0.0': + resolution: {integrity: sha512-uYIMkvHKMtY+nwHTu5rXxiq6KPf0zGpZbtQTn1nDPng0tOyA1vLQ+R6OfE+1LOwuQqvFTEDnAq4vb90By+eBfw==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/picker@1.0.2': + resolution: {integrity: sha512-Lf9qPZ/hODaIBEoXpkpGmHK5oXubquia8bYN8zVWigr312jbl/bI6txRF4p+zci0UTtJQsOX1zp9fqX8rg0vSA==} + peerDependencies: + date-fns: '>= 2.x' + dayjs: '>= 1.x' + luxon: '>= 3.x' + moment: '>= 2.x' + vue: ^3.5.27 + peerDependenciesMeta: + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + + '@v-c/portal@1.0.7': + resolution: {integrity: sha512-iIcU+9C8GNas7BWMXlWkwz9RoB8E7B4f0D+qPNTPLUbdwDvKRNypATYImkIWK/BSGDHOkxu1kIBshxgolaODfA==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/progress@1.0.0': + resolution: {integrity: sha512-kWDTU1uXnPDMmoezwyAECxuSH+WKn92OjSdk/GgDbQgZ0qNy9woOiRe5fOsrcy61agHdJxzf0MvsUy1b6bZVlA==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/qrcode@1.0.0': + resolution: {integrity: sha512-OSMrYDhP/NQiUcO6J0X2X8BskHPRqX/E/F9npH3oayZgjCo5Aom+63Ja3J0u6SOmKP1JgLSgjrm5karc0671jw==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/rate@1.0.0': + resolution: {integrity: sha512-H2cj/dS3guxq9s79HlTzu8uUzH/dQM8Ko5zlPosWrBI33YvySqoxcShY8cZS/tcq8I4xDE/SjeAmBe7rHd9VEA==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/resize-observer@1.0.8': + resolution: {integrity: sha512-VH8WBsNfZA5KQ+CXVaQ1PK5B6FIHnuTdqOLrjRWiZTrIYDZi/MyREi9b21YDj55fbFWMRx4yapnO9tiZX1RNxA==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/segmented@1.0.0': + resolution: {integrity: sha512-HWo8Ck6Lg0epTEvw5d2yhE+mU/SOxTN6/ngMXLz7iwGI2TwskKu8l+atOSNcJ7XqS/QgsqIHpL26GATPOS8qvQ==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/select@1.0.9': + resolution: {integrity: sha512-RpZMtjKi3BIWj2+SKJKFKhydBE0Q0vZYyJduJZ6GioBi7JF26JPQuwZOsthaHDVr6oaOoc9ejlSAQqP92tFIKA==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/slick@1.0.0': + resolution: {integrity: sha512-Pzb4bahxbXvXTCmgOJ9OX6Ek1joUHx0EFUxmjDSAfrvaAkHWv2pSqGLDF0CJvm+/uG+rcdT2YQUNcxMtKInQ3A==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/slider@1.0.10': + resolution: {integrity: sha512-KMIVytBm8K8RQ+aPPraS28GmBptGHESF/gDRbGjOLD7xyivuQDJeEqVaUFY3EcCWsERjh4VP/L96gUbMTF0uag==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/steps@1.0.0': + resolution: {integrity: sha512-DPL0OOb8pDLlTPZB93b8+Saxiz6V5zEpGXKaCnsbXUuOhimkc7089AuEKfpMw+8x1SrVe+gapWf5RRHWXUm2pg==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/switch@1.0.0': + resolution: {integrity: sha512-VIem244KJkYfqDgofpgHjK00sGL9rJ/9OtmK4Gbs4hnPsrTtzHDBRltYxR4IT7HQleathZfj6NhcZ1bjdWKYUw==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/table@1.0.0': + resolution: {integrity: sha512-1/TMEppX3BpLYYSXzAcwrD5Os6O1VX5OGZsvGyqIp9A8Iy8QeI4Vb54XizGyooHNMs378RIWzX4yDe9JxYMm/A==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/tabs@1.0.1': + resolution: {integrity: sha512-6G6cWKdxb8l3IuR802mZGV+l8GAvCEJCoVQcyG3BwiBYOeOii6eyET5D+yMp7mC7dsFRxc2y7q0krxyo97CosQ==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/textarea@1.0.3': + resolution: {integrity: sha512-oCpqdOyiNPFgLRUw913IjTdIMVtryy9maJEaSz+ledn/cVO4OJ44dEP8eCnhxlHTfduLKesKIlDoRIBhLu4qqQ==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/tooltip@1.0.3': + resolution: {integrity: sha512-72EkTfhb67RPJvMXIW6HUYiZ+Jdrb7tBQmS3wDtFDNU7uIrS5DQLyXJDCu9qWlrPv7cQ/RHA4JfCINw88vchzw==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/tour@1.0.3': + resolution: {integrity: sha512-y4DVJPP7jvL+MWUMAKQWxLAMXSWJEfZXaKASPn3DKbSQ8drBhsjMXwcep3glAfrCjCKfj/QD3OrUMxqydi4qFw==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/tree-select@1.0.0': + resolution: {integrity: sha512-EOUt3zBFMm2wCCDgY5pYU2mjff7NQiGss0uM/J2dOw8JP3LgPjhCuT2/0ZgXt6HkqK+Fl5AdhzxYujGbgTw6Ow==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/tree@1.0.2': + resolution: {integrity: sha512-Z/x1DuazauoPtuKWaL6iaNdTq6t/c+6j8dbOxQN7kAJOW4RJ8BKKx8DA0fq49R7OCUH/YQLOWTrWI5gyQ0169A==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/trigger@1.0.11': + resolution: {integrity: sha512-a81J89KmTNn99xtGHYXswkvqxnP17AFsgfkEF2SPj2Hp4igJSUT3XVEaqWLwBdO7icV7Il1qrMKOe/8YA7CTjQ==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/upload@1.0.0': + resolution: {integrity: sha512-W92PNCD61aM/B5w8oUzHQSDHur1T8484726Ls0IoNMO5nPiF/15eEE3RuuI/t7xXQVP/fA06hNSwzXwGWdDg1w==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/util@1.0.13': + resolution: {integrity: sha512-/CUsbqrgqMz2TGqdzUnq1jwNFwX6lqy+HsYzmGH8auTUly9buIQiDmoxLxnjsI2XO6IryCqhzOP2Ii1213zqtA==} + peerDependencies: + vue: ^3.5.27 + + '@v-c/virtual-list@1.0.5': + resolution: {integrity: sha512-hv+ZIXkT7Bprv4pRloa/EYfWsJjOL2hI6wRSWX/XOxMcra+eq9uFvTY5GSOzYURPyzA/ExGq4607+fl1vEhwZQ==} + peerDependencies: + vue: ^3.5.27 + + '@vee-validate/zod@4.15.1': + resolution: {integrity: sha512-329Z4TDBE5Vx0FdbA8S4eR9iGCFFUNGbxjpQ20ff5b5wGueScjocUIx9JHPa79LTG06RnlUR4XogQsjN4tecKA==} + peerDependencies: + zod: ^3.24.0 + + '@vercel/nft@1.3.1': + resolution: {integrity: sha512-ihNT1rswiq3cy4WKQAV5kJi6UjWX1vLUzlLc+Vvq83G8CU9nMgfDWz5f1tOnSlS8LeC4Wp4qTB3+HGj/ccUrFQ==} + engines: {node: '>=20'} + hasBin: true + + '@videojs-player/vue@1.0.0': + resolution: {integrity: sha512-WonTezRfKu3fYdQLt/ta+nuKH6gMZUv8l40Jke/j4Lae7IqeO/+lLAmBnh3ni88bwR+vkFXIlZ2Ci7VKInIYJg==} + peerDependencies: + '@types/video.js': 7.x + video.js: 7.x + vue: ^3.5.27 + + '@videojs/http-streaming@2.16.3': + resolution: {integrity: sha512-91CJv5PnFBzNBvyEjt+9cPzTK/xoVixARj2g7ZAvItA+5bx8VKdk5RxCz/PP2kdzz9W+NiDUMPkdmTsosmy69Q==} + engines: {node: '>=8', npm: '>=5'} + peerDependencies: + video.js: ^6 || ^7 + + '@videojs/vhs-utils@3.0.5': + resolution: {integrity: sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==} + engines: {node: '>=8', npm: '>=5'} + + '@videojs/xhr@2.6.0': + resolution: {integrity: sha512-7J361GiN1tXpm+gd0xz2QWr3xNWBE+rytvo8J3KuggFaLg+U37gZQ2BuPLcnkfGffy2e+ozY70RHC8jt7zjA6Q==} + + '@vite-pwa/vitepress@1.1.0': + resolution: {integrity: sha512-enif5C2JmepS69Ak7PSr6K3Eimsg7VyryZo1Z6NiIPNDnjXFlOqxwBYaq8R/d0M7akArJsjos7KmQnEfNFf5nA==} + peerDependencies: + '@vite-pwa/assets-generator': ^1.0.0 + vite-plugin-pwa: ^1.2.0 + peerDependenciesMeta: + '@vite-pwa/assets-generator': + optional: true + + '@vitejs/plugin-vue-jsx@5.1.4': + resolution: {integrity: sha512-70LmoVk9riR7qc4W2CpjsbNMWTPnuZb9dpFKX1emru0yP57nsc9k8nhLA6U93ngQapv5VDIUq2JatNfLbBIkrA==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + vue: ^3.5.27 + + '@vitejs/plugin-vue@5.2.4': + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.5.27 + + '@vitejs/plugin-vue@6.0.4': + resolution: {integrity: sha512-uM5iXipgYIn13UUQCZNdWkYk+sysBeA97d5mHsAoAt1u/wpN3+zxOmsVJWosuzX+IMGRzeYUNytztrYznboIkQ==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + vue: ^3.5.27 + + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + + '@volar/language-core@2.4.27': + resolution: {integrity: sha512-DjmjBWZ4tJKxfNC1F6HyYERNHPYS7L7OPFyCrestykNdUZMFYzI9WTyvwPcaNaHlrEUwESHYsfEw3isInncZxQ==} + + '@volar/language-core@2.4.28': + resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} + + '@volar/source-map@2.4.27': + resolution: {integrity: sha512-ynlcBReMgOZj2i6po+qVswtDUeeBRCTgDurjMGShbm8WYZgJ0PA4RmtebBJ0BCYol1qPv3GQF6jK7C9qoVc7lg==} + + '@volar/source-map@2.4.28': + resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==} + + '@volar/typescript@2.4.27': + resolution: {integrity: sha512-eWaYCcl/uAPInSK2Lze6IqVWaBu/itVqR5InXcHXFyles4zO++Mglt3oxdgj75BDcv1Knr9Y93nowS8U3wqhxg==} + + '@volar/typescript@2.4.28': + resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} + + '@vue/babel-helper-vue-transform-on@1.5.0': + resolution: {integrity: sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==} + + '@vue/babel-helper-vue-transform-on@2.0.1': + resolution: {integrity: sha512-uZ66EaFbnnZSYqYEyplWvn46GhZ1KuYSThdT68p+am7MgBNbQ3hphTL9L+xSIsWkdktwhPYLwPgVWqo96jDdRA==} + + '@vue/babel-plugin-jsx@1.5.0': + resolution: {integrity: sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + + '@vue/babel-plugin-jsx@2.0.1': + resolution: {integrity: sha512-a8CaLQjD/s4PVdhrLD/zT574ZNPnZBOY+IhdtKWRB4HRZ0I2tXBi5ne7d9eCfaYwp5gU5+4KIyFTV1W1YL9xZA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + + '@vue/babel-plugin-resolve-type@1.5.0': + resolution: {integrity: sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@vue/babel-plugin-resolve-type@2.0.1': + resolution: {integrity: sha512-ybwgIuRGRRBhOU37GImDoWQoz+TlSqap65qVI6iwg/J7FfLTLmMf97TS7xQH9I7Qtr/gp161kYVdhr1ZMraSYQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@vue/compiler-core@3.5.28': + resolution: {integrity: sha512-kviccYxTgoE8n6OCw96BNdYlBg2GOWfBuOW4Vqwrt7mSKWKwFVvI8egdTltqRgITGPsTFYtKYfxIG8ptX2PJHQ==} + + '@vue/compiler-dom@3.5.28': + resolution: {integrity: sha512-/1ZepxAb159jKR1btkefDP+J2xuWL5V3WtleRmxaT+K2Aqiek/Ab/+Ebrw2pPj0sdHO8ViAyyJWfhXXOP/+LQA==} + + '@vue/compiler-sfc@3.5.28': + resolution: {integrity: sha512-6TnKMiNkd6u6VeVDhZn/07KhEZuBSn43Wd2No5zaP5s3xm8IqFTHBj84HJah4UepSUJTro5SoqqlOY22FKY96g==} + + '@vue/compiler-ssr@3.5.28': + resolution: {integrity: sha512-JCq//9w1qmC6UGLWJX7RXzrGpKkroubey/ZFqTpvEIDJEKGgntuDMqkuWiZvzTzTA5h2qZvFBFHY7fAAa9475g==} + + '@vue/compiler-vue2@2.7.16': + resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + + '@vue/devtools-api@6.6.4': + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} + + '@vue/devtools-api@7.7.9': + resolution: {integrity: sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==} + + '@vue/devtools-core@8.0.6': + resolution: {integrity: sha512-fN7iVtpSQQdtMORWwVZ1JiIAKriinhD+lCHqPw9Rr252ae2TczILEmW0zcAZifPW8HfYcbFkn+h7Wv6kQQCayw==} + peerDependencies: + vue: ^3.5.27 + + '@vue/devtools-kit@7.7.9': + resolution: {integrity: sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==} + + '@vue/devtools-kit@8.0.6': + resolution: {integrity: sha512-9zXZPTJW72OteDXeSa5RVML3zWDCRcO5t77aJqSs228mdopYj5AiTpihozbsfFJ0IodfNs7pSgOGO3qfCuxDtw==} + + '@vue/devtools-shared@7.7.9': + resolution: {integrity: sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==} + + '@vue/devtools-shared@8.0.6': + resolution: {integrity: sha512-Pp1JylTqlgMJvxW6MGyfTF8vGvlBSCAvMFaDCYa82Mgw7TT5eE5kkHgDvmOGHWeJE4zIDfCpCxHapsK2LtIAJg==} + + '@vue/language-core@2.2.0': + resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/language-core@3.2.4': + resolution: {integrity: sha512-bqBGuSG4KZM45KKTXzGtoCl9cWju5jsaBKaJJe3h5hRAAWpZUuj5G+L+eI01sPIkm4H6setKRlw7E85wLdDNew==} + + '@vue/reactivity@3.5.28': + resolution: {integrity: sha512-gr5hEsxvn+RNyu9/9o1WtdYdwDjg5FgjUSBEkZWqgTKlo/fvwZ2+8W6AfKsc9YN2k/+iHYdS9vZYAhpi10kNaw==} + + '@vue/runtime-core@3.5.28': + resolution: {integrity: sha512-POVHTdbgnrBBIpnbYU4y7pOMNlPn2QVxVzkvEA2pEgvzbelQq4ZOUxbp2oiyo+BOtiYlm8Q44wShHJoBvDPAjQ==} + + '@vue/runtime-dom@3.5.28': + resolution: {integrity: sha512-4SXxSF8SXYMuhAIkT+eBRqOkWEfPu6nhccrzrkioA6l0boiq7sp18HCOov9qWJA5HML61kW8p/cB4MmBiG9dSA==} + + '@vue/server-renderer@3.5.28': + resolution: {integrity: sha512-pf+5ECKGj8fX95bNincbzJ6yp6nyzuLDhYZCeFxUNp8EBrQpPpQaLX3nNCp49+UbgbPun3CeVE+5CXVV1Xydfg==} + peerDependencies: + vue: ^3.5.27 + + '@vue/shared@3.5.28': + resolution: {integrity: sha512-cfWa1fCGBxrvaHRhvV3Is0MgmrbSCxYTXCSCau2I0a1Xw1N1pHAvkWCiXPRAqjvToILvguNyEwjevUqAuBQWvQ==} + + '@vue/test-utils@2.4.6': + resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==} + + '@vueuse/core@10.11.1': + resolution: {integrity: sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==} + + '@vueuse/core@12.8.2': + resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==} + + '@vueuse/core@13.9.0': + resolution: {integrity: sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==} + peerDependencies: + vue: ^3.5.27 + + '@vueuse/core@14.2.1': + resolution: {integrity: sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==} + peerDependencies: + vue: ^3.5.27 + + '@vueuse/integrations@12.8.2': + resolution: {integrity: sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==} + peerDependencies: + async-validator: ^4 + axios: ^1 + change-case: ^5 + drauu: ^0.4 + focus-trap: ^7 + fuse.js: ^7 + idb-keyval: ^6 + jwt-decode: ^4 + nprogress: ^0.2 + qrcode: ^1.5 + sortablejs: ^1 + universal-cookie: ^7 + peerDependenciesMeta: + async-validator: + optional: true + axios: + optional: true + change-case: + optional: true + drauu: + optional: true + focus-trap: + optional: true + fuse.js: + optional: true + idb-keyval: + optional: true + jwt-decode: + optional: true + nprogress: + optional: true + qrcode: + optional: true + sortablejs: + optional: true + universal-cookie: + optional: true + + '@vueuse/integrations@14.2.1': + resolution: {integrity: sha512-2LIUpBi/67PoXJGqSDQUF0pgQWpNHh7beiA+KG2AbybcNm+pTGWT6oPGlBgUoDWmYwfeQqM/uzOHqcILpKL7nA==} + peerDependencies: + async-validator: ^4 + axios: ^1 + change-case: ^5 + drauu: ^0.4 + focus-trap: ^7 || ^8 + fuse.js: ^7 + idb-keyval: ^6 + jwt-decode: ^4 + nprogress: ^0.2 + qrcode: ^1.5 + sortablejs: ^1 + universal-cookie: ^7 || ^8 + vue: ^3.5.27 + peerDependenciesMeta: + async-validator: + optional: true + axios: + optional: true + change-case: + optional: true + drauu: + optional: true + focus-trap: + optional: true + fuse.js: + optional: true + idb-keyval: + optional: true + jwt-decode: + optional: true + nprogress: + optional: true + qrcode: + optional: true + sortablejs: + optional: true + universal-cookie: + optional: true + + '@vueuse/metadata@10.11.1': + resolution: {integrity: sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==} + + '@vueuse/metadata@12.8.2': + resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==} + + '@vueuse/metadata@13.9.0': + resolution: {integrity: sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==} + + '@vueuse/metadata@14.2.1': + resolution: {integrity: sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw==} + + '@vueuse/motion@3.0.3': + resolution: {integrity: sha512-4B+ITsxCI9cojikvrpaJcLXyq0spj3sdlzXjzesWdMRd99hhtFI6OJ/1JsqwtF73YooLe0hUn/xDR6qCtmn5GQ==} + peerDependencies: + vue: ^3.5.27 + + '@vueuse/shared@10.11.1': + resolution: {integrity: sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==} + + '@vueuse/shared@12.8.2': + resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==} + + '@vueuse/shared@13.9.0': + resolution: {integrity: sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==} + peerDependencies: + vue: ^3.5.27 + + '@vueuse/shared@14.2.1': + resolution: {integrity: sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw==} + peerDependencies: + vue: ^3.5.27 + + '@vxe-ui/core@4.3.1': + resolution: {integrity: sha512-sr2WdFDWM3IKID02HbSaDxxRDvj1LZ5ZkOnH2POvGkkCfCWItkx3avkizfRUk8RtjNU+wXozaPbYTNha5kjSdg==} + peerDependencies: + vue: ^3.5.27 + + '@xmldom/xmldom@0.8.11': + resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} + engines: {node: '>=10.0.0'} + + '@xyflow/svelte@1.5.0': + resolution: {integrity: sha512-kHJVwMtabN7xthDJqLvx5wGT5qjOAVV90J9a26geDS51lrGsGb7CCxNRiZCMuVDlRkczGVIy9dkqdph6FL4slQ==} + peerDependencies: + svelte: ^5.25.0 + + '@xyflow/system@0.0.74': + resolution: {integrity: sha512-7v7B/PkiVrkdZzSbL+inGAo6tkR/WQHHG0/jhSvLQToCsfa8YubOGmBYd1s08tpKpihdHDZFwzQZeR69QSBb4Q==} + + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + + abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + abbrev@3.0.1: + resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==} + engines: {node: ^18.17.0 || >=20.5.0} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + aes-decrypter@3.1.3: + resolution: {integrity: sha512-VkG9g4BbhMBy+N5/XodDeV6F02chEk9IpgRTq/0bS80y4dzy79VH2Gtms02VXomf3HmyRe3yyJYkJ990ns+d6A==} + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + + ajv@8.13.0: + resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + algoliasearch@5.48.0: + resolution: {integrity: sha512-aD8EQC6KEman6/S79FtPdQmB7D4af/etcRL/KwiKFKgAE62iU8c5PeEQvpvIcBPurC3O/4Lj78nOl7ZcoazqSw==} + engines: {node: '>= 14.0.0'} + + alien-signals@0.4.14: + resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} + + alien-signals@3.1.2: + resolution: {integrity: sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} + engines: {node: '>=18'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + ansis@4.2.0: + resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} + engines: {node: '>=14'} + + ant-design-vue@4.2.6: + resolution: {integrity: sha512-t7eX13Yj3i9+i5g9lqFyYneoIb3OzTvQjq9Tts1i+eiOd3Eva/6GagxBSXM1fOCjqemIu0FYVE1ByZ/38epR3Q==} + engines: {node: '>=12.22.0'} + peerDependencies: + vue: ^3.5.27 + + antdv-next@1.0.2: + resolution: {integrity: sha512-JkPXDLk7MfAtye2pS3z/heLiUeow1K3JJCAnmaM+vzZhCds+wXUCNNHJ03qUIQvKCNbFdko4OJ9p0dY/pDJncg==} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + archiver-utils@5.0.2: + resolution: {integrity: sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==} + engines: {node: '>= 14'} + + archiver@7.0.1: + resolution: {integrity: sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==} + engines: {node: '>= 14'} + + are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-differ@3.0.0: + resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==} + engines: {node: '>=8'} + + array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + + array-move@4.0.0: + resolution: {integrity: sha512-+RY54S8OuVvg94THpneQvFRmqWdAHeqtMzgMW6JNurHxe8rsS07cHQdfGkXnTUXiBcyZ0j3SiDIxxj0RPiqCkQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} + + array-tree-filter@2.1.0: + resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + arrify@2.0.1: + resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + engines: {node: '>=8'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + async-sema@3.1.1: + resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} + + async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + + atomically@2.1.1: + resolution: {integrity: sha512-P4w9o2dqARji6P7MHprklbfiArZAWvo07yW7qs3pdljb3BWr12FIB7W+p0zJiuiVsUpRO0iZn1kFFcpPegg0tQ==} + + autolinker@3.16.2: + resolution: {integrity: sha512-JiYl7j2Z19F9NdTmirENSUUIIL/9MytEWtmzhfmsKPCp9E+G35Y0UNCMoM9tFigxT59qSc8Ml2dlZXOCVTYwuA==} + + autoprefixer@10.4.24: + resolution: {integrity: sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axios-mock-adapter@2.1.0: + resolution: {integrity: sha512-AZUe4OjECGCNNssH8SOdtneiQELsqTsat3SQQCWLPjN436/H+L9AjWfV7bF+Zg/YL9cgbhrz5671hoh+Tbn98w==} + peerDependencies: + axios: '>= 0.17.0' + + axios@1.13.5: + resolution: {integrity: sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + b4a@1.7.3: + resolution: {integrity: sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==} + peerDependencies: + react-native-b4a: '*' + peerDependenciesMeta: + react-native-b4a: + optional: true + + babel-plugin-polyfill-corejs2@0.4.15: + resolution: {integrity: sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.14.0: + resolution: {integrity: sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.6: + resolution: {integrity: sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@2.0.0: + resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} + + bare-events@2.8.2: + resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} + peerDependencies: + bare-abort-controller: '*' + peerDependenciesMeta: + bare-abort-controller: + optional: true + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.9.19: + resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} + hasBin: true + + benz-amr-recorder@1.1.5: + resolution: {integrity: sha512-NepctcNTsZHK8NxBb5uKO5p8S+xkbm+vD6GLSkCYdJeEsriexvgumLHpDkanX4QJBcLRMVtg16buWMs+gUPB3g==} + + benz-recorderjs@1.0.5: + resolution: {integrity: sha512-EwedOQo9KLti7HxDi/eZY51PSRbAXnOdEZmLvJ6ro3QQSoF9Y3AXBt57MIllGvVz5vtFYMeikG+GD7qTm3+p9w==} + + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + + bintrees@1.0.2: + resolution: {integrity: sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==} + + birpc@2.9.0: + resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + boxen@8.0.1: + resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} + engines: {node: '>=18'} + + bpmn-js-properties-panel@5.23.0: + resolution: {integrity: sha512-4B27LM8oV14A2QWRvazV17h4NxbkNERcqU+AGJmxKImMlLhu9893MWR+pCdTQCTphBdBkuD8ksWm+1wVCedJ7g==} + peerDependencies: + '@bpmn-io/properties-panel': '>= 3.7' + bpmn-js: '>= 11.5' + camunda-bpmn-js-behaviors: '>= 0.4' + diagram-js: '>= 11.9' + + bpmn-js-token-simulation@0.36.3: + resolution: {integrity: sha512-HyiExdi+vENiStn284gIUQkQliiWly4dk2kY9PJILwwuTIoKtvg1zw8LGr9ReNUiScibNbpkt45bR25Oqfq9wA==} + engines: {node: '>= 16'} + + bpmn-js@17.11.1: + resolution: {integrity: sha512-ywCeTg5kvN8lYkU+fHE+YXTGlfKc55lRBn7zW3k1//toeMNPy/PS/uQiujRWdFhMrH5dbtDvlwWukNw2pjWw8Q==} + + bpmn-moddle@8.1.0: + resolution: {integrity: sha512-yI5OAFfYVJwViKTsTsonVfCBPtB3MlefADUORwNIxxBOMp21vnoxuxsdgUWlPH/dvAEZh/+mr8UtqOBNu8NC5Q==} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer-crc32@1.0.0: + resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} + engines: {node: '>=8.0.0'} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + builtin-modules@5.0.0: + resolution: {integrity: sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==} + engines: {node: '>=18.20'} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + c12@3.3.3: + resolution: {integrity: sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q==} + peerDependencies: + magicast: '*' + peerDependenciesMeta: + magicast: + optional: true + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + cacache@20.0.3: + resolution: {integrity: sha512-3pUp4e8hv07k1QlijZu6Kn7c9+ZpWWk4j3F8N3xPuCExULobqJydKYOTj1FTq58srkJsXvO7LbGAH4C0ZU3WGw==} + engines: {node: ^20.17.0 || >=22.9.0} + + cacheable@2.3.2: + resolution: {integrity: sha512-w+ZuRNmex9c1TR9RcsxbfTKCjSL0rh1WA5SABbrWprIHeNBdmyQLSYonlDy9gpD+63XT8DgZ/wNh1Smvc9WnJA==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsite@1.0.0: + resolution: {integrity: sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + + camunda-bpmn-js-behaviors@1.14.0: + resolution: {integrity: sha512-Brbt6ZY+SklZjc77R4WKyBqmLXshcvAJVGIabvQUKqn6IDzClGRlTX/V2aaIC9OyMFuXJRQSd3zYrbZRQHk9vg==} + peerDependencies: + bpmn-js: '>= 9' + camunda-bpmn-moddle: '>= 7' + zeebe-bpmn-moddle: '>= 0.18' + + camunda-bpmn-moddle@7.0.1: + resolution: {integrity: sha512-Br8Diu6roMpziHdpl66Dhnm0DTnCFMrSD9zwLV08LpD52QA0UsXxU87XfHf08HjuB7ly0Hd1bvajZRpf9hbmYQ==} + + caniuse-api@3.0.0: + resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} + + caniuse-lite@1.0.30001769: + resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + + chalk-template@1.1.2: + resolution: {integrity: sha512-2bxTP2yUH7AJj/VAXfcA+4IcWGdQ87HwBANLt5XxGTeomo8yG0y95N1um9i5StvhT/Bl0/2cARA5v1PpPXUxUA==} + engines: {node: '>=14.16'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + change-case@5.4.4: + resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + chardet@2.1.1: + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + + cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + + cheerio@1.0.0-rc.12: + resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} + engines: {node: '>= 6'} + + cheerio@1.2.0: + resolution: {integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==} + engines: {node: '>=20.18.1'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + + circular-dependency-scanner@2.3.0: + resolution: {integrity: sha512-J1a6SeOL1pfaVdCVECg4h1cLxZipjnibha2uutY7gG7Ax8lre03sWdK1raJew0P+8AGv9/zRF5DCWHkceOYPBQ==} + hasBin: true + + citty@0.1.6: + resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + + citty@0.2.0: + resolution: {integrity: sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA==} + + class-variance-authority@0.7.1: + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + + classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + + clean-css@5.3.3: + resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} + engines: {node: '>= 10.0'} + + clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + + clear-module@4.1.2: + resolution: {integrity: sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==} + engines: {node: '>=8'} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + clipboard@2.0.11: + resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==} + + clipboardy@4.0.0: + resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} + engines: {node: '>=18'} + + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + + codemirror@5.65.21: + resolution: {integrity: sha512-6teYk0bA0nR3QP0ihGMoxuKzpl5W80FpnHpBJpgy66NK3cZv5b/d/HY8PnRvfSsCG1MTfr92u2WUl+wT0E40mQ==} + + codemirror@6.65.7: + resolution: {integrity: sha512-HcfnUFJwI2FvH73YWVbbMh7ObWxZiHIycEhv9ZEXy6e8ZKDjtZKbbYFUtsLN46HFXPvU5V2Uvc2d55Z//oFW5A==} + deprecated: This is an accidentally mis-tagged instance of 5.65.7 + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + engines: {node: '>=20'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + comment-json@4.5.1: + resolution: {integrity: sha512-taEtr3ozUmOB7it68Jll7s0Pwm+aoiHyXKrEC8SEodL4rNpdfDLqa7PfBlrgFoCNNdR8ImL+muti5IGvktJAAg==} + engines: {node: '>= 6'} + + comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} + + comment-parser@1.4.5: + resolution: {integrity: sha512-aRDkn3uyIlCFfk5NUA+VdwMmMsh8JGhc4hapfV4yxymHGQ3BVskMQfoXGpCo5IoBuQ9tS5iiVKhCpTcB4pW4qw==} + engines: {node: '>= 12.0.0'} + + commitlint-plugin-function-rules@4.3.1: + resolution: {integrity: sha512-wRvlVUWRgN9qTlfUelB1EqnhTfGLVUKz6xBSnjnBRIwHEn2Ma39WZHJEzmANOqDYa9kpS5hyr3iLD2OliwlDIw==} + engines: {node: '>=20'} + peerDependencies: + '@commitlint/lint': '>=19 <21' + + common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + + compatx@0.2.0: + resolution: {integrity: sha512-6gLRNt4ygsi5NyMVhceOCFv14CIdDFN7fQjX1U4+47qVE/+kjPoXMK65KWK+dWxmFzMTuKazoQ9sch6pM0p5oA==} + + component-event@0.2.1: + resolution: {integrity: sha512-wGA++isMqiDq1jPYeyv2as/Bt/u+3iLW0rEa+8NQ82jAv3TgqMiCM+B2SaBdn2DfLilLjjq736YcezihRYhfxw==} + + compress-commons@6.0.2: + resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==} + engines: {node: '>= 14'} + + compute-scroll-into-view@1.0.20: + resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + + compute-scroll-into-view@3.1.1: + resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + confbox@0.2.4: + resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + configstore@7.1.0: + resolution: {integrity: sha512-N4oog6YJWbR9kGyXvS7jEykLDXIE2C0ILYqNBZBp9iwiJpoCBWYsuAdW6PPFn6w06jjnC+3JstVvWHO4cZqvRg==} + engines: {node: '>=18'} + + connect-history-api-fallback@1.6.0: + resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} + engines: {node: '>=0.8'} + + consola@2.15.3: + resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + + conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} + + conventional-changelog-conventionalcommits@7.0.2: + resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} + engines: {node: '>=16'} + + conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} + hasBin: true + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-es@1.2.2: + resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} + + cookie-es@2.0.0: + resolution: {integrity: sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg==} + + copy-anything@2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + + copy-anything@4.0.5: + resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==} + engines: {node: '>=18'} + + core-js-compat@3.48.0: + resolution: {integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==} + + core-js-pure@3.48.0: + resolution: {integrity: sha512-1slJgk89tWC51HQ1AEqG+s2VuwpTRr8ocu4n20QUcH1v9lAN0RXen0Q0AABa/DK1I7RrNWLucplOHMx8hfTGTw==} + + core-js@3.48.0: + resolution: {integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cosmiconfig-typescript-loader@6.2.0: + resolution: {integrity: sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==} + engines: {node: '>=v18'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=9' + typescript: '>=5' + + cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + crc32-stream@6.0.0: + resolution: {integrity: sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==} + engines: {node: '>= 14'} + + crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + + croner@9.1.0: + resolution: {integrity: sha512-p9nwwR4qyT5W996vBZhdvBCnMhicY5ytZkR4D1Xj0wuTDEiMnjwR57Q3RXYY/s0EpX6Ay3vgIcfaR+ewGHsi+g==} + engines: {node: '>=18.0'} + + cropperjs@1.6.2: + resolution: {integrity: sha512-nhymn9GdnV3CqiEHJVai54TULFAE3VshJTXSqSJKa8yXAKyBKDWdhHarnlIPrshJ0WMFTGuFvG02YjLXfPiuOA==} + + cross-env@10.1.0: + resolution: {integrity: sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==} + engines: {node: '>=20'} + hasBin: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crossws@0.3.5: + resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} + + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + + crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + + cspell-config-lib@9.6.4: + resolution: {integrity: sha512-MecJNR9bIlcPBhyZFsXP6Q2n8qQ2IR9N9HiIz0yh0gBNVydp3LR5JITP5Ji8m7hexmZzVeoXms/dVN74XbS95g==} + engines: {node: '>=20'} + + cspell-dictionary@9.6.4: + resolution: {integrity: sha512-Ik9ZQVqV/fJfMt5X6IkC7yHGVH46/qjcqCNWwrMSwvROLM3SemNxxZoLvh0wi0GXz9WF1lHcxLJVdeKUk6QB8g==} + engines: {node: '>=20'} + + cspell-gitignore@9.6.4: + resolution: {integrity: sha512-a8asE9BsjJgJ506WUGh5VHrTdVEE8hWELjCJB2atPrW6iY5e4aCIugy0gkRC1ZH9/TseadlmMLrFzHUkJUjzsg==} + engines: {node: '>=20'} + hasBin: true + + cspell-glob@9.6.4: + resolution: {integrity: sha512-253VrjbR8QU15h8GtpDQLX5Ti9uNSuNod2T7f8YEElQOb9I/kUXoCj3Cq4P390IC99klqSHIDxHsxd77ex19lA==} + engines: {node: '>=20'} + + cspell-grammar@9.6.4: + resolution: {integrity: sha512-rvZyTB45/XSRWx7eAsrvTTAZvBTREr/2G2JWVMdqrptFyq1XReAKHhw/x1HJkNgWC9LKAK3bVQJpjLsNG37U9A==} + engines: {node: '>=20'} + hasBin: true + + cspell-io@9.6.4: + resolution: {integrity: sha512-bmvJ4yn5QK2FZWTkZA4sx2qJqIi8BrUUUV7W209drSwkYjhJtXqP0RyF6Qx4Xuu2D1s0UilEtO5Jd+E9UJkQ6w==} + engines: {node: '>=20'} + + cspell-lib@9.6.4: + resolution: {integrity: sha512-fUodKcIHTwvokuowB25XyFzBxlk73yj1QRw2por3BxDz9fAim1zAIohAPAnGuzj3LowYnTMjHLYE7RFDUSxy5A==} + engines: {node: '>=20'} + + cspell-trie-lib@9.6.4: + resolution: {integrity: sha512-JKwyRtyybbaTrixwI1OgU5Hvva2Z5zHVWl92WBa9U7KijAyiD/Ehp3T3DCYuBwGks7egw7MgWPySkXXnpme6mw==} + engines: {node: '>=20'} + peerDependencies: + '@cspell/cspell-types': 9.6.4 + + cspell@9.6.4: + resolution: {integrity: sha512-rZJmgcyBGKX3KcJ3KC9JYVHeKhDEVbmCheSp8eRGMYw6MCG9o7FHqQjGA/u4lEu4A0psr7ACP/5ym/QHyntRbA==} + engines: {node: '>=20.18'} + hasBin: true + + css-blank-pseudo@7.0.1: + resolution: {integrity: sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + css-declaration-sorter@7.3.1: + resolution: {integrity: sha512-gz6x+KkgNCjxq3Var03pRYLhyNfwhkKF1g/yoLgDNtFvVu0/fOLV9C8fFEZRjACp/XQLumjAYo7JVjzH3wLbxA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.0.9 + + css-functions-list@3.3.3: + resolution: {integrity: sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==} + engines: {node: '>=12'} + + css-has-pseudo@7.0.3: + resolution: {integrity: sha512-oG+vKuGyqe/xvEMoxAQrhi7uY16deJR3i7wwhBerVrGQKSqUC5GiOVxTpM9F9B9hw0J+eKeOWLH7E9gZ1Dr5rA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + css-prefers-color-scheme@10.0.0: + resolution: {integrity: sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + css-render@0.15.14: + resolution: {integrity: sha512-9nF4PdUle+5ta4W5SyZdLCCmFd37uVimSjg1evcTqKJCyvCEEj12WKzOSBNak6r4im4J4iYXKH1OWpUV5LBYFg==} + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + css-tree@3.1.0: + resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + cssdb@8.7.1: + resolution: {integrity: sha512-+F6LKx48RrdGOtE4DT5jz7Uo+VeyKXpK797FAevIkzjV8bMHz6xTO5F7gNDcRCHmPgD5jj2g6QCsY9zmVrh38A==} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + cssnano-preset-default@7.0.10: + resolution: {integrity: sha512-6ZBjW0Lf1K1Z+0OKUAUpEN62tSXmYChXWi2NAA0afxEVsj9a+MbcB1l5qel6BHJHmULai2fCGRthCeKSFbScpA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + cssnano-utils@5.0.1: + resolution: {integrity: sha512-ZIP71eQgG9JwjVZsTPSqhc6GHgEr53uJ7tK5///VfyWj6Xp2DBmixWHqJgPno+PqATzn48pL42ww9x5SSGmhZg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + cssnano@7.1.2: + resolution: {integrity: sha512-HYOPBsNvoiFeR1eghKD5C3ASm64v9YVyJB4Ivnl2gqKoQYvjjN/G0rztvKQq8OxocUtC6sjqY8jwYngIB4AByA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + csstype@3.0.11: + resolution: {integrity: sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + cz-git@1.12.0: + resolution: {integrity: sha512-LaZ+8whPPUOo6Y0Zy4nIbf6JOleV3ejp41sT6N4RPKiKKA+ICWf4ueeIlxIO8b6JtdlDxRzHH/EcRji07nDxcg==} + engines: {node: '>=v12.20.0'} + + czg@1.12.0: + resolution: {integrity: sha512-LGltcoZ5m7vhe3WNw16QXqd5WurnHegx9V15MwZJtFAU2AVCYLCqDbwxPUgZOnAcdzzooq33ONcU148HOQsjdA==} + engines: {node: '>=v12.20.0'} + hasBin: true + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + + d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + + d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + + d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + + d3-flextree@2.1.2: + resolution: {integrity: sha512-gJiHrx5uTTHq44bjyIb3xpbmmdZcWLYPKeO9EPVOq8EylMFOiH2+9sWqKAiQ4DcFuOZTAxPOQyv0Rnmji/g15A==} + + d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + + d3-format@3.1.2: + resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==} + engines: {node: '>=12'} + + d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} + + d3-hierarchy@1.1.9: + resolution: {integrity: sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==} + + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + + d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + + d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + + d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + + dargs@8.1.0: + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + engines: {node: '>=12'} + + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + dataloader@1.4.0: + resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} + + date-fns-tz@3.2.0: + resolution: {integrity: sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==} + peerDependencies: + date-fns: ^3.0.0 || ^4.0.0 + + date-fns@4.1.0: + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + + dayjs@1.11.19: + resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + + db0@0.3.4: + resolution: {integrity: sha512-RiXXi4WaNzPTHEOu8UPQKMooIbqOEyqA1t7Z6MsdxSCeb8iUC9ko3LcmsLmeUt2SM5bctfArZKkRQggKZz7JNw==} + peerDependencies: + '@electric-sql/pglite': '*' + '@libsql/client': '*' + better-sqlite3: '*' + drizzle-orm: '*' + mysql2: '*' + sqlite3: '*' + peerDependenciesMeta: + '@electric-sql/pglite': + optional: true + '@libsql/client': + optional: true + better-sqlite3: + optional: true + drizzle-orm: + optional: true + mysql2: + optional: true + sqlite3: + optional: true + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} + + default-passive-events@2.0.0: + resolution: {integrity: sha512-eMtt76GpDVngZQ3ocgvRcNCklUMwID1PaNbCNxfpDXuiOXttSh0HzBbda1HU9SIUsDc02vb7g9+3I5tlqe/qMQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + delaunator@5.0.1: + resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + delegate@3.2.0: + resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==} + + denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + + depcheck@1.4.7: + resolution: {integrity: sha512-1lklS/bV5chOxwNKA/2XUUk/hPORp8zihZsXflr8x0kLwmcZ9Y9BsS6Hs3ssvA+2wUVbG0U2Ciqvm1SokNjPkA==} + engines: {node: '>=10'} + hasBin: true + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + deps-regex@0.2.0: + resolution: {integrity: sha512-PwuBojGMQAYbWkMXOY9Pd/NWCDNHVH12pnS7WHqZkTSeMESe4hwnKKRp0yR87g37113x4JPbo/oIvXY+s/f56Q==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + + detect-file@1.0.0: + resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} + engines: {node: '>=0.10.0'} + + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + devalue@5.6.2: + resolution: {integrity: sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diagram-js-direct-editing@3.3.0: + resolution: {integrity: sha512-EjXYb35J3qBU8lLz5U81hn7wNykVmF7U5DXZ7BvPok2IX7rmPz+ZyaI5AEMiqaC6lpSnHqPxFcPgKEiJcAiv5w==} + peerDependencies: + diagram-js: '*' + + diagram-js@12.8.1: + resolution: {integrity: sha512-LF9BiwjbOPpZd0ez5VSlYRbdbEA59YQX43bWvNDp1rLMv0xwZ5yIg4oaYDK82nIQ0kH1tjvoQRpNevMTCgQVyw==} + + diagram-js@14.11.3: + resolution: {integrity: sha512-Seq9BHAXfzKS60L4v4Gvgvv72wOtvrfJQAyyPm9pntSZDMzjoodPSXnEUPud1G2zVCMGEUUW++s0reEdaWgkXA==} + + didi@10.2.2: + resolution: {integrity: sha512-l8NYkYFXV1izHI65EyT8EXOjUZtKmQkHLTT89cSP7HU5J/G7AOj0dXKtLc04EXYlga99PBY18IPjOeZ+c3DI4w==} + engines: {node: '>= 16'} + + didi@9.0.2: + resolution: {integrity: sha512-q2+aj+lnJcUweV7A9pdUrwFr4LHVmRPwTmQLtHPFz4aT7IBoryN6Iy+jmFku+oIzr5ebBkvtBCOb87+dJhb7bg==} + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + diff-sequences@27.5.1: + resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + diff@8.0.3: + resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} + engines: {node: '>=0.3.1'} + + dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + dom-align@1.12.4: + resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==} + + dom-scroll-into-view@2.0.1: + resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + dom-walk@0.1.2: + resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} + + dom-zindex@1.0.6: + resolution: {integrity: sha512-FKWIhiU96bi3xpP9ewRMgANsoVmMUBnMnmpCT6dPMZOunVYJQmJhSRruoI0XSPoHeIif3kyEuiHbFrOJwEJaEA==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domify@1.4.2: + resolution: {integrity: sha512-m4yreHcUWHBncGVV7U+yQzc12vIlq0jMrtHZ5mW6dQMiL/7skSYNVX9wqKwOtyO9SGCgevrAFEgOCAHmamHTUA==} + + domify@2.0.0: + resolution: {integrity: sha512-rmvrrmWQPD/X1A/nPBfIVg4r05792QdG9Z4Prk6oQG0F9zBMDkr0GKAdds1wjb2dq1rTz/ywc4ZxpZbgz0tttg==} + engines: {node: '>=18'} + + dompurify@3.3.1: + resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + + dot-prop@10.1.0: + resolution: {integrity: sha512-MVUtAugQMOff5RnBy2d9N31iG0lNwg1qAoAOn7pOK5wf94WIaE3My2p3uwTQuvS2AcqchkcR3bHByjaM0mmi7Q==} + engines: {node: '>=20'} + + dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + + dot-prop@9.0.0: + resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==} + engines: {node: '>=18'} + + dotenv-expand@8.0.3: + resolution: {integrity: sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==} + engines: {node: '>=12'} + + dotenv@16.0.3: + resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} + engines: {node: '>=12'} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + + dotenv@17.2.4: + resolution: {integrity: sha512-mudtfb4zRB4bVvdj0xRo+e6duH1csJRM8IukBqfTRvHotn9+LBXB8ynAidP9zHqoRC/fsllXgk4kCKlR21fIhw==} + engines: {node: '>=12'} + + dotenv@8.6.0: + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + echarts@6.0.0: + resolution: {integrity: sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==} + + editorconfig@1.0.4: + resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==} + engines: {node: '>=14'} + hasBin: true + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.286: + resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==} + + element-plus@2.13.2: + resolution: {integrity: sha512-Zjzm1NnFXGhV4LYZ6Ze9skPlYi2B4KAmN18FL63A3PZcjhDfroHwhtM6RE8BonlOPHXUnPQynH0BgaoEfvhrGw==} + peerDependencies: + vue: ^3.5.27 + + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + empathic@2.0.0: + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + encoding-sniffer@0.2.1: + resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} + + enhanced-resolve@5.19.0: + resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==} + engines: {node: '>=10.13.0'} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + env-paths@4.0.0: + resolution: {integrity: sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==} + engines: {node: '>=20'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + errno@0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + error-stack-parser-es@1.0.5: + resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==} + + errx@0.1.0: + resolution: {integrity: sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==} + + es-abstract@1.24.1: + resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-module-lexer@2.0.0: + resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + es-toolkit@1.43.0: + resolution: {integrity: sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA==} + + es-toolkit@1.44.0: + resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==} + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-goat@4.0.0: + resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} + engines: {node: '>=12'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-compat-utils@0.6.5: + resolution: {integrity: sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-config-turbo@2.8.5: + resolution: {integrity: sha512-H4A/Upj+s7lD/HQlwZyryjss149U5XYKmheXHFtorMyEFzuVbZD1JN4o7ZPoBFX7khgGT1vDHla6YIKLN6JHJA==} + peerDependencies: + eslint: '>6.6.0' + turbo: '>2.0.0' + + eslint-import-context@0.1.9: + resolution: {integrity: sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + + eslint-json-compat-utils@0.2.1: + resolution: {integrity: sha512-YzEodbDyW8DX8bImKhAcCeu/L31Dd/70Bidx2Qex9OFUtgzXLqtfWL4Hr5fM/aCCB8QUZLuJur0S9k6UfgFkfg==} + engines: {node: '>=12'} + peerDependencies: + '@eslint/json': '*' + eslint: '*' + jsonc-eslint-parser: ^2.4.0 + peerDependenciesMeta: + '@eslint/json': + optional: true + + eslint-plugin-command@3.4.0: + resolution: {integrity: sha512-EW4eg/a7TKEhG0s5IEti72kh3YOTlnhfFNuctq5WnB1fst37/IHTd5OkD+vnlRf3opTvUcSRihAateP6bT5ZcA==} + peerDependencies: + eslint: '*' + + eslint-plugin-es-x@7.8.0: + resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + + eslint-plugin-eslint-comments@3.2.0: + resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} + engines: {node: '>=6.5.0'} + peerDependencies: + eslint: '>=4.19.1' + + eslint-plugin-import-x@4.16.1: + resolution: {integrity: sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/utils': ^8.0.0 + eslint: ^8.57.0 || ^9.0.0 + eslint-import-resolver-node: '*' + peerDependenciesMeta: + '@typescript-eslint/utils': + optional: true + eslint-import-resolver-node: + optional: true + + eslint-plugin-jsdoc@61.7.1: + resolution: {integrity: sha512-36DpldF95MlTX//n3/naULFVt8d1cV4jmSkx7ZKrE9ikkKHAgMLesuWp1SmwpVwAs5ndIM6abKd6PeOYZUgdWg==} + engines: {node: '>=20.11.0'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + + eslint-plugin-jsonc@2.21.1: + resolution: {integrity: sha512-dbNR5iEnQeORwsK2WZzr3QaMtFCY3kKJVMRHPzUpKzMhmVy2zIpVgFDpX8MNoIdoqz6KCpCfOJavhfiSbZbN+w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + + eslint-plugin-n@17.23.2: + resolution: {integrity: sha512-RhWBeb7YVPmNa2eggvJooiuehdL76/bbfj/OJewyoGT80qn5PXdz8zMOTO6YHOsI7byPt7+Ighh/i/4a5/v7hw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: '>=8.23.0' + + eslint-plugin-no-only-tests@3.3.0: + resolution: {integrity: sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==} + engines: {node: '>=5.0.0'} + + eslint-plugin-perfectionist@4.15.1: + resolution: {integrity: sha512-MHF0cBoOG0XyBf7G0EAFCuJJu4I18wy0zAoT1OHfx2o6EOx1EFTIzr2HGeuZa1kDcusoX0xJ9V7oZmaeFd773Q==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + eslint: '>=8.45.0' + + eslint-plugin-pnpm@1.5.0: + resolution: {integrity: sha512-ayMo1GvrQ/sF/bz1aOAiH0jv9eAqU2Z+a1ycoWz/uFFK5NxQDq49BDKQtBumcOUBf2VHyiTW4a8u+6KVqoIWzQ==} + peerDependencies: + eslint: ^9.0.0 + + eslint-plugin-prettier@5.5.5: + resolution: {integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + + eslint-plugin-regexp@2.10.0: + resolution: {integrity: sha512-ovzQT8ESVn5oOe5a7gIDPD5v9bCSjIFJu57sVPDqgPRXicQzOnYfFN21WoQBQF18vrhT5o7UMKFwJQVVjyJ0ng==} + engines: {node: ^18 || >=20} + peerDependencies: + eslint: '>=8.44.0' + + eslint-plugin-turbo@2.8.5: + resolution: {integrity: sha512-6PaUEaIuh6absmV0v69dSvh//p1rcNiOtK1KXqYXqp8DUP57Jif6uQF0qxziV5XnyNu+A9Viytq8mAyj64kryg==} + peerDependencies: + eslint: '>6.6.0' + turbo: '>2.0.0' + + eslint-plugin-unicorn@62.0.0: + resolution: {integrity: sha512-HIlIkGLkvf29YEiS/ImuDZQbP12gWyx5i3C6XrRxMvVdqMroCI9qoVYCoIl17ChN+U89pn9sVwLxhIWj5nEc7g==} + engines: {node: ^20.10.0 || >=21.0.0} + peerDependencies: + eslint: '>=9.38.0' + + eslint-plugin-unused-imports@4.4.1: + resolution: {integrity: sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 + eslint: ^10.0.0 || ^9.0.0 || ^8.0.0 + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + + eslint-plugin-vitest@0.5.4: + resolution: {integrity: sha512-um+odCkccAHU53WdKAw39MY61+1x990uXjSPguUCq3VcEHdqJrOb8OTMrbYlY6f9jAKx7x98kLVlIe3RJeJqoQ==} + engines: {node: ^18.0.0 || >= 20.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': '*' + eslint: ^8.57.0 || ^9.0.0 + vitest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + vitest: + optional: true + + eslint-plugin-vue@10.7.0: + resolution: {integrity: sha512-r2XFCK4qlo1sxEoAMIoTTX0PZAdla0JJDt1fmYiworZUX67WeEGqm+JbyAg3M+pGiJ5U6Mp5WQbontXWtIW7TA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@stylistic/eslint-plugin': ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + '@typescript-eslint/parser': ^7.0.0 || ^8.0.0 + eslint: ^8.57.0 || ^9.0.0 + vue-eslint-parser: ^10.0.0 + peerDependenciesMeta: + '@stylistic/eslint-plugin': + optional: true + '@typescript-eslint/parser': + optional: true + + eslint-plugin-yml@1.19.1: + resolution: {integrity: sha512-bYkOxyEiXh9WxUhVYPELdSHxGG5pOjCSeJOVkfdIyj6tuiHDxrES2WAW1dBxn3iaZQey57XflwLtCYRcNPOiOg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@5.0.0: + resolution: {integrity: sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@9.39.2: + resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: ^2.6.1 + peerDependenciesMeta: + jiti: + optional: true + + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + espree@11.1.0: + resolution: {integrity: sha512-WFWYhO1fV4iYkqOOvq8FbqIhr2pYfoDY0kCotMkDeNtGpiGGkZ1iov2u8ydjtgM8yF8rzK7oaTbw2NAzbAbehw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrap@2.2.3: + resolution: {integrity: sha512-8fOS+GIGCQZl/ZIlhl59htOlms6U8NvX6ZYgYHpRU/b6tVSh3uHkOHZikl3D4cMbYM0JlpBe+p/BkZEi8J9XIQ==} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@1.0.1: + resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + events-universal@1.0.1: + resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + evtd@0.2.4: + resolution: {integrity: sha512-qaeGN5bx63s/AXgQo8gj6fBkxge+OoLddLniox5qtLAEY5HSnuSlISXVPxnSae1dWblvTh4/HoMIB+mbMsvZzw==} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + execa@9.6.1: + resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} + engines: {node: ^18.19.0 || >=20.5.0} + + expand-tilde@2.0.2: + resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} + engines: {node: '>=0.10.0'} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + + exsolve@1.0.8: + resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} + + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-equals@6.0.0: + resolution: {integrity: sha512-PFhhIGgdM79r5Uztdj9Zb6Tt1zKafqVfdMGwVca1z5z6fbX7DmsySSuJd8HiP6I1j505DCS83cLxo5rmSNeVEA==} + engines: {node: '>=6.0.0'} + + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-string-compare@3.0.0: + resolution: {integrity: sha512-PY66/8HelapGo5nqMN17ZTKqJj1nppuS1OoC9Y0aI2jsUDlZDEYhMODTpb68wVCq+xMbaEbPGXRd7qutHzkRXA==} + engines: {node: ^14.13.1 || >=16.0.0} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + + fast-xml-parser@4.5.3: + resolution: {integrity: sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==} + hasBin: true + + fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + feelers@1.5.1: + resolution: {integrity: sha512-LKIAqtScSfy55Tw62DhBcxIT3k2XnppzWrkmGfsbdad0a+TxMfaLF1CSYhoVRF5FvPAUXvor1Ux/75wtBaDYpA==} + + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-entry-cache@11.1.2: + resolution: {integrity: sha512-N2WFfK12gmrK1c1GXOqiAJ1tc5YE+R53zvQ+t5P8S5XhnmKYVB5eZEiLNZKDSmoG8wqqbF9EXYBBW/nef19log==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up-simple@1.0.1: + resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} + engines: {node: '>=18'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + + findup-sync@5.0.0: + resolution: {integrity: sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==} + engines: {node: '>= 10.13.0'} + + fix-dts-default-cjs-exports@1.0.1: + resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flat-cache@6.1.20: + resolution: {integrity: sha512-AhHYqwvN62NVLp4lObVXGVluiABTHapoB57EyegZVmazN+hhGhLTn3uZbOofoTw4DSDvVCadzzyChXhOAvy8uQ==} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + focus-trap@7.8.0: + resolution: {integrity: sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + formdata-node@6.0.3: + resolution: {integrity: sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg==} + engines: {node: '>= 18'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} + + framesync@6.1.2: + resolution: {integrity: sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==} + + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.3.3: + resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==} + engines: {node: '>=14.14'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fs-minipass@3.0.3: + resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + gensequence@8.0.8: + resolution: {integrity: sha512-omMVniXEXpdx/vKxGnPRoO2394Otlze28TyxECbFVyoSpZ9H3EO7lemjcB12OpQJzRW4e5tt/dL1rOxry6aMHg==} + engines: {node: '>=20'} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.4.0: + resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-own-enumerable-property-symbols@3.0.2: + resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} + + get-port-please@3.2.0: + resolution: {integrity: sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==} + + get-port@7.1.0: + resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} + engines: {node: '>=16'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.13.6: + resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} + + giget@2.0.0: + resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} + hasBin: true + + git-raw-commits@4.0.0: + resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} + engines: {node: '>=16'} + hasBin: true + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} + hasBin: true + + glob@13.0.2: + resolution: {integrity: sha512-035InabNu/c1lW0tzPhAgapKctblppqsKKG9ZaNzbr+gXwWMjXoiyGSyB9sArzrjG7jY+zntRq5ZSUYemrnWVQ==} + engines: {node: 20 || >=22} + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + global-modules@1.0.0: + resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} + engines: {node: '>=0.10.0'} + + global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + + global-prefix@1.0.2: + resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} + engines: {node: '>=0.10.0'} + + global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + + global@4.4.0: + resolution: {integrity: sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} + + globals@16.5.0: + resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + globby@14.1.0: + resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} + engines: {node: '>=18'} + + globby@16.1.0: + resolution: {integrity: sha512-+A4Hq7m7Ze592k9gZRy4gJ27DrXRNnC1vPjxTt1qQxEY8RxagBkBxivkCwg7FxSTG0iLLEMaUx13oOr0R2/qcQ==} + engines: {node: '>=20'} + + globjoin@0.1.4: + resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} + + globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + + good-listener@1.2.2: + resolution: {integrity: sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graph-cycles@3.0.0: + resolution: {integrity: sha512-9qxd8BQK0tZJ3cRUW0Yn2q6P/9h+bgz/4UYuscpdxPz6851NNBA1IwoYDRHDpKzCqmr1UHlGHcp5+0WzpY9F7A==} + engines: {node: ^14.13.1 || >=16.0.0} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + gray-matter@4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + + gzip-size@7.0.0: + resolution: {integrity: sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + h3@1.15.5: + resolution: {integrity: sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==} + + hammerjs@2.0.8: + resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==} + engines: {node: '>=0.8.0'} + + happy-dom@17.6.3: + resolution: {integrity: sha512-UVIHeVhxmxedbWPCfgS55Jg2rDfwf2BCKeylcPSqazLz5w3Kri7Q4xdBJubsr/+VUzFLh0VjIvh13RaDA2/Xug==} + engines: {node: '>=20.0.0'} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hashery@1.4.0: + resolution: {integrity: sha512-Wn2i1In6XFxl8Az55kkgnFRiAlIAushzh26PTjL2AKtQcEfXrcLa7Hn5QOWGZEf3LU057P9TwwZjFyxfS1VuvQ==} + engines: {node: '>=20'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + hey-listen@1.0.8: + resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==} + + highlight.js@11.11.1: + resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} + engines: {node: '>=12.0.0'} + + homedir-polyfill@1.0.3: + resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} + engines: {node: '>=0.10.0'} + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + hookified@1.15.1: + resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==} + + htm@3.1.1: + resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==} + + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + + html-minifier-terser@6.1.0: + resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} + engines: {node: '>=12'} + hasBin: true + + html-minifier-terser@7.2.0: + resolution: {integrity: sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==} + engines: {node: ^14.13.1 || >=16.0.0} + hasBin: true + + html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + htmlparser2@10.1.0: + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} + + htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + http-shutdown@1.2.2: + resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + httpxy@0.1.7: + resolution: {integrity: sha512-pXNx8gnANKAndgga5ahefxc++tJvNL87CXoRwxn1cJE2ZkWEojF3tNfQIEhZX/vfpt+wzeAzpUI4qkediX1MLQ==} + + human-id@4.1.3: + resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} + hasBin: true + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + human-signals@8.0.1: + resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} + engines: {node: '>=18.18.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + + idb@7.1.1: + resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} + + ids@1.0.5: + resolution: {integrity: sha512-XQ0yom/4KWTL29sLG+tyuycy7UmeaM/79GRtSJq6IG9cJGIPeBz5kwDCguie3TwxaMNIc3WtPi0cTa1XYHicpw==} + + ids@3.0.1: + resolution: {integrity: sha512-mr0zAgpgA/hzCrHB0DnoTG6xZjNC3ABs4eaksXrpVtfaDatA2SVdDb1ZPLjmKjqzp4kexQRuHXwDWQILVK8FZQ==} + engines: {node: '>= 20.12'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + + immutable@5.1.4: + resolution: {integrity: sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + + individual@2.0.0: + resolution: {integrity: sha512-pWt8hBCqJsUWI/HtcfWod7+N9SgAqyPEaF7JQjwzjn5vGrpg6aQ5qeAFQ7dx//UH4J1O+7xqew+gCeeFt6xN/g==} + + inherits-browser@0.1.0: + resolution: {integrity: sha512-CJHHvW3jQ6q7lzsXPpapLdMx5hDpSF3FSh45pwsj6bKxJJ8Nl8v43i5yXnr3BdfOimGHKyniewQtnAIp3vyJJw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + + ioredis@5.9.2: + resolution: {integrity: sha512-tAAg/72/VxOUW7RQSX1pIxJVucYKcjFjfvj60L57jrZpYCHC3XN0WCQ3sNYL4Gmvv+7GPvTAjc+KSdeNuE8oWQ==} + engines: {node: '>=12.22.0'} + + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + + is-builtin-module@5.0.0: + resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==} + engines: {node: '>=18.20'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-ci@4.1.0: + resolution: {integrity: sha512-Ab9bQDQ11lWootZUI5qxgN2ZXwxNI5hTwnsvOc1wyxQ7zQ8OkEDw79mI0+9jI3x432NfwbVRru+3noJfXF6lSQ==} + hasBin: true + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} + engines: {node: '>=18'} + + is-function@1.0.2: + resolution: {integrity: sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-in-ci@1.0.0: + resolution: {integrity: sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==} + engines: {node: '>=18'} + hasBin: true + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-installed-globally@1.0.0: + resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==} + engines: {node: '>=18'} + + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-npm@6.1.0: + resolution: {integrity: sha512-O2z4/kNgyjhQwVR1Wpkbfc19JIhggF97NZNCpWTnjH7kVcZMUrnut9XSN7txI7VdyIYk5ZatOq3zvSuWpU8hoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@1.0.1: + resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} + engines: {node: '>=0.10.0'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-path-inside@4.0.0: + resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} + engines: {node: '>=12'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-plain-object@3.0.1: + resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==} + engines: {node: '>=0.10.0'} + + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + + is-reference@3.0.3: + resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-regexp@1.0.0: + resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} + engines: {node: '>=0.10.0'} + + is-safe-filename@0.1.1: + resolution: {integrity: sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==} + engines: {node: '>=20'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + is-what@3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + + is-what@5.5.0: + resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} + engines: {node: '>=18'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + is64bit@2.0.0: + resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==} + engines: {node: '>=18'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jackspeak@4.2.3: + resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} + engines: {node: 20 || >=22} + + jake@10.9.4: + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} + hasBin: true + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + js-beautify@1.15.4: + resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==} + engines: {node: '>=14'} + hasBin: true + + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsdoc-type-pratt-parser@4.8.0: + resolution: {integrity: sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==} + engines: {node: '>=12.0.0'} + + jsdoc-type-pratt-parser@7.0.0: + resolution: {integrity: sha512-c7YbokssPOSHmqTbSAmTtnVgAVa/7lumWNYqomgd5KOMyPrRve2anx6lonfOsXEQacqF9FKVUj7bLg4vRSvdYA==} + engines: {node: '>=20.0.0'} + + jsencrypt@3.5.4: + resolution: {integrity: sha512-kNjfYEMNASxrDGsmcSQh/rUTmcoRfSUkxnAz+MMywM8jtGu+fFEZ3nJjHM58zscVnwR0fYmG9sGkTDjqUdpiwA==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-eslint-parser@2.4.2: + resolution: {integrity: sha512-1e4qoRgnn448pRuMvKGsFFymUCquZV0mpGgOyIKNgD3JVDTsVJyRBGH/Fm0tBb8WsWGgmB1mDe6/yJMQM37DUA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.2.0: + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + + katex@0.16.28: + resolution: {integrity: sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg==} + hasBin: true + + keycode@2.2.1: + resolution: {integrity: sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + keyv@5.6.0: + resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + klona@2.0.6: + resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} + engines: {node: '>= 8'} + + knitwork@1.3.0: + resolution: {integrity: sha512-4LqMNoONzR43B1W0ek0fhXMsDNW/zxa1NdFAVMY+k28pgZLovR4G3PB5MrpTxCy1QaZCqNoiaKPr5w5qZHfSNw==} + + known-css-properties@0.37.0: + resolution: {integrity: sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==} + + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + + ky@1.14.3: + resolution: {integrity: sha512-9zy9lkjac+TR1c2tG+mkNSVlyOpInnWdSMiue4F+kq8TwJSgv6o8jhLRg8Ho6SnZ9wOYUq/yozts9qQCfk7bIw==} + engines: {node: '>=18'} + + latest-version@9.0.0: + resolution: {integrity: sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==} + engines: {node: '>=18'} + + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + + lefthook-darwin-arm64@2.1.0: + resolution: {integrity: sha512-u2hjHLQXWSFfzO7ln2n/uEydSzfC9sc5cDC7tvKSuOdhvBwaJ0AQ7ZeuqqCQ4YfVIJfYOom1SVE9CBd10FVyig==} + cpu: [arm64] + os: [darwin] + + lefthook-darwin-x64@2.1.0: + resolution: {integrity: sha512-zz5rcyrtOZpxon7uE+c0KC/o2ypJeLZql5CL0Y9oaTuECbmhfokm8glsGnyWstW/++PuMpZYYr/qsCJA5elxkQ==} + cpu: [x64] + os: [darwin] + + lefthook-freebsd-arm64@2.1.0: + resolution: {integrity: sha512-+mXNCNuFHNGYLrDqYWDeHH7kWCLCJFPpspx5PAAm+PD37PRMZJrTqDbaNK9qCghC1tdmT4/Lvilf/ewXHPlaKw==} + cpu: [arm64] + os: [freebsd] + + lefthook-freebsd-x64@2.1.0: + resolution: {integrity: sha512-+AU2HD7szuDsUdHue/E3OnF84B2ae/h7CGKpuIUHJntgoJ4kxf89oDvq2/xl8kDCn9cT76UUjgeZUgFYLRj+6Q==} + cpu: [x64] + os: [freebsd] + + lefthook-linux-arm64@2.1.0: + resolution: {integrity: sha512-KM70eV1tsEib1/tk+3TFxIdH84EaYlIg5KTQWAg+LB1N23nTQ7lL4Dnh1je6f6KW4tf21nmoMUqsh0xvMkQk8Q==} + cpu: [arm64] + os: [linux] + + lefthook-linux-x64@2.1.0: + resolution: {integrity: sha512-6Bxmv+l7LiYq9W0IE6v2lmlRtBp6pisnlzhcouMGvH3rDwEGw11NAyRJZA3IPGEMAkIuhnlnVTUwAUzKomfJLg==} + cpu: [x64] + os: [linux] + + lefthook-openbsd-arm64@2.1.0: + resolution: {integrity: sha512-ppJNK0bBSPLC8gqksRw5zI/0uLeMA5cK+hmZ4ofcuGNmdrN1dfl2Tx84fdeef0NcQY0ii9Y3j3icIKngIoid/g==} + cpu: [arm64] + os: [openbsd] + + lefthook-openbsd-x64@2.1.0: + resolution: {integrity: sha512-8k9lQsMYqQGu4spaQ8RNSOJidxIcOyfaoF2FPZhthtBfRV3cgVFGrsQ0hbIi5pvQRGUlCqYuCN79qauXHmnL3Q==} + cpu: [x64] + os: [openbsd] + + lefthook-windows-arm64@2.1.0: + resolution: {integrity: sha512-0WN+grrxt9zP9NGRcztoPXcz25tteem91rfLWgQFab+50csJ47zldlsB7/eOS/eHG5mUg5g5NPR4XefnXtjOcQ==} + cpu: [arm64] + os: [win32] + + lefthook-windows-x64@2.1.0: + resolution: {integrity: sha512-XbO/5nAZQLpUn0tPpgCYfFBFJHnymSglQ73jD6wymNrR1j8I5EcXGlP6YcLhnZ83yzsdLC+gup+N6IqUeiyRdw==} + cpu: [x64] + os: [win32] + + lefthook@2.1.0: + resolution: {integrity: sha512-+vS+yywGQW6CN1J1hbGkez//6ixGHIQqfxDN/d3JDm531w9GfGt2lAWTDfZTw/CEl80XsN0raFcnEraR3ldw9g==} + hasBin: true + + less@4.5.1: + resolution: {integrity: sha512-UKgI3/KON4u6ngSsnDADsUERqhZknsVZbnuzlRZXLQCmfC/MDld42fTydUE9B+Mla1AL6SJ/Pp6SlEFi/AVGfw==} + engines: {node: '>=14'} + hasBin: true + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + + listhen@1.9.0: + resolution: {integrity: sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg==} + hasBin: true + + listr2@8.3.3: + resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==} + engines: {node: '>=18.0.0'} + + local-pkg@1.1.2: + resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} + engines: {node: '>=14'} + + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + locko@1.1.0: + resolution: {integrity: sha512-pYB2dzRY93fJkg2RIl41AMNgTQftEjyTK9vlPrGOJvuGQsOjb267VJBw15BjiN3RBd1oBoKkOu9E2dRdFKIfAA==} + + lodash-es@4.17.23: + resolution: {integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==} + + lodash-unified@1.0.3: + resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==} + peerDependencies: + '@types/lodash-es': '*' + lodash: '*' + lodash-es: '*' + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.isarguments@3.1.0: + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + + lodash@4.17.23: + resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} + + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.2.6: + resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lucide-vue-next@0.553.0: + resolution: {integrity: sha512-0tg9XT+VCElTT+7EXXbBRhWe1nU7Doa32Xv/dHP5/LCleFVgV6cAqziM3C7AetqmsYIsfAtNwRYdtvs4Ds7aUg==} + peerDependencies: + vue: ^3.5.27 + + luxon@3.7.2: + resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} + engines: {node: '>=12'} + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + m3u8-parser@4.8.0: + resolution: {integrity: sha512-UqA2a/Pw3liR6Df3gwxrqghCP17OpPlQj6RBPLYygf/ZSQ4MoSgvdvhvt35qV+3NaaA0FSZx93Ix+2brT1U7cA==} + + magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magicast@0.5.2: + resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} + + make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + + mark.js@8.11.1: + resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} + + markdown-it@14.1.0: + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} + hasBin: true + + marked@17.0.1: + resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==} + engines: {node: '>= 20'} + hasBin: true + + markmap-common@0.16.0: + resolution: {integrity: sha512-q3nlNDMKuWXTm3VwZFY9V5zteL/+iBLZanUK5vS+e26bUbzTSG5VtAzsyJbmgJm1WhwmIIAxbXEnp6JdvtTduA==} + + markmap-html-parser@0.16.1: + resolution: {integrity: sha512-/Mgm4g1qMQ8uEOz8h8K+jPspdgjfw29NqmfTLZSt8yG+vW7fWWduPjGRFc5axAZxCzP7PTzZLEuOxAqOwEg8Bg==} + peerDependencies: + markmap-common: '*' + + markmap-lib@0.16.1: + resolution: {integrity: sha512-jD8VsB67m677IRehGSwwVJDlC6PS+xzDKsJOwdvjZ+ndfXrHa1lyqfvR6mIwvGGUIciF86YEITSKL9hQTHE4Rw==} + peerDependencies: + markmap-common: '*' + + markmap-toolbar@0.17.2: + resolution: {integrity: sha512-WQ05P2xvQmZT0ybRUE0uRzrs30aXlJ6/yEUsA6A9nYEwm8T9jSwBxIM/5zYlkH/XzUcsRRxtCa4k1IWR74gkpQ==} + peerDependencies: + markmap-common: '*' + + markmap-view@0.16.0: + resolution: {integrity: sha512-JOiSEThs8B4bAP9E6rcCWOz2SsMwCBFaR76wLARRVb04C/qLiLmvrm675kNPq4lRBAwtugHCYvjG0otpSlB4Cw==} + peerDependencies: + markmap-common: '*' + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mathml-tag-names@2.1.3: + resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} + + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + + mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + + mdn-data@2.12.2: + resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + + mdn-data@2.27.0: + resolution: {integrity: sha512-/pUmP9UebM48q5BTqZd0yPnDjyRGhITbKh8cwa6/ZwjuDu8xq+VzmugLF7QNxpdaqqNH3J5nnv3yc8oARv096A==} + + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + + medium-zoom@1.1.0: + resolution: {integrity: sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ==} + + memoize-one@6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + + meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + + meow@13.2.0: + resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} + engines: {node: '>=18'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mime@4.1.0: + resolution: {integrity: sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==} + engines: {node: '>=16'} + hasBin: true + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + min-dash@4.2.3: + resolution: {integrity: sha512-VLMYQI5+FcD9Ad24VcB08uA83B07OhueAlZ88jBK6PyupTvEJwllTMUqMy0wPGYs7pZUEtEEMWdHB63m3LtEcg==} + + min-dash@5.0.0: + resolution: {integrity: sha512-EGuoBnVL7/Fnv2sqakpX5WGmZehZ3YMmLayT7sM8E9DRU74kkeyMg4Rik1lsOkR2GbFNeBca4/L+UfU6gF0Edw==} + + min-document@2.19.2: + resolution: {integrity: sha512-8S5I8db/uZN8r9HSLFVWPdJCvYOejMcEC82VIzNUc6Zkklf/d1gg2psfE79/vyhWOj4+J8MtwmoOz3TmvaGu5A==} + + min-dom@4.2.1: + resolution: {integrity: sha512-TMoL8SEEIhUWYgkj7XMSgxmwSyGI+4fP2KFFGnN3FbHfbGHVdsLYSz8LoIsgPhz4dWRmLvxWWSMgzZMJW5sZuA==} + + min-dom@5.2.0: + resolution: {integrity: sha512-shfMH1tFbZCVSx3ECaQV1aGu8fYmGnXEWuItudWRd31DpVJzmVKXFH/Aqgf7YjOmZRgRH5BJafk16oeSbohJDg==} + + minimatch@10.1.2: + resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==} + engines: {node: 20 || >=22} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@7.4.6: + resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} + engines: {node: '>=10'} + + minimatch@9.0.1: + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} + engines: {node: '>=16 || 14 >=14.17'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass-collect@2.0.1: + resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + + minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + minisearch@7.2.0: + resolution: {integrity: sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==} + + minizlib@3.1.0: + resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} + engines: {node: '>= 18'} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mkdist@2.4.1: + resolution: {integrity: sha512-Ezk0gi04GJBkqMfsksICU5Rjoemc4biIekwgrONWVPor2EO/N9nBgN6MZXAf7Yw4mDDhrNyKbdETaHNevfumKg==} + hasBin: true + peerDependencies: + sass: ^1.92.1 + typescript: '>=5.9.2' + vue: ^3.5.27 + vue-sfc-transformer: ^0.1.1 + vue-tsc: ^1.8.27 || ^2.0.21 || ^3.0.0 + peerDependenciesMeta: + sass: + optional: true + typescript: + optional: true + vue: + optional: true + vue-sfc-transformer: + optional: true + vue-tsc: + optional: true + + mlly@1.8.0: + resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} + + moddle-xml@10.1.0: + resolution: {integrity: sha512-erWckwLt+dYskewKXJso9u+aAZ5172lOiYxSOqKCPTy7L/xmqH1PoeoA7eVC7oJTt3PqF5TkZzUmbjGH6soQBg==} + + moddle@6.2.3: + resolution: {integrity: sha512-bLVN+ZHL3aKnhxc19XtjUfvdJsS3EsiEJC7bT6YPD11qYmTzvsxrGgyYz1Ouof7TZuGw0lDJ1OLmEnxcpQWk3Q==} + + mpd-parser@0.22.1: + resolution: {integrity: sha512-fwBebvpyPUU8bOzvhX0VQZgSohncbgYwUyJJoTSNpmy7ccD2ryiCvM7oRkn/xQH5cv73/xU7rJSNCLjdGFor0Q==} + hasBin: true + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + multimatch@5.0.0: + resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==} + engines: {node: '>=10'} + + mux.js@6.0.1: + resolution: {integrity: sha512-22CHb59rH8pWGcPGW5Og7JngJ9s+z4XuSlYvnxhLuc58cA1WqGDQPzuG8I+sPm1/p0CdgpzVTaKW408k5DNn8w==} + engines: {node: '>=8', npm: '>=5'} + hasBin: true + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + naive-ui@2.43.2: + resolution: {integrity: sha512-YlLMnGrwGTOc+zMj90sG3ubaH5/7czsgLgGcjTLA981IUaz8r6t4WIujNt8r9PNr+dqv6XNEr0vxkARgPPjfBQ==} + peerDependencies: + vue: ^3.5.27 + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.1.6: + resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==} + engines: {node: ^18 || >=20} + hasBin: true + + nanopop@2.4.2: + resolution: {integrity: sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==} + + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + natural-orderby@5.0.0: + resolution: {integrity: sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==} + engines: {node: '>=18'} + + needle@3.3.1: + resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==} + engines: {node: '>= 4.4.x'} + hasBin: true + + nitropack@2.13.1: + resolution: {integrity: sha512-2dDj89C4wC2uzG7guF3CnyG+zwkZosPEp7FFBGHB3AJo11AywOolWhyQJFHDzve8COvGxJaqscye9wW2IrUsNw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + xml2js: ^0.6.2 + peerDependenciesMeta: + xml2js: + optional: true + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-cleanup@2.1.2: + resolution: {integrity: sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch-cache@5.1.0: + resolution: {integrity: sha512-4j3rRHNGIKGX7VzXSrBT0bh7+wFuyJv1DxCfCLDHsnDahJWoD9lXe3BzL3BJg/GEIJiM7KIvqVs3byW1GFtRsQ==} + engines: {node: '>=18.19.0'} + + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + node-forge@1.3.3: + resolution: {integrity: sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==} + engines: {node: '>= 6.13.0'} + + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + + node-html-parser@5.4.2: + resolution: {integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==} + + node-mock-http@1.0.4: + resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} + + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + + nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + nopt@8.1.0: + resolution: {integrity: sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-wheel-es@1.2.0: + resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + + npm2url@0.2.4: + resolution: {integrity: sha512-arzGp/hQz0Ey+ZGhF64XVH7Xqwd+1Q/po5uGiBbzph8ebX6T0uvt3N7c1nBHQNsQVykQgHhqoRTX7JFcHecGuw==} + + nprogress@0.2.0: + resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + nypm@0.6.5: + resolution: {integrity: sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==} + engines: {node: '>=18'} + hasBin: true + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-deep-merge@2.0.0: + resolution: {integrity: sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object-refs@0.3.0: + resolution: {integrity: sha512-eP0ywuoWOaDoiake/6kTJlPJhs+k0qNm4nYRzXLNHj6vh+5M3i9R1epJTdxIPGlhWc4fNRQ7a6XJNCX+/L4FOQ==} + + object-refs@0.4.0: + resolution: {integrity: sha512-6kJqKWryKZmtte6QYvouas0/EIJKPI1/MMIuRsiBlNuhIMfqYTggzX2F1AJ2+cDs288xyi9GL7FyasHINR98BQ==} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + ofetch@1.5.1: + resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} + + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + oniguruma-to-es@3.1.1: + resolution: {integrity: sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==} + + open@10.2.0: + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ora@8.2.0: + resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} + engines: {node: '>=18'} + + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-map@7.0.4: + resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} + engines: {node: '>=18'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + package-json@10.0.1: + resolution: {integrity: sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==} + engines: {node: '>=18'} + + package-manager-detector@0.2.11: + resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} + + package-manager-detector@1.6.0: + resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} + + pako@2.1.0: + resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} + + param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parent-module@2.0.0: + resolution: {integrity: sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==} + engines: {node: '>=8'} + + parse-imports-exports@0.2.4: + resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + parse-node-version@1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + + parse-passwd@1.0.0: + resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} + engines: {node: '>=0.10.0'} + + parse-statements@1.0.11: + resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} + + parse5-htmlparser2-tree-adapter@7.1.0: + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} + + parse5-parser-stream@7.1.2: + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + path-intersection@2.2.1: + resolution: {integrity: sha512-9u8xvMcSfuOiStv9bPdnRJQhGQXLKurew94n4GPQCdH1nj9QKC9ObbNoIpiRq8skiOBxKkt277PgOoFgAt3/rA==} + + path-intersection@3.1.0: + resolution: {integrity: sha512-3xS3lvv/vuwm5aH2BVvNRvnvwR2Drde7jQClKpCXTYXIMMjcw/EnMhzCgeHwqbCpzi760PEfAkU53vSIlrNr9A==} + engines: {node: '>= 14.20'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.1: + resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} + engines: {node: 20 || >=22} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + path-type@6.0.0: + resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} + engines: {node: '>=18'} + + pathe@0.2.0: + resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + + perfect-debounce@2.1.0: + resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pinia-plugin-persistedstate@4.7.1: + resolution: {integrity: sha512-WHOqh2esDlR3eAaknPbqXrkkj0D24h8shrDPqysgCFR6ghqP/fpFfJmMPJp0gETHsvrh9YNNg6dQfo2OEtDnIQ==} + peerDependencies: + '@nuxt/kit': '>=3.0.0' + '@pinia/nuxt': '>=0.10.0' + pinia: ^3.0.4 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + '@pinia/nuxt': + optional: true + pinia: + optional: true + + pinia@3.0.4: + resolution: {integrity: sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==} + peerDependencies: + typescript: '>=4.5.0' + vue: ^3.5.27 + peerDependenciesMeta: + typescript: + optional: true + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkcs7@1.0.4: + resolution: {integrity: sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==} + hasBin: true + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pkg-types@2.3.0: + resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + + playwright-core@1.58.2: + resolution: {integrity: sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.58.2: + resolution: {integrity: sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==} + engines: {node: '>=18'} + hasBin: true + + please-upgrade-node@3.2.0: + resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + + pnpm-workspace-yaml@1.5.0: + resolution: {integrity: sha512-PxdyJuFvq5B0qm3s9PaH/xOtSxrcvpBRr+BblhucpWjs8c79d4b7/cXhyY4AyHOHCnqklCYZTjfl0bT/mFVTRw==} + + popmotion@11.0.5: + resolution: {integrity: sha512-la8gPM1WYeFznb/JqF4GiTkRRPZsfaj2+kCxqQgr2MJylMmIKUwBfWW8Wa5fml/8gmtlD5yI01MP1QCZPWmppA==} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-antd-fixes@0.2.0: + resolution: {integrity: sha512-WuV4Ip5DnLg8q+wmNXUq13wZZcA5Lrj+em3Jznl4cxItZDgFp4wEh+5ba59TvFeHfwNuTEZ6YNDsYP9DG6NurQ==} + peerDependencies: + postcss: ^8.0.0 + + postcss-attribute-case-insensitive@7.0.1: + resolution: {integrity: sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-calc@10.1.1: + resolution: {integrity: sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw==} + engines: {node: ^18.12 || ^20.9 || >=22.0} + peerDependencies: + postcss: ^8.4.38 + + postcss-clamp@4.1.0: + resolution: {integrity: sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==} + engines: {node: '>=7.6.0'} + peerDependencies: + postcss: ^8.4.6 + + postcss-color-functional-notation@7.0.12: + resolution: {integrity: sha512-TLCW9fN5kvO/u38/uesdpbx3e8AkTYhMvDZYa9JpmImWuTE99bDQ7GU7hdOADIZsiI9/zuxfAJxny/khknp1Zw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-color-hex-alpha@10.0.0: + resolution: {integrity: sha512-1kervM2cnlgPs2a8Vt/Qbe5cQ++N7rkYo/2rz2BkqJZIHQwaVuJgQH38REHrAi4uM0b1fqxMkWYmese94iMp3w==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-color-rebeccapurple@10.0.0: + resolution: {integrity: sha512-JFta737jSP+hdAIEhk1Vs0q0YF5P8fFcj+09pweS8ktuGuZ8pPlykHsk6mPxZ8awDl4TrcxUqJo9l1IhVr/OjQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-colormin@7.0.5: + resolution: {integrity: sha512-ekIBP/nwzRWhEMmIxHHbXHcMdzd1HIUzBECaj5KEdLz9DVP2HzT065sEhvOx1dkLjYW7jyD0CngThx6bpFi2fA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-convert-values@7.0.8: + resolution: {integrity: sha512-+XNKuPfkHTCEo499VzLMYn94TiL3r9YqRE3Ty+jP7UX4qjewUONey1t7CG21lrlTLN07GtGM8MqFVp86D4uKJg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-custom-media@11.0.6: + resolution: {integrity: sha512-C4lD4b7mUIw+RZhtY7qUbf4eADmb7Ey8BFA2px9jUbwg7pjTZDl4KY4bvlUV+/vXQvzQRfiGEVJyAbtOsCMInw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-custom-properties@14.0.6: + resolution: {integrity: sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-custom-selectors@8.0.5: + resolution: {integrity: sha512-9PGmckHQswiB2usSO6XMSswO2yFWVoCAuih1yl9FVcwkscLjRKjwsjM3t+NIWpSU2Jx3eOiK2+t4vVTQaoCHHg==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-dir-pseudo-class@9.0.1: + resolution: {integrity: sha512-tRBEK0MHYvcMUrAuYMEOa0zg9APqirBcgzi6P21OhxtJyJADo/SWBwY1CAwEohQ/6HDaa9jCjLRG7K3PVQYHEA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-discard-comments@7.0.5: + resolution: {integrity: sha512-IR2Eja8WfYgN5n32vEGSctVQ1+JARfu4UH8M7bgGh1bC+xI/obsPJXaBpQF7MAByvgwZinhpHpdrmXtvVVlKcQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-discard-duplicates@7.0.2: + resolution: {integrity: sha512-eTonaQvPZ/3i1ASDHOKkYwAybiM45zFIc7KXils4mQmHLqIswXD9XNOKEVxtTFnsmwYzF66u4LMgSr0abDlh5w==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-discard-empty@7.0.1: + resolution: {integrity: sha512-cFrJKZvcg/uxB6Ijr4l6qmn3pXQBna9zyrPC+sK0zjbkDUZew+6xDltSF7OeB7rAtzaaMVYSdbod+sZOCWnMOg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-discard-overridden@7.0.1: + resolution: {integrity: sha512-7c3MMjjSZ/qYrx3uc1940GSOzN1Iqjtlqe8uoSg+qdVPYyRb0TILSqqmtlSFuE4mTDECwsm397Ya7iXGzfF7lg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-double-position-gradients@6.0.4: + resolution: {integrity: sha512-m6IKmxo7FxSP5nF2l63QbCC3r+bWpFUWmZXZf096WxG0m7Vl1Q1+ruFOhpdDRmKrRS+S3Jtk+TVk/7z0+BVK6g==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-focus-visible@10.0.1: + resolution: {integrity: sha512-U58wyjS/I1GZgjRok33aE8juW9qQgQUNwTSdxQGuShHzwuYdcklnvK/+qOWX1Q9kr7ysbraQ6ht6r+udansalA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-focus-within@9.0.1: + resolution: {integrity: sha512-fzNUyS1yOYa7mOjpci/bR+u+ESvdar6hk8XNK/TRR0fiGTp2QT5N+ducP0n3rfH/m9I7H/EQU6lsa2BrgxkEjw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-font-variant@5.0.0: + resolution: {integrity: sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==} + peerDependencies: + postcss: ^8.1.0 + + postcss-gap-properties@6.0.0: + resolution: {integrity: sha512-Om0WPjEwiM9Ru+VhfEDPZJAKWUd0mV1HmNXqp2C29z80aQ2uP9UVhLc7e3aYMIor/S5cVhoPgYQ7RtfeZpYTRw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-html@1.8.1: + resolution: {integrity: sha512-OLF6P7qctfAWayOhLpcVnTGqVeJzu2W3WpIYelfz2+JV5oGxfkcEvweN9U4XpeqE0P98dcD9ssusGwlF0TK0uQ==} + engines: {node: ^12 || >=14} + + postcss-image-set-function@7.0.0: + resolution: {integrity: sha512-QL7W7QNlZuzOwBTeXEmbVckNt1FSmhQtbMRvGGqqU4Nf4xk6KUEQhAoWuMzwbSv5jxiRiSZ5Tv7eiDB9U87znA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-import@16.1.1: + resolution: {integrity: sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.1.0: + resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-lab-function@7.0.12: + resolution: {integrity: sha512-tUcyRk1ZTPec3OuKFsqtRzW2Go5lehW29XA21lZ65XmzQkz43VY2tyWEC202F7W3mILOjw0voOiuxRGTsN+J9w==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: ^2.6.1 + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + + postcss-logical@8.1.0: + resolution: {integrity: sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-media-query-parser@0.2.3: + resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} + + postcss-merge-longhand@7.0.5: + resolution: {integrity: sha512-Kpu5v4Ys6QI59FxmxtNB/iHUVDn9Y9sYw66D6+SZoIk4QTz1prC4aYkhIESu+ieG1iylod1f8MILMs1Em3mmIw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-merge-rules@7.0.7: + resolution: {integrity: sha512-njWJrd/Ms6XViwowaaCc+/vqhPG3SmXn725AGrnl+BgTuRPEacjiLEaGq16J6XirMJbtKkTwnt67SS+e2WGoew==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-minify-font-values@7.0.1: + resolution: {integrity: sha512-2m1uiuJeTplll+tq4ENOQSzB8LRnSUChBv7oSyFLsJRtUgAAJGP6LLz0/8lkinTgxrmJSPOEhgY1bMXOQ4ZXhQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-minify-gradients@7.0.1: + resolution: {integrity: sha512-X9JjaysZJwlqNkJbUDgOclyG3jZEpAMOfof6PUZjPnPrePnPG62pS17CjdM32uT1Uq1jFvNSff9l7kNbmMSL2A==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-minify-params@7.0.5: + resolution: {integrity: sha512-FGK9ky02h6Ighn3UihsyeAH5XmLEE2MSGH5Tc4tXMFtEDx7B+zTG6hD/+/cT+fbF7PbYojsmmWjyTwFwW1JKQQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-minify-selectors@7.0.5: + resolution: {integrity: sha512-x2/IvofHcdIrAm9Q+p06ZD1h6FPcQ32WtCRVodJLDR+WMn8EVHI1kvLxZuGKz/9EY5nAmI6lIQIrpo4tBy5+ug==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-nested@5.0.6: + resolution: {integrity: sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-nested@7.0.2: + resolution: {integrity: sha512-5osppouFc0VR9/VYzYxO03VaDa3e8F23Kfd6/9qcZTUI8P58GIYlArOET2Wq0ywSl2o2PjELhYOFI4W7l5QHKw==} + engines: {node: '>=18.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-nesting@13.0.2: + resolution: {integrity: sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-normalize-charset@7.0.1: + resolution: {integrity: sha512-sn413ofhSQHlZFae//m9FTOfkmiZ+YQXsbosqOWRiVQncU2BA3daX3n0VF3cG6rGLSFVc5Di/yns0dFfh8NFgQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-normalize-display-values@7.0.1: + resolution: {integrity: sha512-E5nnB26XjSYz/mGITm6JgiDpAbVuAkzXwLzRZtts19jHDUBFxZ0BkXAehy0uimrOjYJbocby4FVswA/5noOxrQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-normalize-positions@7.0.1: + resolution: {integrity: sha512-pB/SzrIP2l50ZIYu+yQZyMNmnAcwyYb9R1fVWPRxm4zcUFCY2ign7rcntGFuMXDdd9L2pPNUgoODDk91PzRZuQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-normalize-repeat-style@7.0.1: + resolution: {integrity: sha512-NsSQJ8zj8TIDiF0ig44Byo3Jk9e4gNt9x2VIlJudnQQ5DhWAHJPF4Tr1ITwyHio2BUi/I6Iv0HRO7beHYOloYQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-normalize-string@7.0.1: + resolution: {integrity: sha512-QByrI7hAhsoze992kpbMlJSbZ8FuCEc1OT9EFbZ6HldXNpsdpZr+YXC5di3UEv0+jeZlHbZcoCADgb7a+lPmmQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-normalize-timing-functions@7.0.1: + resolution: {integrity: sha512-bHifyuuSNdKKsnNJ0s8fmfLMlvsQwYVxIoUBnowIVl2ZAdrkYQNGVB4RxjfpvkMjipqvbz0u7feBZybkl/6NJg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-normalize-unicode@7.0.5: + resolution: {integrity: sha512-X6BBwiRxVaFHrb2WyBMddIeB5HBjJcAaUHyhLrM2FsxSq5TFqcHSsK7Zu1otag+o0ZphQGJewGH1tAyrD0zX1Q==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-normalize-url@7.0.1: + resolution: {integrity: sha512-sUcD2cWtyK1AOL/82Fwy1aIVm/wwj5SdZkgZ3QiUzSzQQofrbq15jWJ3BA7Z+yVRwamCjJgZJN0I9IS7c6tgeQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-normalize-whitespace@7.0.1: + resolution: {integrity: sha512-vsbgFHMFQrJBJKrUFJNZ2pgBeBkC2IvvoHjz1to0/0Xk7sII24T0qFOiJzG6Fu3zJoq/0yI4rKWi7WhApW+EFA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-opacity-percentage@3.0.0: + resolution: {integrity: sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-ordered-values@7.0.2: + resolution: {integrity: sha512-AMJjt1ECBffF7CEON/Y0rekRLS6KsePU6PRP08UqYW4UGFRnTXNrByUzYK1h8AC7UWTZdQ9O3Oq9kFIhm0SFEw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-overflow-shorthand@6.0.0: + resolution: {integrity: sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-page-break@3.0.4: + resolution: {integrity: sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==} + peerDependencies: + postcss: ^8 + + postcss-place@10.0.0: + resolution: {integrity: sha512-5EBrMzat2pPAxQNWYavwAfoKfYcTADJ8AXGVPcUZ2UkNloUTWzJQExgrzrDkh3EKzmAx1evfTAzF9I8NGcc+qw==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-preset-env@10.6.1: + resolution: {integrity: sha512-yrk74d9EvY+W7+lO9Aj1QmjWY9q5NsKjK2V9drkOPZB/X6KZ0B3igKsHUYakb7oYVhnioWypQX3xGuePf89f3g==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-pseudo-class-any-link@10.0.1: + resolution: {integrity: sha512-3el9rXlBOqTFaMFkWDOkHUTQekFIYnaQY55Rsp8As8QQkpiSgIYEcF/6Ond93oHiDsGb4kad8zjt+NPlOC1H0Q==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-reduce-initial@7.0.5: + resolution: {integrity: sha512-RHagHLidG8hTZcnr4FpyMB2jtgd/OcyAazjMhoy5qmWJOx1uxKh4ntk0Pb46ajKM0rkf32lRH4C8c9qQiPR6IA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-reduce-transforms@7.0.1: + resolution: {integrity: sha512-MhyEbfrm+Mlp/36hvZ9mT9DaO7dbncU0CvWI8V93LRkY6IYlu38OPg3FObnuKTUxJ4qA8HpurdQOo5CyqqO76g==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-replace-overflow-wrap@4.0.0: + resolution: {integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==} + peerDependencies: + postcss: ^8.0.3 + + postcss-resolve-nested-selector@0.1.6: + resolution: {integrity: sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==} + + postcss-safe-parser@6.0.0: + resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.3.3 + + postcss-safe-parser@7.0.1: + resolution: {integrity: sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==} + engines: {node: '>=18.0'} + peerDependencies: + postcss: ^8.4.31 + + postcss-scss@4.0.9: + resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.29 + + postcss-selector-not@8.0.1: + resolution: {integrity: sha512-kmVy/5PYVb2UOhy0+LqUYAhKj7DUGDpSWa5LZqlkWJaaAV+dxxsOG3+St0yNLu6vsKD7Dmqx+nWQt0iil89+WA==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + + postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-selector-parser@7.1.1: + resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} + engines: {node: '>=4'} + + postcss-sorting@9.1.0: + resolution: {integrity: sha512-Mn8KJ45HNNG6JBpBizXcyf6LqY/qyqetGcou/nprDnFwBFBLGj0j/sNKV2lj2KMOVOwdXu14aEzqJv8CIV6e8g==} + peerDependencies: + postcss: ^8.4.20 + + postcss-svgo@7.1.0: + resolution: {integrity: sha512-KnAlfmhtoLz6IuU3Sij2ycusNs4jPW+QoFE5kuuUOK8awR6tMxZQrs5Ey3BUz7nFCzT3eqyFgqkyrHiaU2xx3w==} + engines: {node: ^18.12.0 || ^20.9.0 || >= 18} + peerDependencies: + postcss: ^8.4.32 + + postcss-unique-selectors@7.0.4: + resolution: {integrity: sha512-pmlZjsmEAG7cHd7uK3ZiNSW6otSZ13RHuZ/4cDN/bVglS5EpF2r2oxY99SuOHa8m7AWoBCelTS3JPpzsIs8skQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + preact@10.28.3: + resolution: {integrity: sha512-tCmoRkPQLpBeWzpmbhryairGnhW9tKV6c6gr/w+RhoRoKEJwsjzipwp//1oCpGPOchvSLaAPlpcJi9MwMmoPyA==} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-linter-helpers@1.0.1: + resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==} + engines: {node: '>=6.0.0'} + + prettier-plugin-tailwindcss@0.7.2: + resolution: {integrity: sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA==} + engines: {node: '>=20.19'} + peerDependencies: + '@ianvs/prettier-plugin-sort-imports': '*' + '@prettier/plugin-hermes': '*' + '@prettier/plugin-oxc': '*' + '@prettier/plugin-pug': '*' + '@shopify/prettier-plugin-liquid': '*' + '@trivago/prettier-plugin-sort-imports': '*' + '@zackad/prettier-plugin-twig': '*' + prettier: ^3.0 + prettier-plugin-astro: '*' + prettier-plugin-css-order: '*' + prettier-plugin-jsdoc: '*' + prettier-plugin-marko: '*' + prettier-plugin-multiline-arrays: '*' + prettier-plugin-organize-attributes: '*' + prettier-plugin-organize-imports: '*' + prettier-plugin-sort-imports: '*' + prettier-plugin-svelte: '*' + peerDependenciesMeta: + '@ianvs/prettier-plugin-sort-imports': + optional: true + '@prettier/plugin-hermes': + optional: true + '@prettier/plugin-oxc': + optional: true + '@prettier/plugin-pug': + optional: true + '@shopify/prettier-plugin-liquid': + optional: true + '@trivago/prettier-plugin-sort-imports': + optional: true + '@zackad/prettier-plugin-twig': + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-css-order: + optional: true + prettier-plugin-jsdoc: + optional: true + prettier-plugin-marko: + optional: true + prettier-plugin-multiline-arrays: + optional: true + prettier-plugin-organize-attributes: + optional: true + prettier-plugin-organize-imports: + optional: true + prettier-plugin-sort-imports: + optional: true + prettier-plugin-svelte: + optional: true + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@3.8.1: + resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + engines: {node: '>=14'} + hasBin: true + + pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + + pretty-bytes@6.1.1: + resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} + engines: {node: ^14.13.1 || >=16.0.0} + + pretty-bytes@7.1.0: + resolution: {integrity: sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw==} + engines: {node: '>=20'} + + pretty-ms@9.3.0: + resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} + engines: {node: '>=18'} + + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + prr@1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + + publint@0.3.17: + resolution: {integrity: sha512-Q3NLegA9XM6usW+dYQRG1g9uEHiYUzcCVBJDJ7yMcWRqVU9LYZUWdqbwMZfmTCFC5PZLQpLAmhvRcQRl3exqkw==} + engines: {node: '>=18'} + hasBin: true + + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pupa@3.3.0: + resolution: {integrity: sha512-LjgDO2zPtoXP2wJpDjZrGdojii1uqO0cnwKoIoUzkfS98HDmbeiGmYiXo3lXeFlq2xvne1QFQhwYXSUCLKtEuA==} + engines: {node: '>=12.20'} + + qified@0.6.0: + resolution: {integrity: sha512-tsSGN1x3h569ZSU1u6diwhltLyfUWDp3YbFHedapTmpBl0B3P6U3+Qptg7xu+v+1io1EwhdPyyRHYbEw0KN2FA==} + engines: {node: '>=20'} + + qrcode@1.5.4: + resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} + engines: {node: '>=10.13.0'} + hasBin: true + + qs@6.14.1: + resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} + engines: {node: '>=0.6'} + + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + radix3@1.1.2: + resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + randomcolor@0.6.2: + resolution: {integrity: sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + rc9@2.1.2: + resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} + + rc9@3.0.0: + resolution: {integrity: sha512-MGOue0VqscKWQ104udASX/3GYDcKyPI4j4F8gu/jHHzglpmy9a/anZK3PNe8ug6aZFl+9GxLtdhe3kVZuMaQbA==} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + + read-yaml-file@2.1.0: + resolution: {integrity: sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ==} + engines: {node: '>=10.13'} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + readdir-glob@1.1.3: + resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + + refa@0.12.1: + resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regenerate-unicode-properties@10.2.2: + resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} + engines: {node: '>=4'} + + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.1.0: + resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + + regexp-ast-analysis@0.7.1: + resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + regexpu-core@6.4.0: + resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} + engines: {node: '>=4'} + + registry-auth-token@5.1.1: + resolution: {integrity: sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==} + engines: {node: '>=14'} + + registry-url@6.0.1: + resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} + engines: {node: '>=12'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.13.0: + resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} + hasBin: true + + reka-ui@2.8.0: + resolution: {integrity: sha512-N4JOyIrmDE7w2i06WytqcV2QICubtS2PsK5Uo8FIMAgmO13KhUAgAByP26cXjjm2oF/w7rTyRs8YaqtvaBT+SA==} + peerDependencies: + vue: ^3.5.27 + + relateurl@0.2.7: + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} + + remarkable-katex@1.2.1: + resolution: {integrity: sha512-Y1VquJBZnaVsfsVcKW2hmjT+pDL7mp8l5WAVlvuvViltrdok2m1AIKmJv8SsH+mBY84PoMw67t3kTWw1dIm8+g==} + + remarkable@2.0.1: + resolution: {integrity: sha512-YJyMcOH5lrR+kZdmB0aJJ4+93bEojRZ1HGDn9Eagu6ibg7aVZhc3OWbbShRid+Q5eAfsEqWxpe+g5W5nYNfNiA==} + engines: {node: '>= 6.0.0'} + hasBin: true + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + + require-package-name@2.0.1: + resolution: {integrity: sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==} + + reserved-identifiers@1.2.0: + resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==} + engines: {node: '>=18'} + + resize-observer-polyfill@1.5.1: + resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + + resolve-dir@1.0.1: + resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve.exports@2.0.3: + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} + engines: {node: '>=10'} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rimraf@6.1.2: + resolution: {integrity: sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==} + engines: {node: 20 || >=22} + hasBin: true + + robust-predicates@3.0.2: + resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + + rolldown-string@0.2.1: + resolution: {integrity: sha512-7H8oH5A8+L96pbBTPCt/rZrwayEhZY5/ejhdk9nRODH32H1v7+bfkaCr+kS15DcGQ7VC1HcWdQVNABFYgrMOzg==} + engines: {node: '>=20.19.0'} + + rollup-plugin-dts@6.3.0: + resolution: {integrity: sha512-d0UrqxYd8KyZ6i3M2Nx7WOMy708qsV/7fTHMHxCMCBOAe3V/U7OMPu5GkX8hC+cmkHhzGnfeYongl1IgiooddA==} + engines: {node: '>=16'} + peerDependencies: + rollup: ^3.29.4 || ^4 + typescript: ^4.5 || ^5.0 + + rollup-plugin-visualizer@5.14.0: + resolution: {integrity: sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + rolldown: 1.x + rollup: 2.x || 3.x || 4.x + peerDependenciesMeta: + rolldown: + optional: true + rollup: + optional: true + + rollup-plugin-visualizer@6.0.5: + resolution: {integrity: sha512-9+HlNgKCVbJDs8tVtjQ43US12eqaiHyyiLMdBwQ7vSZPiHMysGNo2E88TAp1si5wx8NAoYriI2A5kuKfIakmJg==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + rolldown: 1.x || ^1.0.0-beta + rollup: 2.x || 3.x || 4.x + peerDependenciesMeta: + rolldown: + optional: true + rollup: + optional: true + + rollup@2.79.2: + resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} + engines: {node: '>=10.0.0'} + hasBin: true + + rollup@4.57.1: + resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + rotated-array-set@3.0.0: + resolution: {integrity: sha512-G7689wvCM0szMFXUAhi3GfNGcSPlndg077cdRWoq7UegOAwfU2MJ0jD7s7jB+2ppKA75Kr/O0HwAP9+rRdBctg==} + engines: {node: ^14.13.1 || >=16.0.0} + + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + rust-result@1.0.0: + resolution: {integrity: sha512-6cJzSBU+J/RJCF063onnQf0cDUOHs9uZI1oroSGnHOph+CQTIJ5Pp2hK5kEQq1+7yE/EEWfulSNXAQ2jikPthA==} + + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-json-parse@4.0.0: + resolution: {integrity: sha512-RjZPPHugjK0TOzFrLZ8inw44s9bKox99/0AZW9o/BEQVrJfhI+fIHMErnPyRa89/yRXUUr93q+tiN6zhoVV4wQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sass@1.97.3: + resolution: {integrity: sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==} + engines: {node: '>=14.0.0'} + hasBin: true + + sax@1.4.4: + resolution: {integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==} + engines: {node: '>=11.0.0'} + + saxen@8.1.2: + resolution: {integrity: sha512-xUOiiFbc3Ow7p8KMxwsGICPx46ZQvy3+qfNVhrkwfz3Vvq45eGt98Ft5IQaA1R/7Tb5B5MKh9fUR9x3c3nDTxw==} + + scroll-into-view-if-needed@2.2.31: + resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} + + scroll-into-view-if-needed@3.1.0: + resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} + + scslre@0.3.0: + resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==} + engines: {node: ^14.0.0 || >=16.0.0} + + scule@1.3.0: + resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} + + search-insights@2.17.3: + resolution: {integrity: sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==} + + section-matter@1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + + secure-ls@2.0.0: + resolution: {integrity: sha512-Wgtnw0QSm0v7gVKv11nOoeyGS65EThGXnBB7jfd4IhZd2eq3B4AMPcXAL5qJ1h55+Qolun7TONTwX7H5m6e2pQ==} + engines: {node: '>=8.0'} + + seemly@0.3.10: + resolution: {integrity: sha512-2+SMxtG1PcsL0uyhkumlOU6Qo9TAQ/WyH7tthnPIOQB05/12jz9naq6GZ6iZ6ApVsO3rr2gsnTf3++OV63kE1Q==} + + select@1.1.2: + resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==} + + semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} + + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + + serve-placeholder@2.0.2: + resolution: {integrity: sha512-/TMG8SboeiQbZJWRlfTCqMs2DD3SZgWp0kDQePz9yUuCnDfDh/92gf7/PxGhzXTKBIPASIHxFcZndoNbp6QOLQ==} + + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shallow-equal@1.2.1: + resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shiki@2.5.0: + resolution: {integrity: sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==} + + short-tree@3.0.0: + resolution: {integrity: sha512-Yd9NFs/o9QSoH4/wTjxk4Xe0+CIzitDRN1Qg7iBeTSejKjlCg/3PbgiRwDUVuaIxD0RRdv7Iz9jKr7e0HljtUg==} + engines: {node: ^14.13.1 || >=16.0.0} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + signature_pad@3.0.0-beta.4: + resolution: {integrity: sha512-cOf2NhVuTiuNqe2X/ycEmizvCDXk0DoemhsEpnkcGnA4kS5iJYTCqZ9As7tFBbsch45Q1EdX61833+6sjJ8rrw==} + + signature_pad@5.1.3: + resolution: {integrity: sha512-zyxW5vuJVnQdGcU+kAj9FYl7WaAunY3kA5S7mPg0xJiujL9+sPAWfSQHS5tXaJXDUa4FuZeKhfdCDQ6K3wfkpQ==} + + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} + engines: {node: '>=18'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.2: + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} + engines: {node: '>=18'} + + smob@1.5.0: + resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} + + smol-toml@1.6.0: + resolution: {integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==} + engines: {node: '>= 18'} + + sortablejs@1.14.0: + resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==} + + sortablejs@1.15.6: + resolution: {integrity: sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + + source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions + + sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + spawndamnit@3.0.1: + resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@4.0.0: + resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} + + spdx-license-ids@3.0.22: + resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + + speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + ssri@13.0.1: + resolution: {integrity: sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ==} + engines: {node: ^20.17.0 || >=22.9.0} + + stable-hash-x@0.2.0: + resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} + engines: {node: '>=12.0.0'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + + steady-xml@0.1.0: + resolution: {integrity: sha512-5sk17qO2wWRtonTNoBhoKAB35OSsGJOa3+NEa6D+1GS+de+ujDWxnflMkXBrviOfkNrPTUqduAdXhrMJs89nAw==} + engines: {node: '>=12.0.0'} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + streamx@2.23.0: + resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + stringify-object@3.3.0: + resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} + engines: {node: '>=4'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + engines: {node: '>=12'} + + strip-bom-string@1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-comments@2.0.1: + resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} + engines: {node: '>=10'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + + strip-indent@4.1.1: + resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==} + engines: {node: '>=12'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + + strnum@1.1.2: + resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} + + stubborn-fs@2.0.0: + resolution: {integrity: sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA==} + + stubborn-utils@1.0.2: + resolution: {integrity: sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg==} + + style-mod@4.1.3: + resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} + + style-search@0.1.0: + resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} + + style-value-types@5.1.2: + resolution: {integrity: sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q==} + + stylehacks@7.0.7: + resolution: {integrity: sha512-bJkD0JkEtbRrMFtwgpJyBbFIwfDDONQ1Ov3sDLZQP8HuJ73kBOyx66H4bOcAbVWmnfLdvQ0AJwXxOMkpujcO6g==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.32 + + stylelint-config-html@1.1.0: + resolution: {integrity: sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ==} + engines: {node: ^12 || >=14} + peerDependencies: + postcss-html: ^1.0.0 + stylelint: '>=14.0.0' + + stylelint-config-recess-order@7.6.1: + resolution: {integrity: sha512-ac0H/Iy2chh1YBADrua87G+nJCmG/SdG7gjnoLvtfpN0D+RuNfuADawfbCKvm0LMp5hvuRFNkJsu6xNoLM5ToA==} + peerDependencies: + stylelint: ^16.18.0 || ^17.0.0 + stylelint-order: ^7.0.0 + + stylelint-config-recommended-scss@16.0.2: + resolution: {integrity: sha512-aUTHhPPWCvFyWaxtckJlCPaXTDFsp4pKO8evXNCsW9OwsaUWyMd6jvcUhSmfGWPrTddvzNqK4rS/UuSLcbVGdQ==} + engines: {node: '>=20'} + peerDependencies: + postcss: ^8.3.3 + stylelint: ^16.24.0 + peerDependenciesMeta: + postcss: + optional: true + + stylelint-config-recommended-vue@1.6.1: + resolution: {integrity: sha512-lLW7hTIMBiTfjenGuDq2kyHA6fBWd/+Df7MO4/AWOxiFeXP9clbpKgg27kHfwA3H7UNMGC7aeP3mNlZB5LMmEQ==} + engines: {node: ^12 || >=14} + peerDependencies: + postcss-html: ^1.0.0 + stylelint: '>=14.0.0' + + stylelint-config-recommended@17.0.0: + resolution: {integrity: sha512-WaMSdEiPfZTSFVoYmJbxorJfA610O0tlYuU2aEwY33UQhSPgFbClrVJYWvy3jGJx+XW37O+LyNLiZOEXhKhJmA==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.23.0 + + stylelint-config-standard@39.0.1: + resolution: {integrity: sha512-b7Fja59EYHRNOTa3aXiuWnhUWXFU2Nfg6h61bLfAb5GS5fX3LMUD0U5t4S8N/4tpHQg3Acs2UVPR9jy2l1g/3A==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.23.0 + + stylelint-order@7.0.1: + resolution: {integrity: sha512-GWPei1zBVDDjxM+/BmcSCiOcHNd8rSqW6FUZtqQGlTRpD0Z5nSzspzWD8rtKif5KPdzUG68DApKEV/y/I9VbTw==} + engines: {node: '>=20.19.0'} + peerDependencies: + stylelint: ^16.18.0 || ^17.0.0 + + stylelint-prettier@5.0.3: + resolution: {integrity: sha512-B6V0oa35ekRrKZlf+6+jA+i50C4GXJ7X1PPmoCqSUoXN6BrNF6NhqqhanvkLjqw2qgvrS0wjdpeC+Tn06KN3jw==} + engines: {node: '>=18.12.0'} + peerDependencies: + prettier: '>=3.0.0' + stylelint: '>=16.0.0' + + stylelint-scss@6.14.0: + resolution: {integrity: sha512-ZKmHMZolxeuYsnB+PCYrTpFce0/QWX9i9gh0hPXzp73WjuIMqUpzdQaBCrKoLWh6XtCFSaNDErkMPqdjy1/8aA==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.8.2 + + stylelint@16.26.1: + resolution: {integrity: sha512-v20V59/crfc8sVTAtge0mdafI3AdnzQ2KsWe6v523L4OA1bJO02S7MO2oyXDCS6iWb9ckIPnqAFVItqSBQr7jw==} + engines: {node: '>=18.12.0'} + hasBin: true + + stylis@4.3.6: + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + superjson@2.2.6: + resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==} + engines: {node: '>=16'} + + supports-color@10.2.2: + resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} + engines: {node: '>=18'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-hyperlinks@3.2.0: + resolution: {integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==} + engines: {node: '>=14.18'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svelte@5.50.1: + resolution: {integrity: sha512-/Jlom4ddkISyVHXpM2O5dXP9pYnaiFrVQzPbIL1/pEoOa77ZunCb6nDgUCTNCQ/X3t64z9ukrK6R+BbB3kPR3A==} + engines: {node: '>=18'} + + sver@2.0.1: + resolution: {integrity: sha512-zqIx4tK5+gR8xE8VgLNr+IA0mqKDgMNdsfX86DTfNNnVKyuVUhjGdz6KA0rO3q445WUfGpEeJym1m3Xym7ot6w==} + + svg-tags@1.0.0: + resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + + svgo@4.0.0: + resolution: {integrity: sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==} + engines: {node: '>=16'} + hasBin: true + + synckit@0.11.12: + resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} + engines: {node: ^14.18.0 || >=16.0.0} + + system-architecture@0.1.0: + resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} + engines: {node: '>=18'} + + tabbable@6.4.0: + resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} + + table@6.9.0: + resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} + engines: {node: '>=10.0.0'} + + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + + tailwind-merge@2.6.1: + resolution: {integrity: sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==} + + tailwindcss-animate@1.0.7: + resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + + tailwindcss@3.4.19: + resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==} + engines: {node: '>=14.0.0'} + hasBin: true + + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} + engines: {node: '>=6'} + + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + + tar@7.5.7: + resolution: {integrity: sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==} + engines: {node: '>=18'} + + tdesign-icons-vue-next@0.4.2: + resolution: {integrity: sha512-mTPk1ApcCA9oxDiSs9ttMdd09H8ICBooZIr2bwDEELnYr60sYSUbvWojQ2tp84MUAMuw21HgyVyGkT49db0GFg==} + peerDependencies: + vue: ^3.5.27 + + tdesign-vue-next@1.18.2: + resolution: {integrity: sha512-Y7hpEHNQPft7TP0TfgZoBMcXUkILOxZRtV0es7ZFcGmsFqkOl4W2p2amYx78Id4W40VizJXzxP1HzFXRI0MYqw==} + engines: {node: '>= 18'} + peerDependencies: + vue: ^3.5.27 + + temp-dir@2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} + + tempy@0.6.0: + resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} + engines: {node: '>=10'} + + term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + + terser@5.46.0: + resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==} + engines: {node: '>=10'} + hasBin: true + + text-decoder@1.2.3: + resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} + + text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + + theme-colors@0.1.0: + resolution: {integrity: sha512-6gTEHQqWlQNiOEGHCSSQmU//E5SnXHJ4H7oHQOD8x77CvNYNQAmt73dqR71mzw5ULV87zaHLxK5pIBnsToFuZw==} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + throttle-debounce@5.0.2: + resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} + engines: {node: '>=12.22'} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + tiny-emitter@2.1.0: + resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} + + tiny-svg@3.1.3: + resolution: {integrity: sha512-9mwnPqXInRsBmH/DO6NMxBE++9LsqpVXQSSTZGc5bomoKKvL5OX/Hlotw7XVXP6XLRcHWIzZpxfovGqWKgCypQ==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinycolor2@1.6.0: + resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tinymce@7.9.1: + resolution: {integrity: sha512-zaOHwmiP1EqTeLRXAvVriDb00JYnfEjWGPdKEuac7MiZJ5aiDMZ4Unc98Gmajn+PBljOmO1GKV6G0KwWn3+k8A==} + + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} + + tippy.js@6.3.7: + resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + to-valid-identifier@1.0.0: + resolution: {integrity: sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==} + engines: {node: '>=20'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + + treemate@0.3.11: + resolution: {integrity: sha512-M8RGFoKtZ8dF+iwJfAJTOH/SM4KluKOKRJpjCMhI8bG3qB74zrFoArKZ62ll0Fr3mqkMJiQOmWYkdYgDeITYQg==} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + ts-api-utils@1.4.3: + resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + ts-api-utils@2.4.0: + resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-declaration-location@1.0.7: + resolution: {integrity: sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==} + peerDependencies: + typescript: '>=4.0.0' + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + + tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + turbo-darwin-64@2.8.5: + resolution: {integrity: sha512-3wngnZrjRh6nXjNFURY9yKV7ysTF2gibpzkQjo4/c4eWjGt39q5p/A/wpxpnVBzyT1/auaPuzxJA98Sv1ZCOJg==} + cpu: [x64] + os: [darwin] + + turbo-darwin-arm64@2.8.5: + resolution: {integrity: sha512-QAFH6X9h8M4G8uTVRBQFw6EN0LmvYYyNEA2EKJOEogyeULSUA04M+FzYuSScl6uS9P78fzOCC0hhzk/Eqo4GQg==} + cpu: [arm64] + os: [darwin] + + turbo-linux-64@2.8.5: + resolution: {integrity: sha512-o01d5g3CZWavW6vP0KD8wJwdqoHaLuOAb3PvuWY95JEcyPRAKGKNxsTW2xNifY4UYENwSVktFZXZlIO2qnrEmg==} + cpu: [x64] + os: [linux] + + turbo-linux-arm64@2.8.5: + resolution: {integrity: sha512-YSNVEUeFVGsA2pmPOokiximJOhKQnrg/M7JlJZzefjmp+j4Raj7YqLwK8pQRbAO4XDoojkf4tvmy+mRVW9O0gQ==} + cpu: [arm64] + os: [linux] + + turbo-windows-64@2.8.5: + resolution: {integrity: sha512-X0MMT+IwWS+veX8h9/SO3+gkorcuGi0nu8CIg0kBhaqbC6Me0tChvHYQpkXj/+5qG5oFpjgkCSCip4/KYesZtg==} + cpu: [x64] + os: [win32] + + turbo-windows-arm64@2.8.5: + resolution: {integrity: sha512-YBHZ1a0y8J0ITKv4TgujMFk04y84KimPDg8Br2lQaywrj3i2eRXLVuxhPi0Sqw+QuoqBVNKsHigxShA/w+rLLQ==} + cpu: [arm64] + os: [win32] + + turbo@2.8.5: + resolution: {integrity: sha512-pUhV1czFZNGOwnwCLaO727uSDH4botIrhOb/AAFqzfi3x4eeRZoOcAjoidnXD/dwCAw0HJf3+Sy4c2e8SlQKxQ==} + hasBin: true + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + type-fest@5.4.4: + resolution: {integrity: sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==} + engines: {node: '>=20'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typescript@5.8.2: + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + engines: {node: '>=14.17'} + hasBin: true + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + + ufo@1.6.3: + resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + + ultrahtml@1.6.0: + resolution: {integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==} + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + unbuild@3.6.1: + resolution: {integrity: sha512-+U5CdtrdjfWkZhuO4N9l5UhyiccoeMEXIc2Lbs30Haxb+tRwB3VwB8AoZRxlAzORXunenSo+j6lh45jx+xkKgg==} + hasBin: true + peerDependencies: + typescript: ^5.9.2 + peerDependenciesMeta: + typescript: + optional: true + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + + unctx@2.5.0: + resolution: {integrity: sha512-p+Rz9x0R7X+CYDkT+Xg8/GhpcShTlU8n+cf9OtOEf7zEQsNcCZO1dPKNRDqvUTaq+P32PMMkxWHwfrxkqfqAYg==} + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + undici@7.21.0: + resolution: {integrity: sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==} + engines: {node: '>=20.18.1'} + + unenv@2.0.0-rc.24: + resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.1: + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.2.0: + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} + engines: {node: '>=4'} + + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + unicorn-magic@0.4.0: + resolution: {integrity: sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==} + engines: {node: '>=20'} + + unimport@5.6.0: + resolution: {integrity: sha512-8rqAmtJV8o60x46kBAJKtHpJDJWkA2xcBqWKPI14MgUb05o1pnpnCnXSxedUXyeq7p8fR5g3pTo2BaswZ9lD9A==} + engines: {node: '>=18.12.0'} + + unique-filename@5.0.0: + resolution: {integrity: sha512-2RaJTAvAb4owyjllTfXzFClJ7WsGxlykkPvCr9pA//LD9goVq+m4PPAeBgNodGZ7nSrntT/auWpJ6Y5IFXcfjg==} + engines: {node: ^20.17.0 || >=22.9.0} + + unique-slug@6.0.0: + resolution: {integrity: sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw==} + engines: {node: ^20.17.0 || >=22.9.0} + + unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unplugin-element-plus@0.11.2: + resolution: {integrity: sha512-jr88ePpv43h8cCmVW0SqM73sTD+g1n9Rmy4uMbTh+pSmceH9ZdKteWX9f+twC4aDlP3svdZuKMqLoUNBT2V6Tg==} + engines: {node: '>=20.19.0'} + + unplugin-utils@0.3.1: + resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==} + engines: {node: '>=20.19.0'} + + unplugin@1.16.1: + resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} + engines: {node: '>=14.0.0'} + + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} + + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + + unstorage@1.17.4: + resolution: {integrity: sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==} + peerDependencies: + '@azure/app-configuration': ^1.8.0 + '@azure/cosmos': ^4.2.0 + '@azure/data-tables': ^13.3.0 + '@azure/identity': ^4.6.0 + '@azure/keyvault-secrets': ^4.9.0 + '@azure/storage-blob': ^12.26.0 + '@capacitor/preferences': ^6 || ^7 || ^8 + '@deno/kv': '>=0.9.0' + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 + '@planetscale/database': ^1.19.0 + '@upstash/redis': ^1.34.3 + '@vercel/blob': '>=0.27.1' + '@vercel/functions': ^2.2.12 || ^3.0.0 + '@vercel/kv': ^1 || ^2 || ^3 + aws4fetch: ^1.0.20 + db0: '>=0.2.1' + idb-keyval: ^6.2.1 + ioredis: ^5.4.2 + uploadthing: ^7.4.4 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@deno/kv': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/blob': + optional: true + '@vercel/functions': + optional: true + '@vercel/kv': + optional: true + aws4fetch: + optional: true + db0: + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + uploadthing: + optional: true + + untun@0.1.3: + resolution: {integrity: sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ==} + hasBin: true + + untyped@2.0.0: + resolution: {integrity: sha512-nwNCjxJTjNuLCgFr42fEak5OcLuB3ecca+9ksPFNvtfYSLpjf+iJqSIaSnIile6ZPbKYxI5k2AfXqeopGudK/g==} + hasBin: true + + unwasm@0.5.3: + resolution: {integrity: sha512-keBgTSfp3r6+s9ZcSma+0chwxQdmLbB5+dAD9vjtB21UTMYuKAxHXCU1K2CbCtnP09EaWeRvACnXk0EJtUx+hw==} + + upath@1.2.0: + resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} + engines: {node: '>=4'} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + update-notifier@7.3.1: + resolution: {integrity: sha512-+dwUY4L35XFYEzE+OAL3sarJdUioVovq+8f7lcIJ7wnmnYQV5UD1Y/lcwaMSyaQ6Bj3JMj1XSTjZbNLHn/19yA==} + engines: {node: '>=18'} + + uqr@0.1.2: + resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url-toolkit@2.2.5: + resolution: {integrity: sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + validator@13.15.26: + resolution: {integrity: sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==} + engines: {node: '>= 0.10'} + + vdirs@0.1.8: + resolution: {integrity: sha512-H9V1zGRLQZg9b+GdMk8MXDN2Lva0zx72MPahDKc30v+DtwKjfyOSXWRIX4t2mhDubM1H09gPhWeth/BJWPHGUw==} + peerDependencies: + vue: ^3.5.27 + + vee-validate@4.15.1: + resolution: {integrity: sha512-DkFsiTwEKau8VIxyZBGdO6tOudD+QoUBPuHj3e6QFqmbfCRj1ArmYWue9lEp6jLSWBIw4XPlDLjFIZNLdRAMSg==} + peerDependencies: + vue: ^3.5.27 + + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + video.js@7.21.7: + resolution: {integrity: sha512-T2s3WFAht7Zjr2OSJamND9x9Dn2O+Z5WuHGdh8jI5SYh5mkMdVTQ7vSRmA5PYpjXJ2ycch6jpMjkJEIEU2xxqw==} + + videojs-font@3.2.0: + resolution: {integrity: sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==} + + videojs-vtt.js@0.15.5: + resolution: {integrity: sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==} + + vite-dev-rpc@1.1.0: + resolution: {integrity: sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0 + + vite-hot-client@2.1.0: + resolution: {integrity: sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==} + peerDependencies: + vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite-plugin-compression@0.5.1: + resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==} + peerDependencies: + vite: '>=2.0.0' + + vite-plugin-dts@4.5.4: + resolution: {integrity: sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg==} + peerDependencies: + typescript: '*' + vite: '*' + peerDependenciesMeta: + vite: + optional: true + + vite-plugin-html@3.2.2: + resolution: {integrity: sha512-vb9C9kcdzcIo/Oc3CLZVS03dL5pDlOFuhGlZYDCJ840BhWl/0nGeZWf3Qy7NlOayscY4Cm/QRgULCQkEZige5Q==} + peerDependencies: + vite: '>=2.0.0' + + vite-plugin-inspect@11.3.3: + resolution: {integrity: sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==} + engines: {node: '>=14'} + peerDependencies: + '@nuxt/kit': '*' + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + + vite-plugin-lazy-import@1.0.7: + resolution: {integrity: sha512-mE6oAObOb4wqso4AoUGi9cLjdR+4vay1RCaKJvziBuFPlziZl7J0aw2hsqRTokLVRx3bli0a0VyjMOwsNDv58A==} + + vite-plugin-pwa@1.2.0: + resolution: {integrity: sha512-a2xld+SJshT9Lgcv8Ji4+srFJL4k/1bVbd1x06JIkvecpQkwkvCncD1+gSzcdm3s+owWLpMJerG3aN5jupJEVw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@vite-pwa/assets-generator': ^1.0.0 + vite: ^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + workbox-build: ^7.4.0 + workbox-window: ^7.4.0 + peerDependenciesMeta: + '@vite-pwa/assets-generator': + optional: true + + vite-plugin-vue-devtools@8.0.6: + resolution: {integrity: sha512-IiTCIJDb1ZliOT8fPbYXllyfgARzz1+R1r8RN9ScGIDzAB6o8bDME1a9JjrfdSJibL7i8DIPQH+pGv0U7haBeA==} + engines: {node: '>=v14.21.3'} + peerDependencies: + vite: ^6.0.0 || ^7.0.0-0 + + vite-plugin-vue-inspector@5.3.2: + resolution: {integrity: sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==} + peerDependencies: + vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: ^2.6.1 + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitepress-plugin-group-icons@1.7.1: + resolution: {integrity: sha512-3ZPcIqwHNBg1btrOOSecOqv8yJxHdu3W2ugxE5LusclDF005LAm60URMEmBQrkgl4JvM32AqJirqghK6lGIk8g==} + peerDependencies: + vite: '>=3' + peerDependenciesMeta: + vite: + optional: true + + vitepress@1.6.4: + resolution: {integrity: sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==} + hasBin: true + peerDependencies: + markdown-it-mathjax3: ^4 + postcss: ^8 + peerDependenciesMeta: + markdown-it-mathjax3: + optional: true + postcss: + optional: true + + vitest@3.2.4: + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + vooks@0.2.12: + resolution: {integrity: sha512-iox0I3RZzxtKlcgYaStQYKEzWWGAduMmq+jS7OrNdQo1FgGfPMubGL3uGHOU9n97NIvfFDBGnpSvkWyb/NSn/Q==} + peerDependencies: + vue: ^3.5.27 + + vscode-languageserver-textdocument@1.0.12: + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-component-type-helpers@2.2.12: + resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==} + + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.5.27 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-dompurify-html@5.3.0: + resolution: {integrity: sha512-HJQGBHbfSPcb6Mu97McdKbX7TqRHZa6Ji8OCpCNyuHca5QvQZ8IiuwghFPSO8OkSQfqXPNPKFMZdCOrnGGmOSQ==} + peerDependencies: + vue: ^3.5.27 + + vue-eslint-parser@10.2.0: + resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + vue-i18n@11.2.8: + resolution: {integrity: sha512-vJ123v/PXCZntd6Qj5Jumy7UBmIuE92VrtdX+AXr+1WzdBHojiBxnAxdfctUFL+/JIN+VQH4BhsfTtiGsvVObg==} + engines: {node: '>= 16'} + peerDependencies: + vue: ^3.5.27 + + vue-json-viewer@3.0.4: + resolution: {integrity: sha512-pnC080rTub6YjccthVSNQod2z9Sl5IUUq46srXtn6rxwhW8QM4rlYn+CTSLFKXWfw+N3xv77Cioxw7B4XUKIbQ==} + peerDependencies: + vue: ^3.5.27 + + vue-router@4.6.4: + resolution: {integrity: sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==} + peerDependencies: + vue: ^3.5.27 + + vue-tippy@6.7.1: + resolution: {integrity: sha512-gdHbBV5/Vc8gH87hQHLA7TN1K4BlLco3MAPrTb70ZYGXxx+55rAU4a4mt0fIoP+gB3etu1khUZ6c29Br1n0CiA==} + peerDependencies: + vue: ^3.5.27 + + vue-tsc@3.2.4: + resolution: {integrity: sha512-xj3YCvSLNDKt1iF9OcImWHhmYcihVu9p4b9s4PGR/qp6yhW+tZJaypGxHScRyOrdnHvaOeF+YkZOdKwbgGvp5g==} + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue-types@3.0.2: + resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==} + engines: {node: '>=10.15.0'} + peerDependencies: + vue: ^3.5.27 + + vue3-print-nb@0.1.4: + resolution: {integrity: sha512-LExI7viEzplR6ZKQ2b+V4U0cwGYbVD4fut/XHvk3UPGlT5CcvIGs6VlwGp107aKgk6P8Pgx4rco3Rehv2lti3A==} + + vue3-signature@0.2.4: + resolution: {integrity: sha512-XFwwFVK9OG3F085pKIq2SlNVqx32WdFH+TXbGEWc5FfEKpx8oMmZuAwZZ50K/pH2FgmJSE8IRwU9DDhrLpd6iA==} + peerDependencies: + vue: ^3.5.27 + + vue@3.5.28: + resolution: {integrity: sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + vuedraggable@4.1.0: + resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==} + peerDependencies: + vue: ^3.5.27 + + vueuc@0.4.65: + resolution: {integrity: sha512-lXuMl+8gsBmruudfxnMF9HW4be8rFziylXFu1VHVNbLVhRTXXV4njvpRuJapD/8q+oFEMSfQMH16E/85VoWRyQ==} + peerDependencies: + vue: ^3.5.27 + + vxe-pc-ui@4.12.36: + resolution: {integrity: sha512-XYTC8aQ26gXY8OZOaiB3zPCf4R29zqUqhMu8Ah7YtjPLrJSE+U5gel07vnNt7UQ78o13QBCehaf2TVlbH3cAPg==} + + vxe-table@4.17.48: + resolution: {integrity: sha512-hd2j3FMA5vu3Qc3wyCavwMdsaT5uEq1GCux3eV5VKPkd/MoSdh9DIyMzmqDKh/0QnpVPsoQuIZPJi/govnw2Iw==} + + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + + wangeditor@4.7.15: + resolution: {integrity: sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg==} + + warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + + watermark-js-plus@1.6.3: + resolution: {integrity: sha512-iCLOGf70KacIwjGF9MDViYxQcRiVwOH7l42qDHLeE2HeUsQD1EQuUC9cKRG/4SErTUmdqV3yf5WnKk2dRARHPQ==} + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + + when-exit@2.1.5: + resolution: {integrity: sha512-VGkKJ564kzt6Ms1dbgPP/yuIoQCrsFAnRbptpC5wOEsDaNsbCB2bnfnaA8i/vRs5tjUSEOtIuvl9/MyVsvQZCg==} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + + which-typed-array@1.1.20: + resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + engines: {node: '>= 0.4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + widest-line@5.0.0: + resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} + engines: {node: '>=18'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + workbox-background-sync@7.4.0: + resolution: {integrity: sha512-8CB9OxKAgKZKyNMwfGZ1XESx89GryWTfI+V5yEj8sHjFH8MFelUwYXEyldEK6M6oKMmn807GoJFUEA1sC4XS9w==} + + workbox-broadcast-update@7.4.0: + resolution: {integrity: sha512-+eZQwoktlvo62cI0b+QBr40v5XjighxPq3Fzo9AWMiAosmpG5gxRHgTbGGhaJv/q/MFVxwFNGh/UwHZ/8K88lA==} + + workbox-build@7.4.0: + resolution: {integrity: sha512-Ntk1pWb0caOFIvwz/hfgrov/OJ45wPEhI5PbTywQcYjyZiVhT3UrwwUPl6TRYbTm4moaFYithYnl1lvZ8UjxcA==} + engines: {node: '>=20.0.0'} + + workbox-cacheable-response@7.4.0: + resolution: {integrity: sha512-0Fb8795zg/x23ISFkAc7lbWes6vbw34DGFIMw31cwuHPgDEC/5EYm6m/ZkylLX0EnEbbOyOCLjKgFS/Z5g0HeQ==} + + workbox-core@7.4.0: + resolution: {integrity: sha512-6BMfd8tYEnN4baG4emG9U0hdXM4gGuDU3ectXuVHnj71vwxTFI7WOpQJC4siTOlVtGqCUtj0ZQNsrvi6kZZTAQ==} + + workbox-expiration@7.4.0: + resolution: {integrity: sha512-V50p4BxYhtA80eOvulu8xVfPBgZbkxJ1Jr8UUn0rvqjGhLDqKNtfrDfjJKnLz2U8fO2xGQJTx/SKXNTzHOjnHw==} + + workbox-google-analytics@7.4.0: + resolution: {integrity: sha512-MVPXQslRF6YHkzGoFw1A4GIB8GrKym/A5+jYDUSL+AeJw4ytQGrozYdiZqUW1TPQHW8isBCBtyFJergUXyNoWQ==} + + workbox-navigation-preload@7.4.0: + resolution: {integrity: sha512-etzftSgdQfjMcfPgbfaZCfM2QuR1P+4o8uCA2s4rf3chtKTq/Om7g/qvEOcZkG6v7JZOSOxVYQiOu6PbAZgU6w==} + + workbox-precaching@7.4.0: + resolution: {integrity: sha512-VQs37T6jDqf1rTxUJZXRl3yjZMf5JX/vDPhmx2CPgDDKXATzEoqyRqhYnRoxl6Kr0rqaQlp32i9rtG5zTzIlNg==} + + workbox-range-requests@7.4.0: + resolution: {integrity: sha512-3Vq854ZNuP6Y0KZOQWLaLC9FfM7ZaE+iuQl4VhADXybwzr4z/sMmnLgTeUZLq5PaDlcJBxYXQ3U91V7dwAIfvw==} + + workbox-recipes@7.4.0: + resolution: {integrity: sha512-kOkWvsAn4H8GvAkwfJTbwINdv4voFoiE9hbezgB1sb/0NLyTG4rE7l6LvS8lLk5QIRIto+DjXLuAuG3Vmt3cxQ==} + + workbox-routing@7.4.0: + resolution: {integrity: sha512-C/ooj5uBWYAhAqwmU8HYQJdOjjDKBp9MzTQ+otpMmd+q0eF59K+NuXUek34wbL0RFrIXe/KKT+tUWcZcBqxbHQ==} + + workbox-strategies@7.4.0: + resolution: {integrity: sha512-T4hVqIi5A4mHi92+5EppMX3cLaVywDp8nsyUgJhOZxcfSV/eQofcOA6/EMo5rnTNmNTpw0rUgjAI6LaVullPpg==} + + workbox-streams@7.4.0: + resolution: {integrity: sha512-QHPBQrey7hQbnTs5GrEVoWz7RhHJXnPT+12qqWM378orDMo5VMJLCkCM1cnCk+8Eq92lccx/VgRZ7WAzZWbSLg==} + + workbox-sw@7.4.0: + resolution: {integrity: sha512-ltU+Kr3qWR6BtbdlMnCjobZKzeV1hN+S6UvDywBrwM19TTyqA03X66dzw1tEIdJvQ4lYKkBFox6IAEhoSEZ8Xw==} + + workbox-window@7.4.0: + resolution: {integrity: sha512-/bIYdBLAVsNR3v7gYGaV4pQW3M3kEPx5E8vDxGvxo6khTrGtSSCS7QiFKv9ogzBgZiy0OXLP9zO28U/1nF1mfw==} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + + xdg-basedir@5.1.0: + resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} + engines: {node: '>=12'} + + xe-utils@3.9.1: + resolution: {integrity: sha512-Ujk5UmoH6Iaqhgz3oGwfCXVcMdUJKlXnfvLABdnMyseMG0eHsX2mcCvLd/8sGlIXtfwsprI9bW7vgcVognLmqQ==} + + xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + + yaml-eslint-parser@1.3.2: + resolution: {integrity: sha512-odxVsHAkZYYglR30aPYRY4nUGJnoJ2y1ww2HDvZALo0BDETv9kWbi16J52eHs+PWRNmF4ub6nZqfVOeesOvntg==} + engines: {node: ^14.17.0 || >=16.0.0} + + yaml-eslint-parser@2.0.0: + resolution: {integrity: sha512-h0uDm97wvT2bokfwwTmY6kJ1hp6YDFL0nRHwNKz8s/VD1FH/vvZjAKoMUE+un0eaYBSG7/c6h+lJTP+31tjgTw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yaml@2.8.2: + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.2.2: + resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} + engines: {node: '>=12.20'} + + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + engines: {node: '>=18'} + + youch-core@0.3.3: + resolution: {integrity: sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==} + + youch@4.1.0-beta.13: + resolution: {integrity: sha512-3+AG1Xvt+R7M7PSDudhbfbwiyveW6B8PLBIwTyEC598biEYIjHhC89i6DBEvR0EZUjGY3uGSnC429HpIa2Z09g==} + + zeebe-bpmn-moddle@1.12.0: + resolution: {integrity: sha512-wYKfgdV5suCNx4IVaq0qOjHRxSQ5XOkxfwC8EBHuGCtmEVk8zv1VRg0opV0kVQe89jvRH3iF3Yl/DoB6qiCV5Q==} + + zimmerframe@1.1.4: + resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + + zip-stream@6.0.1: + resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} + engines: {node: '>= 14'} + + zod-defaults@0.1.3: + resolution: {integrity: sha512-Cp4UjuVfXqwaOx8A5LlM0IRBZs8B7AXgF+XOZWF8CjMDhsY/Jki+y7VS4adVtQj9NNSsAPwylUlJp9INuxPEnA==} + peerDependencies: + zod: ^3.23.8 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zrender@6.0.0: + resolution: {integrity: sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + + zx@8.8.5: + resolution: {integrity: sha512-SNgDF5L0gfN7FwVOdEFguY3orU5AkfFZm9B5YSHog/UDHv+lvmd82ZAsOenOkQixigwH2+yyH198AwNdKhj+RA==} + engines: {node: '>= 12.17.0'} + hasBin: true + +snapshots: + + '@algolia/abtesting@1.14.0': + dependencies: + '@algolia/client-common': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + '@algolia/autocomplete-core@1.17.7(@algolia/client-search@5.48.0)(algoliasearch@5.48.0)(search-insights@2.17.3)': + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.17.7(@algolia/client-search@5.48.0)(algoliasearch@5.48.0)(search-insights@2.17.3) + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.48.0)(algoliasearch@5.48.0) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + - search-insights + + '@algolia/autocomplete-plugin-algolia-insights@1.17.7(@algolia/client-search@5.48.0)(algoliasearch@5.48.0)(search-insights@2.17.3)': + dependencies: + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.48.0)(algoliasearch@5.48.0) + search-insights: 2.17.3 + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + + '@algolia/autocomplete-preset-algolia@1.17.7(@algolia/client-search@5.48.0)(algoliasearch@5.48.0)': + dependencies: + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.48.0)(algoliasearch@5.48.0) + '@algolia/client-search': 5.48.0 + algoliasearch: 5.48.0 + + '@algolia/autocomplete-shared@1.17.7(@algolia/client-search@5.48.0)(algoliasearch@5.48.0)': + dependencies: + '@algolia/client-search': 5.48.0 + algoliasearch: 5.48.0 + + '@algolia/client-abtesting@5.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + '@algolia/client-analytics@5.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + '@algolia/client-common@5.48.0': {} + + '@algolia/client-insights@5.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + '@algolia/client-personalization@5.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + '@algolia/client-query-suggestions@5.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + '@algolia/client-search@5.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + '@algolia/ingestion@1.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + '@algolia/monitoring@1.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + '@algolia/recommend@5.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + '@algolia/requester-browser-xhr@5.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + + '@algolia/requester-fetch@5.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + + '@algolia/requester-node-http@5.48.0': + dependencies: + '@algolia/client-common': 5.48.0 + + '@alloc/quick-lru@5.2.0': {} + + '@ant-design/colors@6.0.0': + dependencies: + '@ctrl/tinycolor': 4.2.0 + + '@ant-design/colors@7.2.1': + dependencies: + '@ant-design/fast-color': 2.0.6 + + '@ant-design/fast-color@2.0.6': + dependencies: + '@babel/runtime': 7.28.6 + + '@ant-design/fast-color@3.0.1': {} + + '@ant-design/icons-svg@4.4.2': {} + + '@ant-design/icons-vue@7.0.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-svg': 4.4.2 + vue: 3.5.28(typescript@5.9.3) + + '@antdv-next/cssinjs@1.0.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@emotion/hash': 0.8.0 + '@emotion/unitless': 0.7.5 + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + csstype: 3.2.3 + defu: 6.1.4 + stylis: 4.3.6 + vue: 3.5.28(typescript@5.9.3) + + '@antdv-next/icons@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@ant-design/colors': 7.2.1 + '@ant-design/icons-svg': 4.4.2 + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + es-toolkit: 1.43.0 + vue: 3.5.28(typescript@5.9.3) + + '@antfu/install-pkg@1.1.0': + dependencies: + package-manager-detector: 1.6.0 + tinyexec: 1.0.2 + + '@apideck/better-ajv-errors@0.3.6(ajv@8.17.1)': + dependencies: + ajv: 8.17.1 + json-schema: 0.4.0 + jsonpointer: 5.0.1 + leven: 3.1.0 + + '@ast-grep/napi-darwin-arm64@0.39.9': + optional: true + + '@ast-grep/napi-darwin-x64@0.39.9': + optional: true + + '@ast-grep/napi-linux-arm64-gnu@0.39.9': + optional: true + + '@ast-grep/napi-linux-arm64-musl@0.39.9': + optional: true + + '@ast-grep/napi-linux-x64-gnu@0.39.9': + optional: true + + '@ast-grep/napi-linux-x64-musl@0.39.9': + optional: true + + '@ast-grep/napi-win32-arm64-msvc@0.39.9': + optional: true + + '@ast-grep/napi-win32-ia32-msvc@0.39.9': + optional: true + + '@ast-grep/napi-win32-x64-msvc@0.39.9': + optional: true + + '@ast-grep/napi@0.39.9': + optionalDependencies: + '@ast-grep/napi-darwin-arm64': 0.39.9 + '@ast-grep/napi-darwin-x64': 0.39.9 + '@ast-grep/napi-linux-arm64-gnu': 0.39.9 + '@ast-grep/napi-linux-arm64-musl': 0.39.9 + '@ast-grep/napi-linux-x64-gnu': 0.39.9 + '@ast-grep/napi-linux-x64-musl': 0.39.9 + '@ast-grep/napi-win32-arm64-msvc': 0.39.9 + '@ast-grep/napi-win32-ia32-msvc': 0.39.9 + '@ast-grep/napi-win32-x64-msvc': 0.39.9 + + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.0': {} + + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.28.6 + '@babel/parser': 7.29.0 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.29.0 + + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.29.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + regexpu-core: 6.4.0 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + debug: 4.4.3 + lodash.debounce: 4.0.8 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.28.5': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.29.0 + + '@babel/helper-plugin-utils@7.28.6': {} + + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-wrap-function': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helper-wrap-function@7.28.6': + dependencies: + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.28.6': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + + '@babel/parser@7.29.0': + dependencies: + '@babel/types': 7.29.0 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-decorators@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-decorators': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + + '@babel/plugin-syntax-decorators@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-globals': 7.28.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/template': 7.28.6 + + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/preset-env@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) + '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.0) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-explicit-resource-management': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-systemjs': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.29.0) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.0) + babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0) + babel-plugin-polyfill-corejs3: 0.14.0(@babel/core@7.29.0) + babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0) + core-js-compat: 3.48.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/types': 7.29.0 + esutils: 2.0.3 + + '@babel/preset-typescript@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/runtime-corejs3@7.29.0': + dependencies: + core-js-pure: 3.48.0 + + '@babel/runtime@7.28.6': {} + + '@babel/template@7.28.6': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.0 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@bpmn-io/cm-theme@0.1.0-alpha.2': + dependencies: + '@codemirror/language': 6.12.1 + '@codemirror/view': 6.39.13 + '@lezer/highlight': 1.2.3 + + '@bpmn-io/diagram-js-ui@0.2.3': + dependencies: + htm: 3.1.1 + preact: 10.28.3 + + '@bpmn-io/extract-process-variables@0.8.0': + dependencies: + min-dash: 4.2.3 + + '@bpmn-io/feel-editor@2.4.0': + dependencies: + '@bpmn-io/feel-lint': 3.1.0 + '@bpmn-io/lang-feel': 3.0.0 + '@camunda/feel-builtins': 0.3.0 + '@codemirror/autocomplete': 6.20.0 + '@codemirror/commands': 6.10.2 + '@codemirror/language': 6.12.1 + '@codemirror/lint': 6.9.3 + '@codemirror/state': 6.5.4 + '@codemirror/view': 6.39.13 + '@lezer/highlight': 1.2.3 + min-dom: 5.2.0 + mitt: 3.0.1 + + '@bpmn-io/feel-lint@3.1.0': + dependencies: + '@bpmn-io/lezer-feel': 2.2.1 + '@codemirror/language': 6.12.1 + + '@bpmn-io/feelin@6.1.0': + dependencies: + '@bpmn-io/lezer-feel': 2.2.1 + '@lezer/common': 1.5.1 + luxon: 3.7.2 + min-dash: 5.0.0 + + '@bpmn-io/lang-feel@3.0.0': + dependencies: + '@bpmn-io/lezer-feel': 2.2.1 + '@codemirror/autocomplete': 6.20.0 + '@codemirror/language': 6.12.1 + '@lezer/common': 1.5.1 + + '@bpmn-io/lezer-feel@2.2.1': + dependencies: + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.8 + min-dash: 5.0.0 + + '@bpmn-io/properties-panel@3.38.0': + dependencies: + '@bpmn-io/feel-editor': 2.4.0 + '@carbon/icons': 11.74.0 + '@codemirror/view': 6.39.13 + classnames: 2.5.1 + feelers: 1.5.1 + focus-trap: 7.8.0 + min-dash: 5.0.0 + min-dom: 5.2.0 + + '@cacheable/memory@2.0.7': + dependencies: + '@cacheable/utils': 2.3.4 + '@keyv/bigmap': 1.3.1(keyv@5.6.0) + hookified: 1.15.1 + keyv: 5.6.0 + + '@cacheable/utils@2.3.4': + dependencies: + hashery: 1.4.0 + keyv: 5.6.0 + + '@camunda/feel-builtins@0.3.0': {} + + '@carbon/icons@11.74.0': + dependencies: + '@ibm/telemetry-js': 1.11.0 + + '@changesets/apply-release-plan@7.0.14': + dependencies: + '@changesets/config': 3.1.2 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.7.4 + + '@changesets/assemble-release-plan@6.0.9': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.7.4 + + '@changesets/changelog-git@0.2.1': + dependencies: + '@changesets/types': 6.1.0 + + '@changesets/changelog-github@0.5.2': + dependencies: + '@changesets/get-github-info': 0.7.0 + '@changesets/types': 6.1.0 + dotenv: 8.6.0 + transitivePeerDependencies: + - encoding + + '@changesets/cli@2.29.8(@types/node@24.10.13)': + dependencies: + '@changesets/apply-release-plan': 7.0.14 + '@changesets/assemble-release-plan': 6.0.9 + '@changesets/changelog-git': 0.2.1 + '@changesets/config': 3.1.2 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/get-release-plan': 4.0.14 + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.6 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@changesets/write': 0.4.0 + '@inquirer/external-editor': 1.0.3(@types/node@24.10.13) + '@manypkg/get-packages': 1.1.3 + ansi-colors: 4.1.3 + ci-info: 3.9.0 + enquirer: 2.4.1 + fs-extra: 7.0.1 + mri: 1.2.0 + p-limit: 2.3.0 + package-manager-detector: 0.2.11 + picocolors: 1.1.1 + resolve-from: 5.0.0 + semver: 7.7.4 + spawndamnit: 3.0.1 + term-size: 2.2.1 + transitivePeerDependencies: + - '@types/node' + + '@changesets/config@3.1.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/logger': 0.1.1 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.8 + + '@changesets/errors@0.2.0': + dependencies: + extendable-error: 0.1.7 + + '@changesets/get-dependents-graph@2.1.3': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + picocolors: 1.1.1 + semver: 7.7.4 + + '@changesets/get-github-info@0.7.0': + dependencies: + dataloader: 1.4.0 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + '@changesets/get-release-plan@4.0.14': + dependencies: + '@changesets/assemble-release-plan': 6.0.9 + '@changesets/config': 3.1.2 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.6 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/get-version-range-type@0.4.0': {} + + '@changesets/git@3.0.4': + dependencies: + '@changesets/errors': 0.2.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.8 + spawndamnit: 3.0.1 + + '@changesets/logger@0.1.1': + dependencies: + picocolors: 1.1.1 + + '@changesets/parse@0.4.2': + dependencies: + '@changesets/types': 6.1.0 + js-yaml: 4.1.1 + + '@changesets/pre@2.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.6': + dependencies: + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.2 + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.2': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.1.0': {} + + '@changesets/write@0.4.0': + dependencies: + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + human-id: 4.1.3 + prettier: 2.8.8 + + '@clack/core@0.5.0': + dependencies: + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@clack/prompts@0.11.0': + dependencies: + '@clack/core': 0.5.0 + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@cloudflare/kv-asset-handler@0.4.2': {} + + '@codemirror/autocomplete@6.20.0': + dependencies: + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.4 + '@codemirror/view': 6.39.13 + '@lezer/common': 1.5.1 + + '@codemirror/commands@6.10.2': + dependencies: + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.4 + '@codemirror/view': 6.39.13 + '@lezer/common': 1.5.1 + + '@codemirror/language@6.12.1': + dependencies: + '@codemirror/state': 6.5.4 + '@codemirror/view': 6.39.13 + '@lezer/common': 1.5.1 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.8 + style-mod: 4.1.3 + + '@codemirror/lint@6.9.3': + dependencies: + '@codemirror/state': 6.5.4 + '@codemirror/view': 6.39.13 + crelt: 1.0.6 + + '@codemirror/state@6.5.4': + dependencies: + '@marijn/find-cluster-break': 1.0.2 + + '@codemirror/view@6.39.13': + dependencies: + '@codemirror/state': 6.5.4 + crelt: 1.0.6 + style-mod: 4.1.3 + w3c-keyname: 2.2.8 + + '@commitlint/cli@19.8.1(@types/node@24.10.13)(typescript@5.9.3)': + dependencies: + '@commitlint/format': 19.8.1 + '@commitlint/lint': 19.8.1 + '@commitlint/load': 19.8.1(@types/node@24.10.13)(typescript@5.9.3) + '@commitlint/read': 19.8.1 + '@commitlint/types': 19.8.1 + tinyexec: 1.0.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/config-conventional@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + conventional-changelog-conventionalcommits: 7.0.2 + + '@commitlint/config-validator@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + ajv: 8.17.1 + + '@commitlint/ensure@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 + + '@commitlint/execute-rule@19.8.1': {} + + '@commitlint/format@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + chalk: 5.6.2 + + '@commitlint/is-ignored@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + semver: 7.7.4 + + '@commitlint/lint@19.8.1': + dependencies: + '@commitlint/is-ignored': 19.8.1 + '@commitlint/parse': 19.8.1 + '@commitlint/rules': 19.8.1 + '@commitlint/types': 19.8.1 + + '@commitlint/load@19.8.1(@types/node@24.10.13)(typescript@5.9.3)': + dependencies: + '@commitlint/config-validator': 19.8.1 + '@commitlint/execute-rule': 19.8.1 + '@commitlint/resolve-extends': 19.8.1 + '@commitlint/types': 19.8.1 + chalk: 5.6.2 + cosmiconfig: 9.0.0(typescript@5.9.3) + cosmiconfig-typescript-loader: 6.2.0(@types/node@24.10.13)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/message@19.8.1': {} + + '@commitlint/parse@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 + + '@commitlint/read@19.8.1': + dependencies: + '@commitlint/top-level': 19.8.1 + '@commitlint/types': 19.8.1 + git-raw-commits: 4.0.0 + minimist: 1.2.8 + tinyexec: 1.0.2 + + '@commitlint/resolve-extends@19.8.1': + dependencies: + '@commitlint/config-validator': 19.8.1 + '@commitlint/types': 19.8.1 + global-directory: 4.0.1 + import-meta-resolve: 4.2.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + + '@commitlint/rules@19.8.1': + dependencies: + '@commitlint/ensure': 19.8.1 + '@commitlint/message': 19.8.1 + '@commitlint/to-lines': 19.8.1 + '@commitlint/types': 19.8.1 + + '@commitlint/to-lines@19.8.1': {} + + '@commitlint/top-level@19.8.1': + dependencies: + find-up: 7.0.0 + + '@commitlint/types@19.8.1': + dependencies: + '@types/conventional-commits-parser': 5.0.2 + chalk: 5.6.2 + + '@cspell/cspell-bundled-dicts@9.6.4': + dependencies: + '@cspell/dict-ada': 4.1.1 + '@cspell/dict-al': 1.1.1 + '@cspell/dict-aws': 4.0.17 + '@cspell/dict-bash': 4.2.2 + '@cspell/dict-companies': 3.2.10 + '@cspell/dict-cpp': 7.0.2 + '@cspell/dict-cryptocurrencies': 5.0.5 + '@cspell/dict-csharp': 4.0.8 + '@cspell/dict-css': 4.0.19 + '@cspell/dict-dart': 2.3.2 + '@cspell/dict-data-science': 2.0.13 + '@cspell/dict-django': 4.1.6 + '@cspell/dict-docker': 1.1.17 + '@cspell/dict-dotnet': 5.0.11 + '@cspell/dict-elixir': 4.0.8 + '@cspell/dict-en-common-misspellings': 2.1.12 + '@cspell/dict-en-gb-mit': 3.1.18 + '@cspell/dict-en_us': 4.4.29 + '@cspell/dict-filetypes': 3.0.15 + '@cspell/dict-flutter': 1.1.1 + '@cspell/dict-fonts': 4.0.5 + '@cspell/dict-fsharp': 1.1.1 + '@cspell/dict-fullstack': 3.2.8 + '@cspell/dict-gaming-terms': 1.1.2 + '@cspell/dict-git': 3.1.0 + '@cspell/dict-golang': 6.0.26 + '@cspell/dict-google': 1.0.9 + '@cspell/dict-haskell': 4.0.6 + '@cspell/dict-html': 4.0.14 + '@cspell/dict-html-symbol-entities': 4.0.5 + '@cspell/dict-java': 5.0.12 + '@cspell/dict-julia': 1.1.1 + '@cspell/dict-k8s': 1.0.12 + '@cspell/dict-kotlin': 1.1.1 + '@cspell/dict-latex': 5.0.0 + '@cspell/dict-lorem-ipsum': 4.0.5 + '@cspell/dict-lua': 4.0.8 + '@cspell/dict-makefile': 1.0.5 + '@cspell/dict-markdown': 2.0.14(@cspell/dict-css@4.0.19)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.14)(@cspell/dict-typescript@3.2.3) + '@cspell/dict-monkeyc': 1.0.12 + '@cspell/dict-node': 5.0.9 + '@cspell/dict-npm': 5.2.33 + '@cspell/dict-php': 4.1.1 + '@cspell/dict-powershell': 5.0.15 + '@cspell/dict-public-licenses': 2.0.15 + '@cspell/dict-python': 4.2.25 + '@cspell/dict-r': 2.1.1 + '@cspell/dict-ruby': 5.1.0 + '@cspell/dict-rust': 4.1.2 + '@cspell/dict-scala': 5.0.9 + '@cspell/dict-shell': 1.1.2 + '@cspell/dict-software-terms': 5.1.20 + '@cspell/dict-sql': 2.2.1 + '@cspell/dict-svelte': 1.0.7 + '@cspell/dict-swift': 2.0.6 + '@cspell/dict-terraform': 1.1.3 + '@cspell/dict-typescript': 3.2.3 + '@cspell/dict-vue': 3.0.5 + '@cspell/dict-zig': 1.0.0 + + '@cspell/cspell-json-reporter@9.6.4': + dependencies: + '@cspell/cspell-types': 9.6.4 + + '@cspell/cspell-performance-monitor@9.6.4': {} + + '@cspell/cspell-pipe@9.6.4': {} + + '@cspell/cspell-resolver@9.6.4': + dependencies: + global-directory: 4.0.1 + + '@cspell/cspell-service-bus@9.6.4': {} + + '@cspell/cspell-types@9.6.4': {} + + '@cspell/cspell-worker@9.6.4': + dependencies: + cspell-lib: 9.6.4 + + '@cspell/dict-ada@4.1.1': {} + + '@cspell/dict-al@1.1.1': {} + + '@cspell/dict-aws@4.0.17': {} + + '@cspell/dict-bash@4.2.2': + dependencies: + '@cspell/dict-shell': 1.1.2 + + '@cspell/dict-companies@3.2.10': {} + + '@cspell/dict-cpp@7.0.2': {} + + '@cspell/dict-cryptocurrencies@5.0.5': {} + + '@cspell/dict-csharp@4.0.8': {} + + '@cspell/dict-css@4.0.19': {} + + '@cspell/dict-dart@2.3.2': {} + + '@cspell/dict-data-science@2.0.13': {} + + '@cspell/dict-django@4.1.6': {} + + '@cspell/dict-docker@1.1.17': {} + + '@cspell/dict-dotnet@5.0.11': {} + + '@cspell/dict-elixir@4.0.8': {} + + '@cspell/dict-en-common-misspellings@2.1.12': {} + + '@cspell/dict-en-gb-mit@3.1.18': {} + + '@cspell/dict-en_us@4.4.29': {} + + '@cspell/dict-filetypes@3.0.15': {} + + '@cspell/dict-flutter@1.1.1': {} + + '@cspell/dict-fonts@4.0.5': {} + + '@cspell/dict-fsharp@1.1.1': {} + + '@cspell/dict-fullstack@3.2.8': {} + + '@cspell/dict-gaming-terms@1.1.2': {} + + '@cspell/dict-git@3.1.0': {} + + '@cspell/dict-golang@6.0.26': {} + + '@cspell/dict-google@1.0.9': {} + + '@cspell/dict-haskell@4.0.6': {} + + '@cspell/dict-html-symbol-entities@4.0.5': {} + + '@cspell/dict-html@4.0.14': {} + + '@cspell/dict-java@5.0.12': {} + + '@cspell/dict-julia@1.1.1': {} + + '@cspell/dict-k8s@1.0.12': {} + + '@cspell/dict-kotlin@1.1.1': {} + + '@cspell/dict-latex@5.0.0': {} + + '@cspell/dict-lorem-ipsum@4.0.5': {} + + '@cspell/dict-lua@4.0.8': {} + + '@cspell/dict-makefile@1.0.5': {} + + '@cspell/dict-markdown@2.0.14(@cspell/dict-css@4.0.19)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.14)(@cspell/dict-typescript@3.2.3)': + dependencies: + '@cspell/dict-css': 4.0.19 + '@cspell/dict-html': 4.0.14 + '@cspell/dict-html-symbol-entities': 4.0.5 + '@cspell/dict-typescript': 3.2.3 + + '@cspell/dict-monkeyc@1.0.12': {} + + '@cspell/dict-node@5.0.9': {} + + '@cspell/dict-npm@5.2.33': {} + + '@cspell/dict-php@4.1.1': {} + + '@cspell/dict-powershell@5.0.15': {} + + '@cspell/dict-public-licenses@2.0.15': {} + + '@cspell/dict-python@4.2.25': + dependencies: + '@cspell/dict-data-science': 2.0.13 + + '@cspell/dict-r@2.1.1': {} + + '@cspell/dict-ruby@5.1.0': {} + + '@cspell/dict-rust@4.1.2': {} + + '@cspell/dict-scala@5.0.9': {} + + '@cspell/dict-shell@1.1.2': {} + + '@cspell/dict-software-terms@5.1.20': {} + + '@cspell/dict-sql@2.2.1': {} + + '@cspell/dict-svelte@1.0.7': {} + + '@cspell/dict-swift@2.0.6': {} + + '@cspell/dict-terraform@1.1.3': {} + + '@cspell/dict-typescript@3.2.3': {} + + '@cspell/dict-vue@3.0.5': {} + + '@cspell/dict-zig@1.0.0': {} + + '@cspell/dynamic-import@9.6.4': + dependencies: + '@cspell/url': 9.6.4 + import-meta-resolve: 4.2.0 + + '@cspell/filetypes@9.6.4': {} + + '@cspell/rpc@9.6.4': {} + + '@cspell/strong-weak-map@9.6.4': {} + + '@cspell/url@9.6.4': {} + + '@css-render/plugin-bem@0.15.14(css-render@0.15.14)': + dependencies: + css-render: 0.15.14 + + '@css-render/vue3-ssr@0.15.14(vue@3.5.28(typescript@5.9.3))': + dependencies: + vue: 3.5.28(typescript@5.9.3) + + '@csstools/cascade-layer-name-parser@2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-syntax-patches-for-csstree@1.0.27': {} + + '@csstools/css-tokenizer@3.0.4': {} + + '@csstools/media-query-list-parser@4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/postcss-alpha-function@1.0.1(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-cascade-layers@5.0.2(postcss@8.5.6)': + dependencies: + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + '@csstools/postcss-color-function-display-p3-linear@1.0.1(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-color-function@4.0.12(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-color-mix-function@3.0.12(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-color-mix-variadic-function-arguments@1.0.2(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-content-alt-text@2.0.8(postcss@8.5.6)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-contrast-color-function@2.0.12(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-exponential-functions@2.0.9(postcss@8.5.6)': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + + '@csstools/postcss-font-format-keywords@4.0.0(postcss@8.5.6)': + dependencies: + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-gamut-mapping@2.0.11(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + + '@csstools/postcss-gradients-interpolation-method@5.0.12(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-hwb-function@4.0.12(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-ic-unit@4.0.4(postcss@8.5.6)': + dependencies: + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-initial@2.0.1(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + + '@csstools/postcss-is-pseudo-class@5.0.3(postcss@8.5.6)': + dependencies: + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + '@csstools/postcss-light-dark-function@2.0.11(postcss@8.5.6)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-logical-float-and-clear@3.0.0(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + + '@csstools/postcss-logical-overflow@2.0.0(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + + '@csstools/postcss-logical-overscroll-behavior@2.0.0(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + + '@csstools/postcss-logical-resize@3.0.0(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-logical-viewport-units@3.0.4(postcss@8.5.6)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-media-minmax@2.0.9(postcss@8.5.6)': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + postcss: 8.5.6 + + '@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5(postcss@8.5.6)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + postcss: 8.5.6 + + '@csstools/postcss-nested-calc@4.0.0(postcss@8.5.6)': + dependencies: + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-normalize-display-values@4.0.1(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-oklab-function@4.0.12(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-position-area-property@1.0.0(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + + '@csstools/postcss-progressive-custom-properties@4.2.1(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-property-rule-prelude-list@1.0.0(postcss@8.5.6)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + + '@csstools/postcss-random-function@2.0.1(postcss@8.5.6)': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + + '@csstools/postcss-relative-color-syntax@3.0.12(postcss@8.5.6)': + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + '@csstools/postcss-scope-pseudo-class@4.0.1(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + '@csstools/postcss-sign-functions@1.1.4(postcss@8.5.6)': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + + '@csstools/postcss-stepped-value-functions@4.0.9(postcss@8.5.6)': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + + '@csstools/postcss-syntax-descriptor-syntax-production@1.0.1(postcss@8.5.6)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + + '@csstools/postcss-system-ui-font-family@1.0.0(postcss@8.5.6)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + + '@csstools/postcss-text-decoration-shorthand@4.0.3(postcss@8.5.6)': + dependencies: + '@csstools/color-helpers': 5.1.0 + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-trigonometric-functions@4.0.9(postcss@8.5.6)': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + + '@csstools/postcss-unset-value@4.0.0(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + + '@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.1)': + dependencies: + postcss-selector-parser: 7.1.1 + + '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.1)': + dependencies: + postcss-selector-parser: 7.1.1 + + '@csstools/utilities@2.0.0(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + + '@ctrl/tinycolor@4.2.0': {} + + '@docsearch/css@3.8.2': {} + + '@docsearch/js@3.8.2(@algolia/client-search@5.48.0)(search-insights@2.17.3)': + dependencies: + '@docsearch/react': 3.8.2(@algolia/client-search@5.48.0)(search-insights@2.17.3) + preact: 10.28.3 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - react + - react-dom + - search-insights + + '@docsearch/react@3.8.2(@algolia/client-search@5.48.0)(search-insights@2.17.3)': + dependencies: + '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.48.0)(algoliasearch@5.48.0)(search-insights@2.17.3) + '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.48.0)(algoliasearch@5.48.0) + '@docsearch/css': 3.8.2 + algoliasearch: 5.48.0 + optionalDependencies: + search-insights: 2.17.3 + transitivePeerDependencies: + - '@algolia/client-search' + + '@dual-bundle/import-meta-resolve@4.2.1': {} + + '@element-plus/icons-vue@2.3.2(vue@3.5.28(typescript@5.9.3))': + dependencies: + vue: 3.5.28(typescript@5.9.3) + + '@emnapi/core@1.8.1': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.8.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emotion/hash@0.8.0': {} + + '@emotion/hash@0.9.2': {} + + '@emotion/unitless@0.7.5': {} + + '@emotion/unitless@0.8.1': {} + + '@epic-web/invariant@1.0.0': {} + + '@es-joy/jsdoccomment@0.78.0': + dependencies: + '@types/estree': 1.0.8 + '@typescript-eslint/types': 8.55.0 + comment-parser: 1.4.1 + esquery: 1.7.0 + jsdoc-type-pratt-parser: 7.0.0 + + '@es-joy/resolve.exports@1.2.0': {} + + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))': + dependencies: + eslint: 9.39.2(jiti@2.6.1) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.1': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.3': + dependencies: + ajv: 6.12.6 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.2': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@floating-ui/core@1.7.4': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.5': + dependencies: + '@floating-ui/core': 1.7.4 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/utils@0.2.10': {} + + '@floating-ui/vue@1.1.10(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@floating-ui/dom': 1.7.5 + '@floating-ui/utils': 0.2.10 + vue-demi: 0.14.10(vue@3.5.28(typescript@5.9.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@form-create/ant-design-vue@3.2.37(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@form-create/component-antdv-frame': 3.2.31 + '@form-create/component-antdv-group': 3.2.34 + '@form-create/component-antdv-upload': 3.2.31 + '@form-create/component-subform': 3.2.34 + '@form-create/core': 3.2.37(vue@3.5.28(typescript@5.9.3)) + '@form-create/utils': 3.2.31 + vue: 3.5.28(typescript@5.9.3) + + '@form-create/antd-designer@3.4.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@form-create/ant-design-vue': 3.2.37(vue@3.5.28(typescript@5.9.3)) + '@form-create/component-wangeditor': 3.2.14 + '@form-create/utils': 3.2.31 + ant-design-vue: 4.2.6(vue@3.5.28(typescript@5.9.3)) + codemirror: 6.65.7 + js-beautify: 1.15.4 + marked: 17.0.1 + signature_pad: 5.1.3 + vue: 3.5.28(typescript@5.9.3) + vuedraggable: 4.1.0(vue@3.5.28(typescript@5.9.3)) + + '@form-create/component-antdv-frame@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-antdv-group@3.2.34': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-antdv-upload@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-elm-checkbox@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-elm-frame@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-elm-group@3.2.34': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-elm-radio@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-elm-select@3.2.37': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-elm-tree@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-elm-upload@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-naive-checkbox@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-naive-frame@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-naive-group@3.2.34': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-naive-radio@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-naive-upload@3.2.31': + dependencies: + '@form-create/utils': 3.2.31 + + '@form-create/component-subform@3.2.34': {} + + '@form-create/component-wangeditor@3.2.14': + dependencies: + wangeditor: 4.7.15 + + '@form-create/core@3.2.37(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@form-create/utils': 3.2.31 + vue: 3.5.28(typescript@5.9.3) + + '@form-create/designer@3.4.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@form-create/component-wangeditor': 3.2.14 + '@form-create/element-ui': 3.2.37(vue@3.5.28(typescript@5.9.3)) + '@form-create/utils': 3.2.31 + codemirror: 6.65.7 + element-plus: 2.13.2(vue@3.5.28(typescript@5.9.3)) + js-beautify: 1.15.4 + marked: 17.0.1 + signature_pad: 5.1.3 + vue: 3.5.28(typescript@5.9.3) + vuedraggable: 4.1.0(vue@3.5.28(typescript@5.9.3)) + transitivePeerDependencies: + - '@vue/composition-api' + + '@form-create/element-ui@3.2.37(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@form-create/component-elm-checkbox': 3.2.31 + '@form-create/component-elm-frame': 3.2.31 + '@form-create/component-elm-group': 3.2.34 + '@form-create/component-elm-radio': 3.2.31 + '@form-create/component-elm-select': 3.2.37 + '@form-create/component-elm-tree': 3.2.31 + '@form-create/component-elm-upload': 3.2.31 + '@form-create/component-subform': 3.2.34 + '@form-create/core': 3.2.37(vue@3.5.28(typescript@5.9.3)) + '@form-create/utils': 3.2.31 + vue: 3.5.28(typescript@5.9.3) + + '@form-create/naive-ui@3.2.37(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@form-create/component-naive-checkbox': 3.2.31 + '@form-create/component-naive-frame': 3.2.31 + '@form-create/component-naive-group': 3.2.34 + '@form-create/component-naive-radio': 3.2.31 + '@form-create/component-naive-upload': 3.2.31 + '@form-create/component-subform': 3.2.34 + '@form-create/core': 3.2.37(vue@3.5.28(typescript@5.9.3)) + '@form-create/utils': 3.2.31 + vue: 3.5.28(typescript@5.9.3) + + '@form-create/utils@3.2.31': {} + + '@gera2ld/jsx-dom@2.2.2': + dependencies: + '@babel/runtime': 7.28.6 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@ibm/telemetry-js@1.11.0': {} + + '@iconify-json/logos@1.2.10': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify-json/octicon@1.2.20': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify-json/simple-icons@1.2.70': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify-json/vscode-icons@1.2.41': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify/json@2.2.438': + dependencies: + '@iconify/types': 2.0.0 + pathe: 2.0.3 + + '@iconify/tailwind@1.2.0': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify/types@2.0.0': {} + + '@iconify/utils@3.1.0': + dependencies: + '@antfu/install-pkg': 1.1.0 + '@iconify/types': 2.0.0 + mlly: 1.8.0 + + '@iconify/vue@5.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@iconify/types': 2.0.0 + vue: 3.5.28(typescript@5.9.3) + + '@inquirer/external-editor@1.0.3(@types/node@24.10.13)': + dependencies: + chardet: 2.1.1 + iconv-lite: 0.7.2 + optionalDependencies: + '@types/node': 24.10.13 + + '@internationalized/date@3.11.0': + dependencies: + '@swc/helpers': 0.5.18 + + '@internationalized/number@3.6.5': + dependencies: + '@swc/helpers': 0.5.18 + + '@intlify/bundle-utils@10.0.1(vue-i18n@11.2.8(vue@3.5.28(typescript@5.9.3)))': + dependencies: + '@intlify/message-compiler': 11.2.8 + '@intlify/shared': 11.2.8 + acorn: 8.15.0 + escodegen: 2.1.0 + estree-walker: 2.0.2 + jsonc-eslint-parser: 2.4.2 + mlly: 1.8.0 + source-map-js: 1.2.1 + yaml-eslint-parser: 1.3.2 + optionalDependencies: + vue-i18n: 11.2.8(vue@3.5.28(typescript@5.9.3)) + + '@intlify/core-base@11.2.8': + dependencies: + '@intlify/message-compiler': 11.2.8 + '@intlify/shared': 11.2.8 + + '@intlify/message-compiler@11.2.8': + dependencies: + '@intlify/shared': 11.2.8 + source-map-js: 1.2.1 + + '@intlify/shared@11.2.8': {} + + '@intlify/unplugin-vue-i18n@6.0.8(@vue/compiler-dom@3.5.28)(eslint@9.39.2(jiti@2.6.1))(rollup@4.57.1)(typescript@5.9.3)(vue-i18n@11.2.8(vue@3.5.28(typescript@5.9.3)))(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@intlify/bundle-utils': 10.0.1(vue-i18n@11.2.8(vue@3.5.28(typescript@5.9.3))) + '@intlify/shared': 11.2.8 + '@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.2.8)(@vue/compiler-dom@3.5.28)(vue-i18n@11.2.8(vue@3.5.28(typescript@5.9.3)))(vue@3.5.28(typescript@5.9.3)) + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + '@typescript-eslint/scope-manager': 8.55.0 + '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3) + debug: 4.4.3 + fast-glob: 3.3.3 + js-yaml: 4.1.1 + json5: 2.2.3 + pathe: 1.1.2 + picocolors: 1.1.1 + source-map-js: 1.2.1 + unplugin: 1.16.1 + vue: 3.5.28(typescript@5.9.3) + optionalDependencies: + vue-i18n: 11.2.8(vue@3.5.28(typescript@5.9.3)) + transitivePeerDependencies: + - '@vue/compiler-dom' + - eslint + - rollup + - supports-color + - typescript + + '@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.2.8)(@vue/compiler-dom@3.5.28)(vue-i18n@11.2.8(vue@3.5.28(typescript@5.9.3)))(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@babel/parser': 7.29.0 + optionalDependencies: + '@intlify/shared': 11.2.8 + '@vue/compiler-dom': 3.5.28 + vue: 3.5.28(typescript@5.9.3) + vue-i18n: 11.2.8(vue@3.5.28(typescript@5.9.3)) + + '@ioredis/commands@1.5.0': {} + + '@isaacs/balanced-match@4.0.1': {} + + '@isaacs/brace-expansion@5.0.1': + dependencies: + '@isaacs/balanced-match': 4.0.1 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.2 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@isaacs/cliui@9.0.0': {} + + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@jspm/generator@2.10.0': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) + '@jspm/import-map': 1.2.2 + es-module-lexer: 1.7.0 + minimatch: 10.1.2 + node-fetch-cache: 5.1.0 + pako: 2.1.0 + sver: 2.0.1 + tar-stream: 3.1.7 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + - supports-color + + '@jspm/import-map@1.2.2': {} + + '@juggle/resize-observer@3.4.0': {} + + '@keyv/bigmap@1.3.1(keyv@5.6.0)': + dependencies: + hashery: 1.4.0 + hookified: 1.15.1 + keyv: 5.6.0 + + '@keyv/serialize@1.1.1': {} + + '@lezer/common@1.5.1': {} + + '@lezer/highlight@1.2.3': + dependencies: + '@lezer/common': 1.5.1 + + '@lezer/lr@1.4.8': + dependencies: + '@lezer/common': 1.5.1 + + '@lezer/markdown@1.6.3': + dependencies: + '@lezer/common': 1.5.1 + '@lezer/highlight': 1.2.3 + + '@manypkg/find-root@1.1.0': + dependencies: + '@babel/runtime': 7.28.6 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + + '@manypkg/find-root@3.1.0': + dependencies: + '@manypkg/tools': 2.1.0 + + '@manypkg/get-packages@1.1.3': + dependencies: + '@babel/runtime': 7.28.6 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + + '@manypkg/get-packages@3.1.0': + dependencies: + '@manypkg/find-root': 3.1.0 + '@manypkg/tools': 2.1.0 + + '@manypkg/tools@2.1.0': + dependencies: + jju: 1.4.0 + js-yaml: 4.1.1 + tinyglobby: 0.2.15 + + '@mapbox/node-pre-gyp@2.0.3': + dependencies: + consola: 3.4.2 + detect-libc: 2.1.2 + https-proxy-agent: 7.0.6 + node-fetch: 2.7.0 + nopt: 8.1.0 + semver: 7.7.4 + tar: 7.5.7 + transitivePeerDependencies: + - encoding + - supports-color + + '@marijn/find-cluster-break@1.0.2': {} + + '@microsoft/api-extractor-model@7.32.2(@types/node@25.2.3)': + dependencies: + '@microsoft/tsdoc': 0.16.0 + '@microsoft/tsdoc-config': 0.18.0 + '@rushstack/node-core-library': 5.19.1(@types/node@25.2.3) + transitivePeerDependencies: + - '@types/node' + + '@microsoft/api-extractor@7.56.3(@types/node@25.2.3)': + dependencies: + '@microsoft/api-extractor-model': 7.32.2(@types/node@25.2.3) + '@microsoft/tsdoc': 0.16.0 + '@microsoft/tsdoc-config': 0.18.0 + '@rushstack/node-core-library': 5.19.1(@types/node@25.2.3) + '@rushstack/rig-package': 0.6.0 + '@rushstack/terminal': 0.21.0(@types/node@25.2.3) + '@rushstack/ts-command-line': 5.2.0(@types/node@25.2.3) + diff: 8.0.3 + lodash: 4.17.23 + minimatch: 10.1.2 + resolve: 1.22.11 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.8.2 + transitivePeerDependencies: + - '@types/node' + + '@microsoft/fetch-event-source@2.0.1': {} + + '@microsoft/tsdoc-config@0.18.0': + dependencies: + '@microsoft/tsdoc': 0.16.0 + ajv: 8.12.0 + jju: 1.4.0 + resolve: 1.22.11 + + '@microsoft/tsdoc@0.16.0': {} + + '@napi-rs/wasm-runtime@0.2.12': + dependencies: + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@nolebase/ui@2.18.2(vitepress@1.6.4(@algolia/client-search@5.48.0)(@types/node@25.2.3)(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(less@4.5.1)(nprogress@0.2.0)(postcss@8.5.6)(qrcode@1.5.4)(sass@1.97.3)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.46.0)(typescript@5.9.3))(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@iconify-json/octicon': 1.2.20 + less: 4.5.1 + vitepress: 1.6.4(@algolia/client-search@5.48.0)(@types/node@25.2.3)(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(less@4.5.1)(nprogress@0.2.0)(postcss@8.5.6)(qrcode@1.5.4)(sass@1.97.3)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.46.0)(typescript@5.9.3) + vue: 3.5.28(typescript@5.9.3) + + '@nolebase/vitepress-plugin-git-changelog@2.18.2(vitepress@1.6.4(@algolia/client-search@5.48.0)(@types/node@25.2.3)(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(less@4.5.1)(nprogress@0.2.0)(postcss@8.5.6)(qrcode@1.5.4)(sass@1.97.3)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.46.0)(typescript@5.9.3))(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@iconify-json/octicon': 1.2.20 + '@nolebase/ui': 2.18.2(vitepress@1.6.4(@algolia/client-search@5.48.0)(@types/node@25.2.3)(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(less@4.5.1)(nprogress@0.2.0)(postcss@8.5.6)(qrcode@1.5.4)(sass@1.97.3)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.46.0)(typescript@5.9.3))(vue@3.5.28(typescript@5.9.3)) + colorette: 2.0.20 + date-fns: 4.1.0 + defu: 6.1.4 + es-toolkit: 1.44.0 + execa: 9.6.1 + globby: 14.1.0 + gray-matter: 4.0.3 + less: 4.5.1 + uncrypto: 0.1.3 + vitepress: 1.6.4(@algolia/client-search@5.48.0)(@types/node@25.2.3)(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(less@4.5.1)(nprogress@0.2.0)(postcss@8.5.6)(qrcode@1.5.4)(sass@1.97.3)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.46.0)(typescript@5.9.3) + transitivePeerDependencies: + - vue + + '@npmcli/fs@5.0.0': + dependencies: + semver: 7.7.4 + + '@nuxt/kit@3.21.1(magicast@0.5.2)': + dependencies: + c12: 3.3.3(magicast@0.5.2) + consola: 3.4.2 + defu: 6.1.4 + destr: 2.0.5 + errx: 0.1.0 + exsolve: 1.0.8 + ignore: 7.0.5 + jiti: 2.6.1 + klona: 2.0.6 + knitwork: 1.3.0 + mlly: 1.8.0 + ohash: 2.0.11 + pathe: 2.0.3 + pkg-types: 2.3.0 + rc9: 3.0.0 + scule: 1.3.0 + semver: 7.7.4 + tinyglobby: 0.2.15 + ufo: 1.6.3 + unctx: 2.5.0 + untyped: 2.0.0 + transitivePeerDependencies: + - magicast + optional: true + + '@nuxt/kit@4.3.1(magicast@0.5.2)': + dependencies: + c12: 3.3.3(magicast@0.5.2) + consola: 3.4.2 + defu: 6.1.4 + destr: 2.0.5 + errx: 0.1.0 + exsolve: 1.0.8 + ignore: 7.0.5 + jiti: 2.6.1 + klona: 2.0.6 + mlly: 1.8.0 + ohash: 2.0.11 + pathe: 2.0.3 + pkg-types: 2.3.0 + rc9: 3.0.0 + scule: 1.3.0 + semver: 7.7.4 + tinyglobby: 0.2.15 + ufo: 1.6.3 + unctx: 2.5.0 + untyped: 2.0.0 + transitivePeerDependencies: + - magicast + + '@one-ini/wasm@0.1.1': {} + + '@parcel/watcher-android-arm64@2.5.6': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.6': + optional: true + + '@parcel/watcher-darwin-x64@2.5.6': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.6': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.6': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.6': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.6': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.6': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.6': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.6': + optional: true + + '@parcel/watcher-wasm@2.5.6': + dependencies: + is-glob: 4.0.3 + picomatch: 4.0.3 + + '@parcel/watcher-win32-arm64@2.5.6': + optional: true + + '@parcel/watcher-win32-ia32@2.5.6': + optional: true + + '@parcel/watcher-win32-x64@2.5.6': + optional: true + + '@parcel/watcher@2.5.6': + dependencies: + detect-libc: 2.1.2 + is-glob: 4.0.3 + node-addon-api: 7.1.1 + picomatch: 4.0.3 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.6 + '@parcel/watcher-darwin-arm64': 2.5.6 + '@parcel/watcher-darwin-x64': 2.5.6 + '@parcel/watcher-freebsd-x64': 2.5.6 + '@parcel/watcher-linux-arm-glibc': 2.5.6 + '@parcel/watcher-linux-arm-musl': 2.5.6 + '@parcel/watcher-linux-arm64-glibc': 2.5.6 + '@parcel/watcher-linux-arm64-musl': 2.5.6 + '@parcel/watcher-linux-x64-glibc': 2.5.6 + '@parcel/watcher-linux-x64-musl': 2.5.6 + '@parcel/watcher-win32-arm64': 2.5.6 + '@parcel/watcher-win32-ia32': 2.5.6 + '@parcel/watcher-win32-x64': 2.5.6 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.2.9': {} + + '@playwright/test@1.58.2': + dependencies: + playwright: 1.58.2 + + '@pnpm/config.env-replace@1.1.0': {} + + '@pnpm/constants@1001.3.1': {} + + '@pnpm/error@1000.0.5': + dependencies: + '@pnpm/constants': 1001.3.1 + + '@pnpm/network.ca-file@1.0.2': + dependencies: + graceful-fs: 4.2.10 + + '@pnpm/npm-conf@3.0.2': + dependencies: + '@pnpm/config.env-replace': 1.1.0 + '@pnpm/network.ca-file': 1.0.2 + config-chain: 1.1.13 + + '@pnpm/types@1001.3.0': {} + + '@pnpm/workspace.read-manifest@1000.2.10': + dependencies: + '@pnpm/constants': 1001.3.1 + '@pnpm/error': 1000.0.5 + '@pnpm/types': 1001.3.0 + read-yaml-file: 2.1.0 + + '@polka/url@1.0.0-next.29': {} + + '@popperjs/core@2.11.8': {} + + '@poppinss/colors@4.1.6': + dependencies: + kleur: 4.1.5 + + '@poppinss/dumper@0.6.5': + dependencies: + '@poppinss/colors': 4.1.6 + '@sindresorhus/is': 7.2.0 + supports-color: 10.2.2 + + '@poppinss/exception@1.2.3': {} + + '@publint/pack@0.1.4': {} + + '@rolldown/pluginutils@1.0.0-rc.2': {} + + '@rolldown/pluginutils@1.0.0-rc.3': {} + + '@rollup/plugin-alias@5.1.1(rollup@4.57.1)': + optionalDependencies: + rollup: 4.57.1 + + '@rollup/plugin-alias@6.0.0(rollup@4.57.1)': + optionalDependencies: + rollup: 4.57.1 + + '@rollup/plugin-babel@5.3.1(@babel/core@7.29.0)(rollup@2.79.2)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + rollup: 2.79.2 + transitivePeerDependencies: + - supports-color + + '@rollup/plugin-commonjs@28.0.9(rollup@4.57.1)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + commondir: 1.0.1 + estree-walker: 2.0.2 + fdir: 6.5.0(picomatch@4.0.3) + is-reference: 1.2.1 + magic-string: 0.30.21 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.57.1 + + '@rollup/plugin-commonjs@29.0.0(rollup@4.57.1)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + commondir: 1.0.1 + estree-walker: 2.0.2 + fdir: 6.5.0(picomatch@4.0.3) + is-reference: 1.2.1 + magic-string: 0.30.21 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.57.1 + + '@rollup/plugin-inject@5.0.5(rollup@4.57.1)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + estree-walker: 2.0.2 + magic-string: 0.30.21 + optionalDependencies: + rollup: 4.57.1 + + '@rollup/plugin-json@6.1.0(rollup@4.57.1)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + optionalDependencies: + rollup: 4.57.1 + + '@rollup/plugin-node-resolve@15.3.1(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@2.79.2) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.11 + optionalDependencies: + rollup: 2.79.2 + + '@rollup/plugin-node-resolve@16.0.3(rollup@4.57.1)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.11 + optionalDependencies: + rollup: 4.57.1 + + '@rollup/plugin-replace@2.4.2(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + magic-string: 0.25.9 + rollup: 2.79.2 + + '@rollup/plugin-replace@6.0.3(rollup@4.57.1)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + magic-string: 0.30.21 + optionalDependencies: + rollup: 4.57.1 + + '@rollup/plugin-terser@0.4.4(rollup@2.79.2)': + dependencies: + serialize-javascript: 6.0.2 + smob: 1.5.0 + terser: 5.46.0 + optionalDependencies: + rollup: 2.79.2 + + '@rollup/plugin-terser@0.4.4(rollup@4.57.1)': + dependencies: + serialize-javascript: 6.0.2 + smob: 1.5.0 + terser: 5.46.0 + optionalDependencies: + rollup: 4.57.1 + + '@rollup/pluginutils@3.1.0(rollup@2.79.2)': + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.79.2 + + '@rollup/pluginutils@4.2.1': + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.1 + + '@rollup/pluginutils@5.3.0(rollup@2.79.2)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 2.79.2 + + '@rollup/pluginutils@5.3.0(rollup@4.57.1)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.57.1 + + '@rollup/rollup-android-arm-eabi@4.57.1': + optional: true + + '@rollup/rollup-android-arm64@4.57.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.57.1': + optional: true + + '@rollup/rollup-darwin-x64@4.57.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.57.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.57.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.57.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.57.1': + optional: true + + '@rollup/rollup-openbsd-x64@4.57.1': + optional: true + + '@rollup/rollup-openharmony-arm64@4.57.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.57.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.57.1': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.57.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.57.1': + optional: true + + '@rushstack/node-core-library@5.19.1(@types/node@25.2.3)': + dependencies: + ajv: 8.13.0 + ajv-draft-04: 1.0.0(ajv@8.13.0) + ajv-formats: 3.0.1(ajv@8.13.0) + fs-extra: 11.3.3 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.11 + semver: 7.5.4 + optionalDependencies: + '@types/node': 25.2.3 + + '@rushstack/problem-matcher@0.1.1(@types/node@25.2.3)': + optionalDependencies: + '@types/node': 25.2.3 + + '@rushstack/rig-package@0.6.0': + dependencies: + resolve: 1.22.11 + strip-json-comments: 3.1.1 + + '@rushstack/terminal@0.21.0(@types/node@25.2.3)': + dependencies: + '@rushstack/node-core-library': 5.19.1(@types/node@25.2.3) + '@rushstack/problem-matcher': 0.1.1(@types/node@25.2.3) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 25.2.3 + + '@rushstack/ts-command-line@5.2.0(@types/node@25.2.3)': + dependencies: + '@rushstack/terminal': 0.21.0(@types/node@25.2.3) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + + '@sec-ant/readable-stream@0.4.1': {} + + '@shikijs/core@2.5.0': + dependencies: + '@shikijs/engine-javascript': 2.5.0 + '@shikijs/engine-oniguruma': 2.5.0 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 3.1.1 + + '@shikijs/engine-oniguruma@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + + '@shikijs/themes@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + + '@shikijs/transformers@2.5.0': + dependencies: + '@shikijs/core': 2.5.0 + '@shikijs/types': 2.5.0 + + '@shikijs/types@2.5.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@10.0.2': {} + + '@simonwep/pickr@1.8.2': + dependencies: + core-js: 3.48.0 + nanopop: 2.4.2 + + '@sindresorhus/base62@1.0.0': {} + + '@sindresorhus/is@7.2.0': {} + + '@sindresorhus/merge-streams@2.3.0': {} + + '@sindresorhus/merge-streams@4.0.0': {} + + '@speed-highlight/core@1.2.14': {} + + '@stylistic/stylelint-plugin@4.0.1(stylelint@16.26.1(typescript@5.9.3))': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + postcss-value-parser: 4.2.0 + style-search: 0.1.0 + stylelint: 16.26.1(typescript@5.9.3) + + '@surma/rollup-plugin-off-main-thread@2.2.3': + dependencies: + ejs: 3.1.10 + json5: 2.2.3 + magic-string: 0.25.9 + string.prototype.matchall: 4.0.12 + + '@svelte-put/shortcut@4.1.0(svelte@5.50.1)': + dependencies: + svelte: 5.50.1 + + '@sveltejs/acorn-typescript@1.0.8(acorn@8.15.0)': + dependencies: + acorn: 8.15.0 + + '@swc/helpers@0.5.18': + dependencies: + tslib: 2.8.1 + + '@sxzz/popperjs-es@2.11.8': {} + + '@tailwindcss/nesting@0.0.0-insiders.565cd3e(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + postcss-nested: 5.0.6(postcss@8.5.6) + + '@tailwindcss/typography@0.5.19(tailwindcss@3.4.19(yaml@2.8.2))': + dependencies: + postcss-selector-parser: 6.0.10 + tailwindcss: 3.4.19(yaml@2.8.2) + + '@tanstack/store@0.8.0': {} + + '@tanstack/virtual-core@3.13.18': {} + + '@tanstack/vue-store@0.8.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@tanstack/store': 0.8.0 + vue: 3.5.28(typescript@5.9.3) + vue-demi: 0.14.10(vue@3.5.28(typescript@5.9.3)) + + '@tanstack/vue-virtual@3.13.18(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@tanstack/virtual-core': 3.13.18 + vue: 3.5.28(typescript@5.9.3) + + '@tinyflow-ai/ui@1.1.10(svelte@5.50.1)': + dependencies: + '@floating-ui/dom': 1.7.5 + '@xyflow/svelte': 1.5.0(svelte@5.50.1) + transitivePeerDependencies: + - svelte + + '@tinyflow-ai/vue@1.1.10(svelte@5.50.1)(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@tinyflow-ai/ui': 1.1.10(svelte@5.50.1) + vue: 3.5.28(typescript@5.9.3) + transitivePeerDependencies: + - svelte + + '@tinymce/tinymce-vue@6.3.0(tinymce@7.9.1)(vue@3.5.28(typescript@5.9.3))': + dependencies: + vue: 3.5.28(typescript@5.9.3) + optionalDependencies: + tinymce: 7.9.1 + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/archiver@6.0.4': + dependencies: + '@types/readdir-glob': 1.1.5 + + '@types/argparse@1.0.38': {} + + '@types/bintrees@1.0.6': {} + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/codemirror@5.60.17': + dependencies: + '@types/tern': 0.23.9 + + '@types/conventional-commits-parser@5.0.2': + dependencies: + '@types/node': 25.2.3 + + '@types/crypto-js@4.2.2': {} + + '@types/d3-array@3.2.2': {} + + '@types/d3-axis@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-brush@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-chord@3.0.6': {} + + '@types/d3-color@3.1.3': {} + + '@types/d3-contour@3.0.6': + dependencies: + '@types/d3-array': 3.2.2 + '@types/geojson': 7946.0.16 + + '@types/d3-delaunay@6.0.4': {} + + '@types/d3-dispatch@3.0.7': {} + + '@types/d3-drag@3.0.7': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-dsv@3.0.7': {} + + '@types/d3-ease@3.0.2': {} + + '@types/d3-fetch@3.0.7': + dependencies: + '@types/d3-dsv': 3.0.7 + + '@types/d3-force@3.0.10': {} + + '@types/d3-format@3.0.4': {} + + '@types/d3-geo@3.1.0': + dependencies: + '@types/geojson': 7946.0.16 + + '@types/d3-hierarchy@3.1.7': {} + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-path@3.1.1': {} + + '@types/d3-polygon@3.0.2': {} + + '@types/d3-quadtree@3.0.6': {} + + '@types/d3-random@3.0.3': {} + + '@types/d3-scale-chromatic@3.1.0': {} + + '@types/d3-scale@4.0.9': + dependencies: + '@types/d3-time': 3.0.4 + + '@types/d3-selection@3.0.11': {} + + '@types/d3-shape@3.1.8': + dependencies: + '@types/d3-path': 3.1.1 + + '@types/d3-time-format@4.0.3': {} + + '@types/d3-time@3.0.4': {} + + '@types/d3-timer@3.0.2': {} + + '@types/d3-transition@3.0.9': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-zoom@3.0.8': + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + + '@types/d3@7.4.3': + dependencies: + '@types/d3-array': 3.2.2 + '@types/d3-axis': 3.0.6 + '@types/d3-brush': 3.0.6 + '@types/d3-chord': 3.0.6 + '@types/d3-color': 3.1.3 + '@types/d3-contour': 3.0.6 + '@types/d3-delaunay': 6.0.4 + '@types/d3-dispatch': 3.0.7 + '@types/d3-drag': 3.0.7 + '@types/d3-dsv': 3.0.7 + '@types/d3-ease': 3.0.2 + '@types/d3-fetch': 3.0.7 + '@types/d3-force': 3.0.10 + '@types/d3-format': 3.0.4 + '@types/d3-geo': 3.1.0 + '@types/d3-hierarchy': 3.1.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-path': 3.1.1 + '@types/d3-polygon': 3.0.2 + '@types/d3-quadtree': 3.0.6 + '@types/d3-random': 3.0.3 + '@types/d3-scale': 4.0.9 + '@types/d3-scale-chromatic': 3.1.0 + '@types/d3-selection': 3.0.11 + '@types/d3-shape': 3.1.8 + '@types/d3-time': 3.0.4 + '@types/d3-time-format': 4.0.3 + '@types/d3-timer': 3.0.2 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + + '@types/deep-eql@4.0.2': {} + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + + '@types/estree@0.0.39': {} + + '@types/estree@1.0.8': {} + + '@types/geojson@7946.0.16': {} + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/html-minifier-terser@7.0.2': {} + + '@types/json-schema@7.0.15': {} + + '@types/katex@0.16.8': {} + + '@types/linkify-it@5.0.0': {} + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.23 + + '@types/lodash.clonedeep@4.5.9': + dependencies: + '@types/lodash': 4.17.23 + + '@types/lodash@4.17.23': {} + + '@types/markdown-it@14.1.2': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdurl@2.0.0': {} + + '@types/minimatch@3.0.5': {} + + '@types/node@12.20.55': {} + + '@types/node@24.10.13': + dependencies: + undici-types: 7.16.0 + + '@types/node@25.2.3': + dependencies: + undici-types: 7.16.0 + + '@types/nprogress@0.2.3': {} + + '@types/parse-json@4.0.2': {} + + '@types/postcss-import@14.0.3': + dependencies: + postcss: 8.5.6 + + '@types/qrcode@1.5.6': + dependencies: + '@types/node': 25.2.3 + + '@types/qs@6.14.0': {} + + '@types/readdir-glob@1.1.5': + dependencies: + '@types/node': 25.2.3 + + '@types/resolve@1.20.2': {} + + '@types/sortablejs@1.15.9': {} + + '@types/tern@0.23.9': + dependencies: + '@types/estree': 1.0.8 + + '@types/tinycolor2@1.4.6': {} + + '@types/trusted-types@2.0.7': {} + + '@types/unist@3.0.3': {} + + '@types/validator@13.15.10': {} + + '@types/video.js@7.3.58': {} + + '@types/web-bluetooth@0.0.20': {} + + '@types/web-bluetooth@0.0.21': {} + + '@typescript-eslint/eslint-plugin@8.55.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.55.0 + '@typescript-eslint/type-utils': 8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.55.0 + eslint: 9.39.2(jiti@2.6.1) + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.55.0 + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.55.0 + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.55.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.9.3) + '@typescript-eslint/types': 8.55.0 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@7.18.0': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + + '@typescript-eslint/scope-manager@8.55.0': + dependencies: + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/visitor-keys': 8.55.0 + + '@typescript-eslint/tsconfig-utils@8.55.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@7.18.0': {} + + '@typescript-eslint/types@8.55.0': {} + + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.4.3 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.4 + ts-api-utils: 1.4.3(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@8.55.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.55.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.9.3) + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/visitor-keys': 8.55.0 + debug: 4.4.3 + minimatch: 9.0.5 + semver: 7.7.4 + tinyglobby: 0.2.15 + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@7.18.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/utils@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.55.0 + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@7.18.0': + dependencies: + '@typescript-eslint/types': 7.18.0 + eslint-visitor-keys: 3.4.3 + + '@typescript-eslint/visitor-keys@8.55.0': + dependencies: + '@typescript-eslint/types': 8.55.0 + eslint-visitor-keys: 4.2.1 + + '@ungap/structured-clone@1.3.0': {} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true + + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + + '@v-c/async-validator@1.0.0': {} + + '@v-c/cascader@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/select': 1.0.9(vue@3.5.28(typescript@5.9.3)) + '@v-c/tree': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/checkbox@1.0.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/collapse@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/color-picker@1.0.5(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@ant-design/fast-color': 3.0.1 + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/dialog@1.0.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/portal': 1.0.7(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/drawer@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/portal': 1.0.7(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/dropdown@1.0.2(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/trigger': 1.0.11(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/image@1.0.2(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/portal': 1.0.7(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/input-number@1.0.2(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/input': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/mini-decimal': 1.0.1 + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/input@1.0.2(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/mentions@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/input': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/menu': 1.0.10(vue@3.5.28(typescript@5.9.3)) + '@v-c/textarea': 1.0.3(vue@3.5.28(typescript@5.9.3)) + '@v-c/trigger': 1.0.11(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/menu@1.0.10(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/overflow': 1.0.3(vue@3.5.28(typescript@5.9.3)) + '@v-c/trigger': 1.0.11(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/mini-decimal@1.0.1': {} + + '@v-c/mutate-observer@1.0.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/resize-observer': 1.0.8(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/notification@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/overflow@1.0.3(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/resize-observer': 1.0.8(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/pagination@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/picker@1.0.2(date-fns@4.1.0)(dayjs@1.11.19)(luxon@3.7.2)(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/overflow': 1.0.3(vue@3.5.28(typescript@5.9.3)) + '@v-c/resize-observer': 1.0.8(vue@3.5.28(typescript@5.9.3)) + '@v-c/trigger': 1.0.11(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + optionalDependencies: + date-fns: 4.1.0 + dayjs: 1.11.19 + luxon: 3.7.2 + + '@v-c/portal@1.0.7(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/progress@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/qrcode@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/rate@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/resize-observer@1.0.8(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + resize-observer-polyfill: 1.5.1 + vue: 3.5.28(typescript@5.9.3) + + '@v-c/segmented@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/select@1.0.9(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/overflow': 1.0.3(vue@3.5.28(typescript@5.9.3)) + '@v-c/trigger': 1.0.11(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + '@v-c/virtual-list': 1.0.5(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/slick@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + es-toolkit: 1.43.0 + vue: 3.5.28(typescript@5.9.3) + + '@v-c/slider@1.0.10(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/steps@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/switch@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/table@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/resize-observer': 1.0.8(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + '@v-c/virtual-list': 1.0.5(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/tabs@1.0.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/dropdown': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/menu': 1.0.10(vue@3.5.28(typescript@5.9.3)) + '@v-c/overflow': 1.0.3(vue@3.5.28(typescript@5.9.3)) + '@v-c/resize-observer': 1.0.8(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/textarea@1.0.3(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/input': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/resize-observer': 1.0.8(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/tooltip@1.0.3(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/trigger': 1.0.11(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/tour@1.0.3(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/portal': 1.0.7(vue@3.5.28(typescript@5.9.3)) + '@v-c/trigger': 1.0.11(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/tree-select@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/select': 1.0.9(vue@3.5.28(typescript@5.9.3)) + '@v-c/tree': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/tree@1.0.2(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + '@v-c/virtual-list': 1.0.5(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/trigger@1.0.11(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/portal': 1.0.7(vue@3.5.28(typescript@5.9.3)) + '@v-c/resize-observer': 1.0.8(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/upload@1.0.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@v-c/util@1.0.13(vue@3.5.28(typescript@5.9.3))': + dependencies: + vue: 3.5.28(typescript@5.9.3) + + '@v-c/virtual-list@1.0.5(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@v-c/resize-observer': 1.0.8(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@vee-validate/zod@4.15.1(vue@3.5.28(typescript@5.9.3))(zod@3.25.76)': + dependencies: + type-fest: 4.41.0 + vee-validate: 4.15.1(vue@3.5.28(typescript@5.9.3)) + zod: 3.25.76 + transitivePeerDependencies: + - vue + + '@vercel/nft@1.3.1(rollup@4.57.1)': + dependencies: + '@mapbox/node-pre-gyp': 2.0.3 + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + acorn: 8.15.0 + acorn-import-attributes: 1.9.5(acorn@8.15.0) + async-sema: 3.1.1 + bindings: 1.5.0 + estree-walker: 2.0.2 + glob: 13.0.2 + graceful-fs: 4.2.11 + node-gyp-build: 4.8.4 + picomatch: 4.0.3 + resolve-from: 5.0.0 + transitivePeerDependencies: + - encoding + - rollup + - supports-color + + '@videojs-player/vue@1.0.0(@types/video.js@7.3.58)(video.js@7.21.7)(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@types/video.js': 7.3.58 + video.js: 7.21.7 + vue: 3.5.28(typescript@5.9.3) + + '@videojs/http-streaming@2.16.3(video.js@7.21.7)': + dependencies: + '@babel/runtime': 7.28.6 + '@videojs/vhs-utils': 3.0.5 + aes-decrypter: 3.1.3 + global: 4.4.0 + m3u8-parser: 4.8.0 + mpd-parser: 0.22.1 + mux.js: 6.0.1 + video.js: 7.21.7 + + '@videojs/vhs-utils@3.0.5': + dependencies: + '@babel/runtime': 7.28.6 + global: 4.4.0 + url-toolkit: 2.2.5 + + '@videojs/xhr@2.6.0': + dependencies: + '@babel/runtime': 7.28.6 + global: 4.4.0 + is-function: 1.0.2 + + '@vite-pwa/vitepress@1.1.0(vite-plugin-pwa@1.2.0(vite@5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0))(workbox-build@7.4.0)(workbox-window@7.4.0))': + dependencies: + vite-plugin-pwa: 1.2.0(vite@5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0))(workbox-build@7.4.0)(workbox-window@7.4.0) + + '@vitejs/plugin-vue-jsx@5.1.4(vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-rc.3 + '@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.29.0) + vite: 7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vue: 3.5.28(typescript@5.9.3) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-vue-jsx@5.1.4(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-rc.3 + '@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.29.0) + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vue: 3.5.28(typescript@5.9.3) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-vue@5.2.4(vite@5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0))(vue@3.5.28(typescript@5.9.3))': + dependencies: + vite: 5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0) + vue: 3.5.28(typescript@5.9.3) + + '@vitejs/plugin-vue@6.0.4(vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@rolldown/pluginutils': 1.0.0-rc.2 + vite: 7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vue: 3.5.28(typescript@5.9.3) + + '@vitejs/plugin-vue@6.0.4(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@rolldown/pluginutils': 1.0.0-rc.2 + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vue: 3.5.28(typescript@5.9.3) + + '@vitest/expect@3.2.4': + dependencies: + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.4': + dependencies: + '@vitest/utils': 3.2.4 + pathe: 2.0.3 + strip-literal: 3.1.0 + + '@vitest/snapshot@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.4 + + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + + '@volar/language-core@2.4.27': + dependencies: + '@volar/source-map': 2.4.27 + + '@volar/language-core@2.4.28': + dependencies: + '@volar/source-map': 2.4.28 + + '@volar/source-map@2.4.27': {} + + '@volar/source-map@2.4.28': {} + + '@volar/typescript@2.4.27': + dependencies: + '@volar/language-core': 2.4.27 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@volar/typescript@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue/babel-helper-vue-transform-on@1.5.0': {} + + '@vue/babel-helper-vue-transform-on@2.0.1': {} + + '@vue/babel-plugin-jsx@1.5.0(@babel/core@7.29.0)': + dependencies: + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@vue/babel-helper-vue-transform-on': 1.5.0 + '@vue/babel-plugin-resolve-type': 1.5.0(@babel/core@7.29.0) + '@vue/shared': 3.5.28 + optionalDependencies: + '@babel/core': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@vue/babel-plugin-jsx@2.0.1(@babel/core@7.29.0)': + dependencies: + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@vue/babel-helper-vue-transform-on': 2.0.1 + '@vue/babel-plugin-resolve-type': 2.0.1(@babel/core@7.29.0) + '@vue/shared': 3.5.28 + optionalDependencies: + '@babel/core': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@vue/babel-plugin-resolve-type@1.5.0(@babel/core@7.29.0)': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/parser': 7.29.0 + '@vue/compiler-sfc': 3.5.28 + transitivePeerDependencies: + - supports-color + + '@vue/babel-plugin-resolve-type@2.0.1(@babel/core@7.29.0)': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/parser': 7.29.0 + '@vue/compiler-sfc': 3.5.28 + transitivePeerDependencies: + - supports-color + + '@vue/compiler-core@3.5.28': + dependencies: + '@babel/parser': 7.29.0 + '@vue/shared': 3.5.28 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.28': + dependencies: + '@vue/compiler-core': 3.5.28 + '@vue/shared': 3.5.28 + + '@vue/compiler-sfc@3.5.28': + dependencies: + '@babel/parser': 7.29.0 + '@vue/compiler-core': 3.5.28 + '@vue/compiler-dom': 3.5.28 + '@vue/compiler-ssr': 3.5.28 + '@vue/shared': 3.5.28 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.6 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.28': + dependencies: + '@vue/compiler-dom': 3.5.28 + '@vue/shared': 3.5.28 + + '@vue/compiler-vue2@2.7.16': + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + '@vue/devtools-api@6.6.4': {} + + '@vue/devtools-api@7.7.9': + dependencies: + '@vue/devtools-kit': 7.7.9 + + '@vue/devtools-core@8.0.6(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@vue/devtools-kit': 8.0.6 + '@vue/devtools-shared': 8.0.6 + mitt: 3.0.1 + nanoid: 5.1.6 + pathe: 2.0.3 + vite-hot-client: 2.1.0(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + vue: 3.5.28(typescript@5.9.3) + transitivePeerDependencies: + - vite + + '@vue/devtools-kit@7.7.9': + dependencies: + '@vue/devtools-shared': 7.7.9 + birpc: 2.9.0 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.6 + + '@vue/devtools-kit@8.0.6': + dependencies: + '@vue/devtools-shared': 8.0.6 + birpc: 2.9.0 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 2.1.0 + speakingurl: 14.0.1 + superjson: 2.2.6 + + '@vue/devtools-shared@7.7.9': + dependencies: + rfdc: 1.4.1 + + '@vue/devtools-shared@8.0.6': + dependencies: + rfdc: 1.4.1 + + '@vue/language-core@2.2.0(typescript@5.9.3)': + dependencies: + '@volar/language-core': 2.4.28 + '@vue/compiler-dom': 3.5.28 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.28 + alien-signals: 0.4.14 + minimatch: 9.0.5 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.9.3 + + '@vue/language-core@3.2.4': + dependencies: + '@volar/language-core': 2.4.27 + '@vue/compiler-dom': 3.5.28 + '@vue/shared': 3.5.28 + alien-signals: 3.1.2 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + picomatch: 4.0.3 + + '@vue/reactivity@3.5.28': + dependencies: + '@vue/shared': 3.5.28 + + '@vue/runtime-core@3.5.28': + dependencies: + '@vue/reactivity': 3.5.28 + '@vue/shared': 3.5.28 + + '@vue/runtime-dom@3.5.28': + dependencies: + '@vue/reactivity': 3.5.28 + '@vue/runtime-core': 3.5.28 + '@vue/shared': 3.5.28 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.28(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@vue/compiler-ssr': 3.5.28 + '@vue/shared': 3.5.28 + vue: 3.5.28(typescript@5.9.3) + + '@vue/shared@3.5.28': {} + + '@vue/test-utils@2.4.6': + dependencies: + js-beautify: 1.15.4 + vue-component-type-helpers: 2.2.12 + + '@vueuse/core@10.11.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@types/web-bluetooth': 0.0.20 + '@vueuse/metadata': 10.11.1 + '@vueuse/shared': 10.11.1(vue@3.5.28(typescript@5.9.3)) + vue-demi: 0.14.10(vue@3.5.28(typescript@5.9.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/core@12.8.2(typescript@5.9.3)': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 12.8.2 + '@vueuse/shared': 12.8.2(typescript@5.9.3) + vue: 3.5.28(typescript@5.9.3) + transitivePeerDependencies: + - typescript + + '@vueuse/core@13.9.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 13.9.0 + '@vueuse/shared': 13.9.0(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@vueuse/core@14.2.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 14.2.1 + '@vueuse/shared': 14.2.1(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + '@vueuse/integrations@12.8.2(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(focus-trap@7.8.0)(nprogress@0.2.0)(qrcode@1.5.4)(sortablejs@1.15.6)(typescript@5.9.3)': + dependencies: + '@vueuse/core': 12.8.2(typescript@5.9.3) + '@vueuse/shared': 12.8.2(typescript@5.9.3) + vue: 3.5.28(typescript@5.9.3) + optionalDependencies: + async-validator: 4.2.5 + axios: 1.13.5 + change-case: 5.4.4 + focus-trap: 7.8.0 + nprogress: 0.2.0 + qrcode: 1.5.4 + sortablejs: 1.15.6 + transitivePeerDependencies: + - typescript + + '@vueuse/integrations@14.2.1(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(focus-trap@7.8.0)(nprogress@0.2.0)(qrcode@1.5.4)(sortablejs@1.15.6)(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@vueuse/core': 14.2.1(vue@3.5.28(typescript@5.9.3)) + '@vueuse/shared': 14.2.1(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + optionalDependencies: + async-validator: 4.2.5 + axios: 1.13.5 + change-case: 5.4.4 + focus-trap: 7.8.0 + nprogress: 0.2.0 + qrcode: 1.5.4 + sortablejs: 1.15.6 + + '@vueuse/metadata@10.11.1': {} + + '@vueuse/metadata@12.8.2': {} + + '@vueuse/metadata@13.9.0': {} + + '@vueuse/metadata@14.2.1': {} + + '@vueuse/motion@3.0.3(magicast@0.5.2)(vue@3.5.28(typescript@5.9.3))': + dependencies: + '@vueuse/core': 13.9.0(vue@3.5.28(typescript@5.9.3)) + '@vueuse/shared': 13.9.0(vue@3.5.28(typescript@5.9.3)) + defu: 6.1.4 + framesync: 6.1.2 + popmotion: 11.0.5 + style-value-types: 5.1.2 + vue: 3.5.28(typescript@5.9.3) + optionalDependencies: + '@nuxt/kit': 3.21.1(magicast@0.5.2) + transitivePeerDependencies: + - magicast + + '@vueuse/shared@10.11.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + vue-demi: 0.14.10(vue@3.5.28(typescript@5.9.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/shared@12.8.2(typescript@5.9.3)': + dependencies: + vue: 3.5.28(typescript@5.9.3) + transitivePeerDependencies: + - typescript + + '@vueuse/shared@13.9.0(vue@3.5.28(typescript@5.9.3))': + dependencies: + vue: 3.5.28(typescript@5.9.3) + + '@vueuse/shared@14.2.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + vue: 3.5.28(typescript@5.9.3) + + '@vxe-ui/core@4.3.1(vue@3.5.28(typescript@5.9.3))': + dependencies: + dom-zindex: 1.0.6 + vue: 3.5.28(typescript@5.9.3) + xe-utils: 3.9.1 + + '@xmldom/xmldom@0.8.11': {} + + '@xyflow/svelte@1.5.0(svelte@5.50.1)': + dependencies: + '@svelte-put/shortcut': 4.1.0(svelte@5.50.1) + '@xyflow/system': 0.0.74 + svelte: 5.50.1 + + '@xyflow/system@0.0.74': + dependencies: + '@types/d3-drag': 3.0.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-zoom: 3.0.0 + + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + + abbrev@2.0.0: {} + + abbrev@3.0.1: {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + acorn-import-attributes@1.9.5(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + aes-decrypter@3.1.3: + dependencies: + '@babel/runtime': 7.28.6 + '@videojs/vhs-utils': 3.0.5 + global: 4.4.0 + pkcs7: 1.0.4 + + agent-base@7.1.4: {} + + ajv-draft-04@1.0.0(ajv@8.13.0): + optionalDependencies: + ajv: 8.13.0 + + ajv-formats@3.0.1(ajv@8.13.0): + optionalDependencies: + ajv: 8.13.0 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.12.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + ajv@8.13.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + algoliasearch@5.48.0: + dependencies: + '@algolia/abtesting': 1.14.0 + '@algolia/client-abtesting': 5.48.0 + '@algolia/client-analytics': 5.48.0 + '@algolia/client-common': 5.48.0 + '@algolia/client-insights': 5.48.0 + '@algolia/client-personalization': 5.48.0 + '@algolia/client-query-suggestions': 5.48.0 + '@algolia/client-search': 5.48.0 + '@algolia/ingestion': 1.48.0 + '@algolia/monitoring': 1.48.0 + '@algolia/recommend': 5.48.0 + '@algolia/requester-browser-xhr': 5.48.0 + '@algolia/requester-fetch': 5.48.0 + '@algolia/requester-node-http': 5.48.0 + + alien-signals@0.4.14: {} + + alien-signals@3.1.2: {} + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-colors@4.1.3: {} + + ansi-escapes@7.3.0: + dependencies: + environment: 1.1.0 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + + ansis@4.2.0: {} + + ant-design-vue@4.2.6(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-vue': 7.0.1(vue@3.5.28(typescript@5.9.3)) + '@babel/runtime': 7.28.6 + '@ctrl/tinycolor': 4.2.0 + '@emotion/hash': 0.9.2 + '@emotion/unitless': 0.8.1 + '@simonwep/pickr': 1.8.2 + array-tree-filter: 2.1.0 + async-validator: 4.2.5 + csstype: 3.2.3 + dayjs: 1.11.19 + dom-align: 1.12.4 + dom-scroll-into-view: 2.0.1 + lodash: 4.17.23 + lodash-es: 4.17.23 + resize-observer-polyfill: 1.5.1 + scroll-into-view-if-needed: 2.2.31 + shallow-equal: 1.2.1 + stylis: 4.3.6 + throttle-debounce: 5.0.2 + vue: 3.5.28(typescript@5.9.3) + vue-types: 3.0.2(vue@3.5.28(typescript@5.9.3)) + warning: 4.0.3 + + antdv-next@1.0.2(date-fns@4.1.0)(luxon@3.7.2)(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@ant-design/colors': 7.2.1 + '@ant-design/fast-color': 3.0.1 + '@antdv-next/cssinjs': 1.0.1(vue@3.5.28(typescript@5.9.3)) + '@antdv-next/icons': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/async-validator': 1.0.0 + '@v-c/cascader': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/checkbox': 1.0.1(vue@3.5.28(typescript@5.9.3)) + '@v-c/collapse': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/color-picker': 1.0.5(vue@3.5.28(typescript@5.9.3)) + '@v-c/dialog': 1.0.1(vue@3.5.28(typescript@5.9.3)) + '@v-c/drawer': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/dropdown': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/image': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/input': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/input-number': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/mentions': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/menu': 1.0.10(vue@3.5.28(typescript@5.9.3)) + '@v-c/mutate-observer': 1.0.1(vue@3.5.28(typescript@5.9.3)) + '@v-c/notification': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/pagination': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/picker': 1.0.2(date-fns@4.1.0)(dayjs@1.11.19)(luxon@3.7.2)(vue@3.5.28(typescript@5.9.3)) + '@v-c/progress': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/qrcode': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/rate': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/resize-observer': 1.0.8(vue@3.5.28(typescript@5.9.3)) + '@v-c/segmented': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/select': 1.0.9(vue@3.5.28(typescript@5.9.3)) + '@v-c/slick': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/slider': 1.0.10(vue@3.5.28(typescript@5.9.3)) + '@v-c/steps': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/switch': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/table': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/tabs': 1.0.1(vue@3.5.28(typescript@5.9.3)) + '@v-c/textarea': 1.0.3(vue@3.5.28(typescript@5.9.3)) + '@v-c/tooltip': 1.0.3(vue@3.5.28(typescript@5.9.3)) + '@v-c/tour': 1.0.3(vue@3.5.28(typescript@5.9.3)) + '@v-c/tree': 1.0.2(vue@3.5.28(typescript@5.9.3)) + '@v-c/tree-select': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/trigger': 1.0.11(vue@3.5.28(typescript@5.9.3)) + '@v-c/upload': 1.0.0(vue@3.5.28(typescript@5.9.3)) + '@v-c/util': 1.0.13(vue@3.5.28(typescript@5.9.3)) + '@v-c/virtual-list': 1.0.5(vue@3.5.28(typescript@5.9.3)) + '@vueuse/core': 14.2.1(vue@3.5.28(typescript@5.9.3)) + dayjs: 1.11.19 + defu: 6.1.4 + es-toolkit: 1.43.0 + scroll-into-view-if-needed: 3.1.0 + throttle-debounce: 5.0.2 + transitivePeerDependencies: + - date-fns + - luxon + - moment + - vue + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + archiver-utils@5.0.2: + dependencies: + glob: 10.4.5 + graceful-fs: 4.2.11 + is-stream: 2.0.1 + lazystream: 1.0.1 + lodash: 4.17.23 + normalize-path: 3.0.0 + readable-stream: 4.7.0 + + archiver@7.0.1: + dependencies: + archiver-utils: 5.0.2 + async: 3.2.6 + buffer-crc32: 1.0.0 + readable-stream: 4.7.0 + readdir-glob: 1.1.3 + tar-stream: 3.1.7 + zip-stream: 6.0.1 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + are-docs-informative@0.0.2: {} + + arg@5.0.2: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + aria-query@5.3.2: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-differ@3.0.0: {} + + array-ify@1.0.0: {} + + array-move@4.0.0: {} + + array-timsort@1.0.3: {} + + array-tree-filter@2.1.0: {} + + array-union@2.1.0: {} + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + arrify@2.0.1: {} + + assertion-error@2.0.1: {} + + astral-regex@2.0.0: {} + + async-function@1.0.0: {} + + async-sema@3.1.1: {} + + async-validator@4.2.5: {} + + async@3.2.6: {} + + asynckit@0.4.0: {} + + at-least-node@1.0.0: {} + + atomically@2.1.1: + dependencies: + stubborn-fs: 2.0.0 + when-exit: 2.1.5 + + autolinker@3.16.2: + dependencies: + tslib: 2.8.1 + + autoprefixer@10.4.24(postcss@8.5.6): + dependencies: + browserslist: 4.28.1 + caniuse-lite: 1.0.30001769 + fraction.js: 5.3.4 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axios-mock-adapter@2.1.0(axios@1.13.5): + dependencies: + axios: 1.13.5 + fast-deep-equal: 3.1.3 + is-buffer: 2.0.5 + + axios@1.13.5: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + axobject-query@4.1.0: {} + + b4a@1.7.3: {} + + babel-plugin-polyfill-corejs2@0.4.15(@babel/core@7.29.0): + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.14.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) + core-js-compat: 3.48.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.6(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + balanced-match@1.0.2: {} + + balanced-match@2.0.0: {} + + bare-events@2.8.2: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.9.19: {} + + benz-amr-recorder@1.1.5: + dependencies: + benz-recorderjs: 1.0.5 + + benz-recorderjs@1.0.5: {} + + better-path-resolve@1.0.0: + dependencies: + is-windows: 1.0.2 + + bignumber.js@9.3.1: {} + + binary-extensions@2.3.0: {} + + bindings@1.5.0: + dependencies: + file-uri-to-path: 1.0.0 + + bintrees@1.0.2: {} + + birpc@2.9.0: {} + + boolbase@1.0.0: {} + + boxen@8.0.1: + dependencies: + ansi-align: 3.0.1 + camelcase: 8.0.0 + chalk: 5.6.2 + cli-boxes: 3.0.0 + string-width: 7.2.0 + type-fest: 4.41.0 + widest-line: 5.0.0 + wrap-ansi: 9.0.2 + + bpmn-js-properties-panel@5.23.0(@bpmn-io/properties-panel@3.38.0)(bpmn-js@17.11.1)(camunda-bpmn-js-behaviors@1.14.0(bpmn-js@17.11.1)(camunda-bpmn-moddle@7.0.1)(zeebe-bpmn-moddle@1.12.0))(diagram-js@12.8.1): + dependencies: + '@bpmn-io/extract-process-variables': 0.8.0 + '@bpmn-io/properties-panel': 3.38.0 + array-move: 4.0.0 + bpmn-js: 17.11.1 + camunda-bpmn-js-behaviors: 1.14.0(bpmn-js@17.11.1)(camunda-bpmn-moddle@7.0.1)(zeebe-bpmn-moddle@1.12.0) + diagram-js: 12.8.1 + ids: 1.0.5 + min-dash: 4.2.3 + min-dom: 4.2.1 + + bpmn-js-token-simulation@0.36.3: + dependencies: + inherits-browser: 0.1.0 + min-dash: 4.2.3 + min-dom: 4.2.1 + randomcolor: 0.6.2 + + bpmn-js@17.11.1: + dependencies: + bpmn-moddle: 8.1.0 + diagram-js: 14.11.3 + diagram-js-direct-editing: 3.3.0(diagram-js@14.11.3) + ids: 1.0.5 + inherits-browser: 0.1.0 + min-dash: 4.2.3 + min-dom: 4.2.1 + tiny-svg: 3.1.3 + + bpmn-moddle@8.1.0: + dependencies: + min-dash: 4.2.3 + moddle: 6.2.3 + moddle-xml: 10.1.0 + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.9.19 + caniuse-lite: 1.0.30001769 + electron-to-chromium: 1.5.286 + node-releases: 2.0.27 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + + buffer-crc32@1.0.0: {} + + buffer-from@1.1.2: {} + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + builtin-modules@5.0.0: {} + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + + c12@3.3.3(magicast@0.5.2): + dependencies: + chokidar: 5.0.0 + confbox: 0.2.4 + defu: 6.1.4 + dotenv: 17.2.4 + exsolve: 1.0.8 + giget: 2.0.0 + jiti: 2.6.1 + ohash: 2.0.11 + pathe: 2.0.3 + perfect-debounce: 2.1.0 + pkg-types: 2.3.0 + rc9: 2.1.2 + optionalDependencies: + magicast: 0.5.2 + + cac@6.7.14: {} + + cacache@20.0.3: + dependencies: + '@npmcli/fs': 5.0.0 + fs-minipass: 3.0.3 + glob: 13.0.2 + lru-cache: 11.2.6 + minipass: 7.1.2 + minipass-collect: 2.0.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + p-map: 7.0.4 + ssri: 13.0.1 + unique-filename: 5.0.0 + + cacheable@2.3.2: + dependencies: + '@cacheable/memory': 2.0.7 + '@cacheable/utils': 2.3.4 + hookified: 1.15.1 + keyv: 5.6.0 + qified: 0.6.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsite@1.0.0: {} + + callsites@3.1.0: {} + + camel-case@4.1.2: + dependencies: + pascal-case: 3.1.2 + tslib: 2.8.1 + + camelcase-css@2.0.1: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + camelcase@8.0.0: {} + + camunda-bpmn-js-behaviors@1.14.0(bpmn-js@17.11.1)(camunda-bpmn-moddle@7.0.1)(zeebe-bpmn-moddle@1.12.0): + dependencies: + bpmn-js: 17.11.1 + camunda-bpmn-moddle: 7.0.1 + ids: 3.0.1 + min-dash: 5.0.0 + zeebe-bpmn-moddle: 1.12.0 + + camunda-bpmn-moddle@7.0.1: {} + + caniuse-api@3.0.0: + dependencies: + browserslist: 4.28.1 + caniuse-lite: 1.0.30001769 + lodash.memoize: 4.1.2 + lodash.uniq: 4.5.0 + + caniuse-lite@1.0.30001769: {} + + ccount@2.0.1: {} + + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + + chalk-template@1.1.2: + dependencies: + chalk: 5.6.2 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + change-case@5.4.4: {} + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + chardet@2.1.1: {} + + check-error@2.1.3: {} + + cheerio-select@2.1.0: + dependencies: + boolbase: 1.0.0 + css-select: 5.2.2 + css-what: 6.2.2 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + + cheerio@1.0.0-rc.12: + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.2.2 + htmlparser2: 8.0.2 + parse5: 7.3.0 + parse5-htmlparser2-tree-adapter: 7.1.0 + + cheerio@1.2.0: + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.2.2 + encoding-sniffer: 0.2.1 + htmlparser2: 10.1.0 + parse5: 7.3.0 + parse5-htmlparser2-tree-adapter: 7.1.0 + parse5-parser-stream: 7.1.2 + undici: 7.21.0 + whatwg-mimetype: 4.0.0 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + chownr@3.0.0: {} + + ci-info@3.9.0: {} + + ci-info@4.4.0: {} + + circular-dependency-scanner@2.3.0: + dependencies: + '@ast-grep/napi': 0.39.9 + '@vue/compiler-sfc': 3.5.28 + commander: 12.1.0 + get-tsconfig: 4.13.6 + graph-cycles: 3.0.0 + listr2: 8.3.3 + minimatch: 9.0.5 + node-cleanup: 2.1.2 + typescript: 5.9.3 + update-notifier: 7.3.1 + zx: 8.8.5 + + citty@0.1.6: + dependencies: + consola: 3.4.2 + + citty@0.2.0: {} + + class-variance-authority@0.7.1: + dependencies: + clsx: 2.1.1 + + classnames@2.5.1: {} + + clean-css@5.3.3: + dependencies: + source-map: 0.6.1 + + clean-regexp@1.0.0: + dependencies: + escape-string-regexp: 1.0.5 + + clear-module@4.1.2: + dependencies: + parent-module: 2.0.0 + resolve-from: 5.0.0 + + cli-boxes@3.0.0: {} + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + clipboard@2.0.11: + dependencies: + good-listener: 1.2.2 + select: 1.1.2 + tiny-emitter: 2.1.0 + + clipboardy@4.0.0: + dependencies: + execa: 8.0.1 + is-wsl: 3.1.0 + is64bit: 2.0.0 + + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clsx@2.1.1: {} + + cluster-key-slot@1.1.2: {} + + codemirror@5.65.21: {} + + codemirror@6.65.7: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colord@2.9.3: {} + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + comma-separated-tokens@2.0.3: {} + + commander@10.0.1: {} + + commander@11.1.0: {} + + commander@12.1.0: {} + + commander@14.0.3: {} + + commander@2.20.3: {} + + commander@4.1.1: {} + + commander@7.2.0: {} + + commander@8.3.0: {} + + comment-json@4.5.1: + dependencies: + array-timsort: 1.0.3 + core-util-is: 1.0.3 + esprima: 4.0.1 + + comment-parser@1.4.1: {} + + comment-parser@1.4.5: {} + + commitlint-plugin-function-rules@4.3.1(@commitlint/lint@19.8.1): + dependencies: + '@commitlint/lint': 19.8.1 + + common-tags@1.8.2: {} + + commondir@1.0.1: {} + + compare-func@2.0.0: + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + + compare-versions@6.1.1: {} + + compatx@0.2.0: {} + + component-event@0.2.1: {} + + compress-commons@6.0.2: + dependencies: + crc-32: 1.2.2 + crc32-stream: 6.0.0 + is-stream: 2.0.1 + normalize-path: 3.0.0 + readable-stream: 4.7.0 + + compute-scroll-into-view@1.0.20: {} + + compute-scroll-into-view@3.1.1: {} + + concat-map@0.0.1: {} + + confbox@0.1.8: {} + + confbox@0.2.4: {} + + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + + configstore@7.1.0: + dependencies: + atomically: 2.1.1 + dot-prop: 9.0.0 + graceful-fs: 4.2.11 + xdg-basedir: 5.1.0 + + connect-history-api-fallback@1.6.0: {} + + consola@2.15.3: {} + + consola@3.4.2: {} + + conventional-changelog-angular@7.0.0: + dependencies: + compare-func: 2.0.0 + + conventional-changelog-conventionalcommits@7.0.2: + dependencies: + compare-func: 2.0.0 + + conventional-commits-parser@5.0.0: + dependencies: + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 + + convert-source-map@2.0.0: {} + + cookie-es@1.2.2: {} + + cookie-es@2.0.0: {} + + copy-anything@2.0.6: + dependencies: + is-what: 3.14.1 + + copy-anything@4.0.5: + dependencies: + is-what: 5.5.0 + + core-js-compat@3.48.0: + dependencies: + browserslist: 4.28.1 + + core-js-pure@3.48.0: {} + + core-js@3.48.0: {} + + core-util-is@1.0.3: {} + + cosmiconfig-typescript-loader@6.2.0(@types/node@24.10.13)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3): + dependencies: + '@types/node': 24.10.13 + cosmiconfig: 9.0.0(typescript@5.9.3) + jiti: 2.6.1 + typescript: 5.9.3 + + cosmiconfig@7.1.0: + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.1 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + + cosmiconfig@9.0.0(typescript@5.9.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.9.3 + + crc-32@1.2.2: {} + + crc32-stream@6.0.0: + dependencies: + crc-32: 1.2.2 + readable-stream: 4.7.0 + + crelt@1.0.6: {} + + croner@9.1.0: {} + + cropperjs@1.6.2: {} + + cross-env@10.1.0: + dependencies: + '@epic-web/invariant': 1.0.0 + cross-spawn: 7.0.6 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crossws@0.3.5: + dependencies: + uncrypto: 0.1.3 + + crypto-js@4.2.0: {} + + crypto-random-string@2.0.0: {} + + cspell-config-lib@9.6.4: + dependencies: + '@cspell/cspell-types': 9.6.4 + comment-json: 4.5.1 + smol-toml: 1.6.0 + yaml: 2.8.2 + + cspell-dictionary@9.6.4: + dependencies: + '@cspell/cspell-performance-monitor': 9.6.4 + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-types': 9.6.4 + cspell-trie-lib: 9.6.4(@cspell/cspell-types@9.6.4) + fast-equals: 6.0.0 + + cspell-gitignore@9.6.4: + dependencies: + '@cspell/url': 9.6.4 + cspell-glob: 9.6.4 + cspell-io: 9.6.4 + + cspell-glob@9.6.4: + dependencies: + '@cspell/url': 9.6.4 + picomatch: 4.0.3 + + cspell-grammar@9.6.4: + dependencies: + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-types': 9.6.4 + + cspell-io@9.6.4: + dependencies: + '@cspell/cspell-service-bus': 9.6.4 + '@cspell/url': 9.6.4 + + cspell-lib@9.6.4: + dependencies: + '@cspell/cspell-bundled-dicts': 9.6.4 + '@cspell/cspell-performance-monitor': 9.6.4 + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-resolver': 9.6.4 + '@cspell/cspell-types': 9.6.4 + '@cspell/dynamic-import': 9.6.4 + '@cspell/filetypes': 9.6.4 + '@cspell/rpc': 9.6.4 + '@cspell/strong-weak-map': 9.6.4 + '@cspell/url': 9.6.4 + clear-module: 4.1.2 + cspell-config-lib: 9.6.4 + cspell-dictionary: 9.6.4 + cspell-glob: 9.6.4 + cspell-grammar: 9.6.4 + cspell-io: 9.6.4 + cspell-trie-lib: 9.6.4(@cspell/cspell-types@9.6.4) + env-paths: 4.0.0 + gensequence: 8.0.8 + import-fresh: 3.3.1 + resolve-from: 5.0.0 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + xdg-basedir: 5.1.0 + + cspell-trie-lib@9.6.4(@cspell/cspell-types@9.6.4): + dependencies: + '@cspell/cspell-types': 9.6.4 + + cspell@9.6.4: + dependencies: + '@cspell/cspell-json-reporter': 9.6.4 + '@cspell/cspell-performance-monitor': 9.6.4 + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-types': 9.6.4 + '@cspell/cspell-worker': 9.6.4 + '@cspell/dynamic-import': 9.6.4 + '@cspell/url': 9.6.4 + ansi-regex: 6.2.2 + chalk: 5.6.2 + chalk-template: 1.1.2 + commander: 14.0.3 + cspell-config-lib: 9.6.4 + cspell-dictionary: 9.6.4 + cspell-gitignore: 9.6.4 + cspell-glob: 9.6.4 + cspell-io: 9.6.4 + cspell-lib: 9.6.4 + fast-json-stable-stringify: 2.1.0 + flatted: 3.3.3 + semver: 7.7.4 + tinyglobby: 0.2.15 + + css-blank-pseudo@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + css-declaration-sorter@7.3.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + css-functions-list@3.3.3: {} + + css-has-pseudo@7.0.3(postcss@8.5.6): + dependencies: + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + postcss-value-parser: 4.2.0 + + css-prefers-color-scheme@10.0.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + css-render@0.15.14: + dependencies: + '@emotion/hash': 0.8.0 + csstype: 3.0.11 + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-tree@2.2.1: + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.2.1 + + css-tree@3.1.0: + dependencies: + mdn-data: 2.12.2 + source-map-js: 1.2.1 + + css-what@6.2.2: {} + + cssdb@8.7.1: {} + + cssesc@3.0.0: {} + + cssnano-preset-default@7.0.10(postcss@8.5.6): + dependencies: + browserslist: 4.28.1 + css-declaration-sorter: 7.3.1(postcss@8.5.6) + cssnano-utils: 5.0.1(postcss@8.5.6) + postcss: 8.5.6 + postcss-calc: 10.1.1(postcss@8.5.6) + postcss-colormin: 7.0.5(postcss@8.5.6) + postcss-convert-values: 7.0.8(postcss@8.5.6) + postcss-discard-comments: 7.0.5(postcss@8.5.6) + postcss-discard-duplicates: 7.0.2(postcss@8.5.6) + postcss-discard-empty: 7.0.1(postcss@8.5.6) + postcss-discard-overridden: 7.0.1(postcss@8.5.6) + postcss-merge-longhand: 7.0.5(postcss@8.5.6) + postcss-merge-rules: 7.0.7(postcss@8.5.6) + postcss-minify-font-values: 7.0.1(postcss@8.5.6) + postcss-minify-gradients: 7.0.1(postcss@8.5.6) + postcss-minify-params: 7.0.5(postcss@8.5.6) + postcss-minify-selectors: 7.0.5(postcss@8.5.6) + postcss-normalize-charset: 7.0.1(postcss@8.5.6) + postcss-normalize-display-values: 7.0.1(postcss@8.5.6) + postcss-normalize-positions: 7.0.1(postcss@8.5.6) + postcss-normalize-repeat-style: 7.0.1(postcss@8.5.6) + postcss-normalize-string: 7.0.1(postcss@8.5.6) + postcss-normalize-timing-functions: 7.0.1(postcss@8.5.6) + postcss-normalize-unicode: 7.0.5(postcss@8.5.6) + postcss-normalize-url: 7.0.1(postcss@8.5.6) + postcss-normalize-whitespace: 7.0.1(postcss@8.5.6) + postcss-ordered-values: 7.0.2(postcss@8.5.6) + postcss-reduce-initial: 7.0.5(postcss@8.5.6) + postcss-reduce-transforms: 7.0.1(postcss@8.5.6) + postcss-svgo: 7.1.0(postcss@8.5.6) + postcss-unique-selectors: 7.0.4(postcss@8.5.6) + + cssnano-utils@5.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + cssnano@7.1.2(postcss@8.5.6): + dependencies: + cssnano-preset-default: 7.0.10(postcss@8.5.6) + lilconfig: 3.1.3 + postcss: 8.5.6 + + csso@5.0.5: + dependencies: + css-tree: 2.2.1 + + csstype@3.0.11: {} + + csstype@3.2.3: {} + + cz-git@1.12.0: {} + + czg@1.12.0: {} + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-axis@3.0.0: {} + + d3-brush@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3-chord@3.0.1: + dependencies: + d3-path: 3.1.0 + + d3-color@3.1.0: {} + + d3-contour@4.0.2: + dependencies: + d3-array: 3.2.4 + + d3-delaunay@6.0.4: + dependencies: + delaunator: 5.0.1 + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-dsv@3.0.1: + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + + d3-ease@3.0.1: {} + + d3-fetch@3.0.1: + dependencies: + d3-dsv: 3.0.1 + + d3-flextree@2.1.2: + dependencies: + d3-hierarchy: 1.1.9 + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-format@3.1.2: {} + + d3-geo@3.1.1: + dependencies: + d3-array: 3.2.4 + + d3-hierarchy@1.1.9: {} + + d3-hierarchy@3.1.2: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@3.1.0: {} + + d3-polygon@3.0.1: {} + + d3-quadtree@3.0.1: {} + + d3-random@3.0.1: {} + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.2 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-selection@3.0.0: {} + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3@7.9.0: + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.2 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + + dargs@8.1.0: {} + + data-uri-to-buffer@4.0.1: {} + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + dataloader@1.4.0: {} + + date-fns-tz@3.2.0(date-fns@4.1.0): + dependencies: + date-fns: 4.1.0 + + date-fns@4.1.0: {} + + dayjs@1.11.19: {} + + db0@0.3.4: {} + + de-indent@1.0.2: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decamelize@1.2.0: {} + + deep-eql@5.0.2: {} + + deep-extend@0.6.0: {} + + deep-is@0.1.4: {} + + deepmerge@4.3.1: {} + + default-browser-id@5.0.1: {} + + default-browser@5.5.0: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + + default-passive-events@2.0.0: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@2.0.0: {} + + define-lazy-prop@3.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + defu@6.1.4: {} + + delaunator@5.0.1: + dependencies: + robust-predicates: 3.0.2 + + delayed-stream@1.0.0: {} + + delegate@3.2.0: {} + + denque@2.1.0: {} + + depcheck@1.4.7: + dependencies: + '@babel/parser': 7.29.0 + '@babel/traverse': 7.29.0 + '@vue/compiler-sfc': 3.5.28 + callsite: 1.0.0 + camelcase: 6.3.0 + cosmiconfig: 7.1.0 + debug: 4.4.3 + deps-regex: 0.2.0 + findup-sync: 5.0.0 + ignore: 5.3.2 + is-core-module: 2.16.1 + js-yaml: 3.14.2 + json5: 2.2.3 + lodash: 4.17.23 + minimatch: 7.4.6 + multimatch: 5.0.0 + please-upgrade-node: 3.2.0 + readdirp: 3.6.0 + require-package-name: 2.0.1 + resolve: 1.22.11 + resolve-from: 5.0.0 + semver: 7.7.4 + yargs: 16.2.0 + transitivePeerDependencies: + - supports-color + + depd@2.0.0: {} + + deps-regex@0.2.0: {} + + dequal@2.0.3: {} + + destr@2.0.5: {} + + detect-file@1.0.0: {} + + detect-indent@6.1.0: {} + + detect-libc@2.1.2: {} + + devalue@5.6.2: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diagram-js-direct-editing@3.3.0(diagram-js@14.11.3): + dependencies: + diagram-js: 14.11.3 + min-dash: 5.0.0 + min-dom: 5.2.0 + + diagram-js@12.8.1: + dependencies: + '@bpmn-io/diagram-js-ui': 0.2.3 + clsx: 2.1.1 + didi: 9.0.2 + hammerjs: 2.0.8 + inherits-browser: 0.1.0 + min-dash: 4.2.3 + min-dom: 4.2.1 + object-refs: 0.3.0 + path-intersection: 2.2.1 + tiny-svg: 3.1.3 + + diagram-js@14.11.3: + dependencies: + '@bpmn-io/diagram-js-ui': 0.2.3 + clsx: 2.1.1 + didi: 10.2.2 + inherits-browser: 0.1.0 + min-dash: 4.2.3 + min-dom: 4.2.1 + object-refs: 0.4.0 + path-intersection: 3.1.0 + tiny-svg: 3.1.3 + + didi@10.2.2: {} + + didi@9.0.2: {} + + didyoumean@1.2.2: {} + + diff-sequences@27.5.1: {} + + diff@8.0.3: {} + + dijkstrajs@1.0.3: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dlv@1.1.3: {} + + dom-align@1.12.4: {} + + dom-scroll-into-view@2.0.1: {} + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + dom-walk@0.1.2: {} + + dom-zindex@1.0.6: {} + + domelementtype@2.3.0: {} + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domify@1.4.2: {} + + domify@2.0.0: {} + + dompurify@3.3.1: + optionalDependencies: + '@types/trusted-types': 2.0.7 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + dot-prop@10.1.0: + dependencies: + type-fest: 5.4.4 + + dot-prop@5.3.0: + dependencies: + is-obj: 2.0.0 + + dot-prop@9.0.0: + dependencies: + type-fest: 4.41.0 + + dotenv-expand@8.0.3: {} + + dotenv@16.0.3: {} + + dotenv@16.6.1: {} + + dotenv@17.2.4: {} + + dotenv@8.6.0: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer@0.1.2: {} + + eastasianwidth@0.2.0: {} + + echarts@6.0.0: + dependencies: + tslib: 2.3.0 + zrender: 6.0.0 + + editorconfig@1.0.4: + dependencies: + '@one-ini/wasm': 0.1.1 + commander: 10.0.1 + minimatch: 9.0.1 + semver: 7.7.4 + + ee-first@1.1.1: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.4 + + electron-to-chromium@1.5.286: {} + + element-plus@2.13.2(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@ctrl/tinycolor': 4.2.0 + '@element-plus/icons-vue': 2.3.2(vue@3.5.28(typescript@5.9.3)) + '@floating-ui/dom': 1.7.5 + '@popperjs/core': '@sxzz/popperjs-es@2.11.8' + '@types/lodash': 4.17.23 + '@types/lodash-es': 4.17.12 + '@vueuse/core': 10.11.1(vue@3.5.28(typescript@5.9.3)) + async-validator: 4.2.5 + dayjs: 1.11.19 + lodash: 4.17.23 + lodash-es: 4.17.23 + lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.23)(lodash@4.17.23) + memoize-one: 6.0.0 + normalize-wheel-es: 1.2.0 + vue: 3.5.28(typescript@5.9.3) + transitivePeerDependencies: + - '@vue/composition-api' + + emoji-regex-xs@1.0.0: {} + + emoji-regex@10.6.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + empathic@2.0.0: {} + + encodeurl@2.0.0: {} + + encoding-sniffer@0.2.1: + dependencies: + iconv-lite: 0.6.3 + whatwg-encoding: 3.1.1 + + enhanced-resolve@5.19.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.0 + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + + entities@2.2.0: {} + + entities@4.5.0: {} + + entities@6.0.1: {} + + entities@7.0.1: {} + + env-paths@2.2.1: {} + + env-paths@4.0.0: + dependencies: + is-safe-filename: 0.1.1 + + environment@1.1.0: {} + + errno@0.1.8: + dependencies: + prr: 1.0.1 + optional: true + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + error-stack-parser-es@1.0.5: {} + + errx@0.1.0: {} + + es-abstract@1.24.1: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.20 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@1.7.0: {} + + es-module-lexer@2.0.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + es-toolkit@1.43.0: {} + + es-toolkit@1.44.0: {} + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + escalade@3.2.0: {} + + escape-goat@4.0.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + escape-string-regexp@5.0.0: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-compat-utils@0.5.1(eslint@9.39.2(jiti@2.6.1)): + dependencies: + eslint: 9.39.2(jiti@2.6.1) + semver: 7.7.4 + + eslint-compat-utils@0.6.5(eslint@9.39.2(jiti@2.6.1)): + dependencies: + eslint: 9.39.2(jiti@2.6.1) + semver: 7.7.4 + + eslint-config-turbo@2.8.5(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.5): + dependencies: + eslint: 9.39.2(jiti@2.6.1) + eslint-plugin-turbo: 2.8.5(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.5) + turbo: 2.8.5 + + eslint-import-context@0.1.9(unrs-resolver@1.11.1): + dependencies: + get-tsconfig: 4.13.6 + stable-hash-x: 0.2.0 + optionalDependencies: + unrs-resolver: 1.11.1 + + eslint-json-compat-utils@0.2.1(eslint@9.39.2(jiti@2.6.1))(jsonc-eslint-parser@2.4.2): + dependencies: + eslint: 9.39.2(jiti@2.6.1) + esquery: 1.7.0 + jsonc-eslint-parser: 2.4.2 + + eslint-plugin-command@3.4.0(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@es-joy/jsdoccomment': 0.78.0 + eslint: 9.39.2(jiti@2.6.1) + + eslint-plugin-es-x@7.8.0(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + eslint: 9.39.2(jiti@2.6.1) + eslint-compat-utils: 0.5.1(eslint@9.39.2(jiti@2.6.1)) + + eslint-plugin-eslint-comments@3.2.0(eslint@9.39.2(jiti@2.6.1)): + dependencies: + escape-string-regexp: 1.0.5 + eslint: 9.39.2(jiti@2.6.1) + ignore: 5.3.2 + + eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@typescript-eslint/types': 8.55.0 + comment-parser: 1.4.5 + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + eslint-import-context: 0.1.9(unrs-resolver@1.11.1) + is-glob: 4.0.3 + minimatch: 10.1.2 + semver: 7.7.4 + stable-hash-x: 0.2.0 + unrs-resolver: 1.11.1 + optionalDependencies: + '@typescript-eslint/utils': 8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + transitivePeerDependencies: + - supports-color + + eslint-plugin-jsdoc@61.7.1(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@es-joy/jsdoccomment': 0.78.0 + '@es-joy/resolve.exports': 1.2.0 + are-docs-informative: 0.0.2 + comment-parser: 1.4.1 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint: 9.39.2(jiti@2.6.1) + espree: 11.1.0 + esquery: 1.7.0 + html-entities: 2.6.0 + object-deep-merge: 2.0.0 + parse-imports-exports: 0.2.4 + semver: 7.7.4 + spdx-expression-parse: 4.0.0 + to-valid-identifier: 1.0.0 + transitivePeerDependencies: + - supports-color + + eslint-plugin-jsonc@2.21.1(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + diff-sequences: 27.5.1 + eslint: 9.39.2(jiti@2.6.1) + eslint-compat-utils: 0.6.5(eslint@9.39.2(jiti@2.6.1)) + eslint-json-compat-utils: 0.2.1(eslint@9.39.2(jiti@2.6.1))(jsonc-eslint-parser@2.4.2) + espree: 10.4.0 + graphemer: 1.4.0 + jsonc-eslint-parser: 2.4.2 + natural-compare: 1.4.0 + synckit: 0.11.12 + transitivePeerDependencies: + - '@eslint/json' + + eslint-plugin-n@17.23.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + enhanced-resolve: 5.19.0 + eslint: 9.39.2(jiti@2.6.1) + eslint-plugin-es-x: 7.8.0(eslint@9.39.2(jiti@2.6.1)) + get-tsconfig: 4.13.6 + globals: 15.15.0 + globrex: 0.1.2 + ignore: 5.3.2 + semver: 7.7.4 + ts-declaration-location: 1.0.7(typescript@5.9.3) + transitivePeerDependencies: + - typescript + + eslint-plugin-no-only-tests@3.3.0: {} + + eslint-plugin-perfectionist@4.15.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): + dependencies: + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/utils': 8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + natural-orderby: 5.0.0 + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-pnpm@1.5.0(eslint@9.39.2(jiti@2.6.1)): + dependencies: + empathic: 2.0.0 + eslint: 9.39.2(jiti@2.6.1) + jsonc-eslint-parser: 2.4.2 + pathe: 2.0.3 + pnpm-workspace-yaml: 1.5.0 + tinyglobby: 0.2.15 + yaml: 2.8.2 + yaml-eslint-parser: 2.0.0 + + eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1): + dependencies: + eslint: 9.39.2(jiti@2.6.1) + prettier: 3.8.1 + prettier-linter-helpers: 1.0.1 + synckit: 0.11.12 + optionalDependencies: + '@types/eslint': 9.6.1 + + eslint-plugin-regexp@2.10.0(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + comment-parser: 1.4.5 + eslint: 9.39.2(jiti@2.6.1) + jsdoc-type-pratt-parser: 4.8.0 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + scslre: 0.3.0 + + eslint-plugin-turbo@2.8.5(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.5): + dependencies: + dotenv: 16.0.3 + eslint: 9.39.2(jiti@2.6.1) + turbo: 2.8.5 + + eslint-plugin-unicorn@62.0.0(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@eslint/plugin-kit': 0.4.1 + change-case: 5.4.4 + ci-info: 4.4.0 + clean-regexp: 1.0.0 + core-js-compat: 3.48.0 + eslint: 9.39.2(jiti@2.6.1) + esquery: 1.7.0 + find-up-simple: 1.0.1 + globals: 16.5.0 + indent-string: 5.0.0 + is-builtin-module: 5.0.0 + jsesc: 3.1.0 + pluralize: 8.0.0 + regexp-tree: 0.1.27 + regjsparser: 0.13.0 + semver: 7.7.4 + strip-indent: 4.1.1 + + eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.55.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): + dependencies: + eslint: 9.39.2(jiti@2.6.1) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.55.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + + eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@8.55.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/node@25.2.3)(happy-dom@17.6.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + dependencies: + '@typescript-eslint/utils': 7.18.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.55.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + vitest: 3.2.4(@types/node@25.2.3)(happy-dom@17.6.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-vue@10.7.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.39.2(jiti@2.6.1))): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + eslint: 9.39.2(jiti@2.6.1) + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 7.1.1 + semver: 7.7.4 + vue-eslint-parser: 10.2.0(eslint@9.39.2(jiti@2.6.1)) + xml-name-validator: 4.0.0 + optionalDependencies: + '@typescript-eslint/parser': 8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + + eslint-plugin-yml@1.19.1(eslint@9.39.2(jiti@2.6.1)): + dependencies: + debug: 4.4.3 + diff-sequences: 27.5.1 + escape-string-regexp: 4.0.0 + eslint: 9.39.2(jiti@2.6.1) + eslint-compat-utils: 0.6.5(eslint@9.39.2(jiti@2.6.1)) + natural-compare: 1.4.0 + yaml-eslint-parser: 1.3.2 + transitivePeerDependencies: + - supports-color + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint-visitor-keys@5.0.0: {} + + eslint@9.39.2(jiti@2.6.1): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.3 + '@eslint/js': 9.39.2 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 + transitivePeerDependencies: + - supports-color + + esm-env@1.2.2: {} + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + espree@11.1.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 5.0.0 + + espree@9.6.1: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 3.4.3 + + esprima@4.0.1: {} + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrap@2.2.3: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@1.0.1: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + esutils@2.0.3: {} + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + eventemitter3@5.0.4: {} + + events-universal@1.0.1: + dependencies: + bare-events: 2.8.2 + transitivePeerDependencies: + - bare-abort-controller + + events@3.3.0: {} + + evtd@0.2.4: {} + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + execa@9.6.1: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.1 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.3.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.2 + + expand-tilde@2.0.2: + dependencies: + homedir-polyfill: 1.0.3 + + expect-type@1.3.0: {} + + exsolve@1.0.8: {} + + extend-shallow@2.0.1: + dependencies: + is-extendable: 0.1.1 + + extendable-error@0.1.7: {} + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + fast-equals@6.0.0: {} + + fast-fifo@1.3.2: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-string-compare@3.0.0: {} + + fast-uri@3.1.0: {} + + fast-xml-parser@4.5.3: + dependencies: + strnum: 1.1.2 + + fastest-levenshtein@1.0.16: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + feelers@1.5.1: + dependencies: + '@bpmn-io/cm-theme': 0.1.0-alpha.2 + '@bpmn-io/feel-lint': 3.1.0 + '@bpmn-io/feelin': 6.1.0 + '@bpmn-io/lezer-feel': 2.2.1 + '@codemirror/autocomplete': 6.20.0 + '@codemirror/commands': 6.10.2 + '@codemirror/language': 6.12.1 + '@codemirror/lint': 6.9.3 + '@codemirror/state': 6.5.4 + '@codemirror/view': 6.39.13 + '@lezer/common': 1.5.1 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.8 + '@lezer/markdown': 1.6.3 + min-dom: 5.2.0 + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + + file-entry-cache@11.1.2: + dependencies: + flat-cache: 6.1.20 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + file-uri-to-path@1.0.0: {} + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up-simple@1.0.1: {} + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + + findup-sync@5.0.0: + dependencies: + detect-file: 1.0.0 + is-glob: 4.0.3 + micromatch: 4.0.8 + resolve-dir: 1.0.1 + + fix-dts-default-cjs-exports@1.0.1: + dependencies: + magic-string: 0.30.21 + mlly: 1.8.0 + rollup: 4.57.1 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flat-cache@6.1.20: + dependencies: + cacheable: 2.3.2 + flatted: 3.3.3 + hookified: 1.15.1 + + flatted@3.3.3: {} + + focus-trap@7.8.0: + dependencies: + tabbable: 6.4.0 + + follow-redirects@1.15.11: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + formdata-node@6.0.3: {} + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + fraction.js@5.3.4: {} + + framesync@6.1.2: + dependencies: + tslib: 2.4.0 + + fresh@2.0.0: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-extra@11.3.3: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-minipass@3.0.3: + dependencies: + minipass: 7.1.2 + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + generator-function@2.0.1: {} + + gensequence@8.0.8: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.4.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-own-enumerable-property-symbols@3.0.2: {} + + get-port-please@3.2.0: {} + + get-port@7.1.0: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@8.0.1: {} + + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + get-tsconfig@4.13.6: + dependencies: + resolve-pkg-maps: 1.0.0 + + giget@2.0.0: + dependencies: + citty: 0.1.6 + consola: 3.4.2 + defu: 6.1.4 + node-fetch-native: 1.6.7 + nypm: 0.6.5 + pathe: 2.0.3 + + git-raw-commits@4.0.0: + dependencies: + dargs: 8.1.0 + meow: 12.1.1 + split2: 4.2.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@11.1.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.2.3 + minimatch: 10.1.2 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.1 + + glob@13.0.2: + dependencies: + minimatch: 10.1.2 + minipass: 7.1.2 + path-scurry: 2.0.1 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + global-modules@1.0.0: + dependencies: + global-prefix: 1.0.2 + is-windows: 1.0.2 + resolve-dir: 1.0.1 + + global-modules@2.0.0: + dependencies: + global-prefix: 3.0.0 + + global-prefix@1.0.2: + dependencies: + expand-tilde: 2.0.2 + homedir-polyfill: 1.0.3 + ini: 1.3.8 + is-windows: 1.0.2 + which: 1.3.1 + + global-prefix@3.0.0: + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + + global@4.4.0: + dependencies: + min-document: 2.19.2 + process: 0.11.10 + + globals@14.0.0: {} + + globals@15.15.0: {} + + globals@16.5.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + globby@14.1.0: + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.3 + ignore: 7.0.5 + path-type: 6.0.0 + slash: 5.1.0 + unicorn-magic: 0.3.0 + + globby@16.1.0: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + fast-glob: 3.3.3 + ignore: 7.0.5 + is-path-inside: 4.0.0 + slash: 5.1.0 + unicorn-magic: 0.4.0 + + globjoin@0.1.4: {} + + globrex@0.1.2: {} + + good-listener@1.2.2: + dependencies: + delegate: 3.2.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.10: {} + + graceful-fs@4.2.11: {} + + graph-cycles@3.0.0: + dependencies: + fast-string-compare: 3.0.0 + rotated-array-set: 3.0.0 + short-tree: 3.0.0 + + graphemer@1.4.0: {} + + gray-matter@4.0.3: + dependencies: + js-yaml: 3.14.2 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + + gzip-size@7.0.0: + dependencies: + duplexer: 0.1.2 + + h3@1.15.5: + dependencies: + cookie-es: 1.2.2 + crossws: 0.3.5 + defu: 6.1.4 + destr: 2.0.5 + iron-webcrypto: 1.2.1 + node-mock-http: 1.0.4 + radix3: 1.1.2 + ufo: 1.6.3 + uncrypto: 0.1.3 + + hammerjs@2.0.8: {} + + happy-dom@17.6.3: + dependencies: + webidl-conversions: 7.0.0 + whatwg-mimetype: 3.0.0 + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hashery@1.4.0: + dependencies: + hookified: 1.15.1 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + he@1.2.0: {} + + hey-listen@1.0.8: {} + + highlight.js@11.11.1: {} + + homedir-polyfill@1.0.3: + dependencies: + parse-passwd: 1.0.0 + + hookable@5.5.3: {} + + hookified@1.15.1: {} + + htm@3.1.1: {} + + html-entities@2.6.0: {} + + html-minifier-terser@6.1.0: + dependencies: + camel-case: 4.1.2 + clean-css: 5.3.3 + commander: 8.3.0 + he: 1.2.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 5.46.0 + + html-minifier-terser@7.2.0: + dependencies: + camel-case: 4.1.2 + clean-css: 5.3.3 + commander: 10.0.1 + entities: 4.5.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 5.46.0 + + html-tags@3.3.1: {} + + html-void-elements@3.0.0: {} + + htmlparser2@10.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 7.0.1 + + htmlparser2@8.0.2: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 4.5.0 + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + http-shutdown@1.2.2: {} + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + httpxy@0.1.7: {} + + human-id@4.1.3: {} + + human-signals@5.0.0: {} + + human-signals@8.0.1: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + + idb@7.1.1: {} + + ids@1.0.5: {} + + ids@3.0.1: {} + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + image-size@0.5.5: + optional: true + + immutable@5.1.4: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-lazy@4.0.0: {} + + import-meta-resolve@4.2.0: {} + + imurmurhash@0.1.4: {} + + indent-string@5.0.0: {} + + individual@2.0.0: {} + + inherits-browser@0.1.0: {} + + inherits@2.0.4: {} + + ini@1.3.8: {} + + ini@4.1.1: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + internmap@2.0.3: {} + + ioredis@5.9.2: + dependencies: + '@ioredis/commands': 1.5.0 + cluster-key-slot: 1.1.2 + debug: 4.4.3 + denque: 2.1.0 + lodash.defaults: 4.2.0 + lodash.isarguments: 3.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + + iron-webcrypto@1.2.1: {} + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.2.1: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-buffer@2.0.5: {} + + is-builtin-module@5.0.0: + dependencies: + builtin-modules: 5.0.0 + + is-callable@1.2.7: {} + + is-ci@4.1.0: + dependencies: + ci-info: 4.4.0 + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-docker@2.2.1: {} + + is-docker@3.0.0: {} + + is-extendable@0.1.1: {} + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.4.0 + + is-function@1.0.2: {} + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-in-ci@1.0.0: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-installed-globally@1.0.0: + dependencies: + global-directory: 4.0.1 + is-path-inside: 4.0.0 + + is-interactive@2.0.0: {} + + is-map@2.0.3: {} + + is-module@1.0.0: {} + + is-negative-zero@2.0.3: {} + + is-npm@6.1.0: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-obj@1.0.1: {} + + is-obj@2.0.0: {} + + is-path-inside@4.0.0: {} + + is-plain-obj@4.1.0: {} + + is-plain-object@3.0.1: {} + + is-plain-object@5.0.0: {} + + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.8 + + is-reference@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-regexp@1.0.0: {} + + is-safe-filename@0.1.1: {} + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-stream@2.0.1: {} + + is-stream@3.0.0: {} + + is-stream@4.0.1: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-text-path@2.0.0: + dependencies: + text-extensions: 2.4.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.20 + + is-unicode-supported@1.3.0: {} + + is-unicode-supported@2.1.0: {} + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-what@3.14.1: {} + + is-what@5.5.0: {} + + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + is64bit@2.0.0: + dependencies: + system-architecture: 0.1.0 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jackspeak@4.2.3: + dependencies: + '@isaacs/cliui': 9.0.0 + + jake@10.9.4: + dependencies: + async: 3.2.6 + filelist: 1.0.4 + picocolors: 1.1.1 + + jiti@2.6.1: {} + + jju@1.4.0: {} + + js-beautify@1.15.4: + dependencies: + config-chain: 1.1.13 + editorconfig: 1.0.4 + glob: 10.4.5 + js-cookie: 3.0.5 + nopt: 7.2.1 + + js-cookie@3.0.5: {} + + js-tokens@4.0.0: {} + + js-tokens@9.0.1: {} + + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsdoc-type-pratt-parser@4.8.0: {} + + jsdoc-type-pratt-parser@7.0.0: {} + + jsencrypt@3.5.4: {} + + jsesc@3.1.0: {} + + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-schema@0.4.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsonc-eslint-parser@2.4.2: + dependencies: + acorn: 8.15.0 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + semver: 7.7.4 + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonparse@1.3.1: {} + + jsonpointer@5.0.1: {} + + katex@0.16.28: + dependencies: + commander: 8.3.0 + + keycode@2.2.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + keyv@5.6.0: + dependencies: + '@keyv/serialize': 1.1.1 + + kind-of@6.0.3: {} + + kleur@4.1.5: {} + + klona@2.0.6: {} + + knitwork@1.3.0: {} + + known-css-properties@0.37.0: {} + + kolorist@1.8.0: {} + + ky@1.14.3: {} + + latest-version@9.0.0: + dependencies: + package-json: 10.0.1 + + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + + lefthook-darwin-arm64@2.1.0: + optional: true + + lefthook-darwin-x64@2.1.0: + optional: true + + lefthook-freebsd-arm64@2.1.0: + optional: true + + lefthook-freebsd-x64@2.1.0: + optional: true + + lefthook-linux-arm64@2.1.0: + optional: true + + lefthook-linux-x64@2.1.0: + optional: true + + lefthook-openbsd-arm64@2.1.0: + optional: true + + lefthook-openbsd-x64@2.1.0: + optional: true + + lefthook-windows-arm64@2.1.0: + optional: true + + lefthook-windows-x64@2.1.0: + optional: true + + lefthook@2.1.0: + optionalDependencies: + lefthook-darwin-arm64: 2.1.0 + lefthook-darwin-x64: 2.1.0 + lefthook-freebsd-arm64: 2.1.0 + lefthook-freebsd-x64: 2.1.0 + lefthook-linux-arm64: 2.1.0 + lefthook-linux-x64: 2.1.0 + lefthook-openbsd-arm64: 2.1.0 + lefthook-openbsd-x64: 2.1.0 + lefthook-windows-arm64: 2.1.0 + lefthook-windows-x64: 2.1.0 + + less@4.5.1: + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.8.1 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.3.1 + source-map: 0.6.1 + + leven@3.1.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + + listhen@1.9.0: + dependencies: + '@parcel/watcher': 2.5.6 + '@parcel/watcher-wasm': 2.5.6 + citty: 0.1.6 + clipboardy: 4.0.0 + consola: 3.4.2 + crossws: 0.3.5 + defu: 6.1.4 + get-port-please: 3.2.0 + h3: 1.15.5 + http-shutdown: 1.2.2 + jiti: 2.6.1 + mlly: 1.8.0 + node-forge: 1.3.3 + pathe: 1.1.2 + std-env: 3.10.0 + ufo: 1.6.3 + untun: 0.1.3 + uqr: 0.1.2 + + listr2@8.3.3: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.4 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 + + local-pkg@1.1.2: + dependencies: + mlly: 1.8.0 + pkg-types: 2.3.0 + quansync: 0.2.11 + + locate-character@3.0.0: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + locko@1.1.0: {} + + lodash-es@4.17.23: {} + + lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.23)(lodash@4.17.23): + dependencies: + '@types/lodash-es': 4.17.12 + lodash: 4.17.23 + lodash-es: 4.17.23 + + lodash.camelcase@4.3.0: {} + + lodash.clonedeep@4.5.0: {} + + lodash.debounce@4.0.8: {} + + lodash.defaults@4.2.0: {} + + lodash.isarguments@3.1.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.kebabcase@4.1.1: {} + + lodash.memoize@4.1.2: {} + + lodash.merge@4.6.2: {} + + lodash.mergewith@4.6.2: {} + + lodash.snakecase@4.1.1: {} + + lodash.sortby@4.7.0: {} + + lodash.startcase@4.4.0: {} + + lodash.truncate@4.4.2: {} + + lodash.uniq@4.5.0: {} + + lodash.upperfirst@4.3.1: {} + + lodash@4.17.23: {} + + log-symbols@6.0.0: + dependencies: + chalk: 5.6.2 + is-unicode-supported: 1.3.0 + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.3.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.1.2 + wrap-ansi: 9.0.2 + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@3.2.1: {} + + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + + lru-cache@10.4.3: {} + + lru-cache@11.2.6: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lucide-vue-next@0.553.0(vue@3.5.28(typescript@5.9.3)): + dependencies: + vue: 3.5.28(typescript@5.9.3) + + luxon@3.7.2: {} + + lz-string@1.5.0: {} + + m3u8-parser@4.8.0: + dependencies: + '@babel/runtime': 7.28.6 + '@videojs/vhs-utils': 3.0.5 + global: 4.4.0 + + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magicast@0.5.2: + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + source-map-js: 1.2.1 + + make-dir@2.1.0: + dependencies: + pify: 4.0.1 + semver: 5.7.2 + optional: true + + mark.js@8.11.1: {} + + markdown-it@14.1.0: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + + marked@17.0.1: {} + + markmap-common@0.16.0: + dependencies: + '@babel/runtime': 7.28.6 + '@gera2ld/jsx-dom': 2.2.2 + npm2url: 0.2.4 + + markmap-html-parser@0.16.1(markmap-common@0.16.0): + dependencies: + '@babel/runtime': 7.28.6 + cheerio: 1.0.0-rc.12 + markmap-common: 0.16.0 + + markmap-lib@0.16.1(markmap-common@0.16.0): + dependencies: + '@babel/runtime': 7.28.6 + highlight.js: 11.11.1 + js-yaml: 4.1.1 + katex: 0.16.28 + markmap-common: 0.16.0 + markmap-html-parser: 0.16.1(markmap-common@0.16.0) + markmap-view: 0.16.0(markmap-common@0.16.0) + prismjs: 1.30.0 + remarkable: 2.0.1 + remarkable-katex: 1.2.1 + + markmap-toolbar@0.17.2(markmap-common@0.16.0): + dependencies: + '@babel/runtime': 7.28.6 + '@gera2ld/jsx-dom': 2.2.2 + markmap-common: 0.16.0 + + markmap-view@0.16.0(markmap-common@0.16.0): + dependencies: + '@babel/runtime': 7.28.6 + '@gera2ld/jsx-dom': 2.2.2 + '@types/d3': 7.4.3 + d3: 7.9.0 + d3-flextree: 2.1.2 + markmap-common: 0.16.0 + + math-intrinsics@1.1.0: {} + + mathml-tag-names@2.1.3: {} + + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + + mdn-data@2.0.28: {} + + mdn-data@2.12.2: {} + + mdn-data@2.27.0: {} + + mdurl@2.0.0: {} + + medium-zoom@1.1.0: {} + + memoize-one@6.0.0: {} + + meow@12.1.1: {} + + meow@13.2.0: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-encode@2.0.1: {} + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + mime@1.6.0: + optional: true + + mime@4.1.0: {} + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + min-dash@4.2.3: {} + + min-dash@5.0.0: {} + + min-document@2.19.2: + dependencies: + dom-walk: 0.1.2 + + min-dom@4.2.1: + dependencies: + component-event: 0.2.1 + domify: 1.4.2 + min-dash: 4.2.3 + + min-dom@5.2.0: + dependencies: + domify: 2.0.0 + min-dash: 5.0.0 + + minimatch@10.1.2: + dependencies: + '@isaacs/brace-expansion': 5.0.1 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.2 + + minimatch@7.4.6: + dependencies: + brace-expansion: 2.0.2 + + minimatch@9.0.1: + dependencies: + brace-expansion: 2.0.2 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + minimist@1.2.8: {} + + minipass-collect@2.0.1: + dependencies: + minipass: 7.1.2 + + minipass-flush@1.0.5: + dependencies: + minipass: 3.3.6 + + minipass-pipeline@1.2.4: + dependencies: + minipass: 3.3.6 + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@7.1.2: {} + + minisearch@7.2.0: {} + + minizlib@3.1.0: + dependencies: + minipass: 7.1.2 + + mitt@3.0.1: {} + + mkdist@2.4.1(sass@1.97.3)(typescript@5.9.3)(vue-tsc@3.2.4(typescript@5.9.3))(vue@3.5.28(typescript@5.9.3)): + dependencies: + autoprefixer: 10.4.24(postcss@8.5.6) + citty: 0.1.6 + cssnano: 7.1.2(postcss@8.5.6) + defu: 6.1.4 + esbuild: 0.25.12 + jiti: 2.6.1 + mlly: 1.8.0 + pathe: 2.0.3 + pkg-types: 2.3.0 + postcss: 8.5.6 + postcss-nested: 7.0.2(postcss@8.5.6) + semver: 7.7.4 + tinyglobby: 0.2.15 + optionalDependencies: + sass: 1.97.3 + typescript: 5.9.3 + vue: 3.5.28(typescript@5.9.3) + vue-tsc: 3.2.4(typescript@5.9.3) + + mlly@1.8.0: + dependencies: + acorn: 8.15.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.3 + + moddle-xml@10.1.0: + dependencies: + min-dash: 4.2.3 + moddle: 6.2.3 + saxen: 8.1.2 + + moddle@6.2.3: + dependencies: + min-dash: 4.2.3 + + mpd-parser@0.22.1: + dependencies: + '@babel/runtime': 7.28.6 + '@videojs/vhs-utils': 3.0.5 + '@xmldom/xmldom': 0.8.11 + global: 4.4.0 + + mri@1.2.0: {} + + mrmime@2.0.1: {} + + ms@2.1.3: {} + + muggle-string@0.4.1: {} + + multimatch@5.0.0: + dependencies: + '@types/minimatch': 3.0.5 + array-differ: 3.0.0 + array-union: 2.1.0 + arrify: 2.0.1 + minimatch: 3.1.2 + + mux.js@6.0.1: + dependencies: + '@babel/runtime': 7.28.6 + global: 4.4.0 + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + naive-ui@2.43.2(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@css-render/plugin-bem': 0.15.14(css-render@0.15.14) + '@css-render/vue3-ssr': 0.15.14(vue@3.5.28(typescript@5.9.3)) + '@types/katex': 0.16.8 + '@types/lodash': 4.17.23 + '@types/lodash-es': 4.17.12 + async-validator: 4.2.5 + css-render: 0.15.14 + csstype: 3.2.3 + date-fns: 4.1.0 + date-fns-tz: 3.2.0(date-fns@4.1.0) + evtd: 0.2.4 + highlight.js: 11.11.1 + lodash: 4.17.23 + lodash-es: 4.17.23 + seemly: 0.3.10 + treemate: 0.3.11 + vdirs: 0.1.8(vue@3.5.28(typescript@5.9.3)) + vooks: 0.2.12(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + vueuc: 0.4.65(vue@3.5.28(typescript@5.9.3)) + + nanoid@3.3.11: {} + + nanoid@5.1.6: {} + + nanopop@2.4.2: {} + + napi-postinstall@0.3.4: {} + + natural-compare@1.4.0: {} + + natural-orderby@5.0.0: {} + + needle@3.3.1: + dependencies: + iconv-lite: 0.6.3 + sax: 1.4.4 + optional: true + + nitropack@2.13.1: + dependencies: + '@cloudflare/kv-asset-handler': 0.4.2 + '@rollup/plugin-alias': 6.0.0(rollup@4.57.1) + '@rollup/plugin-commonjs': 29.0.0(rollup@4.57.1) + '@rollup/plugin-inject': 5.0.5(rollup@4.57.1) + '@rollup/plugin-json': 6.1.0(rollup@4.57.1) + '@rollup/plugin-node-resolve': 16.0.3(rollup@4.57.1) + '@rollup/plugin-replace': 6.0.3(rollup@4.57.1) + '@rollup/plugin-terser': 0.4.4(rollup@4.57.1) + '@vercel/nft': 1.3.1(rollup@4.57.1) + archiver: 7.0.1 + c12: 3.3.3(magicast@0.5.2) + chokidar: 5.0.0 + citty: 0.1.6 + compatx: 0.2.0 + confbox: 0.2.4 + consola: 3.4.2 + cookie-es: 2.0.0 + croner: 9.1.0 + crossws: 0.3.5 + db0: 0.3.4 + defu: 6.1.4 + destr: 2.0.5 + dot-prop: 10.1.0 + esbuild: 0.25.12 + escape-string-regexp: 5.0.0 + etag: 1.8.1 + exsolve: 1.0.8 + globby: 16.1.0 + gzip-size: 7.0.0 + h3: 1.15.5 + hookable: 5.5.3 + httpxy: 0.1.7 + ioredis: 5.9.2 + jiti: 2.6.1 + klona: 2.0.6 + knitwork: 1.3.0 + listhen: 1.9.0 + magic-string: 0.30.21 + magicast: 0.5.2 + mime: 4.1.0 + mlly: 1.8.0 + node-fetch-native: 1.6.7 + node-mock-http: 1.0.4 + ofetch: 1.5.1 + ohash: 2.0.11 + pathe: 2.0.3 + perfect-debounce: 2.1.0 + pkg-types: 2.3.0 + pretty-bytes: 7.1.0 + radix3: 1.1.2 + rollup: 4.57.1 + rollup-plugin-visualizer: 6.0.5(rollup@4.57.1) + scule: 1.3.0 + semver: 7.7.4 + serve-placeholder: 2.0.2 + serve-static: 2.2.1 + source-map: 0.7.6 + std-env: 3.10.0 + ufo: 1.6.3 + ultrahtml: 1.6.0 + uncrypto: 0.1.3 + unctx: 2.5.0 + unenv: 2.0.0-rc.24 + unimport: 5.6.0 + unplugin-utils: 0.3.1 + unstorage: 1.17.4(db0@0.3.4)(ioredis@5.9.2) + untyped: 2.0.0 + unwasm: 0.5.3 + youch: 4.1.0-beta.13 + youch-core: 0.3.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@electric-sql/pglite' + - '@libsql/client' + - '@netlify/blobs' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bare-abort-controller + - better-sqlite3 + - drizzle-orm + - encoding + - idb-keyval + - mysql2 + - react-native-b4a + - rolldown + - sqlite3 + - supports-color + - uploadthing + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + node-addon-api@7.1.1: {} + + node-cleanup@2.1.2: {} + + node-domexception@1.0.0: {} + + node-fetch-cache@5.1.0: + dependencies: + cacache: 20.0.3 + formdata-node: 6.0.3 + locko: 1.1.0 + node-fetch: 3.3.2 + + node-fetch-native@1.6.7: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + node-forge@1.3.3: {} + + node-gyp-build@4.8.4: {} + + node-html-parser@5.4.2: + dependencies: + css-select: 4.3.0 + he: 1.2.0 + + node-mock-http@1.0.4: {} + + node-releases@2.0.27: {} + + nopt@7.2.1: + dependencies: + abbrev: 2.0.0 + + nopt@8.1.0: + dependencies: + abbrev: 3.0.1 + + normalize-path@3.0.0: {} + + normalize-wheel-es@1.2.0: {} + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + + npm2url@0.2.4: {} + + nprogress@0.2.0: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + nypm@0.6.5: + dependencies: + citty: 0.2.0 + pathe: 2.0.3 + tinyexec: 1.0.2 + + object-assign@4.1.1: {} + + object-deep-merge@2.0.0: {} + + object-hash@3.0.0: {} + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object-refs@0.3.0: {} + + object-refs@0.4.0: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + ofetch@1.5.1: + dependencies: + destr: 2.0.5 + node-fetch-native: 1.6.7 + ufo: 1.6.3 + + ohash@2.0.11: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + oniguruma-to-es@3.1.1: + dependencies: + emoji-regex-xs: 1.0.0 + regex: 6.1.0 + regex-recursion: 6.0.2 + + open@10.2.0: + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + ora@8.2.0: + dependencies: + chalk: 5.6.2 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.1.2 + + outdent@0.5.0: {} + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.2.2 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + + p-map@2.1.0: {} + + p-map@7.0.4: {} + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + package-json@10.0.1: + dependencies: + ky: 1.14.3 + registry-auth-token: 5.1.1 + registry-url: 6.0.1 + semver: 7.7.4 + + package-manager-detector@0.2.11: + dependencies: + quansync: 0.2.11 + + package-manager-detector@1.6.0: {} + + pako@2.1.0: {} + + param-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parent-module@2.0.0: + dependencies: + callsites: 3.1.0 + + parse-imports-exports@0.2.4: + dependencies: + parse-statements: 1.0.11 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.0 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-ms@4.0.0: {} + + parse-node-version@1.0.1: {} + + parse-passwd@1.0.0: {} + + parse-statements@1.0.11: {} + + parse5-htmlparser2-tree-adapter@7.1.0: + dependencies: + domhandler: 5.0.3 + parse5: 7.3.0 + + parse5-parser-stream@7.1.2: + dependencies: + parse5: 7.3.0 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + parseurl@1.3.3: {} + + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-exists@5.0.0: {} + + path-intersection@2.2.1: {} + + path-intersection@3.1.0: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-scurry@2.0.1: + dependencies: + lru-cache: 11.2.6 + minipass: 7.1.2 + + path-type@4.0.0: {} + + path-type@6.0.0: {} + + pathe@0.2.0: {} + + pathe@1.1.2: {} + + pathe@2.0.3: {} + + pathval@2.0.1: {} + + perfect-debounce@1.0.0: {} + + perfect-debounce@2.1.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + pify@2.3.0: {} + + pify@4.0.1: {} + + pinia-plugin-persistedstate@4.7.1(@nuxt/kit@4.3.1(magicast@0.5.2))(pinia@3.0.4(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3))): + dependencies: + defu: 6.1.4 + optionalDependencies: + '@nuxt/kit': 4.3.1(magicast@0.5.2) + pinia: 3.0.4(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)) + + pinia@3.0.4(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@vue/devtools-api': 7.7.9 + vue: 3.5.28(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + + pirates@4.0.7: {} + + pkcs7@1.0.4: + dependencies: + '@babel/runtime': 7.28.6 + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.0 + pathe: 2.0.3 + + pkg-types@2.3.0: + dependencies: + confbox: 0.2.4 + exsolve: 1.0.8 + pathe: 2.0.3 + + playwright-core@1.58.2: {} + + playwright@1.58.2: + dependencies: + playwright-core: 1.58.2 + optionalDependencies: + fsevents: 2.3.2 + + please-upgrade-node@3.2.0: + dependencies: + semver-compare: 1.0.0 + + pluralize@8.0.0: {} + + pngjs@5.0.0: {} + + pnpm-workspace-yaml@1.5.0: + dependencies: + yaml: 2.8.2 + + popmotion@11.0.5: + dependencies: + framesync: 6.1.2 + hey-listen: 1.0.8 + style-value-types: 5.1.2 + tslib: 2.4.0 + + possible-typed-array-names@1.1.0: {} + + postcss-antd-fixes@0.2.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-attribute-case-insensitive@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-calc@10.1.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + postcss-value-parser: 4.2.0 + + postcss-clamp@4.1.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-color-functional-notation@7.0.12(postcss@8.5.6): + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + postcss-color-hex-alpha@10.0.0(postcss@8.5.6): + dependencies: + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-color-rebeccapurple@10.0.0(postcss@8.5.6): + dependencies: + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-colormin@7.0.5(postcss@8.5.6): + dependencies: + browserslist: 4.28.1 + caniuse-api: 3.0.0 + colord: 2.9.3 + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-convert-values@7.0.8(postcss@8.5.6): + dependencies: + browserslist: 4.28.1 + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-custom-media@11.0.6(postcss@8.5.6): + dependencies: + '@csstools/cascade-layer-name-parser': 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + postcss: 8.5.6 + + postcss-custom-properties@14.0.6(postcss@8.5.6): + dependencies: + '@csstools/cascade-layer-name-parser': 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-custom-selectors@8.0.5(postcss@8.5.6): + dependencies: + '@csstools/cascade-layer-name-parser': 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-dir-pseudo-class@9.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-discard-comments@7.0.5(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-discard-duplicates@7.0.2(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-discard-empty@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-discard-overridden@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-double-position-gradients@6.0.4(postcss@8.5.6): + dependencies: + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-focus-visible@10.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-focus-within@9.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-font-variant@5.0.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-gap-properties@6.0.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-html@1.8.1: + dependencies: + htmlparser2: 8.0.2 + js-tokens: 9.0.1 + postcss: 8.5.6 + postcss-safe-parser: 6.0.0(postcss@8.5.6) + + postcss-image-set-function@7.0.0(postcss@8.5.6): + dependencies: + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-import@15.1.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.11 + + postcss-import@16.1.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.11 + + postcss-js@4.1.0(postcss@8.5.6): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.5.6 + + postcss-lab-function@7.0.12(postcss@8.5.6): + dependencies: + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/utilities': 2.0.0(postcss@8.5.6) + postcss: 8.5.6 + + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(yaml@2.8.2): + dependencies: + lilconfig: 3.1.3 + optionalDependencies: + jiti: 2.6.1 + postcss: 8.5.6 + yaml: 2.8.2 + + postcss-logical@8.1.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-media-query-parser@0.2.3: {} + + postcss-merge-longhand@7.0.5(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + stylehacks: 7.0.7(postcss@8.5.6) + + postcss-merge-rules@7.0.7(postcss@8.5.6): + dependencies: + browserslist: 4.28.1 + caniuse-api: 3.0.0 + cssnano-utils: 5.0.1(postcss@8.5.6) + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-minify-font-values@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-minify-gradients@7.0.1(postcss@8.5.6): + dependencies: + colord: 2.9.3 + cssnano-utils: 5.0.1(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-minify-params@7.0.5(postcss@8.5.6): + dependencies: + browserslist: 4.28.1 + cssnano-utils: 5.0.1(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-minify-selectors@7.0.5(postcss@8.5.6): + dependencies: + cssesc: 3.0.0 + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-nested@5.0.6(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 6.1.2 + + postcss-nested@6.2.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 6.1.2 + + postcss-nested@7.0.2(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-nesting@13.0.2(postcss@8.5.6): + dependencies: + '@csstools/selector-resolve-nested': 3.1.0(postcss-selector-parser@7.1.1) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-normalize-charset@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-normalize-display-values@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-normalize-positions@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-normalize-repeat-style@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-normalize-string@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-normalize-timing-functions@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-normalize-unicode@7.0.5(postcss@8.5.6): + dependencies: + browserslist: 4.28.1 + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-normalize-url@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-normalize-whitespace@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-opacity-percentage@3.0.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-ordered-values@7.0.2(postcss@8.5.6): + dependencies: + cssnano-utils: 5.0.1(postcss@8.5.6) + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-overflow-shorthand@6.0.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-page-break@3.0.4(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-place@10.0.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-preset-env@10.6.1(postcss@8.5.6): + dependencies: + '@csstools/postcss-alpha-function': 1.0.1(postcss@8.5.6) + '@csstools/postcss-cascade-layers': 5.0.2(postcss@8.5.6) + '@csstools/postcss-color-function': 4.0.12(postcss@8.5.6) + '@csstools/postcss-color-function-display-p3-linear': 1.0.1(postcss@8.5.6) + '@csstools/postcss-color-mix-function': 3.0.12(postcss@8.5.6) + '@csstools/postcss-color-mix-variadic-function-arguments': 1.0.2(postcss@8.5.6) + '@csstools/postcss-content-alt-text': 2.0.8(postcss@8.5.6) + '@csstools/postcss-contrast-color-function': 2.0.12(postcss@8.5.6) + '@csstools/postcss-exponential-functions': 2.0.9(postcss@8.5.6) + '@csstools/postcss-font-format-keywords': 4.0.0(postcss@8.5.6) + '@csstools/postcss-gamut-mapping': 2.0.11(postcss@8.5.6) + '@csstools/postcss-gradients-interpolation-method': 5.0.12(postcss@8.5.6) + '@csstools/postcss-hwb-function': 4.0.12(postcss@8.5.6) + '@csstools/postcss-ic-unit': 4.0.4(postcss@8.5.6) + '@csstools/postcss-initial': 2.0.1(postcss@8.5.6) + '@csstools/postcss-is-pseudo-class': 5.0.3(postcss@8.5.6) + '@csstools/postcss-light-dark-function': 2.0.11(postcss@8.5.6) + '@csstools/postcss-logical-float-and-clear': 3.0.0(postcss@8.5.6) + '@csstools/postcss-logical-overflow': 2.0.0(postcss@8.5.6) + '@csstools/postcss-logical-overscroll-behavior': 2.0.0(postcss@8.5.6) + '@csstools/postcss-logical-resize': 3.0.0(postcss@8.5.6) + '@csstools/postcss-logical-viewport-units': 3.0.4(postcss@8.5.6) + '@csstools/postcss-media-minmax': 2.0.9(postcss@8.5.6) + '@csstools/postcss-media-queries-aspect-ratio-number-values': 3.0.5(postcss@8.5.6) + '@csstools/postcss-nested-calc': 4.0.0(postcss@8.5.6) + '@csstools/postcss-normalize-display-values': 4.0.1(postcss@8.5.6) + '@csstools/postcss-oklab-function': 4.0.12(postcss@8.5.6) + '@csstools/postcss-position-area-property': 1.0.0(postcss@8.5.6) + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) + '@csstools/postcss-property-rule-prelude-list': 1.0.0(postcss@8.5.6) + '@csstools/postcss-random-function': 2.0.1(postcss@8.5.6) + '@csstools/postcss-relative-color-syntax': 3.0.12(postcss@8.5.6) + '@csstools/postcss-scope-pseudo-class': 4.0.1(postcss@8.5.6) + '@csstools/postcss-sign-functions': 1.1.4(postcss@8.5.6) + '@csstools/postcss-stepped-value-functions': 4.0.9(postcss@8.5.6) + '@csstools/postcss-syntax-descriptor-syntax-production': 1.0.1(postcss@8.5.6) + '@csstools/postcss-system-ui-font-family': 1.0.0(postcss@8.5.6) + '@csstools/postcss-text-decoration-shorthand': 4.0.3(postcss@8.5.6) + '@csstools/postcss-trigonometric-functions': 4.0.9(postcss@8.5.6) + '@csstools/postcss-unset-value': 4.0.0(postcss@8.5.6) + autoprefixer: 10.4.24(postcss@8.5.6) + browserslist: 4.28.1 + css-blank-pseudo: 7.0.1(postcss@8.5.6) + css-has-pseudo: 7.0.3(postcss@8.5.6) + css-prefers-color-scheme: 10.0.0(postcss@8.5.6) + cssdb: 8.7.1 + postcss: 8.5.6 + postcss-attribute-case-insensitive: 7.0.1(postcss@8.5.6) + postcss-clamp: 4.1.0(postcss@8.5.6) + postcss-color-functional-notation: 7.0.12(postcss@8.5.6) + postcss-color-hex-alpha: 10.0.0(postcss@8.5.6) + postcss-color-rebeccapurple: 10.0.0(postcss@8.5.6) + postcss-custom-media: 11.0.6(postcss@8.5.6) + postcss-custom-properties: 14.0.6(postcss@8.5.6) + postcss-custom-selectors: 8.0.5(postcss@8.5.6) + postcss-dir-pseudo-class: 9.0.1(postcss@8.5.6) + postcss-double-position-gradients: 6.0.4(postcss@8.5.6) + postcss-focus-visible: 10.0.1(postcss@8.5.6) + postcss-focus-within: 9.0.1(postcss@8.5.6) + postcss-font-variant: 5.0.0(postcss@8.5.6) + postcss-gap-properties: 6.0.0(postcss@8.5.6) + postcss-image-set-function: 7.0.0(postcss@8.5.6) + postcss-lab-function: 7.0.12(postcss@8.5.6) + postcss-logical: 8.1.0(postcss@8.5.6) + postcss-nesting: 13.0.2(postcss@8.5.6) + postcss-opacity-percentage: 3.0.0(postcss@8.5.6) + postcss-overflow-shorthand: 6.0.0(postcss@8.5.6) + postcss-page-break: 3.0.4(postcss@8.5.6) + postcss-place: 10.0.0(postcss@8.5.6) + postcss-pseudo-class-any-link: 10.0.1(postcss@8.5.6) + postcss-replace-overflow-wrap: 4.0.0(postcss@8.5.6) + postcss-selector-not: 8.0.1(postcss@8.5.6) + + postcss-pseudo-class-any-link@10.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-reduce-initial@7.0.5(postcss@8.5.6): + dependencies: + browserslist: 4.28.1 + caniuse-api: 3.0.0 + postcss: 8.5.6 + + postcss-reduce-transforms@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + postcss-replace-overflow-wrap@4.0.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-resolve-nested-selector@0.1.6: {} + + postcss-safe-parser@6.0.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-safe-parser@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-scss@4.0.9(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-selector-not@8.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-selector-parser@6.0.10: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-selector-parser@7.1.1: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-sorting@9.1.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-svgo@7.1.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + svgo: 4.0.0 + + postcss-unique-selectors@7.0.4(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + preact@10.28.3: {} + + prelude-ls@1.2.1: {} + + prettier-linter-helpers@1.0.1: + dependencies: + fast-diff: 1.3.0 + + prettier-plugin-tailwindcss@0.7.2(prettier@3.8.1): + dependencies: + prettier: 3.8.1 + + prettier@2.8.8: {} + + prettier@3.8.1: {} + + pretty-bytes@5.6.0: {} + + pretty-bytes@6.1.1: {} + + pretty-bytes@7.1.0: {} + + pretty-ms@9.3.0: + dependencies: + parse-ms: 4.0.0 + + prismjs@1.30.0: {} + + process-nextick-args@2.0.1: {} + + process@0.11.10: {} + + property-information@7.1.0: {} + + proto-list@1.2.4: {} + + proxy-from-env@1.1.0: {} + + prr@1.0.1: + optional: true + + publint@0.3.17: + dependencies: + '@publint/pack': 0.1.4 + package-manager-detector: 1.6.0 + picocolors: 1.1.1 + sade: 1.8.1 + + punycode.js@2.3.1: {} + + punycode@2.3.1: {} + + pupa@3.3.0: + dependencies: + escape-goat: 4.0.0 + + qified@0.6.0: + dependencies: + hookified: 1.15.1 + + qrcode@1.5.4: + dependencies: + dijkstrajs: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + + qs@6.14.1: + dependencies: + side-channel: 1.1.0 + + quansync@0.2.11: {} + + queue-microtask@1.2.3: {} + + radix3@1.1.2: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + randomcolor@0.6.2: {} + + range-parser@1.2.1: {} + + rc9@2.1.2: + dependencies: + defu: 6.1.4 + destr: 2.0.5 + + rc9@3.0.0: + dependencies: + defu: 6.1.4 + destr: 2.0.5 + + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + read-yaml-file@1.1.0: + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.2 + pify: 4.0.1 + strip-bom: 3.0.0 + + read-yaml-file@2.1.0: + dependencies: + js-yaml: 4.1.1 + strip-bom: 4.0.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.6 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@4.1.2: {} + + readdirp@5.0.0: {} + + redis-errors@1.2.0: {} + + redis-parser@3.0.0: + dependencies: + redis-errors: 1.2.0 + + refa@0.12.1: + dependencies: + '@eslint-community/regexpp': 4.12.2 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regenerate-unicode-properties@10.2.2: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.1.0: + dependencies: + regex-utilities: 2.3.0 + + regexp-ast-analysis@0.7.1: + dependencies: + '@eslint-community/regexpp': 4.12.2 + refa: 0.12.1 + + regexp-tree@0.1.27: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + regexpu-core@6.4.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.2 + regjsgen: 0.8.0 + regjsparser: 0.13.0 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.1 + + registry-auth-token@5.1.1: + dependencies: + '@pnpm/npm-conf': 3.0.2 + + registry-url@6.0.1: + dependencies: + rc: 1.2.8 + + regjsgen@0.8.0: {} + + regjsparser@0.13.0: + dependencies: + jsesc: 3.1.0 + + reka-ui@2.8.0(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@floating-ui/dom': 1.7.5 + '@floating-ui/vue': 1.1.10(vue@3.5.28(typescript@5.9.3)) + '@internationalized/date': 3.11.0 + '@internationalized/number': 3.6.5 + '@tanstack/vue-virtual': 3.13.18(vue@3.5.28(typescript@5.9.3)) + '@vueuse/core': 14.2.1(vue@3.5.28(typescript@5.9.3)) + '@vueuse/shared': 14.2.1(vue@3.5.28(typescript@5.9.3)) + aria-hidden: 1.2.6 + defu: 6.1.4 + ohash: 2.0.11 + vue: 3.5.28(typescript@5.9.3) + transitivePeerDependencies: + - '@vue/composition-api' + + relateurl@0.2.7: {} + + remarkable-katex@1.2.1: {} + + remarkable@2.0.1: + dependencies: + argparse: 1.0.10 + autolinker: 3.16.2 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + require-main-filename@2.0.0: {} + + require-package-name@2.0.1: {} + + reserved-identifiers@1.2.0: {} + + resize-observer-polyfill@1.5.1: {} + + resolve-dir@1.0.1: + dependencies: + expand-tilde: 2.0.2 + global-modules: 1.0.0 + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve.exports@2.0.3: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + rimraf@6.1.2: + dependencies: + glob: 13.0.2 + package-json-from-dist: 1.0.1 + + robust-predicates@3.0.2: {} + + rolldown-string@0.2.1: + dependencies: + magic-string: 0.30.21 + + rollup-plugin-dts@6.3.0(rollup@4.57.1)(typescript@5.9.3): + dependencies: + magic-string: 0.30.21 + rollup: 4.57.1 + typescript: 5.9.3 + optionalDependencies: + '@babel/code-frame': 7.29.0 + + rollup-plugin-visualizer@5.14.0(rollup@4.57.1): + dependencies: + open: 8.4.2 + picomatch: 4.0.3 + source-map: 0.7.6 + yargs: 17.7.2 + optionalDependencies: + rollup: 4.57.1 + + rollup-plugin-visualizer@6.0.5(rollup@4.57.1): + dependencies: + open: 8.4.2 + picomatch: 4.0.3 + source-map: 0.7.6 + yargs: 17.7.2 + optionalDependencies: + rollup: 4.57.1 + + rollup@2.79.2: + optionalDependencies: + fsevents: 2.3.3 + + rollup@4.57.1: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.57.1 + '@rollup/rollup-android-arm64': 4.57.1 + '@rollup/rollup-darwin-arm64': 4.57.1 + '@rollup/rollup-darwin-x64': 4.57.1 + '@rollup/rollup-freebsd-arm64': 4.57.1 + '@rollup/rollup-freebsd-x64': 4.57.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 + '@rollup/rollup-linux-arm-musleabihf': 4.57.1 + '@rollup/rollup-linux-arm64-gnu': 4.57.1 + '@rollup/rollup-linux-arm64-musl': 4.57.1 + '@rollup/rollup-linux-loong64-gnu': 4.57.1 + '@rollup/rollup-linux-loong64-musl': 4.57.1 + '@rollup/rollup-linux-ppc64-gnu': 4.57.1 + '@rollup/rollup-linux-ppc64-musl': 4.57.1 + '@rollup/rollup-linux-riscv64-gnu': 4.57.1 + '@rollup/rollup-linux-riscv64-musl': 4.57.1 + '@rollup/rollup-linux-s390x-gnu': 4.57.1 + '@rollup/rollup-linux-x64-gnu': 4.57.1 + '@rollup/rollup-linux-x64-musl': 4.57.1 + '@rollup/rollup-openbsd-x64': 4.57.1 + '@rollup/rollup-openharmony-arm64': 4.57.1 + '@rollup/rollup-win32-arm64-msvc': 4.57.1 + '@rollup/rollup-win32-ia32-msvc': 4.57.1 + '@rollup/rollup-win32-x64-gnu': 4.57.1 + '@rollup/rollup-win32-x64-msvc': 4.57.1 + fsevents: 2.3.3 + + rotated-array-set@3.0.0: {} + + run-applescript@7.1.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rust-result@1.0.0: + dependencies: + individual: 2.0.0 + + rw@1.3.3: {} + + sade@1.8.1: + dependencies: + mri: 1.2.0 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-json-parse@4.0.0: + dependencies: + rust-result: 1.0.0 + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safer-buffer@2.1.2: {} + + sass@1.97.3: + dependencies: + chokidar: 4.0.3 + immutable: 5.1.4 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.6 + + sax@1.4.4: {} + + saxen@8.1.2: {} + + scroll-into-view-if-needed@2.2.31: + dependencies: + compute-scroll-into-view: 1.0.20 + + scroll-into-view-if-needed@3.1.0: + dependencies: + compute-scroll-into-view: 3.1.1 + + scslre@0.3.0: + dependencies: + '@eslint-community/regexpp': 4.12.2 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + + scule@1.3.0: {} + + search-insights@2.17.3: {} + + section-matter@1.0.0: + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + + secure-ls@2.0.0: + dependencies: + crypto-js: 4.2.0 + lz-string: 1.5.0 + + seemly@0.3.10: {} + + select@1.1.2: {} + + semver-compare@1.0.0: {} + + semver@5.7.2: + optional: true + + semver@6.3.1: {} + + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + + semver@7.7.4: {} + + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + serve-placeholder@2.0.2: + dependencies: + defu: 6.1.4 + + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + + set-blocking@2.0.0: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + setprototypeof@1.2.0: {} + + shallow-equal@1.2.1: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shiki@2.5.0: + dependencies: + '@shikijs/core': 2.5.0 + '@shikijs/engine-javascript': 2.5.0 + '@shikijs/engine-oniguruma': 2.5.0 + '@shikijs/langs': 2.5.0 + '@shikijs/themes': 2.5.0 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + short-tree@3.0.0: + dependencies: + '@types/bintrees': 1.0.6 + bintrees: 1.0.2 + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + signature_pad@3.0.0-beta.4: {} + + signature_pad@5.1.3: {} + + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + slash@5.1.0: {} + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.2: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + + smob@1.5.0: {} + + smol-toml@1.6.0: {} + + sortablejs@1.14.0: {} + + sortablejs@1.15.6: {} + + source-map-js@1.2.1: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + source-map@0.7.6: {} + + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + + sourcemap-codec@1.4.8: {} + + space-separated-tokens@2.0.2: {} + + spawndamnit@3.0.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@4.0.0: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.22 + + spdx-license-ids@3.0.22: {} + + speakingurl@14.0.1: {} + + split2@4.2.0: {} + + sprintf-js@1.0.3: {} + + ssri@13.0.1: + dependencies: + minipass: 7.1.2 + + stable-hash-x@0.2.0: {} + + stackback@0.0.2: {} + + standard-as-callback@2.1.0: {} + + statuses@2.0.2: {} + + std-env@3.10.0: {} + + stdin-discarder@0.2.2: {} + + steady-xml@0.1.0: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + streamx@2.23.0: + dependencies: + events-universal: 1.0.1 + fast-fifo: 1.3.2 + text-decoder: 1.2.3 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + string-argv@0.3.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.2 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.4.0 + strip-ansi: 7.1.2 + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + stringify-object@3.3.0: + dependencies: + get-own-enumerable-property-symbols: 3.0.2 + is-obj: 1.0.1 + is-regexp: 1.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.2: + dependencies: + ansi-regex: 6.2.2 + + strip-bom-string@1.0.0: {} + + strip-bom@3.0.0: {} + + strip-bom@4.0.0: {} + + strip-comments@2.0.1: {} + + strip-final-newline@3.0.0: {} + + strip-final-newline@4.0.0: {} + + strip-indent@4.1.1: {} + + strip-json-comments@2.0.1: {} + + strip-json-comments@3.1.1: {} + + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + + strnum@1.1.2: {} + + stubborn-fs@2.0.0: + dependencies: + stubborn-utils: 1.0.2 + + stubborn-utils@1.0.2: {} + + style-mod@4.1.3: {} + + style-search@0.1.0: {} + + style-value-types@5.1.2: + dependencies: + hey-listen: 1.0.8 + tslib: 2.4.0 + + stylehacks@7.0.7(postcss@8.5.6): + dependencies: + browserslist: 4.28.1 + postcss: 8.5.6 + postcss-selector-parser: 7.1.1 + + stylelint-config-html@1.1.0(postcss-html@1.8.1)(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + postcss-html: 1.8.1 + stylelint: 16.26.1(typescript@5.9.3) + + stylelint-config-recess-order@7.6.1(stylelint-order@7.0.1(stylelint@16.26.1(typescript@5.9.3)))(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + stylelint: 16.26.1(typescript@5.9.3) + stylelint-order: 7.0.1(stylelint@16.26.1(typescript@5.9.3)) + + stylelint-config-recommended-scss@16.0.2(postcss@8.5.6)(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + postcss-scss: 4.0.9(postcss@8.5.6) + stylelint: 16.26.1(typescript@5.9.3) + stylelint-config-recommended: 17.0.0(stylelint@16.26.1(typescript@5.9.3)) + stylelint-scss: 6.14.0(stylelint@16.26.1(typescript@5.9.3)) + optionalDependencies: + postcss: 8.5.6 + + stylelint-config-recommended-vue@1.6.1(postcss-html@1.8.1)(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + postcss-html: 1.8.1 + semver: 7.7.4 + stylelint: 16.26.1(typescript@5.9.3) + stylelint-config-html: 1.1.0(postcss-html@1.8.1)(stylelint@16.26.1(typescript@5.9.3)) + stylelint-config-recommended: 17.0.0(stylelint@16.26.1(typescript@5.9.3)) + + stylelint-config-recommended@17.0.0(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + stylelint: 16.26.1(typescript@5.9.3) + + stylelint-config-standard@39.0.1(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + stylelint: 16.26.1(typescript@5.9.3) + stylelint-config-recommended: 17.0.0(stylelint@16.26.1(typescript@5.9.3)) + + stylelint-order@7.0.1(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + postcss: 8.5.6 + postcss-sorting: 9.1.0(postcss@8.5.6) + stylelint: 16.26.1(typescript@5.9.3) + + stylelint-prettier@5.0.3(prettier@3.8.1)(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + prettier: 3.8.1 + prettier-linter-helpers: 1.0.1 + stylelint: 16.26.1(typescript@5.9.3) + + stylelint-scss@6.14.0(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + css-tree: 3.1.0 + is-plain-object: 5.0.0 + known-css-properties: 0.37.0 + mdn-data: 2.27.0 + postcss-media-query-parser: 0.2.3 + postcss-resolve-nested-selector: 0.1.6 + postcss-selector-parser: 7.1.1 + postcss-value-parser: 4.2.0 + stylelint: 16.26.1(typescript@5.9.3) + + stylelint@16.26.1(typescript@5.9.3): + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-syntax-patches-for-csstree': 1.0.27 + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) + '@dual-bundle/import-meta-resolve': 4.2.1 + balanced-match: 2.0.0 + colord: 2.9.3 + cosmiconfig: 9.0.0(typescript@5.9.3) + css-functions-list: 3.3.3 + css-tree: 3.1.0 + debug: 4.4.3 + fast-glob: 3.3.3 + fastest-levenshtein: 1.0.16 + file-entry-cache: 11.1.2 + global-modules: 2.0.0 + globby: 11.1.0 + globjoin: 0.1.4 + html-tags: 3.3.1 + ignore: 7.0.5 + imurmurhash: 0.1.4 + is-plain-object: 5.0.0 + known-css-properties: 0.37.0 + mathml-tag-names: 2.1.3 + meow: 13.2.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-resolve-nested-selector: 0.1.6 + postcss-safe-parser: 7.0.1(postcss@8.5.6) + postcss-selector-parser: 7.1.1 + postcss-value-parser: 4.2.0 + resolve-from: 5.0.0 + string-width: 4.2.3 + supports-hyperlinks: 3.2.0 + svg-tags: 1.0.0 + table: 6.9.0 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + - typescript + + stylis@4.3.6: {} + + sucrase@3.35.1: + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + commander: 4.1.1 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + tinyglobby: 0.2.15 + ts-interface-checker: 0.1.13 + + superjson@2.2.6: + dependencies: + copy-anything: 4.0.5 + + supports-color@10.2.2: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-hyperlinks@3.2.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svelte@5.50.1: + dependencies: + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.5.5 + '@sveltejs/acorn-typescript': 1.0.8(acorn@8.15.0) + '@types/estree': 1.0.8 + acorn: 8.15.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + clsx: 2.1.1 + devalue: 5.6.2 + esm-env: 1.2.2 + esrap: 2.2.3 + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.21 + zimmerframe: 1.1.4 + + sver@2.0.1: {} + + svg-tags@1.0.0: {} + + svgo@4.0.0: + dependencies: + commander: 11.1.0 + css-select: 5.2.2 + css-tree: 3.1.0 + css-what: 6.2.2 + csso: 5.0.5 + picocolors: 1.1.1 + sax: 1.4.4 + + synckit@0.11.12: + dependencies: + '@pkgr/core': 0.2.9 + + system-architecture@0.1.0: {} + + tabbable@6.4.0: {} + + table@6.9.0: + dependencies: + ajv: 8.17.1 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + tagged-tag@1.0.0: {} + + tailwind-merge@2.6.1: {} + + tailwindcss-animate@1.0.7(tailwindcss@3.4.19(yaml@2.8.2)): + dependencies: + tailwindcss: 3.4.19(yaml@2.8.2) + + tailwindcss@3.4.19(yaml@2.8.2): + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.3 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 2.6.1 + lilconfig: 3.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-import: 15.1.0(postcss@8.5.6) + postcss-js: 4.1.0(postcss@8.5.6) + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(yaml@2.8.2) + postcss-nested: 6.2.0(postcss@8.5.6) + postcss-selector-parser: 6.1.2 + resolve: 1.22.11 + sucrase: 3.35.1 + transitivePeerDependencies: + - tsx + - yaml + + tapable@2.3.0: {} + + tar-stream@3.1.7: + dependencies: + b4a: 1.7.3 + fast-fifo: 1.3.2 + streamx: 2.23.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + tar@7.5.7: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.1.0 + yallist: 5.0.0 + + tdesign-icons-vue-next@0.4.2(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@babel/runtime': 7.28.6 + vue: 3.5.28(typescript@5.9.3) + + tdesign-vue-next@1.18.2(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@babel/runtime': 7.28.6 + '@popperjs/core': 2.11.8 + '@types/lodash-es': 4.17.12 + '@types/sortablejs': 1.15.9 + '@types/tinycolor2': 1.4.6 + '@types/validator': 13.15.10 + dayjs: 1.11.19 + lodash-es: 4.17.23 + mitt: 3.0.1 + sortablejs: 1.15.6 + tdesign-icons-vue-next: 0.4.2(vue@3.5.28(typescript@5.9.3)) + tinycolor2: 1.6.0 + validator: 13.15.26 + vue: 3.5.28(typescript@5.9.3) + + temp-dir@2.0.0: {} + + tempy@0.6.0: + dependencies: + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 + + term-size@2.2.1: {} + + terser@5.46.0: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.15.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + text-decoder@1.2.3: + dependencies: + b4a: 1.7.3 + transitivePeerDependencies: + - react-native-b4a + + text-extensions@2.4.0: {} + + theme-colors@0.1.0: {} + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + throttle-debounce@5.0.2: {} + + through@2.3.8: {} + + tiny-emitter@2.1.0: {} + + tiny-svg@3.1.3: {} + + tinybench@2.9.0: {} + + tinycolor2@1.6.0: {} + + tinyexec@0.3.2: {} + + tinyexec@1.0.2: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tinymce@7.9.1: {} + + tinypool@1.1.1: {} + + tinyrainbow@2.0.0: {} + + tinyspy@4.0.4: {} + + tippy.js@6.3.7: + dependencies: + '@popperjs/core': 2.11.8 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + to-valid-identifier@1.0.0: + dependencies: + '@sindresorhus/base62': 1.0.0 + reserved-identifiers: 1.2.0 + + toidentifier@1.0.1: {} + + totalist@3.0.1: {} + + tr46@0.0.3: {} + + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + + treemate@0.3.11: {} + + trim-lines@3.0.1: {} + + ts-api-utils@1.4.3(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + ts-api-utils@2.4.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + ts-declaration-location@1.0.7(typescript@5.9.3): + dependencies: + picomatch: 4.0.3 + typescript: 5.9.3 + + ts-interface-checker@0.1.13: {} + + tslib@2.3.0: {} + + tslib@2.4.0: {} + + tslib@2.8.1: {} + + turbo-darwin-64@2.8.5: + optional: true + + turbo-darwin-arm64@2.8.5: + optional: true + + turbo-linux-64@2.8.5: + optional: true + + turbo-linux-arm64@2.8.5: + optional: true + + turbo-windows-64@2.8.5: + optional: true + + turbo-windows-arm64@2.8.5: + optional: true + + turbo@2.8.5: + optionalDependencies: + turbo-darwin-64: 2.8.5 + turbo-darwin-arm64: 2.8.5 + turbo-linux-64: 2.8.5 + turbo-linux-arm64: 2.8.5 + turbo-windows-64: 2.8.5 + turbo-windows-arm64: 2.8.5 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.16.0: {} + + type-fest@4.41.0: {} + + type-fest@5.4.4: + dependencies: + tagged-tag: 1.0.0 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typescript@5.8.2: {} + + typescript@5.9.3: {} + + uc.micro@2.1.0: {} + + ufo@1.6.3: {} + + ultrahtml@1.6.0: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + unbuild@3.6.1(sass@1.97.3)(typescript@5.9.3)(vue-tsc@3.2.4(typescript@5.9.3))(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@rollup/plugin-alias': 5.1.1(rollup@4.57.1) + '@rollup/plugin-commonjs': 28.0.9(rollup@4.57.1) + '@rollup/plugin-json': 6.1.0(rollup@4.57.1) + '@rollup/plugin-node-resolve': 16.0.3(rollup@4.57.1) + '@rollup/plugin-replace': 6.0.3(rollup@4.57.1) + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + citty: 0.1.6 + consola: 3.4.2 + defu: 6.1.4 + esbuild: 0.25.12 + fix-dts-default-cjs-exports: 1.0.1 + hookable: 5.5.3 + jiti: 2.6.1 + magic-string: 0.30.21 + mkdist: 2.4.1(sass@1.97.3)(typescript@5.9.3)(vue-tsc@3.2.4(typescript@5.9.3))(vue@3.5.28(typescript@5.9.3)) + mlly: 1.8.0 + pathe: 2.0.3 + pkg-types: 2.3.0 + pretty-bytes: 7.1.0 + rollup: 4.57.1 + rollup-plugin-dts: 6.3.0(rollup@4.57.1)(typescript@5.9.3) + scule: 1.3.0 + tinyglobby: 0.2.15 + untyped: 2.0.0 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - sass + - vue + - vue-sfc-transformer + - vue-tsc + + uncrypto@0.1.3: {} + + unctx@2.5.0: + dependencies: + acorn: 8.15.0 + estree-walker: 3.0.3 + magic-string: 0.30.21 + unplugin: 2.3.11 + + undici-types@7.16.0: {} + + undici@7.21.0: {} + + unenv@2.0.0-rc.24: + dependencies: + pathe: 2.0.3 + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.2.0 + + unicode-match-property-value-ecmascript@2.2.1: {} + + unicode-property-aliases-ecmascript@2.2.0: {} + + unicorn-magic@0.1.0: {} + + unicorn-magic@0.3.0: {} + + unicorn-magic@0.4.0: {} + + unimport@5.6.0: + dependencies: + acorn: 8.15.0 + escape-string-regexp: 5.0.0 + estree-walker: 3.0.3 + local-pkg: 1.1.2 + magic-string: 0.30.21 + mlly: 1.8.0 + pathe: 2.0.3 + picomatch: 4.0.3 + pkg-types: 2.3.0 + scule: 1.3.0 + strip-literal: 3.1.0 + tinyglobby: 0.2.15 + unplugin: 2.3.11 + unplugin-utils: 0.3.1 + + unique-filename@5.0.0: + dependencies: + unique-slug: 6.0.0 + + unique-slug@6.0.0: + dependencies: + imurmurhash: 0.1.4 + + unique-string@2.0.0: + dependencies: + crypto-random-string: 2.0.0 + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + unplugin-element-plus@0.11.2(magicast@0.5.2): + dependencies: + '@nuxt/kit': 4.3.1(magicast@0.5.2) + es-module-lexer: 2.0.0 + escape-string-regexp: 5.0.0 + rolldown-string: 0.2.1 + unplugin: 2.3.11 + transitivePeerDependencies: + - magicast + + unplugin-utils@0.3.1: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.3 + + unplugin@1.16.1: + dependencies: + acorn: 8.15.0 + webpack-virtual-modules: 0.6.2 + + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.15.0 + picomatch: 4.0.3 + webpack-virtual-modules: 0.6.2 + + unrs-resolver@1.11.1: + dependencies: + napi-postinstall: 0.3.4 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + + unstorage@1.17.4(db0@0.3.4)(ioredis@5.9.2): + dependencies: + anymatch: 3.1.3 + chokidar: 5.0.0 + destr: 2.0.5 + h3: 1.15.5 + lru-cache: 11.2.6 + node-fetch-native: 1.6.7 + ofetch: 1.5.1 + ufo: 1.6.3 + optionalDependencies: + db0: 0.3.4 + ioredis: 5.9.2 + + untun@0.1.3: + dependencies: + citty: 0.1.6 + consola: 3.4.2 + pathe: 1.1.2 + + untyped@2.0.0: + dependencies: + citty: 0.1.6 + defu: 6.1.4 + jiti: 2.6.1 + knitwork: 1.3.0 + scule: 1.3.0 + + unwasm@0.5.3: + dependencies: + exsolve: 1.0.8 + knitwork: 1.3.0 + magic-string: 0.30.21 + mlly: 1.8.0 + pathe: 2.0.3 + pkg-types: 2.3.0 + + upath@1.2.0: {} + + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + update-notifier@7.3.1: + dependencies: + boxen: 8.0.1 + chalk: 5.6.2 + configstore: 7.1.0 + is-in-ci: 1.0.0 + is-installed-globally: 1.0.0 + is-npm: 6.1.0 + latest-version: 9.0.0 + pupa: 3.3.0 + semver: 7.7.4 + xdg-basedir: 5.1.0 + + uqr@0.1.2: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url-toolkit@2.2.5: {} + + util-deprecate@1.0.2: {} + + validator@13.15.26: {} + + vdirs@0.1.8(vue@3.5.28(typescript@5.9.3)): + dependencies: + evtd: 0.2.4 + vue: 3.5.28(typescript@5.9.3) + + vee-validate@4.15.1(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@vue/devtools-api': 7.7.9 + type-fest: 4.41.0 + vue: 3.5.28(typescript@5.9.3) + + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + + video.js@7.21.7: + dependencies: + '@babel/runtime': 7.28.6 + '@videojs/http-streaming': 2.16.3(video.js@7.21.7) + '@videojs/vhs-utils': 3.0.5 + '@videojs/xhr': 2.6.0 + aes-decrypter: 3.1.3 + global: 4.4.0 + keycode: 2.2.1 + m3u8-parser: 4.8.0 + mpd-parser: 0.22.1 + mux.js: 6.0.1 + safe-json-parse: 4.0.0 + videojs-font: 3.2.0 + videojs-vtt.js: 0.15.5 + + videojs-font@3.2.0: {} + + videojs-vtt.js@0.15.5: + dependencies: + global: 4.4.0 + + vite-dev-rpc@1.1.0(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + dependencies: + birpc: 2.9.0 + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite-hot-client: 2.1.0(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + + vite-hot-client@2.1.0(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + dependencies: + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + + vite-node@3.2.4(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite-node@3.2.4(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + optional: true + + vite-plugin-compression@0.5.1(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + dependencies: + chalk: 4.1.2 + debug: 4.4.3 + fs-extra: 10.1.0 + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + transitivePeerDependencies: + - supports-color + + vite-plugin-dts@4.5.4(@types/node@25.2.3)(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + dependencies: + '@microsoft/api-extractor': 7.56.3(@types/node@25.2.3) + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + '@volar/typescript': 2.4.28 + '@vue/language-core': 2.2.0(typescript@5.9.3) + compare-versions: 6.1.1 + debug: 4.4.3 + kolorist: 1.8.0 + local-pkg: 1.1.2 + magic-string: 0.30.21 + typescript: 5.9.3 + optionalDependencies: + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + + vite-plugin-html@3.2.2(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + dependencies: + '@rollup/pluginutils': 4.2.1 + colorette: 2.0.20 + connect-history-api-fallback: 1.6.0 + consola: 2.15.3 + dotenv: 16.6.1 + dotenv-expand: 8.0.3 + ejs: 3.1.10 + fast-glob: 3.3.3 + fs-extra: 10.1.0 + html-minifier-terser: 6.1.0 + node-html-parser: 5.4.2 + pathe: 0.2.0 + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + + vite-plugin-inspect@11.3.3(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + dependencies: + ansis: 4.2.0 + debug: 4.4.3 + error-stack-parser-es: 1.0.5 + ohash: 2.0.11 + open: 10.2.0 + perfect-debounce: 2.1.0 + sirv: 3.0.2 + unplugin-utils: 0.3.1 + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite-dev-rpc: 1.1.0(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + transitivePeerDependencies: + - supports-color + + vite-plugin-lazy-import@1.0.7: + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + es-module-lexer: 1.7.0 + rollup: 4.57.1 + xe-utils: 3.9.1 + + vite-plugin-pwa@1.2.0(vite@5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0))(workbox-build@7.4.0)(workbox-window@7.4.0): + dependencies: + debug: 4.4.3 + pretty-bytes: 6.1.1 + tinyglobby: 0.2.15 + vite: 5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0) + workbox-build: 7.4.0 + workbox-window: 7.4.0 + transitivePeerDependencies: + - supports-color + + vite-plugin-pwa@1.2.0(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(workbox-build@7.4.0)(workbox-window@7.4.0): + dependencies: + debug: 4.4.3 + pretty-bytes: 6.1.1 + tinyglobby: 0.2.15 + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + workbox-build: 7.4.0 + workbox-window: 7.4.0 + transitivePeerDependencies: + - supports-color + + vite-plugin-vue-devtools@8.0.6(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@vue/devtools-core': 8.0.6(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.28(typescript@5.9.3)) + '@vue/devtools-kit': 8.0.6 + '@vue/devtools-shared': 8.0.6 + sirv: 3.0.2 + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite-plugin-inspect: 11.3.3(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + vite-plugin-vue-inspector: 5.3.2(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + transitivePeerDependencies: + - '@nuxt/kit' + - supports-color + - vue + + vite-plugin-vue-inspector@5.3.2(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-proposal-decorators': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.29.0) + '@vue/compiler-dom': 3.5.28 + kolorist: 1.8.0 + magic-string: 0.30.21 + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + transitivePeerDependencies: + - supports-color + + vite@5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0): + dependencies: + esbuild: 0.25.12 + postcss: 8.5.6 + rollup: 4.57.1 + optionalDependencies: + '@types/node': 25.2.3 + fsevents: 2.3.3 + less: 4.5.1 + sass: 1.97.3 + terser: 5.46.0 + + vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.57.1 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.10.13 + fsevents: 2.3.3 + jiti: 2.6.1 + less: 4.5.1 + sass: 1.97.3 + terser: 5.46.0 + yaml: 2.8.2 + + vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.57.1 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 25.2.3 + fsevents: 2.3.3 + jiti: 2.6.1 + less: 4.5.1 + sass: 1.97.3 + terser: 5.46.0 + yaml: 2.8.2 + + vitepress-plugin-group-icons@1.7.1(vite@5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)): + dependencies: + '@iconify-json/logos': 1.2.10 + '@iconify-json/vscode-icons': 1.2.41 + '@iconify/utils': 3.1.0 + optionalDependencies: + vite: 5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0) + + vitepress@1.6.4(@algolia/client-search@5.48.0)(@types/node@25.2.3)(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(less@4.5.1)(nprogress@0.2.0)(postcss@8.5.6)(qrcode@1.5.4)(sass@1.97.3)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.46.0)(typescript@5.9.3): + dependencies: + '@docsearch/css': 3.8.2 + '@docsearch/js': 3.8.2(@algolia/client-search@5.48.0)(search-insights@2.17.3) + '@iconify-json/simple-icons': 1.2.70 + '@shikijs/core': 2.5.0 + '@shikijs/transformers': 2.5.0 + '@shikijs/types': 2.5.0 + '@types/markdown-it': 14.1.2 + '@vitejs/plugin-vue': 5.2.4(vite@5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0))(vue@3.5.28(typescript@5.9.3)) + '@vue/devtools-api': 7.7.9 + '@vue/shared': 3.5.28 + '@vueuse/core': 12.8.2(typescript@5.9.3) + '@vueuse/integrations': 12.8.2(async-validator@4.2.5)(axios@1.13.5)(change-case@5.4.4)(focus-trap@7.8.0)(nprogress@0.2.0)(qrcode@1.5.4)(sortablejs@1.15.6)(typescript@5.9.3) + focus-trap: 7.8.0 + mark.js: 8.11.1 + minisearch: 7.2.0 + shiki: 2.5.0 + vite: 5.4.21(@types/node@25.2.3)(less@4.5.1)(sass@1.97.3)(terser@5.46.0) + vue: 3.5.28(typescript@5.9.3) + optionalDependencies: + postcss: 8.5.6 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/node' + - '@types/react' + - async-validator + - axios + - change-case + - drauu + - fuse.js + - idb-keyval + - jwt-decode + - less + - lightningcss + - nprogress + - qrcode + - react + - react-dom + - sass + - sass-embedded + - search-insights + - sortablejs + - stylus + - sugarss + - terser + - typescript + - universal-cookie + + vitest@3.2.4(@types/node@24.10.13)(happy-dom@17.6.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): + dependencies: + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite-node: 3.2.4(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.10.13 + happy-dom: 17.6.3 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vitest@3.2.4(@types/node@25.2.3)(happy-dom@17.6.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): + dependencies: + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.3.1(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite-node: 3.2.4(@types/node@25.2.3)(jiti@2.6.1)(less@4.5.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.2.3 + happy-dom: 17.6.3 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + optional: true + + vooks@0.2.12(vue@3.5.28(typescript@5.9.3)): + dependencies: + evtd: 0.2.4 + vue: 3.5.28(typescript@5.9.3) + + vscode-languageserver-textdocument@1.0.12: {} + + vscode-uri@3.1.0: {} + + vue-component-type-helpers@2.2.12: {} + + vue-demi@0.14.10(vue@3.5.28(typescript@5.9.3)): + dependencies: + vue: 3.5.28(typescript@5.9.3) + + vue-dompurify-html@5.3.0(vue@3.5.28(typescript@5.9.3)): + dependencies: + dompurify: 3.3.1 + vue: 3.5.28(typescript@5.9.3) + + vue-eslint-parser@10.2.0(eslint@9.39.2(jiti@2.6.1)): + dependencies: + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + semver: 7.7.4 + transitivePeerDependencies: + - supports-color + + vue-i18n@11.2.8(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@intlify/core-base': 11.2.8 + '@intlify/shared': 11.2.8 + '@vue/devtools-api': 6.6.4 + vue: 3.5.28(typescript@5.9.3) + + vue-json-viewer@3.0.4(vue@3.5.28(typescript@5.9.3)): + dependencies: + clipboard: 2.0.11 + vue: 3.5.28(typescript@5.9.3) + + vue-router@4.6.4(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.28(typescript@5.9.3) + + vue-tippy@6.7.1(vue@3.5.28(typescript@5.9.3)): + dependencies: + tippy.js: 6.3.7 + vue: 3.5.28(typescript@5.9.3) + + vue-tsc@3.2.4(typescript@5.9.3): + dependencies: + '@volar/typescript': 2.4.27 + '@vue/language-core': 3.2.4 + typescript: 5.9.3 + + vue-types@3.0.2(vue@3.5.28(typescript@5.9.3)): + dependencies: + is-plain-object: 3.0.1 + vue: 3.5.28(typescript@5.9.3) + + vue3-print-nb@0.1.4(typescript@5.9.3): + dependencies: + vue: 3.5.28(typescript@5.9.3) + transitivePeerDependencies: + - typescript + + vue3-signature@0.2.4(vue@3.5.28(typescript@5.9.3)): + dependencies: + default-passive-events: 2.0.0 + signature_pad: 3.0.0-beta.4 + vue: 3.5.28(typescript@5.9.3) + + vue@3.5.28(typescript@5.9.3): + dependencies: + '@vue/compiler-dom': 3.5.28 + '@vue/compiler-sfc': 3.5.28 + '@vue/runtime-dom': 3.5.28 + '@vue/server-renderer': 3.5.28(vue@3.5.28(typescript@5.9.3)) + '@vue/shared': 3.5.28 + optionalDependencies: + typescript: 5.9.3 + + vuedraggable@4.1.0(vue@3.5.28(typescript@5.9.3)): + dependencies: + sortablejs: 1.14.0 + vue: 3.5.28(typescript@5.9.3) + + vueuc@0.4.65(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@css-render/vue3-ssr': 0.15.14(vue@3.5.28(typescript@5.9.3)) + '@juggle/resize-observer': 3.4.0 + css-render: 0.15.14 + evtd: 0.2.4 + seemly: 0.3.10 + vdirs: 0.1.8(vue@3.5.28(typescript@5.9.3)) + vooks: 0.2.12(vue@3.5.28(typescript@5.9.3)) + vue: 3.5.28(typescript@5.9.3) + + vxe-pc-ui@4.12.36(vue@3.5.28(typescript@5.9.3)): + dependencies: + '@vxe-ui/core': 4.3.1(vue@3.5.28(typescript@5.9.3)) + transitivePeerDependencies: + - vue + + vxe-table@4.17.48(vue@3.5.28(typescript@5.9.3)): + dependencies: + vxe-pc-ui: 4.12.36(vue@3.5.28(typescript@5.9.3)) + transitivePeerDependencies: + - vue + + w3c-keyname@2.2.8: {} + + wangeditor@4.7.15: + dependencies: + '@babel/runtime': 7.28.6 + '@babel/runtime-corejs3': 7.29.0 + tslib: 2.8.1 + + warning@4.0.3: + dependencies: + loose-envify: 1.4.0 + + watermark-js-plus@1.6.3: {} + + web-streams-polyfill@3.3.3: {} + + webidl-conversions@3.0.1: {} + + webidl-conversions@4.0.2: {} + + webidl-conversions@7.0.0: {} + + webpack-virtual-modules@0.6.2: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@3.0.0: {} + + whatwg-mimetype@4.0.0: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + + when-exit@2.1.5: {} + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.20 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-module@2.0.1: {} + + which-typed-array@1.1.20: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + widest-line@5.0.0: + dependencies: + string-width: 7.2.0 + + word-wrap@1.2.5: {} + + workbox-background-sync@7.4.0: + dependencies: + idb: 7.1.1 + workbox-core: 7.4.0 + + workbox-broadcast-update@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-build@7.4.0: + dependencies: + '@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1) + '@babel/core': 7.29.0 + '@babel/preset-env': 7.29.0(@babel/core@7.29.0) + '@babel/runtime': 7.28.6 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.29.0)(rollup@2.79.2) + '@rollup/plugin-node-resolve': 15.3.1(rollup@2.79.2) + '@rollup/plugin-replace': 2.4.2(rollup@2.79.2) + '@rollup/plugin-terser': 0.4.4(rollup@2.79.2) + '@surma/rollup-plugin-off-main-thread': 2.2.3 + ajv: 8.17.1 + common-tags: 1.8.2 + fast-json-stable-stringify: 2.1.0 + fs-extra: 9.1.0 + glob: 11.1.0 + lodash: 4.17.23 + pretty-bytes: 5.6.0 + rollup: 2.79.2 + source-map: 0.8.0-beta.0 + stringify-object: 3.3.0 + strip-comments: 2.0.1 + tempy: 0.6.0 + upath: 1.2.0 + workbox-background-sync: 7.4.0 + workbox-broadcast-update: 7.4.0 + workbox-cacheable-response: 7.4.0 + workbox-core: 7.4.0 + workbox-expiration: 7.4.0 + workbox-google-analytics: 7.4.0 + workbox-navigation-preload: 7.4.0 + workbox-precaching: 7.4.0 + workbox-range-requests: 7.4.0 + workbox-recipes: 7.4.0 + workbox-routing: 7.4.0 + workbox-strategies: 7.4.0 + workbox-streams: 7.4.0 + workbox-sw: 7.4.0 + workbox-window: 7.4.0 + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + + workbox-cacheable-response@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-core@7.4.0: {} + + workbox-expiration@7.4.0: + dependencies: + idb: 7.1.1 + workbox-core: 7.4.0 + + workbox-google-analytics@7.4.0: + dependencies: + workbox-background-sync: 7.4.0 + workbox-core: 7.4.0 + workbox-routing: 7.4.0 + workbox-strategies: 7.4.0 + + workbox-navigation-preload@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-precaching@7.4.0: + dependencies: + workbox-core: 7.4.0 + workbox-routing: 7.4.0 + workbox-strategies: 7.4.0 + + workbox-range-requests@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-recipes@7.4.0: + dependencies: + workbox-cacheable-response: 7.4.0 + workbox-core: 7.4.0 + workbox-expiration: 7.4.0 + workbox-precaching: 7.4.0 + workbox-routing: 7.4.0 + workbox-strategies: 7.4.0 + + workbox-routing@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-strategies@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-streams@7.4.0: + dependencies: + workbox-core: 7.4.0 + workbox-routing: 7.4.0 + + workbox-sw@7.4.0: {} + + workbox-window@7.4.0: + dependencies: + '@types/trusted-types': 2.0.7 + workbox-core: 7.4.0 + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.1.2 + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.1.2 + + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.0 + + xdg-basedir@5.1.0: {} + + xe-utils@3.9.1: {} + + xml-name-validator@4.0.0: {} + + y18n@4.0.3: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yallist@4.0.0: {} + + yallist@5.0.0: {} + + yaml-eslint-parser@1.3.2: + dependencies: + eslint-visitor-keys: 3.4.3 + yaml: 2.8.2 + + yaml-eslint-parser@2.0.0: + dependencies: + eslint-visitor-keys: 5.0.0 + yaml: 2.8.2 + + yaml@1.10.2: {} + + yaml@2.8.2: {} + + yargs-parser@18.1.3: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + + yargs-parser@20.2.9: {} + + yargs-parser@21.1.1: {} + + yargs@15.4.1: + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + yocto-queue@1.2.2: {} + + yoctocolors@2.1.2: {} + + youch-core@0.3.3: + dependencies: + '@poppinss/exception': 1.2.3 + error-stack-parser-es: 1.0.5 + + youch@4.1.0-beta.13: + dependencies: + '@poppinss/colors': 4.1.6 + '@poppinss/dumper': 0.6.5 + '@speed-highlight/core': 1.2.14 + cookie-es: 2.0.0 + youch-core: 0.3.3 + + zeebe-bpmn-moddle@1.12.0: {} + + zimmerframe@1.1.4: {} + + zip-stream@6.0.1: + dependencies: + archiver-utils: 5.0.2 + compress-commons: 6.0.2 + readable-stream: 4.7.0 + + zod-defaults@0.1.3(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod@3.25.76: {} + + zrender@6.0.0: + dependencies: + tslib: 2.3.0 + + zwitch@2.0.4: {} + + zx@8.8.5: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..2db2798 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,232 @@ +packages: + - internal/* + - internal/lint-configs/* + - packages/* + - packages/@core/base/* + - packages/@core/ui-kit/* + - packages/@core/forward/* + - packages/@core/* + - packages/effects/* + - packages/business/* + - apps/* + - scripts/* + - docs + +overrides: + '@ast-grep/napi': 'catalog:' + '@ctrl/tinycolor': 'catalog:' + clsx: 'catalog:' + esbuild: 'catalog:' + jiti: 'catalog:' + pinia: 'catalog:' + vue: 'catalog:' +catalog: + '@ast-grep/napi': ^0.39.9 + '@changesets/changelog-github': ^0.5.2 + '@changesets/cli': ^2.29.8 + '@changesets/git': ^3.0.4 + '@clack/prompts': ^0.11.0 + '@commitlint/cli': ^19.8.1 + '@commitlint/config-conventional': ^19.8.1 + '@ctrl/tinycolor': ^4.2.0 + '@eslint/js': ^9.39.2 + '@form-create/ant-design-vue': ^3.2.37 + '@form-create/antd-designer': ^3.4.0 + '@form-create/designer': ^3.4.0 + '@form-create/element-ui': ^3.2.37 + '@form-create/naive-ui': ^3.2.37 + '@iconify/json': ^2.2.432 + '@iconify/tailwind': ^1.2.0 + '@iconify/vue': ^5.0.0 + '@intlify/core-base': ^11.2.8 + '@intlify/unplugin-vue-i18n': ^6.0.8 + '@jspm/generator': ^2.9.0 + '@manypkg/get-packages': ^3.1.0 + '@microsoft/fetch-event-source': ^2.0.1 + '@nolebase/vitepress-plugin-git-changelog': ^2.18.2 + '@playwright/test': ^1.58.2 + '@pnpm/workspace.read-manifest': ^1000.2.10 + '@stylistic/stylelint-plugin': ^4.0.1 + '@tailwindcss/nesting': 0.0.0-insiders.565cd3e + '@tailwindcss/typography': ^0.5.19 + '@tanstack/vue-store': ^0.8.0 + '@tinyflow-ai/vue': ~1.1.10 + '@tinymce/tinymce-vue': ^6.3.0 + '@types/archiver': ^6.0.4 + '@types/codemirror': ^5.60.17 + '@types/crypto-js': ^4.2.2 + '@types/eslint': ^9.6.1 + '@types/html-minifier-terser': ^7.0.2 + '@types/lodash.clonedeep': ^4.5.9 + '@types/markdown-it': ^14.1.2 + '@types/node': ^24.10.12 + '@types/nprogress': ^0.2.3 + '@types/postcss-import': ^14.0.3 + '@types/qrcode': ^1.5.6 + '@types/qs': ^6.14.0 + '@types/sortablejs': ^1.15.9 + '@typescript-eslint/eslint-plugin': ^8.54.0 + '@typescript-eslint/parser': ^8.54.0 + '@vee-validate/zod': ^4.15.1 + '@videojs-player/vue': ^1.0.0 + '@vite-pwa/vitepress': ^1.1.0 + '@vitejs/plugin-vue': ^6.0.4 + '@vitejs/plugin-vue-jsx': ^5.1.4 + '@vue/shared': ^3.5.27 + '@vue/test-utils': ^2.4.6 + '@vueuse/core': ^14.1.0 + '@vueuse/integrations': ^14.1.0 + '@vueuse/motion': ^3.0.3 + ant-design-vue: ^4.2.6 + antdv-next: ^1.0.2 + archiver: ^7.0.1 + autoprefixer: ^10.4.24 + axios: ^1.13.4 + axios-mock-adapter: ^2.1.0 + benz-amr-recorder: ^1.1.5 + bpmn-js: ^17.11.1 + bpmn-js-properties-panel: 5.23.0 + bpmn-js-token-simulation: ^0.36.3 + cac: ^6.7.14 + camunda-bpmn-moddle: ^7.0.1 + chalk: ^5.6.2 + cheerio: ^1.2.0 + circular-dependency-scanner: ^2.3.0 + class-variance-authority: ^0.7.1 + clsx: ^2.1.1 + codemirror: ^5.65.20 + commitlint-plugin-function-rules: ^4.3.1 + consola: ^3.4.2 + cropperjs: ^1.6.2 + cross-env: ^10.1.0 + crypto-js: ^4.2.0 + cspell: ^9.6.4 + cssnano: ^7.1.2 + cz-git: ^1.12.0 + czg: ^1.12.0 + dayjs: ^1.11.19 + defu: ^6.1.4 + depcheck: ^1.4.7 + diagram-js: ^12.8.1 + dotenv: ^16.6.1 + echarts: ^6.0.0 + element-plus: ^2.13.1 + es-toolkit: ^1.44.0 + esbuild: ^0.25.12 + eslint: ^9.39.2 + eslint-config-turbo: ^2.7.6 + eslint-plugin-command: ^3.4.0 + eslint-plugin-eslint-comments: ^3.2.0 + eslint-plugin-import-x: ^4.16.1 + eslint-plugin-jsdoc: ^61.7.1 + eslint-plugin-jsonc: ^2.21.0 + eslint-plugin-n: ^17.23.2 + eslint-plugin-no-only-tests: ^3.3.0 + eslint-plugin-perfectionist: ^4.15.1 + eslint-plugin-pnpm: ^1.5.0 + eslint-plugin-prettier: ^5.5.5 + eslint-plugin-regexp: ^2.10.0 + eslint-plugin-unicorn: ^62.0.0 + eslint-plugin-unused-imports: ^4.3.0 + eslint-plugin-vitest: ^0.5.4 + eslint-plugin-vue: ^10.7.0 + eslint-plugin-yml: ^1.19.1 + execa: ^9.6.1 + fast-xml-parser: ^4.5.3 + find-up: ^7.0.0 + get-port: ^7.1.0 + globals: ^16.5.0 + happy-dom: ^17.6.3 + highlight.js: ^11.11.1 + html-minifier-terser: ^7.2.0 + is-ci: ^4.1.0 + jiti: ^2.6.1 + jsencrypt: ^3.5.4 + json-bigint: ^1.0.0 + jsonc-eslint-parser: ^2.4.2 + lefthook: ^2.1.0 + lodash.clonedeep: ^4.5.0 + lucide-vue-next: ^0.553.0 + markdown-it: ^14.1.0 + markmap-common: ^0.16.0 + markmap-lib: ^0.16.1 + markmap-toolbar: ^0.17.2 + markmap-view: ^0.16.0 + medium-zoom: ^1.1.0 + naive-ui: ^2.43.2 + nitropack: ^2.13.1 + nprogress: ^0.2.0 + ora: ^8.2.0 + pinia: ^3.0.4 + pinia-plugin-persistedstate: ^4.7.1 + pkg-types: ^2.3.0 + playwright: ^1.58.2 + postcss: ^8.5.6 + postcss-antd-fixes: ^0.2.0 + postcss-html: ^1.8.1 + postcss-import: ^16.1.1 + postcss-preset-env: ^10.6.1 + postcss-scss: ^4.0.9 + prettier: ^3.8.1 + prettier-plugin-tailwindcss: ^0.7.2 + publint: ^0.3.17 + qrcode: ^1.5.4 + qs: ^6.14.1 + reka-ui: ^2.7.0 + resolve.exports: ^2.0.3 + rimraf: ^6.1.2 + rollup: ^4.57.0 + rollup-plugin-visualizer: ^5.14.0 + sass: ^1.97.3 + secure-ls: ^2.0.0 + sortablejs: ^1.15.6 + steady-xml: ^0.1.0 + stylelint: ^16.26.1 + stylelint-config-recess-order: ^7.6.0 + stylelint-config-recommended: ^17.0.0 + stylelint-config-recommended-scss: ^16.0.2 + stylelint-config-recommended-vue: ^1.6.1 + stylelint-config-standard: ^39.0.1 + stylelint-order: ^7.0.1 + stylelint-prettier: ^5.0.3 + stylelint-scss: ^6.14.0 + tailwind-merge: ^2.6.0 + tailwindcss: ^3.4.19 + tailwindcss-animate: ^1.0.7 + tdesign-vue-next: ^1.18.0 + theme-colors: ^0.1.0 + tinymce: ^7.3.0 + tippy.js: ^6.3.7 + turbo: ^2.8.3 + typescript: ^5.9.3 + unbuild: ^3.6.1 + unplugin-element-plus: ^0.11.2 + vee-validate: ^4.15.1 + video.js: ^7.21.7 + vite: ^7.3.1 + vite-plugin-compression: ^0.5.1 + vite-plugin-dts: ^4.5.4 + vite-plugin-html: ^3.2.2 + vite-plugin-lazy-import: ^1.0.7 + vite-plugin-pwa: ^1.2.0 + vite-plugin-vue-devtools: ^8.0.5 + vitepress: ^1.6.4 + vitepress-plugin-group-icons: ^1.7.1 + vitest: ^3.2.4 + vue: ^3.5.27 + vue-dompurify-html: ^5.3.0 + vue-eslint-parser: ^10.2.0 + vue-i18n: ^11.2.8 + vue-json-viewer: ^3.0.4 + vue-router: ^4.6.4 + vue-tippy: ^6.7.1 + vue-tsc: ^3.2.4 + vue3-print-nb: ^0.1.4 + vue3-signature: ^0.2.4 + vuedraggable: ^4.1.0 + vxe-pc-ui: ^4.12.16 + vxe-table: ^4.17.46 + watermark-js-plus: ^1.6.3 + yaml-eslint-parser: ^1.3.2 + zod: ^3.25.76 + zod-defaults: 0.1.3 diff --git a/scripts/clean.mjs b/scripts/clean.mjs new file mode 100644 index 0000000..2049e45 --- /dev/null +++ b/scripts/clean.mjs @@ -0,0 +1,141 @@ +import { promises as fs } from 'node:fs'; +import { join, normalize } from 'node:path'; + +const rootDir = process.cwd(); + +// 控制并发数量,避免创建过多的并发任务 +const CONCURRENCY_LIMIT = 10; + +// 需要跳过的目录,避免进入这些目录进行清理 +const SKIP_DIRS = new Set(['.DS_Store', '.git', '.idea', '.vscode']); + +/** + * 处理单个文件/目录项 + * @param {string} currentDir - 当前目录路径 + * @param {string} item - 文件/目录名 + * @param {string[]} targets - 要删除的目标列表 + * @param {number} _depth - 当前递归深度 + * @returns {Promise} - 是否需要进一步递归处理 + */ +async function processItem(currentDir, item, targets, _depth) { + // 跳过特殊目录 + if (SKIP_DIRS.has(item)) { + return false; + } + + try { + const itemPath = normalize(join(currentDir, item)); + + if (targets.includes(item)) { + // 匹配到目标目录或文件时直接删除 + await fs.rm(itemPath, { force: true, recursive: true }); + console.log(`✅ Deleted: ${itemPath}`); + return false; // 已删除,无需递归 + } + + // 使用 readdir 的 withFileTypes 选项,避免额外的 lstat 调用 + return true; // 可能需要递归,由调用方决定 + } catch (error) { + // 更详细的错误信息 + if (error.code === 'ENOENT') { + // 文件不存在,可能已被删除,这是正常情况 + return false; + } else if (error.code === 'EPERM' || error.code === 'EACCES') { + console.error(`❌ Permission denied: ${item} in ${currentDir}`); + } else { + console.error( + `❌ Error handling item ${item} in ${currentDir}: ${error.message}`, + ); + } + return false; + } +} + +/** + * 递归查找并删除目标目录(并发优化版本) + * @param {string} currentDir - 当前遍历的目录路径 + * @param {string[]} targets - 要删除的目标列表 + * @param {number} depth - 当前递归深度,避免过深递归 + */ +async function cleanTargetsRecursively(currentDir, targets, depth = 0) { + // 限制递归深度,避免无限递归 + if (depth > 10) { + console.warn(`Max recursion depth reached at: ${currentDir}`); + return; + } + + let dirents; + try { + // 使用 withFileTypes 选项,一次性获取文件类型信息,避免后续 lstat 调用 + dirents = await fs.readdir(currentDir, { withFileTypes: true }); + } catch (error) { + // 如果无法读取目录,可能已被删除或权限不足 + console.warn(`Cannot read directory ${currentDir}: ${error.message}`); + return; + } + + // 分批处理,控制并发数量 + for (let i = 0; i < dirents.length; i += CONCURRENCY_LIMIT) { + const batch = dirents.slice(i, i + CONCURRENCY_LIMIT); + + const tasks = batch.map(async (dirent) => { + const item = dirent.name; + const shouldRecurse = await processItem(currentDir, item, targets, depth); + + // 如果是目录且没有被删除,则递归处理 + if (shouldRecurse && dirent.isDirectory()) { + const itemPath = normalize(join(currentDir, item)); + return cleanTargetsRecursively(itemPath, targets, depth + 1); + } + + return null; + }); + + // 并发执行当前批次的任务 + const results = await Promise.allSettled(tasks); + + // 检查是否有失败的任务(可选:用于调试) + const failedTasks = results.filter( + (result) => result.status === 'rejected', + ); + if (failedTasks.length > 0) { + console.warn( + `${failedTasks.length} tasks failed in batch starting at index ${i} in directory: ${currentDir}`, + ); + } + } +} + +(async function startCleanup() { + // 要删除的目录及文件名称 + const targets = ['node_modules', 'dist', '.turbo', 'dist.zip']; + const deleteLockFile = process.argv.includes('--del-lock'); + const cleanupTargets = [...targets]; + + if (deleteLockFile) { + cleanupTargets.push('pnpm-lock.yaml'); + } + + console.log( + `🚀 Starting cleanup of targets: ${cleanupTargets.join(', ')} from root: ${rootDir}`, + ); + + const startTime = Date.now(); + + try { + // 先统计要删除的目标数量 + console.log('📊 Scanning for cleanup targets...'); + + await cleanTargetsRecursively(rootDir, cleanupTargets); + + const endTime = Date.now(); + const duration = (endTime - startTime) / 1000; + + console.log( + `✨ Cleanup process completed successfully in ${duration.toFixed(2)}s`, + ); + } catch (error) { + console.error(`💥 Unexpected error during cleanup: ${error.message}`); + process.exit(1); + } +})(); diff --git a/scripts/deploy/Dockerfile b/scripts/deploy/Dockerfile new file mode 100644 index 0000000..86f439f --- /dev/null +++ b/scripts/deploy/Dockerfile @@ -0,0 +1,37 @@ +FROM node:22-slim AS builder + +# --max-old-space-size +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +ENV NODE_OPTIONS=--max-old-space-size=8192 +ENV TZ=Asia/Shanghai + +RUN npm i -g corepack + +WORKDIR /app + +# copy package.json and pnpm-lock.yaml to workspace +COPY . /app + +# 安装依赖 +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile +RUN pnpm run build --filter=\!./docs + +RUN echo "Builder Success 🎉" + +FROM nginx:stable-alpine AS production + +# 配置 nginx +RUN echo "types { application/javascript js mjs; }" > /etc/nginx/conf.d/mjs.conf \ + && rm -rf /etc/nginx/conf.d/default.conf + +# 复制构建产物 +COPY --from=builder /app/playground/dist /usr/share/nginx/html + +# 复制 nginx 配置 +COPY --from=builder /app/scripts/deploy/nginx.conf /etc/nginx/nginx.conf + +EXPOSE 8080 + +# 启动 nginx +CMD ["nginx", "-g", "daemon off;"] diff --git a/scripts/deploy/build-local-docker-image.sh b/scripts/deploy/build-local-docker-image.sh new file mode 100755 index 0000000..4881487 --- /dev/null +++ b/scripts/deploy/build-local-docker-image.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +LOG_FILE=${SCRIPT_DIR}/build-local-docker-image.log +ERROR="" +IMAGE_NAME="vben-admin-local" + +function stop_and_remove_container() { + # Stop and remove the existing container + docker stop ${IMAGE_NAME} >/dev/null 2>&1 + docker rm ${IMAGE_NAME} >/dev/null 2>&1 +} + +function remove_image() { + # Remove the existing image + docker rmi vben-admin-pro >/dev/null 2>&1 +} + +function install_dependencies() { + # Install all dependencies + cd ${SCRIPT_DIR} + pnpm install || ERROR="install_dependencies failed" +} + +function build_image() { + # build docker + docker build ../../ -f Dockerfile -t ${IMAGE_NAME} || ERROR="build_image failed" +} + +function log_message() { + if [[ ${ERROR} != "" ]]; + then + >&2 echo "build failed, Please check build-local-docker-image.log for more details" + >&2 echo "ERROR: ${ERROR}" + exit 1 + else + echo "docker image with tag '${IMAGE_NAME}' built sussessfully. Use below sample command to run the container" + echo "" + echo "docker run -d -p 8010:8080 --name ${IMAGE_NAME} ${IMAGE_NAME}" + fi +} + +echo "Info: Stopping and removing existing container and image" | tee ${LOG_FILE} +stop_and_remove_container +remove_image + +echo "Info: Installing dependencies" | tee -a ${LOG_FILE} +install_dependencies 1>> ${LOG_FILE} 2>> ${LOG_FILE} + +if [[ ${ERROR} == "" ]]; then + echo "Info: Building docker image" | tee -a ${LOG_FILE} + build_image 1>> ${LOG_FILE} 2>> ${LOG_FILE} +fi + +log_message | tee -a ${LOG_FILE} diff --git a/scripts/deploy/nginx.conf b/scripts/deploy/nginx.conf new file mode 100644 index 0000000..8e6ab10 --- /dev/null +++ b/scripts/deploy/nginx.conf @@ -0,0 +1,75 @@ + +#user nobody; +worker_processes 1; + +#error_log logs/error.log; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +#pid logs/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + + types { + application/javascript js mjs; + text/css css; + text/html html; + } + + sendfile on; + # tcp_nopush on; + + #keepalive_timeout 0; + # keepalive_timeout 65; + + # gzip on; + # gzip_buffers 32 16k; + # gzip_comp_level 6; + # gzip_min_length 1k; + # gzip_static on; + # gzip_types text/plain + # text/css + # application/javascript + # application/json + # application/x-javascript + # text/xml + # application/xml + # application/xml+rss + # text/javascript; #设置压缩的文件类型 + # gzip_vary on; + + server { + listen 8080; + server_name localhost; + + location / { + root /usr/share/nginx/html; + try_files $uri $uri/ /index.html; + index index.html; + # Enable CORS + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain charset=UTF-8'; + add_header 'Content-Length' 0; + return 204; + } + } + + error_page 500 502 503 504 /50x.html; + + location = /50x.html { + root /usr/share/nginx/html; + } + } +} diff --git a/scripts/turbo-run/README.md b/scripts/turbo-run/README.md new file mode 100644 index 0000000..4f90a59 --- /dev/null +++ b/scripts/turbo-run/README.md @@ -0,0 +1,59 @@ +# @vben/turbo-run + +`turbo-run` 是一个命令行工具,允许你在多个包中并行运行命令。它提供了一个交互式的界面,让你可以选择要运行命令的包。 + +## 特性 + +- 🚀 交互式选择要运行的包 +- 📦 支持 monorepo 项目结构 +- 🔍 自动检测可用的命令 +- 🎯 精确过滤目标包 + +## 安装 + +```bash +pnpm add -D @vben/turbo-run +``` + +## 使用方法 + +基本语法: + +```bash +turbo-run [script] +``` + +例如,如果你想运行 `dev` 命令: + +```bash +turbo-run dev +``` + +工具会自动检测哪些包有 `dev` 命令,并提供一个交互式界面让你选择要运行的包。 + +## 示例 + +假设你的项目中有以下包: + +- `@vben/app` +- `@vben/admin` +- `@vben/website` + +当你运行: + +```bash +turbo-run dev +``` + +工具会: + +1. 检测哪些包有 `dev` 命令 +2. 显示一个交互式选择界面 +3. 让你选择要运行命令的包 +4. 使用 `pnpm --filter` 在选定的包中运行命令 + +## 注意事项 + +- 确保你的项目使用 pnpm 作为包管理器 +- 确保目标包在 `package.json` 中定义了相应的脚本命令 +- 该工具需要在 monorepo 项目的根目录下运行 diff --git a/scripts/turbo-run/bin/turbo-run.mjs b/scripts/turbo-run/bin/turbo-run.mjs new file mode 100755 index 0000000..407754d --- /dev/null +++ b/scripts/turbo-run/bin/turbo-run.mjs @@ -0,0 +1,3 @@ +#!/usr/bin/env node + +import('../dist/index.mjs'); diff --git a/scripts/turbo-run/build.config.ts b/scripts/turbo-run/build.config.ts new file mode 100644 index 0000000..97e572c --- /dev/null +++ b/scripts/turbo-run/build.config.ts @@ -0,0 +1,7 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + declaration: true, + entries: ['src/index'], +}); diff --git a/scripts/turbo-run/package.json b/scripts/turbo-run/package.json new file mode 100644 index 0000000..5b4353a --- /dev/null +++ b/scripts/turbo-run/package.json @@ -0,0 +1,29 @@ +{ + "name": "@vben/turbo-run", + "version": "5.6.0", + "private": true, + "license": "MIT", + "type": "module", + "scripts": { + "stub": "pnpm unbuild --stub" + }, + "files": [ + "dist" + ], + "bin": { + "turbo-run": "./bin/turbo-run.mjs" + }, + "main": "./dist/index.mjs", + "module": "./dist/index.mjs", + "exports": { + ".": { + "default": "./dist/index.mjs" + }, + "./package.json": "./package.json" + }, + "dependencies": { + "@clack/prompts": "catalog:", + "@vben/node-utils": "workspace:*", + "cac": "catalog:" + } +} diff --git a/scripts/turbo-run/src/index.ts b/scripts/turbo-run/src/index.ts new file mode 100644 index 0000000..2f8dad0 --- /dev/null +++ b/scripts/turbo-run/src/index.ts @@ -0,0 +1,29 @@ +import { colors, consola } from '@vben/node-utils'; + +import { cac } from 'cac'; + +import { run } from './run'; + +try { + const turboRun = cac('turbo-run'); + + turboRun + .command('[script]') + .usage(`Run turbo interactively.`) + .action(async (command: string) => { + run({ command }); + }); + + // Invalid command + turboRun.on('command:*', () => { + consola.error(colors.red('Invalid command!')); + process.exit(1); + }); + + turboRun.usage('turbo-run'); + turboRun.help(); + turboRun.parse(); +} catch (error) { + consola.error(error); + process.exit(1); +} diff --git a/scripts/turbo-run/src/run.ts b/scripts/turbo-run/src/run.ts new file mode 100644 index 0000000..31f9f52 --- /dev/null +++ b/scripts/turbo-run/src/run.ts @@ -0,0 +1,67 @@ +import { execaCommand, getPackages } from '@vben/node-utils'; + +import { cancel, isCancel, select } from '@clack/prompts'; + +interface RunOptions { + command?: string; +} + +export async function run(options: RunOptions) { + const { command } = options; + if (!command) { + console.error('Please enter the command to run'); + process.exit(1); + } + const { packages } = await getPackages(); + // const appPkgs = await findApps(process.cwd(), packages); + // const websitePkg = packages.find( + // (item) => item.packageJson.name === '@vben/website', + // ); + + // 只显示有对应命令的包 + const selectPkgs = packages.filter((pkg) => { + return (pkg?.packageJson as Record)?.scripts?.[command]; + }); + + let selectPkg: string | symbol; + if (selectPkgs.length > 1) { + selectPkg = await select({ + message: `Select the app you need to run [${command}]:`, + options: selectPkgs.map((item) => ({ + label: item?.packageJson.name, + value: item?.packageJson.name, + })), + }); + + if (isCancel(selectPkg) || !selectPkg) { + cancel('👋 Has cancelled'); + process.exit(0); + } + } else { + selectPkg = selectPkgs[0]?.packageJson?.name ?? ''; + } + + if (!selectPkg) { + console.error('No app found'); + process.exit(1); + } + + execaCommand(`pnpm --filter=${selectPkg} run ${command}`, { + stdio: 'inherit', + }); +} + +/** + * 过滤app包 + * @param root + * @param packages + */ +// async function findApps(root: string, packages: Package[]) { +// // apps内的 +// const appPackages = packages.filter((pkg) => { +// const viteConfigExists = fs.existsSync(join(pkg.dir, 'vite.config.mts')); +// return pkg.dir.startsWith(join(root, 'apps')) && viteConfigExists; +// }); + +// return appPackages; +// } diff --git a/scripts/turbo-run/tsconfig.json b/scripts/turbo-run/tsconfig.json new file mode 100644 index 0000000..b2ec3b6 --- /dev/null +++ b/scripts/turbo-run/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/node.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/scripts/vsh/README.md b/scripts/vsh/README.md new file mode 100644 index 0000000..61140d6 --- /dev/null +++ b/scripts/vsh/README.md @@ -0,0 +1,56 @@ +# @vben/vsh + +一个 Shell 脚本工具集合,用于 Vue Vben Admin 项目的开发和管理。 + +## 功能特性 + +- 🚀 基于 Node.js 的现代化 Shell 工具 +- 📦 支持模块化开发和按需加载 +- 🔍 提供依赖检查和分析功能 +- 🔄 支持循环依赖扫描 +- 📝 提供包发布检查功能 + +## 安装 + +```bash +# 使用 pnpm 安装 +pnpm add -D @vben/vsh + +# 或者使用 npm +npm install -D @vben/vsh + +# 或者使用 yarn +yarn add -D @vben/vsh +``` + +## 使用方法 + +### 全局安装 + +```bash +# 全局安装 +pnpm add -g @vben/vsh + +# 使用 vsh 命令 +vsh [command] +``` + +### 本地使用 + +```bash +# 在 package.json 中添加脚本 +{ + "scripts": { + "vsh": "vsh" + } +} + +# 运行命令 +pnpm vsh [command] +``` + +## 命令列表 + +- `vsh check-deps`: 检查项目依赖 +- `vsh scan-circular`: 扫描循环依赖 +- `vsh publish-check`: 检查包发布配置 diff --git a/scripts/vsh/bin/vsh.mjs b/scripts/vsh/bin/vsh.mjs new file mode 100755 index 0000000..407754d --- /dev/null +++ b/scripts/vsh/bin/vsh.mjs @@ -0,0 +1,3 @@ +#!/usr/bin/env node + +import('../dist/index.mjs'); diff --git a/scripts/vsh/build.config.ts b/scripts/vsh/build.config.ts new file mode 100644 index 0000000..97e572c --- /dev/null +++ b/scripts/vsh/build.config.ts @@ -0,0 +1,7 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + declaration: true, + entries: ['src/index'], +}); diff --git a/scripts/vsh/package.json b/scripts/vsh/package.json new file mode 100644 index 0000000..40175e9 --- /dev/null +++ b/scripts/vsh/package.json @@ -0,0 +1,31 @@ +{ + "name": "@vben/vsh", + "version": "5.6.0", + "private": true, + "license": "MIT", + "type": "module", + "scripts": { + "stub": "pnpm unbuild --stub" + }, + "files": [ + "dist" + ], + "bin": { + "vsh": "./bin/vsh.mjs" + }, + "main": "./dist/index.mjs", + "module": "./dist/index.mjs", + "exports": { + ".": { + "default": "./dist/index.mjs" + }, + "./package.json": "./package.json" + }, + "dependencies": { + "@vben/node-utils": "workspace:*", + "cac": "catalog:", + "circular-dependency-scanner": "catalog:", + "depcheck": "catalog:", + "publint": "catalog:" + } +} diff --git a/scripts/vsh/src/check-circular/index.ts b/scripts/vsh/src/check-circular/index.ts new file mode 100644 index 0000000..0642506 --- /dev/null +++ b/scripts/vsh/src/check-circular/index.ts @@ -0,0 +1,170 @@ +import type { CAC } from 'cac'; + +import { extname } from 'node:path'; + +import { getStagedFiles } from '@vben/node-utils'; + +import { circularDepsDetect } from 'circular-dependency-scanner'; + +// 默认配置 +const DEFAULT_CONFIG = { + allowedExtensions: ['.cjs', '.js', '.jsx', '.mjs', '.ts', '.tsx', '.vue'], + ignoreDirs: [ + 'dist', + '.turbo', + 'output', + '.cache', + 'scripts', + 'internal', + 'packages/effects/request/src/', + 'packages/@core/ui-kit/menu-ui/src/', + 'packages/@core/ui-kit/popup-ui/src/', + ], + threshold: 0, // 循环依赖的阈值 +} as const; + +// 类型定义 +type CircularDependencyResult = string[]; + +interface CheckCircularConfig { + allowedExtensions?: string[]; + ignoreDirs?: string[]; + threshold?: number; +} + +interface CommandOptions { + config?: CheckCircularConfig; + staged: boolean; + verbose: boolean; +} + +// 缓存机制 +const cache = new Map(); + +/** + * 格式化循环依赖的输出 + * @param circles - 循环依赖结果 + */ +function formatCircles(circles: CircularDependencyResult[]): void { + if (circles.length === 0) { + console.log('✅ No circular dependencies found'); + return; + } + + console.log('⚠️ Circular dependencies found:'); + circles.forEach((circle, index) => { + console.log(`\nCircular dependency #${index + 1}:`); + circle.forEach((file) => console.log(` → ${file}`)); + }); +} + +/** + * 检查项目中的循环依赖 + * @param options - 检查选项 + * @param options.staged - 是否只检查暂存区文件 + * @param options.verbose - 是否显示详细信息 + * @param options.config - 自定义配置 + * @returns Promise + */ +async function checkCircular({ + config = {}, + staged, + verbose, +}: CommandOptions): Promise { + try { + // 合并配置 + const finalConfig = { + ...DEFAULT_CONFIG, + ...config, + }; + + // 生成忽略模式 + const ignorePattern = `**/{${finalConfig.ignoreDirs.join(',')}}/**`; + + // 检查缓存 + const cacheKey = `${staged}-${process.cwd()}-${ignorePattern}`; + if (cache.has(cacheKey)) { + const cachedResults = cache.get(cacheKey); + if (cachedResults) { + verbose && formatCircles(cachedResults); + } + return; + } + + // 检测循环依赖 + const results = await circularDepsDetect({ + absolute: staged, + cwd: process.cwd(), + ignore: [ignorePattern], + }); + + if (staged) { + let files = await getStagedFiles(); + const allowedExtensions = new Set(finalConfig.allowedExtensions); + + // 过滤文件列表 + files = files.filter((file) => allowedExtensions.has(extname(file))); + + const circularFiles: CircularDependencyResult[] = []; + + for (const file of files) { + for (const result of results) { + const resultFiles = result.flat(); + if (resultFiles.includes(file)) { + circularFiles.push(result); + } + } + } + + // 更新缓存 + cache.set(cacheKey, circularFiles); + verbose && formatCircles(circularFiles); + } else { + // 更新缓存 + cache.set(cacheKey, results); + verbose && formatCircles(results); + } + + // 如果发现循环依赖,只输出警告信息 + if (results.length > 0) { + console.log( + '\n⚠️ Warning: Circular dependencies found, please check and fix', + ); + } + } catch (error) { + console.error( + '❌ Error checking circular dependencies:', + error instanceof Error ? error.message : error, + ); + } +} + +/** + * 定义检查循环依赖的命令 + * @param cac - CAC实例 + */ +function defineCheckCircularCommand(cac: CAC): void { + cac + .command('check-circular') + .option('--staged', 'Only check staged files') + .option('--verbose', 'Show detailed information') + .option('--threshold ', 'Threshold for circular dependencies', { + default: 0, + }) + .option('--ignore-dirs ', 'Directories to ignore, comma separated') + .usage('Analyze project circular dependencies') + .action(async ({ ignoreDirs, staged, threshold, verbose }) => { + const config: CheckCircularConfig = { + threshold: Number(threshold), + ...(ignoreDirs && { ignoreDirs: ignoreDirs.split(',') }), + }; + + await checkCircular({ + config, + staged, + verbose: verbose ?? true, + }); + }); +} + +export { type CheckCircularConfig, defineCheckCircularCommand }; diff --git a/scripts/vsh/src/check-dep/index.ts b/scripts/vsh/src/check-dep/index.ts new file mode 100644 index 0000000..3da10b9 --- /dev/null +++ b/scripts/vsh/src/check-dep/index.ts @@ -0,0 +1,193 @@ +import type { CAC } from 'cac'; + +import { getPackages } from '@vben/node-utils'; + +import depcheck from 'depcheck'; + +// 默认配置 +const DEFAULT_CONFIG = { + // 需要忽略的依赖匹配 + ignoreMatches: [ + 'vite', + 'vitest', + 'unbuild', + '@vben/tsconfig', + '@vben/vite-config', + '@vben/tailwind-config', + '@types/*', + '@vben-core/design', + ], + // 需要忽略的包 + ignorePackages: [ + '@vben/commitlint-config', + '@vben/eslint-config', + '@vben/node-utils', + '@vben/prettier-config', + '@vben/stylelint-config', + '@vben/tailwind-config', + '@vben/tsconfig', + '@vben/vite-config', + '@vben/vsh', + ], + // 需要忽略的文件模式 + ignorePatterns: ['dist', 'node_modules', 'public'], +}; + +interface DepcheckResult { + dependencies: string[]; + devDependencies: string[]; + missing: Record; +} + +interface DepcheckConfig { + ignoreMatches?: string[]; + ignorePackages?: string[]; + ignorePatterns?: string[]; +} + +interface PackageInfo { + dir: string; + packageJson: { + name: string; + }; +} + +/** + * 清理依赖检查结果 + * @param unused - 依赖检查结果 + */ +function cleanDepcheckResult(unused: DepcheckResult): void { + // 删除file:前缀的依赖提示,该依赖是本地依赖 + Reflect.deleteProperty(unused.missing, 'file:'); + + // 清理路径依赖 + Object.keys(unused.missing).forEach((key) => { + unused.missing[key] = (unused.missing[key] || []).filter( + (item: string) => !item.startsWith('/'), + ); + if (unused.missing[key].length === 0) { + Reflect.deleteProperty(unused.missing, key); + } + }); +} + +/** + * 格式化依赖检查结果 + * @param pkgName - 包名 + * @param unused - 依赖检查结果 + */ +function formatDepcheckResult(pkgName: string, unused: DepcheckResult): void { + const hasIssues = + Object.keys(unused.missing).length > 0 || + unused.dependencies.length > 0 || + unused.devDependencies.length > 0; + + if (!hasIssues) { + return; + } + + console.log('\n📦 Package:', pkgName); + + if (Object.keys(unused.missing).length > 0) { + console.log('❌ Missing dependencies:'); + Object.entries(unused.missing).forEach(([dep, files]) => { + console.log(` - ${dep}:`); + files.forEach((file) => console.log(` → ${file}`)); + }); + } + + if (unused.dependencies.length > 0) { + console.log('⚠️ Unused dependencies:'); + unused.dependencies.forEach((dep) => console.log(` - ${dep}`)); + } + + if (unused.devDependencies.length > 0) { + console.log('⚠️ Unused devDependencies:'); + unused.devDependencies.forEach((dep) => console.log(` - ${dep}`)); + } +} + +/** + * 运行依赖检查 + * @param config - 配置选项 + */ +async function runDepcheck(config: DepcheckConfig = {}): Promise { + try { + const finalConfig = { + ...DEFAULT_CONFIG, + ...config, + }; + + const { packages } = await getPackages(); + + let hasIssues = false; + + await Promise.all( + packages.map(async (pkg: PackageInfo) => { + // 跳过需要忽略的包 + if (finalConfig.ignorePackages.includes(pkg.packageJson.name)) { + return; + } + + const unused = await depcheck(pkg.dir, { + ignoreMatches: finalConfig.ignoreMatches, + ignorePatterns: finalConfig.ignorePatterns, + }); + + cleanDepcheckResult(unused); + + const pkgHasIssues = + Object.keys(unused.missing).length > 0 || + unused.dependencies.length > 0 || + unused.devDependencies.length > 0; + + if (pkgHasIssues) { + hasIssues = true; + formatDepcheckResult(pkg.packageJson.name, unused); + } + }), + ); + + if (!hasIssues) { + console.log('\n✅ Dependency check completed, no issues found'); + } + } catch (error) { + console.error( + '❌ Dependency check failed:', + error instanceof Error ? error.message : error, + ); + } +} + +/** + * 定义依赖检查命令 + * @param cac - CAC实例 + */ +function defineDepcheckCommand(cac: CAC): void { + cac + .command('check-dep') + .option( + '--ignore-packages ', + 'Packages to ignore, comma separated', + ) + .option( + '--ignore-matches ', + 'Dependency patterns to ignore, comma separated', + ) + .option( + '--ignore-patterns ', + 'File patterns to ignore, comma separated', + ) + .usage('Analyze project dependencies') + .action(async ({ ignoreMatches, ignorePackages, ignorePatterns }) => { + const config: DepcheckConfig = { + ...(ignorePackages && { ignorePackages: ignorePackages.split(',') }), + ...(ignoreMatches && { ignoreMatches: ignoreMatches.split(',') }), + ...(ignorePatterns && { ignorePatterns: ignorePatterns.split(',') }), + }; + + await runDepcheck(config); + }); +} + +export { defineDepcheckCommand, type DepcheckConfig }; diff --git a/scripts/vsh/src/code-workspace/index.ts b/scripts/vsh/src/code-workspace/index.ts new file mode 100644 index 0000000..d5ec4ee --- /dev/null +++ b/scripts/vsh/src/code-workspace/index.ts @@ -0,0 +1,78 @@ +import type { CAC } from 'cac'; + +import { join, relative } from 'node:path'; + +import { + colors, + consola, + findMonorepoRoot, + getPackages, + gitAdd, + outputJSON, + prettierFormat, + toPosixPath, +} from '@vben/node-utils'; + +const CODE_WORKSPACE_FILE = join('vben-admin.code-workspace'); + +interface CodeWorkspaceCommandOptions { + autoCommit?: boolean; + spaces?: number; +} + +async function createCodeWorkspace({ + autoCommit = false, + spaces = 2, +}: CodeWorkspaceCommandOptions) { + const { packages, rootDir } = await getPackages(); + + let folders = packages.map((pkg) => { + const { dir, packageJson } = pkg; + return { + name: packageJson.name, + path: toPosixPath(relative(rootDir, dir)), + }; + }); + + folders = folders.filter(Boolean); + + const monorepoRoot = findMonorepoRoot(); + const outputPath = join(monorepoRoot, CODE_WORKSPACE_FILE); + await outputJSON(outputPath, { folders }, spaces); + + await prettierFormat(outputPath); + if (autoCommit) { + await gitAdd(CODE_WORKSPACE_FILE, monorepoRoot); + } +} + +async function runCodeWorkspace({ + autoCommit, + spaces, +}: CodeWorkspaceCommandOptions) { + await createCodeWorkspace({ + autoCommit, + spaces, + }); + if (autoCommit) { + return; + } + consola.log(''); + consola.success(colors.green(`${CODE_WORKSPACE_FILE} is updated!`)); + consola.log(''); +} + +function defineCodeWorkspaceCommand(cac: CAC) { + cac + .command('code-workspace') + .usage('Update the `.code-workspace` file') + .option('--spaces [number]', '.code-workspace JSON file spaces.', { + default: 2, + }) + .option('--auto-commit', 'auto commit .code-workspace JSON file.', { + default: false, + }) + .action(runCodeWorkspace); +} + +export { defineCodeWorkspaceCommand }; diff --git a/scripts/vsh/src/index.ts b/scripts/vsh/src/index.ts new file mode 100644 index 0000000..4943425 --- /dev/null +++ b/scripts/vsh/src/index.ts @@ -0,0 +1,74 @@ +import { colors, consola } from '@vben/node-utils'; + +import { cac } from 'cac'; + +import { version } from '../package.json'; +import { defineCheckCircularCommand } from './check-circular'; +import { defineDepcheckCommand } from './check-dep'; +import { defineCodeWorkspaceCommand } from './code-workspace'; +import { defineLintCommand } from './lint'; +import { definePubLintCommand } from './publint'; + +// 命令描述 +const COMMAND_DESCRIPTIONS = { + 'check-circular': 'Check for circular dependencies', + 'check-dep': 'Check for unused dependencies', + 'code-workspace': 'Manage VS Code workspace settings', + lint: 'Run linting on the project', + publint: 'Check package.json files for publishing standards', +} as const; + +/** + * Initialize and run the CLI + */ +async function main(): Promise { + try { + const vsh = cac('vsh'); + + // Register commands + defineLintCommand(vsh); + definePubLintCommand(vsh); + defineCodeWorkspaceCommand(vsh); + defineCheckCircularCommand(vsh); + defineDepcheckCommand(vsh); + + // Handle invalid commands + vsh.on('command:*', ([cmd]) => { + consola.error( + colors.red(`Invalid command: ${cmd}`), + '\n', + colors.yellow('Available commands:'), + '\n', + Object.entries(COMMAND_DESCRIPTIONS) + .map(([cmd, desc]) => ` ${colors.cyan(cmd)} - ${desc}`) + .join('\n'), + ); + process.exit(1); + }); + + // Set up CLI + vsh.usage('vsh [options]'); + vsh.help(); + vsh.version(version); + + // Parse arguments + vsh.parse(); + } catch (error) { + consola.error( + colors.red('An unexpected error occurred:'), + '\n', + error instanceof Error ? error.message : error, + ); + process.exit(1); + } +} + +// Run the CLI +main().catch((error) => { + consola.error( + colors.red('Failed to start CLI:'), + '\n', + error instanceof Error ? error.message : error, + ); + process.exit(1); +}); diff --git a/scripts/vsh/src/lint/index.ts b/scripts/vsh/src/lint/index.ts new file mode 100644 index 0000000..b95ead6 --- /dev/null +++ b/scripts/vsh/src/lint/index.ts @@ -0,0 +1,48 @@ +import type { CAC } from 'cac'; + +import { execaCommand } from '@vben/node-utils'; + +interface LintCommandOptions { + /** + * Format lint problem. + */ + format?: boolean; +} + +async function runLint({ format }: LintCommandOptions) { + // process.env.FORCE_COLOR = '3'; + + if (format) { + await execaCommand(`stylelint "**/*.{vue,css,less,scss}" --cache --fix`, { + stdio: 'inherit', + }); + await execaCommand(`eslint . --cache --fix`, { + stdio: 'inherit', + }); + await execaCommand(`prettier . --write --cache --log-level warn`, { + stdio: 'inherit', + }); + return; + } + await Promise.all([ + execaCommand(`eslint . --cache`, { + stdio: 'inherit', + }), + execaCommand(`prettier . --ignore-unknown --check --cache`, { + stdio: 'inherit', + }), + execaCommand(`stylelint "**/*.{vue,css,less,scss}" --cache`, { + stdio: 'inherit', + }), + ]); +} + +function defineLintCommand(cac: CAC) { + cac + .command('lint') + .usage('Batch execute project lint check.') + .option('--format', 'Format lint problem.') + .action(runLint); +} + +export { defineLintCommand }; diff --git a/scripts/vsh/src/publint/index.ts b/scripts/vsh/src/publint/index.ts new file mode 100644 index 0000000..d078673 --- /dev/null +++ b/scripts/vsh/src/publint/index.ts @@ -0,0 +1,185 @@ +import type { CAC } from 'cac'; +import type { Result } from 'publint'; + +import { basename, dirname, join } from 'node:path'; + +import { + colors, + consola, + ensureFile, + findMonorepoRoot, + generatorContentHash, + getPackages, + outputJSON, + readJSON, + UNICODE, +} from '@vben/node-utils'; + +import { publint } from 'publint'; +import { formatMessage } from 'publint/utils'; + +const CACHE_FILE = join( + 'node_modules', + '.cache', + 'publint', + '.pkglintcache.json', +); + +interface PubLintCommandOptions { + /** + * Only errors are checked, no program exit is performed + */ + check?: boolean; +} + +/** + * Get files that require lint + * @param files + */ +async function getLintFiles(files: string[] = []) { + const lintFiles: string[] = []; + + if (files?.length > 0) { + return files.filter((file) => basename(file) === 'package.json'); + } + + const { packages } = await getPackages(); + + for (const { dir } of packages) { + lintFiles.push(join(dir, 'package.json')); + } + return lintFiles; +} + +function getCacheFile() { + const root = findMonorepoRoot(); + return join(root, CACHE_FILE); +} + +async function readCache(cacheFile: string) { + try { + await ensureFile(cacheFile); + return await readJSON(cacheFile); + } catch { + return {}; + } +} + +async function runPublint(files: string[], { check }: PubLintCommandOptions) { + const lintFiles = await getLintFiles(files); + const cacheFile = getCacheFile(); + + const cacheData = await readCache(cacheFile); + const cache: Record = cacheData; + + const results = await Promise.all( + lintFiles.map(async (file) => { + try { + const pkgJson = await readJSON(file); + + if (pkgJson.private) { + return null; + } + + Reflect.deleteProperty(pkgJson, 'dependencies'); + Reflect.deleteProperty(pkgJson, 'devDependencies'); + Reflect.deleteProperty(pkgJson, 'peerDependencies'); + const content = JSON.stringify(pkgJson); + const hash = generatorContentHash(content); + + const publintResult: Result = + cache?.[file]?.hash === hash + ? (cache?.[file]?.result ?? []) + : await publint({ + level: 'suggestion', + pkgDir: dirname(file), + strict: true, + }); + + cache[file] = { + hash, + result: publintResult, + }; + + return { pkgJson, pkgPath: file, publintResult }; + } catch { + return null; + } + }), + ); + + await outputJSON(cacheFile, cache); + printResult(results, check); +} + +function printResult( + results: Array; + pkgPath: string; + publintResult: Result; + }>, + check?: boolean, +) { + let errorCount = 0; + let warningCount = 0; + let suggestionsCount = 0; + + for (const result of results) { + if (!result) { + continue; + } + const { pkgJson, pkgPath, publintResult } = result; + const messages = publintResult?.messages ?? []; + if (messages?.length < 1) { + continue; + } + + consola.log(''); + consola.log(pkgPath); + for (const message of messages) { + switch (message.type) { + case 'error': { + errorCount++; + + break; + } + case 'suggestion': { + suggestionsCount++; + break; + } + case 'warning': { + warningCount++; + + break; + } + // No default + } + const ruleUrl = `https://publint.dev/rules#${message.code.toLocaleLowerCase()}`; + consola.log( + ` ${formatMessage(message, pkgJson)}${colors.dim(` ${ruleUrl}`)}`, + ); + } + } + + const totalCount = warningCount + errorCount + suggestionsCount; + if (totalCount > 0) { + consola.error( + colors.red( + `${UNICODE.FAILURE} ${totalCount} problem (${errorCount} errors, ${warningCount} warnings, ${suggestionsCount} suggestions)`, + ), + ); + !check && process.exit(1); + } else { + consola.log(colors.green(`${UNICODE.SUCCESS} No problem`)); + } +} + +function definePubLintCommand(cac: CAC) { + cac + .command('publint [...files]') + .usage('Check if the monorepo package conforms to the publint standard.') + .option('--check', 'Only errors are checked, no program exit is performed.') + .action(runPublint); +} + +export { definePubLintCommand }; diff --git a/scripts/vsh/tsconfig.json b/scripts/vsh/tsconfig.json new file mode 100644 index 0000000..b2ec3b6 --- /dev/null +++ b/scripts/vsh/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/node.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/stylelint.config.mjs b/stylelint.config.mjs new file mode 100644 index 0000000..e380674 --- /dev/null +++ b/stylelint.config.mjs @@ -0,0 +1,4 @@ +export default { + extends: ['@vben/stylelint-config'], + root: true, +}; diff --git a/tea.yaml b/tea.yaml new file mode 100644 index 0000000..6e56d6f --- /dev/null +++ b/tea.yaml @@ -0,0 +1,6 @@ +# https://tea.xyz/what-is-this-file +--- +version: 1.0.0 +codeOwners: + - '0xB33cc732DFc15Cd39eF50Fb165c876E24417E48f' +quorum: 1 diff --git a/turbo.json b/turbo.json new file mode 100644 index 0000000..7226f13 --- /dev/null +++ b/turbo.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://turbo.build/schema.json", + "globalDependencies": [ + "pnpm-lock.yaml", + "**/.env.*local", + "**/tsconfig*.json", + "internal/node-utils/*.json", + "internal/node-utils/src/**/*.ts", + "internal/tailwind-config/src/**/*.ts", + "internal/vite-config/*.json", + "internal/vite-config/src/**/*.ts", + "scripts/*/src/**/*.ts", + "scripts/*/src/**/*.json" + ], + "globalEnv": ["NODE_ENV"], + "tasks": { + "build": { + "dependsOn": ["^build"], + "outputs": [ + "dist/**", + "dist.zip", + ".vitepress/dist.zip", + ".vitepress/dist/**" + ] + }, + "preview": { + "dependsOn": ["^build"], + "outputs": ["dist/**"] + }, + "build:analyze": { + "dependsOn": ["^build"], + "outputs": ["dist/**"] + }, + "test:e2e": {}, + "dev": { + "dependsOn": [], + "outputs": [], + "cache": false, + "persistent": true + }, + "typecheck": { + "outputs": [] + } + } +} diff --git a/vben-admin.code-workspace b/vben-admin.code-workspace new file mode 100644 index 0000000..dbe9ae2 --- /dev/null +++ b/vben-admin.code-workspace @@ -0,0 +1,172 @@ +{ + "folders": [ + { + "name": "@vben/web-antd", + "path": "apps/web-antd", + }, + { + "name": "@vben/web-antdv-next", + "path": "apps/web-antdv-next", + }, + { + "name": "@vben/web-ele", + "path": "apps/web-ele", + }, + { + "name": "@vben/web-naive", + "path": "apps/web-naive", + }, + { + "name": "@vben/web-tdesign", + "path": "apps/web-tdesign", + }, + { + "name": "@vben/docs", + "path": "docs", + }, + { + "name": "@vben/commitlint-config", + "path": "internal/lint-configs/commitlint-config", + }, + { + "name": "@vben/eslint-config", + "path": "internal/lint-configs/eslint-config", + }, + { + "name": "@vben/prettier-config", + "path": "internal/lint-configs/prettier-config", + }, + { + "name": "@vben/stylelint-config", + "path": "internal/lint-configs/stylelint-config", + }, + { + "name": "@vben/node-utils", + "path": "internal/node-utils", + }, + { + "name": "@vben/tailwind-config", + "path": "internal/tailwind-config", + }, + { + "name": "@vben/tsconfig", + "path": "internal/tsconfig", + }, + { + "name": "@vben/vite-config", + "path": "internal/vite-config", + }, + { + "name": "@vben-core/design", + "path": "packages/@core/base/design", + }, + { + "name": "@vben-core/icons", + "path": "packages/@core/base/icons", + }, + { + "name": "@vben-core/shared", + "path": "packages/@core/base/shared", + }, + { + "name": "@vben-core/typings", + "path": "packages/@core/base/typings", + }, + { + "name": "@vben-core/composables", + "path": "packages/@core/composables", + }, + { + "name": "@vben-core/preferences", + "path": "packages/@core/preferences", + }, + { + "name": "@vben-core/form-ui", + "path": "packages/@core/ui-kit/form-ui", + }, + { + "name": "@vben-core/layout-ui", + "path": "packages/@core/ui-kit/layout-ui", + }, + { + "name": "@vben-core/menu-ui", + "path": "packages/@core/ui-kit/menu-ui", + }, + { + "name": "@vben-core/popup-ui", + "path": "packages/@core/ui-kit/popup-ui", + }, + { + "name": "@vben-core/shadcn-ui", + "path": "packages/@core/ui-kit/shadcn-ui", + }, + { + "name": "@vben-core/tabs-ui", + "path": "packages/@core/ui-kit/tabs-ui", + }, + { + "name": "@vben/constants", + "path": "packages/constants", + }, + { + "name": "@vben/access", + "path": "packages/effects/access", + }, + { + "name": "@vben/common-ui", + "path": "packages/effects/common-ui", + }, + { + "name": "@vben/hooks", + "path": "packages/effects/hooks", + }, + { + "name": "@vben/layouts", + "path": "packages/effects/layouts", + }, + { + "name": "@vben/plugins", + "path": "packages/effects/plugins", + }, + { + "name": "@vben/request", + "path": "packages/effects/request", + }, + { + "name": "@vben/icons", + "path": "packages/icons", + }, + { + "name": "@vben/locales", + "path": "packages/locales", + }, + { + "name": "@vben/preferences", + "path": "packages/preferences", + }, + { + "name": "@vben/stores", + "path": "packages/stores", + }, + { + "name": "@vben/styles", + "path": "packages/styles", + }, + { + "name": "@vben/types", + "path": "packages/types", + }, + { + "name": "@vben/utils", + "path": "packages/utils", + }, + { + "name": "@vben/turbo-run", + "path": "scripts/turbo-run", + }, + { + "name": "@vben/vsh", + "path": "scripts/vsh", + }, + ], +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..a5ecd3d --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,19 @@ +import Vue from '@vitejs/plugin-vue'; +import VueJsx from '@vitejs/plugin-vue-jsx'; +import { configDefaults, defineConfig } from 'vitest/config'; + +export default defineConfig({ + plugins: [Vue(), VueJsx()], + test: { + environment: 'happy-dom', + exclude: [ + ...configDefaults.exclude, + '**/e2e/**', + '**/dist/**', + '**/.{idea,git,cache,output,temp}/**', + '**/node_modules/**', + '**/{stylelint,eslint}.config.*', + '.prettierrc.mjs', + ], + }, +});