From f56dc58277702ab696ebfebb5723e926bfdec0a3 Mon Sep 17 00:00:00 2001 From: Mrxtyyp <1126084777@qq.com> Date: Wed, 28 Aug 2024 14:28:57 +0800 Subject: [PATCH] feat: first commit --- .DS_Store | Bin 0 -> 8196 bytes .dockerignore | 3 + .env | 5 + .env.analyze | 23 + .env.development | 16 + .env.docker | 22 + .env.production | 25 + .eslintignore | 15 + .eslintrc.js | 15 + .gitignore | 110 + .npmrc | 7 + .prettierignore | 17 + .prettierrc.js | 20 + .stylelintrc.js | 4 + LICENSE-APACHE | 201 + LICENSE-MIT | 21 + README-zh_CN.md | 114 + README.md | 114 + deploy/default.conf | 18 + docs/README_ZH.md | 24 + docs/template/会员信息模板.xlsx | Bin 0 -> 18944 bytes docs/template/供应商模板.xlsx | Bin 0 -> 19456 bytes docs/template/客户信息模板.xlsx | Bin 0 -> 19456 bytes images/add-menu-zh.png | Bin 0 -> 92146 bytes images/home-page-zh.png | Bin 0 -> 121887 bytes images/login-page-en.png | Bin 0 -> 201474 bytes images/register-page-zh.png | Bin 0 -> 194526 bytes images/role-permission-zh.png | Bin 0 -> 98014 bytes images/user-manage-zh.png | Bin 0 -> 78390 bytes images/user-mgt.png | Bin 0 -> 117563 bytes images/wansenai-logo.png | Bin 0 -> 7551 bytes index.html | 153 + internal/.DS_Store | Bin 0 -> 6148 bytes internal/stylelint-config/.eslintignore | 4 + internal/stylelint-config/build.config.ts | 10 + internal/stylelint-config/package.json | 38 + internal/stylelint-config/src/index.ts | 91 + internal/stylelint-config/tsconfig.json | 5 + internal/ts-config/.eslintignore | 4 + internal/ts-config/base.json | 27 + internal/ts-config/node-server.json | 18 + internal/ts-config/node.json | 12 + internal/ts-config/package.json | 16 + internal/ts-config/vue-app.json | 11 + internal/vite-config/.eslintignore | 4 + internal/vite-config/build.config.ts | 10 + internal/vite-config/package.json | 49 + .../vite-config/src/config/application.ts | 109 + internal/vite-config/src/config/common.ts | 22 + internal/vite-config/src/config/package.ts | 42 + internal/vite-config/src/index.ts | 2 + internal/vite-config/src/plugins/appConfig.ts | 104 + internal/vite-config/src/plugins/compress.ts | 38 + internal/vite-config/src/plugins/html.ts | 13 + internal/vite-config/src/plugins/index.ts | 59 + internal/vite-config/src/plugins/mock.ts | 19 + internal/vite-config/src/plugins/svgSprite.ts | 17 + .../vite-config/src/plugins/visualizer.ts | 14 + internal/vite-config/src/utils/env.ts | 49 + internal/vite-config/src/utils/hash.ts | 16 + internal/vite-config/src/utils/modifyVars.ts | 47 + internal/vite-config/tsconfig.json | 5 + nginx.conf | 33 + package.json | 155 + packages/.DS_Store | Bin 0 -> 6148 bytes packages/hooks/.eslintrc.js | 4 + packages/hooks/build.config.ts | 10 + packages/hooks/package.json | 29 + packages/hooks/src/index.ts | 6 + packages/hooks/src/onMountedOrActivated.ts | 25 + packages/hooks/src/useAttrs.ts | 43 + packages/hooks/src/useRefs.ts | 24 + packages/hooks/src/useScrollTo.ts | 60 + packages/hooks/src/useWindowSizeFn.ts | 40 + packages/hooks/tsconfig.json | 5 + packages/types/.eslintrc.js | 4 + packages/types/build.config.ts | 10 + packages/types/package.json | 22 + packages/types/src/index.ts | 1 + packages/types/src/utils.ts | 58 + packages/types/tsconfig.json | 5 + pnpm-lock.yaml | 12718 ++++++++++++++++ pnpm-workspace.yaml | 4 + public/favicon.ico | Bin 0 -> 16025 bytes public/resource/.DS_Store | Bin 0 -> 6148 bytes public/resource/img/logo.png | Bin 0 -> 16025 bytes .../tinymce/icons/default/icons.min.js | 1 + public/resource/tinymce/langs/README.md | 3 + public/resource/tinymce/langs/en.js | 419 + public/resource/tinymce/langs/zh_CN.js | 389 + public/resource/tinymce/license.txt | 21 + .../resource/tinymce/models/dom/model.min.js | 4 + .../tinymce/plugins/advlist/plugin.min.js | 4 + .../tinymce/plugins/anchor/plugin.min.js | 4 + .../tinymce/plugins/autolink/plugin.min.js | 4 + .../tinymce/plugins/autoresize/plugin.min.js | 4 + .../tinymce/plugins/autosave/plugin.min.js | 4 + .../tinymce/plugins/charmap/plugin.min.js | 4 + .../tinymce/plugins/code/plugin.min.js | 4 + .../tinymce/plugins/codesample/plugin.min.js | 4 + .../plugins/directionality/plugin.min.js | 4 + .../plugins/emoticons/js/emojiimages.js | 1 + .../plugins/emoticons/js/emojiimages.min.js | 3 + .../tinymce/plugins/emoticons/js/emojis.js | 1 + .../plugins/emoticons/js/emojis.min.js | 2 + .../tinymce/plugins/emoticons/plugin.min.js | 4 + .../tinymce/plugins/fullscreen/plugin.min.js | 4 + .../tinymce/plugins/help/plugin.min.js | 4 + .../tinymce/plugins/image/plugin.min.js | 4 + .../tinymce/plugins/importcss/plugin.min.js | 4 + .../plugins/insertdatetime/plugin.min.js | 4 + .../tinymce/plugins/link/plugin.min.js | 4 + .../tinymce/plugins/lists/plugin.min.js | 4 + .../tinymce/plugins/media/plugin.min.js | 4 + .../tinymce/plugins/nonbreaking/plugin.min.js | 4 + .../tinymce/plugins/pagebreak/plugin.min.js | 4 + .../tinymce/plugins/preview/plugin.min.js | 4 + .../tinymce/plugins/quickbars/plugin.min.js | 4 + .../tinymce/plugins/save/plugin.min.js | 4 + .../plugins/searchreplace/plugin.min.js | 4 + .../tinymce/plugins/table/plugin.min.js | 4 + .../tinymce/plugins/template/plugin.min.js | 4 + .../plugins/visualblocks/plugin.min.js | 4 + .../tinymce/plugins/visualchars/plugin.min.js | 4 + .../tinymce/plugins/wordcount/plugin.min.js | 4 + .../skins/content/dark/content.min.css | 1 + .../skins/content/default/content.min.css | 1 + .../skins/content/document/content.min.css | 1 + .../content/tinymce-5-dark/content.min.css | 1 + .../skins/content/tinymce-5/content.min.css | 1 + .../skins/content/writer/content.min.css | 1 + .../ui/oxide-dark/content.inline.min.css | 1 + .../skins/ui/oxide-dark/content.min.css | 1 + .../tinymce/skins/ui/oxide-dark/skin.min.css | 1 + .../ui/oxide-dark/skin.shadowdom.min.css | 1 + .../skins/ui/oxide/content.inline.min.css | 1 + .../tinymce/skins/ui/oxide/content.min.css | 1 + .../tinymce/skins/ui/oxide/skin.min.css | 1 + .../skins/ui/oxide/skin.shadowdom.min.css | 1 + .../ui/tinymce-5-dark/content.inline.min.css | 1 + .../skins/ui/tinymce-5-dark/content.min.css | 1 + .../skins/ui/tinymce-5-dark/skin.min.css | 1 + .../ui/tinymce-5-dark/skin.shadowdom.min.css | 1 + .../skins/ui/tinymce-5/content.inline.min.css | 1 + .../skins/ui/tinymce-5/content.min.css | 1 + .../tinymce/skins/ui/tinymce-5/skin.min.css | 1 + .../skins/ui/tinymce-5/skin.shadowdom.min.css | 1 + .../tinymce/themes/silver/theme.min.js | 4 + public/resource/tinymce/tinymce.d.ts | 3185 ++++ public/resource/tinymce/tinymce.min.js | 4 + src/.DS_Store | Bin 0 -> 10244 bytes src/App.vue | 25 + src/api/.DS_Store | Bin 0 -> 8196 bytes src/api/basic/common.ts | 89 + src/api/basic/customer.ts | 82 + src/api/basic/incomeExpense.ts | 69 + src/api/basic/member.ts | 79 + src/api/basic/model/customerModel.ts | 49 + src/api/basic/model/incomeExpenseModel.ts | 24 + src/api/basic/model/memberModel.ts | 29 + src/api/basic/model/operatorModel.ts | 23 + src/api/basic/model/supplierModel.ts | 88 + src/api/basic/model/warehouseModel.ts | 33 + src/api/basic/operator.ts | 68 + src/api/basic/supplier.ts | 94 + src/api/basic/warehouse.ts | 86 + src/api/financial/account.ts | 68 + src/api/financial/advance.ts | 96 + src/api/financial/collection.ts | 99 + src/api/financial/expense.ts | 89 + src/api/financial/income.ts | 88 + src/api/financial/model/accountModel.ts | 29 + src/api/financial/model/advanceModel.ts | 65 + src/api/financial/model/collectionModel.ts | 86 + src/api/financial/model/expenseModel.ts | 58 + src/api/financial/model/incomeModel.ts | 58 + src/api/financial/model/paymentModel.ts | 87 + src/api/financial/model/transferModel.ts | 54 + src/api/financial/payment.ts | 101 + src/api/financial/transfer.ts | 89 + src/api/model/baseModel.ts | 25 + .../product/model/productAttributeModel.ts | 30 + src/api/product/model/productCategoryModel.ts | 24 + src/api/product/model/productModel.ts | 183 + src/api/product/model/productUnitModel.ts | 28 + src/api/product/product.ts | 137 + src/api/product/productAttribute.ts | 52 + src/api/product/productCategory.ts | 43 + src/api/product/productUnit.ts | 58 + src/api/purchase/model/orderModel.ts | 82 + src/api/purchase/model/refundModel.ts | 69 + src/api/purchase/model/storageModel.ts | 68 + src/api/purchase/order.ts | 97 + src/api/purchase/refund.ts | 97 + src/api/purchase/storage.ts | 97 + src/api/receipt/model/receiptModel.ts | 37 + src/api/receipt/receipt.ts | 26 + src/api/report/report.ts | 359 + src/api/report/reportModel.ts | 313 + src/api/retail/model/refundModel.ts | 49 + src/api/retail/model/shipmentsModel.ts | 82 + src/api/retail/refund.ts | 102 + src/api/retail/shipments.ts | 118 + src/api/sale/model/orderModel.ts | 83 + src/api/sale/model/refundModel.ts | 94 + src/api/sale/model/shipmentsModel.ts | 94 + src/api/sale/order.ts | 98 + src/api/sale/refund.ts | 98 + src/api/sale/shipments.ts | 98 + src/api/sys/captcha.ts | 23 + src/api/sys/config.ts | 20 + src/api/sys/dept.ts | 42 + src/api/sys/menu.ts | 37 + src/api/sys/message.ts | 21 + src/api/sys/model/MessageModel.ts | 22 + src/api/sys/model/captchaModel.ts | 12 + src/api/sys/model/configModel.ts | 20 + src/api/sys/model/dpetModel.ts | 29 + src/api/sys/model/menuModel.ts | 70 + src/api/sys/model/roleModel.ts | 35 + src/api/sys/model/tenantModel.ts | 33 + src/api/sys/model/uploadModel.ts | 5 + src/api/sys/model/userModel.ts | 134 + src/api/sys/role.ts | 73 + src/api/sys/tenant.ts | 50 + src/api/sys/upload.ts | 25 + src/api/sys/user.ts | 295 + src/api/warehouse/allotShipments.ts | 89 + src/api/warehouse/assemble.ts | 89 + src/api/warehouse/disassemble.ts | 89 + .../warehouse/model/allotShipmentsModel.ts | 60 + src/api/warehouse/model/assembleModel.ts | 60 + src/api/warehouse/model/disassembleModel.ts | 71 + src/api/warehouse/model/shipmentsModel.ts | 65 + src/api/warehouse/model/storageModel.ts | 64 + src/api/warehouse/shipments.ts | 89 + src/api/warehouse/storage.ts | 89 + src/assets/.DS_Store | Bin 0 -> 6148 bytes src/assets/icons/download-count.svg | 1 + src/assets/icons/dynamic-avatar-1.svg | 1 + src/assets/icons/dynamic-avatar-2.svg | 1 + src/assets/icons/dynamic-avatar-3.svg | 1 + src/assets/icons/dynamic-avatar-4.svg | 1 + src/assets/icons/dynamic-avatar-5.svg | 1 + src/assets/icons/dynamic-avatar-6.svg | 1 + src/assets/icons/moon.svg | 16 + src/assets/icons/sun.svg | 42 + src/assets/icons/test.svg | 21 + src/assets/icons/total-sales.svg | 1 + src/assets/icons/transaction.svg | 1 + src/assets/icons/visit-count.svg | 1 + src/assets/images/demo.png | Bin 0 -> 33342 bytes src/assets/images/header.jpg | Bin 0 -> 31553 bytes src/assets/images/login-page-bg-2.png | Bin 0 -> 253341 bytes src/assets/images/logo.png | Bin 0 -> 16025 bytes src/assets/svg/illustration.svg | 1 + src/assets/svg/login-bg-dark.svg | 19 + src/assets/svg/login-bg.svg | 17 + src/assets/svg/login-box-bg.svg | 1 + src/assets/svg/net-error.svg | 1 + src/assets/svg/no-data.svg | 1 + src/assets/svg/preview/p-rotate.svg | 1 + src/assets/svg/preview/resume.svg | 1 + src/assets/svg/preview/scale.svg | 1 + src/assets/svg/preview/unrotate.svg | 1 + src/assets/svg/preview/unscale.svg | 1 + src/components/.DS_Store | Bin 0 -> 14340 bytes src/components/Application/index.ts | 15 + .../Application/src/AppDarkModeToggle.vue | 89 + .../Application/src/AppLocalePicker.vue | 72 + src/components/Application/src/AppLogo.vue | 90 + .../Application/src/AppProvider.vue | 82 + .../Application/src/search/AppSearch.vue | 33 + .../src/search/AppSearchFooter.vue | 57 + .../src/search/AppSearchKeyItem.vue | 12 + .../Application/src/search/AppSearchModal.vue | 267 + .../Application/src/search/useMenuSearch.ts | 167 + .../Application/src/useAppContext.ts | 17 + src/components/Basic/index.ts | 8 + src/components/Basic/src/BasicArrow.vue | 80 + src/components/Basic/src/BasicHelp.vue | 114 + src/components/Basic/src/BasicTitle.vue | 76 + src/components/Button/index.ts | 9 + src/components/Button/src/BasicButton.vue | 39 + .../Button/src/PopConfirmButton.vue | 54 + src/components/Button/src/props.ts | 26 + src/components/ClickOutSide/index.ts | 4 + .../ClickOutSide/src/ClickOutSide.vue | 20 + src/components/Container/index.ts | 8 + .../Container/src/ScrollContainer.vue | 94 + .../src/collapse/CollapseContainer.vue | 118 + .../Container/src/collapse/CollapseHeader.vue | 44 + src/components/Container/src/typing.ts | 17 + src/components/ContextMenu/index.ts | 3 + .../ContextMenu/src/ContextMenu.vue | 209 + .../ContextMenu/src/createContextMenu.ts | 77 + src/components/ContextMenu/src/typing.ts | 36 + src/components/CountDown/index.ts | 6 + src/components/CountDown/src/CountButton.vue | 62 + .../CountDown/src/CountdownInput.vue | 54 + src/components/CountDown/src/useCountdown.ts | 51 + src/components/CountTo/index.ts | 4 + src/components/CountTo/src/CountTo.vue | 110 + src/components/Cropper/index.ts | 7 + src/components/Cropper/src/Cropper.vue | 188 + src/components/Cropper/src/CropperAvatar.vue | 166 + src/components/Cropper/src/CropperModal.vue | 295 + src/components/Cropper/src/typing.ts | 8 + src/components/Description/index.ts | 6 + .../Description/src/Description.vue | 195 + src/components/Description/src/typing.ts | 50 + .../Description/src/useDescription.ts | 28 + src/components/Drawer/index.ts | 6 + src/components/Drawer/src/BasicDrawer.vue | 256 + .../Drawer/src/components/DrawerFooter.vue | 83 + .../Drawer/src/components/DrawerHeader.vue | 75 + src/components/Drawer/src/props.ts | 45 + src/components/Drawer/src/typing.ts | 194 + src/components/Drawer/src/useDrawer.ts | 161 + src/components/Dropdown/index.ts | 5 + src/components/Dropdown/src/Dropdown.vue | 98 + src/components/Dropdown/src/typing.ts | 9 + src/components/Form/index.ts | 17 + src/components/Form/src/BasicForm.vue | 354 + src/components/Form/src/componentMap.ts | 88 + .../Form/src/components/ApiCascader.vue | 200 + .../Form/src/components/ApiMultipleSelect.vue | 155 + .../src/components/ApiMultipleTreeSelect.vue | 104 + .../Form/src/components/ApiRadioGroup.vue | 136 + .../Form/src/components/ApiSelect.vue | 151 + .../Form/src/components/ApiTransfer.vue | 137 + .../Form/src/components/ApiTree.vue | 92 + .../Form/src/components/ApiTreeSelect.vue | 101 + .../Form/src/components/FormAction.vue | 134 + .../Form/src/components/FormItem.vue | 414 + .../Form/src/components/RadioButtonGroup.vue | 63 + src/components/Form/src/helper.ts | 91 + src/components/Form/src/hooks/useAdvanced.ts | 171 + src/components/Form/src/hooks/useAutoFocus.ts | 40 + .../Form/src/hooks/useComponentRegister.ts | 11 + src/components/Form/src/hooks/useForm.ts | 122 + .../Form/src/hooks/useFormContext.ts | 17 + .../Form/src/hooks/useFormEvents.ts | 428 + .../Form/src/hooks/useFormValues.ts | 161 + .../Form/src/hooks/useLabelWidth.ts | 42 + src/components/Form/src/props.ts | 103 + src/components/Form/src/types/form.ts | 241 + src/components/Form/src/types/formItem.ts | 91 + src/components/Form/src/types/hooks.ts | 6 + src/components/Form/src/types/index.ts | 120 + src/components/Icon/Icon.vue | 121 + src/components/Icon/data/icons.data.ts | 793 + src/components/Icon/index.ts | 4 + src/components/Icon/src/IconPicker.vue | 200 + src/components/Icon/src/SvgIcon.vue | 65 + src/components/Loading/index.ts | 5 + src/components/Loading/src/Loading.vue | 78 + src/components/Loading/src/createLoading.ts | 63 + src/components/Loading/src/typing.ts | 10 + src/components/Loading/src/useLoading.ts | 49 + src/components/Menu/index.ts | 3 + src/components/Menu/src/BasicMenu.vue | 164 + .../Menu/src/components/BasicMenuItem.vue | 21 + .../Menu/src/components/BasicSubMenuItem.vue | 55 + .../Menu/src/components/MenuItemContent.vue | 34 + src/components/Menu/src/index.less | 74 + src/components/Menu/src/props.ts | 61 + src/components/Menu/src/types.ts | 25 + src/components/Menu/src/useOpenKeys.ts | 81 + src/components/Modal/index.ts | 8 + src/components/Modal/src/BasicModal.vue | 246 + src/components/Modal/src/components/Modal.tsx | 29 + .../Modal/src/components/ModalClose.vue | 96 + .../Modal/src/components/ModalFooter.vue | 36 + .../Modal/src/components/ModalHeader.vue | 18 + .../Modal/src/components/ModalWrapper.vue | 170 + src/components/Modal/src/hooks/useModal.ts | 163 + .../Modal/src/hooks/useModalContext.ts | 16 + .../Modal/src/hooks/useModalDrag.ts | 107 + .../Modal/src/hooks/useModalFullScreen.ts | 22 + src/components/Modal/src/index.less | 147 + src/components/Modal/src/props.ts | 83 + src/components/Modal/src/typing.ts | 209 + src/components/Page/index.ts | 7 + src/components/Page/src/PageFooter.vue | 47 + src/components/Page/src/PageWrapper.vue | 205 + src/components/Qrcode/index.ts | 5 + src/components/Qrcode/src/Qrcode.vue | 112 + src/components/Qrcode/src/drawCanvas.ts | 37 + src/components/Qrcode/src/drawLogo.ts | 89 + src/components/Qrcode/src/qrcodePlus.ts | 5 + src/components/Qrcode/src/toCanvas.ts | 11 + src/components/Qrcode/src/typing.ts | 38 + src/components/Scrollbar/index.ts | 8 + src/components/Scrollbar/src/Scrollbar.vue | 207 + src/components/Scrollbar/src/bar.ts | 110 + src/components/Scrollbar/src/types.d.ts | 18 + src/components/Scrollbar/src/util.ts | 51 + src/components/SimpleMenu/index.ts | 2 + src/components/SimpleMenu/src/SimpleMenu.vue | 161 + .../SimpleMenu/src/SimpleMenuTag.vue | 68 + .../SimpleMenu/src/SimpleSubMenu.vue | 116 + .../SimpleMenu/src/components/Menu.vue | 159 + .../src/components/MenuCollapseTransition.vue | 78 + .../SimpleMenu/src/components/MenuItem.vue | 107 + .../SimpleMenu/src/components/SubMenuItem.vue | 336 + .../SimpleMenu/src/components/menu.less | 309 + .../SimpleMenu/src/components/types.ts | 25 + .../SimpleMenu/src/components/useMenu.ts | 84 + .../src/components/useSimpleMenuContext.ts | 18 + src/components/SimpleMenu/src/index.less | 77 + src/components/SimpleMenu/src/types.ts | 0 src/components/SimpleMenu/src/useOpenKeys.ts | 48 + src/components/StrengthMeter/index.ts | 4 + .../StrengthMeter/src/StrengthMeter.vue | 142 + src/components/Table/index.ts | 11 + src/components/Table/src/BasicTable.vue | 467 + src/components/Table/src/componentMap.ts | 40 + .../src/components/EditTableHeaderIcon.vue | 17 + .../Table/src/components/HeaderCell.vue | 60 + .../Table/src/components/TableAction.vue | 202 + .../Table/src/components/TableFooter.vue | 94 + .../Table/src/components/TableHeader.vue | 81 + .../Table/src/components/TableImg.vue | 91 + .../Table/src/components/TableTitle.vue | 53 + .../src/components/editable/CellComponent.ts | 44 + .../src/components/editable/EditableCell.vue | 535 + .../Table/src/components/editable/helper.ts | 28 + .../Table/src/components/editable/index.ts | 68 + .../src/components/settings/ColumnSetting.vue | 515 + .../components/settings/FullScreenSetting.vue | 38 + .../src/components/settings/RedoSetting.vue | 33 + .../src/components/settings/SizeSetting.vue | 64 + .../Table/src/components/settings/index.vue | 76 + src/components/Table/src/const.ts | 38 + src/components/Table/src/hooks/useColumns.ts | 329 + .../Table/src/hooks/useCustomRow.ts | 101 + .../Table/src/hooks/useDataSource.ts | 409 + src/components/Table/src/hooks/useLoading.ts | 21 + .../Table/src/hooks/usePagination.tsx | 85 + .../Table/src/hooks/useRowSelection.ts | 123 + src/components/Table/src/hooks/useScrollTo.ts | 55 + src/components/Table/src/hooks/useTable.ts | 171 + .../Table/src/hooks/useTableContext.ts | 22 + .../Table/src/hooks/useTableExpand.ts | 65 + .../Table/src/hooks/useTableFooter.ts | 56 + .../Table/src/hooks/useTableForm.ts | 50 + .../Table/src/hooks/useTableHeader.ts | 54 + .../Table/src/hooks/useTableScroll.ts | 245 + .../Table/src/hooks/useTableStyle.ts | 20 + src/components/Table/src/props.ts | 151 + src/components/Table/src/types/column.ts | 198 + .../Table/src/types/componentType.ts | 14 + src/components/Table/src/types/pagination.ts | 115 + src/components/Table/src/types/table.ts | 485 + src/components/Table/src/types/tableAction.ts | 40 + src/components/Time/index.ts | 4 + src/components/Time/src/Time.vue | 108 + src/components/Tools/ImportFileModal.vue | 202 + src/components/Transition/index.ts | 27 + .../Transition/src/CollapseTransition.vue | 78 + .../Transition/src/CreateTransition.tsx | 73 + .../Transition/src/ExpandTransition.ts | 89 + src/components/Tree/index.ts | 6 + src/components/Tree/src/BasicTree.vue | 459 + src/components/Tree/src/TreeIcon.ts | 12 + .../Tree/src/components/TreeHeader.vue | 170 + src/components/Tree/src/hooks/useTree.ts | 211 + src/components/Tree/src/types/tree.ts | 195 + src/components/Tree/style/index.less | 52 + src/components/Tree/style/index.ts | 1 + src/components/Upload/index.ts | 4 + src/components/Upload/src/BasicUpload.vue | 124 + src/components/Upload/src/FileList.vue | 104 + src/components/Upload/src/ThumbUrl.vue | 29 + src/components/Upload/src/UploadModal.vue | 323 + .../Upload/src/UploadPreviewModal.vue | 99 + src/components/Upload/src/data.tsx | 153 + src/components/Upload/src/helper.ts | 27 + src/components/Upload/src/props.ts | 83 + src/components/Upload/src/typing.ts | 55 + src/components/Upload/src/useUpload.ts | 61 + src/components/VxeTable/index.ts | 12 + src/components/VxeTable/src/VxeBasicTable.tsx | 116 + src/components/VxeTable/src/componentMap.ts | 59 + src/components/VxeTable/src/componentType.ts | 22 + .../VxeTable/src/components/AApiSelect.tsx | 20 + .../src/components/AApiTreeSelect.tsx | 20 + .../VxeTable/src/components/AAutoComplete.tsx | 16 + .../VxeTable/src/components/AButton.tsx | 120 + .../VxeTable/src/components/AButtonGroup.tsx | 59 + .../VxeTable/src/components/ACascader.tsx | 42 + .../src/components/ACheckboxGroup.tsx | 5 + .../VxeTable/src/components/ADatePicker.tsx | 33 + .../VxeTable/src/components/AEmpty.tsx | 27 + .../VxeTable/src/components/AInput.tsx | 16 + .../VxeTable/src/components/AInputNumber.tsx | 16 + .../VxeTable/src/components/AInputSearch.tsx | 17 + .../VxeTable/src/components/AMonthPicker.tsx | 18 + .../VxeTable/src/components/ARadioGroup.tsx | 5 + .../VxeTable/src/components/ARangePicker.tsx | 30 + .../VxeTable/src/components/ARate.tsx | 15 + .../VxeTable/src/components/ASelect.tsx | 271 + .../VxeTable/src/components/ASwitch.tsx | 53 + .../VxeTable/src/components/ATimePicker.tsx | 18 + .../VxeTable/src/components/ATreeSelect.tsx | 35 + .../VxeTable/src/components/AWeekPicker.tsx | 18 + .../VxeTable/src/components/AYearPicker.tsx | 18 + .../VxeTable/src/components/common.tsx | 427 + .../VxeTable/src/components/index.tsx | 114 + src/components/VxeTable/src/const.ts | 4 + src/components/VxeTable/src/css/common.scss | 8 + .../VxeTable/src/css/component.scss | 123 + src/components/VxeTable/src/css/index.scss | 5 + .../VxeTable/src/css/scrollbar.scss | 29 + src/components/VxeTable/src/css/toolbar.scss | 26 + src/components/VxeTable/src/css/variable.scss | 54 + src/components/VxeTable/src/emits.ts | 17 + src/components/VxeTable/src/helper.ts | 19 + src/components/VxeTable/src/methods.ts | 160 + src/components/VxeTable/src/props.ts | 52 + src/components/VxeTable/src/setting.ts | 4 + src/components/VxeTable/src/types.ts | 7 + src/components/registerGlobComp.ts | 8 + src/design/.DS_Store | Bin 0 -> 6148 bytes src/design/ant/btn.less | 524 + src/design/ant/index.less | 63 + src/design/ant/input.less | 27 + src/design/ant/pagination.less | 96 + src/design/ant/table.less | 72 + src/design/color.less | 160 + src/design/config.less | 2 + src/design/dark.less | 110 + src/design/entry.css | 168 + src/design/index.less | 54 + src/design/public.less | 51 + src/design/theme.less | 28 + src/design/transition/base.less | 18 + src/design/transition/fade.less | 93 + src/design/transition/index.less | 10 + src/design/transition/scale.less | 21 + src/design/transition/scroll.less | 67 + src/design/transition/slide.less | 39 + src/design/transition/zoom.less | 27 + src/design/var/breakpoint.less | 33 + src/design/var/easing.less | 18 + src/design/var/index.less | 39 + src/directives/clickOutside.ts | 86 + src/directives/ellipsis.ts | 42 + src/directives/index.ts | 13 + src/directives/loading.ts | 39 + src/directives/permission.ts | 32 + src/directives/ripple/index.less | 21 + src/directives/ripple/index.ts | 192 + src/enums/appEnum.ts | 56 + src/enums/breakpointEnum.ts | 28 + src/enums/cacheEnum.ts | 34 + src/enums/exceptionEnum.ts | 27 + src/enums/httpEnum.ts | 31 + src/enums/menuEnum.ts | 50 + src/enums/pageEnum.ts | 11 + src/enums/sizeEnum.ts | 5 + src/hooks/.DS_Store | Bin 0 -> 6148 bytes src/hooks/component/useFormItem.ts | 60 + src/hooks/component/usePageContext.ts | 18 + src/hooks/core/useAttrs.ts | 41 + src/hooks/core/useContext.ts | 43 + src/hooks/event/useBreakpoint.ts | 93 + src/hooks/event/useEventListener.ts | 58 + src/hooks/event/useScroll.ts | 65 + src/hooks/setting/index.ts | 18 + src/hooks/setting/useDarkModeTheme.ts | 18 + src/hooks/setting/useHeaderSetting.ts | 105 + src/hooks/setting/useMenuSetting.ts | 168 + src/hooks/setting/useMultipleTabSetting.ts | 28 + src/hooks/setting/useRootSetting.ts | 95 + src/hooks/setting/useTransitionSetting.ts | 31 + src/hooks/web/useAppInject.ts | 10 + src/hooks/web/useContentHeight.ts | 189 + src/hooks/web/useContextMenu.ts | 13 + src/hooks/web/useCopyToClipboard.ts | 70 + src/hooks/web/useDesign.ts | 22 + src/hooks/web/useECharts.ts | 131 + src/hooks/web/useFullContent.ts | 28 + src/hooks/web/useI18n.ts | 55 + src/hooks/web/useLockPage.ts | 72 + src/hooks/web/useMessage.tsx | 121 + src/hooks/web/usePage.ts | 54 + src/hooks/web/usePagination.ts | 34 + src/hooks/web/usePermission.ts | 119 + src/hooks/web/useScript.ts | 46 + src/hooks/web/useSortable.ts | 21 + src/hooks/web/useTabs.ts | 103 + src/hooks/web/useTitle.ts | 34 + src/hooks/web/useWatermark.ts | 106 + src/layouts/.DS_Store | Bin 0 -> 6148 bytes src/layouts/default/content/index.vue | 53 + .../default/content/useContentContext.ts | 17 + .../default/content/useContentViewHeight.ts | 41 + src/layouts/default/feature/index.vue | 84 + src/layouts/default/footer/index.vue | 95 + src/layouts/default/header/MultipleHeader.vue | 126 + .../default/header/components/Breadcrumb.vue | 204 + .../default/header/components/ErrorAction.vue | 47 + .../default/header/components/FullScreen.vue | 45 + .../default/header/components/index.ts | 14 + .../header/components/lock/LockModal.vue | 127 + .../header/components/notify/NoticeList.vue | 177 + .../default/header/components/notify/data.ts | 173 + .../header/components/notify/index.vue | 102 + .../components/user-dropdown/DropMenuItem.vue | 32 + .../header/components/user-dropdown/index.vue | 191 + src/layouts/default/header/index.less | 196 + src/layouts/default/header/index.vue | 153 + src/layouts/default/index.vue | 92 + src/layouts/default/menu/index.vue | 197 + src/layouts/default/menu/useLayoutMenu.ts | 109 + src/layouts/default/setting/SettingDrawer.tsx | 427 + .../setting/components/InputNumberItem.vue | 56 + .../default/setting/components/SelectItem.vue | 75 + .../setting/components/SettingFooter.vue | 100 + .../default/setting/components/SwitchItem.vue | 66 + .../setting/components/ThemeColorPicker.vue | 88 + .../default/setting/components/TypePicker.vue | 179 + .../default/setting/components/index.ts | 8 + src/layouts/default/setting/enum.ts | 156 + src/layouts/default/setting/handler.ts | 172 + src/layouts/default/setting/index.vue | 26 + src/layouts/default/sider/DragBar.vue | 66 + src/layouts/default/sider/LayoutSider.vue | 157 + src/layouts/default/sider/MixSider.vue | 591 + src/layouts/default/sider/index.vue | 59 + src/layouts/default/sider/useLayoutSider.ts | 143 + .../default/tabs/components/FoldButton.vue | 42 + .../default/tabs/components/TabContent.vue | 76 + .../default/tabs/components/TabRedo.vue | 38 + src/layouts/default/tabs/index.less | 199 + src/layouts/default/tabs/index.vue | 144 + src/layouts/default/tabs/types.ts | 25 + src/layouts/default/tabs/useMultipleTabs.ts | 80 + src/layouts/default/tabs/useTabDropdown.ts | 140 + src/layouts/default/trigger/HeaderTrigger.vue | 17 + src/layouts/default/trigger/SiderTrigger.vue | 12 + src/layouts/default/trigger/index.vue | 15 + src/layouts/iframe/index.vue | 29 + src/layouts/iframe/useFrameKeepAlive.ts | 59 + src/layouts/page/index.vue | 70 + src/layouts/page/transition.ts | 33 + src/locales/helper.ts | 37 + src/locales/lang/en.ts | 12 + src/locales/lang/en/basic.ts | 370 + src/locales/lang/en/common.ts | 35 + src/locales/lang/en/component.ts | 130 + src/locales/lang/en/financial.ts | 429 + src/locales/lang/en/home.ts | 21 + src/locales/lang/en/layout.ts | 116 + src/locales/lang/en/product.ts | 204 + src/locales/lang/en/purchase.ts | 320 + src/locales/lang/en/reports.ts | 357 + src/locales/lang/en/retail.ts | 185 + src/locales/lang/en/routes/basic.ts | 4 + src/locales/lang/en/routes/dashboard.ts | 6 + src/locales/lang/en/routes/demo.ts | 199 + src/locales/lang/en/sales.ts | 318 + src/locales/lang/en/sys.ts | 181 + src/locales/lang/en/system.ts | 129 + src/locales/lang/en/warehouse.ts | 395 + .../lang/zh-CN/antdLocale/DatePicker.ts | 19 + src/locales/lang/zh-CN/basic.ts | 370 + src/locales/lang/zh-CN/common.ts | 37 + src/locales/lang/zh-CN/component.ts | 135 + src/locales/lang/zh-CN/financial.ts | 429 + src/locales/lang/zh-CN/home.ts | 21 + src/locales/lang/zh-CN/layout.ts | 116 + src/locales/lang/zh-CN/product.ts | 205 + src/locales/lang/zh-CN/purchase.ts | 320 + src/locales/lang/zh-CN/reports.ts | 359 + src/locales/lang/zh-CN/retail.ts | 185 + src/locales/lang/zh-CN/routes/basic.ts | 4 + src/locales/lang/zh-CN/routes/dashboard.ts | 6 + src/locales/lang/zh-CN/routes/demo.ts | 190 + src/locales/lang/zh-CN/sales.ts | 316 + src/locales/lang/zh-CN/sys.ts | 174 + src/locales/lang/zh-CN/system.ts | 129 + src/locales/lang/zh-CN/warehouse.ts | 395 + src/locales/lang/zh_CN.ts | 10 + src/locales/setupI18n.ts | 44 + src/locales/useLocale.ts | 70 + src/logics/.DS_Store | Bin 0 -> 6148 bytes src/logics/error-handle/index.ts | 184 + src/logics/initAppConfig.ts | 88 + src/logics/mitt/routeChange.ts | 31 + src/logics/theme/dark.ts | 20 + src/logics/theme/index.ts | 1 + src/logics/theme/updateBackground.ts | 198 + src/logics/theme/updateColorWeak.ts | 9 + src/logics/theme/updateGrayMode.ts | 9 + src/logics/theme/util.ts | 11 + src/main.ts | 64 + src/router/.DS_Store | Bin 0 -> 6148 bytes src/router/constant.ts | 24 + src/router/guard/index.ts | 147 + src/router/guard/paramMenuGuard.ts | 47 + src/router/guard/permissionGuard.ts | 119 + src/router/guard/stateGuard.ts | 24 + src/router/helper/menuHelper.ts | 106 + src/router/helper/routeHelper.ts | 178 + src/router/index.ts | 42 + src/router/menus/index.ts | 136 + src/router/routes/basic.ts | 78 + src/router/routes/index.ts | 42 + src/router/types.ts | 58 + src/settings/componentSetting.ts | 51 + src/settings/designSetting.ts | 48 + src/settings/encryptionSetting.ts | 13 + src/settings/localeSetting.ts | 29 + src/settings/projectSetting.ts | 183 + src/settings/siteSetting.ts | 8 + src/store/index.ts | 10 + src/store/modules/app.ts | 112 + src/store/modules/errorLog.ts | 77 + src/store/modules/locale.ts | 72 + src/store/modules/lock.ts | 59 + src/store/modules/multipleTab.ts | 361 + src/store/modules/permission.ts | 276 + src/store/modules/user.ts | 233 + src/utils/.DS_Store | Bin 0 -> 6148 bytes src/utils/auth/index.ts | 25 + src/utils/bem.ts | 52 + src/utils/cache/index.ts | 31 + src/utils/cache/memory.ts | 107 + src/utils/cache/persistent.ts | 132 + src/utils/cache/storageCache.ts | 111 + src/utils/cipher.ts | 54 + src/utils/color.ts | 151 + src/utils/dateUtil.ts | 28 + src/utils/domUtils.ts | 180 + src/utils/env.ts | 82 + src/utils/event/index.ts | 42 + src/utils/factory/createAsyncComponent.tsx | 56 + src/utils/file/base64Conver.ts | 41 + src/utils/file/download.ts | 45 + src/utils/helper/treeHelper.ts | 216 + src/utils/helper/tsxHelper.tsx | 37 + src/utils/http/axios/Axios.ts | 251 + src/utils/http/axios/axiosCancel.ts | 60 + src/utils/http/axios/axiosRetry.ts | 30 + src/utils/http/axios/axiosTransform.ts | 57 + src/utils/http/axios/checkStatus.ts | 80 + src/utils/http/axios/helper.ts | 48 + src/utils/http/axios/index.ts | 297 + src/utils/index.ts | 122 + src/utils/is.ts | 98 + src/utils/lib/echarts.ts | 57 + src/utils/log.ts | 9 + src/utils/mitt.ts | 122 + src/utils/propTypes.ts | 35 + src/utils/props.ts | 184 + src/utils/tree.ts | 83 + src/utils/types.ts | 42 + src/utils/uuid.ts | 28 + src/views/.DS_Store | Bin 0 -> 8196 bytes src/views/basic/account/BaseSetting.vue | 102 + src/views/basic/account/BindEmailModal.vue | 146 + src/views/basic/account/BindPhoneModal.vue | 147 + src/views/basic/account/MsgNotify.vue | 78 + .../basic/account/ResetPasswordModal.vue | 50 + src/views/basic/account/SecureSetting.vue | 96 + src/views/basic/account/data.ts | 151 + src/views/basic/account/index.vue | 59 + .../customer/components/CustomerModal.vue | 102 + src/views/basic/customer/customer.data.ts | 251 + src/views/basic/customer/index.vue | 199 + .../components/AddEditModal.vue | 77 + .../income-expense/incomeExpense.data.ts | 96 + src/views/basic/income-expense/index.vue | 158 + .../basic/member/components/MemberModal.vue | 79 + src/views/basic/member/index.vue | 198 + src/views/basic/member/member.data.ts | 170 + .../operator/components/OperatorModal.vue | 77 + src/views/basic/operator/index.vue | 152 + src/views/basic/operator/operator.data.ts | 118 + .../components/FinancialAccountModal.vue | 80 + .../components/MultipleAccountsModal.vue | 155 + .../financialAccount.data.ts | 147 + src/views/basic/settlement-account/index.vue | 158 + .../supplier/components/SupplierModal.vue | 104 + src/views/basic/supplier/index.vue | 201 + src/views/basic/supplier/supplier.data.ts | 261 + .../warehouse/components/WarehouseModal.vue | 81 + src/views/basic/warehouse/index.vue | 158 + src/views/basic/warehouse/warehouse.data.ts | 165 + .../analysis/components/GrowCard.vue | 59 + .../analysis/components/GrowCardFour.vue | 49 + .../analysis/components/GrowCardThree.vue | 49 + .../analysis/components/GrowCardTwo.vue | 49 + .../analysis/components/SalesProductPie.vue | 65 + .../analysis/components/SiteAnalysis.vue | 38 + .../analysis/components/VisitAnalysis.vue | 89 + .../analysis/components/VisitAnalysisBar.vue | 46 + .../analysis/components/VisitRadar.vue | 64 + .../analysis/components/VisitSource.vue | 65 + .../dashboard/analysis/components/props.ts | 16 + src/views/dashboard/analysis/data.ts | 144 + src/views/dashboard/analysis/index.vue | 81 + .../workbench/components/DynamicInfo.vue | 31 + .../workbench/components/ProjectCard.vue | 32 + .../workbench/components/QuickNav.vue | 15 + .../workbench/components/SaleRadar.vue | 94 + .../workbench/components/WorkbenchHeader.vue | 33 + .../dashboard/workbench/components/data.ts | 144 + src/views/dashboard/workbench/index.vue | 36 + .../financial/advance-charge/advance.data.ts | 181 + .../components/AdvanceChargeModal.vue | 593 + .../components/ViewAdvanceChargeModal.vue | 193 + src/views/financial/advance-charge/index.vue | 228 + .../collection/addEditCollection.data.ts | 159 + .../financial/collection/collection.data.ts | 269 + .../components/AddEditCollectionModal.vue | 635 + .../components/SaleArrearsModal.vue | 98 + .../components/ViewCollectionModal.vue | 205 + src/views/financial/collection/index.vue | 244 + .../financial/expense/addEditExpense.data.ts | 152 + .../components/AddEditExpenseModal.vue | 585 + .../expense/components/ViewExpenseModal.vue | 193 + src/views/financial/expense/expense.data.ts | 162 + src/views/financial/expense/index.vue | 243 + .../financial/income/addEditIncome.data.ts | 153 + .../income/components/AddEditIncomeModal.vue | 592 + .../income/components/ViewIncomeModal.vue | 193 + src/views/financial/income/income.data.ts | 162 + src/views/financial/income/index.vue | 242 + .../financial/payment/addEditPayment.data.ts | 159 + .../components/AddEditPaymentModal.vue | 633 + .../components/PurchaseArrearsModal.vue | 98 + .../payment/components/ViewPaymentModal.vue | 205 + src/views/financial/payment/index.vue | 242 + src/views/financial/payment/payment.data.ts | 269 + .../transfer/addEditTransfer.data.ts | 150 + .../components/AddEditTransferModal.vue | 546 + .../transfer/components/ViewTransferModal.vue | 189 + src/views/financial/transfer/index.vue | 242 + src/views/financial/transfer/transfer.data.ts | 144 + .../product/attributes/attributes.data.ts | 74 + .../attributes/components/AttributeModal.vue | 76 + src/views/product/attributes/index.vue | 114 + src/views/product/category/category.data.ts | 74 + .../category/components/CategoryModal.vue | 77 + src/views/product/category/index.vue | 139 + .../info/components/BatchEditModal.vue | 209 + .../info/components/BatchSetPriceModal.vue | 124 + .../info/components/BatchSetStockModal.vue | 110 + .../info/components/ProductInfoModal.vue | 1311 ++ .../info/components/SelectProductModal.vue | 66 + src/views/product/info/index.vue | 212 + src/views/product/info/info.data.ts | 379 + .../product/info/model/productInfoModel.ts | 99 + .../product/units/components/UnitModal.vue | 93 + src/views/product/units/index.vue | 113 + src/views/product/units/units.data.ts | 173 + src/views/production/tasks/index.vue | 189 + src/views/production/tasks/task.data.ts | 321 + src/views/purchase/model/addEditModel.ts | 480 + .../order/components/AddEditModal.vue | 1093 ++ .../order/components/ViewOrderModal.vue | 207 + src/views/purchase/order/index.vue | 241 + .../purchase/order/purchaseOrder.data.ts | 213 + .../refund/components/AddEditModal.vue | 1271 ++ .../refund/components/ViewRefundModal.vue | 242 + src/views/purchase/refund/index.vue | 241 + .../purchase/refund/purchaseRefund.data.ts | 143 + .../storage/components/AddEditModal.vue | 1272 ++ .../storage/components/ViewStorageModal.vue | 235 + src/views/purchase/storage/index.vue | 243 + .../purchase/storage/purchaseStorage.data.ts | 145 + src/views/receipt/LinkReceiptModal.vue | 128 + src/views/receipt/ReceiptDetailModal.vue | 82 + src/views/receipt/receipt.data.ts | 171 + src/views/report/accountStatistics.vue | 158 + src/views/report/customerBill.vue | 185 + src/views/report/modal/AccountFlowModal.vue | 152 + .../report/modal/CustomerBillDetailModal.vue | 181 + src/views/report/modal/StockFlowModal.vue | 183 + .../report/modal/SupplierBillDetailModal.vue | 182 + src/views/report/productStock.vue | 171 + src/views/report/purchaseStatistics.vue | 154 + src/views/report/report.data.ts | 1461 ++ src/views/report/retailStatistics.vue | 155 + src/views/report/saleStatistics.vue | 154 + src/views/report/shipmentsDetail.vue | 187 + src/views/report/shipmentsSummary.vue | 143 + src/views/report/storageDetail.vue | 191 + src/views/report/storageSummary.vue | 144 + src/views/report/supplierBill.vue | 180 + .../retail/refund/components/AddEditModal.vue | 914 ++ .../refund/components/ViewRefundModal.vue | 226 + src/views/retail/refund/index.vue | 242 + src/views/retail/refund/refund.data.ts | 141 + .../shipments/components/AddEditModal.vue | 903 ++ .../components/ViewShipmentModal.vue | 224 + src/views/retail/shipments/index.vue | 245 + .../retail/shipments/model/addEditModel.ts | 241 + src/views/retail/shipments/shipments.data.ts | 209 + src/views/sales/model/addEditModel.ts | 481 + .../sales/order/components/AddEditModal.vue | 1098 ++ .../order/components/ViewSaleOrderModal.vue | 207 + src/views/sales/order/index.vue | 240 + src/views/sales/order/sales.data.ts | 213 + .../sales/refund/components/AddEditModal.vue | 1245 ++ .../refund/components/ViewSaleRefundModal.vue | 235 + src/views/sales/refund/index.vue | 240 + src/views/sales/refund/saleRefund.data.ts | 143 + .../shipments/components/AddEditModal.vue | 1259 ++ .../components/ViewSaleShipmentsModal.vue | 236 + src/views/sales/shipments/index.vue | 240 + .../sales/shipments/saleShipments.data.ts | 143 + src/views/sys/about/index.vue | 98 + src/views/sys/config/config.data.ts | 85 + src/views/sys/config/index.vue | 89 + .../sys/department/components/DeptModal.vue | 78 + src/views/sys/department/dept.data.ts | 119 + src/views/sys/department/index.vue | 113 + src/views/sys/error-log/DetailModal.vue | 27 + src/views/sys/error-log/data.tsx | 67 + src/views/sys/error-log/index.vue | 96 + src/views/sys/exception/Exception.vue | 148 + src/views/sys/exception/index.ts | 1 + src/views/sys/iframe/FrameBlank.vue | 6 + src/views/sys/iframe/index.vue | 90 + src/views/sys/lock/LockPage.vue | 236 + src/views/sys/lock/index.vue | 13 + src/views/sys/lock/useNow.ts | 60 + src/views/sys/login/EmailForm.vue | 98 + src/views/sys/login/ForgetPasswordForm.vue | 151 + src/views/sys/login/Login.vue | 223 + src/views/sys/login/LoginForm.vue | 205 + src/views/sys/login/LoginFormTitle.vue | 26 + src/views/sys/login/MobileForm.vue | 98 + src/views/sys/login/QrCodeForm.vue | 31 + src/views/sys/login/RegisterForm.vue | 158 + src/views/sys/login/SessionTimeoutLogin.vue | 54 + src/views/sys/login/useLogin.ts | 207 + src/views/sys/menu/MenuDrawer.vue | 97 + src/views/sys/menu/index.vue | 120 + src/views/sys/menu/menu.data.ts | 211 + src/views/sys/redirect/index.vue | 30 + src/views/sys/role/components/RoleDrawer.vue | 72 + .../role/components/RolePermissionModal.vue | 68 + src/views/sys/role/index.vue | 134 + src/views/sys/role/role.data.ts | 163 + .../sys/tenant/components/TenantModal.vue | 92 + src/views/sys/tenant/index.vue | 122 + src/views/sys/tenant/tenant.data.ts | 195 + src/views/sys/user/account.data.ts | 170 + .../sys/user/components/AccountDetail.vue | 61 + .../sys/user/components/AccountModal.vue | 89 + src/views/sys/user/components/DeptTree.vue | 45 + src/views/sys/user/index.vue | 165 + .../addEditAssembleOrDisassemble.data.ts | 206 + .../warehouse/addEditStorageShipments.data.ts | 210 + .../warehouse/allot/allotShipments.data.ts | 160 + .../components/AddEditAllotShipmentsModal.vue | 668 + .../components/ViewAllotShipmentsModal.vue | 160 + .../components/addEditAllotShipments.data.ts | 172 + src/views/warehouse/allot/index.vue | 243 + src/views/warehouse/assemble/assemble.data.ts | 176 + .../components/AddEditAssembleModal.vue | 750 + .../assemble/components/ViewAssembleModal.vue | 160 + src/views/warehouse/assemble/index.vue | 243 + .../components/AddEditDisassembleModal.vue | 754 + .../components/ViewDisassembleModal.vue | 160 + .../warehouse/disassemble/disassemble.data.ts | 176 + src/views/warehouse/disassemble/index.vue | 245 + .../components/AddEditOtherShipmentsModal.vue | 735 + .../components/ViewOtherShipmentsModal.vue | 175 + src/views/warehouse/shipments/index.vue | 242 + .../shipments/otherShipments.data.ts | 189 + .../components/AddEditOtherStorageModal.vue | 723 + .../components/ViewOtherStorageModal.vue | 176 + src/views/warehouse/storage/index.vue | 242 + .../warehouse/storage/otherStorage.data.ts | 189 + src/views/workflow/bpmn/index.vue | 6 + src/views/workflow/bpmn/zh.ts | 271 + tsconfig.json | 27 + turbo.json | 18 + types/axios.d.ts | 56 + types/codemirror.d.ts | 1 + types/config.d.ts | 162 + types/global.d.ts | 91 + types/index.d.ts | 27 + types/module.d.ts | 18 + types/store.d.ts | 48 + types/tree.d.ts | 1 + types/utils.d.ts | 5 + types/vue-router.d.ts | 47 + types/vueuseCore.d.ts | 1 + vite.config.ts | 31 + wansenai-logo.png | Bin 0 -> 7551 bytes 998 files changed, 122601 insertions(+) create mode 100644 .DS_Store create mode 100644 .dockerignore create mode 100644 .env create mode 100644 .env.analyze create mode 100644 .env.development create mode 100644 .env.docker create mode 100644 .env.production create mode 100644 .eslintignore create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 .prettierignore create mode 100644 .prettierrc.js create mode 100644 .stylelintrc.js create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 README-zh_CN.md create mode 100644 README.md create mode 100644 deploy/default.conf create mode 100644 docs/README_ZH.md create mode 100644 docs/template/会员信息模板.xlsx create mode 100644 docs/template/供应商模板.xlsx create mode 100644 docs/template/客户信息模板.xlsx create mode 100644 images/add-menu-zh.png create mode 100644 images/home-page-zh.png create mode 100644 images/login-page-en.png create mode 100644 images/register-page-zh.png create mode 100644 images/role-permission-zh.png create mode 100644 images/user-manage-zh.png create mode 100644 images/user-mgt.png create mode 100644 images/wansenai-logo.png create mode 100644 index.html create mode 100644 internal/.DS_Store create mode 100644 internal/stylelint-config/.eslintignore create mode 100644 internal/stylelint-config/build.config.ts create mode 100644 internal/stylelint-config/package.json create mode 100644 internal/stylelint-config/src/index.ts create mode 100644 internal/stylelint-config/tsconfig.json create mode 100644 internal/ts-config/.eslintignore create mode 100644 internal/ts-config/base.json create mode 100644 internal/ts-config/node-server.json create mode 100644 internal/ts-config/node.json create mode 100644 internal/ts-config/package.json create mode 100644 internal/ts-config/vue-app.json create mode 100644 internal/vite-config/.eslintignore create mode 100644 internal/vite-config/build.config.ts create mode 100644 internal/vite-config/package.json create mode 100644 internal/vite-config/src/config/application.ts create mode 100644 internal/vite-config/src/config/common.ts create mode 100644 internal/vite-config/src/config/package.ts create mode 100644 internal/vite-config/src/index.ts create mode 100644 internal/vite-config/src/plugins/appConfig.ts create mode 100644 internal/vite-config/src/plugins/compress.ts create mode 100644 internal/vite-config/src/plugins/html.ts create mode 100644 internal/vite-config/src/plugins/index.ts create mode 100644 internal/vite-config/src/plugins/mock.ts create mode 100644 internal/vite-config/src/plugins/svgSprite.ts create mode 100644 internal/vite-config/src/plugins/visualizer.ts create mode 100644 internal/vite-config/src/utils/env.ts create mode 100644 internal/vite-config/src/utils/hash.ts create mode 100644 internal/vite-config/src/utils/modifyVars.ts create mode 100644 internal/vite-config/tsconfig.json create mode 100644 nginx.conf create mode 100644 package.json create mode 100644 packages/.DS_Store create mode 100644 packages/hooks/.eslintrc.js create mode 100644 packages/hooks/build.config.ts create mode 100644 packages/hooks/package.json create mode 100644 packages/hooks/src/index.ts create mode 100644 packages/hooks/src/onMountedOrActivated.ts create mode 100644 packages/hooks/src/useAttrs.ts create mode 100644 packages/hooks/src/useRefs.ts create mode 100644 packages/hooks/src/useScrollTo.ts create mode 100644 packages/hooks/src/useWindowSizeFn.ts create mode 100644 packages/hooks/tsconfig.json create mode 100644 packages/types/.eslintrc.js create mode 100644 packages/types/build.config.ts create mode 100644 packages/types/package.json create mode 100644 packages/types/src/index.ts create mode 100644 packages/types/src/utils.ts create mode 100644 packages/types/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 public/favicon.ico create mode 100644 public/resource/.DS_Store create mode 100644 public/resource/img/logo.png create mode 100644 public/resource/tinymce/icons/default/icons.min.js create mode 100644 public/resource/tinymce/langs/README.md create mode 100644 public/resource/tinymce/langs/en.js create mode 100644 public/resource/tinymce/langs/zh_CN.js create mode 100644 public/resource/tinymce/license.txt create mode 100644 public/resource/tinymce/models/dom/model.min.js create mode 100644 public/resource/tinymce/plugins/advlist/plugin.min.js create mode 100644 public/resource/tinymce/plugins/anchor/plugin.min.js create mode 100644 public/resource/tinymce/plugins/autolink/plugin.min.js create mode 100644 public/resource/tinymce/plugins/autoresize/plugin.min.js create mode 100644 public/resource/tinymce/plugins/autosave/plugin.min.js create mode 100644 public/resource/tinymce/plugins/charmap/plugin.min.js create mode 100644 public/resource/tinymce/plugins/code/plugin.min.js create mode 100644 public/resource/tinymce/plugins/codesample/plugin.min.js create mode 100644 public/resource/tinymce/plugins/directionality/plugin.min.js create mode 100644 public/resource/tinymce/plugins/emoticons/js/emojiimages.js create mode 100644 public/resource/tinymce/plugins/emoticons/js/emojiimages.min.js create mode 100644 public/resource/tinymce/plugins/emoticons/js/emojis.js create mode 100644 public/resource/tinymce/plugins/emoticons/js/emojis.min.js create mode 100644 public/resource/tinymce/plugins/emoticons/plugin.min.js create mode 100644 public/resource/tinymce/plugins/fullscreen/plugin.min.js create mode 100644 public/resource/tinymce/plugins/help/plugin.min.js create mode 100644 public/resource/tinymce/plugins/image/plugin.min.js create mode 100644 public/resource/tinymce/plugins/importcss/plugin.min.js create mode 100644 public/resource/tinymce/plugins/insertdatetime/plugin.min.js create mode 100644 public/resource/tinymce/plugins/link/plugin.min.js create mode 100644 public/resource/tinymce/plugins/lists/plugin.min.js create mode 100644 public/resource/tinymce/plugins/media/plugin.min.js create mode 100644 public/resource/tinymce/plugins/nonbreaking/plugin.min.js create mode 100644 public/resource/tinymce/plugins/pagebreak/plugin.min.js create mode 100644 public/resource/tinymce/plugins/preview/plugin.min.js create mode 100644 public/resource/tinymce/plugins/quickbars/plugin.min.js create mode 100644 public/resource/tinymce/plugins/save/plugin.min.js create mode 100644 public/resource/tinymce/plugins/searchreplace/plugin.min.js create mode 100644 public/resource/tinymce/plugins/table/plugin.min.js create mode 100644 public/resource/tinymce/plugins/template/plugin.min.js create mode 100644 public/resource/tinymce/plugins/visualblocks/plugin.min.js create mode 100644 public/resource/tinymce/plugins/visualchars/plugin.min.js create mode 100644 public/resource/tinymce/plugins/wordcount/plugin.min.js create mode 100644 public/resource/tinymce/skins/content/dark/content.min.css create mode 100644 public/resource/tinymce/skins/content/default/content.min.css create mode 100644 public/resource/tinymce/skins/content/document/content.min.css create mode 100644 public/resource/tinymce/skins/content/tinymce-5-dark/content.min.css create mode 100644 public/resource/tinymce/skins/content/tinymce-5/content.min.css create mode 100644 public/resource/tinymce/skins/content/writer/content.min.css create mode 100644 public/resource/tinymce/skins/ui/oxide-dark/content.inline.min.css create mode 100644 public/resource/tinymce/skins/ui/oxide-dark/content.min.css create mode 100644 public/resource/tinymce/skins/ui/oxide-dark/skin.min.css create mode 100644 public/resource/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css create mode 100644 public/resource/tinymce/skins/ui/oxide/content.inline.min.css create mode 100644 public/resource/tinymce/skins/ui/oxide/content.min.css create mode 100644 public/resource/tinymce/skins/ui/oxide/skin.min.css create mode 100644 public/resource/tinymce/skins/ui/oxide/skin.shadowdom.min.css create mode 100644 public/resource/tinymce/skins/ui/tinymce-5-dark/content.inline.min.css create mode 100644 public/resource/tinymce/skins/ui/tinymce-5-dark/content.min.css create mode 100644 public/resource/tinymce/skins/ui/tinymce-5-dark/skin.min.css create mode 100644 public/resource/tinymce/skins/ui/tinymce-5-dark/skin.shadowdom.min.css create mode 100644 public/resource/tinymce/skins/ui/tinymce-5/content.inline.min.css create mode 100644 public/resource/tinymce/skins/ui/tinymce-5/content.min.css create mode 100644 public/resource/tinymce/skins/ui/tinymce-5/skin.min.css create mode 100644 public/resource/tinymce/skins/ui/tinymce-5/skin.shadowdom.min.css create mode 100644 public/resource/tinymce/themes/silver/theme.min.js create mode 100644 public/resource/tinymce/tinymce.d.ts create mode 100644 public/resource/tinymce/tinymce.min.js create mode 100644 src/.DS_Store create mode 100644 src/App.vue create mode 100644 src/api/.DS_Store create mode 100644 src/api/basic/common.ts create mode 100644 src/api/basic/customer.ts create mode 100644 src/api/basic/incomeExpense.ts create mode 100644 src/api/basic/member.ts create mode 100644 src/api/basic/model/customerModel.ts create mode 100644 src/api/basic/model/incomeExpenseModel.ts create mode 100644 src/api/basic/model/memberModel.ts create mode 100644 src/api/basic/model/operatorModel.ts create mode 100644 src/api/basic/model/supplierModel.ts create mode 100644 src/api/basic/model/warehouseModel.ts create mode 100644 src/api/basic/operator.ts create mode 100644 src/api/basic/supplier.ts create mode 100644 src/api/basic/warehouse.ts create mode 100644 src/api/financial/account.ts create mode 100644 src/api/financial/advance.ts create mode 100644 src/api/financial/collection.ts create mode 100644 src/api/financial/expense.ts create mode 100644 src/api/financial/income.ts create mode 100644 src/api/financial/model/accountModel.ts create mode 100644 src/api/financial/model/advanceModel.ts create mode 100644 src/api/financial/model/collectionModel.ts create mode 100644 src/api/financial/model/expenseModel.ts create mode 100644 src/api/financial/model/incomeModel.ts create mode 100644 src/api/financial/model/paymentModel.ts create mode 100644 src/api/financial/model/transferModel.ts create mode 100644 src/api/financial/payment.ts create mode 100644 src/api/financial/transfer.ts create mode 100644 src/api/model/baseModel.ts create mode 100644 src/api/product/model/productAttributeModel.ts create mode 100644 src/api/product/model/productCategoryModel.ts create mode 100644 src/api/product/model/productModel.ts create mode 100644 src/api/product/model/productUnitModel.ts create mode 100644 src/api/product/product.ts create mode 100644 src/api/product/productAttribute.ts create mode 100644 src/api/product/productCategory.ts create mode 100644 src/api/product/productUnit.ts create mode 100644 src/api/purchase/model/orderModel.ts create mode 100644 src/api/purchase/model/refundModel.ts create mode 100644 src/api/purchase/model/storageModel.ts create mode 100644 src/api/purchase/order.ts create mode 100644 src/api/purchase/refund.ts create mode 100644 src/api/purchase/storage.ts create mode 100644 src/api/receipt/model/receiptModel.ts create mode 100644 src/api/receipt/receipt.ts create mode 100644 src/api/report/report.ts create mode 100644 src/api/report/reportModel.ts create mode 100644 src/api/retail/model/refundModel.ts create mode 100644 src/api/retail/model/shipmentsModel.ts create mode 100644 src/api/retail/refund.ts create mode 100644 src/api/retail/shipments.ts create mode 100644 src/api/sale/model/orderModel.ts create mode 100644 src/api/sale/model/refundModel.ts create mode 100644 src/api/sale/model/shipmentsModel.ts create mode 100644 src/api/sale/order.ts create mode 100644 src/api/sale/refund.ts create mode 100644 src/api/sale/shipments.ts create mode 100644 src/api/sys/captcha.ts create mode 100644 src/api/sys/config.ts create mode 100644 src/api/sys/dept.ts create mode 100644 src/api/sys/menu.ts create mode 100644 src/api/sys/message.ts create mode 100644 src/api/sys/model/MessageModel.ts create mode 100644 src/api/sys/model/captchaModel.ts create mode 100644 src/api/sys/model/configModel.ts create mode 100644 src/api/sys/model/dpetModel.ts create mode 100644 src/api/sys/model/menuModel.ts create mode 100644 src/api/sys/model/roleModel.ts create mode 100644 src/api/sys/model/tenantModel.ts create mode 100644 src/api/sys/model/uploadModel.ts create mode 100644 src/api/sys/model/userModel.ts create mode 100644 src/api/sys/role.ts create mode 100644 src/api/sys/tenant.ts create mode 100644 src/api/sys/upload.ts create mode 100644 src/api/sys/user.ts create mode 100644 src/api/warehouse/allotShipments.ts create mode 100644 src/api/warehouse/assemble.ts create mode 100644 src/api/warehouse/disassemble.ts create mode 100644 src/api/warehouse/model/allotShipmentsModel.ts create mode 100644 src/api/warehouse/model/assembleModel.ts create mode 100644 src/api/warehouse/model/disassembleModel.ts create mode 100644 src/api/warehouse/model/shipmentsModel.ts create mode 100644 src/api/warehouse/model/storageModel.ts create mode 100644 src/api/warehouse/shipments.ts create mode 100644 src/api/warehouse/storage.ts create mode 100644 src/assets/.DS_Store create mode 100644 src/assets/icons/download-count.svg create mode 100644 src/assets/icons/dynamic-avatar-1.svg create mode 100644 src/assets/icons/dynamic-avatar-2.svg create mode 100644 src/assets/icons/dynamic-avatar-3.svg create mode 100644 src/assets/icons/dynamic-avatar-4.svg create mode 100644 src/assets/icons/dynamic-avatar-5.svg create mode 100644 src/assets/icons/dynamic-avatar-6.svg create mode 100644 src/assets/icons/moon.svg create mode 100644 src/assets/icons/sun.svg create mode 100644 src/assets/icons/test.svg create mode 100644 src/assets/icons/total-sales.svg create mode 100644 src/assets/icons/transaction.svg create mode 100644 src/assets/icons/visit-count.svg create mode 100644 src/assets/images/demo.png create mode 100644 src/assets/images/header.jpg create mode 100644 src/assets/images/login-page-bg-2.png create mode 100644 src/assets/images/logo.png create mode 100644 src/assets/svg/illustration.svg create mode 100644 src/assets/svg/login-bg-dark.svg create mode 100644 src/assets/svg/login-bg.svg create mode 100644 src/assets/svg/login-box-bg.svg create mode 100644 src/assets/svg/net-error.svg create mode 100644 src/assets/svg/no-data.svg create mode 100644 src/assets/svg/preview/p-rotate.svg create mode 100644 src/assets/svg/preview/resume.svg create mode 100644 src/assets/svg/preview/scale.svg create mode 100644 src/assets/svg/preview/unrotate.svg create mode 100644 src/assets/svg/preview/unscale.svg create mode 100644 src/components/.DS_Store create mode 100644 src/components/Application/index.ts create mode 100644 src/components/Application/src/AppDarkModeToggle.vue create mode 100644 src/components/Application/src/AppLocalePicker.vue create mode 100644 src/components/Application/src/AppLogo.vue create mode 100644 src/components/Application/src/AppProvider.vue create mode 100644 src/components/Application/src/search/AppSearch.vue create mode 100644 src/components/Application/src/search/AppSearchFooter.vue create mode 100644 src/components/Application/src/search/AppSearchKeyItem.vue create mode 100644 src/components/Application/src/search/AppSearchModal.vue create mode 100644 src/components/Application/src/search/useMenuSearch.ts create mode 100644 src/components/Application/src/useAppContext.ts create mode 100644 src/components/Basic/index.ts create mode 100644 src/components/Basic/src/BasicArrow.vue create mode 100644 src/components/Basic/src/BasicHelp.vue create mode 100644 src/components/Basic/src/BasicTitle.vue create mode 100644 src/components/Button/index.ts create mode 100644 src/components/Button/src/BasicButton.vue create mode 100644 src/components/Button/src/PopConfirmButton.vue create mode 100644 src/components/Button/src/props.ts create mode 100644 src/components/ClickOutSide/index.ts create mode 100644 src/components/ClickOutSide/src/ClickOutSide.vue create mode 100644 src/components/Container/index.ts create mode 100644 src/components/Container/src/ScrollContainer.vue create mode 100644 src/components/Container/src/collapse/CollapseContainer.vue create mode 100644 src/components/Container/src/collapse/CollapseHeader.vue create mode 100644 src/components/Container/src/typing.ts create mode 100644 src/components/ContextMenu/index.ts create mode 100644 src/components/ContextMenu/src/ContextMenu.vue create mode 100644 src/components/ContextMenu/src/createContextMenu.ts create mode 100644 src/components/ContextMenu/src/typing.ts create mode 100644 src/components/CountDown/index.ts create mode 100644 src/components/CountDown/src/CountButton.vue create mode 100644 src/components/CountDown/src/CountdownInput.vue create mode 100644 src/components/CountDown/src/useCountdown.ts create mode 100644 src/components/CountTo/index.ts create mode 100644 src/components/CountTo/src/CountTo.vue create mode 100644 src/components/Cropper/index.ts create mode 100644 src/components/Cropper/src/Cropper.vue create mode 100644 src/components/Cropper/src/CropperAvatar.vue create mode 100644 src/components/Cropper/src/CropperModal.vue create mode 100644 src/components/Cropper/src/typing.ts create mode 100644 src/components/Description/index.ts create mode 100644 src/components/Description/src/Description.vue create mode 100644 src/components/Description/src/typing.ts create mode 100644 src/components/Description/src/useDescription.ts create mode 100644 src/components/Drawer/index.ts create mode 100644 src/components/Drawer/src/BasicDrawer.vue create mode 100644 src/components/Drawer/src/components/DrawerFooter.vue create mode 100644 src/components/Drawer/src/components/DrawerHeader.vue create mode 100644 src/components/Drawer/src/props.ts create mode 100644 src/components/Drawer/src/typing.ts create mode 100644 src/components/Drawer/src/useDrawer.ts create mode 100644 src/components/Dropdown/index.ts create mode 100644 src/components/Dropdown/src/Dropdown.vue create mode 100644 src/components/Dropdown/src/typing.ts create mode 100644 src/components/Form/index.ts create mode 100644 src/components/Form/src/BasicForm.vue create mode 100644 src/components/Form/src/componentMap.ts create mode 100644 src/components/Form/src/components/ApiCascader.vue create mode 100644 src/components/Form/src/components/ApiMultipleSelect.vue create mode 100644 src/components/Form/src/components/ApiMultipleTreeSelect.vue create mode 100644 src/components/Form/src/components/ApiRadioGroup.vue create mode 100644 src/components/Form/src/components/ApiSelect.vue create mode 100644 src/components/Form/src/components/ApiTransfer.vue create mode 100644 src/components/Form/src/components/ApiTree.vue create mode 100644 src/components/Form/src/components/ApiTreeSelect.vue create mode 100644 src/components/Form/src/components/FormAction.vue create mode 100644 src/components/Form/src/components/FormItem.vue create mode 100644 src/components/Form/src/components/RadioButtonGroup.vue create mode 100644 src/components/Form/src/helper.ts create mode 100644 src/components/Form/src/hooks/useAdvanced.ts create mode 100644 src/components/Form/src/hooks/useAutoFocus.ts create mode 100644 src/components/Form/src/hooks/useComponentRegister.ts create mode 100644 src/components/Form/src/hooks/useForm.ts create mode 100644 src/components/Form/src/hooks/useFormContext.ts create mode 100644 src/components/Form/src/hooks/useFormEvents.ts create mode 100644 src/components/Form/src/hooks/useFormValues.ts create mode 100644 src/components/Form/src/hooks/useLabelWidth.ts create mode 100644 src/components/Form/src/props.ts create mode 100644 src/components/Form/src/types/form.ts create mode 100644 src/components/Form/src/types/formItem.ts create mode 100644 src/components/Form/src/types/hooks.ts create mode 100644 src/components/Form/src/types/index.ts create mode 100644 src/components/Icon/Icon.vue create mode 100644 src/components/Icon/data/icons.data.ts create mode 100644 src/components/Icon/index.ts create mode 100644 src/components/Icon/src/IconPicker.vue create mode 100644 src/components/Icon/src/SvgIcon.vue create mode 100644 src/components/Loading/index.ts create mode 100644 src/components/Loading/src/Loading.vue create mode 100644 src/components/Loading/src/createLoading.ts create mode 100644 src/components/Loading/src/typing.ts create mode 100644 src/components/Loading/src/useLoading.ts create mode 100644 src/components/Menu/index.ts create mode 100644 src/components/Menu/src/BasicMenu.vue create mode 100644 src/components/Menu/src/components/BasicMenuItem.vue create mode 100644 src/components/Menu/src/components/BasicSubMenuItem.vue create mode 100644 src/components/Menu/src/components/MenuItemContent.vue create mode 100644 src/components/Menu/src/index.less create mode 100644 src/components/Menu/src/props.ts create mode 100644 src/components/Menu/src/types.ts create mode 100644 src/components/Menu/src/useOpenKeys.ts create mode 100644 src/components/Modal/index.ts create mode 100644 src/components/Modal/src/BasicModal.vue create mode 100644 src/components/Modal/src/components/Modal.tsx create mode 100644 src/components/Modal/src/components/ModalClose.vue create mode 100644 src/components/Modal/src/components/ModalFooter.vue create mode 100644 src/components/Modal/src/components/ModalHeader.vue create mode 100644 src/components/Modal/src/components/ModalWrapper.vue create mode 100644 src/components/Modal/src/hooks/useModal.ts create mode 100644 src/components/Modal/src/hooks/useModalContext.ts create mode 100644 src/components/Modal/src/hooks/useModalDrag.ts create mode 100644 src/components/Modal/src/hooks/useModalFullScreen.ts create mode 100644 src/components/Modal/src/index.less create mode 100644 src/components/Modal/src/props.ts create mode 100644 src/components/Modal/src/typing.ts create mode 100644 src/components/Page/index.ts create mode 100644 src/components/Page/src/PageFooter.vue create mode 100644 src/components/Page/src/PageWrapper.vue create mode 100644 src/components/Qrcode/index.ts create mode 100644 src/components/Qrcode/src/Qrcode.vue create mode 100644 src/components/Qrcode/src/drawCanvas.ts create mode 100644 src/components/Qrcode/src/drawLogo.ts create mode 100644 src/components/Qrcode/src/qrcodePlus.ts create mode 100644 src/components/Qrcode/src/toCanvas.ts create mode 100644 src/components/Qrcode/src/typing.ts create mode 100644 src/components/Scrollbar/index.ts create mode 100644 src/components/Scrollbar/src/Scrollbar.vue create mode 100644 src/components/Scrollbar/src/bar.ts create mode 100644 src/components/Scrollbar/src/types.d.ts create mode 100644 src/components/Scrollbar/src/util.ts create mode 100644 src/components/SimpleMenu/index.ts create mode 100644 src/components/SimpleMenu/src/SimpleMenu.vue create mode 100644 src/components/SimpleMenu/src/SimpleMenuTag.vue create mode 100644 src/components/SimpleMenu/src/SimpleSubMenu.vue create mode 100644 src/components/SimpleMenu/src/components/Menu.vue create mode 100644 src/components/SimpleMenu/src/components/MenuCollapseTransition.vue create mode 100644 src/components/SimpleMenu/src/components/MenuItem.vue create mode 100644 src/components/SimpleMenu/src/components/SubMenuItem.vue create mode 100644 src/components/SimpleMenu/src/components/menu.less create mode 100644 src/components/SimpleMenu/src/components/types.ts create mode 100644 src/components/SimpleMenu/src/components/useMenu.ts create mode 100644 src/components/SimpleMenu/src/components/useSimpleMenuContext.ts create mode 100644 src/components/SimpleMenu/src/index.less create mode 100644 src/components/SimpleMenu/src/types.ts create mode 100644 src/components/SimpleMenu/src/useOpenKeys.ts create mode 100644 src/components/StrengthMeter/index.ts create mode 100644 src/components/StrengthMeter/src/StrengthMeter.vue create mode 100644 src/components/Table/index.ts create mode 100644 src/components/Table/src/BasicTable.vue create mode 100644 src/components/Table/src/componentMap.ts create mode 100644 src/components/Table/src/components/EditTableHeaderIcon.vue create mode 100644 src/components/Table/src/components/HeaderCell.vue create mode 100644 src/components/Table/src/components/TableAction.vue create mode 100644 src/components/Table/src/components/TableFooter.vue create mode 100644 src/components/Table/src/components/TableHeader.vue create mode 100644 src/components/Table/src/components/TableImg.vue create mode 100644 src/components/Table/src/components/TableTitle.vue create mode 100644 src/components/Table/src/components/editable/CellComponent.ts create mode 100644 src/components/Table/src/components/editable/EditableCell.vue create mode 100644 src/components/Table/src/components/editable/helper.ts create mode 100644 src/components/Table/src/components/editable/index.ts create mode 100644 src/components/Table/src/components/settings/ColumnSetting.vue create mode 100644 src/components/Table/src/components/settings/FullScreenSetting.vue create mode 100644 src/components/Table/src/components/settings/RedoSetting.vue create mode 100644 src/components/Table/src/components/settings/SizeSetting.vue create mode 100644 src/components/Table/src/components/settings/index.vue create mode 100644 src/components/Table/src/const.ts create mode 100644 src/components/Table/src/hooks/useColumns.ts create mode 100644 src/components/Table/src/hooks/useCustomRow.ts create mode 100644 src/components/Table/src/hooks/useDataSource.ts create mode 100644 src/components/Table/src/hooks/useLoading.ts create mode 100644 src/components/Table/src/hooks/usePagination.tsx create mode 100644 src/components/Table/src/hooks/useRowSelection.ts create mode 100644 src/components/Table/src/hooks/useScrollTo.ts create mode 100644 src/components/Table/src/hooks/useTable.ts create mode 100644 src/components/Table/src/hooks/useTableContext.ts create mode 100644 src/components/Table/src/hooks/useTableExpand.ts create mode 100644 src/components/Table/src/hooks/useTableFooter.ts create mode 100644 src/components/Table/src/hooks/useTableForm.ts create mode 100644 src/components/Table/src/hooks/useTableHeader.ts create mode 100644 src/components/Table/src/hooks/useTableScroll.ts create mode 100644 src/components/Table/src/hooks/useTableStyle.ts create mode 100644 src/components/Table/src/props.ts create mode 100644 src/components/Table/src/types/column.ts create mode 100644 src/components/Table/src/types/componentType.ts create mode 100644 src/components/Table/src/types/pagination.ts create mode 100644 src/components/Table/src/types/table.ts create mode 100644 src/components/Table/src/types/tableAction.ts create mode 100644 src/components/Time/index.ts create mode 100644 src/components/Time/src/Time.vue create mode 100644 src/components/Tools/ImportFileModal.vue create mode 100644 src/components/Transition/index.ts create mode 100644 src/components/Transition/src/CollapseTransition.vue create mode 100644 src/components/Transition/src/CreateTransition.tsx create mode 100644 src/components/Transition/src/ExpandTransition.ts create mode 100644 src/components/Tree/index.ts create mode 100644 src/components/Tree/src/BasicTree.vue create mode 100644 src/components/Tree/src/TreeIcon.ts create mode 100644 src/components/Tree/src/components/TreeHeader.vue create mode 100644 src/components/Tree/src/hooks/useTree.ts create mode 100644 src/components/Tree/src/types/tree.ts create mode 100644 src/components/Tree/style/index.less create mode 100644 src/components/Tree/style/index.ts create mode 100644 src/components/Upload/index.ts create mode 100644 src/components/Upload/src/BasicUpload.vue create mode 100644 src/components/Upload/src/FileList.vue create mode 100644 src/components/Upload/src/ThumbUrl.vue create mode 100644 src/components/Upload/src/UploadModal.vue create mode 100644 src/components/Upload/src/UploadPreviewModal.vue create mode 100644 src/components/Upload/src/data.tsx create mode 100644 src/components/Upload/src/helper.ts create mode 100644 src/components/Upload/src/props.ts create mode 100644 src/components/Upload/src/typing.ts create mode 100644 src/components/Upload/src/useUpload.ts create mode 100644 src/components/VxeTable/index.ts create mode 100644 src/components/VxeTable/src/VxeBasicTable.tsx create mode 100644 src/components/VxeTable/src/componentMap.ts create mode 100644 src/components/VxeTable/src/componentType.ts create mode 100644 src/components/VxeTable/src/components/AApiSelect.tsx create mode 100644 src/components/VxeTable/src/components/AApiTreeSelect.tsx create mode 100644 src/components/VxeTable/src/components/AAutoComplete.tsx create mode 100644 src/components/VxeTable/src/components/AButton.tsx create mode 100644 src/components/VxeTable/src/components/AButtonGroup.tsx create mode 100644 src/components/VxeTable/src/components/ACascader.tsx create mode 100644 src/components/VxeTable/src/components/ACheckboxGroup.tsx create mode 100644 src/components/VxeTable/src/components/ADatePicker.tsx create mode 100644 src/components/VxeTable/src/components/AEmpty.tsx create mode 100644 src/components/VxeTable/src/components/AInput.tsx create mode 100644 src/components/VxeTable/src/components/AInputNumber.tsx create mode 100644 src/components/VxeTable/src/components/AInputSearch.tsx create mode 100644 src/components/VxeTable/src/components/AMonthPicker.tsx create mode 100644 src/components/VxeTable/src/components/ARadioGroup.tsx create mode 100644 src/components/VxeTable/src/components/ARangePicker.tsx create mode 100644 src/components/VxeTable/src/components/ARate.tsx create mode 100644 src/components/VxeTable/src/components/ASelect.tsx create mode 100644 src/components/VxeTable/src/components/ASwitch.tsx create mode 100644 src/components/VxeTable/src/components/ATimePicker.tsx create mode 100644 src/components/VxeTable/src/components/ATreeSelect.tsx create mode 100644 src/components/VxeTable/src/components/AWeekPicker.tsx create mode 100644 src/components/VxeTable/src/components/AYearPicker.tsx create mode 100644 src/components/VxeTable/src/components/common.tsx create mode 100644 src/components/VxeTable/src/components/index.tsx create mode 100644 src/components/VxeTable/src/const.ts create mode 100644 src/components/VxeTable/src/css/common.scss create mode 100644 src/components/VxeTable/src/css/component.scss create mode 100644 src/components/VxeTable/src/css/index.scss create mode 100644 src/components/VxeTable/src/css/scrollbar.scss create mode 100644 src/components/VxeTable/src/css/toolbar.scss create mode 100644 src/components/VxeTable/src/css/variable.scss create mode 100644 src/components/VxeTable/src/emits.ts create mode 100644 src/components/VxeTable/src/helper.ts create mode 100644 src/components/VxeTable/src/methods.ts create mode 100644 src/components/VxeTable/src/props.ts create mode 100644 src/components/VxeTable/src/setting.ts create mode 100644 src/components/VxeTable/src/types.ts create mode 100644 src/components/registerGlobComp.ts create mode 100644 src/design/.DS_Store create mode 100644 src/design/ant/btn.less create mode 100644 src/design/ant/index.less create mode 100644 src/design/ant/input.less create mode 100644 src/design/ant/pagination.less create mode 100644 src/design/ant/table.less create mode 100644 src/design/color.less create mode 100644 src/design/config.less create mode 100644 src/design/dark.less create mode 100644 src/design/entry.css create mode 100644 src/design/index.less create mode 100644 src/design/public.less create mode 100644 src/design/theme.less create mode 100644 src/design/transition/base.less create mode 100644 src/design/transition/fade.less create mode 100644 src/design/transition/index.less create mode 100644 src/design/transition/scale.less create mode 100644 src/design/transition/scroll.less create mode 100644 src/design/transition/slide.less create mode 100644 src/design/transition/zoom.less create mode 100644 src/design/var/breakpoint.less create mode 100644 src/design/var/easing.less create mode 100644 src/design/var/index.less create mode 100644 src/directives/clickOutside.ts create mode 100644 src/directives/ellipsis.ts create mode 100644 src/directives/index.ts create mode 100644 src/directives/loading.ts create mode 100644 src/directives/permission.ts create mode 100644 src/directives/ripple/index.less create mode 100644 src/directives/ripple/index.ts create mode 100644 src/enums/appEnum.ts create mode 100644 src/enums/breakpointEnum.ts create mode 100644 src/enums/cacheEnum.ts create mode 100644 src/enums/exceptionEnum.ts create mode 100644 src/enums/httpEnum.ts create mode 100644 src/enums/menuEnum.ts create mode 100644 src/enums/pageEnum.ts create mode 100644 src/enums/sizeEnum.ts create mode 100644 src/hooks/.DS_Store create mode 100644 src/hooks/component/useFormItem.ts create mode 100644 src/hooks/component/usePageContext.ts create mode 100644 src/hooks/core/useAttrs.ts create mode 100644 src/hooks/core/useContext.ts create mode 100644 src/hooks/event/useBreakpoint.ts create mode 100644 src/hooks/event/useEventListener.ts create mode 100644 src/hooks/event/useScroll.ts create mode 100644 src/hooks/setting/index.ts create mode 100644 src/hooks/setting/useDarkModeTheme.ts create mode 100644 src/hooks/setting/useHeaderSetting.ts create mode 100644 src/hooks/setting/useMenuSetting.ts create mode 100644 src/hooks/setting/useMultipleTabSetting.ts create mode 100644 src/hooks/setting/useRootSetting.ts create mode 100644 src/hooks/setting/useTransitionSetting.ts create mode 100644 src/hooks/web/useAppInject.ts create mode 100644 src/hooks/web/useContentHeight.ts create mode 100644 src/hooks/web/useContextMenu.ts create mode 100644 src/hooks/web/useCopyToClipboard.ts create mode 100644 src/hooks/web/useDesign.ts create mode 100644 src/hooks/web/useECharts.ts create mode 100644 src/hooks/web/useFullContent.ts create mode 100644 src/hooks/web/useI18n.ts create mode 100644 src/hooks/web/useLockPage.ts create mode 100644 src/hooks/web/useMessage.tsx create mode 100644 src/hooks/web/usePage.ts create mode 100644 src/hooks/web/usePagination.ts create mode 100644 src/hooks/web/usePermission.ts create mode 100644 src/hooks/web/useScript.ts create mode 100644 src/hooks/web/useSortable.ts create mode 100644 src/hooks/web/useTabs.ts create mode 100644 src/hooks/web/useTitle.ts create mode 100644 src/hooks/web/useWatermark.ts create mode 100644 src/layouts/.DS_Store create mode 100644 src/layouts/default/content/index.vue create mode 100644 src/layouts/default/content/useContentContext.ts create mode 100644 src/layouts/default/content/useContentViewHeight.ts create mode 100644 src/layouts/default/feature/index.vue create mode 100644 src/layouts/default/footer/index.vue create mode 100644 src/layouts/default/header/MultipleHeader.vue create mode 100644 src/layouts/default/header/components/Breadcrumb.vue create mode 100644 src/layouts/default/header/components/ErrorAction.vue create mode 100644 src/layouts/default/header/components/FullScreen.vue create mode 100644 src/layouts/default/header/components/index.ts create mode 100644 src/layouts/default/header/components/lock/LockModal.vue create mode 100644 src/layouts/default/header/components/notify/NoticeList.vue create mode 100644 src/layouts/default/header/components/notify/data.ts create mode 100644 src/layouts/default/header/components/notify/index.vue create mode 100644 src/layouts/default/header/components/user-dropdown/DropMenuItem.vue create mode 100644 src/layouts/default/header/components/user-dropdown/index.vue create mode 100644 src/layouts/default/header/index.less create mode 100644 src/layouts/default/header/index.vue create mode 100644 src/layouts/default/index.vue create mode 100644 src/layouts/default/menu/index.vue create mode 100644 src/layouts/default/menu/useLayoutMenu.ts create mode 100644 src/layouts/default/setting/SettingDrawer.tsx create mode 100644 src/layouts/default/setting/components/InputNumberItem.vue create mode 100644 src/layouts/default/setting/components/SelectItem.vue create mode 100644 src/layouts/default/setting/components/SettingFooter.vue create mode 100644 src/layouts/default/setting/components/SwitchItem.vue create mode 100644 src/layouts/default/setting/components/ThemeColorPicker.vue create mode 100644 src/layouts/default/setting/components/TypePicker.vue create mode 100644 src/layouts/default/setting/components/index.ts create mode 100644 src/layouts/default/setting/enum.ts create mode 100644 src/layouts/default/setting/handler.ts create mode 100644 src/layouts/default/setting/index.vue create mode 100644 src/layouts/default/sider/DragBar.vue create mode 100644 src/layouts/default/sider/LayoutSider.vue create mode 100644 src/layouts/default/sider/MixSider.vue create mode 100644 src/layouts/default/sider/index.vue create mode 100644 src/layouts/default/sider/useLayoutSider.ts create mode 100644 src/layouts/default/tabs/components/FoldButton.vue create mode 100644 src/layouts/default/tabs/components/TabContent.vue create mode 100644 src/layouts/default/tabs/components/TabRedo.vue create mode 100644 src/layouts/default/tabs/index.less create mode 100644 src/layouts/default/tabs/index.vue create mode 100644 src/layouts/default/tabs/types.ts create mode 100644 src/layouts/default/tabs/useMultipleTabs.ts create mode 100644 src/layouts/default/tabs/useTabDropdown.ts create mode 100644 src/layouts/default/trigger/HeaderTrigger.vue create mode 100644 src/layouts/default/trigger/SiderTrigger.vue create mode 100644 src/layouts/default/trigger/index.vue create mode 100644 src/layouts/iframe/index.vue create mode 100644 src/layouts/iframe/useFrameKeepAlive.ts create mode 100644 src/layouts/page/index.vue create mode 100644 src/layouts/page/transition.ts create mode 100644 src/locales/helper.ts create mode 100644 src/locales/lang/en.ts create mode 100644 src/locales/lang/en/basic.ts create mode 100644 src/locales/lang/en/common.ts create mode 100644 src/locales/lang/en/component.ts create mode 100644 src/locales/lang/en/financial.ts create mode 100644 src/locales/lang/en/home.ts create mode 100644 src/locales/lang/en/layout.ts create mode 100644 src/locales/lang/en/product.ts create mode 100644 src/locales/lang/en/purchase.ts create mode 100644 src/locales/lang/en/reports.ts create mode 100644 src/locales/lang/en/retail.ts create mode 100644 src/locales/lang/en/routes/basic.ts create mode 100644 src/locales/lang/en/routes/dashboard.ts create mode 100644 src/locales/lang/en/routes/demo.ts create mode 100644 src/locales/lang/en/sales.ts create mode 100644 src/locales/lang/en/sys.ts create mode 100644 src/locales/lang/en/system.ts create mode 100644 src/locales/lang/en/warehouse.ts create mode 100644 src/locales/lang/zh-CN/antdLocale/DatePicker.ts create mode 100644 src/locales/lang/zh-CN/basic.ts create mode 100644 src/locales/lang/zh-CN/common.ts create mode 100644 src/locales/lang/zh-CN/component.ts create mode 100644 src/locales/lang/zh-CN/financial.ts create mode 100644 src/locales/lang/zh-CN/home.ts create mode 100644 src/locales/lang/zh-CN/layout.ts create mode 100644 src/locales/lang/zh-CN/product.ts create mode 100644 src/locales/lang/zh-CN/purchase.ts create mode 100644 src/locales/lang/zh-CN/reports.ts create mode 100644 src/locales/lang/zh-CN/retail.ts create mode 100644 src/locales/lang/zh-CN/routes/basic.ts create mode 100644 src/locales/lang/zh-CN/routes/dashboard.ts create mode 100644 src/locales/lang/zh-CN/routes/demo.ts create mode 100644 src/locales/lang/zh-CN/sales.ts create mode 100644 src/locales/lang/zh-CN/sys.ts create mode 100644 src/locales/lang/zh-CN/system.ts create mode 100644 src/locales/lang/zh-CN/warehouse.ts create mode 100644 src/locales/lang/zh_CN.ts create mode 100644 src/locales/setupI18n.ts create mode 100644 src/locales/useLocale.ts create mode 100644 src/logics/.DS_Store create mode 100644 src/logics/error-handle/index.ts create mode 100644 src/logics/initAppConfig.ts create mode 100644 src/logics/mitt/routeChange.ts create mode 100644 src/logics/theme/dark.ts create mode 100644 src/logics/theme/index.ts create mode 100644 src/logics/theme/updateBackground.ts create mode 100644 src/logics/theme/updateColorWeak.ts create mode 100644 src/logics/theme/updateGrayMode.ts create mode 100644 src/logics/theme/util.ts create mode 100644 src/main.ts create mode 100644 src/router/.DS_Store create mode 100644 src/router/constant.ts create mode 100644 src/router/guard/index.ts create mode 100644 src/router/guard/paramMenuGuard.ts create mode 100644 src/router/guard/permissionGuard.ts create mode 100644 src/router/guard/stateGuard.ts create mode 100644 src/router/helper/menuHelper.ts create mode 100644 src/router/helper/routeHelper.ts create mode 100644 src/router/index.ts create mode 100644 src/router/menus/index.ts create mode 100644 src/router/routes/basic.ts create mode 100644 src/router/routes/index.ts create mode 100644 src/router/types.ts create mode 100644 src/settings/componentSetting.ts create mode 100644 src/settings/designSetting.ts create mode 100644 src/settings/encryptionSetting.ts create mode 100644 src/settings/localeSetting.ts create mode 100644 src/settings/projectSetting.ts create mode 100644 src/settings/siteSetting.ts create mode 100644 src/store/index.ts create mode 100644 src/store/modules/app.ts create mode 100644 src/store/modules/errorLog.ts create mode 100644 src/store/modules/locale.ts create mode 100644 src/store/modules/lock.ts create mode 100644 src/store/modules/multipleTab.ts create mode 100644 src/store/modules/permission.ts create mode 100644 src/store/modules/user.ts create mode 100644 src/utils/.DS_Store create mode 100644 src/utils/auth/index.ts create mode 100644 src/utils/bem.ts create mode 100644 src/utils/cache/index.ts create mode 100644 src/utils/cache/memory.ts create mode 100644 src/utils/cache/persistent.ts create mode 100644 src/utils/cache/storageCache.ts create mode 100644 src/utils/cipher.ts create mode 100644 src/utils/color.ts create mode 100644 src/utils/dateUtil.ts create mode 100644 src/utils/domUtils.ts create mode 100644 src/utils/env.ts create mode 100644 src/utils/event/index.ts create mode 100644 src/utils/factory/createAsyncComponent.tsx create mode 100644 src/utils/file/base64Conver.ts create mode 100644 src/utils/file/download.ts create mode 100644 src/utils/helper/treeHelper.ts create mode 100644 src/utils/helper/tsxHelper.tsx create mode 100644 src/utils/http/axios/Axios.ts create mode 100644 src/utils/http/axios/axiosCancel.ts create mode 100644 src/utils/http/axios/axiosRetry.ts create mode 100644 src/utils/http/axios/axiosTransform.ts create mode 100644 src/utils/http/axios/checkStatus.ts create mode 100644 src/utils/http/axios/helper.ts create mode 100644 src/utils/http/axios/index.ts create mode 100644 src/utils/index.ts create mode 100644 src/utils/is.ts create mode 100644 src/utils/lib/echarts.ts create mode 100644 src/utils/log.ts create mode 100644 src/utils/mitt.ts create mode 100644 src/utils/propTypes.ts create mode 100644 src/utils/props.ts create mode 100644 src/utils/tree.ts create mode 100644 src/utils/types.ts create mode 100644 src/utils/uuid.ts create mode 100644 src/views/.DS_Store create mode 100644 src/views/basic/account/BaseSetting.vue create mode 100644 src/views/basic/account/BindEmailModal.vue create mode 100644 src/views/basic/account/BindPhoneModal.vue create mode 100644 src/views/basic/account/MsgNotify.vue create mode 100644 src/views/basic/account/ResetPasswordModal.vue create mode 100644 src/views/basic/account/SecureSetting.vue create mode 100644 src/views/basic/account/data.ts create mode 100644 src/views/basic/account/index.vue create mode 100644 src/views/basic/customer/components/CustomerModal.vue create mode 100644 src/views/basic/customer/customer.data.ts create mode 100644 src/views/basic/customer/index.vue create mode 100644 src/views/basic/income-expense/components/AddEditModal.vue create mode 100644 src/views/basic/income-expense/incomeExpense.data.ts create mode 100644 src/views/basic/income-expense/index.vue create mode 100644 src/views/basic/member/components/MemberModal.vue create mode 100644 src/views/basic/member/index.vue create mode 100644 src/views/basic/member/member.data.ts create mode 100644 src/views/basic/operator/components/OperatorModal.vue create mode 100644 src/views/basic/operator/index.vue create mode 100644 src/views/basic/operator/operator.data.ts create mode 100644 src/views/basic/settlement-account/components/FinancialAccountModal.vue create mode 100644 src/views/basic/settlement-account/components/MultipleAccountsModal.vue create mode 100644 src/views/basic/settlement-account/financialAccount.data.ts create mode 100644 src/views/basic/settlement-account/index.vue create mode 100644 src/views/basic/supplier/components/SupplierModal.vue create mode 100644 src/views/basic/supplier/index.vue create mode 100644 src/views/basic/supplier/supplier.data.ts create mode 100644 src/views/basic/warehouse/components/WarehouseModal.vue create mode 100644 src/views/basic/warehouse/index.vue create mode 100644 src/views/basic/warehouse/warehouse.data.ts create mode 100644 src/views/dashboard/analysis/components/GrowCard.vue create mode 100644 src/views/dashboard/analysis/components/GrowCardFour.vue create mode 100644 src/views/dashboard/analysis/components/GrowCardThree.vue create mode 100644 src/views/dashboard/analysis/components/GrowCardTwo.vue create mode 100644 src/views/dashboard/analysis/components/SalesProductPie.vue create mode 100644 src/views/dashboard/analysis/components/SiteAnalysis.vue create mode 100644 src/views/dashboard/analysis/components/VisitAnalysis.vue create mode 100644 src/views/dashboard/analysis/components/VisitAnalysisBar.vue create mode 100644 src/views/dashboard/analysis/components/VisitRadar.vue create mode 100644 src/views/dashboard/analysis/components/VisitSource.vue create mode 100644 src/views/dashboard/analysis/components/props.ts create mode 100644 src/views/dashboard/analysis/data.ts create mode 100644 src/views/dashboard/analysis/index.vue create mode 100644 src/views/dashboard/workbench/components/DynamicInfo.vue create mode 100644 src/views/dashboard/workbench/components/ProjectCard.vue create mode 100644 src/views/dashboard/workbench/components/QuickNav.vue create mode 100644 src/views/dashboard/workbench/components/SaleRadar.vue create mode 100644 src/views/dashboard/workbench/components/WorkbenchHeader.vue create mode 100644 src/views/dashboard/workbench/components/data.ts create mode 100644 src/views/dashboard/workbench/index.vue create mode 100644 src/views/financial/advance-charge/advance.data.ts create mode 100644 src/views/financial/advance-charge/components/AdvanceChargeModal.vue create mode 100644 src/views/financial/advance-charge/components/ViewAdvanceChargeModal.vue create mode 100644 src/views/financial/advance-charge/index.vue create mode 100644 src/views/financial/collection/addEditCollection.data.ts create mode 100644 src/views/financial/collection/collection.data.ts create mode 100644 src/views/financial/collection/components/AddEditCollectionModal.vue create mode 100644 src/views/financial/collection/components/SaleArrearsModal.vue create mode 100644 src/views/financial/collection/components/ViewCollectionModal.vue create mode 100644 src/views/financial/collection/index.vue create mode 100644 src/views/financial/expense/addEditExpense.data.ts create mode 100644 src/views/financial/expense/components/AddEditExpenseModal.vue create mode 100644 src/views/financial/expense/components/ViewExpenseModal.vue create mode 100644 src/views/financial/expense/expense.data.ts create mode 100644 src/views/financial/expense/index.vue create mode 100644 src/views/financial/income/addEditIncome.data.ts create mode 100644 src/views/financial/income/components/AddEditIncomeModal.vue create mode 100644 src/views/financial/income/components/ViewIncomeModal.vue create mode 100644 src/views/financial/income/income.data.ts create mode 100644 src/views/financial/income/index.vue create mode 100644 src/views/financial/payment/addEditPayment.data.ts create mode 100644 src/views/financial/payment/components/AddEditPaymentModal.vue create mode 100644 src/views/financial/payment/components/PurchaseArrearsModal.vue create mode 100644 src/views/financial/payment/components/ViewPaymentModal.vue create mode 100644 src/views/financial/payment/index.vue create mode 100644 src/views/financial/payment/payment.data.ts create mode 100644 src/views/financial/transfer/addEditTransfer.data.ts create mode 100644 src/views/financial/transfer/components/AddEditTransferModal.vue create mode 100644 src/views/financial/transfer/components/ViewTransferModal.vue create mode 100644 src/views/financial/transfer/index.vue create mode 100644 src/views/financial/transfer/transfer.data.ts create mode 100644 src/views/product/attributes/attributes.data.ts create mode 100644 src/views/product/attributes/components/AttributeModal.vue create mode 100644 src/views/product/attributes/index.vue create mode 100644 src/views/product/category/category.data.ts create mode 100644 src/views/product/category/components/CategoryModal.vue create mode 100644 src/views/product/category/index.vue create mode 100644 src/views/product/info/components/BatchEditModal.vue create mode 100644 src/views/product/info/components/BatchSetPriceModal.vue create mode 100644 src/views/product/info/components/BatchSetStockModal.vue create mode 100644 src/views/product/info/components/ProductInfoModal.vue create mode 100644 src/views/product/info/components/SelectProductModal.vue create mode 100644 src/views/product/info/index.vue create mode 100644 src/views/product/info/info.data.ts create mode 100644 src/views/product/info/model/productInfoModel.ts create mode 100644 src/views/product/units/components/UnitModal.vue create mode 100644 src/views/product/units/index.vue create mode 100644 src/views/product/units/units.data.ts create mode 100644 src/views/production/tasks/index.vue create mode 100644 src/views/production/tasks/task.data.ts create mode 100644 src/views/purchase/model/addEditModel.ts create mode 100644 src/views/purchase/order/components/AddEditModal.vue create mode 100644 src/views/purchase/order/components/ViewOrderModal.vue create mode 100644 src/views/purchase/order/index.vue create mode 100644 src/views/purchase/order/purchaseOrder.data.ts create mode 100644 src/views/purchase/refund/components/AddEditModal.vue create mode 100644 src/views/purchase/refund/components/ViewRefundModal.vue create mode 100644 src/views/purchase/refund/index.vue create mode 100644 src/views/purchase/refund/purchaseRefund.data.ts create mode 100644 src/views/purchase/storage/components/AddEditModal.vue create mode 100644 src/views/purchase/storage/components/ViewStorageModal.vue create mode 100644 src/views/purchase/storage/index.vue create mode 100644 src/views/purchase/storage/purchaseStorage.data.ts create mode 100644 src/views/receipt/LinkReceiptModal.vue create mode 100644 src/views/receipt/ReceiptDetailModal.vue create mode 100644 src/views/receipt/receipt.data.ts create mode 100644 src/views/report/accountStatistics.vue create mode 100644 src/views/report/customerBill.vue create mode 100644 src/views/report/modal/AccountFlowModal.vue create mode 100644 src/views/report/modal/CustomerBillDetailModal.vue create mode 100644 src/views/report/modal/StockFlowModal.vue create mode 100644 src/views/report/modal/SupplierBillDetailModal.vue create mode 100644 src/views/report/productStock.vue create mode 100644 src/views/report/purchaseStatistics.vue create mode 100644 src/views/report/report.data.ts create mode 100644 src/views/report/retailStatistics.vue create mode 100644 src/views/report/saleStatistics.vue create mode 100644 src/views/report/shipmentsDetail.vue create mode 100644 src/views/report/shipmentsSummary.vue create mode 100644 src/views/report/storageDetail.vue create mode 100644 src/views/report/storageSummary.vue create mode 100644 src/views/report/supplierBill.vue create mode 100644 src/views/retail/refund/components/AddEditModal.vue create mode 100644 src/views/retail/refund/components/ViewRefundModal.vue create mode 100644 src/views/retail/refund/index.vue create mode 100644 src/views/retail/refund/refund.data.ts create mode 100644 src/views/retail/shipments/components/AddEditModal.vue create mode 100644 src/views/retail/shipments/components/ViewShipmentModal.vue create mode 100644 src/views/retail/shipments/index.vue create mode 100644 src/views/retail/shipments/model/addEditModel.ts create mode 100644 src/views/retail/shipments/shipments.data.ts create mode 100644 src/views/sales/model/addEditModel.ts create mode 100644 src/views/sales/order/components/AddEditModal.vue create mode 100644 src/views/sales/order/components/ViewSaleOrderModal.vue create mode 100644 src/views/sales/order/index.vue create mode 100644 src/views/sales/order/sales.data.ts create mode 100644 src/views/sales/refund/components/AddEditModal.vue create mode 100644 src/views/sales/refund/components/ViewSaleRefundModal.vue create mode 100644 src/views/sales/refund/index.vue create mode 100644 src/views/sales/refund/saleRefund.data.ts create mode 100644 src/views/sales/shipments/components/AddEditModal.vue create mode 100644 src/views/sales/shipments/components/ViewSaleShipmentsModal.vue create mode 100644 src/views/sales/shipments/index.vue create mode 100644 src/views/sales/shipments/saleShipments.data.ts create mode 100644 src/views/sys/about/index.vue create mode 100644 src/views/sys/config/config.data.ts create mode 100644 src/views/sys/config/index.vue create mode 100644 src/views/sys/department/components/DeptModal.vue create mode 100644 src/views/sys/department/dept.data.ts create mode 100644 src/views/sys/department/index.vue create mode 100644 src/views/sys/error-log/DetailModal.vue create mode 100644 src/views/sys/error-log/data.tsx create mode 100644 src/views/sys/error-log/index.vue create mode 100644 src/views/sys/exception/Exception.vue create mode 100644 src/views/sys/exception/index.ts create mode 100644 src/views/sys/iframe/FrameBlank.vue create mode 100644 src/views/sys/iframe/index.vue create mode 100644 src/views/sys/lock/LockPage.vue create mode 100644 src/views/sys/lock/index.vue create mode 100644 src/views/sys/lock/useNow.ts create mode 100644 src/views/sys/login/EmailForm.vue create mode 100644 src/views/sys/login/ForgetPasswordForm.vue create mode 100644 src/views/sys/login/Login.vue create mode 100644 src/views/sys/login/LoginForm.vue create mode 100644 src/views/sys/login/LoginFormTitle.vue create mode 100644 src/views/sys/login/MobileForm.vue create mode 100644 src/views/sys/login/QrCodeForm.vue create mode 100644 src/views/sys/login/RegisterForm.vue create mode 100644 src/views/sys/login/SessionTimeoutLogin.vue create mode 100644 src/views/sys/login/useLogin.ts create mode 100644 src/views/sys/menu/MenuDrawer.vue create mode 100644 src/views/sys/menu/index.vue create mode 100644 src/views/sys/menu/menu.data.ts create mode 100644 src/views/sys/redirect/index.vue create mode 100644 src/views/sys/role/components/RoleDrawer.vue create mode 100644 src/views/sys/role/components/RolePermissionModal.vue create mode 100644 src/views/sys/role/index.vue create mode 100644 src/views/sys/role/role.data.ts create mode 100644 src/views/sys/tenant/components/TenantModal.vue create mode 100644 src/views/sys/tenant/index.vue create mode 100644 src/views/sys/tenant/tenant.data.ts create mode 100644 src/views/sys/user/account.data.ts create mode 100644 src/views/sys/user/components/AccountDetail.vue create mode 100644 src/views/sys/user/components/AccountModal.vue create mode 100644 src/views/sys/user/components/DeptTree.vue create mode 100644 src/views/sys/user/index.vue create mode 100644 src/views/warehouse/addEditAssembleOrDisassemble.data.ts create mode 100644 src/views/warehouse/addEditStorageShipments.data.ts create mode 100644 src/views/warehouse/allot/allotShipments.data.ts create mode 100644 src/views/warehouse/allot/components/AddEditAllotShipmentsModal.vue create mode 100644 src/views/warehouse/allot/components/ViewAllotShipmentsModal.vue create mode 100644 src/views/warehouse/allot/components/addEditAllotShipments.data.ts create mode 100644 src/views/warehouse/allot/index.vue create mode 100644 src/views/warehouse/assemble/assemble.data.ts create mode 100644 src/views/warehouse/assemble/components/AddEditAssembleModal.vue create mode 100644 src/views/warehouse/assemble/components/ViewAssembleModal.vue create mode 100644 src/views/warehouse/assemble/index.vue create mode 100644 src/views/warehouse/disassemble/components/AddEditDisassembleModal.vue create mode 100644 src/views/warehouse/disassemble/components/ViewDisassembleModal.vue create mode 100644 src/views/warehouse/disassemble/disassemble.data.ts create mode 100644 src/views/warehouse/disassemble/index.vue create mode 100644 src/views/warehouse/shipments/components/AddEditOtherShipmentsModal.vue create mode 100644 src/views/warehouse/shipments/components/ViewOtherShipmentsModal.vue create mode 100644 src/views/warehouse/shipments/index.vue create mode 100644 src/views/warehouse/shipments/otherShipments.data.ts create mode 100644 src/views/warehouse/storage/components/AddEditOtherStorageModal.vue create mode 100644 src/views/warehouse/storage/components/ViewOtherStorageModal.vue create mode 100644 src/views/warehouse/storage/index.vue create mode 100644 src/views/warehouse/storage/otherStorage.data.ts create mode 100644 src/views/workflow/bpmn/index.vue create mode 100644 src/views/workflow/bpmn/zh.ts create mode 100644 tsconfig.json create mode 100644 turbo.json create mode 100644 types/axios.d.ts create mode 100644 types/codemirror.d.ts create mode 100644 types/config.d.ts create mode 100644 types/global.d.ts create mode 100644 types/index.d.ts create mode 100644 types/module.d.ts create mode 100644 types/store.d.ts create mode 100644 types/tree.d.ts create mode 100644 types/utils.d.ts create mode 100644 types/vue-router.d.ts create mode 100644 types/vueuseCore.d.ts create mode 100644 vite.config.ts create mode 100644 wansenai-logo.png diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..77f393261e3a3167ff22892543fde387e7f14b42 GIT binary patch literal 8196 zcmeHMu}<7T6r6<%LPA6-X^^&{MFOg%bBOr@q>wV)9fDKtuoXf<=dZ}`BvooCQ>UTg z8<@AdI{a*}(nU#lEA7s)?>*0W&i39K0PgU5x({ptSZ5b}wZUPaNnCobt)v-GbgTy| z+|1ASk0;fl?q%DAIbaT$1LlA^U=I8Z4sgwuww_t{W7I}-z#Mp%4#@MtvkMjpn~34j z!69q`h$Bvi#?Rabgc_f)NZ3RSr95WbJ-Afr(iX$Ta>l)+6N`jR#8?g&%i$8UOFI-7 z*jeX8I$ROaMsvU%=sVy!wT3CqP-EWTzq`9`d{LF( z1~sT0rQ@Y14gH+q5?`p|Gw~F2?Zb(f)XT}}8OR&d)XP)4+-=lVQ_TdQ20g-d8FY1W zvbuVC8C{(`txII_x~*}IF|XShCd#Y5_p9A_Mvpp1_IqpbC>;ll=vc)SzcH=g&DWn# zkqmdL%dn=X;`>kt-wR$NH$3<5)r#E*9nJ8z>NDJ}48@P{!q2-V+&CP_tGZ!3J~Sk2>%OT)gH} literal 0 HcmV?d00001 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..234f9ca --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +node_modules/ +dist/ +.vscode/ \ No newline at end of file diff --git a/.env b/.env new file mode 100644 index 0000000..7a6f02e --- /dev/null +++ b/.env @@ -0,0 +1,5 @@ +# Configure the name of the global project +VITE_GLOB_APP_TITLE = EAIRP + +# Need to underline here +VITE_GLOB_APP_SHORT_NAME=WanSen_ERP diff --git a/.env.analyze b/.env.analyze new file mode 100644 index 0000000..656b553 --- /dev/null +++ b/.env.analyze @@ -0,0 +1,23 @@ +# Whether to open mock +VITE_USE_MOCK = false + +# public path +VITE_PUBLIC_PATH = / + +# Whether to enable gzip or brotli compression +# Optional: gzip | brotli | none +# If you need multiple forms, you can use `,` to separate +VITE_BUILD_COMPRESS = 'none' + + +# Basic interface address SPA +VITE_GLOB_API_URL=/erp-api + +# File upload address, optional +# It can be forwarded by nginx or write the actual address directly +VITE_GLOB_UPLOAD_URL=/upload + +# Interface prefix +VITE_GLOB_API_URL_PREFIX= + +VITE_ENABLE_ANALYZE = true diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..4e7de53 --- /dev/null +++ b/.env.development @@ -0,0 +1,16 @@ +# Whether to open mock +VITE_USE_MOCK = false + +# public path +VITE_PUBLIC_PATH = / + +VITE_BUILD_COMPRESS = 'none' + +# Delete console +VITE_DROP_CONSOLE = false + +# Basic interface address SPA +VITE_GLOB_API_URL=/erp-api + +# Interface prefix +VITE_GLOB_API_URL_PREFIX= diff --git a/.env.docker b/.env.docker new file mode 100644 index 0000000..8a4caa4 --- /dev/null +++ b/.env.docker @@ -0,0 +1,22 @@ +# Whether to open mock +VITE_USE_MOCK = false + +# public path +VITE_PUBLIC_PATH = / + +# timeout(seconds) +VITE_TIMEOUT = 15 +# Delete console +VITE_DROP_CONSOLE = true + +# Whether to enable gzip or brotli compression +# Optional: gzip | brotli | none +# If you need multiple forms, you can use `,` to separate +VITE_BUILD_COMPRESS = 'none' +VITE_GLOB_API_URL='api_base_url' + +# File upload address, optional +# It can be forwarded by nginx or write the actual address directly +VITE_GLOB_UPLOAD_URL=/files/upload +# Interface prefix +VITE_GLOB_API_URL_PREFIX= \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..effc802 --- /dev/null +++ b/.env.production @@ -0,0 +1,25 @@ +# Whether to open mock +VITE_USE_MOCK = false + +# public path +VITE_PUBLIC_PATH = / + +VITE_BUILD_COMPRESS = 'none' + +# Delete console +VITE_DROP_CONSOLE = false + +# Basic interface address SPA +VITE_GLOB_API_URL=/erp-api + +# Interface prefix +VITE_GLOB_API_URL_PREFIX= + +# Whether to enable image compression +VITE_USE_IMAGEMIN= false + +# use pwa +VITE_USE_PWA = false + +# Is it compatible with older browsers +VITE_LEGACY = false diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..d3f18d8 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,15 @@ +*.sh +node_modules +*.md +*.woff +*.ttf +.vscode +.idea +dist +/public +/docs +.local +/bin +/docker + +/internal/**/dist diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..6f40582 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,15 @@ +/* eslint-env node */ +require('@rushstack/eslint-patch/modern-module-resolution') + +module.exports = { + root: true, + 'extends': [ + 'plugin:vue/vue3-essential', + 'eslint:recommended', + '@vue/eslint-config-typescript', + '@vue/eslint-config-prettier/skip-formatting' + ], + parserOptions: { + ecmaVersion: 'latest' + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9722d32 --- /dev/null +++ b/.gitignore @@ -0,0 +1,110 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and *not* Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# vscode private configuration file +.vscode/redis.json + +.idea + +.vscode diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..642549e --- /dev/null +++ b/.npmrc @@ -0,0 +1,7 @@ +public-hoist-pattern[]=*eslint* +public-hoist-pattern[]=*prettier* +public-hoist-pattern[]=lint-staged +public-hoist-pattern[]=*stylelint* +public-hoist-pattern[]=@commitlint/cli +# Fix CI/CD Github ERR_PNPM_BAD_PM_VERSION  This project is configured to use v9.1.2 of pnpm. Your current pnpm is v9.1.3 +package-manager-strict=false diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..1ff6595 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,17 @@ +dist +.local +.output.js +node_modules + +**/*.svg +**/*.sh + +public +.npmrc + +internal/**/dist + +deploy +docs +docker +mock \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..1acbf9c --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,20 @@ +module.exports = { + printWidth: 100, + semi: true, + vueIndentScriptAndStyle: true, + singleQuote: true, + trailingComma: 'all', + proseWrap: 'never', + // Ignore space sensitivity in HTML tags + htmlWhitespaceSensitivity: 'ignore', + endOfLine: 'auto', + plugins: ['prettier-plugin-packagejson'], + overrides: [ + { + files: '.*rc', + options: { + parser: 'json', + }, + }, + ], +}; diff --git a/.stylelintrc.js b/.stylelintrc.js new file mode 100644 index 0000000..65320e7 --- /dev/null +++ b/.stylelintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['@vben/stylelint-config'], +}; diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..57f9e5b --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, February 2023 + http://www.apache.org/licenses/LICENSE-2.0 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2023-2033 WanSen AI Team, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..1e61332 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (C) 2023-2033 WanSen AI Team + +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-zh_CN.md b/README-zh_CN.md new file mode 100644 index 0000000..a3750d0 --- /dev/null +++ b/README-zh_CN.md @@ -0,0 +1,114 @@ +

+ +

+

+ Enterprise AI Resource Planning Web +

+
+ + + Crates.io version + + + + + + + + +
+ +
+ 下一代人工智能ERP系统 +
+
+ +## Project +[英语](README.md) | [简体中文](./README-zh_CN.md) + +### 快速开始 + +您可以直接使用Docker pull镜像来快速启动。下面是拉取前端镜像的命令 + +### 拉取镜像 +```shell +docker pull wansenai/eairp-web:2.1.1 +``` + +### 运行服务 +请注意该 `API_BASE_URL`参数,这是后端接口映射的地址。如果你是在你的服务器 +上部署,请将此处的localhost地址修改为你的服务器IP地址。 +```shell +docker run --name eairp-web -d -p 3000:80 -e API_BASE_URL=http://localhost:8080/erp-api wansenai/eairp-web:2.1.1 +``` +如果你想使用Docker部署API,也可以拉取API镜像 +```shell +docker pull wansenai/eairp:2.1.1 +``` +并且运行API服务 +```shell +docker run --name eairp -d -p 9998:8088 wansenai/eairp:2.1.1 +``` + +### 在线预览 +- [eairp 在线预览](https://erp.wansen.cloud/) +- 测试账号: wansen +- 测试密码: 123456 +- 部分功能模块正在开发和完善中,请参考我们的[待办事项列表](https://github.com/wansenai/eairp-web/issues/41)。用爱发电并不容易。 +- 如果这个项目对您有帮助,请点击Star。谢谢。 + + 一些功能模块正在开发和改进中, 请参阅我们的[开发计划](https://github.com/wansenai/eairp-web/issues/42), 用爱发电很不容易, 如果这个项目对你有帮助, 请点击Star非常感谢. + +### 代码存储库 +- [wansen-erp](https://github.com/wansenai/wansen-erp) - **ERP Web 模板** + +## 浏览器支持 + +`Chrome 80+` 本地开发推荐使用浏览器 + +支持现代浏览器,不支持 IE + +| [ Edge](http://godban.github.io/browsers-support-badges/)
IE | [ Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | +| :-: | :-: | :-: | :-: | :-: | +| 不支持 | 最新的 2 个版本 | 最新的 2 个版本 | 最新的 2 个版本 | 最新的 2 个版本 | + +## 系统截图(仅部分) +![](images/login-page-en.png) +![](images/home-page-zh.png) +![](images/user-manage-zh.png) +![](images/add-menu-zh.png) +![](images/role-permission-zh.png) + +## 安装与使用 + +- 获取项目代码 + +```bash +git clone https://github.com/wansenai/eairp.git + +cd eairp +``` + +如果您尚未安装pnpm工具,请使用以下命令首先安装pnpm +```bash +npm install -g pnpm +``` + +- 安装依赖 + +```bash +pnpm install +``` + +- 运行服务 +```bash +pnpm serve +``` + +- 构建服务 +```bash +pnpm build +``` diff --git a/README.md b/README.md new file mode 100644 index 0000000..a4f976f --- /dev/null +++ b/README.md @@ -0,0 +1,114 @@ +

+ +

+

+ Enterprise AI Resource Planning Web +

+
+ + + Crates.io version + + + + + + + + +
+ +
+ Next generation artificial intelligent ERP system. +
+
+ +## Project +[English](README.md) | [简体中文](./README-zh_CN.md) + +### Quick Start + +You can directly use the Docker pull image for quick startup. Here are the commands to pull the front-end image + +### Pull images +```shell +docker pull wansenai/eairp-web:2.1.1 +``` + +### Run Server +Please note the `API_BASE_URL` parameter, this is the address mapped by the back-end interface. +If you are deploying on your server, modify the localhost address here to your server IP. +```shell +docker run --name eairp-web -d -p 3000:80 -e API_BASE_URL=http://localhost:8080/erp-api wansenai/eairp-web:2.1.1 +``` +If you want to deploy the API using Docker, you can also pull the API image +```shell +docker pull wansenai/eairp:2.1.1 +``` +And run API services +```shell +docker run --name eairp -d -p 9998:8088 wansenai/eairp:2.1.1 +``` + +### Online preview +- [eairp preview / 在线预览](https://erp.wansen.cloud/) +- test account (测试账号): wansen +- test password (测试密码): 123456 +- Some functional modules are being developed and improved, please refer to our [to-do list](https://github.com/wansenai/eairp-web/issues/41). It's not easy to generate electricity with love. +- If this project is helpful to you, please click on Star. Thank you. + + 一些功能模块正在开发和改进中, 请参阅我们的[开发计划](https://github.com/wansenai/eairp-web/issues/42), 用爱发电很不容易, 如果这个项目对你有帮助, 请点击Star非常感谢. + +### Repository code +- [wansen-erp](https://github.com/wansenai/wansen-erp) - **ERP Web Template** + +## Browser support + +The `Chrome 80+` browser is recommended for local development + +Support modern browsers, not IE + +| [ Edge](http://godban.github.io/browsers-support-badges/)
IE | [ Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | +| :-: | :-: | :-: | :-: | :-: | +| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions | + +## System screenshot (only part) +![](images/login-page-en.png) +![](images/home-page-zh.png) +![](images/user-manage-zh.png) +![](images/add-menu-zh.png) +![](images/role-permission-zh.png) + +## Install and use + +- Get the project code + +```bash +git clone https://github.com/wansenai/eairp.git + +cd eairp +``` + +If you have not installed the pnpm tool, please use the following command to install pnpm first +```bash +npm install -g pnpm +``` + +- Installation dependencies + +```bash +pnpm install +``` + +- run +```bash +pnpm serve +``` + +- build +```bash +pnpm build +``` diff --git a/deploy/default.conf b/deploy/default.conf new file mode 100644 index 0000000..d03d8a6 --- /dev/null +++ b/deploy/default.conf @@ -0,0 +1,18 @@ +server { + listen 80; + listen [::]:80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } + + location /erp-api/ { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header REMOTE-HOST $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } +} diff --git a/docs/README_ZH.md b/docs/README_ZH.md new file mode 100644 index 0000000..d186c66 --- /dev/null +++ b/docs/README_ZH.md @@ -0,0 +1,24 @@ + +# WanSen ERP UI + +## 项目设置 +``` +npm install -g pnpm + +pnpm install +``` + +### 用于打包生产环境的编译程序 +``` +pnpm build + +pnpm preview +``` + +### 查看打包后的程序 +``` +pnpm preview:dist +``` + +### Vue-Cli 自定义配置 +See [Configuration Reference](https://cli.vuejs.org/config/). diff --git a/docs/template/会员信息模板.xlsx b/docs/template/会员信息模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ab2441abb41b54ae5d993f42dbe7aa676d99659f GIT binary patch literal 18944 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 G;eP-igj%@( literal 0 HcmV?d00001 diff --git a/docs/template/供应商模板.xlsx b/docs/template/供应商模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b04a2043719597c36f8c34d3840cc20c81885f9b GIT binary patch literal 19456 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 literal 0 HcmV?d00001 diff --git a/docs/template/客户信息模板.xlsx b/docs/template/客户信息模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..627db504953b550282c507bd6799b46d576418c9 GIT binary patch literal 19456 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 literal 0 HcmV?d00001 diff --git a/images/add-menu-zh.png b/images/add-menu-zh.png new file mode 100644 index 0000000000000000000000000000000000000000..39e482062256cb6e559eec9fc225c0dc6491410b GIT binary patch literal 92146 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 _G}^_>GW9W@hfiq(%4MU!wrAC_fmI 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

  • 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 literal 0 HcmV?d00001 diff --git a/images/register-page-zh.png b/images/register-page-zh.png new file mode 100644 index 0000000000000000000000000000000000000000..d4d3fa19e909f3418692387d8fe357b1aba152ec GIT binary patch literal 194526 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%0A@@9Yz*;ZgZCN( z90I%r$+O_wxTdWWh&C`p~+Z{TzxTGCce)1Kt*WIIaR)zv>#4<{5qS4emb9UVdOwl^zc zw?-F{pm`YEm(yRou=*xz*3e;gCKJIgbn6T*571RTj;joc*=O;gP@jgKGnx*wAq;3vKHfGP8jd7@O()x-VZe2F82 z`*c6|1XxbKNny$*p2Lm(v^R6#m@BSdwNbt+Xo)S=GI9gzYw<9#is5G;7t<6_*d`gU zzQFuvxG#hlsJ2{~?61;Y!!RpB;` z*d-!2=!iY}AHLoW;<4Ei_I%sh97SeE>!+0UMJLKFd}x#`_Wn!M_E?Lz(1v)66|_qw zk|1touHbEclZNuy1NF8?y(7Z6f66v9OD0u27L=7lG0;R!Om`o&c&VX&xP#PihKUW~#pum8%vJYAIjhMH~9jh0_ zD2A7QI)6d3kp0GDCb2|ubYb$7`rwzZX+WjgR}pZ zJ;!%aX8$G#rLX7ret{y^w`=j1)R0+W7RZF9&pPLbF^Ul7fM3U&eIKK}n2rTf;Rbqe zf5HM1g?+T#*DY}<+IOQkNY{%ePZ}Z5!t47yI3Yo;MW2o=M5~YvHcKo&>St9@Yi}mz zey{xehJqjKxbKq%?@A=(e_bQ=tX)Wx#iQol@%|8XOV$fKBm*nYC%Q*`c$e-}WHOQJJK9oVa_DP-<@g2=?R zAwj{3jn5T&@~{2Ya;RvX14Qi}PADO)mV`7=sXgztl~%E}3)DlC9>p)xhNHP%43Q!- z_t@t_GNpuOo=n>QQo#y74r}V zQqB4t}F+>?L0Z)Rt$3qdG?RlHU6B26J}> ztJt|+Mw#!?;3yAickXZLywCNfu&3BP{zq-x|MQ{6*cBet cpcTZkh%onrn4e7GwecI*Z5xZe{O;iY0X(us$N&HU literal 0 HcmV?d00001 diff --git a/images/user-manage-zh.png b/images/user-manage-zh.png new file mode 100644 index 0000000000000000000000000000000000000000..23e21d7d250551c0ff72e1c5a289a462ac60e28a GIT binary patch literal 78390 zcmeEuc|6qp*Y|hEo)8rwRMI9(%DyE<8|qS#ZAL=b#?Hi;k*&qjX3L&RvL=jurc`7X z84QLnBV&wAmSK$NJ6%^@{qFm^ulxD)`Q!P%UKP{KXF2EdIp=-e=bX8H&fHXJgVY89 z0EAARJpKm&@L>RetCpV^e5K-CYAyH=#P1K&V?c4o_OIYC+^$AuMgZ_CL6GIh1O6`H zee$v&00=j7{y>@#FRlW>`mu4klPNml^r0zJW(5z1?NnHz8-XD?&--uJhI1?z<&F zswM3;nU9HeJ??Sh7)gFW{^JAnmAPx*4?WgK=wA$YX`XSz{9;CN&+upaB^tGoZEt_k zet4lbf0~hIxmHK1pL@nD+Js!5bL0Y7{p%_9;>UbeU}9Gm zxZtV0ij?szLpKM%H^yYDMRnc=lyQrmTFF7Kv=goXt9^Z0#?88RBW{V1slMJwWk)d| zKg69G7Js+@%

    MgaLxZX4rF1WJCiwTWT?Ie`|ADskT2aUWJ{98{XiCqZ2XUol`*B(KxS?hY%%(~CRIFGAseukd7ha>Ms$^Cdztwns}cNL3T1 z%o;QbD>Wy4J}EH(@3Kh(z%5iUAA|b(%piR)(^St~U$kPMUl<~Uwg#orS3kQJP}m*r z2KM?(brLAk#i3Up%Dynx7Y$WmLBqI1u#oOfZ{2G{`vfqKJ;7gY@AdtqH@MBosa3Kj zZXi8${$sTvtI^QITz{eWRMZ>Ik>K2cfr0&ULdT&n$pyuDezcPTUuuy1vG1bIQ}#-| z_Qy@2d6egAUTWAO-!rpWYXez{mQDAy0JitSPztD;#rh9*qw9>d1=g+2ni{|e7C|~T z;@7D^DfP)Q;wbbD(tE0Fr{A~t5@~`eb*fhEr0Wky`wH5k(EjesU&4Whoh)@Th6z}! z)XtQ#aP$4yK6IHx{HA#Q9bFK*8Tbz4O0zE(GyFV_bT}Wc7 z{bBpUDS=WI4NbiZ<}a!~+dVT&hF4d}XkKM#EWX+wo~E zCwe}jd9OQM?7D6!|4L;emY9diY(2IZchNvX@*~aM_A_N--cMH~-)MH5bH-i2hXeAf zb2rmkn$$&L0nut}j((G=0V%MmCcFI%jpx;~A03|UftBdMXp&Y%l@`mhwe*hl5LyM{ zF`;3xf=PN?Y+u{<*$S4ij-q4)k=O0Hq40OyUeik13RAvZFaa*-K~L;(pYP>2rQEM5 zsQK>s^C>BFRs2yEs@U(W8THR!HLso-aHf`4i;9zcst;#zw^0Q!3jXy6d`k;scj2aA z7POeEtC^)4JX);WVpNPnsbxtQ3X8;NoU;<}qv=VwmgMVOd73&!zLFN##9BdJ{=Poe z>SE%juWftFTUxO3i2YR}tJI3^5TL3=hdEdtt3AhmkkQOgJ9gQCaB)Xgxb!}^KpM%p zlrCtIT4FdUtNul!=ViHqHohu6$&_xY2Ktiy7f!9oi%7Y9Nq8gm_!w ziA$kwVY8I54%Vm$I~)04(ZSK&aLu1FCW5XC{V*{`r#dX@Fvbnp<7B?DQNFeU*xK}b zs+NWhz#cvjP~FNZUL7h4d%n?C%?oz{Mt;?q@;d$N{z7b%qd-Z|ClpQ=YiHM%>t$=+ zRP$(}~KKbtbY?gXfmNNSEbz_-9=L>|)+E{OuD;-F9!E5mfZ-uW|Djefg>wuCoQ& z8rb~(BF`sr=Jq4bx-*N-;}_=_MPx5=4Q*+uajO0b6$ohczI2TEP@${Hcuar(_@C<= z^^hF?%8Mu12W2q3<<`#o&Ga8)=;9cV=9kRS9b^HSE2)I?l8!P4=3Wtkc}s-}6%Xkk}=HAv)$8K&$xO822tE3C8t*F3hS!d7N}`U@-RIti20&jA=&Oh=jPTY@)wMa8rI^zo{%(n5Oftdn6S%1QBx%9 z%r?j`46xbcW`rq$=9W;FA!Ik)R6BH`Y)of zcb9Kwt@tr+W;ImYI7p2rhbu0eZ;&D9cz0BZ;s`+pBo#55LwsT%%p9 zpG*vDbG$3kYn1nnb|hh`?*>mm;Q~WLq=mH{xs@Dq*uqPzM8D_8P&EO6g)JUDt`G^? z{WiS#WL>Op(kOPDeMoinuz*MB>IBUhIA~OeDwZh^j02Q!I!X5~j&XNrUx&ga$D}tP zogeE-Bt#~5DBYL8*NtP-*IL-gYdVXX7%MfXwQPk$0hd7N-+%#beD7YDT>G>W*XTw0 zl7X$}XZrUu3UyL4cWG=)MqM|QSbF`s$Lb9hH#?&9E)iIAHAFbfwX~s8cad+_!yY2p zokJcDbLj1=Dq0JjcfNkx&BeO0k~nDpkQri_vztUD7rE zzG1xM1%O3hj}638tk$LR=Bk&6rw7bK-s;)#zPYFs`py15x9*pVGBhdKLqppx&v56D z0aZnYVg#Aj2#J=rgL%wf-Dz@GV6dqJdfBD?e(*ro@SR9G-0_uc4<}{D=Cf>(i zIq;HrgwN}no#^4m1Q|&B8Y*J5RsoqofOxNBqg6CD4+aZfGm@GLYG7oL8&+o(^HNxd z)V_d_sU2Z2ByY1CxuhrV&M)<&bU=4Tpc4c!hL?vn*koZ<(VnZ96S47uSvW0QJ}ia< z(m4-i|4yv(tn~f^jKXP6PkVmM_`Q2p1|sOJ!LKMI^oC5-Y$Q{$4Z;XOtlneRz#0Za*KFC%EDJ+AI-c~8bYt5yAx*b^o|vVTXM2njY5CC=5*+_zk@wS#XWE=8$0W692NqaKi`mhm0I@$2r$o!ktcEuo) zYez7to=i|d;aM$wxU1~X%%#U!I_ufm<4;r`lLnTY84P-TCu{IoOj|;_Umo-Q`fAu~ zMw7^6hT%Mh8SWudRvg7ODkk6`fwl9BB?nyg=JxhRDYLJQPwvVot{3{gN?K=M0uEv$ z#3vRz)pUYIzd%RZB-ZALQViDT>kmfcfnK7iZ65a1u?p4u1CNi@m!T?%gddGo4KusPtGb5EECF#8VNUS zn)Z#R0M>70zDhe-896x=+D(Xe&DS=NR*FbA1~w$6?DsoQ9@X-H>Ybvt>>2r7tv$Nv z{mG%l7dEv+s>67!{u6@VQDA7tHmM*d1oPm^(vnlz~HC?GP4)6m*tb?8Q~sYB2m z$XtG2=HQCn?tQQ(*NH2QHwF+-LX{T}m#qeGHEO8m`7Wr2W5n^br_zyK>1z!tX>#m} zkakHN1H-hUgng`IkqHqGPCZgEv@0=9BW z70zBpGno-&#MREVM5_^JHYKZeZ`KmRxf9*kIg}CevCQD|(i8u9K==zU{sdex%dh!B zn-Dj?y)-BQGMBKvoIsHevER*|#70)jl(Y7f-rczGq4Sm7!kG6DVHKTqqb2B)nzkL5 zy!hGX5hDFSW9wowVY>Q&T>v87F1ny-M?g4G)hlG@Y@Y*EW(T7J>hrlqeTUzWlw?bl zJ!-E3bzV=6&Nr%@NDa!Lz;SKgVA;fj4}%l?U|8vu8=Xp8Q0se}f^$e~?cFAW!i^)d z)d^9@!UUXb9lv6LezpPP+rD^+Jm!6$XL?2#mbqR2SBMXPd@X!h2WpP2&*#RAm7c~N zD3Opl;ch4|aM_uCQFOyI8bzMyNfAw6L)NcF#1sHp6=kz0zJiX7I`l!iNeER>xncrh znoUGPDfXT+q5clA>?F6E@&oAkv6g)pnM-v|p=?H$N>={;>+`z!rg)jdhAX*-ZpF2; zHS?)s2e$xsNvj1GsmTqCCJe0k+AXH7q2I-)avG$izVV^}WpO}p?B!YIIZn` z+3f3}LF(Z0`(gUy{c6Q=aqUZ^jDCxT%$&$1iFIUW_I|b#8Eb zk1s`KjB1wa%R@)czc8Yz?(R<{t<#L(!csM($uAtvzyLipZy8l+)m9D48^pe&dx2l> zwEarr&Qc*2g|ms9to;&+mfV=(@N#&>CEe-3t<4(ObBaTi1A9v@%Brj~2A87p+6Y;H zu!Ox&J7@eQr>BgUG0fnC@+iMPnJ!mRJwUQ};vVRy49cs~O zD(&YVeQe?_J>RC-?it5~;^aK;Z_-XvVfXdk_4yHfCe8&BitWLu)E%~J;|E5mWHbr2 zG|WUxZD?V%eFhd76 zbAUd%twY-bY+qLbT0KG~3?yi2)B?Fn>lF}%s#Yc}2j!nu2Jlc4+qD=MX%-im6u6~; z+oj9mnq1Kp5{ktzZ9mglWg+A%alTK18hKI&}52t{hAQ~jPG|>EQ)`~A&o{| zf3@0}kncFVtEFa#5*ma-E?(7>NkeH~r~MSCI{<6eT@rg;owV>lx0f_yHbz>1R+55P zZa_O_E$Wl0VQ5m_s4WgON>Ax# zWX3uLhsa!NM-xDFg~l=mNoeP->^myU-RKtx!7tnjzb*ne0cO8^ZqPc}UHBygkzBS> z9<6!T5#miIgi?bZ<5*3Gt_`z;=!bm?E>!=Uq#-Ihj`3-aylBhp|({`u8lVuv+E*fXVs16a#*dCIEnc zK9_HZZm9$9Q9CYpm5WS-1tGSsw2;)yG9M!0hi`Ad_^p#khtc0Y8(wKxTq`*OTYY2s za3y)<+h#J8#Ly=rRsL|0@Ok?mqXPIXw?r^SVxOL03Xypybnkbv5dfa!zd%%XUHY$| z*a4WF-SHp72hKt`EXx05Z_MV#-}?QbCUID83j^j=CgQ+vngM`5K8WfSr~oDoxzg|B z_dRudQhx4!r-_05-|xbhO;i%S6xSc~dRT1ZY*ttRlXYWyKLgJtl2S`=&_!@Rf8mkl zk?TP{H@h-_o*`GA)KnFA^MM<|RM6Dr60u)5!69{$N|2s_I?RKPX9*l5NN*0XJ9K2kgRV_t@%C1m1dRaD=$`7Cs+*K=x4PKubTnXVJR9B8~%lG@9iJr4k zU-#x(OD@z_%?|{`agV&KN!?&Po!lAZ6CK*{YlKqNrm8?=@IE^S^5A`2FG#9muQzM7 zR>o*8HS&FiZ;nySa=c|$l$PIRg$r#MpIQz5n~+`I;Z2JMw)wQqY`{zg9oGD|SXS0v zM%%eKGaHBlNJPS_aN}@X6Vt1mDv{aLXx2p>Vt2O=)(T zmO0eJ6AT%Vtermxz}H!qTbv8~!~Cs-07_x5p5CzPi)dhyLmyW)TP&ItC8!04?B)*= z8tahH`n>7S%t`EBsVfQrem$~&^E{e~B5qzaqgP+&=_ALdRyJxftI{`wM*kchU|i`o zFwz~gGQJ5Dh>GD&Q?{h$#tvr|cWJ)sa^?(|VgNLJoY5W-9NS%}%jA%JljE^5B|7qH zf%7{$tER_%^T+%>YsFm_kt2vn-R6Cu5Oc z`WBBQ@6CMRtbW76@99o)10UyrPyGb8lZZgb@Fr{70tRIPySLzMa!h-o>x!e#q4uJB zeTn9>_UlpYH_Xilu2o%>ReU0OBO;B_*@?9H?7BCLkZR?UWkT?o4$ZV(Wc~^{@Qbfb zW{s*7?0TeU2SwkiAvXTlnXEKST33Lbv}QYyD6;AQO4!M8d7ITnOUcSn~j zF~D$Xu706h#Lzi2WV-Zl0{812K+6(3GH#K|D5p3C^y{7XvW*xYa8E*C>JO+YQK2fY zC(#Z<$00e4lg0;&ylxnuYI^zM4*Fi#4TFM;!!|v47ATJS_6~2`=Ml)^U0r8w3#9C` z9NQ?;tirOT8_tUZL`-EELZM^TOFk=KC=^R)a8iCh9t_RtzJZYddh${ys#z(=$rPe8 zXu7|oXMxxlXgh&B^v)|mdRn-$AK`FvVqm+GR(i1~;cc5i zF4t)2afFC-%IdegGMux$`ANH2t)zvmW8QvSyr0Vf1s)WBxMAU=CbqA}g+dd7)^Zcf z!HWFYOA;*1r-F}f+xan3Y0BQ%3Sq?L>yM<`I+%2aPG`*ZVkhG72F5`A>*hyz-)8!1 zi=Hv1;$WG6V7bpe?xZfON_qd*X=QQR;Y0#;L*QyAfn(s|p8&0G0g(Fq%t>1v>8R5D}=bxjxlud#qiT^i*0aEd z_(T-Xvnc0u1WV+_=U}vA4|j@({cc{~EeZ^t3)-hfFXMvm+yYGyKu4Xx=BbR*LL8j( zA#-;fR@4|7>r<1{ez%BMrvd9Vp}q%~vZ;}V+9UIpf*2=Lpotql%n%>+)|5MB=ks=Z zXfTU^lvK+OV|0d5k2($R_0k`DOqSYJ<27_t)%fPe8sXg@9?{`p_RZs6{G$zz%liY! z@-_usY9Ye~#~_pyXv`48Ii@v|pr$ zn7Xe}N!U)-n_34_N>V4)qjA$(zz*SnKjbm>s@L5h-s2i=0tkrxLAhm_(d`P&W_r+N zdivT&6aFCy_MM&L+ULuU*%{q*RET|qtQd5g>bodweSk4>z-YWL4(NL&kBM4gBy7a^ zRZ{=k+Aow;lOKb*jT}aGEG^gn=i<*A00z#40pz^{>xuVqUktf@g1$5d5WNwImWrSkI*0v>XAzY7c!kGkWqip|Y1-Ic)R zla9$-P>;$`VtNTe=%{|$tDIt?;MH=5@XpI1>01(sn}_L|y>-x>OBBU}nXFy%$cXT{ ze2K?~Rf}BYg+aet^64G?qhA6m!b-8%cJx-zY*GgDh61%+xV=L+5!IpAbI0J6h1$1Y z`&F$?*us))iqY1rcM9sIU;-+9mM5h5-nrbZ0JiJcIV+W?{?OBxu??|St+&6fY#cWr z1!lV&510T4>BzG{VW>ex+QNTW#%o#Gk##xU^%_I5;M(&S&VTr6L?U-XO1W#r>RL|1 zsz1M$hT1wmMwuTQ^}$9Y-Nzf>9J=z(TXBaMvO=43!4vt;u{eOc)L53=-rG|4^r__@ znW=@I9~&tO3UPgP7`Q~HtLs6nJ>sBAgiex~-%5%oUSoLy!6&2kZr9%8D>w-w$E{OI z>)F}GQN^V4i-ji7Mz(CvIZ$qrfBI-@Nv?K%L6~LFg5(EOgFa-AXTflA-w5$0WKJCQ z`^|njySW^ zKu}}jyh+I5j^OU2FWiY0s;@1XarTDkv<;XH(uB-x7hvs>7c6Jf1+oJ(2`e&U(3o5K z(w>G^5bsm$1g=L?ua+5DNvU&vkk^-j(xd?idVZe(#+L4y3Yl~H4^VTq$ilk^+r(Zh zRgct7ICwbnDx_3n+Un8yH)>x98GFV`gkoc~uf8i0pQy~MKp##4wl&ojbA(i2dflxY zA*lc8$5~gl#iGSM0lT<&?fbaw7BoXb;_7(HKci4_@#m^71i~x6_HA;quv-iFdT0c4 zQNY52$qSp8_g_ME-GjD+o@R(b6!w>v$JjPq(gKR(FTWD~fFS&ig_{0^G^fBsM=(t( zQ(>;6XYy5STSbENmQtBDYRuc=(J`d0*fT;J)wC1Rm}NlFnH{;hL2+3EGi~;I+1ytR$cnOd3f;_45kDqN04Ti6V%=uk6tKz-jTstY_6oMkU1iKNw@zxmgNOm+PyQD;`VpiD zj=`&C{F99lo8ziZ{a<|K6c_wm^#RD7Q-c2U8*`&?SlOiG&cuqP-ENM1J`|uTzw9Bj zUzm9b0~Hg9YWNl7RH4FV{jx0cO3qa7J;;e@YE6C*Aps8^HPx#>gN%KUQkktWzdj58 zP^ByY0?U11$oJdxrA7fn1KEMzJAZp|SFsHz1ajk(`2EE%FaQ5r|4jl`g#e%`TZD@H zmg<^$Xs>ztKEhAJ4FF1Yo+AEO*;mofx{afS7czFQpa4F&d{N!x?cZUd_1;gW`3v?R zPI96X+UT9F0PrEVqU6x8%Lx=p7tz&B{?yK|2}OSz002IG4V8RI43OV*PPgg`4}kf0 zjpiQv>%Rf23AHx%J||8de6v*%0AfwuVNSooCcs+LhU6T}39x#Fi>)1R=q>bGlEe9A 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⋙lutO|vF>@#F7*6|n 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%0D>mc=D32rTX*H7-?}~tWYZCPbljA zt}3Zf`5{udEcV0T=$GysF!YsDRGmL-fV+L;IvcCGc@U3%FbMtDnoE!g_Y?%Pdmd4C z=(xo~KaKma1z;aYMt-QmmRNq+Q1JzuxlX?yTrG$Fd6Zts$|Qm=AEcV8bh*oL80#>3!EQQY5hVzPZckyNNc?) ze+%!LoQvaKy|oFVg-RO`b%Mwb6w;oqUD8fqFk;G+8$ioxDIh0%aX4oGhPhW1Q&X~g z${UwVE8MzVFf*TI5u0wY-wqduL9I9G_z$-|r3JY?tGEJ4#J=G2A?Eo;t|o5TMQGaS z5Kj>Q_<;S?RX?diU*_5VZj*j*aYJG9g7N#nO&=zN1)WW}QV84V1D^6>@wqqXt6MCB zvK6`DxW|_Y7Cch#AG*QS*)F6k>&S7?Ty5 z@oz<`DuW@h32IE~?DC%SIBW_2_?AeT;&zm0bd z9D&{CY>;@2+P7o+L0w4ig2IGm%<+F;py2YGHAm2^{@9cSC=LjYY44}LdEG*oajE~o zPEu1zK`a+sG~ga%dpk8B@%bEff01d{`+Ym$mwZ}piYfOio~{N*B`nYmT{%B<=Ve%H zN@IWE&F7m_P!K-i$`poeTR1iFc+1hGs8G#Hd5ZU;j*o9Fzg+O$8(pk-Yf6d@&OpPU zU4#l~w>mKo)X=J#%N~6^=Z($msm#2BTf&9~L)G7|h<#R;=C!h7a#@DolQraA!y7|O zb-4Nhr-s$t>X-|by<(J{$q>x!7yR@Sz~nfkyZ*z{hMS6xxyL!hq3XugsV*BTnBcfm zx}WReE1Gvkw!RDTJ5)jN*;RilD$S=e)OwRJLmgD`feGJutC#_?b%enoEZ@$QnKr?O zLKD%cB_--Ygt{qfEwv`xkWwXhMrz3AEI*uUJ4EPI`-rt@4O~2){ z3h!1c>pcnaU2Ry3Cw$!^_>m!sywyEHx~y6|Eu30Fco-9UW797i(6So3%Dva>vo-*W zJXQ=ZKKVqM(Y~%PX7%I>SPwhVbm5jeF~Pw7{Mgl}Pa9)DXF~<&CiOoeF>cV4vH%*c z#l!}i?{n(!(86ONjOSub7)xDqU!}Cw7FGjXk-c#jZ`CIXgyFWZ1ZK+hP>%k|nffbv zsGENG!xKTP*mP~kqo~;a@DHlBO|Th2tpdh=SlJrEc4|Fw{5h>=kTh>{gVlEx!>abY zXn}0~MvxkMNgnj+7v1o4CY^xRd^G)C z!kn#pKMoBYUO91v_N$1w1>bOMdoDaW^v##;#TPG}e|PnaOGhW4`sv;GSB_tE=<)LR zJQ*kR3w%5t^v&TM zSxr-kMB44CNScvOEOJP#PS7ozf+20fICot%1}C$xIHa1-)=`)F1q?ROheEMKIdH2% z(HO=WH~NS|@~tD!oX9R;T7_wU2%3}dsZU8F==w4~Kk9ToDK)%L2ER^JkAPt@q*AOI z{;AIJ9Z3Yfn+xZTENRrhf0AY%Qp10)l}q7UmDb)=ysbU+l8FtM9Qxe4YBPr9jS1I* zyJ-}@O*J|`n#5B;5*vUSu8%YLa0oGxZ81!5?_F_5&HM{GDw^?=l1CkszNgBG> zifU!r>H@7{$#Tv+*6cPza5^f^nIi{_tpn0;t(EZyVwCJ<1}WYe!O#<`HI~D^3@Hk3 zJ>Oc#sWuY^tCbcpcbQC@B;7;QndrU<9mz`Z#R|E@)6E;CB1CtVfZfLn<5Tji5I+MB zEm7@eDNa#s9co_zTb-Y+9(|hchv=4AwI~?THn7J!h=|K;VJIx2kfiMjR$>*_u!!Fn zEaRPzY!Km7hI(s4>-dHY0RtgT-4Ix}t_oVR02IUOchILnZK|qKxz;0+XiG7NvE3#^ z3l^9gX30d`W;ousc`@mBmBWpBaqzIUS?2CN_YL45Bz0}cJj=4dw?`J+s^JF(>@)79 zEfCv%63d+1tRt!$;Ols#eXKMKInR3E(g*J1liKrWB%`}(L1R6iq{P(en&EX+HKpGf zm0C>{9pp5lh1kwc_SMheBEsX&&Vzmt1aTo*&XwOS=0gdO&04P{b?+3^eZ;lTeB&wn z!%58B$r3=5d5>&u+H%VQ+dyAk+aimineKxaLO6GEQPg<+gnnBusmdB3VBcgvGhA#2 zI}lQIyh#|IxEOk@ll73KV|(eWbM$vb7;Erl4D+@I2$Mxe3*`~v+ zx&}wgiIE0Vzs8U0R`X0kes{L@VJGmv~7ej%@^bQ4IJIk+>7~Hc})Lx zS;#k_s5Wm@z@f$x1zEnRuvBgV@>G6DEGZKubck z4YEj^RLS%Y?t%Rr)9bGhM_8slMB9A2NTZ_@ZT$lRvT;(QWXNVtGLq*(>!vz&fi2FY zG-JHjP~HqS4?#mLd>f5~);PF%D8nFiwqdBgyxGrM#Kwm?b@4Z{D#BAXRR&vys_B{I zDB%Td^@z7%S*OcmCT1h_KDEd|ENi?3oy7}Y(j^TPDIR>v{LUPj0VQSeBI-m<<^Y+y zCVoMt3Im*gt>Iz%vZ-~5S$}V_=o+vnap8@Voc9=M%S#1Cqi3;7TN2uFPO{;;m=o@( z7XkLJ9x#VWjg%QNiTtjf7DXBgBN2`9BvWA_&7!pGM`NH$a)pFYXUZb0*cKI)Y8_zP ziYO4PYsnOFmV<|O`0RcPLIZT@B)gnNGO>TDFZ-XdAZa!O=D&56)C!{@pdOo;51-tSfu{%rS+{Vl%IV zwP4gec)ZP4a(?Qtes3d58coZaXr|kGM&A}&^VIgJ=4=p0_Q)Q^M18=gD)eKv&NH%Je{O0JL#~#WH_woXB;KhrRK?@C*1&zxGIS-v?eXqHmn3k4E6w~ z$9FZb<{CWWp2ff;S$B=Ma@j_%IsngU3-bhuBiXgeR6$IFKG#ev2c93e#&@{g0A`oE z{O=9hNQJc<2q@YfN`Cxh>j(Dqm8VHP!kxQA^bJiI?X?k8{V%`tP4MAzPNKyB^da$v zX+p-}R?wNCQ?4<=pw`Rs_`*j5<6#m>wq*u+25^$U3npJ>aWCr1`1{1DU;aEZH6$k@ z#fyCP?|rGL6>2sua|=rgx34?!+|0Ot`xS9YTwgY3H+<<1sAKht)5un;#G^a@j; z*HL^^MpA)SwclMVLvPvsZ(QSS&QrmCWw71e{_E#WH1FR&K`E+#cVFqp{>d$^^LzTq zH$U0`y&C)X7f9l^^Z7{mxWBiz9_bFix6`No{jKl^Iof|X^5?(x*x!Mi?BC7$`fqLN zePECW@Q?S2zdg%G9X#ycUHI|eddUwQ=i9%#`>S8yso6agL{jG}b68p~dlH=fe&; z$L^IQ`jh9qNFx67%PJi7v*8w_j8Bx*I-9I+#8h7>=baqLl6jd$bW;~YW~n=Z^DiUn zB=YVcms%+#jHxSDRk-0<(abuXORxzZ;sDmo&jEo%4=y z2yW4+Z^s5M=~AU2=0y2PnuMOKQJ%bU)*j0YzL@R1K`MZ`)zHP;Qvy0+5!rfdj*k-U zdkD3pTis?J?4|f2-goK>nIz_d%+pW5uoy3|@(wx3T)hQTZEe(hIf(^}6q?UXqX~I< z`924I`!H5F`L=uQ5FPTEH$u3Ojr{1aLt8+)_~_UVPq^qfyh`ez+q-}{d8N7>s}4w~ z60RGD&={w#Fa%oIGQ114?ssGEwAsF^T}OU3PlaGS$ohmrl9?}GYLm$%_Zr&EZ+6#4@Jwr+WIKPHM)T3WG~m8JBz#!XHYs z4sB*Ceh-vizIGi!Al??8{jfF%iw#lj`c+Mmp(mUx*@%I9$_kdI_cSLUjdKO7Yp;<~ z$hu0b&2&J~!iDM;9%r(7AP7dsT?o%&VPMk9HK?TDL$Q}lLxt6=2B9}UzYqKT2GV$w zSc5x{Fm2mTqbAmr`@G~qWz;j#Jw4I+nW+tU!?brc2Db|OJyEcIBoPC?$W9YoAu z_9EJP*+SgZEc={{)Dwp&q-m@~%pMTydzaf9%6b;QK(Q9X5g~XWmdq?UrbIUt`qk-L zdRaF=XmzzMf`Kr@v<@ab4K*?M*lfh zeR=i%94owhGhV;2{UW|_D6ev%&298voHy%9sYk z?n!UKt*7->+&aNc=dReP%9b|cLsRr!xgvuZjT>3%2}j4|@AgE~Orzy$0Cnu8Kr6C& zr1&{3on!%s{mm=ik~}3TycUzea0{ePFzdmN1k7=!=Xz>p5qfQOM zv@#PT&_QdMM3=iQ0V%81h)tv)`}IMKgW*vfKqSyQb|hdAW3FVwC<87vI@UpTp{We3Qf+2ky#g?U9OHMm8Y?(*OiSY}zdC;m%AsXY@&QA8j z#2Q3bj^nUii#K$D!mT=^xRo#(kWO~1p&$|z3J%Mgpsa2HcDR4+9cDHWv30A1-UQWmm)Ci0B;d?~8X4kL zW~t`8aAp`tOsr7!2B6sez{iaaQ?9ZUGTuxk4aOe(nSfKr9_@vP5_*f^q&1R+X3lXK z|CN9JGQIM5aQU_C{uB20I#&4;B=kBs`x8F@pBIfbzy0gAw*2PnQ>`i3?9+MpQG<*F zH4Ki5=p%A2%cPQV{FvEr-E~Z~pSefIaYN}cb*Ju~=lDWfk*Hv&?T*9QYhIO@4EL53*&{79G1idUo+^A&zK^ZxPD^J7 zit-}6!u#`_+qf6CX@pUQCg2#2(~fjh*MDlhg8{>dCiQ&>y+WFL=GBh9!Xed#g=jNt zX;v)W;z5*_?*ntXImwo3=eSKtt~cqC?Iw7MVPL3Xs-m1Clwr5Bplz)}d^it8jD1CV zwhfdgQF>sgd_04bRm00WVXEGu4KEQ{={P9}r}59@Yd#8t@XCRw7y6uF-K!=@C&9u6JsBx$T?`&{QU$96`jI!bz;5PN3G8{r2O4&?Ll7Mp=wn#wRqD*qXG z4V=STUPrO5UdTvDbs8@I!uXwjBK)W^=hY4xI9qn`t3}`beRZ^Py_?32>=pTLm4i#o zw;dLevbY1tPpF)JJ;a@0+=7QQiDO@>j?X|mq%mcwUnDl}6~_w5`j@@xsJu>@?YY{2 zIR^VWW&ZDxGXK9rftuf*{A)OEhuTem`!LGl+2+}WG`vQxO1S(gU{m1ST_u?G(*3+Moh+tbP|F)29F;=AK`W*S}Z;3-+u_HZrG#WyPP=Er1#)U1`V2Es=8eO z!5QjJaUVE!asBwkE;XoCulQ{)HHbE!{66nwX=4~13Y0X1&%-BS2_TjwB?ckCe+4U_ zOb9~I1SzfW zaAZp?@4*V*c;8%TYyEEXZVYLTQy2Z#*d8j@smp&@kJKoj8ZKYL{yqDU-0V>?-QBVm#~sXw*mf~;hm%01|pt( zMM69z2C)Pl2c;l9#yjf39$~HHaDDkMuya?Z#|~6xjoWCKKx7zs68sOKe0KnEvL9}a zSf#Xxd~h5thjNI8-yrO@r^VlaAT}Hm{WTMMO+;FkxY7enHL?DgbbTAhY6q|e&#@!| zbuVI^Zyaj~sEi{%PatjRSEn1>WhV_89cn$!aQOmNeZ3*`x9#<%Rnn6#lO{+Bj)F?3lTpCHg5bSI@+u*1Wc8|s? z^B}3Vo!>Jx%Y|H3vP;R1<4oVI3XCjCiP#2g#N!X>#rU6|8~dyKXQjh?>cwc1B*hqDbp=ljF*NL zf(Zu7Gr`w1+}Ms0_5i5xiv9IOQw+&6YDeJJpm2LRAeESg^^?7-tl#R88eXg0+wWro zD1ZLr$b9k^ecO0*�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 SJm0<^-z<*$s^rVf`~MH7Oy!*b literal 0 HcmV?d00001 diff --git a/images/user-mgt.png b/images/user-mgt.png new file mode 100644 index 0000000000000000000000000000000000000000..7fb3fcd6924911e4539cceb151b9701fc50124e1 GIT binary patch literal 117563 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 IQ^3jp2OWIj!vFvP literal 0 HcmV?d00001 diff --git a/images/wansenai-logo.png b/images/wansenai-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1d9126382e1bb4b4ea8db27066e9137250435a6f GIT binary patch literal 7551 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 + + + + + + + <%= VITE_GLOB_APP_TITLE %> + + + +

    + +
    +
    + +
    + +
    +
    <%= VITE_GLOB_APP_TITLE %>
    +
    +
    +
    + + + \ No newline at end of file diff --git a/internal/.DS_Store b/internal/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9bf63cbf17c1d8b34075e154eb5b476efec409a3 GIT binary patch literal 6148 zcmeHK!Ab)$5S{3PtyS2g#~i$R=*{D{u6Ln7P}*uO?7D?k!Q0|L`3wGof8(3XAYFDN z#e+zhfti<`%p{WsNj5~}#?Ol(QA$KTC}VO8(;?i?+L9ynoB>@JO=*K2`-;80yMO0YVJAOeKQD{ra5AsTwG@B;xlc}6<@v0rW{Bm(X974Dk8jp^TYgEf|gtnD7JuCU6Hq zo8JX6k#ehrlNj}Ds^loh}j_+CzokCeSt`-a_FnS$_24BS& a&>-mZ+yG{ZwIDnY`w<8 { + const root = process.cwd(); + const isBuild = command === 'build'; + const { VITE_PUBLIC_PATH, VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_ENABLE_ANALYZE } = loadEnv( + mode, + root, + ); + + const defineData = await createDefineData(root); + const plugins = await createPlugins({ + isBuild, + root, + enableAnalyze: VITE_ENABLE_ANALYZE === 'true', + enableMock: VITE_USE_MOCK === 'true', + compress: VITE_BUILD_COMPRESS, + }); + + const pathResolve = (pathname: string) => resolve(root, '.', pathname); + const timestamp = new Date().getTime(); + const applicationConfig: UserConfig = { + base: VITE_PUBLIC_PATH, + resolve: { + alias: [ + { + find: 'vue-i18n', + replacement: 'vue-i18n/dist/vue-i18n.cjs.js', + }, + // @/xxxx => src/xxxx + { + find: /@\//, + replacement: pathResolve('src') + '/', + }, + // #/xxxx => types/xxxx + { + find: /#\//, + replacement: pathResolve('types') + '/', + }, + ], + }, + define: defineData, + build: { + target: 'es2015', + cssTarget: 'chrome80', + rollupOptions: { + output: { + // 入口文件名 + entryFileNames: `assets/entry/[name]-[hash]-${timestamp}.js`, + manualChunks: { + vue: ['vue', 'pinia', 'vue-router'], + antd: ['ant-design-vue', '@ant-design/icons-vue'], + }, + }, + }, + }, + css: { + preprocessorOptions: { + less: { + modifyVars: generateModifyVars(), + javascriptEnabled: true, + }, + }, + }, + plugins, + }; + + const mergedConfig = mergeConfig(commonConfig(mode), applicationConfig); + + return mergeConfig(mergedConfig, overrides); + }); +} + +async function createDefineData(root: string) { + try { + const pkgJson = await readPackageJSON(root); + const { dependencies, devDependencies, name, version } = pkgJson; + + const __APP_INFO__ = { + pkg: { dependencies, devDependencies, name, version }, + lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), + }; + return { + __APP_INFO__: JSON.stringify(__APP_INFO__), + }; + } catch (error) { + return {}; + } +} + +export { defineApplicationConfig }; \ No newline at end of file diff --git a/internal/vite-config/src/config/common.ts b/internal/vite-config/src/config/common.ts new file mode 100644 index 0000000..5b9de59 --- /dev/null +++ b/internal/vite-config/src/config/common.ts @@ -0,0 +1,22 @@ +import UnoCSS from 'unocss/vite'; +import { type UserConfig } from 'vite'; + +const commonConfig: (mode: string) => UserConfig = (mode) => ({ + server: { + host: true, + }, + esbuild: { + drop: mode === 'production' ? ['console', 'debugger'] : [], + }, + build: { + reportCompressedSize: false, + chunkSizeWarningLimit: 1500, + rollupOptions: { + // TODO: Prevent memory overflow + maxParallelFileOps: 3, + }, + }, + plugins: [UnoCSS()], +}); + +export { commonConfig }; \ No newline at end of file diff --git a/internal/vite-config/src/config/package.ts b/internal/vite-config/src/config/package.ts new file mode 100644 index 0000000..6964b63 --- /dev/null +++ b/internal/vite-config/src/config/package.ts @@ -0,0 +1,42 @@ +import { readPackageJSON } from 'pkg-types'; +import { defineConfig, mergeConfig, type UserConfig } from 'vite'; +import dts from 'vite-plugin-dts'; + +import { commonConfig } from './common'; + +interface DefineOptions { + overrides?: UserConfig; + options?: { + // + }; +} + +function definePackageConfig(defineOptions: DefineOptions = {}) { + const { overrides = {} } = defineOptions; + const root = process.cwd(); + return defineConfig(async ({ mode }) => { + const { dependencies = {}, peerDependencies = {} } = await readPackageJSON(root); + const packageConfig: UserConfig = { + build: { + lib: { + entry: 'src/index.ts', + formats: ['es'], + fileName: () => 'index.mjs', + }, + rollupOptions: { + external: [...Object.keys(dependencies), ...Object.keys(peerDependencies)], + }, + }, + plugins: [ + dts({ + logLevel: 'error', + }), + ], + }; + const mergedConfig = mergeConfig(commonConfig(mode), packageConfig); + + return mergeConfig(mergedConfig, overrides); + }); +} + +export { definePackageConfig }; \ No newline at end of file diff --git a/internal/vite-config/src/index.ts b/internal/vite-config/src/index.ts new file mode 100644 index 0000000..c3844d4 --- /dev/null +++ b/internal/vite-config/src/index.ts @@ -0,0 +1,2 @@ +export * from './config/application'; +export * from './config/package'; \ No newline at end of file diff --git a/internal/vite-config/src/plugins/appConfig.ts b/internal/vite-config/src/plugins/appConfig.ts new file mode 100644 index 0000000..cd94afc --- /dev/null +++ b/internal/vite-config/src/plugins/appConfig.ts @@ -0,0 +1,104 @@ +import colors from 'picocolors'; +import { readPackageJSON } from 'pkg-types'; +import { type PluginOption } from 'vite'; + +import { getEnvConfig } from '../utils/env'; +import { createContentHash } from '../utils/hash'; + +const GLOBAL_CONFIG_FILE_NAME = '_app.config.js'; +const PLUGIN_NAME = 'app-config'; + +async function createAppConfigPlugin({ + root, + isBuild, + }: { + root: string; + isBuild: boolean; +}): Promise { + let publicPath: string; + let source: string; + if (!isBuild) { + return { + name: PLUGIN_NAME, + }; + } + const { version = '' } = await readPackageJSON(root); + + return { + name: PLUGIN_NAME, + async configResolved(_config) { + const appTitle = _config?.env?.VITE_GLOB_APP_TITLE ?? ''; + // appTitle = appTitle.replace(/\s/g, '_').replace(/-/g, '_'); + publicPath = _config.base; + source = await getConfigSource(appTitle); + }, + async transformIndexHtml(html) { + publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/`; + + const appConfigSrc = `${ + publicPath || '/' + }${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}`; + + return { + html, + tags: [ + { + tag: 'script', + attrs: { + src: appConfigSrc, + }, + }, + ], + }; + }, + async generateBundle() { + try { + this.emitFile({ + type: 'asset', + fileName: GLOBAL_CONFIG_FILE_NAME, + source, + }); + + console.log(colors.cyan(`✨configuration file is build successfully!`)); + } catch (error) { + console.log( + colors.red('configuration file configuration file failed to package:\n' + error), + ); + } + }, + }; +} + +/** + * Get the configuration file variable name + * @param env + */ +const getVariableName = (title: string) => { + function strToHex(str: string) { + const result: string[] = []; + for (let i = 0; i < str.length; ++i) { + const hex = str.charCodeAt(i).toString(16); + result.push(('000' + hex).slice(-4)); + } + return result.join('').toUpperCase(); + } + return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, ''); +}; + +async function getConfigSource(appTitle: string) { + const config = await getEnvConfig(); + const variableName = getVariableName(appTitle); + const windowVariable = `window.${variableName}`; + // Ensure that the variable will not be modified + let source = `${windowVariable}=${JSON.stringify(config)};`; + source += ` + Object.freeze(${windowVariable}); + Object.defineProperty(window, "${variableName}", { + configurable: false, + writable: false, + }); + `.replace(/\s/g, ''); + return source; +} + +export { createAppConfigPlugin }; \ No newline at end of file diff --git a/internal/vite-config/src/plugins/compress.ts b/internal/vite-config/src/plugins/compress.ts new file mode 100644 index 0000000..0c1f8e2 --- /dev/null +++ b/internal/vite-config/src/plugins/compress.ts @@ -0,0 +1,38 @@ +/** + * Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated + * https://github.com/anncwb/vite-plugin-compression + */ +import type { PluginOption } from 'vite'; +import compressPlugin from 'vite-plugin-compression'; + +export function configCompressPlugin({ + compress, + deleteOriginFile = false, + }: { + compress: string; + deleteOriginFile?: boolean; +}): PluginOption[] { + const compressList = compress.split(','); + + const plugins: PluginOption[] = []; + + if (compressList.includes('gzip')) { + plugins.push( + compressPlugin({ + ext: '.gz', + deleteOriginFile, + }), + ); + } + + if (compressList.includes('brotli')) { + plugins.push( + compressPlugin({ + ext: '.br', + algorithm: 'brotliCompress', + deleteOriginFile, + }), + ); + } + return plugins; +} \ No newline at end of file diff --git a/internal/vite-config/src/plugins/html.ts b/internal/vite-config/src/plugins/html.ts new file mode 100644 index 0000000..7f34a6a --- /dev/null +++ b/internal/vite-config/src/plugins/html.ts @@ -0,0 +1,13 @@ +/** + * Plugin to minimize and use ejs template syntax in index.html. + * https://github.com/anncwb/vite-plugin-html + */ +import type { PluginOption } from 'vite'; +import { createHtmlPlugin } from 'vite-plugin-html'; + +export function configHtmlPlugin({ isBuild }: { isBuild: boolean }) { + const htmlPlugin: PluginOption[] = createHtmlPlugin({ + minify: isBuild, + }); + return htmlPlugin; +} \ No newline at end of file diff --git a/internal/vite-config/src/plugins/index.ts b/internal/vite-config/src/plugins/index.ts new file mode 100644 index 0000000..c346393 --- /dev/null +++ b/internal/vite-config/src/plugins/index.ts @@ -0,0 +1,59 @@ +import vue from '@vitejs/plugin-vue'; +import vueJsx from '@vitejs/plugin-vue-jsx'; +import { type PluginOption } from 'vite'; +import purgeIcons from 'vite-plugin-purge-icons'; + +import { createAppConfigPlugin } from './appConfig'; +import { configCompressPlugin } from './compress'; +import { configHtmlPlugin } from './html'; +import { configMockPlugin } from './mock'; +import { configSvgIconsPlugin } from './svgSprite'; +import { configVisualizerConfig } from './visualizer'; + +interface Options { + isBuild: boolean; + root: string; + compress: string; + enableMock?: boolean; + enableAnalyze?: boolean; +} + +async function createPlugins({ isBuild, root, enableMock, compress, enableAnalyze }: Options) { + const vitePlugins: (PluginOption | PluginOption[])[] = [vue(), vueJsx()]; + + const appConfigPlugin = await createAppConfigPlugin({ root, isBuild }); + vitePlugins.push(appConfigPlugin); + + // vite-plugin-html + vitePlugins.push(configHtmlPlugin({ isBuild })); + + // vite-plugin-svg-icons + vitePlugins.push(configSvgIconsPlugin({ isBuild })); + + // vite-plugin-purge-icons + vitePlugins.push(purgeIcons()); + + // The following plugins only work in the production environment + if (isBuild) { + // rollup-plugin-gzip + vitePlugins.push( + configCompressPlugin({ + compress, + }), + ); + } + + // rollup-plugin-visualizer + if (enableAnalyze) { + vitePlugins.push(configVisualizerConfig()); + } + + // vite-plugin-mock + if (enableMock) { + vitePlugins.push(configMockPlugin({ isBuild })); + } + + return vitePlugins; +} + +export { createPlugins }; \ No newline at end of file diff --git a/internal/vite-config/src/plugins/mock.ts b/internal/vite-config/src/plugins/mock.ts new file mode 100644 index 0000000..88398ab --- /dev/null +++ b/internal/vite-config/src/plugins/mock.ts @@ -0,0 +1,19 @@ +/** + * Mock plugin for development and production. + * https://github.com/anncwb/vite-plugin-mock + */ +import { viteMockServe } from 'vite-plugin-mock'; + +export function configMockPlugin({ isBuild }: { isBuild: boolean }) { + return viteMockServe({ + ignore: /^_/, + mockPath: 'mock', + localEnabled: !isBuild, + prodEnabled: isBuild, + injectCode: ` + import { setupProdMockServer } from '../mock/_createProductionServer'; + + setupProdMockServer(); + `, + }); +} \ No newline at end of file diff --git a/internal/vite-config/src/plugins/svgSprite.ts b/internal/vite-config/src/plugins/svgSprite.ts new file mode 100644 index 0000000..17a72d2 --- /dev/null +++ b/internal/vite-config/src/plugins/svgSprite.ts @@ -0,0 +1,17 @@ +/** + * Vite Plugin for fast creating SVG sprites. + * https://github.com/anncwb/vite-plugin-svg-icons + */ + +import { resolve } from 'node:path'; + +import type { PluginOption } from 'vite'; +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'; + +export function configSvgIconsPlugin({ isBuild }: { isBuild: boolean }) { + const svgIconsPlugin = createSvgIconsPlugin({ + iconDirs: [resolve(process.cwd(), 'src/assets/icons')], + svgoOptions: isBuild, + }); + return svgIconsPlugin as PluginOption; +} \ No newline at end of file diff --git a/internal/vite-config/src/plugins/visualizer.ts b/internal/vite-config/src/plugins/visualizer.ts new file mode 100644 index 0000000..ed2b339 --- /dev/null +++ b/internal/vite-config/src/plugins/visualizer.ts @@ -0,0 +1,14 @@ +/** + * Package file volume analysis + */ +import visualizer from 'rollup-plugin-visualizer'; +import { type PluginOption } from 'vite'; + +export function configVisualizerConfig() { + return visualizer({ + filename: './node_modules/.cache/visualizer/stats.html', + open: true, + gzipSize: true, + brotliSize: true, + }) as PluginOption; +} \ No newline at end of file diff --git a/internal/vite-config/src/utils/env.ts b/internal/vite-config/src/utils/env.ts new file mode 100644 index 0000000..1d266c1 --- /dev/null +++ b/internal/vite-config/src/utils/env.ts @@ -0,0 +1,49 @@ +import { join } from 'node:path'; + +import dotenv from 'dotenv'; +import { readFile } from 'fs-extra'; + +/** + * 获取当前环境下生效的配置文件名 + */ +function getConfFiles() { + const script = process.env.npm_lifecycle_script as string; + const reg = new RegExp('--mode ([a-z_\\d]+)'); + const result = reg.exec(script); + if (result) { + const mode = result[1]; + return ['.env', `.env.${mode}`]; + } + return ['.env', '.env.production']; +} + +/** + * Get the environment variables starting with the specified prefix + * @param match prefix + * @param confFiles ext + */ +export async function getEnvConfig( + match = 'VITE_GLOB_', + confFiles = getConfFiles(), +): Promise<{ + [key: string]: string; +}> { + let envConfig = {}; + + for (const confFile of confFiles) { + try { + const envPath = await readFile(join(process.cwd(), confFile), { encoding: 'utf8' }); + const env = dotenv.parse(envPath); + envConfig = { ...envConfig, ...env }; + } catch (e) { + console.error(`Error in parsing ${confFile}`, e); + } + } + const reg = new RegExp(`^(${match})`); + Object.keys(envConfig).forEach((key) => { + if (!reg.test(key)) { + Reflect.deleteProperty(envConfig, key); + } + }); + return envConfig; +} \ No newline at end of file diff --git a/internal/vite-config/src/utils/hash.ts b/internal/vite-config/src/utils/hash.ts new file mode 100644 index 0000000..f1d7f62 --- /dev/null +++ b/internal/vite-config/src/utils/hash.ts @@ -0,0 +1,16 @@ +import { createHash } from 'node:crypto'; + +function createContentHash(content: string, hashLSize = 12) { + const hash = createHash('sha256').update(content); + return hash.digest('hex').slice(0, hashLSize); +} +function strToHex(str: string) { + const result: string[] = []; + for (let i = 0; i < str.length; ++i) { + const hex = str.charCodeAt(i).toString(16); + result.push(('000' + hex).slice(-4)); + } + return result.join('').toUpperCase(); +} + +export { createContentHash, strToHex }; \ No newline at end of file diff --git a/internal/vite-config/src/utils/modifyVars.ts b/internal/vite-config/src/utils/modifyVars.ts new file mode 100644 index 0000000..1e93e09 --- /dev/null +++ b/internal/vite-config/src/utils/modifyVars.ts @@ -0,0 +1,47 @@ +import { resolve } from 'node:path'; + +import { generate } from '@ant-design/colors'; +// @ts-ignore: typo +/* import { getThemeVariables } from 'ant-design-vue/dist/theme'; */ +import { theme } from 'ant-design-vue/lib'; +import convertLegacyToken from 'ant-design-vue/lib/theme/convertLegacyToken'; + +const { defaultAlgorithm, defaultSeed } = theme; +const primaryColor = '#0960bd'; + +function generateAntColors(color: string, theme: 'default' | 'dark' = 'default') { + return generate(color, { + theme, + }); +} + +/** + * less global variable + */ +export function generateModifyVars() { + const palettes = generateAntColors(primaryColor); + const primary = palettes[5]; + const primaryColorObj: Record = {}; + + for (let index = 0; index < 10; index++) { + primaryColorObj[`primary-${index + 1}`] = palettes[index]; + } + // const modifyVars = getThemeVariables(); + const mapToken = defaultAlgorithm(defaultSeed); + const v3Token = convertLegacyToken(mapToken); + return { + ...v3Token, + // reference: Avoid repeated references + hack: `true; @import (reference) "${resolve('src/design/config.less')}";`, + 'primary-color': primary, + ...primaryColorObj, + 'info-color': primary, + 'processing-color': primary, + 'success-color': '#55D187', // Success color + 'error-color': '#ED6F6F', // False color + 'warning-color': '#EFBD47', // Warning color + 'font-size-base': '14px', // Main font size + 'border-radius-base': '2px', // Component/float fillet + 'link-color': primary, // Link color + }; +} \ No newline at end of file diff --git a/internal/vite-config/tsconfig.json b/internal/vite-config/tsconfig.json new file mode 100644 index 0000000..cd27063 --- /dev/null +++ b/internal/vite-config/tsconfig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/ts-config/node.json", + "include": ["src"] +} diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..395501f --- /dev/null +++ b/nginx.conf @@ -0,0 +1,33 @@ +#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; + server { + listen 80; + location / { + root /usr/share/nginx/html/dist; + 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; + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..17058c0 --- /dev/null +++ b/package.json @@ -0,0 +1,155 @@ +{ + "name": "eairp-web", + "version": "1.0.1", + "homepage": "https://github.com/wansenai/wansen-erp-ui", + "bugs": { + "url": "https://github.com/wansenai/wansen-erp-ui/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/wansenai/wansen-erp-ui.git" + }, + "license": "MIT And Apache-2.0", + "author": { + "name": "Wansen AI Team", + "email": "hi@wansenai.com", + "url": "https://github.com/wansenai" + }, + "scripts": { + "bootstrap": "pnpm install", + "build": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build", + "build:analyze": "cross-env NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build --mode analyze", + "build:no-cache": "pnpm store prune && npm run build", + "build:test": "cross-env NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build --mode test", + "build:docker": "vite build --mode docker", + "commit": "czg", + "dev": "pnpm vite", + "preinstall": "npx only-allow pnpm", + "postinstall": "turbo run stub", + "lint": "turbo run lint", + "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", + "lint:prettier": "prettier --write .", + "lint:stylelint": "stylelint \"**/*.{vue,css,less.scss}\" --fix --cache --cache-location node_modules/.cache/stylelint/", + "preview": "npm run build && vite preview", + "reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap", + "serve": "npm run dev", + "test:gzip": "npx http-server dist --cors --gzip -c-1", + "type:check": "vue-tsc --noEmit --skipLibCheck" + }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": [ + "eslint --fix", + "prettier --write" + ], + "{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [ + "prettier --write--parser json" + ], + "package.json": [ + "prettier --write" + ], + "*.vue": [ + "eslint --fix", + "prettier --write", + "stylelint --fix" + ], + "*.{scss,less,styl,html}": [ + "stylelint --fix", + "prettier --write" + ], + "*.md": [ + "prettier --write" + ] + }, + "config": { + "commitizen": { + "path": "node_modules/cz-git" + } + }, + "dependencies": { + "@ant-design/icons-vue": "^7.0.1", + "@axolo/tree-array": "^0.1.0", + "@iconify/iconify": "^3.1.1", + "@logicflow/core": "^1.2.26", + "@logicflow/extension": "^1.2.26", + "@vben/hooks": "workspace:*", + "@vue/shared": "^3.4.25", + "@vueuse/core": "^10.9.0", + "@vueuse/shared": "^10.9.0", + "@zxcvbn-ts/core": "^3.0.4", + "ant-design-vue": "^4.2.1", + "axios": "^1.6.8", + "codemirror": "^5.65.16", + "cropperjs": "^1.6.2", + "crypto-js": "^4.2.0", + "dayjs": "^1.11.10", + "echarts": "^5.5.0", + "exceljs": "^4.4.0", + "lodash-es": "^4.17.21", + "mockjs": "^1.1.0", + "nprogress": "^0.2.0", + "path-to-regexp": "^6.2.2", + "pinia": "2.1.7", + "pinia-plugin-persistedstate": "^3.2.1", + "print-js": "^1.6.0", + "qrcode": "^1.5.3", + "qs": "^6.12.1", + "resize-observer-polyfill": "^1.5.1", + "showdown": "^2.1.0", + "sortablejs": "^1.15.2", + "tinymce": "^5.10.9", + "unocss": "^0.59.4", + "vditor": "^3.10.4", + "vue": "^3.4.25", + "vue-i18n": "^9.13.1", + "vue-json-pretty": "^2.4.0", + "vue-router": "^4.3.2", + "vue-types": "^5.1.1", + "vuedraggable": "^4.1.0", + "vxe-table": "^4.6.3", + "vxe-table-plugin-export-xlsx": "^4.0.1", + "xe-utils": "^3.5.25", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@commitlint/cli": "^19.3.0", + "@commitlint/config-conventional": "^19.2.2", + "@iconify/json": "^2.2.203", + "@purge-icons/generated": "^0.10.0", + "@types/codemirror": "^5.60.15", + "@types/crypto-js": "^4.2.2", + "@types/lodash-es": "^4.17.12", + "@types/mockjs": "^1.0.10", + "@types/nprogress": "^0.2.3", + "@types/qrcode": "^1.5.5", + "@types/qs": "^6.9.15", + "@types/showdown": "^2.0.6", + "@types/sortablejs": "^1.15.8", + "@vben/stylelint-config": "workspace:*", + "@vben/ts-config": "workspace:*", + "@vben/types": "workspace:*", + "@vben/vite-config": "workspace:*", + "@vue/compiler-sfc": "^3.4.25", + "@vue/test-utils": "^2.4.5", + "conventional-changelog-cli": "^4.1.0", + "cross-env": "^7.0.3", + "cz-git": "^1.9.1", + "czg": "^1.9.1", + "husky": "^9.0.11", + "lint-staged": "15.2.2", + "prettier": "^3.2.5", + "prettier-plugin-packagejson": "^2.5.0", + "rimraf": "^5.0.5", + "turbo": "^1.13.2", + "typescript": "^5.4.5", + "unbuild": "^2.0.0", + "vite": "^5.2.10", + "vite-plugin-mock": "^2.9.6", + "vite-plugin-vue-inspector": "^5.0.1", + "vue-tsc": "^2.0.14" + }, + "packageManager": "pnpm@9.1.2", + "engines": { + "node": ">=18.12.0", + "pnpm": ">=9.0.2" + } +} diff --git a/packages/.DS_Store b/packages/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0629b09d2d5ec851f68c688ee72193d6aa196c7c GIT binary patch literal 6148 zcmeHKK~BR!475uTMO=D99QVKndPCx}l<1ZsPIB>)X+n}{>gQB zceH++U#F4!ZA7>JTI#zv1I~am@ZT6f&lZ`TDY|tAoB?N`Wk9|U0V)^`vts#lz?2aH zIEA|i)-p>-PB4sySrI!B)>NRTvW*z5>F@`Oi-uWI(}`{PV5`hFp>U~=>xU9f92MO< z1I|E~fg?SgOaH$cpZ~i_e&!4~1AmGEo>r@BiCePXI=DIMwE?<@ibz~mY*Vl(tr)S= ciZ7r=;199@M#HQK55#{23Jq?Yfgfey6AS%6?*IS* literal 0 HcmV?d00001 diff --git a/packages/hooks/.eslintrc.js b/packages/hooks/.eslintrc.js new file mode 100644 index 0000000..cd27a19 --- /dev/null +++ b/packages/hooks/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['@vben/eslint-config/strict'], +}; diff --git a/packages/hooks/build.config.ts b/packages/hooks/build.config.ts new file mode 100644 index 0000000..20c8b54 --- /dev/null +++ b/packages/hooks/build.config.ts @@ -0,0 +1,10 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + entries: ['src/index'], + declaration: true, + rollup: { + emitCJS: true, + }, +}); diff --git a/packages/hooks/package.json b/packages/hooks/package.json new file mode 100644 index 0000000..d5ac172 --- /dev/null +++ b/packages/hooks/package.json @@ -0,0 +1,29 @@ +{ + "name": "@vben/hooks", + "version": "1.0.0", + "license": "MIT", + "sideEffects": false, + "exports": { + ".": { + "default": "./src/index.ts" + } + }, + "main": "./src/index.ts", + "module": "./src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "//build": "pnpm unbuild", + "//stub": "pnpm unbuild --stub", + "clean": "pnpm rimraf node_modules dist", + "lint": "pnpm eslint ." + }, + "dependencies": { + "@vueuse/core": "^9.13.0", + "vue": "^3.2.47" + }, + "devDependencies": { + "@vben/types": "workspace:*" + } +} diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts new file mode 100644 index 0000000..71fb0c5 --- /dev/null +++ b/packages/hooks/src/index.ts @@ -0,0 +1,6 @@ +export * from './onMountedOrActivated'; +export * from './useAttrs'; +export * from './useRefs'; +export * from './useScrollTo'; +export * from './useWindowSizeFn'; +export { useTimeoutFn } from '@vueuse/core'; diff --git a/packages/hooks/src/onMountedOrActivated.ts b/packages/hooks/src/onMountedOrActivated.ts new file mode 100644 index 0000000..53a3c5e --- /dev/null +++ b/packages/hooks/src/onMountedOrActivated.ts @@ -0,0 +1,25 @@ +import { type AnyFunction } from '@vben/types'; +import { nextTick, onActivated, onMounted } from 'vue'; + +/** + * 在 OnMounted 或者 OnActivated 时触发 + * @param hook 任何函数(包括异步函数) + */ +function onMountedOrActivated(hook: AnyFunction) { + let mounted: boolean; + + onMounted(() => { + hook(); + nextTick(() => { + mounted = true; + }); + }); + + onActivated(() => { + if (mounted) { + hook(); + } + }); +} + +export { onMountedOrActivated }; diff --git a/packages/hooks/src/useAttrs.ts b/packages/hooks/src/useAttrs.ts new file mode 100644 index 0000000..df2118d --- /dev/null +++ b/packages/hooks/src/useAttrs.ts @@ -0,0 +1,43 @@ +import { type Recordable } from '@vben/types'; +import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue'; + +interface UseAttrsOptions { + excludeListeners?: boolean; + excludeKeys?: string[]; + excludeDefaultKeys?: boolean; +} + +const DEFAULT_EXCLUDE_KEYS = ['class', 'style']; +const LISTENER_PREFIX = /^on[A-Z]/; + +function entries(obj: Recordable): [string, T][] { + return Object.keys(obj).map((key: string) => [key, obj[key]]); +} + +function useAttrs(options: UseAttrsOptions = {}): Recordable { + const instance = getCurrentInstance(); + if (!instance) return {}; + + const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = options; + const attrs = shallowRef({}); + const allExcludeKeys = excludeKeys.concat(excludeDefaultKeys ? DEFAULT_EXCLUDE_KEYS : []); + + // Since attrs are not reactive, make it reactive instead of doing in `onUpdated` hook for better performance + instance.attrs = reactive(instance.attrs); + + watchEffect(() => { + const res = entries(instance.attrs).reduce((acm, [key, val]) => { + if (!allExcludeKeys.includes(key) && !(excludeListeners && LISTENER_PREFIX.test(key))) { + acm[key] = val; + } + + return acm; + }, {} as Recordable); + + attrs.value = res; + }); + + return attrs; +} + +export { useAttrs, type UseAttrsOptions }; diff --git a/packages/hooks/src/useRefs.ts b/packages/hooks/src/useRefs.ts new file mode 100644 index 0000000..97f1b4b --- /dev/null +++ b/packages/hooks/src/useRefs.ts @@ -0,0 +1,24 @@ +import type { Ref } from 'vue'; +import { onBeforeUpdate, shallowRef } from 'vue'; + +function useRefs(): { + refs: Ref; + setRefs: (index: number) => (el: HTMLElement) => void; +} { + const refs = shallowRef([]) as Ref; + + onBeforeUpdate(() => { + refs.value = []; + }); + + const setRefs = (index: number) => (el: HTMLElement) => { + refs.value[index] = el; + }; + + return { + refs, + setRefs, + }; +} + +export { useRefs }; diff --git a/packages/hooks/src/useScrollTo.ts b/packages/hooks/src/useScrollTo.ts new file mode 100644 index 0000000..f6a95f4 --- /dev/null +++ b/packages/hooks/src/useScrollTo.ts @@ -0,0 +1,60 @@ +import { shallowRef, unref } from 'vue'; + +interface UseScrollToOptions { + el: any; + to: number; + duration?: number; + callback?: () => any; +} + +function easeInOutQuad(t: number, b: number, c: number, d: number) { + t /= d / 2; + if (t < 1) { + return (c / 2) * t * t + b; + } + t--; + return (-c / 2) * (t * (t - 2) - 1) + b; +} + +function move(el: HTMLElement, amount: number) { + el.scrollTop = amount; +} + +const position = (el: HTMLElement) => { + return el.scrollTop; +}; +function useScrollTo({ el, to, duration = 500, callback }: UseScrollToOptions) { + const isActiveRef = shallowRef(false); + const start = position(el); + const change = to - start; + const increment = 20; + let currentTime = 0; + + const animateScroll = function () { + if (!unref(isActiveRef)) { + return; + } + currentTime += increment; + const val = easeInOutQuad(currentTime, start, change, duration); + move(el, val); + if (currentTime < duration && unref(isActiveRef)) { + requestAnimationFrame(animateScroll); + } else { + if (callback && typeof callback === 'function') { + callback(); + } + } + }; + const run = () => { + isActiveRef.value = true; + animateScroll(); + }; + + const stop = () => { + isActiveRef.value = false; + }; + + return { start: run, stop }; +} + +export { useScrollTo, type UseScrollToOptions }; diff --git a/packages/hooks/src/useWindowSizeFn.ts b/packages/hooks/src/useWindowSizeFn.ts new file mode 100644 index 0000000..d8e7710 --- /dev/null +++ b/packages/hooks/src/useWindowSizeFn.ts @@ -0,0 +1,40 @@ +import { type AnyFunction } from '@vben/types'; +import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core'; + +interface UseWindowSizeOptions { + wait?: number; + once?: boolean; + immediate?: boolean; + listenerOptions?: AddEventListenerOptions | boolean; +} + +function useWindowSizeFn(fn: AnyFunction, options: UseWindowSizeOptions = {}) { + const { wait = 150, immediate } = options; + let handler = () => { + fn(); + }; + const handleSize = useDebounceFn(handler, wait); + handler = handleSize; + + const start = () => { + if (immediate) { + handler(); + } + window.addEventListener('resize', handler); + }; + + const stop = () => { + window.removeEventListener('resize', handler); + }; + + tryOnMounted(() => { + start(); + }); + + tryOnUnmounted(() => { + stop(); + }); + return { start, stop }; +} + +export { useWindowSizeFn, type UseWindowSizeOptions }; diff --git a/packages/hooks/tsconfig.json b/packages/hooks/tsconfig.json new file mode 100644 index 0000000..8508d50 --- /dev/null +++ b/packages/hooks/tsconfig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/ts-config/vue-app.json", + "include": ["src"] +} diff --git a/packages/types/.eslintrc.js b/packages/types/.eslintrc.js new file mode 100644 index 0000000..cd27a19 --- /dev/null +++ b/packages/types/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['@vben/eslint-config/strict'], +}; diff --git a/packages/types/build.config.ts b/packages/types/build.config.ts new file mode 100644 index 0000000..20c8b54 --- /dev/null +++ b/packages/types/build.config.ts @@ -0,0 +1,10 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + entries: ['src/index'], + declaration: true, + rollup: { + emitCJS: true, + }, +}); diff --git a/packages/types/package.json b/packages/types/package.json new file mode 100644 index 0000000..14f89b2 --- /dev/null +++ b/packages/types/package.json @@ -0,0 +1,22 @@ +{ + "name": "@vben/types", + "version": "1.0.0", + "license": "MIT", + "sideEffects": false, + "exports": { + ".": { + "default": "./src/index.ts" + } + }, + "main": "./src/index.ts", + "module": "./src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "//build": "pnpm unbuild", + "//stub": "pnpm unbuild --stub", + "clean": "pnpm rimraf node_modules dist", + "lint": "pnpm eslint ." + } +} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts new file mode 100644 index 0000000..04bca77 --- /dev/null +++ b/packages/types/src/index.ts @@ -0,0 +1 @@ +export * from './utils'; diff --git a/packages/types/src/utils.ts b/packages/types/src/utils.ts new file mode 100644 index 0000000..80435fc --- /dev/null +++ b/packages/types/src/utils.ts @@ -0,0 +1,58 @@ +/** + * 任意类型的异步函数 + */ +type AnyPromiseFunction = (...arg: any[]) => PromiseLike; + +/** + * 任意类型的普通函数 + */ +type AnyNormalFunction = (...arg: any[]) => any; + +/** + * 任意类型的函数 + */ +type AnyFunction = AnyNormalFunction | AnyPromiseFunction; + +/** + * T | null 包装 + */ +type Nullable = T | null; + +/** + * T | Not null 包装 + */ +type NonNullable = T extends null | undefined ? never : T; + +/** + * 字符串类型对象 + */ +type Recordable = Record; + +/** + * 字符串类型对象(只读) + */ +interface ReadonlyRecordable { + readonly [key: string]: T; +} + +/** + * setTimeout 返回值类型 + */ +type TimeoutHandle = ReturnType; + +/** + * setInterval 返回值类型 + */ +type IntervalHandle = ReturnType; + +export { + type AnyFunction, + type AnyNormalFunction, + type AnyPromiseFunction, + type IntervalHandle, + type NonNullable, + type Nullable, + type ReadonlyRecordable, + type Recordable, + type TimeoutHandle, +}; diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json new file mode 100644 index 0000000..8508d50 --- /dev/null +++ b/packages/types/tsconfig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/ts-config/vue-app.json", + "include": ["src"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..21f3fd7 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,12718 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@ant-design/icons-vue': + specifier: ^7.0.1 + version: 7.0.1(vue@3.4.25(typescript@5.4.5)) + '@axolo/tree-array': + specifier: ^0.1.0 + version: 0.1.0 + '@iconify/iconify': + specifier: ^3.1.1 + version: 3.1.1 + '@logicflow/core': + specifier: ^1.2.26 + version: 1.2.26 + '@logicflow/extension': + specifier: ^1.2.26 + version: 1.2.26(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5)) + '@vben/hooks': + specifier: workspace:* + version: link:packages/hooks + '@vue/shared': + specifier: ^3.4.25 + version: 3.4.25 + '@vueuse/core': + specifier: ^10.9.0 + version: 10.9.0(vue@3.4.25(typescript@5.4.5)) + '@vueuse/shared': + specifier: ^10.9.0 + version: 10.9.0(vue@3.4.25(typescript@5.4.5)) + '@zxcvbn-ts/core': + specifier: ^3.0.4 + version: 3.0.4 + ant-design-vue: + specifier: ^4.2.1 + version: 4.2.1(vue@3.4.25(typescript@5.4.5)) + axios: + specifier: ^1.6.8 + version: 1.6.8 + codemirror: + specifier: ^5.65.16 + version: 5.65.16 + cropperjs: + specifier: ^1.6.2 + version: 1.6.2 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + dayjs: + specifier: ^1.11.10 + version: 1.11.11 + echarts: + specifier: ^5.5.0 + version: 5.5.0 + exceljs: + specifier: ^4.4.0 + version: 4.4.0 + lodash-es: + specifier: ^4.17.21 + version: 4.17.21 + mockjs: + specifier: ^1.1.0 + version: 1.1.0 + nprogress: + specifier: ^0.2.0 + version: 0.2.0 + path-to-regexp: + specifier: ^6.2.2 + version: 6.2.2 + pinia: + specifier: 2.1.7 + version: 2.1.7(typescript@5.4.5)(vue@3.4.25(typescript@5.4.5)) + pinia-plugin-persistedstate: + specifier: ^3.2.1 + version: 3.2.1(pinia@2.1.7(typescript@5.4.5)(vue@3.4.25(typescript@5.4.5))) + print-js: + specifier: ^1.6.0 + version: 1.6.0 + qrcode: + specifier: ^1.5.3 + version: 1.5.3 + qs: + specifier: ^6.12.1 + version: 6.12.1 + resize-observer-polyfill: + specifier: ^1.5.1 + version: 1.5.1 + showdown: + specifier: ^2.1.0 + version: 2.1.0 + sortablejs: + specifier: ^1.15.2 + version: 1.15.2 + tinymce: + specifier: ^5.10.9 + version: 5.10.9 + unocss: + specifier: ^0.59.4 + version: 0.59.4(postcss@8.4.38)(rollup@3.28.1)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + vditor: + specifier: ^3.10.4 + version: 3.10.4 + vue: + specifier: ^3.4.25 + version: 3.4.25(typescript@5.4.5) + vue-i18n: + specifier: ^9.13.1 + version: 9.13.1(vue@3.4.25(typescript@5.4.5)) + vue-json-pretty: + specifier: ^2.4.0 + version: 2.4.0(vue@3.4.25(typescript@5.4.5)) + vue-router: + specifier: ^4.3.2 + version: 4.3.2(vue@3.4.25(typescript@5.4.5)) + vue-types: + specifier: ^5.1.1 + version: 5.1.1(vue@3.4.25(typescript@5.4.5)) + vuedraggable: + specifier: ^4.1.0 + version: https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz(vue@3.4.25(typescript@5.4.5)) + vxe-table: + specifier: ^4.6.3 + version: 4.6.6(vue@3.4.25(typescript@5.4.5)) + vxe-table-plugin-export-xlsx: + specifier: ^4.0.1 + version: 4.0.1(vxe-table@4.6.6(vue@3.4.25(typescript@5.4.5))) + xe-utils: + specifier: ^3.5.25 + version: 3.5.25 + xlsx: + specifier: ^0.18.5 + version: 0.18.5 + devDependencies: + '@commitlint/cli': + specifier: ^19.3.0 + version: 19.3.0(@types/node@20.12.7)(typescript@5.4.5) + '@commitlint/config-conventional': + specifier: ^19.2.2 + version: 19.2.2 + '@iconify/json': + specifier: ^2.2.203 + version: 2.2.204 + '@purge-icons/generated': + specifier: ^0.10.0 + version: 0.10.0 + '@types/codemirror': + specifier: ^5.60.15 + version: 5.60.15 + '@types/crypto-js': + specifier: ^4.2.2 + version: 4.2.2 + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 + '@types/mockjs': + specifier: ^1.0.10 + version: 1.0.10 + '@types/nprogress': + specifier: ^0.2.3 + version: 0.2.3 + '@types/qrcode': + specifier: ^1.5.5 + version: 1.5.5 + '@types/qs': + specifier: ^6.9.15 + version: 6.9.15 + '@types/showdown': + specifier: ^2.0.6 + version: 2.0.6 + '@types/sortablejs': + specifier: ^1.15.8 + version: 1.15.8 + '@vben/stylelint-config': + specifier: workspace:* + version: link:internal/stylelint-config + '@vben/ts-config': + specifier: workspace:* + version: link:internal/ts-config + '@vben/types': + specifier: workspace:* + version: link:packages/types + '@vben/vite-config': + specifier: workspace:* + version: link:internal/vite-config + '@vue/compiler-sfc': + specifier: ^3.4.25 + version: 3.4.25 + '@vue/test-utils': + specifier: ^2.4.5 + version: 2.4.5 + conventional-changelog-cli: + specifier: ^4.1.0 + version: 4.1.0 + cross-env: + specifier: ^7.0.3 + version: 7.0.3 + cz-git: + specifier: ^1.9.1 + version: 1.9.1 + czg: + specifier: ^1.9.1 + version: 1.9.1 + husky: + specifier: ^9.0.11 + version: 9.0.11 + lint-staged: + specifier: 15.2.2 + version: 15.2.2 + prettier: + specifier: ^3.2.5 + version: 3.2.5 + prettier-plugin-packagejson: + specifier: ^2.5.0 + version: 2.5.0(prettier@3.2.5) + rimraf: + specifier: ^5.0.5 + version: 5.0.5 + turbo: + specifier: ^1.13.2 + version: 1.13.3 + typescript: + specifier: ^5.4.5 + version: 5.4.5 + unbuild: + specifier: ^2.0.0 + version: 2.0.0(sass@1.75.0)(typescript@5.4.5) + vite: + specifier: ^5.2.10 + version: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + vite-plugin-mock: + specifier: ^2.9.6 + version: https://registry.npmmirror.com/vite-plugin-mock/-/vite-plugin-mock-2.9.8.tgz(mockjs@1.1.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + vite-plugin-vue-inspector: + specifier: ^5.0.1 + version: 5.0.1(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + vue-tsc: + specifier: ^2.0.14 + version: 2.0.14(typescript@5.4.5) + + internal/stylelint-config: + devDependencies: + postcss: + specifier: ^8.4.38 + version: 8.4.38 + postcss-html: + specifier: ^1.6.0 + version: 1.6.0 + postcss-less: + specifier: ^6.0.0 + version: 6.0.0(postcss@8.4.38) + postcss-scss: + specifier: ^4.0.9 + version: 4.0.9(postcss@8.4.38) + prettier: + specifier: ^3.2.5 + version: 3.2.5 + stylelint: + specifier: ^16.4.0 + version: 16.4.0(typescript@5.4.5) + stylelint-config-property-sort-order-smacss: + specifier: ^10.0.0 + version: 10.0.0(stylelint@16.4.0(typescript@5.4.5)) + stylelint-config-recommended-scss: + specifier: ^14.0.0 + version: 14.0.0(postcss@8.4.38)(stylelint@16.4.0(typescript@5.4.5)) + stylelint-config-recommended-vue: + specifier: ^1.5.0 + version: 1.5.0(postcss-html@1.6.0)(stylelint@16.4.0(typescript@5.4.5)) + stylelint-config-standard: + specifier: ^36.0.0 + version: 36.0.0(stylelint@16.4.0(typescript@5.4.5)) + stylelint-config-standard-scss: + specifier: ^13.1.0 + version: 13.1.0(postcss@8.4.38)(stylelint@16.4.0(typescript@5.4.5)) + stylelint-order: + specifier: ^6.0.4 + version: 6.0.4(stylelint@16.4.0(typescript@5.4.5)) + stylelint-prettier: + specifier: ^5.0.0 + version: 5.0.0(prettier@3.2.5)(stylelint@16.4.0(typescript@5.4.5)) + + internal/ts-config: + dependencies: + '@types/node': + specifier: ^20.12.7 + version: 20.12.7 + vite: + specifier: ^5.2.10 + version: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + + internal/vite-config: + dependencies: + '@ant-design/colors': + specifier: ^7.0.2 + version: 7.0.2 + vite: + specifier: ^5.2.10 + version: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + devDependencies: + '@types/fs-extra': + specifier: ^11.0.4 + version: 11.0.4 + '@vitejs/plugin-vue': + specifier: ^5.0.4 + version: 5.0.4(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3))(vue@3.4.25(typescript@5.4.5)) + '@vitejs/plugin-vue-jsx': + specifier: ^3.1.0 + version: 3.1.0(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3))(vue@3.4.25(typescript@5.4.5)) + ant-design-vue: + specifier: ^4.2.1 + version: 4.2.1(vue@3.4.25(typescript@5.4.5)) + dayjs: + specifier: ^1.11.10 + version: 1.11.11 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + fs-extra: + specifier: ^11.2.0 + version: 11.2.0 + less: + specifier: ^4.2.0 + version: 4.2.0 + picocolors: + specifier: ^1.0.0 + version: 1.0.0 + pkg-types: + specifier: ^1.1.0 + version: 1.1.0 + rollup-plugin-visualizer: + specifier: ^5.12.0 + version: 5.12.0(rollup@4.17.0) + sass: + specifier: ^1.75.0 + version: 1.75.0 + unocss: + specifier: 0.59.4 + version: 0.59.4(postcss@5.2.18)(rollup@4.17.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + vite-plugin-compression: + specifier: ^0.5.1 + version: 0.5.1(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + vite-plugin-dts: + specifier: ^3.9.0 + version: 3.9.0(@types/node@20.12.7)(rollup@4.17.0)(typescript@5.4.5)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + vite-plugin-html: + specifier: ^3.2.2 + version: 3.2.2(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + vite-plugin-mock: + specifier: ^2.9.6 + version: 2.9.8(mockjs@1.1.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + vite-plugin-purge-icons: + specifier: ^0.10.0 + version: 0.10.0(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + vite-plugin-svg-icons: + specifier: ^2.0.1 + version: 2.0.1(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + + packages/hooks: + dependencies: + '@vueuse/core': + specifier: ^9.13.0 + version: 9.13.0(vue@3.2.47) + vue: + specifier: ^3.2.47 + version: 3.2.47 + devDependencies: + '@vben/types': + specifier: workspace:* + version: link:../types + + packages/types: {} + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@ant-design/colors@6.0.0': + resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==} + + '@ant-design/colors@7.0.2': + resolution: {integrity: sha512-7KJkhTiPiLHSu+LmMJnehfJ6242OCxSlR3xHVBecYxnMW8MS/878NXct1GqYARyL59fyeFdKRxXTfvR9SnDgJg==} + + '@ant-design/icons-svg@4.3.1': + resolution: {integrity: sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g==} + + '@ant-design/icons-vue@7.0.1': + resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==} + peerDependencies: + vue: '>=3.0.3' + + '@antfu/install-pkg@0.1.1': + resolution: {integrity: sha512-LyB/8+bSfa0DFGC06zpCEfs89/XoWZwws5ygEa5D+Xsm3OfI+aXQ86VgVG7Acyef+rSZ5HE7J8rrxzrQeM3PjQ==} + + '@antfu/utils@0.7.7': + resolution: {integrity: sha512-gFPqTG7otEJ8uP6wrhDv6mqwGWYZKNvAcCq6u9hOj0c+IKCEsY4L1oC9trPq2SaWIzAfHvqfBDxF591JkMf+kg==} + + '@axolo/tree-array@0.1.0': + resolution: {integrity: sha512-lmvLattovjw1sqKJNLhPnBTQUm8g7U7FkHG9xUt+hR06YUL9Gtz7zbbe+UQVVGSzwlE7Yf9jiACygMdCxHJRYQ==} + + '@babel/code-frame@7.22.13': + resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} + engines: {node: '>=6.9.0'} + + '@babel/code-frame@7.24.2': + resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.24.4': + resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.24.4': + resolution: {integrity: sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.22.10': + resolution: {integrity: sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.24.4': + resolution: {integrity: sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.22.5': + resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.23.6': + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.24.4': + resolution: {integrity: sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-environment-visitor@7.22.20': + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-environment-visitor@7.22.5': + resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-function-name@7.22.5': + resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-function-name@7.23.0': + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-hoist-variables@7.22.5': + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.23.0': + resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.22.5': + resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.24.3': + resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.23.3': + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.22.5': + resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.22.5': + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.24.0': + resolution: {integrity: sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-replace-supers@7.24.1': + resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-simple-access@7.22.5': + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-skip-transparent-expression-wrappers@7.22.5': + resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-split-export-declaration@7.22.6': + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.22.5': + resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.24.1': + resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.22.20': + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.22.5': + resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.23.5': + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.24.4': + resolution: {integrity: sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.22.13': + resolution: {integrity: sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.2': + resolution: {integrity: sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.22.10': + resolution: {integrity: sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/parser@7.22.13': + resolution: {integrity: sha512-3l6+4YOvc9wx7VlCSw4yQfcBo01ECA8TicQfbnCPuCEpRQrf+gTUyGdxNw+pyTUyywp6JRD1w0YQs9TpBXYlkw==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/parser@7.24.4': + resolution: {integrity: sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-proposal-decorators@7.24.1': + resolution: {integrity: sha512-zPEvzFijn+hRvJuX2Vu3KbEBN39LN3f7tW3MQO2LsIs57B26KU+kUc82BdAktS1VCM6libzh45eKGI65lg0cpA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.24.1': + resolution: {integrity: sha512-05RJdO/cCrtVWuAaSn1tS3bH8jbsJa/Y1uD186u6J4C/1mnHFxseeuWpsqr9anvo7TUulev7tm7GDwRV+VuhDw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.24.1': + resolution: {integrity: sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==} + 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-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.22.5': + resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.24.1': + resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.22.5': + resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.24.1': + resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.24.1': + resolution: {integrity: sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.24.4': + resolution: {integrity: sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.24.1': + resolution: {integrity: sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.22.11': + resolution: {integrity: sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==} + engines: {node: '>=6.9.0'} + + '@babel/standalone@7.22.13': + resolution: {integrity: sha512-JoI61IOKM8jJv8V4yD0HprU/Lnx3Y29bGGULdIdJgvIUS7oCWcl43gtXoLY7nrYZhZerXYncYfDtmq4wUEofcg==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.22.5': + resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.24.0': + resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.22.11': + resolution: {integrity: sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.24.1': + resolution: {integrity: sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.22.10': + resolution: {integrity: sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.22.11': + resolution: {integrity: sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.24.0': + resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@commitlint/cli@19.3.0': + resolution: {integrity: sha512-LgYWOwuDR7BSTQ9OLZ12m7F/qhNY+NpAyPBgo4YNMkACE7lGuUnuQq1yi9hz1KA4+3VqpOYl8H1rY/LYK43v7g==} + engines: {node: '>=v18'} + hasBin: true + + '@commitlint/config-conventional@19.2.2': + resolution: {integrity: sha512-mLXjsxUVLYEGgzbxbxicGPggDuyWNkf25Ht23owXIH+zV2pv1eJuzLK3t1gDY5Gp6pxdE60jZnWUY5cvgL3ufw==} + engines: {node: '>=v18'} + + '@commitlint/config-validator@19.0.3': + resolution: {integrity: sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==} + engines: {node: '>=v18'} + + '@commitlint/ensure@19.0.3': + resolution: {integrity: sha512-SZEpa/VvBLoT+EFZVb91YWbmaZ/9rPH3ESrINOl0HD2kMYsjvl0tF7nMHh0EpTcv4+gTtZBAe1y/SS6/OhfZzQ==} + engines: {node: '>=v18'} + + '@commitlint/execute-rule@19.0.0': + resolution: {integrity: sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==} + engines: {node: '>=v18'} + + '@commitlint/format@19.3.0': + resolution: {integrity: sha512-luguk5/aF68HiF4H23ACAfk8qS8AHxl4LLN5oxPc24H+2+JRPsNr1OS3Gaea0CrH7PKhArBMKBz5RX9sA5NtTg==} + engines: {node: '>=v18'} + + '@commitlint/is-ignored@19.2.2': + resolution: {integrity: sha512-eNX54oXMVxncORywF4ZPFtJoBm3Tvp111tg1xf4zWXGfhBPKpfKG6R+G3G4v5CPlRROXpAOpQ3HMhA9n1Tck1g==} + engines: {node: '>=v18'} + + '@commitlint/lint@19.2.2': + resolution: {integrity: sha512-xrzMmz4JqwGyKQKTpFzlN0dx0TAiT7Ran1fqEBgEmEj+PU98crOFtysJgY+QdeSagx6EDRigQIXJVnfrI0ratA==} + engines: {node: '>=v18'} + + '@commitlint/load@19.2.0': + resolution: {integrity: sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==} + engines: {node: '>=v18'} + + '@commitlint/message@19.0.0': + resolution: {integrity: sha512-c9czf6lU+9oF9gVVa2lmKaOARJvt4soRsVmbR7Njwp9FpbBgste5i7l/2l5o8MmbwGh4yE1snfnsy2qyA2r/Fw==} + engines: {node: '>=v18'} + + '@commitlint/parse@19.0.3': + resolution: {integrity: sha512-Il+tNyOb8VDxN3P6XoBBwWJtKKGzHlitEuXA5BP6ir/3loWlsSqDr5aecl6hZcC/spjq4pHqNh0qPlfeWu38QA==} + engines: {node: '>=v18'} + + '@commitlint/read@19.2.1': + resolution: {integrity: sha512-qETc4+PL0EUv7Q36lJbPG+NJiBOGg7SSC7B5BsPWOmei+Dyif80ErfWQ0qXoW9oCh7GTpTNRoaVhiI8RbhuaNw==} + engines: {node: '>=v18'} + + '@commitlint/resolve-extends@19.1.0': + resolution: {integrity: sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==} + engines: {node: '>=v18'} + + '@commitlint/rules@19.0.3': + resolution: {integrity: sha512-TspKb9VB6svklxNCKKwxhELn7qhtY1rFF8ls58DcFd0F97XoG07xugPjjbVnLqmMkRjZDbDIwBKt9bddOfLaPw==} + engines: {node: '>=v18'} + + '@commitlint/to-lines@19.0.0': + resolution: {integrity: sha512-vkxWo+VQU5wFhiP9Ub9Sre0FYe019JxFikrALVoD5UGa8/t3yOJEpEhxC5xKiENKKhUkTpEItMTRAjHw2SCpZw==} + engines: {node: '>=v18'} + + '@commitlint/top-level@19.0.0': + resolution: {integrity: sha512-KKjShd6u1aMGNkCkaX4aG1jOGdn7f8ZI8TR1VEuNqUOjWTOdcDSsmglinglJ18JTjuBX5I1PtjrhQCRcixRVFQ==} + engines: {node: '>=v18'} + + '@commitlint/types@19.0.3': + resolution: {integrity: sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==} + engines: {node: '>=v18'} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@csstools/css-parser-algorithms@2.6.1': + resolution: {integrity: sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + '@csstools/css-tokenizer': ^2.2.4 + + '@csstools/css-tokenizer@2.2.4': + resolution: {integrity: sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw==} + engines: {node: ^14 || ^16 || >=18} + + '@csstools/media-query-list-parser@2.1.9': + resolution: {integrity: sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + '@csstools/css-parser-algorithms': ^2.6.1 + '@csstools/css-tokenizer': ^2.2.4 + + '@csstools/selector-specificity@3.0.3': + resolution: {integrity: sha512-KEPNw4+WW5AVEIyzC80rTbWEUatTW2lXpN8+8ILC8PiPeWPjwUzrPZDIOZ2wwqDmeqOYTdSGyL3+vE5GC3FB3Q==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss-selector-parser: ^6.0.13 + + '@ctrl/tinycolor@3.6.1': + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + + '@dual-bundle/import-meta-resolve@4.0.0': + resolution: {integrity: sha512-ZKXyJeFAzcpKM2kk8ipoGIPUqx9BX52omTGnfwjJvxOCaZTM2wtDK7zN0aIgPRbT9XYAlha0HtmZ+XKteuh0Gw==} + + '@emotion/hash@0.9.1': + resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} + + '@emotion/unitless@0.8.1': + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + + '@esbuild/aix-ppc64@0.20.2': + resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.18.20': + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.19.2': + resolution: {integrity: sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.20.2': + resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.18.20': + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.19.2': + resolution: {integrity: sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.20.2': + resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.18.20': + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.19.2': + resolution: {integrity: sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.20.2': + resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.18.20': + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.19.2': + resolution: {integrity: sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.20.2': + resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.18.20': + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.19.2': + resolution: {integrity: sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.20.2': + resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.18.20': + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.19.2': + resolution: {integrity: sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.20.2': + resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.18.20': + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.19.2': + resolution: {integrity: sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.20.2': + resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.18.20': + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.19.2': + resolution: {integrity: sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.20.2': + resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.18.20': + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.19.2': + resolution: {integrity: sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.20.2': + resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.18.20': + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.19.2': + resolution: {integrity: sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.20.2': + resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.14.54': + resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.18.20': + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.19.2': + resolution: {integrity: sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.20.2': + resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.18.20': + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.19.2': + resolution: {integrity: sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.20.2': + resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.18.20': + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.19.2': + resolution: {integrity: sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.20.2': + resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.18.20': + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.19.2': + resolution: {integrity: sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.20.2': + resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.18.20': + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.19.2': + resolution: {integrity: sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.20.2': + resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.18.20': + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.19.2': + resolution: {integrity: sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.20.2': + resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.18.20': + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.19.2': + resolution: {integrity: sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.20.2': + resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.18.20': + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.19.2': + resolution: {integrity: sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.20.2': + resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.18.20': + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.19.2': + resolution: {integrity: sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.20.2': + resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.18.20': + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.19.2': + resolution: {integrity: sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.20.2': + resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.18.20': + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.19.2': + resolution: {integrity: sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.20.2': + resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.18.20': + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.19.2': + resolution: {integrity: sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.20.2': + resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@fast-csv/format@4.3.5': + resolution: {integrity: sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==} + + '@fast-csv/parse@4.3.6': + resolution: {integrity: sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==} + + '@hutson/parse-repository-url@5.0.0': + resolution: {integrity: sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==} + engines: {node: '>=10.13.0'} + + '@iconify/iconify@2.1.2': + resolution: {integrity: sha512-QcUzFeEWkE/mW+BVtEGmcWATClcCOIJFiYUD/PiCWuTcdEA297o8D4oN6Ra44WrNOHu1wqNW4J0ioaDIiqaFOQ==} + deprecated: no longer maintained, switch to modern iconify-icon web component + + '@iconify/iconify@3.1.1': + resolution: {integrity: sha512-1nemfyD/OJzh9ALepH7YfuuP8BdEB24Skhd8DXWh0hzcOxImbb1ZizSZkpCzAwSZSGcJFmscIBaBQu+yLyWaxQ==} + + '@iconify/json@2.2.204': + resolution: {integrity: sha512-sFlh+TIF54DZoEzsF5YVWY7XEzjN2ZSmCjtzvajk5EdNjvPAKr9Tvvptoyj6hcuylJsDxiU12FRDSdygW1c8bg==} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@2.1.23': + resolution: {integrity: sha512-YGNbHKM5tyDvdWZ92y2mIkrfvm5Fvhe6WJSkWu7vvOFhMtYDP0casZpoRz0XEHZCrYsR4stdGT3cZ52yp5qZdQ==} + + '@intlify/core-base@9.13.1': + resolution: {integrity: sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==} + engines: {node: '>= 16'} + + '@intlify/message-compiler@9.13.1': + resolution: {integrity: sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==} + engines: {node: '>= 16'} + + '@intlify/shared@9.13.1': + resolution: {integrity: sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==} + engines: {node: '>= 16'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@27.5.1': + resolution: {integrity: sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/core@27.5.1': + resolution: {integrity: sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/environment@27.5.1': + resolution: {integrity: sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/fake-timers@27.5.1': + resolution: {integrity: sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/globals@27.5.1': + resolution: {integrity: sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/reporters@27.5.1': + resolution: {integrity: sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/source-map@27.5.1': + resolution: {integrity: sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/test-result@27.5.1': + resolution: {integrity: sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/test-sequencer@27.5.1': + resolution: {integrity: sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/transform@27.5.1': + resolution: {integrity: sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/types@27.5.1': + resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jridgewell/gen-mapping@0.3.3': + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.1': + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.1.2': + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.5': + resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + '@jridgewell/trace-mapping@0.3.19': + resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@logicflow/core@1.2.26': + resolution: {integrity: sha512-3kJlItEpq8pHaHmeHLkFxOBlBzr3MXG8dT1mAve9pvPLbEflwtV+4Zpv0Iuw3ToGfakXLtNQgsC1cLSDik9Dfg==} + + '@logicflow/extension@1.2.26': + resolution: {integrity: sha512-WnWR7Am9VRQnaMZzd3QI3PuOO2hvA7A45SSuZrxbQMpKsIOy90csD70QxStOF/lsxJrHAYpICE948YRxTijU+A==} + + '@microsoft/api-extractor-model@7.28.13': + resolution: {integrity: sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==} + + '@microsoft/api-extractor@7.43.0': + resolution: {integrity: sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w==} + hasBin: true + + '@microsoft/tsdoc-config@0.16.2': + resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + + '@microsoft/tsdoc@0.14.2': + resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.scandir@https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==, tarball: https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz} + version: 2.1.5 + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, tarball: https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz} + version: 2.0.5 + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, tarball: https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz} + version: 1.2.8 + engines: {node: '>= 8'} + + '@one-ini/wasm@0.1.1': + resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.1.1': + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@polka/url@1.0.0-next.25': + resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} + + '@purge-icons/core@0.10.0': + resolution: {integrity: sha512-AtJbZv5Yy+vWX5v32DPTr+CW7AkSK8HJx52orDbrYt/9s4lGM2t4KKAmwaTQEH2HYr2HVh1mlqs54/S1s3WT1g==} + + '@purge-icons/generated@0.10.0': + resolution: {integrity: sha512-I+1yN7/yDy/eZzfhAZqKF8Z6FM8D/O1vempbPrHJ0m9HlZwvf8sWXOArPJ2qRQGB6mJUVSpaXkoGBuoz1GQX5A==} + + '@rollup/plugin-alias@5.0.0': + resolution: {integrity: sha512-l9hY5chSCjuFRPsnRm16twWBiSApl2uYFLsepQYwtBuAxNMQ/1dJqADld40P0Jkqm65GRTLy/AC6hnpVebtLsA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-commonjs@25.0.7': + resolution: {integrity: sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-json@6.0.0': + resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@15.2.1': + resolution: {integrity: sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-replace@5.0.2': + resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/pluginutils@4.2.1': + resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} + engines: {node: '>= 8.0.0'} + + '@rollup/pluginutils@5.0.4': + resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/pluginutils@5.1.0': + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + 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.17.0': + resolution: {integrity: sha512-nNvLvC2fjC+3+bHYN9uaGF3gcyy7RHGZhtl8TB/kINj9hiOQza8kWJGZh47GRPMrqeseO8U+Z8ElDMCZlWBdHA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.17.0': + resolution: {integrity: sha512-+kjt6dvxnyTIAo7oHeYseYhDyZ7xRKTNl/FoQI96PHkJVxoChldJnne/LzYqpqidoK1/0kX0/q+5rrYqjpth6w==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.17.0': + resolution: {integrity: sha512-Oj6Tp0unMpGTBjvNwbSRv3DopMNLu+mjBzhKTt2zLbDJ/45fB1pltr/rqrO4bE95LzuYwhYn127pop+x/pzf5w==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.17.0': + resolution: {integrity: sha512-3nJx0T+yptxMd+v93rBRxSPTAVCv8szu/fGZDJiKX7kvRe9sENj2ggXjCH/KK1xZEmJOhaNo0c9sGMgGdfkvEw==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.17.0': + resolution: {integrity: sha512-Vb2e8p9b2lxxgqyOlBHmp6hJMu/HSU6g//6Tbr7x5V1DlPCHWLOm37nSIVK314f+IHzORyAQSqL7+9tELxX3zQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.17.0': + resolution: {integrity: sha512-Md60KsmC5ZIaRq/bYYDloklgU+XLEZwS2EXXVcSpiUw+13/ZASvSWQ/P92rQ9YDCL6EIoXxuQ829JkReqdYbGg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.17.0': + resolution: {integrity: sha512-zL5rBFtJ+2EGnMRm2TqKjdjgFqlotSU+ZJEN37nV+fiD3I6Gy0dUh3jBWN0wSlcXVDEJYW7YBe+/2j0N9unb2w==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.17.0': + resolution: {integrity: sha512-s2xAyNkJqUdtRVgNK4NK4P9QttS538JuX/kfVQOdZDI5FIKVAUVdLW7qhGfmaySJ1EvN/Bnj9oPm5go9u8navg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.17.0': + resolution: {integrity: sha512-7F99yzVT67B7IUNMjLD9QCFDCyHkyCJMS1dywZrGgVFJao4VJ9szrIEgH67cR+bXQgEaY01ur/WSL6B0jtcLyA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.17.0': + resolution: {integrity: sha512-leFtyiXisfa3Sg9pgZJwRKITWnrQfhtqDjCamnZhkZuIsk1FXmYwKoTkp6lsCgimIcneFFkHKp/yGLxDesga4g==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.17.0': + resolution: {integrity: sha512-FtOgui6qMJ4jbSXTxElsy/60LEe/3U0rXkkz2G5CJ9rbHPAvjMvI+3qF0A0fwLQ5hW+/ZC6PbnS2KfRW9JkgDQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.17.0': + resolution: {integrity: sha512-v6eiam/1w3HUfU/ZjzIDodencqgrSqzlNuNtiwH7PFJHYSo1ezL0/UIzmS2lpSJF1ORNaplXeKHYmmdt81vV2g==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.17.0': + resolution: {integrity: sha512-OUhkSdpM5ofVlVU2k4CwVubYwiwu1a4jYWPpubzN7Vzao73GoPBowHcCfaRSFRz1SszJ3HIsk3dZYk4kzbqjgw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.17.0': + resolution: {integrity: sha512-uL7UYO/MNJPGL/yflybI+HI+n6+4vlfZmQZOCb4I+z/zy1wisHT3exh7oNQsnL6Eso0EUTEfgQ/PaGzzXf6XyQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.17.0': + resolution: {integrity: sha512-4WnSgaUiUmXILwFqREdOcqvSj6GD/7FrvSjhaDjmwakX9w4Z2F8JwiSP1AZZbuRkPqzi444UI5FPv33VKOWYFQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.17.0': + resolution: {integrity: sha512-ve+D8t1prRSRnF2S3pyDtTXDlvW1Pngbz76tjgYFQW1jxVSysmQCZfPoDAo4WP+Ano8zeYp85LsArZBI12HfwQ==} + cpu: [x64] + os: [win32] + + '@rushstack/node-core-library@4.0.2': + resolution: {integrity: sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/rig-package@0.5.2': + resolution: {integrity: sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==} + + '@rushstack/terminal@0.10.0': + resolution: {integrity: sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/ts-command-line@4.19.1': + resolution: {integrity: sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg==} + + '@simonwep/pickr@1.8.2': + resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==} + + '@sinonjs/commons@1.8.6': + resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==} + + '@sinonjs/fake-timers@8.1.0': + resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==} + + '@tootallnate/once@1.1.2': + resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} + engines: {node: '>= 6'} + + '@trysound/sax@0.2.0': + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + + '@tsconfig/node10@1.0.9': + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.3': + resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} + + '@types/argparse@1.0.38': + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + + '@types/babel__core@7.20.1': + resolution: {integrity: sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==} + + '@types/babel__generator@7.6.4': + resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} + + '@types/babel__template@7.4.1': + resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} + + '@types/babel__traverse@7.20.1': + resolution: {integrity: sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==} + + '@types/codemirror@5.60.15': + resolution: {integrity: sha512-dTOvwEQ+ouKJ/rE9LT1Ue2hmP6H1mZv5+CCnNWu2qtiOe2LQa9lCprEY20HxiDmV/Bxh+dXjywmy5aKvoGjULA==} + + '@types/conventional-commits-parser@5.0.0': + resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==} + + '@types/crypto-js@4.2.2': + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} + + '@types/estree@1.0.1': + resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + + '@types/graceful-fs@4.1.6': + resolution: {integrity: sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==} + + '@types/istanbul-lib-coverage@2.0.4': + resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + + '@types/istanbul-lib-report@3.0.0': + resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} + + '@types/istanbul-reports@3.0.1': + resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} + + '@types/jsonfile@6.1.1': + resolution: {integrity: sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.14.197': + resolution: {integrity: sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==} + + '@types/mockjs@1.0.10': + resolution: {integrity: sha512-SXgrhajHG7boLv6oU93CcmdDm0HYRiceuz6b+7z+/2lCJPTWDv0V5YiwFHT2ejE4bQqgSXQiVPQYPWv7LGsK1g==} + + '@types/mousetrap@1.6.11': + resolution: {integrity: sha512-F0oAily9Q9QQpv9JKxKn0zMKfOo36KHCW7myYsmUyf2t0g+sBTbG3UleTPoguHdE1z3GLFr3p7/wiOio52QFjQ==} + + '@types/node@14.18.56': + resolution: {integrity: sha512-+k+57NVS9opgrEn5l9c0gvD1r6C+PtyhVE4BTnMMRwiEA8ZO8uFcs6Yy2sXIy0eC95ZurBtRSvhZiHXBysbl6w==} + + '@types/node@20.12.7': + resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} + + '@types/normalize-package-data@2.4.1': + resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} + + '@types/nprogress@0.2.3': + resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} + + '@types/prettier@2.7.3': + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + + '@types/qrcode@1.5.5': + resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==} + + '@types/qs@6.9.15': + resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} + + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + + '@types/showdown@2.0.6': + resolution: {integrity: sha512-pTvD/0CIeqe4x23+YJWlX2gArHa8G0J0Oh6GKaVXV7TAeickpkkZiNOgFcFcmLQ5lB/K0qBJL1FtRYltBfbGCQ==} + + '@types/sortablejs@1.15.8': + resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==} + + '@types/stack-utils@2.0.1': + resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} + + '@types/svgo@2.6.4': + resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} + + '@types/tern@0.23.4': + resolution: {integrity: sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==} + + '@types/web-bluetooth@0.0.16': + resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} + + '@types/web-bluetooth@0.0.20': + resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + + '@types/yargs-parser@21.0.0': + resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} + + '@types/yargs@16.0.5': + resolution: {integrity: sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==} + + '@unocss/astro@0.59.4': + resolution: {integrity: sha512-DU3OR5MMR1Uvvec4/wB9EetDASHRg19Moy6z/MiIhn8JWJ0QzWYgSeJcfUX8exomMYv6WUEQJL+CyLI34Wmn8w==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + vite: + optional: true + + '@unocss/cli@0.59.4': + resolution: {integrity: sha512-TT+WKedSifhsRqnpoYD2LfyYipVzEbzIU4DDGIaDNeDxGXYOGpb876zzkPDcvZSpI37IJ/efkkV7PGYpPBcQBQ==} + engines: {node: '>=14'} + hasBin: true + + '@unocss/config@0.59.4': + resolution: {integrity: sha512-h3yhj+D5Ygn5R7gbK4wMrtXZX6FF5DF6YD517sSSb0XB3lxHD9PhhT4HaV1hpHknvu0cMFU3460M45+TN1TI0Q==} + engines: {node: '>=14'} + + '@unocss/core@0.59.4': + resolution: {integrity: sha512-bBZ1sgcAtezQVZ1BST9IS3jqcsTLyqKNjiIf7FTnX3DHpfpYuMDFzSOtmkZDzBleOLO/CtcRWjT0HwTSQAmV0A==} + + '@unocss/extractor-arbitrary-variants@0.59.4': + resolution: {integrity: sha512-RDe4FgMGJQ+tp9GLvhPHni7Cc2O0lHBRMElVlN8LoXJAdODMICdbrEPGJlEfrc+7x/QgVFoR895KpYJh3hIgGA==} + + '@unocss/inspector@0.59.4': + resolution: {integrity: sha512-QczJFNDiggmekkJyNcbcZIUVwlhvxz7ZwjnSf0w7K4znxfjKkZ1hNUbqLviM1HumkTKOdT27VISW7saN/ysO4w==} + + '@unocss/postcss@0.59.4': + resolution: {integrity: sha512-KVz+AD7McHKp7VEWHbFahhyyVEo0oP/e1vnuNSuPlHthe+1V2zfH6lps+iJcvfL2072r5J+0PvD/1kOp5ryUSg==} + engines: {node: '>=14'} + peerDependencies: + postcss: ^8.4.21 + + '@unocss/preset-attributify@0.59.4': + resolution: {integrity: sha512-BeogWuYaIakC1gmOZFFCjFVWmu/m3AqEX8UYQS6tY6lAaK2L4Qf4AstYBlT2zAMxy9LNxPDxFQrvfSfFk5Klsg==} + + '@unocss/preset-icons@0.59.4': + resolution: {integrity: sha512-Afjwh5oC4KRE8TNZDUkRK6hvvV1wKLrS1e5trniE0B0AM9HK3PBolQaIU7QmzPv6WQrog+MZgIwafg1eqsPUCA==} + + '@unocss/preset-mini@0.59.4': + resolution: {integrity: sha512-ZLywGrXi1OCr4My5vX2rLUb5Xgx6ufR9WTQOvpQJGBdIV/jnZn/pyE5avCs476SnOq2K172lnd8mFmTK7/zArA==} + + '@unocss/preset-tagify@0.59.4': + resolution: {integrity: sha512-vWMdTUoghOSmTbdmZtERssffmdUdOuhh4vUdl0R8Kv6KxB0PkvEFCu2FItn97nRJdSPlZSFxxDkaOIg9w+STNQ==} + + '@unocss/preset-typography@0.59.4': + resolution: {integrity: sha512-ZX9bxZUqlXK1qEDzO5lkK96ICt9itR/oNyn/7mMc1JPqwj263LumQMn5silocgzoLSUXEeq//L6GylqYjkL8GA==} + + '@unocss/preset-uno@0.59.4': + resolution: {integrity: sha512-G1f8ZluplvXZ3bERj+sM/8zzY//XD++nNOlAQNKOANSVht3qEoJebrfEiMClNpA5qW5VWOZhEhPkh0M7GsXtnA==} + + '@unocss/preset-web-fonts@0.59.4': + resolution: {integrity: sha512-ehutTjKHnf2KPmdatN42N9a8+y+glKSU3UlcBRNsVIIXVIlaBQuPVGZSPhnMtrKD17IgWylXq2K6RJK+ab0hZA==} + + '@unocss/preset-wind@0.59.4': + resolution: {integrity: sha512-CNX6w0ZpSQg/i1oF0/WKWzto8PtLqoknC5h8JmmcGb7VsyBQeV0oNnhbURxpbuMEhbv1MWVIGvk8a+P6y0rFkQ==} + + '@unocss/reset@0.59.4': + resolution: {integrity: sha512-Upy4xzdWl4RChbLAXBq1BoR4WqxXMoIfjvtcwSZcZK2sylXCFAseSWnyzJFdSiXPqNfmMuNgPXgiSxiQB+cmNA==} + + '@unocss/rule-utils@0.59.4': + resolution: {integrity: sha512-1qoLJlBWAkS4D4sg73990S1MT7E8E5md/YhopKjTQuEC9SyeVmEg+5pR/Xd8xhPKMqbcuBPl/DS8b6l/GQO56A==} + engines: {node: '>=14'} + + '@unocss/scope@0.59.4': + resolution: {integrity: sha512-wBQJ39kw4Tfj4km7AoGvSIobPKVnRZVsgc0bema5Y0PL3g1NeVQ/LopBI2zEJWdpxGXUWxSDsXm7BZo6qVlD/A==} + + '@unocss/transformer-attributify-jsx-babel@0.59.4': + resolution: {integrity: sha512-xtCRSgeTaDBiNJLVX7oOSFe63JiFB5nrdK23PHn3IlZM9O7Bxx4ZxI3MQJtFZFQNE+INFko+DVyY1WiFEm1p/Q==} + + '@unocss/transformer-attributify-jsx@0.59.4': + resolution: {integrity: sha512-m4b83utzKMfUQH/45V2QkjJoXd8Tu2pRP1nic91Xf7QRceyKDD+BxoTneo2JNC2K274cQu7HqqotnCm2aFfEGw==} + + '@unocss/transformer-compile-class@0.59.4': + resolution: {integrity: sha512-Vgk2OCLPW0pU+Uzr1IgDtHVspSBb+gPrQFkV+5gxHk9ZdKi3oYKxLuufVWYDSwv7o9yfQGbYrMH9YLsjRsnA7Q==} + + '@unocss/transformer-directives@0.59.4': + resolution: {integrity: sha512-nXUTEclUbs0vQ4KfLhKt4J/5SLSEq1az2FNlJmiXMmqmn75X89OrtCu2OJu9sGXhn+YyBApxgcSSdxmtpqMi1Q==} + + '@unocss/transformer-variant-group@0.59.4': + resolution: {integrity: sha512-9XLixxn1NRgP62Kj4R/NC/rpqhql5F2s6ulJ8CAMTEbd/NylVhEANluPGDVUGcLJ4cj6E02hFa8C1PLGSm7/xw==} + + '@unocss/vite@0.59.4': + resolution: {integrity: sha512-q7GN7vkQYn79n7vYIUlaa7gXGwc7pk0Qo3z3ZFwWGE43/DtZnn2Hwl5UjgBAgi9McA+xqHJEHRsJnI7HJPHUYA==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + + '@vitejs/plugin-vue-jsx@3.1.0': + resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.0.0 || ^5.0.0 + vue: ^3.0.0 + + '@vitejs/plugin-vue@5.0.4': + resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 + vue: ^3.2.25 + + '@volar/language-core@1.11.1': + resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} + + '@volar/language-core@2.2.0-alpha.10': + resolution: {integrity: sha512-njVJLtpu0zMvDaEk7K5q4BRpOgbyEUljU++un9TfJoJNhxG0z/hWwpwgTRImO42EKvwIxF3XUzeMk+qatAFy7Q==} + + '@volar/source-map@1.11.1': + resolution: {integrity: sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==} + + '@volar/source-map@2.2.0-alpha.10': + resolution: {integrity: sha512-nrdWApVkP5cksAnDEyy1JD9rKdwOJsEq1B+seWO4vNXmZNcxQQCx4DULLBvKt7AzRUAQiAuw5aQkb9RBaSqdVA==} + + '@volar/typescript@1.11.1': + resolution: {integrity: sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==} + + '@volar/typescript@2.2.0-alpha.10': + resolution: {integrity: sha512-GCa0vTVVdA9ULUsu2Rx7jwsIuyZQPvPVT9o3NrANTbYv+523Ao1gv3glC5vzNSDPM6bUl37r94HbCj7KINQr+g==} + + '@vue/babel-helper-vue-transform-on@1.1.5': + resolution: {integrity: sha512-SgUymFpMoAyWeYWLAY+MkCK3QEROsiUnfaw5zxOVD/M64KQs8D/4oK6Q5omVA2hnvEOE0SCkH2TZxs/jnnUj7w==} + + '@vue/babel-plugin-jsx@1.1.5': + resolution: {integrity: sha512-nKs1/Bg9U1n3qSWnsHhCVQtAzI6aQXqua8j/bZrau8ywT1ilXQbK4FwEJGmU8fV7tcpuFvWmmN7TMmV1OBma1g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@vue/compiler-core@3.2.47': + resolution: {integrity: sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==} + + '@vue/compiler-core@3.4.25': + resolution: {integrity: sha512-Y2pLLopaElgWnMNolgG8w3C5nNUVev80L7hdQ5iIKPtMJvhVpG0zhnBG/g3UajJmZdvW0fktyZTotEHD1Srhbg==} + + '@vue/compiler-dom@3.2.47': + resolution: {integrity: sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==} + + '@vue/compiler-dom@3.4.25': + resolution: {integrity: sha512-Ugz5DusW57+HjllAugLci19NsDK+VyjGvmbB2TXaTcSlQxwL++2PETHx/+Qv6qFwNLzSt7HKepPe4DcTE3pBWg==} + + '@vue/compiler-sfc@3.2.47': + resolution: {integrity: sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==} + + '@vue/compiler-sfc@3.4.25': + resolution: {integrity: sha512-m7rryuqzIoQpOBZ18wKyq05IwL6qEpZxFZfRxlNYuIPDqywrXQxgUwLXIvoU72gs6cRdY6wHD0WVZIFE4OEaAQ==} + + '@vue/compiler-ssr@3.2.47': + resolution: {integrity: sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==} + + '@vue/compiler-ssr@3.4.25': + resolution: {integrity: sha512-H2ohvM/Pf6LelGxDBnfbbXFPyM4NE3hrw0e/EpwuSiYu8c819wx+SVGdJ65p/sFrYDd6OnSDxN1MB2mN07hRSQ==} + + '@vue/devtools-api@6.5.0': + resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} + + '@vue/devtools-api@6.6.1': + resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==} + + '@vue/language-core@1.8.27': + resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/language-core@2.0.14': + resolution: {integrity: sha512-3q8mHSNcGTR7sfp2X6jZdcb4yt8AjBXAfKk0qkZIh7GAJxOnoZ10h5HToZglw4ToFvAnq+xu/Z2FFbglh9Icag==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/reactivity-transform@3.2.47': + resolution: {integrity: sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==} + + '@vue/reactivity@3.2.47': + resolution: {integrity: sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==} + + '@vue/reactivity@3.4.25': + resolution: {integrity: sha512-mKbEtKr1iTxZkAG3vm3BtKHAOhuI4zzsVcN0epDldU/THsrvfXRKzq+lZnjczZGnTdh3ojd86/WrP+u9M51pWQ==} + + '@vue/runtime-core@3.2.47': + resolution: {integrity: sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==} + + '@vue/runtime-core@3.4.25': + resolution: {integrity: sha512-3qhsTqbEh8BMH3pXf009epCI5E7bKu28fJLi9O6W+ZGt/6xgSfMuGPqa5HRbUxLoehTNp5uWvzCr60KuiRIL0Q==} + + '@vue/runtime-dom@3.2.47': + resolution: {integrity: sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==} + + '@vue/runtime-dom@3.4.25': + resolution: {integrity: sha512-ode0sj77kuwXwSc+2Yhk8JMHZh1sZp9F/51wdBiz3KGaWltbKtdihlJFhQG4H6AY+A06zzeMLkq6qu8uDSsaoA==} + + '@vue/server-renderer@3.2.47': + resolution: {integrity: sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==} + peerDependencies: + vue: 3.2.47 + + '@vue/server-renderer@3.4.25': + resolution: {integrity: sha512-8VTwq0Zcu3K4dWV0jOwIVINESE/gha3ifYCOKEhxOj6MEl5K5y8J8clQncTcDhKF+9U765nRw4UdUEXvrGhyVQ==} + peerDependencies: + vue: 3.4.25 + + '@vue/shared@3.2.47': + resolution: {integrity: sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==} + + '@vue/shared@3.4.25': + resolution: {integrity: sha512-k0yappJ77g2+KNrIaF0FFnzwLvUBLUYr8VOwz+/6vLsmItFp51AcxLL7Ey3iPd7BIRyWPOcqUjMnm7OkahXllA==} + + '@vue/test-utils@2.4.5': + resolution: {integrity: sha512-oo2u7vktOyKUked36R93NB7mg2B+N7Plr8lxp2JBGwr18ch6EggFjixSCdIVVLkT6Qr0z359Xvnafc9dcKyDUg==} + + '@vueuse/core@10.9.0': + resolution: {integrity: sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==} + + '@vueuse/core@9.13.0': + resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==} + + '@vueuse/metadata@10.9.0': + resolution: {integrity: sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==} + + '@vueuse/metadata@9.13.0': + resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==} + + '@vueuse/shared@10.9.0': + resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==} + + '@vueuse/shared@9.13.0': + resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} + + '@zxcvbn-ts/core@3.0.4': + resolution: {integrity: sha512-aQeiT0F09FuJaAqNrxynlAwZ2mW/1MdXakKWNmGM1Qp/VaY6CnB/GfnMS2T8gB2231Esp1/maCWd8vTG4OuShw==} + + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + + abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + deprecated: Use your platform's native atob() and btoa() methods instead + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + acorn-globals@6.0.0: + resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==} + + acorn-walk@7.2.0: + resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} + engines: {node: '>=0.4.0'} + + acorn-walk@8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + + acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + + add-stream@1.0.0: + resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==} + + adler-32@1.3.1: + resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} + engines: {node: '>=0.8'} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-escapes@6.2.1: + resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} + engines: {node: '>=14.16'} + + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + ansi-styles@https://registry.npmmirror.com/ansi-styles/-/ansi-styles-2.2.1.tgz: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==, tarball: https://registry.npmmirror.com/ansi-styles/-/ansi-styles-2.2.1.tgz} + version: 2.2.1 + engines: {node: '>=0.10.0'} + + ansi-styles@https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==, tarball: https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz} + version: 3.2.1 + engines: {node: '>=4'} + + ansi-styles@https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, tarball: https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz} + version: 4.3.0 + engines: {node: '>=8'} + + ant-design-vue@4.2.1: + resolution: {integrity: sha512-3u6fmfCEJ5AFTsYhogP8lJ/vcqiAJO16o+gGQkWYRGLl0NxmY4hje4cPyv+pcxpeJgcG0vNEmkb1vVHKcnxd+g==} + engines: {node: '>=12.22.0'} + peerDependencies: + vue: '>=3.2.0' + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + anymatch@https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, tarball: https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz} + version: 3.1.3 + engines: {node: '>= 8'} + + archiver-utils@2.1.0: + resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} + engines: {node: '>= 6'} + + archiver@5.3.2: + resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} + engines: {node: '>= 10'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + arr-diff@4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + + arr-flatten@1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + + arr-union@3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + + array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + + 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'} + + array-unique@0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + + assign-symbols@1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + + async@3.2.4: + resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + + axios@0.26.1: + resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==} + + axios@1.6.8: + resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} + + babel-jest@27.5.1: + resolution: {integrity: sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@27.5.1: + resolution: {integrity: sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + babel-preset-current-node-syntax@1.0.1: + resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@27.5.1: + resolution: {integrity: sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@2.0.0: + resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + base@0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + + big-integer@1.6.51: + resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} + engines: {node: '>=0.6'} + + big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + + binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + + binary-extensions@https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==, tarball: https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz} + version: 2.2.0 + engines: {node: '>=8'} + + binary@0.3.0: + resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + bluebird@3.4.7: + resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} + + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + + braces@https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==, tarball: https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz} + version: 3.0.2 + engines: {node: '>=8'} + + browser-process-hrtime@1.0.0: + resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} + + browserslist@4.23.0: + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer-indexof-polyfill@1.0.2: + resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} + engines: {node: '>=0.10'} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + buffers@0.1.1: + resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} + engines: {node: '>=0.2.0'} + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + cache-base@1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001614: + resolution: {integrity: sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==} + + cfb@1.2.2: + resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==} + engines: {node: '>=0.8'} + + chainsaw@0.1.0: + resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==} + + chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + chalk@https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==, tarball: https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz} + version: 2.4.2 + engines: {node: '>=4'} + + chalk@https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, tarball: https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz} + version: 4.1.2 + engines: {node: '>=10'} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==, tarball: https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz} + version: 3.5.3 + engines: {node: '>= 8.10.0'} + + ci-info@3.8.0: + resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} + engines: {node: '>=8'} + + citty@0.1.3: + resolution: {integrity: sha512-tb6zTEb2BDSrzFedqFYFUKUuKNaxVJWCm7o02K4kADGkBDyyiz7D40rDMpguczdZyAN3aetd5fhpB01HkreNyg==} + + cjs-module-lexer@1.2.3: + resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} + + class-utils@0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + + clean-css@5.3.2: + resolution: {integrity: sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==} + engines: {node: '>= 10.0'} + + cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + 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'} + + clone@2.1.2: + resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} + engines: {node: '>=0.8'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + codemirror@5.65.16: + resolution: {integrity: sha512-br21LjYmSlVL0vFCPWPfhzUCT34FM/pAdK7rRIZwa0rrtrIdotvP4Oh4GUHsu2E3IrQMCfRkL/fN3ytMNxVQvg==} + + codepage@1.15.0: + resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} + engines: {node: '>=0.8'} + + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + + collection-visit@1.0.0: + resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} + engines: {node: '>=0.10.0'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-convert@https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==, tarball: https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz} + version: 1.9.3 + + color-convert@https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, tarball: https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz} + version: 2.0.1 + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-name@https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==, tarball: https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz} + version: 1.1.3 + + color-name@https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, tarball: https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz} + version: 1.1.4 + + 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'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@11.0.0: + resolution: {integrity: sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==} + engines: {node: '>=16'} + + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + 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'} + + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + + component-emitter@1.3.0: + resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} + + compress-commons@4.1.1: + resolution: {integrity: sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==} + engines: {node: '>= 10'} + + compute-scroll-into-view@1.0.20: + resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + + computeds@0.0.1: + resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.7: + resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + connect-history-api-fallback@1.6.0: + resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} + engines: {node: '>=0.8'} + + connect@3.7.0: + resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} + engines: {node: '>= 0.10.0'} + + connect@https://registry.npmmirror.com/connect/-/connect-3.7.0.tgz: + resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==, tarball: https://registry.npmmirror.com/connect/-/connect-3.7.0.tgz} + version: 3.7.0 + engines: {node: '>= 0.10.0'} + + consola@2.15.3: + resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} + + consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + 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-atom@4.0.0: + resolution: {integrity: sha512-q2YtiN7rnT1TGwPTwjjBSIPIzDJCRE+XAUahWxnh+buKK99Kks4WLMHoexw38GXx9OUxAsrp44f9qXe5VEMYhw==} + engines: {node: '>=16'} + + conventional-changelog-cli@4.1.0: + resolution: {integrity: sha512-MscvILWZ6nWOoC+p/3Nn3D2cVLkjeQjyZPUr0bQ+vUORE/SPrkClJh8BOoMNpS4yk+zFJ5LlgXACxH6XGQoRXA==} + engines: {node: '>=16'} + hasBin: true + + conventional-changelog-codemirror@4.0.0: + resolution: {integrity: sha512-hQSojc/5imn1GJK3A75m9hEZZhc3urojA5gMpnar4JHmgLnuM3CUIARPpEk86glEKr3c54Po3WV/vCaO/U8g3Q==} + engines: {node: '>=16'} + + conventional-changelog-conventionalcommits@7.0.2: + resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} + engines: {node: '>=16'} + + conventional-changelog-core@7.0.0: + resolution: {integrity: sha512-UYgaB1F/COt7VFjlYKVE/9tTzfU3VUq47r6iWf6lM5T7TlOxr0thI63ojQueRLIpVbrtHK4Ffw+yQGduw2Bhdg==} + engines: {node: '>=16'} + + conventional-changelog-ember@4.0.0: + resolution: {integrity: sha512-D0IMhwcJUg1Y8FSry6XAplEJcljkHVlvAZddhhsdbL1rbsqRsMfGx/PIkPYq0ru5aDgn+OxhQ5N5yR7P9mfsvA==} + engines: {node: '>=16'} + + conventional-changelog-eslint@5.0.0: + resolution: {integrity: sha512-6JtLWqAQIeJLn/OzUlYmzd9fKeNSWmQVim9kql+v4GrZwLx807kAJl3IJVc3jTYfVKWLxhC3BGUxYiuVEcVjgA==} + engines: {node: '>=16'} + + conventional-changelog-express@4.0.0: + resolution: {integrity: sha512-yWyy5c7raP9v7aTvPAWzqrztACNO9+FEI1FSYh7UP7YT1AkWgv5UspUeB5v3Ibv4/o60zj2o9GF2tqKQ99lIsw==} + engines: {node: '>=16'} + + conventional-changelog-jquery@5.0.0: + resolution: {integrity: sha512-slLjlXLRNa/icMI3+uGLQbtrgEny3RgITeCxevJB+p05ExiTgHACP5p3XiMKzjBn80n+Rzr83XMYfRInEtCPPw==} + engines: {node: '>=16'} + + conventional-changelog-jshint@4.0.0: + resolution: {integrity: sha512-LyXq1bbl0yG0Ai1SbLxIk8ZxUOe3AjnlwE6sVRQmMgetBk+4gY9EO3d00zlEt8Y8gwsITytDnPORl8al7InTjg==} + engines: {node: '>=16'} + + conventional-changelog-preset-loader@4.1.0: + resolution: {integrity: sha512-HozQjJicZTuRhCRTq4rZbefaiCzRM2pr6u2NL3XhrmQm4RMnDXfESU6JKu/pnKwx5xtdkYfNCsbhN5exhiKGJA==} + engines: {node: '>=16'} + + conventional-changelog-writer@7.0.1: + resolution: {integrity: sha512-Uo+R9neH3r/foIvQ0MKcsXkX642hdm9odUp7TqgFS7BsalTcjzRlIfWZrZR1gbxOozKucaKt5KAbjW8J8xRSmA==} + engines: {node: '>=16'} + hasBin: true + + conventional-changelog@5.1.0: + resolution: {integrity: sha512-aWyE/P39wGYRPllcCEZDxTVEmhyLzTc9XA6z6rVfkuCD2UBnhV/sgSOKbQrEG5z9mEZJjnopjgQooTKxEg8mAg==} + engines: {node: '>=16'} + + conventional-commits-filter@4.0.0: + resolution: {integrity: sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==} + engines: {node: '>=16'} + + conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} + hasBin: true + + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + copy-anything@2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + + copy-descriptor@0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + + core-js@3.32.1: + resolution: {integrity: sha512-lqufgNn9NLnESg5mQeYsxQP5w7wrViSj0jr/kv6ECQiByzQkrn1MKvV0L3acttpDqfQrHLwr2KCMgX5b8X+lyQ==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + cosmiconfig-typescript-loader@5.0.0: + resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} + engines: {node: '>=v16'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=8.2' + typescript: '>=4' + + 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@4.0.2: + resolution: {integrity: sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==} + engines: {node: '>= 10'} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cropperjs@1.6.2: + resolution: {integrity: sha512-nhymn9GdnV3CqiEHJVai54TULFAE3VshJTXSqSJKa8yXAKyBKDWdhHarnlIPrshJ0WMFTGuFvG02YjLXfPiuOA==} + + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + + cross-fetch@3.1.8: + resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + + css-functions-list@3.2.2: + resolution: {integrity: sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==} + engines: {node: '>=12 || >=16'} + + css-property-sort-order-smacss@2.2.0: + resolution: {integrity: sha512-nXutswsivIEBOrPo/OZw2KQjFPLvtg68aovJf6Kqrm3L6FmTvvFPaeDrk83hh0+pRJGuP3PeKJwMS0E6DFipdQ==} + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + + cssom@0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + + cssom@0.4.4: + resolution: {integrity: sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==} + + cssstyle@2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + + csstype@2.6.21: + resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + cz-git@1.9.1: + resolution: {integrity: sha512-GK3EI5R7GApS8u+g9QPvy/50z0NiG7ijc1NASxZaDnQn0ARzr73MjZb3Lt4cZQvKJBd8GrfvOWqHgwMQQ/OlaA==} + engines: {node: '>=v12.20.0'} + + czg@1.9.1: + resolution: {integrity: sha512-0+vLv7QkoY+YNpGrPjyw6SPqvaOlqQsNJqSI3SC2oh5jNDjMrw2VEWBUg/8j/GZWmn1zCR2ssA8yAG9WK7A5sA==} + engines: {node: '>=v12.20.0'} + hasBin: true + + dargs@8.1.0: + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + engines: {node: '>=12'} + + data-urls@2.0.0: + resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} + engines: {node: '>=10'} + + dayjs@1.11.11: + resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==} + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==, tarball: https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz} + version: 3.2.7 + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==, tarball: https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz} + version: 4.3.4 + 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'} + + decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + + decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + + dedent@0.7.0: + resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + 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-property@0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + + define-property@1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + + define-property@2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + + defu@6.1.2: + resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + destr@2.0.3: + resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} + + detect-indent@7.0.1: + resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} + engines: {node: '>=12.20'} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + detect-newline@4.0.0: + resolution: {integrity: sha512-1aXUEPdfGdzVPFpzGJJNgq9o81bGg1s09uxTWsqBlo9PI332uyJRQq13+LK/UN4JfxJbFdCXonUFQ9R/p7yCtw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + diff-match-patch@1.0.5: + resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} + + 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@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + 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'} + + 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@0.2.2: + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + dom-zindex@1.0.2: + resolution: {integrity: sha512-QceDZxPlvzhpg6e8szxNiKPUt5Y9SfFTe3nZy8og3JoPQPlAlzBzHa/lhDkhgeG3cjbKyQcuoic+wymF0o0d1Q==} + + domelementtype@1.3.1: + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domexception@2.0.1: + resolution: {integrity: sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==} + engines: {node: '>=8'} + deprecated: Use your platform's native DOMException instead + + domhandler@2.4.2: + resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==} + + 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'} + + domutils@1.7.0: + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + + dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + + dotenv-expand@8.0.3: + resolution: {integrity: sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==} + engines: {node: '>=12'} + + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + + duplexer2@0.1.4: + resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} + + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + echarts@5.5.0: + resolution: {integrity: sha512-rNYnNCzqDAPCr4m/fqyUFv7fD9qIsd50S6GDFgO1DxZhncCsNsG7IfUlAlvZe5oSEQxtsjnHiUuppzccry93Xw==} + + 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==} + + ee-first@https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, tarball: https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz} + version: 1.1.1 + + ejs@3.1.9: + resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.4.750: + resolution: {integrity: sha512-9ItEpeu15hW5m8jKdriL+BQrgwDTXEL9pn4SkillWFu73ZNNNQ2BKKLS+ZHv2vC9UkNhosAeyfxOf/5OSeTCPA==} + + emittery@0.8.1: + resolution: {integrity: sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==} + engines: {node: '>=10'} + + emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + + encode-utf8@1.0.3: + resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==, tarball: https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz} + version: 1.0.2 + engines: {node: '>= 0.8'} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + entities@1.1.2: + resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + errno@0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + esbuild-android-64@0.14.54: + resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + esbuild-android-arm64@0.14.54: + resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + esbuild-darwin-64@0.14.54: + resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + esbuild-darwin-arm64@0.14.54: + resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + esbuild-freebsd-64@0.14.54: + resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + esbuild-freebsd-arm64@0.14.54: + resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + esbuild-linux-32@0.14.54: + resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + esbuild-linux-64@0.14.54: + resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + esbuild-linux-arm64@0.14.54: + resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + esbuild-linux-arm@0.14.54: + resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + esbuild-linux-mips64le@0.14.54: + resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + esbuild-linux-ppc64le@0.14.54: + resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + esbuild-linux-riscv64@0.14.54: + resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + esbuild-linux-s390x@0.14.54: + resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + esbuild-netbsd-64@0.14.54: + resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + esbuild-openbsd-64@0.14.54: + resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + esbuild-sunos-64@0.14.54: + resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + esbuild-windows-32@0.14.54: + resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + esbuild-windows-64@0.14.54: + resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + esbuild-windows-arm64@0.14.54: + resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + esbuild@0.14.54: + resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.19.2: + resolution: {integrity: sha512-G6hPax8UbFakEj3hWO0Vs52LQ8k3lnBhxZWomUJDxfz3rZTLqF5k/FCzuNdLx2RbpBiQQF9H9onlDDH1lZsnjg==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.20.2: + resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} + engines: {node: '>=12'} + hasBin: true + + esbuild@https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz: + resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==, tarball: https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz} + version: 0.14.54 + engines: {node: '>=12'} + hasBin: true + + escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-html@https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, tarball: https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz} + version: 1.0.3 + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + 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'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + exceljs@4.4.0: + resolution: {integrity: sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==} + engines: {node: '>=8.3.0'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + + expand-brackets@2.1.4: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + + expect@27.5.1: + resolution: {integrity: sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + + extend-shallow@3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + + extglob@2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + + fast-csv@4.3.6: + resolution: {integrity: sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==} + engines: {node: '>=10.0.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.2.0: + resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-glob@https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.1.tgz: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==, tarball: https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.1.tgz} + version: 3.3.1 + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + + fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + + fastq@https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==, tarball: https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz} + version: 1.15.0 + + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + fill-range@4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} + engines: {node: '>=0.10.0'} + + fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + + fill-range@https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==, tarball: https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz} + version: 7.0.1 + engines: {node: '>=8'} + + finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + + finalhandler@https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.2.tgz: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==, tarball: https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.2.tgz} + version: 1.1.2 + engines: {node: '>= 0.8'} + + 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@6.3.0: + resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + + foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + + form-data@3.0.1: + resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} + engines: {node: '>= 6'} + + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + + frac@1.1.2: + resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==} + engines: {node: '>=0.8'} + + fragment-cache@0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fstream@1.0.12: + resolution: {integrity: sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==} + engines: {node: '>=0.6'} + + function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + 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.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-stdin@9.0.0: + resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} + engines: {node: '>=12'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-value@2.0.6: + resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} + engines: {node: '>=0.10.0'} + + git-hooks-list@3.1.0: + resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==} + + git-raw-commits@4.0.0: + resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} + engines: {node: '>=16'} + hasBin: true + + git-semver-tags@7.0.1: + resolution: {integrity: sha512-NY0ZHjJzyyNXHTDZmj+GG7PyuAKtMsyWSwh07CR2hOZFa+/yoTsXci/nF2obzL8UDhakFNkD9gNdt/Ed+cxh2Q==} + engines: {node: '>=16'} + hasBin: true + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, tarball: https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz} + version: 5.1.2 + engines: {node: '>= 6'} + + glob@10.3.12: + resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + + global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + globjoin@0.1.4: + resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + + has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-flag@https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, tarball: https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz} + version: 3.0.0 + engines: {node: '>=4'} + + has-flag@https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, tarball: https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz} + version: 4.0.0 + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-value@0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} + + has-value@1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + + has-values@0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + + has-values@1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + + has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + hosted-git-info@7.0.1: + resolution: {integrity: sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==} + engines: {node: ^16.14.0 || >=18.0.0} + + html-encoding-sniffer@2.0.1: + resolution: {integrity: sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==} + engines: {node: '>=10'} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + html-minifier-terser@6.1.0: + resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} + engines: {node: '>=12'} + hasBin: true + + html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + + htmlparser2@3.10.1: + resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==} + + htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + + http-proxy-agent@4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + husky@9.0.11: + resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} + engines: {node: '>=18'} + hasBin: true + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + 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 + + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + + immutable@4.3.4: + resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + + import-local@3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + + import-meta-resolve@4.0.0: + resolution: {integrity: sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + inherits@https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, tarball: https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz} + version: 2.0.4 + + 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} + + is-accessor-descriptor@0.1.6: + resolution: {integrity: sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==} + engines: {node: '>=0.10.0'} + + is-accessor-descriptor@1.0.0: + resolution: {integrity: sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==} + engines: {node: '>=0.10.0'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-binary-path@https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==, tarball: https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz} + version: 2.1.0 + engines: {node: '>=8'} + + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + + is-core-module@2.13.0: + resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} + + is-data-descriptor@0.1.4: + resolution: {integrity: sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==} + engines: {node: '>=0.10.0'} + + is-data-descriptor@1.0.0: + resolution: {integrity: sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==} + engines: {node: '>=0.10.0'} + + is-descriptor@0.1.6: + resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} + engines: {node: '>=0.10.0'} + + is-descriptor@1.0.2: + resolution: {integrity: sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==} + engines: {node: '>=0.10.0'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + + is-extendable@1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-extglob@https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, tarball: https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz} + version: 2.1.1 + engines: {node: '>=0.10.0'} + + 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.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-glob@https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, tarball: https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz} + version: 4.0.3 + engines: {node: '>=0.10.0'} + + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + + is-number@3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-number@https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, tarball: https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz} + version: 7.0.0 + engines: {node: '>=0.12.0'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + + 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-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + + 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-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + + is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + + is-what@3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + + 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'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isobject@2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + + istanbul-lib-coverage@3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + + istanbul-reports@3.1.6: + resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} + engines: {node: '>=8'} + + jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + + jake@10.8.7: + resolution: {integrity: sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==} + engines: {node: '>=10'} + hasBin: true + + jest-changed-files@27.5.1: + resolution: {integrity: sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-circus@27.5.1: + resolution: {integrity: sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-cli@27.5.1: + resolution: {integrity: sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@27.5.1: + resolution: {integrity: sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + ts-node: '>=9.0.0' + peerDependenciesMeta: + ts-node: + optional: true + + jest-diff@27.5.1: + resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-docblock@27.5.1: + resolution: {integrity: sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-each@27.5.1: + resolution: {integrity: sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-environment-jsdom@27.5.1: + resolution: {integrity: sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-environment-node@27.5.1: + resolution: {integrity: sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-get-type@27.5.1: + resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-haste-map@27.5.1: + resolution: {integrity: sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-jasmine2@27.5.1: + resolution: {integrity: sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-leak-detector@27.5.1: + resolution: {integrity: sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-matcher-utils@27.5.1: + resolution: {integrity: sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-message-util@27.5.1: + resolution: {integrity: sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-mock@27.5.1: + resolution: {integrity: sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@27.5.1: + resolution: {integrity: sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-resolve-dependencies@27.5.1: + resolution: {integrity: sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-resolve@27.5.1: + resolution: {integrity: sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-runner@27.5.1: + resolution: {integrity: sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-runtime@27.5.1: + resolution: {integrity: sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-serializer@27.5.1: + resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-snapshot@27.5.1: + resolution: {integrity: sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-util@27.5.1: + resolution: {integrity: sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-validate@27.5.1: + resolution: {integrity: sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-watcher@27.5.1: + resolution: {integrity: sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + + jest@27.5.1: + resolution: {integrity: sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jiti@1.19.3: + resolution: {integrity: sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==} + hasBin: true + + jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + js-base64@2.6.4: + resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} + + js-beautify@1.14.9: + resolution: {integrity: sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==} + engines: {node: '>=12'} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-tokens@8.0.1: + resolution: {integrity: sha512-3AGrZT6tuMm1ZWWn9mLXh7XMfi2YtiLNPALCVxBCiUVq0LD1OQMxV/AdS/s7rLJU5o9i/jBZw/N4vXXL5dm29A==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsdom@16.7.0: + resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} + engines: {node: '>=10'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + + 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-parse-even-better-errors@3.0.1: + resolution: {integrity: sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + 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-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + + kind-of@4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + + kind-of@5.1.0: + resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} + engines: {node: '>=0.10.0'} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + known-css-properties@0.29.0: + resolution: {integrity: sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==} + + known-css-properties@0.30.0: + resolution: {integrity: sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==} + + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + + less@4.2.0: + resolution: {integrity: sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==} + engines: {node: '>=6'} + hasBin: true + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + + lilconfig@3.0.0: + resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lines-and-columns@2.0.4: + resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lint-staged@15.2.2: + resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} + engines: {node: '>=18.12.0'} + hasBin: true + + listenercount@1.0.1: + resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==} + + listr2@8.0.1: + resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} + engines: {node: '>=18.0.0'} + + loader-utils@1.4.2: + resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} + engines: {node: '>=4.0.0'} + + local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + + 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} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.difference@4.5.0: + resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} + + lodash.escaperegexp@4.1.2: + resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==} + + lodash.flatten@4.4.0: + resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + + lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + + lodash.groupby@4.6.0: + resolution: {integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + + lodash.isfunction@3.0.9: + resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} + + lodash.isnil@4.0.0: + resolution: {integrity: sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isundefined@3.0.1: + resolution: {integrity: sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==} + + lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + + 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.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash.union@4.6.0: + resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} + + 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.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-update@6.0.0: + resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + engines: {node: '>=18'} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lru-cache@10.0.1: + resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==} + engines: {node: 14 || >=16.14} + + lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} + engines: {node: 14 || >=16.14} + + 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'} + + magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + + magic-string@0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} + + magic-string@0.30.10: + resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} + + magic-string@0.30.3: + resolution: {integrity: sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==} + engines: {node: '>=12'} + + make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + + map-visit@1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + + mathml-tag-names@2.1.3: + resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} + + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + + 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-options@1.0.1: + resolution: {integrity: sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==} + engines: {node: '>=4'} + + 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'} + + merge2@https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, tarball: https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz} + version: 1.4.1 + engines: {node: '>= 8'} + + micromatch@3.1.0: + resolution: {integrity: sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==} + engines: {node: '>=0.10.0'} + + micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + minimatch@3.0.8: + resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} + + 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@9.0.1: + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} + engines: {node: '>=16 || 14 >=14.17'} + + minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.7: + resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + + mixin-deep@1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + mkdist@1.3.0: + resolution: {integrity: sha512-ZQrUvcL7LkRdzMREpDyg9AT18N9Tl5jc2qeKAUeEw0KGsgykbHbuRvysGAzTuGtwuSg0WQyNit5jh/k+Er3JEg==} + hasBin: true + peerDependencies: + sass: ^1.63.6 + typescript: '>=5.1.6' + peerDependenciesMeta: + sass: + optional: true + typescript: + optional: true + + mlly@1.4.1: + resolution: {integrity: sha512-SCDs78Q2o09jiZiE2WziwVBEqXQ02XkGdUy45cbJf+BpYRIjArXRJ1Wbowxkb+NaM9DWvS3UC9GiO/6eqvQ/pg==} + + mlly@1.6.1: + resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==} + + mockjs@1.1.0: + resolution: {integrity: sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==} + hasBin: true + + mousetrap@1.6.5: + resolution: {integrity: sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + ms@https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==, tarball: https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz} + version: 2.0.0 + + ms@https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==, tarball: https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz} + version: 2.1.2 + + ms@https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, tarball: https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz} + version: 2.1.3 + + muggle-string@0.3.1: + resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanomatch@1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + + nanopop@2.3.0: + resolution: {integrity: sha512-fzN+T2K7/Ah25XU02MJkPZ5q4Tj5FpjmIYq4rvoHX4yb16HzFdCO6JxFFn5Y/oBhQ8no8fUZavnyIv9/+xkBBw==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + needle@3.2.0: + resolution: {integrity: sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-fetch-native@1.6.4: + resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} + + 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-html-parser@5.4.2: + resolution: {integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==} + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + + nopt@6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + + normalize-package-data@6.0.0: + resolution: {integrity: sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==} + engines: {node: ^16.14.0 || >=18.0.0} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-path@https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, tarball: https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz} + version: 3.0.0 + engines: {node: '>=0.10.0'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + npm-run-path@5.1.0: + resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + nprogress@0.2.0: + resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + nwsapi@2.2.7: + resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-copy@0.1.0: + resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + + object-visit@1.0.1: + resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} + engines: {node: '>=0.10.0'} + + object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + + ofetch@1.3.4: + resolution: {integrity: sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==} + + on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + + on-finished@https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==, tarball: https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz} + version: 2.3.0 + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + 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-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + 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'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-json@7.1.1: + resolution: {integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==} + engines: {node: '>=16'} + + parse-node-version@1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + + parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + parseurl@https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==, tarball: https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz} + version: 1.3.3 + engines: {node: '>= 0.8'} + + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + + pascalcase@0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + + 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-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + 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.10.2: + resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} + engines: {node: '>=16 || 14 >=14.17'} + + path-to-regexp@6.2.2: + resolution: {integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@0.2.0: + resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} + + pathe@1.1.1: + resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + + picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pinia-plugin-persistedstate@3.2.1: + resolution: {integrity: sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ==} + peerDependencies: + pinia: ^2.0.0 + + pinia@2.1.7: + resolution: {integrity: sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==} + peerDependencies: + '@vue/composition-api': ^1.4.0 + typescript: '>=4.4.4' + vue: ^2.6.14 || ^3.3.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + typescript: + optional: true + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + pkg-types@1.1.0: + resolution: {integrity: sha512-/RpmvKdxKf8uILTtoOhAgf30wYbP2Qw+L9p3Rvshx1JZVX+XQNZQFjlbmGHEGIm4CkVPlSn+NXmIM8+9oWQaSA==} + + pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + + posix-character-classes@0.1.1: + resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} + engines: {node: '>=0.10.0'} + + postcss-html@1.6.0: + resolution: {integrity: sha512-OWgQ9/Pe23MnNJC0PL4uZp8k0EDaUvqpJFSiwFxOLClAhmD7UEisyhO3x5hVsD4xFrjReVTXydlrMes45dJ71w==} + engines: {node: ^12 || >=14} + + postcss-less@6.0.0: + resolution: {integrity: sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==} + engines: {node: '>=12'} + peerDependencies: + postcss: ^8.3.5 + + postcss-media-query-parser@0.2.3: + resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} + + postcss-prefix-selector@1.16.0: + resolution: {integrity: sha512-rdVMIi7Q4B0XbXqNUEI+Z4E+pueiu/CS5E6vRCQommzdQ/sgsS4dK42U7GX8oJR+TJOtT+Qv3GkNo6iijUMp3Q==} + peerDependencies: + postcss: '>4 <9' + + postcss-resolve-nested-selector@0.1.1: + resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==} + + 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.0: + resolution: {integrity: sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==} + 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-parser@6.0.16: + resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} + engines: {node: '>=4'} + + postcss-sorting@8.0.2: + resolution: {integrity: sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==} + peerDependencies: + postcss: ^8.4.20 + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@5.2.18: + resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==} + engines: {node: '>=0.12'} + + postcss@8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + + posthtml-parser@0.2.1: + resolution: {integrity: sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==} + + posthtml-rename-id@1.0.12: + resolution: {integrity: sha512-UKXf9OF/no8WZo9edRzvuMenb6AD5hDLzIepJW+a4oJT+T/Lx7vfMYWT4aWlGNQh0WMhnUx1ipN9OkZ9q+ddEw==} + + posthtml-render@1.4.0: + resolution: {integrity: sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==} + engines: {node: '>=10'} + + posthtml-svg-mode@1.0.3: + resolution: {integrity: sha512-hEqw9NHZ9YgJ2/0G7CECOeuLQKZi8HjWLkBaSVtOWjygQ9ZD8P7tqeowYs7WrFdKsWEKG7o+IlsPY8jrr0CJpQ==} + + posthtml@0.9.2: + resolution: {integrity: sha512-spBB5sgC4cv2YcW03f/IAUN1pgDJWNWD8FzkyY4mArLUMJW+KlQhlmUdKAHQuPfb00Jl5xIfImeOsf6YL8QK7Q==} + engines: {node: '>=0.10.0'} + + preact@10.17.1: + resolution: {integrity: sha512-X9BODrvQ4Ekwv9GURm9AKAGaomqXmip7NQTZgY7gcNmr7XE83adOMJvd3N42id1tMFU7ojiynRsYnY6/BRFxLA==} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier-plugin-packagejson@2.5.0: + resolution: {integrity: sha512-6XkH3rpin5QEQodBSVNg+rBo4r91g/1mCaRwS1YGdQJZ6jwqrg2UchBsIG9tpS1yK1kNBvOt84OILsX8uHzBGg==} + peerDependencies: + prettier: '>= 1.16.0' + peerDependenciesMeta: + prettier: + optional: true + + prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + + pretty-bytes@6.1.1: + resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} + engines: {node: ^14.13.1 || >=16.0.0} + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + print-js@1.6.0: + resolution: {integrity: sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg==} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + 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==} + + psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + + punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + + qrcode@1.5.3: + resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==} + engines: {node: '>=10.13.0'} + hasBin: true + + qs@6.12.1: + resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} + engines: {node: '>=0.6'} + + query-string@4.3.4: + resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==} + engines: {node: '>=0.10.0'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + queue-microtask@https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, tarball: https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz} + version: 1.2.3 + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + read-pkg-up@10.1.0: + resolution: {integrity: sha512-aNtBq4jR8NawpKJQldrQcSW9y/d+KWH4v24HWkHljOZ7H0av+YTGANBzRh9A5pw7v/bLVsLVPpOhJ7gHNVy8lA==} + engines: {node: '>=16'} + + read-pkg@8.1.0: + resolution: {integrity: sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==} + engines: {node: '>=16'} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + 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@https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, tarball: https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz} + version: 3.6.0 + engines: {node: '>=8.10.0'} + + regenerator-runtime@0.14.0: + resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} + + regex-not@1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + + relateurl@0.2.7: + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} + + repeat-element@1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + + repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + + 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==} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resize-observer-polyfill@1.5.1: + resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-from@https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, tarball: https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz} + version: 4.0.0 + engines: {node: '>=4'} + + resolve-url@0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + + resolve.exports@1.1.1: + resolution: {integrity: sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==} + engines: {node: '>=10'} + + resolve@1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + + resolve@1.22.4: + resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} + hasBin: true + + restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + ret@0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + reusify@https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==, tarball: https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz} + version: 1.0.4 + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + + rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + hasBin: true + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + + rimraf@5.0.5: + resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} + engines: {node: '>=14'} + hasBin: true + + rollup-plugin-dts@6.1.0: + resolution: {integrity: sha512-ijSCPICkRMDKDLBK9torss07+8dl9UpY9z1N/zTeA1cIqdzMlpkV3MOOC7zukyvQfDyxa1s3Dl2+DeiP/G6DOw==} + engines: {node: '>=16'} + peerDependencies: + rollup: ^3.29.4 || ^4 + typescript: ^4.5 || ^5.0 + + rollup-plugin-purge-icons@0.10.0: + resolution: {integrity: sha512-GD2ftg4L9G/sagIhtCmBn5vdyzePOisniythubpbywP0Q3ix9rZuDeFvgXTPemOsc22pvH7t22ryYQIl0rwGog==} + engines: {node: '>= 12'} + + rollup-plugin-visualizer@5.12.0: + resolution: {integrity: sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ==} + engines: {node: '>=14'} + hasBin: true + peerDependencies: + rollup: 2.x || 3.x || 4.x + peerDependenciesMeta: + rollup: + optional: true + + rollup@3.28.1: + resolution: {integrity: sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + + rollup@4.17.0: + resolution: {integrity: sha512-wZJSn0WMtWrxhYKQRt5Z6GIXlziOoMDFmbHmRfL3v+sBTAshx2DBq1AfMArB7eIjF63r4ocn2ZTAyUptg/7kmQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + run-parallel@https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, tarball: https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz} + version: 1.2.0 + + 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-regex@1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sass@1.75.0: + resolution: {integrity: sha512-ShMYi3WkrDWxExyxSZPst4/okE9ts46xZmJDSawJQrnte7M1V9fScVB+uNXOVKRBt0PggHOwoZcn8mYX4trnBw==} + engines: {node: '>=14.0.0'} + hasBin: true + + sax@1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + + saxes@5.0.1: + resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} + engines: {node: '>=10'} + + scroll-into-view-if-needed@2.2.31: + resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} + + scule@1.0.0: + resolution: {integrity: sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==} + + 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.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true + + semver@https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==, tarball: https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz} + version: 5.7.2 + hasBin: true + + 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-value@2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + 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'} + + showdown@2.1.0: + resolution: {integrity: sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==} + hasBin: true + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + + 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.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + + snapdragon-node@2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + + snapdragon-util@3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + + snapdragon@0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + + sort-object-keys@1.1.3: + resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} + + sort-package-json@2.10.0: + resolution: {integrity: sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g==} + hasBin: true + + sortablejs@1.14.0: + resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==} + + sortablejs@1.15.2: + resolution: {integrity: sha512-FJF5jgdfvoKn1MAKSdGs33bIqLi3LmsgVTliuX6iITj834F+JRQZN90Z93yql8h0K2t0RwDPBmxwlbZfDcxNZA==} + + source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + + source-map-resolve@0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map-url@0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + + sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + + spdx-correct@3.1.1: + resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} + + spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.12: + resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} + + split-string@3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + 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==} + + ssf@0.11.2: + resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==} + engines: {node: '>=0.8'} + + stable@0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + static-extend@0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + statuses@https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==, tarball: https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz} + version: 1.5.0 + engines: {node: '>= 0.6'} + + strict-uri-encode@1.1.0: + resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} + engines: {node: '>=0.10.0'} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + 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.1.0: + resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} + engines: {node: '>=18'} + + 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==} + + strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + 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-property-sort-order-smacss@10.0.0: + resolution: {integrity: sha512-NuiTgyqD8UdYY1IpTBIodBbrWKwaib5r8sq5kGHQ52UrmT8O7Fa8ZWYGipSZw6k9tGoljl9Hng2jtH+wBTMa1Q==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^14.0.0 || ^15.0.0 || ^16.0.0 + + stylelint-config-recommended-scss@14.0.0: + resolution: {integrity: sha512-HDvpoOAQ1RpF+sPbDOT2Q2/YrBDEJDnUymmVmZ7mMCeNiFSdhRdyGEimBkz06wsN+HaFwUh249gDR+I9JR7Onw==} + engines: {node: '>=18.12.0'} + peerDependencies: + postcss: ^8.3.3 + stylelint: ^16.0.2 + peerDependenciesMeta: + postcss: + optional: true + + stylelint-config-recommended-vue@1.5.0: + resolution: {integrity: sha512-65TAK/clUqkNtkZLcuytoxU0URQYlml+30Nhop7sRkCZ/mtWdXt7T+spPSB3KMKlb+82aEVJ4OrcstyDBdbosg==} + engines: {node: ^12 || >=14} + peerDependencies: + postcss-html: ^1.0.0 + stylelint: '>=14.0.0' + + stylelint-config-recommended@12.0.0: + resolution: {integrity: sha512-x6x8QNARrGO2sG6iURkzqL+Dp+4bJorPMMRNPScdvaUK8PsynriOcMW7AFDKqkWAS5wbue/u8fUT/4ynzcmqdQ==} + peerDependencies: + stylelint: ^15.5.0 + + stylelint-config-recommended@14.0.0: + resolution: {integrity: sha512-jSkx290CglS8StmrLp2TxAppIajzIBZKYm3IxT89Kg6fGlxbPiTiyH9PS5YUuVAFwaJLl1ikiXX0QWjI0jmgZQ==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.0.0 + + stylelint-config-standard-scss@13.1.0: + resolution: {integrity: sha512-Eo5w7/XvwGHWkeGLtdm2FZLOMYoZl1omP2/jgFCXyl2x5yNz7/8vv4Tj6slHvMSSUNTaGoam/GAZ0ZhukvalfA==} + engines: {node: '>=18.12.0'} + peerDependencies: + postcss: ^8.3.3 + stylelint: ^16.3.1 + peerDependenciesMeta: + postcss: + optional: true + + stylelint-config-standard@36.0.0: + resolution: {integrity: sha512-3Kjyq4d62bYFp/Aq8PMKDwlgUyPU4nacXsjDLWJdNPRUgpuxALu1KnlAHIj36cdtxViVhXexZij65yM0uNIHug==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.1.0 + + stylelint-order@6.0.4: + resolution: {integrity: sha512-0UuKo4+s1hgQ/uAxlYU4h0o0HS4NiQDud0NAUNI0aa8FJdmYHA5ZZTFHiV5FpmE3071e9pZx5j0QpVJW5zOCUA==} + peerDependencies: + stylelint: ^14.0.0 || ^15.0.0 || ^16.0.1 + + stylelint-prettier@5.0.0: + resolution: {integrity: sha512-RHfSlRJIsaVg5Br94gZVdWlz/rBTyQzZflNE6dXvSxt/GthWMY3gEHsWZEBaVGg7GM+XrtVSp4RznFlB7i0oyw==} + engines: {node: '>=18.12.0'} + peerDependencies: + prettier: '>=3.0.0' + stylelint: '>=16.0.0' + + stylelint-scss@6.2.1: + resolution: {integrity: sha512-ZoGLbVb1keZYRVGQlhB8G6sZOoNqw61whzzzGFWp05N12ErqLFfBv3JPrXiMLZaW98sBS7K/vUQhRnvUj4vwdw==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.0.2 + + stylelint@16.4.0: + resolution: {integrity: sha512-uSx7VMuXwLuYcNSIg+0/fFNv0WinsfLAqsVVy7h7p80clKOHiGE8pfY6UjqwylTHiJrRIahTl6a8FPxGezhWoA==} + engines: {node: '>=18.12.0'} + hasBin: true + + stylis@4.3.0: + resolution: {integrity: sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==} + + supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + + supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + 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-color@https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, tarball: https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz} + version: 5.5.0 + engines: {node: '>=4'} + + supports-color@https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, tarball: https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz} + version: 7.2.0 + engines: {node: '>=8'} + + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + + supports-hyperlinks@3.0.0: + resolution: {integrity: sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==} + engines: {node: '>=14.18'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svg-baker@1.7.0: + resolution: {integrity: sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==} + + svg-tags@1.0.0: + resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + + svgo@2.8.0: + resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} + engines: {node: '>=10.13.0'} + hasBin: true + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + synckit@0.9.0: + resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==} + engines: {node: ^14.18.0 || >=16.0.0} + + table@6.8.2: + resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==} + engines: {node: '>=10.0.0'} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + temp-dir@3.0.0: + resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} + engines: {node: '>=14.16'} + + tempfile@5.0.0: + resolution: {integrity: sha512-bX655WZI/F7EoTDw9JvQURqAXiPHi8o8+yFxPF2lWYyz1aHnmMRuXWqL6YB6GmeO0o4DIYWHLgGNi/X64T+X4Q==} + engines: {node: '>=14.18'} + + terminal-link@2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + + terser@5.19.3: + resolution: {integrity: sha512-pQzJ9UJzM0IgmT4FAtYI6+VqFf0lj/to58AV0Xfgg0Up37RyPG7Al+1cepC6/BVuAxR9oNb41/DL4DEoHJvTdg==} + engines: {node: '>=10'} + hasBin: true + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + + throat@6.0.2: + resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==} + + throttle-debounce@5.0.0: + resolution: {integrity: sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==} + engines: {node: '>=12.22'} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + tinymce@5.10.9: + resolution: {integrity: sha512-5bkrors87X9LhYX2xq8GgPHrIgJYHl87YNs+kBcjQ5I3CiUgzo/vFcGvT3MZQ9QHsEeYMhYO6a5CLGGffR8hMg==} + + tmp@0.2.1: + resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} + engines: {node: '>=8.17.0'} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + to-object-path@0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + + to-regex-range@2.1.1: + resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} + engines: {node: '>=0.10.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + to-regex-range@https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, tarball: https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz} + version: 5.0.1 + engines: {node: '>=8.0'} + + to-regex@3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} + engines: {node: '>=6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tr46@2.1.0: + resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==} + engines: {node: '>=8'} + + traverse@0.3.9: + resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} + + traverse@0.6.7: + resolution: {integrity: sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==} + + ts-node@10.9.1: + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + + tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + turbo-darwin-64@1.13.3: + resolution: {integrity: sha512-glup8Qx1qEFB5jerAnXbS8WrL92OKyMmg5Hnd4PleLljAeYmx+cmmnsmLT7tpaVZIN58EAAwu8wHC6kIIqhbWA==} + cpu: [x64] + os: [darwin] + + turbo-darwin-arm64@1.13.3: + resolution: {integrity: sha512-/np2xD+f/+9qY8BVtuOQXRq5f9LehCFxamiQnwdqWm5iZmdjygC5T3uVSYuagVFsZKMvX3ycySwh8dylGTl6lg==} + cpu: [arm64] + os: [darwin] + + turbo-linux-64@1.13.3: + resolution: {integrity: sha512-G+HGrau54iAnbXLfl+N/PynqpDwi/uDzb6iM9hXEDG+yJnSJxaHMShhOkXYJPk9offm9prH33Khx2scXrYVW1g==} + cpu: [x64] + os: [linux] + + turbo-linux-arm64@1.13.3: + resolution: {integrity: sha512-qWwEl5VR02NqRyl68/3pwp3c/olZuSp+vwlwrunuoNTm6JXGLG5pTeme4zoHNnk0qn4cCX7DFrOboArlYxv0wQ==} + cpu: [arm64] + os: [linux] + + turbo-windows-64@1.13.3: + resolution: {integrity: sha512-Nudr4bRChfJzBPzEmpVV85VwUYRCGKecwkBFpbp2a4NtrJ3+UP1VZES653ckqCu2FRyRuS0n03v9euMbAvzH+Q==} + cpu: [x64] + os: [win32] + + turbo-windows-arm64@1.13.3: + resolution: {integrity: sha512-ouJCgsVLd3icjRLmRvHQDDZnmGzT64GBupM1Y+TjtYn2LVaEBoV6hicFy8x5DUpnqdLy+YpCzRMkWlwhmkX7sQ==} + cpu: [arm64] + os: [win32] + + turbo@1.13.3: + resolution: {integrity: sha512-n17HJv4F4CpsYTvKzUJhLbyewbXjq1oLCi90i5tW1TiWDz16ML1eDG7wi5dHaKxzh5efIM56SITnuVbMq5dk4g==} + hasBin: true + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + + type-fest@4.17.0: + resolution: {integrity: sha512-9flrz1zkfLRH3jO3bLflmTxryzKMxVa7841VeMgBaNQGY6vH4RCcpN/sQLB7mQQYh1GZ5utT2deypMuCy4yicw==} + engines: {node: '>=16'} + + typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + + typescript@5.4.2: + resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} + engines: {node: '>=14.17'} + hasBin: true + + typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.3.0: + resolution: {integrity: sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw==} + + ufo@1.5.3: + resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} + + uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + + unbuild@2.0.0: + resolution: {integrity: sha512-JWCUYx3Oxdzvw2J9kTAp+DKE8df/BnH/JTSj6JyA4SH40ECdFu7FoJJcrm8G92B7TjofQ6GZGjJs50TRxoH6Wg==} + hasBin: true + peerDependencies: + typescript: ^5.1.6 + peerDependenciesMeta: + typescript: + optional: true + + unconfig@0.3.13: + resolution: {integrity: sha512-N9Ph5NC4+sqtcOjPfHrRcHekBCadCXWTBzp2VYYbySOHW0PfD9XLCeXshTXjkPYwLrBr9AtSeU0CZmkYECJhng==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + + union-value@1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + + unocss@0.59.4: + resolution: {integrity: sha512-QmCVjRObvVu/gsGrJGVt0NnrdhFFn314BUZn2WQyXV9rIvHLRmG5bIu0j5vibJkj7ZhFchTrnTM1pTFXP1xt5g==} + engines: {node: '>=14'} + peerDependencies: + '@unocss/webpack': 0.59.4 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + '@unocss/webpack': + optional: true + vite: + optional: true + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + unpipe@https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==, tarball: https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz} + version: 1.0.0 + engines: {node: '>= 0.8'} + + unset-value@1.0.0: + resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} + engines: {node: '>=0.10.0'} + + untyped@1.4.0: + resolution: {integrity: sha512-Egkr/s4zcMTEuulcIb7dgURS6QpN7DyqQYdf+jBtiaJvQ+eRsrtWUoX84SbvQWuLkXsOjM+8sJC9u6KoMK/U7Q==} + hasBin: true + + unzipper@0.10.14: + resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==} + + update-browserslist-db@1.0.13: + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + urix@0.1.0: + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} + deprecated: Please see https://github.com/lydell/urix#deprecated + + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + + use@3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + utils-merge@https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==, tarball: https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz} + version: 1.0.1 + engines: {node: '>= 0.4.0'} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + v8-to-istanbul@8.1.1: + resolution: {integrity: sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==} + engines: {node: '>=10.12.0'} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + validator@13.11.0: + resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} + engines: {node: '>= 0.10'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vditor@3.10.4: + resolution: {integrity: sha512-NWaMom0buUvRjOCaK/jKeJEVfZNmfTgblK4+pxBoeTdiCYn5yWokcGYMh9GzHIvt5gy6FiQFc1VQvytIwyeIwA==} + + 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@3.9.0: + resolution: {integrity: sha512-pwFIEYQ3LZvMafkEGvNnileb6af5JuyZsBfYQrTDYxdeGEy0OS4B4hCsLPo5YGnhK5k9EzyO6BXVO6y+Lt5T2A==} + engines: {node: ^14.18.0 || >=16.0.0} + 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-mock@2.9.8: + resolution: {integrity: sha512-YTQM5Sn7t+/DNOwTkr+W26QGTCk1PrDkhGHslTJ90lIPJhJtDTwuSkEYMAuLP9TcVQ/qExTFx/x/GE3kxJ05sw==} + engines: {node: '>=12.0.0'} + peerDependencies: + mockjs: '>=1.1.0' + vite: '>=2.0.0' + + vite-plugin-mock@https://registry.npmmirror.com/vite-plugin-mock/-/vite-plugin-mock-2.9.8.tgz: + resolution: {integrity: sha512-YTQM5Sn7t+/DNOwTkr+W26QGTCk1PrDkhGHslTJ90lIPJhJtDTwuSkEYMAuLP9TcVQ/qExTFx/x/GE3kxJ05sw==, tarball: https://registry.npmmirror.com/vite-plugin-mock/-/vite-plugin-mock-2.9.8.tgz} + version: 2.9.8 + engines: {node: '>=12.0.0'} + peerDependencies: + mockjs: '>=1.1.0' + vite: '>=2.0.0' + + vite-plugin-purge-icons@0.10.0: + resolution: {integrity: sha512-4fMJKQuBu9lAPJWjqGEytRaxty1pP9bWgQLA68dwbbaCXu6NBrOUb/3kMaUc7TP09kerEk+qTriCk05OZXpjwA==} + engines: {node: '>= 12'} + peerDependencies: + vite: '>=2' + + vite-plugin-svg-icons@2.0.1: + resolution: {integrity: sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==} + peerDependencies: + vite: '>=2.0.0' + + vite-plugin-vue-inspector@5.0.1: + resolution: {integrity: sha512-R93P8iFa6BPODhc/aOtO04A8FFMMyFIfm8ZVSmN+8vU1TgwsHya734APGpX4fVHSPX2aVwYyiezXBUYQ0Opsqw==} + peerDependencies: + vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 + + vite@5.2.10: + resolution: {integrity: sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==} + 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: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vue-component-type-helpers@2.0.14: + resolution: {integrity: sha512-DInfgOyXlMyliyqAAD9frK28tTfch0+tMi4qoWJcZlRxUf+NFAtraJBnAsKLep+FOyLMiajkhfyEb3xLK08i7w==} + + vue-demi@0.14.0: + resolution: {integrity: sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-demi@0.14.6: + resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-demi@0.14.7: + resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-i18n@9.13.1: + resolution: {integrity: sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==} + engines: {node: '>= 16'} + peerDependencies: + vue: ^3.0.0 + + vue-json-pretty@2.4.0: + resolution: {integrity: sha512-e9bP41DYYIc2tWaB6KuwqFJq5odZ8/GkE6vHQuGcbPn37kGk4a3n1RNw3ZYeDrl66NWXgTlOfS+M6NKkowmkWw==} + engines: {node: '>= 10.0.0', npm: '>= 5.0.0'} + peerDependencies: + vue: '>=3.0.0' + + vue-router@4.3.2: + resolution: {integrity: sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==} + peerDependencies: + vue: ^3.2.0 + + vue-template-compiler@2.7.14: + resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} + + vue-tsc@1.8.27: + resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==} + hasBin: true + peerDependencies: + typescript: '*' + + vue-tsc@2.0.14: + resolution: {integrity: sha512-DgAO3U1cnCHOUO7yB35LENbkapeRsBZ7Ugq5hGz/QOHny0+1VQN8eSwSBjYbjLVPfvfw6EY7sNPjbuHHUhckcg==} + hasBin: true + peerDependencies: + typescript: '*' + + vue-types@3.0.2: + resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==} + engines: {node: '>=10.15.0'} + peerDependencies: + vue: ^3.0.0 + + vue-types@5.1.1: + resolution: {integrity: sha512-FMY/JCLWePXgGIcMDqYdJsQm1G0CDxEjq6W0+tZMJZlX37q/61eSGSIa/XFRwa9T7kkKXuxxl94/2kgxyWQqKw==} + engines: {node: '>=14.0.0'} + peerDependencies: + vue: ^2.0.0 || ^3.0.0 + peerDependenciesMeta: + vue: + optional: true + + vue@3.2.47: + resolution: {integrity: sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==} + + vue@3.4.25: + resolution: {integrity: sha512-HWyDqoBHMgav/OKiYA2ZQg+kjfMgLt/T0vg4cbIF7JbXAjDexRf5JRg+PWAfrAkSmTd2I8aPSXtooBFWHB98cg==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + vuedraggable@https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz: + resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==, tarball: https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz} + version: 4.1.0 + peerDependencies: + vue: ^3.0.1 + + vxe-table-plugin-export-xlsx@4.0.1: + resolution: {integrity: sha512-puUOUfptu5ciEiFqTlVni3twLICSbkl87uXOsjZzrEyXJHJS9dYu7ZTD7/DRMqyuWyU3Idg7AekfcdcslP4Y/A==} + peerDependencies: + vxe-table: ^4.5.0 + + vxe-table@4.6.6: + resolution: {integrity: sha512-HZ+CVgqsIL1YfconiTW843xosPzelL/uX5yq+cbDzr+O5Yi4VFzNJjV4qr3y/nNyothQfC3MuxzyalUAF0lT+A==} + peerDependencies: + vue: ^3.2.28 + + w3c-hr-time@1.0.2: + resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} + deprecated: Use your platform's native performance.now() and performance.timeOrigin. + + w3c-xmlserializer@2.0.0: + resolution: {integrity: sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==} + engines: {node: '>=10'} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webidl-conversions@5.0.0: + resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==} + engines: {node: '>=8'} + + webidl-conversions@6.1.0: + resolution: {integrity: sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==} + engines: {node: '>=10.4'} + + whatwg-encoding@1.0.5: + resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} + + whatwg-mimetype@2.3.0: + resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + whatwg-url@8.7.0: + resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==} + engines: {node: '>=10'} + + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + + 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 + + wmf@1.0.2: + resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==} + engines: {node: '>=0.8'} + + word@0.3.0: + resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==} + engines: {node: '>=0.8'} + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + 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.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ws@7.5.9: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xe-utils@3.5.25: + resolution: {integrity: sha512-d/ty5eo4hXtho/3195XAvqereIoSYJ+XfC52f3ZEPxTaCeyLFivDZTyX6gTdsR65ISH1Irvn85H0bSL60dUhSQ==} + + xlsx@0.18.5: + resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==} + engines: {node: '>=0.8'} + hasBin: true + + xml-name-validator@3.0.0: + resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + 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==} + + yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + + 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'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + + z-schema@5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + + zip-stream@4.1.0: + resolution: {integrity: sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==} + engines: {node: '>= 10'} + + zrender@5.5.0: + resolution: {integrity: sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w==} + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@ant-design/colors@6.0.0': + dependencies: + '@ctrl/tinycolor': 3.6.1 + + '@ant-design/colors@7.0.2': + dependencies: + '@ctrl/tinycolor': 3.6.1 + + '@ant-design/icons-svg@4.3.1': {} + + '@ant-design/icons-vue@7.0.1(vue@3.4.25(typescript@5.4.5))': + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-svg': 4.3.1 + vue: 3.4.25(typescript@5.4.5) + + '@antfu/install-pkg@0.1.1': + dependencies: + execa: 5.1.1 + find-up: 5.0.0 + + '@antfu/utils@0.7.7': {} + + '@axolo/tree-array@0.1.0': {} + + '@babel/code-frame@7.22.13': + dependencies: + '@babel/highlight': 7.22.13 + chalk: https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz + + '@babel/code-frame@7.24.2': + dependencies: + '@babel/highlight': 7.24.2 + picocolors: 1.0.0 + + '@babel/compat-data@7.24.4': {} + + '@babel/core@7.24.4': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.4 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) + '@babel/helpers': 7.24.4 + '@babel/parser': 7.24.4 + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.1 + '@babel/types': 7.24.0 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.22.10': + dependencies: + '@babel/types': 7.22.11 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.19 + jsesc: 2.5.2 + + '@babel/generator@7.24.4': + dependencies: + '@babel/types': 7.24.0 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + + '@babel/helper-annotate-as-pure@7.22.5': + dependencies: + '@babel/types': 7.22.11 + + '@babel/helper-compilation-targets@7.23.6': + dependencies: + '@babel/compat-data': 7.24.4 + '@babel/helper-validator-option': 7.23.5 + browserslist: 4.23.0 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.24.4(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-member-expression-to-functions': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.4) + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + semver: 6.3.1 + + '@babel/helper-environment-visitor@7.22.20': {} + + '@babel/helper-environment-visitor@7.22.5': {} + + '@babel/helper-function-name@7.22.5': + dependencies: + '@babel/template': 7.22.5 + '@babel/types': 7.22.11 + + '@babel/helper-function-name@7.23.0': + dependencies: + '@babel/template': 7.24.0 + '@babel/types': 7.24.0 + + '@babel/helper-hoist-variables@7.22.5': + dependencies: + '@babel/types': 7.22.11 + + '@babel/helper-member-expression-to-functions@7.23.0': + dependencies: + '@babel/types': 7.24.0 + + '@babel/helper-module-imports@7.22.5': + dependencies: + '@babel/types': 7.22.11 + + '@babel/helper-module-imports@7.24.3': + dependencies: + '@babel/types': 7.24.0 + + '@babel/helper-module-transforms@7.23.3(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.24.3 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + + '@babel/helper-optimise-call-expression@7.22.5': + dependencies: + '@babel/types': 7.22.11 + + '@babel/helper-plugin-utils@7.22.5': {} + + '@babel/helper-plugin-utils@7.24.0': {} + + '@babel/helper-replace-supers@7.24.1(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-member-expression-to-functions': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + + '@babel/helper-simple-access@7.22.5': + dependencies: + '@babel/types': 7.22.11 + + '@babel/helper-skip-transparent-expression-wrappers@7.22.5': + dependencies: + '@babel/types': 7.22.11 + + '@babel/helper-split-export-declaration@7.22.6': + dependencies: + '@babel/types': 7.22.11 + + '@babel/helper-string-parser@7.22.5': {} + + '@babel/helper-string-parser@7.24.1': {} + + '@babel/helper-validator-identifier@7.22.20': {} + + '@babel/helper-validator-identifier@7.22.5': {} + + '@babel/helper-validator-option@7.23.5': {} + + '@babel/helpers@7.24.4': + dependencies: + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.1 + '@babel/types': 7.24.0 + transitivePeerDependencies: + - supports-color + + '@babel/highlight@7.22.13': + dependencies: + '@babel/helper-validator-identifier': 7.22.5 + chalk: https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz + js-tokens: 4.0.0 + + '@babel/highlight@7.24.2': + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.0 + + '@babel/parser@7.22.10': + dependencies: + '@babel/types': 7.22.10 + + '@babel/parser@7.22.13': + dependencies: + '@babel/types': 7.22.11 + + '@babel/parser@7.24.4': + dependencies: + '@babel/types': 7.22.11 + + '@babel/plugin-proposal-decorators@7.24.1(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) + '@babel/helper-plugin-utils': 7.24.0 + '@babel/plugin-syntax-decorators': 7.24.1(@babel/core@7.24.4) + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-decorators@7.24.1(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.24.0 + + '@babel/plugin-syntax-import-attributes@7.24.1(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.24.0 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.24.0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.22.5 + + '@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.24.0 + + '@babel/plugin-transform-modules-commonjs@7.24.1(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) + '@babel/helper-plugin-utils': 7.24.0 + '@babel/helper-simple-access': 7.22.5 + + '@babel/plugin-transform-typescript@7.24.4(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) + '@babel/helper-plugin-utils': 7.24.0 + '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.4) + + '@babel/preset-typescript@7.24.1(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.24.0 + '@babel/helper-validator-option': 7.23.5 + '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) + '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.4) + '@babel/plugin-transform-typescript': 7.24.4(@babel/core@7.24.4) + + '@babel/runtime@7.22.11': + dependencies: + regenerator-runtime: 0.14.0 + + '@babel/standalone@7.22.13': {} + + '@babel/template@7.22.5': + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/parser': 7.22.13 + '@babel/types': 7.22.11 + + '@babel/template@7.24.0': + dependencies: + '@babel/code-frame': 7.24.2 + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + + '@babel/traverse@7.22.11': + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.22.10 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-function-name': 7.22.5 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.22.13 + '@babel/types': 7.22.11 + debug: https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/traverse@7.24.1': + dependencies: + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.4 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.22.10': + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.5 + to-fast-properties: 2.0.0 + + '@babel/types@7.22.11': + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.5 + to-fast-properties: 2.0.0 + + '@babel/types@7.24.0': + dependencies: + '@babel/helper-string-parser': 7.24.1 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + + '@bcoe/v8-coverage@0.2.3': {} + + '@commitlint/cli@19.3.0(@types/node@20.12.7)(typescript@5.4.5)': + dependencies: + '@commitlint/format': 19.3.0 + '@commitlint/lint': 19.2.2 + '@commitlint/load': 19.2.0(@types/node@20.12.7)(typescript@5.4.5) + '@commitlint/read': 19.2.1 + '@commitlint/types': 19.0.3 + execa: 8.0.1 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/config-conventional@19.2.2': + dependencies: + '@commitlint/types': 19.0.3 + conventional-changelog-conventionalcommits: 7.0.2 + + '@commitlint/config-validator@19.0.3': + dependencies: + '@commitlint/types': 19.0.3 + ajv: 8.12.0 + + '@commitlint/ensure@19.0.3': + dependencies: + '@commitlint/types': 19.0.3 + 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.0.0': {} + + '@commitlint/format@19.3.0': + dependencies: + '@commitlint/types': 19.0.3 + chalk: 5.3.0 + + '@commitlint/is-ignored@19.2.2': + dependencies: + '@commitlint/types': 19.0.3 + semver: 7.6.0 + + '@commitlint/lint@19.2.2': + dependencies: + '@commitlint/is-ignored': 19.2.2 + '@commitlint/parse': 19.0.3 + '@commitlint/rules': 19.0.3 + '@commitlint/types': 19.0.3 + + '@commitlint/load@19.2.0(@types/node@20.12.7)(typescript@5.4.5)': + dependencies: + '@commitlint/config-validator': 19.0.3 + '@commitlint/execute-rule': 19.0.0 + '@commitlint/resolve-extends': 19.1.0 + '@commitlint/types': 19.0.3 + chalk: 5.3.0 + cosmiconfig: 9.0.0(typescript@5.4.5) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.12.7)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/message@19.0.0': {} + + '@commitlint/parse@19.0.3': + dependencies: + '@commitlint/types': 19.0.3 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 + + '@commitlint/read@19.2.1': + dependencies: + '@commitlint/top-level': 19.0.0 + '@commitlint/types': 19.0.3 + execa: 8.0.1 + git-raw-commits: 4.0.0 + minimist: 1.2.8 + + '@commitlint/resolve-extends@19.1.0': + dependencies: + '@commitlint/config-validator': 19.0.3 + '@commitlint/types': 19.0.3 + global-directory: 4.0.1 + import-meta-resolve: 4.0.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + + '@commitlint/rules@19.0.3': + dependencies: + '@commitlint/ensure': 19.0.3 + '@commitlint/message': 19.0.0 + '@commitlint/to-lines': 19.0.0 + '@commitlint/types': 19.0.3 + execa: 8.0.1 + + '@commitlint/to-lines@19.0.0': {} + + '@commitlint/top-level@19.0.0': + dependencies: + find-up: 7.0.0 + + '@commitlint/types@19.0.3': + dependencies: + '@types/conventional-commits-parser': 5.0.0 + chalk: 5.3.0 + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + optional: true + + '@csstools/css-parser-algorithms@2.6.1(@csstools/css-tokenizer@2.2.4)': + dependencies: + '@csstools/css-tokenizer': 2.2.4 + + '@csstools/css-tokenizer@2.2.4': {} + + '@csstools/media-query-list-parser@2.1.9(@csstools/css-parser-algorithms@2.6.1(@csstools/css-tokenizer@2.2.4))(@csstools/css-tokenizer@2.2.4)': + dependencies: + '@csstools/css-parser-algorithms': 2.6.1(@csstools/css-tokenizer@2.2.4) + '@csstools/css-tokenizer': 2.2.4 + + '@csstools/selector-specificity@3.0.3(postcss-selector-parser@6.0.16)': + dependencies: + postcss-selector-parser: 6.0.16 + + '@ctrl/tinycolor@3.6.1': {} + + '@dual-bundle/import-meta-resolve@4.0.0': {} + + '@emotion/hash@0.9.1': {} + + '@emotion/unitless@0.8.1': {} + + '@esbuild/aix-ppc64@0.20.2': + optional: true + + '@esbuild/android-arm64@0.18.20': + optional: true + + '@esbuild/android-arm64@0.19.2': + optional: true + + '@esbuild/android-arm64@0.20.2': + optional: true + + '@esbuild/android-arm@0.18.20': + optional: true + + '@esbuild/android-arm@0.19.2': + optional: true + + '@esbuild/android-arm@0.20.2': + optional: true + + '@esbuild/android-x64@0.18.20': + optional: true + + '@esbuild/android-x64@0.19.2': + optional: true + + '@esbuild/android-x64@0.20.2': + optional: true + + '@esbuild/darwin-arm64@0.18.20': + optional: true + + '@esbuild/darwin-arm64@0.19.2': + optional: true + + '@esbuild/darwin-arm64@0.20.2': + optional: true + + '@esbuild/darwin-x64@0.18.20': + optional: true + + '@esbuild/darwin-x64@0.19.2': + optional: true + + '@esbuild/darwin-x64@0.20.2': + optional: true + + '@esbuild/freebsd-arm64@0.18.20': + optional: true + + '@esbuild/freebsd-arm64@0.19.2': + optional: true + + '@esbuild/freebsd-arm64@0.20.2': + optional: true + + '@esbuild/freebsd-x64@0.18.20': + optional: true + + '@esbuild/freebsd-x64@0.19.2': + optional: true + + '@esbuild/freebsd-x64@0.20.2': + optional: true + + '@esbuild/linux-arm64@0.18.20': + optional: true + + '@esbuild/linux-arm64@0.19.2': + optional: true + + '@esbuild/linux-arm64@0.20.2': + optional: true + + '@esbuild/linux-arm@0.18.20': + optional: true + + '@esbuild/linux-arm@0.19.2': + optional: true + + '@esbuild/linux-arm@0.20.2': + optional: true + + '@esbuild/linux-ia32@0.18.20': + optional: true + + '@esbuild/linux-ia32@0.19.2': + optional: true + + '@esbuild/linux-ia32@0.20.2': + optional: true + + '@esbuild/linux-loong64@0.14.54': + optional: true + + '@esbuild/linux-loong64@0.18.20': + optional: true + + '@esbuild/linux-loong64@0.19.2': + optional: true + + '@esbuild/linux-loong64@0.20.2': + optional: true + + '@esbuild/linux-mips64el@0.18.20': + optional: true + + '@esbuild/linux-mips64el@0.19.2': + optional: true + + '@esbuild/linux-mips64el@0.20.2': + optional: true + + '@esbuild/linux-ppc64@0.18.20': + optional: true + + '@esbuild/linux-ppc64@0.19.2': + optional: true + + '@esbuild/linux-ppc64@0.20.2': + optional: true + + '@esbuild/linux-riscv64@0.18.20': + optional: true + + '@esbuild/linux-riscv64@0.19.2': + optional: true + + '@esbuild/linux-riscv64@0.20.2': + optional: true + + '@esbuild/linux-s390x@0.18.20': + optional: true + + '@esbuild/linux-s390x@0.19.2': + optional: true + + '@esbuild/linux-s390x@0.20.2': + optional: true + + '@esbuild/linux-x64@0.18.20': + optional: true + + '@esbuild/linux-x64@0.19.2': + optional: true + + '@esbuild/linux-x64@0.20.2': + optional: true + + '@esbuild/netbsd-x64@0.18.20': + optional: true + + '@esbuild/netbsd-x64@0.19.2': + optional: true + + '@esbuild/netbsd-x64@0.20.2': + optional: true + + '@esbuild/openbsd-x64@0.18.20': + optional: true + + '@esbuild/openbsd-x64@0.19.2': + optional: true + + '@esbuild/openbsd-x64@0.20.2': + optional: true + + '@esbuild/sunos-x64@0.18.20': + optional: true + + '@esbuild/sunos-x64@0.19.2': + optional: true + + '@esbuild/sunos-x64@0.20.2': + optional: true + + '@esbuild/win32-arm64@0.18.20': + optional: true + + '@esbuild/win32-arm64@0.19.2': + optional: true + + '@esbuild/win32-arm64@0.20.2': + optional: true + + '@esbuild/win32-ia32@0.18.20': + optional: true + + '@esbuild/win32-ia32@0.19.2': + optional: true + + '@esbuild/win32-ia32@0.20.2': + optional: true + + '@esbuild/win32-x64@0.18.20': + optional: true + + '@esbuild/win32-x64@0.19.2': + optional: true + + '@esbuild/win32-x64@0.20.2': + optional: true + + '@fast-csv/format@4.3.5': + dependencies: + '@types/node': 14.18.56 + lodash.escaperegexp: 4.1.2 + lodash.isboolean: 3.0.3 + lodash.isequal: 4.5.0 + lodash.isfunction: 3.0.9 + lodash.isnil: 4.0.0 + + '@fast-csv/parse@4.3.6': + dependencies: + '@types/node': 14.18.56 + lodash.escaperegexp: 4.1.2 + lodash.groupby: 4.6.0 + lodash.isfunction: 3.0.9 + lodash.isnil: 4.0.0 + lodash.isundefined: 3.0.1 + lodash.uniq: 4.5.0 + + '@hutson/parse-repository-url@5.0.0': {} + + '@iconify/iconify@2.1.2': + dependencies: + cross-fetch: 3.1.8 + transitivePeerDependencies: + - encoding + + '@iconify/iconify@3.1.1': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify/json@2.2.204': + dependencies: + '@iconify/types': 2.0.0 + pathe: 1.1.2 + + '@iconify/types@2.0.0': {} + + '@iconify/utils@2.1.23': + dependencies: + '@antfu/install-pkg': 0.1.1 + '@antfu/utils': 0.7.7 + '@iconify/types': 2.0.0 + debug: 4.3.4 + kolorist: 1.8.0 + local-pkg: 0.5.0 + mlly: 1.6.1 + transitivePeerDependencies: + - supports-color + + '@intlify/core-base@9.13.1': + dependencies: + '@intlify/message-compiler': 9.13.1 + '@intlify/shared': 9.13.1 + + '@intlify/message-compiler@9.13.1': + dependencies: + '@intlify/shared': 9.13.1 + source-map-js: 1.2.0 + + '@intlify/shared@9.13.1': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@27.5.1': + dependencies: + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + chalk: 4.1.2 + jest-message-util: 27.5.1 + jest-util: 27.5.1 + slash: 3.0.0 + + '@jest/core@27.5.1(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5))': + dependencies: + '@jest/console': 27.5.1 + '@jest/reporters': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.8.1 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 27.5.1 + jest-config: 27.5.1(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5)) + jest-haste-map: 27.5.1 + jest-message-util: 27.5.1 + jest-regex-util: 27.5.1 + jest-resolve: 27.5.1 + jest-resolve-dependencies: 27.5.1 + jest-runner: 27.5.1 + jest-runtime: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + jest-validate: 27.5.1 + jest-watcher: 27.5.1 + micromatch: 4.0.5 + rimraf: 3.0.2 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + '@jest/environment@27.5.1': + dependencies: + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + jest-mock: 27.5.1 + + '@jest/fake-timers@27.5.1': + dependencies: + '@jest/types': 27.5.1 + '@sinonjs/fake-timers': 8.1.0 + '@types/node': 20.12.7 + jest-message-util: 27.5.1 + jest-mock: 27.5.1 + jest-util: 27.5.1 + + '@jest/globals@27.5.1': + dependencies: + '@jest/environment': 27.5.1 + '@jest/types': 27.5.1 + expect: 27.5.1 + + '@jest/reporters@27.5.1': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-instrument: 5.2.1 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.6 + jest-haste-map: 27.5.1 + jest-resolve: 27.5.1 + jest-util: 27.5.1 + jest-worker: 27.5.1 + slash: 3.0.0 + source-map: 0.6.1 + string-length: 4.0.2 + terminal-link: 2.1.1 + v8-to-istanbul: 8.1.1 + transitivePeerDependencies: + - supports-color + + '@jest/source-map@27.5.1': + dependencies: + callsites: 3.1.0 + graceful-fs: 4.2.11 + source-map: 0.6.1 + + '@jest/test-result@27.5.1': + dependencies: + '@jest/console': 27.5.1 + '@jest/types': 27.5.1 + '@types/istanbul-lib-coverage': 2.0.4 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@27.5.1': + dependencies: + '@jest/test-result': 27.5.1 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-runtime: 27.5.1 + transitivePeerDependencies: + - supports-color + + '@jest/transform@27.5.1': + dependencies: + '@babel/core': 7.24.4 + '@jest/types': 27.5.1 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 1.9.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-regex-util: 27.5.1 + jest-util: 27.5.1 + micromatch: 4.0.5 + pirates: 4.0.6 + slash: 3.0.0 + source-map: 0.6.1 + write-file-atomic: 3.0.3 + transitivePeerDependencies: + - supports-color + + '@jest/types@27.5.1': + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 20.12.7 + '@types/yargs': 16.0.5 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.3': + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.19 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.1': {} + + '@jridgewell/set-array@1.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/source-map@0.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/sourcemap-codec@1.4.15': {} + + '@jridgewell/trace-mapping@0.3.19': + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + optional: true + + '@logicflow/core@1.2.26': + dependencies: + '@types/mousetrap': 1.6.11 + mousetrap: 1.6.5 + preact: 10.17.1 + + '@logicflow/extension@1.2.26(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5))': + dependencies: + '@logicflow/core': 1.2.26 + jest: 27.5.1(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5)) + lodash-es: 4.17.21 + preact: 10.17.1 + transitivePeerDependencies: + - bufferutil + - canvas + - node-notifier + - supports-color + - ts-node + - utf-8-validate + + '@microsoft/api-extractor-model@7.28.13(@types/node@20.12.7)': + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 4.0.2(@types/node@20.12.7) + transitivePeerDependencies: + - '@types/node' + + '@microsoft/api-extractor@7.43.0(@types/node@20.12.7)': + dependencies: + '@microsoft/api-extractor-model': 7.28.13(@types/node@20.12.7) + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 4.0.2(@types/node@20.12.7) + '@rushstack/rig-package': 0.5.2 + '@rushstack/terminal': 0.10.0(@types/node@20.12.7) + '@rushstack/ts-command-line': 4.19.1(@types/node@20.12.7) + lodash: 4.17.21 + minimatch: 3.0.8 + resolve: 1.22.4 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.4.2 + transitivePeerDependencies: + - '@types/node' + + '@microsoft/tsdoc-config@0.16.2': + dependencies: + '@microsoft/tsdoc': 0.14.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + + '@microsoft/tsdoc@0.14.2': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.scandir@https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz': + dependencies: + '@nodelib/fs.stat': https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz + run-parallel: https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.stat@https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + + '@nodelib/fs.walk@https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz': + dependencies: + '@nodelib/fs.scandir': https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz + fastq: https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz + + '@one-ini/wasm@0.1.1': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.1.1': {} + + '@polka/url@1.0.0-next.25': {} + + '@purge-icons/core@0.10.0': + dependencies: + '@iconify/iconify': 2.1.2 + axios: 0.26.1(debug@4.3.4) + debug: 4.3.4 + fast-glob: 3.3.2 + fs-extra: 10.1.0 + transitivePeerDependencies: + - encoding + - supports-color + + '@purge-icons/generated@0.10.0': + dependencies: + '@iconify/iconify': 3.1.1 + + '@rollup/plugin-alias@5.0.0(rollup@3.28.1)': + dependencies: + slash: 4.0.0 + optionalDependencies: + rollup: 3.28.1 + + '@rollup/plugin-commonjs@25.0.7(rollup@3.28.1)': + dependencies: + '@rollup/pluginutils': 5.0.4(rollup@3.28.1) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 8.1.0 + is-reference: 1.2.1 + magic-string: 0.30.3 + optionalDependencies: + rollup: 3.28.1 + + '@rollup/plugin-json@6.0.0(rollup@3.28.1)': + dependencies: + '@rollup/pluginutils': 5.0.4(rollup@3.28.1) + optionalDependencies: + rollup: 3.28.1 + + '@rollup/plugin-node-resolve@15.2.1(rollup@3.28.1)': + dependencies: + '@rollup/pluginutils': 5.0.4(rollup@3.28.1) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-builtin-module: 3.2.1 + is-module: 1.0.0 + resolve: 1.22.4 + optionalDependencies: + rollup: 3.28.1 + + '@rollup/plugin-replace@5.0.2(rollup@3.28.1)': + dependencies: + '@rollup/pluginutils': 5.0.4(rollup@3.28.1) + magic-string: 0.27.0 + optionalDependencies: + rollup: 3.28.1 + + '@rollup/pluginutils@4.2.1': + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.1 + + '@rollup/pluginutils@5.0.4(rollup@3.28.1)': + dependencies: + '@types/estree': 1.0.1 + estree-walker: 2.0.2 + picomatch: 2.3.1 + optionalDependencies: + rollup: 3.28.1 + + '@rollup/pluginutils@5.1.0(rollup@3.28.1)': + dependencies: + '@types/estree': 1.0.1 + estree-walker: 2.0.2 + picomatch: 2.3.1 + optionalDependencies: + rollup: 3.28.1 + + '@rollup/pluginutils@5.1.0(rollup@4.17.0)': + dependencies: + '@types/estree': 1.0.1 + estree-walker: 2.0.2 + picomatch: 2.3.1 + optionalDependencies: + rollup: 4.17.0 + + '@rollup/rollup-android-arm-eabi@4.17.0': + optional: true + + '@rollup/rollup-android-arm64@4.17.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.17.0': + optional: true + + '@rollup/rollup-darwin-x64@4.17.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.17.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.17.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.17.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.17.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.17.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.17.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.17.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.17.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.17.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.17.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.17.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.17.0': + optional: true + + '@rushstack/node-core-library@4.0.2(@types/node@20.12.7)': + dependencies: + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.4 + semver: 7.5.4 + z-schema: 5.0.5 + optionalDependencies: + '@types/node': 20.12.7 + + '@rushstack/rig-package@0.5.2': + dependencies: + resolve: 1.22.4 + strip-json-comments: 3.1.1 + + '@rushstack/terminal@0.10.0(@types/node@20.12.7)': + dependencies: + '@rushstack/node-core-library': 4.0.2(@types/node@20.12.7) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 20.12.7 + + '@rushstack/ts-command-line@4.19.1(@types/node@20.12.7)': + dependencies: + '@rushstack/terminal': 0.10.0(@types/node@20.12.7) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + + '@simonwep/pickr@1.8.2': + dependencies: + core-js: 3.32.1 + nanopop: 2.3.0 + + '@sinonjs/commons@1.8.6': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@8.1.0': + dependencies: + '@sinonjs/commons': 1.8.6 + + '@tootallnate/once@1.1.2': {} + + '@trysound/sax@0.2.0': {} + + '@tsconfig/node10@1.0.9': + optional: true + + '@tsconfig/node12@1.0.11': + optional: true + + '@tsconfig/node14@1.0.3': + optional: true + + '@tsconfig/node16@1.0.3': + optional: true + + '@types/argparse@1.0.38': {} + + '@types/babel__core@7.20.1': + dependencies: + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + '@types/babel__generator': 7.6.4 + '@types/babel__template': 7.4.1 + '@types/babel__traverse': 7.20.1 + + '@types/babel__generator@7.6.4': + dependencies: + '@babel/types': 7.24.0 + + '@types/babel__template@7.4.1': + dependencies: + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + + '@types/babel__traverse@7.20.1': + dependencies: + '@babel/types': 7.24.0 + + '@types/codemirror@5.60.15': + dependencies: + '@types/tern': 0.23.4 + + '@types/conventional-commits-parser@5.0.0': + dependencies: + '@types/node': 20.12.7 + + '@types/crypto-js@4.2.2': {} + + '@types/estree@1.0.1': {} + + '@types/estree@1.0.5': {} + + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.1 + '@types/node': 20.12.7 + + '@types/graceful-fs@4.1.6': + dependencies: + '@types/node': 20.12.7 + + '@types/istanbul-lib-coverage@2.0.4': {} + + '@types/istanbul-lib-report@3.0.0': + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + + '@types/istanbul-reports@3.0.1': + dependencies: + '@types/istanbul-lib-report': 3.0.0 + + '@types/jsonfile@6.1.1': + dependencies: + '@types/node': 20.12.7 + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.14.197 + + '@types/lodash@4.14.197': {} + + '@types/mockjs@1.0.10': {} + + '@types/mousetrap@1.6.11': {} + + '@types/node@14.18.56': {} + + '@types/node@20.12.7': + dependencies: + undici-types: 5.26.5 + + '@types/normalize-package-data@2.4.1': {} + + '@types/nprogress@0.2.3': {} + + '@types/prettier@2.7.3': {} + + '@types/qrcode@1.5.5': + dependencies: + '@types/node': 20.12.7 + + '@types/qs@6.9.15': {} + + '@types/resolve@1.20.2': {} + + '@types/showdown@2.0.6': {} + + '@types/sortablejs@1.15.8': {} + + '@types/stack-utils@2.0.1': {} + + '@types/svgo@2.6.4': + dependencies: + '@types/node': 20.12.7 + + '@types/tern@0.23.4': + dependencies: + '@types/estree': 1.0.1 + + '@types/web-bluetooth@0.0.16': {} + + '@types/web-bluetooth@0.0.20': {} + + '@types/yargs-parser@21.0.0': {} + + '@types/yargs@16.0.5': + dependencies: + '@types/yargs-parser': 21.0.0 + + '@unocss/astro@0.59.4(rollup@3.28.1)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3))': + dependencies: + '@unocss/core': 0.59.4 + '@unocss/reset': 0.59.4 + '@unocss/vite': 0.59.4(rollup@3.28.1)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + optionalDependencies: + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - rollup + + '@unocss/astro@0.59.4(rollup@4.17.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3))': + dependencies: + '@unocss/core': 0.59.4 + '@unocss/reset': 0.59.4 + '@unocss/vite': 0.59.4(rollup@4.17.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + optionalDependencies: + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - rollup + + '@unocss/cli@0.59.4(rollup@3.28.1)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.0(rollup@3.28.1) + '@unocss/config': 0.59.4 + '@unocss/core': 0.59.4 + '@unocss/preset-uno': 0.59.4 + cac: 6.7.14 + chokidar: 3.6.0 + colorette: 2.0.20 + consola: 3.2.3 + fast-glob: 3.3.2 + magic-string: 0.30.10 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + transitivePeerDependencies: + - rollup + + '@unocss/cli@0.59.4(rollup@4.17.0)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.0(rollup@4.17.0) + '@unocss/config': 0.59.4 + '@unocss/core': 0.59.4 + '@unocss/preset-uno': 0.59.4 + cac: 6.7.14 + chokidar: 3.6.0 + colorette: 2.0.20 + consola: 3.2.3 + fast-glob: 3.3.2 + magic-string: 0.30.10 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + transitivePeerDependencies: + - rollup + + '@unocss/config@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + unconfig: 0.3.13 + + '@unocss/core@0.59.4': {} + + '@unocss/extractor-arbitrary-variants@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + + '@unocss/inspector@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + '@unocss/rule-utils': 0.59.4 + gzip-size: 6.0.0 + sirv: 2.0.4 + + '@unocss/postcss@0.59.4(postcss@5.2.18)': + dependencies: + '@unocss/config': 0.59.4 + '@unocss/core': 0.59.4 + '@unocss/rule-utils': 0.59.4 + css-tree: 2.3.1 + fast-glob: 3.3.2 + magic-string: 0.30.10 + postcss: 5.2.18 + + '@unocss/postcss@0.59.4(postcss@8.4.38)': + dependencies: + '@unocss/config': 0.59.4 + '@unocss/core': 0.59.4 + '@unocss/rule-utils': 0.59.4 + css-tree: 2.3.1 + fast-glob: 3.3.2 + magic-string: 0.30.10 + postcss: 8.4.38 + + '@unocss/preset-attributify@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + + '@unocss/preset-icons@0.59.4': + dependencies: + '@iconify/utils': 2.1.23 + '@unocss/core': 0.59.4 + ofetch: 1.3.4 + transitivePeerDependencies: + - supports-color + + '@unocss/preset-mini@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + '@unocss/extractor-arbitrary-variants': 0.59.4 + '@unocss/rule-utils': 0.59.4 + + '@unocss/preset-tagify@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + + '@unocss/preset-typography@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + '@unocss/preset-mini': 0.59.4 + + '@unocss/preset-uno@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + '@unocss/preset-mini': 0.59.4 + '@unocss/preset-wind': 0.59.4 + '@unocss/rule-utils': 0.59.4 + + '@unocss/preset-web-fonts@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + ofetch: 1.3.4 + + '@unocss/preset-wind@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + '@unocss/preset-mini': 0.59.4 + '@unocss/rule-utils': 0.59.4 + + '@unocss/reset@0.59.4': {} + + '@unocss/rule-utils@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + magic-string: 0.30.10 + + '@unocss/scope@0.59.4': {} + + '@unocss/transformer-attributify-jsx-babel@0.59.4': + dependencies: + '@babel/core': 7.24.4 + '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) + '@babel/preset-typescript': 7.24.1(@babel/core@7.24.4) + '@unocss/core': 0.59.4 + transitivePeerDependencies: + - supports-color + + '@unocss/transformer-attributify-jsx@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + + '@unocss/transformer-compile-class@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + + '@unocss/transformer-directives@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + '@unocss/rule-utils': 0.59.4 + css-tree: 2.3.1 + + '@unocss/transformer-variant-group@0.59.4': + dependencies: + '@unocss/core': 0.59.4 + + '@unocss/vite@0.59.4(rollup@3.28.1)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.0(rollup@3.28.1) + '@unocss/config': 0.59.4 + '@unocss/core': 0.59.4 + '@unocss/inspector': 0.59.4 + '@unocss/scope': 0.59.4 + '@unocss/transformer-directives': 0.59.4 + chokidar: 3.6.0 + fast-glob: 3.3.2 + magic-string: 0.30.10 + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - rollup + + '@unocss/vite@0.59.4(rollup@4.17.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.0(rollup@4.17.0) + '@unocss/config': 0.59.4 + '@unocss/core': 0.59.4 + '@unocss/inspector': 0.59.4 + '@unocss/scope': 0.59.4 + '@unocss/transformer-directives': 0.59.4 + chokidar: 3.6.0 + fast-glob: 3.3.2 + magic-string: 0.30.10 + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - rollup + + '@vitejs/plugin-vue-jsx@3.1.0(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3))(vue@3.4.25(typescript@5.4.5))': + dependencies: + '@babel/core': 7.24.4 + '@babel/plugin-transform-typescript': 7.24.4(@babel/core@7.24.4) + '@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.24.4) + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + vue: 3.4.25(typescript@5.4.5) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-vue@5.0.4(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3))(vue@3.4.25(typescript@5.4.5))': + dependencies: + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + vue: 3.4.25(typescript@5.4.5) + + '@volar/language-core@1.11.1': + dependencies: + '@volar/source-map': 1.11.1 + + '@volar/language-core@2.2.0-alpha.10': + dependencies: + '@volar/source-map': 2.2.0-alpha.10 + + '@volar/source-map@1.11.1': + dependencies: + muggle-string: 0.3.1 + + '@volar/source-map@2.2.0-alpha.10': + dependencies: + muggle-string: 0.4.1 + + '@volar/typescript@1.11.1': + dependencies: + '@volar/language-core': 1.11.1 + path-browserify: 1.0.1 + + '@volar/typescript@2.2.0-alpha.10': + dependencies: + '@volar/language-core': 2.2.0-alpha.10 + path-browserify: 1.0.1 + + '@vue/babel-helper-vue-transform-on@1.1.5': {} + + '@vue/babel-plugin-jsx@1.1.5(@babel/core@7.24.4)': + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-module-imports': 7.22.5 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.24.4) + '@babel/template': 7.22.5 + '@babel/traverse': 7.22.11 + '@babel/types': 7.22.11 + '@vue/babel-helper-vue-transform-on': 1.1.5 + camelcase: 6.3.0 + html-tags: 3.3.1 + svg-tags: 1.0.0 + transitivePeerDependencies: + - supports-color + + '@vue/compiler-core@3.2.47': + dependencies: + '@babel/parser': 7.24.4 + '@vue/shared': 3.2.47 + estree-walker: 2.0.2 + source-map: 0.6.1 + + '@vue/compiler-core@3.4.25': + dependencies: + '@babel/parser': 7.24.4 + '@vue/shared': 3.4.25 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.0 + + '@vue/compiler-dom@3.2.47': + dependencies: + '@vue/compiler-core': 3.2.47 + '@vue/shared': 3.2.47 + + '@vue/compiler-dom@3.4.25': + dependencies: + '@vue/compiler-core': 3.4.25 + '@vue/shared': 3.4.25 + + '@vue/compiler-sfc@3.2.47': + dependencies: + '@babel/parser': 7.22.10 + '@vue/compiler-core': 3.2.47 + '@vue/compiler-dom': 3.2.47 + '@vue/compiler-ssr': 3.2.47 + '@vue/reactivity-transform': 3.2.47 + '@vue/shared': 3.2.47 + estree-walker: 2.0.2 + magic-string: 0.25.9 + postcss: 8.4.38 + source-map: 0.6.1 + + '@vue/compiler-sfc@3.4.25': + dependencies: + '@babel/parser': 7.24.4 + '@vue/compiler-core': 3.4.25 + '@vue/compiler-dom': 3.4.25 + '@vue/compiler-ssr': 3.4.25 + '@vue/shared': 3.4.25 + estree-walker: 2.0.2 + magic-string: 0.30.10 + postcss: 8.4.38 + source-map-js: 1.2.0 + + '@vue/compiler-ssr@3.2.47': + dependencies: + '@vue/compiler-dom': 3.2.47 + '@vue/shared': 3.2.47 + + '@vue/compiler-ssr@3.4.25': + dependencies: + '@vue/compiler-dom': 3.4.25 + '@vue/shared': 3.4.25 + + '@vue/devtools-api@6.5.0': {} + + '@vue/devtools-api@6.6.1': {} + + '@vue/language-core@1.8.27(typescript@5.4.5)': + dependencies: + '@volar/language-core': 1.11.1 + '@volar/source-map': 1.11.1 + '@vue/compiler-dom': 3.4.25 + '@vue/shared': 3.4.25 + computeds: 0.0.1 + minimatch: 9.0.3 + muggle-string: 0.3.1 + path-browserify: 1.0.1 + vue-template-compiler: 2.7.14 + optionalDependencies: + typescript: 5.4.5 + + '@vue/language-core@2.0.14(typescript@5.4.5)': + dependencies: + '@volar/language-core': 2.2.0-alpha.10 + '@vue/compiler-dom': 3.4.25 + '@vue/shared': 3.4.25 + computeds: 0.0.1 + minimatch: 9.0.3 + path-browserify: 1.0.1 + vue-template-compiler: 2.7.14 + optionalDependencies: + typescript: 5.4.5 + + '@vue/reactivity-transform@3.2.47': + dependencies: + '@babel/parser': 7.24.4 + '@vue/compiler-core': 3.2.47 + '@vue/shared': 3.2.47 + estree-walker: 2.0.2 + magic-string: 0.25.9 + + '@vue/reactivity@3.2.47': + dependencies: + '@vue/shared': 3.2.47 + + '@vue/reactivity@3.4.25': + dependencies: + '@vue/shared': 3.4.25 + + '@vue/runtime-core@3.2.47': + dependencies: + '@vue/reactivity': 3.2.47 + '@vue/shared': 3.2.47 + + '@vue/runtime-core@3.4.25': + dependencies: + '@vue/reactivity': 3.4.25 + '@vue/shared': 3.4.25 + + '@vue/runtime-dom@3.2.47': + dependencies: + '@vue/runtime-core': 3.2.47 + '@vue/shared': 3.2.47 + csstype: 2.6.21 + + '@vue/runtime-dom@3.4.25': + dependencies: + '@vue/runtime-core': 3.4.25 + '@vue/shared': 3.4.25 + csstype: 3.1.3 + + '@vue/server-renderer@3.2.47(vue@3.2.47)': + dependencies: + '@vue/compiler-ssr': 3.2.47 + '@vue/shared': 3.2.47 + vue: 3.2.47 + + '@vue/server-renderer@3.4.25(vue@3.4.25(typescript@5.4.5))': + dependencies: + '@vue/compiler-ssr': 3.4.25 + '@vue/shared': 3.4.25 + vue: 3.4.25(typescript@5.4.5) + + '@vue/shared@3.2.47': {} + + '@vue/shared@3.4.25': {} + + '@vue/test-utils@2.4.5': + dependencies: + js-beautify: 1.14.9 + vue-component-type-helpers: 2.0.14 + + '@vueuse/core@10.9.0(vue@3.4.25(typescript@5.4.5))': + dependencies: + '@types/web-bluetooth': 0.0.20 + '@vueuse/metadata': 10.9.0 + '@vueuse/shared': 10.9.0(vue@3.4.25(typescript@5.4.5)) + vue-demi: 0.14.7(vue@3.4.25(typescript@5.4.5)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/core@9.13.0(vue@3.2.47)': + dependencies: + '@types/web-bluetooth': 0.0.16 + '@vueuse/metadata': 9.13.0 + '@vueuse/shared': 9.13.0(vue@3.2.47) + vue-demi: 0.14.0(vue@3.2.47) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/metadata@10.9.0': {} + + '@vueuse/metadata@9.13.0': {} + + '@vueuse/shared@10.9.0(vue@3.4.25(typescript@5.4.5))': + dependencies: + vue-demi: 0.14.7(vue@3.4.25(typescript@5.4.5)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/shared@9.13.0(vue@3.2.47)': + dependencies: + vue-demi: 0.14.0(vue@3.2.47) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@zxcvbn-ts/core@3.0.4': + dependencies: + fastest-levenshtein: 1.0.16 + + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + + abab@2.0.6: {} + + abbrev@1.1.1: {} + + acorn-globals@6.0.0: + dependencies: + acorn: 7.4.1 + acorn-walk: 7.2.0 + + acorn-walk@7.2.0: {} + + acorn-walk@8.2.0: + optional: true + + acorn@7.4.1: {} + + acorn@8.10.0: {} + + acorn@8.11.3: {} + + add-stream@1.0.0: {} + + adler-32@1.3.1: {} + + agent-base@6.0.2: + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + 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 + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-escapes@6.2.1: {} + + ansi-regex@2.1.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.0.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.1: {} + + ansi-styles@https://registry.npmmirror.com/ansi-styles/-/ansi-styles-2.2.1.tgz: {} + + ansi-styles@https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz: + dependencies: + color-convert: https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz + + ansi-styles@https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz: + dependencies: + color-convert: https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz + + ant-design-vue@4.2.1(vue@3.4.25(typescript@5.4.5)): + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-vue': 7.0.1(vue@3.4.25(typescript@5.4.5)) + '@babel/runtime': 7.22.11 + '@ctrl/tinycolor': 3.6.1 + '@emotion/hash': 0.9.1 + '@emotion/unitless': 0.8.1 + '@simonwep/pickr': 1.8.2 + array-tree-filter: 2.1.0 + async-validator: 4.2.5 + csstype: 3.1.3 + dayjs: 1.11.11 + dom-align: 1.12.4 + dom-scroll-into-view: 2.0.1 + lodash: 4.17.21 + lodash-es: 4.17.21 + resize-observer-polyfill: 1.5.1 + scroll-into-view-if-needed: 2.2.31 + shallow-equal: 1.2.1 + stylis: 4.3.0 + throttle-debounce: 5.0.0 + vue: 3.4.25(typescript@5.4.5) + vue-types: 3.0.2(vue@3.4.25(typescript@5.4.5)) + warning: 4.0.3 + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + anymatch@https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + archiver-utils@2.1.0: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 2.3.8 + + archiver@5.3.2: + dependencies: + archiver-utils: 2.1.0 + async: 3.2.4 + buffer-crc32: 0.2.13 + readable-stream: 3.6.2 + readdir-glob: 1.1.3 + tar-stream: 2.2.0 + zip-stream: 4.1.0 + + arg@4.1.3: + optional: true + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + arr-diff@4.0.0: {} + + arr-flatten@1.1.0: {} + + arr-union@3.1.0: {} + + array-ify@1.0.0: {} + + array-tree-filter@2.1.0: {} + + array-union@2.1.0: {} + + array-unique@0.3.2: {} + + assign-symbols@1.0.0: {} + + astral-regex@2.0.0: {} + + async-validator@4.2.5: {} + + async@3.2.4: {} + + asynckit@0.4.0: {} + + atob@2.1.2: {} + + axios@0.26.1(debug@4.3.4): + dependencies: + follow-redirects: 1.15.6(debug@4.3.4) + transitivePeerDependencies: + - debug + + axios@1.6.8: + dependencies: + follow-redirects: 1.15.6(debug@4.3.4) + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + babel-jest@27.5.1(@babel/core@7.24.4): + dependencies: + '@babel/core': 7.24.4 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/babel__core': 7.20.1 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 27.5.1(@babel/core@7.24.4) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.22.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@27.5.1: + dependencies: + '@babel/template': 7.24.0 + '@babel/types': 7.24.0 + '@types/babel__core': 7.20.1 + '@types/babel__traverse': 7.20.1 + + babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.4): + dependencies: + '@babel/core': 7.24.4 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.4) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.4) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.4) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.4) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.4) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.4) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.4) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.4) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.4) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.4) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.4) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.4) + + babel-preset-jest@27.5.1(@babel/core@7.24.4): + dependencies: + '@babel/core': 7.24.4 + babel-plugin-jest-hoist: 27.5.1 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.4) + + balanced-match@1.0.2: {} + + balanced-match@2.0.0: {} + + base64-js@1.5.1: {} + + base@0.11.2: + dependencies: + cache-base: 1.0.1 + class-utils: 0.3.6 + component-emitter: 1.3.0 + define-property: 1.0.0 + isobject: 3.0.1 + mixin-deep: 1.3.2 + pascalcase: 0.1.1 + + big-integer@1.6.51: {} + + big.js@5.2.2: {} + + binary-extensions@2.2.0: {} + + binary-extensions@https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz: {} + + binary@0.3.0: + dependencies: + buffers: 0.1.1 + chainsaw: 0.1.0 + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + bluebird@3.4.7: {} + + bluebird@3.7.2: {} + + boolbase@1.0.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@2.3.2: + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + braces@3.0.2: + dependencies: + fill-range: 7.0.1 + + braces@https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz: + dependencies: + fill-range: https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz + + browser-process-hrtime@1.0.0: {} + + browserslist@4.23.0: + dependencies: + caniuse-lite: 1.0.30001614 + electron-to-chromium: 1.4.750 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.23.0) + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-crc32@0.2.13: {} + + buffer-from@1.1.2: {} + + buffer-indexof-polyfill@1.0.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buffers@0.1.1: {} + + builtin-modules@3.3.0: {} + + cac@6.7.14: {} + + cache-base@1.0.1: + dependencies: + collection-visit: 1.0.0 + component-emitter: 1.3.0 + get-value: 2.0.6 + has-value: 1.0.0 + isobject: 3.0.1 + set-value: 2.0.1 + to-object-path: 0.3.0 + union-value: 1.0.1 + unset-value: 1.0.0 + + call-bind@1.0.7: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + + callsites@3.1.0: {} + + camel-case@4.1.2: + dependencies: + pascal-case: 3.1.2 + tslib: 2.6.2 + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001614: {} + + cfb@1.2.2: + dependencies: + adler-32: 1.3.1 + crc-32: 1.2.2 + + chainsaw@0.1.0: + dependencies: + traverse: 0.3.9 + + chalk@1.1.3: + dependencies: + ansi-styles: https://registry.npmmirror.com/ansi-styles/-/ansi-styles-2.2.1.tgz + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.3.0: {} + + chalk@https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz: + dependencies: + ansi-styles: https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz + escape-string-regexp: 1.0.5 + supports-color: https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz + + chalk@https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz: + dependencies: + ansi-styles: https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz + supports-color: https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz + + char-regex@1.0.2: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + 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@https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz: + dependencies: + anymatch: https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz + braces: https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz + glob-parent: https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz + is-binary-path: https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz + is-glob: https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz + normalize-path: https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz + readdirp: https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz + optionalDependencies: + fsevents: 2.3.3 + + ci-info@3.8.0: {} + + citty@0.1.3: + dependencies: + consola: 3.2.3 + + cjs-module-lexer@1.2.3: {} + + class-utils@0.3.6: + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + + clean-css@5.3.2: + dependencies: + source-map: 0.6.1 + + cli-cursor@4.0.0: + dependencies: + restore-cursor: 4.0.0 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.1.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 + + clone@2.1.2: {} + + co@4.6.0: {} + + codemirror@5.65.16: {} + + codepage@1.15.0: {} + + collect-v8-coverage@1.0.2: {} + + collection-visit@1.0.0: + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-convert@https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz: + dependencies: + color-name: https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz + + color-convert@https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz: + dependencies: + color-name: https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-name@https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz: {} + + color-name@https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz: {} + + colord@2.9.3: {} + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@10.0.1: {} + + commander@11.0.0: {} + + commander@11.1.0: {} + + commander@2.20.3: {} + + commander@7.2.0: {} + + commander@8.3.0: {} + + commander@9.5.0: {} + + commondir@1.0.1: {} + + compare-func@2.0.0: + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + + component-emitter@1.3.0: {} + + compress-commons@4.1.1: + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 4.0.2 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + compute-scroll-into-view@1.0.20: {} + + computeds@0.0.1: {} + + concat-map@0.0.1: {} + + confbox@0.1.7: {} + + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + + connect-history-api-fallback@1.6.0: {} + + connect@3.7.0: + dependencies: + debug: 2.6.9 + finalhandler: 1.1.2 + parseurl: 1.3.3 + utils-merge: 1.0.1 + transitivePeerDependencies: + - supports-color + + connect@https://registry.npmmirror.com/connect/-/connect-3.7.0.tgz: + dependencies: + debug: 2.6.9 + finalhandler: https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.2.tgz + parseurl: https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz + utils-merge: https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz + transitivePeerDependencies: + - supports-color + + consola@2.15.3: {} + + consola@3.2.3: {} + + conventional-changelog-angular@7.0.0: + dependencies: + compare-func: 2.0.0 + + conventional-changelog-atom@4.0.0: {} + + conventional-changelog-cli@4.1.0: + dependencies: + add-stream: 1.0.0 + conventional-changelog: 5.1.0 + meow: 12.1.1 + tempfile: 5.0.0 + + conventional-changelog-codemirror@4.0.0: {} + + conventional-changelog-conventionalcommits@7.0.2: + dependencies: + compare-func: 2.0.0 + + conventional-changelog-core@7.0.0: + dependencies: + '@hutson/parse-repository-url': 5.0.0 + add-stream: 1.0.0 + conventional-changelog-writer: 7.0.1 + conventional-commits-parser: 5.0.0 + git-raw-commits: 4.0.0 + git-semver-tags: 7.0.1 + hosted-git-info: 7.0.1 + normalize-package-data: 6.0.0 + read-pkg: 8.1.0 + read-pkg-up: 10.1.0 + + conventional-changelog-ember@4.0.0: {} + + conventional-changelog-eslint@5.0.0: {} + + conventional-changelog-express@4.0.0: {} + + conventional-changelog-jquery@5.0.0: {} + + conventional-changelog-jshint@4.0.0: + dependencies: + compare-func: 2.0.0 + + conventional-changelog-preset-loader@4.1.0: {} + + conventional-changelog-writer@7.0.1: + dependencies: + conventional-commits-filter: 4.0.0 + handlebars: 4.7.8 + json-stringify-safe: 5.0.1 + meow: 12.1.1 + semver: 7.5.4 + split2: 4.2.0 + + conventional-changelog@5.1.0: + dependencies: + conventional-changelog-angular: 7.0.0 + conventional-changelog-atom: 4.0.0 + conventional-changelog-codemirror: 4.0.0 + conventional-changelog-conventionalcommits: 7.0.2 + conventional-changelog-core: 7.0.0 + conventional-changelog-ember: 4.0.0 + conventional-changelog-eslint: 5.0.0 + conventional-changelog-express: 4.0.0 + conventional-changelog-jquery: 5.0.0 + conventional-changelog-jshint: 4.0.0 + conventional-changelog-preset-loader: 4.1.0 + + conventional-commits-filter@4.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@1.9.0: {} + + convert-source-map@2.0.0: {} + + copy-anything@2.0.6: + dependencies: + is-what: 3.14.1 + + copy-descriptor@0.1.1: {} + + core-js@3.32.1: {} + + core-util-is@1.0.3: {} + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cosmiconfig-typescript-loader@5.0.0(@types/node@20.12.7)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5): + dependencies: + '@types/node': 20.12.7 + cosmiconfig: 9.0.0(typescript@5.4.5) + jiti: 1.19.3 + typescript: 5.4.5 + + cosmiconfig@9.0.0(typescript@5.4.5): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.4.5 + + crc-32@1.2.2: {} + + crc32-stream@4.0.2: + dependencies: + crc-32: 1.2.2 + readable-stream: 3.6.2 + + create-require@1.1.1: + optional: true + + cropperjs@1.6.2: {} + + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.3 + + cross-fetch@3.1.8: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-js@4.2.0: {} + + css-functions-list@3.2.2: {} + + css-property-sort-order-smacss@2.2.0: {} + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.0 + + css-what@6.1.0: {} + + cssesc@3.0.0: {} + + csso@4.2.0: + dependencies: + css-tree: 1.1.3 + + cssom@0.3.8: {} + + cssom@0.4.4: {} + + cssstyle@2.3.0: + dependencies: + cssom: 0.3.8 + + csstype@2.6.21: {} + + csstype@3.1.3: {} + + cz-git@1.9.1: {} + + czg@1.9.1: {} + + dargs@8.1.0: {} + + data-urls@2.0.0: + dependencies: + abab: 2.0.6 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + + dayjs@1.11.11: {} + + de-indent@1.0.2: {} + + debug@2.6.9: + dependencies: + ms: https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz + + debug@4.3.4: + dependencies: + ms: 2.1.2 + + debug@https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz: + dependencies: + ms: https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz + optional: true + + debug@https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz: + dependencies: + ms: https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz + + decamelize@1.2.0: {} + + decimal.js@10.4.3: {} + + decode-uri-component@0.2.2: {} + + dedent@0.7.0: {} + + deepmerge@4.3.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + define-lazy-prop@2.0.0: {} + + define-property@0.2.5: + dependencies: + is-descriptor: 0.1.6 + + define-property@1.0.0: + dependencies: + is-descriptor: 1.0.2 + + define-property@2.0.2: + dependencies: + is-descriptor: 1.0.2 + isobject: 3.0.1 + + defu@6.1.2: {} + + defu@6.1.4: {} + + delayed-stream@1.0.0: {} + + destr@2.0.3: {} + + detect-indent@7.0.1: {} + + detect-newline@3.1.0: {} + + detect-newline@4.0.0: {} + + diff-match-patch@1.0.5: {} + + diff-sequences@27.5.1: {} + + diff@4.0.2: + optional: true + + dijkstrajs@1.0.3: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dom-align@1.12.4: {} + + dom-scroll-into-view@2.0.1: {} + + dom-serializer@0.2.2: + dependencies: + domelementtype: 2.3.0 + entities: 2.2.0 + + 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-zindex@1.0.2: {} + + domelementtype@1.3.1: {} + + domelementtype@2.3.0: {} + + domexception@2.0.1: + dependencies: + webidl-conversions: 5.0.0 + + domhandler@2.4.2: + dependencies: + domelementtype: 1.3.1 + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@1.7.0: + dependencies: + dom-serializer: 0.2.2 + domelementtype: 1.3.1 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + domutils@3.1.0: + 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.6.2 + + dot-prop@5.3.0: + dependencies: + is-obj: 2.0.0 + + dotenv-expand@8.0.3: {} + + dotenv@16.4.5: {} + + duplexer2@0.1.4: + dependencies: + readable-stream: 2.3.8 + + duplexer@0.1.2: {} + + eastasianwidth@0.2.0: {} + + echarts@5.5.0: + dependencies: + tslib: 2.3.0 + zrender: 5.5.0 + + editorconfig@1.0.4: + dependencies: + '@one-ini/wasm': 0.1.1 + commander: 10.0.1 + minimatch: 9.0.1 + semver: 7.5.4 + + ee-first@1.1.1: {} + + ee-first@https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz: {} + + ejs@3.1.9: + dependencies: + jake: 10.8.7 + + electron-to-chromium@1.4.750: {} + + emittery@0.8.1: {} + + emoji-regex@10.3.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + emojis-list@3.0.0: {} + + encode-utf8@1.0.3: {} + + encodeurl@1.0.2: {} + + encodeurl@https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz: {} + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + entities@1.1.2: {} + + entities@2.2.0: {} + + entities@4.5.0: {} + + env-paths@2.2.1: {} + + errno@0.1.8: + dependencies: + prr: 1.0.1 + optional: true + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} + + esbuild-android-64@0.14.54: + optional: true + + esbuild-android-arm64@0.14.54: + optional: true + + esbuild-darwin-64@0.14.54: + optional: true + + esbuild-darwin-arm64@0.14.54: + optional: true + + esbuild-freebsd-64@0.14.54: + optional: true + + esbuild-freebsd-arm64@0.14.54: + optional: true + + esbuild-linux-32@0.14.54: + optional: true + + esbuild-linux-64@0.14.54: + optional: true + + esbuild-linux-arm64@0.14.54: + optional: true + + esbuild-linux-arm@0.14.54: + optional: true + + esbuild-linux-mips64le@0.14.54: + optional: true + + esbuild-linux-ppc64le@0.14.54: + optional: true + + esbuild-linux-riscv64@0.14.54: + optional: true + + esbuild-linux-s390x@0.14.54: + optional: true + + esbuild-netbsd-64@0.14.54: + optional: true + + esbuild-openbsd-64@0.14.54: + optional: true + + esbuild-sunos-64@0.14.54: + optional: true + + esbuild-windows-32@0.14.54: + optional: true + + esbuild-windows-64@0.14.54: + optional: true + + esbuild-windows-arm64@0.14.54: + optional: true + + esbuild@0.14.54: + optionalDependencies: + '@esbuild/linux-loong64': 0.14.54 + esbuild-android-64: 0.14.54 + esbuild-android-arm64: 0.14.54 + esbuild-darwin-64: 0.14.54 + esbuild-darwin-arm64: 0.14.54 + esbuild-freebsd-64: 0.14.54 + esbuild-freebsd-arm64: 0.14.54 + esbuild-linux-32: 0.14.54 + esbuild-linux-64: 0.14.54 + esbuild-linux-arm: 0.14.54 + esbuild-linux-arm64: 0.14.54 + esbuild-linux-mips64le: 0.14.54 + esbuild-linux-ppc64le: 0.14.54 + esbuild-linux-riscv64: 0.14.54 + esbuild-linux-s390x: 0.14.54 + esbuild-netbsd-64: 0.14.54 + esbuild-openbsd-64: 0.14.54 + esbuild-sunos-64: 0.14.54 + esbuild-windows-32: 0.14.54 + esbuild-windows-64: 0.14.54 + esbuild-windows-arm64: 0.14.54 + + esbuild@0.18.20: + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + + esbuild@0.19.2: + optionalDependencies: + '@esbuild/android-arm': 0.19.2 + '@esbuild/android-arm64': 0.19.2 + '@esbuild/android-x64': 0.19.2 + '@esbuild/darwin-arm64': 0.19.2 + '@esbuild/darwin-x64': 0.19.2 + '@esbuild/freebsd-arm64': 0.19.2 + '@esbuild/freebsd-x64': 0.19.2 + '@esbuild/linux-arm': 0.19.2 + '@esbuild/linux-arm64': 0.19.2 + '@esbuild/linux-ia32': 0.19.2 + '@esbuild/linux-loong64': 0.19.2 + '@esbuild/linux-mips64el': 0.19.2 + '@esbuild/linux-ppc64': 0.19.2 + '@esbuild/linux-riscv64': 0.19.2 + '@esbuild/linux-s390x': 0.19.2 + '@esbuild/linux-x64': 0.19.2 + '@esbuild/netbsd-x64': 0.19.2 + '@esbuild/openbsd-x64': 0.19.2 + '@esbuild/sunos-x64': 0.19.2 + '@esbuild/win32-arm64': 0.19.2 + '@esbuild/win32-ia32': 0.19.2 + '@esbuild/win32-x64': 0.19.2 + + esbuild@0.20.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.20.2 + '@esbuild/android-arm': 0.20.2 + '@esbuild/android-arm64': 0.20.2 + '@esbuild/android-x64': 0.20.2 + '@esbuild/darwin-arm64': 0.20.2 + '@esbuild/darwin-x64': 0.20.2 + '@esbuild/freebsd-arm64': 0.20.2 + '@esbuild/freebsd-x64': 0.20.2 + '@esbuild/linux-arm': 0.20.2 + '@esbuild/linux-arm64': 0.20.2 + '@esbuild/linux-ia32': 0.20.2 + '@esbuild/linux-loong64': 0.20.2 + '@esbuild/linux-mips64el': 0.20.2 + '@esbuild/linux-ppc64': 0.20.2 + '@esbuild/linux-riscv64': 0.20.2 + '@esbuild/linux-s390x': 0.20.2 + '@esbuild/linux-x64': 0.20.2 + '@esbuild/netbsd-x64': 0.20.2 + '@esbuild/openbsd-x64': 0.20.2 + '@esbuild/sunos-x64': 0.20.2 + '@esbuild/win32-arm64': 0.20.2 + '@esbuild/win32-ia32': 0.20.2 + '@esbuild/win32-x64': 0.20.2 + + esbuild@https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz: + optionalDependencies: + '@esbuild/linux-loong64': 0.14.54 + esbuild-android-64: 0.14.54 + esbuild-android-arm64: 0.14.54 + esbuild-darwin-64: 0.14.54 + esbuild-darwin-arm64: 0.14.54 + esbuild-freebsd-64: 0.14.54 + esbuild-freebsd-arm64: 0.14.54 + esbuild-linux-32: 0.14.54 + esbuild-linux-64: 0.14.54 + esbuild-linux-arm: 0.14.54 + esbuild-linux-arm64: 0.14.54 + esbuild-linux-mips64le: 0.14.54 + esbuild-linux-ppc64le: 0.14.54 + esbuild-linux-riscv64: 0.14.54 + esbuild-linux-s390x: 0.14.54 + esbuild-netbsd-64: 0.14.54 + esbuild-openbsd-64: 0.14.54 + esbuild-sunos-64: 0.14.54 + esbuild-windows-32: 0.14.54 + esbuild-windows-64: 0.14.54 + esbuild-windows-arm64: 0.14.54 + + escalade@3.1.1: {} + + escape-html@1.0.3: {} + + escape-html@https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.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 + + esprima@4.0.1: {} + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + eventemitter3@5.0.1: {} + + exceljs@4.4.0: + dependencies: + archiver: 5.3.2 + dayjs: 1.11.11 + fast-csv: 4.3.6 + jszip: 3.10.1 + readable-stream: 3.6.2 + saxes: 5.0.1 + tmp: 0.2.1 + unzipper: 0.10.14 + uuid: 8.3.2 + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + exit@0.1.2: {} + + expand-brackets@2.1.4: + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + expect@27.5.1: + dependencies: + '@jest/types': 27.5.1 + jest-get-type: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + + extend-shallow@2.0.1: + dependencies: + is-extendable: 0.1.1 + + extend-shallow@3.0.2: + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + + extglob@2.0.4: + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + fast-csv@4.3.6: + dependencies: + '@fast-csv/format': 4.3.5 + '@fast-csv/parse': 4.3.6 + + fast-deep-equal@3.1.3: {} + + fast-diff@1.2.0: {} + + fast-glob@3.3.2: + 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.5 + + fast-glob@https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.1.tgz: + dependencies: + '@nodelib/fs.stat': https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz + '@nodelib/fs.walk': https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz + glob-parent: https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz + merge2: https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz + micromatch: 4.0.5 + + fast-json-stable-stringify@2.1.0: {} + + fastest-levenshtein@1.0.16: {} + + fastq@1.15.0: + dependencies: + reusify: 1.0.4 + + fastq@https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz: + dependencies: + reusify: https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz + + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + + fill-range@4.0.0: + dependencies: + extend-shallow: 2.0.1 + is-number: 3.0.0 + repeat-string: 1.6.1 + to-regex-range: 2.1.1 + + fill-range@7.0.1: + dependencies: + to-regex-range: 5.0.1 + + fill-range@https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz: + dependencies: + to-regex-range: https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz + + finalhandler@1.1.2: + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + finalhandler@https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.2.tgz: + dependencies: + debug: 2.6.9 + encodeurl: https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz + escape-html: https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz + on-finished: https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz + parseurl: https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz + statuses: https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz + unpipe: https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz + transitivePeerDependencies: + - supports-color + + 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@6.3.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + + flatted@3.3.1: {} + + follow-redirects@1.15.6(debug@4.3.4): + optionalDependencies: + debug: 4.3.4 + + for-in@1.0.2: {} + + foreground-child@3.1.1: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + + form-data@3.0.1: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + frac@1.1.2: {} + + fragment-cache@0.2.1: + dependencies: + map-cache: 0.2.2 + + fs-constants@1.0.0: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + + fs-extra@11.2.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + fstream@1.0.12: + dependencies: + graceful-fs: 4.2.11 + inherits: 2.0.4 + mkdirp: 0.5.6 + rimraf: 2.7.1 + + function-bind@1.1.1: {} + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.2.0: {} + + get-intrinsic@1.2.4: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.2 + + get-package-type@0.1.0: {} + + get-stdin@9.0.0: {} + + get-stream@6.0.1: {} + + get-stream@8.0.1: {} + + get-value@2.0.6: {} + + git-hooks-list@3.1.0: {} + + git-raw-commits@4.0.0: + dependencies: + dargs: 8.1.0 + meow: 12.1.1 + split2: 4.2.0 + + git-semver-tags@7.0.1: + dependencies: + meow: 12.1.1 + semver: 7.5.4 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz: + dependencies: + is-glob: https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz + + glob@10.3.12: + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.3 + minipass: 7.0.4 + path-scurry: 1.10.2 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + global-modules@2.0.0: + dependencies: + global-prefix: 3.0.0 + + global-prefix@3.0.0: + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + + globals@11.12.0: {} + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + + globby@13.2.2: + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 4.0.0 + + globjoin@0.1.4: {} + + gopd@1.0.1: + dependencies: + get-intrinsic: 1.2.4 + + graceful-fs@4.2.11: {} + + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + + handlebars@4.7.8: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.17.4 + + has-ansi@2.0.0: + dependencies: + ansi-regex: 2.1.1 + + has-flag@1.0.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-flag@https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz: {} + + has-flag@https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.0 + + has-proto@1.0.1: {} + + has-symbols@1.0.3: {} + + has-value@0.3.1: + dependencies: + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 + + has-value@1.0.0: + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + + has-values@0.1.4: {} + + has-values@1.0.0: + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + + has@1.0.3: + dependencies: + function-bind: 1.1.1 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + hookable@5.5.3: {} + + hosted-git-info@7.0.1: + dependencies: + lru-cache: 10.0.1 + + html-encoding-sniffer@2.0.1: + dependencies: + whatwg-encoding: 1.0.5 + + html-escaper@2.0.2: {} + + html-minifier-terser@6.1.0: + dependencies: + camel-case: 4.1.2 + clean-css: 5.3.2 + commander: 8.3.0 + he: 1.2.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 5.19.3 + + html-tags@3.3.1: {} + + htmlparser2@3.10.1: + dependencies: + domelementtype: 1.3.1 + domhandler: 2.4.2 + domutils: 1.7.0 + entities: 1.1.2 + inherits: https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz + readable-stream: 3.6.2 + + htmlparser2@8.0.2: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.5.0 + + http-proxy-agent@4.0.1: + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + human-signals@5.0.0: {} + + husky@9.0.11: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + optional: true + + ieee754@1.2.1: {} + + ignore@5.2.4: {} + + ignore@5.3.1: {} + + image-size@0.5.5: {} + + immediate@3.0.6: {} + + immutable@4.3.4: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz + + import-lazy@4.0.0: {} + + import-local@3.1.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + import-meta-resolve@4.0.0: {} + + imurmurhash@0.1.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + inherits@https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz: {} + + ini@1.3.8: {} + + ini@4.1.1: {} + + is-accessor-descriptor@0.1.6: + dependencies: + kind-of: 3.2.2 + + is-accessor-descriptor@1.0.0: + dependencies: + kind-of: 6.0.3 + + is-arrayish@0.2.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.2.0 + + is-binary-path@https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz: + dependencies: + binary-extensions: https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz + + is-buffer@1.1.6: {} + + is-builtin-module@3.2.1: + dependencies: + builtin-modules: 3.3.0 + + is-core-module@2.13.0: + dependencies: + has: 1.0.3 + + is-data-descriptor@0.1.4: + dependencies: + kind-of: 3.2.2 + + is-data-descriptor@1.0.0: + dependencies: + kind-of: 6.0.3 + + is-descriptor@0.1.6: + dependencies: + is-accessor-descriptor: 0.1.6 + is-data-descriptor: 0.1.4 + kind-of: 5.1.0 + + is-descriptor@1.0.2: + dependencies: + is-accessor-descriptor: 1.0.0 + is-data-descriptor: 1.0.0 + kind-of: 6.0.3 + + is-docker@2.2.1: {} + + is-extendable@0.1.1: {} + + is-extendable@1.0.1: + dependencies: + is-plain-object: 2.0.4 + + is-extglob@2.1.1: {} + + is-extglob@https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz: {} + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.2.0 + + is-generator-fn@2.1.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-glob@https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz: + dependencies: + is-extglob: https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz + + is-module@1.0.0: {} + + is-number@3.0.0: + dependencies: + kind-of: 3.2.2 + + is-number@7.0.0: {} + + is-number@https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz: {} + + is-obj@2.0.0: {} + + is-plain-obj@1.1.0: {} + + is-plain-obj@4.1.0: {} + + is-plain-object@2.0.4: + dependencies: + isobject: 3.0.1 + + is-plain-object@3.0.1: {} + + is-plain-object@5.0.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.1 + + is-stream@2.0.1: {} + + is-stream@3.0.0: {} + + is-text-path@2.0.0: + dependencies: + text-extensions: 2.4.0 + + is-typedarray@1.0.0: {} + + is-what@3.14.1: {} + + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isarray@1.0.0: {} + + isexe@2.0.0: {} + + isobject@2.1.0: + dependencies: + isarray: 1.0.0 + + isobject@3.0.1: {} + + istanbul-lib-coverage@3.2.0: {} + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.24.4 + '@babel/parser': 7.24.4 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.0 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.6: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@2.3.6: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jake@10.8.7: + dependencies: + async: 3.2.4 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + + jest-changed-files@27.5.1: + dependencies: + '@jest/types': 27.5.1 + execa: 5.1.1 + throat: 6.0.2 + + jest-circus@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + chalk: 4.1.2 + co: 4.6.0 + dedent: 0.7.0 + expect: 27.5.1 + is-generator-fn: 2.1.0 + jest-each: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + jest-runtime: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + pretty-format: 27.5.1 + slash: 3.0.0 + stack-utils: 2.0.6 + throat: 6.0.2 + transitivePeerDependencies: + - supports-color + + jest-cli@27.5.1(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5)): + dependencies: + '@jest/core': 27.5.1(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5)) + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + import-local: 3.1.0 + jest-config: 27.5.1(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5)) + jest-util: 27.5.1 + jest-validate: 27.5.1 + prompts: 2.4.2 + yargs: 16.2.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-config@27.5.1(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5)): + dependencies: + '@babel/core': 7.24.4 + '@jest/test-sequencer': 27.5.1 + '@jest/types': 27.5.1 + babel-jest: 27.5.1(@babel/core@7.24.4) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 27.5.1 + jest-environment-jsdom: 27.5.1 + jest-environment-node: 27.5.1 + jest-get-type: 27.5.1 + jest-jasmine2: 27.5.1 + jest-regex-util: 27.5.1 + jest-resolve: 27.5.1 + jest-runner: 27.5.1 + jest-util: 27.5.1 + jest-validate: 27.5.1 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 27.5.1 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + ts-node: 10.9.1(@types/node@20.12.7)(typescript@5.4.5) + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-diff@27.5.1: + dependencies: + chalk: 4.1.2 + diff-sequences: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + + jest-docblock@27.5.1: + dependencies: + detect-newline: 3.1.0 + + jest-each@27.5.1: + dependencies: + '@jest/types': 27.5.1 + chalk: 4.1.2 + jest-get-type: 27.5.1 + jest-util: 27.5.1 + pretty-format: 27.5.1 + + jest-environment-jsdom@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + jest-mock: 27.5.1 + jest-util: 27.5.1 + jsdom: 16.7.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-environment-node@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + jest-mock: 27.5.1 + jest-util: 27.5.1 + + jest-get-type@27.5.1: {} + + jest-haste-map@27.5.1: + dependencies: + '@jest/types': 27.5.1 + '@types/graceful-fs': 4.1.6 + '@types/node': 20.12.7 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 27.5.1 + jest-serializer: 27.5.1 + jest-util: 27.5.1 + jest-worker: 27.5.1 + micromatch: 4.0.5 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-jasmine2@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/source-map': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + chalk: 4.1.2 + co: 4.6.0 + expect: 27.5.1 + is-generator-fn: 2.1.0 + jest-each: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + jest-runtime: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + pretty-format: 27.5.1 + throat: 6.0.2 + transitivePeerDependencies: + - supports-color + + jest-leak-detector@27.5.1: + dependencies: + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + + jest-matcher-utils@27.5.1: + dependencies: + chalk: 4.1.2 + jest-diff: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + + jest-message-util@27.5.1: + dependencies: + '@babel/code-frame': 7.24.2 + '@jest/types': 27.5.1 + '@types/stack-utils': 2.0.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.5 + pretty-format: 27.5.1 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@27.5.1: + dependencies: + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + + jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): + optionalDependencies: + jest-resolve: 27.5.1 + + jest-regex-util@27.5.1: {} + + jest-resolve-dependencies@27.5.1: + dependencies: + '@jest/types': 27.5.1 + jest-regex-util: 27.5.1 + jest-snapshot: 27.5.1 + transitivePeerDependencies: + - supports-color + + jest-resolve@27.5.1: + dependencies: + '@jest/types': 27.5.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-pnp-resolver: 1.2.3(jest-resolve@27.5.1) + jest-util: 27.5.1 + jest-validate: 27.5.1 + resolve: 1.22.4 + resolve.exports: 1.1.1 + slash: 3.0.0 + + jest-runner@27.5.1: + dependencies: + '@jest/console': 27.5.1 + '@jest/environment': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + chalk: 4.1.2 + emittery: 0.8.1 + graceful-fs: 4.2.11 + jest-docblock: 27.5.1 + jest-environment-jsdom: 27.5.1 + jest-environment-node: 27.5.1 + jest-haste-map: 27.5.1 + jest-leak-detector: 27.5.1 + jest-message-util: 27.5.1 + jest-resolve: 27.5.1 + jest-runtime: 27.5.1 + jest-util: 27.5.1 + jest-worker: 27.5.1 + source-map-support: 0.5.21 + throat: 6.0.2 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-runtime@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/globals': 27.5.1 + '@jest/source-map': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + chalk: 4.1.2 + cjs-module-lexer: 1.2.3 + collect-v8-coverage: 1.0.2 + execa: 5.1.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-message-util: 27.5.1 + jest-mock: 27.5.1 + jest-regex-util: 27.5.1 + jest-resolve: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-serializer@27.5.1: + dependencies: + '@types/node': 20.12.7 + graceful-fs: 4.2.11 + + jest-snapshot@27.5.1: + dependencies: + '@babel/core': 7.24.4 + '@babel/generator': 7.24.4 + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.24.4) + '@babel/traverse': 7.24.1 + '@babel/types': 7.24.0 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/babel__traverse': 7.20.1 + '@types/prettier': 2.7.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.4) + chalk: 4.1.2 + expect: 27.5.1 + graceful-fs: 4.2.11 + jest-diff: 27.5.1 + jest-get-type: 27.5.1 + jest-haste-map: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + jest-util: 27.5.1 + natural-compare: 1.4.0 + pretty-format: 27.5.1 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + + jest-util@27.5.1: + dependencies: + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + chalk: 4.1.2 + ci-info: 3.8.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@27.5.1: + dependencies: + '@jest/types': 27.5.1 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 27.5.1 + leven: 3.1.0 + pretty-format: 27.5.1 + + jest-watcher@27.5.1: + dependencies: + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 20.12.7 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + jest-util: 27.5.1 + string-length: 4.0.2 + + jest-worker@27.5.1: + dependencies: + '@types/node': 20.12.7 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@27.5.1(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5)): + dependencies: + '@jest/core': 27.5.1(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5)) + import-local: 3.1.0 + jest-cli: 27.5.1(ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5)) + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jiti@1.19.3: {} + + jiti@1.21.0: {} + + jju@1.4.0: {} + + js-base64@2.6.4: {} + + js-beautify@1.14.9: + dependencies: + config-chain: 1.1.13 + editorconfig: 1.0.4 + glob: 8.1.0 + nopt: 6.0.0 + + js-tokens@4.0.0: {} + + js-tokens@8.0.1: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsdom@16.7.0: + dependencies: + abab: 2.0.6 + acorn: 8.11.3 + acorn-globals: 6.0.0 + cssom: 0.4.4 + cssstyle: 2.3.0 + data-urls: 2.0.0 + decimal.js: 10.4.3 + domexception: 2.0.1 + escodegen: 2.1.0 + form-data: 3.0.1 + html-encoding-sniffer: 2.0.1 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.7 + parse5: 6.0.1 + saxes: 5.0.1 + symbol-tree: 3.2.4 + tough-cookie: 4.1.3 + w3c-hr-time: 1.0.2 + w3c-xmlserializer: 2.0.0 + webidl-conversions: 6.1.0 + whatwg-encoding: 1.0.5 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + ws: 7.5.9 + xml-name-validator: 3.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@2.5.2: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-parse-even-better-errors@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stringify-safe@5.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.7 + + json5@2.2.3: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonparse@1.3.1: {} + + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kind-of@3.2.2: + dependencies: + is-buffer: 1.1.6 + + kind-of@4.0.0: + dependencies: + is-buffer: 1.1.6 + + kind-of@5.1.0: {} + + kind-of@6.0.3: {} + + kleur@3.0.3: {} + + known-css-properties@0.29.0: {} + + known-css-properties@0.30.0: {} + + kolorist@1.8.0: {} + + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + + less@4.2.0: + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.6.2 + 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.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + leven@3.1.0: {} + + lie@3.3.0: + dependencies: + immediate: 3.0.6 + + lilconfig@3.0.0: {} + + lines-and-columns@1.2.4: {} + + lines-and-columns@2.0.4: {} + + lint-staged@15.2.2: + dependencies: + chalk: 5.3.0 + commander: 11.1.0 + debug: 4.3.4 + execa: 8.0.1 + lilconfig: 3.0.0 + listr2: 8.0.1 + micromatch: 4.0.5 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.3.4 + transitivePeerDependencies: + - supports-color + + listenercount@1.0.1: {} + + listr2@8.0.1: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.0.0 + rfdc: 1.3.0 + wrap-ansi: 9.0.0 + + loader-utils@1.4.2: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 1.0.2 + + local-pkg@0.5.0: + dependencies: + mlly: 1.6.1 + pkg-types: 1.1.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 + + lodash-es@4.17.21: {} + + lodash.camelcase@4.3.0: {} + + lodash.defaults@4.2.0: {} + + lodash.difference@4.5.0: {} + + lodash.escaperegexp@4.1.2: {} + + lodash.flatten@4.4.0: {} + + lodash.get@4.4.2: {} + + lodash.groupby@4.6.0: {} + + lodash.isboolean@3.0.3: {} + + lodash.isequal@4.5.0: {} + + lodash.isfunction@3.0.9: {} + + lodash.isnil@4.0.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.isundefined@3.0.1: {} + + lodash.kebabcase@4.1.1: {} + + lodash.merge@4.6.2: {} + + lodash.mergewith@4.6.2: {} + + lodash.snakecase@4.1.1: {} + + lodash.startcase@4.4.0: {} + + lodash.truncate@4.4.2: {} + + lodash.union@4.6.0: {} + + lodash.uniq@4.5.0: {} + + lodash.upperfirst@4.3.1: {} + + lodash@4.17.21: {} + + log-update@6.0.0: + dependencies: + ansi-escapes: 6.2.1 + cli-cursor: 4.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lower-case@2.0.2: + dependencies: + tslib: 2.6.2 + + lru-cache@10.0.1: {} + + lru-cache@10.2.2: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + + magic-string@0.27.0: + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + + magic-string@0.30.10: + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + + magic-string@0.30.3: + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + + make-dir@2.1.0: + dependencies: + pify: 4.0.1 + semver: https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz + optional: true + + make-dir@4.0.0: + dependencies: + semver: 7.6.0 + + make-error@1.3.6: + optional: true + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + map-cache@0.2.2: {} + + map-visit@1.0.0: + dependencies: + object-visit: 1.0.1 + + mathml-tag-names@2.1.3: {} + + mdn-data@2.0.14: {} + + mdn-data@2.0.30: {} + + meow@12.1.1: {} + + meow@13.2.0: {} + + merge-options@1.0.1: + dependencies: + is-plain-obj: 1.1.0 + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + merge2@https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz: {} + + micromatch@3.1.0: + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2 + define-property: 1.0.0 + extend-shallow: 2.0.1 + extglob: 2.0.4 + fragment-cache: 0.2.1 + kind-of: 5.1.0 + nanomatch: 1.2.13 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + micromatch@4.0.5: + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: + optional: true + + mimic-fn@2.1.0: {} + + mimic-fn@4.0.0: {} + + minimatch@3.0.8: + dependencies: + brace-expansion: 1.1.11 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + + minimatch@9.0.1: + dependencies: + brace-expansion: 2.0.1 + + minimatch@9.0.3: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.7: {} + + minimist@1.2.8: {} + + minipass@7.0.4: {} + + mixin-deep@1.3.2: + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + mkdist@1.3.0(sass@1.75.0)(typescript@5.4.5): + dependencies: + citty: 0.1.3 + defu: 6.1.2 + esbuild: 0.18.20 + fs-extra: 11.2.0 + globby: 13.2.2 + jiti: 1.19.3 + mlly: 1.6.1 + mri: 1.2.0 + pathe: 1.1.2 + optionalDependencies: + sass: 1.75.0 + typescript: 5.4.5 + + mlly@1.4.1: + dependencies: + acorn: 8.10.0 + pathe: 1.1.2 + pkg-types: 1.1.0 + ufo: 1.3.0 + + mlly@1.6.1: + dependencies: + acorn: 8.11.3 + pathe: 1.1.2 + pkg-types: 1.1.0 + ufo: 1.5.3 + + mockjs@1.1.0: + dependencies: + commander: 11.0.0 + + mousetrap@1.6.5: {} + + mri@1.2.0: {} + + mrmime@2.0.0: {} + + ms@2.1.2: {} + + ms@https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz: {} + + ms@https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz: {} + + ms@https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz: + optional: true + + muggle-string@0.3.1: {} + + muggle-string@0.4.1: {} + + nanoid@3.3.7: {} + + nanomatch@1.2.13: + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + nanopop@2.3.0: {} + + natural-compare@1.4.0: {} + + needle@3.2.0: + dependencies: + debug: https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz + iconv-lite: 0.6.3 + sax: 1.2.4 + transitivePeerDependencies: + - supports-color + optional: true + + neo-async@2.6.2: {} + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.6.2 + + node-fetch-native@1.6.4: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-html-parser@5.4.2: + dependencies: + css-select: 4.3.0 + he: 1.2.0 + + node-int64@0.4.0: {} + + node-releases@2.0.14: {} + + nopt@6.0.0: + dependencies: + abbrev: 1.1.1 + + normalize-package-data@6.0.0: + dependencies: + hosted-git-info: 7.0.1 + is-core-module: 2.13.0 + semver: 7.5.4 + validate-npm-package-license: 3.0.4 + + normalize-path@3.0.0: {} + + normalize-path@https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + npm-run-path@5.1.0: + dependencies: + path-key: 4.0.0 + + nprogress@0.2.0: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + nwsapi@2.2.7: {} + + object-assign@4.1.1: {} + + object-copy@0.1.0: + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + + object-inspect@1.13.1: {} + + object-visit@1.0.1: + dependencies: + isobject: 3.0.1 + + object.pick@1.3.0: + dependencies: + isobject: 3.0.1 + + ofetch@1.3.4: + dependencies: + destr: 2.0.3 + node-fetch-native: 1.6.4 + ufo: 1.5.3 + + on-finished@2.3.0: + dependencies: + ee-first: 1.1.1 + + on-finished@https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz: + dependencies: + ee-first: https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.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.0.0 + + 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-try@2.2.0: {} + + pako@1.0.11: {} + + param-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.6.2 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.24.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-json@7.1.1: + dependencies: + '@babel/code-frame': 7.22.13 + error-ex: 1.3.2 + json-parse-even-better-errors: 3.0.1 + lines-and-columns: 2.0.4 + type-fest: 3.13.1 + + parse-node-version@1.0.1: {} + + parse5@6.0.1: {} + + parseurl@1.3.3: {} + + parseurl@https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz: {} + + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.6.2 + + pascalcase@0.1.1: {} + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-exists@5.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.10.2: + dependencies: + lru-cache: 10.2.2 + minipass: 7.0.4 + + path-to-regexp@6.2.2: {} + + path-type@4.0.0: {} + + pathe@0.2.0: {} + + pathe@1.1.1: {} + + pathe@1.1.2: {} + + perfect-debounce@1.0.0: {} + + picocolors@1.0.0: {} + + picomatch@2.3.1: {} + + pidtree@0.6.0: {} + + pify@4.0.1: + optional: true + + pinia-plugin-persistedstate@3.2.1(pinia@2.1.7(typescript@5.4.5)(vue@3.4.25(typescript@5.4.5))): + dependencies: + pinia: 2.1.7(typescript@5.4.5)(vue@3.4.25(typescript@5.4.5)) + + pinia@2.1.7(typescript@5.4.5)(vue@3.4.25(typescript@5.4.5)): + dependencies: + '@vue/devtools-api': 6.5.0 + vue: 3.4.25(typescript@5.4.5) + vue-demi: 0.14.6(vue@3.4.25(typescript@5.4.5)) + optionalDependencies: + typescript: 5.4.5 + + pirates@4.0.6: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + pkg-types@1.1.0: + dependencies: + confbox: 0.1.7 + mlly: 1.6.1 + pathe: 1.1.2 + + pngjs@5.0.0: {} + + posix-character-classes@0.1.1: {} + + postcss-html@1.6.0: + dependencies: + htmlparser2: 8.0.2 + js-tokens: 8.0.1 + postcss: 8.4.38 + postcss-safe-parser: 6.0.0(postcss@8.4.38) + + postcss-less@6.0.0(postcss@8.4.38): + dependencies: + postcss: 8.4.38 + + postcss-media-query-parser@0.2.3: {} + + postcss-prefix-selector@1.16.0(postcss@5.2.18): + dependencies: + postcss: 5.2.18 + + postcss-resolve-nested-selector@0.1.1: {} + + postcss-safe-parser@6.0.0(postcss@8.4.38): + dependencies: + postcss: 8.4.38 + + postcss-safe-parser@7.0.0(postcss@8.4.38): + dependencies: + postcss: 8.4.38 + + postcss-scss@4.0.9(postcss@8.4.38): + dependencies: + postcss: 8.4.38 + + postcss-selector-parser@6.0.16: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-sorting@8.0.2(postcss@8.4.38): + dependencies: + postcss: 8.4.38 + + postcss-value-parser@4.2.0: {} + + postcss@5.2.18: + dependencies: + chalk: 1.1.3 + js-base64: 2.6.4 + source-map: 0.5.7 + supports-color: 3.2.3 + + postcss@8.4.38: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.2.0 + + posthtml-parser@0.2.1: + dependencies: + htmlparser2: 3.10.1 + isobject: 2.1.0 + + posthtml-rename-id@1.0.12: + dependencies: + escape-string-regexp: 1.0.5 + + posthtml-render@1.4.0: {} + + posthtml-svg-mode@1.0.3: + dependencies: + merge-options: 1.0.1 + posthtml: 0.9.2 + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + + posthtml@0.9.2: + dependencies: + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + + preact@10.17.1: {} + + prettier-linter-helpers@1.0.0: + dependencies: + fast-diff: 1.2.0 + + prettier-plugin-packagejson@2.5.0(prettier@3.2.5): + dependencies: + sort-package-json: 2.10.0 + synckit: 0.9.0 + optionalDependencies: + prettier: 3.2.5 + + prettier@3.2.5: {} + + pretty-bytes@6.1.1: {} + + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + print-js@1.6.0: {} + + process-nextick-args@2.0.1: {} + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + proto-list@1.2.4: {} + + proxy-from-env@1.1.0: {} + + prr@1.0.1: + optional: true + + psl@1.9.0: {} + + punycode@2.3.0: {} + + qrcode@1.5.3: + dependencies: + dijkstrajs: 1.0.3 + encode-utf8: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + + qs@6.12.1: + dependencies: + side-channel: 1.0.6 + + query-string@4.3.4: + dependencies: + object-assign: 4.1.1 + strict-uri-encode: 1.1.0 + + querystringify@2.2.0: {} + + queue-microtask@1.2.3: {} + + queue-microtask@https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz: {} + + react-is@17.0.2: {} + + read-pkg-up@10.1.0: + dependencies: + find-up: 6.3.0 + read-pkg: 8.1.0 + type-fest: 4.17.0 + + read-pkg@8.1.0: + dependencies: + '@types/normalize-package-data': 2.4.1 + normalize-package-data: 6.0.0 + parse-json: 7.1.1 + type-fest: 4.17.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@3.6.2: + dependencies: + inherits: https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.6 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz: + dependencies: + picomatch: 2.3.1 + + regenerator-runtime@0.14.0: {} + + regex-not@1.0.2: + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + + relateurl@0.2.7: {} + + repeat-element@1.1.4: {} + + repeat-string@1.6.1: {} + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + require-main-filename@2.0.0: {} + + requires-port@1.0.0: {} + + resize-observer-polyfill@1.5.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-from@5.0.0: {} + + resolve-from@https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz: {} + + resolve-url@0.2.1: {} + + resolve.exports@1.1.1: {} + + resolve@1.19.0: + dependencies: + is-core-module: 2.13.0 + path-parse: 1.0.7 + + resolve@1.22.4: + dependencies: + is-core-module: 2.13.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@4.0.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + ret@0.1.15: {} + + reusify@1.0.4: {} + + reusify@https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz: {} + + rfdc@1.3.0: {} + + rimraf@2.7.1: + dependencies: + glob: 7.2.3 + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rimraf@5.0.5: + dependencies: + glob: 10.3.12 + + rollup-plugin-dts@6.1.0(rollup@3.28.1)(typescript@5.4.5): + dependencies: + magic-string: 0.30.10 + rollup: 3.28.1 + typescript: 5.4.5 + optionalDependencies: + '@babel/code-frame': 7.22.13 + + rollup-plugin-purge-icons@0.10.0: + dependencies: + '@purge-icons/core': 0.10.0 + '@purge-icons/generated': 0.10.0 + transitivePeerDependencies: + - encoding + - supports-color + + rollup-plugin-visualizer@5.12.0(rollup@4.17.0): + dependencies: + open: 8.4.2 + picomatch: 2.3.1 + source-map: 0.7.4 + yargs: 17.7.2 + optionalDependencies: + rollup: 4.17.0 + + rollup@3.28.1: + optionalDependencies: + fsevents: 2.3.3 + + rollup@4.17.0: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.17.0 + '@rollup/rollup-android-arm64': 4.17.0 + '@rollup/rollup-darwin-arm64': 4.17.0 + '@rollup/rollup-darwin-x64': 4.17.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.17.0 + '@rollup/rollup-linux-arm-musleabihf': 4.17.0 + '@rollup/rollup-linux-arm64-gnu': 4.17.0 + '@rollup/rollup-linux-arm64-musl': 4.17.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.17.0 + '@rollup/rollup-linux-riscv64-gnu': 4.17.0 + '@rollup/rollup-linux-s390x-gnu': 4.17.0 + '@rollup/rollup-linux-x64-gnu': 4.17.0 + '@rollup/rollup-linux-x64-musl': 4.17.0 + '@rollup/rollup-win32-arm64-msvc': 4.17.0 + '@rollup/rollup-win32-ia32-msvc': 4.17.0 + '@rollup/rollup-win32-x64-msvc': 4.17.0 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + run-parallel@https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz: + dependencies: + queue-microtask: https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-regex@1.1.0: + dependencies: + ret: 0.1.15 + + safer-buffer@2.1.2: {} + + sass@1.75.0: + dependencies: + chokidar: 3.6.0 + immutable: 4.3.4 + source-map-js: 1.2.0 + + sax@1.2.4: + optional: true + + saxes@5.0.1: + dependencies: + xmlchars: 2.2.0 + + scroll-into-view-if-needed@2.2.31: + dependencies: + compute-scroll-into-view: 1.0.20 + + scule@1.0.0: {} + + semver@6.3.1: {} + + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + + semver@7.6.0: + dependencies: + lru-cache: 6.0.0 + + semver@https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz: + optional: true + + 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.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + + set-value@2.0.1: + dependencies: + extend-shallow: 2.0.1 + is-extendable: 0.1.1 + is-plain-object: 2.0.4 + split-string: 3.1.0 + + setimmediate@1.0.5: {} + + shallow-equal@1.2.1: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + showdown@2.1.0: + dependencies: + commander: 9.5.0 + + side-channel@1.0.6: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.1 + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.25 + mrmime: 2.0.0 + totalist: 3.0.1 + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + slash@4.0.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.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + + snapdragon-node@2.1.1: + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + + snapdragon-util@3.0.1: + dependencies: + kind-of: 3.2.2 + + snapdragon@0.8.2: + dependencies: + base: 0.11.2 + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + + sort-object-keys@1.1.3: {} + + sort-package-json@2.10.0: + dependencies: + detect-indent: 7.0.1 + detect-newline: 4.0.0 + get-stdin: 9.0.0 + git-hooks-list: 3.1.0 + globby: 13.2.2 + is-plain-obj: 4.1.0 + semver: 7.6.0 + sort-object-keys: 1.1.3 + + sortablejs@1.14.0: {} + + sortablejs@1.15.2: {} + + source-map-js@1.2.0: {} + + source-map-resolve@0.5.3: + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.2 + resolve-url: 0.2.1 + source-map-url: 0.4.1 + urix: 0.1.0 + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map-url@0.4.1: {} + + source-map@0.5.7: {} + + source-map@0.6.1: {} + + source-map@0.7.4: {} + + sourcemap-codec@1.4.8: {} + + spdx-correct@3.1.1: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.12 + + spdx-exceptions@2.3.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.12 + + spdx-license-ids@3.0.12: {} + + split-string@3.1.0: + dependencies: + extend-shallow: 3.0.2 + + split2@4.2.0: {} + + sprintf-js@1.0.3: {} + + ssf@0.11.2: + dependencies: + frac: 1.1.2 + + stable@0.1.8: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + static-extend@0.1.2: + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + + statuses@1.5.0: {} + + statuses@https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz: {} + + strict-uri-encode@1.1.0: {} + + string-argv@0.3.2: {} + + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + 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.0 + + string-width@7.1.0: + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.0.1 + + strip-bom@4.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-final-newline@3.0.0: {} + + strip-json-comments@3.1.1: {} + + stylelint-config-html@1.1.0(postcss-html@1.6.0)(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + postcss-html: 1.6.0 + stylelint: 16.4.0(typescript@5.4.5) + + stylelint-config-property-sort-order-smacss@10.0.0(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + css-property-sort-order-smacss: 2.2.0 + stylelint: 16.4.0(typescript@5.4.5) + stylelint-order: 6.0.4(stylelint@16.4.0(typescript@5.4.5)) + + stylelint-config-recommended-scss@14.0.0(postcss@8.4.38)(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + postcss-scss: 4.0.9(postcss@8.4.38) + stylelint: 16.4.0(typescript@5.4.5) + stylelint-config-recommended: 14.0.0(stylelint@16.4.0(typescript@5.4.5)) + stylelint-scss: 6.2.1(stylelint@16.4.0(typescript@5.4.5)) + optionalDependencies: + postcss: 8.4.38 + + stylelint-config-recommended-vue@1.5.0(postcss-html@1.6.0)(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + postcss-html: 1.6.0 + semver: 7.5.4 + stylelint: 16.4.0(typescript@5.4.5) + stylelint-config-html: 1.1.0(postcss-html@1.6.0)(stylelint@16.4.0(typescript@5.4.5)) + stylelint-config-recommended: 12.0.0(stylelint@16.4.0(typescript@5.4.5)) + + stylelint-config-recommended@12.0.0(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + stylelint: 16.4.0(typescript@5.4.5) + + stylelint-config-recommended@14.0.0(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + stylelint: 16.4.0(typescript@5.4.5) + + stylelint-config-standard-scss@13.1.0(postcss@8.4.38)(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + stylelint: 16.4.0(typescript@5.4.5) + stylelint-config-recommended-scss: 14.0.0(postcss@8.4.38)(stylelint@16.4.0(typescript@5.4.5)) + stylelint-config-standard: 36.0.0(stylelint@16.4.0(typescript@5.4.5)) + optionalDependencies: + postcss: 8.4.38 + + stylelint-config-standard@36.0.0(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + stylelint: 16.4.0(typescript@5.4.5) + stylelint-config-recommended: 14.0.0(stylelint@16.4.0(typescript@5.4.5)) + + stylelint-order@6.0.4(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + postcss: 8.4.38 + postcss-sorting: 8.0.2(postcss@8.4.38) + stylelint: 16.4.0(typescript@5.4.5) + + stylelint-prettier@5.0.0(prettier@3.2.5)(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + prettier: 3.2.5 + prettier-linter-helpers: 1.0.0 + stylelint: 16.4.0(typescript@5.4.5) + + stylelint-scss@6.2.1(stylelint@16.4.0(typescript@5.4.5)): + dependencies: + known-css-properties: 0.29.0 + postcss-media-query-parser: 0.2.3 + postcss-resolve-nested-selector: 0.1.1 + postcss-selector-parser: 6.0.16 + postcss-value-parser: 4.2.0 + stylelint: 16.4.0(typescript@5.4.5) + + stylelint@16.4.0(typescript@5.4.5): + dependencies: + '@csstools/css-parser-algorithms': 2.6.1(@csstools/css-tokenizer@2.2.4) + '@csstools/css-tokenizer': 2.2.4 + '@csstools/media-query-list-parser': 2.1.9(@csstools/css-parser-algorithms@2.6.1(@csstools/css-tokenizer@2.2.4))(@csstools/css-tokenizer@2.2.4) + '@csstools/selector-specificity': 3.0.3(postcss-selector-parser@6.0.16) + '@dual-bundle/import-meta-resolve': 4.0.0 + balanced-match: 2.0.0 + colord: 2.9.3 + cosmiconfig: 9.0.0(typescript@5.4.5) + css-functions-list: 3.2.2 + css-tree: 2.3.1 + debug: 4.3.4 + fast-glob: 3.3.2 + fastest-levenshtein: 1.0.16 + file-entry-cache: 8.0.0 + global-modules: 2.0.0 + globby: 11.1.0 + globjoin: 0.1.4 + html-tags: 3.3.1 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-plain-object: 5.0.0 + known-css-properties: 0.30.0 + mathml-tag-names: 2.1.3 + meow: 13.2.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.38 + postcss-resolve-nested-selector: 0.1.1 + postcss-safe-parser: 7.0.0(postcss@8.4.38) + postcss-selector-parser: 6.0.16 + postcss-value-parser: 4.2.0 + resolve-from: 5.0.0 + string-width: 4.2.3 + strip-ansi: 7.1.0 + supports-hyperlinks: 3.0.0 + svg-tags: 1.0.0 + table: 6.8.2 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + - typescript + + stylis@4.3.0: {} + + supports-color@2.0.0: {} + + supports-color@3.2.3: + dependencies: + has-flag: 1.0.0 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-color@https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz: + dependencies: + has-flag: https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz + + supports-color@https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz: + dependencies: + has-flag: https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz + + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-hyperlinks@3.0.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svg-baker@1.7.0: + dependencies: + bluebird: 3.7.2 + clone: 2.1.2 + he: 1.2.0 + image-size: 0.5.5 + loader-utils: 1.4.2 + merge-options: 1.0.1 + micromatch: 3.1.0 + postcss: 5.2.18 + postcss-prefix-selector: 1.16.0(postcss@5.2.18) + posthtml-rename-id: 1.0.12 + posthtml-svg-mode: 1.0.3 + query-string: 4.3.4 + traverse: 0.6.7 + transitivePeerDependencies: + - supports-color + + svg-tags@1.0.0: {} + + svgo@2.8.0: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 4.3.0 + css-tree: 1.1.3 + csso: 4.2.0 + picocolors: 1.0.0 + stable: 0.1.8 + + symbol-tree@3.2.4: {} + + synckit@0.9.0: + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.6.2 + + table@6.8.2: + dependencies: + ajv: 8.12.0 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + temp-dir@3.0.0: {} + + tempfile@5.0.0: + dependencies: + temp-dir: 3.0.0 + + terminal-link@2.1.1: + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + + terser@5.19.3: + dependencies: + '@jridgewell/source-map': 0.3.5 + acorn: 8.11.3 + commander: 2.20.3 + source-map-support: 0.5.21 + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + + text-extensions@2.4.0: {} + + throat@6.0.2: {} + + throttle-debounce@5.0.0: {} + + through@2.3.8: {} + + tinymce@5.10.9: {} + + tmp@0.2.1: + dependencies: + rimraf: 3.0.2 + + tmpl@1.0.5: {} + + to-fast-properties@2.0.0: {} + + to-object-path@0.3.0: + dependencies: + kind-of: 3.2.2 + + to-regex-range@2.1.1: + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + to-regex-range@https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz: + dependencies: + is-number: https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz + + to-regex@3.0.2: + dependencies: + define-property: 2.0.2 + extend-shallow: 3.0.2 + regex-not: 1.0.2 + safe-regex: 1.1.0 + + totalist@3.0.1: {} + + tough-cookie@4.1.3: + dependencies: + psl: 1.9.0 + punycode: 2.3.0 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@0.0.3: {} + + tr46@2.1.0: + dependencies: + punycode: 2.3.0 + + traverse@0.3.9: {} + + traverse@0.6.7: {} + + ts-node@10.9.1(@types/node@20.12.7)(typescript@5.4.5): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.3 + '@types/node': 20.12.7 + acorn: 8.11.3 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.4.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optional: true + + tslib@2.3.0: {} + + tslib@2.6.2: {} + + turbo-darwin-64@1.13.3: + optional: true + + turbo-darwin-arm64@1.13.3: + optional: true + + turbo-linux-64@1.13.3: + optional: true + + turbo-linux-arm64@1.13.3: + optional: true + + turbo-windows-64@1.13.3: + optional: true + + turbo-windows-arm64@1.13.3: + optional: true + + turbo@1.13.3: + optionalDependencies: + turbo-darwin-64: 1.13.3 + turbo-darwin-arm64: 1.13.3 + turbo-linux-64: 1.13.3 + turbo-linux-arm64: 1.13.3 + turbo-windows-64: 1.13.3 + turbo-windows-arm64: 1.13.3 + + type-detect@4.0.8: {} + + type-fest@0.21.3: {} + + type-fest@3.13.1: {} + + type-fest@4.17.0: {} + + typedarray-to-buffer@3.1.5: + dependencies: + is-typedarray: 1.0.0 + + typescript@5.4.2: {} + + typescript@5.4.5: {} + + ufo@1.3.0: {} + + ufo@1.5.3: {} + + uglify-js@3.17.4: + optional: true + + unbuild@2.0.0(sass@1.75.0)(typescript@5.4.5): + dependencies: + '@rollup/plugin-alias': 5.0.0(rollup@3.28.1) + '@rollup/plugin-commonjs': 25.0.7(rollup@3.28.1) + '@rollup/plugin-json': 6.0.0(rollup@3.28.1) + '@rollup/plugin-node-resolve': 15.2.1(rollup@3.28.1) + '@rollup/plugin-replace': 5.0.2(rollup@3.28.1) + '@rollup/pluginutils': 5.0.4(rollup@3.28.1) + chalk: 5.3.0 + citty: 0.1.3 + consola: 3.2.3 + defu: 6.1.2 + esbuild: 0.19.2 + globby: 13.2.2 + hookable: 5.5.3 + jiti: 1.19.3 + magic-string: 0.30.3 + mkdist: 1.3.0(sass@1.75.0)(typescript@5.4.5) + mlly: 1.4.1 + pathe: 1.1.1 + pkg-types: 1.1.0 + pretty-bytes: 6.1.1 + rollup: 3.28.1 + rollup-plugin-dts: 6.1.0(rollup@3.28.1)(typescript@5.4.5) + scule: 1.0.0 + untyped: 1.4.0 + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - sass + - supports-color + + unconfig@0.3.13: + dependencies: + '@antfu/utils': 0.7.7 + defu: 6.1.4 + jiti: 1.21.0 + + undici-types@5.26.5: {} + + unicorn-magic@0.1.0: {} + + union-value@1.0.1: + dependencies: + arr-union: 3.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + set-value: 2.0.1 + + universalify@0.1.2: {} + + universalify@0.2.0: {} + + universalify@2.0.0: {} + + unocss@0.59.4(postcss@5.2.18)(rollup@4.17.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)): + dependencies: + '@unocss/astro': 0.59.4(rollup@4.17.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + '@unocss/cli': 0.59.4(rollup@4.17.0) + '@unocss/core': 0.59.4 + '@unocss/extractor-arbitrary-variants': 0.59.4 + '@unocss/postcss': 0.59.4(postcss@5.2.18) + '@unocss/preset-attributify': 0.59.4 + '@unocss/preset-icons': 0.59.4 + '@unocss/preset-mini': 0.59.4 + '@unocss/preset-tagify': 0.59.4 + '@unocss/preset-typography': 0.59.4 + '@unocss/preset-uno': 0.59.4 + '@unocss/preset-web-fonts': 0.59.4 + '@unocss/preset-wind': 0.59.4 + '@unocss/reset': 0.59.4 + '@unocss/transformer-attributify-jsx': 0.59.4 + '@unocss/transformer-attributify-jsx-babel': 0.59.4 + '@unocss/transformer-compile-class': 0.59.4 + '@unocss/transformer-directives': 0.59.4 + '@unocss/transformer-variant-group': 0.59.4 + '@unocss/vite': 0.59.4(rollup@4.17.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + optionalDependencies: + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - postcss + - rollup + - supports-color + + unocss@0.59.4(postcss@8.4.38)(rollup@3.28.1)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)): + dependencies: + '@unocss/astro': 0.59.4(rollup@3.28.1)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + '@unocss/cli': 0.59.4(rollup@3.28.1) + '@unocss/core': 0.59.4 + '@unocss/extractor-arbitrary-variants': 0.59.4 + '@unocss/postcss': 0.59.4(postcss@8.4.38) + '@unocss/preset-attributify': 0.59.4 + '@unocss/preset-icons': 0.59.4 + '@unocss/preset-mini': 0.59.4 + '@unocss/preset-tagify': 0.59.4 + '@unocss/preset-typography': 0.59.4 + '@unocss/preset-uno': 0.59.4 + '@unocss/preset-web-fonts': 0.59.4 + '@unocss/preset-wind': 0.59.4 + '@unocss/reset': 0.59.4 + '@unocss/transformer-attributify-jsx': 0.59.4 + '@unocss/transformer-attributify-jsx-babel': 0.59.4 + '@unocss/transformer-compile-class': 0.59.4 + '@unocss/transformer-directives': 0.59.4 + '@unocss/transformer-variant-group': 0.59.4 + '@unocss/vite': 0.59.4(rollup@3.28.1)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)) + optionalDependencies: + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - postcss + - rollup + - supports-color + + unpipe@1.0.0: {} + + unpipe@https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz: {} + + unset-value@1.0.0: + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + + untyped@1.4.0: + dependencies: + '@babel/core': 7.24.4 + '@babel/standalone': 7.22.13 + '@babel/types': 7.22.11 + defu: 6.1.2 + jiti: 1.19.3 + mri: 1.2.0 + scule: 1.0.0 + transitivePeerDependencies: + - supports-color + + unzipper@0.10.14: + dependencies: + big-integer: 1.6.51 + binary: 0.3.0 + bluebird: 3.4.7 + buffer-indexof-polyfill: 1.0.2 + duplexer2: 0.1.4 + fstream: 1.0.12 + graceful-fs: 4.2.11 + listenercount: 1.0.1 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + + update-browserslist-db@1.0.13(browserslist@4.23.0): + dependencies: + browserslist: 4.23.0 + escalade: 3.1.1 + picocolors: 1.0.0 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.0 + + urix@0.1.0: {} + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + use@3.1.1: {} + + util-deprecate@1.0.2: {} + + utils-merge@1.0.1: {} + + utils-merge@https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz: {} + + uuid@8.3.2: {} + + v8-compile-cache-lib@3.0.1: + optional: true + + v8-to-istanbul@8.1.1: + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + convert-source-map: 1.9.0 + source-map: 0.7.4 + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.1.1 + spdx-expression-parse: 3.0.1 + + validator@13.11.0: {} + + vary@1.1.2: {} + + vditor@3.10.4: + dependencies: + diff-match-patch: 1.0.5 + + vite-plugin-compression@0.5.1(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)): + dependencies: + chalk: 4.1.2 + debug: 4.3.4 + fs-extra: 10.1.0 + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - supports-color + + vite-plugin-dts@3.9.0(@types/node@20.12.7)(rollup@4.17.0)(typescript@5.4.5)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)): + dependencies: + '@microsoft/api-extractor': 7.43.0(@types/node@20.12.7) + '@rollup/pluginutils': 5.1.0(rollup@4.17.0) + '@vue/language-core': 1.8.27(typescript@5.4.5) + debug: 4.3.4 + kolorist: 1.8.0 + magic-string: 0.30.10 + typescript: 5.4.5 + vue-tsc: 1.8.27(typescript@5.4.5) + optionalDependencies: + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + + vite-plugin-html@3.2.2(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)): + dependencies: + '@rollup/pluginutils': 4.2.1 + colorette: 2.0.20 + connect-history-api-fallback: 1.6.0 + consola: 2.15.3 + dotenv: 16.4.5 + dotenv-expand: 8.0.3 + ejs: 3.1.9 + fast-glob: 3.3.2 + fs-extra: 10.1.0 + html-minifier-terser: 6.1.0 + node-html-parser: 5.4.2 + pathe: 0.2.0 + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + + vite-plugin-mock@2.9.8(mockjs@1.1.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)): + dependencies: + '@types/mockjs': 1.0.10 + chalk: 4.1.2 + chokidar: 3.6.0 + connect: 3.7.0 + debug: 4.3.4 + esbuild: 0.14.54 + fast-glob: 3.3.2 + mockjs: 1.1.0 + path-to-regexp: 6.2.2 + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - supports-color + + vite-plugin-mock@https://registry.npmmirror.com/vite-plugin-mock/-/vite-plugin-mock-2.9.8.tgz(mockjs@1.1.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)): + dependencies: + '@types/mockjs': 1.0.10 + chalk: https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz + chokidar: https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz + connect: https://registry.npmmirror.com/connect/-/connect-3.7.0.tgz + debug: https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz + esbuild: https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz + fast-glob: https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.1.tgz + mockjs: 1.1.0 + path-to-regexp: 6.2.2 + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - supports-color + + vite-plugin-purge-icons@0.10.0(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)): + dependencies: + '@purge-icons/core': 0.10.0 + '@purge-icons/generated': 0.10.0 + rollup-plugin-purge-icons: 0.10.0 + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - encoding + - supports-color + + vite-plugin-svg-icons@2.0.1(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)): + dependencies: + '@types/svgo': 2.6.4 + cors: 2.8.5 + debug: 4.3.4 + etag: 1.8.1 + fs-extra: 10.1.0 + pathe: 0.2.0 + svg-baker: 1.7.0 + svgo: 2.8.0 + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - supports-color + + vite-plugin-vue-inspector@5.0.1(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3)): + dependencies: + '@babel/core': 7.24.4 + '@babel/plugin-proposal-decorators': 7.24.1(@babel/core@7.24.4) + '@babel/plugin-syntax-import-attributes': 7.24.1(@babel/core@7.24.4) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.4) + '@babel/plugin-transform-typescript': 7.24.4(@babel/core@7.24.4) + '@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.24.4) + '@vue/compiler-dom': 3.4.25 + kolorist: 1.8.0 + magic-string: 0.30.10 + vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3) + transitivePeerDependencies: + - supports-color + + vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.19.3): + dependencies: + esbuild: 0.20.2 + postcss: 8.4.38 + rollup: 4.17.0 + optionalDependencies: + '@types/node': 20.12.7 + fsevents: 2.3.3 + less: 4.2.0 + sass: 1.75.0 + terser: 5.19.3 + + vue-component-type-helpers@2.0.14: {} + + vue-demi@0.14.0(vue@3.2.47): + dependencies: + vue: 3.2.47 + + vue-demi@0.14.6(vue@3.4.25(typescript@5.4.5)): + dependencies: + vue: 3.4.25(typescript@5.4.5) + + vue-demi@0.14.7(vue@3.4.25(typescript@5.4.5)): + dependencies: + vue: 3.4.25(typescript@5.4.5) + + vue-i18n@9.13.1(vue@3.4.25(typescript@5.4.5)): + dependencies: + '@intlify/core-base': 9.13.1 + '@intlify/shared': 9.13.1 + '@vue/devtools-api': 6.5.0 + vue: 3.4.25(typescript@5.4.5) + + vue-json-pretty@2.4.0(vue@3.4.25(typescript@5.4.5)): + dependencies: + vue: 3.4.25(typescript@5.4.5) + + vue-router@4.3.2(vue@3.4.25(typescript@5.4.5)): + dependencies: + '@vue/devtools-api': 6.6.1 + vue: 3.4.25(typescript@5.4.5) + + vue-template-compiler@2.7.14: + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + vue-tsc@1.8.27(typescript@5.4.5): + dependencies: + '@volar/typescript': 1.11.1 + '@vue/language-core': 1.8.27(typescript@5.4.5) + semver: 7.6.0 + typescript: 5.4.5 + + vue-tsc@2.0.14(typescript@5.4.5): + dependencies: + '@volar/typescript': 2.2.0-alpha.10 + '@vue/language-core': 2.0.14(typescript@5.4.5) + semver: 7.5.4 + typescript: 5.4.5 + + vue-types@3.0.2(vue@3.4.25(typescript@5.4.5)): + dependencies: + is-plain-object: 3.0.1 + vue: 3.4.25(typescript@5.4.5) + + vue-types@5.1.1(vue@3.4.25(typescript@5.4.5)): + dependencies: + is-plain-object: 5.0.0 + optionalDependencies: + vue: 3.4.25(typescript@5.4.5) + + vue@3.2.47: + dependencies: + '@vue/compiler-dom': 3.2.47 + '@vue/compiler-sfc': 3.2.47 + '@vue/runtime-dom': 3.2.47 + '@vue/server-renderer': 3.2.47(vue@3.2.47) + '@vue/shared': 3.2.47 + + vue@3.4.25(typescript@5.4.5): + dependencies: + '@vue/compiler-dom': 3.4.25 + '@vue/compiler-sfc': 3.4.25 + '@vue/runtime-dom': 3.4.25 + '@vue/server-renderer': 3.4.25(vue@3.4.25(typescript@5.4.5)) + '@vue/shared': 3.4.25 + optionalDependencies: + typescript: 5.4.5 + + vuedraggable@https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz(vue@3.4.25(typescript@5.4.5)): + dependencies: + sortablejs: 1.14.0 + vue: 3.4.25(typescript@5.4.5) + + vxe-table-plugin-export-xlsx@4.0.1(vxe-table@4.6.6(vue@3.4.25(typescript@5.4.5))): + dependencies: + vxe-table: 4.6.6(vue@3.4.25(typescript@5.4.5)) + + vxe-table@4.6.6(vue@3.4.25(typescript@5.4.5)): + dependencies: + dom-zindex: 1.0.2 + vue: 3.4.25(typescript@5.4.5) + xe-utils: 3.5.25 + + w3c-hr-time@1.0.2: + dependencies: + browser-process-hrtime: 1.0.0 + + w3c-xmlserializer@2.0.0: + dependencies: + xml-name-validator: 3.0.0 + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + warning@4.0.3: + dependencies: + loose-envify: 1.4.0 + + webidl-conversions@3.0.1: {} + + webidl-conversions@5.0.0: {} + + webidl-conversions@6.1.0: {} + + whatwg-encoding@1.0.5: + dependencies: + iconv-lite: 0.4.24 + + whatwg-mimetype@2.3.0: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + whatwg-url@8.7.0: + dependencies: + lodash: 4.17.21 + tr46: 2.1.0 + webidl-conversions: 6.1.0 + + which-module@2.0.1: {} + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wmf@1.0.2: {} + + word@0.3.0: {} + + wordwrap@1.0.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.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.1.0 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + write-file-atomic@3.0.3: + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + + ws@7.5.9: {} + + xe-utils@3.5.25: {} + + xlsx@0.18.5: + dependencies: + adler-32: 1.3.1 + cfb: 1.2.2 + codepage: 1.15.0 + crc-32: 1.2.2 + ssf: 0.11.2 + wmf: 1.0.2 + word: 0.3.0 + + xml-name-validator@3.0.0: {} + + xmlchars@2.2.0: {} + + y18n@4.0.3: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yallist@4.0.0: {} + + yaml@2.3.4: {} + + 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.1.1 + 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.1.1 + 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 + + yn@3.1.1: + optional: true + + yocto-queue@0.1.0: {} + + yocto-queue@1.0.0: {} + + z-schema@5.0.5: + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.11.0 + optionalDependencies: + commander: 9.5.0 + + zip-stream@4.1.0: + dependencies: + archiver-utils: 2.1.0 + compress-commons: 4.1.1 + readable-stream: 3.6.2 + + zrender@5.5.0: + dependencies: + tslib: 2.3.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..7195df0 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,4 @@ +packages: + - 'internal/*' + - 'packages/*' + - 'apps/test-server' diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e95efb7b01555c2c79e5cad114013a9ea5bd5 GIT binary patch literal 16025 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 literal 0 HcmV?d00001 diff --git a/public/resource/.DS_Store b/public/resource/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ff76ad292ecab449324f719da078148b72c66d2c GIT binary patch literal 6148 zcmeHKy-veG47S@!6tQ&dcmq2s6B9a0c!ItFYKvN=hIF7qw|fmF2XmlBQ)u z2yDssUHo%SzDRLQL_FTiM??c6>O%!P=U9%2_(faNF^f1^&KON*Rk?1(x#9ORAn&eA z&s5T4wWzRx?* zv?ET`KRBnXj^4*XRO5cG<#t@00cXG&_;(DTXN&YN6n%9DoB?NG&wzX%0#q;>CdK^e zz>-G*U=QXj*vl*-Il(X*CPjE4tf@dvWg9VA(_s%57Y&o5rW4!n!B&}VLg8E;=Z73l z92I?a2AqK=16{owNdJF0J^we8{K^?{2L2QS+$$!<7>{JVwe@h)YXkHVDk5=7ai4-s gZpDa|Ry>4efj!6u7!8vmED-+@$Taxk4E!hqJLIK5-2eap literal 0 HcmV?d00001 diff --git a/public/resource/img/logo.png b/public/resource/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c04e95efb7b01555c2c79e5cad114013a9ea5bd5 GIT binary patch literal 16025 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 literal 0 HcmV?d00001 diff --git a/public/resource/tinymce/icons/default/icons.min.js b/public/resource/tinymce/icons/default/icons.min.js new file mode 100644 index 0000000..7ed2965 --- /dev/null +++ b/public/resource/tinymce/icons/default/icons.min.js @@ -0,0 +1 @@ +tinymce.IconManager.add("default",{icons:{"accessibility-check":'',"action-next":'',"action-prev":'',addtag:'',"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-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:'',minus:'',"more-drawer":'',"new-document":'',"new-tab":'',"non-breaking":'',notice:'',"ordered-list-rtl":'',"ordered-list":'',orientation:'',outdent:'',"page-break":'',paragraph:'',"paste-column-after":'',"paste-column-before":'',"paste-row-after":'',"paste-row-before":'',"paste-text":'',paste:'',"anent-pen":'',plus:'',preferences:'',preview:'',print:'',quote:'',redo:'',reload:'',"remove-formatting":'',remove:'',"resize-handle":'',resize:'',"restore-draft":'',"rotate-left":'',"rotate-right":'',rtl:'',save:'',search:'',"select-all":'',selected:'',settings:'',sharpen:'',sourcecode:'',"spell-check":'',"strike-through":'',subscript:'',superscript:'',"table-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:'',user:'',"vertical-align":'',visualblocks:'',visualchars:'',warning:'',"zoom-in":'',"zoom-out":''}}); diff --git a/public/resource/tinymce/langs/README.md b/public/resource/tinymce/langs/README.md new file mode 100644 index 0000000..a52bf03 --- /dev/null +++ b/public/resource/tinymce/langs/README.md @@ -0,0 +1,3 @@ +This is where language files should be placed. + +Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/ diff --git a/public/resource/tinymce/langs/en.js b/public/resource/tinymce/langs/en.js new file mode 100644 index 0000000..27337c3 --- /dev/null +++ b/public/resource/tinymce/langs/en.js @@ -0,0 +1,419 @@ +tinymce.addI18n('es', { + Redo: 'Rehacer', + Undo: 'Deshacer', + Cut: 'Cortar', + Copy: 'Copiar', + Paste: 'Pegar', + 'Select all': 'Seleccionar todo', + 'New document': 'Nuevo documento', + Ok: 'Ok', + Cancel: 'Cancelar', + 'Visual aids': 'Ayudas visuales', + Bold: 'Negrita', + Italic: 'Cursiva', + Underline: 'Subrayado', + Strikethrough: 'Tachado', + Superscript: 'Super\u00edndice', + Subscript: 'Sub\u00edndice', + 'Clear formatting': 'Limpiar formato', + 'Align left': 'Alinear a la izquierda', + 'Align center': 'Alinear al centro', + 'Align right': 'Alinear a la derecha', + Justify: 'Justificar', + 'Bullet list': 'Lista de vi\u00f1etas', + 'Numbered list': 'Lista numerada', + 'Decrease indent': 'Disminuir sangr\u00eda', + 'Increase indent': 'Incrementar sangr\u00eda', + Close: 'Cerrar', + Formats: 'Formatos', + "Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": 'Su navegador no es compatible con el acceso directo al portapapeles. Use las teclas Crtl+X\/C\/V de su teclado.', + Headers: 'Encabezados', + 'Header 1': 'Encabezado 1', + 'Header 2': 'Encabezado 2', + 'Header 3': 'Encabezado 3', + 'Header 4': 'Encabezado 4', + 'Header 5': 'Encabezado 5', + 'Header 6': 'Encabezado 6', + Headings: 'Encabezados', + 'Heading 1': 'Encabezado 1', + 'Heading 2': 'Encabezado 2', + 'Heading 3': 'Encabezado 3', + 'Heading 4': 'Encabezado 4', + 'Heading 5': 'Encabezado 5', + 'Heading 6': 'Encabezado 6', + Preformatted: 'Con formato previo', + Div: 'Div', + Pre: 'Pre', + Code: 'C\u00f3digo', + Paragraph: 'P\u00e1rrafo', + Blockquote: 'Blockquote', + Inline: 'Alineado', + Blocks: 'Bloques', + 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.': 'Pegar est\u00e1 ahora en modo de texto plano. El contenido se pegar\u00e1 como texto plano hasta que desactive esta opci\u00f3n.', + Fonts: 'Fuentes', + 'Font Sizes': 'Tama\u00f1os de fuente', + Class: 'Clase', + 'Browse for an image': 'Buscar una imagen', + OR: 'OR', + 'Drop an image here': 'Arrastre una imagen aqu\u00ed', + Upload: 'Cargar', + Block: 'Bloque', + Align: 'Alinear', + Default: 'Por defecto', + Circle: 'C\u00edrculo', + Disc: 'Disco', + Square: 'Cuadrado', + 'Lower Alpha': 'Inferior Alfa', + 'Lower Greek': 'Inferior Griega', + 'Lower Roman': 'Inferior Romana', + 'Upper Alpha': 'Superior Alfa', + 'Upper Roman': 'Superior Romana', + 'Anchor...': 'Anclaje...', + Name: 'Nombre', + Id: 'Id', + 'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.': 'Deber\u00eda comenzar por una letra, seguida solo de letras, n\u00fameros, guiones, puntos, dos puntos o guiones bajos.', + 'You have unsaved changes are you sure you want to navigate away?': 'Tiene cambios sin guardar. \u00bfEst\u00e1 seguro de que quiere salir?', + 'Restore last draft': 'Restaurar el \u00faltimo borrador', + 'Special character...': 'Car\u00e1cter especial...', + 'Source code': 'C\u00f3digo fuente', + 'Insert\/Edit code sample': 'Insertar\/editar c\u00f3digo de prueba', + Language: 'Idioma', + 'Code sample...': 'Ejemplo de c\u00f3digo...', + 'Color Picker': 'Selector de colores', + R: 'R', + G: 'V', + B: 'A', + 'Left to right': 'De izquierda a derecha', + 'Right to left': 'De derecha a izquierda', + 'Emoticons...': 'Emoticones...', + 'Metadata and Document Properties': 'Metadatos y propiedades del documento', + Title: 'T\u00edtulo', + Keywords: 'Palabras clave', + Description: 'Descripci\u00f3n', + Robots: 'Robots', + Author: 'Autor', + Encoding: 'Codificaci\u00f3n', + Fullscreen: 'Pantalla completa', + Action: 'Acci\u00f3n', + Shortcut: 'Atajo', + Help: 'Ayuda', + Address: 'Direcci\u00f3n', + 'Focus to menubar': 'Enfocar la barra del men\u00fa', + 'Focus to toolbar': 'Enfocar la barra de herramientas', + 'Focus to element path': 'Enfocar la ruta del elemento', + 'Focus to contextual toolbar': 'Enfocar la barra de herramientas contextual', + 'Insert link (if link plugin activated)': 'Insertar enlace (si el complemento de enlace est\u00e1 activado)', + 'Save (if save plugin activated)': 'Guardar (si el componente de salvar est\u00e1 activado)', + 'Find (if searchreplace plugin activated)': 'Buscar (si el complemento buscar-remplazar est\u00e1 activado)', + 'Plugins installed ({0}):': 'Plugins instalados ({0}):', + 'Premium plugins:': 'Complementos premium:', + 'Learn more...': 'Aprende m\u00e1s...', + 'You are using {0}': 'Estas usando {0}', + Plugins: 'Complementos', + 'Handy Shortcuts': 'Accesos directos', + 'Horizontal line': 'L\u00ednea horizontal', + 'Insert\/edit image': 'Insertar\/editar imagen', + 'Image description': 'Descripci\u00f3n de la imagen', + Source: 'Enlace', + Dimensions: 'Dimensiones', + 'Constrain proportions': 'Restringir proporciones', + General: 'General', + Advanced: 'Avanzado', + Style: 'Estilo', + 'Vertical space': 'Espacio vertical', + 'Horizontal space': 'Espacio horizontal', + Border: 'Borde', + 'Insert image': 'Insertar imagen', + 'Image...': 'Imagen...', + 'Image list': 'Lista de im\u00e1genes', + 'Rotate counterclockwise': 'Girar a la izquierda', + 'Rotate clockwise': 'Girar a la derecha', + 'Flip vertically': 'Invertir verticalmente', + 'Flip horizontally': 'Invertir horizontalmente', + 'Edit image': 'Editar imagen', + 'Image options': 'Opciones de imagen', + 'Zoom in': 'Acercar', + 'Zoom out': 'Alejar', + Crop: 'Recortar', + Resize: 'Redimensionar', + Orientation: 'Orientaci\u00f3n', + Brightness: 'Brillo', + Sharpen: 'Forma', + Contrast: 'Contraste', + 'Color levels': 'Niveles de color', + Gamma: 'Gamma', + Invert: 'Invertir', + Apply: 'Aplicar', + Back: 'Atr\u00e1s', + 'Insert date\/time': 'Insertar fecha\/hora', + 'Date\/time': 'Fecha\/hora', + 'Insert\/Edit Link': 'Insertar\/editar enlace', + 'Insert\/edit link': 'Insertar\/editar enlace', + 'Text to display': 'Texto para mostrar', + Url: 'URL', + 'Open link in...': 'Abrir enlace en...', + 'Current window': 'Ventana actual', + None: 'Ninguno', + 'New window': 'Nueva ventana', + 'Remove link': 'Quitar enlace', + Anchors: 'Anclas', + 'Link...': 'Enlace...', + 'Paste or type a link': 'Pega o introduce un enlace', + 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?': 'El enlace que has introducido no parece ser una direcci\u00f3n de correo electr\u00f3nico. Quieres a\u00f1adir el prefijo necesario mailto: ?', + 'The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?': 'El enlace que has introducido no parece ser una enlace externo. Quieres a\u00f1adir el prefijo necesario http:\/\/ ?', + 'Link list': 'Lista de enlaces', + 'Insert video': 'Insertar video', + 'Insert\/edit video': 'Insertar\/editar video', + 'Insert\/edit media': 'Insertar\/editar medio', + 'Alternative source': 'Enlace alternativo', + 'Alternative source URL': 'Origen de URL alternativo', + 'Media poster (Image URL)': 'P\u00f3ster de medio (URL de imagen)', + 'Paste your embed code below:': 'Pega tu c\u00f3digo embebido debajo', + Embed: 'Incrustado', + 'Media...': 'Medios...', + 'Nonbreaking space': 'Espacio fijo', + 'Page break': 'Salto de p\u00e1gina', + 'Paste as text': 'Pegar como texto', + Preview: 'Previsualizar', + 'Print...': 'Imprimir...', + Save: 'Guardar', + Find: 'Buscar', + 'Replace with': 'Reemplazar con', + Replace: 'Reemplazar', + 'Replace all': 'Reemplazar todo', + Previous: 'Anterior', + Next: 'Siguiente', + 'Find and replace...': 'Buscar y reemplazar...', + 'Could not find the specified string.': 'No se encuentra la cadena de texto especificada', + 'Match case': 'Coincidencia exacta', + 'Find whole words only': 'Solo palabras completas', + 'Spell check': 'Revisar ortograf\u00eda', + Ignore: 'Ignorar', + 'Ignore all': 'Ignorar todos', + Finish: 'Finalizar', + 'Add to Dictionary': 'A\u00f1adir al Diccionario', + 'Insert table': 'Insertar tabla', + 'Table properties': 'Propiedades de la tabla', + 'Delete table': 'Eliminar tabla', + Cell: 'Celda', + Row: 'Fila', + Column: 'Columna', + 'Cell properties': 'Propiedades de la celda', + 'Merge cells': 'Combinar celdas', + 'Split cell': 'Dividir celdas', + 'Insert row before': 'Insertar fila antes', + 'Insert row after': 'Insertar fila despu\u00e9s ', + 'Delete row': 'Eliminar fila', + 'Row properties': 'Propiedades de la fila', + 'Cut row': 'Cortar fila', + 'Copy row': 'Copiar fila', + 'Paste row before': 'Pegar la fila antes', + 'Paste row after': 'Pegar la fila despu\u00e9s', + 'Insert column before': 'Insertar columna antes', + 'Insert column after': 'Insertar columna despu\u00e9s', + 'Delete column': 'Eliminar columna', + Cols: 'Columnas', + Rows: 'Filas', + Width: 'Ancho', + Height: 'Alto', + 'Cell spacing': 'Espacio entre celdas', + 'Cell padding': 'Relleno de celda', + 'Show caption': 'Mostrar t\u00edtulo', + Left: 'Izquierda', + Center: 'Centrado', + Right: 'Derecha', + 'Cell type': 'Tipo de celda', + Scope: '\u00c1mbito', + Alignment: 'Alineaci\u00f3n', + 'H Align': 'Alineamiento Horizontal', + 'V Align': 'Alineamiento Vertical', + Top: 'Arriba', + Middle: 'Centro', + Bottom: 'Abajo', + 'Header cell': 'Celda de la cebecera', + 'Row group': 'Grupo de filas', + 'Column group': 'Grupo de columnas', + 'Row type': 'Tipo de fila', + Header: 'Cabecera', + Body: 'Cuerpo', + Footer: 'Pie de p\u00e1gina', + 'Border color': 'Color del borde', + 'Insert template...': 'Insertar plantilla...', + Templates: 'Plantillas', + Template: 'Plantilla', + 'Text color': 'Color del texto', + 'Background color': 'Color de fondo', + 'Custom...': 'Personalizar...', + 'Custom color': 'Color personalizado', + 'No color': 'Sin color', + 'Remove color': 'Quitar color', + 'Table of Contents': 'Tabla de contenidos', + 'Show blocks': 'Mostrar bloques', + 'Show invisible characters': 'Mostrar caracteres invisibles', + 'Word count': 'Contar palabras', + Count: 'Recuento', + Document: 'Documento', + Selection: 'Selecci\u00f3n', + Words: 'Palabras', + 'Words: {0}': 'Palabras: {0}', + '{0} words': '{0} palabras', + File: 'Archivo', + Edit: 'Editar', + Insert: 'Insertar', + View: 'Ver', + Format: 'Formato', + Table: 'Tabla', + Tools: 'Herramientas', + 'Powered by {0}': 'Desarrollado por {0}', + 'Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help': '\u00c1rea de texto enriquecido. Pulse ALT-F9 para el menu. Pulse ALT-F10 para la barra de herramientas. Pulse ALT-0 para ayuda', + 'Image title': 'Titulo de imagen', + 'Border width': 'Ancho de borde', + 'Border style': 'Estilo de borde', + Error: 'Error', + Warn: 'Advertencia', + Valid: 'V\u00e1lido', + 'To open the popup, press Shift+Enter': 'Para abrir el elemento emergente, pulse May\u00fas+Intro', + 'Rich Text Area. Press ALT-0 for help.': '\u00c1rea de texto enriquecido. Pulse ALT-0 para abrir la ayuda.', + 'System Font': 'Fuente de sistema', + 'Failed to upload image: {0}': 'Fallo al cargar imagen: {0}', + 'Failed to load plugin: {0} from url {1}': 'Fallo al cargar complemento: {0} desde URL {1}', + 'Failed to load plugin url: {0}': 'Fallo al cargar URL del complemento: {0}', + 'Failed to initialize plugin: {0}': 'Fallo al iniciar el complemento: {0}', + example: 'ejemplo', + Search: 'Buscar', + All: 'Todo', + Currency: 'Divisa', + Text: 'Texto', + Quotations: 'Comillas', + Mathematical: 'S\u00edmbolo matem\u00e1tico', + 'Extended Latin': 'Latino extendido A', + Symbols: 'S\u00edmbolos', + Arrows: 'Flechas', + 'User Defined': 'Definido por el usuario', + 'dollar sign': 'signo de d\u00f3lar', + 'currency sign': 'signo de divisa', + 'euro-currency sign': 'signo de euro', + 'colon sign': 'signo de dos puntos', + 'cruzeiro sign': 'signo de cruceiro', + 'french franc sign': 'signo de franco franc\u00e9s', + 'lira sign': 'signo de lira', + 'mill sign': 'signo de mill', + 'naira sign': 'signo de naira', + 'peseta sign': 'signo de peseta', + 'rupee sign': 'signo de rupia', + 'won sign': 'signo de won', + 'new sheqel sign': 'signo de nuevo s\u00e9quel', + 'dong sign': 'signo de dong', + 'kip sign': 'signo de kip', + 'tugrik sign': 'signo de tugrik', + 'drachma sign': 'signo de dracma', + 'german penny symbol': 'signo de penique alem\u00e1n', + 'peso sign': 'signo de peso', + 'guarani sign': 'signo de guaran\u00ed', + 'austral sign': 'signo de austral', + 'hryvnia sign': 'signo de grivna', + 'cedi sign': 'signo de cedi', + 'livre tournois sign': 'signo de libra tornesa', + 'spesmilo sign': 'signo de spesmilo', + 'tenge sign': 'signo de tenge', + 'indian rupee sign': 'signo de rupia india', + 'turkish lira sign': 'signo de lira turca', + 'nordic mark sign': 'signo de marco n\u00f3rdico', + 'manat sign': 'signo de manat', + 'ruble sign': 'signo de rublo', + 'yen character': 'car\u00e1cter de yen', + 'yuan character': 'car\u00e1cter de yuan', + 'yuan character, in hong kong and taiwan': 'car\u00e1cter de yuan en Hong Kong y Taiw\u00e1n', + 'yen\/yuan character variant one': 'Variante uno de car\u00e1cter de yen\/yuan', + 'Loading emoticons...': 'Cargando emoticonos...', + 'Could not load emoticons': 'No se han podido cargar los emoticonos', + People: 'Personas', + 'Animals and Nature': 'Animales y naturaleza', + 'Food and Drink': 'Comida y bebida', + Activity: 'Actividad', + 'Travel and Places': 'Viajes y lugares', + Objects: 'Objetos', + Flags: 'Banderas', + Characters: 'Caracteres', + 'Characters (no spaces)': 'Caracteres (sin espacios)', + '{0} characters': '{0} caracteres', + 'Error: Form submit field collision.': 'Error: Colisi\u00f3n de campo al enviar formulario.', + 'Error: No form element found.': 'Error: No se encuentra ning\u00fan elemento de formulario.', + Update: 'Actualizar', + 'Color swatch': 'Muestrario de colores', + Turquoise: 'Turquesa', + Green: 'Verde', + Blue: 'Azul', + Purple: 'P\u00farpura', + 'Navy Blue': 'Azul marino', + 'Dark Turquoise': 'Turquesa oscuro', + 'Dark Green': 'Verde oscuro', + 'Medium Blue': 'Azul medio', + 'Medium Purple': 'P\u00farpura medio', + 'Midnight Blue': 'Azul medio', + Yellow: 'Amarillo', + Orange: 'Naranja', + Red: 'Rojo', + 'Light Gray': 'Gris claro', + Gray: 'Gris', + 'Dark Yellow': 'Amarillo oscuro', + 'Dark Orange': 'Naranja oscuro', + 'Dark Red': 'Rojo oscuro', + 'Medium Gray': 'Gris medio', + 'Dark Gray': 'Gris oscuro', + 'Light Green': 'Verde claro', + 'Light Yellow': 'Amarillo claro', + 'Light Red': 'Rojo claro', + 'Light Purple': 'Morado claro', + 'Light Blue': 'Azul claro', + 'Dark Purple': 'Morado oscuro', + 'Dark Blue': 'Azul oscuro', + Black: 'Negro', + White: 'Blanco', + 'Switch to or from fullscreen mode': 'Activar o desactivar modo pantalla completa', + 'Open help dialog': 'Abrir di\u00e1logo de ayuda', + history: 'historial', + styles: 'estilos', + formatting: 'formato', + alignment: 'alineaci\u00f3n', + indentation: 'sangr\u00eda', + 'permanent pen': 'bol\u00edgrafo permanente', + comments: 'comentarios', + 'Format Painter': 'Copiar formato', + 'Insert\/edit iframe': 'Insertar\/editar iframe', + Capitalization: 'Uso de may\u00fasculas', + lowercase: 'min\u00fasculas', + UPPERCASE: 'MAY\u00daSCULAS', + 'Title Case': 'Tipo T\u00edtulo', + 'Permanent Pen Properties': 'Propiedades del bol\u00edgrafo permanente', + 'Permanent pen properties...': 'Propiedades del bol\u00edgrafo permanente...', + Font: 'Fuente', + Size: 'Tama\u00f1o', + 'More...': 'M\u00e1s...', + 'Spellcheck Language': 'Corrector', + 'Select...': 'Seleccionar...', + Preferences: 'Preferencias', + Yes: 'S\u00ed', + No: 'No', + 'Keyboard Navigation': 'Navegaci\u00f3n con el teclado', + Version: 'Versi\u00f3n', + Anchor: 'Ancla', + 'Special character': 'Car\u00e1cter especial', + 'Code sample': 'Ejemplo de c\u00f3digo', + Color: 'Color', + Emoticons: 'Emoticonos', + 'Document properties': 'Propiedades del documento', + Image: 'Imagen', + 'Insert link': 'Insertar enlace', + Target: 'Destino', + Link: 'Enlace', + Poster: 'Miniatura', + Media: 'Media', + Print: 'Imprimir', + Prev: 'Anterior', + 'Find and replace': 'Buscar y reemplazar', + 'Whole words': 'Palabras completas', + Spellcheck: 'Corrector ortogr\u00e1fico', + Caption: 'Subt\u00edtulo', + 'Insert template': 'Insertar plantilla' +}) diff --git a/public/resource/tinymce/langs/zh_CN.js b/public/resource/tinymce/langs/zh_CN.js new file mode 100644 index 0000000..f9d8b5c --- /dev/null +++ b/public/resource/tinymce/langs/zh_CN.js @@ -0,0 +1,389 @@ +tinymce.addI18n('zh_CN',{ +"Redo": "\u91cd\u505a", +"Undo": "\u64a4\u9500", +"Cut": "\u526a\u5207", +"Copy": "\u590d\u5236", +"Paste": "\u7c98\u8d34", +"Select all": "\u5168\u9009", +"New document": "\u65b0\u6587\u4ef6", +"Ok": "\u786e\u5b9a", +"Cancel": "\u53d6\u6d88", +"Visual aids": "\u7f51\u683c\u7ebf", +"Bold": "\u7c97\u4f53", +"Italic": "\u659c\u4f53", +"Underline": "\u4e0b\u5212\u7ebf", +"Strikethrough": "\u5220\u9664\u7ebf", +"Superscript": "\u4e0a\u6807", +"Subscript": "\u4e0b\u6807", +"Clear formatting": "\u6e05\u9664\u683c\u5f0f", +"Align left": "\u5de6\u8fb9\u5bf9\u9f50", +"Align center": "\u4e2d\u95f4\u5bf9\u9f50", +"Align right": "\u53f3\u8fb9\u5bf9\u9f50", +"Justify": "\u4e24\u7aef\u5bf9\u9f50", +"Bullet list": "\u9879\u76ee\u7b26\u53f7", +"Numbered list": "\u7f16\u53f7\u5217\u8868", +"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb", +"Increase indent": "\u589e\u52a0\u7f29\u8fdb", +"Close": "\u5173\u95ed", +"Formats": "\u683c\u5f0f", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u7b49\u5feb\u6377\u952e\u3002", +"Headers": "\u6807\u9898", +"Header 1": "\u6807\u98981", +"Header 2": "\u6807\u98982", +"Header 3": "\u6807\u98983", +"Header 4": "\u6807\u98984", +"Header 5": "\u6807\u98985", +"Header 6": "\u6807\u98986", +"Headings": "\u6807\u9898", +"Heading 1": "\u6807\u98981", +"Heading 2": "\u6807\u98982", +"Heading 3": "\u6807\u98983", +"Heading 4": "\u6807\u98984", +"Heading 5": "\u6807\u98985", +"Heading 6": "\u6807\u98986", +"Preformatted": "\u9884\u5148\u683c\u5f0f\u5316\u7684", +"Div": "Div", +"Pre": "Pre", +"Code": "\u4ee3\u7801", +"Paragraph": "\u6bb5\u843d", +"Blockquote": "\u5f15\u6587\u533a\u5757", +"Inline": "\u6587\u672c", +"Blocks": "\u57fa\u5757", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002", +"Fonts": "\u5b57\u4f53", +"Font Sizes": "\u5b57\u53f7", +"Class": "\u7c7b\u578b", +"Browse for an image": "\u6d4f\u89c8\u56fe\u50cf", +"OR": "\u6216", +"Drop an image here": "\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64", +"Upload": "\u4e0a\u4f20", +"Block": "\u5757", +"Align": "\u5bf9\u9f50", +"Default": "\u9ed8\u8ba4", +"Circle": "\u7a7a\u5fc3\u5706", +"Disc": "\u5b9e\u5fc3\u5706", +"Square": "\u65b9\u5757", +"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd", +"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd", +"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd", +"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd", +"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd", +"Anchor...": "\u951a\u70b9...", +"Name": "\u540d\u79f0", +"Id": "\u6807\u8bc6\u7b26", +"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002", +"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f", +"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f", +"Special characters...": "\u7279\u6b8a\u5b57\u7b26...", +"Source code": "\u6e90\u4ee3\u7801", +"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b", +"Language": "\u8bed\u8a00", +"Code sample...": "\u793a\u4f8b\u4ee3\u7801...", +"Color Picker": "\u9009\u8272\u5668", +"R": "R", +"G": "G", +"B": "B", +"Left to right": "\u4ece\u5de6\u5230\u53f3", +"Right to left": "\u4ece\u53f3\u5230\u5de6", +"Emoticons...": "\u8868\u60c5\u7b26\u53f7...", +"Metadata and Document Properties": "\u5143\u6570\u636e\u548c\u6587\u6863\u5c5e\u6027", +"Title": "\u6807\u9898", +"Keywords": "\u5173\u952e\u8bcd", +"Description": "\u63cf\u8ff0", +"Robots": "\u673a\u5668\u4eba", +"Author": "\u4f5c\u8005", +"Encoding": "\u7f16\u7801", +"Fullscreen": "\u5168\u5c4f", +"Action": "\u64cd\u4f5c", +"Shortcut": "\u5feb\u6377\u952e", +"Help": "\u5e2e\u52a9", +"Address": "\u5730\u5740", +"Focus to menubar": "\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f", +"Focus to toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f", +"Focus to element path": "\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84", +"Focus to contextual toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355", +"Insert link (if link plugin activated)": "\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Save (if save plugin activated)": "\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Find (if searchreplace plugin activated)": "\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Plugins installed ({0}):": "\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):", +"Premium plugins:": "\u4f18\u79c0\u63d2\u4ef6\uff1a", +"Learn more...": "\u4e86\u89e3\u66f4\u591a...", +"You are using {0}": "\u4f60\u6b63\u5728\u4f7f\u7528 {0}", +"Plugins": "\u63d2\u4ef6", +"Handy Shortcuts": "\u5feb\u6377\u952e", +"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf", +"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247", +"Image description": "\u56fe\u7247\u63cf\u8ff0", +"Source": "\u5730\u5740", +"Dimensions": "\u5927\u5c0f", +"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4", +"General": "\u666e\u901a", +"Advanced": "\u9ad8\u7ea7", +"Style": "\u6837\u5f0f", +"Vertical space": "\u5782\u76f4\u8fb9\u8ddd", +"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd", +"Border": "\u8fb9\u6846", +"Insert image": "\u63d2\u5165\u56fe\u7247", +"Image...": "\u56fe\u7247...", +"Image list": "\u56fe\u7247\u5217\u8868", +"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c", +"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c", +"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c", +"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c", +"Edit image": "\u7f16\u8f91\u56fe\u7247", +"Image options": "\u56fe\u7247\u9009\u9879", +"Zoom in": "\u653e\u5927", +"Zoom out": "\u7f29\u5c0f", +"Crop": "\u88c1\u526a", +"Resize": "\u8c03\u6574\u5927\u5c0f", +"Orientation": "\u65b9\u5411", +"Brightness": "\u4eae\u5ea6", +"Sharpen": "\u9510\u5316", +"Contrast": "\u5bf9\u6bd4\u5ea6", +"Color levels": "\u989c\u8272\u5c42\u6b21", +"Gamma": "\u4f3d\u9a6c\u503c", +"Invert": "\u53cd\u8f6c", +"Apply": "\u5e94\u7528", +"Back": "\u540e\u9000", +"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4", +"Date\/time": "\u65e5\u671f\/\u65f6\u95f4", +"Insert\/Edit Link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5", +"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5", +"Text to display": "\u663e\u793a\u6587\u5b57", +"Url": "\u5730\u5740", +"Open link in...": "\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...", +"Current window": "\u5f53\u524d\u7a97\u53e3", +"None": "\u65e0", +"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00", +"Remove link": "\u5220\u9664\u94fe\u63a5", +"Anchors": "\u951a\u70b9", +"Link...": "\u94fe\u63a5...", +"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f", +"Link list": "\u94fe\u63a5\u5217\u8868", +"Insert video": "\u63d2\u5165\u89c6\u9891", +"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891", +"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53", +"Alternative source": "\u955c\u50cf", +"Alternative source URL": "\u66ff\u4ee3\u6765\u6e90\u7f51\u5740", +"Media poster (Image URL)": "\u5c01\u9762(\u56fe\u7247\u5730\u5740)", +"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:", +"Embed": "\u5185\u5d4c", +"Media...": "\u591a\u5a92\u4f53...", +"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c", +"Page break": "\u5206\u9875\u7b26", +"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c", +"Preview": "\u9884\u89c8", +"Print...": "\u6253\u5370...", +"Save": "\u4fdd\u5b58", +"Find": "\u67e5\u627e", +"Replace with": "\u66ff\u6362\u4e3a", +"Replace": "\u66ff\u6362", +"Replace all": "\u5168\u90e8\u66ff\u6362", +"Previous": "\u4e0a\u4e00\u4e2a", +"Next": "\u4e0b\u4e00\u4e2a", +"Find and replace...": "\u67e5\u627e\u5e76\u66ff\u6362...", +"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.", +"Match case": "\u533a\u5206\u5927\u5c0f\u5199", +"Find whole words only": "\u5168\u5b57\u5339\u914d", +"Spell check": "\u62fc\u5199\u68c0\u67e5", +"Ignore": "\u5ffd\u7565", +"Ignore all": "\u5168\u90e8\u5ffd\u7565", +"Finish": "\u5b8c\u6210", +"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178", +"Insert table": "\u63d2\u5165\u8868\u683c", +"Table properties": "\u8868\u683c\u5c5e\u6027", +"Delete table": "\u5220\u9664\u8868\u683c", +"Cell": "\u5355\u5143\u683c", +"Row": "\u884c", +"Column": "\u5217", +"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027", +"Merge cells": "\u5408\u5e76\u5355\u5143\u683c", +"Split cell": "\u62c6\u5206\u5355\u5143\u683c", +"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165", +"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165", +"Delete row": "\u5220\u9664\u884c", +"Row properties": "\u884c\u5c5e\u6027", +"Cut row": "\u526a\u5207\u884c", +"Copy row": "\u590d\u5236\u884c", +"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9", +"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9", +"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165", +"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165", +"Delete column": "\u5220\u9664\u5217", +"Cols": "\u5217", +"Rows": "\u884c", +"Width": "\u5bbd", +"Height": "\u9ad8", +"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd", +"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd", +"Show caption": "\u663e\u793a\u6807\u9898", +"Left": "\u5de6\u5bf9\u9f50", +"Center": "\u5c45\u4e2d", +"Right": "\u53f3\u5bf9\u9f50", +"Cell type": "\u5355\u5143\u683c\u7c7b\u578b", +"Scope": "\u8303\u56f4", +"Alignment": "\u5bf9\u9f50\u65b9\u5f0f", +"H Align": "\u6c34\u5e73\u5bf9\u9f50", +"V Align": "\u5782\u76f4\u5bf9\u9f50", +"Top": "\u9876\u90e8\u5bf9\u9f50", +"Middle": "\u5782\u76f4\u5c45\u4e2d", +"Bottom": "\u5e95\u90e8\u5bf9\u9f50", +"Header cell": "\u8868\u5934\u5355\u5143\u683c", +"Row group": "\u884c\u7ec4", +"Column group": "\u5217\u7ec4", +"Row type": "\u884c\u7c7b\u578b", +"Header": "\u8868\u5934", +"Body": "\u8868\u4f53", +"Footer": "\u8868\u5c3e", +"Border color": "\u8fb9\u6846\u989c\u8272", +"Insert template...": "\u63d2\u5165\u6a21\u677f...", +"Templates": "\u6a21\u677f", +"Template": "\u6a21\u677f", +"Text color": "\u6587\u5b57\u989c\u8272", +"Background color": "\u80cc\u666f\u8272", +"Custom...": "\u81ea\u5b9a\u4e49...", +"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272", +"No color": "\u65e0", +"Remove color": "\u79fb\u9664\u989c\u8272", +"Table of Contents": "\u5185\u5bb9\u5217\u8868", +"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846", +"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26", +"Word count": "\u5b57\u6570", +"Words: {0}": "\u5b57\u6570\uff1a{0}", +"{0} words": "{0} \u5b57", +"File": "\u6587\u4ef6", +"Edit": "\u7f16\u8f91", +"Insert": "\u63d2\u5165", +"View": "\u89c6\u56fe", +"Format": "\u683c\u5f0f", +"Table": "\u8868\u683c", +"Tools": "\u5de5\u5177", +"Powered by {0}": "\u7531{0}\u9a71\u52a8", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9", +"Image title": "\u56fe\u7247\u6807\u9898", +"Border width": "\u8fb9\u6846\u5bbd\u5ea6", +"Border style": "\u8fb9\u6846\u6837\u5f0f", +"Error": "\u9519\u8bef", +"Warn": "\u8b66\u544a", +"Valid": "\u6709\u6548", +"To open the popup, press Shift+Enter": "\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846", +"Rich Text Area. Press ALT-0 for help.": "\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002", +"System Font": "\u7cfb\u7edf\u5b57\u4f53", +"Failed to upload image: {0}": "\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}", +"Failed to load plugin: {0} from url {1}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}", +"Failed to load plugin url: {0}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}", +"Failed to initialize plugin: {0}": "\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}", +"example": "\u793a\u4f8b", +"Search": "\u641c\u7d22", +"All": "\u5168\u90e8", +"Currency": "\u8d27\u5e01", +"Text": "\u6587\u5b57", +"Quotations": "\u5f15\u7528", +"Mathematical": "\u6570\u5b66", +"Extended Latin": "\u62c9\u4e01\u8bed\u6269\u5145", +"Symbols": "\u7b26\u53f7", +"Arrows": "\u7bad\u5934", +"User Defined": "\u81ea\u5b9a\u4e49", +"dollar sign": "\u7f8e\u5143\u7b26\u53f7", +"currency sign": "\u8d27\u5e01\u7b26\u53f7", +"euro-currency sign": "\u6b27\u5143\u7b26\u53f7", +"colon sign": "\u5192\u53f7", +"cruzeiro sign": "\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7", +"french franc sign": "\u6cd5\u90ce\u7b26\u53f7", +"lira sign": "\u91cc\u62c9\u7b26\u53f7", +"mill sign": "\u5bc6\u5c14\u7b26\u53f7", +"naira sign": "\u5948\u62c9\u7b26\u53f7", +"peseta sign": "\u6bd4\u585e\u5854\u7b26\u53f7", +"rupee sign": "\u5362\u6bd4\u7b26\u53f7", +"won sign": "\u97e9\u5143\u7b26\u53f7", +"new sheqel sign": "\u65b0\u8c22\u514b\u5c14\u7b26\u53f7", +"dong sign": "\u8d8a\u5357\u76fe\u7b26\u53f7", +"kip sign": "\u8001\u631d\u57fa\u666e\u7b26\u53f7", +"tugrik sign": "\u56fe\u683c\u91cc\u514b\u7b26\u53f7", +"drachma sign": "\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7", +"german penny symbol": "\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7", +"peso sign": "\u6bd4\u7d22\u7b26\u53f7", +"guarani sign": "\u74dc\u62c9\u5c3c\u7b26\u53f7", +"austral sign": "\u6fb3\u5143\u7b26\u53f7", +"hryvnia sign": "\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7", +"cedi sign": "\u585e\u5730\u7b26\u53f7", +"livre tournois sign": "\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7", +"spesmilo sign": "spesmilo\u7b26\u53f7", +"tenge sign": "\u575a\u6208\u7b26\u53f7", +"indian rupee sign": "\u5370\u5ea6\u5362\u6bd4", +"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9", +"nordic mark sign": "\u5317\u6b27\u9a6c\u514b", +"manat sign": "\u9a6c\u7eb3\u7279\u7b26\u53f7", +"ruble sign": "\u5362\u5e03\u7b26\u53f7", +"yen character": "\u65e5\u5143\u5b57\u6837", +"yuan character": "\u4eba\u6c11\u5e01\u5143\u5b57\u6837", +"yuan character, in hong kong and taiwan": "\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09", +"yen\/yuan character variant one": "\u5143\u5b57\u6837\uff08\u5927\u5199\uff09", +"Loading emoticons...": "\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7...", +"Could not load emoticons": "\u4e0d\u80fd\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7", +"People": "\u4eba\u7c7b", +"Animals and Nature": "\u52a8\u7269\u548c\u81ea\u7136", +"Food and Drink": "\u98df\u7269\u548c\u996e\u54c1", +"Activity": "\u6d3b\u52a8", +"Travel and Places": "\u65c5\u6e38\u548c\u5730\u70b9", +"Objects": "\u7269\u4ef6", +"Flags": "\u65d7\u5e1c", +"Characters": "\u5b57\u7b26", +"Characters (no spaces)": "\u5b57\u7b26(\u65e0\u7a7a\u683c)", +"Error: Form submit field collision.": "\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002", +"Error: No form element found.": "\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002", +"Update": "\u66f4\u65b0", +"Color swatch": "\u989c\u8272\u6837\u672c", +"Turquoise": "\u9752\u7eff\u8272", +"Green": "\u7eff\u8272", +"Blue": "\u84dd\u8272", +"Purple": "\u7d2b\u8272", +"Navy Blue": "\u6d77\u519b\u84dd", +"Dark Turquoise": "\u6df1\u84dd\u7eff\u8272", +"Dark Green": "\u6df1\u7eff\u8272", +"Medium Blue": "\u4e2d\u84dd\u8272", +"Medium Purple": "\u4e2d\u7d2b\u8272", +"Midnight Blue": "\u6df1\u84dd\u8272", +"Yellow": "\u9ec4\u8272", +"Orange": "\u6a59\u8272", +"Red": "\u7ea2\u8272", +"Light Gray": "\u6d45\u7070\u8272", +"Gray": "\u7070\u8272", +"Dark Yellow": "\u6697\u9ec4\u8272", +"Dark Orange": "\u6df1\u6a59\u8272", +"Dark Red": "\u6df1\u7ea2\u8272", +"Medium Gray": "\u4e2d\u7070\u8272", +"Dark Gray": "\u6df1\u7070\u8272", +"Black": "\u9ed1\u8272", +"White": "\u767d\u8272", +"Switch to or from fullscreen mode": "\u5207\u6362\u5168\u5c4f\u6a21\u5f0f", +"Open help dialog": "\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846", +"history": "\u5386\u53f2", +"styles": "\u6837\u5f0f", +"formatting": "\u683c\u5f0f\u5316", +"alignment": "\u5bf9\u9f50", +"indentation": "\u7f29\u8fdb", +"permanent pen": "\u8bb0\u53f7\u7b14", +"comments": "\u5907\u6ce8", +"Anchor": "\u951a\u70b9", +"Special character": "\u7279\u6b8a\u7b26\u53f7", +"Code sample": "\u4ee3\u7801\u793a\u4f8b", +"Color": "\u989c\u8272", +"Emoticons": "\u8868\u60c5", +"Document properties": "\u6587\u6863\u5c5e\u6027", +"Image": "\u56fe\u7247", +"Insert link": "\u63d2\u5165\u94fe\u63a5", +"Target": "\u6253\u5f00\u65b9\u5f0f", +"Link": "\u94fe\u63a5", +"Poster": "\u5c01\u9762", +"Media": "\u5a92\u4f53", +"Print": "\u6253\u5370", +"Prev": "\u4e0a\u4e00\u4e2a", +"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362", +"Whole words": "\u5168\u5b57\u5339\u914d", +"Spellcheck": "\u62fc\u5199\u68c0\u67e5", +"Caption": "\u6807\u9898", +"Insert template": "\u63d2\u5165\u6a21\u677f" +}); \ No newline at end of file diff --git a/public/resource/tinymce/license.txt b/public/resource/tinymce/license.txt new file mode 100644 index 0000000..3a49f66 --- /dev/null +++ b/public/resource/tinymce/license.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Ephox Corporation DBA Tiny Technologies, Inc. + +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/public/resource/tinymce/models/dom/model.min.js b/public/resource/tinymce/models/dom/model.min.js new file mode 100644 index 0000000..323b2c5 --- /dev/null +++ b/public/resource/tinymce/models/dom/model.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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 w(e,...t){return(...o)=>{const n=t.concat(o);return e.apply(null,n)}}const b=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),L=(e,t,o)=>(N(e,((e,n)=>{o=t(o,e,n)})),o),W=(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;o_(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),q=e=>F(e,e.length-1),V=(e,t)=>{for(let o=0;o{const o=$(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},we=(e,t)=>C.from(pe(e,t)),be=(e,t)=>{e.dom.removeAttribute(t)},ve=e=>L(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),Be=e=>C.from(e.dom.parentElement).map(xe.fromDom),ze=(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},Ae=e=>C.from(e.dom.previousSibling).map(xe.fromDom),Le=e=>C.from(e.dom.nextSibling).map(xe.fromDom),We=e=>E(e.dom.childNodes,xe.fromDom),Me=(e,t)=>{const o=e.dom.childNodes;return C.from(o[t]).map(xe.fromDom)},_e=(e,t)=>{Ne(e).each((o=>{o.dom.insertBefore(t.dom,e.dom)}))},je=(e,t)=>{Le(e).fold((()=>{Ne(e).each((e=>{Ie(e,t)}))}),(e=>{_e(e,t)}))},Pe=(e,t)=>{const o=(e=>Me(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)=>{_e(e,t),Ie(t,e)},He=(e,t)=>{N(t,((o,n)=>{const r=0===n?e:t[n-1];je(r,o)}))},qe=(e,t)=>{N(t,(t=>{Ie(e,t)}))},Ve=e=>{e.dom.textContent="",N(We(e),(e=>{$e(e)}))},$e=e=>{const t=e.dom;null!==t.parentNode&&t.parentNode.removeChild(t)},Ue=e=>{const t=We(e);t.length>0&&He(e,t),$e(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=d(Element.prototype.attachShadow)&&d(Node.prototype.getRootNode),nt=g(ot),rt=ot?e=>xe.fromDom(e.dom.getRootNode()):Ee,st=e=>xe.fromDom(e.dom.host),lt=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=rt(e);return de(o=t)&&m(o.dom.host)?C.some(t):C.none();var o})(xe.fromDom(t)).fold((()=>o.body.contains(t)),(n=lt,r=st,e=>n(r(e))));var n,r},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(We(e),(e=>{t(e)&&(o=o.concat([e])),o=o.concat(ct(e,t))})),o},it=(e,t,o)=>((e,o,n)=>z(ze(e,n),(e=>Ce(e,t))))(e,0,o),mt=(e,t)=>((e,o)=>z(We(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,o)=>W(e.dom.childNodes,(e=>{return o=xe.fromDom(e),Ce(o,t);var o})).map(xe.fromDom))(e),wt=(e,t)=>Te(t,e),bt=(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)},Bt=(e,t)=>{const o=e.dom;G(t,((e,t)=>{Et(o,t,e)}))},zt=(e,t)=>{const o=e.dom,n=window.getComputedStyle(o).getPropertyValue(t);return""!==n||lt(e)?n:At(o,t)},At=(e,t)=>kt(e)?e.style.getPropertyValue(t):"",Lt=(e,t)=>{const o=e.dom,n=At(o,t);return C.from(n).filter((e=>e.length>0))},Wt=(e,t)=>{((e,t)=>{kt(e)&&e.style.removeProperty(t)})(e.dom,t),vt(we(e,"style").map(Dt),"")&&be(e,"style")},Mt=(e,t,o=0)=>we(e,t).map((e=>parseInt(e,10))).getOr(o),_t=(e,t)=>Mt(e,t,1),jt=e=>ue("col")(e)?Mt(e,"span",1)>1:_t(e,"colspan")>1,Pt=e=>_t(e,"rowspan")>1,It=(e,t)=>parseInt(zt(e,t),10),Ft=g(10),Ht=g(10),qt=(e,t)=>Vt(e,t,x),Vt=(e,t,o)=>j(We(e),(e=>Ce(e,t)?o(e)?[e]:[]:Vt(e,t,o))),$t=(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),Ut=e=>qt(e,"th,td"),Gt=e=>Ce(e,"colgroup")?mt(e,"col"):j(Jt(e),(e=>mt(e,"col"))),Kt=(e,t)=>bt(e,"table",t),Yt=e=>qt(e,"tr"),Jt=e=>Kt(e).fold(g([]),(e=>mt(e,"colgroup"))),Qt=(e,t)=>E(e,(e=>{if("colgroup"===ne(e)){const t=E(Gt(e),(e=>{const t=Mt(e,"span",1);return Xe(e,1,t)}));return Ze(e,t,"colgroup")}{const o=E(Ut(e),(e=>{const t=Mt(e,"rowspan",1),o=Mt(e,"colspan",1);return Xe(e,t,o)}));return Ze(e,o,t(e))}})),Xt=e=>Ne(e).map((e=>{const t=ne(e);return(e=>D(Qe,e))(t)?t:"tbody"})).getOr("tbody"),Zt=e=>{const t=Yt(e),o=[...Jt(e),...t];return Qt(o,Xt)},eo=e=>{let t,o=!1;return(...n)=>(o||(o=!0,t=e.apply(null,n)),t)},to=()=>oo(0,0),oo=(e,t)=>({major:e,minor:t}),no={nu:oo,detect:(e,t)=>{const o=String(t).toLowerCase();return 0===e.length?to():((e,t)=>{const o=((e,t)=>{for(let o=0;oNumber(t.replace(o,"$"+e));return oo(n(1),n(2))})(e,o)},unknown:to},ro=(e,t)=>{const o=String(t).toLowerCase();return W(e,(e=>e.search(o)))},so=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,lo=e=>t=>St(t,e),ao=[{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]+).*/,so],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:[so,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:lo("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:lo("firefox")},{name:"Safari",versionRegexes:[so,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:e=>(St(e,"safari")||St(e,"mobile/"))&&St(e,"applewebkit")}],co=[{name:"Windows",search:lo("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:lo("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"macOS",search:lo("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:lo("linux"),versionRegexes:[]},{name:"Solaris",search:lo("sunos"),versionRegexes:[]},{name:"FreeBSD",search:lo("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:lo("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}],io={browsers:g(ao),oses:g(co)},mo="Edge",uo="Chromium",fo="Opera",go="Firefox",ho="Safari",po=e=>{const t=e.current,o=e.version,n=e=>()=>t===e;return{current:t,version:o,isEdge:n(mo),isChromium:n(uo),isIE:n("IE"),isOpera:n(fo),isFirefox:n(go),isSafari:n(ho)}},wo=()=>po({current:void 0,version:no.unknown()}),bo=po,vo=(g(mo),g(uo),g("IE"),g(fo),g(go),g(ho),"Windows"),yo="Android",xo="Linux",Co="macOS",So="Solaris",To="FreeBSD",Ro="ChromeOS",Do=e=>{const t=e.current,o=e.version,n=e=>()=>t===e;return{current:t,version:o,isWindows:n(vo),isiOS:n("iOS"),isAndroid:n(yo),isMacOS:n(Co),isLinux:n(xo),isSolaris:n(So),isFreeBSD:n(To),isChromeOS:n(Ro)}},Oo=()=>Do({current:void 0,version:no.unknown()}),ko=Do,Eo=(g(vo),g("iOS"),g(yo),g(xo),g(Co),g(So),g(To),g(Ro),e=>window.matchMedia(e).matches);let No=eo((()=>((e,t,o)=>{const n=io.browsers(),r=io.oses(),s=t.bind((e=>((e,t)=>V(t.brands,(t=>{const o=t.brand.toLowerCase();return W(e,(e=>{var t;return o===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())})).map((e=>({current:e.name,version:no.nu(parseInt(t.version,10),0)})))})))(n,e))).orThunk((()=>((e,t)=>ro(e,t).map((e=>{const o=no.detect(e.versionRegexes,t);return{current:e.name,version:o}})))(n,e))).fold(wo,bo),l=((e,t)=>ro(e,t).map((e=>{const o=no.detect(e.versionRegexes,t);return{current:e.name,version:o}})))(r,e).fold(Oo,ko),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}})(navigator.userAgent,C.from(navigator.userAgentData),Eo)));const Bo=()=>No(),zo=(e,t)=>{const o=o=>{const n=t(o);if(n<=0||null===n){const t=zt(o,e);return parseFloat(t)||0}return n},n=(e,t)=>L(t,((t,o)=>{const n=zt(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}}},Ao=(e,t,o)=>((e,t)=>(e=>{const t=parseFloat(e);return isNaN(t)?C.none():C.some(t)})(e).getOr(t))(zt(e,t),o),Lo=zo("width",(e=>e.dom.offsetWidth)),Wo=e=>Lo.get(e),Mo=e=>Lo.getOuter(e),_o=e=>((e,t)=>{const o=e.dom,n=o.getBoundingClientRect().width||o.offsetWidth;return"border-box"===t?n:((e,t,o,n)=>t-Ao(e,"padding-left",0)-Ao(e,"padding-right",0)-Ao(e,"border-left-width",0)-Ao(e,"border-right-width",0))(e,n)})(e,"content-box"),jo=(e,t,o)=>{const n=e.cells,r=n.slice(0,t),s=n.slice(t),l=r.concat(o).concat(s);return Fo(e,l)},Po=(e,t,o)=>jo(e,t,[o]),Io=(e,t,o)=>{e.cells[t]=o},Fo=(e,t)=>tt(e.element,t,e.section,e.isNew),Ho=(e,t)=>e.cells[t],qo=(e,t)=>Ho(e,t).element,Vo=e=>e.cells.length,$o=e=>{const t=B(e,(e=>"colgroup"===e.section));return{rows:t.fail,cols:t.pass}},Uo=(e,t,o)=>{const n=E(e.cells,o);return tt(t(e.element),n,e.section,!0)},Go="data-snooker-locked-cols",Ko=e=>we(e,Go).bind((e=>C.from(e.match(/\d+/g)))).map((e=>I(e,x))),Yo=e=>{const t=L($o(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,t)=>{const o=S.call(e,0);return o.sort(void 0),o})(o)},Jo=(e,t)=>e+","+t,Qo=(e,t)=>{const o=j(e.all,(e=>e.cells));return z(o,t)},Xo=e=>{const t={},o=[],n=H(e).map((e=>e.element)).bind(Kt).bind(Ko).getOr({});let r=0,s=0,l=0;const{pass:a,fail:c}=B(e,(e=>"colgroup"===e.section));N(c,(e=>{const a=[];N(e.cells,(e=>{let o=0;for(;void 0!==t[Jo(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}},Zo=e=>{const t=Zt(e);return Xo(t)},en=Xo,tn=(e,t,o)=>C.from(e.access[Jo(t,o)]),on=(e,t,o)=>{const n=Qo(e,(e=>o(t,e.element)));return n.length>0?C.some(n[0]):C.none()},nn=Qo,rn=e=>j(e.all,(e=>e.cells)),sn=e=>Q(e.columns),ln=e=>$(e.columns).length>0,an=(e,t)=>C.from(e.columns[t]),cn=(e,t=x)=>{const o=e.grid,n=k(o.columns,h),r=k(o.rows,h);return E(n,(o=>mn((()=>j(r,(t=>tn(e,t,o).filter((e=>e.column===o)).toArray()))),(e=>1===e.colspan&&t(e.element)),(()=>tn(e,0,o)))))},mn=(e,t,o)=>{const n=e();return W(n,t).orThunk((()=>C.from(n[0]).orThunk(o))).map((e=>e.element))},dn=e=>{const t=e.grid,o=k(t.rows,h),n=k(t.columns,h);return E(o,(t=>mn((()=>j(n,(o=>tn(e,t,o).filter((e=>e.row===t)).fold(g([]),(e=>[e]))))),(e=>1===e.rowspan),(()=>tn(e,t,0)))))},un=(e,t)=>o=>"rtl"===fn(o)?t:e,fn=e=>"rtl"===zt(e,"direction")?"rtl":"ltr",gn=zo("height",(e=>{const t=e.dom;return lt(e)?t.getBoundingClientRect().height:t.offsetHeight})),hn=e=>gn.get(e),pn=e=>gn.getOuter(e),wn=(e,t)=>({left:e,top:t,translate:(o,n)=>wn(e+o,t+n)}),bn=wn,vn=(e,t)=>void 0!==e?e:void 0!==t?t:0,yn=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=vn(null==n?void 0:n.pageYOffset,r.scrollTop),l=vn(null==n?void 0:n.pageXOffset,r.scrollLeft),a=vn(r.clientTop,o.clientTop),c=vn(r.clientLeft,o.clientLeft);return xn(e).translate(l-c,s-a)},xn=e=>{const t=e.dom,o=t.ownerDocument.body;return o===t?bn(o.offsetLeft,o.offsetTop):lt(e)?(e=>{const t=e.getBoundingClientRect();return bn(t.left,t.top)})(t):bn(0,0)},Cn=(e,t)=>({row:e,y:t}),Sn=(e,t)=>({col:e,x:t}),Tn=e=>yn(e).left+Mo(e),Rn=e=>yn(e).left,Dn=(e,t)=>Sn(e,Rn(t)),On=(e,t)=>Sn(e,Tn(t)),kn=e=>yn(e).top,En=(e,t)=>Cn(e,kn(t)),Nn=(e,t)=>Cn(e,kn(t)+pn(t)),Bn=(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])},zn={delta:h,positions:e=>Bn(En,Nn,e),edge:kn},An=un({delta:h,edge:Rn,positions:e=>Bn(Dn,On,e)},{delta:e=>-e,edge:Tn,positions:e=>Bn(On,Dn,e)}),Ln={delta:(e,t)=>An(t).delta(e,t),positions:(e,t)=>An(t).positions(e,t),edge:e=>An(e).edge(e)},Wn={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:[""]},Mn=(()=>{const e="[0-9]+",t="[eE][+-]?[0-9]+",o=e=>`(?:${e})?`,n=["Infinity","[0-9]+\\."+o(e)+o(t),"\\.[0-9]+"+o(t),e+o(t)].join("|");return new RegExp(`^([+-]?(?:${n}))(.*)$`)})(),_n=/(\d+(\.\d+)?)%/,jn=/(\d+(\.\d+)?)px|em/,Pn=ue("col"),In=(e,t,o)=>{const n=Be(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+"%")},qn=(e,t)=>{Nt(e,"height",t+"px")},Vn=e=>{const t=(e=>{return Ao(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=Kt(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,hn,qn):hn(e)},$n=(e,t)=>Lt(e,t).orThunk((()=>we(e,t).map((e=>e+"px")))),Un=e=>$n(e,"width"),Gn=e=>In(e,Wo,_o),Kn=e=>{return Pn(e)?Wo(e):Ao(t=e,"width",t.dom.offsetWidth);var t},Yn=e=>((e,t,o)=>o(e)/_t(e,"rowspan"))(e,0,Vn),Jn=(e,t,o)=>{Nt(e,"width",t+o)},Qn=e=>In(e,Wo,_o)+"%",Xn=g(_n),Zn=ue("col"),er=e=>Un(e).getOrThunk((()=>Kn(e)+"px")),tr=e=>{return(t=e,$n(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=cn(e),s=ln(e)?(e=>E(sn(e),(e=>C.from(e.element))))(e):r,l=[C.some(Ln.edge(t))].concat(E(Ln.positions(r,t),(e=>e.map((e=>e.x))))),a=b(jt);return E(s,((e,t)=>or(e,t,l,a,(e=>{if((e=>{const t=Bo().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(Wo(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,r)=>{const s=dn(e),l=[C.some(o.edge(t))].concat(E(o.positions(s,t),(e=>e.map((e=>e.y)))));return E(s,((e,t)=>or(e,t,l,b(Pt),n,r)))},ar=(e,t)=>()=>lt(e)?t(e):parseFloat(Lt(e,"width").getOr("0")),cr=e=>{const t=ar(e,(e=>parseFloat(Qn(e)))),o=ar(e,Wo);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:()=>Ft()/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,Wo);return{width:t,pixelWidth:t,getWidths:(t,o)=>sr(t,e,o),getCellDelta:h,singleColumnWidth:(e,t)=>[Math.max(Ft(),e+t)-e],minCellWidth:Ft,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,Wo),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,t)=>{const o=t=>e(t)?C.from(t.dom.nodeValue):C.none();return{get:t=>{if(!e(t))throw new Error("Can only get text value of a text node");return o(t).getOr("")},getOption:o,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),wr=(e,t)=>gr.set(e,t),br=e=>"img"===ne(e)?1:pr(e).fold((()=>We(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=We(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=We(Ye(e));return qe(o,n),o})(e,t);return G(o,((e,t)=>{null===e?be(n,t):ge(n,t,e)})),n},Nr=e=>e,Br=(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),Wt(t,"height"),1!==e.colspan&&Wt(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 A(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)=>we(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)}},zr=e=>({col:Dr(e),colgroup:Or(e),row:kr(e),cell:Rr(e),replace:Nr,colGap:Dr(e),gap:Rr(e)}),Ar=e=>bt(e,"[contenteditable]"),Lr=(e,t=!1)=>lt(e)?e.dom.isContentEditable:Ar(e).fold(g(t),(e=>"true"===Wr(e))),Wr=e=>e.dom.contentEditable,Mr=e=>xe.fromDom(e.getBody()),_r=e=>t=>Re(t,Mr(e)),jr=e=>{be(e,"data-mce-style");const t=e=>be(e,"data-mce-style");N(Ut(e),t),N(Gt(e),t),N(Yt(e),t)},Pr=e=>xe.fromDom(e.selection.getStart()),Ir=e=>e.getBoundingClientRect().width,Fr=e=>e.getBoundingClientRect().height,Hr=e=>gt(e,ue("table")).exists(Lr),qr=(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},Vr=(e,t)=>t.column>=e.startCol&&t.column+t.colspan-1<=e.finishCol&&t.row>=e.startRow&&t.row+t.rowspan-1<=e.finishRow,$r=(e,t,o)=>{const n=on(e,t,Re),r=on(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}))))},Ur=(e,t,o)=>$r(e,t,o).map((t=>{const o=nn(e,w(qr,t));return E(o,(e=>e.element))})),Gr=(e,t)=>on(e,t,((e,t)=>De(t,e))).map((e=>e.element)),Kr=(e,t,o)=>{const n=Jr(e);return Ur(n,t,o)},Yr=(e,t,o,n,r)=>{const s=Jr(e),l=Re(e,o)?C.some(t):Gr(s,t),a=Re(e,r)?C.some(n):Gr(s,n);return l.bind((e=>a.bind((t=>Ur(s,e,t)))))},Jr=Zo;var Qr=["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"],Xr=()=>({up:g({selector:ht,closest:bt,predicate:ft,all:ze}),down:g({selector:dt,predicate:ct}),styles:g({get:zt,getRaw:Lt,set:Nt,remove:Wt}),attrs:g({get:pe,set:ge,remove:be,copyTo:(e,t)=>{const o=ve(e);he(t,o)}}),insert:g({before:_e,after:je,afterAll:He,append:Ie,appendAll:qe,prepend:Pe,wrap:Fe}),remove:g({unwrap:Ue,remove:$e}),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:Ae,nextSibling:Le}),property:g({children:We,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)?we(e,"lang"):C.none(),getText:hr,setText:wr,isBoundary:e=>!!ce(e)&&("body"===ne(e)||D(Qr,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 Zr=(e,t,o,n)=>{const r=t(e,o);return A(n,((o,n)=>{const r=t(e,n);return es(e,o,r)}),r)},es=(e,t,o)=>t.bind((t=>o.filter(w(e.eq,t)))),ts=Xr(),os=(e,t)=>((e,t,o)=>o.length>0?((e,t,o,n)=>n(e,t,o[0],o.slice(1)))(e,t,o,Zr):C.none())(ts,((t,o)=>e(o)),t),ns=e=>ht(e,"table"),rs=(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}):ns(e).bind((r=>ns(t).bind((s=>{if(Re(r,s))return C.some({boxes:Kr(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:Yr(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:Yr(s,e,r,t,s),start:e,finish:l})}return((e,t,o)=>((e,t,o,n=y)=>{const r=[t].concat(e.up().all(t)),s=[o].concat(e.up().all(o)),l=e=>M(e,n).fold((()=>e),(t=>e.slice(0,t+1))),a=l(r),c=l(s),i=W(a,(t=>O(c,((e,t)=>w(e.eq,t))(e,t))));return{firstpath:a,secondpath:c,shared:i}})(ts,e,t,void 0))(e,t).shared.bind((l=>bt(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:Yr(o,e,r,t,s),start:i,finish:a})}))))}))))},ss=(e,t)=>{const o=dt(e,t);return o.length>0?C.some(o):C.none()},ls=(e,t,o)=>wt(e,t).bind((t=>wt(e,o).bind((e=>os(ns,[t,e]).map((o=>({first:t,last:e,table:o}))))))),as=(e,t,o,n,r)=>((e,t)=>W(e,(e=>Ce(e,t))))(e,r).bind((e=>((e,t,o)=>Kt(e).bind((n=>((e,t,o,n)=>on(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 tn(e,r+o,s+n).map((e=>e.element))})))(Jr(n),e,t,o))))(e,t,o).bind((e=>((e,t)=>ht(e,"table").bind((o=>wt(o,t).bind((t=>rs(t,e).bind((e=>e.boxes.map((t=>({boxes:t,start:e.start,finish:e.finish}))))))))))(e,n))))),cs=(e,t)=>ss(e,t),is=(e,t,o)=>ls(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)=>$r(e,t,o).bind((t=>((e,t)=>{let o=!0;const n=w(Vr,t);for(let r=t.startRow;r<=t.finishRow;r++)for(let s=t.startCol;s<=t.finishCol;s++)o=o&&tn(e,r,s).exists(n);return o?C.some(t):C.none()})(e,t))))(Jr(e),t,o))(t.table,t.first,t.last):C.none()))))})),ms=h,ds=e=>{const t=(e,t)=>we(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()},us=(e,t,o)=>t.length<=1?C.none():is(e,o.firstSelectedSelector,o.lastSelectedSelector).map((e=>({bounds:e,cells:t}))),fs={selected:"data-mce-selected",selectedSelector:"td[data-mce-selected],th[data-mce-selected]",firstSelected:"data-mce-first-selected",firstSelectedSelector:"td[data-mce-first-selected],th[data-mce-first-selected]",lastSelected:"data-mce-last-selected",lastSelectedSelector:"td[data-mce-last-selected],th[data-mce-last-selected]"},gs=(e,t,o)=>({element:o,mergable:us(t,e,fs),unmergable:ds(e),selection:ms(e)}),hs=e=>(t,o)=>{const n=ne(t),r="col"===n||"colgroup"===n?Kt(s=t).bind((e=>cs(e,fs.firstSelectedSelector))).fold(g(s),(e=>e[0])):t;var s;return bt(r,e,o)},ps=hs("th,td,caption"),ws=hs("th,td"),bs=e=>{return t=e.model.table.getSelectedCells(),E(t,xe.fromDom);var t},vs=(e,t)=>{e.on("BeforeGetContent",(t=>{const o=o=>{t.preventDefault(),(e=>Kt(e[0]).map((e=>{const t=((e,t)=>{const o=e=>Ce(e.element,t),n=Ye(e),r=Zt(n),s=mr(e),l=en(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=Vt(n,"th,td",(e=>Ce(e,c)));N(i,$e),((e,t,o,n)=>{const r=z(e,(e=>"colgroup"!==e.section)),s=t.grid.columns,l=t.grid.rows;for(let e=0;eo.maxRow||ao.maxCol||(tn(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=L(r,((e,t)=>e+t),0),l=L(r.slice(n.minCol,n.maxCol+1),((e,t)=>e+t),0),a=l/s*o.pixelWidth()-o.pixelWidth();return o.getCellDelta(a)})(e,Zo(e),s,a);return((e,t,o,n)=>{G(o.columns,(e=>{(e.columnt.maxCol)&&$e(e.element)}));const r=z(qt(e,"tr"),(e=>0===e.dom.childElementCount));N(r,$e),t.minCol!==t.maxCol&&t.minRow!==t.maxRow||N(qt(e,"th,td"),(e=>{be(e,"rowspan"),be(e,"colspan")})),be(e,Go),be(e,"data-snooker-col-series"),mr(e).adjustTableWidth(n)})(n,a,l,m),n})(e,"[data-mce-selected]");return jr(t),[t]})))(o).each((o=>{t.content="text"===t.format?(e=>E(e,(e=>e.dom.innerText)).join(""))(o):((e,t)=>E(t,(t=>e.selection.serializer.serialize(t.dom,{}))).join(""))(e,o)}))};if(!0===t.selection){const t=(e=>z(bs(e),(e=>Ce(e,fs.selectedSelector))))(e);t.length>=1&&o(t)}})),e.on("BeforeSetContent",(o=>{if(!0===o.selection&&!0===o.paste){const n=bs(e);H(n).each((n=>{Kt(n).each((r=>{const s=z(((e,t)=>{const o=document.createElement("div");return o.innerHTML=e,We(xe.fromDom(o))})(o.content),(e=>"meta"!==ne(e))),l=ue("table");if(1===s.length&&l(s[0])){o.preventDefault();const l=xe.fromDom(e.getDoc()),a=zr(l),c=((e,t,o)=>({element:e,clipboard:t,generators:o}))(n,s[0],a);t.pasteCells(r,c).each((()=>{e.focus()}))}}))}))}}))},ys=(e,t)=>({element:e,offset:t}),xs=(e,t,o)=>e.property().isText(t)&&0===e.property().getText(t).trim().length||e.property().isComment(t)?o(t).bind((t=>xs(e,t,o).orThunk((()=>C.some(t))))):C.none(),Cs=(e,t)=>e.property().isText(t)?e.property().getText(t).length:e.property().children(t).length,Ss=(e,t)=>{const o=xs(e,t,e.query().prevSibling).getOr(t);if(e.property().isText(o))return ys(o,Cs(e,o));const n=e.property().children(o);return n.length>0?Ss(e,n[n.length-1]):ys(o,Cs(e,o))},Ts=Ss,Rs=Xr(),Ds=(e,t)=>{if(!jt(e)){const o=(e=>Un(e).bind((e=>{return t=e,o=["fixed","relative","empty"],C.from(Mn.exec(t)).bind((e=>{const t=Number(e[1]),n=e[2];return((e,t)=>O(t,(t=>O(Wn[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)}))}},Os=e=>E(e,g(0)),ks=(e,t,o,n,r)=>r(e.slice(0,t)).concat(n).concat(r(e.slice(o))),Es=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},Ns=Es((e=>e<0)),Bs=Es(x),zs=()=>{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=Ns(e,t,n,r);return ks(e,t,o+1,[s,0],Os)})(t,o,n,r,s);return{resizeTable:(e,t)=>e(t),clampTableDelta:Ns,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=Ns(t,n,r,s);return Os(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}}}},As=()=>{const e=(e,t,o,n,r)=>{const s=Bs(e,n>=0?o:t,n,r);return ks(e,t,o+1,[s,-s],Os)};return{resizeTable:(e,t,o)=>{o&&e(t)},clampTableDelta:(e,t,o,n,r)=>{if(r){if(o>=0)return o;{const t=L(e,((e,t)=>e+t-n),0);return Math.max(-t,o)}}return Ns(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 Os(e);{const t=n/e.length;return E(e,g(t))}},calcRedestributedWidths:(e,t,o,n)=>({delta:0,newSizes:e})}},Ls=e=>Zo(e).grid,Ws=ue("th"),Ms=e=>P(e,(e=>Ws(e.element))),_s=(e,t)=>e&&t?"sectionCells":e?"section":"cells",js=e=>{const t="thead"===e.section,o=vt(Ps(e.cells),"th");return"tfoot"===e.section?{type:"footer"}:t||o?{type:"header",subType:_s(t,o)}:{type:"body"}},Ps=e=>{const t=z(e,(e=>Ws(e.element)));return 0===t.length?C.some("td"):t.length===e.length?C.some("th"):C.none()},Is=(e,t,o)=>et(o(e.element,t),!0,e.isLocked),Fs=(e,t)=>e.section!==t?tt(e.element,e.cells,t,e.isNew):e,Hs=()=>({transformRow:Fs,transformCell:(e,t,o)=>{const n=o(e.element,t),r="td"!==ne(n)?((e,t)=>{const o=Je(e,"td");je(e,o);const n=We(e);return qe(o,n),$e(e),o})(n):n;return et(r,e.isNew,e.isLocked)}}),qs=()=>({transformRow:Fs,transformCell:Is}),Vs=()=>({transformRow:(e,t)=>Fs(e,"thead"===t?"tbody":t),transformCell:Is}),$s=Hs,Us=qs,Gs=Vs,Ks=()=>({transformRow:h,transformCell:Is}),Ys=(e,t,o,n)=>{o===n?be(e,t):ge(e,t,o)},Js=(e,t,o)=>{q(mt(e,t)).fold((()=>Pe(e,o)),(e=>je(e,o)))},Qs=(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),Ys(e.element,"colspan",e.colspan,1),Ys(e.element,"rowspan",e.rowspan,1),Ie(t,e.element)})),t})),s=e=>j(e,(e=>E(e.cells,(e=>(Ys(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?Js(e,"caption,colgroup",o):"colgroup"===t?Js(e,"caption",o):Ie(e,o),o}));return Ve(o),o})(e,o),l=("colgroup"===o?s:r)(t);qe(n,l)},a=(t,o)=>{t.length>0?l(t,o):(t=>{pt(e,t).each($e)})(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}},Xs=(e,t)=>{if(0===e.length)return 0;const o=e[0];return M(e,(e=>!t(o.element,e.element))).getOr(e.length)},Zs=(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=Xs(r.cells.slice(o),n),a=s?1:Xs(((e,t)=>E(e,(e=>Ho(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)}))},el=(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},tl=e=>Zs(e,Re),ol=(e,t)=>V(e.all,(e=>W(e.cells,(e=>Re(t,e.element))))),nl=(e,t,o)=>{const n=E(t.selection,(t=>$t(t).bind((t=>ol(e,t))).filter(o))),r=yt(n);return xt(r.length>0,r)},rl=(e,t,o,n,r)=>(s,l,a,c)=>{const i=Zo(s),m=C.from(null==c?void 0:c.section).getOrThunk(Ks);return t(i,l).map((t=>{const o=((e,t)=>el(e,t,!1))(i,a),n=e(o,t,Re,r(a),m),s=Yo(n.grid);return{info:t,grid:tl(n.grid),cursor:n.cursor,lockedColumns:s}})).bind((e=>{const t=Qs(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(As);return o(s,e.grid,e.info,{sizing:r,resize:l,section:m}),n(s),be(s,Go),e.lockedColumns.length>0&&ge(s,Go,e.lockedColumns.join(",")),C.some({cursor:e.cursor,newRows:t.newRows,newCells:t.newCells})}))},sl=(e,t)=>nl(e,t,x).map((e=>({cells:e,generators:t.generators,clipboard:t.clipboard}))),ll=(e,t)=>nl(e,t,x),al=(e,t)=>nl(e,t,(e=>!e.isLocked)),cl=(e,t)=>P(t,(t=>((e,t)=>ol(e,t).exists((e=>!e.isLocked)))(e,t))),il=(e,t,o,n)=>{const r=$o(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=>ul.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},dl=e=>{const t=()=>o,o={tag:!1,inner:e,fold:(t,o)=>t(e),isValue:y,isError:x,map:t,mapError:t=>ul.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},ul={value:ml,error:dl,fromOption:(e,t)=>e.fold((()=>dl(t)),ml)},fl=(e,t)=>({rowDelta:0,colDelta:Vo(e[0])-Vo(t[0])}),gl=(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))))},pl=(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=Uo(r,e,h),s=hl(t.cells.length,t,o,(e=>X(n,e.toString())));return Fo(t,s)})))},wl=(e,t,o,n)=>E(e,(e=>{const r=hl(t,e,o,y);return jo(e,n,r)})),bl=(e,t,o)=>{const n=t.colDelta<0?wl:h,r=t.rowDelta<0?pl:h,s=Yo(e),l=Vo(e[0]),a=O(s,(e=>e===l-1)),c=n(e,Math.abs(t.colDelta),o,a?l-1:l),i=Yo(c);return r(c,Math.abs(t.rowDelta),o,I(i,x))},vl=(e,t,o,n)=>{const r=w(n,Ho(e[t],o).element),s=e[t];return e.length>1&&Vo(s)>1&&(o>0&&r(qo(s,o-1))||o0&&r(qo(e[t-1],o))||tz(o,(o=>o>=e.column&&o<=Vo(t[0])+e.column)),xl=(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);)Io(e,t+s,et(l,!0,e.cells[t+s].isLocked)),s++}))})(t,e,r,n.cell);const s=gl(o,t),l=bl(o,s,n),a=gl(t,l),c=bl(t,a,n);return E(c,((t,o)=>jo(t,e,l[o].cells)))},Cl=(e,t,o,n,r)=>{((e,t,o,n)=>{const r=$o(e).rows;if(t>0&&tL(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{Io(a,t,et(e,!0,c.isLocked))})))}}))}})(t,e,r,n.cell);const s=Yo(t),l=fl(t,o),a={...l,colDelta:l.colDelta-s.length},c=bl(t,a,n),{cols:i,rows:m}=$o(c),d=Yo(c),u=fl(o,t),f={...u,colDelta:u.colDelta+d.length},g=(p=n,w=d,E(o,(e=>L(w,((t,o)=>{const n=hl(1,e,p,x)[0];return Po(t,o,n)}),e)))),h=bl(g,f,n);var p,w;return[...i,...m.slice(0,e),...h,...m.slice(e,m.length)]},Sl=(e,t,o,n,r)=>{const{rows:s,cols:l}=$o(e),a=s.slice(0,t),c=s.slice(t);return[...l,...a,((e,t,o,n)=>Uo(e,(e=>n(e,o)),t))(s[o],((e,o)=>t>0&&tE(e,(e=>{const s=t>0&&t{if("colgroup"!==o&&n)return Ho(e,t);{const t=Ho(e,r);return et(l(t.element,s),!0,!1)}})(e,t,e.section,s,o,n,r);return Po(e,t,l)})),Rl=(e,t,o,n)=>((e,t,o,n)=>void 0!==qo(e[t],o)&&t>0&&n(qo(e[t-1],o),qo(e[t],o)))(e,t,o,n)||((e,t,o)=>t>0&&o(qo(e,t-1),qo(e,t)))(e[t],o,n),Dl=(e,t,o,n)=>{const r=e=>(e=>"row"===e?Pt(t):jt(t))(e)?`${e}group`:e;return e?Ws(t)?r(o):null:n&&Ws(t)?r("row"===o?"col":"row"):null},Ol=(e,t,o)=>et(o(e.element,t),!0,e.isLocked),kl=(e,t,o,n,r,s,l)=>E(e,((e,a)=>((e,c)=>{const i=e.cells,m=E(i,((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((()=>{be(o,t)}),(e=>{fe(o.dom,t,e)}))}))})),t}return e}));return tt(e.element,m,e.section,e.isNew)})(e))),El=(e,t,o)=>j(e,((n,r)=>Rl(e,r,t,o)?[]:[Ho(n,t)])),Nl=(e,t,o,n,r)=>{const s=$o(e).rows,l=j(t,(e=>El(s,e,n))),a=E(s,(e=>Ms(e.cells))),c=((e,t)=>P(t,h)&&Ms(e)?x:(e,o,n)=>!("th"===ne(e.element)&&t[o]))(l,a),i=((e,t)=>(o,n)=>C.some(Dl(e,o.element,"row",t[n])))(o,a);return kl(e,l,n,r,Ol,i,c)},Bl=(e,t,o,n)=>{const r=$o(e).rows,s=E(t,(e=>Ho(r[e.row],e.column)));return kl(e,s,o,n,Ol,C.none,x)},zl=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=$(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=$(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},Al={...zl([{none:[]},{only:["index"]},{left:["index","next"]},{middle:["prev","index","next"]},{right:["prev","index"]}])},Ll=(e,t,o)=>{let n=0;for(let r=e;r{const o=rn(e);return E(o,(e=>{const o=Ll(e.row,e.row+e.rowspan,t);return{element:e.element,height:o,rowspan:e.rowspan}}))},Ml=(e,t,o)=>{const n=((e,t)=>ln(e)?((e,t)=>{const o=sn(e);return E(o,((e,o)=>({element:e.element,width:t[o],colspan:e.colspan})))})(e,t):((e,t)=>{const o=rn(e);return E(o,(e=>{const o=Ll(e.column,e.column+e.colspan,t);return{element:e.element,width:o,colspan:e.colspan}}))})(e,t))(e,t);N(n,(e=>{o.setElementWidth(e.element,e.width)}))},_l=(e,t,o,n,r)=>{const s=Zo(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?Al.none():1===e.length?Al.only(0):0===t?Al.left(0,1):t===e.length-1?Al.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]));Ml(s,d,r),n.resizeTable(r.adjustTableWidth,i,c)},jl=e=>L(e,((e,t)=>O(e,(e=>e.column===t.column))?e:e.concat([t])),[]).sort(((e,t)=>e.column-t.column)),Pl=ue("col"),Il=ue("colgroup"),Fl=e=>"tr"===ne(e)||Il(e),Hl=e=>({element:e,colspan:Mt(e,"colspan",1),rowspan:Mt(e,"rowspan",1)}),ql=e=>we(e,"scope").map((e=>e.substr(0,3))),Vl=(e,t=Hl)=>{const o=o=>{if(Fl(o))return Il((r={element:o}).element)?e.colgroup(r):e.row(r);{const r=o,s=(t=>Pl(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)))}},$l=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(Fl(e)||Pl(e))return e;{const r=e;return((e,t)=>W(o,(o=>t(o.item,e))))(r,t).fold((()=>n(r)),(o=>t(e,o.item)?o.sub:n(r)))}}}},Ul=e=>({unmerge:t=>{const o=ql(t);return o.each((e=>ge(t,"scope",e))),()=>{const n=e.cell({element:t,colspan:1,rowspan:1});return Wt(n,"width"),Wt(t,"width"),o.each((e=>ge(n,"scope",e))),n}},merge:e=>(Wt(e[0],"width"),(()=>{const t=yt(E(e,ql));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((()=>be(e[0],"scope")),(t=>ge(e[0],"scope",t+"group"))),g(e[0]))}),Gl=["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"],Kl=Xr(),Yl=e=>((e,t)=>{const o=e.property().name(t);return D(Gl,o)})(Kl,e),Jl=e=>((e,t)=>{const o=e.property().name(t);return D(["ol","ul"],o)})(Kl,e),Ql=e=>{const t=ue("br"),o=e=>Cr(e).bind((o=>{const n=Le(o).map((e=>!!Yl(e)||!!((e,t)=>D(["br","img","hr","input"],e.property().name(t)))(Kl,e)&&"img"!==ne(e))).getOr(!1);return Ne(o).map((r=>{return!0===n||("li"===ne(s=r)||ft(s,Jl).isSome())||t(o)||Yl(r)&&!Re(e,r)?[]:[xe.fromTag("br")];var s}))})).getOr([]),n=(()=>{const n=j(e,(e=>{const n=We(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]),qe(e[0],n)},Xl=e=>Lr(e,!0),Zl=e=>{0===Ut(e).length&&$e(e)},ea=(e,t)=>({grid:e,cursor:t}),ta=(e,t,o)=>{const n=((e,t,o)=>{var n,r;const s=$o(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(Xl).orThunk((()=>(e=>V(e,(e=>V(e.cells,(e=>{const t=e.element;return xt(Xl(t),t)})))))(s)))})(e,t,o);return ea(e,n)},oa=e=>L(e,((e,t)=>O(e,(e=>e.row===t.row))?e:e.concat([t])),[]).sort(((e,t)=>e.row-t.row)),na=(e,t)=>(o,n,r,s,l)=>{const a=oa(n),c=E(a,(e=>e.row)),i=((e,t,o,n,r,s,l)=>{const{cols:a,rows:c}=$o(e),i=c[t[0]],m=j(t,(e=>((e,t,o)=>{const n=e[t];return j(n.cells,((n,r)=>Rl(e,t,r,o)?[]:[n]))})(c,e,r))),d=E(i.cells,((e,t)=>Ms(El(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)&&Ms(e.cells)?x:(e,o,n)=>!("th"===ne(e.element)&&t[n]))(i,d),p=((e,t)=>(o,n,r)=>C.some(Dl(e,o.element,"col",t[r])))(n,d);return kl(f,m,r,s,l.transformCell,p,g)})(o,c,e,t,r,s.replaceOrInit,l);return ta(i,n[0].row,n[0].column)},ra=na("thead",!0),sa=na("tbody",!1),la=na("tfoot",!1),aa=(e,t,o)=>{const n=((e,t)=>Qt(e,(()=>t)))(e,o.section),r=en(n);return el(r,t,!0)},ca=(e,t,o,n)=>((e,t,o,n)=>{const r=en(t),s=n.getWidths(r,n);Ml(r,s,n)})(0,t,0,n.sizing),ia=(e,t,o,n)=>((e,t,o,n,r)=>{const s=en(t),l=n.getWidths(s,n),a=n.pixelWidth(),{newSizes:c,delta:i}=r.calcRedestributedWidths(l,a,o.pixelDelta,n.isRelative);Ml(s,c,n),n.adjustTableWidth(i)})(0,t,o,n.sizing,n.resize),ma=(e,t)=>O(t,(e=>0===e.column&&e.isLocked)),da=(e,t)=>O(t,(t=>t.column+t.colspan>=e.grid.columns&&t.isLocked)),ua=(e,t)=>{const o=cn(e),n=jl(t);return L(n,((e,t)=>e+o[t.column].map(Mo).getOr(0)),0)},fa=e=>(t,o)=>ll(t,o).filter((o=>!(e?ma:da)(t,o))).map((e=>({details:e,pixelDelta:ua(t,e)}))),ga=e=>(t,o)=>sl(t,o).filter((o=>!(e?ma:da)(t,o.cells))),ha=$l("th"),pa=$l("td"),wa=rl(((e,t,o,n)=>{const r=t[0].row,s=oa(t),l=A(s,((e,t)=>({grid:Sl(e.grid,r,t.row+e.delta,o,n.getOrInit),delta:e.delta+1})),{grid:e,delta:0}).grid;return ta(l,r,t[0].column)}),ll,f,f,Vl),ba=rl(((e,t,o,n)=>{const r=oa(t),s=r[r.length-1],l=s.row+s.rowspan,a=A(r,((e,t)=>Sl(e,l,t.row,o,n.getOrInit)),e);return ta(a,l,t[0].column)}),ll,f,f,Vl),va=rl(((e,t,o,n)=>{const r=t.details,s=jl(r),l=s[0].column,a=A(s,((e,t)=>({grid:Tl(e.grid,l,t.column+e.delta,o,n.getOrInit),delta:e.delta+1})),{grid:e,delta:0}).grid;return ta(a,r[0].row,l)}),fa(!0),ia,f,Vl),ya=rl(((e,t,o,n)=>{const r=t.details,s=r[r.length-1],l=s.column+s.colspan,a=jl(r),c=A(a,((e,t)=>Tl(e,l,t.column,o,n.getOrInit)),e);return ta(c,r[0].row,l)}),fa(!1),ia,f,Vl),xa=rl(((e,t,o,n)=>{const r=jl(t.details),s=((e,t)=>j(e,(e=>{const o=e.cells,n=A(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 ta(s,r[0].row,Math.min(r[0].column,l))}),((e,t)=>al(e,t).map((t=>({details:t,pixelDelta:-ua(e,t)})))),ia,Zl,Vl),Ca=rl(((e,t,o,n)=>{const r=oa(t),s=((e,t,o)=>{const{rows:n,cols:r}=$o(e);return[...r,...n.slice(0,t),...n.slice(o+1)]})(e,r[0].row,r[r.length-1].row),l=s.length>0?s.length-1:0;return ta(s,Math.min(t[0].row,l),t[0].column)}),ll,f,Zl,Vl),Sa=rl(((e,t,o,n)=>{const r=jl(t),s=E(r,(e=>e.column)),l=Nl(e,s,!0,o,n.replaceOrInit);return ta(l,t[0].row,t[0].column)}),al,f,f,ha),Ta=rl(((e,t,o,n)=>{const r=jl(t),s=E(r,(e=>e.column)),l=Nl(e,s,!1,o,n.replaceOrInit);return ta(l,t[0].row,t[0].column)}),al,f,f,pa),Ra=rl(ra,al,f,f,ha),Da=rl(sa,al,f,f,pa),Oa=rl(la,al,f,f,pa),ka=rl(((e,t,o,n)=>{const r=Bl(e,t,o,n.replaceOrInit);return ta(r,t[0].row,t[0].column)}),al,f,f,ha),Ea=rl(((e,t,o,n)=>{const r=Bl(e,t,o,n.replaceOrInit);return ta(r,t[0].row,t[0].column)}),al,f,f,pa),Na=rl(((e,t,o,n)=>{const r=t.cells;Ql(r);const s=((e,t,o,n)=>{const r=$o(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=Ho(t,o).isLocked;Io(t,o,et(n(),!1,s))}return e})(e,t.bounds,0,n.merge(r));return ea(s,C.from(r[0]))}),((e,t)=>((e,t)=>t.mergable)(0,t).filter((t=>cl(e,t.cells)))),ca,f,Ul),Ba=rl(((e,t,o,n)=>{const r=A(t,((e,t)=>il(e,t,o,n.unmerge(t))),e);return ea(r,C.from(t[0]))}),((e,t)=>((e,t)=>t.unmergable)(0,t).filter((t=>cl(e,t)))),ca,f,Ul),za=rl(((e,t,o,n)=>{const r=((e,t)=>{const o=Zo(e);return el(o,t,!0)})(t.clipboard,t.generators);var s,l;return((e,t,o,n,r)=>{const s=Yo(t),l=((e,t,o)=>{const n=Vo(t[0]),r=$o(t).cols.length+e.row,s=k(n-e.column,(t=>t+e.column));return{row:r,column:W(s,(e=>P(o,(t=>t!==e)))).getOr(n-1)}})(e,t,s),a=$o(o).rows,c=yl(l,a,s),i=((e,t,o)=>{if(e.row>=t.length||e.column>Vo(t[0]))return ul.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=Vo(o[0]),l=o.length;return ul.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=bl(t,o,n),i=Yo(s),m=yl(l,a,i);return((e,t,o,n,r,s)=>{const l=e.row,a=e.column,c=l+o.length,i=a+Vo(o[0])+s.length,m=I(s,x);for(let e=l;eea(e,C.some(t.element))),(e=>ta(e,t.row,t.column)))}),((e,t)=>$t(t.element).bind((o=>ol(e,o).map((e=>({...e,generators:t.generators,clipboard:t.clipboard})))))),ca,f,Vl),Aa=rl(((e,t,o,n)=>{const r=$o(e).rows,s=t.cells[0].column,l=r[t.cells[0].row],a=aa(t.clipboard,t.generators,l),c=xl(s,e,a,t.generators,o);return ta(c,t.cells[0].row,t.cells[0].column)}),ga(!0),f,f,Vl),La=rl(((e,t,o,n)=>{const r=$o(e).rows,s=t.cells[t.cells.length-1].column+t.cells[t.cells.length-1].colspan,l=r[t.cells[0].row],a=aa(t.clipboard,t.generators,l),c=xl(s,e,a,t.generators,o);return ta(c,t.cells[0].row,t.cells[0].column)}),ga(!1),f,f,Vl),Wa=rl(((e,t,o,n)=>{const r=$o(e).rows,s=t.cells[0].row,l=r[s],a=aa(t.clipboard,t.generators,l),c=Cl(s,e,a,t.generators,o);return ta(c,t.cells[0].row,t.cells[0].column)}),sl,f,f,Vl),Ma=rl(((e,t,o,n)=>{const r=$o(e).rows,s=t.cells[t.cells.length-1].row+t.cells[t.cells.length-1].rowspan,l=r[t.cells[0].row],a=aa(t.clipboard,t.generators,l),c=Cl(s,e,a,t.generators,o);return ta(c,t.cells[0].row,t.cells[0].column)}),sl,f,f,Vl),_a=(e,t)=>{const o=Zo(e);return ll(o,t).bind((e=>{const t=e[e.length-1],n=e[0].column,r=t.column+t.colspan,s=_(E(o.all,(e=>z(e.cells,(e=>e.column>=n&&e.column{const o=Zo(e);return ll(o,t).bind(Ps).getOr("")},Pa=(e,t)=>{const o=Zo(e);return ll(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=>js(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("")},Ia=(e,t)=>e.dispatch("NewRow",{node:t}),Fa=(e,t)=>e.dispatch("NewCell",{node:t}),Ha=(e,t,o)=>{e.dispatch("TableModified",{...o,table:t})},qa={structure:!1,style:!0},Va={structure:!0,style:!1},$a={structure:!0,style:!0},Ua=e=>t=>t.options.get(e),Ga="100%",Ka=e=>{var t;const o=e.dom,n=null!==(t=o.getParent(e.selection.getStart(),o.isBlock))&&void 0!==t?t:e.getBody();return _o(xe.fromDom(n))+"px"},Ya=e=>C.from(e.options.get("table_clone_elements")),Ja=Ua("table_header_type"),Qa=Ua("table_column_resizing"),Xa=e=>"preservetable"===Qa(e),Za=e=>"resizetable"===Qa(e),ec=Ua("table_sizing_mode"),tc=e=>"relative"===ec(e),oc=e=>"fixed"===ec(e),nc=e=>"responsive"===ec(e),rc=Ua("table_resize_bars"),sc=Ua("table_style_by_css"),lc=e=>{const t=e.options,o=t.get("table_default_attributes");return t.isSet("table_default_attributes")?o:((e,t)=>nc(e)||sc(e)?t:oc(e)?{...t,width:Ka(e)}:{...t,width:Ga})(e,o)},ac=Ua("table_use_colgroups"),cc=(e,t)=>tc(e)?ur(t):oc(e)?dr(t):mr(t),ic=(e,t,o)=>{const n=e=>"table"===ne(Mr(e)),r=Ya(e),s=Za(e)?f:Ds,l=t=>{switch(Ja(e)){case"section":return $s();case"sectionCells":return Us();case"cells":return Gs();default:return((e,t)=>{var o;switch((o=Zo(e),V(o.all,(e=>{const t=js(e);return"header"===t.type?C.from(t.subType):C.none()}))).getOr(t)){case"section":return Hs();case"sectionCells":return qs();case"cells":return Vs()}})(t,"section")}},a=(n,s,a,c)=>(i,m,d=!1)=>{jr(i);const u=xe.fromDom(e.getDoc()),f=Br(a,u,r),g={sizing:cc(e,i),resize:Za(e)?zs():As(),section:l(i)};return s(i)?n(i,m,f,g).bind((n=>{t.refresh(i.dom),N(n.newRows,(t=>{Ia(e,t.dom)})),N(n.newCells,(t=>{Fa(e,t.dom)}));const r=((t,n)=>n.cursor.fold((()=>{const n=Ut(t);return H(n).filter(lt).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=Ts(Rs,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 lt(i)&&(jr(i),d||Ha(e,i.dom,c)),r.map((e=>({rng:e,effect:c})))})):C.none()},c=a(Ca,(t=>!n(e)||Ls(t).rows>1),f,Va),i=a(xa,(t=>!n(e)||Ls(t).columns>1),f,Va);return{deleteRow:c,deleteColumn:i,insertRowsBefore:a(wa,x,f,Va),insertRowsAfter:a(ba,x,f,Va),insertColumnsBefore:a(va,x,s,Va),insertColumnsAfter:a(ya,x,s,Va),mergeCells:a(Na,x,f,Va),unmergeCells:a(Ba,x,f,Va),pasteColsBefore:a(Aa,x,f,Va),pasteColsAfter:a(La,x,f,Va),pasteRowsBefore:a(Wa,x,f,Va),pasteRowsAfter:a(Ma,x,f,Va),pasteCells:a(za,x,f,$a),makeCellsHeader:a(ka,x,f,Va),unmakeCellsHeader:a(Ea,x,f,Va),makeColumnsHeader:a(Sa,x,f,Va),unmakeColumnsHeader:a(Ta,x,f,Va),makeRowsHeader:a(Ra,x,f,Va),makeRowsBody:a(Da,x,f,Va),makeRowsFooter:a(Oa,x,f,Va),getTableRowType:Pa,getTableCellType:ja,getTableColType:_a}},mc=(e,t,o)=>{const n=Mt(e,t,1);1===o||n<=1?be(e,t):ge(e,t,Math.min(o,n))},dc=(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):uc.invalid(o)},gc={...uc,from:e=>Rt(e,"%")?fc("%",uc.percent,e):Rt(e,"px")?fc("px",uc.pixels,e):uc.invalid(e)},hc=(e,t,o)=>{const n=gc.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=>gc.from(e).fold((()=>e),(e=>e*n+"px"),(e=>e/100*o+"px"))))})(t,o,e)),(e=>((e,t)=>E(e,(e=>gc.from(e).fold((()=>e),(e=>e/t*100+"%"),(e=>e+"%")))))(t,o))))(n,e,t);return bc(r)},pc=(e,t)=>0===e.length?t:A(e,((e,t)=>gc.from(t).fold(g(0),h,h)+e),0),wc=(e,t)=>gc.from(e).fold(g(e),(e=>e+t+"px"),(e=>e+t+"%")),bc=e=>{if(0===e.length)return e;const t=A(e,((e,t)=>{const o=gc.from(t).fold((()=>({value:t,remainder:0})),(e=>((e,t)=>{const o=Math.floor(e);return{value:o+"px",remainder:e-o}})(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([wc(o[o.length-1],Math.round(t.remainder))])},vc=gc.from,yc=e=>vc(e).fold(g("px"),g("px"),g("%")),xc=(e,t,o)=>{const n=Zo(e),r=n.all,s=rn(n),l=sn(n);t.each((t=>{const o=yc(t),r=Wo(e),a=((e,t)=>nr(e,t,er,rr))(n,e),c=hc(a,r,t);ln(n)?((e,t,o)=>{N(t,((t,n)=>{const r=pc([e[n]],Ft());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=pc(n,Ft());Nt(t.element,"width",r+o)}))})(c,s,o),Nt(e,"width",t)})),o.each((t=>{const o=yc(t),l=hn(e),a=((e,t,o)=>lr(e,t,o,tr,rr))(n,e,zn);((e,t,o,n)=>{N(o,(t=>{const o=e.slice(t.row,t.rowspan+t.row),r=pc(o,Ht());Nt(t.element,"height",r+n)})),N(t,((t,o)=>{Nt(t.element,"height",e[o])}))})(hc(a,l,t),r,s,o),Nt(e,"height",t)}))},Cc=e=>Un(e).exists((e=>_n.test(e))),Sc=e=>Un(e).exists((e=>jn.test(e))),Tc=e=>Un(e).isNone(),Rc=e=>{be(e,"width")},Dc=e=>{const t=Qn(e);xc(e,C.some(t),C.none()),Rc(e)},Oc=e=>{const t=(e=>Wo(e)+"px")(e);xc(e,C.some(t),C.none()),Rc(e)},kc=e=>{Wt(e,"width");const t=Gt(e),o=t.length>0?t:Ut(e);N(o,(e=>{Wt(e,"width"),Rc(e)})),Rc(e)},Ec={styles:{"border-collapse":"collapse",width:"100%"},attributes:{border:"1"},colGroups:!1},Nc=(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)},zc=(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)=>nc(e)||!sc(e)?t:oc(e)?{...t,width:Ka(e)}:{...t,width:Ga})(e,o)})(e),a={styles:l,attributes:lc(e),colGroups:ac(e)};return e.undoManager.ignore((()=>{const r=((e,t,o,n,r,s=Ec)=>{const l=xe.fromTag("table"),a="cells"!==r;Bt(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=Nc(o,t,"sectionCells"===r?c:0,n);qe(e,s)}const i=xe.fromTag("tbody");Ie(l,i);const m=Nc(a?e-c:e,t,a?0:o,n);return qe(i,m),l})(o,t,s,n,Ja(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()})),wt(Mr(e),'table[data-mce-id="__mce"]').map((t=>(oc(e)?Oc(t):nc(e)?kc(t):(tc(e)||(e=>r(e)&&-1!==e.indexOf("%"))(l.width))&&Dc(t),jr(t),be(t,"data-mce-id"),((e,t)=>{N(dt(t,"tr"),(t=>{Ia(e,t.dom),N(dt(t,"th,td"),(t=>{Fa(e,t.dom)}))}))})(e,t),((e,t)=>{wt(t,"td,th").each(w(Bc,e))})(e,t),t.dom))).getOrNull()};var Ac=tinymce.util.Tools.resolve("tinymce.FakeClipboard");const Lc="x-tinymce/dom-table-",Wc=Lc+"rows",Mc=Lc+"columns",_c=e=>{const t=Ac.FakeClipboardItem(e);Ac.write([t])},jc=e=>{var t;const o=null!==(t=Ac.read())&&void 0!==t?t:[];return V(o,(t=>C.from(t.getType(e))))},Pc=e=>{jc(e).isSome()&&Ac.clear()},Ic=e=>{e.fold(Hc,(e=>_c({[Wc]:e})))},Fc=()=>jc(Wc),Hc=()=>Pc(Wc),qc=e=>{e.fold($c,(e=>_c({[Mc]:e})))},Vc=()=>jc(Mc),$c=()=>Pc(Mc),Uc=e=>ps(Pr(e),_r(e)).filter(Hr),Gc=(e,t)=>{const o=_r(e),n=e=>Kt(e,o),l=t=>(e=>ws(Pr(e),_r(e)).filter(Hr))(e).bind((e=>n(e).map((o=>t(o,e))))),a=t=>{e.focus()},c=(t,o=!1)=>l(((n,r)=>{const s=gs(bs(e),n,r);t(n,s,o).each(a)})),i=()=>l(((t,o)=>((e,t,o)=>{const n=Zo(e);return ll(n,t).bind((e=>{const t=el(n,o,!1),r=$o(t).rows.slice(e[0].row,e[e.length-1].row+e[e.length-1].rowspan),s=j(r,(e=>{const t=z(e.cells,(e=>!e.isLocked));return t.length>0?[{...e,cells:t}]:[]})),l=tl(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);Ys(o,"colspan",e.colspan,1),Ys(o,"rowspan",e.rowspan,1),Ie(t,o)})),t}))))})(t,gs(bs(e),t,o),Br(f,xe.fromDom(e.getDoc()),C.none())))),m=()=>l(((t,o)=>((e,t)=>{const o=Zo(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(ln(e)){const n=z(sn(e),dc(t,o)),r=E(n,(e=>{const n=Ye(e.element);return mc(n,"span",o-t),n})),s=xe.fromTag("colgroup");return qe(s,r),[s]}return[]})(o,n,r),l=((e,t,o)=>E(e.all,(e=>{const n=z(e.cells,dc(t,o)),r=E(n,(e=>{const n=Ye(e.element);return mc(n,"colspan",o-t),n})),s=xe.fromTag("tr");return qe(s,r),s})))(o,n,r);return[...s,...l]}))})(t,gs(bs(e),t,o)))),d=(t,o)=>o().each((o=>{const n=E(o,(e=>Ye(e)));l(((o,r)=>{const s=zr(xe.fromDom(e.getDoc())),l=((e,t,o,n)=>({selection:ms(e),clipboard:o,generators:n}))(bs(e),0,n,s);t(o,l).each(a)}))})),g=e=>(t,o)=>((e,t)=>X(e,t)?C.from(e.type):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=>{qc(e),c(t.deleteColumn)})),mceTableCutRow:()=>i().each((e=>{Ic(e),c(t.deleteRow)})),mceTableCopyCol:()=>m().each((e=>qc(e))),mceTableCopyRow:()=>i().each((e=>Ic(e))),mceTablePasteColBefore:()=>d(t.pasteColsBefore,Vc),mceTablePasteColAfter:()=>d(t.pasteColsAfter,Vc),mceTablePasteRowBefore:()=>d(t.pasteRowsBefore,Fc),mceTablePasteRowAfter:()=>d(t.pasteRowsAfter,Fc),mceTableDelete:()=>Uc(e).each((t=>{Kt(t,o).filter(b(o)).each((t=>{const o=xe.fromText("");if(je(t,o),$e(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=bs(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))),Ha(e,t.dom,qa)}))},mceTableToggleClass:(t,o)=>{l((t=>{e.formatter.toggle("tableclass",{value:o},t.dom),Ha(e,t.dom,qa)}))},mceTableToggleCaption:()=>{Uc(e).each((t=>{Kt(t,o).each((o=>{pt(o,"caption").fold((()=>{const t=xe.fromTag("caption");Ie(t,xe.fromText("Caption")),((e,t,o)=>{Me(e,0).fold((()=>{Ie(e,t)}),(e=>{_e(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))),$e(n)})),Ha(e,o.dom,Va)}))}))},mceTableSizingMode:(t,n)=>(t=>Uc(e).each((n=>{nc(e)||oc(e)||tc(e)||Kt(n,o).each((o=>{"relative"!==t||Cc(o)?"fixed"!==t||Sc(o)?"responsive"!==t||Tc(o)||kc(o):Oc(o):Dc(o),jr(o),Ha(e,o.dom,Va)}))})))(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 zc(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=z(bs(e),Hr);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=>Ha(e,t.dom,qa))))}))},Kc=zl([{before:["element"]},{on:["element","offset"]},{after:["element"]}]),Yc={before:Kc.before,on:Kc.on,after:Kc.after,cata:(e,t,o,n)=>e.fold(t,o,n),getStart:e=>e.fold(h,h,h)},Jc=(e,t)=>({selection:e,kill:t}),Qc=(e,t)=>{const o=e.document.createRange();return o.selectNode(t.dom),o},Xc=(e,t)=>{const o=e.document.createRange();return Zc(o,t),o},Zc=(e,t)=>e.selectNodeContents(t.dom),ei=(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},ti=(e,t,o,n,r)=>{const s=e.document.createRange();return s.setStart(t.dom,o),s.setEnd(n.dom,r),s},oi=e=>({left:e.left,top:e.top,right:e.right,bottom:e.bottom,width:e.width,height:e.height}),ni=zl([{ltr:["start","soffset","finish","foffset"]},{rtl:["start","soffset","finish","foffset"]}]),ri=(e,t,o)=>t(xe.fromDom(o.startContainer),o.startOffset,xe.fromDom(o.endContainer),o.endOffset),si=(e,t)=>{const o=((e,t)=>t.match({domRange:e=>({ltr:g(e),rtl:C.none}),relative:(t,o)=>({ltr:eo((()=>ei(e,t,o))),rtl:eo((()=>C.some(ei(e,o,t))))}),exact:(t,o,n,r)=>({ltr:eo((()=>ti(e,t,o,n,r))),rtl:eo((()=>C.some(ti(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=>ni.rtl(xe.fromDom(e.endContainer),e.endOffset,xe.fromDom(e.startContainer),e.startOffset))).getOrThunk((()=>ri(0,ni.ltr,o))):ri(0,ni.ltr,o)})(0,o)},li=(e,t)=>si(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}});ni.ltr,ni.rtl;const ai=(e,t,o,n)=>({start:e,soffset:t,finish:o,foffset:n}),ci=(e,t,o,n)=>({start:Yc.on(e,t),finish:Yc.on(o,n)}),ii=(e,t)=>{const o=li(e,t);return ai(xe.fromDom(o.startContainer),o.startOffset,xe.fromDom(o.endContainer),o.endOffset)},mi=ci,di=(e,t,o,n,r)=>Re(o,n)?C.none():rs(o,n,t).bind((t=>{const n=t.boxes.getOr([]);return n.length>1?(r(e,n,t.start,t.finish),C.some(Jc(C.some(mi(o,0,o,br(o))),!0))):C.none()})),ui=(e,t)=>({item:e,mode:t}),fi=(e,t,o,n=gi)=>e.property().parent(t).map((e=>ui(e,n))),gi=(e,t,o,n=hi)=>o.sibling(e,t).map((e=>ui(e,n))),hi=(e,t,o,n=hi)=>{const r=e.property().children(t);return o.first(r).map((e=>ui(e,n)))},pi=[{current:fi,next:gi,fallback:C.none()},{current:gi,next:hi,fallback:C.some(fi)},{current:hi,next:hi,fallback:C.some(gi)}],wi=(e,t,o,n,r=pi)=>W(r,(e=>e.current===o)).bind((o=>o.current(e,t,n,o.next).orThunk((()=>o.fallback.bind((o=>wi(e,t,o,n))))))),bi=(e,t,o,n,r,s)=>wi(e,t,n,r).bind((t=>s(t.item)?C.none():o(t.item)?C.some(t.item):bi(e,t.item,o,t.mode,r,s))),vi=e=>t=>0===e.property().children(t).length,yi=(e,t,o,n)=>bi(e,t,o,gi,{sibling:(e,t)=>e.query().prevSibling(t),first:e=>e.length>0?C.some(e[e.length-1]):C.none()},n),xi=(e,t,o,n)=>bi(e,t,o,gi,{sibling:(e,t)=>e.query().nextSibling(t),first:e=>e.length>0?C.some(e[0]):C.none()},n),Ci=Xr(),Si=(e,t)=>((e,t,o)=>yi(e,t,vi(e),o))(Ci,e,t),Ti=(e,t)=>((e,t,o)=>xi(e,t,vi(e),o))(Ci,e,t),Ri=zl([{none:["message"]},{success:[]},{failedUp:["cell"]},{failedDown:["cell"]}]),Di=e=>bt(e,"tr"),Oi={...Ri,verify:(e,t,o,n,r,s,l)=>bt(n,"td,th",l).bind((o=>bt(t,"td,th",l).map((t=>Re(o,t)?Re(n,o)&&br(o)===r?s(t):Ri.none("in same cell"):os(Di,[o,t]).fold((()=>((e,t,o)=>{const n=e.getRect(t),r=e.getRect(o);return r.right>n.left&&r.lefts(t))))))).getOr(Ri.none("default")),cata:(e,t,o,n,r)=>e.fold(t,o,n,r)},ki=ue("br"),Ei=(e,t,o)=>t(e,o).bind((e=>ie(e)&&0===hr(e).trim().length?Ei(e,t,o):C.some(e))),Ni=(e,t,o,n)=>((e,t)=>Me(e,t).filter(ki).orThunk((()=>Me(e,t-1).filter(ki))))(t,o).bind((t=>n.traverse(t).fold((()=>Ei(t,n.gather,e).map(n.relative)),(e=>(e=>Ne(e).bind((t=>{const o=We(t);return((e,t)=>M(e,w(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=>Yc.on(e.parent,e.index))))))),Bi=(e,t)=>({left:e.left,top:e.top+t,right:e.right,bottom:e.bottom+t}),zi=(e,t)=>({left:e.left,top:e.top-t,right:e.right,bottom:e.bottom-t}),Ai=(e,t,o)=>({left:e.left+t,top:e.top+o,right:e.right+t,bottom:e.bottom+o}),Li=e=>({left:e.left,top:e.top,right:e.right,bottom:e.bottom}),Wi=(e,t)=>C.some(e.getRect(t)),Mi=(e,t,o)=>ce(t)?Wi(e,t).map(Li):ie(t)?((e,t,o)=>o>=0&&o0?e.getRangedRect(t,o-1,t,o):C.none())(e,t,o).map(Li):C.none(),_i=(e,t)=>ce(t)?Wi(e,t).map(Li):ie(t)?e.getRangedRect(t,0,t,br(t)).map(Li):C.none(),ji=zl([{none:[]},{retry:["caret"]}]),Pi=(e,t,o)=>gt(t,Yl).fold(y,(t=>_i(e,t).exists((e=>((e,t)=>e.leftt.right)(o,e))))),Ii={point:e=>e.bottom,adjuster:(e,t,o,n,r)=>{const s=Bi(r,5);return Math.abs(o.bottom-n.bottom)<1||o.top>r.bottom?ji.retry(s):o.top===r.bottom?ji.retry(Bi(r,1)):Pi(e,t,r)?ji.retry(Ai(s,5,0)):ji.none()},move:Bi,gather:Ti},Fi=(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)=>Fi(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=>_i(e,s).bind((l=>t.adjuster(e,s,l,o,n).fold(C.none,(n=>Fi(e,t,o,n,r-1))))).orThunk((()=>C.some(n)))),C.none))),Hi=(e,t,o)=>{const n=e.move(o,5),r=Fi(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))))},qi={tryUp:w(Hi,{point:e=>e.top,adjuster:(e,t,o,n,r)=>{const s=zi(r,5);return Math.abs(o.top-n.top)<1||o.bottome.getSelection().bind((n=>((e,t,o,n)=>{const r=ki(t)?((e,t,o)=>o.traverse(t).orThunk((()=>Ei(t,o.gather,e))).map(o.relative))(e,t,n):Ni(e,t,o,n);return r.map((e=>({start:e,finish:e})))})(t,n.finish,n.foffset,o).fold((()=>C.some(ys(n.finish,n.foffset))),(r=>{const s=e.fromSitus(r);return l=Oi.verify(e,n.finish,n.foffset,s.finish,s.foffset,o.failure,t),Oi.cata(l,(e=>C.none()),(()=>C.none()),(e=>C.some(ys(e,0))),(e=>C.some(ys(e,br(e)))));var l})))),$i=(e,t,o,n,r,s)=>0===s?C.none():Ki(e,t,o,n,r).bind((l=>{const a=e.fromSitus(l),c=Oi.verify(e,o,n,a.finish,a.foffset,r.failure,t);return Oi.cata(c,(()=>C.none()),(()=>C.some(l)),(l=>Re(o,l)&&0===n?Ui(e,o,n,zi,r):$i(e,t,l,0,r,s-1)),(l=>Re(o,l)&&n===br(l)?Ui(e,o,n,Bi,r):$i(e,t,l,br(l),r,s-1)))})),Ui=(e,t,o,n,r)=>Mi(e,t,o).bind((t=>Gi(e,r,n(t,qi.getJumpSize())))),Gi=(e,t,o)=>{const n=Bo().browser;return n.isChromium()||n.isSafari()||n.isFirefox()?t.retry(e,o):C.none()},Ki=(e,t,o,n,r)=>Mi(e,o,n).bind((t=>Gi(e,r,t))),Yi=(e,t,o,n,r)=>bt(n,"td,th",t).bind((n=>bt(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)=>Vi(e,t,o).bind((n=>$i(e,t,n.element,n.offset,o,20).map(e.fromSitus))))(e,t,o).bind((e=>bt(e.finish,"td,th",t).map((t=>({start:n,finish:t,range:e}))))):C.none())))),Ji=(e,t,o,n,r,s)=>s(n,t).orThunk((()=>Yi(e,t,o,n,r).map((e=>{const t=e.range;return Jc(C.some(mi(t.start,t.soffset,t.finish,t.foffset)),!0)})))),Qi=(e,t)=>bt(e,"tr",t).bind((e=>bt(e,"table",t).bind((o=>{const n=dt(o,"tr");return Re(e,n[0])?((e,t,o)=>yi(Ci,e,(e=>Cr(e).isSome()),o))(o,0,t).map((e=>{const t=br(e);return Jc(C.some(mi(e,t,e,t)),!0)})):C.none()})))),Xi=(e,t)=>bt(e,"tr",t).bind((e=>bt(e,"table",t).bind((o=>{const n=dt(o,"tr");return Re(e,n[n.length-1])?((e,t,o)=>xi(Ci,e,(e=>xr(e).isSome()),o))(o,0,t).map((e=>Jc(C.some(mi(e,0,e,0)),!0))):C.none()})))),Zi=(e,t,o,n,r,s,l)=>Yi(e,o,n,r,s).bind((e=>di(t,o,e.start,e.finish,l))),em=e=>{let t=e;return{get:()=>t,set:e=>{t=e}}},tm=()=>{const e=(e=>{const t=em(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)}},om=(e,t)=>bt(e,"td,th",t),nm=e=>Be(e).exists(Lr),rm={traverse:Le,gather:Ti,relative:Yc.before,retry:qi.tryDown,failure:Oi.failedDown},sm={traverse:Ae,gather:Si,relative:Yc.before,retry:qi.tryUp,failure:Oi.failedUp},lm=e=>t=>t===e,am=lm(38),cm=lm(40),im=e=>e>=37&&e<=40,mm={isBackward:lm(37),isForward:lm(39)},dm={isBackward:lm(39),isForward:lm(37)},um=zl([{domRange:["rng"]},{relative:["startSitu","finishSitu"]},{exact:["start","soffset","finish","foffset"]}]),fm={domRange:um.domRange,relative:um.relative,exact:um.exact,exactFromRange:e=>um.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)=>Yc.getStart(e),exact:(e,t,o,n)=>e}))(e);return xe.fromDom(Ee(t).dom.defaultView)},range:ai},gm=document.caretPositionFromPoint?(e,t,o)=>{var n,r;return C.from(null===(r=(n=e.dom).caretPositionFromPoint)||void 0===r?void 0:r.call(n,t,o)).bind((t=>{if(null===t.offsetNode)return C.none();const o=e.dom.createRange();return o.setStart(t.offsetNode,t.offset),o.collapse(),C.some(o)}))}:document.caretRangeFromPoint?(e,t,o)=>{var n,r;return C.from(null===(r=(n=e.dom).caretRangeFromPoint)||void 0===r?void 0:r.call(n,t,o))}:C.none,hm=(e,t)=>{const o=ne(e);return"input"===o?Yc.after(e):D(["br","img"],o)?0===t?Yc.before(e):Yc.after(e):Yc.on(e,t)},pm=e=>C.from(e.getSelection()),wm=(e,t)=>{pm(e).each((e=>{e.removeAllRanges(),e.addRange(t)}))},bm=(e,t,o,n,r)=>{const s=ti(e,t,o,n,r);wm(e,s)},vm=(e,t)=>si(e,t).match({ltr:(t,o,n,r)=>{bm(e,t,o,n,r)},rtl:(t,o,n,r)=>{pm(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){bm(e,n,r,t,o)}else bm(e,n,r,t,o)}))}}),ym=(e,t,o,n,r)=>{const s=((e,t,o,n)=>{const r=hm(e,t),s=hm(o,n);return fm.relative(r,s)})(t,o,n,r);vm(e,s)},xm=(e,t,o)=>{const n=((e,t)=>{const o=e.fold(Yc.before,hm,Yc.after),n=t.fold(Yc.before,hm,Yc.after);return fm.relative(o,n)})(t,o);vm(e,n)},Cm=e=>{if(e.rangeCount>0){const t=e.getRangeAt(0),o=e.getRangeAt(e.rangeCount-1);return C.some(ai(xe.fromDom(t.startContainer),t.startOffset,xe.fromDom(o.endContainer),o.endOffset))}return C.none()},Sm=e=>{if(null===e.anchorNode||null===e.focusNode)return Cm(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(ai(t,e.anchorOffset,o,e.focusOffset)):Cm(e)}},Tm=(e,t,o=!0)=>{const n=(o?Xc:Qc)(e,t);wm(e,n)},Rm=e=>(e=>pm(e).filter((e=>e.rangeCount>0)).bind(Sm))(e).map((e=>fm.exact(e.start,e.soffset,e.finish,e.foffset))),Dm=e=>({elementFromPoint:(t,o)=>xe.fromPoint(xe.fromDom(e.document),t,o),getRect:e=>e.dom.getBoundingClientRect(),getRangedRect:(t,o,n,r)=>{const s=fm.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(oi):C.none()})(li(e,t)))(e,s)},getSelection:()=>Rm(e).map((t=>ii(e,t))),fromSitus:t=>{const o=fm.relative(t.start,t.finish);return ii(e,o)},situsFromPoint:(t,o)=>((e,t,o)=>((e,t,o)=>{const n=xe.fromDom(e.document);return gm(n,t,o).map((e=>ai(xe.fromDom(e.startContainer),e.startOffset,xe.fromDom(e.endContainer),e.endOffset)))})(e,t,o))(e,t,o).map((e=>ci(e.start,e.soffset,e.finish,e.foffset))),clearSelection:()=>{(e=>{pm(e).each((e=>e.removeAllRanges()))})(e)},collapseSelection:(t=!1)=>{Rm(e).each((o=>o.fold((e=>e.collapse(t)),((o,n)=>{const r=t?o:n;xm(e,r,r)}),((o,n,r,s)=>{const l=t?o:r,a=t?n:s;ym(e,l,a,l,a)}))))},setSelection:t=>{ym(e,t.start,t.soffset,t.finish,t.foffset)},setRelativeSelection:(t,o)=>{xm(e,t,o)},selectNode:t=>{Tm(e,t,!1)},selectContents:t=>{Tm(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))}}),Om=(e,t)=>({rows:e,cols:t}),km=e=>gt(e,ae).exists(Lr),Em=(e,t)=>km(e)||km(t),Nm=e=>void 0!==e.dom.classList,Bm=(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),zm=(e,t)=>{Nm(e)?e.dom.classList.add(t):Bm(e,t)},Am=(e,t)=>Nm(e)&&e.dom.classList.contains(t),Lm=()=>({tag:"none"}),Wm=e=>({tag:"multiple",elements:e}),Mm=e=>({tag:"single",element:e}),_m=e=>{const t=xe.fromDom((e=>{if(nt()&&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)},jm=(e,t,o,n)=>{e.dom.removeEventListener(t,o,n)},Pm=x,Im=(e,t,o)=>((e,t,o,n)=>((e,t,o,n,r)=>{const s=((e,t)=>o=>{e(o)&&t(_m(o))})(o,n);return e.dom.addEventListener(t,s,r),{unbind:w(jm,e,t,s,r)}})(e,t,o,n,!1))(e,t,Pm,o),Fm=_m,Hm=e=>!Am(xe.fromDom(e.target),"ephox-snooker-resizer-bar"),qm=(e,t)=>{const o=(r=fs.selectedSelector,{get:()=>cs(xe.fromDom(e.getBody()),r).fold((()=>ws(Pr(e),_r(e)).fold(Lm,Mm)),Wm)}),n=((e,t,o)=>{const n=t=>{be(t,e.selected),be(t,e.firstSelected),be(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}})(fs,((t,o,n)=>{Kt(o).each((r=>{const s=Ya(e),l=Br(f,xe.fromDom(e.getDoc()),s),a=((e,t,o)=>{const n=Zo(e);return ll(n,t).map((e=>{const t=el(n,o,!1),{rows:r}=$o(t),s=((e,t)=>{const o=e.slice(0,t[t.length-1].row+1),n=tl(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=tl(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:bs(e)},l);((e,t,o,n,r)=>{e.dispatch("TableSelectionChange",{cells:t,start:o,finish:n,otherCells:r})})(e,t,o,n,a)}))}),(()=>(e=>{e.dispatch("TableSelectionClear")})(e)));var r;return e.on("init",(o=>{const r=e.getWin(),s=Mr(e),l=_r(e),a=((e,t,o,n)=>{const r=((e,t,o,n)=>{const r=tm(),s=r.clear,l=s=>{r.on((r=>{n.clearBeforeUpdate(t),om(s.target,o).each((l=>{rs(r,l,o).each((o=>{const r=o.boxes.getOr([]);if(1===r.length){const o=r[0],l="false"===Wr(o),a=vt(Ar(s.target),o,Re);l&&a&&(n.selectRange(t,r,o,o),e.selectContents(o))}else r.length>1&&(n.selectRange(t,r,o.start,o.finish),e.selectContents(l))}))}))}))};return{clearstate:s,mousedown:e=>{n.clear(t),om(e.target,o).filter(nm).each(r.set)},mouseover:e=>{l(e)},mouseup:e=>{l(e),s()}}})(Dm(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=Dm(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=ss(t,n.selectedSelector).fold((()=>(im(u)&&!f&&n.clearBeforeUpdate(t),im(u)&&f&&!Em(l,c)?C.none:cm(u)&&f?w(Zi,r,t,o,rm,c,l,n.selectRange):am(u)&&f?w(Zi,r,t,o,sm,c,l,n.selectRange):cm(u)?w(Ji,r,o,rm,c,l,Xi):am(u)?w(Ji,r,o,sm,c,l,Qi):C.none)),(e=>{const o=o=>()=>{const s=V(o,(o=>((e,t,o,n,r)=>as(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((()=>ls(t,n.firstSelectedSelector,n.lastSelectedSelector).map((e=>{const o=cm(u)||m.isForward(u)?Yc.after:Yc.before;return r.setRelativeSelection(Yc.on(e.first,0),o(e.table)),n.clear(t),Jc(C.none(),!0)}))),(e=>C.some(Jc(C.none(),!0))))};return im(u)&&f&&!Em(l,c)?C.none:cm(u)&&f?o([Om(1,0)]):am(u)&&f?o([Om(-1,0)]):m.isBackward(u)&&f?o([Om(0,-1),Om(-1,0)]):m.isForward(u)&&f?o([Om(0,1),Om(1,0)]):im(u)&&!f?s:C.none}));return g()},keyup:(e,r,s,l,a)=>ss(t,n.selectedSelector).fold((()=>{const c=e.raw,i=c.which;return!0===c.shiftKey&&im(i)&&Em(r,l)?((e,t,o,n,r,s,l)=>Re(o,r)&&n===s?C.none():bt(o,"td,th",t).bind((o=>bt(r,"td,th",t).bind((n=>di(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=Dm(e);return(e,s)=>{n.clearBeforeUpdate(t),rs(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=fm.relative(t.start,t.finish),n=li(r,o);e.selection.setRng(n)})))},d=e=>0===e.button,u=(()=>{const e=em(xe.fromDom(s)),t=em(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)&&Hm(e)&&a.mousedown(Fm(e))})),e.on("mouseover",(e=>{var t;void 0!==(t=e).buttons&&0==(1&t.buttons)||!Hm(e)||a.mouseover(Fm(e))})),e.on("mouseup",(e=>{d(e)&&Hm(e)&&a.mouseup(Fm(e))})),e.on("touchend",u.touchEnd),e.on("keyup",(t=>{const o=Fm(t);if(o.raw.shiftKey&&im(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=Fm(o);t.hide();const r=e.selection.getRng(),s=xe.fromDom(r.startContainer),l=xe.fromDom(r.endContainer),a=un(mm,dm)(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());os(Kt,[o,r]).fold((()=>n.clear(s)),f)}))})),e.on("PreInit",(()=>{e.serializer.addTempAttr(fs.firstSelected),e.serializer.addTempAttr(fs.lastSelected)})),{getSelectedCells:()=>((e,t,o,n)=>{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))}},Vm=e=>{let t=[];return{bind:e=>{if(void 0===e)throw new Error("Event bind error: undefined handler");t.push(e)},unbind:e=>{t=z(t,(t=>t!==e))},trigger:(...o)=>{const n={};N(e,((e,t)=>{n[e]=o[t]})),N(t,(e=>{e(n)}))}}},$m=e=>({registry:K(e,(e=>({bind:e.bind,unbind:e.unbind}))),trigger:K(e,(e=>e.trigger))}),Um=e=>e.slice(0).sort(),Gm=(e,t)=>{const o=z(t,(t=>!D(e,t)));o.length>0&&(e=>{throw new Error("Unsupported keys for object: "+Um(e).join(", "))})(o)},Km=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 required 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=Um(e);W(t,((e,o)=>o{throw new Error("The field: "+e+" occurs more than once in the combined fields: ["+t.join(", ")+"].")}))})(t),n=>{const r=$(n);P(t,(e=>D(r,e)))||((e,t)=>{throw new Error("All required keys ("+Um(e).join(", ")+") were not specified. Specified keys were: "+Um(t).join(", ")+".")})(t,r),e(t,r);const s=z(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 ("+Um(e).join(", ")+") were not.")})(s,o.label),n}})(e,t,{validate:d,label:"function"}))(Gm,e),Ym=Km(["compare","extract","mutate","sink"]),Jm=Km(["element","start","stop","destroy"]),Qm=Km(["forceDrop","drop","move","delayDrop"]),Xm=()=>{const e=(()=>{const e=$m({move:Vm(["info"])});return{onEvent:f,reset:f,events:e.registry}})(),t=(()=>{let e=C.none();const t=$m({move:Vm(["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}},Zm=e=>{const t=e.replace(/\./g,"-");return{resolve:e=>t+"-"+e}},ed=Zm("ephox-dragster").resolve;var td=Ym({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:ed("blocker"),...e},o=xe.fromTag("div");return ge(o,"role","presentation"),Bt(o,{position:"fixed",left:"0px",top:"0px",width:"100%",height:"100%"}),zm(o,ed("blocker")),zm(o,t.layerClass),{element:g(o),destroy:()=>{$e(o)}}})(t),n=Im(o.element(),"mousedown",e.forceDrop),r=Im(o.element(),"mouseup",e.drop),s=Im(o.element(),"mousemove",e.move),l=Im(o.element(),"mouseout",e.delayDrop);return Jm({element:o.element,start:e=>{Ie(e,o.element())},stop:()=>{$e(o.element())},destroy:()=>{o.destroy(),r.unbind(),s.unbind(),l.unbind(),n.unbind()}})},mutate:(e,t)=>{e.mutate(t.left,t.top)}});const od=Zm("ephox-snooker").resolve,nd=od("resizer-bar"),rd=od("resizer-rows"),sd=od("resizer-cols"),ld=e=>{const t=dt(e.parent(),"."+nd);N(t,$e)},ad=(e,t,o)=>{const n=e.origin();N(t,(t=>{t.each((t=>{const r=o(n,t);zm(r,nd),Ie(e.parent(),r)}))}))},cd=(e,t,o,n,r)=>{const s=yn(o),l=t.isResizable,a=n.length>0?zn.positions(n,o):[],c=a.length>0?((e,t)=>j(e.all,((e,o)=>t(e.element)?[o]:[])))(e,l):[];((e,t,o,n)=>{ad(e,t,((e,t)=>{const r=((e,t,o,n,r)=>{const s=xe.fromTag("div");return Bt(s,{position:"absolute",left:t+"px",top:o-3.5+"px",height:"7px",width:n+"px"}),he(s,{"data-row":e,role:"presentation"}),s})(t.row,o.left-e.left,t.y-e.top,n);return zm(r,rd),r}))})(t,z(a,((e,t)=>O(c,(e=>t===e)))),s,Mo(o));const i=r.length>0?Ln.positions(r,o):[],m=i.length>0?((e,t)=>{const o=[];return k(e.grid.columns,(n=>{an(e,n).map((e=>e.element)).forall(t)&&o.push(n)})),z(o,(o=>{const n=nn(e,(e=>e.column===o));return P(n,(e=>t(e.element)))}))})(e,l):[];((e,t,o,n)=>{ad(e,t,((e,t)=>{const r=((e,t,o,n,r)=>{const s=xe.fromTag("div");return Bt(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 zm(r,sd),r}))})(t,z(i,((e,t)=>O(m,(e=>t===e)))),s,pn(o))},id=(e,t)=>{if(ld(e),e.isResizable(t)){const o=Zo(t),n=dn(o),r=cn(o);cd(o,e,t,n,r)}},md=(e,t)=>{const o=dt(e.parent(),"."+nd);N(o,t)},dd=e=>{md(e,(e=>{Nt(e,"display","none")}))},ud=e=>{md(e,(e=>{Nt(e,"display","block")}))},fd=od("resizer-bar-dragging"),gd=e=>{const t=(()=>{const e=$m({drag:Vm(["xDelta","yDelta","target"])});let t=C.none();const o=(()=>{const e=$m({drag:Vm(["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=$m({start:Vm([]),stop:Vm([])}),s=Xm(),l=()=>{m.stop(),s.isOn()&&(s.off(),r.trigger.stop())},c=((e,t)=>{let o=null;const n=()=>{a(o)||(clearTimeout(o),o=null)};return{cancel:n,throttle:(...t)=>{n(),o=setTimeout((()=>{o=null,e.apply(null,t)}),200)}}})(l);s.events.move.bind((o=>{t.mutate(e,o.info)}));const i=e=>(...t)=>{n&&e.apply(null,t)},m=t.sink(Qm({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:td,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=It(e.target,"top");Nt(e.target,"top",o+e.yDelta+"px")})),r(e.target,"data-column").each((t=>{const o=It(e.target,"left");Nt(e.target,"left",o+e.xDelta+"px")}))}));const s=(e,t)=>It(e,t)-Mt(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");be(t,"data-initial-top"),d.trigger.adjustHeight(o,n,parseInt(e,10))})),r(t,"data-column").each((e=>{const n=s(t,"left");be(t,"data-initial-left"),d.trigger.adjustWidth(o,n,parseInt(e,10))})),id(e,o)}))}))}));const l=(n,r)=>{d.trigger.startAdjust(),t.assign(n),ge(n,"data-initial-"+r,It(n,r)),zm(n,fd),Nt(n,"opacity","0.2"),o.go(e.parent())},c=Im(e.parent(),"mousedown",(e=>{var t;t=e.target,Am(t,rd)&&l(e.target,"top"),(e=>Am(e,sd))(e.target)&&l(e.target,"left")})),i=t=>Re(t,e.view()),m=Im(e.view(),"mouseover",(t=>{var r;(r=t.target,bt(r,"table",i).filter(Lr)).fold((()=>{lt(t.target)&&ld(e)}),(t=>{o.isActive()&&(n=C.some(t),id(e,t))}))})),d=$m({adjustHeight:Vm(["table","delta","row"]),adjustWidth:Vm(["table","delta","column"]),startAdjust:Vm([])});return{destroy:()=>{c.unbind(),m.unbind(),o.destroy(),ld(e)},refresh:t=>{id(e,t)},on:o.on,off:o.off,hideBars:w(dd,e),showBars:w(ud,e),events:d.registry}},hd=(e,t,o)=>{const n=zn,r=Ln,s=gd(e),l=$m({beforeResize:Vm(["table","type"]),afterResize:Vm(["table","type"]),startDrag:Vm([])});return s.events.adjustHeight.bind((e=>{const t=e.table;l.trigger.beforeResize(t,"row");((e,t,o,n)=>{const r=Zo(e),s=((e,t,o)=>lr(e,t,o,Yn,(e=>e.getOrThunk(Ht))))(r,e,n),l=E(s,((e,n)=>o===n?Math.max(t+e,Ht()):e)),a=Wl(r,l),c=((e,t)=>E(e.all,((e,o)=>({element:e.element,height:t[o]}))))(r,l);N(c,(e=>{qn(e.element,e.height)})),N(a,(e=>{qn(e.element,e.height)}));const i=A(l,((e,t)=>e+t),0);qn(e,i)})(t,n.delta(e.delta,t),e.row,n),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);_l(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}},pd=e=>m(e)&&"TABLE"===e.nodeName,wd="bar-",bd=e=>"false"!==pe(e,"data-mce-resize"),vd=e=>{const t=tm(),o=tm(),n=tm();let r,s;const l=t=>cc(e,t),a=()=>Xa(e)?As():zs();return e.on("init",(()=>{const r=((e,t)=>e.inline?((e,t,o)=>({parent:g(t),view:g(e),origin:g(bn(0,0)),isResizable:o}))(xe.fromDom(e.getBody()),(()=>{const e=xe.fromTag("div");return Bt(e,{position:"static",height:"0",width:"0",padding:"0",margin:"0",border:"0"}),Ie(at(xe.fromDom(document)),e),e})(),t):((e,t)=>{const o=me(e)?(e=>xe.fromDom(Ee(e).dom.documentElement))(e):e;return{parent:g(o),view:g(e),origin:g(bn(0,0)),isResizable:t}})(xe.fromDom(e.getDoc()),t))(e,bd);if(n.set(r),(e=>{const t=e.options.get("object_resizing");return D(t.split(","),"table")})(e)&&rc(e)){const n=a(),s=hd(r,n,l);s.on(),s.events.startDrag.bind((o=>{t.set(e.selection.getRng())})),s.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,Ir(o),Fr(o),wd+t.type)})),s.events.afterResize.bind((o=>{const n=o.table,r=n.dom;jr(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,Ir(r),Fr(r),wd+o.type),e.undoManager.add()})),o.set(s)}})),e.on("ObjectResizeStart",(t=>{const o=t.target;if(pd(o)){const n=xe.fromDom(o);N(e.dom.select(".mce-clonedresizable"),(t=>{e.dom.addClass(t,"mce-"+Qa(e)+"-columns")})),!Sc(n)&&oc(e)?Oc(n):!Cc(n)&&tc(e)&&Dc(n),Tc(n)&&Tt(t.origin,wd)&&Dc(n),r=t.width,s=nc(e)?"":((e,t)=>{const o=e.dom.getStyle(t,"width")||e.dom.getAttrib(t,"width");return C.from(o).filter(Ot)})(e,o).getOr("")}})),e.on("ObjectResized",(t=>{const o=t.target;if(pd(o)){const n=xe.fromDom(o),c=t.origin;Tt(c,"corner-")&&((t,o,n)=>{const c=Rt(o,"e");if(""===s&&Dc(t),n!==r&&""!==s){Nt(t,"width",s);const o=a(),i=l(t),m=Xa(e)||c?(e=>Ls(e).columns)(t)-1:0;_l(t,n-r,m,o,i)}else if((e=>/^(\d+(\.\d+)?)%$/.test(e))(s)){const e=parseFloat(s.replace("%",""));Nt(t,"width",n*e/r+"%")}(e=>/^(\d+(\.\d+)?)px$/.test(e))(s)&&(e=>{const t=Zo(e);ln(t)||N(Ut(e),(e=>{const t=zt(e,"width");Nt(e,"width",t),be(e,"width")}))})(t)})(n,c,t.width),jr(n),Ha(e,n.dom,qa)}})),e.on("SwitchMode",(()=>{o.on((t=>{e.mode.isReadOnly()?t.hideBars():t.showBars()}))})),e.on("dragstart dragend",(e=>{o.on((t=>{"dragstart"===e.type?(t.hideBars(),t.off()):(t.on(),t.showBars())}))})),e.on("remove",(()=>{o.on((e=>{e.destroy()})),n.on((t=>{((e,t)=>{e.inline&&$e(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()))}}},yd=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})})(e);const t=vd(e),o=qm(e,t),n=ic(e,t,o);return Gc(e,n),((e,t)=>{const o=_r(e),n=t=>ws(Pr(e)).bind((n=>Kt(n,o).map((o=>{const r=gs(bs(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),vs(e,n),{getSelectedCells:o.getSelectedCells,clearSelectedCells:o.clearSelectedCells}};e.add("dom",(e=>({table:yd(e)})))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/advlist/plugin.min.js b/public/resource/tinymce/plugins/advlist/plugin.min.js new file mode 100644 index 0000000..9916936 --- /dev/null +++ b/public/resource/tinymce/plugins/advlist/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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);var o=tinymce.util.Tools.resolve("tinymce.util.Tools");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 i(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=>i(e)&&t.test(e.nodeName),d=u(/^(OL|UL|DL)$/),g=u(/^(TH|TD)$/),c=t=>l(t)||"default"===t?"":t,h=(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,n))})(t,r.parents))),m=(t,s,r,n,l,i)=>{i.length>1?((t,s,r,n,l,i)=>{t.ui.registry.addSplitButton(s,{tooltip:r,icon:"OL"===l?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:t=>{t(o.map(i,(t=>{const e="OL"===l?"num":"bull",s="disc"===t||"decimal"===t?"default":t,r=c(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 a.from(s)})(t);return s.map((t=>e===t)).getOr(!1)},onSetup:h(t,l)})})(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:h(t,l),onAction:()=>t.queryCommandState(n)||""===i?t.execCommand(n):e(t,l,i)})})(t,s,r,n,l,c(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=>{m(t,"numlist","Numbered list","InsertOrderedList","OL",r(t)),m(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 Advanced List plugin.")}))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/anchor/plugin.min.js b/public/resource/tinymce/plugins/anchor/plugin.min.js new file mode 100644 index 0000000..e54d62f --- /dev/null +++ b/public/resource/tinymce/plugins/anchor/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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=("allow_html_in_named_anchor",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;o{(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=>e.selection.selectorChangedWithUnbind("a:not([href])",t.setActive).unbind}),e.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:t})})(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/public/resource/tinymce/plugins/autolink/plugin.min.js b/public/resource/tinymce/plugins/autolink/plugin.min.js new file mode 100644 index 0000000..672f45d --- /dev/null +++ b/public/resource/tinymce/plugins/autolink/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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=("string",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=(void 0,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]"))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),h=null!==(o=i.getParent(p,i.isBlock))&&void 0!==o?o:i.getRoot(),w=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}),h);if(!w)return null;let v=w.container;const _=k.backwards(w.container,w.offset,((e,t)=>{v=e;const n=g(e.data,t,f);return-1===n?n:n+1}),h),A=i.createRng();_?A.setStart(_.container,_.offset):A.setStart(v,0),A.setEnd(w.container,w.offset);const C=A.toString().replace(/\uFEFF/g,"").match(s);if(C){let t=C[0];return $="www.",(b=t).length>=$.length&&b.substr(0,0+$.length)===$?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/public/resource/tinymce/plugins/autoresize/plugin.min.js b/public/resource/tinymce/plugins/autoresize/plugin.min.js new file mode 100644 index 0000000..8f7a19c --- /dev/null +++ b/public/resource/tinymce/plugins/autoresize/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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),s=o("min_height"),i=o("max_height"),n=o("autoresize_overflow_padding"),r=o("autoresize_bottom_margin"),l=(e,t)=>{const o=e.getBody();o&&(o.style.overflowY=t?"":"hidden",t||(o.scrollTop=0))},g=(e,t,o,s)=>{var i;const n=parseInt(null!==(i=e.getStyle(t,o,s))&&void 0!==i?i:"",10);return isNaN(n)?0:n},a=(e,o,r,c)=>{var d;const f=e.dom,u=e.getDoc();if(!u)return;if((e=>e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen())(e))return void l(e,!0);const m=u.documentElement,h=c?c():n(e),p=null!==(d=s(e))&&void 0!==d?d:e.getElement().offsetHeight;let y=p;const S=g(f,m,"margin-top",!0),v=g(f,m,"margin-bottom",!0);let C=m.offsetHeight+S+v+h;C<0&&(C=0);const b=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;C+b>p&&(y=C+b);const w=i(e);if(w&&y>w?(y=w,l(e,!0)):l(e,!1),y!==o.get()){const s=y-o.get();if(f.setStyle(e.getContainer(),"height",y+"px"),o.set(y),(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())&&s<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=(e=>{let t=0;return{get:()=>t,set:e=>{t=e}}})();((e,t)=>{e.addCommand("mceAutoResize",(()=>{a(e,t)}))})(e,o),((e,o)=>{let s,i,l=()=>r(e);e.on("init",(i=>{s=0;const r=n(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,i,l),s+=1})),e.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",(t=>{if(1===s)i=e.getContainer().offsetHeight,a(e,o,t,l),s+=1;else if(2===s){const t=i0):l,s+=1}else a(e,o,t,l)}))})(e,o)}}))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/autosave/plugin.min.js b/public/resource/tinymce/plugins/autosave/plugin.min.js new file mode 100644 index 0000000..74dbd66 --- /dev/null +++ b/public/resource/tinymce/plugins/autosave/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=("string",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=(void 0,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)},g=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))},y=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=>{e.setEnabled(f(t));const r=()=>e.setEnabled(f(t));return t.on("StoreDraft RestoreDraft RemoveDraft",r),()=>t.off("StoreDraft RestoreDraft RemoveDraft",r)};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,(()=>{g(t)}),e)})(t);const e=()=>{(t=>{t.undoManager.transact((()=>{y(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())&&y(t)})),(t=>({hasDraft:()=>f(t),storeDraft:()=>g(t),restoreDraft:()=>y(t),removeDraft:e=>p(t,e),isEmpty:e=>v(t,e)}))(t))))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/charmap/plugin.min.js b/public/resource/tinymce/plugins/charmap/plugin.min.js new file mode 100644 index 0000000..50a48fa --- /dev/null +++ b/public/resource/tinymce/plugins/charmap/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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=("array",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=(!1,()=>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},w=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}}},b=(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,t)=>{for(let t=0,i=e.length;t!!b(k(e).toLowerCase(),r)||b(t.toLowerCase(),r)||b(t.toLowerCase().replace(/\s+/g,""),r))((n=e[t])[0],n[1],a)&&r.push(n);var n})(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?v(f):v("All"),o=((e,t)=>{let r=null;const a=()=>{n(r)||(clearTimeout(r),r=null)};return{cancel:a,throttle:(...t)=>{a(),r=setTimeout((()=>{r=null,e.apply(null,t)}),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)};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=w(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}),e.ui.registry.addMenuItem("charmap",{icon:"insert-character",text:"Special character...",onAction:t})})(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:()=>w(e),insertChar:r=>{t(e,r)}}))(e)}))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/code/plugin.min.js b/public/resource/tinymce/plugins/code/plugin.min.js new file mode 100644 index 0000000..34e553b --- /dev/null +++ b/public/resource/tinymce/plugins/code/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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/public/resource/tinymce/plugins/codesample/plugin.min.js b/public/resource/tinymce/plugins/codesample/plugin.min.js new file mode 100644 index 0000000..4329d5e --- /dev/null +++ b/public/resource/tinymce/plugins/codesample/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>!(e=>null==e)(e);class n{constructor(e,t){this.tag=e,this.value=t}static some(e){return new n(!0,e)}static none(){return n.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?n.some(e(this.value)):n.none()}bind(e){return this.tag?e(this.value):n.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:n.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)?n.some(e):n.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()"}}n.singletonNone=new n(!1);var a=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils");const s="undefined"!=typeof window?window:Function("return this;")(),r=function(e,t,n){const a=window.Prism;window.Prism={manual:!0};var s=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 s.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)}}}})}(s),s.languages.c=s.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|[?:~]|[-+*/%&|^!=<>]=?/}),s.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),s.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},s.languages.c.string],char:s.languages.c.char,comment:s.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:s.languages.c}}}}),s.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 s.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"])}(s),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}(s),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,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"))}(s),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}}),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:/\./}}})}(s),s.languages.javascript=s.languages.extend("clike",{"class-name":[s.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}|\?\?=?|\?\.?|[~:]/}),s.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,s.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:s.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:s.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:s.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:s.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:s.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),s.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:s.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"}}),s.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),s.languages.markup&&(s.languages.markup.tag.addInlined("script","javascript"),s.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")),s.languages.js=s.languages.javascript,s.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"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},s.languages.markup.tag.inside["attr-value"].inside.entity=s.languages.markup.entity,s.languages.markup.doctype.inside["internal-subset"].inside=s.languages.markup,s.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(s.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:s.languages[t]},n.cdata=/^$/i;var a={"included-cdata":{pattern://i,inside:n}};a["language-"+t]={pattern:/[\s\S]+/,inside:s.languages[t]};var r={};r[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:a},s.languages.insertBefore("markup","cdata",r)}}),Object.defineProperty(s.languages.markup.tag,"addAttribute",{value:function(e,t){s.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:[t,"language-"+t],inside:s.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),s.languages.html=s.languages.markup,s.languages.mathml=s.languages.markup,s.languages.svg=s.languages.markup,s.languages.xml=s.languages.extend("markup",{}),s.languages.ssml=s.languages.xml,s.languages.atom=s.languages.xml,s.languages.rss=s.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")}))}(s),s.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:/[{}[\];(),.:]/},s.languages.python["string-interpolation"].inside.interpolation.inside.rest=s.languages.python,s.languages.py=s.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}(s),window.Prism=a,s}(),i=e=>t=>t.options.get(e),o=i("codesample_languages"),l=i("codesample_global_prismjs"),u=e=>s.Prism&&l(e)?s.Prism:r,c=e=>t(e)&&"PRE"===e.nodeName&&-1!==e.className.indexOf("language-"),d=e=>{const t=e.selection?e.selection.getNode():null;return c(t)?n.some(t):n.none()},g=e=>{const t=(e=>o(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),s=(r=t,((e,t)=>0""),(e=>e.value));var r;const i=((e,t)=>d(e).fold((()=>t),(e=>{const n=e.className.match(/language-(\w+)/);return n?n[1]:t})))(e,s),l=(e=>d(e).bind((e=>n.from(e.textContent))).getOr(""))(e);e.windowManager.open({title:"Insert/Edit Code Sample",size:"large",body:{type:"panel",items:[{type:"selectbox",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:l},onSubmit:t=>{const n=t.getData();((e,t,n)=>{const s=e.dom;e.undoManager.transact((()=>{const r=d(e);return n=a.DOM.encode(n),r.fold((()=>{e.insertContent('
    '+n+"
    ");const a=s.select("#__new")[0];s.setAttrib(a,"id",null),e.selection.select(a)}),(a=>{s.setAttrib(a,"class","language-"+t),a.innerHTML=n,u(e).highlightElement(a),e.selection.select(a)}))}))})(e,n.language,n.code),t.close()}})},p=(b=/^\s+|\s+$/g,e=>e.replace(b,""));var b,h=tinymce.util.Tools.resolve("tinymce.util.Tools");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);h.each(h.grep(a,c),(e=>{const t=e.textContent;let a;for(n.setAttrib(e,"class",p(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=h.grep(t.select("pre"),(e=>c(e)&&"true"!==t.getAttrib(e,"data-mce-highlighted")));n.length&&e.undoManager.transact((()=>{h.each(n,(n=>{var a;h.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:""),u(e).highlightElement(n),t.setAttrib(n,"data-mce-highlighted",!0),n.className=p(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:t=>{const n=()=>{t.setActive((e=>{const t=e.selection.getStart();return e.dom.is(t,'pre[class*="language-"]')})(e))};return e.on("NodeChange",n),()=>e.off("NodeChange",n)}}),e.ui.registry.addMenuItem("codesample",{text:"Code sample...",icon:"code-sample",onAction:t})})(e),(e=>{e.addCommand("codesample",(()=>{const t=e.selection.getNode();e.selection.isCollapsed()||c(t)?g(e):e.formatter.toggle("code")}))})(e),e.on("dblclick",(t=>{c(t.target)&&g(e)}))}))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/directionality/plugin.min.js b/public/resource/tinymce/plugins/directionality/plugin.min.js new file mode 100644 index 0000000..ee3a450 --- /dev/null +++ b/public/resource/tinymce/plugins/directionality/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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=(!1,()=>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(9),p=m(11),y=(t,e)=>{t.dom.removeAttribute(e)},w=i(Element.prototype.attachShadow)&&i(Node.prototype.getRootNode)?t=>d(t.dom.getRootNode()):t=>v(t)?t:d(t.dom.ownerDocument),N=t=>d(t.dom.host),b=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=w(t);return p(o=e)&&n(o.dom.host)?a.some(e):a.none();var o})(d(e)).fold((()=>o.body.contains(e)),(r=b,i=N,t=>r(i(t))));var r,i},S=t=>"rtl"===((t,e)=>{const o=t.dom,r=window.getComputedStyle(o).getPropertyValue(e);return""!==r||b(t)?r:((t,e)=>(t=>void 0!==t.style&&i(t.style.getPropertyValue))(t)?t.style.getPropertyValue(e):"")(o,e)})(t,"direction")?"rtl":"ltr",A=(t,e)=>((t,o)=>((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),T=("li",t=>g(t)&&"li"===t.dom.nodeName.toLowerCase());const C=(t,e)=>{const n=t.selection.getSelectedBlocks();n.length>0&&(u(n,(t=>{const n=d(t),c=T(n),m=((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})(n,c);var f;(f=m,(t=>a.from(t.dom.parentNode).map(d))(f).filter(g)).each((t=>{if(S(t)!==e?((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)})(m,"dir",e):S(m)!==e&&y(m,"dir"),c){const t=A(m,"li[dir]");u(t,(t=>y(t,"dir")))}}))})),t.nodeChanged())},D=(t,e)=>o=>{const r=t=>{const r=d(t.element);o.setActive(S(r)===e)};return t.on("NodeChange",r),()=>t.off("NodeChange",r)};t.add("directionality",(t=>{(t=>{t.addCommand("mceDirectionLTR",(()=>{C(t,"ltr")})),t.addCommand("mceDirectionRTL",(()=>{C(t,"rtl")}))})(t),(t=>{t.ui.registry.addToggleButton("ltr",{tooltip:"Left to right",icon:"ltr",onAction:()=>t.execCommand("mceDirectionLTR"),onSetup:D(t,"ltr")}),t.ui.registry.addToggleButton("rtl",{tooltip:"Right to left",icon:"rtl",onAction:()=>t.execCommand("mceDirectionRTL"),onSetup:D(t,"rtl")})})(t)}))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/emoticons/js/emojiimages.js b/public/resource/tinymce/plugins/emoticons/js/emojiimages.js new file mode 100644 index 0000000..6fcec71 --- /dev/null +++ b/public/resource/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/public/resource/tinymce/plugins/emoticons/js/emojiimages.min.js b/public/resource/tinymce/plugins/emoticons/js/emojiimages.min.js new file mode 100644 index 0000000..37f3bcf --- /dev/null +++ b/public/resource/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/public/resource/tinymce/plugins/emoticons/js/emojis.js b/public/resource/tinymce/plugins/emoticons/js/emojis.js new file mode 100644 index 0000000..88455e9 --- /dev/null +++ b/public/resource/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/public/resource/tinymce/plugins/emoticons/js/emojis.min.js b/public/resource/tinymce/plugins/emoticons/js/emojis.min.js new file mode 100644 index 0000000..5a1c491 --- /dev/null +++ b/public/resource/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/public/resource/tinymce/plugins/emoticons/plugin.min.js b/public/resource/tinymce/plugins/emoticons/plugin.min.js new file mode 100644 index 0000000..af3e1d7 --- /dev/null +++ b/public/resource/tinymce/plugins/emoticons/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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),h=(d=(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)}},v=(t,e,o=0,s)=>{const r=t.indexOf(e,o);return-1!==r&&(!!n(s)||r+e.length<=s)};var y=tinymce.util.Tools.resolve("tinymce.Resource");const f=t=>e=>e.options.get(t),b=f("emoticons_database"),w=f("emoticons_database_url"),_=f("emoticons_database_id"),j=f("emoticons_append"),C=f("emoticons_images_url"),k="All",A={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)=>m(t,e)?t[e]:e,x=t=>{const e=j(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},L=(t,e)=>v(t.title.toLowerCase(),e)||((t,o)=>{for(let o=0,s=t.length;o{const n=[],s=e.toLowerCase(),a=o.fold((()=>r),(t=>e=>e>=t));for(let o=0;o{const n={pattern:"",results:T(e.listAll(),"",a.some(300))},s=l(k),r=((t,e)=>{let n=null;const s=()=>{o(n)||(clearTimeout(n),n=null)};return{cancel:s,throttle:(...e)=>{s(),n=setTimeout((()=>{n=null,t.apply(null,e)}),200)}}})((t=>{(t=>{const o=t.getData(),n=s.get(),r=e.listCategory(n),i=T(r,o.pattern,n===k?a.some(300):a.none());t.setData({results:i})})(t)})),c={label:"Search",type:"input",name:D},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}]}),m=t.windowManager.open(g());m.focus(D),e.hasLoaded()||(m.block("Loading emojis..."),e.waitForLoad().then((()=>{m.redial(g()),r.throttle(m),m.focus(D),m.unblock()})).catch((t=>{m.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:[]}}),m.focus(D),m.unblock()})))};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://twemoji.maxcdn.com/v/13.0.1/72x72/"})})(t,e);const o=((t,e,o)=>{const n=p(),s=p(),r=C(t),i=t=>{return o="=o.length&&e.substr(0,0+o.length)===o?t.char.replace(/src="([^"]+)"/,((t,e)=>`src="${r}${e}"`)):t.char;var e,o};t.on("init",(()=>{y.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(A,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)})(h(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:()=>[k].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===k?l():n.get().bind((e=>a.from(e[t]))).getOr([])}})(t,w(t),_(t));((t,e)=>{t.addCommand("mceEmoticons",(()=>E(t,e)))})(t,o),(t=>{const e=()=>t.execCommand("mceEmoticons");t.ui.registry.addButton("emoticons",{tooltip:"Emojis",icon:"emoji",onAction:e}),t.ui.registry.addMenuItem("emoticons",{text:"Emojis...",icon:"emoji",onAction:e})})(t),((t,e)=>{t.ui.registry.addAutocompleter("emoticons",{trigger:":",columns:"auto",minChars:2,fetch:(t,o)=>e.waitForLoad().then((()=>{const n=e.listAll();return T(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,e)=>{for(let e=0,n=t.length;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("array"),l=o(null),a=r("boolean"),c=o(void 0),u=e=>!(e=>null==e)(e),d=r("function"),m=r("number"),h=()=>{},g=e=>()=>e;function p(e,...t){return(...n)=>{const r=t.concat(n);return e.apply(null,r)}}const f=g(!1),v=g(!0);class w{constructor(e,t){this.tag=e,this.value=t}static some(e){return new w(!0,e)}static none(){return w.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?w.some(e(this.value)):w.none()}bind(e){return this.tag?e(this.value):w.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:w.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 u(e)?w.some(e):w.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()"}}w.singletonNone=new w(!1);const y=t=>{const n=e(w.none()),r=()=>n.get().each(t);return{clear:()=>{r(),n.set(w.none())},isSet:()=>n.get().isSome(),get:()=>n.get(),set:e=>{r(),n.set(w.some(e))}}},b=()=>y((e=>e.unbind())),S=Array.prototype.push,x=(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 o=e.indexOf(t,n);return-1!==o&&(!!c(r)||o+t.length<=r)},C=e=>void 0!==e.style&&d(e.style.getPropertyValue),A=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},R=A;"undefined"!=typeof window?window:Function("return this;")();const L=e=>t=>(e=>e.dom.nodeType)(t)===e,M=L(1),N=L(3),P=L(9),D=L(11),W=(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")}},q=e=>R(e.dom.ownerDocument),H=e=>x(e.dom.childNodes,R),I=d(Element.prototype.attachShadow)&&d(Node.prototype.getRootNode),B=g(I),V=I?e=>R(e.dom.getRootNode()):e=>P(e)?e:q(e),_=e=>{const t=V(e);return D(n=t)&&u(n.dom.host)?w.some(t):w.none();var n},j=e=>R(e.dom.host),z=e=>{const t=N(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;const n=t.ownerDocument;return _(R(t)).fold((()=>n.body.contains(t)),(r=z,o=j,e=>r(o(e))));var r,o},$=(e,t)=>{const n=e.dom.getAttribute(t);return null===n?void 0:n},U=(e,t)=>{e.dom.removeAttribute(t)},K=(e,t)=>{const n=e.dom;((e,t)=>{const n=T(e);for(let r=0,o=n.length;r{((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);C(e)&&e.style.setProperty(t,n)})(n,t,e)}))},X=e=>{const t=R((e=>{if(B()&&u(e.target)){const t=R(e.target);if(M(t)&&u(t.dom.shadowRoot)&&e.composed&&e.composedPath){const t=e.composedPath();if(t)return((e,t)=>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)},Y=(e,t,n,r)=>{e.dom.removeEventListener(t,n,r)},G=v,J=(e,t,n)=>((e,t,n,r)=>((e,t,n,r,o)=>{const s=((e,t)=>n=>{e(n)&&t(X(n))})(n,r);return e.dom.addEventListener(t,s,o),{unbind:p(Y,e,t,s,o)}})(e,t,n,r,!1))(e,t,G,n),Q=()=>Z(0,0),Z=(e,t)=>({major:e,minor:t}),ee={nu:Z,detect:(e,t)=>{const n=String(t).toLowerCase();return 0===e.length?Q():((e,t)=>{const n=((e,t)=>{for(let n=0;nNumber(t.replace(n,"$"+e));return Z(r(1),r(2))})(e,n)},unknown:Q},te=(e,t)=>{const n=String(t).toLowerCase();return O(e,(e=>e.search(n)))},ne=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,re=e=>t=>k(t,e),oe=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:e=>k(e,"edge/")&&k(e,"chrome")&&k(e,"safari")&&k(e,"applewebkit")},{name:"Chromium",brand:"Chromium",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,ne],search:e=>k(e,"chrome")&&!k(e,"chromeframe")},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:e=>k(e,"msie")||k(e,"trident")},{name:"Opera",versionRegexes:[ne,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:re("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:re("firefox")},{name:"Safari",versionRegexes:[ne,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:e=>(k(e,"safari")||k(e,"mobile/"))&&k(e,"applewebkit")}],se=[{name:"Windows",search:re("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:e=>k(e,"iphone")||k(e,"ipad"),versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:re("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"macOS",search:re("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:re("linux"),versionRegexes:[]},{name:"Solaris",search:re("sunos"),versionRegexes:[]},{name:"FreeBSD",search:re("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:re("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}],ie={browsers:g(oe),oses:g(se)},le="Edge",ae="Chromium",ce="Opera",ue="Firefox",de="Safari",me=e=>{const t=e.current,n=e.version,r=e=>()=>t===e;return{current:t,version:n,isEdge:r(le),isChromium:r(ae),isIE:r("IE"),isOpera:r(ce),isFirefox:r(ue),isSafari:r(de)}},he=()=>me({current:void 0,version:ee.unknown()}),ge=me,pe=(g(le),g(ae),g("IE"),g(ce),g(ue),g(de),"Windows"),fe="Android",ve="Linux",we="macOS",ye="Solaris",be="FreeBSD",Se="ChromeOS",xe=e=>{const t=e.current,n=e.version,r=e=>()=>t===e;return{current:t,version:n,isWindows:r(pe),isiOS:r("iOS"),isAndroid:r(fe),isMacOS:r(we),isLinux:r(ve),isSolaris:r(ye),isFreeBSD:r(be),isChromeOS:r(Se)}},Ee=()=>xe({current:void 0,version:ee.unknown()}),Fe=xe,Oe=(g(pe),g("iOS"),g(fe),g(ve),g(we),g(ye),g(be),g(Se),(e,t,n)=>{const r=ie.browsers(),o=ie.oses(),s=t.bind((e=>((e,t)=>((e,t)=>{for(let n=0;n{const n=t.brand.toLowerCase();return O(e,(e=>{var t;return n===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())})).map((e=>({current:e.name,version:ee.nu(parseInt(t.version,10),0)})))})))(r,e))).orThunk((()=>((e,t)=>te(e,t).map((e=>{const n=ee.detect(e.versionRegexes,t);return{current:e.name,version:n}})))(r,e))).fold(he,ge),i=((e,t)=>te(e,t).map((e=>{const n=ee.detect(e.versionRegexes,t);return{current:e.name,version:n}})))(o,e).fold(Ee,Fe),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:g(o),isiPhone:g(s),isTablet:g(a),isPhone:g(c),isTouch:g(l),isAndroid:e.isAndroid,isiOS:e.isiOS,isWebView:g(u),isDesktop:g(d)}})(i,s,e,n);return{browser:s,os:i,deviceType:l}}),Te=e=>window.matchMedia(e).matches;let ke=(e=>{let t,n=!1;return(...r)=>(n||(n=!0,t=e.apply(null,r)),t)})((()=>Oe(navigator.userAgent,w.from(navigator.userAgentData),Te)));const Ce=(e,t)=>({left:e,top:t,translate:(n,r)=>Ce(e+n,t+r)}),Ae=Ce,Re=e=>{const t=void 0===e?window:e;return ke().browser.isFirefox()?w.none():w.from(t.visualViewport)},Le=(e,t,n,r)=>({x:e,y:t,width:n,height:r,right:e+n,bottom:t+r}),Me=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 Ae(n,r)})(R(n));return Re(t).fold((()=>{const e=t.document.documentElement,n=e.clientWidth,o=e.clientHeight;return Le(r.left,r.top,n,o)}),(e=>Le(Math.max(e.pageLeft,r.left),Math.max(e.pageTop,r.top),e.width,e.height)))},Ne=(e,t,n)=>Re(n).map((n=>{const r=e=>t(X(e));return n.addEventListener(e,r),{unbind:()=>n.removeEventListener(e,r)}})).getOrThunk((()=>({unbind:h})));var Pe=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),De=tinymce.util.Tools.resolve("tinymce.Env");const We=(e,t)=>{e.dispatch("FullscreenStateChanged",{state:t}),e.dispatch("ResizeEditor")},qe=("fullscreen_native",e=>e.options.get("fullscreen_native"));const He=e=>{return e.dom===(void 0!==(t=q(e).dom).fullscreenElement?t.fullscreenElement:void 0!==t.msFullscreenElement?t.msFullscreenElement:void 0!==t.webkitFullscreenElement?t.webkitFullscreenElement:null);var t},Ie=(e,t,n)=>((e,t,n)=>F(((e,t)=>{const n=d(t)?t:f;let r=e.dom;const o=[];for(;null!==r.parentNode&&void 0!==r.parentNode;){const e=r.parentNode,t=R(e);if(o.push(t),!0===n(t))break;r=e}return o})(e,n),t))(e,(e=>W(e,t)),n),Be=(e,t)=>((e,n)=>{return F((e=>w.from(e.dom.parentNode).map(R))(r=e).map(H).map((e=>F(e,(e=>{return t=e,!(r.dom===t.dom);var t})))).getOr([]),(e=>W(e,t)));var r})(e),Ve="data-ephox-mobile-fullscreen-style",_e="position:absolute!important;",je="top:0!important;left:0!important;margin:0!important;padding:0!important;width:100%!important;height:100%!important;overflow:visible!important;",ze=De.os.isAndroid(),$e=e=>{const t=((e,t)=>{const n=e.dom,r=window.getComputedStyle(n).getPropertyValue(t);return""!==r||z(e)?r:((e,t)=>C(e)?e.style.getPropertyValue(t):"")(n,t)})(e,"background-color");return void 0!==t&&""!==t?"background-color:"+t+"!important":"background-color:rgb(255,255,255)!important;"},Ue=Pe.DOM,Ke=Re().fold((()=>({bind:h,unbind:h})),(e=>{const t=(()=>{const e=y(h);return{...e,on:t=>e.get().each(t)}})(),n=b(),r=b(),o=((e,t)=>{let n=null;return{cancel:()=>{l(n)||(clearTimeout(n),n=null)},throttle:(...t)=>{l(n)&&(n=setTimeout((()=>{n=null,e.apply(null,t)}),50))}}})((()=>{document.body.scrollTop=0,document.documentElement.scrollTop=0,window.requestAnimationFrame((()=>{t.on((t=>K(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(Ne("resize",o.throttle)),r.set(Ne("scroll",o.throttle))},unbind:()=>{t.on((()=>{n.clear(),r.clear()})),t.clear()}}})),Xe=(e,t)=>{const n=document.body,r=document.documentElement,o=e.getContainer(),l=R(o),c=(e=>{const t=R(e.getElement());return _(t).map(j).getOrThunk((()=>(e=>{const t=e.dom.body;if(null==t)throw new Error("Body is not available yet");return R(t)})(q(t))))})(e),u=t.get(),d=R(e.getBody()),h=De.deviceType.isTouch(),g=o.style,p=e.iframeElement,f=null==p?void 0:p.style,v=e=>{e(n,"tox-fullscreen"),e(r,"tox-fullscreen"),e(o,"tox-fullscreen"),_(l).map((e=>j(e).dom)).each((t=>{e(t,"tox-fullscreen"),e(t,"tox-shadowhost")}))},y=()=>{h&&(e=>{const t=((e,t)=>{const n=document;return 1!==(r=n).nodeType&&9!==r.nodeType&&11!==r.nodeType||0===r.childElementCount?[]:x(n.querySelectorAll(e),R);var r})("["+Ve+"]");E(t,(t=>{const n=$(t,Ve);n&&"no-styles"!==n?K(t,e.parseStyle(n)):U(t,"style"),U(t,Ve)}))})(e.dom),v(Ue.removeClass),Ke.unbind(),w.from(t.get()).each((e=>e.fullscreenChangeHandler.unbind()))};if(u)u.fullscreenChangeHandler.unbind(),qe(e)&&He(c)&&(e=>{const t=e.dom;t.exitFullscreen?t.exitFullscreen():t.msExitFullscreen?t.msExitFullscreen():t.webkitCancelFullScreen&&t.webkitCancelFullScreen()})(q(c)),f.width=u.iframeWidth,f.height=u.iframeHeight,g.width=u.containerWidth,g.height=u.containerHeight,g.top=u.containerTop,g.left=u.containerLeft,y(),b=u.scrollPos,window.scrollTo(b.x,b.y),t.set(null),We(e,!1),e.off("remove",y);else{const n=J(q(c),void 0!==document.fullscreenElement?"fullscreenchange":void 0!==document.msFullscreenElement?"MSFullscreenChange":void 0!==document.webkitFullscreenElement?"webkitfullscreenchange":"fullscreenchange",(n=>{qe(e)&&(He(c)||null===t.get()||Xe(e,t))})),r={scrollPos:Me(window),containerWidth:g.width,containerHeight:g.height,containerTop:g.top,containerLeft:g.left,iframeWidth:f.width,iframeHeight:f.height,fullscreenChangeHandler:n};h&&((e,t,n)=>{const r=t=>n=>{const r=$(n,"style"),o=void 0===r?"no-styles":r.trim();o!==t&&(((e,t,n)=>{((e,t,n)=>{if(!(s(n)||a(n)||m(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,Ve,o),K(n,e.parseStyle(t)))},o=Ie(t,"*"),l=(e=>{const t=[];for(let n=0,r=e.length;nBe(e,"*:not(.tox-silver-sink)")))),c=$e(n);E(l,r("display:none!important;")),E(o,r(_e+je+c)),r((!0===ze?"":_e)+je+c)(t)})(e.dom,l,d),f.width=f.height="100%",g.width=g.height="",v(Ue.addClass),Ke.bind(l),e.on("remove",y),t.set(r),qe(e)&&(e=>{const t=e.dom;t.requestFullscreen?t.requestFullscreen():t.msRequestFullscreen?t.msRequestFullscreen():t.webkitRequestFullScreen&&t.webkitRequestFullScreen()})(c),We(e,!0)}var b},Ye=(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",(()=>{Xe(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:Ye(e,t)}),e.ui.registry.addToggleButton("fullscreen",{tooltip:"Fullscreen",icon:"fullscreen",onAction:n,onSetup:Ye(e,t)})})(t,n),t.addShortcut("Meta+Shift+F","","mceFullScreen")),(e=>({isFullscreen:()=>null!==e.get()}))(n)}))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/help/plugin.min.js b/public/resource/tinymce/plugins/help/plugin.min.js new file mode 100644 index 0000000..7c330c7 --- /dev/null +++ b/public/resource/tinymce/plugins/help/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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(1e9*Math.random());return t++,e+"_"+a+t+String(n)},a=e=>t=>t.options.get(e),o=a("help_tabs"),i=a("forced_plugins"),r=("string",e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=a=e,(o=String).prototype.isPrototypeOf(n)||(null===(i=a.constructor)||void 0===i?void 0:i.name)===o.name)?"string":t;var n,a,o,i})(e));const s=(void 0,e=>undefined===e);const l=e=>"function"==typeof e,c=(!1,()=>false);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 null==e?u.none():u.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()"}}u.singletonNone=new u(!1);const m=Array.prototype.slice,h=Array.prototype.indexOf,p=(e,t)=>{const n=e.length,a=new Array(n);for(let o=0;o{const n=[];for(let a=0,o=e.length;a{const n=m.call(e,0);return n.sort(t),n},y=Object.keys,b=Object.hasOwnProperty,k=(e,t)=>b.call(e,t);var v=tinymce.util.Tools.resolve("tinymce.Env");const f=e=>{const t=v.os.isMacOS()||v.os.isiOS(),n=t?{alt:"⌥",ctrl:"⌃",shift:"⇧",meta:"⌘",access:"⌃⌥"}:{meta:"Ctrl ",access:"Shift + Alt "},a=e.split("+"),o=p(a,(e=>{const t=e.toLowerCase().trim();return k(n,t)?n[t]:e}));return t?o.join("").replace(/\s/,""):o.join("+")},w=[{shortcuts:["Meta + B"],action:"Bold"},{shortcuts:["Meta + I"],action:"Italic"},{shortcuts:["Meta + U"],action:"Underline"},{shortcuts:["Meta + A"],action:"Select all"},{shortcuts:["Meta + Y","Meta + Shift + Z"],action:"Redo"},{shortcuts:["Meta + Z"],action:"Undo"},{shortcuts:["Access + 1"],action:"Heading 1"},{shortcuts:["Access + 2"],action:"Heading 2"},{shortcuts:["Access + 3"],action:"Heading 3"},{shortcuts:["Access + 4"],action:"Heading 4"},{shortcuts:["Access + 5"],action:"Heading 5"},{shortcuts:["Access + 6"],action:"Heading 6"},{shortcuts:["Access + 7"],action:"Paragraph"},{shortcuts:["Access + 8"],action:"Div"},{shortcuts:["Access + 9"],action:"Address"},{shortcuts:["Alt + 0"],action:"Open help dialog"},{shortcuts:["Alt + F9"],action:"Focus to menubar"},{shortcuts:["Alt + F10"],action:"Focus to toolbar"},{shortcuts:["Alt + F11"],action:"Focus to element path"},{shortcuts:["Ctrl + F9"],action:"Focus to contextual toolbar"},{shortcuts:["Shift + Enter"],action:"Open popup menu for split buttons"},{shortcuts:["Meta + K"],action:"Insert link (if link plugin activated)"},{shortcuts:["Meta + S"],action:"Save (if save plugin activated)"},{shortcuts:["Meta + F"],action:"Find (if searchreplace plugin activated)"},{shortcuts:["Meta + Shift + F"],action:"Switch to or from fullscreen mode"}],A=()=>({name:"shortcuts",title:"Handy Shortcuts",items:[{type:"table",header:["Action","Shortcut"],cells:p(w,(e=>{const t=p(e.shortcuts,f).join(" or ");return[e.action,t]}))}]});var T=tinymce.util.Tools.resolve("tinymce.util.I18n");const x=p([{key:"advlist",name:"Advanced List"},{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:"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:"template",name:"Template"},{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:"advcode",name:"Advanced Code Editor",type:"premium"},{key:"advtable",name:"Advanced Tables",type:"premium"},{key:"advtemplate",name:"Advanced Templates",type:"premium",slug:"advanced-templates"},{key:"casechange",name:"Case Change",type:"premium"},{key:"checklist",name:"Checklist",type:"premium"},{key:"editimage",name:"Enhanced Image Editing",type:"premium"},{key:"footnotes",name:"Footnotes",type:"premium"},{key:"typography",name:"Advanced Typography",type:"premium",slug:"advanced-typography"},{key:"mediaembed",name:"Enhanced Media Embed",type:"premium",slug:"introduction-to-mediaembed"},{key:"export",name:"Export",type:"premium"},{key:"formatpainter",name:"Format Painter",type:"premium"},{key:"inlinecss",name:"Inline CSS",type:"premium",slug:"inline-css"},{key:"linkchecker",name:"Link Checker",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:"rtc",name:"Real-Time Collaboration",type:"premium",slug:"rtc-introduction"},{key:"tinymcespellchecker",name:"Spell Checker Pro",type:"premium",slug:"introduction-to-tiny-spellchecker"},{key:"autocorrect",name:"Spelling Autocorrect",type:"premium"},{key:"tableofcontents",name:"Table of Contents",type:"premium"},{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}))),C=e=>{const t=e=>`
    ${e.name}`,n=(e,n)=>{return(a=x,o=e=>e.key===n,((e,t,n)=>{for(let a=0,o=e.length;a((e,n)=>{const a=e.plugins[n].getMetadata;if(l(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/6/${e.slug}/`})}}));var a,o},a=e=>{const t=(e=>{const t=y(e.plugins),n=i(e);return s(n)?t:d(t,(e=>!(((e,t)=>h.call(e,t))(n,e)>-1)))})(e),a=g(p(t,(t=>n(e,t))),((e,t)=>e.name.localeCompare(t.name))),o=p(a,(e=>"
  • "+e.html+"
  • ")),r=o.length,l=o.join("");return"

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

      "+l+"
    "},o={type:"htmlpanel",presets:"document",html:[(e=>null==e?"":'
    '+a(e)+"
    ")(e),(()=>{const e=d(x,(({type:e})=>"premium"===e)),t=g(p(e,(e=>e.name)),((e,t)=>e.localeCompare(t))),n=p(t,(e=>`
  • ${e}
  • `)).join("");return'

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

    "})()].join("")};return{name:"plugins",title:"Plugins",items:[o]}};var M=tinymce.util.Tools.resolve("tinymce.EditorManager");const S=(e,t)=>()=>{const{tabs:a,names:i}=((e,t)=>{const a=A(),i={name:"keyboardnav",title:"Keyboard Navigation",items:[{type:"htmlpanel",presets:"document",html:"

    Editor UI keyboard navigation

    \n\n

    Activating keyboard navigation

    \n\n

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

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

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

    \n\n

    Moving between UI sections

    \n\n

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

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

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

    \n\n

    Moving within UI sections

    \n\n

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

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

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

    \n\n

    Executing buttons

    \n\n

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

    \n\n

    Opening, navigating and closing menus

    \n\n

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

    \n\n

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

    \n\n

    Context toolbars and menus

    \n\n

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

    \n\n

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

    \n\n

    Dialog navigation

    \n\n

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

    \n\n

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

    \n\n

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

    "}]},s=C(e),l=(()=>{var e,t;const n='TinyMCE '+(e=M.majorVersion,t=M.minorVersion,(0===e.indexOf("@")?"X.X.X":e+"."+t)+"");return{name:"versions",title:"Version",items:[{type:"htmlpanel",html:"

    "+T.translate(["You are using {0}",n])+"

    ",presets:"document"}]}})(),c={[a.name]:a,[i.name]:i,[s.name]:s,[l.name]:l,...t.get()};return u.from(o(e)).fold((()=>(e=>{const t=y(e),n=t.indexOf("versions");return-1!==n&&(t.splice(n,1),t.push("versions")),{tabs:e,names:t}})(c)),(e=>((e,t)=>{const a={},o=p(e,(e=>{var o;if(r(e))return k(t,e)&&(a[e]=t[e]),e;{const t=null!==(o=e.name)&&void 0!==o?o:n("tab-name");return a[t]=e,t}}));return{tabs:a,names:o}})(e,c)))})(e,t),s={type:"tabpanel",tabs:(e=>{const t=[],n=e=>{t.push(e)};for(let t=0;t{return k(t=a,n=e)?u.from(t[n]):u.none();var t,n})))};e.windowManager.open({title:"Help",size:"normal",body:s,buttons:[{type:"cancel",name:"close",text:"Close",primary:!0}],initialData:{}})};e.add("help",(e=>{const t=(e=>{let t={};return{get:()=>t,set:e=>{t=e}}})(),a=(e=>({addTab:t=>{var a;const o=null!==(a=t.name)&&void 0!==a?a:n("tab-name"),i=e.get();i[o]=t,e.set(i)}}))(t);(e=>{(0,e.options.register)("help_tabs",{processor:"array"})})(e);const o=S(e,t);return((e,t)=>{e.ui.registry.addButton("help",{icon:"help",tooltip:"Help",onAction:t}),e.ui.registry.addMenuItem("help",{text:"Help",icon:"help",shortcut:"Alt+0",onAction:t})})(e,o),((e,t)=>{e.addCommand("mceHelp",t)})(e,o),e.shortcuts.add("Alt+0","Open help dialog","mceHelp"),a}))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/image/plugin.min.js b/public/resource/tinymce/plugins/image/plugin.min.js new file mode 100644 index 0000000..ceb4826 --- /dev/null +++ b/public/resource/tinymce/plugins/image/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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=(null,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,x=e=>t=>t.options.get(e),S=x("image_dimensions"),N=x("image_advtab"),T=x("image_uploadtab"),O=x("image_prepend_url"),L=x("image_class_list"),E=x("image_description"),j=x("image_title"),M=x("image_caption"),R=x("image_list"),k=x("a11y_advanced_options"),z=x("automatic_uploads"),P=(e,t)=>Math.max(parseInt(e,10),parseInt(t,10)),B=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?B(e.style.marginLeft):"",V=e=>e.style.marginTop&&e.style.marginBottom&&e.style.marginTop===e.style.marginBottom?B(e.style.marginTop):"",K=e=>e.style.borderWidth?B(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]?B(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)){"alt",_(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,a)=>{const i={};var s;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")),(s=i,(e,t)=>{s[t]=e}),p),i})(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)){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||!S(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,a)=>{for(let a=0;ay(e,"items"))(i=e[a])?Ue(i.items,t):i.value===t?h.some(i):h.none();if(s.isSome())return s}var i;return h.none()})(e),xe=Ie,Se=(e,t)=>e.bind((e=>Ue(e,t))),Ne=e=>{const t=xe((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=E(e),u=j(e),p=S(e),b=M(e),v=k(e),y=z(e),f=h.some(O(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"}],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},Oe=e=>({title:"General",name:"general",items:Te(e)}),Le=Te,Ee=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)&&Se(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=Se(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,t)=>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)};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)})):(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=Se(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},Pe=e=>e.hasAdvTab||e.hasUploadUrl||e.hasUploadHandler?{type:"tabpanel",tabs:w([[Oe(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)},Be=(e,t,a)=>i=>{const s=fe(Ee(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.onload=a.onerror=null,a.parentNode&&a.parentNode.removeChild(a),t(e)};a.onload=()=>{const e={width:P(a.width,a.clientWidth),height:P(a.height,a.clientHeight)};i(Promise.resolve(e))},a.onerror=()=>{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=>{e.windowManager.alert(t)},$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:Se(e.imageList,e.image.src),prevAlt:e.image.alt,open:!0}))(a);return{title:"Insert/Edit Image",size:"normal",body:Pe(a),buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:Ee(a.image),onSubmit:Be(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))}};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))),e.selection.selectorChangedWithUnbind("img:not([data-mce-object]):not([data-mce-placeholder]),figure.image",t.setActive).unbind)}),e.ui.registry.addMenuItem("image",{icon:"image",text:"Image...",onAction:qe(e).open}),e.ui.registry.addContextMenu("image",{update:e=>re(e)||"IMG"===e.nodeName&&!H(e)?["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/public/resource/tinymce/plugins/importcss/plugin.min.js b/public/resource/tinymce/plugins/importcss/plugin.min.js new file mode 100644 index 0000000..3bd9ba5 --- /dev/null +++ b/public/resource/tinymce/plugins/importcss/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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=("function",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"),_=p("importcss_file_filter"),g=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),w=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=g(e);if(s){const r=v(e),o=r?e.documentBaseURI.toAbsolute(r):i.baseURL+"/skins/ui/"+s,n=i.baseURL+"/skins/content/";return t===o+"/content"+(e.inline?".inline":"")+".min.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?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(_(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),w(e),(e=>({convertSelectorToFormat:t=>S(e,t)}))(e))))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/insertdatetime/plugin.min.js b/public/resource/tinymce/plugins/insertdatetime/plugin.min.js new file mode 100644 index 0000000..b0dae30 --- /dev/null +++ b/public/resource/tinymce/plugins/insertdatetime/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),a=t("insertdatetime_dateformat"),r=t("insertdatetime_timeformat"),n=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)){const a=d(e,t);let r;r=/%[HMSIp]/.test(t)?d(e,"%Y-%m-%dT%H:%M"):d(e,"%Y-%m-%d");const n=e.dom.getParent(e.selection.getStart(),"time");n?((e,t,a,r)=>{const n=e.dom.create("time",{datetime:a},r);e.dom.replace(n,t),e.selection.select(n,!0),e.selection.collapse(!1)})(e,n,r,a):e.insertContent('")}else e.insertContent(d(e,t))};var p=tinymce.util.Tools.resolve("tinymce.util.Tools");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,r)=>{u(e,null!=r?r:a(e))})),e.addCommand("mceInsertTime",((t,a)=>{u(e,null!=a?a:r(e))}))})(e),(e=>{const t=n(e),a=(e=>{let t=e;return{get:()=>t,set:e=>{t=e}}})((e=>{const t=n(e);return t.length>0?t[0]:r(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)}});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)})))})})(e)}))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/link/plugin.min.js b/public/resource/tinymce/plugins/link/plugin.min.js new file mode 100644 index 0000000..f9639d4 --- /dev/null +++ b/public/resource/tinymce/plugins/link/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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"),a=(null,e=>null===e);const i=n("boolean"),s=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 s(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,f=Array.prototype.push,p=e=>{const t=[];for(let n=0,o=e.length;n{for(let n=0;ne.exists((e=>n(e,t))),y=e=>{const t=[],n=e=>{t.push(e)};for(let t=0;te?m.some(t):m.none(),b=e=>t=>t.options.get(e),_=b("link_assume_external_targets"),w=b("link_context_toolbar"),C=b("link_list"),O=b("link_default_target"),N=b("link_default_protocol"),A=b("link_target_list"),S=b("link_rel_list"),T=b("link_class_list"),E=b("link_title"),R=b("allow_unsafe_link_target"),P=b("link_quicklink");var L=tinymce.util.Tools.resolve("tinymce.util.Tools");const M=e=>o(e.value)?e.value:"",D=(e,t)=>{const n=[];return L.each(e,(e=>{const r=(e=>o(e.text)?e.text:o(e.title)?e.title:"")(e);if(void 0!==e.menu){const o=D(e.menu,t);n.push({text:r,items:o})}else{const o=t(e);n.push({text:r,value:o})}})),n},B=(e=M)=>t=>m.from(t).map((t=>D(t,e))),I=e=>B(M)(e),j=B,K=(e,t)=>n=>({name:e,type:"listbox",label:t,items:n}),U=M,q=Object.keys,F=Object.hasOwnProperty,V=(e,t)=>F.call(e,t);var $=tinymce.util.Tools.resolve("tinymce.dom.TreeWalker"),z=tinymce.util.Tools.resolve("tinymce.util.URI");const G=e=>s(e)&&"a"===e.nodeName.toLowerCase(),H=e=>G(e)&&!!Q(e),J=(e,t)=>{if(e.collapsed)return[];{const n=e.cloneContents(),o=n.firstChild,r=new $(o,n),l=[];let a=o;do{t(a)&&l.push(a)}while(a=r.next());return l}},W=e=>/^\w+:/i.test(e),Q=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:""},X=(e,t)=>{const n=["noopener"],o=e?e.split(/\s+/):[],r=e=>e.filter((e=>-1===L.inArray(n,e))),l=t?(e=>(e=r(e)).length>0?e.concat(n):n)(o):r(o);return l.length>0?(e=>L.trim(e.sort().join(" ")))(l):""},Y=(e,t)=>(t=t||te(e.selection.getRng())[0]||e.selection.getNode(),le(t)?m.from(e.dom.select("a[href]",t)[0]):m.from(e.dom.getParent(t,"a[href]"))),Z=(e,t)=>Y(e,t).isSome(),ee=(e,t)=>t.fold((()=>e.getContent({format:"text"})),(e=>e.innerText||e.textContent||"")).replace(/\uFEFF/g,""),te=e=>J(e,H),ne=e=>L.grep(e,H),oe=e=>ne(e).length>0,re=e=>{const t=e.schema.getTextInlineElements();if(Y(e).exists((e=>e.hasAttribute("data-mce-block"))))return!1;const n=e.selection.getRng();return!!n.collapsed||0===J(n,(e=>1===e.nodeType&&!G(e)&&!V(t,e.nodeName.toLowerCase()))).length},le=e=>s(e)&&"FIGURE"===e.nodeName&&/\bimage\b/i.test(e.className),ae=(e,t,n)=>{const o=e.selection.getNode(),r=Y(e,o),l=((e,t)=>{const n={...t};if(0===S(e).length&&!R(e)){const e=X(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||W(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));e.undoManager.transact((()=>{n.href===t.href&&t.attach(),r.fold((()=>{((e,t,n,o)=>{const r=e.dom;le(t)?ge(r,t,o):n.fold((()=>{e.execCommand("mceInsertLink",!1,o)}),(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=>{V(t,"innerText")?t.innerText=e:t.textContent=e})),e.dom.setAttribs(t,o),e.selection.select(t)})(e,t,n.text,l)}))}))},ie=e=>{const{class:t,href:n,rel:o,target:r,text:l,title:i}=e;return((e,t)=>{const n={};var o;return((e,t,n,o)=>{((e,t)=>{const n=q(e);for(let o=0,r=n.length;o{(t(e,r)?n:o)(e,r)}))})(e,((e,t)=>!1===a(e)),(o=n,(e,t)=>{o[t]=e}),g),n})({class:t.getOrNull(),href:n,rel:o.getOrNull(),target:r.getOrNull(),text:l.getOrNull(),title:i.getOrNull()})},se=(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:z.isDomSafe(r,"a",o)?r:""}})(e,n);e.hasPlugin("rtc",!0)?e.execCommand("createlink",!1,ie(o)):ae(e,t,o)},ce=e=>{e.hasPlugin("rtc",!0)?e.execCommand("unlink"):(e=>{e.undoManager.transact((()=>{const t=e.selection.getNode();le(t)?ue(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()),a=t.getParent(r.endContainer,"a[href]",e.getBody());l&&r.setStartBefore(l),a&&r.setEndAfter(a),n.setRng(r),e.execCommand("unlink"),n.moveToBookmark(o)})(e),e.focus()}))})(e)},ue=(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))}},ge=(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)}},de=(e,t)=>k(t,(t=>(e=>{return V(t=e,n="items")&&void 0!==t[n]&&null!==t[n];var t,n})(t)?de(e,t.items):x(t.value===e,t))),me=(e,t)=>{const n={text:e.text,title:e.title},o=(e,o)=>{const r=(l=t,a=o,"link"===a?l.link:"anchor"===a?l.anchor:m.none()).getOr([]);var l,a;return((e,t,n,o)=>{const r=o[t],l=e.length>0;return void 0!==r?de(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 he=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()},pe=(e,t)=>n=>{const o=n.href;return 1===e&&!W(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()},ke=e=>{const t=e.dom.select("a:not([href])"),n=p(((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()},ve=e=>{const t=T(e);return t.length>0?I(t):m.none()},ye=e=>{try{return m.some(JSON.parse(e))}catch(e){return m.none()}},xe=(e,t)=>{const n=S(e);if(n.length>0){const o=v(t,"_blank"),r=e=>X(U(e),o);return(!1===R(e)?j(r):I)(n)}return m.none()},be=[{text:"Current window",value:""},{text:"New window",value:"_blank"}],_e=e=>{const t=A(e);return l(t)?I(t).orThunk((()=>m.some(be))):!1===t?m.none():m.some(be)},we=(e,t,n)=>{const o=e.getAttrib(t,n);return null!==o&&o.length>0?m.some(o):m.none()},Ce=(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(ye):Promise.reject())).then(e,(()=>e(m.none()))):c(n)?n((t=>e(m.some(t)))):e(m.from(n))})).then((e=>e.bind(j(t)).map((e=>e.length>0?[{text:"None",value:""}].concat(e):e))))})(e).then((n=>{const o=((e,t)=>{const n=e.dom,o=re(e)?m.some(ee(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")))),a=t.bind((e=>we(n,e,"rel"))),i=t.bind((e=>we(n,e,"class")));return{url:r,text:o,title:t.bind((e=>we(n,e,"title"))),target:l,rel:a,linkClass:i}})(e,t);return{anchor:o,catalogs:{targets:_e(e),rels:xe(e,o.target),classes:ve(e),anchor:ke(e),link:n},optNode:t,flags:{titleEnabled:E(e)}}})),Oe=e=>{const t=(e=>{const t=Y(e);return Ce(e,t)})(e);t.then((t=>{const n=((e,t)=>n=>{const o=n.getData();if(!o.url.value)return ce(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")},a={href:o.url.value,attach:void 0!==o.url.meta&&o.url.meta.attach?o.url.meta.attach:g};((e,t)=>k([fe,pe(_(e),N(e))],(e=>e(t))).fold((()=>Promise.resolve(t)),(n=>new Promise((o=>{((e,t,n)=>{const o=e.selection.getRng();he.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=>{se(e,a,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))),a=e.catalogs,i=me(l,a);return{title:"Insert/Edit Link",size:"normal",body:{type:"panel",items:p([[{name:"url",type:"urlinput",filetype:"file",label:"URL"}],o,r,y([a.anchor.map(K("anchor","Anchors")),a.rels.map(K("rel","Rel")),a.targets.map(K("target","Open link in...")),a.link.map(K("link","Link list")),a.classes.map(K("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 Ne=tinymce.util.Tools.resolve("tinymce.util.VK");const Ae=(e,t)=>e.dom.getParent(t,"a[href]"),Se=e=>Ae(e,e.selection.getStart()),Te=(e,t)=>{if(t){const n=Q(t);if(/^#/.test(n)){const t=e.dom.select(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=document.createEvent("MouseEvents");n.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),((e,t)=>{document.body.appendChild(e),e.dispatchEvent(t),document.body.removeChild(e)})(t,n)})(t.href)}},Ee=e=>()=>{e.execCommand("mceLink",!1,{dialog:!0})},Re=e=>()=>{Te(e,Se(e))},Pe=(e,t)=>(e.on("NodeChange",t),()=>e.off("NodeChange",t)),Le=e=>t=>{const n=()=>t.setActive(!e.mode.isReadOnly()&&Z(e,e.selection.getNode()));return n(),Pe(e,n)},Me=e=>t=>{const n=()=>t.setEnabled((e=>1===(e.selection.isCollapsed()?ne(e.dom.getParents(e.selection.getStart())):te(e.selection.getRng())).length)(e));return n(),Pe(e,n)},De=e=>t=>{const n=t=>{return oe(t)||(n=e.selection.getRng(),te(n).length>0);var n},o=e.dom.getParents(e.selection.getStart());return t.setEnabled(n(o)),Pe(e,(e=>t.setEnabled(n(e.parents))))};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})})(e),(e=>{e.ui.registry.addToggleButton("link",{icon:"link",tooltip:"Insert/edit link",onAction:Ee(e),onSetup:Le(e)}),e.ui.registry.addButton("openlink",{icon:"new-tab",tooltip:"Open link",onAction:Re(e),onSetup:Me(e)}),e.ui.registry.addButton("unlink",{icon:"unlink",tooltip:"Remove link",onAction:()=>ce(e),onSetup:De(e)})})(e),(e=>{e.ui.registry.addMenuItem("openlink",{text:"Open link",icon:"new-tab",onAction:Re(e),onSetup:Me(e)}),e.ui.registry.addMenuItem("link",{icon:"link",text:"Link...",shortcut:"Meta+K",onAction:Ee(e)}),e.ui.registry.addMenuItem("unlink",{icon:"unlink",text:"Remove link",onAction:()=>ce(e),onSetup:De(e)})})(e),(e=>{e.ui.registry.addContextMenu("link",{update:t=>e.dom.isEditable(t)?oe(e.dom.getParents(t,"a"))?"link unlink openlink":"link":""})})(e),(e=>{const t=t=>{const n=e.selection.getNode();return t.setEnabled(Z(e,n)),g};e.ui.registry.addContextForm("quicklink",{launch:{type:"contextformtogglebutton",icon:"link",tooltip:"Link",onSetup:Le(e)},label:"Link",predicate:t=>w(e)&&Z(e,t),initValue:()=>Y(e).fold((()=>""),Q),commands:[{type:"contextformtogglebutton",icon:"link",tooltip:"Link",primary:!0,onSetup:t=>{const n=e.selection.getNode();return t.setActive(Z(e,n)),Le(e)(t)},onAction:t=>{const n=t.getValue(),o=(t=>{const n=Y(e),o=re(e);if(n.isNone()&&o){const o=ee(e.selection,n);return x(0===o.length,t)}return m.none()})(n);se(e,{href:n,attach:g},{href:n,text:o,title:m.none(),rel:m.none(),target:m.none(),class:m.none()}),(e=>{e.selection.collapse(!1)})(e),t.hide()}},{type:"contextformbutton",icon:"unlink",tooltip:"Remove link",onSetup:t,onAction:t=>{ce(e),t.hide()}},{type:"contextformbutton",icon:"new-tab",tooltip:"Open link",onSetup:t,onAction:t=>{Re(e)(),t.hide()}}]})})(e),(e=>{e.on("click",(t=>{const n=Ae(e,t.target);n&&Ne.metaKeyPressed(t)&&(t.preventDefault(),Te(e,n))})),e.on("keydown",(t=>{if(!t.isDefaultPrevented()&&13===t.keyCode&&(e=>!0===e.altKey&&!1===e.shiftKey&&!1===e.ctrlKey&&!1===e.metaKey)(t)){const n=Se(e);n&&(t.preventDefault(),Te(e,n))}}))})(e),(e=>{e.addCommand("mceLink",((t,n)=>{!0!==(null==n?void 0:n.dialog)&&P(e)?e.dispatch("contexttoolbar-show",{toolbarKey:"quicklink"}):Oe(e)}))})(e),(e=>{e.addShortcut("Meta+K","",(()=>{e.execCommand("mceLink")}))})(e)}))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/lists/plugin.min.js b/public/resource/tinymce/plugins/lists/plugin.min.js new file mode 100644 index 0000000..6e811c2 --- /dev/null +++ b/public/resource/tinymce/plugins/lists/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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=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,n=e=>t=>typeof t===e,r=t("string"),o=t("object"),s=t("array"),i=n("boolean"),l=e=>!(e=>null==e)(e),a=n("function"),d=n("number"),c=()=>{},u=(e,t)=>e===t,m=e=>t=>!e(t),p=(!1,()=>false);class g{constructor(e,t){this.tag=e,this.value=t}static some(e){return new g(!0,e)}static none(){return g.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?g.some(e(this.value)):g.none()}bind(e){return this.tag?e(this.value):g.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:g.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)?g.some(e):g.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()"}}g.singletonNone=new g(!1);const h=Array.prototype.slice,f=Array.prototype.indexOf,y=Array.prototype.push,v=(e,t)=>{return n=e,r=t,f.call(n,r)>-1;var n,r},C=(e,t)=>{for(let n=0,r=e.length;n{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(S(e,((e,r)=>{n=t(n,e,r)})),n),O=(e,t,n)=>{for(let r=0,o=e.length;rO(e,t,p),T=(e,t)=>(e=>{const t=[];for(let n=0,r=e.length;n{const t=h.call(e,0);return t.reverse(),t},x=(e,t)=>t>=0&&tx(e,0),D=e=>x(e,e.length-1),E=(e,t)=>{const n=[],r=a(t)?e=>C(n,(n=>t(n,e))):e=>v(n,e);for(let t=0,o=e.length;te.exists((e=>n(e,t))),I=(e,t,n)=>e.isSome()&&t.isSome()?g.some(n(e.getOrDie(),t.getOrDie())):g.none(),P=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},M=(e,t)=>{const n=(t||document).createElement(e);return P(n)},R=P,U=(e,t)=>e.dom===t.dom;"undefined"!=typeof window?window:Function("return this;")();const $=e=>e.dom.nodeName.toLowerCase(),_=(1,e=>1===(e=>e.dom.nodeType)(e));const F=e=>t=>_(t)&&$(t)===e,H=e=>g.from(e.dom.parentNode).map(R),V=e=>b(e.dom.childNodes,R),j=(e,t)=>{const n=e.dom.childNodes;return g.from(n[t]).map(R)},K=e=>j(e,0),z=e=>j(e,e.dom.childNodes.length-1),Q=(e,t,n)=>{let r=e.dom;const o=a(n)?n:p;for(;r.parentNode;){r=r.parentNode;const e=R(r);if(t(e))return g.some(e);if(o(e))break}return g.none()},q=(e,t,n)=>((e,t,n,r,o)=>r(n)?g.some(n):a(o)&&o(n)?g.none():t(n,r,o))(0,Q,e,t,n),W=(e,t)=>{H(e).each((n=>{n.dom.insertBefore(t.dom,e.dom)}))},Z=(e,t)=>{e.dom.appendChild(t.dom)},G=(e,t)=>{S(t,(t=>{Z(e,t)}))},J=e=>{e.dom.textContent="",S(V(e),(e=>{X(e)}))},X=e=>{const t=e.dom;null!==t.parentNode&&t.parentNode.removeChild(t)};var Y=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),ee=tinymce.util.Tools.resolve("tinymce.dom.TreeWalker"),te=tinymce.util.Tools.resolve("tinymce.util.VK");const ne=e=>b(e,R),re=Object.keys,oe=(e,t)=>{const n=re(e);for(let r=0,o=n.length;r{const n=e.dom;oe(t,((e,t)=>{((e,t,n)=>{if(!(r(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)}))},ie=e=>L(e.dom.attributes,((e,t)=>(e[t.name]=t.value,e)),{}),le=e=>((e,t)=>R(e.dom.cloneNode(!0)))(e),ae=(e,t)=>{const n=((e,t)=>{const n=M(t),r=ie(e);return se(n,r),n})(e,t);((e,t)=>{const n=(e=>g.from(e.dom.nextSibling).map(R))(e);n.fold((()=>{H(e).each((e=>{Z(e,t)}))}),(e=>{W(e,t)}))})(e,n);const r=V(e);return G(n,r),X(e),n};var de=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),ce=tinymce.util.Tools.resolve("tinymce.util.Tools");const ue=e=>t=>l(t)&&t.nodeName.toLowerCase()===e,me=e=>t=>l(t)&&e.test(t.nodeName),pe=e=>l(e)&&3===e.nodeType,ge=e=>l(e)&&1===e.nodeType,he=me(/^(OL|UL|DL)$/),fe=me(/^(OL|UL)$/),ye=ue("ol"),ve=me(/^(LI|DT|DD)$/),Ce=me(/^(DT|DD)$/),be=me(/^(TH|TD)$/),Se=ue("br"),Ne=(e,t)=>l(t)&&t.nodeName in e.schema.getTextBlockElements(),Le=(e,t)=>l(e)&&e.nodeName in t,Oe=(e,t)=>l(t)&&t.nodeName in e.schema.getVoidElements(),ke=(e,t,n)=>{const r=e.isEmpty(t);return!(n&&e.select("span[data-mce-type=bookmark]",t).length>0)&&r},Te=(e,t)=>e.isChildOf(t,e.getRoot()),Ae=e=>t=>t.options.get(e),xe=Ae("lists_indent_on_tab"),we=Ae("forced_root_block"),De=Ae("forced_root_block_attrs"),Ee=(e,t)=>{const n=e.dom,r=e.schema.getBlockElements(),o=n.createFragment(),s=we(e),i=De(e);let l,a,d=!1;for(a=n.create(s,i),Le(t.firstChild,r)||o.appendChild(a);l=t.firstChild;){const e=l.nodeName;d||"SPAN"===e&&"bookmark"===l.getAttribute("data-mce-type")||(d=!0),Le(l,r)?(o.appendChild(l),a=null):(a||(a=n.create(s,i),o.appendChild(a)),a.appendChild(l))}return!d&&a&&a.appendChild(n.create("br",{"data-mce-bogus":"1"})),o},Be=de.DOM,Ie=F("dd"),Pe=F("dt"),Me=(e,t)=>{var n;Ie(t)?ae(t,"dt"):Pe(t)&&(n=t,g.from(n.dom.parentElement).map(R)).each((n=>((e,t,n)=>{const r=Be.select('span[data-mce-type="bookmark"]',t),o=Ee(e,n),s=Be.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)){Be.remove(t);break}e.dom.isEmpty(i)||Be.insertAfter(i,t),Be.insertAfter(o,t);const l=n.parentElement;l&&ke(e.dom,l)&&(e=>{const t=e.parentNode;t&&ce.each(r,(e=>{t.insertBefore(e,n.parentNode)})),Be.remove(e)})(l),Be.remove(n),ke(e.dom,t)&&Be.remove(t)})(e,n.dom,t.dom)))},Re=e=>{Pe(e)&&ae(e,"dd")},Ue=(e,t)=>{if(pe(e))return{container:e,offset:t};const n=Y.getNode(e,t);return pe(n)?{container:n,offset:t>=e.childNodes.length?n.data.length:0}:n.previousSibling&&pe(n.previousSibling)?{container:n.previousSibling,offset:n.previousSibling.data.length}:n.nextSibling&&pe(n.nextSibling)?{container:n.nextSibling,offset:0}:{container:e,offset:t}},$e=e=>{const t=e.cloneRange(),n=Ue(e.startContainer,e.startOffset);t.setStart(n.container,n.offset);const r=Ue(e.endContainer,e.endOffset);return t.setEnd(r.container,r.offset),t},_e=["OL","UL","DL"],Fe=_e.join(","),He=(e,t)=>{const n=t||e.selection.getStart(!0);return e.dom.getParent(n,Fe,Ke(e,n))},Ve=e=>{const t=e.selection.getSelectedBlocks();return N(((e,t)=>{const n=ce.map(t,(t=>e.dom.getParent(t,"li,dd,dt",Ke(e,t))||t));return E(n)})(e,t),ve)},je=(e,t)=>{const n=e.dom.getParents(t,"TD,TH");return n.length>0?n[0]:e.getBody()},Ke=(e,t)=>{const n=e.dom.getParents(t,e.dom.isBlock),r=k(n,(t=>{return n=e.schema,!he(r=t)&&!ve(r)&&C(_e,(e=>n.isValidChild(r.nodeName,e)));var n,r}));return r.getOr(e.getBody())},ze=(e,t)=>{const n=e.dom.getParents(t,"ol,ul",Ke(e,t));return D(n)},Qe=(e,t)=>{const n=b(t,(t=>ze(e,t).getOr(t)));return E(n)},qe=e=>/\btox\-/.test(e.className),We=(e,t)=>O(e,he,be).exists((e=>e.nodeName===t&&!qe(e))),Ze=(e,t)=>null!==t&&!e.dom.isEditable(t),Ge=(e,t)=>{const n=e.dom.getParent(t,"ol,ul,dl");return Ze(e,n)},Je=(e,t)=>{const n=e.selection.getNode();return t({parents:e.dom.getParents(n),element:n}),e.on("NodeChange",t),()=>e.off("NodeChange",t)},Xe=(e,t,n)=>e.dispatch("ListMutation",{action:t,element:n}),Ye=(et=/^\s+|\s+$/g,e=>e.replace(et,""));var et;const tt=(e,t,n)=>{((e,t,n)=>{if(!r(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)},nt=(e,t)=>{Z(e.item,t.list)},rt=(e,t)=>{const n={list:M(t,e),item:M("li",e)};return Z(n.list,n.item),n},ot=e=>((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,"OL,UL"),st=e=>K(e).exists(ot),it=e=>e.depth>0,lt=e=>e.isSelected,at=e=>{const t=V(e),n=z(e).exists(ot)?t.slice(0,-1):t;return b(n,le)},dt=e=>(S(e,((t,n)=>{((e,t)=>{const n=e[t].depth,r=e=>e.depth===n&&!e.dirty,o=e=>e.depthO(e.slice(t+1),r,o)))})(e,n).fold((()=>{t.dirty&&(e=>{e.listAttributes=((e,t)=>{const n={};var r;return((e,t,n,r)=>{oe(e,((e,o)=>{(t(e,o)?n:r)(e,o)}))})(e,t,(r=n,(e,t)=>{r[t]=e}),c),n})(e.listAttributes,((e,t)=>"start"!==t))})(t)}),(e=>{return r=e,(n=t).listType=r.listType,void(n.listAttributes={...r.listAttributes});var n,r}))})),e),ct=(e,t,n,r)=>K(r).filter(ot).fold((()=>{t.each((e=>{U(e.start,r)&&n.set(!0)}));const o=((e,t,n)=>H(e).filter(_).map((r=>({depth:t,dirty:!1,isSelected:n,content:at(e),itemAttributes:ie(e),listAttributes:ie(r),listType:$(r)}))))(r,e,n.get());t.each((e=>{U(e.end,r)&&n.set(!1)}));const s=z(r).filter(ot).map((r=>ut(e,t,n,r))).getOr([]);return o.toArray().concat(s)}),(r=>ut(e,t,n,r))),ut=(e,t,n,r)=>T(V(r),(r=>(ot(r)?ut:ct)(e+1,t,n,r))),mt=(e,t)=>{const n=dt(t);return((e,t)=>{const n=L(t,((t,n)=>n.depth>t.length?((e,t,n)=>{const r=((e,t,n)=>{const r=[];for(let o=0;o{for(let t=1;t{for(let t=0;t{se(e.list,t.listAttributes),se(e.item,t.itemAttributes),G(e.item,t.content)}))})(r,n),o=r,I(D(t),w(o),nt),t.concat(r)})(e,t,n):((e,t,n)=>{const r=t.slice(0,n.depth);return D(r).each((t=>{const r=((e,t,n)=>{const r=M("li",e);return se(r,t),G(r,n),r})(e,n.itemAttributes,n.content);((e,t)=>{Z(e.list,t),e.item=t})(t,r),((e,t)=>{$(e.list)!==t.listType&&(e.list=ae(e.list,t.listType)),se(e.list,t.listAttributes)})(t,n)})),r})(e,t,n)),[]);return w(n).map((e=>e.list))})(e.contentDocument,n).toArray()},pt=(e,t,n)=>{const r=((e,t)=>{const n=(e=>{let t=!1;return{get:()=>t,set:e=>{t=e}}})();return b(e,(e=>({sourceList:e,entries:ut(0,t,n,e)})))})(t,(e=>{const t=b(Ve(e),R);return I(k(t,m(st)),k(A(t),m(st)),((e,t)=>({start:e,end:t})))})(e));S(r,(t=>{((e,t)=>{S(N(e,lt),(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 r=((e,t)=>T(((e,t)=>{if(0===e.length)return[];{let n=t(e[0]);const r=[];let o=[];for(let s=0,i=e.length;sw(t).exists(it)?mt(e,t):((e,t)=>{const n=dt(t);return b(n,(t=>{const n=((e,t)=>{const n=document.createDocumentFragment();return S(e,(e=>{n.appendChild(e.dom)})),R(n)})(t.content);return R(Ee(e,n.dom))}))})(e,t))))(e,t.entries);var o;S(r,(t=>{Xe(e,"Indent"===n?"IndentList":"OutdentList",t.dom)})),o=t.sourceList,S(r,(e=>{W(o,e)})),X(t.sourceList)}))},gt=(e,t)=>{const n=ne((e=>{const t=(e=>{const t=ze(e,e.selection.getStart()),n=N(e.selection.getSelectedBlocks(),fe);return t.toArray().concat(n)})(e);return Qe(e,t)})(e)),r=ne((e=>N(Ve(e),Ce))(e));let o=!1;if(n.length||r.length){const s=e.selection.getBookmark();pt(e,n,t),((e,t,n)=>{S(n,"Indent"===t?Re:t=>Me(e,t))})(e,t,r),e.selection.moveToBookmark(s),e.selection.setRng($e(e.selection.getRng())),e.nodeChanged(),o=!0}return o},ht=(e,t)=>!(e=>{const t=He(e);return Ze(e,t)})(e)&>(e,t),ft=e=>ht(e,"Indent"),yt=e=>ht(e,"Outdent"),vt=e=>ht(e,"Flatten"),Ct=e=>"\ufeff"===e;var bt=tinymce.util.Tools.resolve("tinymce.dom.BookmarkManager");const St=de.DOM,Nt=e=>{const t={},n=n=>{let r=e[n?"startContainer":"endContainer"],o=e[n?"startOffset":"endOffset"];if(ge(r)){const e=St.create("span",{"data-mce-type":"bookmark"});r.hasChildNodes()?(o=Math.min(o,r.childNodes.length-1),n?r.insertBefore(e,r.childNodes[o]):St.insertAfter(e,r.childNodes[o])):r.appendChild(e),r=e,o=0}t[n?"startContainer":"endContainer"]=r,t[n?"startOffset":"endOffset"]=o};return n(!0),e.collapsed||n(),t},Lt=e=>{const t=t=>{let n=e[t?"startContainer":"endContainer"],r=e[t?"startOffset":"endOffset"];if(n){if(ge(n)&&n.parentNode){const e=n;r=(e=>{var t;let n=null===(t=e.parentNode)||void 0===t?void 0:t.firstChild,r=0;for(;n;){if(n===e)return r;ge(n)&&"bookmark"===n.getAttribute("data-mce-type")||r++,n=n.nextSibling}return-1})(n),n=n.parentNode,St.remove(e),!n.hasChildNodes()&&St.isBlock(n)&&n.appendChild(St.create("br"))}e[t?"startContainer":"endContainer"]=n,e[t?"startOffset":"endOffset"]=r}};t(!0),t();const n=St.createRng();return n.setStart(e.startContainer,e.startOffset),e.endContainer&&n.setEnd(e.endContainer,e.endOffset),$e(n)},Ot=e=>{switch(e){case"UL":return"ToggleUlList";case"OL":return"ToggleOlList";case"DL":return"ToggleDLList"}},kt=(e,t)=>{ce.each(t,((t,n)=>{e.setAttribute(n,t)}))},Tt=(e,t,n)=>{((e,t,n)=>{const r=n["list-style-type"]?n["list-style-type"]:null;e.setStyle(t,"list-style-type",r)})(e,t,n),((e,t,n)=>{kt(t,n["list-attributes"]),ce.each(e.select("li",t),(e=>{kt(e,n["list-item-attributes"])}))})(e,t,n)},At=(e,t)=>l(t)&&!Le(t,e.schema.getBlockElements()),xt=(e,t,n,r)=>{let o=t[n?"startContainer":"endContainer"];const s=t[n?"startOffset":"endOffset"];ge(o)&&(o=o.childNodes[Math.min(s,o.childNodes.length-1)]||o),!n&&Se(o.nextSibling)&&(o=o.nextSibling);const i=(t,n)=>{var o;const s=new ee(t,r),i=n?"next":"prev";let l;for(;l=s[i]();)if(!Oe(e,l)&&!Ct(l.textContent)&&0!==(null===(o=l.textContent)||void 0===o?void 0:o.length))return g.some(l);return g.none()};if(n&&pe(o))if(Ct(o.textContent))o=i(o,!1).getOr(o);else for(null!==o.parentNode&&At(e,o.parentNode)&&(o=o.parentNode);null!==o.previousSibling&&(At(e,o.previousSibling)||pe(o.previousSibling));)o=o.previousSibling;if(!n&&pe(o))if(Ct(o.textContent))o=i(o,!0).getOr(o);else for(null!==o.parentNode&&At(e,o.parentNode)&&(o=o.parentNode);null!==o.nextSibling&&(At(e,o.nextSibling)||pe(o.nextSibling));)o=o.nextSibling;for(;o.parentNode!==r;){const t=o.parentNode;if(Ne(e,o))return o;if(/^(TD|TH)$/.test(t.nodeName))return o;o=t}return o},wt=(e,t,n)=>{const r=e.selection.getRng();let o="LI";const s=Ke(e,e.selection.getStart(!0)),i=e.dom;if("false"===i.getContentEditable(e.selection.getNode()))return;"DL"===(t=t.toUpperCase())&&(o="DT");const l=Nt(r),a=((e,t,n)=>{const r=[],o=e.dom,s=xt(e,t,!0,n),i=xt(e,t,!1,n);let l;const a=[];for(let e=s;e&&(a.push(e),e!==i);e=e.nextSibling);return ce.each(a,(t=>{var s;if(Ne(e,t))return r.push(t),void(l=null);if(o.isBlock(t)||Se(t))return Se(t)&&o.remove(t),void(l=null);const i=t.nextSibling;bt.isBookmarkNode(t)&&(he(i)||Ne(e,i)||!i&&t.parentNode===n)?l=null:(l||(l=o.create("p"),null===(s=t.parentNode)||void 0===s||s.insertBefore(l,t),r.push(l)),l.appendChild(t))})),r})(e,r,s);ce.each(a,(r=>{let s;const l=r.previousSibling,a=r.parentNode;ve(a)||(l&&he(l)&&l.nodeName===t&&((e,t,n)=>{const r=e.getStyle(t,"list-style-type");let o=n?n["list-style-type"]:"";return o=null===o?"":o,r===o})(i,l,n)?(s=l,r=i.rename(r,o),l.appendChild(r)):(s=i.create(t),a.insertBefore(s,r),s.appendChild(r),r=i.rename(r,o)),((e,t,n)=>{ce.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,r),Tt(i,s,n),Et(e.dom,s))})),e.selection.setRng(Lt(l))},Dt=(e,t,n)=>{return((e,t)=>he(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)&&(r=n,t.className===r.className);var r},Et=(e,t)=>{let n,r=t.nextSibling;if(Dt(e,t,r)){const o=r;for(;n=o.firstChild;)t.appendChild(n);e.remove(o)}if(r=t.previousSibling,Dt(e,t,r)){const o=r;for(;n=o.lastChild;)t.insertBefore(n,t.firstChild);e.remove(o)}},Bt=e=>"list-style-type"in e,It=(e,t,n)=>{const r=He(e);if(Ge(e,r)||(e=>C(e.selection.getSelectedBlocks(),m(e.dom.isEditable)))(e))return;const s=(e=>{const t=He(e),n=e.selection.getSelectedBlocks();return((e,t)=>l(e)&&1===t.length&&t[0]===e)(t,n)?(e=>N(e.querySelectorAll(Fe),he))(t):N(n,(e=>he(e)&&t!==e))})(e),i=o(n)?n:{};s.length>0?((e,t,n,r,o)=>{const s=he(t);if(s&&t.nodeName===r&&!Bt(o))vt(e);else{wt(e,r,o);const i=Nt(e.selection.getRng()),l=s?[t,...n]:n;ce.each(l,(t=>{((e,t,n,r)=>{if(t.nodeName!==n){const o=e.dom.rename(t,n);Tt(e.dom,o,r),Xe(e,Ot(n),o)}else Tt(e.dom,t,r),Xe(e,Ot(n),t)})(e,t,r,o)})),e.selection.setRng(Lt(i))}})(e,r,s,t,i):((e,t,n,r)=>{if(t!==e.getBody())if(t)if(t.nodeName!==n||Bt(r)||qe(t)){const o=Nt(e.selection.getRng());Tt(e.dom,t,r);const s=e.dom.rename(t,n);Et(e.dom,s),e.selection.setRng(Lt(o)),wt(e,n,r),Xe(e,Ot(n),s)}else vt(e);else wt(e,n,r),Xe(e,Ot(n),t)})(e,r,t,i)},Pt=de.DOM,Mt=(e,t)=>{const n=ce.grep(e.select("ol,ul",t));ce.each(n,(t=>{((e,t)=>{const n=t.parentElement;if(n&&"LI"===n.nodeName&&n.firstChild===t){const r=n.previousSibling;r&&"LI"===r.nodeName?(r.appendChild(t),ke(e,n)&&Pt.remove(n)):Pt.setStyle(n,"listStyleType","none")}if(he(n)){const e=n.previousSibling;e&&"LI"===e.nodeName&&e.appendChild(t)}})(e,t)}))},Rt=(e,t,n,r)=>{let o=t.startContainer;const s=t.startOffset;if(pe(o)&&(n?s0))return o;const i=e.schema.getNonEmptyElements();ge(o)&&(o=Y.getNode(o,s));const l=new ee(o,r);n&&((e,t)=>!!Se(t)&&e.isBlock(t.nextSibling)&&!Se(t.previousSibling))(e.dom,o)&&l.next();const a=n?l.next.bind(l):l.prev2.bind(l);for(;o=a();){if("LI"===o.nodeName&&!o.hasChildNodes())return o;if(i[o.nodeName])return o;if(pe(o)&&o.data.length>0)return o}return null},Ut=(e,t)=>{const n=t.childNodes;return 1===n.length&&!he(n[0])&&e.isBlock(n[0])},$t=(e,t,n)=>{let r;const o=t.parentNode;if(!Te(e,t)||!Te(e,n))return;he(n.lastChild)&&(r=n.lastChild),o===n.lastChild&&Se(o.previousSibling)&&e.remove(o.previousSibling);const s=n.lastChild;s&&Se(s)&&t.hasChildNodes()&&e.remove(s),ke(e,n,!0)&&J(R(n)),((e,t,n)=>{let r;const o=Ut(e,n)?n.firstChild:n;if(((e,t)=>{Ut(e,t)&&e.remove(t.firstChild,!0)})(e,t),!ke(e,t,!0))for(;r=t.firstChild;)o.appendChild(r)})(e,t,n),r&&n.appendChild(r);const i=((e,t)=>{const n=e.dom,r=t.dom;return n!==r&&n.contains(r)})(R(n),R(t))?e.getParents(t,he,n):[];e.remove(t),S(i,(t=>{ke(e,t)&&t!==e.getRoot()&&e.remove(t)}))},_t=(e,t)=>{const n=e.dom,r=e.selection,o=r.getStart(),s=je(e,o),i=n.getParent(r.getStart(),"LI",s);if(i){const o=i.parentElement;if(o===e.getBody()&&ke(n,o))return!0;const l=$e(r.getRng()),a=n.getParent(Rt(e,l,t,s),"LI",s);if(a&&a!==i)return e.undoManager.transact((()=>{var n,r;t?((e,t,n,r)=>{const o=e.dom;if(o.isEmpty(r))((e,t,n)=>{J(R(n)),$t(e.dom,t,n),e.selection.setCursorLocation(n,0)})(e,n,r);else{const s=Nt(t);$t(o,n,r),e.selection.setRng(Lt(s))}})(e,l,a,i):(null===(r=(n=i).parentNode)||void 0===r?void 0:r.firstChild)===n?yt(e):((e,t,n,r)=>{const o=Nt(t);$t(e.dom,n,r);const s=Lt(o);e.selection.setRng(s)})(e,l,i,a)})),!0;if(!a&&!t&&0===l.startOffset&&0===l.endOffset)return e.undoManager.transact((()=>{vt(e)})),!0}return!1},Ft=e=>{const t=e.selection.getStart(),n=je(e,t);return e.dom.getParent(t,"LI,DT,DD",n)||Ve(e).length>0},Ht=(e,t)=>{const n=e.selection;return!Ge(e,n.getNode())&&(n.isCollapsed()?((e,t)=>_t(e,t)||((e,t)=>{const n=e.dom,r=e.selection.getStart(),o=je(e,r),s=n.getParent(r,n.isBlock,o);if(s&&n.isEmpty(s)){const r=$e(e.selection.getRng()),i=n.getParent(Rt(e,r,t,o),"LI",o);if(i){const l=e=>v(["td","th","caption"],$(e)),a=e=>e.dom===o;return!!((e,t,n=u)=>I(e,t,n).getOr(e.isNone()&&t.isNone()))(q(R(i),l,a),q(R(r.startContainer),l,a),U)&&(e.undoManager.transact((()=>{((e,t,n)=>{const r=e.getParent(t.parentNode,e.isBlock,n);e.remove(t),r&&e.isEmpty(r)&&e.remove(r)})(n,s,o),Et(n,i.parentNode),e.selection.select(i,!0),e.selection.collapse(t)})),!0)}}return!1})(e,t))(e,t):(e=>!!Ft(e)&&(e.undoManager.transact((()=>{e.execCommand("Delete"),Mt(e.dom,e.getBody())})),!0))(e))},Vt=e=>{const t=A(Ye(e).split("")),n=b(t,((e,t)=>{const n=e.toUpperCase().charCodeAt(0)-"A".charCodeAt(0)+1;return Math.pow(26,t)*n}));return L(n,((e,t)=>e+t),0)},jt=e=>{if(--e<0)return"";{const t=e%26,n=Math.floor(e/26);return jt(n)+String.fromCharCode("A".charCodeAt(0)+t)}},Kt=e=>{const t=parseInt(e.start,10);return B(e.listStyleType,"upper-alpha")?jt(t):B(e.listStyleType,"lower-alpha")?jt(t).toLowerCase():e.start},zt=(e,t)=>()=>{const n=He(e);return l(n)&&n.nodeName===t},Qt=e=>{e.addCommand("mceListProps",(()=>{(e=>{const t=He(e);ye(t)&&!Ge(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:Kt({start:e.dom.getAttrib(t,"start","1"),listStyleType:g.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 g.some({listStyleType:g.none(),start:e});case 0:return g.some({listStyleType:g.some("upper-alpha"),start:Vt(e).toString()});case 1:return g.some({listStyleType:g.some("lower-alpha"),start:Vt(e).toString()});case 3:return g.some({listStyleType:g.none(),start:""});case 4:return g.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 qt=tinymce.util.Tools.resolve("tinymce.html.Node");const Wt=e=>3===e.type,Zt=e=>0===e.length,Gt=e=>{const t=(t,n)=>{const r=qt.create("li");S(t,(e=>r.append(e))),n?e.insert(r,n,!0):e.append(r)},n=L(e.children(),((e,n)=>Wt(n)?[...e,n]:Zt(e)||Wt(n)?e:(t(e,n),[])),[]);Zt(n)||t(n)},Jt=(e,t)=>n=>Je(e,(r=>{n.setActive(We(r.parents,t)),n.setEnabled(!Ge(e,r.element))})),Xt=(e,t)=>n=>Je(e,(r=>n.setEnabled(We(r.parents,t)&&!Ge(e,r.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,Gt)))}))})(e),e.hasPlugin("rtc",!0)?Qt(e):((e=>{xe(e)&&(e=>{e.on("keydown",(t=>{t.keyCode!==te.TAB||te.metaKeyPressed(t)||e.undoManager.transact((()=>{(t.shiftKey?yt(e):ft(e))&&t.preventDefault()}))}))})(e),(e=>{e.on("ExecCommand",(t=>{const n=t.command.toLowerCase();"delete"!==n&&"forwarddelete"!==n||!Ft(e)||Mt(e.dom,e.getBody())})),e.on("keydown",(t=>{t.keyCode===te.BACKSPACE?Ht(e,!1)&&t.preventDefault():t.keyCode===te.DELETE&&Ht(e,!0)&&t.preventDefault()}))})(e)})(e),(e=>{e.on("BeforeExecCommand",(t=>{const n=t.command.toLowerCase();"indent"===n?ft(e):"outdent"===n&&yt(e)})),e.addCommand("InsertUnorderedList",((t,n)=>{It(e,"UL",n)})),e.addCommand("InsertOrderedList",((t,n)=>{It(e,"OL",n)})),e.addCommand("InsertDefinitionList",((t,n)=>{It(e,"DL",n)})),e.addCommand("RemoveList",(()=>{vt(e)})),Qt(e),e.addCommand("mceListUpdate",((t,n)=>{o(n)&&((e,t)=>{const n=He(e);null===n||Ge(e,n)||e.undoManager.transact((()=>{o(t.styles)&&e.dom.setStyles(n,t.styles),o(t.attrs)&&oe(t.attrs,((t,r)=>e.dom.setAttrib(n,r,t)))}))})(e,n)})),e.addQueryStateHandler("InsertUnorderedList",zt(e,"UL")),e.addQueryStateHandler("InsertOrderedList",zt(e,"OL")),e.addQueryStateHandler("InsertDefinitionList",zt(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:Jt(e,"OL")}),e.ui.registry.addToggleButton("bullist",{icon:"unordered-list",active:!1,tooltip:"Bullet list",onAction:t("InsertUnorderedList"),onSetup:Jt(e,"UL")}))})(e),(e=>{const t={text:"List properties...",icon:"ordered-list",onAction:()=>e.execCommand("mceListProps"),onSetup:Xt(e,"OL")};e.ui.registry.addMenuItem("listprops",t),e.ui.registry.addContextMenu("lists",{update:t=>{const n=He(e,t);return ye(n)?["listprops"]:[]}})})(e),(e=>({backspaceDelete:t=>{Ht(e,t)}}))(e))))}(); \ No newline at end of file diff --git a/public/resource/tinymce/plugins/media/plugin.min.js b/public/resource/tinymce/plugins/media/plugin.min.js new file mode 100644 index 0000000..340c0a3 --- /dev/null +++ b/public/resource/tinymce/plugins/media/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.4.2 (2023-04-26) + */ +!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=a=e,(o=String).prototype.isPrototypeOf(r)||(null===(s=a.constructor)||void 0===s?void 0:s.name)===o.name)?"string":t;var r,a,o,s})(t)===e,r=t("string"),a=t("object"),o=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,c=(e,t)=>{for(let r=0,a=e.length;r{const t=[];for(let r=0,a=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"),j=p("media_dimensions");var k=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,C=e=>e.replace(/px$/,""),D=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(C).getOr(""),height:d(r,"max-height").map(C).getOr("")}},T=(e,t)=>{let r={};for(let a=A({validate:!1,forced_root_block:!1},t).parse(e);a;a=a.walk())if(1===a.type){const e=a.name;if(a.attr("data-ephox-embed-iri")){r=D(a);break}r.source||"param"!==e||(r.source=a.attr("movie")),"iframe"!==e&&"object"!==e&&"embed"!==e&&"video"!==e&&"audio"!==e||(r.type||(r.type=e),r=k.extend(a.attributes.map,r)),"script"===e&&(r={type:"script",source:a.attr("src")}),"source"===e&&(r.source?r.altsource||(r.altsource=a.attr("src")):r.source=a.attr("src")),"img"!==e||r.poster||(r.poster=a.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 $=tinymce.util.Tools.resolve("tinymce.html.Node"),M=tinymce.util.Tools.resolve("tinymce.html.Serializer");const F=(e,t={})=>A({forced_root_block:!1,validate:!1,allow_conditional_comments:!0,...t},e),N=O.DOM,R=e=>/^[0-9.]+$/.test(e)?e+"px":e,U=(e,t)=>{const r=t.attr("style"),a=r?N.parseStyle(r):{};s(e.width)&&(a["max-width"]=R(e.width)),s(e.height)&&(a["max-height"]=R(e.height)),t.attr("style",N.serializeStyle(a))},P=["source","altsource"],E=(e,t,r,a)=>{let o=0,s=0;const i=F(a);i.addNodeFilter("source",(e=>o=e.length));const n=i.parse(e);for(let e=n;e;e=e.walk())if(1===e.type){const a=e.name;if(e.attr("data-ephox-embed-iri")){U(t,e);break}switch(a){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(a){case"video":e.attr("poster",t.poster),e.attr("src",null);for(let r=o;r<2;r++)if(t[P[r]]){const a=new $("source",1);a.attr("src",t[P[r]]),a.attr("type",t[P[r]+"mime"]||null),e.append(a)}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 $("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[P[s]]),e.attr("type",t[P[s]+"mime"]||null),!t[P[s]])){e.remove();continue}s++;break;case"img":t.poster||e.remove()}}return M({},a).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]+)/,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),a=e.regex.exec(t);let o=r+e.url;if(s(a))for(let e=0;ea[e]?a[e]:""));return o.replace(/\?$/,"")},B=(e,t)=>{var r;const a=k.extend({},t);if(!a.source&&(k.extend(a,T(null!==(r=a.embed)&&void 0!==r?r:"",e.schema)),!a.source))return"";a.altsource||(a.altsource=""),a.poster||(a.poster=""),a.source=e.convertURL(a.source,"source"),a.altsource=e.convertURL(a.altsource,"source"),a.sourcemime=z(a.source),a.altsourcemime=z(a.altsource),a.poster=e.convertURL(a.poster,"poster");const o=(e=>{const t=L.filter((t=>t.regex.test(e)));return t.length>0?k.extend({},t[0],{url:I(t[0],e)}):null})(a.source);if(o&&(a.source=o.url,a.type=o.type,a.allowfullscreen=o.allowFullscreen,a.width=a.width||String(o.w),a.height=a.height||String(o.h)),a.embed)return E(a.embed,a,!0,e.schema);{const t=g(e),r=b(e),o=w(e);return a.width=a.width||"300",a.height=a.height||"150",k.each(a,((t,r)=>{a[r]=e.dom.encode(""+t)})),"iframe"===a.type?((e,t)=>{if(t)return t(e);{const t=e.allowfullscreen?' allowFullscreen="1"':"";return'"}})(a,o):"application/x-shockwave-flash"===a.sourcemime?(e=>{let t='';return e.poster&&(t+=''),t+="",t})(a):-1!==a.sourcemime.indexOf("audio")?((e,t)=>t?t(e):'")(a,t):"script"===a.type?(e=>' diff --git a/src/api/.DS_Store b/src/api/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..45aa1163e11dc56829428ec05c9d88b3eadf7f75 GIT binary patch literal 8196 zcmeHMu}<7T5SGKc# z17(y?;5X>n>3aA3A!2h8D-r3yxiTA$q>Zl5+0#8x_-XAh_ zwz;>Bvv%viU`qhl9;R)>G3o#tlX;ta+c;}OaZXn~7$0hUiD6tg{29Yxb8j1GT{syR zPR3_8zCtlJJK{16CzCs?qbi^ZbQR#*eU*lELKk!v*6*KhrFT{p#c)~;G0TtJ_J{rJ z_aS2Z0HU5Oet?hIX2~NRz5{v?rXC6K5F?hBq zSTFBhEc+7q+t`E#tzYIHaNZT<{Z1Ehm45ks=Sk%BafyuHEAqKt8yoZu*U4*ff_uL} z_TY*?y+Q5>D#0U)jNX9=Qt+c+NUTj2unMd=9k#gsKTLoBSG80DRp1dTV0y)Iaexc- zwRPuGxz^6m2k6`w*EnlKFxYY&)|TV2?H`6X&H&|@+}p-k%%J`A4*|7JOZxtII_UT` G75EGCrfkpv literal 0 HcmV?d00001 diff --git a/src/api/basic/common.ts b/src/api/basic/common.ts new file mode 100644 index 0000000..73ea4ec --- /dev/null +++ b/src/api/basic/common.ts @@ -0,0 +1,89 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import {ContentTypeEnum} from "@/enums/httpEnum"; + +enum Api { + UploadXlsx = '/v2/common/upload/excel', + ExportXlsx = '/v2/common/export/excel', + UploadOss = '/v2/common/uploadOss', + GenerateId = '/v2/common/nextId', + productCoverUpload = '/v2/common/upload/productCoverUpload', +} + +export interface UploadFileParams { + // file name + file: File | any; +} + +export interface UploadCoverProductParams { + // file name + file: File | any; + type: number; +} + +export function uploadXlsx(params: UploadFileParams) { + return defHttp.post( + { + url: Api.UploadXlsx, + params, + headers: { + 'Content-type': ContentTypeEnum.FORM_DATA, + // @ts-ignore + ignoreCancelToken: true, + }, + } + ); +} + +export function productCoverUpload(params: UploadCoverProductParams) { + return defHttp.post( + { + url: Api.productCoverUpload, + params, + timeout: 100000, // 设置超时时间为160秒 + headers: { + 'Content-type': ContentTypeEnum.FORM_DATA, + // @ts-ignore + ignoreCancelToken: true, + }, + } + ); +} + +export function exportXlsx(type: string, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.get>( + { + url: `${Api.ExportXlsx}?type=${type}`, + responseType: "blob" + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function uploadOss(params: UploadFileParams, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: Api.UploadOss, + params, + headers: { + 'Content-type': ContentTypeEnum.FORM_DATA, + // @ts-ignore + ignoreCancelToken: true, + }, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function generateId(type: string) { + return defHttp.get>( + { + url: `${Api.GenerateId}/${type}`, + } + ); +} \ No newline at end of file diff --git a/src/api/basic/customer.ts b/src/api/basic/customer.ts new file mode 100644 index 0000000..ca1b985 --- /dev/null +++ b/src/api/basic/customer.ts @@ -0,0 +1,82 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + CustomerResp, + AddOrUpdateCustomerReq, + QueryCustomerReq +} from "@/api/basic/model/customerModel"; + + +enum API { + PageList = '/basic/customer/pageList', + List = '/basic/customer/list', + AddOrUpdateCustomer = '/basic/customer/addOrUpdate', + DeleteBatch = '/basic/customer/deleteBatch', + UpdateStatus = '/basic/customer/updateStatus', + Export = '/basic/customer/export', +} + +export function getCustomerPageList(params: QueryCustomerReq) { + return defHttp.post>( + { + url: API.PageList, + params, + }, + ); +} + +export function getCustomerList() { + return defHttp.get>( + { + url: API.List + } + ); +} + +export function addOrUpdateCustomer(params: AddOrUpdateCustomerReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateCustomer, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function updateCustomerStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function deleteBatchCustomer(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.delete( + { + url: `${API.DeleteBatch}?ids=${ids}` + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function exportCustomer(params: QueryCustomerReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/basic/incomeExpense.ts b/src/api/basic/incomeExpense.ts new file mode 100644 index 0000000..3c43c2f --- /dev/null +++ b/src/api/basic/incomeExpense.ts @@ -0,0 +1,69 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + QueryIncomeExpenseReq, + AddOrUpdateIncomeExpenseReq, + IncomeExpenseResp, +} from "@/api/basic/model/incomeExpenseModel"; + +enum API { + PageList = '/basic/incomeExpense/pageList', + List = '/basic/incomeExpense/list', + AddOrUpdateIncomeExpense = '/basic/incomeExpense/addOrUpdate', + DeleteBatch = '/basic/incomeExpense/deleteBatch', + UpdateStatus = '/basic/incomeExpense/updateStatus', +} + +export function getIncomeExpensePageList(params: QueryIncomeExpenseReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function getIncomeExpenseList(type: string) { + return defHttp.get>( + { + url: `${API.List}/${type}` + } + ); +} + +export function addOrUpdateIncomeExpense(params: AddOrUpdateIncomeExpenseReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateIncomeExpense, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteIncomeExpense(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.delete( + { + url: `${API.DeleteBatch}?ids=${ids}` + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function updateIncomeExpenseStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} diff --git a/src/api/basic/member.ts b/src/api/basic/member.ts new file mode 100644 index 0000000..a5cac99 --- /dev/null +++ b/src/api/basic/member.ts @@ -0,0 +1,79 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + MemberResp, + AddOrUpdateMemberReq, + QueryMemberReq +} from "@/api/basic/model/memberModel"; + + +enum API { + List = '/basic/member/list', + PageList = '/basic/member/pageList', + AddOrUpdateMember = '/basic/member/addOrUpdate', + DeleteBatch = '/basic/member/deleteBatch', + UpdateStatus = '/basic/member/updateStatus', + Export = '/basic/member/export', +} + +export function getMemberPageList(params: QueryMemberReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateMember(params: AddOrUpdateMemberReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateMember, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateMemberStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchMember(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.delete( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getMemberList() { + return defHttp.get>( + { + url: API.List + } + ); +} + +export function exportMember(params: QueryMemberReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/basic/model/customerModel.ts b/src/api/basic/model/customerModel.ts new file mode 100644 index 0000000..f6ac2da --- /dev/null +++ b/src/api/basic/model/customerModel.ts @@ -0,0 +1,49 @@ +export interface CustomerResp { + id: number | string; + customerName: string; + contact: string; + phoneNumber: string; + address: string; + email: string; + status: number; + firstQuarterAccountReceivable: number; + secondQuarterAccountReceivable: number; + thirdQuarterAccountReceivable: number; + fourthQuarterAccountReceivable: number; + totalAccountReceivable: number; + fax: string; + taxNumber: string; + bankName: string; + accountNumber: string; + taxRate: string; + sort: number; + remark: string; + createTime: string; +} + +export interface AddOrUpdateCustomerReq { + id: number | string | undefined; + customerName: string; + contact: string; + phoneNumber: string; + address: string; + email: string; + status: number; + firstQuarterAccountReceivable: number; + secondQuarterAccountReceivable: number; + thirdQuarterAccountReceivable: number; + fourthQuarterAccountReceivable: number; + fax: string; + taxNumber: string; + bankName: string; + accountNumber: string; + taxRate: string; + sort: number; + remark: string; +} + +export interface QueryCustomerReq { + customerName: string; + contact: string; + phoneNumber: string; +} \ No newline at end of file diff --git a/src/api/basic/model/incomeExpenseModel.ts b/src/api/basic/model/incomeExpenseModel.ts new file mode 100644 index 0000000..7c8ece7 --- /dev/null +++ b/src/api/basic/model/incomeExpenseModel.ts @@ -0,0 +1,24 @@ +export interface QueryIncomeExpenseReq { + name: string; + type: string; + remark: string; +} + +export interface AddOrUpdateIncomeExpenseReq { + id: number | string | undefined; + name: string; + type: string; + remark: string; + status: number; + sort: number; +} + +export interface IncomeExpenseResp { + id: string; + name: string; + type: string; + remark: string; + status: number; + sort: number; + createTime: string; +} \ No newline at end of file diff --git a/src/api/basic/model/memberModel.ts b/src/api/basic/model/memberModel.ts new file mode 100644 index 0000000..a63685c --- /dev/null +++ b/src/api/basic/model/memberModel.ts @@ -0,0 +1,29 @@ +export interface MemberResp { + id: number | string; + memberNumber: string; + memberName: string; + phoneNumber: string; + email: string; + advancePayment: number; + status: number; + remark: string; + sort: number; + createTime: string; +} + +export interface AddOrUpdateMemberReq { + id: number | string | undefined; + memberNumber: string; + memberName: string; + phoneNumber: string; + email: string; + advancePayment: number; + status: number; + remark: string; + sort: number; +} + +export interface QueryMemberReq { + memberNumber: string; + phoneNumber: string; +} \ No newline at end of file diff --git a/src/api/basic/model/operatorModel.ts b/src/api/basic/model/operatorModel.ts new file mode 100644 index 0000000..b832694 --- /dev/null +++ b/src/api/basic/model/operatorModel.ts @@ -0,0 +1,23 @@ +export interface OperatorResp { + id: number | string; + name: string; + type: string; + status: number; + sort: number; + remark: string; + createTime: string; +} + +export interface AddOrUpdateOperatorReq { + id: number | string | undefined; + name: string; + type: number; + status: number; + remark: string; + sort: number; +} + +export interface QueryOperatorReq { + name: string; + type: string; +} \ No newline at end of file diff --git a/src/api/basic/model/supplierModel.ts b/src/api/basic/model/supplierModel.ts new file mode 100644 index 0000000..dfb5283 --- /dev/null +++ b/src/api/basic/model/supplierModel.ts @@ -0,0 +1,88 @@ +export interface SupplierResp { + id: number | string; + supplierName: string; + contact: string; + contactNumber: string; + phoneNumber: string; + address: string; + email: string; + status: number; + firstQuarterAccountReceivable: number; + secondQuarterAccountReceivable: number; + thirdQuarterAccountReceivable: number; + fourthQuarterAccountReceivable: number; + totalAccountReceivable: number; + firstQuarterAccountPayment: number; + secondQuarterAccountPayment: number; + thirdQuarterAccountPayment: number; + fourthQuarterAccountPayment: number; + totalAccountPayment: number; + fax: string; + taxNumber: string; + bankName: string; + accountNumber: string; + taxRate: string; + sort: number; + remark: string; + createTime: string; +} + +export interface AddSupplierReq { + supplierName: string; + contact: string; + contactNumber: string; + phoneNumber: string; + address: string; + email: string; + status: number; + firstQuarterAccountReceivable: number; + secondQuarterAccountReceivable: number; + thirdQuarterAccountReceivable: number; + fourthQuarterAccountReceivable: number; + firstQuarterAccountPayment: number; + secondQuarterAccountPayment: number; + thirdQuarterAccountPayment: number; + fourthQuarterAccountPayment: number; + fax: string; + taxNumber: string; + bankName: string; + accountNumber: string; + taxRate: string; + sort: number; + remark: string; +} + +export interface UpdateSupplierReq { + id: number | string; + supplierName: string; + contact: string; + contactNumber: string; + phoneNumber: string; + address: string; + email: string; + status: number; + firstQuarterAccountReceivable: number; + secondQuarterAccountReceivable: number; + thirdQuarterAccountReceivable: number; + fourthQuarterAccountReceivable: number; + totalAccountReceivable: number; + firstQuarterAccountPayment: number; + secondQuarterAccountPayment: number; + thirdQuarterAccountPayment: number; + fourthQuarterAccountPayment: number; + totalAccountPayment: number; + fax: string; + taxNumber: string; + bankName: string; + accountNumber: string; + taxRate: string; + sort: number; + remark: string; +} + +export interface QuerySupplierReq { + supplierName: string; + contact: string; + contactNumber: string; + phoneNumber: string; +} \ No newline at end of file diff --git a/src/api/basic/model/warehouseModel.ts b/src/api/basic/model/warehouseModel.ts new file mode 100644 index 0000000..7224241 --- /dev/null +++ b/src/api/basic/model/warehouseModel.ts @@ -0,0 +1,33 @@ +export interface WarehouseResp { + id: number | string; + warehouseManager: string; + warehouseName: string; + address: string; + price: number; + truckage: number; + type: number; + status: number; + remark: string; + sort: number; + isDefault: number; + createTime: string; +} + +export interface AddOrUpdateWarehouseReq { + id: number | string | undefined; + warehouseName: string; + warehouseManager: number; + address: string; + price: number; + truckage: number; + type: number; + isDefault: number; + status: number; + remark: string; + sort: number; +} + +export interface QueryWarehouseReq { + warehouseName: string; + remark: string; +} \ No newline at end of file diff --git a/src/api/basic/operator.ts b/src/api/basic/operator.ts new file mode 100644 index 0000000..cbb9880 --- /dev/null +++ b/src/api/basic/operator.ts @@ -0,0 +1,68 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + OperatorResp, + AddOrUpdateOperatorReq, + QueryOperatorReq +} from "@/api/basic/model/operatorModel"; + + +enum API { + PageList = '/basic/operator/pageList', + AddOrUpdateOperator = '/basic/operator/addOrUpdate', + DeleteBatch = '/basic/operator/delete', + UpdateStatus = '/basic/operator/updateStatus', + List = '/basic/operator/list', +} + +export function getOperatorPageList(params: QueryOperatorReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateOperator(params: AddOrUpdateOperatorReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateOperator, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateOperatorStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchOperator(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.delete( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getOperatorList(type: string) { + return defHttp.get>( + { + url: `${API.List}/${type}`, + } + ); +} \ No newline at end of file diff --git a/src/api/basic/supplier.ts b/src/api/basic/supplier.ts new file mode 100644 index 0000000..3d26689 --- /dev/null +++ b/src/api/basic/supplier.ts @@ -0,0 +1,94 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + SupplierResp, + AddSupplierReq, + UpdateSupplierReq, + QuerySupplierReq +} from "@/api/basic/model/supplierModel"; + + +enum API { + PageList = '/basic/supplier/pageList', + List = '/basic/supplier/list', + AddSupplier = '/basic/supplier/add', + UpdateSupplier = '/basic/supplier/update', + DeleteBatch = '/basic/supplier/deleteBatch', + UpdateStatus = '/basic/supplier/updateStatus', + Export = '/basic/supplier/export', +} + +export function getSupplierPageList(params: QuerySupplierReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function getSupplierList() { + return defHttp.get>( + { + url: API.List + } + ); +} + +export function addSupplier(params: AddSupplierReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddSupplier, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateSupplier(params: UpdateSupplierReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.UpdateSupplier, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateSupplierStatus(params: { ids: number[], status: number }, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.UpdateStatus, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchSuppliers(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.delete( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function exportSupplier(params: QuerySupplierReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/basic/warehouse.ts b/src/api/basic/warehouse.ts new file mode 100644 index 0000000..c513998 --- /dev/null +++ b/src/api/basic/warehouse.ts @@ -0,0 +1,86 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + WarehouseResp, + AddOrUpdateWarehouseReq, + QueryWarehouseReq +} from "@/api/basic/model/warehouseModel"; + + +enum API { + PageList = '/basic/warehouse/pageList', + AddOrUpdateWarehouse = '/basic/warehouse/addOrUpdate', + DeleteBatch = '/basic/warehouse/delete', + UpdateStatus = '/basic/warehouse/updateStatus', + GetWarehouse = '/basic/warehouse/getWarehouse', + List = '/basic/warehouse/list', + GetDefaultWarehouse = '/basic/warehouse/getDefaultWarehouse', +} + +export function getWarehousePageList(params: QueryWarehouseReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateWarehouse(params: AddOrUpdateWarehouseReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateWarehouse, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateWarehouseStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchWarehouse(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.delete( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getWarehouse() { + return defHttp.get>( + { + url: API.GetWarehouse, + } + ); +} + +export function getWarehouseList() { + return defHttp.get>( + { + url: API.List, + } + ); +} + +export function getDefaultWarehouse() { + return defHttp.get>( + { + url: API.GetDefaultWarehouse, + } + ); +} \ No newline at end of file diff --git a/src/api/financial/account.ts b/src/api/financial/account.ts new file mode 100644 index 0000000..966e765 --- /dev/null +++ b/src/api/financial/account.ts @@ -0,0 +1,68 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AccountResp, + AddOrUpdateAccountReq, + QueryAccountReq +} from "@/api/financial/model/accountModel"; + + +enum API { + PageList = '/financial/account/pageList', + AddOrUpdateAccount = '/financial/account/addOrUpdate', + DeleteBatch = '/financial/account/delete', + UpdateStatus = '/financial/account/updateStatus', + List = '/financial/account/list', +} + +export function getAccountPageList(params: QueryAccountReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateAccount(params: AddOrUpdateAccountReq, mode: ErrorMessageMode = 'notice', successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateAccountStatus(ids: number[], status: number, mode: ErrorMessageMode = 'notice', successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchAccount(ids: number[], mode: ErrorMessageMode = 'notice', successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.delete( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getAccountList() { + return defHttp.get>( + { + url: API.List, + } + ); +} \ No newline at end of file diff --git a/src/api/financial/advance.ts b/src/api/financial/advance.ts new file mode 100644 index 0000000..c340619 --- /dev/null +++ b/src/api/financial/advance.ts @@ -0,0 +1,96 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AdvanceChargeResp, + AddOrUpdateAdvanceReq, + QueryAdvanceReq, AdvanceChargeDetailResp, +} from "@/api/financial/model/advanceModel"; + +enum API { + PageList = '/financial/advance-charge/pageList', + AddOrUpdateAccount = '/financial/advance-charge/addOrUpdate', + DeleteBatch = '/financial/advance-charge/deleteByIds', + UpdateStatus = '/financial/advance-charge/updateStatusByIds', + GetDetail = '/financial/advance-charge/getDetailById', + Export = '/financial/advance-charge/export', + ExportDetail = '/financial/advance-charge/exportDetail', +} + +export function getAdvancePageList(params: QueryAdvanceReq, errorMode: ErrorMessageMode = 'message') { + return defHttp.post>( + { + url: API.PageList, + params, + }, + { + errorMessageMode: errorMode, + }, + ); +} + +export function addOrUpdateAdvance(params: AddOrUpdateAdvanceReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateAdvanceStatus(ids: number[] | string[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function deleteBatchAdvance(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function getAdvanceDetail(id: number | string, mode: ErrorMessageMode = 'notice') { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + { + errorMessageMode: mode, + }, + ); +} + +export function exportAdvance(params: QueryAdvanceReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportAdvanceDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/financial/collection.ts b/src/api/financial/collection.ts new file mode 100644 index 0000000..55c51a6 --- /dev/null +++ b/src/api/financial/collection.ts @@ -0,0 +1,99 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddOrUpdateCollectionReq, + QueryCollectionReq, + CollectionResp, + CollectionDetailResp, QuerySaleArrearsReq, SaleArrearsResp, +} from "@/api/financial/model/collectionModel"; + +enum API { + PageList = '/financial/collection/pageList', + AddOrUpdateAccount = '/financial/collection/addOrUpdate', + DeleteBatch = '/financial/collection/deleteByIds', + UpdateStatus = '/financial/collection/updateStatusByIds', + GetDetail = '/financial/collection/getDetailById', + GetArrearsPage = '/sale/arrears/pageList', + Export = '/financial/collection/export', + ExportDetail = '/financial/collection/exportDetail', +} + +export function getCollectionPageList(params: QueryCollectionReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateCollection(params: AddOrUpdateCollectionReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateCollectionStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchCollection(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getCollectionDetailById(id: number) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + ); +} + +export function getArrearsPageList(params: QuerySaleArrearsReq) { + return defHttp.post>( + { + url: API.GetArrearsPage, + params, + } + ); +} + +export function exportCollection(params: QueryCollectionReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportCollectionDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/financial/expense.ts b/src/api/financial/expense.ts new file mode 100644 index 0000000..95ecb90 --- /dev/null +++ b/src/api/financial/expense.ts @@ -0,0 +1,89 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddOrUpdateExpenseReq, + QueryExpenseReq, + ExpenseResp, + ExpenseDetailResp, +} from "@/api/financial/model/expenseModel"; + +enum API { + PageList = '/financial/expense/pageList', + AddOrUpdateAccount = '/financial/expense/addOrUpdate', + DeleteBatch = '/financial/expense/deleteByIds', + UpdateStatus = '/financial/expense/updateStatusByIds', + GetDetail = '/financial/expense/getDetailById', + Export = '/financial/expense/export', + ExportDetail = '/financial/expense/exportDetail', +} + +export function getExpensePageList(params: QueryExpenseReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateExpense(params: AddOrUpdateExpenseReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateExpenseStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchExpense(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getExpenseDetailById(id: number) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + ); +} + +export function exportExpense(params: QueryExpenseReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportExpenseDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/financial/income.ts b/src/api/financial/income.ts new file mode 100644 index 0000000..7566be0 --- /dev/null +++ b/src/api/financial/income.ts @@ -0,0 +1,88 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + IncomeDetailResp, + AddOrUpdateIncomeReq, + QueryIncomeReq, IncomeResp, +} from "@/api/financial/model/incomeModel"; + +enum API { + PageList = '/financial/income/pageList', + AddOrUpdateAccount = '/financial/income/addOrUpdate', + DeleteBatch = '/financial/income/deleteByIds', + UpdateStatus = '/financial/income/updateStatusByIds', + GetDetail = '/financial/income/getDetailById', + Export = '/financial/income/export', + ExportDetail = '/financial/income/exportDetail', +} + +export function getIncomePageList(params: QueryIncomeReq, mode: ErrorMessageMode = 'notice') { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateIncome(params: AddOrUpdateIncomeReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateIncomeStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchIncome(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getIncomeDetailById(id: number) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + ); +} + +export function exportIncome(params: QueryIncomeReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportIncomeDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/financial/model/accountModel.ts b/src/api/financial/model/accountModel.ts new file mode 100644 index 0000000..08283a4 --- /dev/null +++ b/src/api/financial/model/accountModel.ts @@ -0,0 +1,29 @@ +export interface AccountResp { + id: number | string; + accountNumber: string; + accountName: string; + initialAmount: number; + currentAmount: number; + isDefault: number; + status: number; + sort: number; + remark: string; + createTime: string; +} + +export interface AddOrUpdateAccountReq { + id: number | string | undefined; + accountNumber: string; + accountName: string; + initialAmount: number; + currentAmount: number; + isDefault: number; + status: number; + sort: number; + remark: string; +} + +export interface QueryAccountReq { + accountNumber: string; + accountName: string; +} \ No newline at end of file diff --git a/src/api/financial/model/advanceModel.ts b/src/api/financial/model/advanceModel.ts new file mode 100644 index 0000000..871e641 --- /dev/null +++ b/src/api/financial/model/advanceModel.ts @@ -0,0 +1,65 @@ +export interface FileData { + id: number | string; + uid: number | string; + fileName: string; + fileUrl: string; + fileType: string; + fileSize: number; +} + +export interface AdvanceChargeData { + accountId: number | string; + accountName: string; + amount: number; + remark: string; +} + +export interface AddOrUpdateAdvanceReq { + id: number | string | undefined; + memberId: number | string; + receiptDate: string; + receiptNumber: string; + financialPersonnelId: number | string; + totalAmount: number; + collectedAmount: number; + remark: string; + tableData: AdvanceChargeData[]; + fileDataList: FileData[]; + review: number; +} + +export interface QueryAdvanceReq { + receiptNumber: string; + memberId: number | string; + operatorId: number | string; + financialPersonnelId: number | string; + status: number; + remark: string; +} + +export interface AdvanceChargeResp { + id: number | string; + memberName: string; + receiptNumber: string; + receiptDate: string; + operator: string; + financialPersonnel: string; + totalAmount: number; + collectedAmount: number; + status: number; + remark: string; +} + +export interface AdvanceChargeDetailResp { + memberId: string; + memberName: string; + receiptNumber: string; + receiptDate: string; + financialPersonnel: string; + financialPersonnelId: string; + remark: string; + totalAmount: number; + collectedAmount: number; + tableData: AdvanceChargeData[]; + files: FileData[]; +} \ No newline at end of file diff --git a/src/api/financial/model/collectionModel.ts b/src/api/financial/model/collectionModel.ts new file mode 100644 index 0000000..5921c43 --- /dev/null +++ b/src/api/financial/model/collectionModel.ts @@ -0,0 +1,86 @@ +import {FileData} from "@/api/financial/model/advanceModel"; + +export interface CollectionData { + collectionId: number | string; + saleReceiptNumber: string | undefined; + receivableArrears: number; + receivedArrears: number; + thisCollectionAmount: number; + remark: string; +} + +export interface AddOrUpdateCollectionReq { + id: number | undefined; + customerId: number; + receiptDate: string; + receiptNumber: string; + financialPersonId: number; + collectionAccountId: number; + totalCollectionAmount: number; + discountAmount: number; + actualCollectionAmount: number; + remark: string; + status: number; + files: FileData[]; + tableData: CollectionData[]; +} + +export interface QueryCollectionReq { + receiptNumber: string; + financialPersonId: number; + saleReceiptNumber: string; + customerId: number; + accountId: number; + status: number; + remark: string; +} + +export interface CollectionResp { + id: string | undefined; + customerName: string; + receiptNumber: string; + receiptDate: string; + financialPerson: string; + collectionAccountName: string; + totalCollectionAmount: number; + discountAmount: number; + actualCollectionAmount: number; + remark: string; + status: number; +} + +export interface CollectionDetailResp { + id: string; + customerId: number; + customerName: string; + receiptDate: string; + receiptNumber: string; + financialPersonId: number; + financialPersonName: string; + collectionAccountId: number; + collectionAccountName: string; + totalCollectionAmount: number; + discountAmount: number; + actualCollectionAmount: number; + remark: string; + status: number; + files: FileData[]; + tableData: CollectionData[]; +} + +export interface QuerySaleArrearsReq { + customerId: number; + receiptNumber: string; + productInfo: string; +} + +export interface SaleArrearsResp { + customerName: string; + receiptNumber: string; + receiptDate: string; + productInfo: string; + operatorName: string; + thisReceiptArrears: number; + receivedArrears: number; + receivableArrears: number; +} \ No newline at end of file diff --git a/src/api/financial/model/expenseModel.ts b/src/api/financial/model/expenseModel.ts new file mode 100644 index 0000000..f87d98d --- /dev/null +++ b/src/api/financial/model/expenseModel.ts @@ -0,0 +1,58 @@ +import {FileData} from "@/api/financial/model/advanceModel"; + +export interface ExpenseData { + accountId: number | string; + accountName: string | undefined; + amount: number; + remark: string; + incomeExpenseId: string | number; + incomeExpenseAmount: number; +} + +export interface AddOrUpdateExpenseReq { + id: number | undefined; + relatedPersonId: number; + receiptDate: string; + receiptNumber: string; + financialPersonId: number; + expenseAccountId: number; + expenseAmount: number; + remark: string; + status: number; + files: FileData[]; + tableData: ExpenseData[]; +} + +export interface QueryExpenseReq { + receiptNumber: string; + relatedPersonId: number; + financialPersonId: number; + accountId: number; + status: number; + remark: string; +} + +export interface ExpenseResp { + id: string | undefined; + name: string; + receiptNumber: string; + receiptDate: string; + financialPerson: string; + expenseAccountName: string; + expenseAmount: number; + remark: string; + status: number; +} + +export interface ExpenseDetailResp { + id: string | undefined; + relatedPersonId: number; + receiptDate: string; + receiptNumber: string; + financialPersonId: number; + expenseAccountId: number; + expenseAmount: number; + remark: string; + files: FileData[]; + tableData: ExpenseData[]; +} \ No newline at end of file diff --git a/src/api/financial/model/incomeModel.ts b/src/api/financial/model/incomeModel.ts new file mode 100644 index 0000000..215979e --- /dev/null +++ b/src/api/financial/model/incomeModel.ts @@ -0,0 +1,58 @@ +import {FileData} from "@/api/financial/model/advanceModel"; + +export interface IncomeData { + accountId: number | string; + accountName: string | undefined; + amount: number; + remark: string; + incomeExpenseId: string | number; + incomeExpenseAmount: number; +} + +export interface AddOrUpdateIncomeReq { + id: number | undefined; + relatedPersonId: number; + receiptDate: string; + receiptNumber: string; + financialPersonId: number; + incomeAccountId: number; + incomeAmount: number; + remark: string; + status: number; + files: FileData[]; + tableData: IncomeData[]; +} + +export interface QueryIncomeReq { + receiptNumber: string; + relatedPersonId: number; + financialPersonId: number; + accountId: number; + status: number; + remark: string; +} + +export interface IncomeResp { + id: string | undefined; + name: string; + receiptNumber: string; + receiptDate: string; + financialPerson: string; + incomeAccountName: string; + incomeAmount: number; + remark: string; + status: number; +} + +export interface IncomeDetailResp { + id: string | undefined; + relatedPersonId: number; + receiptDate: string; + receiptNumber: string; + financialPersonId: number; + incomeAccountId: number; + incomeAmount: number; + remark: string; + files: FileData[]; + tableData: IncomeData[]; +} \ No newline at end of file diff --git a/src/api/financial/model/paymentModel.ts b/src/api/financial/model/paymentModel.ts new file mode 100644 index 0000000..09162d5 --- /dev/null +++ b/src/api/financial/model/paymentModel.ts @@ -0,0 +1,87 @@ +import {FileData} from "@/api/financial/model/advanceModel"; + +export interface PaymentData { + paymentId: number | string; + purchaseReceiptNumber: string | undefined; + paymentArrears: number; + prepaidArrears: number; + thisPaymentAmount: number; + remark: string; +} + +export interface AddOrUpdatePaymentReq { + id: number | undefined; + supplierId: number; + receiptDate: string; + receiptNumber: string; + financialPersonId: number; + paymentAccountId: number; + totalPaymentAmount: number; + discountAmount: number; + actualPaymentAmount: number; + remark: string; + status: number; + files: FileData[]; + tableData: PaymentData[]; +} + +export interface QueryPaymentReq { + receiptNumber: string; + financialPersonId: number; + purchaseReceiptNumber: string; + supplierId: number; + accountId: number; + status: number; + remark: string; +} + +export interface PaymentResp { + id: string | undefined; + supplierName: string; + receiptNumber: string; + receiptDate: string; + financialPerson: string; + paymentAccountName: string; + totalPaymentAmount: number; + discountAmount: number; + actualPaymentAmount: number; + remark: string; + status: number; +} + +export interface PaymentDetailResp { + id: string; + supplierId: number; + supplierName: string; + receiptDate: string; + receiptNumber: string; + financialPersonId: number; + financialPersonName: string; + paymentAccountId: number; + paymentAccountName: string; + totalPaymentAmount: number; + discountAmount: number; + actualPaymentAmount: number; + remark: string; + status: number; + files: FileData[]; + tableData: PaymentData[]; +} + +export interface QueryPaymentArrearsReq { + supplierId: number; + receiptNumber: string; + productInfo: string; +} + +export interface PaymentArrearsResp { + id: string; + supplierName: string; + receiptNumber: string; + receiptDate: string; + productInfo: string; + operatorName: string; + thisReceiptArrears: number; + prepaidArrears: number; + paymentArrears: number; +} \ No newline at end of file diff --git a/src/api/financial/model/transferModel.ts b/src/api/financial/model/transferModel.ts new file mode 100644 index 0000000..77c0d26 --- /dev/null +++ b/src/api/financial/model/transferModel.ts @@ -0,0 +1,54 @@ +import {FileData} from "@/api/financial/model/advanceModel"; + +export interface TransferData { + accountId: number | string; + accountName: string | undefined; + transferAmount: number; + remark: string; +} + +export interface AddOrUpdateTransferReq { + id: number | undefined; + receiptDate: string; + receiptNumber: string; + financialPersonId: number; + paymentAccountId: number; + paymentAmount: number; + remark: string; + status: number; + files: FileData[]; + tableData: TransferData[]; +} + +export interface QueryTransferReq { + receiptNumber: string; + financialPersonId: number; + accountId: number; + status: number; + remark: string; +} + +export interface TransferResp { + id: string | undefined; + receiptNumber: string; + receiptDate: string; + financialPerson: string; + paymentAccountName: string; + paymentAmount: number; + remark: string; + status: number; +} + +export interface TransferDetailResp { + receiptDate: string; + receiptNumber: string; + financialPersonId: number; + financialPersonName: string; + paymentAccountId: number; + paymentAccountName: string; + paymentAmount: number; + remark: string; + status: number; + files: FileData[]; + tableData: TransferData[]; +} \ No newline at end of file diff --git a/src/api/financial/payment.ts b/src/api/financial/payment.ts new file mode 100644 index 0000000..41d77be --- /dev/null +++ b/src/api/financial/payment.ts @@ -0,0 +1,101 @@ +import {defHttp} from '@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddOrUpdatePaymentReq, + QueryPaymentReq, + PaymentResp, + PaymentDetailResp, + QueryPaymentArrearsReq, + PaymentArrearsResp, +} from "@/api/financial/model/paymentModel"; + +enum API { + PageList = '/financial/payment/pageList', + AddOrUpdateAccount = '/financial/payment/addOrUpdate', + DeleteBatch = '/financial/payment/deleteByIds', + UpdateStatus = '/financial/payment/updateStatusByIds', + GetDetail = '/financial/payment/getDetailById', + GetArrearsPage = '/purchase/arrears/pageList', + Export = '/financial/payment/export', + ExportDetail = '/financial/payment/exportDetail', +} + +export function getPaymentPageList(params: QueryPaymentReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdatePayment(params: AddOrUpdatePaymentReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updatePaymentStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchPayment(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getPaymentDetailById(id: number) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + ); +} + +export function getArrearsPageList(params: QueryPaymentArrearsReq) { + return defHttp.post>( + { + url: API.GetArrearsPage, + params, + } + ); +} + +export function exportPayment(params: QueryPaymentReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportPaymentDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/financial/transfer.ts b/src/api/financial/transfer.ts new file mode 100644 index 0000000..f7a0e9e --- /dev/null +++ b/src/api/financial/transfer.ts @@ -0,0 +1,89 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + TransferDetailResp, + AddOrUpdateTransferReq, + QueryTransferReq, + TransferResp, +} from "@/api/financial/model/transferModel"; + +enum API { + PageList = '/financial/transfer/pageList', + AddOrUpdateAccount = '/financial/transfer/addOrUpdate', + DeleteBatch = '/financial/transfer/deleteByIds', + UpdateStatus = '/financial/transfer/updateStatusByIds', + GetDetail = '/financial/transfer/getDetailById', + Export = '/financial/transfer/export', + ExportDetail = '/financial/transfer/exportDetail', +} + +export function getTransferPageList(params: QueryTransferReq, mode: ErrorMessageMode = 'notice') { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateTransfer(params: AddOrUpdateTransferReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateTransferStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchTransfer(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getTransferDetailById(id: number) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + ); +} + +export function exportTransfer(params: QueryTransferReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportTransferDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/model/baseModel.ts b/src/api/model/baseModel.ts new file mode 100644 index 0000000..43a33ab --- /dev/null +++ b/src/api/model/baseModel.ts @@ -0,0 +1,25 @@ +export interface BasicPageParams { + page: number; + pageSize: number; +} + +export interface BasicFetchResult { + items: T[]; + total: number; +} + +export interface BaseDataResp { + code: string; + msg: string; + data: T; +} + +export interface BaseResp { + code?: string; + msg: string; +} + +export interface BaseListResp { + data: T[]; + total: number; +} diff --git a/src/api/product/model/productAttributeModel.ts b/src/api/product/model/productAttributeModel.ts new file mode 100644 index 0000000..0a82fac --- /dev/null +++ b/src/api/product/model/productAttributeModel.ts @@ -0,0 +1,30 @@ +/** + * Although it seems that the parameters of the two objects are very similar here, + * there is no guarantee that new fields will be added to the view object return in the future. For extension purposes, + * it is still necessary to distinguish between them + * + * @author James + * @since 2023-10-08 17:27 + */ + +export interface ProductAttributeResp { + id: number | string; + attributeName: string; + attributeValue: string; + remark: string; + sort: number; +} + +export interface AddOrUpdateProductAttributeReq { + id: number | string; + attributeName: string; + attributeValue: string; + remark: string; + sort: number; +} + +export interface ProductAttributeListReq { + attributeName: string | undefined; + page: number; + pageSize: number; +} \ No newline at end of file diff --git a/src/api/product/model/productCategoryModel.ts b/src/api/product/model/productCategoryModel.ts new file mode 100644 index 0000000..823488a --- /dev/null +++ b/src/api/product/model/productCategoryModel.ts @@ -0,0 +1,24 @@ +export interface ProductCategoryResp { + id: number | string; + parentId: number | string; + parentName: string; + categoryName: string; + categoryNumber: string; + remark: string; + sort: number; + createTime: string; + children?: ProductCategoryResp[]; +} + +export interface AddOrUpdateProductCategoryReq { + id: number | string; + parentId: number | string; + categoryName: string; + categoryNumber: number; + remark: string; + sort: number; +} + +export interface ProductCategoryListReq { + categoryName: string; +} \ No newline at end of file diff --git a/src/api/product/model/productModel.ts b/src/api/product/model/productModel.ts new file mode 100644 index 0000000..dd31e37 --- /dev/null +++ b/src/api/product/model/productModel.ts @@ -0,0 +1,183 @@ +export interface AddProductStockReq { + productStockId: number | string; + warehouseId: number | string; + warehouseName: string; + initStockQuantity: number; + lowStockQuantity: number; + highStockQuantity: number; +} + +export interface AddProductPriceReq { + productPriceId: number | string; + barCode: number; + productUnit: string; + multiAttribute: string; + purchasePrice: number; + retailPrice: number; + salesPrice: number; + lowSalesPrice: number; +} + +export interface AddProductImageReq { + productImageId: number | string | null; + uid: string | null; + type: string | null | undefined; + status: string | null | undefined; + imageName: string | null; + imageUrl: string | null; + imageSize: number | null | undefined; +} + +export interface AddProductReq { + productId: number | string; + productName: string; + productStandard: string; + productModel: string + productUnit: string + productUnitId: number | string; + productColor: string + productWeight: number | string; + productExpiryNum: number | string; + productCategoryId: number | string; + enableSerialNumber: number | string; + enableBatchNumber: number | string; + warehouseShelves: string + remark: string + productManufacturer: string + otherFieldOne: string + otherFieldTwo: string + otherFieldThree: string + priceList: AddProductPriceReq[]; + stockList: AddProductStockReq[]; + imageList: AddProductImageReq[]; +} + +export interface QueryProductReq { + productCategoryId: number | string + keywords: string + productColor: string + extendInfo: string + remark: string + warehouseShelves: string + status: number + enableSerialNumber: number + enableBatchNumber: number +} + +export interface ProductStockSkuReq { + warehouseId: number | string; + productInfo: string; + productCategoryId: number | string; + warehouseShelves: string; + isExportDetail: boolean; +} + +export interface ProductInfoDetailResp { + productId: string; + productCategoryId: string; + productUnitId: string; + productUnit: string; + productName: string; + productStandard: string; + productModel: string; + productColor: string; + productWeight: number; + productExpiryNum: number; + productCategoryName: string; + enableSerialNumber: number; + enableBatchNumber: number; + warehouseShelves: string; + productManufacturer: string; + otherFieldOne: string; + otherFieldTwo: string; + otherFieldThree: string; + remark: string; + priceList: ProductPriceResp[]; + imageList: ProductImageResp[]; +} + +export interface ProductImageResp { + productImageId: string; + imageName: string; + imageUrl: string; +} + +export interface ProductPriceResp { + productPriceId: string; + barCode: number; + productUnit: string; + multiAttribute: string; + purchasePrice: number; + retailPrice: number; + salesPrice: number; + lowSalesPrice: number; + stockList: ProductStockResp[]; +} + +export interface ProductStockSkuResp { + id: string; + productId: string; + warehouseId: string; + productBarcode: string; + warehouseName: string; + productName: string; + productCategoryName: string; + productStandard: string; + productModel: string; + productColor: string; + productUnit: string; + warehouseShelves: string; + productWeight: number; + unitPrice: number; + retailPrice: number; + salePrice: number; + purchasePrice: number; + initialStock: number; + currentStock: number; + stockAmount: number; +} + +export interface ProductStockResp { + productStockId: number | string; + warehouseId: number | string; + warehouseName: string; + initStockQuantity: number; + lowStockQuantity: number; + highStockQuantity: number; +} + +export interface UpdateBatchProductInfoReq { + productIds: number[]; + productCategoryId: number | string; + productColor: string; + productWeight: number; + productExpiryNum: number; + enableSerialNumber: string; + enableBatchNumber: string; + remark: string; +} + +export interface QueryProductExtendPriceReq { + productCategoryId: number | string; + warehouseId: number | string; + productName: string; + enableSerialNumber: number; + enableBatchNumber: number; +} + +export interface ProductExtendPriceResp { + id: number | string; + productId: number | string; + productCategoryId: number | string; + warehouseId: number | string; + barCode: string; + productName: string; + productStandard: string; + productModel: string; + productColor: string; + productUnit: string; + multiAttribute: string; + stock: number; + extendInfo: string; + retailPrice: number; +} \ No newline at end of file diff --git a/src/api/product/model/productUnitModel.ts b/src/api/product/model/productUnitModel.ts new file mode 100644 index 0000000..f23b9ed --- /dev/null +++ b/src/api/product/model/productUnitModel.ts @@ -0,0 +1,28 @@ +export interface ProductUnitResp { + id: number | string; + computeUnit: string; + basicUnit: string; + otherUnit: string; + otherUnitTwo: string; + otherUnitThree: number; + status: number; + createTime: string; +} + +export interface AddOrUpdateProductUnitReq { + id: number | string; + basicUnit: string; + otherUnit: string; + otherUnitTwo: string; + otherUnitThree: string; + ratio: number; + ratioTwo: number; + ratioThree: number; + status: number; +} + +export interface ProductUnitQueryReq { + computeUnit: string | undefined; + page: number; + pageSize: number; +} \ No newline at end of file diff --git a/src/api/product/product.ts b/src/api/product/product.ts new file mode 100644 index 0000000..4b85a3e --- /dev/null +++ b/src/api/product/product.ts @@ -0,0 +1,137 @@ +import {defHttp} from '@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddProductReq, + ProductInfoDetailResp, + QueryProductReq, + UpdateBatchProductInfoReq, + ProductExtendPriceResp, + QueryProductExtendPriceReq, ProductStockSkuResp, +} from "@/api/product/model/productModel"; +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; + +enum Api { + getProductCode = '/product/getProductCode', + addProduct = '/product/addOrUpdateProduct', + getProductInfo = '/product/getProductInfo', + getProductInfoDetail = '/product/getProductInfoDetail', + deleteProduct = '/product/deleteProduct', + updateProductStatus = '/product/updateProductStatus', + updateBatchProductInfo = '/product/updateBatchProductInfo', + getProductSku = '/product/sku/pageList', + getProductSkuByBarCode = '/product/sku/getProduct', + getProductListInfo = '/product/sku/productStockSku', + exportProductData = '/product/export' +} + +export function getProductCode() { + return defHttp.get>( + { + url: Api.getProductCode, + } + ); +} + +export function addOrUpdateProduct(params: AddProductReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: Api.addProduct, + params + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function getProductInfo(params: QueryProductReq) { + return defHttp.post( + { + url: Api.getProductInfo, + params + }, + ); +} + +export function getProductInfoDetail(productId: number) { + return defHttp.get>( + { + url: `${Api.getProductInfoDetail}/${productId}`, + } + ); +} + +export function deleteProduct(productIds: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.delete( + { + url: `${Api.deleteProduct}/${productIds}`, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function updateProductStatus(productIds: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${Api.updateProductStatus}/${productIds}/${status}`, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function updateBatchProductInfo(params: UpdateBatchProductInfoReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: Api.updateBatchProductInfo, + params + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function getProductSkuPage(params: QueryProductExtendPriceReq) { + return defHttp.post( + { + url: Api.getProductSku, + params + } + ); +} + +export function getProductSkuByBarCode(barCode: number | string, warehouseId: number | string) { + return defHttp.get>( + { + url: `${Api.getProductSkuByBarCode}/${barCode}/${warehouseId}`, + } + ); +} + +export function getProductStockSku() { + return defHttp.post>( + { + url: Api.getProductListInfo, + timeout: 100000, + } + ); +} + +export function exportProduct(params: QueryProductReq) { + return defHttp.get>( + { + url: `${Api.exportProductData}`, + params, + responseType: "blob", + timeout: 100000, // 设置超时时间为100秒 + } + ); +} \ No newline at end of file diff --git a/src/api/product/productAttribute.ts b/src/api/product/productAttribute.ts new file mode 100644 index 0000000..dc375a1 --- /dev/null +++ b/src/api/product/productAttribute.ts @@ -0,0 +1,52 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import {AddOrUpdateProductAttributeReq, ProductAttributeResp, ProductAttributeListReq} from "@/api/product/model/productAttributeModel"; + +enum Api { + List = '/product/attribute/list', + addOrUpdate = '/product/attribute/addOrUpdate', + deleteBatch = '/product/attribute/deleteBatch', + GetAttributeById = '/product/attribute/getValuesById', +} + +export function getAttributeList(params: ProductAttributeListReq) { + return defHttp.post>( + { + url: Api.List, + params, + } + ); +} + +export function addOrUpdateAttribute(params: AddOrUpdateProductAttributeReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: Api.addOrUpdate, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchAttribute(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.delete( + { + url: `${Api.deleteBatch}?ids=${ids}` + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function getAttributeById(id: number) { + return defHttp.get>( + { + url: `${Api.GetAttributeById}?id=${id}` + } + ); +} \ No newline at end of file diff --git a/src/api/product/productCategory.ts b/src/api/product/productCategory.ts new file mode 100644 index 0000000..790b7da --- /dev/null +++ b/src/api/product/productCategory.ts @@ -0,0 +1,43 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp} from "@/api/model/baseModel"; +import {AddOrUpdateProductCategoryReq, ProductCategoryResp} from "@/api/product/model/productCategoryModel"; + +enum Api { + List = '/product/category/list', + addOrUpdate = '/product/category/addOrUpdate', + deleteBatch = '/product/category/deleteBatch', +} + +export function getCategoryList() { + return defHttp.get>( + { + url: Api.List, + } + ); +} + +export function addOrUpdateCategory(params: AddOrUpdateProductCategoryReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post>( + { + url: Api.addOrUpdate, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function deleteCategory(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post>( + { + url: `${Api.deleteBatch}?ids=${ids}`, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} \ No newline at end of file diff --git a/src/api/product/productUnit.ts b/src/api/product/productUnit.ts new file mode 100644 index 0000000..4808ee7 --- /dev/null +++ b/src/api/product/productUnit.ts @@ -0,0 +1,58 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import {AddOrUpdateProductUnitReq, ProductUnitResp, ProductUnitQueryReq} from "@/api/product/model/productUnitModel"; + +enum Api { + List = '/product/unit/list', + AddOrUpdate = '/product/unit/addOrUpdate', + DeleteBatch = '/product/unit/deleteBatch', + UpdateStatus = '/product/unit/updateUnitStatus', +} + +export function getUnitList(params: ProductUnitQueryReq) { + return defHttp.post>( + { + url: Api.List, + params, + } + ); +} + +export function addOrUpdateUnit(params: AddOrUpdateProductUnitReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: Api.AddOrUpdate, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchUnits(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.delete( + { + url: `${Api.DeleteBatch}?ids=${ids}` + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateUnitStatus(params: {id: number, status: number}, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: Api.UpdateStatus, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} \ No newline at end of file diff --git a/src/api/purchase/model/orderModel.ts b/src/api/purchase/model/orderModel.ts new file mode 100644 index 0000000..0fd1f63 --- /dev/null +++ b/src/api/purchase/model/orderModel.ts @@ -0,0 +1,82 @@ +import {FileData} from '/@/api/retail/model/shipmentsModel'; + +export interface QueryPurchaseOrderReq { + receiptNumber: string; + productInfo: string; + supplierId: number | string; + operatorId: number | string; + status: number; + remark: string; +} + +export interface PurchaseData { + warehouseId: number | string; + productId: number | string; + barCode: number | string; + productName: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + unitPrice: number; + purchasePrice: number; + amount: number; + taxRate: number; + taxAmount: number; + taxTotalPrice: number; + remark: string; +} + +export interface AddOrUpdateReceiptReq { + id: number | string | undefined; + supplierId: string; + receiptNumber: string; + receiptDate: string; + discountRate: number; + discountAmount: number; + discountLastAmount: number; + deposit: number; + accountId: number | string; + multipleAccountIds: number[]; + multipleAccountAmounts: number[]; + status: number; + remark: string; + tableData: PurchaseData[]; + files: FileData[]; +} + +export interface LinkReceiptDetailResp { + id: number | string | undefined; + supplierId: string; + supplierName: string; + receiptNumber: string; + receiptDate: string; + discountRate: number; + discountAmount: number; + discountLastAmount: number; + deposit: number; + accountId: number | string; + accountName: string; + multipleAccountIds: number[]; + multipleAccountAmounts: number[]; + status: number; + remark: string; + tableData: PurchaseData[]; + files: FileData[]; +} + +export interface PurchaseDetailData { + supplierId: number | string; + accountId: number; + receiptDate: string; + receiptNumber: string; + multipleAccountAmounts: number[]; + multipleAccountIds: number[]; + discountRate: number; + discountAmount: number; + discountLastAmount: number; + deposit: number; + remark: string; + tableData: PurchaseData[]; + files: FileData[]; +} \ No newline at end of file diff --git a/src/api/purchase/model/refundModel.ts b/src/api/purchase/model/refundModel.ts new file mode 100644 index 0000000..ade24d2 --- /dev/null +++ b/src/api/purchase/model/refundModel.ts @@ -0,0 +1,69 @@ +import {FileData} from '/@/api/retail/model/shipmentsModel'; + +export interface QueryPurchaseRefundReq { + receiptNumber: string; + productInfo: string; + supplierId: number | string; + operatorId: number | string; + status: number; + remark: string; +} + +export interface PurchaseRefundData { + warehouseId: number | string; + productId: number | string; + barCode: number | string; + productName: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + unitPrice: number; + amount: number; + taxRate: number; + taxAmount: number; + taxTotalPrice: number; + remark: string; +} + +export interface AddOrUpdatePurchaseRefundReq { + id: number | string | undefined; + supplierId: string; + receiptNumber: string; + receiptDate: string; + refundOfferRate: number; + refundOfferAmount: number; + refundLastAmount: number; + otherAmount: number; + otherReceipt: string; + thisRefundAmount: number; + thisArrearsAmount: number; + accountId: number | string; + multipleAccountIds: number[]; + multipleAccountAmounts: number[]; + status: number; + remark: string; + tableData: PurchaseRefundData[]; + files: FileData[]; +} + +export interface PurchaseRefundDetailData { + supplierId: number | string; + supplierName: string; + accountId: number; + accountName: string; + otherReceipt: string; + receiptDate: string; + receiptNumber: string; + multipleAccountAmounts: number[]; + multipleAccountIds: number[]; + refundOfferRate: number; + refundOfferAmount: number; + refundLastAmount: number; + otherAmount: number; + thisRefundAmount: number; + thisArrearsAmount: number; + remark: string; + tableData: PurchaseRefundData[]; + files: FileData[]; +} \ No newline at end of file diff --git a/src/api/purchase/model/storageModel.ts b/src/api/purchase/model/storageModel.ts new file mode 100644 index 0000000..587be27 --- /dev/null +++ b/src/api/purchase/model/storageModel.ts @@ -0,0 +1,68 @@ +import {FileData} from '/@/api/retail/model/shipmentsModel'; + +export interface QueryPurchaseStorageReq { + receiptNumber: string; + productInfo: string; + supplierId: number | string; + operatorId: number | string; + status: number; + remark: string; +} + +export interface PurchaseData { + warehouseId: number | string; + productId: number | string; + barCode: number | string; + productName: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + unitPrice: number; + amount: number; + taxRate: number; + taxAmount: number; + taxTotalPrice: number; + remark: string; +} + +export interface AddOrUpdatePurchaseStorageReq { + id: number | string | undefined; + supplierId: string; + receiptNumber: string; + receiptDate: string; + paymentRate: number; + paymentAmount: number; + paymentLastAmount: number; + otherAmount: number; + otherReceipt: string; + thisPaymentAmount: number; + thisArrearsAmount: number; + accountId: number | string; + multipleAccountIds: number[]; + multipleAccountAmounts: number[]; + status: number; + remark: string; + tableData: PurchaseData[]; + files: FileData[]; +} + +export interface PurchaseStorageDetailData { + supplierId: number | string; + supplierName: string; + accountId: number; + accountName: string; + receiptDate: string; + receiptNumber: string; + multipleAccountAmounts: number[]; + multipleAccountIds: number[]; + paymentRate: number; + paymentAmount: number; + paymentLastAmount: number; + otherAmount: number; + thisPaymentAmount: number; + thisArrearsAmount: number; + remark: string; + tableData: PurchaseData[]; + files: FileData[]; +} \ No newline at end of file diff --git a/src/api/purchase/order.ts b/src/api/purchase/order.ts new file mode 100644 index 0000000..b85ad5d --- /dev/null +++ b/src/api/purchase/order.ts @@ -0,0 +1,97 @@ +import {defHttp} from '@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + QueryPurchaseOrderReq, + AddOrUpdateReceiptReq, + PurchaseDetailData, LinkReceiptDetailResp +} from "@/api/purchase/model/orderModel" +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; + +enum API { + PageList = '/purchase/order/pageList', + AddOrUpdate = '/purchase/order/addOrUpdate', + GetDetail = '/purchase/order/detail', + UpdateStatus = '/purchase/order/updateStatus', + Delete = '/purchase/order/delete', + GetLinkOrderDetail = '/purchase/order/getLinkOrderDetail', + Export = '/purchase/order/export', + ExportDetail = '/purchase/order/exportDetail', +} + +export function getPurchaseOrderPageList(params: QueryPurchaseOrderReq) { + return defHttp.get>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdatePurchaseOrder(params: AddOrUpdateReceiptReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + { + url: API.AddOrUpdate, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getPurchaseOrderDetail(id: string) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}`, + } + ); +} + +export function getLinkOrderDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.GetLinkOrderDetail}/${receiptNumber}`, + } + ); +} + +export function updatePurchaseOrderStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.put( + { + url: `${API.UpdateStatus}/${ids}/${status}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deletePurchaseOrder(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.put( + { + url: `${API.Delete}/${ids}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function exportOrder(params: QueryPurchaseOrderReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportOrderDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/purchase/refund.ts b/src/api/purchase/refund.ts new file mode 100644 index 0000000..81b82e8 --- /dev/null +++ b/src/api/purchase/refund.ts @@ -0,0 +1,97 @@ +import {defHttp} from '@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + QueryPurchaseRefundReq, + AddOrUpdatePurchaseRefundReq, + PurchaseRefundDetailData +} from "@/api/purchase/model/refundModel" +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; + +enum API { + PageList = '/purchase/refund/pageList', + AddOrUpdate = '/purchase/refund/addOrUpdate', + GetDetail = '/purchase/refund/detail', + UpdateStatus = '/purchase/refund/updateStatus', + Delete = '/purchase/refund/delete', + GetLinkRefundDetail = '/purchase/refund/getLinkRefundDetail', + Export = '/purchase/refund/export', + ExportDetail = '/purchase/order/exportDetail', +} + +export function getPurchaseRefundPageList(params: QueryPurchaseRefundReq) { + return defHttp.get>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdatePurchaseRefund(params: AddOrUpdatePurchaseRefundReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + { + url: API.AddOrUpdate, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getPurchaseRefundDetail(id: string) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}`, + } + ); +} + +export function updatePurchaseRefundStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.put( + { + url: `${API.UpdateStatus}/${ids}/${status}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deletePurchaseRefund(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.put( + { + url: `${API.Delete}/${ids}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getLinkRefundDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.GetLinkRefundDetail}/${receiptNumber}`, + } + ); +} + +export function exportRefund(params: QueryPurchaseRefundReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportRefundDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/purchase/storage.ts b/src/api/purchase/storage.ts new file mode 100644 index 0000000..4b24ae1 --- /dev/null +++ b/src/api/purchase/storage.ts @@ -0,0 +1,97 @@ +import {defHttp} from '@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + QueryPurchaseStorageReq, + AddOrUpdatePurchaseStorageReq, + PurchaseStorageDetailData +} from "@/api/purchase/model/storageModel" +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; + +enum API { + PageList = '/purchase/storage/pageList', + AddOrUpdate = '/purchase/storage/addOrUpdate', + GetDetail = '/purchase/storage/detail', + UpdateStatus = '/purchase/storage/updateStatus', + Delete = '/purchase/storage/delete', + GetLinkStorageDetail = '/purchase/storage/getLinkStorageDetail', + Export = '/purchase/storage/export', + ExportDetail = '/purchase/order/exportDetail', +} + +export function getPurchaseStoragePageList(params: QueryPurchaseStorageReq) { + return defHttp.get>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdatePurchaseStorage(params: AddOrUpdatePurchaseStorageReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + { + url: API.AddOrUpdate, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getPurchaseStorageDetail(id: string) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}`, + } + ); +} + +export function updatePurchaseStorageStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.put( + { + url: `${API.UpdateStatus}/${ids}/${status}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deletePurchaseStorage(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.put( + { + url: `${API.Delete}/${ids}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getLinkStorageDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.GetLinkStorageDetail}/${receiptNumber}`, + } + ); +} + +export function exportStorage(params: QueryPurchaseStorageReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportStorageDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/receipt/model/receiptModel.ts b/src/api/receipt/model/receiptModel.ts new file mode 100644 index 0000000..834735f --- /dev/null +++ b/src/api/receipt/model/receiptModel.ts @@ -0,0 +1,37 @@ +export interface ReceiptDetailResp { + id: string; + productBarcode : string | number; + warehouseId: string; + productId: string; + productName : string; + productStandard : string; + productModel : string; + unit : string; + productNumber : number; + amount : number; + taxRate : number; + taxAmount : number; + taxIncludedAmount : number; + remark : string; +} + +export interface ReceiptResp { + id: string; + name : string; + uid: string; + receiptNumber : string; + productInfo : string; + receiptDate : string; + operator : string; + productNumber : number; + totalAmount : number; + taxRateTotalAmount : number | undefined; +} + +export interface queryReceipt { + id: string | number; + type: string; + subType: string; + receiptNumber: string; + productInfo: string; +} \ No newline at end of file diff --git a/src/api/receipt/receipt.ts b/src/api/receipt/receipt.ts new file mode 100644 index 0000000..0009af1 --- /dev/null +++ b/src/api/receipt/receipt.ts @@ -0,0 +1,26 @@ +import {defHttp} from '/@/utils/http/axios'; +import {BaseDataResp} from "@/api/model/baseModel"; +import {queryReceipt, ReceiptDetailResp, ReceiptResp} from "@/api/receipt/model/receiptModel" + +enum API { + GetOtherReceipt = '/receipt/otherReceipt', + GetOtherReceiptDetail = '/receipt/otherReceiptDetail', +} + +export function getReceipt(params: queryReceipt, type: string, subType: string) { + return defHttp.get>( + { + url: API.GetOtherReceipt, + params: params + } + ); +} + +export function getReceiptDetail(params: queryReceipt) { + return defHttp.get>( + { + url: API.GetOtherReceiptDetail, + params: params + } + ); +} \ No newline at end of file diff --git a/src/api/report/report.ts b/src/api/report/report.ts new file mode 100644 index 0000000..e20afa9 --- /dev/null +++ b/src/api/report/report.ts @@ -0,0 +1,359 @@ +import {defHttp} from '/@/utils/http/axios'; +import {BaseDataResp} from "@/api/model/baseModel"; +import { + ProductStockResp, + QueryProductStockReq, + RetailStatisticalResp, + ProductStockFlowResp, + QueryProductStockFlowReq, + QueryAccountStatisticsReq, + AccountStatisticsResp, + AccountFlowResp, + QueryRetailStatisticsReq, + RetailStatisticsResp, + QueryPurchaseStatisticsReq, + PurchaseStatisticsResp, + QuerySalesStatisticsReq, + SalesStatisticsResp, + QueryShipmentsDetailStatisticsReq, + ShipmentsDetailStatisticsResp, + QueryStorageDetailStatisticsReq, + StorageDetailStatisticsResp, + RelatedPersonResp, + QueryShipmentsSummaryStatisticsReq, + ShipmentsSummaryStatisticsResp, + QueryStorageSummaryStatisticsReq, + StorageSummaryStatisticsResp, + CustomerBillStatisticsResp, + QueryCustomerBillReq, + QueryCustomerBillDetailReq, + CustomerBillDetailStatisticsResp, + SupplierBillStatisticsResp, + QuerySupplierBillReq, QuerySupplierBillDetailReq, SupplierBillDetailStatisticsResp +} from "@/api/report/reportModel"; + +enum API { + GetStatisticalData = '/report/homePage/statistics', + GetProductStockData = '/report/productStock', + GetProductStockFlowData = '/report/productStockFlow', + GetAccountStatistics = '/report/accountStatistics', + GetAccountFlow = '/report/accountFlow', + GetRetailStatistics = '/report/retailStatistics', + GetPurchaseStatistics = '/report/purchaseStatistics', + GetSalesStatistics = '/report/salesStatistics', + GetShipmentsDetail = '/report/shipmentsDetail', + GetStorageDetail = '/report/storageDetail', + GetRelatedPerson = '/report/relatedPerson', + GetShipmentsSummary = '/report/shipmentsSummary', + GetStorageSummary = '/report/storageSummary', + GetCustomerBill = '/report/customerBill', + GetCustomerBillDetail = '/report/customerBillDetail', + GetSupplierBill = '/report/supplierBill', + GetSupplierBillDetail = '/report/supplierBillDetail', + ExportProductStockData = '/report/productStock/export', + ExportAccountStatistics = '/report/accountStatistics/export', + ExportRetailStatistics = '/report/retailStatistics/export', + ExportPurchaseStatistics = '/report/purchaseStatistics/export', + ExportSalesStatistics = '/report/salesStatistics/export', + ExportShipmentsDetail = '/report/shipmentsDetail/export', + ExportStorageDetail = '/report/storageDetail/export', + ExportShipmentsSummary = '/report/shipmentsSummary/export', + ExportStorageSummary = '/report/storageSummary/export', + ExportCustomerBill = '/report/customerBill/export', + ExportSupplierBill = '/report/supplierBill/export', + ExportProductStockFlowData = '/report/productStockFlow/export', + ExportCustomerBillDetail = '/report/customerBillDetail/export', + ExportSupplierBillDetail = '/report/supplierBillDetail/export', +} + + +export function getStatistical() { + return defHttp.get>( + { + url: API.GetStatisticalData, + }, + ); +} + +export function getProductStock(params: QueryProductStockReq) { + return defHttp.post>( + { + url: API.GetProductStockData, + params + } + ); +} + +export function getProductStockFlow(params: QueryProductStockFlowReq, productId: number) { + return defHttp.post>( + { + url: API.GetProductStockFlowData, + params + } + ); +} + +export function getAccountStatistics(params: QueryAccountStatisticsReq) { + return defHttp.post>( + { + url: API.GetAccountStatistics, + params + } + ); +} + +export function getAccountFlow(accountId: number) { + return defHttp.get>( + { + url: API.GetAccountFlow, + params: accountId + } + ); +} + +export function getRetailStatistics(params: QueryRetailStatisticsReq) { + return defHttp.post>( + { + url: API.GetRetailStatistics, + params + } + ); +} + +export function getPurchaseStatistics(params: QueryPurchaseStatisticsReq) { + return defHttp.post>( + { + url: API.GetPurchaseStatistics, + params + } + ); +} + +export function getSalesStatistics(params: QuerySalesStatisticsReq) { + return defHttp.post>( + { + url: API.GetSalesStatistics, + params + } + ); +} + +export function getShipmentsDetail(params: QueryShipmentsDetailStatisticsReq) { + return defHttp.post>( + { + url: API.GetShipmentsDetail, + params + } + ); +} + +export function getStorageDetail(params: QueryStorageDetailStatisticsReq) { + return defHttp.post>( + { + url: API.GetStorageDetail, + params + } + ); +} + +export function getRelatedPerson() { + return defHttp.get>( + { + url: API.GetRelatedPerson, + } + ); +} + +export function getShipmentsSummary(params: QueryShipmentsSummaryStatisticsReq) { + return defHttp.post>( + { + url: API.GetShipmentsSummary, + params + } + ); +} + +export function getStorageSummary(params: QueryStorageSummaryStatisticsReq) { + return defHttp.post>( + { + url: API.GetStorageSummary, + params + } + ); +} + +export function getCustomerBill(params: QueryCustomerBillReq) { + return defHttp.post>( + { + url: API.GetCustomerBill, + params + } + ); +} + +export function getCustomerBillDetail(params: QueryCustomerBillDetailReq) { + return defHttp.post>( + { + url: API.GetCustomerBillDetail, + params + } + ); +} + +export function getSupplierBill(params: QuerySupplierBillReq) { + return defHttp.post>( + { + url: API.GetSupplierBill, + params + } + ); +} + +export function getSupplierBillDetail(params: QuerySupplierBillDetailReq) { + return defHttp.post>( + { + url: API.GetSupplierBillDetail, + params + } + ); +} + +export function exportProductStock(params: QueryProductStockReq) { + return defHttp.get>( + { + url: `${API.ExportProductStockData}`, + params, + responseType: "blob" + } + ); +} + +export function exportAccountStatistics(params: QueryAccountStatisticsReq) { + return defHttp.get>( + { + url: `${API.ExportAccountStatistics}`, + params, + responseType: "blob" + } + ); +} + +export function exportRetailStatistics(params: QueryRetailStatisticsReq) { + return defHttp.get>( + { + url: `${API.ExportRetailStatistics}`, + params, + responseType: "blob" + } + ); +} + +export function exportPurchaseStatistics(params: QueryPurchaseStatisticsReq) { + return defHttp.get>( + { + url: `${API.ExportPurchaseStatistics}`, + params, + responseType: "blob" + } + ); +} + +export function exportSalesStatistics(params: QuerySalesStatisticsReq) { + return defHttp.get>( + { + url: `${API.ExportSalesStatistics}`, + params, + responseType: "blob" + } + ); +} + +export function exportShipmentsDetail(params: QueryShipmentsDetailStatisticsReq) { + return defHttp.get>( + { + url: `${API.ExportShipmentsDetail}`, + params, + responseType: "blob" + } + ); +} + +export function exportStorageDetail(params: QueryStorageDetailStatisticsReq) { + return defHttp.get>( + { + url: `${API.ExportStorageDetail}`, + params, + responseType: "blob" + } + ); +} + +export function exportShipmentsSummary(params: QueryShipmentsSummaryStatisticsReq) { + return defHttp.get>( + { + url: `${API.ExportShipmentsSummary}`, + params, + responseType: "blob" + } + ); +} + +export function exportStorageSummary(params: QueryStorageSummaryStatisticsReq) { + return defHttp.get>( + { + url: `${API.ExportStorageSummary}`, + params, + responseType: "blob" + } + ); +} + +export function exportCustomerBill(params: QueryCustomerBillReq) { + return defHttp.get>( + { + url: `${API.ExportCustomerBill}`, + params, + responseType: "blob" + } + ); +} + +export function exportSupplierBill(params: QuerySupplierBillReq) { + return defHttp.get>( + { + url: `${API.ExportSupplierBill}`, + params, + responseType: "blob" + } + ); +} + +export function exportStockFlow(params: QueryProductStockFlowReq) { + return defHttp.get>( + { + url: `${API.ExportProductStockFlowData}`, + params, + responseType: "blob" + } + ); +} + +export function exportCustomerBillDetail(params: QueryCustomerBillDetailReq) { + return defHttp.get>( + { + url: `${API.ExportCustomerBillDetail}`, + params, + responseType: "blob" + } + ); +} + +export function exportSupplierBillDetail(params: QuerySupplierBillDetailReq) { + return defHttp.get>( + { + url: `${API.ExportSupplierBillDetail}`, + params, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/report/reportModel.ts b/src/api/report/reportModel.ts new file mode 100644 index 0000000..fe64e64 --- /dev/null +++ b/src/api/report/reportModel.ts @@ -0,0 +1,313 @@ +export interface RetailStatisticalResp { + todaySales: number; + yesterdaySales: number; + todayRetailSales: number; + yesterdayRetailSales: number; + todayPurchase: number; + yesterdayPurchase: number; + monthSales: number; + monthRetailSales: number; + monthPurchase: number; + yearSales: number; + yearRetailSales: number; + yearPurchase: number; + retailAxisStatisticalDataVO: XyAxisData[]; + saleAxisStatisticalDataVO: XyAxisData[]; + purchaseAxisStatisticalDataVO: XyAxisData[]; +} + +export interface XyAxisData { + xaxisData: string; + yaxisData: number; +} + +export interface QueryProductStockReq { + warehouseId: number | string; + productInfo: string; + productCategoryId: number | string; + warehouseShelves: string; +} + +export interface QueryProductStockFlowReq { + productId: number; + warehouseId: number; + productBarcode: number; + receiptNumber: string; +} + +export interface ProductStockResp { + id: string; + productBarcode: string; + productName: string; + productCategoryName: string; + productStandard: string; + productModel: string; + productColor: string; + productUnit: string; + warehouseShelves: string; + productWeight: number; + unitPrice: number; + initialStock: number; + currentStock: number; + stockAmount: number; +} + +export interface ProductStockFlowResp { + receiptNumber: string; + type: String; + productBarcode: number; + productName: string; + warehouseName: string; + productNumber: number; + receiptDate: string; +} + +export interface QueryAccountStatisticsReq { + accountName: string; + accountNumber: string; +} + +export interface AccountStatisticsResp { + accountId: string; + accountName: string; + accountNumber: string; + initialAmount: number; + thisMonthChangeAmount: number; + currentAmount: number; +} + +export interface AccountFlowResp { + receiptNumber: string; + subType: string; + useType: string; + name: string; + amount: number; + balance: number; + receiptDate: string; +} + +export interface QueryRetailStatisticsReq { + productExtendInfo: string; + memberId: number; + warehouseId: number; +} + +export interface RetailStatisticsResp { + productBarcode: string; + productName: string; + productStandard: string; + productModel: string; + productExtendInfo: string; + productUnit: string; + retailNumber: number; + retailAmount: number; + retailRefundNumber: number; + retailRefundAmount: number; + retailLastAmount: number; +} + +export interface QueryPurchaseStatisticsReq { + productExtendInfo: string; + supplierId: number; + warehouseId: number; +} + +export interface PurchaseStatisticsResp { + productBarcode: string; + productName: string; + productStandard: string; + productModel: string; + productExtendInfo: string; + productUnit: string; + purchaseNumber: number; + purchaseAmount: number; + purchaseRefundNumber: number; + purchaseRefundAmount: number; + purchaseLastAmount: number; +} + +export interface QuerySalesStatisticsReq { + productExtendInfo: string; + customerId: number; + warehouseId: number; +} + +export interface SalesStatisticsResp { + productBarcode: string; + productName: string; + productStandard: string; + productModel: string; + productExtendInfo: string; + productUnit: string; + salesNumber: number; + salesAmount: number; + salesRefundNumber: number; + salesRefundAmount: number; + salesLastAmount: number; +} + +export interface QueryShipmentsDetailStatisticsReq { + receiptNumber: string; + productInfo: string; + relatedPersonId: number; + warehouseId: number; + operatorId: number; + remark: string; +} + +export interface ShipmentsDetailStatisticsResp { + receiptNumber: string; + productBarcode: string; + productName: string; + productStandard: string; + productModel: string; + productUnit: string; + type: string; + name: string; + productNumber: number; + unitPrice: number; + amount: number; + taxRate: number; + taxAmount: number; + createTime: string; +} + +export interface QueryStorageDetailStatisticsReq { + receiptNumber: string; + productInfo: string; + relatedPersonId: number; + warehouseId: number; + operatorId: number; + remark: string; +} + +export interface RelatedPersonResp { + id: string; + type: string; + name: string; +} + +export interface StorageDetailStatisticsResp { + receiptNumber: string; + productBarcode: string; + productName: string; + productStandard: string; + productModel: string; + productUnit: string; + type: string; + name: string; + productNumber: number; + unitPrice: number; + amount: number; + taxRate: number; + taxAmount: number; + createTime: string; +} + +export interface QueryShipmentsSummaryStatisticsReq { + productInfo: string; + relatedPersonId: number; + warehouseId: number; +} + +export interface ShipmentsSummaryStatisticsResp { + productBarcode: string; + productName: string; + warehouseName: string; + productStandard: string; + productCategoryName: string; + productModel: string; + productUnit: string; + shipmentsNumber: number; + shipmentsAmount: number; +} + +export interface QueryStorageSummaryStatisticsReq { + productInfo: string; + relatedPersonId: number; + warehouseId: number; +} + +export interface StorageSummaryStatisticsResp { + productBarcode: string; + productName: string; + warehouseName: string; + productStandard: string; + productCategoryName: string; + productModel: string; + productUnit: string; + storageNumber: number; + storageAmount: number; +} + +export interface QueryCustomerBillReq { + customerId: number | string; +} + +export interface CustomerBillStatisticsResp { + id: string; + customerId: string; + customerName: string; + contactName: string; + contactPhone: string; + email: string; + firstQuarterReceivable: number; + secondQuarterReceivable: number; + thirdQuarterReceivable: number; + fourthQuarterReceivable: number; + totalQuarterReceivable: number; + totalQuarterArrears: number; + remainingReceivableArrears: number; +} + +export interface QueryCustomerBillDetailReq { + receiptNumber: number | string; + productInfo: string; +} + +export interface CustomerBillDetailStatisticsResp { + receiptNumber: string; + customerName: string; + productInfo: string; + receiptDate: string; + operator: string; + thisReceiptArrears: number; + receivedArrears: number; + receivableArrears: number; +} + +export interface QuerySupplierBillReq { + supplierId: number | string; +} + +export interface SupplierBillStatisticsResp { + id: string; + supplierId: string; + supplierName: string; + contactName: string; + contactPhone: string; + email: string; + firstQuarterPayment: number; + secondQuarterPayment: number; + thirdQuarterPayment: number; + fourthQuarterPayment: number; + totalPayment: number; + totalArrears: number; + remainingPaymentArrears: number; +} + +export interface QuerySupplierBillDetailReq { + receiptNumber: number | string; + productInfo: string; +} + +export interface SupplierBillDetailStatisticsResp { + receiptNumber: string; + supplierName: string; + productInfo: string; + receiptDate: string; + operator: string; + thisReceiptArrears: number; + prepaidArrears: number; + paymentArrears: number; +} \ No newline at end of file diff --git a/src/api/retail/model/refundModel.ts b/src/api/retail/model/refundModel.ts new file mode 100644 index 0000000..eeceab5 --- /dev/null +++ b/src/api/retail/model/refundModel.ts @@ -0,0 +1,49 @@ +import {ShipmentsData, FileData} from '/@/api/retail/model/shipmentsModel'; + +export interface AddOrUpdateRefundReq { + id: number | string | undefined; + memberId: string; + accountId: string; + receiptDate: string; + receiptNumber: string; + otherReceipt: string; + paymentAmount: number; + receiptAmount: number; + backAmount: number; + remark: string; + status: number; + tableData: ShipmentsData[]; + files: FileData[]; +} + +export interface AddOrUpdateRefundResp { + id: number | string | undefined; + memberId: string; + memberName: string; + accountId: string; + accountName: string; + receiptDate: string; + receiptNumber: string; + otherReceipt: string; + paymentAmount: number; + receiptAmount: number; + backAmount: number; + remark: string; + status: number; + tableData: ShipmentsData[]; + files: FileData[]; +} + +export interface RefundResp { + id: number | string; + memberName: string; + receiptNumber: string; + receiptDate: string; + productInfo: string; + operator: string; + productNumber: number; + totalPrice: number; + paymentAmount: number; + backAmount: string; + status: number; +} \ No newline at end of file diff --git a/src/api/retail/model/shipmentsModel.ts b/src/api/retail/model/shipmentsModel.ts new file mode 100644 index 0000000..96fad02 --- /dev/null +++ b/src/api/retail/model/shipmentsModel.ts @@ -0,0 +1,82 @@ +export interface FileData { + id: number | string; + uid: string; + fileName: string; + fileUrl: string; + fileType: string; + fileSize: number; + status: string; +} + +export interface ShipmentsData { + warehouseId: number | string; + barCode: string | number; + productId: number | string; + productName: string; + productStandard: string; + productUnit: string; + stock: number; + productNumber: number; + unitPrice: number; + amount: number; +} + +export interface AddOrUpdateShipmentsReq { + id: number | string | undefined; + memberId: number | string; + accountId: number | string; + receiptDate: string; + receiptNumber: string; + receiptType: string; + collectionAmount: number; + receiptAmount: number; + backAmount: number; + remark: string; + status: number; + tableData: ShipmentsData[]; + fileDataList: FileData[]; +} + +export interface AddOrUpdateShipmentsResp { + id: number | string | undefined; + memberId: number | string; + memberName: string; + paymentType: string; + accountId: number | string; + accountName: string; + receiptDate: string; + receiptNumber: string; + receiptType: string; + collectionAmount: number; + receiptAmount: number; + backAmount: number; + remark: string; + status: number; + tableData: ShipmentsData[]; + fileDataList: FileData[]; +} + +export interface QueryShipmentsReq { + receiptNumber: string; + productInfo: string; + memberId: number | string; + warehouseId: number | string; + accountId: number | string; + operatorId: number | string; + status: number; + remark: string; +} + +export interface ShipmentsResp { + id: number | string; + memberName: string; + receiptNumber: string; + receiptDate: string; + productInfo: string; + operator: string; + productNumber: number; + totalPrice: number; + collectionAmount: number; + backAmount: string; + status: number; +} \ No newline at end of file diff --git a/src/api/retail/refund.ts b/src/api/retail/refund.ts new file mode 100644 index 0000000..614e78a --- /dev/null +++ b/src/api/retail/refund.ts @@ -0,0 +1,102 @@ +import {defHttp} from '@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { QueryShipmentsReq } from "@/api/retail/model/shipmentsModel" +import { + AddOrUpdateRefundReq, AddOrUpdateRefundResp, + RefundResp +} from "@/api/retail/model/refundModel" +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; + +enum API { + PageList = '/retail/refund/pageList', + AddOrUpdate = '/retail/refund/addOrUpdate', + GetDetail = '/retail/refund/detail', + UpdateStatus = '/retail/refund/updateStatus', + Delete = '/retail/refund/deleteByIds', + GetLinkRefundDetail = '/retail/refund/getLinkRefundDetail', + Export = '/retail/refund/export', + ExportDetail = '/retail/refund/exportDetail', +} + +export function getRefundPageList(params: QueryShipmentsReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateRefund(params: AddOrUpdateRefundReq, + successMode: SuccessMessageMode = 'notice', + errorMode: ErrorMessageMode = 'notice',) { + return defHttp.post( + { + url: API.AddOrUpdate, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getRefundDetail(id: string) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}`, + } + ); +} + +export function getLinkRefundDetail(otherReceipt: string) { + return defHttp.get>( + { + url: `${API.GetLinkRefundDetail}/${otherReceipt}`, + } + ); +} + +export function updateRefundStatus(ids: string[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}`, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteRefund(ids: string[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + { + url: `${API.Delete}?ids=${ids}`, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function exportRefund(params: QueryShipmentsReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportRefundDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/retail/shipments.ts b/src/api/retail/shipments.ts new file mode 100644 index 0000000..a29da98 --- /dev/null +++ b/src/api/retail/shipments.ts @@ -0,0 +1,118 @@ +import {defHttp} from '@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddOrUpdateShipmentsReq, AddOrUpdateShipmentsResp, + QueryShipmentsReq, + ShipmentsResp +} from "@/api/retail/model/shipmentsModel" +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; + +enum API { + PageList = '/retail/shipments/pageList', + List = '/retail/shipments/list', + AddOrUpdate = '/retail/shipments/addOrUpdate', + DeleteBatch = '/retail/shipments/deleteByIds', + UpdateStatus = '/retail/shipments/updateStatus', + GetDetail = '/retail/shipments/detail', + GetLinkShipmentDetail = '/retail/shipments/getLinkShipmentDetail', + Export = '/retail/shipments/export', + ExportDetail = '/retail/shipments/exportDetail', +} + +export function getShipmentsPageList(params: QueryShipmentsReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function getShipmentsList(params: QueryShipmentsReq) { + return defHttp.post>( + { + url: API.List, + params, + } + ); +} + +export function addOrUpdateShipments(params: AddOrUpdateShipmentsReq, + successMode: SuccessMessageMode = 'notice', + errorMode: ErrorMessageMode = 'notice',) { + return defHttp.post( + { + url: API.AddOrUpdate, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteShipments(ids: string[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + { + url: `${API.DeleteBatch}?ids=${ids}`, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateShipmentsStatus(ids: string[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}`, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getShipmentsDetail(id: string | number, errorMode: ErrorMessageMode = 'notice') { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}`, + }, + { + errorMessageMode: errorMode, + } + ); +} + +export function getLinkShipmentsDetail(otherReceipt: string, errorMode: ErrorMessageMode = 'notice') { + return defHttp.get>( + { + url: `${API.GetLinkShipmentDetail}/${otherReceipt}`, + }, + { + errorMessageMode: errorMode, + } + ); +} + +export function exportShipments(params: QueryShipmentsReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportShipmentsDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/sale/model/orderModel.ts b/src/api/sale/model/orderModel.ts new file mode 100644 index 0000000..6fea523 --- /dev/null +++ b/src/api/sale/model/orderModel.ts @@ -0,0 +1,83 @@ +import {FileData} from '/@/api/retail/model/shipmentsModel'; + +export interface QuerySaleOrderReq { + receiptNumber: string; + productInfo: string; + customerId: number | string; + operatorId: number | string; + status: number; + remark: string; +} + +export interface SalesData { + warehouseId: number | string; + productId: number | string; + barCode: number | string; + productCode: string; + productName: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + salePrice: number; + amount: number; + taxRate: number; + taxAmount: number; + taxTotalPrice: number; + remark: string; +} + +export interface AddOrUpdateReceiptReq { + id: number | string | undefined; + customerId: string; + receiptNumber: string; + receiptDate: string; + operatorIds: number[]; + discountRate: number; + discountAmount: number; + discountLastAmount: number; + deposit: number; + accountId: number | string; + multipleAccountIds: number[]; + multipleAccountAmounts: number[]; + status: number; + remark: string; + tableData: SalesData[]; + files: FileData[]; +} + +export interface LinkReceiptSaleOrderDetailResp { + id: number | string | undefined; + customerId: string; + customerName: string; + accountName: string; + receiptNumber: string; + receiptDate: string; + operatorIds: number[]; + discountRate: number; + discountAmount: number; + discountLastAmount: number; + deposit: number; + accountId: number | string; + multipleAccountIds: number[]; + multipleAccountAmounts: number[]; + status: number; + remark: string; + tableData: SalesData[]; + files: FileData[]; +} + +export interface SaleDetailData { + customerId: number | string; + receiptDate: string; + receiptNumber: string; + operatorIds: number[]; + discountRate: number; + discountAmount: number; + discountLastAmount: number; + deposit: number; + accountIds: number; + remark: string; + tableData: SalesData[]; + files: FileData[]; +} \ No newline at end of file diff --git a/src/api/sale/model/refundModel.ts b/src/api/sale/model/refundModel.ts new file mode 100644 index 0000000..c9ea1f6 --- /dev/null +++ b/src/api/sale/model/refundModel.ts @@ -0,0 +1,94 @@ +import {FileData} from '/@/api/retail/model/shipmentsModel'; + +export interface QuerySaleRefundReq { + receiptNumber: string; + productInfo: string; + customerId: number | string; + operatorId: number | string; + otherReceipt: string; + arrearsStatus: number; + status: number; + remark: string; +} + +export interface SaleRefundTableData { + warehouseId: number | string; + productId: number | string; + barCode: number | string; + productName: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + unitPrice: number; + amount: number; + taxRate: number; + taxAmount: number; + taxTotalPrice: number; + remark: string; +} + +export interface AddOrUpdateReceiptSaleRefundReq { + id: number | string | undefined; + customerId: string; + receiptNumber: string; + receiptDate: string; + otherReceipt: string; + operatorIds: number[]; + refundOfferRate: number; + refundOfferAmount: number; + refundLastAmount: number; + otherAmount: number; + thisRefundAmount: number; + thisArrearsAmount: number; + accountId: number | string; + multipleAccountIds: number[]; + multipleAccountAmounts: number[]; + status: number; + remark: string; + tableData: SaleRefundTableData[]; + files: FileData[]; +} + +export interface LinkReceiptSaleRefundDetailResp { + id: number | string | undefined; + customerId: string; + customerName: string; + accountName: string; + receiptNumber: string; + receiptDate: string; + otherReceipt: string; + operatorIds: number[]; + refundOfferRate: number; + refundOfferAmount: number; + refundLastAmount: number; + otherAmount: number; + thisRefundAmount: number; + thisArrearsAmount: number; + accountId: number | string; + multipleAccountIds: number[]; + multipleAccountAmounts: number[]; + status: number; + remark: string; + tableData: SaleRefundTableData[]; + files: FileData[]; +} + +export interface SaleRefundDetailData { + customerId: number | string; + receiptDate: string; + receiptNumber: string; + operatorIds: number[]; + refundOfferRate: number; + refundOfferAmount: number; + refundLastAmount: number; + otherAmount: number; + thisRefundAmount: number; + thisArrearsAmount: number; + accountIds: number; + multipleAccountAmounts: number[]; + multipleAccountIds: number[]; + remark: string; + tableData: SaleRefundTableData[]; + files: FileData[]; +} \ No newline at end of file diff --git a/src/api/sale/model/shipmentsModel.ts b/src/api/sale/model/shipmentsModel.ts new file mode 100644 index 0000000..53744f2 --- /dev/null +++ b/src/api/sale/model/shipmentsModel.ts @@ -0,0 +1,94 @@ +import {FileData} from '/@/api/retail/model/shipmentsModel'; + +export interface QuerySaleShipmentsReq { + receiptNumber: string; + productInfo: string; + customerId: number | string; + operatorId: number | string; + otherReceipt: string; + arrearsStatus: number; + status: number; + remark: string; +} + +export interface tableData { + warehouseId: number | string; + productId: number | string; + barCode: number | string; + productName: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + unitPrice: number; + amount: number; + taxRate: number; + taxAmount: number; + taxTotalPrice: number; + remark: string; +} + +export interface AddOrUpdateReceiptSaleShipmentsReq { + id: number | string | undefined; + customerId: string; + receiptNumber: string; + receiptDate: string; + otherReceipt: string; + operatorIds: number[]; + collectOfferRate: number; + collectOfferAmount: number; + collectOfferLastAmount: number; + otherAmount: number; + thisCollectAmount: number; + thisArrearsAmount: number; + accountId: number | string; + multipleAccountIds: number[]; + multipleAccountAmounts: number[]; + status: number; + remark: string; + tableData: tableData[]; + files: FileData[]; +} + +export interface LinkReceiptSaleShipmentsDetailResp { + id: number | string | undefined; + customerId: string; + customerName: string; + accountName: string; + receiptNumber: string; + receiptDate: string; + otherReceipt: string; + operatorIds: number[]; + collectOfferRate: number; + collectOfferAmount: number; + collectOfferLastAmount: number; + otherAmount: number; + thisCollectAmount: number; + thisArrearsAmount: number; + accountId: number | string; + multipleAccountIds: number[]; + multipleAccountAmounts: number[]; + status: number; + remark: string; + tableData: tableData[]; + files: FileData[]; +} + +export interface SaleShipmentDetailData { + customerId: number | string; + receiptDate: string; + receiptNumber: string; + operatorIds: number[]; + collectOfferRate: number; + collectOfferAmount: number; + collectOfferLastAmount: number; + otherAmount: number; + thisCollectAmount: number; + thisArrearsAmount: number; + accountIds: number; + multipleAccountAmounts: number[]; + multipleAccountIds: number[]; + remark: string; + tableData: tableData[]; + files: FileData[]; +} \ No newline at end of file diff --git a/src/api/sale/order.ts b/src/api/sale/order.ts new file mode 100644 index 0000000..c752ecb --- /dev/null +++ b/src/api/sale/order.ts @@ -0,0 +1,98 @@ +import {defHttp} from '/@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + QuerySaleOrderReq, + AddOrUpdateReceiptReq, + SaleDetailData, + LinkReceiptSaleOrderDetailResp +} from "@/api/sale/model/orderModel" +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; + +enum API { + PageList = '/sale/order/pageList', + AddOrUpdate = '/sale/order/addOrUpdate', + GetDetail = '/sale/order/detail', + UpdateStatus = '/sale/order/updateStatus', + Delete = '/sale/order/delete', + GetLinkOrderDetail = '/sale/order/getLinkOrderDetail', + Export = '/sale/order/export', + ExportDetail = '/sale/order/exportDetail', +} + +export function getSaleOrderPageList(params: QuerySaleOrderReq) { + return defHttp.get>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateSaleOrder(params: AddOrUpdateReceiptReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdate, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getSaleOrderDetail(id: string) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}`, + } + ); +} + +export function updateSaleOrderStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}/${ids}/${status}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteSaleOrder(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.Delete}/${ids}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getLinkOrderDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.GetLinkOrderDetail}/${receiptNumber}`, + } + ); +} + +export function exportOrder(params: QuerySaleOrderReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportOrderDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/sale/refund.ts b/src/api/sale/refund.ts new file mode 100644 index 0000000..2a85e2c --- /dev/null +++ b/src/api/sale/refund.ts @@ -0,0 +1,98 @@ +import {defHttp} from '/@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + QuerySaleRefundReq, + AddOrUpdateReceiptSaleRefundReq, + SaleRefundDetailData, + LinkReceiptSaleRefundDetailResp +} from "@/api/sale/model/refundModel" +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; + +enum API { + PageList = '/sale/refund/pageList', + AddOrUpdate = '/sale/refund/addOrUpdate', + GetDetail = '/sale/refund/detail', + UpdateStatus = '/sale/refund/updateStatus', + Delete = '/sale/refund/delete', + GetLinkRefundDetail = '/sale/refund/getLinkRefundDetail', + Export = '/sale/refund/export', + ExportDetail = '/sale/refund/exportDetail', +} + +export function getSaleRefundPageList(params: QuerySaleRefundReq) { + return defHttp.get>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateSaleRefund(params: AddOrUpdateReceiptSaleRefundReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdate, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getSaleRefundDetail(id: string) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}`, + } + ); +} + +export function updateSaleRefundStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}/${ids}/${status}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteSaleRefund(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.Delete}/${ids}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getLinkRefundDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.GetLinkRefundDetail}/${receiptNumber}`, + } + ); +} + +export function exportRefund(params: QuerySaleRefundReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportRefundDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/sale/shipments.ts b/src/api/sale/shipments.ts new file mode 100644 index 0000000..426c064 --- /dev/null +++ b/src/api/sale/shipments.ts @@ -0,0 +1,98 @@ +import {defHttp} from '/@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + QuerySaleShipmentsReq, + AddOrUpdateReceiptSaleShipmentsReq, + SaleShipmentDetailData, + LinkReceiptSaleShipmentsDetailResp +} from "@/api/sale/model/shipmentsModel" +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; + +enum API { + PageList = '/sale/shipments/pageList', + AddOrUpdate = '/sale/shipments/addOrUpdate', + GetDetail = '/sale/shipments/detail', + UpdateStatus = '/sale/shipments/updateStatus', + Delete = '/sale/shipments/delete', + GetLinkShipmentsDetail = '/sale/shipments/getLinkShipmentDetail', + Export = '/sale/shipments/export', + ExportDetail = '/sale/shipments/exportDetail', +} + +export function getSaleShipmentsPageList(params: QuerySaleShipmentsReq) { + return defHttp.get>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateSaleShipments(params: AddOrUpdateReceiptSaleShipmentsReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdate, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getSaleShipmentsDetail(id: string) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}`, + } + ); +} + +export function updateSaleShipmentsStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}/${ids}/${status}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteSaleShipments(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.Delete}/${ids}`, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getLinkShipmentsDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.GetLinkShipmentsDetail}/${receiptNumber}`, + } + ); +} + +export function exportShipments(params: QuerySaleShipmentsReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportShipmentsDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/sys/captcha.ts b/src/api/sys/captcha.ts new file mode 100644 index 0000000..57902f1 --- /dev/null +++ b/src/api/sys/captcha.ts @@ -0,0 +1,23 @@ +import { BaseDataResp } from '../model/baseModel'; +import { ErrorMessageMode } from '/#/axios'; +import { defHttp } from '/@/utils/http/axios'; + +enum Api { + GetCaptcha = '/v2/common/captcha' +} + +interface CaptchaResp { + captchaId: string; + imagePath: string; +} + +export function getCaptcha(mode: ErrorMessageMode = 'notice') { + return defHttp.get>( + { + url: Api.GetCaptcha, + }, + { + errorMessageMode: mode, + }, + ); +} diff --git a/src/api/sys/config.ts b/src/api/sys/config.ts new file mode 100644 index 0000000..c28dd28 --- /dev/null +++ b/src/api/sys/config.ts @@ -0,0 +1,20 @@ +import { defHttp } from '@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddOrUpdateSystemConfigModel, + GetSystemConfigModel, +} from '@/api/sys/model/configModel'; + +enum Api { + GetConfigInfo = '/sys/config/getCompanyInfo', + AddOrUpdateConfigInfo = '/sys/config/addOrUpdate', +} + +export function getConfigInfo() { + return defHttp.get>({url: Api.GetConfigInfo}) +} + +export function addOrUpdateConfigInfo(params: AddOrUpdateSystemConfigModel) { + return defHttp.post({url: Api.AddOrUpdateConfigInfo, params}) +} + diff --git a/src/api/sys/dept.ts b/src/api/sys/dept.ts new file mode 100644 index 0000000..d0d43be --- /dev/null +++ b/src/api/sys/dept.ts @@ -0,0 +1,42 @@ +import { + addOrUpdateDeptReq, + DeptListItem, + GetDeptInfoModel, +} from './model/dpetModel'; + +import { defHttp } from '/@/utils/http/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; + +enum Api { + DeptList = '/dept/list', + UserBindDept = '/dept/userBindDept', + AddOrUpdateDept = '/dept/addOrUpdate', + DeleteDept = '/dept/delete', +} +export function getDeptList(params?: DeptListItem) { + return defHttp.get>({url: Api.DeptList, params}) +} +export function getUserBindDept() { + return defHttp.get>({url: Api.UserBindDept}) +} + +export function addOrUpdateDept(params: addOrUpdateDeptReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post({ + url: Api.AddOrUpdateDept, params}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +export function deleteDept(id: number | string, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post({ + url: `${Api.DeleteDept}?id=${id}`}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} \ No newline at end of file diff --git a/src/api/sys/menu.ts b/src/api/sys/menu.ts new file mode 100644 index 0000000..6ddac62 --- /dev/null +++ b/src/api/sys/menu.ts @@ -0,0 +1,37 @@ +import {defHttp} from '/@/utils/http/axios'; +import {BaseDataResp} from "@/api/model/baseModel"; +import {MenuListResp, AddOrUpdateMenuReq} from "@/api/sys/model/menuModel"; +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; +enum Api { + GetMenuList = '/sysRole/menu', + AddOrUpdateMenu = '/menu/addOrUpdate', + DeleteMenu = '/menu/delete', +} + +/** + * @description: Get user menu based on id + */ + +export const getMenuList = () => { + return defHttp.get>({url: Api.GetMenuList}); +}; + +export const addOrUpdateMenu = (params: AddOrUpdateMenuReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') => { + return defHttp.post>( + {url: Api.AddOrUpdateMenu, params}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +export const deleteMenu = (id: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') => { + return defHttp.post>( + {url: `${Api.DeleteMenu}?id=${id}`}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} diff --git a/src/api/sys/message.ts b/src/api/sys/message.ts new file mode 100644 index 0000000..27b377d --- /dev/null +++ b/src/api/sys/message.ts @@ -0,0 +1,21 @@ +import { defHttp } from '@/utils/http/axios'; +import {MessageInfo, ReadMessageReq} from "@/api/sys/model/MessageModel"; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; + +enum Api { + List = '/sys/message/list', + Read = '/sys/message/read', +} + +export function getMessageList() { + return defHttp.get>({ + url: Api.List, + }); +} + +export function readMessage(params: ReadMessageReq) { + return defHttp.post({ + url: Api.Read, + params, + }); +} \ No newline at end of file diff --git a/src/api/sys/model/MessageModel.ts b/src/api/sys/model/MessageModel.ts new file mode 100644 index 0000000..e5c4f50 --- /dev/null +++ b/src/api/sys/model/MessageModel.ts @@ -0,0 +1,22 @@ +export interface MessageInfo { + key: string; + name: string; + list: ListItem[]; +} + +export interface ListItem { + id: string; + title: string; + avatar: string; + description: string; + msgContent: string; + type: string; + status: string; + datetime: string; +} + +export interface ReadMessageReq { + id: string; + userId: string | number; + status: number; +} \ No newline at end of file diff --git a/src/api/sys/model/captchaModel.ts b/src/api/sys/model/captchaModel.ts new file mode 100644 index 0000000..8266e78 --- /dev/null +++ b/src/api/sys/model/captchaModel.ts @@ -0,0 +1,12 @@ +export interface CaptchaResp { + captchaId: string; + imgPath: string; +} + +export interface GetEmailCaptchaReq { + email: string; +} + +export interface GetSmsCaptchaReq { + phoneNumber: string; +} diff --git a/src/api/sys/model/configModel.ts b/src/api/sys/model/configModel.ts new file mode 100644 index 0000000..83d5f40 --- /dev/null +++ b/src/api/sys/model/configModel.ts @@ -0,0 +1,20 @@ +export interface GetSystemConfigModel { + companyName: string; + companyContact: string; + companyAddress: string; + companyPhone: string; + companyFax: string; + companyPostCode: string; + companyLogo: string; +} + +export interface AddOrUpdateSystemConfigModel { + id: number | string; + companyName: string; + companyContact: string; + companyAddress: string; + companyPhone: string; + companyFax: string; + companyPostCode: string; + companyLogo: string; +} \ No newline at end of file diff --git a/src/api/sys/model/dpetModel.ts b/src/api/sys/model/dpetModel.ts new file mode 100644 index 0000000..ba02138 --- /dev/null +++ b/src/api/sys/model/dpetModel.ts @@ -0,0 +1,29 @@ +export interface DeptListItem { + deptName: string; +} + +export interface GetDeptInfoModel { + // 机构id + id: string | number; + // 机构编号 + deptNumber: string; + // 机构名称 + deptName: string; + // 备注 + remark: string; + // 父级部门id + parentId: string; + // 排序 + sort: number; +} + +export interface addOrUpdateDeptReq { + id: number | string; + deptName: string; + parentId: number; + deptNumber: string; + leader: string; + status: number; + remark: string; + sort: string; +} diff --git a/src/api/sys/model/menuModel.ts b/src/api/sys/model/menuModel.ts new file mode 100644 index 0000000..d618169 --- /dev/null +++ b/src/api/sys/model/menuModel.ts @@ -0,0 +1,70 @@ +import type {RouteMeta} from 'vue-router'; +import {BaseListResp} from '../../model/baseModel'; + +export interface RouteItem { + path: string; + component: any; + meta: RouteMeta; + name?: string; + alias?: string | string[]; + redirect?: string; + caseSensitive?: boolean; + children?: RouteItem[]; +} + +export interface MenuPageResp { + total: number; + data: RouteItem[]; +} + +export interface MenuInfo { + id: number; + type?: number; + parentId?: number; + path?: string; + name?: string; + title?: string; + redirect?: string; + component?: string; + sort?: number; + disabled?: boolean; + meta: Meta; +} + +interface Meta { + title?: string; + icon?: string; + hideMenu?: boolean; + hideBreadcrumb?: boolean; + ignoreKeepAlive?: boolean; + hideTab?: boolean; + frameSrc?: string; + carryParam?: boolean; + hideChildrenInMenu?: boolean; + affix?: boolean; + dynamicLevel?: number; + realPath?: string; +} + +export interface AddOrUpdateMenuReq { + id: number; + menuType: number; + name: string; + title: string; + parentId: number; + sort: number; + icon: string; + path: string; + component: string; + status: number; + blank: number; + ignoreKeepAlive: number; + hideMenu: number; +} + +export type MenuListResp = BaseListResp; + +/** + * @description: Get menu return value + */ +export type RoleMenuResp = BaseListResp; diff --git a/src/api/sys/model/roleModel.ts b/src/api/sys/model/roleModel.ts new file mode 100644 index 0000000..7c9c59d --- /dev/null +++ b/src/api/sys/model/roleModel.ts @@ -0,0 +1,35 @@ +export interface GetRoleInfoModel { + // 角色id + id: number | string, + // 角色名称 + roleName: string, + // 角色类型 + type: string, + // 价格屏蔽 1-屏蔽采购价 2-屏蔽零售价 3-屏蔽销售价 + priceLimit: number, + // 状态 0-启用 1-停用 + status: number, + // 描述 + description: string, + // 创建时间 + createTime: string +} + +export interface queryRoleListReq { + roleName: string; + status: number; +} + +export interface addOrUpdateRoleInfoReq { + id: string | undefined + roleName: string, + type: string, + priceLimit: number, + status: number, + description: string, +} + +export interface addOrUpdateRolePermissionReq { + id: string | undefined, + menuIds: number[] +} \ No newline at end of file diff --git a/src/api/sys/model/tenantModel.ts b/src/api/sys/model/tenantModel.ts new file mode 100644 index 0000000..8db039c --- /dev/null +++ b/src/api/sys/model/tenantModel.ts @@ -0,0 +1,33 @@ +export interface TenantInfoModel { + id: number; + tenantId: number; + tenantName: number; + userNumLimit: number; + type: number; + status: number; + remark: string; + createTime: string; +} + +export interface queryTenantListReq { + loginUser: string; + tenantName: string; + type: number; + status: number; +} + +export interface addOrUpdateTenantReq { + id: number | string; + username: string; + password: string; + type: number; + status: number; + userNumLimit: number; + tenantName: string; + expireTime: string; + email: string; + phoneNumber: string; + roleId: number; + deptId: number; + remark: string; +} \ No newline at end of file diff --git a/src/api/sys/model/uploadModel.ts b/src/api/sys/model/uploadModel.ts new file mode 100644 index 0000000..4015bbd --- /dev/null +++ b/src/api/sys/model/uploadModel.ts @@ -0,0 +1,5 @@ +export interface UploadApiResult { + msg: string; + code: string; + url: string; +} diff --git a/src/api/sys/model/userModel.ts b/src/api/sys/model/userModel.ts new file mode 100644 index 0000000..6735cf0 --- /dev/null +++ b/src/api/sys/model/userModel.ts @@ -0,0 +1,134 @@ +/** + * @description: Login interface parameters + */ +export interface LoginReq { + username: string; + password: string; + captcha: string; + captchaId: string; +} + +export interface mobileLoginReq { + phoneNumber: string; + sms: string; + type: number; +} + +export interface emailLoginReq { + email: string; + emailCode: string; + type: number; +} + +export interface registerReq { + username: string; + password: string; + phoneNumber: string; + email: string; + sms: number; +} + +export interface queryUserListReq { + username: string; + name: string; +} + +export interface updatePasswordReq { + password: string; + phoneNumber: string; + sms: number; +} + +export interface updatePasswordByEmailReq { + password: string; + email: string; + emailCode: number; +} + +export interface resetPasswordReq { + id: number | string; + userName: string; + password: string; + newPassword: string; +} + +export interface resetPhoneNumberReq { + userId: number | string; + oldPhoneNumber: string; + phoneNumber: string; + sms: string; +} + +export interface resetEmailReq { + userId: number | string; + oldEmail: string; + email: string; + emailCode: string; +} + +export interface updateUserInfoReq { + id: number | string; + name: string; + status: number; + email: string; + phoneNumber: string; + position: string; + leaderFlag: number; + systemLanguage: string; +} + +export interface addOrUpdateUserReq { + id: number | string; + username: string; + password: string; + name: string; + email: string; + phoneNumber: string; + roleId: number; + deptId: number; + remake: string; +} + +export interface RoleInfo { + roleName: string; + value: string; +} + +export interface LoginResp { + userId: string | number; + token: string; + expire?: number; +} + +/** + * @description: Login interface return value + */ +export interface LoginResultModel { + userId: string | number; + token: string; + roles: RoleInfo[]; +} + +/** + * @description: Get user information return value + */ +export interface GetUserInfoModel { + // 用户id + id: string | number; + // 用户名 + username: string; + // 昵称 + name: string; + // 邮箱 + email: string; + // 电话 + phoneNumber: string; + // 状态 + status: number; + // 用户角色名称 + roleName: string; + // 头像 + avatar: string; + // 系统语言 + systemLanguage: string; +} diff --git a/src/api/sys/role.ts b/src/api/sys/role.ts new file mode 100644 index 0000000..5d26ac0 --- /dev/null +++ b/src/api/sys/role.ts @@ -0,0 +1,73 @@ +import {ErrorMessageMode, SuccessMessageMode} from "#/axios"; +import {defHttp} from "@/utils/http/axios"; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + addOrUpdateRoleInfoReq, + addOrUpdateRolePermissionReq, + GetRoleInfoModel, + queryRoleListReq +} from "@/api/sys/model/roleModel"; + +enum Api { + List = '/sysRole/list', + PageList = '/sysRole/PageList', + UpdateStatus = '/sysRole/updateStatus', + AddOrUpdateRole = '/sysRole/addOrUpdateRole', + DeleteRole = '/sysRole/deleteRole', + RolePermission = '/sysRole/permission' +} + +export function getRoleList(errorMode: ErrorMessageMode = 'notice') { + return defHttp.get( + {url: Api.List}, + { + errorMessageMode: errorMode, + } + ) +} + +export function getPageList(params: queryRoleListReq) { + return defHttp.post>( + {url: Api.PageList, params}, + ) +} + +export function setRoleStatus(id: string, status: number, successMode: SuccessMessageMode ='notice', errorMode: ErrorMessageMode = 'notice'){ + return defHttp.post( + {url: `${Api.UpdateStatus}?id=${id}&status=${status}`}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ) +} + +export function addOrUpdateRole(params: addOrUpdateRoleInfoReq, successMode: SuccessMessageMode ='notice', errorMode: ErrorMessageMode = 'notice'){ + return defHttp.post( + {url: Api.AddOrUpdateRole, params: params}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +export function deleteRole(id: string, successMode: SuccessMessageMode ='notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + {url: `${Api.DeleteRole}?id=${id}`}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +export function rolePermission(params: addOrUpdateRolePermissionReq, successMode: SuccessMessageMode ='notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + {url: Api.RolePermission, params: params}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} \ No newline at end of file diff --git a/src/api/sys/tenant.ts b/src/api/sys/tenant.ts new file mode 100644 index 0000000..8607659 --- /dev/null +++ b/src/api/sys/tenant.ts @@ -0,0 +1,50 @@ +import { defHttp } from '@/utils/http/axios'; + +import {addOrUpdateTenantReq, queryTenantListReq, TenantInfoModel} from './model/tenantModel'; +import { ErrorMessageMode, SuccessMessageMode } from '#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; + +enum Api { + List= '/tenant/list', + AddOrUpdate = '/tenant/addOrUpdate', + Delete = '/tenant/delete', + CheckAddUser = '/tenant/checkAddUser', + Update = '/tenant/update', +} + +export function getTenantList(params: queryTenantListReq) { + return defHttp.post>( + {url: Api.List, params}, + ); +} + +export function addOrUpdateTenant(params: addOrUpdateTenantReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + {url: Api.AddOrUpdate, params}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function checkAddUser() { + return defHttp.get( + {url: Api.CheckAddUser}, + ); +} + +export function deleteTenant(tenantId: string) { + return defHttp.post( + {url: `${Api.Delete}?tenantId=${tenantId}`}, + ); +} +export function updateStatus(params: { id: any; status: number }, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + {url: Api.Update, params}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ) +} \ No newline at end of file diff --git a/src/api/sys/upload.ts b/src/api/sys/upload.ts new file mode 100644 index 0000000..1eb3039 --- /dev/null +++ b/src/api/sys/upload.ts @@ -0,0 +1,25 @@ +import { defHttp } from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode, UploadFileParams} from '/#/axios'; +import {BaseResp} from "@/api/model/baseModel"; +import {ContentTypeEnum} from "@/enums/httpEnum"; + +enum Api { + UploadOss = '/v2/common/uploadOss', +} + +export function uploadApi(params: UploadFileParams, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: Api.UploadOss, + params, + headers: { + 'Content-type': ContentTypeEnum.FORM_DATA, + // @ts-ignore + ignoreCancelToken: true, + }, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} \ No newline at end of file diff --git a/src/api/sys/user.ts b/src/api/sys/user.ts new file mode 100644 index 0000000..39067f1 --- /dev/null +++ b/src/api/sys/user.ts @@ -0,0 +1,295 @@ +import {defHttp} from '@/utils/http/axios'; +import { + addOrUpdateUserReq, emailLoginReq, + GetUserInfoModel, + LoginReq, + LoginResp, + mobileLoginReq, queryUserListReq, + registerReq, resetEmailReq, resetPasswordReq, resetPhoneNumberReq, updatePasswordByEmailReq, + updatePasswordReq, + updateUserInfoReq, +} from './model/userModel'; + +import {ErrorMessageMode, SuccessMessageMode, UploadFileParams} from '#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import {ContentTypeEnum} from "@/enums/httpEnum"; + +enum Api { + Login = '/user/login', + MobileLogin = '/user/mobileLogin', + EmailLogin = '/user/emailLogin', + Logout = '/user/logout', + Register = '/user/register', + SMS = '/v2/common/sms', + EmailSMS = '/v2/common/email', + UpdatePassword = '/user/updatePassword', + UpdatePasswordByEmail = '/user/updatePasswordByEmail', + GetUserInfo = '/user/info', + GetPermCode = '/user/perm', + TestRetry = '/testRetry', + List = '/user/list', + ListAll = '/user/listAll', + UpdateUser = '/user/update', + UpdateStatus = '/user/updateStatus', + AddOrUpdateUser = '/user/addOrUpdate', + DeleteUser = '/user/delete', + ResetPassword = '/user/resetPassword', + GetUserOperatorList = '/user/operator', + UpdateAvatar = '/user/uploadAvatar', + UserUpdatePassword = '/user/userUpdatePassword', + ResetPhoneNumber = '/user/resetPhoneNumber', + ResetEmail = '/user/resetEmail', +} + +/** + * @description: user login api + */ +export function login(params: LoginReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post>( + { + url: Api.Login, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function mobileLogin(params: mobileLoginReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post>( + { + url: Api.MobileLogin, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function emailLogin(params: emailLoginReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post>( + { + url: Api.EmailLogin, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ); +} + +export function register(params: registerReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + { + url: Api.Register, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +export function sendSmsRegister(type: number, phoneNumber: string, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.get( + { + url: `${Api.SMS}/${type}/${phoneNumber}` + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +export function sendEmailCode(type: number, email: string, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.get( + { + url: `${Api.EmailSMS}/${type}/${email}` + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +export function updatePassword(params: updatePasswordReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + { + url: Api.UpdatePassword, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} +export function UpdatePasswordByEmail(params: updatePasswordByEmailReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + { + url: Api.UpdatePasswordByEmail, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +/** + * @description: getUserInfo + */ +export function getUserInfo() { + return defHttp.get>( + {url: Api.GetUserInfo}, + {errorMessageMode: 'none'}, + ); +} + +export function getUserList(params: queryUserListReq) { + return defHttp.post>( + {url: Api.List, params}, + ); +} + +export function getTenantUserList() { + return defHttp.get>( + {url: Api.ListAll}, + ); +} + +export function updateUser(params: updateUserInfoReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + {url: Api.UpdateUser, params}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ) +} + +export function updateStatus(params: { id: any; status: number }, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + {url: Api.UpdateStatus, params}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + }, + ) +} + +export function addOrUpdateUser(params: addOrUpdateUserReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + {url: Api.AddOrUpdateUser, params}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +export function deleteUser(ids: string[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + {url: `${Api.DeleteUser}?ids=${ids}`}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +export function resetPassword(id: string, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.post( + {url: `${Api.ResetPassword}?id=${id}`}, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ) +} + +export function getPermCode() { + return defHttp.get({url: Api.GetPermCode}); +} + +export function doLogout(successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.get({url: Api.Logout}, { + successMessageMode: successMode, + errorMessageMode: errorMode, + }); +} + +export function getUserOperatorList() { + return defHttp.get>({url: Api.GetUserOperatorList}); +} + +export function testRetry() { + return defHttp.get( + {url: Api.TestRetry}, + { + retryRequest: { + isOpenRetry: true, + count: 5, + waitTime: 1000, + }, + }, + ); +} + +export function UpdateAvatar(params: UploadFileParams) { + return defHttp.post( + { + url: Api.UpdateAvatar, + params, + headers: { + 'Content-type': ContentTypeEnum.FORM_DATA, + // @ts-ignore + ignoreCancelToken: true, + }, + } + ); +} + +export function userUpdatePassword(params: resetPasswordReq) { + return defHttp.put( + { + url: Api.UserUpdatePassword, + params, + } + ); +} + +export function resetPhoneNumber(params: resetPhoneNumberReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.put( + { + url: Api.ResetPhoneNumber, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function resetEmail(params: resetEmailReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'notice') { + return defHttp.put( + { + url: Api.ResetEmail, + params, + }, + { + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} \ No newline at end of file diff --git a/src/api/warehouse/allotShipments.ts b/src/api/warehouse/allotShipments.ts new file mode 100644 index 0000000..3c4acc4 --- /dev/null +++ b/src/api/warehouse/allotShipments.ts @@ -0,0 +1,89 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddOrUpdateAllotShipmentsReq, + QueryAllotShipmentsReq, + AllotShipmentsResp, + AllotShipmentsDetailResp, +} from "@/api/warehouse/model/allotShipmentsModel"; + +enum API { + PageList = '/warehouse/allotShipments/pageList', + AddOrUpdateAccount = '/warehouse/allotShipments/addOrUpdate', + DeleteBatch = '/warehouse/allotShipments/deleteByIds', + UpdateStatus = '/warehouse/allotShipments/updateStatusByIds', + GetDetail = '/warehouse/allotShipments/getDetailById', + Export = '/warehouse/allotShipments/export', + ExportDetail = '/warehouse/allotShipments/exportDetail', +} + +export function getAllotShipmentsPageList(params: QueryAllotShipmentsReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateAllotShipments(params: AddOrUpdateAllotShipmentsReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateAllotShipmentsStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchAllotShipments(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getAllotShipmentsDetailById(id: number) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + ); +} + +export function exportAllotShipments(params: QueryAllotShipmentsReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportAllotShipmentsDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/warehouse/assemble.ts b/src/api/warehouse/assemble.ts new file mode 100644 index 0000000..93e4b7a --- /dev/null +++ b/src/api/warehouse/assemble.ts @@ -0,0 +1,89 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddOrUpdateAssembleReq, + QueryAssembleReq, + AssembleResp, + AssembleDetailResp, +} from "@/api/warehouse/model/assembleModel"; + +enum API { + PageList = '/warehouse/assemble/pageList', + AddOrUpdateAccount = '/warehouse/assemble/addOrUpdate', + DeleteBatch = '/warehouse/assemble/deleteByIds', + UpdateStatus = '/warehouse/assemble/updateStatusByIds', + GetDetail = '/warehouse/assemble/getDetailById', + Export = '/warehouse/assemble/export', + ExportDetail = '/warehouse/assemble/exportDetail', +} + +export function getAssemblePageList(params: QueryAssembleReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateAssemble(params: AddOrUpdateAssembleReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateAssembleStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchAssemble(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getAssembleDetailById(id: number) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + ); +} + +export function exportAssemble(params: QueryAssembleReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportAssembleDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/warehouse/disassemble.ts b/src/api/warehouse/disassemble.ts new file mode 100644 index 0000000..5f80ce2 --- /dev/null +++ b/src/api/warehouse/disassemble.ts @@ -0,0 +1,89 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddOrUpdateDisAssembleReq, + QueryDisAssembleReq, + DisAssembleResp, + DisAssembleDetailResp, ExportDisAssembleReq, +} from "@/api/warehouse/model/disassembleModel"; + +enum API { + PageList = '/warehouse/disassemble/pageList', + AddOrUpdateAccount = '/warehouse/disassemble/addOrUpdate', + DeleteBatch = '/warehouse/disassemble/deleteByIds', + UpdateStatus = '/warehouse/disassemble/updateStatusByIds', + GetDetail = '/warehouse/disassemble/getDetailById', + Export = '/warehouse/disassemble/export', + ExportDetail = '/warehouse/disassemble/exportDetail', +} + +export function getDisAssemblePageList(params: QueryDisAssembleReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateDisAssemble(params: AddOrUpdateDisAssembleReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateDisAssembleStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchDisAssemble(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getDisAssembleDetailById(id: number) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + ); +} + +export function exportDisAssemble(params: ExportDisAssembleReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportDisAssembleDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/warehouse/model/allotShipmentsModel.ts b/src/api/warehouse/model/allotShipmentsModel.ts new file mode 100644 index 0000000..af9768b --- /dev/null +++ b/src/api/warehouse/model/allotShipmentsModel.ts @@ -0,0 +1,60 @@ +import {FileData} from "@/api/financial/model/advanceModel"; + +export interface AllotShipmentsData { + id: number | string; + warehouseId: number | string; + warehouseName: string; + otherWarehouseId: number | string; + otherWarehouseName: string; + barCode: string; + productId: number | string; + productName: string; + productModel: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + unitPrice: number; + amount: number; + remark: string; +} + +export interface AddOrUpdateAllotShipmentsReq { + id: number | undefined; + receiptNumber: string; + receiptDate: string; + remark: string; + status: number; + files: FileData[]; + tableData: AllotShipmentsData[]; +} + +export interface QueryAllotShipmentsReq { + receiptNumber: string; + productInfo: string; + operatorId: number; + otherReceipt: string; + status: number; + remark: string; +} + +export interface AllotShipmentsResp { + id: string | undefined; + receiptNumber: string; + productInfo: string; + receiptDate: string; + operator: string; + productNumber: number; + totalAmount: number; + status: number; +} + +export interface AllotShipmentsDetailResp { + id: string | undefined; + receiptNumber: string; + receiptDate: string; + remark: string; + status: number; + files: FileData[]; + tableData: AllotShipmentsData[]; +} \ No newline at end of file diff --git a/src/api/warehouse/model/assembleModel.ts b/src/api/warehouse/model/assembleModel.ts new file mode 100644 index 0000000..c951621 --- /dev/null +++ b/src/api/warehouse/model/assembleModel.ts @@ -0,0 +1,60 @@ +import {FileData} from "@/api/financial/model/advanceModel"; + +export interface AssembleStockData { + id: number | string; + type: string; + warehouseId: number | string; + warehouseName: string; + barCode: string; + productId: number | string; + productName: string; + productModel: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + unitPrice: number; + amount: number; + remark: string; +} + +export interface AddOrUpdateAssembleReq { + id: number | undefined; + receiptNumber: string; + receiptDate: string; + remark: string; + status: number; + files: FileData[]; + tableData: AssembleStockData[]; +} + +export interface QueryAssembleReq { + receiptNumber: string; + productInfo: string; + operatorId: number; + warehouseId: number; + otherReceipt: string; + status: number; + remark: string; +} + +export interface AssembleResp { + id: string | undefined; + receiptNumber: string; + productInfo: string; + receiptDate: string; + operator: string; + productNumber: number; + totalAmount: number; + status: number; +} + +export interface AssembleDetailResp { + id: string | undefined; + receiptNumber: string; + receiptDate: string; + remark: string; + status: number; + files: FileData[]; + tableData: AssembleStockData[]; +} \ No newline at end of file diff --git a/src/api/warehouse/model/disassembleModel.ts b/src/api/warehouse/model/disassembleModel.ts new file mode 100644 index 0000000..ac0cfb7 --- /dev/null +++ b/src/api/warehouse/model/disassembleModel.ts @@ -0,0 +1,71 @@ +import {FileData} from "@/api/financial/model/advanceModel"; + +export interface DisAssembleStockData { + id: number | string; + type: string; + warehouseId: number | string; + warehouseName: string; + barCode: string; + productId: number | string; + productName: string; + productModel: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + unitPrice: number; + amount: number; + remark: string; +} + +export interface AddOrUpdateDisAssembleReq { + id: number | undefined; + receiptNumber: string; + receiptDate: string; + remark: string; + status: number; + files: FileData[]; + tableData: DisAssembleStockData[]; +} + +export interface QueryDisAssembleReq { + receiptNumber: string; + productInfo: string; + operatorId: number; + warehouseId: number; + otherReceipt: string; + status: number; + remark: string; +} + +export interface ExportDisAssembleReq { + receiptNumber: string; + productInfo: string; + operatorId: number; + warehouseId: number; + otherReceipt: string; + status: number; + remark: string; + isExportDetail: boolean; +} + +export interface DisAssembleResp { + id: string | undefined; + receiptNumber: string; + productInfo: string; + receiptDate: string; + operator: string; + productNumber: number; + totalAmount: number; + status: number; +} + +export interface DisAssembleDetailResp { + id: string | undefined; + receiptNumber: string; + receiptDate: string; + remark: string; + status: number; + files: FileData[]; + tableData: DisAssembleStockData[]; +} \ No newline at end of file diff --git a/src/api/warehouse/model/shipmentsModel.ts b/src/api/warehouse/model/shipmentsModel.ts new file mode 100644 index 0000000..db33aa9 --- /dev/null +++ b/src/api/warehouse/model/shipmentsModel.ts @@ -0,0 +1,65 @@ +import {FileData} from "@/api/financial/model/advanceModel"; + +export interface OtherShipmentsData { + id: number | string; + warehouseId: number | string; + customerId: number | string; + warehouseName: string; + barCode: string; + productId: number | string; + productName: string; + productModel: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + unitPrice: number; + amount: number; + remark: string; +} + +export interface AddOrUpdateOtherShipmentsReq { + id: number | undefined; + customerId: number; + receiptNumber: string; + receiptDate: string; + remark: string; + status: number; + files: FileData[]; + tableData: OtherShipmentsData[]; +} + +export interface QueryOtherShipmentsReq { + receiptNumber: string; + productInfo: string; + customerId: number; + warehouseId: number; + operatorId: number; + otherReceipt: string; + status: number; + remark: string; +} + +export interface OtherShipmentsResp { + id: string | undefined; + customerName: string; + receiptNumber: string; + productInfo: string; + receiptDate: string; + operator: string; + productNumber: number; + totalAmount: number; + status: number; +} + +export interface OtherShipmentsDetailResp { + id: string | undefined; + customerId: string; + customerName: string; + receiptNumber: string; + receiptDate: string; + remark: string; + status: number; + files: FileData[]; + tableData: OtherShipmentsData[]; +} \ No newline at end of file diff --git a/src/api/warehouse/model/storageModel.ts b/src/api/warehouse/model/storageModel.ts new file mode 100644 index 0000000..165d43e --- /dev/null +++ b/src/api/warehouse/model/storageModel.ts @@ -0,0 +1,64 @@ +import {FileData} from "@/api/financial/model/advanceModel"; + +export interface OtherStorageData { + id: number | string; + warehouseId: number | string; + warehouseName: string; + barCode: string; + productId: number | string; + productName: string; + productModel: string; + productUnit: string; + productStandard: string; + stock: number; + productNumber: number; + unitPrice: number; + amount: number; + remark: string; +} + +export interface AddOrUpdateOtherStorageReq { + id: number | undefined; + supplierId: number; + receiptNumber: string; + receiptDate: string; + remark: string; + status: number; + files: FileData[]; + tableData: OtherStorageData[]; +} + +export interface QueryOtherStorageReq { + receiptNumber: string; + productInfo: string; + supplierId: number; + warehouseId: number; + operatorId: number; + otherReceipt: string; + status: number; + remark: string; +} + +export interface OtherStorageResp { + id: string | undefined; + supplierName: string; + receiptNumber: string; + productInfo: string; + receiptDate: string; + operator: string; + productNumber: number; + totalAmount: number; + status: number; +} + +export interface OtherStorageDetailResp { + id: string | undefined; + supplierId: string; + supplierName: string; + receiptNumber: string; + receiptDate: string; + remark: string; + status: number; + files: FileData[]; + tableData: OtherStorageData[]; +} \ No newline at end of file diff --git a/src/api/warehouse/shipments.ts b/src/api/warehouse/shipments.ts new file mode 100644 index 0000000..83188df --- /dev/null +++ b/src/api/warehouse/shipments.ts @@ -0,0 +1,89 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddOrUpdateOtherShipmentsReq, + QueryOtherShipmentsReq, + OtherShipmentsResp, + OtherShipmentsDetailResp, +} from "@/api/warehouse/model/shipmentsModel"; + +enum API { + PageList = '/warehouse/otherShipments/pageList', + AddOrUpdateAccount = '/warehouse/otherShipments/addOrUpdate', + DeleteBatch = '/warehouse/otherShipments/deleteByIds', + UpdateStatus = '/warehouse/otherShipments/updateStatusByIds', + GetDetail = '/warehouse/otherShipments/getDetailById', + Export = '/warehouse/otherShipments/export', + ExportDetail = '/warehouse/otherShipments/exportDetail', +} + +export function getOtherShipmentsPageList(params: QueryOtherShipmentsReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateOtherShipments(params: AddOrUpdateOtherShipmentsReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateOtherShipmentsStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchOtherShipments(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getOtherShipmentsDetailById(id: number) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + ); +} + +export function exportOtherShipments(params: QueryOtherShipmentsReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportOtherShipmentsDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/api/warehouse/storage.ts b/src/api/warehouse/storage.ts new file mode 100644 index 0000000..1ef9dea --- /dev/null +++ b/src/api/warehouse/storage.ts @@ -0,0 +1,89 @@ +import {defHttp} from '/@/utils/http/axios'; +import {ErrorMessageMode, SuccessMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; +import { + AddOrUpdateOtherStorageReq, + QueryOtherStorageReq, + OtherStorageResp, + OtherStorageDetailResp, +} from "@/api/warehouse/model/storageModel"; + +enum API { + PageList = '/warehouse/otherStorage/pageList', + AddOrUpdateAccount = '/warehouse/otherStorage/addOrUpdate', + DeleteBatch = '/warehouse/otherStorage/deleteByIds', + UpdateStatus = '/warehouse/otherStorage/updateStatusByIds', + GetDetail = '/warehouse/otherStorage/getDetailById', + Export = '/warehouse/otherStorage/export', + ExportDetail = '/warehouse/otherStorage/exportDetail', +} + +export function getOtherStoragePageList(params: QueryOtherStorageReq) { + return defHttp.post>( + { + url: API.PageList, + params, + } + ); +} + +export function addOrUpdateOtherStorage(params: AddOrUpdateOtherStorageReq, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.post( + { + url: API.AddOrUpdateAccount, + params, + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function updateOtherStorageStatus(ids: number[], status: number, successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.UpdateStatus}?ids=${ids}&status=${status}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function deleteBatchOtherStorage(ids: number[], successMode: SuccessMessageMode = 'notice', errorMode: ErrorMessageMode = 'message') { + return defHttp.put( + { + url: `${API.DeleteBatch}?ids=${ids}` + },{ + successMessageMode: successMode, + errorMessageMode: errorMode, + } + ); +} + +export function getOtherStorageDetailById(id: number) { + return defHttp.get>( + { + url: `${API.GetDetail}/${id}` + }, + ); +} + +export function exportOtherStorage(params: QueryOtherStorageReq) { + return defHttp.get>( + { + url: `${API.Export}`, + params, + responseType: "blob" + } + ); +} + +export function exportOtherStorageDetail(receiptNumber: string) { + return defHttp.get>( + { + url: `${API.ExportDetail}/${receiptNumber}`, + responseType: "blob" + } + ); +} \ No newline at end of file diff --git a/src/assets/.DS_Store b/src/assets/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7c6693f33acbc86913c0afad30ae0f00b318c884 GIT binary patch literal 6148 zcmeHKJ5Iwu5S?)n6a+;|=(gYhq@y&!lvLpWkOT#!7)Oer_EES51sC8%9Dp}Fqrf_` z=mJ7B((GH$$FqK3dAvl#qo>)BXh1}Ls9?5_VT*`gbVD+;90EDsW3`wM$J44@Zp6Cb zZ!#e7u160vrHURYeSg{2N9rxBqL?hI39PaqPA<;g&zljmA0n3b-*!m$f^^zL{gQ5J zPIrwJ^p0Pf{+2Z)_b98at4Ly!b@WbU9UWTHGtHAd%x~9Uo|f8{*HYEINxdvcJr`%d z8E^)Eivjd(k^X_AkIsNI;0&x8kncl)3g(8jV*GSqh(`cm7v?CK%UMElf?;l0E5ZX| zO$BNy+Yy5`9rj>xxnZrS>BM&UV5`h_Lg82)_YX0gI9K%18E^(t20D5rcr*9PbfR7B!x#dQiMu@xg$TJaGy3hY59z}&D_gazV1 N0+9wEoPnJ(@CjmwSb6{e literal 0 HcmV?d00001 diff --git a/src/assets/icons/download-count.svg b/src/assets/icons/download-count.svg new file mode 100644 index 0000000..1c95195 --- /dev/null +++ b/src/assets/icons/download-count.svg @@ -0,0 +1 @@ +Asset 91 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-1.svg b/src/assets/icons/dynamic-avatar-1.svg new file mode 100644 index 0000000..e1553e5 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-1.svg @@ -0,0 +1 @@ +Asset 15 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-2.svg b/src/assets/icons/dynamic-avatar-2.svg new file mode 100644 index 0000000..c4c1722 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-2.svg @@ -0,0 +1 @@ +Asset 16 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-3.svg b/src/assets/icons/dynamic-avatar-3.svg new file mode 100644 index 0000000..81145f9 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-3.svg @@ -0,0 +1 @@ +Asset 17 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-4.svg b/src/assets/icons/dynamic-avatar-4.svg new file mode 100644 index 0000000..e586ed4 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-4.svg @@ -0,0 +1 @@ +Asset 120 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-5.svg b/src/assets/icons/dynamic-avatar-5.svg new file mode 100644 index 0000000..746e4b8 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-5.svg @@ -0,0 +1 @@ +Asset 110 \ No newline at end of file diff --git a/src/assets/icons/dynamic-avatar-6.svg b/src/assets/icons/dynamic-avatar-6.svg new file mode 100644 index 0000000..b2432f2 --- /dev/null +++ b/src/assets/icons/dynamic-avatar-6.svg @@ -0,0 +1 @@ +Asset 100 \ No newline at end of file diff --git a/src/assets/icons/moon.svg b/src/assets/icons/moon.svg new file mode 100644 index 0000000..e6667f0 --- /dev/null +++ b/src/assets/icons/moon.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/src/assets/icons/sun.svg b/src/assets/icons/sun.svg new file mode 100644 index 0000000..a3997cb --- /dev/null +++ b/src/assets/icons/sun.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/test.svg b/src/assets/icons/test.svg new file mode 100644 index 0000000..244252d --- /dev/null +++ b/src/assets/icons/test.svg @@ -0,0 +1,21 @@ + + + + Icon1@3x + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/icons/total-sales.svg b/src/assets/icons/total-sales.svg new file mode 100644 index 0000000..eff7964 --- /dev/null +++ b/src/assets/icons/total-sales.svg @@ -0,0 +1 @@ +Asset 500 \ No newline at end of file diff --git a/src/assets/icons/transaction.svg b/src/assets/icons/transaction.svg new file mode 100644 index 0000000..7ba9e2f --- /dev/null +++ b/src/assets/icons/transaction.svg @@ -0,0 +1 @@ +Asset 480% \ No newline at end of file diff --git a/src/assets/icons/visit-count.svg b/src/assets/icons/visit-count.svg new file mode 100644 index 0000000..ba2a306 --- /dev/null +++ b/src/assets/icons/visit-count.svg @@ -0,0 +1 @@ +Asset 510 \ No newline at end of file diff --git a/src/assets/images/demo.png b/src/assets/images/demo.png new file mode 100644 index 0000000000000000000000000000000000000000..1a45c9835b7b2c708c114b04fb445e6ef00d8827 GIT binary patch literal 33342 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 literal 0 HcmV?d00001 diff --git a/src/assets/images/login-page-bg-2.png b/src/assets/images/login-page-bg-2.png new file mode 100644 index 0000000000000000000000000000000000000000..dd4b4c9e56a587e7c30b088519ebc294d30556ce GIT binary patch literal 253341 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 literal 0 HcmV?d00001 diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c04e95efb7b01555c2c79e5cad114013a9ea5bd5 GIT binary patch literal 16025 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 literal 0 HcmV?d00001 diff --git a/src/assets/svg/illustration.svg b/src/assets/svg/illustration.svg new file mode 100644 index 0000000..b45215b --- /dev/null +++ b/src/assets/svg/illustration.svg @@ -0,0 +1 @@ +Asset 336 \ No newline at end of file diff --git a/src/assets/svg/login-bg-dark.svg b/src/assets/svg/login-bg-dark.svg new file mode 100644 index 0000000..888da7a --- /dev/null +++ b/src/assets/svg/login-bg-dark.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/svg/login-bg.svg b/src/assets/svg/login-bg.svg new file mode 100644 index 0000000..7b66baf --- /dev/null +++ b/src/assets/svg/login-bg.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/assets/svg/login-box-bg.svg b/src/assets/svg/login-box-bg.svg new file mode 100644 index 0000000..ee7dbdc --- /dev/null +++ b/src/assets/svg/login-box-bg.svg @@ -0,0 +1 @@ +responsive \ No newline at end of file diff --git a/src/assets/svg/net-error.svg b/src/assets/svg/net-error.svg new file mode 100644 index 0000000..81f2004 --- /dev/null +++ b/src/assets/svg/net-error.svg @@ -0,0 +1 @@ +personal settings \ No newline at end of file diff --git a/src/assets/svg/no-data.svg b/src/assets/svg/no-data.svg new file mode 100644 index 0000000..2b9f257 --- /dev/null +++ b/src/assets/svg/no-data.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svg/preview/p-rotate.svg b/src/assets/svg/preview/p-rotate.svg new file mode 100644 index 0000000..5153a81 --- /dev/null +++ b/src/assets/svg/preview/p-rotate.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/resume.svg b/src/assets/svg/preview/resume.svg new file mode 100644 index 0000000..0e86c5f --- /dev/null +++ b/src/assets/svg/preview/resume.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/scale.svg b/src/assets/svg/preview/scale.svg new file mode 100644 index 0000000..1f7adae --- /dev/null +++ b/src/assets/svg/preview/scale.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/unrotate.svg b/src/assets/svg/preview/unrotate.svg new file mode 100644 index 0000000..e4708be --- /dev/null +++ b/src/assets/svg/preview/unrotate.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/unscale.svg b/src/assets/svg/preview/unscale.svg new file mode 100644 index 0000000..1359b34 --- /dev/null +++ b/src/assets/svg/preview/unscale.svg @@ -0,0 +1 @@ + diff --git a/src/components/.DS_Store b/src/components/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..35c8db63fc7946fa7420119a55fe2397275bf501 GIT binary patch literal 14340 zcmeHNF>f426n=X-8z&b-5(y;~;6s8Mr$I>(5Gf4>1)>Fn1mBxkFY|WZJBb3};*GUCd;7kb@7r&7&-3P% zh>F$2{#Bx7B3i)4^@a1;eM!{jIw>6IEh}emrocAEhT{uFW7->y``zu~csoPqCmJ}# z?VDlyfO@s|O#0T^wI5bc)90^Z*P<2L$KQ~4`J5Mbz#VW0+yQsM9r)J{@c&+vg;uP6 z?+&;F?m*=Le?PRbaos8FqgaQp4(xae&vBl@hk|3|0pVP`tUG0W6zk9wZ9-Gjv1w7J z7)5N3^KFKs?v(XWtYdR3Vsk1==Az6{iolL`?Et5u6KmhQ1MWcXzzv*gQki@2-@Cfe z8;|xQ?3k;U=p$t1ThvF!y+=F4ofL6tHAjrb-IM%3&EISNB&!57P*Tr2>uJ)*G=P#r zspR_OG-hb1+8XRtT=E_>?;Lo?aAAvvlKIi6GHP%q?G5$>A^77rT9ekny+Z@Ze&rXi zS22S-iC1egsq0l-@WwCRdAdcDurkxHbH8~P+#+u9*D$IEfss1G?Rb_ppkjhC7~*dm zUQDDDZ*M}4f-*FzNL87Fl=|2PItP8bGzx1|1N|QT<|hkhXjJ<&?j98@bQa63a}heH z@R6UP9UR>YTBrD2^K(Me$j`aL0}Xe3v`Db;QIBagq}ZvmJDO)QE=+mWH_O# z@r?cP;tse2?tnYs4!8rS$ANbtCH+;shdG`)yUTumPmsp^!RXhR*%)Xsm!L40n4?vw zew<3s*of%`}hGxP|Q`efAl zl6t;kJuT`&$3a-%+Jz?d`*-PA8)@h>`Zatr&{A)BKIWm9*8=Y6?%lcxl_G9vt6@~< z1V-vO1`YC9*1_Z0*Y5ho6%AwP$@(%}%5YNGGV5y6`_MC?k+{=~@Bc_+hK{PO!C%D% zZ{um?E!Xh{FHQdpyw&@4-E4i{(30i#hNcWBwLN2PUfcn9z#VW0+yQssbT}{Z4fW2<3lx5wMn#%WTQ>e`K!7Dul@8@DdV=$jhaBp8vz2Dn}RIoU;7? EZw3wg0{{R3 literal 0 HcmV?d00001 diff --git a/src/components/Application/index.ts b/src/components/Application/index.ts new file mode 100644 index 0000000..d7c5133 --- /dev/null +++ b/src/components/Application/index.ts @@ -0,0 +1,15 @@ +import { withInstall } from '/@/utils'; + +import appLogo from './src/AppLogo.vue'; +import appProvider from './src/AppProvider.vue'; +import appSearch from './src/search/AppSearch.vue'; +import appLocalePicker from './src/AppLocalePicker.vue'; +import appDarkModeToggle from './src/AppDarkModeToggle.vue'; + +export { useAppProviderContext } from './src/useAppContext'; + +export const AppLogo = withInstall(appLogo); +export const AppProvider = withInstall(appProvider); +export const AppSearch = withInstall(appSearch); +export const AppLocalePicker = withInstall(appLocalePicker); +export const AppDarkModeToggle = withInstall(appDarkModeToggle); diff --git a/src/components/Application/src/AppDarkModeToggle.vue b/src/components/Application/src/AppDarkModeToggle.vue new file mode 100644 index 0000000..69343e9 --- /dev/null +++ b/src/components/Application/src/AppDarkModeToggle.vue @@ -0,0 +1,89 @@ + + + \ No newline at end of file diff --git a/src/components/Application/src/AppLocalePicker.vue b/src/components/Application/src/AppLocalePicker.vue new file mode 100644 index 0000000..3e57092 --- /dev/null +++ b/src/components/Application/src/AppLocalePicker.vue @@ -0,0 +1,72 @@ + + + + diff --git a/src/components/Application/src/AppLogo.vue b/src/components/Application/src/AppLogo.vue new file mode 100644 index 0000000..180726b --- /dev/null +++ b/src/components/Application/src/AppLogo.vue @@ -0,0 +1,90 @@ + + + diff --git a/src/components/Application/src/AppProvider.vue b/src/components/Application/src/AppProvider.vue new file mode 100644 index 0000000..fe19a80 --- /dev/null +++ b/src/components/Application/src/AppProvider.vue @@ -0,0 +1,82 @@ + diff --git a/src/components/Application/src/search/AppSearch.vue b/src/components/Application/src/search/AppSearch.vue new file mode 100644 index 0000000..63d346e --- /dev/null +++ b/src/components/Application/src/search/AppSearch.vue @@ -0,0 +1,33 @@ + diff --git a/src/components/Application/src/search/AppSearchFooter.vue b/src/components/Application/src/search/AppSearchFooter.vue new file mode 100644 index 0000000..6c39938 --- /dev/null +++ b/src/components/Application/src/search/AppSearchFooter.vue @@ -0,0 +1,57 @@ + + + + diff --git a/src/components/Application/src/search/AppSearchKeyItem.vue b/src/components/Application/src/search/AppSearchKeyItem.vue new file mode 100644 index 0000000..08e3dbd --- /dev/null +++ b/src/components/Application/src/search/AppSearchKeyItem.vue @@ -0,0 +1,12 @@ + + diff --git a/src/components/Application/src/search/AppSearchModal.vue b/src/components/Application/src/search/AppSearchModal.vue new file mode 100644 index 0000000..612b372 --- /dev/null +++ b/src/components/Application/src/search/AppSearchModal.vue @@ -0,0 +1,267 @@ + + + + diff --git a/src/components/Application/src/search/useMenuSearch.ts b/src/components/Application/src/search/useMenuSearch.ts new file mode 100644 index 0000000..6a585e0 --- /dev/null +++ b/src/components/Application/src/search/useMenuSearch.ts @@ -0,0 +1,167 @@ +import { type Menu } from '/@/router/types'; +import { type AnyFunction } from '@vben/types'; +import { ref, onBeforeMount, unref, Ref, nextTick } from 'vue'; +import { getMenus } from '/@/router/menus'; +import { cloneDeep } from 'lodash-es'; +import { filter, forEach } from '/@/utils/helper/treeHelper'; +import { useGo } from '/@/hooks/web/usePage'; +import { useScrollTo } from '@vben/hooks'; +import { onKeyStroke, useDebounceFn } from '@vueuse/core'; +import { useI18n } from '/@/hooks/web/useI18n'; + +export interface SearchResult { + name: string; + path: string; + icon?: string; +} + +// Translate special characters +function transform(c: string) { + const code: string[] = ['$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|']; + return code.includes(c) ? `\\${c}` : c; +} + +function createSearchReg(key: string) { + const keys = [...key].map((item) => transform(item)); + const str = ['', ...keys, ''].join('.*'); + return new RegExp(str); +} + +export function useMenuSearch(refs: Ref, scrollWrap: Ref, emit: AnyFunction) { + const searchResult = ref([]); + const keyword = ref(''); + const activeIndex = ref(-1); + + let menuList: Menu[] = []; + + const { t } = useI18n(); + const go = useGo(); + const handleSearch = useDebounceFn(search, 200); + + onBeforeMount(async () => { + const list = await getMenus(); + menuList = cloneDeep(list); + forEach(menuList, (item) => { + item.name = t(item.name); + }); + }); + + function search(e: ChangeEvent) { + e?.stopPropagation(); + const key = e.target.value; + keyword.value = key.trim().toLowerCase(); + if (!key) { + searchResult.value = []; + return; + } + const reg = createSearchReg(unref(keyword)); + const filterMenu = filter(menuList, (item) => { + return reg.test(item.name) && !item.hideMenu; + }); + searchResult.value = handlerSearchResult(filterMenu, reg); + activeIndex.value = 0; + } + + function handlerSearchResult(filterMenu: Menu[], reg: RegExp, parent?: Menu) { + const ret: SearchResult[] = []; + filterMenu.forEach((item) => { + const { name, path, icon, children, hideMenu, meta } = item; + if (!hideMenu && reg.test(name) && (!children?.length || meta?.hideChildrenInMenu)) { + ret.push({ + name: parent?.name ? `${parent.name} > ${name}` : name, + path, + icon, + }); + } + if (!meta?.hideChildrenInMenu && Array.isArray(children) && children.length) { + ret.push(...handlerSearchResult(children, reg, item)); + } + }); + return ret; + } + + // Activate when the mouse moves to a certain line + function handleMouseenter(e: any) { + const index = e.target.dataset.index; + activeIndex.value = Number(index); + } + + // Arrow key up + function handleUp() { + if (!searchResult.value.length) return; + activeIndex.value--; + if (activeIndex.value < 0) { + activeIndex.value = searchResult.value.length - 1; + } + handleScroll(); + } + + // Arrow key down + function handleDown() { + if (!searchResult.value.length) return; + activeIndex.value++; + if (activeIndex.value > searchResult.value.length - 1) { + activeIndex.value = 0; + } + handleScroll(); + } + + // When the keyboard up and down keys move to an invisible place + // the scroll bar needs to scroll automatically + function handleScroll() { + const refList = unref(refs); + if (!refList || !Array.isArray(refList) || refList.length === 0 || !unref(scrollWrap)) { + return; + } + + const index = unref(activeIndex); + const currentRef = refList[index]; + if (!currentRef) { + return; + } + const wrapEl = unref(scrollWrap); + if (!wrapEl) { + return; + } + const scrollHeight = currentRef.offsetTop + currentRef.offsetHeight; + const wrapHeight = wrapEl.offsetHeight; + const { start } = useScrollTo({ + el: wrapEl, + duration: 100, + to: scrollHeight - wrapHeight, + }); + start(); + } + + // enter keyboard event + async function handleEnter() { + if (!searchResult.value.length) { + return; + } + const result = unref(searchResult); + const index = unref(activeIndex); + if (result.length === 0 || index < 0) { + return; + } + const to = result[index]; + handleClose(); + await nextTick(); + go(to.path); + } + + // close search modal + function handleClose() { + searchResult.value = []; + emit('close'); + } + + // enter search + onKeyStroke('Enter', handleEnter); + // Monitor keyboard arrow keys + onKeyStroke('ArrowUp', handleUp); + onKeyStroke('ArrowDown', handleDown); + // esc close + onKeyStroke('Escape', handleClose); + + return { handleSearch, searchResult, keyword, activeIndex, handleMouseenter, handleEnter }; +} diff --git a/src/components/Application/src/useAppContext.ts b/src/components/Application/src/useAppContext.ts new file mode 100644 index 0000000..8bdfb4f --- /dev/null +++ b/src/components/Application/src/useAppContext.ts @@ -0,0 +1,17 @@ +import { InjectionKey, Ref } from 'vue'; +import { createContext, useContext } from '/@/hooks/core/useContext'; + +export interface AppProviderContextProps { + prefixCls: Ref; + isMobile: Ref; +} + +const key: InjectionKey = Symbol(); + +export function createAppProviderContext(context: AppProviderContextProps) { + return createContext(context, key); +} + +export function useAppProviderContext() { + return useContext(key); +} diff --git a/src/components/Basic/index.ts b/src/components/Basic/index.ts new file mode 100644 index 0000000..97a53a1 --- /dev/null +++ b/src/components/Basic/index.ts @@ -0,0 +1,8 @@ +import { withInstall } from '/@/utils'; +import basicArrow from './src/BasicArrow.vue'; +import basicTitle from './src/BasicTitle.vue'; +import basicHelp from './src/BasicHelp.vue'; + +export const BasicArrow = withInstall(basicArrow); +export const BasicTitle = withInstall(basicTitle); +export const BasicHelp = withInstall(basicHelp); diff --git a/src/components/Basic/src/BasicArrow.vue b/src/components/Basic/src/BasicArrow.vue new file mode 100644 index 0000000..2de3a44 --- /dev/null +++ b/src/components/Basic/src/BasicArrow.vue @@ -0,0 +1,80 @@ + + + diff --git a/src/components/Basic/src/BasicHelp.vue b/src/components/Basic/src/BasicHelp.vue new file mode 100644 index 0000000..3b7dd4c --- /dev/null +++ b/src/components/Basic/src/BasicHelp.vue @@ -0,0 +1,114 @@ + + diff --git a/src/components/Basic/src/BasicTitle.vue b/src/components/Basic/src/BasicTitle.vue new file mode 100644 index 0000000..8ad399f --- /dev/null +++ b/src/components/Basic/src/BasicTitle.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/components/Button/index.ts b/src/components/Button/index.ts new file mode 100644 index 0000000..98add5c --- /dev/null +++ b/src/components/Button/index.ts @@ -0,0 +1,9 @@ +import { withInstall } from '/@/utils'; +import type { ExtractPropTypes } from 'vue'; +import button from './src/BasicButton.vue'; +import popConfirmButton from './src/PopConfirmButton.vue'; +import { buttonProps } from './src/props'; + +export const Button = withInstall(button); +export const PopConfirmButton = withInstall(popConfirmButton); +export declare type ButtonProps = Partial>; diff --git a/src/components/Button/src/BasicButton.vue b/src/components/Button/src/BasicButton.vue new file mode 100644 index 0000000..19e6dbb --- /dev/null +++ b/src/components/Button/src/BasicButton.vue @@ -0,0 +1,39 @@ + + + diff --git a/src/components/Button/src/PopConfirmButton.vue b/src/components/Button/src/PopConfirmButton.vue new file mode 100644 index 0000000..4c90ace --- /dev/null +++ b/src/components/Button/src/PopConfirmButton.vue @@ -0,0 +1,54 @@ + diff --git a/src/components/Button/src/props.ts b/src/components/Button/src/props.ts new file mode 100644 index 0000000..fd5fa52 --- /dev/null +++ b/src/components/Button/src/props.ts @@ -0,0 +1,26 @@ +const validColors = ['primary', 'error', 'warning', 'success', ''] as const; +type ButtonColorType = (typeof validColors)[number]; + +export const buttonProps = { + color: { + type: String as PropType, + validator: (v) => validColors.includes(v), + default: '', + }, + loading: { type: Boolean }, + disabled: { type: Boolean }, + /** + * Text before icon. + */ + preIcon: { type: String }, + /** + * Text after icon. + */ + postIcon: { type: String }, + /** + * preIcon and postIcon icon size. + * @default: 14 + */ + iconSize: { type: Number, default: 14 }, + onClick: { type: [Function, Array] as PropType<(() => any) | (() => any)[]>, default: null }, +}; diff --git a/src/components/ClickOutSide/index.ts b/src/components/ClickOutSide/index.ts new file mode 100644 index 0000000..5e7dd2d --- /dev/null +++ b/src/components/ClickOutSide/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from '/@/utils'; +import clickOutSide from './src/ClickOutSide.vue'; + +export const ClickOutSide = withInstall(clickOutSide); diff --git a/src/components/ClickOutSide/src/ClickOutSide.vue b/src/components/ClickOutSide/src/ClickOutSide.vue new file mode 100644 index 0000000..901a508 --- /dev/null +++ b/src/components/ClickOutSide/src/ClickOutSide.vue @@ -0,0 +1,20 @@ + + diff --git a/src/components/Container/index.ts b/src/components/Container/index.ts new file mode 100644 index 0000000..502a0dd --- /dev/null +++ b/src/components/Container/index.ts @@ -0,0 +1,8 @@ +import { withInstall } from '/@/utils'; +import collapseContainer from './src/collapse/CollapseContainer.vue'; +import scrollContainer from './src/ScrollContainer.vue'; + +export const CollapseContainer = withInstall(collapseContainer); +export const ScrollContainer = withInstall(scrollContainer); + +export * from './src/typing'; diff --git a/src/components/Container/src/ScrollContainer.vue b/src/components/Container/src/ScrollContainer.vue new file mode 100644 index 0000000..ca19003 --- /dev/null +++ b/src/components/Container/src/ScrollContainer.vue @@ -0,0 +1,94 @@ + + + + diff --git a/src/components/Container/src/collapse/CollapseContainer.vue b/src/components/Container/src/collapse/CollapseContainer.vue new file mode 100644 index 0000000..c9128b0 --- /dev/null +++ b/src/components/Container/src/collapse/CollapseContainer.vue @@ -0,0 +1,118 @@ + + + diff --git a/src/components/Container/src/collapse/CollapseHeader.vue b/src/components/Container/src/collapse/CollapseHeader.vue new file mode 100644 index 0000000..8b80cf8 --- /dev/null +++ b/src/components/Container/src/collapse/CollapseHeader.vue @@ -0,0 +1,44 @@ + diff --git a/src/components/Container/src/typing.ts b/src/components/Container/src/typing.ts new file mode 100644 index 0000000..86c03be --- /dev/null +++ b/src/components/Container/src/typing.ts @@ -0,0 +1,17 @@ +export type ScrollType = 'default' | 'main'; + +export interface CollapseContainerOptions { + canExpand?: boolean; + title?: string; + helpMessage?: Array | string; +} +export interface ScrollContainerOptions { + enableScroll?: boolean; + type?: ScrollType; +} + +export type ScrollActionType = RefType<{ + scrollBottom: () => void; + getScrollWrap: () => Nullable; + scrollTo: (top: number) => void; +}>; diff --git a/src/components/ContextMenu/index.ts b/src/components/ContextMenu/index.ts new file mode 100644 index 0000000..ed294d7 --- /dev/null +++ b/src/components/ContextMenu/index.ts @@ -0,0 +1,3 @@ +export { createContextMenu, destroyContextMenu } from './src/createContextMenu'; + +export * from './src/typing'; diff --git a/src/components/ContextMenu/src/ContextMenu.vue b/src/components/ContextMenu/src/ContextMenu.vue new file mode 100644 index 0000000..823b90e --- /dev/null +++ b/src/components/ContextMenu/src/ContextMenu.vue @@ -0,0 +1,209 @@ + + diff --git a/src/components/ContextMenu/src/createContextMenu.ts b/src/components/ContextMenu/src/createContextMenu.ts new file mode 100644 index 0000000..0d93290 --- /dev/null +++ b/src/components/ContextMenu/src/createContextMenu.ts @@ -0,0 +1,77 @@ +import contextMenuVue from './ContextMenu.vue'; +import { isClient } from '/@/utils/is'; +import { CreateContextOptions, ContextMenuProps } from './typing'; +import { createVNode, render } from 'vue'; + +const menuManager: { + domList: Element[]; + resolve: Fn; +} = { + domList: [], + resolve: () => {}, +}; + +export const createContextMenu = function (options: CreateContextOptions) { + const { event } = options || {}; + + event && event?.preventDefault(); + + if (!isClient) { + return; + } + return new Promise((resolve) => { + const body = document.body; + + const container = document.createElement('div'); + const propsData: Partial = {}; + if (options.styles) { + propsData.styles = options.styles; + } + + if (options.items) { + propsData.items = options.items; + } + + if (options.event) { + propsData.customEvent = event; + propsData.axis = { x: event.clientX, y: event.clientY }; + } + + const vm = createVNode(contextMenuVue, propsData); + render(vm, container); + + const handleClick = function () { + menuManager.resolve(''); + }; + + menuManager.domList.push(container); + + const remove = function () { + menuManager.domList.forEach((dom: Element) => { + try { + dom && body.removeChild(dom); + } catch (error) { + // + } + }); + body.removeEventListener('click', handleClick); + body.removeEventListener('scroll', handleClick); + }; + + menuManager.resolve = function (arg) { + remove(); + resolve(arg); + }; + remove(); + body.appendChild(container); + body.addEventListener('click', handleClick); + body.addEventListener('scroll', handleClick); + }); +}; + +export const destroyContextMenu = function () { + if (menuManager) { + menuManager.resolve(''); + menuManager.domList = []; + } +}; diff --git a/src/components/ContextMenu/src/typing.ts b/src/components/ContextMenu/src/typing.ts new file mode 100644 index 0000000..63d3d37 --- /dev/null +++ b/src/components/ContextMenu/src/typing.ts @@ -0,0 +1,36 @@ +export interface Axis { + x: number; + y: number; +} + +export interface ContextMenuItem { + label: string; + icon?: string; + hidden?: boolean; + disabled?: boolean; + handler?: Fn; + divider?: boolean; + children?: ContextMenuItem[]; +} +export interface CreateContextOptions { + event: MouseEvent; + icon?: string; + styles?: any; + items?: ContextMenuItem[]; +} + +export interface ContextMenuProps { + event?: MouseEvent; + styles?: any; + items: ContextMenuItem[]; + customEvent?: MouseEvent; + axis?: Axis; + width?: number; + showIcon?: boolean; +} + +export interface ItemContentProps { + showIcon: boolean | undefined; + item: ContextMenuItem; + handler: Fn; +} diff --git a/src/components/CountDown/index.ts b/src/components/CountDown/index.ts new file mode 100644 index 0000000..9809416 --- /dev/null +++ b/src/components/CountDown/index.ts @@ -0,0 +1,6 @@ +import { withInstall } from '/@/utils'; +import countButton from './src/CountButton.vue'; +import countdownInput from './src/CountdownInput.vue'; + +export const CountdownInput = withInstall(countdownInput); +export const CountButton = withInstall(countButton); diff --git a/src/components/CountDown/src/CountButton.vue b/src/components/CountDown/src/CountButton.vue new file mode 100644 index 0000000..1ef520e --- /dev/null +++ b/src/components/CountDown/src/CountButton.vue @@ -0,0 +1,62 @@ + + diff --git a/src/components/CountDown/src/CountdownInput.vue b/src/components/CountDown/src/CountdownInput.vue new file mode 100644 index 0000000..5cd939d --- /dev/null +++ b/src/components/CountDown/src/CountdownInput.vue @@ -0,0 +1,54 @@ + + + diff --git a/src/components/CountDown/src/useCountdown.ts b/src/components/CountDown/src/useCountdown.ts new file mode 100644 index 0000000..316d69a --- /dev/null +++ b/src/components/CountDown/src/useCountdown.ts @@ -0,0 +1,51 @@ +import { ref, unref } from 'vue'; +import { tryOnUnmounted } from '@vueuse/core'; + +export function useCountdown(count: number) { + const currentCount = ref(count); + + const isStart = ref(false); + + let timerId: ReturnType | null; + + function clear() { + timerId && window.clearInterval(timerId); + } + + function stop() { + isStart.value = false; + clear(); + timerId = null; + } + + function start() { + if (unref(isStart) || !!timerId) { + return; + } + isStart.value = true; + timerId = setInterval(() => { + if (unref(currentCount) === 1) { + stop(); + currentCount.value = count; + } else { + currentCount.value -= 1; + } + }, 1000); + } + + function reset() { + currentCount.value = count; + stop(); + } + + function restart() { + reset(); + start(); + } + + tryOnUnmounted(() => { + reset(); + }); + + return { start, reset, restart, clear, stop, currentCount, isStart }; +} diff --git a/src/components/CountTo/index.ts b/src/components/CountTo/index.ts new file mode 100644 index 0000000..36a4e65 --- /dev/null +++ b/src/components/CountTo/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from '/@/utils'; +import countTo from './src/CountTo.vue'; + +export const CountTo = withInstall(countTo); diff --git a/src/components/CountTo/src/CountTo.vue b/src/components/CountTo/src/CountTo.vue new file mode 100644 index 0000000..7de3361 --- /dev/null +++ b/src/components/CountTo/src/CountTo.vue @@ -0,0 +1,110 @@ + + diff --git a/src/components/Cropper/index.ts b/src/components/Cropper/index.ts new file mode 100644 index 0000000..88d6d1d --- /dev/null +++ b/src/components/Cropper/index.ts @@ -0,0 +1,7 @@ +import { withInstall } from '/@/utils'; +import cropperImage from './src/Cropper.vue'; +import avatarCropper from './src/CropperAvatar.vue'; + +export * from './src/typing'; +export const CropperImage = withInstall(cropperImage); +export const CropperAvatar = withInstall(avatarCropper); diff --git a/src/components/Cropper/src/Cropper.vue b/src/components/Cropper/src/Cropper.vue new file mode 100644 index 0000000..4523ad4 --- /dev/null +++ b/src/components/Cropper/src/Cropper.vue @@ -0,0 +1,188 @@ + + + diff --git a/src/components/Cropper/src/CropperAvatar.vue b/src/components/Cropper/src/CropperAvatar.vue new file mode 100644 index 0000000..ee15757 --- /dev/null +++ b/src/components/Cropper/src/CropperAvatar.vue @@ -0,0 +1,166 @@ + + + + diff --git a/src/components/Cropper/src/CropperModal.vue b/src/components/Cropper/src/CropperModal.vue new file mode 100644 index 0000000..3755a03 --- /dev/null +++ b/src/components/Cropper/src/CropperModal.vue @@ -0,0 +1,295 @@ + + + + diff --git a/src/components/Cropper/src/typing.ts b/src/components/Cropper/src/typing.ts new file mode 100644 index 0000000..e76cc6f --- /dev/null +++ b/src/components/Cropper/src/typing.ts @@ -0,0 +1,8 @@ +import type Cropper from 'cropperjs'; + +export interface CropendResult { + imgBase64: string; + imgInfo: Cropper.Data; +} + +export type { Cropper }; diff --git a/src/components/Description/index.ts b/src/components/Description/index.ts new file mode 100644 index 0000000..58277d0 --- /dev/null +++ b/src/components/Description/index.ts @@ -0,0 +1,6 @@ +import { withInstall } from '/@/utils'; +import description from './src/Description.vue'; + +export * from './src/typing'; +export { useDescription } from './src/useDescription'; +export const Description = withInstall(description); diff --git a/src/components/Description/src/Description.vue b/src/components/Description/src/Description.vue new file mode 100644 index 0000000..d24b381 --- /dev/null +++ b/src/components/Description/src/Description.vue @@ -0,0 +1,195 @@ + diff --git a/src/components/Description/src/typing.ts b/src/components/Description/src/typing.ts new file mode 100644 index 0000000..ee96084 --- /dev/null +++ b/src/components/Description/src/typing.ts @@ -0,0 +1,50 @@ +import type { VNode, CSSProperties } from 'vue'; +import type { CollapseContainerOptions } from '/@/components/Container/index'; +import type { DescriptionsProps } from 'ant-design-vue/es/descriptions/index'; + +export interface DescItem { + labelMinWidth?: number; + contentMinWidth?: number; + labelStyle?: CSSProperties; + field: string; + label: string | VNode | JSX.Element; + // Merge column + span?: number; + show?: (...arg: any) => boolean; + // render + render?: ( + val: any, + data: Recordable, + ) => VNode | undefined | JSX.Element | Element | string | number; +} + +export interface DescriptionProps extends DescriptionsProps { + // Whether to include the collapse component + useCollapse?: boolean; + /** + * item configuration + * @type DescItem + */ + schema: DescItem[]; + /** + * 数据 + * @type object + */ + data: Recordable; + /** + * Built-in CollapseContainer component configuration + * @type CollapseContainerOptions + */ + collapseOptions?: CollapseContainerOptions; +} + +export interface DescInstance { + setDescProps(descProps: Partial): void; +} + +export type Register = (descInstance: DescInstance) => void; + +/** + * @description: + */ +export type UseDescReturnType = [Register, DescInstance]; diff --git a/src/components/Description/src/useDescription.ts b/src/components/Description/src/useDescription.ts new file mode 100644 index 0000000..d1037d0 --- /dev/null +++ b/src/components/Description/src/useDescription.ts @@ -0,0 +1,28 @@ +import type { DescriptionProps, DescInstance, UseDescReturnType } from './typing'; +import { ref, getCurrentInstance, unref } from 'vue'; +import { isProdMode } from '/@/utils/env'; + +export function useDescription(props?: Partial): UseDescReturnType { + if (!getCurrentInstance()) { + throw new Error('useDescription() can only be used inside setup() or functional components!'); + } + const desc = ref>(null); + const loaded = ref(false); + + function register(instance: DescInstance) { + if (unref(loaded) && isProdMode()) { + return; + } + desc.value = instance; + props && instance.setDescProps(props); + loaded.value = true; + } + + const methods: DescInstance = { + setDescProps: (descProps: Partial): void => { + unref(desc)?.setDescProps(descProps); + }, + }; + + return [register, methods]; +} diff --git a/src/components/Drawer/index.ts b/src/components/Drawer/index.ts new file mode 100644 index 0000000..820ade5 --- /dev/null +++ b/src/components/Drawer/index.ts @@ -0,0 +1,6 @@ +import { withInstall } from '/@/utils'; +import basicDrawer from './src/BasicDrawer.vue'; + +export const BasicDrawer = withInstall(basicDrawer); +export * from './src/typing'; +export { useDrawer, useDrawerInner } from './src/useDrawer'; diff --git a/src/components/Drawer/src/BasicDrawer.vue b/src/components/Drawer/src/BasicDrawer.vue new file mode 100644 index 0000000..b3fd122 --- /dev/null +++ b/src/components/Drawer/src/BasicDrawer.vue @@ -0,0 +1,256 @@ + + + diff --git a/src/components/Drawer/src/components/DrawerFooter.vue b/src/components/Drawer/src/components/DrawerFooter.vue new file mode 100644 index 0000000..507b693 --- /dev/null +++ b/src/components/Drawer/src/components/DrawerFooter.vue @@ -0,0 +1,83 @@ + + + + diff --git a/src/components/Drawer/src/components/DrawerHeader.vue b/src/components/Drawer/src/components/DrawerHeader.vue new file mode 100644 index 0000000..09a3ad0 --- /dev/null +++ b/src/components/Drawer/src/components/DrawerHeader.vue @@ -0,0 +1,75 @@ + + + + diff --git a/src/components/Drawer/src/props.ts b/src/components/Drawer/src/props.ts new file mode 100644 index 0000000..824ec67 --- /dev/null +++ b/src/components/Drawer/src/props.ts @@ -0,0 +1,45 @@ +import type { PropType } from 'vue'; + +import { useI18n } from '/@/hooks/web/useI18n'; + +const { t } = useI18n(); + +export const footerProps = { + confirmLoading: { type: Boolean }, + /** + * @description: Show close button + */ + showCancelBtn: { type: Boolean, default: true }, + cancelButtonProps: Object as PropType, + cancelText: { type: String, default: t('common.cancelText') }, + /** + * @description: Show confirmation button + */ + showOkBtn: { type: Boolean, default: true }, + okButtonProps: Object as PropType, + okText: { type: String, default: t('common.okText') }, + okType: { type: String, default: 'primary' }, + showFooter: { type: Boolean }, + footerHeight: { + type: [String, Number] as PropType, + default: 60, + }, +}; +export const basicProps = { + isDetail: { type: Boolean }, + title: { type: String, default: '' }, + loadingText: { type: String }, + showDetailBack: { type: Boolean, default: true }, + open: { type: Boolean }, + loading: { type: Boolean }, + maskClosable: { type: Boolean, default: true }, + getContainer: { + type: [Object, String] as PropType, + }, + closeFunc: { + type: [Function, Object] as PropType, + default: null, + }, + destroyOnClose: { type: Boolean }, + ...footerProps, +}; diff --git a/src/components/Drawer/src/typing.ts b/src/components/Drawer/src/typing.ts new file mode 100644 index 0000000..c8ac392 --- /dev/null +++ b/src/components/Drawer/src/typing.ts @@ -0,0 +1,194 @@ +import type { ButtonProps } from 'ant-design-vue/lib/button/buttonTypes'; +import type { CSSProperties, VNodeChild, ComputedRef } from 'vue'; +import type { ScrollContainerOptions } from '/@/components/Container/index'; + +export interface DrawerInstance { + setDrawerProps: (props: Partial | boolean) => void; + emitOpen?: (open: boolean, uid: number) => void; +} + +export interface ReturnMethods extends DrawerInstance { + openDrawer: (open?: boolean, data?: T, openOnSet?: boolean) => void; + closeDrawer: () => void; + getOpen?: ComputedRef; +} + +export type RegisterFn = (drawerInstance: DrawerInstance, uuid?: string) => void; + +export interface ReturnInnerMethods extends DrawerInstance { + closeDrawer: () => void; + changeLoading: (loading: boolean) => void; + changeOkLoading: (loading: boolean) => void; + getOpen?: ComputedRef; +} + +export type UseDrawerReturnType = [RegisterFn, ReturnMethods]; + +export type UseDrawerInnerReturnType = [RegisterFn, ReturnInnerMethods]; + +export interface DrawerFooterProps { + showOkBtn: boolean; + showCancelBtn: boolean; + /** + * Text of the Cancel button + * @default 'cancel' + * @type string + */ + cancelText: string; + /** + * Text of the OK button + * @default 'OK' + * @type string + */ + okText: string; + + /** + * Button type of the OK button + * @default 'primary' + * @type string + */ + okType: 'primary' | 'danger' | 'dashed' | 'ghost' | 'default'; + /** + * The ok button props, follow jsx rules + * @type object + */ + okButtonProps: { props: ButtonProps; on: {} }; + + /** + * The cancel button props, follow jsx rules + * @type object + */ + cancelButtonProps: { props: ButtonProps; on: {} }; + /** + * Whether to apply loading visual effect for OK button or not + * @default false + * @type boolean + */ + confirmLoading: boolean; + + showFooter: boolean; + footerHeight: string | number; +} +export interface DrawerProps extends DrawerFooterProps { + isDetail?: boolean; + loading?: boolean; + showDetailBack?: boolean; + open?: boolean; + /** + * Built-in ScrollContainer component configuration + * @type ScrollContainerOptions + */ + scrollOptions?: ScrollContainerOptions; + closeFunc?: () => Promise; + triggerWindowResize?: boolean; + /** + * Whether a close (x) button is visible on top right of the Drawer dialog or not. + * @default true + * @type boolean + */ + closable?: boolean; + + /** + * Whether to unmount child components on closing drawer or not. + * @default false + * @type boolean + */ + destroyOnClose?: boolean; + + /** + * Return the mounted node for Drawer. + * @default 'body' + * @type any ( HTMLElement| () => HTMLElement | string) + */ + getContainer?: () => HTMLElement | string; + + /** + * Whether to show mask or not. + * @default true + * @type boolean + */ + mask?: boolean; + + /** + * Clicking on the mask (area outside the Drawer) to close the Drawer or not. + * @default true + * @type boolean + */ + maskClosable?: boolean; + + /** + * Style for Drawer's mask element. + * @default {} + * @type object + */ + maskStyle?: CSSProperties; + + /** + * The title for Drawer. + * @type any (string | slot) + */ + title?: VNodeChild | JSX.Element; + /** + * The class name of the container of the Drawer dialog. + * @type string + */ + wrapClassName?: string; + class?: string; + rootClassName?: string; + /** + * Style of wrapper element which **contains mask** compare to `drawerStyle` + * @type object + */ + wrapStyle?: CSSProperties; + + /** + * Style of the popup layer element + * @type object + */ + drawerStyle?: CSSProperties; + + /** + * Style of floating layer, typically used for adjusting its position. + * @type object + */ + bodyStyle?: CSSProperties; + headerStyle?: CSSProperties; + + /** + * Width of the Drawer dialog. + * @default 256 + * @type string | number + */ + width?: string | number; + + /** + * placement is top or bottom, height of the Drawer dialog. + * @type string | number + */ + height?: string | number; + + /** + * The z-index of the Drawer. + * @default 1000 + * @type number + */ + zIndex?: number; + + /** + * The placement of the Drawer. + * @default 'right' + * @type string + */ + placement?: 'top' | 'right' | 'bottom' | 'left'; + afterOpenChange?: (open?: boolean) => void; + keyboard?: boolean; + /** + * Specify a callback that will be called when a user clicks mask, close button or Cancel button. + */ + onClose?: (e?: Event) => void; +} +export interface DrawerActionType { + scrollBottom: () => void; + scrollTo: (to: number) => void; + getScrollWrap: () => Element | null; +} diff --git a/src/components/Drawer/src/useDrawer.ts b/src/components/Drawer/src/useDrawer.ts new file mode 100644 index 0000000..60b65af --- /dev/null +++ b/src/components/Drawer/src/useDrawer.ts @@ -0,0 +1,161 @@ +import type { + UseDrawerReturnType, + DrawerInstance, + ReturnMethods, + DrawerProps, + UseDrawerInnerReturnType, +} from './typing'; +import { + ref, + getCurrentInstance, + unref, + reactive, + watchEffect, + nextTick, + toRaw, + computed, +} from 'vue'; +import { isProdMode } from '/@/utils/env'; +import { isFunction } from '/@/utils/is'; +import { tryOnUnmounted } from '@vueuse/core'; +import { isEqual } from 'lodash-es'; +import { error } from '/@/utils/log'; + +const dataTransferRef = reactive({}); + +const openData = reactive<{ [key: number]: boolean }>({}); + +/** + * @description: Applicable to separate drawer and call outside + */ +export function useDrawer(): UseDrawerReturnType { + if (!getCurrentInstance()) { + throw new Error('useDrawer() can only be used inside setup() or functional components!'); + } + const drawer = ref(null); + const loaded = ref>(false); + const uid = ref(''); + + function register(drawerInstance: DrawerInstance, uuid: string) { + isProdMode() && + tryOnUnmounted(() => { + drawer.value = null; + loaded.value = null; + dataTransferRef[unref(uid)] = null; + }); + + if (unref(loaded) && isProdMode() && drawerInstance === unref(drawer)) { + return; + } + uid.value = uuid; + drawer.value = drawerInstance; + loaded.value = true; + + drawerInstance.emitOpen = (open: boolean, uid: number) => { + openData[uid] = open; + }; + } + + const getInstance = () => { + const instance = unref(drawer); + if (!instance) { + error('useDrawer instance is undefined!'); + } + return instance; + }; + + const methods: ReturnMethods = { + setDrawerProps: (props: Partial): void => { + getInstance()?.setDrawerProps(props); + }, + + getOpen: computed((): boolean => { + return openData[~~unref(uid)]; + }), + + openDrawer: (open = true, data?: T, openOnSet = true): void => { + getInstance()?.setDrawerProps({ + open, + }); + if (!data) return; + + if (openOnSet) { + dataTransferRef[unref(uid)] = null; + dataTransferRef[unref(uid)] = toRaw(data); + return; + } + const equal = isEqual(toRaw(dataTransferRef[unref(uid)]), toRaw(data)); + if (!equal) { + dataTransferRef[unref(uid)] = toRaw(data); + } + }, + closeDrawer: () => { + getInstance()?.setDrawerProps({ open: false }); + }, + }; + + return [register, methods]; +} + +export const useDrawerInner = (callbackFn?: Fn): UseDrawerInnerReturnType => { + const drawerInstanceRef = ref>(null); + const currentInstance = getCurrentInstance(); + const uidRef = ref(''); + + if (!getCurrentInstance()) { + throw new Error('useDrawerInner() can only be used inside setup() or functional components!'); + } + + const getInstance = () => { + const instance = unref(drawerInstanceRef); + if (!instance) { + error('useDrawerInner instance is undefined!'); + return; + } + return instance; + }; + + const register = (modalInstance: DrawerInstance, uuid: string) => { + isProdMode() && + tryOnUnmounted(() => { + drawerInstanceRef.value = null; + }); + + uidRef.value = uuid; + drawerInstanceRef.value = modalInstance; + currentInstance?.emit('register', modalInstance, uuid); + }; + + watchEffect(() => { + const data = dataTransferRef[unref(uidRef)]; + if (!data) return; + if (!callbackFn || !isFunction(callbackFn)) return; + nextTick(() => { + callbackFn(data); + }); + }); + + return [ + register, + { + changeLoading: (loading = true) => { + getInstance()?.setDrawerProps({ loading }); + }, + + changeOkLoading: (loading = true) => { + getInstance()?.setDrawerProps({ confirmLoading: loading }); + }, + getOpen: computed((): boolean => { + return openData[~~unref(uidRef)]; + }), + + closeDrawer: () => { + getInstance()?.setDrawerProps({ open: false }); + }, + + setDrawerProps: (props: Partial | boolean) => { + getInstance()?.setDrawerProps(props); + }, + }, + ]; +}; diff --git a/src/components/Dropdown/index.ts b/src/components/Dropdown/index.ts new file mode 100644 index 0000000..80439e5 --- /dev/null +++ b/src/components/Dropdown/index.ts @@ -0,0 +1,5 @@ +import { withInstall } from '/@/utils'; +import dropdown from './src/Dropdown.vue'; + +export * from './src/typing'; +export const Dropdown = withInstall(dropdown); diff --git a/src/components/Dropdown/src/Dropdown.vue b/src/components/Dropdown/src/Dropdown.vue new file mode 100644 index 0000000..973a7a3 --- /dev/null +++ b/src/components/Dropdown/src/Dropdown.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/components/Dropdown/src/typing.ts b/src/components/Dropdown/src/typing.ts new file mode 100644 index 0000000..29de8cb --- /dev/null +++ b/src/components/Dropdown/src/typing.ts @@ -0,0 +1,9 @@ +export interface DropMenu { + onClick?: Fn; + to?: string; + icon?: string; + event: string | number; + text: string; + disabled?: boolean; + divider?: boolean; +} diff --git a/src/components/Form/index.ts b/src/components/Form/index.ts new file mode 100644 index 0000000..d85b3c5 --- /dev/null +++ b/src/components/Form/index.ts @@ -0,0 +1,17 @@ +import BasicForm from './src/BasicForm.vue'; + +export * from './src/types/form'; +export * from './src/types/formItem'; + +export { useComponentRegister } from './src/hooks/useComponentRegister'; +export { useForm } from './src/hooks/useForm'; + +export { default as ApiSelect } from './src/components/ApiSelect.vue'; +export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue'; +export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue'; +export { default as ApiTree } from './src/components/ApiTree.vue'; +export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue'; +export { default as ApiCascader } from './src/components/ApiCascader.vue'; +export { default as ApiTransfer } from './src/components/ApiTransfer.vue'; + +export { BasicForm }; diff --git a/src/components/Form/src/BasicForm.vue b/src/components/Form/src/BasicForm.vue new file mode 100644 index 0000000..2442cff --- /dev/null +++ b/src/components/Form/src/BasicForm.vue @@ -0,0 +1,354 @@ + + + diff --git a/src/components/Form/src/componentMap.ts b/src/components/Form/src/componentMap.ts new file mode 100644 index 0000000..5f7b964 --- /dev/null +++ b/src/components/Form/src/componentMap.ts @@ -0,0 +1,88 @@ +import type { Component } from 'vue'; +import type { ComponentType } from './types/index'; + +/** + * Component list, register here to setting it in the form + */ +import { + Input, + Select, + Radio, + Checkbox, + AutoComplete, + Cascader, + DatePicker, + InputNumber, + Switch, + TimePicker, + TreeSelect, + Slider, + Rate, + Divider, +} from 'ant-design-vue'; + +import ApiRadioGroup from './components/ApiRadioGroup.vue'; +import RadioButtonGroup from './components/RadioButtonGroup.vue'; +import ApiSelect from './components/ApiSelect.vue'; +import ApiTree from './components/ApiTree.vue'; +import ApiTreeSelect from './components/ApiTreeSelect.vue'; +import ApiMultipleSelect from './components/ApiMultipleSelect.vue'; +import ApiMultipleTreeSelect from "./components/ApiMultipleTreeSelect.vue"; +import ApiCascader from './components/ApiCascader.vue'; +import ApiTransfer from './components/ApiTransfer.vue'; +import { BasicUpload } from '/@/components/Upload'; +import { StrengthMeter } from '/@/components/StrengthMeter'; +import { IconPicker } from '/@/components/Icon'; +import { CountdownInput } from '/@/components/CountDown'; + +const componentMap = new Map(); + +componentMap.set('Input', Input); +componentMap.set('InputGroup', Input.Group); +componentMap.set('InputPassword', Input.Password); +componentMap.set('InputSearch', Input.Search); +componentMap.set('InputTextArea', Input.TextArea); +componentMap.set('InputNumber', InputNumber); +componentMap.set('AutoComplete', AutoComplete); + +componentMap.set('Select', Select); +componentMap.set('ApiSelect', ApiSelect); +componentMap.set('ApiTree', ApiTree); +componentMap.set('TreeSelect', TreeSelect); +componentMap.set('ApiTreeSelect', ApiTreeSelect); +componentMap.set('ApiMultipleSelect', ApiMultipleSelect); +componentMap.set('ApiMultipleTreeSelect', ApiMultipleTreeSelect); +componentMap.set('ApiRadioGroup', ApiRadioGroup); +componentMap.set('Switch', Switch); +componentMap.set('RadioButtonGroup', RadioButtonGroup); +componentMap.set('RadioGroup', Radio.Group); +componentMap.set('Checkbox', Checkbox); +componentMap.set('CheckboxGroup', Checkbox.Group); +componentMap.set('ApiCascader', ApiCascader); +componentMap.set('Cascader', Cascader); +componentMap.set('Slider', Slider); +componentMap.set('Rate', Rate); +componentMap.set('ApiTransfer', ApiTransfer); + +componentMap.set('DatePicker', DatePicker); +componentMap.set('MonthPicker', DatePicker.MonthPicker); +componentMap.set('RangePicker', DatePicker.RangePicker); +componentMap.set('WeekPicker', DatePicker.WeekPicker); +componentMap.set('TimePicker', TimePicker); +componentMap.set('TimeRangePicker', TimePicker.TimeRangePicker); +componentMap.set('StrengthMeter', StrengthMeter); +componentMap.set('IconPicker', IconPicker); +componentMap.set('InputCountDown', CountdownInput); + +componentMap.set('Upload', BasicUpload); +componentMap.set('Divider', Divider); + +export function add(compName: ComponentType, component: Component) { + componentMap.set(compName, component); +} + +export function del(compName: ComponentType) { + componentMap.delete(compName); +} + +export { componentMap }; diff --git a/src/components/Form/src/components/ApiCascader.vue b/src/components/Form/src/components/ApiCascader.vue new file mode 100644 index 0000000..cc400b1 --- /dev/null +++ b/src/components/Form/src/components/ApiCascader.vue @@ -0,0 +1,200 @@ + + diff --git a/src/components/Form/src/components/ApiMultipleSelect.vue b/src/components/Form/src/components/ApiMultipleSelect.vue new file mode 100644 index 0000000..115c4e8 --- /dev/null +++ b/src/components/Form/src/components/ApiMultipleSelect.vue @@ -0,0 +1,155 @@ + + \ No newline at end of file diff --git a/src/components/Form/src/components/ApiMultipleTreeSelect.vue b/src/components/Form/src/components/ApiMultipleTreeSelect.vue new file mode 100644 index 0000000..194ec59 --- /dev/null +++ b/src/components/Form/src/components/ApiMultipleTreeSelect.vue @@ -0,0 +1,104 @@ + + + diff --git a/src/components/Form/src/components/ApiRadioGroup.vue b/src/components/Form/src/components/ApiRadioGroup.vue new file mode 100644 index 0000000..8285cdf --- /dev/null +++ b/src/components/Form/src/components/ApiRadioGroup.vue @@ -0,0 +1,136 @@ + + + diff --git a/src/components/Form/src/components/ApiSelect.vue b/src/components/Form/src/components/ApiSelect.vue new file mode 100644 index 0000000..b301ec5 --- /dev/null +++ b/src/components/Form/src/components/ApiSelect.vue @@ -0,0 +1,151 @@ + + diff --git a/src/components/Form/src/components/ApiTransfer.vue b/src/components/Form/src/components/ApiTransfer.vue new file mode 100644 index 0000000..7eccd43 --- /dev/null +++ b/src/components/Form/src/components/ApiTransfer.vue @@ -0,0 +1,137 @@ + + + diff --git a/src/components/Form/src/components/ApiTree.vue b/src/components/Form/src/components/ApiTree.vue new file mode 100644 index 0000000..41a7413 --- /dev/null +++ b/src/components/Form/src/components/ApiTree.vue @@ -0,0 +1,92 @@ + + + diff --git a/src/components/Form/src/components/ApiTreeSelect.vue b/src/components/Form/src/components/ApiTreeSelect.vue new file mode 100644 index 0000000..7e9a0b9 --- /dev/null +++ b/src/components/Form/src/components/ApiTreeSelect.vue @@ -0,0 +1,101 @@ + + + \ No newline at end of file diff --git a/src/components/Form/src/components/FormAction.vue b/src/components/Form/src/components/FormAction.vue new file mode 100644 index 0000000..3f02675 --- /dev/null +++ b/src/components/Form/src/components/FormAction.vue @@ -0,0 +1,134 @@ + + diff --git a/src/components/Form/src/components/FormItem.vue b/src/components/Form/src/components/FormItem.vue new file mode 100644 index 0000000..7652941 --- /dev/null +++ b/src/components/Form/src/components/FormItem.vue @@ -0,0 +1,414 @@ + diff --git a/src/components/Form/src/components/RadioButtonGroup.vue b/src/components/Form/src/components/RadioButtonGroup.vue new file mode 100644 index 0000000..698635e --- /dev/null +++ b/src/components/Form/src/components/RadioButtonGroup.vue @@ -0,0 +1,63 @@ + + + diff --git a/src/components/Form/src/helper.ts b/src/components/Form/src/helper.ts new file mode 100644 index 0000000..ce251a6 --- /dev/null +++ b/src/components/Form/src/helper.ts @@ -0,0 +1,91 @@ +import type { ValidationRule } from 'ant-design-vue/lib/form/Form'; +import type { ComponentType } from './types/index'; +import { useI18n } from '/@/hooks/web/useI18n'; +import { dateUtil } from '/@/utils/dateUtil'; +import { isNumber, isObject } from '/@/utils/is'; + +const { t } = useI18n(); + +/** + * @description: 生成placeholder + */ +export function createPlaceholderMessage(component: ComponentType) { + if (component.includes('Input') || component.includes('Complete')) { + return t('common.inputText'); + } + if (component.includes('Picker')) { + return t('common.chooseText'); + } + if ( + component.includes('Select') || + component.includes('Cascader') || + component.includes('Checkbox') || + component.includes('Radio') || + component.includes('Switch') + ) { + // return `请选择${label}`; + return t('common.chooseText'); + } + return ''; +} + +const DATE_TYPE = ['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker']; + +function genType() { + return [...DATE_TYPE, 'RangePicker']; +} + +export function setComponentRuleType( + rule: ValidationRule, + component: ComponentType, + valueFormat: string, +) { + if (Reflect.has(rule, 'type')) { + return; + } + if (['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'].includes(component)) { + rule.type = valueFormat ? 'string' : 'object'; + } else if (['RangePicker', 'Upload', 'CheckboxGroup', 'TimePicker'].includes(component)) { + rule.type = 'array'; + } else if (['InputNumber'].includes(component)) { + rule.type = 'number'; + } +} + +export function processDateValue(attr: Recordable, component: string) { + const { valueFormat, value } = attr; + if (valueFormat) { + attr.value = isObject(value) ? dateUtil(value).format(valueFormat) : value; + } else if (DATE_TYPE.includes(component) && value) { + attr.value = dateUtil(attr.value); + } +} + +export function handleInputNumberValue(component?: ComponentType, val?: any) { + if (!component) return val; + if (['Input', 'InputPassword', 'InputSearch', 'InputTextArea'].includes(component)) { + return val && isNumber(val) ? `${val}` : val; + } + return val; +} + +/** + * 时间字段 + */ +export const dateItemType = genType(); + +export const defaultValueComponents = ['Input', 'InputPassword', 'InputSearch', 'InputTextArea']; + +// TODO 自定义组件封装会出现验证问题,因此这里目前改成手动触发验证 +export const NO_AUTO_LINK_COMPONENTS: ComponentType[] = [ + 'Upload', + 'ApiTransfer', + 'ApiTree', + 'ApiSelect', + 'ApiMultipleSelect', + 'ApiTreeSelect', + 'ApiRadioGroup', + 'ApiCascader', + 'AutoComplete', + 'RadioButtonGroup', +]; diff --git a/src/components/Form/src/hooks/useAdvanced.ts b/src/components/Form/src/hooks/useAdvanced.ts new file mode 100644 index 0000000..96dacb2 --- /dev/null +++ b/src/components/Form/src/hooks/useAdvanced.ts @@ -0,0 +1,171 @@ +import type { ColEx } from '../types'; +import type { AdvanceState } from '../types/hooks'; +import { ComputedRef, getCurrentInstance, Ref, shallowReactive, computed, unref, watch } from 'vue'; +import type { FormProps, FormSchema } from '../types/form'; +import { isBoolean, isFunction, isNumber, isObject } from '/@/utils/is'; +import { useBreakpoint } from '/@/hooks/event/useBreakpoint'; +import { useDebounceFn } from '@vueuse/core'; + +const BASIC_COL_LEN = 24; + +interface UseAdvancedContext { + advanceState: AdvanceState; + emit: EmitType; + getProps: ComputedRef; + getSchema: ComputedRef; + formModel: Recordable; + defaultValueRef: Ref; +} + +export default function ({ + advanceState, + emit, + getProps, + getSchema, + formModel, + defaultValueRef, +}: UseAdvancedContext) { + const vm = getCurrentInstance(); + + const { realWidthRef, screenEnum, screenRef } = useBreakpoint(); + + const getEmptySpan = computed((): number => { + if (!advanceState.isAdvanced) { + return 0; + } + // For some special cases, you need to manually specify additional blank lines + const emptySpan = unref(getProps).emptySpan || 0; + + if (isNumber(emptySpan)) { + return emptySpan; + } + if (isObject(emptySpan)) { + const { span = 0 } = emptySpan; + const screen = unref(screenRef) as string; + + const screenSpan = (emptySpan as any)[screen.toLowerCase()]; + return screenSpan || span || 0; + } + return 0; + }); + + const debounceUpdateAdvanced = useDebounceFn(updateAdvanced, 30); + + watch( + [() => unref(getSchema), () => advanceState.isAdvanced, () => unref(realWidthRef)], + () => { + const { showAdvancedButton } = unref(getProps); + if (showAdvancedButton) { + debounceUpdateAdvanced(); + } + }, + { immediate: true }, + ); + + function getAdvanced(itemCol: Partial, itemColSum = 0, isLastAction = false) { + const width = unref(realWidthRef); + + const mdWidth = + parseInt(itemCol.md as string) || + parseInt(itemCol.xs as string) || + parseInt(itemCol.sm as string) || + (itemCol.span as number) || + BASIC_COL_LEN; + + const lgWidth = parseInt(itemCol.lg as string) || mdWidth; + const xlWidth = parseInt(itemCol.xl as string) || lgWidth; + const xxlWidth = parseInt(itemCol.xxl as string) || xlWidth; + if (width <= screenEnum.LG) { + itemColSum += mdWidth; + } else if (width < screenEnum.XL) { + itemColSum += lgWidth; + } else if (width < screenEnum.XXL) { + itemColSum += xlWidth; + } else { + itemColSum += xxlWidth; + } + + if (isLastAction) { + advanceState.hideAdvanceBtn = false; + if (itemColSum <= BASIC_COL_LEN * 2) { + // When less than or equal to 2 lines, the collapse and expand buttons are not displayed + advanceState.hideAdvanceBtn = true; + advanceState.isAdvanced = true; + } else if ( + itemColSum > BASIC_COL_LEN * 2 && + itemColSum <= BASIC_COL_LEN * (unref(getProps).autoAdvancedLine || 3) + ) { + advanceState.hideAdvanceBtn = false; + + // More than 3 lines collapsed by default + } else if (!advanceState.isLoad) { + advanceState.isLoad = true; + advanceState.isAdvanced = !advanceState.isAdvanced; + } + return { isAdvanced: advanceState.isAdvanced, itemColSum }; + } + if (itemColSum > BASIC_COL_LEN * (unref(getProps).alwaysShowLines || 1)) { + return { isAdvanced: advanceState.isAdvanced, itemColSum }; + } else { + // The first line is always displayed + return { isAdvanced: true, itemColSum }; + } + } + + const fieldsIsAdvancedMap = shallowReactive({}); + + function updateAdvanced() { + let itemColSum = 0; + let realItemColSum = 0; + const { baseColProps = {} } = unref(getProps); + + for (const schema of unref(getSchema)) { + const { show, colProps } = schema; + let isShow = true; + + if (isBoolean(show)) { + isShow = show; + } + + if (isFunction(show)) { + isShow = show({ + schema: schema, + model: formModel, + field: schema.field, + values: { + ...unref(defaultValueRef), + ...formModel, + }, + }); + } + + if (isShow && (colProps || baseColProps)) { + const { itemColSum: sum, isAdvanced } = getAdvanced( + { ...baseColProps, ...colProps }, + itemColSum, + ); + + itemColSum = sum || 0; + if (isAdvanced) { + realItemColSum = itemColSum; + } + fieldsIsAdvancedMap[schema.field] = isAdvanced; + } + } + + // 确保页面发送更新 + vm?.proxy?.$forceUpdate(); + + advanceState.actionSpan = (realItemColSum % BASIC_COL_LEN) + unref(getEmptySpan); + + getAdvanced(unref(getProps).actionColOptions || { span: BASIC_COL_LEN }, itemColSum, true); + + emit('advanced-change'); + } + + function handleToggleAdvanced() { + advanceState.isAdvanced = !advanceState.isAdvanced; + } + + return { handleToggleAdvanced, fieldsIsAdvancedMap }; +} diff --git a/src/components/Form/src/hooks/useAutoFocus.ts b/src/components/Form/src/hooks/useAutoFocus.ts new file mode 100644 index 0000000..e24dd6b --- /dev/null +++ b/src/components/Form/src/hooks/useAutoFocus.ts @@ -0,0 +1,40 @@ +import type { ComputedRef, Ref } from 'vue'; +import type { FormSchema, FormActionType, FormProps } from '../types/form'; + +import { unref, nextTick, watchEffect } from 'vue'; + +interface UseAutoFocusContext { + getSchema: ComputedRef; + getProps: ComputedRef; + isInitedDefault: Ref; + formElRef: Ref; +} +export async function useAutoFocus({ + getSchema, + getProps, + formElRef, + isInitedDefault, +}: UseAutoFocusContext) { + watchEffect(async () => { + if (unref(isInitedDefault) || !unref(getProps).autoFocusFirstItem) { + return; + } + await nextTick(); + const schemas = unref(getSchema); + const formEl = unref(formElRef); + const el = (formEl as any)?.$el as HTMLElement; + if (!formEl || !el || !schemas || schemas.length === 0) { + return; + } + + const firstItem = schemas[0]; + // Only open when the first form item is input type + if (!firstItem.component.includes('Input')) { + return; + } + + const inputEl = el.querySelector('.ant-row:first-child input') as Nullable; + if (!inputEl) return; + inputEl?.focus(); + }); +} diff --git a/src/components/Form/src/hooks/useComponentRegister.ts b/src/components/Form/src/hooks/useComponentRegister.ts new file mode 100644 index 0000000..218aaa9 --- /dev/null +++ b/src/components/Form/src/hooks/useComponentRegister.ts @@ -0,0 +1,11 @@ +import type { ComponentType } from '../types/index'; +import { tryOnUnmounted } from '@vueuse/core'; +import { add, del } from '../componentMap'; +import type { Component } from 'vue'; + +export function useComponentRegister(compName: ComponentType, comp: Component) { + add(compName, comp); + tryOnUnmounted(() => { + del(compName); + }); +} diff --git a/src/components/Form/src/hooks/useForm.ts b/src/components/Form/src/hooks/useForm.ts new file mode 100644 index 0000000..40f246d --- /dev/null +++ b/src/components/Form/src/hooks/useForm.ts @@ -0,0 +1,122 @@ +import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form'; +import type { NamePath } from 'ant-design-vue/lib/form/interface'; +import type { DynamicProps } from '/#/utils'; +import { ref, onUnmounted, unref, nextTick, watch } from 'vue'; +import { isProdMode } from '/@/utils/env'; +import { error } from '/@/utils/log'; +import { getDynamicProps } from '/@/utils'; + +export declare type ValidateFields = (nameList?: NamePath[]) => Promise; + +type Props = Partial>; + +export function useForm(props?: Props): UseFormReturnType { + const formRef = ref>(null); + const loadedRef = ref>(false); + + async function getForm() { + const form = unref(formRef); + if (!form) { + error( + 'The form instance has not been obtained, please make sure that the form has been rendered when performing the form operation!', + ); + } + await nextTick(); + return form as FormActionType; + } + + function register(instance: FormActionType) { + isProdMode() && + onUnmounted(() => { + formRef.value = null; + loadedRef.value = null; + }); + if (unref(loadedRef) && isProdMode() && instance === unref(formRef)) return; + + formRef.value = instance; + loadedRef.value = true; + + watch( + () => props, + () => { + props && instance.setProps(getDynamicProps(props)); + }, + { + immediate: true, + deep: true, + }, + ); + } + + const methods: FormActionType = { + scrollToField: async (name: NamePath, options?: ScrollOptions | undefined) => { + const form = await getForm(); + form.scrollToField(name, options); + }, + setProps: async (formProps: Partial) => { + const form = await getForm(); + form.setProps(formProps); + }, + + updateSchema: async (data: Partial | Partial[]) => { + const form = await getForm(); + form.updateSchema(data); + }, + + resetSchema: async (data: Partial | Partial[]) => { + const form = await getForm(); + form.resetSchema(data); + }, + + clearValidate: async (name?: string | string[]) => { + const form = await getForm(); + form.clearValidate(name); + }, + + resetFields: async () => { + getForm().then(async (form) => { + await form.resetFields(); + }); + }, + + removeSchemaByField: async (field: string | string[]) => { + unref(formRef)?.removeSchemaByField(field); + }, + + // TODO promisify + getFieldsValue: () => { + return unref(formRef)?.getFieldsValue() as T; + }, + + setFieldsValue: async (values: T) => { + const form = await getForm(); + form.setFieldsValue(values); + }, + + appendSchemaByField: async ( + schema: FormSchema | FormSchema[], + prefixField: string | undefined, + first: boolean, + ) => { + const form = await getForm(); + form.appendSchemaByField(schema, prefixField, first); + }, + + submit: async (): Promise => { + const form = await getForm(); + return form.submit(); + }, + + validate: async (nameList?: NamePath[]): Promise => { + const form = await getForm(); + return form.validate(nameList); + }, + + validateFields: async (nameList?: NamePath[]): Promise => { + const form = await getForm(); + return form.validateFields(nameList); + }, + }; + + return [register, methods]; +} diff --git a/src/components/Form/src/hooks/useFormContext.ts b/src/components/Form/src/hooks/useFormContext.ts new file mode 100644 index 0000000..01dfadd --- /dev/null +++ b/src/components/Form/src/hooks/useFormContext.ts @@ -0,0 +1,17 @@ +import type { InjectionKey } from 'vue'; +import { createContext, useContext } from '/@/hooks/core/useContext'; + +export interface FormContextProps { + resetAction: () => Promise; + submitAction: () => Promise; +} + +const key: InjectionKey = Symbol(); + +export function createFormContext(context: FormContextProps) { + return createContext(context, key); +} + +export function useFormContext() { + return useContext(key); +} diff --git a/src/components/Form/src/hooks/useFormEvents.ts b/src/components/Form/src/hooks/useFormEvents.ts new file mode 100644 index 0000000..3dcf37e --- /dev/null +++ b/src/components/Form/src/hooks/useFormEvents.ts @@ -0,0 +1,428 @@ +import type { ComputedRef, Ref } from 'vue'; +import type { FormProps, FormSchema, FormActionType } from '../types/form'; +import type { NamePath } from 'ant-design-vue/lib/form/interface'; +import { unref, toRaw, nextTick } from 'vue'; +import { + isArray, + isFunction, + isObject, + isString, + isDef, + isNullOrUnDef, + isEmpty, +} from '/@/utils/is'; +import { deepMerge } from '/@/utils'; +import { dateItemType, handleInputNumberValue, defaultValueComponents } from '../helper'; +import { dateUtil } from '/@/utils/dateUtil'; +import { cloneDeep, set, uniqBy, get } from 'lodash-es'; +import { error } from '/@/utils/log'; + +interface UseFormActionContext { + emit: EmitType; + getProps: ComputedRef; + getSchema: ComputedRef; + formModel: Recordable; + defaultValueRef: Ref; + formElRef: Ref; + schemaRef: Ref; + handleFormValues: Fn; +} + +function tryConstructArray(field: string, values: Recordable = {}): any[] | undefined { + const pattern = /^\[(.+)\]$/; + if (pattern.test(field)) { + const match = field.match(pattern); + if (match && match[1]) { + const keys = match[1].split(','); + if (!keys.length) { + return undefined; + } + + const result = []; + keys.forEach((k, index) => { + set(result, index, values[k.trim()]); + }); + + return result.filter(Boolean).length ? result : undefined; + } + } +} + +function tryConstructObject(field: string, values: Recordable = {}): Recordable | undefined { + const pattern = /^\{(.+)\}$/; + if (pattern.test(field)) { + const match = field.match(pattern); + if (match && match[1]) { + const keys = match[1].split(','); + if (!keys.length) { + return; + } + + const result = {}; + keys.forEach((k) => { + set(result, k.trim(), values[k.trim()]); + }); + + return Object.values(result).filter(Boolean).length ? result : undefined; + } + } +} + +export function useFormEvents({ + emit, + getProps, + formModel, + getSchema, + defaultValueRef, + formElRef, + schemaRef, + handleFormValues, +}: UseFormActionContext) { + async function resetFields(): Promise { + const { resetFunc, submitOnReset } = unref(getProps); + resetFunc && isFunction(resetFunc) && (await resetFunc()); + + const formEl = unref(formElRef); + if (!formEl) return; + + Object.keys(formModel).forEach((key) => { + const schema = unref(getSchema).find((item) => item.field === key); + const defaultValueObj = schema?.defaultValueObj; + const fieldKeys = Object.keys(defaultValueObj || {}); + if (fieldKeys.length) { + fieldKeys.map((field) => { + formModel[field] = defaultValueObj![field]; + }); + } + formModel[key] = getDefaultValue(schema, defaultValueRef, key); + }); + nextTick(() => clearValidate()); + + emit('reset', toRaw(formModel)); + submitOnReset && handleSubmit(); + } + // 获取表单fields + const getAllFields = () => + unref(getSchema) + .map((item) => [...(item.fields || []), item.field]) + .flat(1) + .filter(Boolean); + /** + * @description: Set form value + */ + async function setFieldsValue(values: Recordable): Promise { + const fields = getAllFields(); + + // key 支持 a.b.c 的嵌套写法 + const delimiter = '.'; + const nestKeyArray = fields.filter((item) => String(item).indexOf(delimiter) >= 0); + + const validKeys: string[] = []; + fields.forEach((key) => { + const schema = unref(getSchema).find((item) => item.field === key); + let value = get(values, key); + const hasKey = Reflect.has(values, key); + + value = handleInputNumberValue(schema?.component, value); + const { componentProps } = schema || {}; + let _props = componentProps as any; + if (typeof componentProps === 'function') { + _props = _props({ formModel: unref(formModel) }); + } + + const constructValue = tryConstructArray(key, values) || tryConstructObject(key, values); + + // 0| '' is allow + if (hasKey || !!constructValue) { + const fieldValue = constructValue || value; + // time type + if (itemIsDateType(key)) { + if (Array.isArray(fieldValue)) { + const arr: any[] = []; + for (const ele of fieldValue) { + arr.push(ele ? dateUtil(ele) : null); + } + unref(formModel)[key] = arr; + } else { + unref(formModel)[key] = fieldValue + ? _props?.valueFormat + ? fieldValue + : dateUtil(fieldValue) + : null; + } + } else { + unref(formModel)[key] = fieldValue; + } + if (_props?.onChange) { + _props?.onChange(fieldValue); + } + validKeys.push(key); + } else { + nestKeyArray.forEach((nestKey: string) => { + try { + const value = nestKey.split('.').reduce((out, item) => out[item], values); + if (isDef(value)) { + unref(formModel)[nestKey] = unref(value); + validKeys.push(nestKey); + } + } catch (e) { + // key not exist + if (isDef(defaultValueRef.value[nestKey])) { + unref(formModel)[nestKey] = cloneDeep(unref(defaultValueRef.value[nestKey])); + } + } + }); + } + }); + validateFields(validKeys).catch((_) => {}); + } + + /** + * @description: Delete based on field name + */ + async function removeSchemaByField(fields: string | string[]): Promise { + const schemaList: FormSchema[] = cloneDeep(unref(getSchema)); + if (!fields) { + return; + } + + let fieldList: string[] = isString(fields) ? [fields] : fields; + if (isString(fields)) { + fieldList = [fields]; + } + for (const field of fieldList) { + _removeSchemaByFeild(field, schemaList); + } + schemaRef.value = schemaList; + } + + /** + * @description: Delete based on field name + */ + function _removeSchemaByFeild(field: string, schemaList: FormSchema[]): void { + if (isString(field)) { + const index = schemaList.findIndex((schema) => schema.field === field); + if (index !== -1) { + delete formModel[field]; + schemaList.splice(index, 1); + } + } + } + + /** + * @description: Insert after a certain field, if not insert the last + */ + async function appendSchemaByField( + schema: FormSchema | FormSchema[], + prefixField?: string, + first = false, + ) { + const schemaList: FormSchema[] = cloneDeep(unref(getSchema)); + const addSchemaIds: string[] = Array.isArray(schema) + ? schema.map((item) => item.field) + : [schema.field]; + if (schemaList.find((item) => addSchemaIds.includes(item.field))) { + error('There are schemas that have already been added'); + return; + } + const index = schemaList.findIndex((schema) => schema.field === prefixField); + const _schemaList = isObject(schema) ? [schema as FormSchema] : (schema as FormSchema[]); + if (!prefixField || index === -1 || first) { + first ? schemaList.unshift(..._schemaList) : schemaList.push(..._schemaList); + } else if (index !== -1) { + schemaList.splice(index + 1, 0, ..._schemaList); + } + schemaRef.value = schemaList; + _setDefaultValue(schema); + } + + async function resetSchema(data: Partial | Partial[]) { + let updateData: Partial[] = []; + if (isObject(data)) { + updateData.push(data as FormSchema); + } + if (isArray(data)) { + updateData = [...data]; + } + + const hasField = updateData.every( + (item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field), + ); + + if (!hasField) { + error( + 'All children of the form Schema array that need to be updated must contain the `field` field', + ); + return; + } + schemaRef.value = updateData as FormSchema[]; + } + + async function updateSchema(data: Partial | Partial[]) { + let updateData: Partial[] = []; + if (isObject(data)) { + updateData.push(data as FormSchema); + } + if (isArray(data)) { + updateData = [...data]; + } + + const hasField = updateData.every( + (item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field), + ); + + if (!hasField) { + error( + 'All children of the form Schema array that need to be updated must contain the `field` field', + ); + return; + } + const schema: FormSchema[] = []; + unref(getSchema).forEach((val) => { + let _val; + updateData.forEach((item) => { + if (val.field === item.field) { + _val = item; + } + }); + if (_val !== undefined && val.field === _val.field) { + const newSchema = deepMerge(val, _val); + schema.push(newSchema as FormSchema); + } else { + schema.push(val); + } + }); + _setDefaultValue(schema); + + schemaRef.value = uniqBy(schema, 'field'); + } + + function _setDefaultValue(data: FormSchema | FormSchema[]) { + let schemas: FormSchema[] = []; + if (isObject(data)) { + schemas.push(data as FormSchema); + } + if (isArray(data)) { + schemas = [...data]; + } + + const obj: Recordable = {}; + const currentFieldsValue = getFieldsValue(); + schemas.forEach((item) => { + if ( + item.component != 'Divider' && + Reflect.has(item, 'field') && + item.field && + !isNullOrUnDef(item.defaultValue) && + (!(item.field in currentFieldsValue) || + isNullOrUnDef(currentFieldsValue[item.field]) || + isEmpty(currentFieldsValue[item.field])) + ) { + obj[item.field] = item.defaultValue; + } + }); + setFieldsValue(obj); + } + + function getFieldsValue(): Recordable { + const formEl = unref(formElRef); + if (!formEl) return {}; + return handleFormValues(toRaw(unref(formModel))); + } + + /** + * @description: Is it time + */ + function itemIsDateType(key: string) { + return unref(getSchema).some((item) => { + return item.field === key ? dateItemType.includes(item.component) : false; + }); + } + + async function validateFields(nameList?: NamePath[] | undefined) { + return unref(formElRef)?.validateFields(nameList); + } + + async function validate(nameList?: NamePath[] | false | undefined) { + let _nameList: any; + if (nameList === undefined) { + _nameList = getAllFields(); + } else { + _nameList = nameList === Array.isArray(nameList) ? nameList : undefined; + } + return await unref(formElRef)?.validate(_nameList); + } + + async function clearValidate(name?: string | string[]) { + await unref(formElRef)?.clearValidate(name); + } + + async function scrollToField(name: NamePath, options?: ScrollOptions | undefined) { + await unref(formElRef)?.scrollToField(name, options); + } + + /** + * @description: Form submission + */ + async function handleSubmit(e?: Event): Promise { + e && e.preventDefault(); + const { submitFunc } = unref(getProps); + if (submitFunc && isFunction(submitFunc)) { + await submitFunc(); + return; + } + const formEl = unref(formElRef); + if (!formEl) return; + try { + const values = await validate(); + const res = handleFormValues(values); + emit('submit', res); + } catch (error: any) { + if (error?.outOfDate === false && error?.errorFields) { + return; + } + throw new Error(error); + } + } + + return { + handleSubmit, + clearValidate, + validate, + validateFields, + getFieldsValue, + updateSchema, + resetSchema, + appendSchemaByField, + removeSchemaByField, + resetFields, + setFieldsValue, + scrollToField, + }; +} + +function getDefaultValue( + schema: FormSchema | undefined, + defaultValueRef: UseFormActionContext['defaultValueRef'], + key: string, +) { + let defaultValue = cloneDeep(defaultValueRef.value[key]); + const isInput = checkIsInput(schema); + if (isInput) { + return defaultValue || ''; + } + if (!defaultValue && schema && checkIsRangeSlider(schema)) { + defaultValue = [0, 0]; + } + return defaultValue; +} + +function checkIsRangeSlider(schema: FormSchema) { + if (schema.component === 'Slider' && schema.componentProps && schema.componentProps.range) { + return true; + } +} + +function checkIsInput(schema?: FormSchema) { + return schema?.component && defaultValueComponents.includes(schema.component); +} diff --git a/src/components/Form/src/hooks/useFormValues.ts b/src/components/Form/src/hooks/useFormValues.ts new file mode 100644 index 0000000..4317287 --- /dev/null +++ b/src/components/Form/src/hooks/useFormValues.ts @@ -0,0 +1,161 @@ +import { isArray, isFunction, isObject, isString, isNullOrUnDef } from '/@/utils/is'; +import { dateUtil } from '/@/utils/dateUtil'; +import { unref } from 'vue'; +import type { Ref, ComputedRef } from 'vue'; +import type { FormProps, FormSchema } from '../types/form'; +import { cloneDeep, set } from 'lodash-es'; + +interface UseFormValuesContext { + defaultValueRef: Ref; + getSchema: ComputedRef; + getProps: ComputedRef; + formModel: Recordable; +} + +/** + * @desription deconstruct array-link key. This method will mutate the target. + */ +function tryDeconstructArray(key: string, value: any, target: Recordable) { + const pattern = /^\[(.+)\]$/; + if (pattern.test(key)) { + const match = key.match(pattern); + if (match && match[1]) { + const keys = match[1].split(','); + value = Array.isArray(value) ? value : [value]; + keys.forEach((k, index) => { + set(target, k.trim(), value[index]); + }); + return true; + } + } +} + +/** + * @desription deconstruct object-link key. This method will mutate the target. + */ +function tryDeconstructObject(key: string, value: any, target: Recordable) { + const pattern = /^\{(.+)\}$/; + if (pattern.test(key)) { + const match = key.match(pattern); + if (match && match[1]) { + const keys = match[1].split(','); + value = isObject(value) ? value : {}; + keys.forEach((k) => { + set(target, k.trim(), value[k.trim()]); + }); + return true; + } + } +} + +export function useFormValues({ + defaultValueRef, + getSchema, + formModel, + getProps, +}: UseFormValuesContext) { + // Processing form values + function handleFormValues(values: Recordable) { + if (!isObject(values)) { + return {}; + } + const res: Recordable = {}; + for (const item of Object.entries(values)) { + let [, value] = item; + const [key] = item; + if (!key || (isArray(value) && value.length === 0) || isFunction(value)) { + continue; + } + const transformDateFunc = unref(getProps).transformDateFunc; + if (isObject(value)) { + value = transformDateFunc?.(value); + } + + if (isArray(value) && value[0]?.format && value[1]?.format) { + value = value.map((item) => transformDateFunc?.(item)); + } + // Remove spaces + if (isString(value)) { + // remove params from URL + if (value === '') { + value = undefined; + } else { + value = value.trim(); + } + } + if (!tryDeconstructArray(key, value, res) && !tryDeconstructObject(key, value, res)) { + // 没有解构成功的,按原样赋值 + set(res, key, value); + } + } + return handleRangeTimeValue(res); + } + + /** + * @description: Processing time interval parameters + */ + function handleRangeTimeValue(values: Recordable) { + const fieldMapToTime = unref(getProps).fieldMapToTime; + + if (!fieldMapToTime || !Array.isArray(fieldMapToTime)) { + return values; + } + + for (const [field, [startTimeKey, endTimeKey], format = 'YYYY-MM-DD'] of fieldMapToTime) { + if (!field || !startTimeKey || !endTimeKey) { + continue; + } + // If the value to be converted is empty, remove the field + if (!values[field]) { + Reflect.deleteProperty(values, field); + continue; + } + + const [startTime, endTime]: string[] = values[field]; + + const [startTimeFormat, endTimeFormat] = Array.isArray(format) ? format : [format, format]; + + values[startTimeKey] = formatTime(startTime, startTimeFormat); + values[endTimeKey] = formatTime(endTime, endTimeFormat); + Reflect.deleteProperty(values, field); + } + + return values; + } + + function formatTime(time: string, format: string) { + if (format === 'timestamp') { + return dateUtil(time).unix(); + } else if (format === 'timestampStartDay') { + return dateUtil(time).startOf('day').unix(); + } + return dateUtil(time).format(format); + } + + function initDefault() { + const schemas = unref(getSchema); + const obj: Recordable = {}; + schemas.forEach((item) => { + const { defaultValue, defaultValueObj } = item; + const fieldKeys = Object.keys(defaultValueObj || {}); + if (fieldKeys.length) { + fieldKeys.map((field) => { + obj[field] = defaultValueObj![field]; + if (formModel[field] === undefined) { + formModel[field] = defaultValueObj![field]; + } + }); + } + if (!isNullOrUnDef(defaultValue)) { + obj[item.field] = defaultValue; + + if (formModel[item.field] === undefined) { + formModel[item.field] = defaultValue; + } + } + }); + defaultValueRef.value = cloneDeep(obj); + } + + return { handleFormValues, initDefault }; +} diff --git a/src/components/Form/src/hooks/useLabelWidth.ts b/src/components/Form/src/hooks/useLabelWidth.ts new file mode 100644 index 0000000..3befa1c --- /dev/null +++ b/src/components/Form/src/hooks/useLabelWidth.ts @@ -0,0 +1,42 @@ +import type { Ref } from 'vue'; +import { computed, unref } from 'vue'; +import type { FormProps, FormSchema } from '../types/form'; +import { isNumber } from '/@/utils/is'; + +export function useItemLabelWidth(schemaItemRef: Ref, propsRef: Ref) { + return computed(() => { + const schemaItem = unref(schemaItemRef); + const { labelCol = {}, wrapperCol = {} } = schemaItem.itemProps || {}; + const { labelWidth, disabledLabelWidth } = schemaItem; + + const { + labelWidth: globalLabelWidth, + labelCol: globalLabelCol, + wrapperCol: globWrapperCol, + layout, + } = unref(propsRef); + + // If labelWidth is set globally, all items setting + if ((!globalLabelWidth && !labelWidth && !globalLabelCol) || disabledLabelWidth) { + labelCol.style = { + textAlign: 'left', + }; + return { labelCol, wrapperCol }; + } + let width = labelWidth || globalLabelWidth; + const col = { ...globalLabelCol, ...labelCol }; + const wrapCol = { ...globWrapperCol, ...wrapperCol }; + + if (width) { + width = isNumber(width) ? `${width}px` : width; + } + + return { + labelCol: { style: { width }, ...col }, + wrapperCol: { + style: { width: layout === 'vertical' ? '100%' : `calc(100% - ${width})` }, + ...wrapCol, + }, + }; + }); +} diff --git a/src/components/Form/src/props.ts b/src/components/Form/src/props.ts new file mode 100644 index 0000000..f3f6a2e --- /dev/null +++ b/src/components/Form/src/props.ts @@ -0,0 +1,103 @@ +import type { FieldMapToTime, FormSchema } from './types/form'; +import type { CSSProperties, PropType } from 'vue'; +import type { ColEx } from './types'; +import type { TableActionType } from '/@/components/Table'; +import type { ButtonProps } from 'ant-design-vue/es/button/buttonTypes'; +import type { RowProps } from 'ant-design-vue/lib/grid/Row'; +import { propTypes } from '/@/utils/propTypes'; + +export const basicProps = { + model: { + type: Object as PropType, + default: () => ({}), + }, + // 标签宽度 固定宽度 + labelWidth: { + type: [Number, String] as PropType, + default: 0, + }, + fieldMapToTime: { + type: Array as PropType, + default: () => [], + }, + compact: propTypes.bool, + // 表单配置规则 + schemas: { + type: Array as PropType, + default: () => [], + }, + mergeDynamicData: { + type: Object as PropType, + default: null, + }, + baseRowStyle: { + type: Object as PropType, + }, + baseColProps: { + type: Object as PropType>, + }, + autoSetPlaceHolder: propTypes.bool.def(true), + // 在INPUT组件上单击回车时,是否自动提交 + autoSubmitOnEnter: propTypes.bool.def(false), + submitOnReset: propTypes.bool, + submitOnChange: propTypes.bool, + size: propTypes.oneOf(['default', 'small', 'large']).def('default'), + // 禁用表单 + disabled: propTypes.bool, + emptySpan: { + type: [Number, Object] as PropType, + default: 0, + }, + // 是否显示收起展开按钮 + showAdvancedButton: propTypes.bool, + // 转化时间 + transformDateFunc: { + type: Function as PropType, + default: (date: any) => { + return date?.format?.('YYYY-MM-DD HH:mm:ss') ?? date; + }, + }, + rulesMessageJoinLabel: propTypes.bool.def(true), + // 超过3行自动折叠 + autoAdvancedLine: propTypes.number.def(3), + // 不受折叠影响的行数 + alwaysShowLines: propTypes.number.def(1), + + // 是否显示操作按钮 + showActionButtonGroup: propTypes.bool.def(true), + // 操作列Col配置 + actionColOptions: Object as PropType>, + // 显示重置按钮 + showResetButton: propTypes.bool.def(true), + // 是否聚焦第一个输入框,只在第一个表单项为input的时候作用 + autoFocusFirstItem: propTypes.bool, + // 重置按钮配置 + resetButtonOptions: Object as PropType>, + + // 显示确认按钮 + showSubmitButton: propTypes.bool.def(true), + // 确认按钮配置 + submitButtonOptions: Object as PropType>, + + // 自定义重置函数 + resetFunc: Function as PropType<() => Promise>, + submitFunc: Function as PropType<() => Promise>, + + // 以下为默认props + hideRequiredMark: propTypes.bool, + + labelCol: Object as PropType>, + + layout: propTypes.oneOf(['horizontal', 'vertical', 'inline']).def('horizontal'), + tableAction: { + type: Object as PropType, + }, + + wrapperCol: Object as PropType>, + + colon: propTypes.bool, + + labelAlign: propTypes.string, + + rowProps: Object as PropType, +}; diff --git a/src/components/Form/src/types/form.ts b/src/components/Form/src/types/form.ts new file mode 100644 index 0000000..0cd5708 --- /dev/null +++ b/src/components/Form/src/types/form.ts @@ -0,0 +1,241 @@ +import type { NamePath, RuleObject } from 'ant-design-vue/lib/form/interface'; +import type { VNode, CSSProperties } from 'vue'; +import type { ButtonProps as AntdButtonProps } from '/@/components/Button'; +import type { FormItem } from './formItem'; +import type { ColEx, ComponentType } from './index'; +import type { TableActionType } from '/@/components/Table/src/types/table'; +import type { RowProps } from 'ant-design-vue/lib/grid/Row'; + +export type FieldMapToTime = [string, [string, string], (string | [string, string])?][]; + +export type Rule = RuleObject & { + trigger?: 'blur' | 'change' | ['change', 'blur']; +}; + +export interface RenderCallbackParams { + schema: FormSchema; + values: Recordable; + model: Recordable; + field: string; +} + +export interface ButtonProps extends AntdButtonProps { + text?: string; +} + +export interface FormActionType { + submit: () => Promise; + setFieldsValue: (values: Recordable) => Promise; + resetFields: () => Promise; + getFieldsValue: () => Recordable; + clearValidate: (name?: string | string[]) => Promise; + updateSchema: (data: Partial | Partial[]) => Promise; + resetSchema: (data: Partial | Partial[]) => Promise; + setProps: (formProps: Partial) => Promise; + removeSchemaByField: (field: string | string[]) => Promise; + appendSchemaByField: ( + schema: FormSchema | FormSchema[], + prefixField: string | undefined, + first?: boolean | undefined, + ) => Promise; + validateFields: (nameList?: NamePath[]) => Promise; + validate: (nameList?: NamePath[] | false) => Promise; + scrollToField: (name: NamePath, options?: ScrollOptions) => Promise; +} + +export type RegisterFn = (formInstance: FormActionType) => void; + +export type UseFormReturnType = [RegisterFn, FormActionType]; + +export interface FormProps { + name?: string; + layout?: 'vertical' | 'inline' | 'horizontal'; + // Form value + model?: Recordable; + // The width of all items in the entire form + labelWidth?: number | string; + // alignment + labelAlign?: 'left' | 'right'; + // Row configuration for the entire form + rowProps?: RowProps; + // Submit form on reset + submitOnReset?: boolean; + // Submit form on form changing + submitOnChange?: boolean; + // Col configuration for the entire form + labelCol?: Partial; + // Col configuration for the entire form + wrapperCol?: Partial; + + // General row style + baseRowStyle?: CSSProperties; + + // General col configuration + baseColProps?: Partial; + + // Form configuration rules + schemas?: FormSchema[]; + // Function values used to merge into dynamic control form items + mergeDynamicData?: Recordable; + // Compact mode for search forms + compact?: boolean; + // Blank line span + emptySpan?: number | Partial; + // Internal component size of the form + size?: 'default' | 'small' | 'large'; + // Whether to disable + disabled?: boolean; + // Time interval fields are mapped into multiple + fieldMapToTime?: FieldMapToTime; + // Placeholder is set automatically + autoSetPlaceHolder?: boolean; + // Auto submit on press enter on input + autoSubmitOnEnter?: boolean; + // Check whether the information is added to the label + rulesMessageJoinLabel?: boolean; + // Whether to show collapse and expand buttons + showAdvancedButton?: boolean; + // Whether to focus on the first input box, only works when the first form item is input + autoFocusFirstItem?: boolean; + // Automatically collapse over the specified number of rows + autoAdvancedLine?: number; + // Always show lines + alwaysShowLines?: number; + // Whether to show the operation button + showActionButtonGroup?: boolean; + + // Reset button configuration + resetButtonOptions?: Partial; + + // Confirm button configuration + submitButtonOptions?: Partial; + + // Operation column configuration + actionColOptions?: Partial; + + // Show reset button + showResetButton?: boolean; + // Show confirmation button + showSubmitButton?: boolean; + + resetFunc?: () => Promise; + submitFunc?: () => Promise; + transformDateFunc?: (date: any) => string; + colon?: boolean; +} +export type RenderOpts = { + disabled: boolean; + [key: string]: any; +}; +export interface FormSchema { + // Field name + field: string; + // Extra Fields name[] + fields?: string[]; + // Event name triggered by internal value change, default change + changeEvent?: string; + // Variable name bound to v-model Default value + valueField?: string; + // Label name + label?: string | VNode; + // Auxiliary text + subLabel?: string; + // Help text on the right side of the text + helpMessage?: + | string + | string[] + | ((renderCallbackParams: RenderCallbackParams) => string | string[]); + // BaseHelp component props + helpComponentProps?: Partial; + // Label width, if it is passed, the labelCol and WrapperCol configured by itemProps will be invalid + labelWidth?: string | number; + // Disable the adjustment of labelWidth with global settings of formModel, and manually set labelCol and wrapperCol by yourself + disabledLabelWidth?: boolean; + // render component + component: ComponentType; + // Component parameters + componentProps?: + | ((opt: { + schema: FormSchema; + tableAction: TableActionType; + formActionType: FormActionType; + formModel: Recordable; + }) => Recordable) + | object; + // Required + required?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean); + + suffix?: string | number | ((values: RenderCallbackParams) => string | number); + + // Validation rules + rules?: Rule[]; + // Check whether the information is added to the label + rulesMessageJoinLabel?: boolean; + + // Reference formModelItem + itemProps?: Partial; + + // col configuration outside formModelItem + colProps?: Partial; + + // 默认值 + defaultValue?: any; + + // 额外默认值数组对象 + defaultValueObj?: { [key: string]: any }; + + // 是否自动处理与时间相关组件的默认值 + isHandleDateDefaultValue?: boolean; + + isAdvanced?: boolean; + + // Matching details components + span?: number; + + ifShow?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean); + + show?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean); + + // Render the content in the form-item tag + render?: ( + renderCallbackParams: RenderCallbackParams, + opts: RenderOpts, + ) => VNode | VNode[] | string; + + // Rendering col content requires outer wrapper form-item + renderColContent?: ( + renderCallbackParams: RenderCallbackParams, + opts: RenderOpts, + ) => VNode | VNode[] | string; + + renderComponentContent?: + | ((renderCallbackParams: RenderCallbackParams, opts: RenderOpts) => any) + | VNode + | VNode[] + | string; + + // Custom slot, in from-item + slot?: string; + + // Custom slot, similar to renderColContent + colSlot?: string; + + dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean); + + dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[]; +} +export interface HelpComponentProps { + maxWidth: string; + // Whether to display the serial number + showIndex: boolean; + // Text list + text: any; + // colour + color: string; + // font size + fontSize: string; + icon: string; + absolute: boolean; + // Positioning + position: any; +} diff --git a/src/components/Form/src/types/formItem.ts b/src/components/Form/src/types/formItem.ts new file mode 100644 index 0000000..77b238a --- /dev/null +++ b/src/components/Form/src/types/formItem.ts @@ -0,0 +1,91 @@ +import type { NamePath } from 'ant-design-vue/lib/form/interface'; +import type { ColProps } from 'ant-design-vue/lib/grid/Col'; +import type { HTMLAttributes, VNodeChild } from 'vue'; + +export interface FormItem { + /** + * Used with label, whether to display : after label text. + * @default true + * @type boolean + */ + colon?: boolean; + + /** + * The extra prompt message. It is similar to help. Usage example: to display error message and prompt message at the same time. + * @type any (string | slot) + */ + extra?: string | VNodeChild | JSX.Element; + + /** + * Used with validateStatus, this option specifies the validation status icon. Recommended to be used only with Input. + * @default false + * @type boolean + */ + hasFeedback?: boolean; + + /** + * The prompt message. If not provided, the prompt message will be generated by the validation rule. + * @type any (string | slot) + */ + help?: string | VNodeChild | JSX.Element; + + /** + * Label test + * @type any (string | slot) + */ + label?: string | VNodeChild | JSX.Element; + + /** + * The layout of label. You can set span offset to something like {span: 3, offset: 12} or sm: {span: 3, offset: 12} same as with + * @type Col + */ + labelCol?: ColProps & HTMLAttributes; + + /** + * Whether provided or not, it will be generated by the validation rule. + * @default false + * @type boolean + */ + required?: boolean; + + /** + * The validation status. If not provided, it will be generated by validation rule. options: 'success' 'warning' 'error' 'validating' + * @type string + */ + validateStatus?: '' | 'success' | 'warning' | 'error' | 'validating'; + + /** + * The layout for input controls, same as labelCol + * @type Col + */ + wrapperCol?: ColProps; + /** + * Set sub label htmlFor. + */ + htmlFor?: string; + /** + * text align of label + */ + labelAlign?: 'left' | 'right'; + /** + * a key of model. In the setting of validate and resetFields method, the attribute is required + */ + name?: NamePath; + /** + * validation rules of form + */ + rules?: object | object[]; + /** + * Whether to automatically associate form fields. In most cases, you can setting automatic association. + * If the conditions for automatic association are not met, you can manually associate them. See the notes below. + */ + autoLink?: boolean; + /** + * Whether stop validate on first rule of error for this field. + */ + validateFirst?: boolean; + /** + * When to validate the value of children node + */ + validateTrigger?: string | string[] | false; +} diff --git a/src/components/Form/src/types/hooks.ts b/src/components/Form/src/types/hooks.ts new file mode 100644 index 0000000..0308e73 --- /dev/null +++ b/src/components/Form/src/types/hooks.ts @@ -0,0 +1,6 @@ +export interface AdvanceState { + isAdvanced: boolean; + hideAdvanceBtn: boolean; + isLoad: boolean; + actionSpan: number; +} diff --git a/src/components/Form/src/types/index.ts b/src/components/Form/src/types/index.ts new file mode 100644 index 0000000..7238247 --- /dev/null +++ b/src/components/Form/src/types/index.ts @@ -0,0 +1,120 @@ +type ColSpanType = number | string; +export interface ColEx { + style?: any; + /** + * raster number of cells to occupy, 0 corresponds to display: none + * @default none (0) + * @type ColSpanType + */ + span?: ColSpanType; + + /** + * raster order, used in flex layout mode + * @default 0 + * @type ColSpanType + */ + order?: ColSpanType; + + /** + * the layout fill of flex + * @default none + * @type ColSpanType + */ + flex?: ColSpanType; + + /** + * the number of cells to offset Col from the left + * @default 0 + * @type ColSpanType + */ + offset?: ColSpanType; + + /** + * the number of cells that raster is moved to the right + * @default 0 + * @type ColSpanType + */ + push?: ColSpanType; + + /** + * the number of cells that raster is moved to the left + * @default 0 + * @type ColSpanType + */ + pull?: ColSpanType; + + /** + * <576px and also default setting, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + xs?: { span: ColSpanType; offset: ColSpanType } | ColSpanType; + + /** + * ≥576px, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + sm?: { span: ColSpanType; offset: ColSpanType } | ColSpanType; + + /** + * ≥768px, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + md?: { span: ColSpanType; offset: ColSpanType } | ColSpanType; + + /** + * ≥992px, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + lg?: { span: ColSpanType; offset: ColSpanType } | ColSpanType; + + /** + * ≥1200px, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + xl?: { span: ColSpanType; offset: ColSpanType } | ColSpanType; + + /** + * ≥1600px, could be a span value or an object containing above props + * @type { span: ColSpanType, offset: ColSpanType } | ColSpanType + */ + xxl?: { span: ColSpanType; offset: ColSpanType } | ColSpanType; +} + +export type ComponentType = + | 'Input' + | 'InputGroup' + | 'InputPassword' + | 'InputSearch' + | 'InputTextArea' + | 'InputNumber' + | 'InputCountDown' + | 'Select' + | 'ApiSelect' + | 'TreeSelect' + | 'ApiTree' + | 'ApiTreeSelect' + | 'ApiMultipleSelect' + | 'ApiMultipleTreeSelect' + | 'ApiRadioGroup' + | 'RadioButtonGroup' + | 'RadioGroup' + | 'Checkbox' + | 'CheckboxGroup' + | 'AutoComplete' + | 'ApiCascader' + | 'Cascader' + | 'DatePicker' + | 'MonthPicker' + | 'RangePicker' + | 'WeekPicker' + | 'TimePicker' + | 'TimeRangePicker' + | 'Switch' + | 'StrengthMeter' + | 'Upload' + | 'IconPicker' + | 'Render' + | 'Slider' + | 'Rate' + | 'Divider' + | 'ApiTransfer'; diff --git a/src/components/Icon/Icon.vue b/src/components/Icon/Icon.vue new file mode 100644 index 0000000..58b970e --- /dev/null +++ b/src/components/Icon/Icon.vue @@ -0,0 +1,121 @@ + + + diff --git a/src/components/Icon/data/icons.data.ts b/src/components/Icon/data/icons.data.ts new file mode 100644 index 0000000..e5fe3e2 --- /dev/null +++ b/src/components/Icon/data/icons.data.ts @@ -0,0 +1,793 @@ +export default { + prefix: 'ant-design', + icons: [ + 'account-book-filled', + 'account-book-outlined', + 'account-book-twotone', + 'aim-outlined', + 'alert-filled', + 'alert-outlined', + 'alert-twotone', + 'alibaba-outlined', + 'align-center-outlined', + 'align-left-outlined', + 'align-right-outlined', + 'alipay-circle-filled', + 'alipay-circle-outlined', + 'alipay-outlined', + 'alipay-square-filled', + 'aliwangwang-filled', + 'aliwangwang-outlined', + 'aliyun-outlined', + 'amazon-circle-filled', + 'amazon-outlined', + 'amazon-square-filled', + 'android-filled', + 'android-outlined', + 'ant-cloud-outlined', + 'ant-design-outlined', + 'apartment-outlined', + 'api-filled', + 'api-outlined', + 'api-twotone', + 'apple-filled', + 'apple-outlined', + 'appstore-add-outlined', + 'appstore-filled', + 'appstore-outlined', + 'appstore-twotone', + 'area-chart-outlined', + 'arrow-down-outlined', + 'arrow-left-outlined', + 'arrow-right-outlined', + 'arrow-up-outlined', + 'arrows-alt-outlined', + 'audio-filled', + 'audio-muted-outlined', + 'audio-outlined', + 'audio-twotone', + 'audit-outlined', + 'backward-filled', + 'backward-outlined', + 'bank-filled', + 'bank-outlined', + 'bank-twotone', + 'bar-chart-outlined', + 'barcode-outlined', + 'bars-outlined', + 'behance-circle-filled', + 'behance-outlined', + 'behance-square-filled', + 'behance-square-outlined', + 'bell-filled', + 'bell-outlined', + 'bell-twotone', + 'bg-colors-outlined', + 'block-outlined', + 'bold-outlined', + 'book-filled', + 'book-outlined', + 'book-twotone', + 'border-bottom-outlined', + 'border-horizontal-outlined', + 'border-inner-outlined', + 'border-left-outlined', + 'border-outer-outlined', + 'border-outlined', + 'border-right-outlined', + 'border-top-outlined', + 'border-verticle-outlined', + 'borderless-table-outlined', + 'box-plot-filled', + 'box-plot-outlined', + 'box-plot-twotone', + 'branches-outlined', + 'bug-filled', + 'bug-outlined', + 'bug-twotone', + 'build-filled', + 'build-outlined', + 'build-twotone', + 'bulb-filled', + 'bulb-outlined', + 'bulb-twotone', + 'calculator-filled', + 'calculator-outlined', + 'calculator-twotone', + 'calendar-filled', + 'calendar-outlined', + 'calendar-twotone', + 'camera-filled', + 'camera-outlined', + 'camera-twotone', + 'car-filled', + 'car-outlined', + 'car-twotone', + 'caret-down-filled', + 'caret-down-outlined', + 'caret-left-filled', + 'caret-left-outlined', + 'caret-right-filled', + 'caret-right-outlined', + 'caret-up-filled', + 'caret-up-outlined', + 'carry-out-filled', + 'carry-out-outlined', + 'carry-out-twotone', + 'check-circle-filled', + 'check-circle-outlined', + 'check-circle-twotone', + 'check-outlined', + 'check-square-filled', + 'check-square-outlined', + 'check-square-twotone', + 'chrome-filled', + 'chrome-outlined', + 'ci-circle-filled', + 'ci-circle-outlined', + 'ci-circle-twotone', + 'ci-outlined', + 'ci-twotone', + 'clear-outlined', + 'clock-circle-filled', + 'clock-circle-outlined', + 'clock-circle-twotone', + 'close-circle-filled', + 'close-circle-outlined', + 'close-circle-twotone', + 'close-outlined', + 'close-square-filled', + 'close-square-outlined', + 'close-square-twotone', + 'cloud-download-outlined', + 'cloud-filled', + 'cloud-outlined', + 'cloud-server-outlined', + 'cloud-sync-outlined', + 'cloud-twotone', + 'cloud-upload-outlined', + 'cluster-outlined', + 'code-filled', + 'code-outlined', + 'code-sandbox-circle-filled', + 'code-sandbox-outlined', + 'code-sandbox-square-filled', + 'code-twotone', + 'codepen-circle-filled', + 'codepen-circle-outlined', + 'codepen-outlined', + 'codepen-square-filled', + 'coffee-outlined', + 'column-height-outlined', + 'column-width-outlined', + 'comment-outlined', + 'compass-filled', + 'compass-outlined', + 'compass-twotone', + 'compress-outlined', + 'console-sql-outlined', + 'contacts-filled', + 'contacts-outlined', + 'contacts-twotone', + 'container-filled', + 'container-outlined', + 'container-twotone', + 'control-filled', + 'control-outlined', + 'control-twotone', + 'copy-filled', + 'copy-outlined', + 'copy-twotone', + 'copyright-circle-filled', + 'copyright-circle-outlined', + 'copyright-circle-twotone', + 'copyright-outlined', + 'copyright-twotone', + 'credit-card-filled', + 'credit-card-outlined', + 'credit-card-twotone', + 'crown-filled', + 'crown-outlined', + 'crown-twotone', + 'customer-service-filled', + 'customer-service-outlined', + 'customer-service-twotone', + 'dash-outlined', + 'dashboard-filled', + 'dashboard-outlined', + 'dashboard-twotone', + 'database-filled', + 'database-outlined', + 'database-twotone', + 'delete-column-outlined', + 'delete-filled', + 'delete-outlined', + 'delete-row-outlined', + 'delete-twotone', + 'delivered-procedure-outlined', + 'deployment-unit-outlined', + 'desktop-outlined', + 'diff-filled', + 'diff-outlined', + 'diff-twotone', + 'dingding-outlined', + 'dingtalk-circle-filled', + 'dingtalk-outlined', + 'dingtalk-square-filled', + 'disconnect-outlined', + 'dislike-filled', + 'dislike-outlined', + 'dislike-twotone', + 'dollar-circle-filled', + 'dollar-circle-outlined', + 'dollar-circle-twotone', + 'dollar-outlined', + 'dollar-twotone', + 'dot-chart-outlined', + 'double-left-outlined', + 'double-right-outlined', + 'down-circle-filled', + 'down-circle-outlined', + 'down-circle-twotone', + 'down-outlined', + 'down-square-filled', + 'down-square-outlined', + 'down-square-twotone', + 'download-outlined', + 'drag-outlined', + 'dribbble-circle-filled', + 'dribbble-outlined', + 'dribbble-square-filled', + 'dribbble-square-outlined', + 'dropbox-circle-filled', + 'dropbox-outlined', + 'dropbox-square-filled', + 'edit-filled', + 'edit-outlined', + 'edit-twotone', + 'ellipsis-outlined', + 'enter-outlined', + 'environment-filled', + 'environment-outlined', + 'environment-twotone', + 'euro-circle-filled', + 'euro-circle-outlined', + 'euro-circle-twotone', + 'euro-outlined', + 'euro-twotone', + 'exception-outlined', + 'exclamation-circle-filled', + 'exclamation-circle-outlined', + 'exclamation-circle-twotone', + 'exclamation-outlined', + 'expand-alt-outlined', + 'expand-outlined', + 'experiment-filled', + 'experiment-outlined', + 'experiment-twotone', + 'export-outlined', + 'eye-filled', + 'eye-invisible-filled', + 'eye-invisible-outlined', + 'eye-invisible-twotone', + 'eye-outlined', + 'eye-twotone', + 'facebook-filled', + 'facebook-outlined', + 'fall-outlined', + 'fast-backward-filled', + 'fast-backward-outlined', + 'fast-forward-filled', + 'fast-forward-outlined', + 'field-binary-outlined', + 'field-number-outlined', + 'field-string-outlined', + 'field-time-outlined', + 'file-add-filled', + 'file-add-outlined', + 'file-add-twotone', + 'file-done-outlined', + 'file-excel-filled', + 'file-excel-outlined', + 'file-excel-twotone', + 'file-exclamation-filled', + 'file-exclamation-outlined', + 'file-exclamation-twotone', + 'file-filled', + 'file-gif-outlined', + 'file-image-filled', + 'file-image-outlined', + 'file-image-twotone', + 'file-jpg-outlined', + 'file-markdown-filled', + 'file-markdown-outlined', + 'file-markdown-twotone', + 'file-outlined', + 'file-pdf-filled', + 'file-pdf-outlined', + 'file-pdf-twotone', + 'file-ppt-filled', + 'file-ppt-outlined', + 'file-ppt-twotone', + 'file-protect-outlined', + 'file-search-outlined', + 'file-sync-outlined', + 'file-text-filled', + 'file-text-outlined', + 'file-text-twotone', + 'file-twotone', + 'file-unknown-filled', + 'file-unknown-outlined', + 'file-unknown-twotone', + 'file-word-filled', + 'file-word-outlined', + 'file-word-twotone', + 'file-zip-filled', + 'file-zip-outlined', + 'file-zip-twotone', + 'filter-filled', + 'filter-outlined', + 'filter-twotone', + 'fire-filled', + 'fire-outlined', + 'fire-twotone', + 'flag-filled', + 'flag-outlined', + 'flag-twotone', + 'folder-add-filled', + 'folder-add-outlined', + 'folder-add-twotone', + 'folder-filled', + 'folder-open-filled', + 'folder-open-outlined', + 'folder-open-twotone', + 'folder-outlined', + 'folder-twotone', + 'folder-view-outlined', + 'font-colors-outlined', + 'font-size-outlined', + 'fork-outlined', + 'form-outlined', + 'format-painter-filled', + 'format-painter-outlined', + 'forward-filled', + 'forward-outlined', + 'frown-filled', + 'frown-outlined', + 'frown-twotone', + 'fullscreen-exit-outlined', + 'fullscreen-outlined', + 'function-outlined', + 'fund-filled', + 'fund-outlined', + 'fund-projection-screen-outlined', + 'fund-twotone', + 'fund-view-outlined', + 'funnel-plot-filled', + 'funnel-plot-outlined', + 'funnel-plot-twotone', + 'gateway-outlined', + 'gif-outlined', + 'gift-filled', + 'gift-outlined', + 'gift-twotone', + 'github-filled', + 'github-outlined', + 'gitlab-filled', + 'gitlab-outlined', + 'global-outlined', + 'gold-filled', + 'gold-outlined', + 'gold-twotone', + 'golden-filled', + 'google-circle-filled', + 'google-outlined', + 'google-plus-circle-filled', + 'google-plus-outlined', + 'google-plus-square-filled', + 'google-square-filled', + 'group-outlined', + 'hdd-filled', + 'hdd-outlined', + 'hdd-twotone', + 'heart-filled', + 'heart-outlined', + 'heart-twotone', + 'heat-map-outlined', + 'highlight-filled', + 'highlight-outlined', + 'highlight-twotone', + 'history-outlined', + 'home-filled', + 'home-outlined', + 'home-twotone', + 'hourglass-filled', + 'hourglass-outlined', + 'hourglass-twotone', + 'html5-filled', + 'html5-outlined', + 'html5-twotone', + 'idcard-filled', + 'idcard-outlined', + 'idcard-twotone', + 'ie-circle-filled', + 'ie-outlined', + 'ie-square-filled', + 'import-outlined', + 'inbox-outlined', + 'info-circle-filled', + 'info-circle-outlined', + 'info-circle-twotone', + 'info-outlined', + 'insert-row-above-outlined', + 'insert-row-below-outlined', + 'insert-row-left-outlined', + 'insert-row-right-outlined', + 'instagram-filled', + 'instagram-outlined', + 'insurance-filled', + 'insurance-outlined', + 'insurance-twotone', + 'interaction-filled', + 'interaction-outlined', + 'interaction-twotone', + 'issues-close-outlined', + 'italic-outlined', + 'key-outlined', + 'laptop-outlined', + 'layout-filled', + 'layout-outlined', + 'layout-twotone', + 'left-circle-filled', + 'left-circle-outlined', + 'left-circle-twotone', + 'left-outlined', + 'left-square-filled', + 'left-square-outlined', + 'left-square-twotone', + 'like-filled', + 'like-outlined', + 'like-twotone', + 'line-chart-outlined', + 'line-height-outlined', + 'line-outlined', + 'link-outlined', + 'linkedin-filled', + 'linkedin-outlined', + 'loading-3-quarters-outlined', + 'loading-outlined', + 'lock-filled', + 'lock-outlined', + 'lock-twotone', + 'login-outlined', + 'logout-outlined', + 'mac-command-filled', + 'mac-command-outlined', + 'mail-filled', + 'mail-outlined', + 'mail-twotone', + 'man-outlined', + 'medicine-box-filled', + 'medicine-box-outlined', + 'medicine-box-twotone', + 'medium-circle-filled', + 'medium-outlined', + 'medium-square-filled', + 'medium-workmark-outlined', + 'meh-filled', + 'meh-outlined', + 'meh-twotone', + 'menu-fold-outlined', + 'menu-outlined', + 'menu-unfold-outlined', + 'merge-cells-outlined', + 'message-filled', + 'message-outlined', + 'message-twotone', + 'minus-circle-filled', + 'minus-circle-outlined', + 'minus-circle-twotone', + 'minus-outlined', + 'minus-square-filled', + 'minus-square-outlined', + 'minus-square-twotone', + 'mobile-filled', + 'mobile-outlined', + 'mobile-twotone', + 'money-collect-filled', + 'money-collect-outlined', + 'money-collect-twotone', + 'monitor-outlined', + 'more-outlined', + 'node-collapse-outlined', + 'node-expand-outlined', + 'node-index-outlined', + 'notification-filled', + 'notification-outlined', + 'notification-twotone', + 'number-outlined', + 'one-to-one-outlined', + 'ordered-list-outlined', + 'paper-clip-outlined', + 'partition-outlined', + 'pause-circle-filled', + 'pause-circle-outlined', + 'pause-circle-twotone', + 'pause-outlined', + 'pay-circle-filled', + 'pay-circle-outlined', + 'percentage-outlined', + 'phone-filled', + 'phone-outlined', + 'phone-twotone', + 'pic-center-outlined', + 'pic-left-outlined', + 'pic-right-outlined', + 'picture-filled', + 'picture-outlined', + 'picture-twotone', + 'pie-chart-filled', + 'pie-chart-outlined', + 'pie-chart-twotone', + 'play-circle-filled', + 'play-circle-outlined', + 'play-circle-twotone', + 'play-square-filled', + 'play-square-outlined', + 'play-square-twotone', + 'plus-circle-filled', + 'plus-circle-outlined', + 'plus-circle-twotone', + 'plus-outlined', + 'plus-square-filled', + 'plus-square-outlined', + 'plus-square-twotone', + 'pound-circle-filled', + 'pound-circle-outlined', + 'pound-circle-twotone', + 'pound-outlined', + 'poweroff-outlined', + 'printer-filled', + 'printer-outlined', + 'printer-twotone', + 'profile-filled', + 'profile-outlined', + 'profile-twotone', + 'project-filled', + 'project-outlined', + 'project-twotone', + 'property-safety-filled', + 'property-safety-outlined', + 'property-safety-twotone', + 'pull-request-outlined', + 'pushpin-filled', + 'pushpin-outlined', + 'pushpin-twotone', + 'qq-circle-filled', + 'qq-outlined', + 'qq-square-filled', + 'qrcode-outlined', + 'question-circle-filled', + 'question-circle-outlined', + 'question-circle-twotone', + 'question-outlined', + 'radar-chart-outlined', + 'radius-bottomleft-outlined', + 'radius-bottomright-outlined', + 'radius-setting-outlined', + 'radius-upleft-outlined', + 'radius-upright-outlined', + 'read-filled', + 'read-outlined', + 'reconciliation-filled', + 'reconciliation-outlined', + 'reconciliation-twotone', + 'red-envelope-filled', + 'red-envelope-outlined', + 'red-envelope-twotone', + 'reddit-circle-filled', + 'reddit-outlined', + 'reddit-square-filled', + 'redo-outlined', + 'reload-outlined', + 'rest-filled', + 'rest-outlined', + 'rest-twotone', + 'retweet-outlined', + 'right-circle-filled', + 'right-circle-outlined', + 'right-circle-twotone', + 'right-outlined', + 'right-square-filled', + 'right-square-outlined', + 'right-square-twotone', + 'rise-outlined', + 'robot-filled', + 'robot-outlined', + 'rocket-filled', + 'rocket-outlined', + 'rocket-twotone', + 'rollback-outlined', + 'rotate-left-outlined', + 'rotate-right-outlined', + 'safety-certificate-filled', + 'safety-certificate-outlined', + 'safety-certificate-twotone', + 'safety-outlined', + 'save-filled', + 'save-outlined', + 'save-twotone', + 'scan-outlined', + 'schedule-filled', + 'schedule-outlined', + 'schedule-twotone', + 'scissor-outlined', + 'search-outlined', + 'security-scan-filled', + 'security-scan-outlined', + 'security-scan-twotone', + 'select-outlined', + 'send-outlined', + 'setting-filled', + 'setting-outlined', + 'setting-twotone', + 'shake-outlined', + 'share-alt-outlined', + 'shop-filled', + 'shop-outlined', + 'shop-twotone', + 'shopping-cart-outlined', + 'shopping-filled', + 'shopping-outlined', + 'shopping-twotone', + 'shrink-outlined', + 'signal-filled', + 'sisternode-outlined', + 'sketch-circle-filled', + 'sketch-outlined', + 'sketch-square-filled', + 'skin-filled', + 'skin-outlined', + 'skin-twotone', + 'skype-filled', + 'skype-outlined', + 'slack-circle-filled', + 'slack-outlined', + 'slack-square-filled', + 'slack-square-outlined', + 'sliders-filled', + 'sliders-outlined', + 'sliders-twotone', + 'small-dash-outlined', + 'smile-filled', + 'smile-outlined', + 'smile-twotone', + 'snippets-filled', + 'snippets-outlined', + 'snippets-twotone', + 'solution-outlined', + 'sort-ascending-outlined', + 'sort-descending-outlined', + 'sound-filled', + 'sound-outlined', + 'sound-twotone', + 'split-cells-outlined', + 'star-filled', + 'star-outlined', + 'star-twotone', + 'step-backward-filled', + 'step-backward-outlined', + 'step-forward-filled', + 'step-forward-outlined', + 'stock-outlined', + 'stop-filled', + 'stop-outlined', + 'stop-twotone', + 'strikethrough-outlined', + 'subnode-outlined', + 'swap-left-outlined', + 'swap-outlined', + 'swap-right-outlined', + 'switcher-filled', + 'switcher-outlined', + 'switcher-twotone', + 'sync-outlined', + 'table-outlined', + 'tablet-filled', + 'tablet-outlined', + 'tablet-twotone', + 'tag-filled', + 'tag-outlined', + 'tag-twotone', + 'tags-filled', + 'tags-outlined', + 'tags-twotone', + 'taobao-circle-filled', + 'taobao-circle-outlined', + 'taobao-outlined', + 'taobao-square-filled', + 'team-outlined', + 'thunderbolt-filled', + 'thunderbolt-outlined', + 'thunderbolt-twotone', + 'to-top-outlined', + 'tool-filled', + 'tool-outlined', + 'tool-twotone', + 'trademark-circle-filled', + 'trademark-circle-outlined', + 'trademark-circle-twotone', + 'trademark-outlined', + 'transaction-outlined', + 'translation-outlined', + 'trophy-filled', + 'trophy-outlined', + 'trophy-twotone', + 'twitter-circle-filled', + 'twitter-outlined', + 'twitter-square-filled', + 'underline-outlined', + 'undo-outlined', + 'ungroup-outlined', + 'unlock-filled', + 'unlock-outlined', + 'unlock-twotone', + 'unordered-list-outlined', + 'up-circle-filled', + 'up-circle-outlined', + 'up-circle-twotone', + 'up-outlined', + 'up-square-filled', + 'up-square-outlined', + 'up-square-twotone', + 'upload-outlined', + 'usb-filled', + 'usb-outlined', + 'usb-twotone', + 'user-add-outlined', + 'user-delete-outlined', + 'user-outlined', + 'user-switch-outlined', + 'usergroup-add-outlined', + 'usergroup-delete-outlined', + 'verified-outlined', + 'vertical-align-bottom-outlined', + 'vertical-align-middle-outlined', + 'vertical-align-top-outlined', + 'vertical-left-outlined', + 'vertical-right-outlined', + 'video-camera-add-outlined', + 'video-camera-filled', + 'video-camera-outlined', + 'video-camera-twotone', + 'wallet-filled', + 'wallet-outlined', + 'wallet-twotone', + 'warning-filled', + 'warning-outlined', + 'warning-twotone', + 'wechat-filled', + 'wechat-outlined', + 'weibo-circle-filled', + 'weibo-circle-outlined', + 'weibo-outlined', + 'weibo-square-filled', + 'weibo-square-outlined', + 'whats-app-outlined', + 'wifi-outlined', + 'windows-filled', + 'windows-outlined', + 'woman-outlined', + 'yahoo-filled', + 'yahoo-outlined', + 'youtube-filled', + 'youtube-outlined', + 'yuque-filled', + 'yuque-outlined', + 'zhihu-circle-filled', + 'zhihu-outlined', + 'zhihu-square-filled', + 'zoom-in-outlined', + 'zoom-out-outlined', + ], +}; diff --git a/src/components/Icon/index.ts b/src/components/Icon/index.ts new file mode 100644 index 0000000..9e2bc0b --- /dev/null +++ b/src/components/Icon/index.ts @@ -0,0 +1,4 @@ +import SvgIcon from './src/SvgIcon.vue'; +import IconPicker from './src/IconPicker.vue'; + +export { IconPicker, SvgIcon }; diff --git a/src/components/Icon/src/IconPicker.vue b/src/components/Icon/src/IconPicker.vue new file mode 100644 index 0000000..adcf01a --- /dev/null +++ b/src/components/Icon/src/IconPicker.vue @@ -0,0 +1,200 @@ + + + diff --git a/src/components/Icon/src/SvgIcon.vue b/src/components/Icon/src/SvgIcon.vue new file mode 100644 index 0000000..ca3c497 --- /dev/null +++ b/src/components/Icon/src/SvgIcon.vue @@ -0,0 +1,65 @@ + + + diff --git a/src/components/Loading/index.ts b/src/components/Loading/index.ts new file mode 100644 index 0000000..3673a44 --- /dev/null +++ b/src/components/Loading/index.ts @@ -0,0 +1,5 @@ +import Loading from './src/Loading.vue'; + +export { Loading }; +export { useLoading } from './src/useLoading'; +export { createLoading } from './src/createLoading'; diff --git a/src/components/Loading/src/Loading.vue b/src/components/Loading/src/Loading.vue new file mode 100644 index 0000000..3803085 --- /dev/null +++ b/src/components/Loading/src/Loading.vue @@ -0,0 +1,78 @@ + + + diff --git a/src/components/Loading/src/createLoading.ts b/src/components/Loading/src/createLoading.ts new file mode 100644 index 0000000..0076dc1 --- /dev/null +++ b/src/components/Loading/src/createLoading.ts @@ -0,0 +1,63 @@ +import { VNode, defineComponent, createVNode, render, reactive, h } from 'vue'; +import type { LoadingProps } from './typing'; + +import Loading from './Loading.vue'; + +export function createLoading(props?: Partial, target?: HTMLElement, wait = false) { + let vm: Nullable = null; + const data = reactive({ + tip: '', + loading: true, + ...props, + }); + + const LoadingWrap = defineComponent({ + render() { + return h(Loading, { ...data }); + }, + }); + + vm = createVNode(LoadingWrap); + + if (wait) { + setTimeout(() => { + render(vm, document.createElement('div')); + }, 0); + } else { + render(vm, document.createElement('div')); + } + + function close() { + if (vm?.el && vm.el.parentNode) { + vm.el.parentNode.removeChild(vm.el); + } + } + + function open(target: HTMLElement = document.body) { + if (!vm || !vm.el) { + return; + } + target.appendChild(vm.el as HTMLElement); + } + + if (target) { + open(target); + } + return { + vm, + close, + open, + setTip: (tip: string) => { + data.tip = tip; + }, + setLoading: (loading: boolean) => { + data.loading = loading; + }, + get loading() { + return data.loading; + }, + get $el() { + return vm?.el as HTMLElement; + }, + }; +} diff --git a/src/components/Loading/src/typing.ts b/src/components/Loading/src/typing.ts new file mode 100644 index 0000000..9af60e6 --- /dev/null +++ b/src/components/Loading/src/typing.ts @@ -0,0 +1,10 @@ +import { SizeEnum } from '/@/enums/sizeEnum'; + +export interface LoadingProps { + tip: string; + size: SizeEnum; + absolute: boolean; + loading: boolean; + background: string; + theme: 'dark' | 'light'; +} diff --git a/src/components/Loading/src/useLoading.ts b/src/components/Loading/src/useLoading.ts new file mode 100644 index 0000000..356df7d --- /dev/null +++ b/src/components/Loading/src/useLoading.ts @@ -0,0 +1,49 @@ +import { unref } from 'vue'; +import { createLoading } from './createLoading'; +import type { LoadingProps } from './typing'; +import type { Ref } from 'vue'; + +export interface UseLoadingOptions { + target?: any; + props?: Partial; +} + +interface Fn { + (): void; +} + +export function useLoading(props: Partial): [Fn, Fn, (string) => void]; +export function useLoading(opt: Partial): [Fn, Fn, (string) => void]; + +export function useLoading( + opt: Partial | Partial, +): [Fn, Fn, (string) => void] { + let props: Partial; + let target: HTMLElement | Ref = document.body; + + if (Reflect.has(opt, 'target') || Reflect.has(opt, 'props')) { + const options = opt as Partial; + props = options.props || {}; + target = options.target || document.body; + } else { + props = opt as Partial; + } + + const instance = createLoading(props, undefined, true); + + const open = (): void => { + const t = unref(target as Ref); + if (!t) return; + instance.open(t); + }; + + const close = (): void => { + instance.close(); + }; + + const setTip = (tip: string) => { + instance.setTip(tip); + }; + + return [open, close, setTip]; +} diff --git a/src/components/Menu/index.ts b/src/components/Menu/index.ts new file mode 100644 index 0000000..4a59225 --- /dev/null +++ b/src/components/Menu/index.ts @@ -0,0 +1,3 @@ +import BasicMenu from './src/BasicMenu.vue'; + +export { BasicMenu }; diff --git a/src/components/Menu/src/BasicMenu.vue b/src/components/Menu/src/BasicMenu.vue new file mode 100644 index 0000000..ca8dcaa --- /dev/null +++ b/src/components/Menu/src/BasicMenu.vue @@ -0,0 +1,164 @@ + + + diff --git a/src/components/Menu/src/components/BasicMenuItem.vue b/src/components/Menu/src/components/BasicMenuItem.vue new file mode 100644 index 0000000..4d48362 --- /dev/null +++ b/src/components/Menu/src/components/BasicMenuItem.vue @@ -0,0 +1,21 @@ + + diff --git a/src/components/Menu/src/components/BasicSubMenuItem.vue b/src/components/Menu/src/components/BasicSubMenuItem.vue new file mode 100644 index 0000000..d5139fc --- /dev/null +++ b/src/components/Menu/src/components/BasicSubMenuItem.vue @@ -0,0 +1,55 @@ + + diff --git a/src/components/Menu/src/components/MenuItemContent.vue b/src/components/Menu/src/components/MenuItemContent.vue new file mode 100644 index 0000000..3d3351d --- /dev/null +++ b/src/components/Menu/src/components/MenuItemContent.vue @@ -0,0 +1,34 @@ + + diff --git a/src/components/Menu/src/index.less b/src/components/Menu/src/index.less new file mode 100644 index 0000000..ff85930 --- /dev/null +++ b/src/components/Menu/src/index.less @@ -0,0 +1,74 @@ +@basic-menu-prefix-cls: ~'@{namespace}-basic-menu'; + +.app-top-menu-popup { + min-width: 150px; +} + +.@{basic-menu-prefix-cls} { + width: 100%; + + .ant-menu-item { + transition: unset; + } + + &__sidebar-hor { + &.ant-menu-horizontal { + display: flex; + align-items: center; + + &.ant-menu-dark { + background-color: transparent; + + .ant-menu-submenu:hover, + .ant-menu-item-open, + .ant-menu-submenu-open, + .ant-menu-item-selected, + .ant-menu-submenu-selected, + .ant-menu-item:hover, + .ant-menu-item-active, + .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open, + .ant-menu-submenu-active, + .ant-menu-submenu-title:hover { + background-color: @top-menu-active-bg-color !important; + color: #fff; + } + + .ant-menu-item:hover, + .ant-menu-item-active, + .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open, + .ant-menu-submenu-active, + .ant-menu-submenu-title:hover { + background-color: @top-menu-active-bg-color; + } + + .@{basic-menu-prefix-cls}-item__level1 { + background-color: transparent; + + &.ant-menu-item-selected, + &.ant-menu-submenu-selected { + background-color: @top-menu-active-bg-color !important; + } + } + + .ant-menu-item, + .ant-menu-submenu { + &.@{basic-menu-prefix-cls}-item__level1, + .ant-menu-submenu-title { + height: @header-height; + line-height: @header-height; + } + } + } + } + } + + .ant-menu-submenu, + .ant-menu-submenu-inline { + transition: unset; + } + + .ant-menu-inline.ant-menu-sub { + transition: unset; + box-shadow: unset !important; + } +} diff --git a/src/components/Menu/src/props.ts b/src/components/Menu/src/props.ts new file mode 100644 index 0000000..480297d --- /dev/null +++ b/src/components/Menu/src/props.ts @@ -0,0 +1,61 @@ +import type { Menu } from '/@/router/types'; +import type { PropType } from 'vue'; + +import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; +import { ThemeEnum } from '/@/enums/appEnum'; +import { propTypes } from '/@/utils/propTypes'; +import type { MenuTheme } from 'ant-design-vue'; +import type { MenuMode } from 'ant-design-vue/lib/menu/src/interface'; + +export const basicProps = { + items: { + type: Array as PropType, + default: () => [], + }, + collapsedShowTitle: propTypes.bool, + // 最好是4 倍数 + inlineIndent: propTypes.number.def(20), + // 菜单组件的mode属性 + mode: { + type: String as PropType, + default: MenuModeEnum.INLINE, + }, + + type: { + type: String as PropType, + default: MenuTypeEnum.MIX, + }, + theme: { + type: String as PropType, + default: ThemeEnum.DARK, + }, + inlineCollapsed: propTypes.bool, + mixSider: propTypes.bool, + + isHorizontal: propTypes.bool, + accordion: propTypes.bool.def(true), + beforeClickFn: { + type: Function as PropType<(key: string) => Promise>, + }, +}; + +export const itemProps = { + item: { + type: Object as PropType

    , + default: () => ({}), + }, + level: propTypes.number, + theme: propTypes.oneOf(['dark', 'light']), + showTitle: propTypes.bool, + isHorizontal: propTypes.bool, +}; + +export const contentProps = { + item: { + type: Object as PropType, + default: null, + }, + showTitle: propTypes.bool.def(true), + level: propTypes.number.def(0), + isHorizontal: propTypes.bool.def(true), +}; diff --git a/src/components/Menu/src/types.ts b/src/components/Menu/src/types.ts new file mode 100644 index 0000000..ad711c2 --- /dev/null +++ b/src/components/Menu/src/types.ts @@ -0,0 +1,25 @@ +// import { ComputedRef } from 'vue'; +// import { ThemeEnum } from '/@/enums/appEnum'; +// import { MenuModeEnum } from '/@/enums/menuEnum'; +export interface MenuState { + // 默认选中的列表 + defaultSelectedKeys: string[]; + + // 模式 + // mode: MenuModeEnum; + + // // 主题 + // theme: ComputedRef | ThemeEnum; + + // 缩进 + inlineIndent?: number; + + // 展开数组 + openKeys: string[]; + + // 当前选中的菜单项 key 数组 + selectedKeys: string[]; + + // 收缩状态下展开的数组 + collapsedOpenKeys: string[]; +} diff --git a/src/components/Menu/src/useOpenKeys.ts b/src/components/Menu/src/useOpenKeys.ts new file mode 100644 index 0000000..fc0b5a5 --- /dev/null +++ b/src/components/Menu/src/useOpenKeys.ts @@ -0,0 +1,81 @@ +import { MenuModeEnum } from '/@/enums/menuEnum'; +import type { Menu as MenuType } from '/@/router/types'; +import type { MenuState } from './types'; +import { computed, Ref, toRaw, unref } from 'vue'; +import { useTimeoutFn } from '@vben/hooks'; +import { uniq } from 'lodash-es'; +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; +import { getAllParentPath } from '/@/router/helper/menuHelper'; + +export function useOpenKeys( + menuState: MenuState, + menus: Ref, + mode: Ref, + accordion: Ref, +) { + const { getCollapsed, getIsMixSidebar } = useMenuSetting(); + + async function setOpenKeys(path: string) { + if (mode.value === MenuModeEnum.HORIZONTAL) { + return; + } + const native = unref(getIsMixSidebar); + const handle = () => { + const menuList = toRaw(menus.value); + if (menuList?.length === 0) { + menuState.openKeys = []; + return; + } + if (!unref(accordion)) { + menuState.openKeys = uniq([...menuState.openKeys, ...getAllParentPath(menuList, path)]); + } else { + menuState.openKeys = getAllParentPath(menuList, path); + } + }; + if (native) { + handle(); + } else { + useTimeoutFn(handle, 16); + } + } + + const getOpenKeys = computed(() => { + const collapse = unref(getIsMixSidebar) ? false : unref(getCollapsed); + + return collapse ? menuState.collapsedOpenKeys : menuState.openKeys; + }); + + /** + * @description: 重置值 + */ + function resetKeys() { + menuState.selectedKeys = []; + menuState.openKeys = []; + } + + function handleOpenChange(openKeys: string[]) { + if (unref(mode) === MenuModeEnum.HORIZONTAL || !unref(accordion) || unref(getIsMixSidebar)) { + menuState.openKeys = openKeys; + } else { + // const menuList = toRaw(menus.value); + // getAllParentPath(menuList, path); + const rootSubMenuKeys: string[] = []; + for (const { children, path } of unref(menus)) { + if (children && children.length > 0) { + rootSubMenuKeys.push(path); + } + } + if (!unref(getCollapsed)) { + const latestOpenKey = openKeys.find((key) => menuState.openKeys.indexOf(key) === -1); + if (rootSubMenuKeys.indexOf(latestOpenKey as string) === -1) { + menuState.openKeys = openKeys; + } else { + menuState.openKeys = latestOpenKey ? [latestOpenKey] : []; + } + } else { + menuState.collapsedOpenKeys = openKeys; + } + } + } + return { setOpenKeys, resetKeys, getOpenKeys, handleOpenChange }; +} diff --git a/src/components/Modal/index.ts b/src/components/Modal/index.ts new file mode 100644 index 0000000..f93615a --- /dev/null +++ b/src/components/Modal/index.ts @@ -0,0 +1,8 @@ +import { withInstall } from '@/utils'; +import './src/index.less'; +import basicModal from './src/BasicModal.vue'; + +export const BasicModal = withInstall(basicModal); +export { useModalContext } from './src/hooks/useModalContext'; +export { useModal, useModalInner } from './src/hooks/useModal'; +export * from './src/typing'; \ No newline at end of file diff --git a/src/components/Modal/src/BasicModal.vue b/src/components/Modal/src/BasicModal.vue new file mode 100644 index 0000000..8f55a41 --- /dev/null +++ b/src/components/Modal/src/BasicModal.vue @@ -0,0 +1,246 @@ + + \ No newline at end of file diff --git a/src/components/Modal/src/components/Modal.tsx b/src/components/Modal/src/components/Modal.tsx new file mode 100644 index 0000000..1165835 --- /dev/null +++ b/src/components/Modal/src/components/Modal.tsx @@ -0,0 +1,29 @@ +import { Modal } from 'ant-design-vue'; +import { defineComponent, toRefs, unref } from 'vue'; +import { basicProps } from '../props'; +import { useModalDragMove } from '../hooks/useModalDrag'; +import { extendSlots } from '@/utils/helper/tsxHelper'; + +export default defineComponent({ + name: 'Modal', + inheritAttrs: false, + props: basicProps as any, + emits: ['cancel'], + setup(props, { slots, emit, attrs }) { + const { open, draggable, destroyOnClose } = toRefs(props); + useModalDragMove({ + open, + destroyOnClose, + draggable, + }); + + const onCancel = (e: Event) => { + emit('cancel', e); + }; + + return () => { + const propsData = { ...unref(attrs), ...props, onCancel } as Recordable; + return {extendSlots(slots)}; + }; + }, +}); \ No newline at end of file diff --git a/src/components/Modal/src/components/ModalClose.vue b/src/components/Modal/src/components/ModalClose.vue new file mode 100644 index 0000000..b92d2e0 --- /dev/null +++ b/src/components/Modal/src/components/ModalClose.vue @@ -0,0 +1,96 @@ + + + \ No newline at end of file diff --git a/src/components/Modal/src/components/ModalFooter.vue b/src/components/Modal/src/components/ModalFooter.vue new file mode 100644 index 0000000..bdb269e --- /dev/null +++ b/src/components/Modal/src/components/ModalFooter.vue @@ -0,0 +1,36 @@ + + \ No newline at end of file diff --git a/src/components/Modal/src/components/ModalHeader.vue b/src/components/Modal/src/components/ModalHeader.vue new file mode 100644 index 0000000..36e24d1 --- /dev/null +++ b/src/components/Modal/src/components/ModalHeader.vue @@ -0,0 +1,18 @@ + + \ No newline at end of file diff --git a/src/components/Modal/src/components/ModalWrapper.vue b/src/components/Modal/src/components/ModalWrapper.vue new file mode 100644 index 0000000..42781eb --- /dev/null +++ b/src/components/Modal/src/components/ModalWrapper.vue @@ -0,0 +1,170 @@ + + diff --git a/src/components/Modal/src/hooks/useModal.ts b/src/components/Modal/src/hooks/useModal.ts new file mode 100644 index 0000000..51f1eab --- /dev/null +++ b/src/components/Modal/src/hooks/useModal.ts @@ -0,0 +1,163 @@ +import type { + UseModalReturnType, + ModalMethods, + ModalProps, + ReturnMethods, + UseModalInnerReturnType, +} from '../typing'; +import { + ref, + onUnmounted, + unref, + getCurrentInstance, + reactive, + watchEffect, + nextTick, + toRaw, + computed, +} from 'vue'; +import { isProdMode } from '@/utils/env'; +import { isFunction } from '@/utils/is'; +import { isEqual } from 'lodash-es'; +import { tryOnUnmounted } from '@vueuse/core'; +import { error } from '@/utils/log'; + +const dataTransfer = reactive({}); + +const openData = reactive<{ [key: number]: boolean }>({}); + +/** + * @description: Applicable to independent modal and call outside + */ +export function useModal(): UseModalReturnType { + const modal = ref>(null); + const loaded = ref>(false); + const uid = ref(0); + + function register(modalMethod: ModalMethods, uuid: number) { + if (!getCurrentInstance()) { + throw new Error('useModal() can only be used inside setup() or functional components!'); + } + uid.value = uuid; + isProdMode() && + onUnmounted(() => { + modal.value = null; + loaded.value = false; + dataTransfer[String(unref(uid))] = null; + }); + if (unref(loaded) && isProdMode() && modalMethod === unref(modal)) return; + + modal.value = modalMethod; + loaded.value = true; + modalMethod.emitOpen = (open: boolean, uid: number) => { + openData[uid] = open; + }; + } + + const getInstance = () => { + const instance = unref(modal); + if (!instance) { + error('useModal instance is undefined!'); + } + return instance; + }; + + const methods: ReturnMethods = { + setModalProps: (props: Partial): void => { + getInstance()?.setModalProps(props); + }, + + getOpen: computed((): boolean => { + return openData[~~unref(uid)]; + }), + + redoModalHeight: () => { + getInstance()?.redoModalHeight?.(); + }, + + openModal: (open = true, data?: T, openOnSet = true): void => { + getInstance()?.setModalProps({ + open, + }); + + if (!data) return; + const id = unref(uid); + if (openOnSet) { + dataTransfer[id] = null; + dataTransfer[id] = toRaw(data); + return; + } + const equal = isEqual(toRaw(dataTransfer[id]), toRaw(data)); + if (!equal) { + dataTransfer[id] = toRaw(data); + } + }, + + closeModal: () => { + getInstance()?.setModalProps({ open: false }); + }, + }; + return [register, methods]; +} + +export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => { + const modalInstanceRef = ref>(null); + const currentInstance = getCurrentInstance(); + const uidRef = ref(0); + + const getInstance = () => { + const instance = unref(modalInstanceRef); + if (!instance) { + error('useModalInner instance is undefined!'); + } + return instance; + }; + + const register = (modalInstance: ModalMethods, uuid: number) => { + isProdMode() && + tryOnUnmounted(() => { + modalInstanceRef.value = null; + }); + uidRef.value = uuid; + modalInstanceRef.value = modalInstance; + currentInstance?.emit('register', modalInstance, uuid); + }; + + watchEffect(() => { + const data = dataTransfer[unref(uidRef)]; + if (!data) return; + if (!callbackFn || !isFunction(callbackFn)) return; + nextTick(() => { + callbackFn(data); + }); + }); + + return [ + register, + { + changeLoading: (loading = true) => { + getInstance()?.setModalProps({ loading }); + }, + getOpen: computed((): boolean => { + return openData[~~unref(uidRef)]; + }), + + changeOkLoading: (loading = true) => { + getInstance()?.setModalProps({ confirmLoading: loading }); + }, + + closeModal: () => { + getInstance()?.setModalProps({ open: false }); + }, + + setModalProps: (props: Partial) => { + getInstance()?.setModalProps(props); + }, + + redoModalHeight: () => { + const callRedo = getInstance()?.redoModalHeight; + callRedo && callRedo(); + }, + }, + ]; +}; \ No newline at end of file diff --git a/src/components/Modal/src/hooks/useModalContext.ts b/src/components/Modal/src/hooks/useModalContext.ts new file mode 100644 index 0000000..fe3110e --- /dev/null +++ b/src/components/Modal/src/hooks/useModalContext.ts @@ -0,0 +1,16 @@ +import { InjectionKey } from 'vue'; +import { createContext, useContext } from '@/hooks/core/useContext'; + +export interface ModalContextProps { + redoModalHeight: () => void; +} + +const key: InjectionKey = Symbol(); + +export function createModalContext(context: ModalContextProps) { + return createContext(context, key); +} + +export function useModalContext() { + return useContext(key); +} \ No newline at end of file diff --git a/src/components/Modal/src/hooks/useModalDrag.ts b/src/components/Modal/src/hooks/useModalDrag.ts new file mode 100644 index 0000000..d9ff0fc --- /dev/null +++ b/src/components/Modal/src/hooks/useModalDrag.ts @@ -0,0 +1,107 @@ +import { Ref, unref, watchEffect } from 'vue'; +import { useTimeoutFn } from '@vben/hooks'; + +export interface UseModalDragMoveContext { + draggable: Ref; + destroyOnClose: Ref | undefined; + open: Ref; +} + +export function useModalDragMove(context: UseModalDragMoveContext) { + const getStyle = (dom: any, attr: any) => { + return getComputedStyle(dom)[attr]; + }; + const drag = (wrap: any) => { + if (!wrap) return; + wrap.setAttribute('data-drag', unref(context.draggable)); + const dialogHeaderEl = wrap.querySelector('.ant-modal-header'); + const dragDom = wrap.querySelector('.ant-modal'); + + if (!dialogHeaderEl || !dragDom || !unref(context.draggable)) return; + + dialogHeaderEl.style.cursor = 'move'; + + dialogHeaderEl.onmousedown = (e: any) => { + if (!e) return; + // 鼠标按下,计算当前元素距离可视区的距离 + const disX = e.clientX; + const disY = e.clientY; + const screenWidth = document.body.clientWidth; // body当前宽度 + const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度,可某些环境下无法获取) + + const dragDomWidth = dragDom.offsetWidth; // 对话框宽度 + const dragDomheight = dragDom.offsetHeight; // 对话框高度 + + const minDragDomLeft = dragDom.offsetLeft; + + const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth; + const minDragDomTop = dragDom.offsetTop; + const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight; + // 获取到的值带px 正则匹配替换 + const domLeft = getStyle(dragDom, 'left'); + const domTop = getStyle(dragDom, 'top'); + let styL = +domLeft; + let styT = +domTop; + + // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px + if (domLeft.includes('%')) { + styL = +document.body.clientWidth * (+domLeft.replace(/%/g, '') / 100); + styT = +document.body.clientHeight * (+domTop.replace(/%/g, '') / 100); + } else { + styL = +domLeft.replace(/px/g, ''); + styT = +domTop.replace(/px/g, ''); + } + + document.onmousemove = function (e) { + // 通过事件委托,计算移动的距离 + let left = e.clientX - disX; + let top = e.clientY - disY; + + // 边界处理 + if (-left > minDragDomLeft) { + left = -minDragDomLeft; + } else if (left > maxDragDomLeft) { + left = maxDragDomLeft; + } + + if (-top > minDragDomTop) { + top = -minDragDomTop; + } else if (top > maxDragDomTop) { + top = maxDragDomTop; + } + + // 移动当前元素 + dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`; + }; + + document.onmouseup = () => { + document.onmousemove = null; + document.onmouseup = null; + }; + }; + }; + + const handleDrag = () => { + const dragWraps = document.querySelectorAll('.ant-modal-wrap'); + for (const wrap of Array.from(dragWraps)) { + if (!wrap) continue; + const display = getStyle(wrap, 'display'); + const draggable = wrap.getAttribute('data-drag'); + if (display !== 'none') { + // 拖拽位置 + if (draggable === null || unref(context.destroyOnClose)) { + drag(wrap); + } + } + } + }; + + watchEffect(() => { + if (!unref(context.open) || !unref(context.draggable)) { + return; + } + useTimeoutFn(() => { + handleDrag(); + }, 30); + }); +} \ No newline at end of file diff --git a/src/components/Modal/src/hooks/useModalFullScreen.ts b/src/components/Modal/src/hooks/useModalFullScreen.ts new file mode 100644 index 0000000..fd06198 --- /dev/null +++ b/src/components/Modal/src/hooks/useModalFullScreen.ts @@ -0,0 +1,22 @@ +import { computed, Ref, ref, unref } from 'vue'; + +export interface UseFullScreenContext { + wrapClassName: Ref; + modalWrapperRef: Ref; + extHeightRef: Ref; +} + +export function useFullScreen(context: UseFullScreenContext) { + const fullScreenRef = ref(false); + + const getWrapClassName = computed(() => { + const clsName = unref(context.wrapClassName) || ''; + return unref(fullScreenRef) ? `fullscreen-modal ${clsName} ` : unref(clsName); + }); + + function handleFullScreen(e: Event) { + e && e.stopPropagation(); + fullScreenRef.value = !unref(fullScreenRef); + } + return { getWrapClassName, handleFullScreen, fullScreenRef }; +} diff --git a/src/components/Modal/src/index.less b/src/components/Modal/src/index.less new file mode 100644 index 0000000..e70cefe --- /dev/null +++ b/src/components/Modal/src/index.less @@ -0,0 +1,147 @@ + +@modal-prefix-cls: ~'@{namespace}-basic-modal'; + +.fullscreen-modal { + overflow: hidden; + + .ant-modal { + inset: 0 !important; + width: 100% !important; + max-width: 100%; + height: 100%; + + &-content { + height: 100%; + overflow: hidden; + } + } + + .ant-modal-footer { + margin-top: 0; + } +} + +.@{modal-prefix-cls} { + .ant-modal { + width: 520px; + padding-bottom: 0; + + .ant-modal-body > .scrollbar { + padding: 14px; + } + + &-title { + font-size: 16px; + font-weight: bold; + + .base-title { + cursor: move !important; + } + } + + .ant-modal-body { + padding: 0; + + > .scrollbar > .scrollbar__bar.is-horizontal { + display: none; + } + } + + &-large { + top: 60px; + + &--mini { + top: 16px; + } + } + + &-header { + padding: 16px; + border-bottom: 1px solid @border-color-base; + } + + &-content { + padding: 0 !important; + box-shadow: + 0 4px 8px 0 rgb(0 0 0 / 20%), + 0 6px 20px 0 rgb(0 0 0 / 19%); + } + + &-footer { + padding: 10px 16px; + border-top: 1px solid @border-color-base; + + button + button { + margin-left: 10px; + } + } + + &-close { + top: 0 !important; + right: 0 !important; + width: auto !important; + outline: none; + background: transparent !important; + font-weight: normal; + } + + &-close-x { + display: inline-block; + width: 96px; + height: 56px; + line-height: 56px !important; + } + + &-confirm-body { + .ant-modal-confirm-content { + > * { + color: @text-color-help-dark; + } + } + } + + &-confirm-confirm.error .ant-modal-confirm-body > .anticon { + color: @error-color; + } + + &-confirm-btns { + .ant-btn:last-child { + margin-right: 0; + } + } + + &-confirm-info { + .ant-modal-confirm-body > .anticon { + color: @warning-color; + } + } + + &-confirm-confirm.success { + .ant-modal-confirm-body > .anticon { + color: @success-color; + } + } + } + + .ant-modal-confirm .ant-modal-body { + padding: 24px !important; + } +} + +@media screen and (max-height: 600px) { + .ant-modal { + top: 60px; + } +} + +@media screen and (max-height: 540px) { + .ant-modal { + top: 30px; + } +} + +@media screen and (max-height: 480px) { + .ant-modal { + top: 10px; + } +} diff --git a/src/components/Modal/src/props.ts b/src/components/Modal/src/props.ts new file mode 100644 index 0000000..bd13b81 --- /dev/null +++ b/src/components/Modal/src/props.ts @@ -0,0 +1,83 @@ +import type { PropType, CSSProperties } from 'vue'; +import type { ModalWrapperProps } from './typing'; +import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes'; +import { useI18n } from '@/hooks/web/useI18n'; + +const { t } = useI18n(); + +export const modalProps = { + open: { type: Boolean }, + scrollTop: { type: Boolean, default: true }, + height: { type: Number }, + minHeight: { type: Number }, + // open drag + draggable: { type: Boolean, default: true }, + centered: { type: Boolean }, + cancelText: { type: String, default: t('common.cancelText') }, + okText: { type: String, default: t('common.okText') }, + + closeFunc: Function as PropType<() => Promise>, +}; + +export const basicProps = Object.assign({}, modalProps, { + defaultFullscreen: { type: Boolean }, + // Can it be full screen + canFullscreen: { type: Boolean, default: true }, + // After enabling the wrapper, the bottom can be increased in height + wrapperFooterOffset: { type: Number, default: 0 }, + // Warm reminder message + helpMessage: [String, Array] as PropType, + // Whether to setting wrapper + useWrapper: { type: Boolean, default: true }, + loading: { type: Boolean }, + loadingTip: { type: String }, + /** + * @description: Show close button + */ + showCancelBtn: { type: Boolean, default: true }, + /** + * @description: Show confirmation button + */ + showOkBtn: { type: Boolean, default: true }, + + wrapperProps: Object as PropType>, + + afterClose: Function as PropType<() => Promise>, + + bodyStyle: Object as PropType, + + closable: { type: Boolean, default: true }, + + closeIcon: Object as PropType, + + confirmLoading: { type: Boolean }, + + destroyOnClose: { type: Boolean }, + + footer: Object as PropType, + + getContainer: Function as PropType<() => any>, + + mask: { type: Boolean, default: true }, + + maskClosable: { type: Boolean, default: true }, + keyboard: { type: Boolean, default: true }, + + maskStyle: Object as PropType, + + okType: { type: String, default: 'primary' }, + + okButtonProps: Object as PropType, + + cancelButtonProps: Object as PropType, + + title: { type: String }, + + open: { type: Boolean }, + + width: [String, Number] as PropType, + + wrapClassName: { type: String }, + + zIndex: { type: Number }, +}); \ No newline at end of file diff --git a/src/components/Modal/src/typing.ts b/src/components/Modal/src/typing.ts new file mode 100644 index 0000000..e9afc4c --- /dev/null +++ b/src/components/Modal/src/typing.ts @@ -0,0 +1,209 @@ +import type { ButtonProps } from 'ant-design-vue/lib/button/buttonTypes'; +import type { CSSProperties, VNodeChild, ComputedRef } from 'vue'; +/** + * @description: 弹窗对外暴露的方法 + */ +export interface ModalMethods { + setModalProps: (props: Partial) => void; + emitOpen?: (open: boolean, uid: number) => void; + redoModalHeight?: () => void; +} + +export type RegisterFn = (modalMethods: ModalMethods, uuid?: string) => void; + +export interface ReturnMethods extends ModalMethods { + openModal: (props?: boolean, data?: T, openOnSet?: boolean) => void; + closeModal: () => void; + getOpen?: ComputedRef; +} + +export type UseModalReturnType = [RegisterFn, ReturnMethods]; + +export interface ReturnInnerMethods extends ModalMethods { + closeModal: () => void; + changeLoading: (loading: boolean) => void; + changeOkLoading: (loading: boolean) => void; + getOpen?: ComputedRef; + redoModalHeight: () => void; +} + +export type UseModalInnerReturnType = [RegisterFn, ReturnInnerMethods]; + +export interface ModalProps { + minHeight?: number; + height?: number; + // 启用wrapper后 底部可以适当增加高度 + wrapperFooterOffset?: number; + draggable?: boolean; + scrollTop?: boolean; + + // 是否可以进行全屏 + canFullscreen?: boolean; + defaultFullscreen?: boolean; + open?: boolean; + // 温馨提醒信息 + helpMessage: string | string[]; + + // 是否使用modalWrapper + useWrapper: boolean; + + loading: boolean; + loadingTip?: string; + + wrapperProps: Omit; + + showOkBtn: boolean; + showCancelBtn: boolean; + closeFunc: () => Promise; + + /** + * Specify a function that will be called when modal is closed completely. + * @type Function + */ + afterClose?: () => any; + + /** + * Body style for modal body element. Such as height, padding etc. + * @default {} + * @type object + */ + bodyStyle?: CSSProperties; + + /** + * Text of the Cancel button + * @default 'cancel' + * @type string + */ + cancelText?: string; + + /** + * Centered Modal + * @default false + * @type boolean + */ + centered?: boolean; + + /** + * Whether a close (x) button is visible on top right of the modal dialog or not + * @default true + * @type boolean + */ + closable?: boolean; + /** + * Whether a close (x) button is visible on top right of the modal dialog or not + */ + closeIcon?: VNodeChild | JSX.Element; + + /** + * Whether to apply loading visual effect for OK button or not + * @default false + * @type boolean + */ + confirmLoading?: boolean; + + /** + * Whether to unmount child components on onClose + * @default false + * @type boolean + */ + destroyOnClose?: boolean; + + /** + * Footer content, set as :footer="null" when you don't need default buttons + * @default OK and Cancel buttons + * @type any (string | slot) + */ + footer?: VNodeChild | JSX.Element; + + /** + * Return the mount node for Modal + * @default () => document.body + * @type Function + */ + getContainer?: (instance: any) => HTMLElement; + + /** + * Whether show mask or not. + * @default true + * @type boolean + */ + mask?: boolean; + + /** + * Whether to close the modal dialog when the mask (area outside the modal) is clicked + * @default true + * @type boolean + */ + maskClosable?: boolean; + + /** + * Style for modal's mask element. + * @default {} + * @type object + */ + maskStyle?: CSSProperties; + + /** + * Text of the OK button + * @default 'OK' + * @type string + */ + okText?: string; + + /** + * Button type of the OK button + * @default 'primary' + * @type string + */ + okType?: 'primary' | 'danger' | 'dashed' | 'ghost' | 'default'; + + /** + * The ok button props, follow jsx rules + * @type object + */ + okButtonProps?: ButtonProps; + + /** + * The cancel button props, follow jsx rules + * @type object + */ + cancelButtonProps?: ButtonProps; + + /** + * The modal dialog's title + * @type any (string | slot) + */ + title?: VNodeChild | JSX.Element; + + /** + * Width of the modal dialog + * @default 520 + * @type string | number + */ + width?: string | number; + + /** + * The class name of the container of the modal dialog + * @type string + */ + wrapClassName?: string; + + /** + * The z-index of the Modal + * @default 1000 + * @type number + */ + zIndex?: number; +} + +export interface ModalWrapperProps { + footerOffset?: number; + loading: boolean; + modalHeaderHeight: number; + modalFooterHeight: number; + minHeight: number; + height: number; + open: boolean; + fullScreen: boolean; + useWrapper: boolean; +} \ No newline at end of file diff --git a/src/components/Page/index.ts b/src/components/Page/index.ts new file mode 100644 index 0000000..d096264 --- /dev/null +++ b/src/components/Page/index.ts @@ -0,0 +1,7 @@ +import { withInstall } from '/@/utils'; + +import pageFooter from './src/PageFooter.vue'; +import pageWrapper from './src/PageWrapper.vue'; + +export const PageFooter = withInstall(pageFooter); +export const PageWrapper = withInstall(pageWrapper); diff --git a/src/components/Page/src/PageFooter.vue b/src/components/Page/src/PageFooter.vue new file mode 100644 index 0000000..8d45fb6 --- /dev/null +++ b/src/components/Page/src/PageFooter.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/components/Page/src/PageWrapper.vue b/src/components/Page/src/PageWrapper.vue new file mode 100644 index 0000000..fc3024f --- /dev/null +++ b/src/components/Page/src/PageWrapper.vue @@ -0,0 +1,205 @@ + + + diff --git a/src/components/Qrcode/index.ts b/src/components/Qrcode/index.ts new file mode 100644 index 0000000..16a2f40 --- /dev/null +++ b/src/components/Qrcode/index.ts @@ -0,0 +1,5 @@ +import { withInstall } from '/@/utils'; +import qrCode from './src/Qrcode.vue'; + +export const QrCode = withInstall(qrCode); +export * from './src/typing'; diff --git a/src/components/Qrcode/src/Qrcode.vue b/src/components/Qrcode/src/Qrcode.vue new file mode 100644 index 0000000..81194e1 --- /dev/null +++ b/src/components/Qrcode/src/Qrcode.vue @@ -0,0 +1,112 @@ + + diff --git a/src/components/Qrcode/src/drawCanvas.ts b/src/components/Qrcode/src/drawCanvas.ts new file mode 100644 index 0000000..53198e8 --- /dev/null +++ b/src/components/Qrcode/src/drawCanvas.ts @@ -0,0 +1,37 @@ +import { toCanvas } from 'qrcode'; +import type { QRCodeRenderersOptions } from 'qrcode'; +import { RenderQrCodeParams, ContentType } from './typing'; +import { cloneDeep } from 'lodash-es'; + +export const renderQrCode = ({ + canvas, + content, + width = 0, + options: params = {}, +}: RenderQrCodeParams) => { + const options = cloneDeep(params); + // 容错率,默认对内容少的二维码采用高容错率,内容多的二维码采用低容错率 + options.errorCorrectionLevel = options.errorCorrectionLevel || getErrorCorrectionLevel(content); + + return getOriginWidth(content, options).then((_width: number) => { + options.scale = width === 0 ? undefined : (width / _width) * 4; + return toCanvas(canvas, content, options); + }); +}; + +// 得到原QrCode的大小,以便缩放得到正确的QrCode大小 +function getOriginWidth(content: ContentType, options: QRCodeRenderersOptions) { + const _canvas = document.createElement('canvas'); + return toCanvas(_canvas, content, options).then(() => _canvas.width); +} + +// 对于内容少的QrCode,增大容错率 +function getErrorCorrectionLevel(content: ContentType) { + if (content.length > 36) { + return 'M'; + } else if (content.length > 16) { + return 'Q'; + } else { + return 'H'; + } +} diff --git a/src/components/Qrcode/src/drawLogo.ts b/src/components/Qrcode/src/drawLogo.ts new file mode 100644 index 0000000..82df278 --- /dev/null +++ b/src/components/Qrcode/src/drawLogo.ts @@ -0,0 +1,89 @@ +import { isString } from '/@/utils/is'; +import { RenderQrCodeParams, LogoType } from './typing'; + +export const drawLogo = ({ canvas, logo }: RenderQrCodeParams) => { + if (!logo) { + return new Promise((resolve) => { + resolve((canvas as HTMLCanvasElement).toDataURL()); + }); + } + const canvasWidth = (canvas as HTMLCanvasElement).width; + const { + logoSize = 0.15, + bgColor = '#ffffff', + borderSize = 0.05, + crossOrigin, + borderRadius = 8, + logoRadius = 0, + } = logo as LogoType; + + const logoSrc: string = isString(logo) ? logo : logo.src; + const logoWidth = canvasWidth * logoSize; + const logoXY = (canvasWidth * (1 - logoSize)) / 2; + const logoBgWidth = canvasWidth * (logoSize + borderSize); + const logoBgXY = (canvasWidth * (1 - logoSize - borderSize)) / 2; + + const ctx = canvas.getContext('2d'); + if (!ctx) return; + + // logo 底色 + canvasRoundRect(ctx)(logoBgXY, logoBgXY, logoBgWidth, logoBgWidth, borderRadius); + ctx.fillStyle = bgColor; + ctx.fill(); + + // logo + const image = new Image(); + if (crossOrigin || logoRadius) { + image.setAttribute('crossOrigin', crossOrigin || 'anonymous'); + } + image.src = logoSrc; + + // 使用image绘制可以避免某些跨域情况 + const drawLogoWithImage = (image: CanvasImageSource) => { + ctx.drawImage(image, logoXY, logoXY, logoWidth, logoWidth); + }; + + // 使用canvas绘制以获得更多的功能 + const drawLogoWithCanvas = (image: HTMLImageElement) => { + const canvasImage = document.createElement('canvas'); + canvasImage.width = logoXY + logoWidth; + canvasImage.height = logoXY + logoWidth; + const imageCanvas = canvasImage.getContext('2d'); + if (!imageCanvas || !ctx) return; + imageCanvas.drawImage(image, logoXY, logoXY, logoWidth, logoWidth); + + canvasRoundRect(ctx)(logoXY, logoXY, logoWidth, logoWidth, logoRadius); + if (!ctx) return; + const fillStyle = ctx.createPattern(canvasImage, 'no-repeat'); + if (fillStyle) { + ctx.fillStyle = fillStyle; + ctx.fill(); + } + }; + + // 将 logo绘制到 canvas上 + return new Promise((resolve) => { + image.onload = () => { + logoRadius ? drawLogoWithCanvas(image) : drawLogoWithImage(image); + resolve((canvas as HTMLCanvasElement).toDataURL()); + }; + }); +}; + +// copy来的方法,用于绘制圆角 +function canvasRoundRect(ctx: CanvasRenderingContext2D) { + return (x: number, y: number, w: number, h: number, r: number) => { + const minSize = Math.min(w, h); + if (r > minSize / 2) { + r = minSize / 2; + } + ctx.beginPath(); + ctx.moveTo(x + r, y); + ctx.arcTo(x + w, y, x + w, y + h, r); + ctx.arcTo(x + w, y + h, x, y + h, r); + ctx.arcTo(x, y + h, x, y, r); + ctx.arcTo(x, y, x + w, y, r); + ctx.closePath(); + return ctx; + }; +} diff --git a/src/components/Qrcode/src/qrcodePlus.ts b/src/components/Qrcode/src/qrcodePlus.ts new file mode 100644 index 0000000..ddf6116 --- /dev/null +++ b/src/components/Qrcode/src/qrcodePlus.ts @@ -0,0 +1,5 @@ +// 参考 qr-code-with-logo 进行ts版本修改 +import { toCanvas } from './toCanvas'; + +export * from './typing'; +export { toCanvas }; diff --git a/src/components/Qrcode/src/toCanvas.ts b/src/components/Qrcode/src/toCanvas.ts new file mode 100644 index 0000000..0a9799f --- /dev/null +++ b/src/components/Qrcode/src/toCanvas.ts @@ -0,0 +1,11 @@ +import { renderQrCode } from './drawCanvas'; +import { drawLogo } from './drawLogo'; +import { RenderQrCodeParams } from './typing'; + +export const toCanvas = (options: RenderQrCodeParams) => { + return renderQrCode(options) + .then(() => { + return options; + }) + .then(drawLogo) as Promise; +}; diff --git a/src/components/Qrcode/src/typing.ts b/src/components/Qrcode/src/typing.ts new file mode 100644 index 0000000..3a037e9 --- /dev/null +++ b/src/components/Qrcode/src/typing.ts @@ -0,0 +1,38 @@ +import type { QRCodeSegment, QRCodeRenderersOptions } from 'qrcode'; + +export type ContentType = string | QRCodeSegment[]; + +export type { QRCodeRenderersOptions }; + +export type LogoType = { + src: string; + logoSize: number; + borderColor: string; + bgColor: string; + borderSize: number; + crossOrigin: string; + borderRadius: number; + logoRadius: number; +}; + +export interface RenderQrCodeParams { + canvas: any; + content: ContentType; + width?: number; + options?: QRCodeRenderersOptions; + logo?: LogoType | string; + image?: HTMLImageElement; + downloadName?: string; + download?: boolean | Fn; +} + +export type ToCanvasFn = (options: RenderQrCodeParams) => Promise; + +export interface QrCodeActionType { + download: (fileName?: string) => void; +} + +export interface QrcodeDoneEventParams { + url: string; + ctx?: CanvasRenderingContext2D | null; +} diff --git a/src/components/Scrollbar/index.ts b/src/components/Scrollbar/index.ts new file mode 100644 index 0000000..e5b2cb2 --- /dev/null +++ b/src/components/Scrollbar/index.ts @@ -0,0 +1,8 @@ +/** + * copy from element-ui + */ + +import Scrollbar from './src/Scrollbar.vue'; + +export { Scrollbar }; +export type { ScrollbarType } from './src/types'; diff --git a/src/components/Scrollbar/src/Scrollbar.vue b/src/components/Scrollbar/src/Scrollbar.vue new file mode 100644 index 0000000..daeb230 --- /dev/null +++ b/src/components/Scrollbar/src/Scrollbar.vue @@ -0,0 +1,207 @@ + + + diff --git a/src/components/Scrollbar/src/bar.ts b/src/components/Scrollbar/src/bar.ts new file mode 100644 index 0000000..64bd289 --- /dev/null +++ b/src/components/Scrollbar/src/bar.ts @@ -0,0 +1,110 @@ +import { + defineComponent, + h, + computed, + ref, + getCurrentInstance, + onUnmounted, + inject, + Ref, +} from 'vue'; +import { on, off } from '/@/utils/domUtils'; + +import { renderThumbStyle, BAR_MAP } from './util'; + +export default defineComponent({ + name: 'Bar', + + props: { + vertical: Boolean, + size: String, + move: Number, + }, + + setup(props) { + const instance = getCurrentInstance(); + const thumb = ref(); + const wrap = inject('scroll-bar-wrap', {} as Ref>) as any; + const bar = computed(() => { + return BAR_MAP[props.vertical ? 'vertical' : 'horizontal']; + }); + const barStore = ref({}); + const cursorDown = ref(); + const clickThumbHandler = (e: any) => { + // prevent click event of right button + if (e.ctrlKey || e.button === 2) { + return; + } + window.getSelection()?.removeAllRanges(); + startDrag(e); + barStore.value[bar.value.axis] = + e.currentTarget[bar.value.offset] - + (e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]); + }; + + const clickTrackHandler = (e: any) => { + const offset = Math.abs( + e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client], + ); + const thumbHalf = thumb.value[bar.value.offset] / 2; + const thumbPositionPercentage = + ((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset]; + + wrap.value[bar.value.scroll] = + (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100; + }; + const startDrag = (e: any) => { + e.stopImmediatePropagation(); + cursorDown.value = true; + on(document, 'mousemove', mouseMoveDocumentHandler); + on(document, 'mouseup', mouseUpDocumentHandler); + document.onselectstart = () => false; + }; + + const mouseMoveDocumentHandler = (e: any) => { + if (cursorDown.value === false) return; + const prevPage = barStore.value[bar.value.axis]; + + if (!prevPage) return; + + const offset = + (instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) * + -1; + const thumbClickPosition = thumb.value[bar.value.offset] - prevPage; + const thumbPositionPercentage = + ((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset]; + wrap.value[bar.value.scroll] = + (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100; + }; + + function mouseUpDocumentHandler() { + cursorDown.value = false; + barStore.value[bar.value.axis] = 0; + off(document, 'mousemove', mouseMoveDocumentHandler); + document.onselectstart = null; + } + + onUnmounted(() => { + off(document, 'mouseup', mouseUpDocumentHandler); + }); + + return () => + h( + 'div', + { + class: ['scrollbar__bar', 'is-' + bar.value.key], + onMousedown: clickTrackHandler, + }, + h('div', { + ref: thumb, + class: 'scrollbar__thumb', + onMousedown: clickThumbHandler, + style: renderThumbStyle({ + size: props.size, + move: props.move, + bar: bar.value, + }), + }), + ); + }, +}); diff --git a/src/components/Scrollbar/src/types.d.ts b/src/components/Scrollbar/src/types.d.ts new file mode 100644 index 0000000..4c7eeea --- /dev/null +++ b/src/components/Scrollbar/src/types.d.ts @@ -0,0 +1,18 @@ +export interface BarMapItem { + offset: string; + scroll: string; + scrollSize: string; + size: string; + key: string; + axis: string; + client: string; + direction: string; +} +export interface BarMap { + vertical: BarMapItem; + horizontal: BarMapItem; +} + +export interface ScrollbarType { + wrap: ElRef; +} diff --git a/src/components/Scrollbar/src/util.ts b/src/components/Scrollbar/src/util.ts new file mode 100644 index 0000000..77694a9 --- /dev/null +++ b/src/components/Scrollbar/src/util.ts @@ -0,0 +1,51 @@ +import type { BarMap } from './types'; + +export const BAR_MAP: BarMap = { + vertical: { + offset: 'offsetHeight', + scroll: 'scrollTop', + scrollSize: 'scrollHeight', + size: 'height', + key: 'vertical', + axis: 'Y', + client: 'clientY', + direction: 'top', + }, + horizontal: { + offset: 'offsetWidth', + scroll: 'scrollLeft', + scrollSize: 'scrollWidth', + size: 'width', + key: 'horizontal', + axis: 'X', + client: 'clientX', + direction: 'left', + }, +}; + +// @ts-ignore +export function renderThumbStyle({ move, size, bar }) { + const style = {} as any; + const translate = `translate${bar.axis}(${move}%)`; + + style[bar.size] = size; + style.transform = translate; + style.msTransform = translate; + style.webkitTransform = translate; + + return style; +} + +function extend(to: T, _from: K): T & K { + return Object.assign(to, _from); +} + +export function toObject(arr: Array): Recordable { + const res = {}; + for (let i = 0; i < arr.length; i++) { + if (arr[i]) { + extend(res, arr[i]); + } + } + return res; +} diff --git a/src/components/SimpleMenu/index.ts b/src/components/SimpleMenu/index.ts new file mode 100644 index 0000000..0dfd248 --- /dev/null +++ b/src/components/SimpleMenu/index.ts @@ -0,0 +1,2 @@ +export { default as SimpleMenu } from './src/SimpleMenu.vue'; +export { default as SimpleMenuTag } from './src/SimpleMenuTag.vue'; diff --git a/src/components/SimpleMenu/src/SimpleMenu.vue b/src/components/SimpleMenu/src/SimpleMenu.vue new file mode 100644 index 0000000..a391d06 --- /dev/null +++ b/src/components/SimpleMenu/src/SimpleMenu.vue @@ -0,0 +1,161 @@ + + + diff --git a/src/components/SimpleMenu/src/SimpleMenuTag.vue b/src/components/SimpleMenu/src/SimpleMenuTag.vue new file mode 100644 index 0000000..b7d3cb3 --- /dev/null +++ b/src/components/SimpleMenu/src/SimpleMenuTag.vue @@ -0,0 +1,68 @@ + + diff --git a/src/components/SimpleMenu/src/SimpleSubMenu.vue b/src/components/SimpleMenu/src/SimpleSubMenu.vue new file mode 100644 index 0000000..1accfc7 --- /dev/null +++ b/src/components/SimpleMenu/src/SimpleSubMenu.vue @@ -0,0 +1,116 @@ + + diff --git a/src/components/SimpleMenu/src/components/Menu.vue b/src/components/SimpleMenu/src/components/Menu.vue new file mode 100644 index 0000000..28e0b3e --- /dev/null +++ b/src/components/SimpleMenu/src/components/Menu.vue @@ -0,0 +1,159 @@ + + + + diff --git a/src/components/SimpleMenu/src/components/MenuCollapseTransition.vue b/src/components/SimpleMenu/src/components/MenuCollapseTransition.vue new file mode 100644 index 0000000..5295439 --- /dev/null +++ b/src/components/SimpleMenu/src/components/MenuCollapseTransition.vue @@ -0,0 +1,78 @@ + + diff --git a/src/components/SimpleMenu/src/components/MenuItem.vue b/src/components/SimpleMenu/src/components/MenuItem.vue new file mode 100644 index 0000000..3a99796 --- /dev/null +++ b/src/components/SimpleMenu/src/components/MenuItem.vue @@ -0,0 +1,107 @@ + + + diff --git a/src/components/SimpleMenu/src/components/SubMenuItem.vue b/src/components/SimpleMenu/src/components/SubMenuItem.vue new file mode 100644 index 0000000..87c9e07 --- /dev/null +++ b/src/components/SimpleMenu/src/components/SubMenuItem.vue @@ -0,0 +1,336 @@ + + + diff --git a/src/components/SimpleMenu/src/components/menu.less b/src/components/SimpleMenu/src/components/menu.less new file mode 100644 index 0000000..2fe0b54 --- /dev/null +++ b/src/components/SimpleMenu/src/components/menu.less @@ -0,0 +1,309 @@ +@menu-prefix-cls: ~'@{namespace}-menu'; +@menu-popup-prefix-cls: ~'@{namespace}-menu-popup'; +@submenu-popup-prefix-cls: ~'@{namespace}-menu-submenu-popup'; + +@transition-time: 0.2s; +@menu-dark-subsidiary-color: rgba(255, 255, 255, 0.7); + +.light-border { + &::after { + content: ''; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 2px; + background-color: @primary-color; + } +} + +.@{menu-prefix-cls}-menu-popover { + .ant-popover-arrow { + display: none; + } + + .ant-popover-inner-content { + padding: 0; + } + + .@{menu-prefix-cls} { + &-opened > * > &-submenu-title-icon { + transform: translateY(-50%) rotate(90deg) !important; + } + + &-item, + &-submenu-title { + position: relative; + z-index: 1; + padding: 12px 20px; + transition: all @transition-time @ease-in-out; + color: @menu-dark-subsidiary-color; + cursor: pointer; + + &-icon { + position: absolute; + top: 50%; + right: 18px; + transform: translateY(-50%) rotate(-90deg); + transition: transform @transition-time @ease-in-out; + } + } + + &-dark { + .@{menu-prefix-cls}-item, + .@{menu-prefix-cls}-submenu-title { + color: @menu-dark-subsidiary-color; + // background: @menu-dark-active-bg; + + &:hover { + color: #fff; + } + + &-selected { + background-color: @primary-color !important; + color: #fff; + } + } + } + + &-light { + .@{menu-prefix-cls}-item, + .@{menu-prefix-cls}-submenu-title { + color: @text-color-base; + + &:hover { + color: @primary-color; + } + + &-selected { + z-index: 2; + background-color: fade(@primary-color, 10); + color: @primary-color; + + .light-border(); + } + } + } + } +} + +.content(); +.content() { + .@{menu-prefix-cls} { + display: block; + position: relative; + width: 100%; + margin: 0; + padding: 0; + outline: none; + color: @text-color-base; + font-size: @font-size-base; + list-style: none; + + // .collapse-transition { + // transition: @transition-time height ease-in-out, @transition-time padding-top ease-in-out, + // @transition-time padding-bottom ease-in-out; + // } + + &-light { + background-color: #fff; + + .@{menu-prefix-cls}-submenu-active { + color: @primary-color !important; + + &-border { + .light-border(); + } + } + } + + &-dark { + .@{menu-prefix-cls}-submenu-active { + color: #fff !important; + } + } + + &-item { + display: flex; + position: relative; + z-index: 1; + align-items: center; + outline: none; + color: inherit; + font-size: @font-size-base; + list-style: none; + cursor: pointer; + + &:hover, + &:active { + color: inherit; + } + } + + &-item > i { + margin-right: 6px; + } + + &-submenu-title > i, + &-submenu-title span > i { + margin-right: 8px; + } + + // vertical + &-vertical &-item, + &-vertical &-submenu-title { + position: relative; + z-index: 1; + padding: 14px 24px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: pointer; + + &:hover { + color: @primary-color; + } + + .@{menu-prefix-cls}-tooltip { + width: calc(100% - 0px); + padding: 12px 0; + text-align: center; + } + .@{menu-prefix-cls}-submenu-popup { + padding: 12px 0; + } + } + + &-vertical &-submenu-collapse { + .@{submenu-popup-prefix-cls} { + display: flex; + align-items: center; + justify-content: center; + } + .@{menu-prefix-cls}-submenu-collapsed-show-tit { + flex-direction: column; + } + } + + &-vertical&-collapse &-item, + &-vertical&-collapse &-submenu-title { + padding: 0; + } + + &-vertical &-submenu-title-icon { + position: absolute; + top: 50%; + right: 18px; + transform: translateY(-50%); + } + + &-submenu-title-icon { + transition: transform @transition-time @ease-in-out; + } + + &-vertical &-opened > * > &-submenu-title-icon { + transform: translateY(-50%) rotate(180deg); + } + + &-vertical &-submenu { + &-nested { + padding-left: 20px; + } + .@{menu-prefix-cls}-item { + padding-left: 43px; + } + } + + &-light&-vertical &-item { + &-active:not(.@{menu-prefix-cls}-submenu) { + z-index: 2; + background-color: fade(@primary-color, 10); + color: @primary-color; + + .light-border(); + } + &-active.@{menu-prefix-cls}-submenu { + color: @primary-color; + } + } + + &-light&-vertical&-collapse { + > li.@{menu-prefix-cls}-item-active, + .@{menu-prefix-cls}-submenu-active { + position: relative; + background-color: fade(@primary-color, 5); + + &::after { + display: none; + } + + &::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 3px; + height: 100%; + background-color: @primary-color; + } + } + } + + &-dark&-vertical &-item, + &-dark&-vertical &-submenu-title { + color: @menu-dark-subsidiary-color; + &-active:not(.@{menu-prefix-cls}-submenu) { + background-color: @primary-color !important; + color: #fff !important; + } + + &:hover { + color: #fff; + } + } + + &-dark&-vertical&-collapse { + > li.@{menu-prefix-cls}-item-active, + .@{menu-prefix-cls}-submenu-active { + position: relative; + background-color: @sider-dark-darken-bg-color !important; + color: #fff !important; + + &::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 3px; + height: 100%; + background-color: @primary-color; + } + + .@{menu-prefix-cls}-submenu-collapse { + background-color: transparent; + } + } + } + + &-dark&-vertical &-submenu &-item { + &-active, + &-active:hover { + border-right: none; + color: #fff; + } + } + + &-dark&-vertical &-child-item-active > &-submenu-title { + color: #fff; + } + + &-dark&-vertical &-opened { + .@{menu-prefix-cls}-submenu-has-parent-submenu { + .@{menu-prefix-cls}-submenu-title { + background-color: transparent; + } + } + } + } +} diff --git a/src/components/SimpleMenu/src/components/types.ts b/src/components/SimpleMenu/src/components/types.ts new file mode 100644 index 0000000..d828e89 --- /dev/null +++ b/src/components/SimpleMenu/src/components/types.ts @@ -0,0 +1,25 @@ +import { Ref } from 'vue'; + +export interface Props { + theme: string; + activeName?: string | number | undefined; + openNames: string[]; + accordion: boolean; + width: string; + collapsedWidth: string; + indentSize: number; + collapse: boolean; + activeSubMenuNames: (string | number)[]; +} + +export interface SubMenuProvider { + addSubMenu: (name: string | number, update?: boolean) => void; + removeSubMenu: (name: string | number, update?: boolean) => void; + removeAll: () => void; + sliceIndex: (index: number) => void; + isRemoveAllPopup: Ref; + getOpenNames: () => (string | number)[]; + handleMouseleave?: Fn; + level: number; + props: Props; +} diff --git a/src/components/SimpleMenu/src/components/useMenu.ts b/src/components/SimpleMenu/src/components/useMenu.ts new file mode 100644 index 0000000..8830559 --- /dev/null +++ b/src/components/SimpleMenu/src/components/useMenu.ts @@ -0,0 +1,84 @@ +import { computed, ComponentInternalInstance, unref } from 'vue'; +import type { CSSProperties } from 'vue'; + +export function useMenuItem(instance: ComponentInternalInstance | null) { + const getParentMenu = computed(() => { + return findParentMenu(['Menu', 'SubMenu']); + }); + + const getParentRootMenu = computed(() => { + return findParentMenu(['Menu']); + }); + + const getParentSubMenu = computed(() => { + return findParentMenu(['SubMenu']); + }); + + const getItemStyle = computed((): CSSProperties => { + let parent = instance?.parent; + if (!parent) return {}; + const indentSize = (unref(getParentRootMenu)?.props.indentSize as number) ?? 20; + let padding = indentSize; + + if (unref(getParentRootMenu)?.props.collapse) { + padding = indentSize; + } else { + while (parent && parent.type.name !== 'Menu') { + if (parent.type.name === 'SubMenu') { + padding += indentSize; + } + parent = parent.parent; + } + } + return { paddingLeft: padding + 'px' }; + }); + + function findParentMenu(name: string[]) { + let parent = instance?.parent; + if (!parent) return null; + while (parent && name.indexOf(parent.type.name!) === -1) { + parent = parent.parent; + } + return parent; + } + + function getParentList() { + let parent = instance; + if (!parent) + return { + uidList: [], + list: [], + }; + const ret: any[] = []; + while (parent && parent.type.name !== 'Menu') { + if (parent.type.name === 'SubMenu') { + ret.push(parent); + } + parent = parent.parent; + } + return { + uidList: ret.map((item) => item.uid), + list: ret, + }; + } + + function getParentInstance(instance: ComponentInternalInstance, name = 'SubMenu') { + let parent = instance.parent; + while (parent) { + if (parent.type.name !== name) { + return parent; + } + parent = parent.parent; + } + return parent; + } + + return { + getParentMenu, + getParentInstance, + getParentRootMenu, + getParentList, + getParentSubMenu, + getItemStyle, + }; +} diff --git a/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts b/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts new file mode 100644 index 0000000..f3d8100 --- /dev/null +++ b/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts @@ -0,0 +1,18 @@ +import type { InjectionKey, Ref } from 'vue'; +import type { Emitter } from '/@/utils/mitt'; +import { createContext, useContext } from '/@/hooks/core/useContext'; + +export interface SimpleRootMenuContextProps { + rootMenuEmitter: Emitter; + activeName: Ref; +} + +const key: InjectionKey = Symbol(); + +export function createSimpleRootMenuContext(context: SimpleRootMenuContextProps) { + return createContext(context, key, { readonly: false, native: true }); +} + +export function useSimpleRootMenuContext() { + return useContext(key); +} diff --git a/src/components/SimpleMenu/src/index.less b/src/components/SimpleMenu/src/index.less new file mode 100644 index 0000000..74fe82b --- /dev/null +++ b/src/components/SimpleMenu/src/index.less @@ -0,0 +1,77 @@ +@simple-prefix-cls: ~'@{namespace}-simple-menu'; +@prefix-cls: ~'@{namespace}-menu'; + +.@{prefix-cls} { + &-dark&-vertical .@{simple-prefix-cls}__parent { + background-color: @sider-dark-bg-color; + > .@{prefix-cls}-submenu-title { + background-color: @sider-dark-bg-color; + } + } + + &-dark&-vertical .@{simple-prefix-cls}__children, + &-dark&-popup .@{simple-prefix-cls}__children { + background-color: @sider-dark-lighten-bg-color; + > .@{prefix-cls}-submenu-title { + background-color: @sider-dark-lighten-bg-color; + } + } + + .collapse-title { + overflow: hidden; + font-size: 12px; + text-overflow: ellipsis; + white-space: nowrap; + } +} + +.@{simple-prefix-cls} { + &-sub-title { + overflow: hidden; + transition: all 0.3s; + text-overflow: ellipsis; + white-space: nowrap; + } + + &-tag { + display: inline-block; + position: absolute; + top: calc(50% - 8px); + right: 30px; + margin-right: 4px; + padding: 2px 3px; + border-radius: 2px; + color: #fff; + font-size: 10px; + line-height: 14px; + + &--collapse { + top: 6px !important; + right: 2px; + } + + &--dot { + top: calc(50% - 2px); + width: 6px; + height: 6px; + padding: 0; + border-radius: 50%; + } + + &--primary { + background-color: @primary-color; + } + + &--error { + background-color: @error-color; + } + + &--success { + background-color: @success-color; + } + + &--warn { + background-color: @warning-color; + } + } +} diff --git a/src/components/SimpleMenu/src/types.ts b/src/components/SimpleMenu/src/types.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/components/SimpleMenu/src/useOpenKeys.ts b/src/components/SimpleMenu/src/useOpenKeys.ts new file mode 100644 index 0000000..1028f97 --- /dev/null +++ b/src/components/SimpleMenu/src/useOpenKeys.ts @@ -0,0 +1,48 @@ +import type { Menu as MenuType } from '/@/router/types'; +import type { MenuState } from './types'; +import { computed, Ref, toRaw, unref } from 'vue'; +import { uniq } from 'lodash-es'; +import { getAllParentPath } from '/@/router/helper/menuHelper'; +import { useTimeoutFn } from '@vben/hooks'; +import { useDebounceFn } from '@vueuse/core'; + +export function useOpenKeys( + menuState: MenuState, + menus: Ref, + accordion: Ref, + mixSider: Ref, + collapse: Ref, +) { + const debounceSetOpenKeys = useDebounceFn(setOpenKeys, 50); + async function setOpenKeys(path: string) { + const native = !mixSider.value; + const menuList = toRaw(menus.value); + + const handle = () => { + if (menuList?.length === 0) { + menuState.activeSubMenuNames = []; + menuState.openNames = []; + return; + } + const keys = getAllParentPath(menuList, path); + + if (!unref(accordion)) { + menuState.openNames = uniq([...menuState.openNames, ...keys]); + } else { + menuState.openNames = keys; + } + menuState.activeSubMenuNames = menuState.openNames; + }; + if (native) { + handle(); + } else { + useTimeoutFn(handle, 30); + } + } + + const getOpenKeys = computed(() => { + return unref(collapse) ? [] : menuState.openNames; + }); + + return { setOpenKeys: debounceSetOpenKeys, getOpenKeys }; +} diff --git a/src/components/StrengthMeter/index.ts b/src/components/StrengthMeter/index.ts new file mode 100644 index 0000000..9763afa --- /dev/null +++ b/src/components/StrengthMeter/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from '/@/utils'; +import strengthMeter from './src/StrengthMeter.vue'; + +export const StrengthMeter = withInstall(strengthMeter); diff --git a/src/components/StrengthMeter/src/StrengthMeter.vue b/src/components/StrengthMeter/src/StrengthMeter.vue new file mode 100644 index 0000000..39074d9 --- /dev/null +++ b/src/components/StrengthMeter/src/StrengthMeter.vue @@ -0,0 +1,142 @@ + + + + diff --git a/src/components/Table/index.ts b/src/components/Table/index.ts new file mode 100644 index 0000000..1ec9568 --- /dev/null +++ b/src/components/Table/index.ts @@ -0,0 +1,11 @@ +export { default as BasicTable } from './src/BasicTable.vue'; +export { default as TableAction } from './src/components/TableAction.vue'; +export { default as EditTableHeaderIcon } from './src/components/EditTableHeaderIcon.vue'; +export { default as TableImg } from './src/components/TableImg.vue'; + +export * from './src/types/table'; +export * from './src/types/pagination'; +export * from './src/types/tableAction'; +export { useTable } from './src/hooks/useTable'; +export type { FormSchema, FormProps } from '/@/components/Form/src/types/form'; +export type { EditRecordRow } from './src/components/editable'; diff --git a/src/components/Table/src/BasicTable.vue b/src/components/Table/src/BasicTable.vue new file mode 100644 index 0000000..038b8bb --- /dev/null +++ b/src/components/Table/src/BasicTable.vue @@ -0,0 +1,467 @@ + + + \ No newline at end of file diff --git a/src/components/Table/src/componentMap.ts b/src/components/Table/src/componentMap.ts new file mode 100644 index 0000000..ace83f5 --- /dev/null +++ b/src/components/Table/src/componentMap.ts @@ -0,0 +1,40 @@ +import type { Component } from 'vue'; +import { + Input, + Select, + Checkbox, + InputNumber, + Switch, + DatePicker, + TimePicker, + AutoComplete, + Radio, +} from 'ant-design-vue'; +import type { ComponentType } from './types/componentType'; +import { ApiSelect, ApiTreeSelect, RadioButtonGroup, ApiRadioGroup } from '/@/components/Form'; + +const componentMap = new Map(); + +componentMap.set('Input', Input); +componentMap.set('InputNumber', InputNumber); +componentMap.set('Select', Select); +componentMap.set('ApiSelect', ApiSelect); +componentMap.set('AutoComplete', AutoComplete); +componentMap.set('ApiTreeSelect', ApiTreeSelect); +componentMap.set('Switch', Switch); +componentMap.set('Checkbox', Checkbox); +componentMap.set('DatePicker', DatePicker); +componentMap.set('TimePicker', TimePicker); +componentMap.set('RadioGroup', Radio.Group); +componentMap.set('RadioButtonGroup', RadioButtonGroup); +componentMap.set('ApiRadioGroup', ApiRadioGroup); + +export function add(compName: ComponentType, component: Component) { + componentMap.set(compName, component); +} + +export function del(compName: ComponentType) { + componentMap.delete(compName); +} + +export { componentMap }; diff --git a/src/components/Table/src/components/EditTableHeaderIcon.vue b/src/components/Table/src/components/EditTableHeaderIcon.vue new file mode 100644 index 0000000..ed05c31 --- /dev/null +++ b/src/components/Table/src/components/EditTableHeaderIcon.vue @@ -0,0 +1,17 @@ + + diff --git a/src/components/Table/src/components/HeaderCell.vue b/src/components/Table/src/components/HeaderCell.vue new file mode 100644 index 0000000..e906bef --- /dev/null +++ b/src/components/Table/src/components/HeaderCell.vue @@ -0,0 +1,60 @@ + + diff --git a/src/components/Table/src/components/TableAction.vue b/src/components/Table/src/components/TableAction.vue new file mode 100644 index 0000000..73bf691 --- /dev/null +++ b/src/components/Table/src/components/TableAction.vue @@ -0,0 +1,202 @@ + + + diff --git a/src/components/Table/src/components/TableFooter.vue b/src/components/Table/src/components/TableFooter.vue new file mode 100644 index 0000000..68e556b --- /dev/null +++ b/src/components/Table/src/components/TableFooter.vue @@ -0,0 +1,94 @@ + + diff --git a/src/components/Table/src/components/TableHeader.vue b/src/components/Table/src/components/TableHeader.vue new file mode 100644 index 0000000..cfcd090 --- /dev/null +++ b/src/components/Table/src/components/TableHeader.vue @@ -0,0 +1,81 @@ + + + diff --git a/src/components/Table/src/components/TableImg.vue b/src/components/Table/src/components/TableImg.vue new file mode 100644 index 0000000..0867bda --- /dev/null +++ b/src/components/Table/src/components/TableImg.vue @@ -0,0 +1,91 @@ + + + diff --git a/src/components/Table/src/components/TableTitle.vue b/src/components/Table/src/components/TableTitle.vue new file mode 100644 index 0000000..0f7417b --- /dev/null +++ b/src/components/Table/src/components/TableTitle.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/components/Table/src/components/editable/CellComponent.ts b/src/components/Table/src/components/editable/CellComponent.ts new file mode 100644 index 0000000..547940b --- /dev/null +++ b/src/components/Table/src/components/editable/CellComponent.ts @@ -0,0 +1,44 @@ +import type { FunctionalComponent, defineComponent } from 'vue'; +import type { ComponentType } from '../../types/componentType'; +import { componentMap } from '/@/components/Table/src/componentMap'; + +import { Popover } from 'ant-design-vue'; +import { h } from 'vue'; + +export interface ComponentProps { + component: ComponentType; + rule: boolean; + popoverVisible: boolean; + ruleMessage: string; + getPopupContainer?: Fn; +} + +export const CellComponent: FunctionalComponent = ( + { + component = 'Input', + rule = true, + ruleMessage, + popoverVisible, + getPopupContainer, + }: ComponentProps, + { attrs }, +) => { + const Comp = componentMap.get(component) as typeof defineComponent; + + const DefaultComp = h(Comp, attrs); + if (!rule) { + return DefaultComp; + } + return h( + Popover, + { + overlayClassName: 'edit-cell-rule-popover', + open: !!popoverVisible, + ...(getPopupContainer ? { getPopupContainer } : {}), + }, + { + default: () => DefaultComp, + content: () => ruleMessage, + }, + ); +}; diff --git a/src/components/Table/src/components/editable/EditableCell.vue b/src/components/Table/src/components/editable/EditableCell.vue new file mode 100644 index 0000000..e24e0e6 --- /dev/null +++ b/src/components/Table/src/components/editable/EditableCell.vue @@ -0,0 +1,535 @@ + + diff --git a/src/components/Table/src/components/editable/helper.ts b/src/components/Table/src/components/editable/helper.ts new file mode 100644 index 0000000..9c600c9 --- /dev/null +++ b/src/components/Table/src/components/editable/helper.ts @@ -0,0 +1,28 @@ +import { ComponentType } from '../../types/componentType'; +import { useI18n } from '/@/hooks/web/useI18n'; + +const { t } = useI18n(); + +/** + * @description: 生成placeholder + */ +export function createPlaceholderMessage(component: ComponentType) { + if (component.includes('Input') || component.includes('AutoComplete')) { + return t('common.inputText'); + } + if (component.includes('Picker')) { + return t('common.chooseText'); + } + + if ( + component.includes('Select') || + component.includes('Checkbox') || + component.includes('Radio') || + component.includes('Switch') || + component.includes('DatePicker') || + component.includes('TimePicker') + ) { + return t('common.chooseText'); + } + return ''; +} diff --git a/src/components/Table/src/components/editable/index.ts b/src/components/Table/src/components/editable/index.ts new file mode 100644 index 0000000..548c9e4 --- /dev/null +++ b/src/components/Table/src/components/editable/index.ts @@ -0,0 +1,68 @@ +import type { BasicColumn } from '/@/components/Table/src/types/table'; + +import { h, Ref, toRaw } from 'vue'; + +import EditableCell from './EditableCell.vue'; +import { isArray } from '/@/utils/is'; + +interface Params { + text: string; + record: Recordable; + index: number; +} + +export function renderEditCell(column: BasicColumn) { + return ({ text: value, record, index }: Params) => { + toRaw(record).onValid = async () => { + if (isArray(record?.validCbs)) { + const validFns = (record?.validCbs || []).map((fn) => fn()); + const res = await Promise.all(validFns); + return res.every((item) => !!item); + } else { + return false; + } + }; + + toRaw(record).onEdit = async (edit: boolean, submit = false) => { + if (!submit) { + record.editable = edit; + } + + if (!edit && submit) { + if (!(await record.onValid())) return false; + const res = await record.onSubmitEdit?.(); + if (res) { + record.editable = false; + return true; + } + return false; + } + // cancel + if (!edit && !submit) { + record.onCancelEdit?.(); + } + return true; + }; + + return h(EditableCell, { + value, + record, + column, + index, + }); + }; +} + +export type EditRecordRow = Partial< + { + onEdit: (editable: boolean, submit?: boolean) => Promise; + onValid: () => Promise; + editable: boolean; + onCancel: Fn; + onSubmit: Fn; + submitCbs: Fn[]; + cancelCbs: Fn[]; + validCbs: Fn[]; + editValueRefs: Recordable; + } & T +>; diff --git a/src/components/Table/src/components/settings/ColumnSetting.vue b/src/components/Table/src/components/settings/ColumnSetting.vue new file mode 100644 index 0000000..7b494b0 --- /dev/null +++ b/src/components/Table/src/components/settings/ColumnSetting.vue @@ -0,0 +1,515 @@ + + + diff --git a/src/components/Table/src/components/settings/FullScreenSetting.vue b/src/components/Table/src/components/settings/FullScreenSetting.vue new file mode 100644 index 0000000..af07f84 --- /dev/null +++ b/src/components/Table/src/components/settings/FullScreenSetting.vue @@ -0,0 +1,38 @@ + + diff --git a/src/components/Table/src/components/settings/RedoSetting.vue b/src/components/Table/src/components/settings/RedoSetting.vue new file mode 100644 index 0000000..81829a1 --- /dev/null +++ b/src/components/Table/src/components/settings/RedoSetting.vue @@ -0,0 +1,33 @@ + + diff --git a/src/components/Table/src/components/settings/SizeSetting.vue b/src/components/Table/src/components/settings/SizeSetting.vue new file mode 100644 index 0000000..79c4a22 --- /dev/null +++ b/src/components/Table/src/components/settings/SizeSetting.vue @@ -0,0 +1,64 @@ + + diff --git a/src/components/Table/src/components/settings/index.vue b/src/components/Table/src/components/settings/index.vue new file mode 100644 index 0000000..ab03cb2 --- /dev/null +++ b/src/components/Table/src/components/settings/index.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/components/Table/src/const.ts b/src/components/Table/src/const.ts new file mode 100644 index 0000000..2a45fac --- /dev/null +++ b/src/components/Table/src/const.ts @@ -0,0 +1,38 @@ +import componentSetting from '/@/settings/componentSetting'; + +const { table } = componentSetting; + +const { + pageSizeOptions, + defaultPageSize, + fetchSetting, + defaultSize, + defaultSortFn, + defaultFilterFn, +} = table; + +export const ROW_KEY = 'key'; + +// Optional display number per page; +export const PAGE_SIZE_OPTIONS = pageSizeOptions; + +// Number of items displayed per page +export const PAGE_SIZE = defaultPageSize; + +// Common interface field settings +export const FETCH_SETTING = fetchSetting; + +// Default Size +export const DEFAULT_SIZE = defaultSize; + +// Configure general sort function +export const DEFAULT_SORT_FN = defaultSortFn; + +export const DEFAULT_FILTER_FN = defaultFilterFn; + +// Default layout of table cells +export const DEFAULT_ALIGN = 'center'; + +export const INDEX_COLUMN_FLAG = 'INDEX'; + +export const ACTION_COLUMN_FLAG = 'ACTION'; diff --git a/src/components/Table/src/hooks/useColumns.ts b/src/components/Table/src/hooks/useColumns.ts new file mode 100644 index 0000000..7523725 --- /dev/null +++ b/src/components/Table/src/hooks/useColumns.ts @@ -0,0 +1,329 @@ +import type { BasicColumn, BasicTableProps, CellFormat, GetColumnsParams } from '../types/table'; +import type { PaginationProps } from '../types/pagination'; +import type { ComputedRef } from 'vue'; +import { computed, Ref, ref, reactive, toRaw, unref, watch } from 'vue'; +import { renderEditCell } from '../components/editable'; +import { usePermission } from '/@/hooks/web/usePermission'; +import { useI18n } from '/@/hooks/web/useI18n'; +import { isArray, isBoolean, isFunction, isMap, isString } from '/@/utils/is'; +import { cloneDeep, isEqual } from 'lodash-es'; +import { formatToDate } from '/@/utils/dateUtil'; +import { ACTION_COLUMN_FLAG, DEFAULT_ALIGN, INDEX_COLUMN_FLAG, PAGE_SIZE } from '../const'; + +function handleItem(item: BasicColumn, ellipsis: boolean) { + const { key, dataIndex, children } = item; + item.align = item.align || DEFAULT_ALIGN; + if (ellipsis) { + if (!key) { + item.key = typeof dataIndex == 'object' ? dataIndex.join('-') : dataIndex; + } + if (!isBoolean(item.ellipsis)) { + Object.assign(item, { + ellipsis, + }); + } + } + if (children && children.length) { + handleChildren(children, !!ellipsis); + } +} + +function handleChildren(children: BasicColumn[] | undefined, ellipsis: boolean) { + if (!children) return; + children.forEach((item) => { + const { children } = item; + handleItem(item, ellipsis); + handleChildren(children, ellipsis); + }); +} + +function handleIndexColumn( + propsRef: ComputedRef, + getPaginationRef: ComputedRef, + columns: BasicColumn[], +) { + const { t } = useI18n(); + + const { showIndexColumn, indexColumnProps, isTreeTable } = unref(propsRef); + + let pushIndexColumns = false; + if (unref(isTreeTable)) { + return; + } + columns.forEach(() => { + const indIndex = columns.findIndex((column) => column.flag === INDEX_COLUMN_FLAG); + if (showIndexColumn) { + pushIndexColumns = indIndex === -1; + } else if (!showIndexColumn && indIndex !== -1) { + columns.splice(indIndex, 1); + } + }); + + if (!pushIndexColumns) return; + + const isFixedLeft = columns.some((item) => item.fixed === 'left'); + + columns.unshift({ + flag: INDEX_COLUMN_FLAG, + width: 50, + title: t('component.table.index'), + align: 'center', + customRender: ({ index }) => { + const getPagination = unref(getPaginationRef); + if (isBoolean(getPagination)) { + return `${index + 1}`; + } + const { current = 1, pageSize = PAGE_SIZE } = getPagination; + return ((current < 1 ? 1 : current) - 1) * pageSize + index + 1; + }, + ...(isFixedLeft + ? { + fixed: 'left', + } + : {}), + ...indexColumnProps, + }); +} + +function handleActionColumn(propsRef: ComputedRef, columns: BasicColumn[]) { + const { actionColumn } = unref(propsRef); + if (!actionColumn) return; + + const hasIndex = columns.findIndex((column) => column.flag === ACTION_COLUMN_FLAG); + if (hasIndex === -1) { + columns.push({ + ...columns[hasIndex], + fixed: 'right', + ...actionColumn, + flag: ACTION_COLUMN_FLAG, + }); + } +} + +export function useColumns( + propsRef: ComputedRef, + getPaginationRef: ComputedRef, +) { + const columnsRef = ref(unref(propsRef).columns) as unknown as Ref; + let cacheColumns = unref(propsRef).columns; + + const getColumnsRef = computed(() => { + const columns = cloneDeep(unref(columnsRef)); + + handleIndexColumn(propsRef, getPaginationRef, columns); + handleActionColumn(propsRef, columns); + if (!columns) { + return []; + } + const { ellipsis } = unref(propsRef); + + columns.forEach((item) => { + const { customRender, slots } = item; + + handleItem( + item, + Reflect.has(item, 'ellipsis') ? !!item.ellipsis : !!ellipsis && !customRender && !slots, + ); + }); + return columns; + }); + + function isIfShow(column: BasicColumn): boolean { + const ifShow = column.ifShow; + + let isIfShow = true; + + if (isBoolean(ifShow)) { + isIfShow = ifShow; + } + if (isFunction(ifShow)) { + isIfShow = ifShow(column); + } + return isIfShow; + } + const { hasPermission } = usePermission(); + + const getViewColumns = computed(() => { + const viewColumns = sortFixedColumn(unref(getColumnsRef)); + + const mapFn = (column) => { + const { slots, customRender, format, edit, editRow, flag } = column; + + if (!slots || !slots?.title) { + // column.slots = { title: `header-${dataIndex}`, ...(slots || {}) }; + column.customTitle = column.title; + Reflect.deleteProperty(column, 'title'); + } + const isDefaultAction = [INDEX_COLUMN_FLAG, ACTION_COLUMN_FLAG].includes(flag!); + if (!customRender && format && !edit && !isDefaultAction) { + column.customRender = ({ text, record, index }) => { + return formatCell(text, format, record, index); + }; + } + + // edit table + if ((edit || editRow) && !isDefaultAction) { + column.customRender = renderEditCell(column); + } + return reactive(column); + }; + + const columns = cloneDeep(viewColumns); + return columns + .filter((column) => hasPermission(column.auth) && isIfShow(column)) + .map((column) => { + // Support table multiple header editable + if (column.children?.length) { + column.children = column.children.map(mapFn); + } + + return mapFn(column); + }); + }); + + watch( + () => unref(propsRef).columns, + (columns) => { + columnsRef.value = columns; + cacheColumns = columns?.filter((item) => !item.flag) ?? []; + }, + ); + + function setCacheColumnsByField(dataIndex: string | undefined, value: Partial) { + if (!dataIndex || !value) { + return; + } + cacheColumns.forEach((item) => { + if (item.dataIndex === dataIndex) { + Object.assign(item, value); + return; + } + }); + } + /** + * set columns + * @param columnList key|column + */ + function setColumns(columnList: Partial[] | (string | string[])[]) { + const columns = cloneDeep(columnList); + if (!isArray(columns)) return; + + if (columns.length <= 0) { + columnsRef.value = []; + return; + } + + const firstColumn = columns[0]; + + const cacheKeys = cacheColumns.map((item) => item.dataIndex); + + if (!isString(firstColumn) && !isArray(firstColumn)) { + columnsRef.value = columns as BasicColumn[]; + } else { + const columnKeys = (columns as (string | string[])[]).map((m) => m.toString()); + const newColumns: BasicColumn[] = []; + cacheColumns.forEach((item) => { + newColumns.push({ + ...item, + defaultHidden: !columnKeys.includes(item.dataIndex?.toString() || (item.key as string)), + }); + }); + // Sort according to another array + if (!isEqual(cacheKeys, columns)) { + newColumns.sort((prev, next) => { + return ( + columnKeys.indexOf(prev.dataIndex?.toString() as string) - + columnKeys.indexOf(next.dataIndex?.toString() as string) + ); + }); + } + columnsRef.value = newColumns; + } + } + + function getColumns(opt?: GetColumnsParams) { + const { ignoreIndex, ignoreAction, sort } = opt || {}; + let columns = toRaw(unref(getColumnsRef)); + if (ignoreIndex) { + columns = columns.filter((item) => item.flag !== INDEX_COLUMN_FLAG); + } + if (ignoreAction) { + columns = columns.filter((item) => item.flag !== ACTION_COLUMN_FLAG); + } + + if (sort) { + columns = sortFixedColumn(columns); + } + + return columns; + } + function getCacheColumns() { + return cacheColumns; + } + function setCacheColumns(columns: BasicColumn[]) { + if (!isArray(columns)) return; + cacheColumns = columns.filter((item) => !item.flag); + } + + return { + getColumnsRef, + getCacheColumns, + getColumns, + setColumns, + getViewColumns, + setCacheColumnsByField, + setCacheColumns, + }; +} + +function sortFixedColumn(columns: BasicColumn[]) { + const fixedLeftColumns: BasicColumn[] = []; + const fixedRightColumns: BasicColumn[] = []; + const defColumns: BasicColumn[] = []; + for (const column of columns) { + if (column.fixed === 'left') { + fixedLeftColumns.push(column); + continue; + } + if (column.fixed === 'right') { + fixedRightColumns.push(column); + continue; + } + defColumns.push(column); + } + return [...fixedLeftColumns, ...defColumns, ...fixedRightColumns].filter( + (item) => !item.defaultHidden, + ); +} + +// format cell +export function formatCell(text: string, format: CellFormat, record: Recordable, index: number) { + if (!format) { + return text; + } + + // custom function + if (isFunction(format)) { + return format(text, record, index); + } + + try { + // date type + const DATE_FORMAT_PREFIX = 'date|'; + if (isString(format) && format.startsWith(DATE_FORMAT_PREFIX) && text) { + const dateFormat = format.replace(DATE_FORMAT_PREFIX, ''); + + if (!dateFormat) { + return text; + } + return formatToDate(text, dateFormat); + } + + // Map + if (isMap(format)) { + return format.get(text); + } + } catch (error) { + return text; + } +} diff --git a/src/components/Table/src/hooks/useCustomRow.ts b/src/components/Table/src/hooks/useCustomRow.ts new file mode 100644 index 0000000..0f7a6ea --- /dev/null +++ b/src/components/Table/src/hooks/useCustomRow.ts @@ -0,0 +1,101 @@ +import type { ComputedRef } from 'vue'; +import type { BasicTableProps } from '../types/table'; +import { unref } from 'vue'; +import { ROW_KEY } from '../const'; +import { isString, isFunction } from '/@/utils/is'; + +interface Options { + setSelectedRowKeys: (keys: string[]) => void; + getSelectRowKeys: () => string[]; + clearSelectedRowKeys: () => void; + emit: EmitType; + getAutoCreateKey: ComputedRef; +} + +function getKey( + record: Recordable, + rowKey: string | ((record: Record) => string) | undefined, + autoCreateKey?: boolean, +) { + if (!rowKey || autoCreateKey) { + return record[ROW_KEY]; + } + if (isString(rowKey)) { + return record[rowKey]; + } + if (isFunction(rowKey)) { + return record[rowKey(record)]; + } + return null; +} + +export function useCustomRow( + propsRef: ComputedRef, + { setSelectedRowKeys, getSelectRowKeys, getAutoCreateKey, clearSelectedRowKeys, emit }: Options, +) { + const customRow = (record: Recordable, index: number) => { + return { + onClick: (e: Event) => { + e?.stopPropagation(); + function handleClick() { + const { rowSelection, rowKey, clickToRowSelect } = unref(propsRef); + if (!rowSelection || !clickToRowSelect) return; + const keys = getSelectRowKeys() || []; + const key = getKey(record, rowKey, unref(getAutoCreateKey)); + if (key === null) return; + + const isCheckbox = rowSelection.type === 'checkbox'; + if (isCheckbox) { + // 找到tr + const tr: HTMLElement = (e as MouseEvent) + .composedPath?.() + .find((dom: HTMLElement) => dom.tagName === 'TR') as HTMLElement; + if (!tr) return; + // 找到Checkbox,检查是否为disabled + const checkBox = tr.querySelector('input[type=checkbox]'); + if (!checkBox || checkBox.hasAttribute('disabled')) return; + if (!keys.includes(key)) { + keys.push(key); + setSelectedRowKeys(keys); + return; + } + const keyIndex = keys.findIndex((item) => item === key); + keys.splice(keyIndex, 1); + setSelectedRowKeys(keys); + return; + } + + const isRadio = rowSelection.type === 'radio'; + if (isRadio) { + if (!keys.includes(key)) { + if (keys.length) { + clearSelectedRowKeys(); + } + setSelectedRowKeys([key]); + return; + } + clearSelectedRowKeys(); + } + } + handleClick(); + emit('row-click', record, index, e); + }, + onDblclick: (event: Event) => { + emit('row-dbClick', record, index, event); + }, + onContextmenu: (event: Event) => { + emit('row-contextmenu', record, index, event); + }, + onMouseenter: (event: Event) => { + emit('row-mouseenter', record, index, event); + }, + onMouseleave: (event: Event) => { + emit('row-mouseleave', record, index, event); + }, + }; + }; + + return { + customRow, + }; +} diff --git a/src/components/Table/src/hooks/useDataSource.ts b/src/components/Table/src/hooks/useDataSource.ts new file mode 100644 index 0000000..d748ac1 --- /dev/null +++ b/src/components/Table/src/hooks/useDataSource.ts @@ -0,0 +1,409 @@ +import type { BasicTableProps, FetchParams, SorterResult } from '../types/table'; +import type { PaginationProps } from '../types/pagination'; +import { + ref, + unref, + ComputedRef, + computed, + onMounted, + watch, + reactive, + Ref, + watchEffect, +} from 'vue'; +import { useTimeoutFn } from '@vben/hooks'; +import { buildUUID } from '/@/utils/uuid'; +import { isFunction, isBoolean, isObject } from '/@/utils/is'; +import { get, cloneDeep, merge } from 'lodash-es'; +import { FETCH_SETTING, ROW_KEY, PAGE_SIZE } from '../const'; +import { array2tree } from '@axolo/tree-array'; + +interface ActionType { + getPaginationInfo: ComputedRef; + setPagination: (info: Partial) => void; + setLoading: (loading: boolean) => void; + getFieldsValue: () => Recordable; + clearSelectedRowKeys: () => void; + tableData: Ref; +} + +interface SearchState { + sortInfo: Recordable; + filterInfo: Record; +} +export function useDataSource( + propsRef: ComputedRef, + { + getPaginationInfo, + setPagination, + setLoading, + getFieldsValue, + clearSelectedRowKeys, + tableData, + }: ActionType, + emit: EmitType, +) { + const searchState = reactive({ + sortInfo: {}, + filterInfo: {}, + }); + const dataSourceRef = ref([]); + const rawDataSourceRef = ref({}); + + watchEffect(() => { + tableData.value = unref(dataSourceRef); + }); + + watch( + () => unref(propsRef).dataSource, + () => { + const { dataSource, api } = unref(propsRef); + !api && dataSource && (dataSourceRef.value = dataSource); + }, + { + immediate: true, + }, + ); + + function handleTableChange( + pagination: PaginationProps, + filters: Partial>, + sorter: SorterResult, + ) { + const { clearSelectOnPageChange, sortFn, filterFn } = unref(propsRef); + if (clearSelectOnPageChange) { + clearSelectedRowKeys(); + } + setPagination(pagination); + + const params: Recordable = {}; + if (sorter && isFunction(sortFn)) { + const sortInfo = sortFn(sorter); + searchState.sortInfo = sortInfo; + params.sortInfo = sortInfo; + } + + if (filters && isFunction(filterFn)) { + const filterInfo = filterFn(filters); + searchState.filterInfo = filterInfo; + params.filterInfo = filterInfo; + } + fetch(params); + } + + function setTableKey(items: any[]) { + if (!items || !Array.isArray(items)) return; + items.forEach((item) => { + if (!item[ROW_KEY]) { + item[ROW_KEY] = buildUUID(); + } + if (item.children && item.children.length) { + setTableKey(item.children); + } + }); + } + + const getAutoCreateKey = computed(() => { + return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey; + }); + + const getRowKey = computed(() => { + const { rowKey } = unref(propsRef); + return unref(getAutoCreateKey) ? ROW_KEY : rowKey; + }); + + const getDataSourceRef = computed(() => { + const dataSource = unref(dataSourceRef); + if (!dataSource || dataSource.length === 0) { + return unref(dataSourceRef); + } + if (unref(getAutoCreateKey)) { + const firstItem = dataSource[0]; + const lastItem = dataSource[dataSource.length - 1]; + + if (firstItem && lastItem) { + if (!firstItem[ROW_KEY] || !lastItem[ROW_KEY]) { + const data = cloneDeep(unref(dataSourceRef)); + data.forEach((item) => { + if (!item[ROW_KEY]) { + item[ROW_KEY] = buildUUID(); + } + if (item.children && item.children.length) { + setTableKey(item.children); + } + }); + dataSourceRef.value = data; + } + } + } + return unref(dataSourceRef); + }); + + async function updateTableData(index: number, key: string, value: any) { + const record = dataSourceRef.value[index]; + if (record) { + dataSourceRef.value[index][key] = value; + } + return dataSourceRef.value[index]; + } + + function updateTableDataRecord( + rowKey: string | number, + record: Recordable, + ): Recordable | undefined { + const row = findTableDataRecord(rowKey); + + if (row) { + for (const field in row) { + if (Reflect.has(record, field)) row[field] = record[field]; + } + return row; + } + } + + function deleteTableDataRecord(rowKey: string | number | string[] | number[]) { + if (!dataSourceRef.value || dataSourceRef.value.length == 0) return; + const rowKeyName = unref(getRowKey); + if (!rowKeyName) return; + const rowKeys = !Array.isArray(rowKey) ? [rowKey] : rowKey; + + function deleteRow(data, key) { + const row: { index: number; data: [] } = findRow(data, key); + if (row === null || row.index === -1) { + return; + } + row.data.splice(row.index, 1); + + function findRow(data, key) { + if (data === null || data === undefined) { + return null; + } + for (let i = 0; i < data.length; i++) { + const row = data[i]; + let targetKeyName: string = rowKeyName as string; + if (isFunction(rowKeyName)) { + targetKeyName = rowKeyName(row); + } + if (row[targetKeyName] === key) { + return { index: i, data }; + } + if (row.children?.length > 0) { + const result = findRow(row.children, key); + if (result != null) { + return result; + } + } + } + return null; + } + } + + for (const key of rowKeys) { + deleteRow(dataSourceRef.value, key); + deleteRow(unref(propsRef).dataSource, key); + } + setPagination({ + total: unref(propsRef).dataSource?.length, + }); + } + + function insertTableDataRecord( + record: Recordable | Recordable[], + index?: number, + ): Recordable[] | undefined { + // if (!dataSourceRef.value || dataSourceRef.value.length == 0) return; + index = index ?? dataSourceRef.value?.length; + const _record = isObject(record) ? [record as Recordable] : (record as Recordable[]); + unref(dataSourceRef).splice(index, 0, ..._record); + return unref(dataSourceRef); + } + + function findTableDataRecord(rowKey: string | number) { + if (!dataSourceRef.value || dataSourceRef.value.length == 0) return; + + const rowKeyName = unref(getRowKey); + if (!rowKeyName) return; + + const { childrenColumnName = 'children' } = unref(propsRef); + + const findRow = (array: any[]) => { + let ret; + array.some(function iter(r) { + if (typeof rowKeyName === 'function') { + if ((rowKeyName(r) as string) === rowKey) { + ret = r; + return true; + } + } else { + if (Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey) { + ret = r; + return true; + } + } + return r[childrenColumnName] && r[childrenColumnName].some(iter); + }); + return ret; + }; + + // const row = dataSourceRef.value.find(r => { + // if (typeof rowKeyName === 'function') { + // return (rowKeyName(r) as string) === rowKey + // } else { + // return Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey + // } + // }) + return findRow(dataSourceRef.value); + } + + async function fetch(opt?: FetchParams) { + const { + api, + searchInfo, + defSort, + fetchSetting, + beforeFetch, + afterFetch, + useSearchForm, + pagination, + isTreeTable, + } = unref(propsRef); + if (!api || !isFunction(api)) return; + try { + setLoading(true); + const { pageField, sizeField, listField, totalField } = Object.assign( + {}, + FETCH_SETTING, + fetchSetting, + ); + let pageParams: Recordable = {}; + + const { current = 1, pageSize = PAGE_SIZE } = unref(getPaginationInfo) as PaginationProps; + + if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) { + pageParams = {}; + } else { + pageParams[pageField] = (opt && opt.page) || current; + pageParams[sizeField] = pageSize; + } + + const { sortInfo = {}, filterInfo } = searchState; + + let params: Recordable = merge( + pageParams, + useSearchForm ? getFieldsValue() : {}, + searchInfo, + opt?.searchInfo ?? {}, + defSort, + sortInfo, + filterInfo, + opt?.sortInfo ?? {}, + opt?.filterInfo ?? {}, + ); + if (beforeFetch && isFunction(beforeFetch)) { + params = (await beforeFetch(params)) || params; + } + + let isArrayResult: boolean; + let resultItems: Recordable[]; + let resultTotal: number; + + const result = await api(params); + const res = result.data; + if (isTreeTable) { + if(res.data){ + const tree = array2tree(res.data); + rawDataSourceRef.value = tree; + isArrayResult = Array.isArray(tree); + resultItems = isArrayResult ? tree : get(tree, listField); + resultTotal = isArrayResult ? tree.length : get(tree, totalField); + }else { + const tree = array2tree(res); + rawDataSourceRef.value = array2tree(res); + isArrayResult = Array.isArray(tree); + resultItems = isArrayResult ? tree : get(tree, listField); + resultTotal = isArrayResult ? tree.length : get(tree, totalField); + } + } else { + rawDataSourceRef.value = res; + isArrayResult = Array.isArray(res); + resultItems = isArrayResult ? res : get(res, listField); + resultTotal = isArrayResult ? res.length : get(res, totalField); + } + // 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行 + if (Number(resultTotal)) { + const currentTotalPage = Math.ceil(resultTotal / pageSize); + if (current > currentTotalPage) { + setPagination({ + current: currentTotalPage, + }); + return await fetch(opt); + } + } + + if (afterFetch && isFunction(afterFetch)) { + resultItems = (await afterFetch(resultItems)) || resultItems; + } + dataSourceRef.value = resultItems; + setPagination({ + total: resultTotal || 0, + }); + if (opt && opt.page) { + setPagination({ + current: opt.page || 1, + }); + } + emit('fetch-success', { + items: unref(resultItems), + total: resultTotal, + }); + return resultItems; + } catch (error) { + emit('fetch-error', error); + dataSourceRef.value = []; + setPagination({ + total: 0, + }); + } finally { + setLoading(false); + } + } + + function setTableData(values: T[]) { + dataSourceRef.value = values as Recordable[]; + } + + function getDataSource() { + return getDataSourceRef.value as T[]; + } + + function getRawDataSource() { + return rawDataSourceRef.value as T; + } + + async function reload(opt?: FetchParams) { + return await fetch(opt); + } + + onMounted(() => { + useTimeoutFn(() => { + unref(propsRef).immediate && fetch(); + }, 16); + }); + + return { + getDataSourceRef, + getDataSource, + getRawDataSource, + getRowKey, + setTableData, + getAutoCreateKey, + fetch, + reload, + updateTableData, + updateTableDataRecord, + deleteTableDataRecord, + insertTableDataRecord, + findTableDataRecord, + handleTableChange, + }; +} diff --git a/src/components/Table/src/hooks/useLoading.ts b/src/components/Table/src/hooks/useLoading.ts new file mode 100644 index 0000000..fe8a0f1 --- /dev/null +++ b/src/components/Table/src/hooks/useLoading.ts @@ -0,0 +1,21 @@ +import { ref, ComputedRef, unref, computed, watch } from 'vue'; +import type { BasicTableProps } from '../types/table'; + +export function useLoading(props: ComputedRef) { + const loadingRef = ref(unref(props).loading); + + watch( + () => unref(props).loading, + (loading) => { + loadingRef.value = loading; + }, + ); + + const getLoading = computed(() => unref(loadingRef)); + + function setLoading(loading: boolean) { + loadingRef.value = loading; + } + + return { getLoading, setLoading }; +} diff --git a/src/components/Table/src/hooks/usePagination.tsx b/src/components/Table/src/hooks/usePagination.tsx new file mode 100644 index 0000000..ba310bd --- /dev/null +++ b/src/components/Table/src/hooks/usePagination.tsx @@ -0,0 +1,85 @@ +import type { PaginationProps } from '../types/pagination'; +import type { BasicTableProps } from '../types/table'; +import { computed, unref, ref, ComputedRef, watch } from 'vue'; +import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue'; +import { isBoolean } from '/@/utils/is'; +import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../const'; +import { useI18n } from '/@/hooks/web/useI18n'; + +interface ItemRender { + page: number; + type: 'page' | 'prev' | 'next'; + originalElement: any; +} + +function itemRender({ page, type, originalElement }: ItemRender) { + if (type === 'prev') { + return page === 0 ? null : ; + } else if (type === 'next') { + return page === 1 ? null : ; + } + return originalElement; +} + +export function usePagination(refProps: ComputedRef) { + const { t } = useI18n(); + + const configRef = ref({}); + const show = ref(true); + + watch( + () => unref(refProps).pagination, + (pagination) => { + if (!isBoolean(pagination) && pagination) { + configRef.value = { + ...unref(configRef), + ...(pagination ?? {}), + }; + } + }, + ); + + const getPaginationInfo = computed((): PaginationProps | boolean => { + const { pagination } = unref(refProps); + + if (!unref(show) || (isBoolean(pagination) && !pagination)) { + return false; + } + + return { + current: 1, + pageSize: PAGE_SIZE, + size: 'small', + defaultPageSize: PAGE_SIZE, + showTotal: (total) => t('component.table.total', { total }), + showSizeChanger: true, + pageSizeOptions: PAGE_SIZE_OPTIONS, + itemRender: itemRender, + showQuickJumper: true, + ...(isBoolean(pagination) ? {} : pagination), + ...unref(configRef), + }; + }); + + function setPagination(info: Partial) { + const paginationInfo = unref(getPaginationInfo); + configRef.value = { + ...(!isBoolean(paginationInfo) ? paginationInfo : {}), + ...info, + }; + } + + function getPagination() { + return unref(getPaginationInfo); + } + + function getShowPagination() { + return unref(show); + } + + async function setShowPagination(flag: boolean) { + show.value = flag; + } + + return { getPagination, getPaginationInfo, setShowPagination, getShowPagination, setPagination }; +} diff --git a/src/components/Table/src/hooks/useRowSelection.ts b/src/components/Table/src/hooks/useRowSelection.ts new file mode 100644 index 0000000..e87c3df --- /dev/null +++ b/src/components/Table/src/hooks/useRowSelection.ts @@ -0,0 +1,123 @@ +import { isFunction } from '/@/utils/is'; +import type { BasicTableProps, TableRowSelection } from '../types/table'; +import { computed, ComputedRef, nextTick, Ref, ref, toRaw, unref, watch } from 'vue'; +import { ROW_KEY } from '../const'; +import { omit } from 'lodash-es'; +import { findNodeAll } from '/@/utils/helper/treeHelper'; +import type { Key } from 'ant-design-vue/lib/table/interface'; + +export function useRowSelection( + propsRef: ComputedRef, + tableData: Ref, + emit: EmitType, +) { + const selectedRowKeysRef = ref([]); + const selectedRowRef = ref([]); + + const getRowSelectionRef = computed((): TableRowSelection | null => { + const { rowSelection } = unref(propsRef); + if (!rowSelection) { + return null; + } + + return { + selectedRowKeys: unref(selectedRowKeysRef), + onChange: (selectedRowKeys: Key[]) => { + setSelectedRowKeys(selectedRowKeys); + }, + ...omit(rowSelection, ['onChange']), + }; + }); + + watch( + () => unref(propsRef).rowSelection?.selectedRowKeys, + (v?: Key[]) => { + setSelectedRowKeys(v); + }, + ); + + watch( + () => unref(selectedRowKeysRef), + () => { + nextTick(() => { + const { rowSelection } = unref(propsRef); + if (rowSelection) { + const { onChange } = rowSelection; + if (onChange && isFunction(onChange)) onChange(getSelectRowKeys(), getSelectRows()); + } + emit('selection-change', { + keys: getSelectRowKeys(), + rows: getSelectRows(), + }); + }); + }, + { deep: true }, + ); + + const getAutoCreateKey = computed(() => { + return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey; + }); + + const getRowKey = computed(() => { + const { rowKey } = unref(propsRef); + return unref(getAutoCreateKey) ? ROW_KEY : rowKey; + }); + + function setSelectedRowKeys(rowKeys?: Key[]) { + selectedRowKeysRef.value = rowKeys || []; + const allSelectedRows = findNodeAll( + toRaw(unref(tableData)).concat(toRaw(unref(selectedRowRef))), + (item) => rowKeys?.includes(item[unref(getRowKey) as string]), + { + children: propsRef.value.childrenColumnName ?? 'children', + }, + ); + const trueSelectedRows: any[] = []; + rowKeys?.forEach((key: Key) => { + const found = allSelectedRows.find((item) => item[unref(getRowKey) as string] === key); + found && trueSelectedRows.push(found); + }); + selectedRowRef.value = trueSelectedRows; + } + + function setSelectedRows(rows: Recordable[]) { + selectedRowRef.value = rows; + } + + function clearSelectedRowKeys() { + selectedRowRef.value = []; + selectedRowKeysRef.value = []; + } + + function deleteSelectRowByKey(key: string) { + const selectedRowKeys = unref(selectedRowKeysRef); + const index = selectedRowKeys.findIndex((item) => item === key); + if (index !== -1) { + unref(selectedRowKeysRef).splice(index, 1); + } + } + + function getSelectRowKeys() { + return unref(selectedRowKeysRef); + } + + function getSelectRows() { + // const ret = toRaw(unref(selectedRowRef)).map((item) => toRaw(item)); + return unref(selectedRowRef) as T[]; + } + + function getRowSelection() { + return unref(getRowSelectionRef)!; + } + + return { + getRowSelection, + getRowSelectionRef, + getSelectRows, + getSelectRowKeys, + setSelectedRowKeys, + clearSelectedRowKeys, + deleteSelectRowByKey, + setSelectedRows, + }; +} diff --git a/src/components/Table/src/hooks/useScrollTo.ts b/src/components/Table/src/hooks/useScrollTo.ts new file mode 100644 index 0000000..b368f81 --- /dev/null +++ b/src/components/Table/src/hooks/useScrollTo.ts @@ -0,0 +1,55 @@ +import type { ComputedRef, Ref } from 'vue'; +import { nextTick, unref } from 'vue'; +import { warn } from '/@/utils/log'; + +export function useTableScrollTo( + tableElRef: Ref, + getDataSourceRef: ComputedRef, +) { + let bodyEl: HTMLElement | null; + + async function findTargetRowToScroll(targetRowData: Recordable) { + const { id } = targetRowData; + const targetRowEl: HTMLElement | null | undefined = bodyEl?.querySelector( + `[data-row-key="${id}"]`, + ); + //Add a delay to get new dataSource + await nextTick(); + bodyEl?.scrollTo({ + top: targetRowEl?.offsetTop ?? 0, + behavior: 'smooth', + }); + } + + function scrollTo(pos: string): void { + const table = unref(tableElRef); + if (!table) return; + + const tableEl: Element = table.$el; + if (!tableEl) return; + + if (!bodyEl) { + bodyEl = tableEl.querySelector('.ant-table-body'); + if (!bodyEl) return; + } + + const dataSource = unref(getDataSourceRef); + if (!dataSource) return; + + // judge pos type + if (pos === 'top') { + findTargetRowToScroll(dataSource[0]); + } else if (pos === 'bottom') { + findTargetRowToScroll(dataSource[dataSource.length - 1]); + } else { + const targetRowData = dataSource.find((data) => data.id === pos); + if (targetRowData) { + findTargetRowToScroll(targetRowData); + } else { + warn(`id: ${pos} doesn't exist`); + } + } + } + + return { scrollTo }; +} diff --git a/src/components/Table/src/hooks/useTable.ts b/src/components/Table/src/hooks/useTable.ts new file mode 100644 index 0000000..f7f29df --- /dev/null +++ b/src/components/Table/src/hooks/useTable.ts @@ -0,0 +1,171 @@ +import type { BasicTableProps, TableActionType, FetchParams, BasicColumn } from '../types/table'; +import type { PaginationProps } from '../types/pagination'; +import type { DynamicProps } from '/#/utils'; +import type { FormActionType } from '/@/components/Form'; +import type { WatchStopHandle } from 'vue'; +import { getDynamicProps } from '/@/utils'; +import { ref, onUnmounted, unref, watch, toRaw } from 'vue'; +import { isProdMode } from '/@/utils/env'; +import { error } from '/@/utils/log'; +import type { Key } from 'ant-design-vue/lib/table/interface'; + +type Props = Partial>; + +type UseTableMethod = TableActionType & { + getForm: () => FormActionType; +}; + +export function useTable(tableProps?: Props): [ + (instance: TableActionType, formInstance: UseTableMethod) => void, + TableActionType & { + getForm: () => FormActionType; + }, +] { + const tableRef = ref>(null); + const loadedRef = ref>(false); + const formRef = ref>(null); + + let stopWatch: WatchStopHandle; + + function register(instance: TableActionType, formInstance: UseTableMethod) { + isProdMode() && + onUnmounted(() => { + tableRef.value = null; + loadedRef.value = null; + }); + + if (unref(loadedRef) && isProdMode() && instance === unref(tableRef)) return; + + tableRef.value = instance; + formRef.value = formInstance; + tableProps && instance.setProps(getDynamicProps(tableProps)); + loadedRef.value = true; + + stopWatch?.(); + + stopWatch = watch( + () => tableProps, + () => { + tableProps && instance.setProps(getDynamicProps(tableProps)); + }, + { + immediate: true, + deep: true, + }, + ); + } + + function getTableInstance(): TableActionType { + const table = unref(tableRef); + if (!table) { + error( + 'The table instance has not been obtained yet, please make sure the table is presented when performing the table operation!', + ); + } + return table as TableActionType; + } + + const methods: TableActionType & { + getForm: () => FormActionType; + } = { + reload: async (opt?: FetchParams) => { + return await getTableInstance().reload(opt); + }, + setProps: (props: Partial) => { + getTableInstance().setProps(props); + }, + redoHeight: () => { + getTableInstance().redoHeight(); + }, + setSelectedRows: (rows: Recordable[]) => { + return toRaw(getTableInstance().setSelectedRows(rows)); + }, + setLoading: (loading: boolean) => { + getTableInstance().setLoading(loading); + }, + getDataSource: () => { + return getTableInstance().getDataSource(); + }, + getRawDataSource: () => { + return getTableInstance().getRawDataSource(); + }, + getColumns: ({ ignoreIndex = false }: { ignoreIndex?: boolean } = {}) => { + const columns = getTableInstance().getColumns({ ignoreIndex }) || []; + return toRaw(columns); + }, + setColumns: (columns: BasicColumn[] | string[]) => { + getTableInstance().setColumns(columns); + }, + setTableData: (values: any[]) => { + return getTableInstance().setTableData(values); + }, + setPagination: (info: Partial) => { + return getTableInstance().setPagination(info); + }, + deleteSelectRowByKey: (key: string) => { + getTableInstance().deleteSelectRowByKey(key); + }, + getSelectRowKeys: () => { + return toRaw(getTableInstance().getSelectRowKeys()); + }, + getSelectRows: () => { + return toRaw(getTableInstance().getSelectRows()); + }, + clearSelectedRowKeys: () => { + getTableInstance().clearSelectedRowKeys(); + }, + setSelectedRowKeys: (keys: (string | number)[]) => { + getTableInstance().setSelectedRowKeys(keys); + }, + getPaginationRef: () => { + return getTableInstance().getPaginationRef(); + }, + getSize: () => { + return toRaw(getTableInstance().getSize()); + }, + updateTableData: (index: number, key: string, value: any) => { + return getTableInstance().updateTableData(index, key, value); + }, + deleteTableDataRecord: (rowKey: string | number | string[] | number[]) => { + return getTableInstance().deleteTableDataRecord(rowKey); + }, + insertTableDataRecord: (record: Recordable | Recordable[], index?: number) => { + return getTableInstance().insertTableDataRecord(record, index); + }, + updateTableDataRecord: (rowKey: string | number, record: Recordable) => { + return getTableInstance().updateTableDataRecord(rowKey, record); + }, + findTableDataRecord: (rowKey: string | number) => { + return getTableInstance().findTableDataRecord(rowKey); + }, + getRowSelection: () => { + return toRaw(getTableInstance().getRowSelection()); + }, + getCacheColumns: () => { + return toRaw(getTableInstance().getCacheColumns()); + }, + getForm: () => { + return unref(formRef) as unknown as FormActionType; + }, + setShowPagination: async (show: boolean) => { + getTableInstance().setShowPagination(show); + }, + getShowPagination: () => { + return toRaw(getTableInstance().getShowPagination()); + }, + expandAll: () => { + getTableInstance().expandAll(); + }, + expandRows: (keys: Key[]) => { + getTableInstance().expandRows(keys); + }, + collapseAll: () => { + getTableInstance().collapseAll(); + }, + scrollTo: (pos: string) => { + getTableInstance().scrollTo(pos); + }, + }; + + return [register, methods]; +} diff --git a/src/components/Table/src/hooks/useTableContext.ts b/src/components/Table/src/hooks/useTableContext.ts new file mode 100644 index 0000000..b657bb2 --- /dev/null +++ b/src/components/Table/src/hooks/useTableContext.ts @@ -0,0 +1,22 @@ +import type { Ref } from 'vue'; +import type { BasicTableProps, TableActionType } from '../types/table'; +import { provide, inject, ComputedRef } from 'vue'; + +const key = Symbol('basic-table'); + +type Instance = TableActionType & { + wrapRef: Ref>; + getBindValues: ComputedRef; +}; + +type RetInstance = Omit & { + getBindValues: ComputedRef; +}; + +export function createTableContext(instance: Instance) { + provide(key, instance); +} + +export function useTableContext(): RetInstance { + return inject(key) as RetInstance; +} diff --git a/src/components/Table/src/hooks/useTableExpand.ts b/src/components/Table/src/hooks/useTableExpand.ts new file mode 100644 index 0000000..49fd2d9 --- /dev/null +++ b/src/components/Table/src/hooks/useTableExpand.ts @@ -0,0 +1,65 @@ +import type { ComputedRef, Ref } from 'vue'; +import type { BasicTableProps } from '../types/table'; +import { computed, unref, ref, toRaw } from 'vue'; +import { ROW_KEY } from '../const'; + +export function useTableExpand( + propsRef: ComputedRef, + tableData: Ref, + emit: EmitType, +) { + const expandedRowKeys = ref<(string | number)[]>([]); + + const getAutoCreateKey = computed(() => { + return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey; + }); + + const getRowKey = computed(() => { + const { rowKey } = unref(propsRef); + return unref(getAutoCreateKey) ? ROW_KEY : rowKey; + }); + + const getExpandOption = computed(() => { + const { isTreeTable } = unref(propsRef); + if (!isTreeTable) return {}; + + return { + expandedRowKeys: unref(expandedRowKeys), + onExpandedRowsChange: (keys: string[]) => { + expandedRowKeys.value = keys; + emit('expanded-rows-change', keys); + }, + }; + }); + + function expandAll() { + const keys = getAllKeys(); + expandedRowKeys.value = keys; + } + + function expandRows(keys: (string | number)[]) { + // use row ID expands the specified table row + const { isTreeTable } = unref(propsRef); + if (!isTreeTable) return; + expandedRowKeys.value = [...expandedRowKeys.value, ...keys]; + } + + function getAllKeys(data?: Recordable[]) { + const keys: string[] = []; + const { childrenColumnName } = unref(propsRef); + toRaw(data || unref(tableData)).forEach((item) => { + keys.push(item[unref(getRowKey) as string]); + const children = item[childrenColumnName || 'children']; + if (children?.length) { + keys.push(...getAllKeys(children)); + } + }); + return keys; + } + + function collapseAll() { + expandedRowKeys.value = []; + } + + return { getExpandOption, expandAll, expandRows, collapseAll }; +} diff --git a/src/components/Table/src/hooks/useTableFooter.ts b/src/components/Table/src/hooks/useTableFooter.ts new file mode 100644 index 0000000..6a3aa58 --- /dev/null +++ b/src/components/Table/src/hooks/useTableFooter.ts @@ -0,0 +1,56 @@ +import type { ComputedRef, Ref } from 'vue'; +import type { BasicTableProps } from '../types/table'; +import { unref, computed, h, nextTick, watchEffect } from 'vue'; +import TableFooter from '../components/TableFooter.vue'; +import { useEventListener } from '/@/hooks/event/useEventListener'; + +export function useTableFooter( + propsRef: ComputedRef, + scrollRef: ComputedRef<{ + x: string | number | true; + y: string | number | null; + scrollToFirstRowOnChange: boolean; + }>, + tableElRef: Ref, + getDataSourceRef: ComputedRef, +) { + const getIsEmptyData = computed(() => { + return (unref(getDataSourceRef) || []).length === 0; + }); + + const getFooterProps = computed((): Recordable | undefined => { + const { summaryFunc, showSummary, summaryData } = unref(propsRef); + return showSummary && !unref(getIsEmptyData) + ? () => h(TableFooter, { summaryFunc, summaryData, scroll: unref(scrollRef) }) + : undefined; + }); + + watchEffect(() => { + handleSummary(); + }); + + function handleSummary() { + const { showSummary } = unref(propsRef); + if (!showSummary || unref(getIsEmptyData)) return; + + nextTick(() => { + const tableEl = unref(tableElRef); + if (!tableEl) return; + const bodyDom = tableEl.$el.querySelector('.ant-table-content'); + useEventListener({ + el: bodyDom, + name: 'scroll', + listener: () => { + const footerBodyDom = tableEl.$el.querySelector( + '.ant-table-footer .ant-table-content', + ) as HTMLDivElement; + if (!footerBodyDom || !bodyDom) return; + footerBodyDom.scrollLeft = bodyDom.scrollLeft; + }, + wait: 0, + options: true, + }); + }); + } + return { getFooterProps }; +} diff --git a/src/components/Table/src/hooks/useTableForm.ts b/src/components/Table/src/hooks/useTableForm.ts new file mode 100644 index 0000000..9d5712d --- /dev/null +++ b/src/components/Table/src/hooks/useTableForm.ts @@ -0,0 +1,50 @@ +import type { ComputedRef, Slots } from 'vue'; +import type { BasicTableProps, FetchParams } from '../types/table'; +import { unref, computed } from 'vue'; +import type { FormProps } from '/@/components/Form'; +import { isFunction } from '/@/utils/is'; + +export function useTableForm( + propsRef: ComputedRef, + slots: Slots, + fetch: (opt?: FetchParams | undefined) => Promise, + getLoading: ComputedRef, +) { + const getFormProps = computed((): Partial => { + const { formConfig } = unref(propsRef); + const { submitButtonOptions } = formConfig || {}; + return { + showAdvancedButton: true, + ...formConfig, + submitButtonOptions: { loading: unref(getLoading), ...submitButtonOptions }, + compact: true, + }; + }); + + const getFormSlotKeys: ComputedRef = computed(() => { + const keys = Object.keys(slots); + return keys + .map((item) => (item.startsWith('form-') ? item : null)) + .filter((item) => !!item) as string[]; + }); + + function replaceFormSlotKey(key: string) { + if (!key) return ''; + return key?.replace?.(/form-/, '') ?? ''; + } + + function handleSearchInfoChange(info: Recordable) { + const { handleSearchInfoFn } = unref(propsRef); + if (handleSearchInfoFn && isFunction(handleSearchInfoFn)) { + info = handleSearchInfoFn(info) || info; + } + fetch({ searchInfo: info, page: 1 }); + } + + return { + getFormProps, + replaceFormSlotKey, + getFormSlotKeys, + handleSearchInfoChange, + }; +} diff --git a/src/components/Table/src/hooks/useTableHeader.ts b/src/components/Table/src/hooks/useTableHeader.ts new file mode 100644 index 0000000..e728207 --- /dev/null +++ b/src/components/Table/src/hooks/useTableHeader.ts @@ -0,0 +1,54 @@ +import type { ComputedRef, Slots } from 'vue'; +import type { BasicTableProps, InnerHandlers } from '../types/table'; +import { unref, computed, h } from 'vue'; +import TableHeader from '../components/TableHeader.vue'; +import { isString } from '/@/utils/is'; +import { getSlot } from '/@/utils/helper/tsxHelper'; + +export function useTableHeader( + propsRef: ComputedRef, + slots: Slots, + handlers: InnerHandlers, +) { + const getHeaderProps = computed((): Recordable => { + const { title, showTableSetting, titleHelpMessage, tableSetting } = unref(propsRef); + const hideTitle = !slots.tableTitle && !title && !slots.toolbar && !showTableSetting; + if (hideTitle && !isString(title)) { + return {}; + } + + return { + title: hideTitle + ? null + : () => + h( + TableHeader, + { + title, + titleHelpMessage, + showTableSetting, + tableSetting, + onColumnsChange: handlers.onColumnsChange, + } as Recordable, + { + ...(slots.toolbar + ? { + toolbar: () => getSlot(slots, 'toolbar'), + } + : {}), + ...(slots.tableTitle + ? { + tableTitle: () => getSlot(slots, 'tableTitle'), + } + : {}), + ...(slots.headerTop + ? { + headerTop: () => getSlot(slots, 'headerTop'), + } + : {}), + }, + ), + }; + }); + return { getHeaderProps }; +} diff --git a/src/components/Table/src/hooks/useTableScroll.ts b/src/components/Table/src/hooks/useTableScroll.ts new file mode 100644 index 0000000..95f3a91 --- /dev/null +++ b/src/components/Table/src/hooks/useTableScroll.ts @@ -0,0 +1,245 @@ +import type { BasicTableProps, TableRowSelection, BasicColumn } from '../types/table'; +import { Ref, ComputedRef, ref, computed, unref, nextTick, watch } from 'vue'; +import { getViewportOffset } from '/@/utils/domUtils'; +import { isBoolean } from '/@/utils/is'; +import { useWindowSizeFn, onMountedOrActivated } from '@vben/hooks'; +import { useModalContext } from '/@/components/Modal'; +import { useDebounceFn } from '@vueuse/core'; + +export function useTableScroll( + propsRef: ComputedRef, + tableElRef: Ref, + columnsRef: ComputedRef, + rowSelectionRef: ComputedRef, + getDataSourceRef: ComputedRef, + wrapRef: Ref, + formRef: Ref, +) { + const tableHeightRef: Ref> = ref(167); + const modalFn = useModalContext(); + + // Greater than animation time 280 + const debounceRedoHeight = useDebounceFn(redoHeight, 100); + + const getCanResize = computed(() => { + const { canResize, scroll } = unref(propsRef); + return canResize && !(scroll || {}).y; + }); + + watch( + () => [unref(getCanResize), unref(getDataSourceRef)?.length], + () => { + debounceRedoHeight(); + }, + { + flush: 'post', + }, + ); + + function redoHeight() { + nextTick(() => { + calcTableHeight(); + }); + } + + function setHeight(height: number) { + tableHeightRef.value = height; + // Solve the problem of modal adaptive height calculation when the form is placed in the modal + modalFn?.redoModalHeight?.(); + } + + // No need to repeat queries + let paginationEl: HTMLElement | null; + let footerEl: HTMLElement | null; + let bodyEl: HTMLElement | null; + + function handleScrollBar(bodyEl: HTMLElement, tableEl: Element) { + const hasScrollBarY = bodyEl.scrollHeight > bodyEl.clientHeight; + const hasScrollBarX = bodyEl.scrollWidth > bodyEl.clientWidth; + + if (hasScrollBarY) { + tableEl.classList.contains('hide-scrollbar-y') && + tableEl.classList.remove('hide-scrollbar-y'); + } else { + !tableEl.classList.contains('hide-scrollbar-y') && tableEl.classList.add('hide-scrollbar-y'); + } + + if (hasScrollBarX) { + tableEl.classList.contains('hide-scrollbar-x') && + tableEl.classList.remove('hide-scrollbar-x'); + } else { + !tableEl.classList.contains('hide-scrollbar-x') && tableEl.classList.add('hide-scrollbar-x'); + } + } + + function caclPaginationHeight(tableEl: Element): number { + const { pagination } = unref(propsRef); + // Pager height + let paginationHeight = 2; + if (!isBoolean(pagination)) { + paginationEl = tableEl.querySelector('.ant-pagination') as HTMLElement; + if (paginationEl) { + const offsetHeight = paginationEl.offsetHeight; + paginationHeight += offsetHeight || 0; + } else { + // TODO First fix 24 + paginationHeight += 24; + } + } else { + paginationHeight = -8; + } + return paginationHeight; + } + + function caclFooterHeight(tableEl: Element): number { + const { pagination } = unref(propsRef); + let footerHeight = 0; + if (!isBoolean(pagination)) { + if (!footerEl) { + footerEl = tableEl.querySelector('.ant-table-footer') as HTMLElement; + } else { + const offsetHeight = footerEl.offsetHeight; + footerHeight += offsetHeight || 0; + } + } + return footerHeight; + } + + function calcHeaderHeight(headEl: Element): number { + let headerHeight = 0; + if (headEl) { + headerHeight = (headEl as HTMLElement).offsetHeight; + } + return headerHeight; + } + + function calcBottomAndPaddingHeight(tableEl: Element, headEl: Element) { + const { pagination, isCanResizeParent, useSearchForm } = unref(propsRef); + // Table height from bottom height-custom offset + let paddingHeight = 30; + let bottomIncludeBody = 0; + if (unref(wrapRef) && isCanResizeParent) { + const tablePadding = 12; + const formMargin = 16; + let paginationMargin = 10; + const wrapHeight = unref(wrapRef)?.offsetHeight ?? 0; + + let formHeight = unref(formRef)?.$el.offsetHeight ?? 0; + if (formHeight) { + formHeight += formMargin; + } + if (isBoolean(pagination) && !pagination) { + paginationMargin = 0; + } + if (isBoolean(useSearchForm) && !useSearchForm) { + paddingHeight = 0; + } + + const headerCellHeight = + (tableEl.querySelector('.ant-table-title') as HTMLElement)?.offsetHeight ?? 0; + + console.log(wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin); + bottomIncludeBody = + wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin; + } else { + // Table height from bottom + bottomIncludeBody = getViewportOffset(headEl).bottomIncludeBody; + } + + return { + paddingHeight, + bottomIncludeBody, + }; + } + + async function calcTableHeight() { + const { resizeHeightOffset, maxHeight } = unref(propsRef); + const tableData = unref(getDataSourceRef); + + const table = unref(tableElRef); + if (!table) return; + + const tableEl: Element = table.$el; + if (!tableEl) return; + + if (!bodyEl) { + bodyEl = tableEl.querySelector('.ant-table-body'); + if (!bodyEl) return; + } + + handleScrollBar(bodyEl, tableEl); + + bodyEl!.style.height = 'unset'; + + if (!unref(getCanResize) || !unref(tableData) || tableData.length === 0) return; + + await nextTick(); + // Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight + + const headEl = tableEl.querySelector('.ant-table-thead '); + + if (!headEl) return; + + const paginationHeight = caclPaginationHeight(tableEl); + const footerHeight = caclFooterHeight(tableEl); + const headerHeight = calcHeaderHeight(headEl); + const { paddingHeight, bottomIncludeBody } = calcBottomAndPaddingHeight(tableEl, headEl); + + let height = + bottomIncludeBody - + (resizeHeightOffset || 0) - + paddingHeight - + paginationHeight - + footerHeight - + headerHeight; + height = (height > maxHeight! ? (maxHeight as number) : height) ?? height; + setHeight(height); + + bodyEl!.style.height = `${height}px`; + } + useWindowSizeFn(calcTableHeight, { wait: 280 }); + onMountedOrActivated(() => { + calcTableHeight(); + nextTick(() => { + debounceRedoHeight(); + }); + }); + + const getScrollX = computed(() => { + let width = 0; + if (unref(rowSelectionRef)) { + width += 60; + } + + // TODO props ?? 0; + const NORMAL_WIDTH = 150; + + const columns = unref(columnsRef).filter((item) => !item.defaultHidden); + columns.forEach((item) => { + width += Number.parseFloat(item.width as string) || 0; + }); + const unsetWidthColumns = columns.filter((item) => !Reflect.has(item, 'width')); + + const len = unsetWidthColumns.length; + if (len !== 0) { + width += len * NORMAL_WIDTH; + } + + const table = unref(tableElRef); + const tableWidth = table?.$el?.offsetWidth ?? 0; + return tableWidth > width ? '100%' : width; + }); + + const getScrollRef = computed(() => { + const tableHeight = unref(tableHeightRef); + const { canResize, scroll } = unref(propsRef); + return { + x: unref(getScrollX), + y: canResize ? tableHeight : null, + scrollToFirstRowOnChange: false, + ...scroll, + }; + }); + + return { getScrollRef, redoHeight }; +} diff --git a/src/components/Table/src/hooks/useTableStyle.ts b/src/components/Table/src/hooks/useTableStyle.ts new file mode 100644 index 0000000..292187d --- /dev/null +++ b/src/components/Table/src/hooks/useTableStyle.ts @@ -0,0 +1,20 @@ +import type { ComputedRef } from 'vue'; +import type { BasicTableProps, TableCustomRecord } from '../types/table'; +import { unref } from 'vue'; +import { isFunction } from '/@/utils/is'; + +export function useTableStyle(propsRef: ComputedRef, prefixCls: string) { + function getRowClassName(record: TableCustomRecord, index: number) { + const { striped, rowClassName } = unref(propsRef); + const classNames: string[] = []; + if (striped) { + classNames.push((index || 0) % 2 === 1 ? `${prefixCls}-row__striped` : ''); + } + if (rowClassName && isFunction(rowClassName)) { + classNames.push(rowClassName(record, index)); + } + return classNames.filter((cls) => !!cls).join(' '); + } + + return { getRowClassName }; +} diff --git a/src/components/Table/src/props.ts b/src/components/Table/src/props.ts new file mode 100644 index 0000000..888cd9f --- /dev/null +++ b/src/components/Table/src/props.ts @@ -0,0 +1,151 @@ +import type { PropType } from 'vue'; +import type { PaginationProps } from './types/pagination'; +import type { + BasicColumn, + FetchSetting, + TableSetting, + SorterResult, + TableCustomRecord, + TableRowSelection, + SizeType, +} from './types/table'; +import type { FormProps } from '/@/components/Form'; + +import { DEFAULT_FILTER_FN, DEFAULT_SORT_FN, FETCH_SETTING, DEFAULT_SIZE } from './const'; +import { propTypes } from '/@/utils/propTypes'; + +export const basicProps = { + clickToRowSelect: { type: Boolean, default: true }, + isTreeTable: Boolean, + tableSetting: propTypes.shape({}), + inset: Boolean, + sortFn: { + type: Function as PropType<(sortInfo: SorterResult) => any>, + default: DEFAULT_SORT_FN, + }, + filterFn: { + type: Function as PropType<(data: Partial>) => any>, + default: DEFAULT_FILTER_FN, + }, + showTableSetting: Boolean, + autoCreateKey: { type: Boolean, default: true }, + striped: { type: Boolean, default: true }, + showSummary: Boolean, + summaryFunc: { + type: [Function, Array] as PropType<(...arg: any[]) => any[]>, + default: null, + }, + summaryData: { + type: Array as PropType, + default: null, + }, + indentSize: propTypes.number.def(24), + canColDrag: { type: Boolean, default: true }, + api: { + type: Function as PropType<(...arg: any[]) => Promise>, + default: null, + }, + beforeFetch: { + type: Function as PropType, + default: null, + }, + afterFetch: { + type: Function as PropType, + default: null, + }, + handleSearchInfoFn: { + type: Function as PropType, + default: null, + }, + fetchSetting: { + type: Object as PropType, + default: () => { + return FETCH_SETTING; + }, + }, + // 立即请求接口 + immediate: { type: Boolean, default: true }, + emptyDataIsShowTable: { type: Boolean, default: true }, + // 额外的请求参数 + searchInfo: { + type: Object as PropType, + default: null, + }, + // 默认的排序参数 + defSort: { + type: Object as PropType, + default: null, + }, + // 使用搜索表单 + useSearchForm: propTypes.bool, + // 表单配置 + formConfig: { + type: Object as PropType>, + default: null, + }, + columns: { + type: Array as PropType, + default: () => [], + }, + showIndexColumn: { type: Boolean, default: true }, + indexColumnProps: { + type: Object as PropType, + default: null, + }, + actionColumn: { + type: Object as PropType, + default: null, + }, + ellipsis: { type: Boolean, default: true }, + isCanResizeParent: { type: Boolean, default: false }, + canResize: { type: Boolean, default: true }, + clearSelectOnPageChange: propTypes.bool, + resizeHeightOffset: propTypes.number.def(0), + rowSelection: { + type: Object as PropType, + default: null, + }, + title: { + type: [String, Function] as PropType string)>, + default: null, + }, + titleHelpMessage: { + type: [String, Array] as PropType, + }, + maxHeight: propTypes.number, + dataSource: { + type: Array as PropType, + default: null, + }, + rowKey: { + type: [String, Function] as PropType string)>, + default: '', + }, + bordered: propTypes.bool, + pagination: { + type: [Object, Boolean] as PropType, + default: null, + }, + loading: propTypes.bool, + rowClassName: { + type: Function as PropType<(record: TableCustomRecord, index: number) => string>, + }, + scroll: { + type: Object as PropType<{ x: number | string | true; y: number | string }>, + default: null, + }, + beforeEditSubmit: { + type: Function as PropType< + (data: { + record: Recordable; + index: number; + key: string | number; + value: any; + }) => Promise + >, + }, + size: { + type: String as PropType, + default: DEFAULT_SIZE, + }, +}; diff --git a/src/components/Table/src/types/column.ts b/src/components/Table/src/types/column.ts new file mode 100644 index 0000000..9ffd579 --- /dev/null +++ b/src/components/Table/src/types/column.ts @@ -0,0 +1,198 @@ +import { VNodeChild } from 'vue'; + +export interface ColumnFilterItem { + text?: string; + value?: string; + children?: any; +} + +export declare type SortOrder = 'ascend' | 'descend'; + +export interface RecordProps { + text: any; + record: T; + index: number; +} + +export interface FilterDropdownProps { + prefixCls?: string; + setSelectedKeys?: (selectedKeys: string[]) => void; + selectedKeys?: string[]; + confirm?: () => void; + clearFilters?: () => void; + filters?: ColumnFilterItem[]; + getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement; + visible?: boolean; +} + +export declare type CustomRenderFunction = (record: RecordProps) => VNodeChild | JSX.Element; + +export interface ColumnProps { + /** + * specify how content is aligned + * @default 'left' + * @type string + */ + align?: 'left' | 'right' | 'center'; + + /** + * ellipsize cell content, not working with sorter and filters for now. + * tableLayout would be fixed when ellipsis is true. + * @default false + * @type boolean + */ + ellipsis?: boolean; + + /** + * Span of this column's title + * @type number + */ + colSpan?: number; + + /** + * Display field of the data record, could be set like a.b.c + * @type string + */ + dataIndex?: string; + + /** + * Default filtered values + * @type string[] + */ + defaultFilteredValue?: string[]; + + /** + * Default order of sorted values: 'ascend' 'descend' null + * @type string + */ + defaultSortOrder?: SortOrder; + + /** + * Customized filter overlay + * @type any (slot) + */ + filterDropdown?: + | VNodeChild + | JSX.Element + | ((props: FilterDropdownProps) => VNodeChild | JSX.Element); + + /** + * Whether filterDropdown is visible + * @type boolean + */ + filterDropdownOpen?: boolean; + + /** + * Whether the dataSource is filtered + * @default false + * @type boolean + */ + filtered?: boolean; + + /** + * Controlled filtered value, filter icon will highlight + * @type string[] + */ + filteredValue?: string[]; + + /** + * Customized filter icon + * @default false + * @type any + */ + filterIcon?: boolean | VNodeChild | JSX.Element; + + /** + * Whether multiple filters can be selected + * @default true + * @type boolean + */ + filterMultiple?: boolean; + + /** + * Filter menu config + * @type object[] + */ + filters?: ColumnFilterItem[]; + + /** + * Set column to be fixed: true(same as left) 'left' 'right' + * @default false + * @type boolean | string + */ + fixed?: boolean | 'left' | 'right'; + + /** + * Unique key of this column, you can ignore this prop if you've set a unique dataIndex + * @type string + */ + key?: string; + + /** + * Renderer of the table cell. The return value should be a VNode, or an object for colSpan/rowSpan config + * @type Function | ScopedSlot + */ + customRender?: CustomRenderFunction | VNodeChild | JSX.Element; + + /** + * Sort function for local sort, see Array.sort's compareFunction. If you need sort buttons only, set to true + * @type boolean | Function + */ + sorter?: boolean | Function; + + /** + * Order of sorted values: 'ascend' 'descend' false + * @type boolean | string + */ + sortOrder?: boolean | SortOrder; + + /** + * supported sort way, could be 'ascend', 'descend' + * @default ['ascend', 'descend'] + * @type string[] + */ + sortDirections?: SortOrder[]; + + /** + * Title of this column + * @type any (string | slot) + */ + title?: VNodeChild | JSX.Element; + + /** + * Width of this column + * @type string | number + */ + width?: string | number; + + /** + * Set props on per cell + * @type Function + */ + customCell?: (record: T, rowIndex: number) => object; + + /** + * Set props on per header cell + * @type object + */ + customHeaderCell?: (column: ColumnProps) => object; + + /** + * Callback executed when the confirm filter button is clicked, Use as a filter event when using template or jsx + * @type Function + */ + onFilter?: (value: any, record: T) => boolean; + + /** + * Callback executed when filterDropdownVisible is changed, Use as a filterDropdownVisible event when using template or jsx + * @type Function + */ + onFilterDropdownVisibleChange?: (visible: boolean) => void; + + /** + * When using columns, you can setting this property to configure the properties that support the slot, + * such as slots: { filterIcon: 'XXX'} + * @type object + */ + slots?: Recordable; +} diff --git a/src/components/Table/src/types/componentType.ts b/src/components/Table/src/types/componentType.ts new file mode 100644 index 0000000..d71cc28 --- /dev/null +++ b/src/components/Table/src/types/componentType.ts @@ -0,0 +1,14 @@ +export type ComponentType = + | 'Input' + | 'InputNumber' + | 'Select' + | 'ApiSelect' + | 'AutoComplete' + | 'ApiTreeSelect' + | 'Checkbox' + | 'Switch' + | 'DatePicker' + | 'TimePicker' + | 'RadioGroup' + | 'RadioButtonGroup' + | 'ApiRadioGroup'; diff --git a/src/components/Table/src/types/pagination.ts b/src/components/Table/src/types/pagination.ts new file mode 100644 index 0000000..c705f33 --- /dev/null +++ b/src/components/Table/src/types/pagination.ts @@ -0,0 +1,115 @@ +import Pagination from 'ant-design-vue/lib/pagination'; +import { VNodeChild } from 'vue'; + +interface PaginationRenderProps { + page: number; + type: 'page' | 'prev' | 'next'; + originalElement: any; +} + +type PaginationPositon = + | 'topLeft' + | 'topCenter' + | 'topRight' + | 'bottomLeft' + | 'bottomCenter' + | 'bottomRight'; + +export declare class PaginationConfig extends Pagination { + position?: PaginationPositon[]; +} + +export interface PaginationProps { + /** + * total number of data items + * @default 0 + * @type number + */ + total?: number; + + /** + * default initial page number + * @default 1 + * @type number + */ + defaultCurrent?: number; + + /** + * current page number + * @type number + */ + current?: number; + + /** + * default number of data items per page + * @default 10 + * @type number + */ + defaultPageSize?: number; + + /** + * number of data items per page + * @type number + */ + pageSize?: number; + + /** + * Whether to hide pager on single page + * @default false + * @type boolean + */ + hideOnSinglePage?: boolean; + + /** + * determine whether pageSize can be changed + * @default false + * @type boolean + */ + showSizeChanger?: boolean; + + /** + * specify the sizeChanger options + * @default ['10', '20', '30', '40'] + * @type string[] + */ + pageSizeOptions?: string[]; + + /** + * determine whether you can jump to pages directly + * @default false + * @type boolean + */ + showQuickJumper?: boolean | object; + + /** + * to display the total number and range + * @type Function + */ + showTotal?: (total: number, range: [number, number]) => any; + + /** + * specify the size of Pagination, can be set to small + * @default '' + * @type string + */ + size?: string; + + /** + * whether to setting simple mode + * @type boolean + */ + simple?: boolean; + + /** + * to customize item innerHTML + * @type Function + */ + itemRender?: (props: PaginationRenderProps) => VNodeChild | JSX.Element; + + /** + * specify the position of Pagination + * @default ['bottomRight'] + * @type string[] + */ + position?: PaginationPositon[]; +} diff --git a/src/components/Table/src/types/table.ts b/src/components/Table/src/types/table.ts new file mode 100644 index 0000000..d9e9ce6 --- /dev/null +++ b/src/components/Table/src/types/table.ts @@ -0,0 +1,485 @@ +import type { VNodeChild } from 'vue'; +import type { PaginationProps } from './pagination'; +import type { FormProps } from '/@/components/Form'; +import type { + TableRowSelection as ITableRowSelection, + Key, +} from 'ant-design-vue/lib/table/interface'; +import type { ColumnProps } from 'ant-design-vue/lib/table'; + +import { ComponentType } from './componentType'; +import { VueNode } from '/@/utils/propTypes'; +import { RoleEnum } from '/@/enums/roleEnum'; + +export declare type SortOrder = 'ascend' | 'descend'; + +export interface TableCurrentDataSource { + currentDataSource: T[]; +} + +export interface TableRowSelection extends ITableRowSelection { + /** + * Callback executed when selected rows change + * @type Function + */ + onChange?: (selectedRowKeys: Key[], selectedRows: T[]) => any; + + /** + * Callback executed when select/deselect one row + * @type Function + */ + onSelect?: (record: T, selected: boolean, selectedRows: Object[], nativeEvent: Event) => any; + + /** + * Callback executed when select/deselect all rows + * @type Function + */ + onSelectAll?: (selected: boolean, selectedRows: T[], changeRows: T[]) => any; + + /** + * Callback executed when row selection is inverted + * @type Function + */ + onSelectInvert?: (selectedRows: Key[]) => any; +} + +export interface TableCustomRecord { + record?: T; + index?: number; +} + +export interface ExpandedRowRenderRecord extends TableCustomRecord { + indent?: number; + expanded?: boolean; +} +export interface ColumnFilterItem { + text?: string; + value?: string; + children?: any; +} + +export interface TableCustomRecord { + record?: T; + index?: number; +} + +export interface SorterResult { + column: ColumnProps; + order: SortOrder; + field: string; + columnKey: string; +} + +export interface FetchParams { + searchInfo?: Recordable; + page?: number; + sortInfo?: Recordable; + filterInfo?: Recordable; +} + +export interface GetColumnsParams { + ignoreIndex?: boolean; + ignoreAction?: boolean; + sort?: boolean; +} + +export type SizeType = 'default' | 'middle' | 'small' | 'large'; + +export interface TableActionType { + reload: (opt?: FetchParams) => Promise; + setSelectedRows: (rows: Recordable[]) => void; + getSelectRows: () => T[]; + clearSelectedRowKeys: () => void; + expandAll: () => void; + expandRows: (keys: (string | number)[]) => void; + collapseAll: () => void; + scrollTo: (pos: string) => void; // pos: id | "top" | "bottom" + getSelectRowKeys: () => string[]; + deleteSelectRowByKey: (key: string) => void; + setPagination: (info: Partial) => void; + setTableData: (values: T[]) => void; + updateTableDataRecord: (rowKey: string | number, record: Recordable) => Recordable | void; + deleteTableDataRecord: (rowKey: string | number | string[] | number[]) => void; + insertTableDataRecord: (record: Recordable | Recordable[], index?: number) => Recordable[] | void; + findTableDataRecord: (rowKey: string | number) => Recordable | void; + getColumns: (opt?: GetColumnsParams) => BasicColumn[]; + setColumns: (columns: BasicColumn[] | string[]) => void; + getDataSource: () => T[]; + getRawDataSource: () => T; + setLoading: (loading: boolean) => void; + setProps: (props: Partial) => void; + redoHeight: () => void; + setSelectedRowKeys: (rowKeys: Key[]) => void; + getPaginationRef: () => PaginationProps | boolean; + getSize: () => SizeType; + getRowSelection: () => TableRowSelection; + getCacheColumns: () => BasicColumn[]; + emit?: EmitType; + updateTableData: (index: number, key: string, value: any) => Recordable; + setShowPagination: (show: boolean) => Promise; + getShowPagination: () => boolean; + setCacheColumnsByField?: (dataIndex: string | undefined, value: BasicColumn) => void; + setCacheColumns?: (columns: BasicColumn[]) => void; +} + +export interface FetchSetting { + // 请求接口当前页数 + pageField: string; + // 每页显示多少条 + sizeField: string; + // 请求结果列表字段 支持 a.b.c + listField: string; + // 请求结果总数字段 支持 a.b.c + totalField: string; +} + +export interface TableSetting { + redo?: boolean; + size?: boolean; + setting?: boolean; + fullScreen?: boolean; +} + +export interface BasicTableProps { + // 点击行选中 + clickToRowSelect?: boolean; + isTreeTable?: boolean; + // 自定义排序方法 + sortFn?: (sortInfo: SorterResult) => any; + // 排序方法 + filterFn?: (data: Partial>) => any; + // 取消表格的默认padding + inset?: boolean; + // 显示表格设置 + showTableSetting?: boolean; + tableSetting?: TableSetting; + // 斑马纹 + striped?: boolean; + // 是否自动生成key + autoCreateKey?: boolean; + // 计算合计行的方法 + summaryFunc?: (...arg: any) => Recordable[]; + // 自定义合计表格内容 + summaryData?: Recordable[]; + // 是否显示合计行 + showSummary?: boolean; + // 是否可拖拽列 + canColDrag?: boolean; + // 接口请求对象 + api?: (...arg: any) => Promise; + // 请求之前处理参数 + beforeFetch?: Fn; + // 自定义处理接口返回参数 + afterFetch?: Fn; + // 查询条件请求之前处理 + handleSearchInfoFn?: Fn; + // 请求接口配置 + fetchSetting?: Partial; + // 立即请求接口 + immediate?: boolean; + // 在开起搜索表单的时候,如果没有数据是否显示表格 + emptyDataIsShowTable?: boolean; + // 额外的请求参数 + searchInfo?: Recordable; + // 默认的排序参数 + defSort?: Recordable; + // 使用搜索表单 + useSearchForm?: boolean; + // 表单配置 + formConfig?: Partial; + // 列配置 + columns: BasicColumn[]; + // 是否显示序号列 + showIndexColumn?: boolean; + // 序号列配置 + indexColumnProps?: BasicColumn; + actionColumn?: BasicColumn; + // 文本超过宽度是否显示。。。 + ellipsis?: boolean; + // 是否继承父级高度(父级高度-表单高度-padding高度) + isCanResizeParent?: boolean; + // 是否可以自适应高度 + canResize?: boolean; + // 自适应高度偏移, 计算结果-偏移量 + resizeHeightOffset?: number; + + // 在分页改变的时候清空选项 + clearSelectOnPageChange?: boolean; + // + rowKey?: string | ((record: Recordable) => string); + // 数据 + dataSource?: Recordable[]; + // 标题右侧提示 + titleHelpMessage?: string | string[]; + // 表格滚动最大高度 + maxHeight?: number; + // 是否显示边框 + bordered?: boolean; + // 分页配置 + pagination?: PaginationProps | boolean; + // loading加载 + loading?: boolean; + + /** + * The column contains children to display + * @default 'children' + * @type string | string[] + */ + childrenColumnName?: string; + + /** + * Override default table elements + * @type object + */ + components?: object; + + /** + * Expand all rows initially + * @default false + * @type boolean + */ + defaultExpandAllRows?: boolean; + + /** + * Initial expanded row keys + * @type string[] + */ + defaultExpandedRowKeys?: string[]; + + /** + * Current expanded row keys + * @type string[] + */ + expandedRowKeys?: string[]; + + /** + * Expanded container render for each row + * @type Function + */ + expandedRowRender?: (record?: ExpandedRowRenderRecord) => VNodeChild | JSX.Element; + + /** + * Customize row expand Icon. + * @type Function | VNodeChild + */ + expandIcon?: Function | VNodeChild | JSX.Element; + + /** + * Whether to expand row by clicking anywhere in the whole row + * @default false + * @type boolean + */ + expandRowByClick?: boolean; + + /** + * The index of `expandIcon` which column will be inserted when `expandIconAsCell` is false. default 0 + */ + expandIconColumnIndex?: number; + + /** + * Table footer renderer + * @type Function | VNodeChild + */ + footer?: Function | VNodeChild | JSX.Element; + + /** + * Indent size in pixels of tree data + * @default 15 + * @type number + */ + indentSize?: number; + + /** + * i18n text including filter, sort, empty text, etc + * @default { filterConfirm: 'Ok', filterReset: 'Reset', emptyText: 'No Data' } + * @type object + */ + locale?: object; + + /** + * Row's className + * @type Function + */ + rowClassName?: (record: TableCustomRecord, index: number) => string; + + /** + * Row selection config + * @type object + */ + rowSelection?: TableRowSelection; + + /** + * Set horizontal or vertical scrolling, can also be used to specify the width and height of the scroll area. + * It is recommended to set a number for x, if you want to set it to true, + * you need to add style .ant-table td { white-space: nowrap; }. + * @type object + */ + scroll?: { x?: number | string | true; y?: number | string }; + + /** + * Whether to show table header + * @default true + * @type boolean + */ + showHeader?: boolean; + + /** + * Size of table + * @default 'default' + * @type string + */ + size?: SizeType; + + /** + * Table title renderer + * @type Function | ScopedSlot + */ + title?: VNodeChild | JSX.Element | string | ((data: Recordable) => string); + + /** + * Set props on per header row + * @type Function + */ + customHeaderRow?: (column: ColumnProps, index: number) => object; + + /** + * Set props on per row + * @type Function + */ + customRow?: (record: T, index: number) => object; + + /** + * `table-layout` attribute of table element + * `fixed` when header/columns are fixed, or using `column.ellipsis` + * + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout + * @version 1.5.0 + */ + tableLayout?: 'auto' | 'fixed' | string; + + /** + * the render container of dropdowns in table + * @param triggerNode + * @version 1.5.0 + */ + getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement; + + /** + * Data can be changed again before rendering. + * The default configuration of general user empty data. + * You can configured globally through [ConfigProvider](https://antdv.com/components/config-provider-cn/) + * + * @version 1.5.4 + */ + transformCellText?: Function; + + /** + * Callback executed before editable cell submit value, not for row-editor + * + * The cell will not submit data while callback return false + */ + beforeEditSubmit?: (data: { + record: Recordable; + index: number; + key: string | number; + value: any; + }) => Promise; + + /** + * Callback executed when pagination, filters or sorter is changed + * @param pagination + * @param filters + * @param sorter + * @param currentDataSource + */ + onChange?: (pagination: any, filters: any, sorter: any, extra: any) => void; + + /** + * Callback executed when the row expand icon is clicked + * + * @param expanded + * @param record + */ + onExpand?: (expande: boolean, record: T) => void; + + /** + * Callback executed when the expanded rows change + * @param expandedRows + */ + onExpandedRowsChange?: (expandedRows: string[] | number[]) => void; + + onColumnsChange?: (data: ColumnChangeParam[]) => void; +} + +export type CellFormat = + | string + | ((text: string, record: Recordable, index: number) => string | number) + | Map; + +// @ts-ignore +export interface BasicColumn extends ColumnProps { + children?: BasicColumn[]; + filters?: { + text: string; + value: string; + children?: + | unknown[] + | (((props: Record) => unknown[]) & (() => unknown[]) & (() => unknown[])); + }[]; + + // + flag?: 'INDEX' | 'DEFAULT' | 'CHECKBOX' | 'RADIO' | 'ACTION'; + customTitle?: VueNode; + + slots?: Recordable; + + // 自定义header渲染 + customHeaderRender?: (column: BasicColumn) => string | VNodeChild | JSX.Element; + // Whether to hide the column by default, it can be displayed in the column configuration + defaultHidden?: boolean; + + // Help text for table column header + helpMessage?: string | string[]; + + format?: CellFormat; + + // Editable + edit?: boolean; + editRow?: boolean; + editable?: boolean; + editComponent?: ComponentType; + editComponentProps?: + | ((opt: { + text: string | number | boolean | Recordable; + record: Recordable; + column: BasicColumn; + index: number; + }) => Recordable) + | Recordable; + editRule?: boolean | ((text: string, record: Recordable) => Promise); + editValueMap?: (value: any) => string; + onEditRow?: () => void; + // 权限编码控制是否显示 + auth?: RoleEnum | RoleEnum[] | string | string[]; + // 业务控制是否显示 + ifShow?: boolean | ((column: BasicColumn) => boolean); + // 自定义修改后显示的内容 + editRender?: (opt: { + text: string | number | boolean | Recordable; + record: Recordable; + column: BasicColumn; + index: number; + }) => VNodeChild | JSX.Element; + // 动态 Disabled + editDynamicDisabled?: boolean | ((record: Recordable) => boolean); +} + +export type ColumnChangeParam = { + dataIndex: string; + fixed: boolean | 'left' | 'right' | undefined; + visible: boolean; +}; + +export interface InnerHandlers { + onColumnsChange: (data: ColumnChangeParam[]) => void; +} diff --git a/src/components/Table/src/types/tableAction.ts b/src/components/Table/src/types/tableAction.ts new file mode 100644 index 0000000..d847707 --- /dev/null +++ b/src/components/Table/src/types/tableAction.ts @@ -0,0 +1,40 @@ +import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes'; +import { TooltipProps } from 'ant-design-vue/es/tooltip/Tooltip'; +import { RoleEnum } from '/@/enums/roleEnum'; + +export interface ActionItem extends ButtonProps { + onClick?: Fn; + label?: string; + color?: 'success' | 'error' | 'warning'; + icon?: string; + popConfirm?: PopConfirm; + disabled?: boolean; + divider?: boolean; + // 权限编码控制是否显示 + auth?: RoleEnum | RoleEnum[] | string | string[]; + // 业务控制是否显示 + ifShow?: boolean | ((action: ActionItem) => boolean); + tooltip?: string | TooltipProps; +} + +export interface PopConfirm { + title: string; + okText?: string; + cancelText?: string; + confirm: Fn; + cancel?: Fn; + icon?: string; + placement?: + | 'top' + | 'left' + | 'right' + | 'bottom' + | 'topLeft' + | 'topRight' + | 'leftTop' + | 'leftBottom' + | 'rightTop' + | 'rightBottom' + | 'bottomLeft' + | 'bottomRight'; +} diff --git a/src/components/Time/index.ts b/src/components/Time/index.ts new file mode 100644 index 0000000..7e2f4c0 --- /dev/null +++ b/src/components/Time/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from '/@/utils/index'; +import time from './src/Time.vue'; + +export const Time = withInstall(time); diff --git a/src/components/Time/src/Time.vue b/src/components/Time/src/Time.vue new file mode 100644 index 0000000..2789368 --- /dev/null +++ b/src/components/Time/src/Time.vue @@ -0,0 +1,108 @@ + + diff --git a/src/components/Tools/ImportFileModal.vue b/src/components/Tools/ImportFileModal.vue new file mode 100644 index 0000000..cecd8b3 --- /dev/null +++ b/src/components/Tools/ImportFileModal.vue @@ -0,0 +1,202 @@ + + \ No newline at end of file diff --git a/src/components/Transition/index.ts b/src/components/Transition/index.ts new file mode 100644 index 0000000..7eb79b5 --- /dev/null +++ b/src/components/Transition/index.ts @@ -0,0 +1,27 @@ +import { createSimpleTransition, createJavascriptTransition } from './src/CreateTransition'; + +import ExpandTransitionGenerator from './src/ExpandTransition'; + +export { default as CollapseTransition } from './src/CollapseTransition.vue'; + +export const FadeTransition = createSimpleTransition('fade-transition'); +export const ScaleTransition = createSimpleTransition('scale-transition'); +export const SlideYTransition = createSimpleTransition('slide-y-transition'); +export const ScrollYTransition = createSimpleTransition('scroll-y-transition'); +export const SlideYReverseTransition = createSimpleTransition('slide-y-reverse-transition'); +export const ScrollYReverseTransition = createSimpleTransition('scroll-y-reverse-transition'); +export const SlideXTransition = createSimpleTransition('slide-x-transition'); +export const ScrollXTransition = createSimpleTransition('scroll-x-transition'); +export const SlideXReverseTransition = createSimpleTransition('slide-x-reverse-transition'); +export const ScrollXReverseTransition = createSimpleTransition('scroll-x-reverse-transition'); +export const ScaleRotateTransition = createSimpleTransition('scale-rotate-transition'); + +export const ExpandXTransition = createJavascriptTransition( + 'expand-x-transition', + ExpandTransitionGenerator('', true), +); + +export const ExpandTransition = createJavascriptTransition( + 'expand-transition', + ExpandTransitionGenerator(''), +); diff --git a/src/components/Transition/src/CollapseTransition.vue b/src/components/Transition/src/CollapseTransition.vue new file mode 100644 index 0000000..6b50fa1 --- /dev/null +++ b/src/components/Transition/src/CollapseTransition.vue @@ -0,0 +1,78 @@ + + diff --git a/src/components/Transition/src/CreateTransition.tsx b/src/components/Transition/src/CreateTransition.tsx new file mode 100644 index 0000000..d12518d --- /dev/null +++ b/src/components/Transition/src/CreateTransition.tsx @@ -0,0 +1,73 @@ +import type { PropType } from 'vue'; + +import { defineComponent, Transition, TransitionGroup } from 'vue'; +import { getSlot } from '/@/utils/helper/tsxHelper'; + +type Mode = 'in-out' | 'out-in' | 'default' | undefined; + +export function createSimpleTransition(name: string, origin = 'top center 0', mode?: Mode) { + return defineComponent({ + name, + props: { + group: { + type: Boolean as PropType, + default: false, + }, + mode: { + type: String as PropType, + default: mode, + }, + origin: { + type: String as PropType, + default: origin, + }, + }, + setup(props, { slots, attrs }) { + const onBeforeEnter = (el: HTMLElement) => { + el.style.transformOrigin = props.origin; + }; + + return () => { + const Tag = !props.group ? Transition : TransitionGroup; + return ( + + {() => getSlot(slots)} + + ); + }; + }, + }); +} +export function createJavascriptTransition( + name: string, + functions: Recordable, + mode: Mode = 'in-out', +) { + return defineComponent({ + name, + props: { + mode: { + type: String as PropType, + default: mode, + }, + }, + setup(props, { attrs, slots }) { + return () => { + return ( + + {() => getSlot(slots)} + + ); + }; + }, + }); +} diff --git a/src/components/Transition/src/ExpandTransition.ts b/src/components/Transition/src/ExpandTransition.ts new file mode 100644 index 0000000..2aaef9a --- /dev/null +++ b/src/components/Transition/src/ExpandTransition.ts @@ -0,0 +1,89 @@ +/** + * Makes the first character of a string uppercase + */ +export function upperFirst(str: string): string { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +interface HTMLExpandElement extends HTMLElement { + _parent?: (Node & ParentNode & HTMLElement) | null; + _initialStyle: { + transition: string; + overflow: string | null; + height?: string | null; + width?: string | null; + }; +} + +export default function (expandedParentClass = '', x = false) { + const sizeProperty = x ? 'width' : ('height' as 'width' | 'height'); + const offsetProperty = `offset${upperFirst(sizeProperty)}` as 'offsetHeight' | 'offsetWidth'; + + return { + beforeEnter(el: HTMLExpandElement) { + el._parent = el.parentNode as (Node & ParentNode & HTMLElement) | null; + el._initialStyle = { + transition: el.style.transition, + overflow: el.style.overflow, + [sizeProperty]: el.style[sizeProperty], + }; + }, + + enter(el: HTMLExpandElement) { + const initialStyle = el._initialStyle; + + el.style.setProperty('transition', 'none', 'important'); + el.style.overflow = 'hidden'; + // const offset = `${el[offsetProperty]}px`; + + // el.style[sizeProperty] = '0'; + + void el.offsetHeight; // force reflow + + el.style.transition = initialStyle.transition; + + if (expandedParentClass && el._parent) { + el._parent.classList.add(expandedParentClass); + } + + requestAnimationFrame(() => { + // el.style[sizeProperty] = offset; + }); + }, + + afterEnter: resetStyles, + enterCancelled: resetStyles, + + leave(el: HTMLExpandElement) { + el._initialStyle = { + transition: '', + overflow: el.style.overflow, + [sizeProperty]: el.style[sizeProperty], + }; + + el.style.overflow = 'hidden'; + el.style[sizeProperty] = `${el[offsetProperty]}px`; + /* eslint-disable-next-line */ + void el.offsetHeight; // force reflow + + requestAnimationFrame(() => (el.style[sizeProperty] = '0')); + }, + + afterLeave, + leaveCancelled: afterLeave, + }; + + function afterLeave(el: HTMLExpandElement) { + if (expandedParentClass && el._parent) { + el._parent.classList.remove(expandedParentClass); + } + resetStyles(el); + } + + function resetStyles(el: HTMLExpandElement) { + const size = el._initialStyle[sizeProperty]; + el.style.overflow = el._initialStyle.overflow!; + if (size != null) el.style[sizeProperty] = size; + Reflect.deleteProperty(el, '_initialStyle'); + } +} diff --git a/src/components/Tree/index.ts b/src/components/Tree/index.ts new file mode 100644 index 0000000..169035a --- /dev/null +++ b/src/components/Tree/index.ts @@ -0,0 +1,6 @@ +import BasicTree from './src/BasicTree.vue'; +import './style'; + +export { BasicTree }; +export type { ContextMenuItem } from '/@/hooks/web/useContextMenu'; +export * from './src/types/tree'; diff --git a/src/components/Tree/src/BasicTree.vue b/src/components/Tree/src/BasicTree.vue new file mode 100644 index 0000000..008b247 --- /dev/null +++ b/src/components/Tree/src/BasicTree.vue @@ -0,0 +1,459 @@ + diff --git a/src/components/Tree/src/TreeIcon.ts b/src/components/Tree/src/TreeIcon.ts new file mode 100644 index 0000000..dd4eab1 --- /dev/null +++ b/src/components/Tree/src/TreeIcon.ts @@ -0,0 +1,12 @@ +import type { VNode, FunctionalComponent } from 'vue'; +import { h } from 'vue'; +import { isString } from 'lodash-es'; +import Icon from '@/components/Icon/Icon.vue'; + +export const TreeIcon: FunctionalComponent = ({ icon }: { icon: VNode | string }) => { + if (!icon) return null; + if (isString(icon)) { + return h(Icon, { icon, class: 'mr-1' }); + } + return Icon; +}; diff --git a/src/components/Tree/src/components/TreeHeader.vue b/src/components/Tree/src/components/TreeHeader.vue new file mode 100644 index 0000000..cb269f5 --- /dev/null +++ b/src/components/Tree/src/components/TreeHeader.vue @@ -0,0 +1,170 @@ + + diff --git a/src/components/Tree/src/hooks/useTree.ts b/src/components/Tree/src/hooks/useTree.ts new file mode 100644 index 0000000..6bd0539 --- /dev/null +++ b/src/components/Tree/src/hooks/useTree.ts @@ -0,0 +1,211 @@ +import type { InsertNodeParams, KeyType, FieldNames, TreeItem } from '../types/tree'; +import type { Ref, ComputedRef } from 'vue'; +import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree'; + +import { cloneDeep } from 'lodash-es'; +import { unref } from 'vue'; +import { forEach } from '/@/utils/helper/treeHelper'; + +export function useTree(treeDataRef: Ref, getFieldNames: ComputedRef) { + function getAllKeys(list?: TreeDataItem[]) { + const keys: string[] = []; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return keys; + + for (let index = 0; index < treeData.length; index++) { + const node = treeData[index]; + keys.push(node[keyField]!); + const children = node[childrenField]; + if (children && children.length) { + keys.push(...(getAllKeys(children) as string[])); + } + } + return keys as KeyType[]; + } + + // get keys that can be checked and selected + function getEnabledKeys(list?: TreeDataItem[]) { + const keys: string[] = []; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return keys; + + for (let index = 0; index < treeData.length; index++) { + const node = treeData[index]; + node.disabled !== true && node.selectable !== false && keys.push(node[keyField]!); + const children = node[childrenField]; + if (children && children.length) { + keys.push(...(getEnabledKeys(children) as string[])); + } + } + return keys as KeyType[]; + } + + function getChildrenKeys(nodeKey: string | number, list?: TreeDataItem[]) { + const keys: KeyType[] = []; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return keys; + for (let index = 0; index < treeData.length; index++) { + const node = treeData[index]; + const children = node[childrenField]; + if (nodeKey === node[keyField]) { + keys.push(node[keyField]!); + if (children && children.length) { + keys.push(...(getAllKeys(children) as string[])); + } + } else { + if (children && children.length) { + keys.push(...getChildrenKeys(nodeKey, children)); + } + } + } + return keys as KeyType[]; + } + + // Update node + function updateNodeByKey(key: string, node: TreeDataItem, list?: TreeDataItem[]) { + if (!key) return; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + + if (!childrenField || !keyField) return; + + for (let index = 0; index < treeData.length; index++) { + const element: any = treeData[index]; + const children = element[childrenField]; + + if (element[keyField] === key) { + treeData[index] = { ...treeData[index], ...node }; + break; + } else if (children && children.length) { + updateNodeByKey(key, node, element[childrenField]); + } + } + } + + // Expand the specified level + function filterByLevel(level = 1, list?: TreeDataItem[], currentLevel = 1) { + if (!level) { + return []; + } + const res: (string | number)[] = []; + const data = list || unref(treeDataRef) || []; + for (let index = 0; index < data.length; index++) { + const item = data[index]; + + const { key: keyField, children: childrenField } = unref(getFieldNames); + const key = keyField ? item[keyField] : ''; + const children = childrenField ? item[childrenField] : []; + res.push(key); + if (children && children.length && currentLevel < level) { + currentLevel += 1; + res.push(...filterByLevel(level, children, currentLevel)); + } + } + return res as string[] | number[]; + } + + /** + * 添加节点 + */ + function insertNodeByKey({ parentKey = null, node, push = 'push' }: InsertNodeParams) { + const treeData: any = cloneDeep(unref(treeDataRef)); + if (!parentKey) { + treeData[push](node); + treeDataRef.value = treeData; + return; + } + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return; + + forEach(treeData, (treeItem) => { + if (treeItem[keyField] === parentKey) { + treeItem[childrenField] = treeItem[childrenField] || []; + treeItem[childrenField][push](node); + return true; + } + }); + treeDataRef.value = treeData; + } + /** + * 批量添加节点 + */ + function insertNodesByKey({ parentKey = null, list, push = 'push' }: InsertNodeParams) { + const treeData: any = cloneDeep(unref(treeDataRef)); + if (!list || list.length < 1) { + return; + } + if (!parentKey) { + for (let i = 0; i < list.length; i++) { + treeData[push](list[i]); + } + treeDataRef.value = treeData; + return; + } else { + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return; + + forEach(treeData, (treeItem) => { + if (treeItem[keyField] === parentKey) { + treeItem[childrenField] = treeItem[childrenField] || []; + for (let i = 0; i < list.length; i++) { + treeItem[childrenField][push](list[i]); + } + treeDataRef.value = treeData; + return true; + } + }); + } + } + // Delete node + function deleteNodeByKey(key: string, list?: TreeDataItem[]) { + if (!key) return; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!childrenField || !keyField) return; + + for (let index = 0; index < treeData.length; index++) { + const element: any = treeData[index]; + const children = element[childrenField]; + + if (element[keyField] === key) { + treeData.splice(index, 1); + break; + } else if (children && children.length) { + deleteNodeByKey(key, element[childrenField]); + } + } + } + + // Get selected node + function getSelectedNode(key: KeyType, list?: TreeItem[], selectedNode?: TreeItem | null) { + if (!key && key !== 0) return null; + const treeData = list || unref(treeDataRef); + const { key: keyField, children: childrenField } = unref(getFieldNames); + if (!keyField) return; + treeData.forEach((item) => { + if (selectedNode?.key || selectedNode?.key === 0) return selectedNode; + if (item[keyField] === key) { + selectedNode = item; + return; + } + if (item[childrenField!] && item[childrenField!].length) { + selectedNode = getSelectedNode(key, item[childrenField!], selectedNode); + } + }); + return selectedNode || null; + } + return { + deleteNodeByKey, + insertNodeByKey, + insertNodesByKey, + filterByLevel, + updateNodeByKey, + getAllKeys, + getChildrenKeys, + getEnabledKeys, + getSelectedNode, + }; +} diff --git a/src/components/Tree/src/types/tree.ts b/src/components/Tree/src/types/tree.ts new file mode 100644 index 0000000..8988d59 --- /dev/null +++ b/src/components/Tree/src/types/tree.ts @@ -0,0 +1,195 @@ +import type { ExtractPropTypes } from 'vue'; +import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree'; + +import { buildProps } from '/@/utils/props'; + +export enum ToolbarEnum { + SELECT_ALL, + UN_SELECT_ALL, + EXPAND_ALL, + UN_EXPAND_ALL, + CHECK_STRICTLY, + CHECK_UN_STRICTLY, +} + +export const treeEmits = [ + 'update:expandedKeys', + 'update:selectedKeys', + 'update:value', + 'change', + 'check', + 'update:searchValue', +]; + +export interface TreeState { + expandedKeys: KeyType[]; + selectedKeys: KeyType[]; + checkedKeys: CheckKeys; + checkStrictly: boolean; +} + +export interface FieldNames { + children?: string; + title?: string; + key?: string; +} + +export type KeyType = string | number; + +export type CheckKeys = + | KeyType[] + | { checked: string[] | number[]; halfChecked: string[] | number[] }; + +export const treeProps = buildProps({ + value: { + type: [Object, Array] as PropType, + }, + + renderIcon: { + type: Function as PropType<(params: Recordable) => string>, + }, + + helpMessage: { + type: [String, Array] as PropType, + default: '', + }, + + title: { + type: String, + default: '', + }, + toolbar: Boolean, + search: Boolean, + searchValue: { + type: String, + default: '', + }, + checkStrictly: Boolean, + clickRowToExpand: { + type: Boolean, + default: false, + }, + checkable: Boolean, + defaultExpandLevel: { + type: [String, Number] as PropType, + default: '', + }, + defaultExpandAll: Boolean, + + fieldNames: { + type: Object as PropType, + }, + + treeData: { + type: Array as PropType, + }, + + actionList: { + type: Array as PropType, + default: () => [], + }, + + expandedKeys: { + type: Array as PropType, + default: () => [], + }, + + selectedKeys: { + type: Array as PropType, + default: () => [], + }, + + checkedKeys: { + type: [Array, Object] as PropType, + default: () => [], + }, + + beforeRightClick: { + type: Function as PropType<(...arg: any) => Promise>, + default: undefined, + }, + + rightMenuList: { + type: Array as PropType, + }, + // 自定义数据过滤判断方法(注: 不是整个过滤方法,而是内置过滤的判断方法,用于增强原本仅能通过title进行过滤的方式) + filterFn: { + type: Function as PropType< + (searchValue: any, node: TreeItem, fieldNames: FieldNames) => boolean + >, + default: undefined, + }, + // 高亮搜索值,仅高亮具体匹配值(通过title)值为true时使用默认色值,值为#xxx时使用此值替代且高亮开启 + highlight: { + type: [Boolean, String] as PropType, + default: false, + }, + // 搜索完成时自动展开结果 + expandOnSearch: Boolean, + // 搜索完成自动选中所有结果,当且仅当 checkable===true 时生效 + checkOnSearch: Boolean, + // 搜索完成自动select所有结果 + selectedOnSearch: Boolean, + loading: { + type: Boolean, + default: false, + }, + treeWrapperClassName: String, +}); + +export type TreeProps = ExtractPropTypes; + +export interface ContextMenuItem { + label: string; + icon?: string; + hidden?: boolean; + disabled?: boolean; + handler?: Fn; + divider?: boolean; + children?: ContextMenuItem[]; +} + +export interface ContextMenuOptions { + icon?: string; + styles?: any; + items?: ContextMenuItem[]; +} + +export interface TreeItem extends TreeDataItem { + icon?: any; +} + +export interface TreeActionItem { + render: (record: Recordable) => any; + show?: boolean | ((record: Recordable) => boolean); +} + +export interface InsertNodeParams { + parentKey: string | null; + node: TreeDataItem; + list?: TreeDataItem[]; + push?: 'push' | 'unshift'; +} + +export interface TreeActionType { + checkAll: (checkAll: boolean) => void; + expandAll: (expandAll: boolean) => void; + setExpandedKeys: (keys: KeyType[]) => void; + getExpandedKeys: () => KeyType[]; + setSelectedKeys: (keys: KeyType[]) => void; + getSelectedKeys: () => KeyType[]; + setCheckedKeys: (keys: CheckKeys) => void; + getCheckedKeys: () => CheckKeys; + filterByLevel: (level: number) => void; + insertNodeByKey: (opt: InsertNodeParams) => void; + insertNodesByKey: (opt: InsertNodeParams) => void; + deleteNodeByKey: (key: string) => void; + updateNodeByKey: (key: string, node: Omit) => void; + setSearchValue: (value: string) => void; + getSearchValue: () => string; + getSelectedNode: ( + key: KeyType, + treeList?: TreeItem[], + selectNode?: TreeItem | null, + ) => TreeItem | null; +} diff --git a/src/components/Tree/style/index.less b/src/components/Tree/style/index.less new file mode 100644 index 0000000..231f27b --- /dev/null +++ b/src/components/Tree/style/index.less @@ -0,0 +1,52 @@ +@tree-prefix-cls: ~'@{namespace}-tree'; + +.@{tree-prefix-cls} { + background-color: @component-background; + + .ant-tree-node-content-wrapper { + position: relative; + + .ant-tree-title { + position: absolute; + left: 0; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + + &__title { + display: flex; + position: relative; + align-items: center; + width: 100%; + padding-right: 10px; + + &:hover { + .@{tree-prefix-cls}__action { + visibility: visible; + } + } + } + + &__content { + overflow: hidden; + } + + &__actions { + display: flex; + position: absolute; + //top: 2px; + right: 3px; + } + + &__action { + visibility: hidden; + margin-left: 4px; + } + + &-header { + border-bottom: 1px solid @border-color-base; + } +} diff --git a/src/components/Tree/style/index.ts b/src/components/Tree/style/index.ts new file mode 100644 index 0000000..d74e52e --- /dev/null +++ b/src/components/Tree/style/index.ts @@ -0,0 +1 @@ +import './index.less'; diff --git a/src/components/Upload/index.ts b/src/components/Upload/index.ts new file mode 100644 index 0000000..568a7d9 --- /dev/null +++ b/src/components/Upload/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from '/@/utils'; +import basicUpload from './src/BasicUpload.vue'; + +export const BasicUpload = withInstall(basicUpload); diff --git a/src/components/Upload/src/BasicUpload.vue b/src/components/Upload/src/BasicUpload.vue new file mode 100644 index 0000000..9f4b348 --- /dev/null +++ b/src/components/Upload/src/BasicUpload.vue @@ -0,0 +1,124 @@ + + diff --git a/src/components/Upload/src/FileList.vue b/src/components/Upload/src/FileList.vue new file mode 100644 index 0000000..ddb087e --- /dev/null +++ b/src/components/Upload/src/FileList.vue @@ -0,0 +1,104 @@ + + diff --git a/src/components/Upload/src/ThumbUrl.vue b/src/components/Upload/src/ThumbUrl.vue new file mode 100644 index 0000000..1b268dc --- /dev/null +++ b/src/components/Upload/src/ThumbUrl.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/components/Upload/src/UploadModal.vue b/src/components/Upload/src/UploadModal.vue new file mode 100644 index 0000000..268e560 --- /dev/null +++ b/src/components/Upload/src/UploadModal.vue @@ -0,0 +1,323 @@ + + + diff --git a/src/components/Upload/src/UploadPreviewModal.vue b/src/components/Upload/src/UploadPreviewModal.vue new file mode 100644 index 0000000..bc4091b --- /dev/null +++ b/src/components/Upload/src/UploadPreviewModal.vue @@ -0,0 +1,99 @@ + + + diff --git a/src/components/Upload/src/data.tsx b/src/components/Upload/src/data.tsx new file mode 100644 index 0000000..8e08833 --- /dev/null +++ b/src/components/Upload/src/data.tsx @@ -0,0 +1,153 @@ +import type { BasicColumn, ActionItem } from '/@/components/Table'; +import { FileItem, PreviewFileItem, UploadResultStatus } from './typing'; +import { + // checkImgType, + isImgTypeByName, +} from './helper'; +import { Progress, Tag } from 'ant-design-vue'; +import TableAction from '/@/components/Table/src/components/TableAction.vue'; +import ThumbUrl from './ThumbUrl.vue'; +import { useI18n } from '/@/hooks/web/useI18n'; + +const { t } = useI18n(); + +// 文件上传列表 +export function createTableColumns(): BasicColumn[] { + return [ + { + dataIndex: 'thumbUrl', + title: t('component.upload.legend'), + width: 100, + customRender: ({ record }) => { + const { thumbUrl } = (record as FileItem) || {}; + return thumbUrl && ; + }, + }, + { + dataIndex: 'name', + title: t('component.upload.fileName'), + align: 'left', + customRender: ({ text, record }) => { + const { percent, status: uploadStatus } = (record as FileItem) || {}; + let status: 'normal' | 'exception' | 'active' | 'success' = 'normal'; + if (uploadStatus === UploadResultStatus.ERROR) { + status = 'exception'; + } else if (uploadStatus === UploadResultStatus.UPLOADING) { + status = 'active'; + } else if (uploadStatus === UploadResultStatus.SUCCESS) { + status = 'success'; + } + return ( + +

    + {text} +

    + +
    + ); + }, + }, + { + dataIndex: 'size', + title: t('component.upload.fileSize'), + width: 100, + customRender: ({ text = 0 }) => { + return text && (text / 1024).toFixed(2) + 'KB'; + }, + }, + // { + // dataIndex: 'type', + // title: '文件类型', + // width: 100, + // }, + { + dataIndex: 'status', + title: t('component.upload.fileStatue'), + width: 100, + customRender: ({ text }) => { + if (text === UploadResultStatus.SUCCESS) { + return {() => t('component.upload.uploadSuccess')}; + } else if (text === UploadResultStatus.ERROR) { + return {() => t('component.upload.uploadError')}; + } else if (text === UploadResultStatus.UPLOADING) { + return {() => t('component.upload.uploading')}; + } + + return text; + }, + }, + ]; +} +export function createActionColumn(handleRemove: Function): BasicColumn { + return { + width: 120, + title: t('component.upload.operating'), + dataIndex: 'action', + fixed: false, + customRender: ({ record }) => { + const actions: ActionItem[] = [ + { + label: t('component.upload.del'), + color: 'error', + onClick: handleRemove.bind(null, record), + }, + ]; + // if (checkImgType(record)) { + // actions.unshift({ + // label: t('component.upload.preview'), + // onClick: handlePreview.bind(null, record), + // }); + // } + return ; + }, + }; +} +// 文件预览列表 +export function createPreviewColumns(): BasicColumn[] { + return [ + { + dataIndex: 'url', + title: t('component.upload.legend'), + width: 100, + customRender: ({ record }) => { + const { url } = (record as PreviewFileItem) || {}; + return isImgTypeByName(url) && ; + }, + }, + { + dataIndex: 'name', + title: t('component.upload.fileName'), + align: 'left', + }, + ]; +} + +export function createPreviewActionColumn({ + handleRemove, + handleDownload, +}: { + handleRemove: Fn; + handleDownload: Fn; +}): BasicColumn { + return { + width: 160, + title: t('component.upload.operating'), + dataIndex: 'action', + fixed: false, + customRender: ({ record }) => { + const actions: ActionItem[] = [ + { + label: t('component.upload.del'), + color: 'error', + onClick: handleRemove.bind(null, record), + }, + { + label: t('component.upload.download'), + onClick: handleDownload.bind(null, record), + }, + ]; + + return ; + }, + }; +} diff --git a/src/components/Upload/src/helper.ts b/src/components/Upload/src/helper.ts new file mode 100644 index 0000000..7e8494e --- /dev/null +++ b/src/components/Upload/src/helper.ts @@ -0,0 +1,27 @@ +export function checkFileType(file: File, accepts: string[]) { + const newTypes = accepts.join('|'); + // const reg = /\.(jpg|jpeg|png|gif|txt|doc|docx|xls|xlsx|xml)$/i; + const reg = new RegExp('\\.(' + newTypes + ')$', 'i'); + + return reg.test(file.name); +} + +export function checkImgType(file: File) { + return isImgTypeByName(file.name); +} + +export function isImgTypeByName(name: string) { + return /\.(jpg|jpeg|png|gif|webp)$/i.test(name); +} + +export function getBase64WithFile(file: File) { + return new Promise<{ + result: string; + file: File; + }>((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => resolve({ result: reader.result as string, file }); + reader.onerror = (error) => reject(error); + }); +} diff --git a/src/components/Upload/src/props.ts b/src/components/Upload/src/props.ts new file mode 100644 index 0000000..d37f68b --- /dev/null +++ b/src/components/Upload/src/props.ts @@ -0,0 +1,83 @@ +import type { PropType } from 'vue'; +import { FileBasicColumn } from './typing'; + +export const basicProps = { + helpText: { + type: String as PropType, + default: '', + }, + // 文件最大多少MB + maxSize: { + type: Number as PropType, + default: 2, + }, + // 最大数量的文件,Infinity不限制 + maxNumber: { + type: Number as PropType, + default: Infinity, + }, + // 根据后缀,或者其他 + accept: { + type: Array as PropType, + default: () => [], + }, + multiple: { + type: Boolean as PropType, + default: true, + }, + uploadParams: { + type: Object as PropType, + default: () => ({}), + }, + api: { + type: Function as PropType, + default: null, + required: true, + }, + name: { + type: String as PropType, + default: 'file', + }, + filename: { + type: String as PropType, + default: null, + }, +}; + +export const uploadContainerProps = { + value: { + type: Array as PropType, + default: () => [], + }, + ...basicProps, + showPreviewNumber: { + type: Boolean as PropType, + default: true, + }, + emptyHidePreview: { + type: Boolean as PropType, + default: false, + }, +}; + +export const previewProps = { + value: { + type: Array as PropType, + default: () => [], + }, +}; + +export const fileListProps = { + columns: { + type: Array as PropType, + default: null, + }, + actionColumn: { + type: Object as PropType, + default: null, + }, + dataSource: { + type: Array as PropType, + default: null, + }, +}; diff --git a/src/components/Upload/src/typing.ts b/src/components/Upload/src/typing.ts new file mode 100644 index 0000000..c630110 --- /dev/null +++ b/src/components/Upload/src/typing.ts @@ -0,0 +1,55 @@ +import { UploadApiResult } from '/@/api/sys/model/uploadModel'; + +export enum UploadResultStatus { + SUCCESS = 'success', + ERROR = 'error', + UPLOADING = 'uploading', +} + +export interface FileItem { + thumbUrl?: string; + name: string; + size: string | number; + type?: string; + percent: number; + file: File; + status?: UploadResultStatus; + responseData?: UploadApiResult; + uuid: string; +} + +export interface PreviewFileItem { + url: string; + name: string; + type: string; +} + +export interface FileBasicColumn { + /** + * Renderer of the table cell. The return value should be a VNode, or an object for colSpan/rowSpan config + * @type Function | ScopedSlot + */ + customRender?: Function; + /** + * Title of this column + * @type any (string | slot) + */ + title: string; + + /** + * Width of this column + * @type string | number + */ + width?: number; + /** + * Display field of the data record, could be set like a.b.c + * @type string + */ + dataIndex: string; + /** + * specify how content is aligned + * @default 'left' + * @type string + */ + align?: 'left' | 'right' | 'center'; +} diff --git a/src/components/Upload/src/useUpload.ts b/src/components/Upload/src/useUpload.ts new file mode 100644 index 0000000..fb178d0 --- /dev/null +++ b/src/components/Upload/src/useUpload.ts @@ -0,0 +1,61 @@ +import { Ref, unref, computed } from 'vue'; +import { useI18n } from '/@/hooks/web/useI18n'; + +const { t } = useI18n(); +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) => { + if (item.indexOf('/') > 0 || item.startsWith('.')) { + return item; + } else { + return `.${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('component.upload.accept', [accept.join(',')])); + } + + const maxSize = unref(maxSizeRef); + if (maxSize) { + helpTexts.push(t('component.upload.maxSize', [maxSize])); + } + + const maxNumber = unref(maxNumberRef); + if (maxNumber && maxNumber !== Infinity) { + helpTexts.push(t('component.upload.maxNumber', [maxNumber])); + } + return helpTexts.join(','); + }); + return { getAccept, getStringAccept, getHelpText }; +} diff --git a/src/components/VxeTable/index.ts b/src/components/VxeTable/index.ts new file mode 100644 index 0000000..bc24c39 --- /dev/null +++ b/src/components/VxeTable/index.ts @@ -0,0 +1,12 @@ +import { withInstall } from '/@/utils'; +import vxeBasicTable from './src/VxeBasicTable'; +import { VXETable } from 'vxe-table'; +import VXETablePluginAntd from './src/components'; +import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx'; +import './src/setting'; + +export const VxeBasicTable = withInstall(vxeBasicTable); +export * from 'vxe-table'; +export * from './src/types'; + +VXETable.use(VXETablePluginAntd).use(VXETablePluginExportXLSX); diff --git a/src/components/VxeTable/src/VxeBasicTable.tsx b/src/components/VxeTable/src/VxeBasicTable.tsx new file mode 100644 index 0000000..8133142 --- /dev/null +++ b/src/components/VxeTable/src/VxeBasicTable.tsx @@ -0,0 +1,116 @@ +import { defineComponent, computed, ref } from 'vue'; +import { BasicTableProps } from './types'; +import { basicProps } from './props'; +import { ignorePropKeys } from './const'; +import { basicEmits } from './emits'; +import XEUtils from 'xe-utils'; +import type { + VxeGridInstance, + VxeGridEventProps, + GridMethods, + TableMethods, + TableEditMethods, + TableValidatorMethods, +} from 'vxe-table'; +import { Grid as VxeGrid } from 'vxe-table'; + +import { extendSlots } from '/@/utils/helper/tsxHelper'; +import { gridComponentMethodKeys } from './methods'; +import { omit } from 'lodash-es'; + +export default defineComponent({ + name: 'VxeBasicTable', + props: basicProps, + emits: basicEmits, + setup(props, { emit, attrs }) { + const tableElRef = ref(); + const emitEvents: VxeGridEventProps = {}; + + const extendTableMethods = (methodKeys) => { + const funcs: any = {}; + methodKeys.forEach((name) => { + funcs[name] = (...args: any[]) => { + const $vxegrid: any = tableElRef.value; + if ($vxegrid && $vxegrid[name]) { + return $vxegrid[name](...args); + } + }; + }); + + return funcs; + }; + + const gridExtendTableMethods = extendTableMethods(gridComponentMethodKeys) as GridMethods & + TableMethods & + TableEditMethods & + TableValidatorMethods; + + basicEmits.forEach((name) => { + const type = XEUtils.camelCase(`on-${name}`) as keyof VxeGridEventProps; + + emitEvents[type] = (...args: any[]) => emit(name, ...args); + }); + + /** + * @description: 二次封装需要的所有属性 + * 1.部分属性需要和全局属性进行合并 + */ + const getBindValues = computed(() => { + const propsData: BasicTableProps = { + ...attrs, + ...props, + }; + + return propsData; + }); + + /** + * @description: Table 所有属性 + */ + const getBindGridValues = computed(() => { + const omitProps = omit(getBindValues.value, ignorePropKeys); + + return { + ...omitProps, + ...getBindGridEvent, + }; + }); + + /** + * @description: 组件外层class + */ + const getWrapperClass = computed(() => { + return [attrs.class]; + }); + + /** + * @description: 重写Vxe-table 方法 + */ + const getBindGridEvent: VxeGridEventProps = { + ...emitEvents, + }; + + return { + getWrapperClass, + getBindGridValues, + tableElRef, + ...gridExtendTableMethods, + }; + }, + render() { + const { tableClass, tableStyle } = this.$props; + + return ( +
    + + {extendSlots(this.$slots)} + +
    + ); + }, +}); diff --git a/src/components/VxeTable/src/componentMap.ts b/src/components/VxeTable/src/componentMap.ts new file mode 100644 index 0000000..d1ca62e --- /dev/null +++ b/src/components/VxeTable/src/componentMap.ts @@ -0,0 +1,59 @@ +import type { Component } from 'vue'; + +import type { ComponentType } from './componentType'; +import { ApiSelect, ApiTreeSelect } from '/@/components/Form'; +import { + Input, + Select, + Radio, + Checkbox, + AutoComplete, + Cascader, + DatePicker, + InputNumber, + Switch, + TimePicker, + TreeSelect, + Rate, + Empty, +} from 'ant-design-vue'; +import { Button } from '/@/components/Button'; + +const componentMap = new Map(); + +componentMap.set('AButton', Button); + +componentMap.set('AInput', Input); +componentMap.set('AInputSearch', Input.Search); +componentMap.set('AInputNumber', InputNumber); +componentMap.set('AAutoComplete', AutoComplete); + +componentMap.set('ASelect', Select); +componentMap.set('ATreeSelect', TreeSelect); +componentMap.set('ASwitch', Switch); +componentMap.set('ARadioGroup', Radio.Group); +componentMap.set('ACheckboxGroup', Checkbox.Group); +componentMap.set('ACascader', Cascader); +componentMap.set('ARate', Rate); + +componentMap.set('ADatePicker', DatePicker); +componentMap.set('AMonthPicker', DatePicker.MonthPicker); +componentMap.set('ARangePicker', DatePicker.RangePicker); +componentMap.set('AWeekPicker', DatePicker.WeekPicker); +componentMap.set('AYearPicker', DatePicker.YearPicker); +componentMap.set('ATimePicker', TimePicker); + +componentMap.set('AApiSelect', ApiSelect); +componentMap.set('AApiTreeSelect', ApiTreeSelect); + +componentMap.set('AEmpty', Empty); + +export function add(compName: ComponentType, component: Component) { + componentMap.set(compName, component); +} + +export function del(compName: ComponentType) { + componentMap.delete(compName); +} + +export { componentMap }; diff --git a/src/components/VxeTable/src/componentType.ts b/src/components/VxeTable/src/componentType.ts new file mode 100644 index 0000000..4a55e64 --- /dev/null +++ b/src/components/VxeTable/src/componentType.ts @@ -0,0 +1,22 @@ +export type ComponentType = + | 'AInput' + | 'AInputNumber' + | 'ASelect' + | 'AApiSelect' + | 'ATreeSelect' + | 'AApiTreeSelect' + | 'ARadioGroup' + | 'ACheckboxGroup' + | 'AAutoComplete' + | 'ACascader' + | 'ADatePicker' + | 'AMonthPicker' + | 'ARangePicker' + | 'AWeekPicker' + | 'ATimePicker' + | 'AYearPicker' + | 'ASwitch' + | 'ARate' + | 'AInputSearch' + | 'AButton' + | 'AEmpty'; diff --git a/src/components/VxeTable/src/components/AApiSelect.tsx b/src/components/VxeTable/src/components/AApiSelect.tsx new file mode 100644 index 0000000..8fb1d3d --- /dev/null +++ b/src/components/VxeTable/src/components/AApiSelect.tsx @@ -0,0 +1,20 @@ +import XEUtils from 'xe-utils'; +import { createDefaultRender, createEditRender, createFormItemRender } from './common'; + +export default { + renderDefault: createDefaultRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), + renderEdit: createEditRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), + renderItemContent: createFormItemRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), +}; diff --git a/src/components/VxeTable/src/components/AApiTreeSelect.tsx b/src/components/VxeTable/src/components/AApiTreeSelect.tsx new file mode 100644 index 0000000..8fb1d3d --- /dev/null +++ b/src/components/VxeTable/src/components/AApiTreeSelect.tsx @@ -0,0 +1,20 @@ +import XEUtils from 'xe-utils'; +import { createDefaultRender, createEditRender, createFormItemRender } from './common'; + +export default { + renderDefault: createDefaultRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), + renderEdit: createEditRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), + renderItemContent: createFormItemRender({}, (_, params) => { + return { + params: XEUtils.get(params, 'row'), + }; + }), +}; diff --git a/src/components/VxeTable/src/components/AAutoComplete.tsx b/src/components/VxeTable/src/components/AAutoComplete.tsx new file mode 100644 index 0000000..41ca4a4 --- /dev/null +++ b/src/components/VxeTable/src/components/AAutoComplete.tsx @@ -0,0 +1,16 @@ +import { + createEditRender, + createDefaultRender, + createFilterRender, + createDefaultFilterRender, + createFormItemRender, +} from './common'; + +export default { + autofocus: 'input.ant-input', + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter: createFilterRender(), + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/AButton.tsx b/src/components/VxeTable/src/components/AButton.tsx new file mode 100644 index 0000000..67468d1 --- /dev/null +++ b/src/components/VxeTable/src/components/AButton.tsx @@ -0,0 +1,120 @@ +import { h } from 'vue'; +import { + FormItemContentRenderParams, + FormItemRenderOptions, + VxeGlobalRendererHandles, +} from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { cellText, createEvents, createProps, getComponent } from './common'; + +const COMPONENT_NAME = 'AButton'; + +export function createEditRender() { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderEditOptions, + params: VxeGlobalRendererHandles.RenderEditParams, + ) { + const { attrs } = renderOpts; + const Component = getComponent(COMPONENT_NAME); + + return [ + h(Component, { + ...attrs, + ...createProps(renderOpts, null), + ...createEvents(renderOpts, params), + }), + ]; + }; +} + +export function createDefaultRender() { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderEditOptions, + params: VxeGlobalRendererHandles.RenderEditParams, + ) { + const { attrs } = renderOpts; + const Component = getComponent(COMPONENT_NAME); + + return [ + h( + Component, + { + ...attrs, + ...createProps(renderOpts, null), + ...createEvents(renderOpts, params), + }, + cellText(renderOpts.content), + ), + ]; + }; +} + +export function createFormItemRender() { + return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) { + const { attrs, content } = renderOpts; + const { property, $form, data } = params; + const props = createProps(renderOpts, null); + const Component = getComponent(COMPONENT_NAME); + + return [ + h( + Component, + { + ...attrs, + ...props, + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + XEUtils.set(data, property, value); + }, + () => { + // 处理 change 事件相关逻辑 + $form.updateStatus({ + ...params, + field: property, + }); + }, + ), + }, + { + default: () => cellText(content || props.content), + }, + ), + ]; + }; +} + +function createToolbarButtonRender() { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderToolOptions, + params: VxeGlobalRendererHandles.RenderButtonParams, + ) { + const { attrs } = renderOpts; + const { button } = params; + const props = createProps(renderOpts, null); + const Component = getComponent(COMPONENT_NAME); + + return [ + h( + Component, + { + ...attrs, + ...props, + ...createEvents(renderOpts, params), + }, + { + default: () => cellText(button?.content || props.content), + }, + ), + ]; + }; +} + +export default { + renderEdit: createEditRender(), + renderDefault: createDefaultRender(), + renderItemContent: createFormItemRender(), + renderToolbarButton: createToolbarButtonRender(), +}; diff --git a/src/components/VxeTable/src/components/AButtonGroup.tsx b/src/components/VxeTable/src/components/AButtonGroup.tsx new file mode 100644 index 0000000..ed0fc84 --- /dev/null +++ b/src/components/VxeTable/src/components/AButtonGroup.tsx @@ -0,0 +1,59 @@ +import { + FormItemContentRenderParams, + FormItemRenderOptions, + VxeGlobalRendererHandles, +} from 'vxe-table'; +import { createDefaultRender, createEditRender, createFormItemRender } from './AButton'; + +function createEditButtonRender() { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderEditOptions, + params: VxeGlobalRendererHandles.RenderEditParams, + ) { + const buttonEditRender = createEditRender(); + const { children } = renderOpts; + if (children) { + return children.map( + (childRenderOpts: VxeGlobalRendererHandles.RenderEditOptions) => + buttonEditRender(childRenderOpts, params)[0], + ); + } + return []; + }; +} + +function createDefaultButtonRender() { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions, + params: VxeGlobalRendererHandles.RenderDefaultParams, + ) { + const buttonDefaultRender = createDefaultRender(); + const { children } = renderOpts; + if (children) { + return children.map( + (childRenderOpts: VxeGlobalRendererHandles.RenderDefaultOptions) => + buttonDefaultRender(childRenderOpts, params)[0], + ); + } + return []; + }; +} + +function createButtonItemRender() { + return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) { + const buttonItemRender = createFormItemRender(); + const { children } = renderOpts; + if (children) { + return children.map( + (childRenderOpts: FormItemRenderOptions) => buttonItemRender(childRenderOpts, params)[0], + ); + } + return []; + }; +} + +export default { + renderEdit: createEditButtonRender(), + renderDefault: createDefaultButtonRender(), + renderItemContent: createButtonItemRender(), +}; diff --git a/src/components/VxeTable/src/components/ACascader.tsx b/src/components/VxeTable/src/components/ACascader.tsx new file mode 100644 index 0000000..650f32f --- /dev/null +++ b/src/components/VxeTable/src/components/ACascader.tsx @@ -0,0 +1,42 @@ +import { VxeGlobalRendererHandles } from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { + createEditRender, + createCellRender, + createFormItemRender, + createExportMethod, +} from './common'; + +function matchCascaderData(index: number, list: any[], values: any[], labels: any[]) { + const val = values[index]; + if (list && values.length > index) { + XEUtils.each(list, (item) => { + if (item.value === val) { + labels.push(item.label); + matchCascaderData(++index, item.children, values, labels); + } + }); + } +} + +function getCascaderCellValue( + renderOpts: VxeGlobalRendererHandles.RenderOptions, + params: VxeGlobalRendererHandles.RenderCellParams, +) { + const { props = {} } = renderOpts; + const { row, column } = params; + const cellValue = XEUtils.get(row, column.field as string); + const values = cellValue || []; + const labels: Array = []; + matchCascaderData(0, props.options, values, labels); + return ( + props.showAllLevels === false ? labels.slice(labels.length - 1, labels.length) : labels + ).join(` ${props.separator || '/'} `); +} + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getCascaderCellValue), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getCascaderCellValue), +}; diff --git a/src/components/VxeTable/src/components/ACheckboxGroup.tsx b/src/components/VxeTable/src/components/ACheckboxGroup.tsx new file mode 100644 index 0000000..d01092a --- /dev/null +++ b/src/components/VxeTable/src/components/ACheckboxGroup.tsx @@ -0,0 +1,5 @@ +import { createFormItemRender } from './common'; + +export default { + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/ADatePicker.tsx b/src/components/VxeTable/src/components/ADatePicker.tsx new file mode 100644 index 0000000..3e90638 --- /dev/null +++ b/src/components/VxeTable/src/components/ADatePicker.tsx @@ -0,0 +1,33 @@ +import { VxeGlobalRendererHandles } from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { + createCellRender, + createEditRender, + createExportMethod, + createFormItemRender, +} from './common'; + +export function getDatePickerCellValue( + renderOpts: VxeGlobalRendererHandles.RenderOptions, + params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams, + defaultFormat: string, +) { + const { props = {} } = renderOpts; + const { row, column } = params; + let cellValue = XEUtils.get(row, column.field as string); + if (cellValue) { + cellValue = cellValue.format(props.format || defaultFormat); + } + return cellValue; +} + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getDatePickerCellValue, () => { + return ['YYYY-MM-DD']; + }), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getDatePickerCellValue, () => { + return ['YYYY-MM-DD']; + }), +}; diff --git a/src/components/VxeTable/src/components/AEmpty.tsx b/src/components/VxeTable/src/components/AEmpty.tsx new file mode 100644 index 0000000..aed5007 --- /dev/null +++ b/src/components/VxeTable/src/components/AEmpty.tsx @@ -0,0 +1,27 @@ +import { h } from 'vue'; +import { VxeGlobalRendererHandles } from 'vxe-table'; +import { getComponent } from './common'; + +function createEmptyRender() { + return function (renderOpts: VxeGlobalRendererHandles.RenderEmptyOptions) { + const { name, attrs, props } = renderOpts; + + const Component = getComponent(name); + return [ + h( + 'div', + { + class: 'flex items-center justify-center', + }, + h(Component, { + ...attrs, + ...props, + }), + ), + ]; + }; +} + +export default { + renderEmpty: createEmptyRender(), +}; diff --git a/src/components/VxeTable/src/components/AInput.tsx b/src/components/VxeTable/src/components/AInput.tsx new file mode 100644 index 0000000..41ca4a4 --- /dev/null +++ b/src/components/VxeTable/src/components/AInput.tsx @@ -0,0 +1,16 @@ +import { + createEditRender, + createDefaultRender, + createFilterRender, + createDefaultFilterRender, + createFormItemRender, +} from './common'; + +export default { + autofocus: 'input.ant-input', + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter: createFilterRender(), + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/AInputNumber.tsx b/src/components/VxeTable/src/components/AInputNumber.tsx new file mode 100644 index 0000000..22f299e --- /dev/null +++ b/src/components/VxeTable/src/components/AInputNumber.tsx @@ -0,0 +1,16 @@ +import { + createEditRender, + createFilterRender, + createFormItemRender, + createDefaultFilterRender, + createDefaultRender, +} from './common'; + +export default { + autofocus: 'input.ant-input-number-input', + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter: createFilterRender(), + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/AInputSearch.tsx b/src/components/VxeTable/src/components/AInputSearch.tsx new file mode 100644 index 0000000..e365ef3 --- /dev/null +++ b/src/components/VxeTable/src/components/AInputSearch.tsx @@ -0,0 +1,17 @@ +import { + createEditRender, + createDefaultRender, + createFilterRender, + createDefaultFilterRender, + createFormItemRender, + createToolbarToolRender, +} from './common'; + +export default { + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter: createFilterRender(), + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), + renderToolbarTool: createToolbarToolRender(), +}; diff --git a/src/components/VxeTable/src/components/AMonthPicker.tsx b/src/components/VxeTable/src/components/AMonthPicker.tsx new file mode 100644 index 0000000..f46bbae --- /dev/null +++ b/src/components/VxeTable/src/components/AMonthPicker.tsx @@ -0,0 +1,18 @@ +import { getDatePickerCellValue } from './ADatePicker'; +import { + createCellRender, + createEditRender, + createExportMethod, + createFormItemRender, +} from './common'; + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getDatePickerCellValue, () => { + return ['YYYY-MM']; + }), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getDatePickerCellValue, () => { + return ['YYYY-MM']; + }), +}; diff --git a/src/components/VxeTable/src/components/ARadioGroup.tsx b/src/components/VxeTable/src/components/ARadioGroup.tsx new file mode 100644 index 0000000..d01092a --- /dev/null +++ b/src/components/VxeTable/src/components/ARadioGroup.tsx @@ -0,0 +1,5 @@ +import { createFormItemRender } from './common'; + +export default { + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/ARangePicker.tsx b/src/components/VxeTable/src/components/ARangePicker.tsx new file mode 100644 index 0000000..ce0da2c --- /dev/null +++ b/src/components/VxeTable/src/components/ARangePicker.tsx @@ -0,0 +1,30 @@ +import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { + createCellRender, + createEditRender, + createExportMethod, + createFormItemRender, +} from './common'; + +function getRangePickerCellValue( + renderOpts: VxeColumnPropTypes.EditRender, + params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams, +) { + const { props = {} } = renderOpts; + const { row, column } = params; + let cellValue = XEUtils.get(row, column.field as string); + if (cellValue) { + cellValue = XEUtils.map(cellValue, (date: any) => + date.format(props.format || 'YYYY-MM-DD'), + ).join(' ~ '); + } + return cellValue; +} + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getRangePickerCellValue), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getRangePickerCellValue), +}; diff --git a/src/components/VxeTable/src/components/ARate.tsx b/src/components/VxeTable/src/components/ARate.tsx new file mode 100644 index 0000000..3ec3f6b --- /dev/null +++ b/src/components/VxeTable/src/components/ARate.tsx @@ -0,0 +1,15 @@ +import { + createEditRender, + createDefaultRender, + createFilterRender, + createDefaultFilterRender, + createFormItemRender, +} from './common'; + +export default { + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter: createFilterRender(), + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/ASelect.tsx b/src/components/VxeTable/src/components/ASelect.tsx new file mode 100644 index 0000000..2785fe7 --- /dev/null +++ b/src/components/VxeTable/src/components/ASelect.tsx @@ -0,0 +1,271 @@ +import { ComponentOptions, h, resolveComponent } from 'vue'; +import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { + cellText, + createCellRender, + createEvents, + createProps, + isEmptyValue, + createExportMethod, + createFormItemRender, +} from './common'; + +function renderOptions(options: any[], optionProps: VxeGlobalRendererHandles.RenderOptionProps) { + const labelProp = optionProps.label || 'label'; + const valueProp = optionProps.value || 'value'; + return XEUtils.map(options, (item, oIndex) => { + return h( + resolveComponent('a-select-option') as ComponentOptions, + { + key: oIndex, + value: item[valueProp], + disabled: item.disabled, + }, + { + default: () => cellText(item[labelProp]), + }, + ); + }); +} + +function createEditRender() { + return function ( + renderOpts: VxeColumnPropTypes.EditRender, + params: VxeGlobalRendererHandles.RenderEditParams, + ) { + const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts; + const { row, column, $table } = params; + const { attrs } = renderOpts; + const cellValue = XEUtils.get(row, column.field as string); + const props = createProps(renderOpts, cellValue); + const ons = createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + XEUtils.set(row, column.field as string, value); + }, + () => { + // 处理 change 事件相关逻辑 + $table.updateStatus(params); + }, + ); + if (optionGroups) { + const groupOptions = optionGroupProps.options || 'options'; + const groupLabel = optionGroupProps.label || 'label'; + return [ + h( + resolveComponent('a-select') as ComponentOptions, + { + ...attrs, + ...props, + ...ons, + }, + { + default: () => { + return XEUtils.map(optionGroups, (group, gIndex) => { + return h( + resolveComponent('a-select-opt-group') as ComponentOptions, + { + key: gIndex, + }, + { + label: () => { + return h('span', {}, group[groupLabel]); + }, + default: () => renderOptions(group[groupOptions], optionProps), + }, + ); + }); + }, + }, + ), + ]; + } + return [ + h( + resolveComponent('a-select') as ComponentOptions, + { + ...props, + ...attrs, + ...ons, + }, + { + default: () => renderOptions(options, optionProps), + }, + ), + ]; + }; +} + +function getSelectCellValue( + renderOpts: VxeGlobalRendererHandles.RenderCellOptions, + params: VxeGlobalRendererHandles.RenderCellParams, +) { + const { + options = [], + optionGroups, + props = {}, + optionProps = {}, + optionGroupProps = {}, + } = renderOpts; + const { row, column } = params; + const labelProp = optionProps.label || 'label'; + const valueProp = optionProps.value || 'value'; + const groupOptions = optionGroupProps.options || 'options'; + const cellValue = XEUtils.get(row, column.field as string); + if (!isEmptyValue(cellValue)) { + return XEUtils.map( + props.mode === 'multiple' ? cellValue : [cellValue], + optionGroups + ? (value) => { + let selectItem; + for (let index = 0; index < optionGroups.length; index++) { + selectItem = XEUtils.find( + optionGroups[index][groupOptions], + (item) => item[valueProp] === value, + ); + if (selectItem) { + break; + } + } + return selectItem ? selectItem[labelProp] : value; + } + : (value) => { + const selectItem = XEUtils.find(options, (item) => item[valueProp] === value); + return selectItem ? selectItem[labelProp] : value; + }, + ).join(', '); + } + return ''; +} + +function createFilterRender() { + return function ( + renderOpts: VxeColumnPropTypes.FilterRender, + params: VxeGlobalRendererHandles.RenderFilterParams, + ) { + const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts; + const groupOptions = optionGroupProps.options || 'options'; + const groupLabel = optionGroupProps.label || 'label'; + const { column } = params; + const { attrs } = renderOpts; + + return [ + h( + 'div', + { + class: 'vxe-table--filter-antd-wrapper', + }, + optionGroups + ? column.filters.map((option, oIndex) => { + const optionValue = option.data; + const props = createProps(renderOpts, optionValue); + + return h( + resolveComponent('a-select') as ComponentOptions, + { + key: oIndex, + ...attrs, + ...props, + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + option.data = value; + }, + () => { + // 处理 change 事件相关逻辑 + const { $panel } = params; + $panel.changeOption( + null, + props.mode === 'multiple' + ? option.data && option.data.length > 0 + : !XEUtils.eqNull(option.data), + option, + ); + }, + ), + }, + { + default: () => { + return XEUtils.map(optionGroups, (group, gIndex) => { + return h( + resolveComponent('a-select-opt-group') as ComponentOptions, + { + key: gIndex, + }, + { + label: () => { + return h('span', {}, group[groupLabel]); + }, + default: () => renderOptions(group[groupOptions], optionProps), + }, + ); + }); + }, + }, + ); + }) + : column.filters.map((option, oIndex) => { + const optionValue = option.data; + const props = createProps(renderOpts, optionValue); + return h( + resolveComponent('a-select') as ComponentOptions, + { + key: oIndex, + ...attrs, + ...props, + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + option.data = value; + }, + () => { + // 处理 change 事件相关逻辑 + const { $panel } = params; + $panel.changeOption( + null, + props.mode === 'multiple' + ? option.data && option.data.length > 0 + : !XEUtils.eqNull(option.data), + option, + ); + }, + ), + }, + { + default: () => renderOptions(options, optionProps), + }, + ); + }), + ), + ]; + }; +} + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getSelectCellValue), + renderFilter: createFilterRender(), + defaultFilterMethod(params) { + const { option, row, column } = params; + const { data } = option; + const { field, filterRender: renderOpts } = column; + const { props = {} } = renderOpts; + const cellValue = XEUtils.get(row, field); + if (props.mode === 'multiple') { + if (XEUtils.isArray(cellValue)) { + return XEUtils.includeArrays(cellValue, data); + } + return data.indexOf(cellValue) > -1; + } + return cellValue == data; + }, + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getSelectCellValue), +}; diff --git a/src/components/VxeTable/src/components/ASwitch.tsx b/src/components/VxeTable/src/components/ASwitch.tsx new file mode 100644 index 0000000..634ab7f --- /dev/null +++ b/src/components/VxeTable/src/components/ASwitch.tsx @@ -0,0 +1,53 @@ +import { h } from 'vue'; +import XEUtils from 'xe-utils'; +import { + createEditRender, + createDefaultRender, + createProps, + createEvents, + createDefaultFilterRender, + createFormItemRender, + getComponent, +} from './common'; + +export default { + renderDefault: createDefaultRender(), + renderEdit: createEditRender(), + renderFilter(renderOpts, params) { + const { column } = params; + const { name, attrs } = renderOpts; + const Component = getComponent(name); + + return [ + h( + 'div', + { + class: 'vxe-table--filter-antd-wrapper', + }, + column.filters.map((option, oIndex) => { + const optionValue = option.data; + return h(Component, { + key: oIndex, + ...attrs, + ...createProps(renderOpts, optionValue), + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + option.data = value; + }, + () => { + // 处理 change 事件相关逻辑 + const { $panel } = params; + $panel.changeOption(null, XEUtils.isBoolean(option.data), option); + }, + ), + }); + }), + ), + ]; + }, + defaultFilterMethod: createDefaultFilterRender(), + renderItemContent: createFormItemRender(), +}; diff --git a/src/components/VxeTable/src/components/ATimePicker.tsx b/src/components/VxeTable/src/components/ATimePicker.tsx new file mode 100644 index 0000000..7d2be54 --- /dev/null +++ b/src/components/VxeTable/src/components/ATimePicker.tsx @@ -0,0 +1,18 @@ +import { getDatePickerCellValue } from './ADatePicker'; +import { + createEditRender, + createCellRender, + createFormItemRender, + createExportMethod, +} from './common'; + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getDatePickerCellValue, () => { + return ['HH:mm:ss']; + }), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getDatePickerCellValue, () => { + return ['HH:mm:ss']; + }), +}; diff --git a/src/components/VxeTable/src/components/ATreeSelect.tsx b/src/components/VxeTable/src/components/ATreeSelect.tsx new file mode 100644 index 0000000..5cb577a --- /dev/null +++ b/src/components/VxeTable/src/components/ATreeSelect.tsx @@ -0,0 +1,35 @@ +import { VxeGlobalRendererHandles } from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { + createEditRender, + createCellRender, + isEmptyValue, + createFormItemRender, + createExportMethod, +} from './common'; + +function getTreeSelectCellValue( + renderOpts: VxeGlobalRendererHandles.RenderOptions, + params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams, +) { + const { props = {} } = renderOpts; + const { treeData, treeCheckable } = props; + const { row, column } = params; + const cellValue = XEUtils.get(row, column.field as string); + if (!isEmptyValue(cellValue)) { + return XEUtils.map(treeCheckable ? cellValue : [cellValue], (value) => { + const matchObj = XEUtils.findTree(treeData, (item: any) => item.value === value, { + children: 'children', + }); + return matchObj ? matchObj.item.title : value; + }).join(', '); + } + return cellValue; +} + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getTreeSelectCellValue), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getTreeSelectCellValue), +}; diff --git a/src/components/VxeTable/src/components/AWeekPicker.tsx b/src/components/VxeTable/src/components/AWeekPicker.tsx new file mode 100644 index 0000000..97b34e5 --- /dev/null +++ b/src/components/VxeTable/src/components/AWeekPicker.tsx @@ -0,0 +1,18 @@ +import { getDatePickerCellValue } from './ADatePicker'; +import { + createEditRender, + createCellRender, + createFormItemRender, + createExportMethod, +} from './common'; + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getDatePickerCellValue, () => { + return ['YYYY-WW周']; + }), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getDatePickerCellValue, () => { + return ['YYYY-WW周']; + }), +}; diff --git a/src/components/VxeTable/src/components/AYearPicker.tsx b/src/components/VxeTable/src/components/AYearPicker.tsx new file mode 100644 index 0000000..6e73c19 --- /dev/null +++ b/src/components/VxeTable/src/components/AYearPicker.tsx @@ -0,0 +1,18 @@ +import { getDatePickerCellValue } from './ADatePicker'; +import { + createEditRender, + createCellRender, + createFormItemRender, + createExportMethod, +} from './common'; + +export default { + renderEdit: createEditRender(), + renderCell: createCellRender(getDatePickerCellValue, () => { + return ['YYYY']; + }), + renderItemContent: createFormItemRender(), + exportMethod: createExportMethod(getDatePickerCellValue, () => { + return ['YYYY']; + }), +}; diff --git a/src/components/VxeTable/src/components/common.tsx b/src/components/VxeTable/src/components/common.tsx new file mode 100644 index 0000000..f2ba1e3 --- /dev/null +++ b/src/components/VxeTable/src/components/common.tsx @@ -0,0 +1,427 @@ +import { ComponentOptions, h } from 'vue'; +import { + FormItemContentRenderParams, + FormItemRenderOptions, + VxeGlobalRendererHandles, +} from 'vxe-table'; +import XEUtils from 'xe-utils'; +import { componentMap } from '../componentMap'; +import { ComponentType } from '../componentType'; +import { createPlaceholderMessage } from '../helper'; + +/** + * @description: 获取组件 + */ +export function getComponent(componentName) { + const Component = componentMap.get(componentName as ComponentType); + if (!Component) throw `您还没注册此组件 ${componentName}`; + return Component as ComponentOptions; +} + +export function isEmptyValue(cellValue: any) { + return cellValue === null || cellValue === undefined || cellValue === ''; +} + +export function formatText(cellValue: any) { + return '' + (isEmptyValue(cellValue) ? '' : cellValue); +} + +export function cellText(cellValue: any): string[] { + return [formatText(cellValue)]; +} + +/** + * @description: 方法名转换 + */ +export function getOnName(type: string) { + return 'on' + type.substring(0, 1).toLocaleUpperCase() + type.substring(1); +} + +/** + * @description: 获取组件传值所接受的属性 + */ +function getModelKey(renderOpts: VxeGlobalRendererHandles.RenderOptions) { + let prop = 'value'; + switch (renderOpts.name) { + case 'ASwitch': + prop = 'checked'; + break; + } + return prop; +} + +/** + * @description: 回去双向更新的方法 + */ +function getModelEvent(renderOpts: VxeGlobalRendererHandles.RenderOptions) { + let type = 'update:value'; + switch (renderOpts.name) { + case 'ASwitch': + type = 'update:checked'; + break; + } + return type; +} + +/** + * @description: chang值改变方法 + * @param {} + * @return {*} + * @author: * + */ +function getChangeEvent() { + return 'change'; +} + +function getClickEvent() { + return 'click'; +} +/** + * @description: 获取方法 + * @param {} + * @return {*} + * @author: * + */ +export function createEvents( + renderOpts: VxeGlobalRendererHandles.RenderOptions, + params: VxeGlobalRendererHandles.RenderParams, + inputFunc?: Function, + changeFunc?: Function, + clickFunc?: Function, +) { + const { events } = renderOpts; + const modelEvent = getModelEvent(renderOpts); + const changeEvent = getChangeEvent(); + const clickEvent = getClickEvent(); + const isSameEvent = changeEvent === modelEvent; + const ons: { [type: string]: Function } = {}; + + XEUtils.objectEach(events, (func: Function, key: string) => { + ons[getOnName(key)] = function (...args: any[]) { + func(params, ...args); + }; + }); + if (inputFunc) { + ons[getOnName(modelEvent)] = function (targetEvnt: any) { + inputFunc(targetEvnt); + if (events && events[modelEvent]) { + events[modelEvent](params, targetEvnt); + } + if (isSameEvent && changeFunc) { + changeFunc(targetEvnt); + } + }; + } + if (!isSameEvent && changeFunc) { + ons[getOnName(changeEvent)] = function (...args: any[]) { + changeFunc(...args); + if (events && events[changeEvent]) { + events[changeEvent](params, ...args); + } + }; + } + if (clickFunc) { + ons[getOnName(clickEvent)] = function (...args: any[]) { + clickFunc(...args); + if (events && events[clickEvent]) { + events[clickEvent](params, ...args); + } + }; + } + return ons; +} + +/** + * @description: 获取属性 + */ +export function createProps( + renderOpts: VxeGlobalRendererHandles.RenderOptions, + value: any, + defaultProps?: { [prop: string]: any }, +) { + const name = renderOpts.name as ComponentType; + return XEUtils.assign( + { + placeholder: createPlaceholderMessage(name), + allowClear: true, + }, + defaultProps, + renderOpts.props, + { + [getModelKey(renderOpts)]: value, + }, + ); +} + +/** + * @description: 创建单元格默认显示内容 + */ +export function createDefaultRender( + defaultProps?: { [key: string]: any }, + callBack?: ( + renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions, + params: VxeGlobalRendererHandles.RenderDefaultParams, + ) => Record, +) { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions, + params: VxeGlobalRendererHandles.RenderDefaultParams, + ) { + const { row, column, $table } = params; + const { name, attrs } = renderOpts; + const cellValue = XEUtils.get(row, column.field as string); + const args = (callBack && callBack(renderOpts, params)) ?? {}; + + const Component = getComponent(name); + return [ + h(Component, { + ...attrs, + ...createProps(renderOpts, cellValue, defaultProps), + ...args, + ...createEvents( + renderOpts, + params, + (value: any) => XEUtils.set(row, column.field as string, value), + () => $table.updateStatus(params), + ), + }), + ]; + }; +} + +/** + * @description: 创建编辑单元格 + */ +export function createEditRender( + defaultProps?: { [key: string]: any }, + callBack?: ( + renderOpts: VxeGlobalRendererHandles.RenderEditOptions, + params: VxeGlobalRendererHandles.RenderEditParams, + ) => Record, +) { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderEditOptions, + params: VxeGlobalRendererHandles.RenderEditParams, + ) { + const { row, column, $table } = params; + const { name, attrs } = renderOpts; + const cellValue = XEUtils.get(row, column.field as string); + const args = (callBack && callBack(renderOpts, params)) ?? {}; + + const Component = getComponent(name); + return [ + h(Component, { + ...attrs, + ...createProps(renderOpts, cellValue, defaultProps), + ...args, + ...createEvents( + renderOpts, + params, + (value: any) => XEUtils.set(row, column.field as string, value), + () => $table.updateStatus(params), + ), + }), + ]; + }; +} + +/** + * @description: 创建筛选渲染内容 + */ +export function createFilterRender( + defaultProps?: { [key: string]: any }, + callBack?: ( + renderOpts: VxeGlobalRendererHandles.RenderFilterOptions, + params: VxeGlobalRendererHandles.RenderFilterParams, + ) => Record, +) { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderFilterOptions, + params: VxeGlobalRendererHandles.RenderFilterParams, + ) { + const { column } = params; + const { name, attrs } = renderOpts; + const args = (callBack && callBack(renderOpts, params)) ?? {}; + + const Component = getComponent(name); + return [ + h( + 'div', + { + class: 'vxe-table--filter-antd-wrapper', + }, + column.filters.map((option, oIndex) => { + const optionValue = option.data; + const checked = !!option.data; + + return h(Component, { + key: oIndex, + ...attrs, + ...createProps(renderOpts, optionValue, defaultProps), + ...args, + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + option.data = value; + }, + () => { + // 处理 change 事件相关逻辑 + const { $panel } = params; + $panel.changeOption(null, checked, option); + }, + ), + }); + }), + ), + ]; + }; +} + +/** + * @description: 默认过滤 + * @param {} + * @return {*} + * @author: * + */ + +export function createDefaultFilterRender() { + return function (params: VxeGlobalRendererHandles.FilterMethodParams) { + const { option, row, column } = params; + const { data } = option; + const cellValue = XEUtils.get(row, column.field as string); + return cellValue === data; + }; +} + +/** + * @description: 创建 form表单渲染 + */ +export function createFormItemRender( + defaultProps?: { [key: string]: any }, + callBack?: ( + renderOpts: FormItemRenderOptions, + params: FormItemContentRenderParams, + ) => Record, +) { + return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) { + const args = (callBack && callBack(renderOpts, params)) ?? {}; + const { data, property, $form } = params; + const { name } = renderOpts; + const { attrs } = renderOpts; + const itemValue = XEUtils.get(data, property); + + const Component = getComponent(name); + return [ + h(Component, { + ...attrs, + ...createProps(renderOpts, itemValue, defaultProps), + ...args, + ...createEvents( + renderOpts, + params, + (value: any) => { + // 处理 model 值双向绑定 + XEUtils.set(data, property, value); + }, + () => { + // 处理 change 事件相关逻辑 + $form.updateStatus({ + ...params, + field: property, + }); + }, + ), + }), + ]; + }; +} + +/** + * @description: cell渲染 + */ +export function createCellRender( + getSelectCellValue: Function, + callBack?: ( + renderOpts: VxeGlobalRendererHandles.RenderCellOptions, + params: VxeGlobalRendererHandles.RenderCellParams, + ) => Array, +) { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderCellOptions, + params: VxeGlobalRendererHandles.RenderCellParams, + ) { + const args = (callBack && callBack(renderOpts, params)) ?? []; + const cellLabel = getSelectCellValue && getSelectCellValue(renderOpts, params, ...args); + const { placeholder } = renderOpts; + + return [ + h( + 'span', + { + class: 'vxe-cell--label', + }, + placeholder && isEmptyValue(cellLabel) + ? [ + h( + 'span', + { + class: 'vxe-cell--placeholder', + }, + formatText(placeholder), + ), + ] + : formatText(cellLabel), + ), + ]; + }; +} + +/** + * @description: 创建 导出渲染 + * @param {} + * @return {*} + * @author: * + */ +export function createExportMethod( + getExportCellValue: Function, + callBack?: (params: VxeGlobalRendererHandles.ExportMethodParams) => Array, +) { + return function (params: VxeGlobalRendererHandles.ExportMethodParams) { + const { row, column, options } = params; + const args = (callBack && callBack(params)) ?? []; + return options && options.original + ? XEUtils.get(row, column.field as string) + : getExportCellValue(column.editRender || column.cellRender, params, ...args); + }; +} + +/** + * @description: 创建单元格默认显示内容 + */ +export function createToolbarToolRender( + defaultProps?: { [key: string]: any }, + callBack?: ( + renderOpts: VxeGlobalRendererHandles.RenderToolOptions, + params: VxeGlobalRendererHandles.RenderToolParams, + ) => Record, +) { + return function ( + renderOpts: VxeGlobalRendererHandles.RenderToolOptions, + params: VxeGlobalRendererHandles.RenderToolParams, + ) { + const { name, attrs } = renderOpts; + const args = (callBack && callBack(renderOpts, params)) ?? {}; + + const Component = getComponent(name); + return [ + h(Component, { + ...attrs, + ...createProps(renderOpts, null, defaultProps), + ...args, + ...createEvents(renderOpts, params), + }), + ]; + }; +} diff --git a/src/components/VxeTable/src/components/index.tsx b/src/components/VxeTable/src/components/index.tsx new file mode 100644 index 0000000..ba8c6d8 --- /dev/null +++ b/src/components/VxeTable/src/components/index.tsx @@ -0,0 +1,114 @@ +import { VXETableCore, VxeGlobalInterceptorHandles } from 'vxe-table'; +import AAutoComplete from './AAutoComplete'; +import AInput from './AInput'; +import AInputNumber from './AInputNumber'; +import ASelect from './ASelect'; +import ACascader from './ACascader'; +import ADatePicker from './ADatePicker'; +import AMonthPicker from './AMonthPicker'; +import ARangePicker from './ARangePicker'; +import AWeekPicker from './AWeekPicker'; +import ATreeSelect from './ATreeSelect'; +import ATimePicker from './ATimePicker'; +import ARate from './ARate'; +import ASwitch from './ASwitch'; +import ARadioGroup from './ARadioGroup'; +import ACheckboxGroup from './ACheckboxGroup'; +import AButton from './AButton'; +import AButtonGroup from './AButtonGroup'; +import AApiSelect from './AApiSelect'; +import AApiTreeSelect from './AApiTreeSelect'; +import AEmpty from './AEmpty'; +import AInputSearch from './AInputSearch'; +import AYearPicker from './AYearPicker'; + +/** + * 检查触发源是否属于目标节点 + */ +function getEventTargetNode(evnt: any, container: HTMLElement, className: string) { + let targetElem; + let target = evnt.target; + while (target && target.nodeType && target !== document) { + if ( + className && + target.className && + target.className.split && + target.className.split(' ').indexOf(className) > -1 + ) { + targetElem = target; + } else if (target === container) { + return { flag: className ? !!targetElem : true, container, targetElem: targetElem }; + } + target = target.parentNode; + } + return { flag: false }; +} + +/** + * 事件兼容性处理 + */ +function handleClearEvent( + params: + | VxeGlobalInterceptorHandles.InterceptorClearFilterParams + | VxeGlobalInterceptorHandles.InterceptorClearActivedParams + | VxeGlobalInterceptorHandles.InterceptorClearAreasParams, +) { + const { $event } = params; + const bodyElem = document.body; + if ( + // 下拉框 + getEventTargetNode($event, bodyElem, 'ant-select-dropdown').flag || + // 级联 + getEventTargetNode($event, bodyElem, 'ant-cascader-menus').flag || + // 日期 + getEventTargetNode($event, bodyElem, 'ant-calendar-picker-container').flag || + // 时间选择 + getEventTargetNode($event, bodyElem, 'ant-time-picker-panel').flag + ) { + return false; + } +} + +/** + * 基于 vxe-table 表格的适配插件,用于兼容 ant-design-vue 组件库 + */ +export const VXETablePluginAntd = { + install(vxetablecore: VXETableCore) { + const { interceptor, renderer } = vxetablecore; + + renderer.mixin({ + AAutoComplete, + AInput, + AInputNumber, + ASelect, + ACascader, + ADatePicker, + AMonthPicker, + ARangePicker, + AWeekPicker, + ATimePicker, + ATreeSelect, + ARate, + ASwitch, + ARadioGroup, + ACheckboxGroup, + AButton, + AButtonGroup, + AApiSelect, + AApiTreeSelect, + AEmpty, + AInputSearch, + AYearPicker, + }); + + interceptor.add('event.clearFilter', handleClearEvent); + interceptor.add('event.clearActived', handleClearEvent); + interceptor.add('event.clearAreas', handleClearEvent); + }, +}; + +if (typeof window !== 'undefined' && window.VXETable && window.VXETable.use) { + window.VXETable.use(VXETablePluginAntd); +} + +export default VXETablePluginAntd; diff --git a/src/components/VxeTable/src/const.ts b/src/components/VxeTable/src/const.ts new file mode 100644 index 0000000..6827bb4 --- /dev/null +++ b/src/components/VxeTable/src/const.ts @@ -0,0 +1,4 @@ +/** + * @description: 传给vxe-table 时需要忽略的prop + */ +export const ignorePropKeys = ['tableClass', 'tableStyle']; diff --git a/src/components/VxeTable/src/css/common.scss b/src/components/VxeTable/src/css/common.scss new file mode 100644 index 0000000..a8eb58e --- /dev/null +++ b/src/components/VxeTable/src/css/common.scss @@ -0,0 +1,8 @@ +*, +::before, +::after { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: initial; +} diff --git a/src/components/VxeTable/src/css/component.scss b/src/components/VxeTable/src/css/component.scss new file mode 100644 index 0000000..a9f7ba2 --- /dev/null +++ b/src/components/VxeTable/src/css/component.scss @@ -0,0 +1,123 @@ +/* stylelint-disable scss/percent-placeholder-pattern */ +%ResetBorder { + border: 0; + box-shadow: none; +} + +%CompWidth { + & > .ant-input, + & > .ant-input-number, + & > .ant-select, + & > .ant-cascader-picker, + & > .ant-calendar-picker, + & > .ant-time-picker { + width: 100%; + } +} + +.vxe-form { + .vxe-form--item-content { + @extend %CompWidth; + } +} + +.vxe-table--filter-antd-wrapper { + & > .ant-input, + & > .ant-input-number, + & > .ant-select, + & > .ant-rate { + width: 180px; + } +} + +.vxe-cell, +.vxe-tree-cell { + @extend %CompWidth; + + & > .ant-rate { + vertical-align: bottom; + + .anticon-star { + display: block; + } + } +} + +.col--valid-error { + & > .vxe-cell, + & > .vxe-tree-cell { + & > .ant-input, + & > .ant-select .ant-input, + & > .ant-select .ant-select-selection, + & > .ant-input-number, + & > .ant-cascader-picker .ant-cascader-input, + & > .ant-calendar-picker .ant-calendar-picker-input { + box-shadow: none; + } + } +} + +.vxe-table.cell--highlight { + .vxe-cell, + .vxe-tree-cell { + & > .ant-input, + & > .ant-input-number { + @extend %ResetBorder; + + padding: 0; + } + + & > .ant-select { + .ant-input { + @extend %ResetBorder; + + padding: 0; + } + + .ant-select-selection { + @extend %ResetBorder; + + .ant-select-selection__rendered { + margin: 0; + } + } + } + + & > .ant-input-number { + .ant-input-number-input { + padding: 0; + } + + .ant-input-number-handler-wrap, + .ant-input-number-handler-down { + @extend %ResetBorder; + } + } + + & > .ant-cascader-picker { + .ant-input { + @extend %ResetBorder; + } + + .ant-cascader-picker-label { + padding: 0; + } + } + + & > .ant-calendar-picker { + .ant-calendar-picker-input { + @extend %ResetBorder; + + padding: 0; + } + } + + & > .ant-time-picker { + .ant-time-picker-input { + @extend %ResetBorder; + + padding: 0; + } + } + } +} \ No newline at end of file diff --git a/src/components/VxeTable/src/css/index.scss b/src/components/VxeTable/src/css/index.scss new file mode 100644 index 0000000..7f34cab --- /dev/null +++ b/src/components/VxeTable/src/css/index.scss @@ -0,0 +1,5 @@ +@import './common'; +@import './variable'; +@import './toolbar'; +@import './component'; +@import 'vxe-table/styles/index'; \ No newline at end of file diff --git a/src/components/VxeTable/src/css/scrollbar.scss b/src/components/VxeTable/src/css/scrollbar.scss new file mode 100644 index 0000000..4464aa2 --- /dev/null +++ b/src/components/VxeTable/src/css/scrollbar.scss @@ -0,0 +1,29 @@ +.vxe-grid_scrollbar { + ::-webkit-scrollbar { + width: 8px; + height: 8px; + } + + ::-webkit-scrollbar-track { + background-color: #fff; + } + + ::-webkit-scrollbar-thumb { + border: 1px solid #f1f1f1; + border-radius: 5px; + background-color: rgb(0 0 0 / 10%); + box-shadow: inset 0 0 6px rgb(0 0 0 / 30%); + } + + ::-webkit-scrollbar-thumb:hover { + background-color: #a8a8a8; + } + + ::-webkit-scrollbar-thumb:active { + background-color: #a8a8a8; + } + + ::-webkit-scrollbar-corner { + background-color: #fff; + } +} \ No newline at end of file diff --git a/src/components/VxeTable/src/css/toolbar.scss b/src/components/VxeTable/src/css/toolbar.scss new file mode 100644 index 0000000..4a8897b --- /dev/null +++ b/src/components/VxeTable/src/css/toolbar.scss @@ -0,0 +1,26 @@ +.vxe-toolbar .vxe-custom--option-wrapper .vxe-custom--footer { + display: flex; +} + +.vxe-toolbar .vxe-tools--wrapper, +.vxe-toolbar .vxe-tools--operate button:first-child { + margin: 0; + margin-left: 10px; +} + +.vxe-toolbar .vxe-tools--wrapper, +.vxe-toolbar .vxe-tools--operate .vxe-button { + margin-left: 10px; + border-radius: 0 !important; +} + +.vxe-toolbar .vxe-tools--wrapper, +.vxe-toolbar .vxe-tools--operate .vxe-custom--wrapper { + margin-left: 1px; + border-radius: 0 !important; +} + +.vxe-toolbar .vxe-tools--wrapper, +.vxe-toolbar .vxe-tools--operate .vxe-custom--wrapper .vxe-button { + margin-left: 10px; +} \ No newline at end of file diff --git a/src/components/VxeTable/src/css/variable.scss b/src/components/VxeTable/src/css/variable.scss new file mode 100644 index 0000000..56bf213 --- /dev/null +++ b/src/components/VxeTable/src/css/variable.scss @@ -0,0 +1,54 @@ +/* stylelint-disable scss/no-global-function-names */ +html[data-theme='dark'] { + // $bg-color: #151515; + // $tooltip-bg-color: #303133; + // $text-color: #c9d1d9; + // $border-color: #303030; + // $selected-bg-color: #1e1e1e; + // $striped-bg-color: #1e1e1e; + + --vxe-form-background-color: #151515; + --vxe-toolbar-background-color: #151515; + --vxe-pager-background-color: #151515; + --vxe-button-default-background-color: lighten(#151515, 15%); + --vxe-table-header-background-color: lighten(#151515, 5%); + --vxe-font-color: darken(#c9d1d9, 12%); + --vxe-table-header-font-color: #c9d1d9; + --vxe-table-footer-font-color: #c9d1d9; + --vxe-table-body-background-color: #151515; + --vxe-table-footer-background-color: #151515; + --vxe-table-row-striped-background-color: #1e1e1e; + --vxe-table-border-color: #303030; + --vxe-table-row-hover-background-color: #1e1e1e; + --vxe-table-row-hover-striped-background-color: darken(#1e1e1e, 10%); + --vxe-table-row-current-background-color: fade(#1e1e1e, 20%); + --vxe-table-row-hover-current-background-color: fade(#1e1e1e, 20%); + --vxe-table-column-hover-background-color: fade(#1e1e1e, 20%); + --vxe-table-column-current-background-color: fade(#1e1e1e, 20%); + --vxe-table-row-checkbox-checked-background-color: fade(#1e1e1e, 15%); + --vxe-table-row-hover-checkbox-checked-background-color: fade(#1e1e1e, 20%); + --vxe-table-menu-background-color: lighten(#303133, 10%); + --vxe-table-filter-panel-background-color: lighten(#151515, 5%); + --vxe-grid-maximize-background-color: #151515; + --vxe-pager-perfect-background-color: #151515; + --vxe-pager-perfect-button-background-color: lighten(#151515, 15%); + --vxe-input-background-color: #151515; + --vxe-input-border-color: #303030; + --vxe-select-panel-background-color: #151515; + --vxe-table-popup-border-color: #303030; + --vxe-select-option-hover-background-color: lighten(#1e1e1e, 15%); + --vxe-pulldown-panel-background-color: #151515; + --vxe-table-fixed-left-scrolling-box-shadow: 8px 0px 10px -5px rgb(255 255 255 / 12%); + --vxe-table-fixed-right-scrolling-box-shadow: -8px 0px 10px -5px rgb(255 255 255 / 12%); + --vxe-loading-background-color: rgb(0 0 0 / 50%); + --vxe-tooltip-dark-background-color: lighten(#303133, 25%); + --vxe-modal-header-background-color: #1e1e1e; + --vxe-modal-body-background-color: #303133; + --vxe-modal-border-color: #303030; + --vxe-toolbar-panel-background-color: #151515; + --vxe-input-disabled-color: lighten(#1e1e1e, 20%); + --vxe-input-disabled-background-color: lighten(#1e1e1e, 25%); + --vxe-checkbox-icon-background-color: lighten(#1e1e1e, 15%); + --vxe-checkbox-checked-icon-border-color: #303030; + --vxe-checkbox-indeterminate-icon-background-color: lighten(#1e1e1e, 15%); +} \ No newline at end of file diff --git a/src/components/VxeTable/src/emits.ts b/src/components/VxeTable/src/emits.ts new file mode 100644 index 0000000..4920d73 --- /dev/null +++ b/src/components/VxeTable/src/emits.ts @@ -0,0 +1,17 @@ +import tableEmits from 'vxe-table/es/table/src/emits'; + +export const basicEmits = [ + ...tableEmits, + 'page-change', + 'form-submit', + 'form-submit-invalid', + 'form-reset', + 'form-collapse', + 'form-toggle-collapse', + 'toolbar-button-click', + 'toolbar-tool-click', + 'zoom', + + //... 如有缺少在此处追加 + // xxx +]; diff --git a/src/components/VxeTable/src/helper.ts b/src/components/VxeTable/src/helper.ts new file mode 100644 index 0000000..07aa8fd --- /dev/null +++ b/src/components/VxeTable/src/helper.ts @@ -0,0 +1,19 @@ +import { ComponentType } from './componentType'; +import { useI18n } from '/@/hooks/web/useI18n'; + +const { t } = useI18n(); + +/** + * @description: 生成placeholder + */ +export function createPlaceholderMessage(component: ComponentType) { + if (!component) return; + if (component.includes('RangePicker')) { + return [t('common.chooseText'), t('common.chooseText')]; + } + if (component.includes('Input') || component.includes('Complete') || component.includes('Rate')) { + return t('common.inputText'); + } else { + return t('common.chooseText'); + } +} diff --git a/src/components/VxeTable/src/methods.ts b/src/components/VxeTable/src/methods.ts new file mode 100644 index 0000000..78a81c2 --- /dev/null +++ b/src/components/VxeTable/src/methods.ts @@ -0,0 +1,160 @@ +import { GridMethods, TableMethods, TableEditMethods, TableValidatorMethods } from 'vxe-table'; + +export const gridComponentMethodKeys: ( + | keyof GridMethods + | keyof TableMethods + | keyof TableEditMethods + | keyof TableValidatorMethods +)[] = [ + // vxe-grid 部分 + 'dispatchEvent', + 'commitProxy', + 'getFormItems', + 'getPendingRecords', + 'zoom', + 'isMaximized', + 'maximize', + 'revert', + 'getProxyInfo', + + // vxe-table和vxe-grid公共部分 + 'clearAll', + 'syncData', + 'updateData', + 'loadData', + 'reloadData', + 'reloadRow', + 'loadColumn', + 'reloadColumn', + 'getRowNode', + 'getColumnNode', + 'getRowIndex', + 'getVTRowIndex', + 'getVMRowIndex', + 'getColumnIndex', + 'getVTColumnIndex', + 'getVMColumnIndex', + 'createData', + 'createRow', + 'revertData', + 'clearData', + 'isInsertByRow', + 'isUpdateByRow', + 'getColumns', + 'getColumnById', + 'getColumnByField', + 'getTableColumn', + 'getData', + 'getCheckboxRecords', + 'getParentRow', + 'getRowSeq', + 'getRowById', + 'getRowid', + 'getTableData', + 'hideColumn', + 'showColumn', + 'resetColumn', + 'refreshColumn', + 'refreshScroll', + 'recalculate', + 'closeTooltip', + 'isAllCheckboxChecked', + 'isAllCheckboxIndeterminate', + 'getCheckboxIndeterminateRecords', + 'setCheckboxRow', + 'isCheckedByCheckboxRow', + 'isIndeterminateByCheckboxRow', + 'toggleCheckboxRow', + 'setAllCheckboxRow', + 'getRadioReserveRecord', + 'clearRadioReserve', + 'getCheckboxReserveRecords', + 'clearCheckboxReserve', + 'toggleAllCheckboxRow', + 'clearCheckboxRow', + 'setCurrentRow', + 'isCheckedByRadioRow', + 'setRadioRow', + 'clearCurrentRow', + 'clearRadioRow', + 'getCurrentRecord', + 'getRadioRecord', + 'getCurrentColumn', + 'setCurrentColumn', + 'clearCurrentColumn', + 'sort', + 'clearSort', + 'isSort', + 'getSortColumns', + 'closeFilter', + 'isFilter', + 'isRowExpandLoaded', + 'clearRowExpandLoaded', + 'reloadRowExpand', + 'reloadRowExpand', + 'toggleRowExpand', + 'setAllRowExpand', + 'setRowExpand', + 'isExpandByRow', + 'clearRowExpand', + 'clearRowExpandReserve', + 'getRowExpandRecords', + 'getTreeExpandRecords', + 'isTreeExpandLoaded', + 'clearTreeExpandLoaded', + 'reloadTreeExpand', + 'reloadTreeChilds', + 'toggleTreeExpand', + 'setAllTreeExpand', + 'setTreeExpand', + 'isTreeExpandByRow', + 'clearTreeExpand', + 'clearTreeExpandReserve', + 'getScroll', + 'scrollTo', + 'scrollToRow', + 'scrollToColumn', + 'clearScroll', + 'updateFooter', + 'updateStatus', + 'setMergeCells', + 'removeInsertRow', + 'removeMergeCells', + 'getMergeCells', + 'clearMergeCells', + 'setMergeFooterItems', + 'removeMergeFooterItems', + 'getMergeFooterItems', + 'clearMergeFooterItems', + 'openTooltip', + 'focus', + 'blur', + 'connect', + + // vxe-table-edit部分 + 'insert', + 'insertAt', + 'remove', + 'removeCheckboxRow', + 'removeRadioRow', + 'removeCurrentRow', + 'getRecordset', + 'getInsertRecords', + 'getRemoveRecords', + 'getUpdateRecords', + 'getEditRecord', + 'getSelectedCell', + 'clearSelected', + 'isEditByRow', + 'setEditRow', + 'setEditCell', + 'setSelectCell', + + // vxe-table-validator + 'clearValidate', + 'fullValidate', + 'validate', + + //... 如有缺少在此处追加 + // xxx +]; diff --git a/src/components/VxeTable/src/props.ts b/src/components/VxeTable/src/props.ts new file mode 100644 index 0000000..fff29de --- /dev/null +++ b/src/components/VxeTable/src/props.ts @@ -0,0 +1,52 @@ +import { VxeGridPropTypes, VxeTablePropTypes } from 'vxe-table'; +import tableProps from 'vxe-table/es/table/src/props'; +import { CSSProperties } from 'vue'; + +/** + * @description: table二次开发需要后,需要接受的所有prop属性 + */ +export const basicProps = { + ...tableProps, + columns: Array as PropType, + pagerConfig: { + type: Object as PropType, + default: () => ({}), + }, + proxyConfig: { + type: Object as PropType, + default: () => ({}), + }, + toolbarConfig: { + type: Object as PropType, + default: () => ({}), + }, + formConfig: { + type: Object as PropType, + default: () => ({}), + }, + zoomConfig: { + type: Object as PropType, + default: () => ({}), + }, + printConfig: { + type: Object as PropType, + default: () => ({}), + }, + exportConfig: { + type: Object as PropType, + default: () => ({}), + }, + importConfig: { + type: Object as PropType, + default: () => ({}), + }, + size: String as PropType, + tableClass: { + type: String, + default: '', + }, + tableStyle: { + type: Object as PropType, + default: () => ({}), + }, +}; diff --git a/src/components/VxeTable/src/setting.ts b/src/components/VxeTable/src/setting.ts new file mode 100644 index 0000000..a1df882 --- /dev/null +++ b/src/components/VxeTable/src/setting.ts @@ -0,0 +1,4 @@ +import { VXETable } from '..'; +import componentSetting from '/@/settings/componentSetting'; + +VXETable.setup(componentSetting.vxeTable); diff --git a/src/components/VxeTable/src/types.ts b/src/components/VxeTable/src/types.ts new file mode 100644 index 0000000..1319e69 --- /dev/null +++ b/src/components/VxeTable/src/types.ts @@ -0,0 +1,7 @@ +import { CSSProperties } from 'vue'; +import { VxeGridProps } from 'vxe-table'; + +export type BasicTableProps = VxeGridProps & { + tableClass?: string; + tableStyle?: CSSProperties; +}; diff --git a/src/components/registerGlobComp.ts b/src/components/registerGlobComp.ts new file mode 100644 index 0000000..5a8e591 --- /dev/null +++ b/src/components/registerGlobComp.ts @@ -0,0 +1,8 @@ +import type { App } from 'vue'; +import { Button } from './Button'; +import { Input, Layout } from 'ant-design-vue'; +import VXETable from 'vxe-table'; + +export function registerGlobComp(app: App) { + app.use(Input).use(Button).use(Layout).use(VXETable); +} diff --git a/src/design/.DS_Store b/src/design/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..642ddf852669d202e9d275cdf7ed202c7f750daf GIT binary patch literal 6148 zcmeHKJ5Iwu5S@)vn2(T4N*5e}bd*joC&&dLL?V&mI0}K<1vlVMoQpRf1zTQIMhMMF zyKg<8-SM;K@eom%y)7q184;xzjH5G55n(%zo{UU$2@Jf)Wd2-NyPlsb{w@Rj>=JsS zEgd#5?dLbW`mt1XSuQs90vdi1Ztm~Crfuu;7wc}--c??Xb2`vo&U~dc)@!P1+dVz| z!2VIcfm{ZBqnSm0BY7tDjx6`x%+gP}bFmEMVsTX+J>9I`^KP-Ji! zy-@Vo8E^)ifg=O_eaJBw3&TcHJ{_2(1ptnr7Qvc(369AP3&Tbc7D&)gpoRu(F@lCe zpPOG{*eGf^1#3QnogAz~33592&&8cWq3E+S;0$ybNc1w}`u{N8|96A@${BD5{uKjZ zT+YiGZpmtE@8-DH<`|C{EbP}P9z(E@QVd@%#n%`j(C54W7KV)?G!Xw05E^`P22RSr EHwEiifdBvi literal 0 HcmV?d00001 diff --git a/src/design/ant/btn.less b/src/design/ant/btn.less new file mode 100644 index 0000000..bc18305 --- /dev/null +++ b/src/design/ant/btn.less @@ -0,0 +1,524 @@ +/* stylelint-disable order/properties-order */ +// button reset +.ant-btn { + &-link:hover, + &-link:focus, + &-link:active { + border-color: transparent !important; + } + + &-primary { + color: @white; + background-color: @button-primary-color; + + &:hover, + &:focus { + color: @white; + background-color: @button-primary-hover-color; + } + } + + &-primary:not(&-background-ghost):not([disabled]) { + color: @white; + } + + &-default { + color: @button-cancel-color; + background-color: @button-cancel-bg-color; + border-color: @button-cancel-border-color; + + &:hover, + &:focus { + color: @button-cancel-hover-color; + background-color: @button-cancel-hover-bg-color; + border-color: @button-cancel-hover-border-color; + } + } + + &.ant-btn-link.is-disabled { + color: rgb(0 0 0 / 25%); + text-shadow: none; + cursor: not-allowed !important; + background-color: transparent !important; + border-color: transparent !important; + box-shadow: none; + } + + // color: @white; + + &-success.ant-btn-link:not([disabled='disabled']) { + color: @button-success-color; + + &:hover, + &:focus { + color: @button-success-hover-color; + border-color: transparent; + } + + &:active { + color: @button-success-active-color; + } + } + + &-success.ant-btn-link.ant-btn-loading, + &-warning.ant-btn-link.ant-btn-loading, + &-error.ant-btn-link.ant-btn-loading, + &-background-ghost.ant-btn-link.ant-btn-loading, + &.ant-btn-link.ant-btn-loading { + &::before { + background: transparent; + } + } + + &-success:not(.ant-btn-link, .is-disabled) { + color: @white; + background-color: @button-success-color; + border-color: @button-success-color; + //border-width: 0; + + &:hover, + &:focus { + color: @white; + background-color: @button-success-hover-color; + border-color: @button-success-hover-color; + } + + &:active { + background-color: @button-success-active-color; + border-color: @button-success-active-color; + } + } + + &-warning.ant-btn-link:not([disabled='disabled']) { + color: @button-warn-color; + + &:hover, + &:focus { + color: @button-warn-hover-color; + border-color: transparent; + } + + &:active { + color: @button-warn-active-color; + } + } + + &-warning:not(.ant-btn-link, .is-disabled) { + color: @white; + background-color: @button-warn-color; + border-color: @button-warn-color; + + &:hover, + &:focus { + color: @white; + background-color: @button-warn-hover-color; + border-color: @button-warn-hover-color; + } + + &:active { + background-color: @button-warn-active-color; + border-color: @button-warn-active-color; + } + } + + &-error.ant-btn-link:not([disabled='disabled']) { + color: @button-error-color; + + &:hover, + &:focus { + color: @button-error-hover-color; + border-color: transparent; + } + + &:active { + color: @button-error-active-color; + } + } + + &-error:not(.ant-btn-link, .is-disabled) { + color: @white; + background-color: @button-error-color; + border-color: @button-error-color; + + &:hover, + &:focus { + color: @white; + background-color: @button-error-hover-color; + border-color: @button-error-hover-color; + } + + &:active { + background-color: @button-error-active-color; + border-color: @button-error-active-color; + } + } + + &-background-ghost { + border-width: 1px; + background-color: transparent !important; + + &[disabled], + &[disabled]:hover { + color: fade(@white, 40%) !important; + background-color: transparent !important; + border-color: fade(@white, 40%) !important; + } + } + + &-dashed&-background-ghost, + &-default&-background-ghost { + color: @button-ghost-color; + border-color: @button-ghost-color; + + &:hover, + &:focus { + color: @button-ghost-hover-color; + border-color: @button-ghost-hover-color; + } + + &:active { + color: @button-ghost-active-color; + border-color: @button-ghost-active-color; + } + + &[disabled], + &[disabled]:hover { + color: fade(@white, 40%) !important; + border-color: fade(@white, 40%) !important; + } + } + + &-background-ghost&-success:not(.ant-btn-link) { + color: @button-success-color; + background-color: transparent; + border-color: @button-success-color; + border-width: 1px; + + &:hover, + &:focus { + color: @button-success-hover-color !important; + border-color: @button-success-hover-color; + } + + &:active { + color: @button-success-active-color; + border-color: @button-success-active-color; + } + } + + &-background-ghost&-warning:not(.ant-btn-link) { + color: @button-warn-color; + background-color: transparent; + border-color: @button-warn-color; + border-width: 1px; + + &:hover, + &:focus { + color: @button-warn-hover-color !important; + border-color: @button-warn-hover-color; + } + + &:active { + color: @button-warn-active-color; + border-color: @button-warn-active-color; + } + } + + &-background-ghost&-error:not(.ant-btn-link) { + color: @button-error-color; + background-color: transparent; + border-color: @button-error-color; + border-width: 1px; + + &:hover, + &:focus { + color: @button-error-hover-color !important; + border-color: @button-error-hover-color; + } + + &:active { + color: @button-error-active-color; + border-color: @button-error-active-color; + } + } + + &-ghost.ant-btn-link:not([disabled='disabled']) { + color: @button-ghost-color; + + &:hover, + &:focus { + color: @button-ghost-hover-color; + border-color: transparent; + } + } +} + + +.dark-btn { + &-link:hover, + &-link:focus, + &-link:active { + border-color: transparent !important; + } + + &-primary { + color: @white; + background-color: @button-primary-color; + + &:hover, + &:focus { + color: @white; + background-color: @button-primary-hover-color; + } + } + + &-primary:not(&-background-ghost):not([disabled]) { + color: @white; + } + + &-default { + color: @button-cancel-color; + background-color: @button-cancel-bg-color; + border-color: @button-cancel-border-color; + + &:hover, + &:focus { + color: @button-cancel-hover-color; + background-color: @button-cancel-hover-bg-color; + border-color: @button-cancel-hover-border-color; + } + } + + &.ant-btn-link.is-disabled { + color: rgb(0 0 0 / 25%); + text-shadow: none; + cursor: not-allowed !important; + background-color: transparent !important; + border-color: transparent !important; + box-shadow: none; + } + + // color: @white; + + &-success.ant-btn-link:not([disabled='disabled']) { + color: @button-success-color; + + &:hover, + &:focus { + color: @button-success-hover-color; + border-color: transparent; + } + + &:active { + color: @button-success-active-color; + } + } + + &-success.ant-btn-link.ant-btn-loading, + &-warning.ant-btn-link.ant-btn-loading, + &-error.ant-btn-link.ant-btn-loading, + &-background-ghost.ant-btn-link.ant-btn-loading, + &.ant-btn-link.ant-btn-loading { + &::before { + background: transparent; + } + } + + &-success:not(.ant-btn-link, .is-disabled) { + color: @white; + background-color: @button-success-color; + border-color: @button-success-color; + //border-width: 0; + + &:hover, + &:focus { + color: @white; + background-color: @button-success-hover-color; + border-color: @button-success-hover-color; + } + + &:active { + background-color: @button-success-active-color; + border-color: @button-success-active-color; + } + } + + &-warning.ant-btn-link:not([disabled='disabled']) { + color: @button-warn-color; + + &:hover, + &:focus { + color: @button-warn-hover-color; + border-color: transparent; + } + + &:active { + color: @button-warn-active-color; + } + } + + &-warning:not(.ant-btn-link, .is-disabled) { + color: @white; + background-color: @button-warn-color; + border-color: @button-warn-color; + //border-width: 0; + + &:hover, + &:focus { + color: @white; + background-color: @button-warn-hover-color; + border-color: @button-warn-hover-color; + } + + &:active { + background-color: @button-warn-active-color; + border-color: @button-warn-active-color; + } + + //&[disabled], + //&[disabled]:hover { + // color: @white; + // background-color: fade(@button-warn-color, 40%); + // border-color: fade(@button-warn-color, 40%); + //} + } + + &-error.ant-btn-link:not([disabled='disabled']) { + color: @button-error-color; + + &:hover, + &:focus { + color: @button-error-hover-color; + border-color: transparent; + } + + &:active { + color: @button-error-active-color; + } + } + + &-error:not(.ant-btn-link, .is-disabled) { + color: @white; + background-color: @button-error-color; + border-color: @button-error-color; + //border-width: 0; + + &:hover, + &:focus { + color: @white; + background-color: @button-error-hover-color; + border-color: @button-error-hover-color; + } + + &:active { + background-color: @button-error-active-color; + border-color: @button-error-active-color; + } + + //&[disabled], + //&[disabled]:hover { + // color: @white; + // background-color: fade(@button-error-color, 40%); + // border-color: fade(@button-error-color, 40%); + //} + } + + &-background-ghost { + border-width: 1px; + background-color: transparent !important; + + &[disabled], + &[disabled]:hover { + color: fade(@white, 40%) !important; + background-color: transparent !important; + border-color: fade(@white, 40%) !important; + } + } + + &-dashed&-background-ghost, + &-default&-background-ghost { + color: @button-ghost-color; + border-color: @button-ghost-color; + + &:hover, + &:focus { + color: @button-ghost-hover-color; + border-color: @button-ghost-hover-color; + } + + &:active { + color: @button-ghost-active-color; + border-color: @button-ghost-active-color; + } + + &[disabled], + &[disabled]:hover { + color: fade(@white, 40%) !important; + border-color: fade(@white, 40%) !important; + } + } + + &-background-ghost&-success:not(.ant-btn-link) { + color: @button-success-color; + background-color: transparent; + border-color: @button-success-color; + border-width: 1px; + + &:hover, + &:focus { + color: @button-success-hover-color !important; + border-color: @button-success-hover-color; + } + + &:active { + color: @button-success-active-color; + border-color: @button-success-active-color; + } + } + + &-background-ghost&-warning:not(.ant-btn-link) { + color: @button-warn-color; + background-color: transparent; + border-color: @button-warn-color; + border-width: 1px; + + &:hover, + &:focus { + color: @button-warn-hover-color !important; + border-color: @button-warn-hover-color; + } + + &:active { + color: @button-warn-active-color; + border-color: @button-warn-active-color; + } + } + + &-background-ghost&-error:not(.ant-btn-link) { + color: @button-error-color; + background-color: transparent; + border-color: @button-error-color; + border-width: 1px; + + &:hover, + &:focus { + color: @button-error-hover-color !important; + border-color: @button-error-hover-color; + } + + &:active { + color: @button-error-active-color; + border-color: @button-error-active-color; + } + } + + &-ghost.ant-btn-link:not([disabled='disabled']) { + color: @button-ghost-color; + + &:hover, + &:focus { + color: @button-ghost-hover-color; + border-color: transparent; + } + } +} \ No newline at end of file diff --git a/src/design/ant/index.less b/src/design/ant/index.less new file mode 100644 index 0000000..d508217 --- /dev/null +++ b/src/design/ant/index.less @@ -0,0 +1,63 @@ +@import './pagination.less'; +@import './input.less'; +@import './btn.less'; + +.ant-image-preview-root { + img { + display: unset; + } +} + +.ant-back-top { + right: 20px; + bottom: 20px; +} + +.collapse-container__body { + > .ant-descriptions { + margin-left: 6px; + } +} + +.ant-image-preview-operations { + background-color: rgb(0 0 0 / 30%); +} + +.ant-popover { + &-content { + box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%); + } +} + +// ================================= +// ==============modal message====== +// ================================= +.modal-icon-warning { + color: @warning-color !important; +} + +.modal-icon-success { + color: @success-color !important; +} + +.modal-icon-error { + color: @error-color !important; +} + +.modal-icon-info { + color: @primary-color !important; +} + +.ant-checkbox-checked .ant-checkbox-inner::after, +.ant-tree-checkbox-checked .ant-tree-checkbox-inner::after { + border-top: 0 !important; + border-left: 0 !important; +} + +.ant-form-item-control-input-content { + > div { + > div { + max-width: 100%; + } + } +} diff --git a/src/design/ant/input.less b/src/design/ant/input.less new file mode 100644 index 0000000..8245fb7 --- /dev/null +++ b/src/design/ant/input.less @@ -0,0 +1,27 @@ +@import (reference) '../color.less'; + +// input +.ant-input { + &-number, + &-number-group-wrapper { + width: 100% !important; + min-width: 110px; + max-width: 100%; + } +} + +.ant-input-affix-wrapper .ant-input-suffix { + right: 9px; +} + +.ant-input-clear-icon { + margin-right: 5px; +} + +.ant-input-affix-wrapper-textarea-with-clear-btn { + padding: 0 !important; + + textarea.ant-input { + padding: 4px; + } +} diff --git a/src/design/ant/pagination.less b/src/design/ant/pagination.less new file mode 100644 index 0000000..0fb6711 --- /dev/null +++ b/src/design/ant/pagination.less @@ -0,0 +1,96 @@ +html[data-theme='dark'] { + .ant-pagination { + &.mini { + .ant-pagination-prev, + .ant-pagination-next, + .ant-pagination-item { + background-color: rgb(255 255 255 / 4%) !important; + + a { + color: #8b949e !important; + } + } + + .ant-select-arrow { + color: @text-color-secondary !important; + } + + .ant-pagination-item-active { + border: none; + border-radius: none !important; + background-color: @primary-color !important; + + a { + color: @white !important; + } + } + } + } +} + +.ant-pagination { + &.mini { + .ant-pagination-prev, + .ant-pagination-next { + border: 1px solid; + color: @text-color-base; + font-size: 12px; + } + + .ant-pagination-prev:hover, + .ant-pagination-next:hover, + .ant-pagination-item:focus, + .ant-pagination-item:hover { + a { + color: @primary-color; + } + } + + .ant-pagination-prev, + .ant-pagination-next, + .ant-pagination-item { + margin: 0 4px !important; + border: none; + border-radius: none !important; + background-color: #f4f4f5 !important; + + a { + margin-top: 1px; + color: #606266; + } + + &:last-child { + margin-right: 0 !important; + } + } + + .ant-pagination-item-active { + border: none; + border-radius: none !important; + background-color: @primary-color !important; + + a { + color: @white !important; + } + } + + .ant-pagination-options { + margin-left: 12px; + } + + .ant-pagination-options-quick-jumper input { + height: 22px; + margin: 0 6px; + line-height: 22px; + text-align: center; + } + + .ant-select-arrow { + color: @border-color-shallow-dark; + } + } + + &-disabled { + display: none !important; + } +} diff --git a/src/design/ant/table.less b/src/design/ant/table.less new file mode 100644 index 0000000..fd50da7 --- /dev/null +++ b/src/design/ant/table.less @@ -0,0 +1,72 @@ +@prefix-cls: ~'@{namespace}-basic-table'; + +// fix table unnecessary scrollbar +.@{prefix-cls} { + .hide-scrollbar-y { + .ant-spin-nested-loading { + .ant-spin-container { + .ant-table { + .ant-table-content { + .ant-table-scroll { + .ant-table-hide-scrollbar { + overflow-y: auto !important; + } + + .ant-table-body { + overflow-y: auto !important; + } + } + + .ant-table-fixed-right { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-y: auto !important; + } + } + } + + .ant-table-fixed-left { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-y: auto !important; + } + } + } + } + } + } + } + } + + .hide-scrollbar-x { + .ant-spin-nested-loading { + .ant-spin-container { + .ant-table { + .ant-table-content { + .ant-table-scroll { + .ant-table-body { + overflow: auto !important; + } + } + + .ant-table-fixed-right { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-x: auto !important; + } + } + } + + .ant-table-fixed-left { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-x: auto !important; + } + } + } + } + } + } + } + } +} diff --git a/src/design/color.less b/src/design/color.less new file mode 100644 index 0000000..bd17e18 --- /dev/null +++ b/src/design/color.less @@ -0,0 +1,160 @@ +html { + // text + --text-color: rgb(0 0 0 85%); + + // border + --border-color: #eee; + + // header + --header-bg-color: #394664; + --header-bg-hover-color: #273352; + --header-active-menu-bg-color: #273352; + + // sider + --sider-dark-bg-color: #273352; + --sider-dark-darken-bg-color: #273352; + --sider-dark-lighten-bg-color: #273352; + + // component + --component-background-color: #fff; + + // app + --app-content-background-color: #fafafa; +} + +@white: #fff; + +@content-bg: #f4f7f9; + +@border-color-base: var(--border-color); + +@text-color-secondary: #8b949e; + +@component-background: var(--component-background-color); + +// :export { +// name: "less"; +// mainColor: @mainColor; +// fontSize: @fontSize; +// } +@iconify-bg-color: #5551; + +// ================================= +// ==============border-color======= +// ================================= + +// Dark-dark +@border-color-dark: #b6b7b9; + +// Dark-light +@border-color-shallow-dark: #cececd; + +// Light-dark +@border-color-light: @border-color-base; + +// ================================= +// ==============message============== +// ================================= + +// success-bg-color +@success-background-color: #f1f9ec; +// info-bg-color +@info-background-color: #e8eff8; +// warn-bg-color +@warning-background-color: #fdf6ed; +// danger-bg-color +@danger-background-color: #fef0f0; + +// ================================= +// ==============Header============= +// ================================= +@header-dark-bg-color: var(--header-bg-color); +@header-dark-bg-hover-color: var(--header-bg-hover-color); +@header-light-bg-hover-color: #f6f6f6; +@header-light-desc-color: #7c8087; +@header-light-bottom-border-color: #eee; +// top-menu +@top-menu-active-bg-color: var(--header-active-menu-bg-color); + +// ================================= +// ==============Menu============ +// ================================= + +// let -menu +@sider-dark-bg-color: var(--sider-dark-bg-color); +@sider-dark-darken-bg-color: var(--sider-dark-darken-bg-color); +@sider-dark-lighten-bg-color: var(--sider-dark-lighten-bg-color); + +// trigger +@trigger-dark-hover-bg-color: rgba(255, 255, 255, 0.2); +@trigger-dark-bg-color: rgba(255, 255, 255, 0.1); + +// ================================= +// ==============tree============ +// ================================= +// tree item hover background +@tree-hover-background-color: #f5f7fa; +// tree item hover font color +@tree-hover-font-color: #f5f7fa; + +// ================================= +// ==============link============ +// ================================= +@link-hover-color: @primary-color; +@link-active-color: darken(@primary-color, 10%); + +// ================================= +// ==============Text color-============= +// ================================= + +// Main text color +@text-color-base: var(--text-color); + +// ================================= +// ==============app content color-============= +// ================================= +@app-content-background: var(--app-content-background-color); + +// Label color +@text-color-call-out: #606266; + +// Auxiliary information color-dark +@text-color-help-dark: #909399; + +// ================================= +// ==============breadcrumb========= +// ================================= +@breadcrumb-item-normal-color: #999; +// ================================= +// ==============button============= +// ================================= + +@button-primary-color: @primary-color; +@button-primary-hover-color: lighten(@primary-color, 5%); +@button-primary-active-color: darken(@primary-color, 5%); + +@button-ghost-color: @white; +@button-ghost-hover-color: lighten(@white, 10%); +@button-ghost-hover-bg-color: #e1ebf6; +@button-ghost-active-color: darken(@white, 10%); + +@button-success-color: @success-color; +@button-success-hover-color: lighten(@success-color, 10%); +@button-success-active-color: darken(@success-color, 10%); + +@button-warn-color: @warning-color; +@button-warn-hover-color: lighten(@warning-color, 10%); +@button-warn-active-color: darken(@warning-color, 10%); + +@button-error-color: @error-color; +@button-error-hover-color: lighten(@error-color, 10%); +@button-error-active-color: darken(@error-color, 10%); + +@button-cancel-color: @text-color-call-out; +@button-cancel-bg-color: @white; +@button-cancel-border-color: @border-color-shallow-dark; + +// Mouse over +@button-cancel-hover-color: @primary-color; +@button-cancel-hover-bg-color: @white; +@button-cancel-hover-border-color: @primary-color; diff --git a/src/design/config.less b/src/design/config.less new file mode 100644 index 0000000..64c33f6 --- /dev/null +++ b/src/design/config.less @@ -0,0 +1,2 @@ +@import (reference) 'color.less'; +@import (reference) 'var/index.less'; diff --git a/src/design/dark.less b/src/design/dark.less new file mode 100644 index 0000000..1c66c8e --- /dev/null +++ b/src/design/dark.less @@ -0,0 +1,110 @@ +[data-theme='dark'] { + body { + background-color: #000; + color: @text-color-base; + } + + .ant-btn { + &[disabled], + &[disabled]:hover, + &[disabled]:focus, + &[disabled]:active { + border-color: #303030; + background: rgb(255 255 255 / 8%); + color: rgb(255 255 255 / 30%); + } + + &-success.ant-btn-link.ant-btn-loading, + &-warning.ant-btn-link.ant-btn-loading, + &-error.ant-btn-link.ant-btn-loading, + &-background-ghost.ant-btn-link.ant-btn-loading, + &.ant-btn-link.ant-btn-loading { + &::before { + background: transparent; + } + } + + &:not( + .ant-btn-link, + .is-disabled, + .ant-btn-primary, + .ant-btn-success, + .ant-btn-warning, + .ant-btn-error, + .ant-btn-dangerous + ) { + background: transparent; + color: @text-color-base; + + &:hover { + color: @button-primary-hover-color; + } + } + + &-dangerous.ant-btn-primary { + &:focus { + background: @error-color !important; + } + } + + &-default.ant-btn-dangerous { + border-color: @error-color; + background: transparent !important; + color: @error-color; + + &:hover, + &:focus { + border-color: @button-error-hover-color !important; + color: @button-error-hover-color !important; + } + } + + &-default:not(.ant-btn-background-ghost) { + border-color: #303030; + + &:hover, + &:focus { + border-color: @button-cancel-hover-color; + color: @button-cancel-hover-color; + } + } + + &-default.is-disabled { + &:hover, + &:focus { + border-color: #303030; + color: rgb(255 255 255 / 30%); + } + } + + &-success:not(.is-disabled, .ant-btn-link, .ant-btn-background-ghost) { + &:hover, + &:focus, + &:active { + border-color: @button-success-active-color !important; + background-color: @button-success-active-color !important; + color: @white !important; + } + } + + &-warning:not(.is-disabled, .ant-btn-link, .ant-btn-background-ghost) { + &:hover, + &:focus, + &:active { + border-color: @button-warn-active-color !important; + background-color: @button-warn-active-color !important; + color: @white !important; + } + } + + &-error:not(.is-disabled, .ant-btn-link, .ant-btn-background-ghost) { + &:hover, + &:focus, + &:active { + border-color: @button-error-active-color !important; + background-color: @button-error-active-color !important; + color: @white !important; + } + } + } +} diff --git a/src/design/entry.css b/src/design/entry.css new file mode 100644 index 0000000..1d40f5d --- /dev/null +++ b/src/design/entry.css @@ -0,0 +1,168 @@ +* > .enter-x:nth-child(1) { + transform: translateX(50px); +} +* > .-enter-x:nth-child(1) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(1), +* > .-enter-x:nth-child(1) { + z-index: 9; + opacity: 0; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.1s; +} +* > .enter-x:nth-child(2) { + transform: translateX(50px); +} +* > .-enter-x:nth-child(2) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(2), +* > .-enter-x:nth-child(2) { + z-index: 8; + opacity: 0; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.2s; +} +* > .enter-x:nth-child(3) { + transform: translateX(50px); +} +* > .-enter-x:nth-child(3) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(3), +* > .-enter-x:nth-child(3) { + z-index: 7; + opacity: 0; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.3s; +} + +* > .enter-x:nth-child(4) { + transform: translateX(50px); +} +* > .-enter-x:nth-child(4) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(4), +* > .-enter-x:nth-child(4) { + z-index: 6; + opacity: 0; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.4s; +} + +* > .enter-x:nth-child(5) { + transform: translateX(50px); +} +* > .-enter-x:nth-child(5) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(5), +* > .-enter-x:nth-child(5) { + z-index: 5; + opacity: 0; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.5s; +} + +* > .enter-y:nth-child(1) { + transform: translateX(50px); +} +* > .-enter-y:nth-child(1) { + transform: translateX(-50px); +} + +* > .enter-y:nth-child(1), +* > .-enter-y:nth-child(1) { + z-index: 9; + opacity: 0; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.1s; +} +* > .enter-y:nth-child(2) { + transform: translateX(50px); +} +* > .-enter-y:nth-child(2) { + transform: translateX(-50px); +} + +* > .enter-y:nth-child(2), +* > .-enter-y:nth-child(2) { + z-index: 8; + opacity: 0; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.2s; +} +* > .enter-y:nth-child(3) { + transform: translateX(50px); +} +* > .-enter-y:nth-child(3) { + transform: translateX(-50px); +} + +* > .enter-y:nth-child(3), +* > .-enter-y:nth-child(3) { + z-index: 7; + opacity: 0; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.3s; +} + +* > .enter-y:nth-child(4) { + transform: translateX(50px); +} +* > .-enter-y:nth-child(4) { + transform: translateX(-50px); +} + +* > .enter-y:nth-child(4), +* > .-enter-y:nth-child(4) { + z-index: 6; + opacity: 0; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.4s; +} + +* > .enter-y:nth-child(5) { + transform: translateX(50px); +} +* > .-enter-y:nth-child(5) { + transform: translateX(-50px); +} + +* > .enter-y:nth-child(5), +* > .-enter-y:nth-child(5) { + z-index: 5; + opacity: 0; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation-fill-mode: forwards; + animation-delay: 0.5s; +} + +@keyframes enter-x-animation { + to { + opacity: 1; + transform: translateX(0); + } +} +@keyframes enter-y-animation { + to { + opacity: 1; + transform: translateY(0); + } +} diff --git a/src/design/index.less b/src/design/index.less new file mode 100644 index 0000000..65307eb --- /dev/null +++ b/src/design/index.less @@ -0,0 +1,54 @@ +@import 'transition/index.less'; +@import 'var/index.less'; +@import 'public.less'; +@import 'ant/index.less'; +@import './theme.less'; +@import './entry.css'; +@import './dark.less'; + +input:-webkit-autofill { + box-shadow: 0 0 0 1000px white inset !important; +} + +:-webkit-autofill { + transition: background-color 5000s ease-in-out 0s !important; +} + +html { + overflow: hidden; + text-size-adjust: 100%; +} + +html, +body { + position: relative; + width: 100%; + height: 100%; + overflow: visible; + overflow-x: hidden; + + &.color-weak { + filter: invert(80%); + } + + &.gray-mode { + filter: grayscale(100%); + filter: progid:dximagetransform.microsoft.basicimage(grayscale=1); + } +} + +a:focus, +a:active, +button, +div, +svg, +span { + outline: none; +} + +// 保持 和 windi 一样的全局样式,减少升级带来的影响 +ul { + margin: 0; + padding: 0; + list-style: none; +} diff --git a/src/design/public.less b/src/design/public.less new file mode 100644 index 0000000..b8b3991 --- /dev/null +++ b/src/design/public.less @@ -0,0 +1,51 @@ +#app { + width: 100%; + height: 100%; +} + +// ================================= +// ==============scrollbar========== +// ================================= + +::-webkit-scrollbar { + width: 7px; + height: 8px; +} + +// ::-webkit-scrollbar-track { +// background: transparent; +// } + +::-webkit-scrollbar-track { + background-color: rgb(0 0 0 / 5%); +} + +::-webkit-scrollbar-thumb { + // background-color: rgba(144, 147, 153, 0.3); + border-radius: 2px; + // background: rgba(0, 0, 0, 0.6); + background-color: rgb(144 147 153 / 30%); + box-shadow: inset 0 0 6px rgb(0 0 0 / 20%); +} + +::-webkit-scrollbar-thumb:hover { + background-color: @border-color-dark; +} + +// ================================= +// ==============nprogress========== +// ================================= +#nprogress { + pointer-events: none; + + .bar { + position: fixed; + z-index: 99999; + top: 0; + left: 0; + width: 100%; + height: 2px; + opacity: 0.75; + background-color: @primary-color; + } +} diff --git a/src/design/theme.less b/src/design/theme.less new file mode 100644 index 0000000..22a139e --- /dev/null +++ b/src/design/theme.less @@ -0,0 +1,28 @@ +.bg-white { + background-color: @component-background !important; +} + +html[data-theme='light'] { + .text-secondary { + color: rgb(0 0 0 / 45%); + } + + .ant-alert-success { + border: 1px solid #b7eb8f; + background-color: #f6ffed; + } + + .ant-alert-error { + border: 1px solid #ffccc7; + background-color: #fff2f0; + } + + .ant-alert-warning { + border: 1px solid #ffe58f; + background-color: #fffbe6; + } + + :not(:root):fullscreen::backdrop { + background-color: @layout-body-background !important; + } +} diff --git a/src/design/transition/base.less b/src/design/transition/base.less new file mode 100644 index 0000000..7944c8b --- /dev/null +++ b/src/design/transition/base.less @@ -0,0 +1,18 @@ +.transition-default() { + &-enter-active, + &-leave-active { + transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1) !important; + } + + &-move { + transition: transform 0.4s; + } +} + +.expand-transition { + .transition-default(); +} + +.expand-x-transition { + .transition-default(); +} diff --git a/src/design/transition/fade.less b/src/design/transition/fade.less new file mode 100644 index 0000000..2df4c7f --- /dev/null +++ b/src/design/transition/fade.less @@ -0,0 +1,93 @@ +.fade-transition { + &-enter-active, + &-leave-active { + transition: opacity 0.2s ease-in-out; + } + + &-enter-from, + &-leave-to { + opacity: 0; + } +} + +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.2s ease-in-out; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +/* fade-slide */ +.fade-slide-leave-active, +.fade-slide-enter-active { + transition: all 0.3s; +} + +.fade-slide-enter-from { + transform: translateX(-30px); + opacity: 0; +} + +.fade-slide-leave-to { + transform: translateX(30px); + opacity: 0; +} + +// /////////////////////////////////////////////// +// Fade Bottom +// /////////////////////////////////////////////// + +// Speed: 1x +.fade-bottom-enter-active, +.fade-bottom-leave-active { + transition: opacity 0.25s, transform 0.3s; +} + +.fade-bottom-enter-from { + transform: translateY(-10%); + opacity: 0; +} + +.fade-bottom-leave-to { + transform: translateY(10%); + opacity: 0; +} + +// fade-scale +.fade-scale-leave-active, +.fade-scale-enter-active { + transition: all 0.28s; +} + +.fade-scale-enter-from { + transform: scale(1.2); + opacity: 0; +} + +.fade-scale-leave-to { + transform: scale(0.8); + opacity: 0; +} + +// /////////////////////////////////////////////// +// Fade Top +// /////////////////////////////////////////////// + +// Speed: 1x +.fade-top-enter-active, +.fade-top-leave-active { + transition: opacity 0.2s, transform 0.25s; +} + +.fade-top-enter-from { + transform: translateY(8%); + opacity: 0; +} + +.fade-top-leave-to { + transform: translateY(-8%); + opacity: 0; +} diff --git a/src/design/transition/index.less b/src/design/transition/index.less new file mode 100644 index 0000000..e372b25 --- /dev/null +++ b/src/design/transition/index.less @@ -0,0 +1,10 @@ +@import './base.less'; +@import './fade.less'; +@import './scale.less'; +@import './slide.less'; +@import './scroll.less'; +@import './zoom.less'; + +.collapse-transition { + transition: 0.2s height ease-in-out, 0.2s padding-top ease-in-out, 0.2s padding-bottom ease-in-out; +} diff --git a/src/design/transition/scale.less b/src/design/transition/scale.less new file mode 100644 index 0000000..521fce3 --- /dev/null +++ b/src/design/transition/scale.less @@ -0,0 +1,21 @@ +.scale-transition { + .transition-default(); + + &-enter-from, + &-leave, + &-leave-to { + transform: scale(0); + opacity: 0; + } +} + +.scale-rotate-transition { + .transition-default(); + + &-enter-from, + &-leave, + &-leave-to { + transform: scale(0) rotate(-45deg); + opacity: 0; + } +} diff --git a/src/design/transition/scroll.less b/src/design/transition/scroll.less new file mode 100644 index 0000000..a5f45e4 --- /dev/null +++ b/src/design/transition/scroll.less @@ -0,0 +1,67 @@ +.scroll-y-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateY(-15px); + } + + &-leave-to { + transform: translateY(15px); + } +} + +.scroll-y-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateY(15px); + } + + &-leave-to { + transform: translateY(-15px); + } +} + +.scroll-x-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateX(-15px); + } + + &-leave-to { + transform: translateX(15px); + } +} + +.scroll-x-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateX(15px); + } + + &-leave-to { + transform: translateX(-15px); + } +} diff --git a/src/design/transition/slide.less b/src/design/transition/slide.less new file mode 100644 index 0000000..fe1be22 --- /dev/null +++ b/src/design/transition/slide.less @@ -0,0 +1,39 @@ +.slide-y-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + transform: translateY(-15px); + opacity: 0; + } +} + +.slide-y-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + transform: translateY(15px); + opacity: 0; + } +} + +.slide-x-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + transform: translateX(-15px); + opacity: 0; + } +} + +.slide-x-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + transform: translateX(15px); + opacity: 0; + } +} diff --git a/src/design/transition/zoom.less b/src/design/transition/zoom.less new file mode 100644 index 0000000..2cfdada --- /dev/null +++ b/src/design/transition/zoom.less @@ -0,0 +1,27 @@ +// zoom-out +.zoom-out-enter-active, +.zoom-out-leave-active { + transition: opacity 0.1 ease-in-out, transform 0.15s ease-out; +} + +.zoom-out-enter-from, +.zoom-out-leave-to { + transform: scale(0); + opacity: 0; +} + +// zoom-fade +.zoom-fade-enter-active, +.zoom-fade-leave-active { + transition: transform 0.2s, opacity 0.3s ease-out; +} + +.zoom-fade-enter-from { + transform: scale(0.92); + opacity: 0; +} + +.zoom-fade-leave-to { + transform: scale(1.06); + opacity: 0; +} diff --git a/src/design/var/breakpoint.less b/src/design/var/breakpoint.less new file mode 100644 index 0000000..793e826 --- /dev/null +++ b/src/design/var/breakpoint.less @@ -0,0 +1,33 @@ +// ================================= +// ==============屏幕断点============ +// ================================= + +// Extra small screen / phone +@screen-xs: 480px; +@screen-xs-min: @screen-xs; + +// Small screen / tablet +@screen-sm: 576px; +@screen-sm-min: @screen-sm; + +// Medium screen / desktop +@screen-md: 768px; +@screen-md-min: @screen-md; + +// Large screen / wide desktop +@screen-lg: 992px; +@screen-lg-min: @screen-lg; + +// Extra large screen / full hd +@screen-xl: 1200px; +@screen-xl-min: @screen-xl; + +// Extra extra large screen / large desktop +@screen-2xl: 1600px; +@screen-2xl-min: @screen-2xl; + +@screen-xs-max: (@screen-sm-min - 1px); +@screen-sm-max: (@screen-md-min - 1px); +@screen-md-max: (@screen-lg-min - 1px); +@screen-lg-max: (@screen-xl-min - 1px); +@screen-xl-max: (@screen-2xl-min - 1px); diff --git a/src/design/var/easing.less b/src/design/var/easing.less new file mode 100644 index 0000000..e19735f --- /dev/null +++ b/src/design/var/easing.less @@ -0,0 +1,18 @@ +// ================================= +// ==============动画函数-=========== +// ================================= + +@ease-base-out: cubic-bezier(0.7, 0.3, 0.1, 1); +@ease-base-in: cubic-bezier(0.9, 0, 0.3, 0.7); +@ease-out: cubic-bezier(0.215, 0.61, 0.355, 1); +@ease-in: cubic-bezier(0.55, 0.055, 0.675, 0.19); +@ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1); +@ease-out-back: cubic-bezier(0.12, 0.4, 0.29, 1.46); +@ease-in-back: cubic-bezier(0.71, -0.46, 0.88, 0.6); +@ease-in-out-back: cubic-bezier(0.71, -0.46, 0.29, 1.46); +@ease-out-circ: cubic-bezier(0.08, 0.82, 0.17, 1); +@ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.34); +@ease-in-out-circ: cubic-bezier(0.78, 0.14, 0.15, 0.86); +@ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1); +@ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06); +@ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1); diff --git a/src/design/var/index.less b/src/design/var/index.less new file mode 100644 index 0000000..1689f76 --- /dev/null +++ b/src/design/var/index.less @@ -0,0 +1,39 @@ +@import (reference) '../color.less'; +@import 'easing'; +@import 'breakpoint'; + +@namespace: vben; + +// tabs +@multiple-height: 30px; + +// headers +@header-height: 48px; + +// logo width +@logo-width: 32px; + +// +@side-drag-z-index: 200; + +@page-loading-z-index: 10000; + +@lock-page-z-index: 3000; + +@layout-header-fixed-z-index: 500; + +@multiple-tab-fixed-z-index: 505; + +@layout-sider-fixed-z-index: 510; + +@layout-mix-sider-fixed-z-index: 550; + +@preview-comp-z-index: 1000; + +@page-footer-z-index: 99; + +.bem(@n; @content) { + @{namespace}-@{n} { + @content(); + } +} diff --git a/src/directives/clickOutside.ts b/src/directives/clickOutside.ts new file mode 100644 index 0000000..f6f3051 --- /dev/null +++ b/src/directives/clickOutside.ts @@ -0,0 +1,86 @@ +import { on } from '/@/utils/domUtils'; +import { isServer } from '/@/utils/is'; +import type { ComponentPublicInstance, DirectiveBinding, ObjectDirective } from 'vue'; + +type DocumentHandler = (mouseup: T, mousedown: T) => void; + +type FlushList = Map< + HTMLElement, + { + documentHandler: DocumentHandler; + bindingFn: (...args: unknown[]) => unknown; + } +>; + +const nodeList: FlushList = new Map(); + +let startClick: MouseEvent; + +if (!isServer) { + on(document, 'mousedown', (e: MouseEvent) => (startClick = e)); + on(document, 'mouseup', (e: MouseEvent) => { + for (const { documentHandler } of nodeList.values()) { + documentHandler(e, startClick); + } + }); +} + +function createDocumentHandler(el: HTMLElement, binding: DirectiveBinding): DocumentHandler { + let excludes: HTMLElement[] = []; + if (Array.isArray(binding.arg)) { + excludes = binding.arg; + } else { + // due to current implementation on binding type is wrong the type casting is necessary here + excludes.push(binding.arg as unknown as HTMLElement); + } + return function (mouseup, mousedown) { + const popperRef = ( + binding.instance as ComponentPublicInstance<{ + popperRef: Nullable; + }> + ).popperRef; + const mouseUpTarget = mouseup.target as Node; + const mouseDownTarget = mousedown.target as Node; + const isBound = !binding || !binding.instance; + const isTargetExists = !mouseUpTarget || !mouseDownTarget; + const isContainedByEl = el.contains(mouseUpTarget) || el.contains(mouseDownTarget); + const isSelf = el === mouseUpTarget; + + const isTargetExcluded = + (excludes.length && excludes.some((item) => item?.contains(mouseUpTarget))) || + (excludes.length && excludes.includes(mouseDownTarget as HTMLElement)); + const isContainedByPopper = + popperRef && (popperRef.contains(mouseUpTarget) || popperRef.contains(mouseDownTarget)); + if ( + isBound || + isTargetExists || + isContainedByEl || + isSelf || + isTargetExcluded || + isContainedByPopper + ) { + return; + } + binding.value(); + }; +} + +const ClickOutside: ObjectDirective = { + beforeMount(el, binding) { + nodeList.set(el, { + documentHandler: createDocumentHandler(el, binding), + bindingFn: binding.value, + }); + }, + updated(el, binding) { + nodeList.set(el, { + documentHandler: createDocumentHandler(el, binding), + bindingFn: binding.value, + }); + }, + unmounted(el) { + nodeList.delete(el); + }, +}; + +export default ClickOutside; diff --git a/src/directives/ellipsis.ts b/src/directives/ellipsis.ts new file mode 100644 index 0000000..2370f4e --- /dev/null +++ b/src/directives/ellipsis.ts @@ -0,0 +1,42 @@ +import type { CSSProperties, DirectiveBinding, ObjectDirective, App } from 'vue'; + +interface IValue { + width?: number; + line?: number; +} + +interface IOptions { + [key: string]: CSSProperties; +} + +const cssProperties: IOptions = { + single: { + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + }, + multiple: { + display: '-webkit-box', + overflow: 'hidden', + wordBreak: 'break-all', + }, +}; + +const Ellipsis: ObjectDirective = { + mounted(el: HTMLElement, binding: DirectiveBinding>) { + const { value = [100, 1], arg = 'single' } = binding; + const [width, line] = value; + Object.entries(cssProperties[arg]).forEach(([key, value]) => { + el.style[key] = value; + }); + el.style.width = `${width}px`; + if (arg === 'multiple') { + el.style.webkitLineClamp = `${line}`; + el.style.webkitBoxOrient = 'vertical'; + } + }, +}; +export function setupEllipsisDirective(app: App) { + app.directive('ellipsis', Ellipsis); +} +export default Ellipsis; diff --git a/src/directives/index.ts b/src/directives/index.ts new file mode 100644 index 0000000..ad58631 --- /dev/null +++ b/src/directives/index.ts @@ -0,0 +1,13 @@ +/** + * Configure and register global directives + */ +import type { App } from 'vue'; +import { setupPermissionDirective } from './permission'; +import { setupLoadingDirective } from './loading'; +import { setupEllipsisDirective } from './ellipsis'; + +export function setupGlobDirectives(app: App) { + setupPermissionDirective(app); + setupLoadingDirective(app); + setupEllipsisDirective(app); +} diff --git a/src/directives/loading.ts b/src/directives/loading.ts new file mode 100644 index 0000000..712b71c --- /dev/null +++ b/src/directives/loading.ts @@ -0,0 +1,39 @@ +import { createLoading } from '/@/components/Loading'; +import type { Directive, App } from 'vue'; + +const loadingDirective: Directive = { + mounted(el, binding) { + const tip = el.getAttribute('loading-tip'); + const background = el.getAttribute('loading-background'); + const size = el.getAttribute('loading-size'); + const fullscreen = !!binding.modifiers.fullscreen; + const instance = createLoading( + { + tip, + background, + size: size || 'large', + loading: !!binding.value, + absolute: !fullscreen, + }, + fullscreen ? document.body : el, + ); + el.instance = instance; + }, + updated(el, binding) { + const instance = el.instance; + if (!instance) return; + instance.setTip(el.getAttribute('loading-tip')); + if (binding.oldValue !== binding.value) { + instance.setLoading?.(binding.value && !instance.loading); + } + }, + unmounted(el) { + el?.instance?.close(); + }, +}; + +export function setupLoadingDirective(app: App) { + app.directive('loading', loadingDirective); +} + +export default loadingDirective; diff --git a/src/directives/permission.ts b/src/directives/permission.ts new file mode 100644 index 0000000..ca5d0fc --- /dev/null +++ b/src/directives/permission.ts @@ -0,0 +1,32 @@ +/** + * Global authority directive + * Used for fine-grained control of component permissions + * @Example v-auth="RoleEnum.TEST" + */ +import type { App, Directive, DirectiveBinding } from 'vue'; + +import { usePermission } from '/@/hooks/web/usePermission'; + +function isAuth(el: Element, binding: any) { + const { hasPermission } = usePermission(); + + const value = binding.value; + if (!value) return; + if (!hasPermission(value)) { + el.parentNode?.removeChild(el); + } +} + +const mounted = (el: Element, binding: DirectiveBinding) => { + isAuth(el, binding); +}; + +const authDirective: Directive = { + mounted, +}; + +export function setupPermissionDirective(app: App) { + app.directive('auth', authDirective); +} + +export default authDirective; diff --git a/src/directives/ripple/index.less b/src/directives/ripple/index.less new file mode 100644 index 0000000..70a1c3f --- /dev/null +++ b/src/directives/ripple/index.less @@ -0,0 +1,21 @@ +.ripple-container { + position: absolute; + top: 0; + left: 0; + width: 0; + height: 0; + overflow: hidden; + pointer-events: none; +} + +.ripple-effect { + position: relative; + z-index: 9999; + width: 1px; + height: 1px; + margin-top: 0; + margin-left: 0; + transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); + border-radius: 50%; + pointer-events: none; +} diff --git a/src/directives/ripple/index.ts b/src/directives/ripple/index.ts new file mode 100644 index 0000000..3da8014 --- /dev/null +++ b/src/directives/ripple/index.ts @@ -0,0 +1,192 @@ +import type { Directive } from 'vue'; +import './index.less'; + +export interface RippleOptions { + event: string; + transition: number; +} + +export interface RippleProto { + background?: string; + zIndex?: string; +} + +export type EventType = Event & MouseEvent & TouchEvent; + +const options: RippleOptions = { + event: 'mousedown', + transition: 400, +}; + +const RippleDirective: Directive & RippleProto = { + beforeMount: (el: HTMLElement, binding) => { + if (binding.value === false) return; + + const bg = el.getAttribute('ripple-background'); + setProps(Object.keys(binding.modifiers), options); + + const background = bg || RippleDirective.background; + const zIndex = RippleDirective.zIndex; + + el.addEventListener(options.event, (event: EventType) => { + rippler({ + event, + el, + background, + zIndex, + }); + }); + }, + updated(el, binding) { + if (!binding.value) { + el?.clearRipple?.(); + return; + } + const bg = el.getAttribute('ripple-background'); + el?.setBackground?.(bg); + }, +}; + +function rippler({ + event, + el, + zIndex, + background, +}: { event: EventType; el: HTMLElement } & RippleProto) { + const targetBorder = parseInt(getComputedStyle(el).borderWidth.replace('px', '')); + const clientX = event.clientX || event.touches[0].clientX; + const clientY = event.clientY || event.touches[0].clientY; + + const rect = el.getBoundingClientRect(); + const { left, top } = rect; + const { offsetWidth: width, offsetHeight: height } = el; + const { transition } = options; + const dx = clientX - left; + const dy = clientY - top; + const maxX = Math.max(dx, width - dx); + const maxY = Math.max(dy, height - dy); + const style = window.getComputedStyle(el); + const radius = Math.sqrt(maxX * maxX + maxY * maxY); + const border = targetBorder > 0 ? targetBorder : 0; + + const ripple = document.createElement('div'); + const rippleContainer = document.createElement('div'); + + // Styles for ripple + ripple.className = 'ripple'; + + Object.assign(ripple.style ?? {}, { + marginTop: '0px', + marginLeft: '0px', + width: '1px', + height: '1px', + transition: `all ${transition}ms cubic-bezier(0.4, 0, 0.2, 1)`, + borderRadius: '50%', + pointerEvents: 'none', + position: 'relative', + zIndex: zIndex ?? '9999', + backgroundColor: background ?? 'rgba(0, 0, 0, 0.12)', + }); + + // Styles for rippleContainer + rippleContainer.className = 'ripple-container'; + Object.assign(rippleContainer.style ?? {}, { + position: 'absolute', + left: `${0 - border}px`, + top: `${0 - border}px`, + height: '0', + width: '0', + pointerEvents: 'none', + overflow: 'hidden', + }); + + const storedTargetPosition = + el.style.position.length > 0 ? el.style.position : getComputedStyle(el).position; + + if (storedTargetPosition !== 'relative') { + el.style.position = 'relative'; + } + + rippleContainer.appendChild(ripple); + el.appendChild(rippleContainer); + + Object.assign(ripple.style, { + marginTop: `${dy}px`, + marginLeft: `${dx}px`, + }); + + const { + borderTopLeftRadius, + borderTopRightRadius, + borderBottomLeftRadius, + borderBottomRightRadius, + } = style; + Object.assign(rippleContainer.style, { + width: `${width}px`, + height: `${height}px`, + direction: 'ltr', + borderTopLeftRadius, + borderTopRightRadius, + borderBottomLeftRadius, + borderBottomRightRadius, + }); + + setTimeout(() => { + const wh = `${radius * 2}px`; + Object.assign(ripple.style ?? {}, { + width: wh, + height: wh, + marginLeft: `${dx - radius}px`, + marginTop: `${dy - radius}px`, + }); + }, 0); + + function clearRipple() { + setTimeout(() => { + ripple.style.backgroundColor = 'rgba(0, 0, 0, 0)'; + }, 250); + + setTimeout(() => { + rippleContainer?.parentNode?.removeChild(rippleContainer); + }, 850); + el.removeEventListener('mouseup', clearRipple, false); + el.removeEventListener('mouseleave', clearRipple, false); + el.removeEventListener('dragstart', clearRipple, false); + setTimeout(() => { + let clearPosition = true; + for (let i = 0; i < el.childNodes.length; i++) { + if ((el.childNodes[i] as Recordable).className === 'ripple-container') { + clearPosition = false; + } + } + + if (clearPosition) { + el.style.position = storedTargetPosition !== 'static' ? storedTargetPosition : ''; + } + }, options.transition + 260); + } + + if (event.type === 'mousedown') { + el.addEventListener('mouseup', clearRipple, false); + el.addEventListener('mouseleave', clearRipple, false); + el.addEventListener('dragstart', clearRipple, false); + } else { + clearRipple(); + } + + (el as Recordable).setBackground = (bgColor: string) => { + if (!bgColor) { + return; + } + ripple.style.backgroundColor = bgColor; + }; +} + +function setProps(modifiers: Recordable, props: Recordable) { + modifiers.forEach((item: Recordable) => { + if (isNaN(Number(item))) props.event = item; + else props.transition = item; + }); +} + +export default RippleDirective; diff --git a/src/enums/appEnum.ts b/src/enums/appEnum.ts new file mode 100644 index 0000000..def8027 --- /dev/null +++ b/src/enums/appEnum.ts @@ -0,0 +1,56 @@ +export const SIDE_BAR_MINI_WIDTH = 48; +export const SIDE_BAR_SHOW_TIT_MINI_WIDTH = 80; + +export enum ContentEnum { + // auto width + FULL = 'full', + // fixed width + FIXED = 'fixed', +} + +// menu theme enum +export enum ThemeEnum { + DARK = 'dark', + LIGHT = 'light', +} + +export enum SettingButtonPositionEnum { + AUTO = 'auto', + HEADER = 'header', + FIXED = 'fixed', +} + +export enum SessionTimeoutProcessingEnum { + ROUTE_JUMP, + PAGE_COVERAGE, +} + +/** + * 权限模式 + */ +export enum PermissionModeEnum { + // role + // 角色权限 + ROLE = 'ROLE', + // black + // 后端 + BACK = 'BACK', + // route mapping + // 路由映射 + ROUTE_MAPPING = 'ROUTE_MAPPING', +} + +// Route switching animation +// 路由切换动画 +export enum RouterTransitionEnum { + ZOOM_FADE = 'zoom-fade', + ZOOM_OUT = 'zoom-out', + FADE_SIDE = 'fade-slide', + FADE = 'fade', + FADE_BOTTOM = 'fade-bottom', + FADE_SCALE = 'fade-scale', +} + +export enum ParentIdEnum { + DEFAULT = 0, +} \ No newline at end of file diff --git a/src/enums/breakpointEnum.ts b/src/enums/breakpointEnum.ts new file mode 100644 index 0000000..93acc1a --- /dev/null +++ b/src/enums/breakpointEnum.ts @@ -0,0 +1,28 @@ +export enum sizeEnum { + XS = 'XS', + SM = 'SM', + MD = 'MD', + LG = 'LG', + XL = 'XL', + XXL = 'XXL', +} + +export enum screenEnum { + XS = 480, + SM = 576, + MD = 768, + LG = 992, + XL = 1200, + XXL = 1600, +} + +const screenMap = new Map(); + +screenMap.set(sizeEnum.XS, screenEnum.XS); +screenMap.set(sizeEnum.SM, screenEnum.SM); +screenMap.set(sizeEnum.MD, screenEnum.MD); +screenMap.set(sizeEnum.LG, screenEnum.LG); +screenMap.set(sizeEnum.XL, screenEnum.XL); +screenMap.set(sizeEnum.XXL, screenEnum.XXL); + +export { screenMap }; diff --git a/src/enums/cacheEnum.ts b/src/enums/cacheEnum.ts new file mode 100644 index 0000000..de656da --- /dev/null +++ b/src/enums/cacheEnum.ts @@ -0,0 +1,34 @@ +// token key +export const TOKEN_KEY = 'TOKEN__'; + +export const LOCALE_KEY = 'LOCALE__'; + +// user info key +export const USER_INFO_KEY = 'USER__INFO__'; + +// role info key +export const ROLES_KEY = 'ROLES__KEY__'; + +// project config key +export const PROJ_CFG_KEY = 'PROJ__CFG__KEY__'; +export const API_ADDRESS = 'API_ADDRESS__'; + +export const ROLES_NAME_KEY = 'ROLES__NAME__KEY__'; + +// lock info +export const LOCK_INFO_KEY = 'LOCK__INFO__KEY__'; + +export const MULTIPLE_TABS_KEY = 'MULTIPLE_TABS__KEY__'; + +export const APP_DARK_MODE_KEY = '__APP__DARK__MODE__'; + +// base global local key +export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__'; + +// base global session key +export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY__'; + +export enum CacheTypeEnum { + SESSION, + LOCAL, +} diff --git a/src/enums/exceptionEnum.ts b/src/enums/exceptionEnum.ts new file mode 100644 index 0000000..d28f4d0 --- /dev/null +++ b/src/enums/exceptionEnum.ts @@ -0,0 +1,27 @@ +/** + * @description: Exception related enumeration + */ +export enum ExceptionEnum { + // page not access + PAGE_NOT_ACCESS = 403, + + // page not found + PAGE_NOT_FOUND = 404, + + // error + ERROR = 500, + + // net work error + NET_WORK_ERROR = 10000, + + // No data on the page. In fact, it is not an exception page + PAGE_NOT_DATA = 10100, +} + +export enum ErrorTypeEnum { + VUE = 'vue', + SCRIPT = 'script', + RESOURCE = 'resource', + AJAX = 'ajax', + PROMISE = 'promise', +} diff --git a/src/enums/httpEnum.ts b/src/enums/httpEnum.ts new file mode 100644 index 0000000..e1fbd69 --- /dev/null +++ b/src/enums/httpEnum.ts @@ -0,0 +1,31 @@ +/** + * @description: Request result set + */ +export enum ResultEnum { + SUCCESS = '00000', + ERROR = 'A0500', + TIMEOUT = 'A0501', + TYPE = 'success', +} + +/** + * @description: request method + */ +export enum RequestEnum { + GET = 'GET', + POST = 'POST', + PUT = 'PUT', + DELETE = 'DELETE', +} + +/** + * @description: contentType + */ +export enum ContentTypeEnum { + // json + JSON = 'application/json;charset=UTF-8', + // form-data qs + FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8', + // form-data upload + FORM_DATA = 'multipart/form-data;charset=UTF-8', +} diff --git a/src/enums/menuEnum.ts b/src/enums/menuEnum.ts new file mode 100644 index 0000000..89cfa9f --- /dev/null +++ b/src/enums/menuEnum.ts @@ -0,0 +1,50 @@ +/** + * @description: menu type + */ +export enum MenuTypeEnum { + // left menu + SIDEBAR = 'sidebar', + + MIX_SIDEBAR = 'mix-sidebar', + // mixin menu + MIX = 'mix', + // top menu + TOP_MENU = 'top-menu', +} + +// 折叠触发器位置 +export enum TriggerEnum { + // 不显示 + NONE = 'NONE', + // 菜单底部 + FOOTER = 'FOOTER', + // 头部 + HEADER = 'HEADER', +} + +export type Mode = 'vertical' | 'vertical-right' | 'horizontal' | 'inline'; + +// menu mode +export enum MenuModeEnum { + VERTICAL = 'vertical', + HORIZONTAL = 'horizontal', + VERTICAL_RIGHT = 'vertical-right', + INLINE = 'inline', +} + +export enum MenuSplitTyeEnum { + NONE, + TOP, + LEFT, +} + +export enum TopMenuAlignEnum { + CENTER = 'center', + START = 'start', + END = 'end', +} + +export enum MixSidebarTriggerEnum { + HOVER = 'hover', + CLICK = 'click', +} diff --git a/src/enums/pageEnum.ts b/src/enums/pageEnum.ts new file mode 100644 index 0000000..8ac2274 --- /dev/null +++ b/src/enums/pageEnum.ts @@ -0,0 +1,11 @@ +export enum PageEnum { + // basic login path + BASE_LOGIN = '/login', + // basic home path + BASE_HOME = '/dashboard', + // error page path + ERROR_PAGE = '/exception', + // error log page path + ERROR_LOG_PAGE = '/error-log/list', +} +export const PageWrapperFixedHeightKey = 'PageWrapperFixedHeight'; diff --git a/src/enums/sizeEnum.ts b/src/enums/sizeEnum.ts new file mode 100644 index 0000000..cbbc152 --- /dev/null +++ b/src/enums/sizeEnum.ts @@ -0,0 +1,5 @@ +export enum SizeEnum { + DEFAULT = 'default', + SMALL = 'small', + LARGE = 'large', +} diff --git a/src/hooks/.DS_Store b/src/hooks/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..405c3117849b233183c24f99958f0ca1518cd80b GIT binary patch literal 6148 zcmeHKu};G<5IxhN7FaqU#OQ$)i4I6CNTGx;=ntT@RY7V<1qIe@O#Bu*f5bcc2yqij zEFgsLs=Jr^?tJH0#jc6Sj2~wsq9G9tpp3~bOoyKV6w zuBq~K4B*UW8SHsfs|+Xu%0SHk?++HrmxQUrGk}5pH4yXd?tN8st zOww=4fHLr}7%)jT$;MccoUN_J@mXu3*H9LYt30|C7&(sJ10ThQP$%$NegLL|l}C&~ P^pAj}L5(u-s|>( + props: T, + key?: K, + changeEvent?, + emitData?: Ref, +): [WritableComputedRef, (val: V) => void, DeepReadonly]; + +export function useRuleFormItem( + props: T, + key: keyof T = 'value', + changeEvent = 'change', + emitData?: Ref, +) { + const instance = getCurrentInstance(); + const emit = instance?.emit; + + const innerState = reactive({ + value: props[key], + }); + + const defaultState = readonly(innerState); + + const setState = (val: UnwrapRef): void => { + innerState.value = val as T[keyof T]; + }; + + watchEffect(() => { + innerState.value = props[key]; + }); + + const state: any = computed({ + get() { + return innerState.value; + }, + set(value) { + if (isEqual(value, defaultState.value)) return; + + innerState.value = value as T[keyof T]; + nextTick(() => { + emit?.(changeEvent, value, ...(toRaw(unref(emitData)) || [])); + }); + }, + }); + + return [state, setState, defaultState]; +} diff --git a/src/hooks/component/usePageContext.ts b/src/hooks/component/usePageContext.ts new file mode 100644 index 0000000..12cc160 --- /dev/null +++ b/src/hooks/component/usePageContext.ts @@ -0,0 +1,18 @@ +import type { InjectionKey, ComputedRef, Ref } from 'vue'; +import { createContext, useContext } from '/@/hooks/core/useContext'; + +export interface PageContextProps { + contentHeight: ComputedRef; + pageHeight: Ref; + setPageHeight: (height: number) => Promise; +} + +const key: InjectionKey = Symbol(); + +export function createPageContext(context: PageContextProps) { + return createContext(context, key, { native: true }); +} + +export function usePageContext() { + return useContext(key); +} diff --git a/src/hooks/core/useAttrs.ts b/src/hooks/core/useAttrs.ts new file mode 100644 index 0000000..7de9296 --- /dev/null +++ b/src/hooks/core/useAttrs.ts @@ -0,0 +1,41 @@ +import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue'; +import type { Ref } from 'vue'; + +interface Params { + excludeListeners?: boolean; + excludeKeys?: string[]; + excludeDefaultKeys?: boolean; +} + +const DEFAULT_EXCLUDE_KEYS = ['class', 'style']; +const LISTENER_PREFIX = /^on[A-Z]/; + +export function entries(obj: Recordable): [string, T][] { + return Object.keys(obj).map((key: string) => [key, obj[key]]); +} + +export function useAttrs(params: Params = {}): Ref | {} { + const instance = getCurrentInstance(); + if (!instance) return {}; + + const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = params; + const attrs = shallowRef({}); + const allExcludeKeys = excludeKeys.concat(excludeDefaultKeys ? DEFAULT_EXCLUDE_KEYS : []); + + // Since attrs are not reactive, make it reactive instead of doing in `onUpdated` hook for better performance + instance.attrs = reactive(instance.attrs); + + watchEffect(() => { + const res = entries(instance.attrs).reduce((acm, [key, val]) => { + if (!allExcludeKeys.includes(key) && !(excludeListeners && LISTENER_PREFIX.test(key))) { + acm[key] = val; + } + + return acm; + }, {} as Recordable); + + attrs.value = res; + }); + + return attrs; +} \ No newline at end of file diff --git a/src/hooks/core/useContext.ts b/src/hooks/core/useContext.ts new file mode 100644 index 0000000..04a9433 --- /dev/null +++ b/src/hooks/core/useContext.ts @@ -0,0 +1,43 @@ +import { + InjectionKey, + provide, + inject, + reactive, + readonly as defineReadonly, + UnwrapRef, +} from 'vue'; + +export interface CreateContextOptions { + readonly?: boolean; + createProvider?: boolean; + native?: boolean; +} + +type ShallowUnwrap = { + [P in keyof T]: UnwrapRef; +}; + +export function createContext( + context: any, + key: InjectionKey = Symbol(), + options: CreateContextOptions = {}, +) { + const { readonly = true, createProvider = true, native = false } = options; + + const state = reactive(context); + const provideData = readonly ? defineReadonly(state) : state; + createProvider && provide(key, native ? context : provideData); + + return { + state, + }; +} + +export function useContext(key: InjectionKey, native?: boolean): T; + +export function useContext( + key: InjectionKey = Symbol(), + defaultValue?: any, +): ShallowUnwrap { + return inject(key, defaultValue || {}); +} diff --git a/src/hooks/event/useBreakpoint.ts b/src/hooks/event/useBreakpoint.ts new file mode 100644 index 0000000..0ca3a6b --- /dev/null +++ b/src/hooks/event/useBreakpoint.ts @@ -0,0 +1,93 @@ +import { ref, computed, ComputedRef, unref } from 'vue'; +import { useEventListener } from '/@/hooks/event/useEventListener'; +import { screenMap, sizeEnum, screenEnum } from '/@/enums/breakpointEnum'; + +// 可以用这个替换,优化项 +// import { Grid } from 'ant-design-vue'; +// const { useBreakpoint } = Grid; + +let globalScreenRef: ComputedRef; +let globalWidthRef: ComputedRef; +let globalRealWidthRef: ComputedRef; + +export interface CreateCallbackParams { + screen: ComputedRef; + width: ComputedRef; + realWidth: ComputedRef; + screenEnum: typeof screenEnum; + screenMap: Map; + sizeEnum: typeof sizeEnum; +} + +export function useBreakpoint() { + return { + screenRef: computed(() => unref(globalScreenRef)), + widthRef: globalWidthRef, + screenEnum, + realWidthRef: globalRealWidthRef, + }; +} + +// Just call it once +export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void) { + const screenRef = ref(sizeEnum.XL); + const realWidthRef = ref(window.innerWidth); + + function getWindowWidth() { + const width = document.body.clientWidth; + const xs = screenMap.get(sizeEnum.XS)!; + const sm = screenMap.get(sizeEnum.SM)!; + const md = screenMap.get(sizeEnum.MD)!; + const lg = screenMap.get(sizeEnum.LG)!; + const xl = screenMap.get(sizeEnum.XL)!; + if (width < xs) { + screenRef.value = sizeEnum.XS; + } else if (width < sm) { + screenRef.value = sizeEnum.SM; + } else if (width < md) { + screenRef.value = sizeEnum.MD; + } else if (width < lg) { + screenRef.value = sizeEnum.LG; + } else if (width < xl) { + screenRef.value = sizeEnum.XL; + } else { + screenRef.value = sizeEnum.XXL; + } + realWidthRef.value = width; + } + + useEventListener({ + el: window, + name: 'resize', + + listener: () => { + getWindowWidth(); + resizeFn(); + }, + // wait: 100, + }); + + getWindowWidth(); + globalScreenRef = computed(() => unref(screenRef)); + globalWidthRef = computed((): number => screenMap.get(unref(screenRef)!)!); + globalRealWidthRef = computed((): number => unref(realWidthRef)); + + function resizeFn() { + fn?.({ + screen: globalScreenRef, + width: globalWidthRef, + realWidth: globalRealWidthRef, + screenEnum, + screenMap, + sizeEnum, + }); + } + + resizeFn(); + return { + screenRef: globalScreenRef, + screenEnum, + widthRef: globalWidthRef, + realWidthRef: globalRealWidthRef, + }; +} diff --git a/src/hooks/event/useEventListener.ts b/src/hooks/event/useEventListener.ts new file mode 100644 index 0000000..892cd92 --- /dev/null +++ b/src/hooks/event/useEventListener.ts @@ -0,0 +1,58 @@ +import type { Ref } from 'vue'; +import { ref, watch, unref } from 'vue'; +import { useThrottleFn, useDebounceFn } from '@vueuse/core'; + +export type RemoveEventFn = () => void; +export interface UseEventParams { + el?: Element | Ref | Window | any; + name: string; + listener: EventListener; + options?: boolean | AddEventListenerOptions; + autoRemove?: boolean; + isDebounce?: boolean; + wait?: number; +} +export function useEventListener({ + el = window, + name, + listener, + options, + autoRemove = true, + isDebounce = true, + wait = 80, +}: UseEventParams): { removeEvent: RemoveEventFn } { + /* eslint-disable-next-line */ + let remove: RemoveEventFn = () => {}; + const isAddRef = ref(false); + + if (el) { + const element = ref(el as Element) as Ref; + + const handler = isDebounce ? useDebounceFn(listener, wait) : useThrottleFn(listener, wait); + const realHandler = wait ? handler : listener; + const removeEventListener = (e: Element) => { + isAddRef.value = true; + e.removeEventListener(name, realHandler, options); + }; + const addEventListener = (e: Element) => e.addEventListener(name, realHandler, options); + + const removeWatch = watch( + element, + (v, _ov, cleanUp) => { + if (v) { + !unref(isAddRef) && addEventListener(v); + cleanUp(() => { + autoRemove && removeEventListener(v); + }); + } + }, + { immediate: true }, + ); + + remove = () => { + removeEventListener(element.value); + removeWatch(); + }; + } + return { removeEvent: remove }; +} diff --git a/src/hooks/event/useScroll.ts b/src/hooks/event/useScroll.ts new file mode 100644 index 0000000..cc60f9b --- /dev/null +++ b/src/hooks/event/useScroll.ts @@ -0,0 +1,65 @@ +import type { Ref } from 'vue'; + +import { ref, onMounted, watch, onUnmounted } from 'vue'; +import { isWindow, isObject } from '/@/utils/is'; +import { useThrottleFn } from '@vueuse/core'; + +export function useScroll( + refEl: Ref, + options?: { + wait?: number; + leading?: boolean; + trailing?: boolean; + }, +) { + const refX = ref(0); + const refY = ref(0); + let handler = () => { + if (isWindow(refEl.value)) { + refX.value = refEl.value.scrollX; + refY.value = refEl.value.scrollY; + } else if (refEl.value) { + refX.value = (refEl.value as Element).scrollLeft; + refY.value = (refEl.value as Element).scrollTop; + } + }; + + if (isObject(options)) { + let wait = 0; + if (options.wait && options.wait > 0) { + wait = options.wait; + Reflect.deleteProperty(options, 'wait'); + } + + handler = useThrottleFn(handler, wait); + } + + let stopWatch: () => void; + onMounted(() => { + stopWatch = watch( + refEl, + (el, prevEl, onCleanup) => { + if (el) { + el.addEventListener('scroll', handler); + } else if (prevEl) { + prevEl.removeEventListener('scroll', handler); + } + onCleanup(() => { + refX.value = refY.value = 0; + el && el.removeEventListener('scroll', handler); + }); + }, + { immediate: true }, + ); + }); + + onUnmounted(() => { + refEl.value && refEl.value.removeEventListener('scroll', handler); + }); + + function stop() { + stopWatch && stopWatch(); + } + + return { refX, refY, stop }; +} diff --git a/src/hooks/setting/index.ts b/src/hooks/setting/index.ts new file mode 100644 index 0000000..62ee13e --- /dev/null +++ b/src/hooks/setting/index.ts @@ -0,0 +1,18 @@ +import type { GlobConfig } from '#/config'; + +import { getAppEnvConfig } from '@/utils/env'; + +export const useGlobSetting = (): Readonly => { + const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL } = + getAppEnvConfig(); + + // Take global configuration + const glob: Readonly = { + title: VITE_GLOB_APP_TITLE, + apiUrl: VITE_GLOB_API_URL, + shortName: VITE_GLOB_APP_TITLE.replace(/\s/g, '_').replace(/-/g, '_'), + urlPrefix: VITE_GLOB_API_URL_PREFIX, + uploadUrl: VITE_GLOB_UPLOAD_URL, + }; + return glob as Readonly; +}; \ No newline at end of file diff --git a/src/hooks/setting/useDarkModeTheme.ts b/src/hooks/setting/useDarkModeTheme.ts new file mode 100644 index 0000000..abad5c9 --- /dev/null +++ b/src/hooks/setting/useDarkModeTheme.ts @@ -0,0 +1,18 @@ +import { computed } from 'vue'; +import { theme } from 'ant-design-vue'; +import { useRootSetting } from '/@/hooks/setting/useRootSetting'; +import { ThemeEnum } from '/@/enums/appEnum'; + +export function useDarkModeTheme() { + const { getDarkMode } = useRootSetting(); + const { darkAlgorithm } = theme; + const isDark = computed(() => getDarkMode.value === ThemeEnum.DARK); + const darkTheme = { + algorithm: [darkAlgorithm], + }; + + return { + isDark, + darkTheme, + }; +} diff --git a/src/hooks/setting/useHeaderSetting.ts b/src/hooks/setting/useHeaderSetting.ts new file mode 100644 index 0000000..abb51d7 --- /dev/null +++ b/src/hooks/setting/useHeaderSetting.ts @@ -0,0 +1,105 @@ +import type { HeaderSetting } from '/#/config'; + +import { computed, unref } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; + +import { useMenuSetting } from '@/hooks/setting/useMenuSetting'; +import { useRootSetting } from '@/hooks/setting/useRootSetting'; +import { useFullContent } from '@/hooks/web/useFullContent'; +import { MenuModeEnum } from '@/enums/menuEnum'; + +export function useHeaderSetting() { + const { getFullContent } = useFullContent(); + const appStore = useAppStore(); + + const getShowFullHeaderRef = computed(() => { + return ( + !unref(getFullContent) && + unref(getShowMixHeaderRef) && + unref(getShowHeader) && + !unref(getIsTopMenu) && + !unref(getIsMixSidebar) + ); + }); + + const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef)); + + const getShowInsetHeaderRef = computed(() => { + const need = !unref(getFullContent) && unref(getShowHeader); + return ( + (need && !unref(getShowMixHeaderRef)) || + (need && unref(getIsTopMenu)) || + (need && unref(getIsMixSidebar)) + ); + }); + + const { + getMenuMode, + getSplit, + getShowHeaderTrigger, + getIsSidebarType, + getIsMixSidebar, + getIsTopMenu, + } = useMenuSetting(); + const { getShowBreadCrumb, getShowLogo } = useRootSetting(); + + const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader)); + + const getShowDoc = computed(() => appStore.getHeaderSetting.showDoc); + + const getHeaderTheme = computed(() => appStore.getHeaderSetting.theme); + + const getShowHeader = computed(() => appStore.getHeaderSetting.show); + + const getFixed = computed(() => appStore.getHeaderSetting.fixed); + + const getHeaderBgColor = computed(() => appStore.getHeaderSetting.bgColor); + + const getShowSearch = computed(() => appStore.getHeaderSetting.showSearch); + + const getUseLockPage = computed(() => appStore.getHeaderSetting.useLockPage); + + const getShowFullScreen = computed(() => appStore.getHeaderSetting.showFullScreen); + + const getShowNotice = computed(() => appStore.getHeaderSetting.showNotice); + + const getShowBread = computed(() => { + return ( + unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit) + ); + }); + + const getShowHeaderLogo = computed(() => { + return unref(getShowLogo) && !unref(getIsSidebarType) && !unref(getIsMixSidebar); + }); + + const getShowContent = computed(() => { + return unref(getShowBread) || unref(getShowHeaderTrigger); + }); + + // Set header configuration + function setHeaderSetting(headerSetting: Partial) { + appStore.setProjectConfig({ headerSetting }); + } + return { + setHeaderSetting, + + getShowDoc, + getShowSearch, + getHeaderTheme, + getUseLockPage, + getShowFullScreen, + getShowNotice, + getShowBread, + getShowContent, + getShowHeaderLogo, + getShowHeader, + getFixed, + getShowMixHeaderRef, + getShowFullHeaderRef, + getShowInsetHeaderRef, + getUnFixedAndFull, + getHeaderBgColor, + }; +} diff --git a/src/hooks/setting/useMenuSetting.ts b/src/hooks/setting/useMenuSetting.ts new file mode 100644 index 0000000..ed43e73 --- /dev/null +++ b/src/hooks/setting/useMenuSetting.ts @@ -0,0 +1,168 @@ +import type { MenuSetting } from '/#/config'; + +import { computed, unref, ref } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; + +import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '@/enums/appEnum'; +import { MenuModeEnum, MenuTypeEnum, TriggerEnum } from '@/enums/menuEnum'; +import { useFullContent } from '@/hooks/web/useFullContent'; + +const mixSideHasChildren = ref(false); + +export function useMenuSetting() { + const { getFullContent: fullContent } = useFullContent(); + const appStore = useAppStore(); + + const getShowSidebar = computed(() => { + return ( + unref(getSplit) || + (unref(getShowMenu) && unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && !unref(fullContent)) + ); + }); + + const getCollapsed = computed(() => appStore.getMenuSetting.collapsed); + + const getMenuType = computed(() => appStore.getMenuSetting.type); + + const getMenuMode = computed(() => appStore.getMenuSetting.mode); + + const getMenuFixed = computed(() => appStore.getMenuSetting.fixed); + + const getShowMenu = computed(() => appStore.getMenuSetting.show); + + const getMenuHidden = computed(() => appStore.getMenuSetting.hidden); + + const getMenuWidth = computed(() => appStore.getMenuSetting.menuWidth); + + const getTrigger = computed(() => appStore.getMenuSetting.trigger); + + const getMenuTheme = computed(() => appStore.getMenuSetting.theme); + + const getSplit = computed(() => appStore.getMenuSetting.split); + + const getMenuBgColor = computed(() => appStore.getMenuSetting.bgColor); + + const getMixSideTrigger = computed(() => appStore.getMenuSetting.mixSideTrigger); + + const getCanDrag = computed(() => appStore.getMenuSetting.canDrag); + + const getAccordion = computed(() => appStore.getMenuSetting.accordion); + + const getMixSideFixed = computed(() => appStore.getMenuSetting.mixSideFixed); + + const getTopMenuAlign = computed(() => appStore.getMenuSetting.topMenuAlign); + + const getCloseMixSidebarOnChange = computed( + () => appStore.getMenuSetting.closeMixSidebarOnChange, + ); + + const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR); + + const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU); + + const getCollapsedShowTitle = computed(() => appStore.getMenuSetting.collapsedShowTitle); + + const getShowTopMenu = computed(() => { + return unref(getMenuMode) === MenuModeEnum.HORIZONTAL || unref(getSplit); + }); + + const getShowHeaderTrigger = computed(() => { + if ( + unref(getMenuType) === MenuTypeEnum.TOP_MENU || + !unref(getShowMenu) || + unref(getMenuHidden) + ) { + return false; + } + + return unref(getTrigger) === TriggerEnum.HEADER; + }); + + const getIsHorizontal = computed(() => { + return unref(getMenuMode) === MenuModeEnum.HORIZONTAL; + }); + + const getIsMixSidebar = computed(() => { + return unref(getMenuType) === MenuTypeEnum.MIX_SIDEBAR; + }); + + const getIsMixMode = computed(() => { + return unref(getMenuMode) === MenuModeEnum.INLINE && unref(getMenuType) === MenuTypeEnum.MIX; + }); + + const getRealWidth = computed(() => { + if (unref(getIsMixSidebar)) { + return unref(getCollapsed) && !unref(getMixSideFixed) + ? unref(getMiniWidthNumber) + : unref(getMenuWidth); + } + return unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMenuWidth); + }); + + const getMiniWidthNumber = computed(() => { + const { collapsedShowTitle, siderHidden } = appStore.getMenuSetting; + return siderHidden + ? 0 + : collapsedShowTitle + ? SIDE_BAR_SHOW_TIT_MINI_WIDTH + : SIDE_BAR_MINI_WIDTH; + }); + + const getCalcContentWidth = computed(() => { + const width = + unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && unref(getMenuHidden)) + ? 0 + : unref(getIsMixSidebar) + ? (unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH) + + (unref(getMixSideFixed) && unref(mixSideHasChildren) ? unref(getRealWidth) : 0) + : unref(getRealWidth); + + return `calc(100% - ${unref(width)}px)`; + }); + + // Set menu configuration + function setMenuSetting(menuSetting: Partial): void { + appStore.setMenuSetting(menuSetting); + } + + function toggleCollapsed() { + setMenuSetting({ + collapsed: !unref(getCollapsed), + }); + } + return { + setMenuSetting, + toggleCollapsed, + getMenuFixed, + getRealWidth, + getMenuType, + getMenuMode, + getShowMenu, + getCollapsed, + getMiniWidthNumber, + getCalcContentWidth, + getMenuWidth, + getTrigger, + getSplit, + getMenuTheme, + getCanDrag, + getCollapsedShowTitle, + getIsHorizontal, + getIsSidebarType, + getAccordion, + getShowTopMenu, + getShowHeaderTrigger, + getTopMenuAlign, + getMenuHidden, + getIsTopMenu, + getMenuBgColor, + getShowSidebar, + getIsMixMode, + getIsMixSidebar, + getCloseMixSidebarOnChange, + getMixSideTrigger, + getMixSideFixed, + mixSideHasChildren, + }; +} diff --git a/src/hooks/setting/useMultipleTabSetting.ts b/src/hooks/setting/useMultipleTabSetting.ts new file mode 100644 index 0000000..078e9cb --- /dev/null +++ b/src/hooks/setting/useMultipleTabSetting.ts @@ -0,0 +1,28 @@ +import type { MultiTabsSetting } from '/#/config'; + +import { computed } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; + +export function useMultipleTabSetting() { + const appStore = useAppStore(); + + const getShowMultipleTab = computed(() => appStore.getMultiTabsSetting.show); + + const getShowQuick = computed(() => appStore.getMultiTabsSetting.showQuick); + + const getShowRedo = computed(() => appStore.getMultiTabsSetting.showRedo); + + const getShowFold = computed(() => appStore.getMultiTabsSetting.showFold); + + function setMultipleTabSetting(multiTabsSetting: Partial) { + appStore.setProjectConfig({ multiTabsSetting }); + } + return { + setMultipleTabSetting, + getShowMultipleTab, + getShowQuick, + getShowRedo, + getShowFold, + }; +} diff --git a/src/hooks/setting/useRootSetting.ts b/src/hooks/setting/useRootSetting.ts new file mode 100644 index 0000000..f9b970a --- /dev/null +++ b/src/hooks/setting/useRootSetting.ts @@ -0,0 +1,95 @@ +import type { ProjectConfig } from '/#/config'; + +import { computed } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; +import { ContentEnum, ThemeEnum } from '@/enums/appEnum'; + +type RootSetting = Omit< + ProjectConfig, + 'locale' | 'headerSetting' | 'menuSetting' | 'multiTabsSetting' +>; + +export function useRootSetting() { + const appStore = useAppStore(); + + const getPageLoading = computed(() => appStore.getPageLoading); + + const getOpenKeepAlive = computed(() => appStore.getProjectConfig.openKeepAlive); + + const getSettingButtonPosition = computed(() => appStore.getProjectConfig.settingButtonPosition); + + const getCanEmbedIFramePage = computed(() => appStore.getProjectConfig.canEmbedIFramePage); + + const getPermissionMode = computed(() => appStore.getProjectConfig.permissionMode); + + const getShowLogo = computed(() => appStore.getProjectConfig.showLogo); + + const getContentMode = computed(() => appStore.getProjectConfig.contentMode); + + const getUseOpenBackTop = computed(() => appStore.getProjectConfig.useOpenBackTop); + + const getShowSettingButton = computed(() => appStore.getProjectConfig.showSettingButton); + + const getUseErrorHandle = computed(() => appStore.getProjectConfig.useErrorHandle); + + const getShowFooter = computed(() => appStore.getProjectConfig.showFooter); + + const getShowBreadCrumb = computed(() => appStore.getProjectConfig.showBreadCrumb); + + const getThemeColor = computed(() => appStore.getProjectConfig.themeColor); + + const getShowBreadCrumbIcon = computed(() => appStore.getProjectConfig.showBreadCrumbIcon); + + const getFullContent = computed(() => appStore.getProjectConfig.fullContent); + + const getColorWeak = computed(() => appStore.getProjectConfig.colorWeak); + + const getGrayMode = computed(() => appStore.getProjectConfig.grayMode); + + const getLockTime = computed(() => appStore.getProjectConfig.lockTime); + + const getShowDarkModeToggle = computed(() => appStore.getProjectConfig.showDarkModeToggle); + + const getDarkMode = computed(() => appStore.getDarkMode); + + const getLayoutContentMode = computed(() => + appStore.getProjectConfig.contentMode === ContentEnum.FULL + ? ContentEnum.FULL + : ContentEnum.FIXED, + ); + + function setRootSetting(setting: Partial) { + appStore.setProjectConfig(setting); + } + + function setDarkMode(mode: ThemeEnum) { + appStore.setDarkMode(mode); + } + return { + setRootSetting, + + getSettingButtonPosition, + getFullContent, + getColorWeak, + getGrayMode, + getLayoutContentMode, + getPageLoading, + getOpenKeepAlive, + getCanEmbedIFramePage, + getPermissionMode, + getShowLogo, + getUseErrorHandle, + getShowBreadCrumb, + getShowBreadCrumbIcon, + getUseOpenBackTop, + getShowSettingButton, + getShowFooter, + getContentMode, + getLockTime, + getThemeColor, + getDarkMode, + setDarkMode, + getShowDarkModeToggle, + }; +} diff --git a/src/hooks/setting/useTransitionSetting.ts b/src/hooks/setting/useTransitionSetting.ts new file mode 100644 index 0000000..9ba1977 --- /dev/null +++ b/src/hooks/setting/useTransitionSetting.ts @@ -0,0 +1,31 @@ +import type { TransitionSetting } from '/#/config'; + +import { computed } from 'vue'; + +import { useAppStore } from '@/store/modules/app'; + +export function useTransitionSetting() { + const appStore = useAppStore(); + + const getEnableTransition = computed(() => appStore.getTransitionSetting?.enable); + + const getOpenNProgress = computed(() => appStore.getTransitionSetting?.openNProgress); + + const getOpenPageLoading = computed((): boolean => { + return !!appStore.getTransitionSetting?.openPageLoading; + }); + + const getBasicTransition = computed(() => appStore.getTransitionSetting?.basicTransition); + + function setTransitionSetting(transitionSetting: Partial) { + appStore.setProjectConfig({ transitionSetting }); + } + return { + setTransitionSetting, + + getEnableTransition, + getOpenNProgress, + getOpenPageLoading, + getBasicTransition, + }; +} diff --git a/src/hooks/web/useAppInject.ts b/src/hooks/web/useAppInject.ts new file mode 100644 index 0000000..7d6efb2 --- /dev/null +++ b/src/hooks/web/useAppInject.ts @@ -0,0 +1,10 @@ +import { useAppProviderContext } from '/@/components/Application'; +import { computed, unref } from 'vue'; + +export function useAppInject() { + const values = useAppProviderContext(); + + return { + getIsMobile: computed(() => unref(values.isMobile)), + }; +} diff --git a/src/hooks/web/useContentHeight.ts b/src/hooks/web/useContentHeight.ts new file mode 100644 index 0000000..558cd51 --- /dev/null +++ b/src/hooks/web/useContentHeight.ts @@ -0,0 +1,189 @@ +import { ComputedRef, isRef, nextTick, Ref, ref, unref, watch } from 'vue'; +import { onMountedOrActivated, useWindowSizeFn } from '@vben/hooks'; +import { useLayoutHeight } from '/@/layouts/default/content/useContentViewHeight'; +import { getViewportOffset } from '/@/utils/domUtils'; +import { isNumber, isString } from '/@/utils/is'; + +export interface CompensationHeight { + // 使用 layout Footer 高度作为判断补偿高度的条件 + useLayoutFooter: boolean; + // refs HTMLElement + elements?: Ref[]; +} + +type Upward = number | string | null | undefined; + +/** + * 动态计算内容高度,根据锚点dom最下坐标到屏幕最下坐标,根据传入dom的高度、padding、margin等值进行动态计算 + * 最终获取合适的内容高度 + * + * @param flag 用于开启计算的响应式标识 + * @param anchorRef 锚点组件 Ref + * @param subtractHeightRefs 待减去高度的组件列表 Ref + * @param substractSpaceRefs 待减去空闲空间(margins/paddings)的组件列表 Ref + * @param offsetHeightRef 计算偏移的响应式高度,计算高度时将直接减去此值 + * @param upwardSpace 向上递归减去空闲空间的 层级 或 直到指定class为止 数值为2代表向上递归两次|数值为ant-layout表示向上递归直到碰见.ant-layout为止 + * @returns 响应式高度 + */ +export function useContentHeight( + flag: ComputedRef, + anchorRef: Ref, + subtractHeightRefs: Ref[], + substractSpaceRefs: Ref[], + upwardSpace: Ref | ComputedRef | Upward = 0, + offsetHeightRef: Ref = ref(0), +) { + const contentHeight: Ref> = ref(null); + const { footerHeightRef: layoutFooterHeightRef } = useLayoutHeight(); + let compensationHeight: CompensationHeight = { + useLayoutFooter: true, + }; + + const setCompensation = (params: CompensationHeight) => { + compensationHeight = params; + }; + + function redoHeight() { + nextTick(() => { + calcContentHeight(); + }); + } + + function calcSubtractSpace( + element: Element | null | undefined, + direction: 'all' | 'top' | 'bottom' = 'all', + ): number { + function numberPx(px: string) { + return Number(px.replace(/[^\d]/g, '')); + } + let subtractHeight = 0; + const ZERO_PX = '0px'; + if (element) { + const cssStyle = getComputedStyle(element); + const marginTop = numberPx(cssStyle?.marginTop ?? ZERO_PX); + const marginBottom = numberPx(cssStyle?.marginBottom ?? ZERO_PX); + const paddingTop = numberPx(cssStyle?.paddingTop ?? ZERO_PX); + const paddingBottom = numberPx(cssStyle?.paddingBottom ?? ZERO_PX); + if (direction === 'all') { + subtractHeight += marginTop; + subtractHeight += marginBottom; + subtractHeight += paddingTop; + subtractHeight += paddingBottom; + } else if (direction === 'top') { + subtractHeight += marginTop; + subtractHeight += paddingTop; + } else { + subtractHeight += marginBottom; + subtractHeight += paddingBottom; + } + } + return subtractHeight; + } + + function getEl(element: any): Nullable { + if (element == null) { + return null; + } + return (element instanceof HTMLDivElement ? element : element.$el) as HTMLDivElement; + } + + async function calcContentHeight() { + if (!flag.value) { + return; + } + // Add a delay to get the correct height + await nextTick(); + + const anchorEl = getEl(unref(anchorRef)); + if (!anchorEl) { + return; + } + const { bottomIncludeBody } = getViewportOffset(anchorEl); + + // substract elements height + let substractHeight = 0; + subtractHeightRefs.forEach((item) => { + substractHeight += getEl(unref(item))?.offsetHeight ?? 0; + }); + + // subtract margins / paddings + let substractSpaceHeight = calcSubtractSpace(anchorEl) ?? 0; + substractSpaceRefs.forEach((item) => { + substractSpaceHeight += calcSubtractSpace(getEl(unref(item))); + }); + + // upwardSpace + let upwardSpaceHeight = 0; + function upward(element: Element | null, upwardLvlOrClass: number | string | null | undefined) { + if (element && upwardLvlOrClass) { + const parent = element.parentElement; + if (parent) { + if (isString(upwardLvlOrClass)) { + if (!parent.classList.contains(upwardLvlOrClass)) { + upwardSpaceHeight += calcSubtractSpace(parent, 'bottom'); + upward(parent, upwardLvlOrClass); + } else { + upwardSpaceHeight += calcSubtractSpace(parent, 'bottom'); + } + } else if (isNumber(upwardLvlOrClass)) { + if (upwardLvlOrClass > 0) { + upwardSpaceHeight += calcSubtractSpace(parent, 'bottom'); + upward(parent, --upwardLvlOrClass); + } + } + } + } + } + if (isRef(upwardSpace)) { + upward(anchorEl, unref(upwardSpace)); + } else { + upward(anchorEl, upwardSpace); + } + + let height = + bottomIncludeBody - + unref(layoutFooterHeightRef) - + unref(offsetHeightRef) - + substractHeight - + substractSpaceHeight - + upwardSpaceHeight; + + // compensation height + const calcCompensationHeight = () => { + compensationHeight.elements?.forEach((item) => { + height += getEl(unref(item))?.offsetHeight ?? 0; + }); + }; + if (compensationHeight.useLayoutFooter && unref(layoutFooterHeightRef) > 0) { + calcCompensationHeight(); + } else { + calcCompensationHeight(); + } + + contentHeight.value = height; + } + + onMountedOrActivated(() => { + nextTick(() => { + calcContentHeight(); + }); + }); + useWindowSizeFn( + () => { + calcContentHeight(); + }, + { wait: 50, immediate: true }, + ); + watch( + () => [layoutFooterHeightRef.value], + () => { + calcContentHeight(); + }, + { + flush: 'post', + immediate: true, + }, + ); + + return { redoHeight, setCompensation, contentHeight }; +} diff --git a/src/hooks/web/useContextMenu.ts b/src/hooks/web/useContextMenu.ts new file mode 100644 index 0000000..3237d35 --- /dev/null +++ b/src/hooks/web/useContextMenu.ts @@ -0,0 +1,13 @@ +import { onUnmounted, getCurrentInstance } from 'vue'; +import { createContextMenu, destroyContextMenu } from '/@/components/ContextMenu'; +import type { ContextMenuItem } from '/@/components/ContextMenu'; + +export type { ContextMenuItem }; +export function useContextMenu(authRemove = true) { + if (getCurrentInstance() && authRemove) { + onUnmounted(() => { + destroyContextMenu(); + }); + } + return [createContextMenu, destroyContextMenu]; +} diff --git a/src/hooks/web/useCopyToClipboard.ts b/src/hooks/web/useCopyToClipboard.ts new file mode 100644 index 0000000..5072f9c --- /dev/null +++ b/src/hooks/web/useCopyToClipboard.ts @@ -0,0 +1,70 @@ +import { ref, watch } from 'vue'; + +import { isDef } from '/@/utils/is'; + +interface Options { + target?: HTMLElement; +} +export function useCopyToClipboard(initial?: string) { + const clipboardRef = ref(initial || ''); + const isSuccessRef = ref(false); + const copiedRef = ref(false); + + watch( + clipboardRef, + (str?: string) => { + if (isDef(str)) { + copiedRef.value = true; + isSuccessRef.value = copyTextToClipboard(str); + } + }, + { immediate: !!initial, flush: 'sync' }, + ); + + return { clipboardRef, isSuccessRef, copiedRef }; +} + +export function copyTextToClipboard(input: string, { target = document.body }: Options = {}) { + const element = document.createElement('textarea'); + const previouslyFocusedElement = document.activeElement; + + element.value = input; + + element.setAttribute('readonly', ''); + + (element.style as any).contain = 'strict'; + element.style.position = 'absolute'; + element.style.left = '-9999px'; + element.style.fontSize = '12pt'; + + const selection = document.getSelection(); + let originalRange; + if (selection && selection.rangeCount > 0) { + originalRange = selection.getRangeAt(0); + } + + target.append(element); + element.select(); + + element.selectionStart = 0; + element.selectionEnd = input.length; + + let isSuccess = false; + try { + isSuccess = document.execCommand('copy'); + } catch (e: any) { + throw new Error(e); + } + + element.remove(); + + if (originalRange && selection) { + selection.removeAllRanges(); + selection.addRange(originalRange); + } + + if (previouslyFocusedElement) { + (previouslyFocusedElement as HTMLElement).focus(); + } + return isSuccess; +} diff --git a/src/hooks/web/useDesign.ts b/src/hooks/web/useDesign.ts new file mode 100644 index 0000000..046674b --- /dev/null +++ b/src/hooks/web/useDesign.ts @@ -0,0 +1,22 @@ +import { useAppProviderContext } from '/@/components/Application'; +// import { computed } from 'vue'; +// import { lowerFirst } from 'lodash-es'; +export function useDesign(scope: string) { + const values = useAppProviderContext(); + // const $style = cssModule ? useCssModule() : {}; + + // const style: Record = {}; + // if (cssModule) { + // Object.keys($style).forEach((key) => { + // // const moduleCls = $style[key]; + // const k = key.replace(new RegExp(`^${values.prefixCls}-?`, 'ig'), ''); + // style[lowerFirst(k)] = $style[key]; + // }); + // } + return { + // prefixCls: computed(() => `${values.prefixCls}-${scope}`), + prefixCls: `${values.prefixCls}-${scope}`, + prefixVar: values.prefixCls, + // style, + }; +} diff --git a/src/hooks/web/useECharts.ts b/src/hooks/web/useECharts.ts new file mode 100644 index 0000000..643ce60 --- /dev/null +++ b/src/hooks/web/useECharts.ts @@ -0,0 +1,131 @@ +import type { EChartsOption } from 'echarts'; +import type { Ref } from 'vue'; +import { useTimeoutFn } from '@vben/hooks'; +import { tryOnUnmounted, useDebounceFn } from '@vueuse/core'; +import { unref, nextTick, watch, computed, ref } from 'vue'; +import { useEventListener } from '/@/hooks/event/useEventListener'; +import { useBreakpoint } from '/@/hooks/event/useBreakpoint'; +import echarts from '/@/utils/lib/echarts'; +import { useRootSetting } from '/@/hooks/setting/useRootSetting'; +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; + +export function useECharts( + elRef: Ref, + theme: 'light' | 'dark' | 'default' = 'default', +) { + const { getDarkMode: getSysDarkMode } = useRootSetting(); + const { getCollapsed } = useMenuSetting(); + + const getDarkMode = computed(() => { + return theme === 'default' ? getSysDarkMode.value : theme; + }); + let chartInstance: echarts.ECharts | null = null; + let resizeFn: Fn = resize; + const cacheOptions = ref({}) as Ref; + let removeResizeFn: Fn = () => {}; + + resizeFn = useDebounceFn(resize, 200); + + const getOptions = computed(() => { + if (getDarkMode.value !== 'dark') { + return cacheOptions.value as EChartsOption; + } + return { + backgroundColor: 'transparent', + ...cacheOptions.value, + } as EChartsOption; + }); + + function initCharts(t = theme) { + const el = unref(elRef); + if (!el || !unref(el)) { + return; + } + + chartInstance = echarts.init(el, t); + const { removeEvent } = useEventListener({ + el: window, + name: 'resize', + listener: resizeFn, + }); + removeResizeFn = removeEvent; + const { widthRef, screenEnum } = useBreakpoint(); + if (unref(widthRef) <= screenEnum.MD || el.offsetHeight === 0) { + useTimeoutFn(() => { + resizeFn(); + }, 30); + } + } + + function setOptions(options: EChartsOption, clear = true) { + cacheOptions.value = options; + return new Promise((resolve) => { + if (unref(elRef)?.offsetHeight === 0) { + useTimeoutFn(() => { + setOptions(unref(getOptions)); + resolve(null); + }, 30); + } + nextTick(() => { + useTimeoutFn(() => { + if (!chartInstance) { + initCharts(getDarkMode.value as 'default'); + + if (!chartInstance) return; + } + clear && chartInstance?.clear(); + + chartInstance?.setOption(unref(getOptions)); + resolve(null); + }, 30); + }); + }); + } + + function resize() { + chartInstance?.resize({ + animation: { + duration: 300, + easing: 'quadraticIn', + }, + }); + } + + watch( + () => getDarkMode.value, + (theme) => { + if (chartInstance) { + chartInstance.dispose(); + initCharts(theme as 'default'); + setOptions(cacheOptions.value); + } + }, + ); + + watch(getCollapsed, (_) => { + useTimeoutFn(() => { + resizeFn(); + }, 300); + }); + + tryOnUnmounted(() => { + if (!chartInstance) return; + removeResizeFn(); + chartInstance.dispose(); + chartInstance = null; + }); + + function getInstance(): echarts.ECharts | null { + if (!chartInstance) { + initCharts(getDarkMode.value as 'default'); + } + return chartInstance; + } + + return { + setOptions, + resize, + echarts, + getInstance, + }; +} diff --git a/src/hooks/web/useFullContent.ts b/src/hooks/web/useFullContent.ts new file mode 100644 index 0000000..7dea077 --- /dev/null +++ b/src/hooks/web/useFullContent.ts @@ -0,0 +1,28 @@ +import { computed, unref } from 'vue'; + +import { useAppStore } from '/@/store/modules/app'; + +import { useRouter } from 'vue-router'; + +/** + * @description: Full screen display content + */ +export const useFullContent = () => { + const appStore = useAppStore(); + const router = useRouter(); + const { currentRoute } = router; + + // Whether to display the content in full screen without displaying the menu + const getFullContent = computed(() => { + // Query parameters, the full screen is displayed when the address bar has a full parameter + const route = unref(currentRoute); + const query = route.query; + if (query && Reflect.has(query, '__full__')) { + return true; + } + // Return to the configuration in the configuration file + return appStore.getProjectConfig.fullContent; + }); + + return { getFullContent }; +}; diff --git a/src/hooks/web/useI18n.ts b/src/hooks/web/useI18n.ts new file mode 100644 index 0000000..2a777b7 --- /dev/null +++ b/src/hooks/web/useI18n.ts @@ -0,0 +1,55 @@ +import { i18n } from '/@/locales/setupI18n'; + +type I18nGlobalTranslation = { + (key: string): string; + (key: string, locale: string): string; + (key: string, locale: string, list: unknown[]): string; + (key: string, locale: string, named: Record): string; + (key: string, list: unknown[]): string; + (key: string, named: Record): string; +}; + +type I18nTranslationRestParameters = [string, any]; + +function getKey(namespace: string | undefined, key: string) { + if (!namespace) { + return key; + } + if (key.startsWith(namespace)) { + return key; + } + return `${namespace}.${key}`; +} + +export function useI18n(namespace?: string): { + t: I18nGlobalTranslation; +} { + const normalFn = { + t: (key: string) => { + return getKey(namespace, key); + }, + }; + + if (!i18n) { + return normalFn; + } + + const { t, ...methods } = i18n.global; + + const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => { + if (!key) return ''; + if (!key.includes('.') && !namespace) return key; + return t(getKey(namespace, key), ...(arg as I18nTranslationRestParameters)); + }; + return { + ...methods, + t: tFn, + }; +} + +// Why write this function? +// Mainly to configure the vscode i18nn ally plugin. This function is only used for routing and menus. Please use useI18n for other places + +// 为什么要编写此函数? +// 主要用于配合vscode i18nn ally插件。此功能仅用于路由和菜单。请在其他地方使用useI18n +export const t = (key: string) => key; diff --git a/src/hooks/web/useLockPage.ts b/src/hooks/web/useLockPage.ts new file mode 100644 index 0000000..c543be9 --- /dev/null +++ b/src/hooks/web/useLockPage.ts @@ -0,0 +1,72 @@ +import { computed, onUnmounted, unref, watchEffect } from 'vue'; +import { useThrottleFn } from '@vueuse/core'; + +import { useAppStore } from '/@/store/modules/app'; +import { useLockStore } from '/@/store/modules/lock'; + +import { useUserStore } from '/@/store/modules/user'; +import { useRootSetting } from '../setting/useRootSetting'; + +export function useLockPage() { + const { getLockTime } = useRootSetting(); + const lockStore = useLockStore(); + const userStore = useUserStore(); + const appStore = useAppStore(); + + let timeId: TimeoutHandle; + + function clear(): void { + window.clearTimeout(timeId); + } + + function resetCalcLockTimeout(): void { + // not login + if (!userStore.getToken) { + clear(); + return; + } + const lockTime = appStore.getProjectConfig.lockTime; + if (!lockTime || lockTime < 1) { + clear(); + return; + } + clear(); + + timeId = setTimeout(() => { + lockPage(); + }, lockTime * 60 * 1000); + } + + function lockPage(): void { + lockStore.setLockInfo({ + isLock: true, + pwd: undefined, + }); + } + + watchEffect((onClean) => { + if (userStore.getToken) { + resetCalcLockTimeout(); + } else { + clear(); + } + onClean(() => { + clear(); + }); + }); + + onUnmounted(() => { + clear(); + }); + + const keyupFn = useThrottleFn(resetCalcLockTimeout, 2000); + + return computed(() => { + if (unref(getLockTime)) { + return { onKeyup: keyupFn, onMousemove: keyupFn }; + } else { + clear(); + return {}; + } + }); +} diff --git a/src/hooks/web/useMessage.tsx b/src/hooks/web/useMessage.tsx new file mode 100644 index 0000000..2de8a38 --- /dev/null +++ b/src/hooks/web/useMessage.tsx @@ -0,0 +1,121 @@ +import type { ModalFunc, ModalFuncProps } from 'ant-design-vue/lib/modal/Modal'; +import { Modal, message as Message, notification } from 'ant-design-vue'; +import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons-vue'; +import { NotificationArgsProps, ConfigProps } from 'ant-design-vue/lib/notification'; +import { useI18n } from './useI18n'; +import { isString } from '/@/utils/is'; + +export interface NotifyApi { + info(config: NotificationArgsProps): void; + success(config: NotificationArgsProps): void; + error(config: NotificationArgsProps): void; + warn(config: NotificationArgsProps): void; + warning(config: NotificationArgsProps): void; + open(args: NotificationArgsProps): void; + close(key: String): void; + config(options: ConfigProps): void; + destroy(): void; +} + +export declare type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'; +export declare type IconType = 'success' | 'info' | 'error' | 'warning'; +export interface ModalOptionsEx extends Omit { + iconType: 'warning' | 'success' | 'error' | 'info'; +} +export type ModalOptionsPartial = Partial & Pick; + +interface ConfirmOptions { + info: ModalFunc; + success: ModalFunc; + error: ModalFunc; + warn: ModalFunc; + warning: ModalFunc; +} + +function getIcon(iconType: string) { + if (iconType === 'warning') { + return ; + } else if (iconType === 'success') { + return ; + } else if (iconType === 'info') { + return ; + } else { + return ; + } +} + +function renderContent({ content }: Pick) { + if (isString(content)) { + return
    ${content as string}
    `}>; + } else { + return content; + } +} + +/** + * @description: Create confirmation box + */ +function createConfirm(options: ModalOptionsEx): ConfirmOptions { + const iconType = options.iconType || 'warning'; + Reflect.deleteProperty(options, 'iconType'); + const opt: ModalFuncProps = { + centered: true, + icon: getIcon(iconType), + ...options, + content: renderContent(options), + }; + return Modal.confirm(opt) as unknown as ConfirmOptions; +} + +const getBaseOptions = () => { + const { t } = useI18n(); + return { + okText: t('common.okText'), + centered: true, + }; +}; + +function createModalOptions(options: ModalOptionsPartial, icon: string): ModalOptionsPartial { + return { + ...getBaseOptions(), + ...options, + content: renderContent(options), + icon: getIcon(icon), + }; +} + +function createSuccessModal(options: ModalOptionsPartial) { + return Modal.success(createModalOptions(options, 'success')); +} + +function createErrorModal(options: ModalOptionsPartial) { + return Modal.error(createModalOptions(options, 'error')); +} + +function createInfoModal(options: ModalOptionsPartial) { + return Modal.info(createModalOptions(options, 'info')); +} + +function createWarningModal(options: ModalOptionsPartial) { + return Modal.warning(createModalOptions(options, 'warning')); +} + +notification.config({ + placement: 'topRight', + duration: 3, +}); + +/** + * @description: message + */ +export function useMessage() { + return { + createMessage: Message, + notification: notification as NotifyApi, + createConfirm: createConfirm, + createSuccessModal, + createErrorModal, + createInfoModal, + createWarningModal, + }; +} diff --git a/src/hooks/web/usePage.ts b/src/hooks/web/usePage.ts new file mode 100644 index 0000000..a4a5c73 --- /dev/null +++ b/src/hooks/web/usePage.ts @@ -0,0 +1,54 @@ +import type { RouteLocationRaw, Router } from 'vue-router'; + +import { PageEnum } from '/@/enums/pageEnum'; +import { unref } from 'vue'; + +import { useRouter } from 'vue-router'; +import { REDIRECT_NAME } from '/@/router/constant'; + +export type PathAsPageEnum = T extends { path: string } ? T & { path: PageEnum } : T; +export type RouteLocationRawEx = PathAsPageEnum; + +function handleError(e: Error) { + console.error(e); +} + +/** + * page switch + */ +export function useGo(_router?: Router) { + const { push, replace } = _router || useRouter(); + function go(opt: RouteLocationRawEx = PageEnum.BASE_HOME, isReplace = false) { + if (!opt) { + return; + } + isReplace ? replace(opt).catch(handleError) : push(opt).catch(handleError); + } + return go; +} + +/** + * @description: redo current page + */ +export const useRedo = (_router?: Router) => { + const { replace, currentRoute } = _router || useRouter(); + const { query, params = {}, name, fullPath } = unref(currentRoute.value); + function redo(): Promise { + return new Promise((resolve) => { + if (name === REDIRECT_NAME) { + resolve(false); + return; + } + if (name && Object.keys(params).length > 0) { + params['_origin_params'] = JSON.stringify(params ?? {}); + params['_redirect_type'] = 'name'; + params['path'] = String(name); + } else { + params['_redirect_type'] = 'path'; + params['path'] = fullPath; + } + replace({ name: REDIRECT_NAME, params, query }).then(() => resolve(true)); + }); + } + return redo; +}; diff --git a/src/hooks/web/usePagination.ts b/src/hooks/web/usePagination.ts new file mode 100644 index 0000000..1e19913 --- /dev/null +++ b/src/hooks/web/usePagination.ts @@ -0,0 +1,34 @@ +import type { Ref } from 'vue'; +import { ref, unref, computed } from 'vue'; + +function pagination(list: T[], pageNo: number, pageSize: number): T[] { + const offset = (pageNo - 1) * Number(pageSize); + const ret = + offset + Number(pageSize) >= list.length + ? list.slice(offset, list.length) + : list.slice(offset, offset + Number(pageSize)); + return ret; +} + +export function usePagination(list: Ref, pageSize: number) { + const currentPage = ref(1); + const pageSizeRef = ref(pageSize); + + const getPaginationList = computed(() => { + return pagination(unref(list), unref(currentPage), unref(pageSizeRef)); + }); + + const getTotal = computed(() => { + return unref(list).length; + }); + + function setCurrentPage(page: number) { + currentPage.value = page; + } + + function setPageSize(pageSize: number) { + pageSizeRef.value = pageSize; + } + + return { setCurrentPage, getTotal, setPageSize, getPaginationList }; +} diff --git a/src/hooks/web/usePermission.ts b/src/hooks/web/usePermission.ts new file mode 100644 index 0000000..8a82d46 --- /dev/null +++ b/src/hooks/web/usePermission.ts @@ -0,0 +1,119 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { useAppStore } from '/@/store/modules/app'; +import { usePermissionStore } from '/@/store/modules/permission'; +import { useUserStore } from '/@/store/modules/user'; + +import { useTabs } from './useTabs'; + +import { router, resetRouter } from '/@/router'; +// import { RootRoute } from '/@/router/routes'; + +import projectSetting from '/@/settings/projectSetting'; +import { PermissionModeEnum } from '/@/enums/appEnum'; +import { RoleEnum } from '/@/enums/roleEnum'; + +import { intersection } from 'lodash-es'; +import { isArray } from '/@/utils/is'; +import { useMultipleTabStore } from '/@/store/modules/multipleTab'; + +// User permissions related operations +export function usePermission() { + const userStore = useUserStore(); + const appStore = useAppStore(); + const permissionStore = usePermissionStore(); + const { closeAll } = useTabs(router); + + /** + * Change permission mode + */ + async function togglePermissionMode() { + appStore.setProjectConfig({ + permissionMode: + appStore.projectConfig?.permissionMode === PermissionModeEnum.BACK + ? PermissionModeEnum.ROUTE_MAPPING + : PermissionModeEnum.BACK, + }); + location.reload(); + } + + /** + * Reset and regain authority resource information + * 重置和重新获得权限资源信息 + * @param id + */ + async function resume() { + const tabStore = useMultipleTabStore(); + tabStore.clearCacheTabs(); + resetRouter(); + const routes = await permissionStore.buildRoutesAction(); + routes.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw); + }); + permissionStore.setLastBuildMenuTime(); + closeAll(); + } + + /** + * Determine whether there is permission + */ + function hasPermission(value?: RoleEnum | RoleEnum[] | string | string[], def = true): boolean { + // Visible by default + if (!value) { + return def; + } + + const permMode = projectSetting.permissionMode; + + if ([PermissionModeEnum.ROUTE_MAPPING, PermissionModeEnum.ROLE].includes(permMode)) { + if (!isArray(value)) { + return userStore.getRoleList?.includes(value as RoleEnum); + } + return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0; + } + + if (PermissionModeEnum.BACK === permMode) { + const allCodeList = permissionStore.getPermCodeList as string[]; + if (!isArray(value)) { + const splits = ['||', '&&']; + const splitName = splits.find((item) => value.includes(item)); + if (splitName) { + const splitCodes = value.split(splitName); + return splitName === splits[0] + ? intersection(splitCodes, allCodeList).length > 0 + : intersection(splitCodes, allCodeList).length === splitCodes.length; + } + return allCodeList.includes(value); + } + return (intersection(value, allCodeList) as string[]).length > 0; + } + return true; + } + + /** + * Change roles + * @param roles + */ + async function changeRole(roles: RoleEnum | RoleEnum[]): Promise { + if (projectSetting.permissionMode !== PermissionModeEnum.ROUTE_MAPPING) { + throw new Error( + 'Please switch PermissionModeEnum to ROUTE_MAPPING mode in the configuration to operate!', + ); + } + + if (!isArray(roles)) { + roles = [roles]; + } + userStore.setRoleList(roles); + await resume(); + } + + /** + * refresh menu data + */ + async function refreshMenu() { + resume(); + } + + return { changeRole, hasPermission, togglePermissionMode, refreshMenu }; +} diff --git a/src/hooks/web/useScript.ts b/src/hooks/web/useScript.ts new file mode 100644 index 0000000..9707116 --- /dev/null +++ b/src/hooks/web/useScript.ts @@ -0,0 +1,46 @@ +import { onMounted, onUnmounted, ref } from 'vue'; + +interface ScriptOptions { + src: string; +} + +export function useScript(opts: ScriptOptions) { + const isLoading = ref(false); + const error = ref(false); + const success = ref(false); + let script: HTMLScriptElement; + + const promise = new Promise((resolve, reject) => { + onMounted(() => { + script = document.createElement('script'); + script.type = 'text/javascript'; + script.onload = function () { + isLoading.value = false; + success.value = true; + error.value = false; + resolve(''); + }; + + script.onerror = function (err) { + isLoading.value = false; + success.value = false; + error.value = true; + reject(err); + }; + + script.src = opts.src; + document.head.appendChild(script); + }); + }); + + onUnmounted(() => { + script && script.remove(); + }); + + return { + isLoading, + error, + success, + toPromise: () => promise, + }; +} diff --git a/src/hooks/web/useSortable.ts b/src/hooks/web/useSortable.ts new file mode 100644 index 0000000..4c66b6a --- /dev/null +++ b/src/hooks/web/useSortable.ts @@ -0,0 +1,21 @@ +import { nextTick, unref } from 'vue'; +import type { Ref } from 'vue'; +import type { Options } from 'sortablejs'; + +export function useSortable(el: HTMLElement | Ref, options?: Options) { + function initSortable() { + nextTick(async () => { + if (!el) return; + + const Sortable = (await import('sortablejs')).default; + Sortable.create(unref(el), { + animation: 500, + delay: 400, + delayOnTouchOnly: true, + ...options, + }); + }); + } + + return { initSortable }; +} diff --git a/src/hooks/web/useTabs.ts b/src/hooks/web/useTabs.ts new file mode 100644 index 0000000..51f3fce --- /dev/null +++ b/src/hooks/web/useTabs.ts @@ -0,0 +1,103 @@ +import type { RouteLocationNormalized, Router } from 'vue-router'; + +import { useRouter } from 'vue-router'; +import { unref } from 'vue'; + +import { useMultipleTabStore } from '/@/store/modules/multipleTab'; +import { useAppStore } from '/@/store/modules/app'; + +enum TableActionEnum { + REFRESH, + CLOSE_ALL, + CLOSE_LEFT, + CLOSE_RIGHT, + CLOSE_OTHER, + CLOSE_CURRENT, + CLOSE, +} + +export function useTabs(_router?: Router) { + const appStore = useAppStore(); + + function canIUseTabs(): boolean { + const { show } = appStore.getMultiTabsSetting; + if (!show) { + throw new Error('The multi-tab page is currently not open, please open it in the settings!'); + } + return show; + } + + const tabStore = useMultipleTabStore(); + const router = _router || useRouter(); + + const { currentRoute } = router; + + function getCurrentTab() { + const route = unref(currentRoute); + return tabStore.getTabList.find((item) => item.fullPath === route.fullPath)!; + } + + async function updateTabTitle(title: string, tab?: RouteLocationNormalized) { + const canIUse = canIUseTabs; + if (!canIUse) { + return; + } + const targetTab = tab || getCurrentTab(); + await tabStore.setTabTitle(title, targetTab); + } + + async function updateTabPath(path: string, tab?: RouteLocationNormalized) { + const canIUse = canIUseTabs; + if (!canIUse) { + return; + } + const targetTab = tab || getCurrentTab(); + await tabStore.updateTabPath(path, targetTab); + } + + async function handleTabAction(action: TableActionEnum, tab?: RouteLocationNormalized) { + const canIUse = canIUseTabs; + if (!canIUse) { + return; + } + const currentTab = getCurrentTab(); + switch (action) { + case TableActionEnum.REFRESH: + await tabStore.refreshPage(router); + break; + + case TableActionEnum.CLOSE_ALL: + await tabStore.closeAllTab(router); + break; + + case TableActionEnum.CLOSE_LEFT: + await tabStore.closeLeftTabs(currentTab, router); + break; + + case TableActionEnum.CLOSE_RIGHT: + await tabStore.closeRightTabs(currentTab, router); + break; + + case TableActionEnum.CLOSE_OTHER: + await tabStore.closeOtherTabs(currentTab, router); + break; + + case TableActionEnum.CLOSE_CURRENT: + case TableActionEnum.CLOSE: + await tabStore.closeTab(tab || currentTab, router); + break; + } + } + + return { + refreshPage: () => handleTabAction(TableActionEnum.REFRESH), + closeAll: () => handleTabAction(TableActionEnum.CLOSE_ALL), + closeLeft: () => handleTabAction(TableActionEnum.CLOSE_LEFT), + closeRight: () => handleTabAction(TableActionEnum.CLOSE_RIGHT), + closeOther: () => handleTabAction(TableActionEnum.CLOSE_OTHER), + closeCurrent: () => handleTabAction(TableActionEnum.CLOSE_CURRENT), + close: (tab?: RouteLocationNormalized) => handleTabAction(TableActionEnum.CLOSE, tab), + setTitle: (title: string, tab?: RouteLocationNormalized) => updateTabTitle(title, tab), + updatePath: (fullPath: string, tab?: RouteLocationNormalized) => updateTabPath(fullPath, tab), + }; +} diff --git a/src/hooks/web/useTitle.ts b/src/hooks/web/useTitle.ts new file mode 100644 index 0000000..675a5db --- /dev/null +++ b/src/hooks/web/useTitle.ts @@ -0,0 +1,34 @@ +import { watch, unref } from 'vue'; +import { useI18n } from '/@/hooks/web/useI18n'; +import { useTitle as usePageTitle } from '@vueuse/core'; +import { useGlobSetting } from '/@/hooks/setting'; +import { useRouter } from 'vue-router'; +import { useLocaleStore } from '/@/store/modules/locale'; +import { REDIRECT_NAME } from '/@/router/constant'; + +/** + * Listening to page changes and dynamically changing site titles + */ +export function useTitle() { + const { title } = useGlobSetting(); + const { t } = useI18n(); + const { currentRoute } = useRouter(); + const localeStore = useLocaleStore(); + + const pageTitle = usePageTitle(); + + watch( + [() => currentRoute.value.path, () => localeStore.getLocale], + () => { + const route = unref(currentRoute); + + if (route.name === REDIRECT_NAME) { + return; + } + + const tTitle = t(route?.meta?.title as string); + pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}`; + }, + { immediate: true }, + ); +} diff --git a/src/hooks/web/useWatermark.ts b/src/hooks/web/useWatermark.ts new file mode 100644 index 0000000..5840c14 --- /dev/null +++ b/src/hooks/web/useWatermark.ts @@ -0,0 +1,106 @@ +import { getCurrentInstance, onBeforeUnmount, ref, Ref, shallowRef, unref } from 'vue'; +import { useRafThrottle } from '/@/utils/domUtils'; +import { addResizeListener, removeResizeListener } from '/@/utils/event'; +import { isDef } from '/@/utils/is'; + +const domSymbol = Symbol('watermark-dom'); +const sourceMap = new WeakMap(); + +export function useWatermark( + appendEl: Ref = ref(document.body) as Ref, +) { + const appendElRaw = unref(appendEl); + if (appendElRaw && sourceMap.has(appendElRaw)) { + return sourceMap.get(appendElRaw); + } + const func = useRafThrottle(function () { + const el = unref(appendEl); + if (!el) return; + const { clientHeight: height, clientWidth: width } = el; + updateWatermark({ height, width }); + }); + const id = domSymbol.toString(); + const watermarkEl = shallowRef(); + + const clear = () => { + const domId = unref(watermarkEl); + watermarkEl.value = undefined; + const el = unref(appendEl); + if (!el) return; + domId && el.removeChild(domId); + removeResizeListener(el, func); + }; + + function createBase64(str: string) { + const can = document.createElement('canvas'); + const width = 300; + const height = 240; + Object.assign(can, { width, height }); + + const cans = can.getContext('2d'); + if (cans) { + cans.rotate((-20 * Math.PI) / 120); + cans.font = '15px Vedana'; + cans.fillStyle = 'rgba(0, 0, 0, 0.15)'; + cans.textAlign = 'left'; + cans.textBaseline = 'middle'; + cans.fillText(str, width / 20, height); + } + return can.toDataURL('image/png'); + } + + function updateWatermark( + options: { + width?: number; + height?: number; + str?: string; + } = {}, + ) { + const el = unref(watermarkEl); + if (!el) return; + if (isDef(options.width)) { + el.style.width = `${options.width}px`; + } + if (isDef(options.height)) { + el.style.height = `${options.height}px`; + } + if (isDef(options.str)) { + el.style.background = `url(${createBase64(options.str)}) left top repeat`; + } + } + + const createWatermark = (str: string) => { + if (unref(watermarkEl)) { + updateWatermark({ str }); + return id; + } + const div = document.createElement('div'); + watermarkEl.value = div; + div.id = id; + div.style.pointerEvents = 'none'; + div.style.top = '0px'; + div.style.left = '0px'; + div.style.position = 'absolute'; + div.style.zIndex = '100000'; + const el = unref(appendEl); + if (!el) return id; + const { clientHeight: height, clientWidth: width } = el; + updateWatermark({ str, width, height }); + el.appendChild(div); + sourceMap.set(el, { setWatermark, clear }); + return id; + }; + + function setWatermark(str: string) { + createWatermark(str); + addResizeListener(document.documentElement, func); + const instance = getCurrentInstance(); + if (instance) { + onBeforeUnmount(() => { + clear(); + }); + } + } + + return { setWatermark, clear }; +} diff --git a/src/layouts/.DS_Store b/src/layouts/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..075bcbed2521c769d6612cb8d98ca43bdd1a4331 GIT binary patch literal 6148 zcmeHKu};H44E3cE6w1(%@dg$q)D1BmC451D07^TpFfQ({KW>M-@^5(6FML`w+vF45&=I|& znm5!_(nd~`+UfM>&^}U2XOFTPtfb@9se?S%ky4Eswud#$F86IC`PD}6UO1^77^a0AkevM!of=RrJ;mcR?IW!8^Jx_o^u@S@y P#C`-K4K^49zskTD5|>(? literal 0 HcmV?d00001 diff --git a/src/layouts/default/content/index.vue b/src/layouts/default/content/index.vue new file mode 100644 index 0000000..00cad20 --- /dev/null +++ b/src/layouts/default/content/index.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/layouts/default/content/useContentContext.ts b/src/layouts/default/content/useContentContext.ts new file mode 100644 index 0000000..f12e77b --- /dev/null +++ b/src/layouts/default/content/useContentContext.ts @@ -0,0 +1,17 @@ +import type { InjectionKey, ComputedRef } from 'vue'; +import { createContext, useContext } from '/@/hooks/core/useContext'; + +export interface ContentContextProps { + contentHeight: ComputedRef; + setPageHeight: (height: number) => Promise; +} + +const key: InjectionKey = Symbol(); + +export function createContentContext(context: ContentContextProps) { + return createContext(context, key, { native: true }); +} + +export function useContentContext() { + return useContext(key); +} diff --git a/src/layouts/default/content/useContentViewHeight.ts b/src/layouts/default/content/useContentViewHeight.ts new file mode 100644 index 0000000..8dd63fa --- /dev/null +++ b/src/layouts/default/content/useContentViewHeight.ts @@ -0,0 +1,41 @@ +import { ref, computed, unref } from 'vue'; +import { createPageContext } from '/@/hooks/component/usePageContext'; +import { useWindowSizeFn } from '@vben/hooks'; + +const headerHeightRef = ref(0); +const footerHeightRef = ref(0); + +export function useLayoutHeight() { + function setHeaderHeight(val) { + headerHeightRef.value = val; + } + function setFooterHeight(val) { + footerHeightRef.value = val; + } + return { headerHeightRef, footerHeightRef, setHeaderHeight, setFooterHeight }; +} + +export function useContentViewHeight() { + const contentHeight = ref(window.innerHeight); + const pageHeight = ref(window.innerHeight); + const getViewHeight = computed(() => { + return unref(contentHeight) - unref(headerHeightRef) - unref(footerHeightRef) || 0; + }); + + useWindowSizeFn( + () => { + contentHeight.value = window.innerHeight; + }, + { wait: 100, immediate: true }, + ); + + async function setPageHeight(height: number) { + pageHeight.value = height; + } + + createPageContext({ + contentHeight: getViewHeight, + setPageHeight, + pageHeight, + }); +} diff --git a/src/layouts/default/feature/index.vue b/src/layouts/default/feature/index.vue new file mode 100644 index 0000000..3595848 --- /dev/null +++ b/src/layouts/default/feature/index.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/src/layouts/default/footer/index.vue b/src/layouts/default/footer/index.vue new file mode 100644 index 0000000..5abc0d1 --- /dev/null +++ b/src/layouts/default/footer/index.vue @@ -0,0 +1,95 @@ + + + + diff --git a/src/layouts/default/header/MultipleHeader.vue b/src/layouts/default/header/MultipleHeader.vue new file mode 100644 index 0000000..7244221 --- /dev/null +++ b/src/layouts/default/header/MultipleHeader.vue @@ -0,0 +1,126 @@ + + + diff --git a/src/layouts/default/header/components/Breadcrumb.vue b/src/layouts/default/header/components/Breadcrumb.vue new file mode 100644 index 0000000..1869d18 --- /dev/null +++ b/src/layouts/default/header/components/Breadcrumb.vue @@ -0,0 +1,204 @@ + + + diff --git a/src/layouts/default/header/components/ErrorAction.vue b/src/layouts/default/header/components/ErrorAction.vue new file mode 100644 index 0000000..086f2ff --- /dev/null +++ b/src/layouts/default/header/components/ErrorAction.vue @@ -0,0 +1,47 @@ + + diff --git a/src/layouts/default/header/components/FullScreen.vue b/src/layouts/default/header/components/FullScreen.vue new file mode 100644 index 0000000..2e124b5 --- /dev/null +++ b/src/layouts/default/header/components/FullScreen.vue @@ -0,0 +1,45 @@ + + diff --git a/src/layouts/default/header/components/index.ts b/src/layouts/default/header/components/index.ts new file mode 100644 index 0000000..09e767e --- /dev/null +++ b/src/layouts/default/header/components/index.ts @@ -0,0 +1,14 @@ +import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; +import FullScreen from './FullScreen.vue'; + +export const UserDropDown = createAsyncComponent(() => import('./user-dropdown/index.vue'), { + loading: true, +}); + +export const LayoutBreadcrumb = createAsyncComponent(() => import('./Breadcrumb.vue')); + +export const Notify = createAsyncComponent(() => import('./notify/index.vue')); + +export const ErrorAction = createAsyncComponent(() => import('./ErrorAction.vue')); + +export { FullScreen }; diff --git a/src/layouts/default/header/components/lock/LockModal.vue b/src/layouts/default/header/components/lock/LockModal.vue new file mode 100644 index 0000000..daca092 --- /dev/null +++ b/src/layouts/default/header/components/lock/LockModal.vue @@ -0,0 +1,127 @@ + + + diff --git a/src/layouts/default/header/components/notify/NoticeList.vue b/src/layouts/default/header/components/notify/NoticeList.vue new file mode 100644 index 0000000..a049a81 --- /dev/null +++ b/src/layouts/default/header/components/notify/NoticeList.vue @@ -0,0 +1,177 @@ + + + \ No newline at end of file diff --git a/src/layouts/default/header/components/notify/data.ts b/src/layouts/default/header/components/notify/data.ts new file mode 100644 index 0000000..6a474b5 --- /dev/null +++ b/src/layouts/default/header/components/notify/data.ts @@ -0,0 +1,173 @@ +export interface ListItem { + id: string; + avatar: string; + // 通知的标题内容 + title: string; + // 是否在标题上显示删除线 + titleDelete?: boolean; + datetime: string; + type: string; + read?: boolean; + description: string; + clickClose?: boolean; + extra?: string; + color?: string; +} + +export interface TabItem { + key: string; + name: string; + list: ListItem[]; + unreadlist?: ListItem[]; +} + +export const tabListData: TabItem[] = [ + { + key: '1', + name: '通知', + list: [ + { + id: '000000001', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', + title: '物品XXXXX的采购订单已完成', + description: '采购订单单据:79165111336', + datetime: '2024-07-04', + type: '系统通知', + }, + { + id: '000000002', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png', + title: '你添加的商品已经通过审核', + description: '', + datetime: '2024-07-01', + type: '1', + }, + { + id: '000000003', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png', + title: '这种模板可以区分多种通知类型', + description: '', + datetime: '2017-08-07', + // read: true, + type: '1', + }, + { + id: '000000004', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000005', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: + '标题可以设置自动显示省略号,本例中标题行数已设为1行,如果内容超过1行将自动截断并支持tooltip显示完整标题。', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000006', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000007', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000008', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000009', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000010', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000010', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + ], + }, + { + key: '2', + name: '消息', + list: [ + ], + }, + { + key: '3', + name: '待办', + list: [ + { + id: '000000009', + avatar: '', + title: '采购订单', + description: '任务需要部门经理xxxx审核', + datetime: '', + extra: '未审核', + color: '', + type: '3', + }, + { + id: '000000010', + avatar: '', + title: '销售出库', + description: '您需要对单据XXXXX进行审核处理并核对出库信息', + datetime: '', + extra: '马上到期', + color: 'red', + type: '3', + }, + // { + // id: '000000011', + // avatar: '', + // title: '零售订单', + // description: '指派竹尔于 2017-01-09 前完成更新并发布', + // datetime: '', + // extra: '已耗时 8 天', + // color: 'gold', + // type: '3', + // }, + { + id: '000000012', + avatar: '', + title: '采购入库', + description: 'XXXXXXX指派竹尔于 2024-07-09 前完成XXX商品入库', + datetime: '', + extra: '进行中', + color: 'blue', + type: '3', + }, + ], + }, +]; diff --git a/src/layouts/default/header/components/notify/index.vue b/src/layouts/default/header/components/notify/index.vue new file mode 100644 index 0000000..71e8c08 --- /dev/null +++ b/src/layouts/default/header/components/notify/index.vue @@ -0,0 +1,102 @@ + + + \ No newline at end of file diff --git a/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue b/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue new file mode 100644 index 0000000..6f2b903 --- /dev/null +++ b/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue @@ -0,0 +1,32 @@ + + diff --git a/src/layouts/default/header/components/user-dropdown/index.vue b/src/layouts/default/header/components/user-dropdown/index.vue new file mode 100644 index 0000000..11f9318 --- /dev/null +++ b/src/layouts/default/header/components/user-dropdown/index.vue @@ -0,0 +1,191 @@ + + + diff --git a/src/layouts/default/header/index.less b/src/layouts/default/header/index.less new file mode 100644 index 0000000..bfa2e90 --- /dev/null +++ b/src/layouts/default/header/index.less @@ -0,0 +1,196 @@ +@header-trigger-prefix-cls: ~'@{namespace}-layout-header-trigger'; +@header-prefix-cls: ~'@{namespace}-layout-header'; +@breadcrumb-prefix-cls: ~'@{namespace}-layout-breadcrumb'; +@logo-prefix-cls: ~'@{namespace}-app-logo'; + +.ant-layout .@{header-prefix-cls} { + display: flex; + align-items: center; + justify-content: space-between; + height: @header-height; + margin-left: -1px; + padding: 0; + background-color: @white; + color: @white; + line-height: @header-height; + + &--mobile { + .@{breadcrumb-prefix-cls}, + .error-action, + .notify-item, + .fullscreen-item { + display: none; + } + + .@{logo-prefix-cls} { + min-width: unset; + padding-right: 0; + + &__title { + display: none; + } + } + .@{header-trigger-prefix-cls} { + padding: 0 4px 0 8px !important; + } + .@{header-prefix-cls}-action { + padding-right: 4px; + } + } + + &--fixed { + position: fixed; + z-index: @layout-header-fixed-z-index; + top: 0; + left: 0; + width: 100%; + } + + &-logo { + min-width: 192px; + height: @header-height; + padding: 0 10px; + font-size: 14px; + + img { + width: @logo-width; + height: @logo-width; + margin-right: 2px; + } + } + + &-left { + display: flex; + align-items: center; + height: 100%; + + .@{header-trigger-prefix-cls} { + display: flex; + align-items: center; + height: 100%; + padding: 1px 10px 0; + cursor: pointer; + + .anticon { + font-size: 16px; + } + + &.light { + &:hover { + background-color: @header-light-bg-hover-color; + } + + svg { + fill: #000; + } + } + + &.dark { + &:hover { + background-color: @header-dark-bg-hover-color; + } + } + } + } + + &-menu { + flex: 1; + align-items: center; + min-width: 0; + height: 100%; + } + + &-action { + display: flex; + // padding-right: 12px; + align-items: center; + min-width: 180px; + + &__item { + display: flex !important; + align-items: center; + height: @header-height; + padding: 0 2px; + font-size: 1.2em; + cursor: pointer; + + .ant-badge { + height: @header-height; + line-height: @header-height; + } + + .ant-badge-dot { + top: 14px; + right: 2px; + } + } + + span[role='img'] { + padding: 0 8px; + } + } + + &--light { + border-bottom: 1px solid @header-light-bottom-border-color; + border-left: 1px solid @header-light-bottom-border-color; + background-color: @white !important; + + .@{header-prefix-cls}-logo { + color: @text-color-base; + + &:hover { + background-color: @header-light-bg-hover-color; + } + } + + .@{header-prefix-cls}-action { + &__item { + color: @text-color-base; + + .app-iconify { + padding: 0 10px; + font-size: 16px !important; + } + + &:hover { + background-color: @header-light-bg-hover-color; + } + } + + &-icon, + span[role='img'] { + color: @text-color-base; + } + } + } + + &--dark { + border-bottom: 1px solid #303030; + border-left: 1px solid @border-color-base; + background-color: @header-dark-bg-color !important; + .@{header-prefix-cls}-logo { + &:hover { + background-color: @header-dark-bg-hover-color; + } + } + + .@{header-prefix-cls}-action { + &__item { + .app-iconify { + padding: 0 10px; + font-size: 16px !important; + } + + .ant-badge { + span { + color: @white; + } + } + + &:hover { + background-color: @header-dark-bg-hover-color; + } + } + } + } +} \ No newline at end of file diff --git a/src/layouts/default/header/index.vue b/src/layouts/default/header/index.vue new file mode 100644 index 0000000..2ffd43c --- /dev/null +++ b/src/layouts/default/header/index.vue @@ -0,0 +1,153 @@ + + + diff --git a/src/layouts/default/index.vue b/src/layouts/default/index.vue new file mode 100644 index 0000000..de7fcae --- /dev/null +++ b/src/layouts/default/index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/src/layouts/default/menu/index.vue b/src/layouts/default/menu/index.vue new file mode 100644 index 0000000..35f8fcf --- /dev/null +++ b/src/layouts/default/menu/index.vue @@ -0,0 +1,197 @@ + + diff --git a/src/layouts/default/menu/useLayoutMenu.ts b/src/layouts/default/menu/useLayoutMenu.ts new file mode 100644 index 0000000..33c7768 --- /dev/null +++ b/src/layouts/default/menu/useLayoutMenu.ts @@ -0,0 +1,109 @@ +import type { Menu } from '/@/router/types'; +import type { Ref } from 'vue'; +import { watch, unref, ref, computed } from 'vue'; +import { useRouter } from 'vue-router'; +import { MenuSplitTyeEnum } from '/@/enums/menuEnum'; +import { useThrottleFn } from '@vueuse/core'; +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; +import { getChildrenMenus, getCurrentParentPath, getMenus, getShallowMenus } from '/@/router/menus'; +import { usePermissionStore } from '/@/store/modules/permission'; +import { useAppInject } from '/@/hooks/web/useAppInject'; + +export function useSplitMenu(splitType: Ref) { + // Menu array + const menusRef = ref([]); + const { currentRoute } = useRouter(); + const { getIsMobile } = useAppInject(); + const permissionStore = usePermissionStore(); + const { setMenuSetting, getIsHorizontal, getSplit } = useMenuSetting(); + + const throttleHandleSplitLeftMenu = useThrottleFn(handleSplitLeftMenu, 50); + + const splitNotLeft = computed( + () => unref(splitType) !== MenuSplitTyeEnum.LEFT && !unref(getIsHorizontal), + ); + + const getSplitLeft = computed( + () => !unref(getSplit) || unref(splitType) !== MenuSplitTyeEnum.LEFT, + ); + + const getSpiltTop = computed(() => unref(splitType) === MenuSplitTyeEnum.TOP); + + const normalType = computed(() => { + return unref(splitType) === MenuSplitTyeEnum.NONE || !unref(getSplit); + }); + + watch( + [() => unref(currentRoute).path, () => unref(splitType)], + async ([path]: [string, MenuSplitTyeEnum]) => { + if (unref(splitNotLeft) || unref(getIsMobile)) return; + + const { meta } = unref(currentRoute); + const currentActiveMenu = meta.currentActiveMenu as string; + let parentPath = await getCurrentParentPath(path); + if (!parentPath) { + parentPath = await getCurrentParentPath(currentActiveMenu); + } + parentPath && throttleHandleSplitLeftMenu(parentPath); + }, + { + immediate: true, + }, + ); + + // Menu changes + watch( + [() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList], + () => { + genMenus(); + }, + { + immediate: true, + }, + ); + + // split Menu changes + watch( + () => getSplit.value, + () => { + if (unref(splitNotLeft)) return; + genMenus(); + }, + ); + + // Handle left menu split + async function handleSplitLeftMenu(parentPath: string) { + if (unref(getSplitLeft) || unref(getIsMobile)) return; + + // spilt mode left + const children = await getChildrenMenus(parentPath); + + if (!children || !children.length) { + setMenuSetting({ hidden: true }); + menusRef.value = []; + return; + } + + setMenuSetting({ hidden: false }); + menusRef.value = children; + } + + // get menus + async function genMenus() { + // normal mode + if (unref(normalType) || unref(getIsMobile)) { + menusRef.value = await getMenus(); + return; + } + + // split-top + if (unref(getSpiltTop)) { + const shallowMenus = await getShallowMenus(); + + menusRef.value = shallowMenus; + return; + } + } + + return { menusRef }; +} diff --git a/src/layouts/default/setting/SettingDrawer.tsx b/src/layouts/default/setting/SettingDrawer.tsx new file mode 100644 index 0000000..79b2284 --- /dev/null +++ b/src/layouts/default/setting/SettingDrawer.tsx @@ -0,0 +1,427 @@ +import { defineComponent, computed, unref } from 'vue'; +import { BasicDrawer } from '/@/components/Drawer/index'; +import { Divider } from 'ant-design-vue'; +import { + TypePicker, + ThemeColorPicker, + SettingFooter, + SwitchItem, + SelectItem, + InputNumberItem, +} from './components'; + +import { AppDarkModeToggle } from '/@/components/Application'; + +import { MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum'; + +import { useRootSetting } from '/@/hooks/setting/useRootSetting'; +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; +import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; +import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; +import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'; +import { useI18n } from '/@/hooks/web/useI18n'; + +import { baseHandler } from './handler'; + +import { + HandlerEnum, + contentModeOptions, + topMenuAlignOptions, + getMenuTriggerOptions, + routerTransitionOptions, + menuTypeList, + mixSidebarTriggerOptions, +} from './enum'; + +import { +// HEADER_PRESET_BG_COLOR_LIST, +// SIDE_BAR_BG_COLOR_LIST, + APP_PRESET_COLOR_LIST, + } from '/@/settings/designSetting'; + +const { t } = useI18n(); + +export default defineComponent({ + name: 'SettingDrawer', + setup(_, { attrs }) { + const { + getContentMode, + getShowFooter, + getShowBreadCrumb, + getShowBreadCrumbIcon, + getShowLogo, + getFullContent, + getColorWeak, + getGrayMode, + getLockTime, + getShowDarkModeToggle, + getThemeColor, + } = useRootSetting(); + + const { getOpenPageLoading, getBasicTransition, getEnableTransition, getOpenNProgress } = + useTransitionSetting(); + + const { + getIsHorizontal, + getShowMenu, + getMenuType, + getTrigger, + getCollapsedShowTitle, + getMenuFixed, + getCollapsed, + getCanDrag, + getTopMenuAlign, + getAccordion, + getMenuWidth, + // getMenuBgColor, + getIsTopMenu, + getSplit, + getIsMixSidebar, + getCloseMixSidebarOnChange, + getMixSideTrigger, + getMixSideFixed, + } = useMenuSetting(); + + const { + getShowHeader, + getFixed: getHeaderFixed, + // getHeaderBgColor, + getShowSearch, + } = useHeaderSetting(); + + const { getShowMultipleTab, getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting(); + + const getShowMenuRef = computed(() => { + return unref(getShowMenu) && !unref(getIsHorizontal); + }); + + function renderSidebar() { + return ( + <> + { + baseHandler(HandlerEnum.CHANGE_LAYOUT, { + mode: item.mode, + type: item.type, + split: unref(getIsHorizontal) ? false : undefined, + }); + }} + def={unref(getMenuType)} + /> + + ); + } + + // function renderHeaderTheme() { + // return ( + // + // ); + // } + + // function renderSiderTheme() { + // return ( + // + // ); + // } + + function renderMainTheme() { + return ( + + ); + } + + /** + * @description: + */ + function renderFeatures() { + let triggerDef = unref(getTrigger); + + const triggerOptions = getMenuTriggerOptions(unref(getSplit)); + const some = triggerOptions.some((item) => item.value === triggerDef); + if (!some) { + triggerDef = TriggerEnum.FOOTER; + } + + return ( + <> + + + + + + + + + + + + + + + + + + + { + return parseInt(value) === 0 + ? `0(${t('layout.setting.notAutoScreenLock')})` + : `${value}${t('layout.setting.minute')}`; + }} + /> + `${parseInt(value)}px`} + /> + + ); + } + + function renderContent() { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + ); + } + + function renderTransition() { + return ( + <> + + + + + + + + ); + } + + return () => ( + + {unref(getShowDarkModeToggle) && {() => t('layout.setting.darkMode')}} + {unref(getShowDarkModeToggle) && } + {() => t('layout.setting.navMode')} + {renderSidebar()} + {/*{ {() => t('layout.setting.sysTheme')} }*/} + {/*{renderMainTheme()}*/} + {/*{() => t('layout.setting.headerTheme')}*/} + {/*{renderHeaderTheme()}*/} + {/*{() => t('layout.setting.sidebarTheme')}*/} + {/*{renderSiderTheme()}*/} + {/*{() => t('layout.setting.interfaceFunction')}*/} + {/*{renderFeatures()}*/} + {/*{() => t('layout.setting.interfaceDisplay')}*/} + {/*{renderContent()}*/} + {/*{() => t('layout.setting.animation')}*/} + {/*{renderTransition()}*/} + {/**/} + {/**/} + + ); + }, +}); diff --git a/src/layouts/default/setting/components/InputNumberItem.vue b/src/layouts/default/setting/components/InputNumberItem.vue new file mode 100644 index 0000000..9f350ef --- /dev/null +++ b/src/layouts/default/setting/components/InputNumberItem.vue @@ -0,0 +1,56 @@ + + + diff --git a/src/layouts/default/setting/components/SelectItem.vue b/src/layouts/default/setting/components/SelectItem.vue new file mode 100644 index 0000000..676ca91 --- /dev/null +++ b/src/layouts/default/setting/components/SelectItem.vue @@ -0,0 +1,75 @@ + + + diff --git a/src/layouts/default/setting/components/SettingFooter.vue b/src/layouts/default/setting/components/SettingFooter.vue new file mode 100644 index 0000000..d243795 --- /dev/null +++ b/src/layouts/default/setting/components/SettingFooter.vue @@ -0,0 +1,100 @@ + + + diff --git a/src/layouts/default/setting/components/SwitchItem.vue b/src/layouts/default/setting/components/SwitchItem.vue new file mode 100644 index 0000000..ff27477 --- /dev/null +++ b/src/layouts/default/setting/components/SwitchItem.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/layouts/default/setting/components/ThemeColorPicker.vue b/src/layouts/default/setting/components/ThemeColorPicker.vue new file mode 100644 index 0000000..95c73a0 --- /dev/null +++ b/src/layouts/default/setting/components/ThemeColorPicker.vue @@ -0,0 +1,88 @@ + + + diff --git a/src/layouts/default/setting/components/TypePicker.vue b/src/layouts/default/setting/components/TypePicker.vue new file mode 100644 index 0000000..d13f7d7 --- /dev/null +++ b/src/layouts/default/setting/components/TypePicker.vue @@ -0,0 +1,179 @@ + + + diff --git a/src/layouts/default/setting/components/index.ts b/src/layouts/default/setting/components/index.ts new file mode 100644 index 0000000..bd24888 --- /dev/null +++ b/src/layouts/default/setting/components/index.ts @@ -0,0 +1,8 @@ +import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; + +export const TypePicker = createAsyncComponent(() => import('./TypePicker.vue')); +export const ThemeColorPicker = createAsyncComponent(() => import('./ThemeColorPicker.vue')); +export const SettingFooter = createAsyncComponent(() => import('./SettingFooter.vue')); +export const SwitchItem = createAsyncComponent(() => import('./SwitchItem.vue')); +export const SelectItem = createAsyncComponent(() => import('./SelectItem.vue')); +export const InputNumberItem = createAsyncComponent(() => import('./InputNumberItem.vue')); diff --git a/src/layouts/default/setting/enum.ts b/src/layouts/default/setting/enum.ts new file mode 100644 index 0000000..1e9633a --- /dev/null +++ b/src/layouts/default/setting/enum.ts @@ -0,0 +1,156 @@ +import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum'; +import { + MenuModeEnum, + MenuTypeEnum, + TopMenuAlignEnum, + TriggerEnum, + MixSidebarTriggerEnum, +} from '/@/enums/menuEnum'; + +import { useI18n } from '/@/hooks/web/useI18n'; + +const { t } = useI18n(); + +export enum HandlerEnum { + CHANGE_LAYOUT, + CHANGE_THEME_COLOR, + CHANGE_THEME, + // menu + MENU_HAS_DRAG, + MENU_ACCORDION, + MENU_TRIGGER, + MENU_TOP_ALIGN, + MENU_COLLAPSED, + MENU_COLLAPSED_SHOW_TITLE, + MENU_WIDTH, + MENU_SHOW_SIDEBAR, + MENU_THEME, + MENU_SPLIT, + MENU_FIXED, + MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE, + MENU_TRIGGER_MIX_SIDEBAR, + MENU_FIXED_MIX_SIDEBAR, + + // header + HEADER_SHOW, + HEADER_THEME, + HEADER_FIXED, + + HEADER_SEARCH, + + TABS_SHOW_QUICK, + TABS_SHOW_REDO, + TABS_SHOW, + TABS_SHOW_FOLD, + + LOCK_TIME, + FULL_CONTENT, + CONTENT_MODE, + SHOW_BREADCRUMB, + SHOW_BREADCRUMB_ICON, + GRAY_MODE, + COLOR_WEAK, + SHOW_LOGO, + SHOW_FOOTER, + + ROUTER_TRANSITION, + OPEN_PROGRESS, + OPEN_PAGE_LOADING, + OPEN_ROUTE_TRANSITION, +} + +export const contentModeOptions = [ + { + value: ContentEnum.FULL, + label: t('layout.setting.contentModeFull'), + }, + { + value: ContentEnum.FIXED, + label: t('layout.setting.contentModeFixed'), + }, +]; + +export const topMenuAlignOptions = [ + { + value: TopMenuAlignEnum.CENTER, + label: t('layout.setting.topMenuAlignRight'), + }, + { + value: TopMenuAlignEnum.START, + label: t('layout.setting.topMenuAlignLeft'), + }, + { + value: TopMenuAlignEnum.END, + label: t('layout.setting.topMenuAlignCenter'), + }, +]; + +export const getMenuTriggerOptions = (hideTop: boolean) => { + return [ + { + value: TriggerEnum.NONE, + label: t('layout.setting.menuTriggerNone'), + }, + { + value: TriggerEnum.FOOTER, + label: t('layout.setting.menuTriggerBottom'), + }, + ...(hideTop + ? [] + : [ + { + value: TriggerEnum.HEADER, + label: t('layout.setting.menuTriggerTop'), + }, + ]), + ]; +}; + +export const routerTransitionOptions = [ + RouterTransitionEnum.ZOOM_FADE, + RouterTransitionEnum.FADE, + RouterTransitionEnum.ZOOM_OUT, + RouterTransitionEnum.FADE_SIDE, + RouterTransitionEnum.FADE_BOTTOM, + RouterTransitionEnum.FADE_SCALE, +].map((item) => { + return { + label: item, + value: item, + }; +}); + +export const menuTypeList = [ + { + title: t('layout.setting.menuTypeSidebar'), + mode: MenuModeEnum.INLINE, + type: MenuTypeEnum.SIDEBAR, + }, + { + title: t('layout.setting.menuTypeMix'), + mode: MenuModeEnum.INLINE, + type: MenuTypeEnum.MIX, + }, + + { + title: t('layout.setting.menuTypeTopMenu'), + mode: MenuModeEnum.HORIZONTAL, + type: MenuTypeEnum.TOP_MENU, + }, + { + title: t('layout.setting.menuTypeMixSidebar'), + mode: MenuModeEnum.INLINE, + type: MenuTypeEnum.MIX_SIDEBAR, + }, +]; + +export const mixSidebarTriggerOptions = [ + { + value: MixSidebarTriggerEnum.HOVER, + label: t('layout.setting.triggerHover'), + }, + { + value: MixSidebarTriggerEnum.CLICK, + label: t('layout.setting.triggerClick'), + }, +]; diff --git a/src/layouts/default/setting/handler.ts b/src/layouts/default/setting/handler.ts new file mode 100644 index 0000000..e541081 --- /dev/null +++ b/src/layouts/default/setting/handler.ts @@ -0,0 +1,172 @@ +import { HandlerEnum } from './enum'; +import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground'; +import { updateColorWeak } from '/@/logics/theme/updateColorWeak'; +import { updateGrayMode } from '/@/logics/theme/updateGrayMode'; + +import { useAppStore } from '/@/store/modules/app'; +import { ProjectConfig } from '/#/config'; +import { updateDarkTheme } from '/@/logics/theme/dark'; +import { useRootSetting } from '/@/hooks/setting/useRootSetting'; + +export function baseHandler(event: HandlerEnum, value: any) { + const appStore = useAppStore(); + const config = handler(event, value); + appStore.setProjectConfig(config); + if (event === HandlerEnum.CHANGE_THEME) { + updateHeaderBgColor(); + updateSidebarBgColor(); + } +} + +export function handler(event: HandlerEnum, value: any): DeepPartial { + const appStore = useAppStore(); + + const { getThemeColor, getDarkMode } = useRootSetting(); + switch (event) { + case HandlerEnum.CHANGE_LAYOUT: + const { mode, type, split } = value; + const splitOpt = split === undefined ? { split } : {}; + + return { + menuSetting: { + mode, + type, + collapsed: false, + show: true, + hidden: false, + ...splitOpt, + }, + }; + + case HandlerEnum.CHANGE_THEME_COLOR: + if (getThemeColor.value === value) { + return {}; + } + + return { themeColor: value }; + + case HandlerEnum.CHANGE_THEME: + if (getDarkMode.value === value) { + return {}; + } + updateDarkTheme(value); + + return {}; + + case HandlerEnum.MENU_HAS_DRAG: + return { menuSetting: { canDrag: value } }; + + case HandlerEnum.MENU_ACCORDION: + return { menuSetting: { accordion: value } }; + + case HandlerEnum.MENU_TRIGGER: + return { menuSetting: { trigger: value } }; + + case HandlerEnum.MENU_TOP_ALIGN: + return { menuSetting: { topMenuAlign: value } }; + + case HandlerEnum.MENU_COLLAPSED: + return { menuSetting: { collapsed: value } }; + + case HandlerEnum.MENU_WIDTH: + return { menuSetting: { menuWidth: value } }; + + case HandlerEnum.MENU_SHOW_SIDEBAR: + return { menuSetting: { show: value } }; + + case HandlerEnum.MENU_COLLAPSED_SHOW_TITLE: + return { menuSetting: { collapsedShowTitle: value } }; + + case HandlerEnum.MENU_THEME: + updateSidebarBgColor(value); + return { menuSetting: { bgColor: value } }; + + case HandlerEnum.MENU_SPLIT: + return { menuSetting: { split: value } }; + + case HandlerEnum.MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE: + return { menuSetting: { closeMixSidebarOnChange: value } }; + + case HandlerEnum.MENU_FIXED: + return { menuSetting: { fixed: value } }; + + case HandlerEnum.MENU_TRIGGER_MIX_SIDEBAR: + return { menuSetting: { mixSideTrigger: value } }; + + case HandlerEnum.MENU_FIXED_MIX_SIDEBAR: + return { menuSetting: { mixSideFixed: value } }; + + // ============transition================== + case HandlerEnum.OPEN_PAGE_LOADING: + appStore.setPageLoading(false); + return { transitionSetting: { openPageLoading: value } }; + + case HandlerEnum.ROUTER_TRANSITION: + return { transitionSetting: { basicTransition: value } }; + + case HandlerEnum.OPEN_ROUTE_TRANSITION: + return { transitionSetting: { enable: value } }; + + case HandlerEnum.OPEN_PROGRESS: + return { transitionSetting: { openNProgress: value } }; + // ============root================== + + case HandlerEnum.LOCK_TIME: + return { lockTime: value }; + + case HandlerEnum.FULL_CONTENT: + return { fullContent: value }; + + case HandlerEnum.CONTENT_MODE: + return { contentMode: value }; + + case HandlerEnum.SHOW_BREADCRUMB: + return { showBreadCrumb: value }; + + case HandlerEnum.SHOW_BREADCRUMB_ICON: + return { showBreadCrumbIcon: value }; + + case HandlerEnum.GRAY_MODE: + updateGrayMode(value); + return { grayMode: value }; + + case HandlerEnum.SHOW_FOOTER: + return { showFooter: value }; + + case HandlerEnum.COLOR_WEAK: + updateColorWeak(value); + return { colorWeak: value }; + + case HandlerEnum.SHOW_LOGO: + return { showLogo: value }; + + // ============tabs================== + case HandlerEnum.TABS_SHOW_QUICK: + return { multiTabsSetting: { showQuick: value } }; + + case HandlerEnum.TABS_SHOW: + return { multiTabsSetting: { show: value } }; + + case HandlerEnum.TABS_SHOW_REDO: + return { multiTabsSetting: { showRedo: value } }; + + case HandlerEnum.TABS_SHOW_FOLD: + return { multiTabsSetting: { showFold: value } }; + + // ============header================== + case HandlerEnum.HEADER_THEME: + updateHeaderBgColor(value); + return { headerSetting: { bgColor: value } }; + + case HandlerEnum.HEADER_SEARCH: + return { headerSetting: { showSearch: value } }; + + case HandlerEnum.HEADER_FIXED: + return { headerSetting: { fixed: value } }; + + case HandlerEnum.HEADER_SHOW: + return { headerSetting: { show: value } }; + default: + return {}; + } +} diff --git a/src/layouts/default/setting/index.vue b/src/layouts/default/setting/index.vue new file mode 100644 index 0000000..dd52c37 --- /dev/null +++ b/src/layouts/default/setting/index.vue @@ -0,0 +1,26 @@ + + diff --git a/src/layouts/default/sider/DragBar.vue b/src/layouts/default/sider/DragBar.vue new file mode 100644 index 0000000..ce74d85 --- /dev/null +++ b/src/layouts/default/sider/DragBar.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/layouts/default/sider/LayoutSider.vue b/src/layouts/default/sider/LayoutSider.vue new file mode 100644 index 0000000..7fd712f --- /dev/null +++ b/src/layouts/default/sider/LayoutSider.vue @@ -0,0 +1,157 @@ + + + diff --git a/src/layouts/default/sider/MixSider.vue b/src/layouts/default/sider/MixSider.vue new file mode 100644 index 0000000..da05e97 --- /dev/null +++ b/src/layouts/default/sider/MixSider.vue @@ -0,0 +1,591 @@ + + + diff --git a/src/layouts/default/sider/index.vue b/src/layouts/default/sider/index.vue new file mode 100644 index 0000000..1f73fd7 --- /dev/null +++ b/src/layouts/default/sider/index.vue @@ -0,0 +1,59 @@ + + + + diff --git a/src/layouts/default/sider/useLayoutSider.ts b/src/layouts/default/sider/useLayoutSider.ts new file mode 100644 index 0000000..66656b2 --- /dev/null +++ b/src/layouts/default/sider/useLayoutSider.ts @@ -0,0 +1,143 @@ +import type { Ref } from 'vue'; + +import { computed, unref, onMounted, nextTick } from 'vue'; + +import { TriggerEnum } from '/@/enums/menuEnum'; + +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; +import { useDebounceFn } from '@vueuse/core'; +import { useAppStore } from '/@/store/modules/app'; + +/** + * Handle related operations of menu events + */ +export function useSiderEvent() { + const appStore = useAppStore(); + const { getMiniWidthNumber } = useMenuSetting(); + + const getCollapsedWidth = computed(() => { + return unref(getMiniWidthNumber); + }); + + function onBreakpointChange(broken: boolean) { + appStore.setProjectConfig({ + menuSetting: { + siderHidden: broken, + }, + }); + } + + return { getCollapsedWidth, onBreakpointChange }; +} + +/** + * Handle related operations of menu folding + */ +export function useTrigger(getIsMobile: Ref) { + const { getTrigger, getSplit } = useMenuSetting(); + + const getShowTrigger = computed(() => { + const trigger = unref(getTrigger); + + return ( + trigger !== TriggerEnum.NONE && + !unref(getIsMobile) && + (trigger === TriggerEnum.FOOTER || unref(getSplit)) + ); + }); + + const getTriggerAttr = computed(() => { + if (unref(getShowTrigger)) { + return {}; + } + return { + trigger: null, + }; + }); + + return { getTriggerAttr, getShowTrigger }; +} + +/** + * Handle menu drag and drop related operations + * @param siderRef + * @param dragBarRef + */ +export function useDragLine(siderRef: Ref, dragBarRef: Ref, mix = false) { + const { getMiniWidthNumber, getCollapsed, setMenuSetting } = useMenuSetting(); + + onMounted(() => { + nextTick(() => { + const exec = useDebounceFn(changeWrapWidth, 80); + exec(); + }); + }); + + function getEl(elRef: Ref): any { + const el = unref(elRef); + if (!el) return null; + if (Reflect.has(el, '$el')) { + return (unref(elRef) as ComponentRef)?.$el; + } + return unref(elRef); + } + + function handleMouseMove(ele: HTMLElement, wrap: HTMLElement, clientX: number) { + document.onmousemove = function (innerE) { + let iT = (ele as any).left + (innerE.clientX - clientX); + innerE = innerE || window.event; + const maxT = 800; + const minT = unref(getMiniWidthNumber); + iT < 0 && (iT = 0); + iT > maxT && (iT = maxT); + iT < minT && (iT = minT); + ele.style.left = wrap.style.width = iT + 'px'; + return false; + }; + } + + // Drag and drop in the menu area-release the mouse + function removeMouseup(ele: any) { + const wrap = getEl(siderRef); + document.onmouseup = function () { + document.onmousemove = null; + document.onmouseup = null; + wrap.style.transition = 'width 0.2s'; + const width = parseInt(wrap.style.width); + + if (!mix) { + const miniWidth = unref(getMiniWidthNumber); + if (!unref(getCollapsed)) { + width > miniWidth + 20 + ? setMenuSetting({ menuWidth: width }) + : setMenuSetting({ collapsed: true }); + } else { + width > miniWidth && setMenuSetting({ collapsed: false, menuWidth: width }); + } + } else { + setMenuSetting({ menuWidth: width }); + } + + ele.releaseCapture?.(); + }; + } + + function changeWrapWidth() { + const ele = getEl(dragBarRef); + if (!ele) return; + const wrap = getEl(siderRef); + if (!wrap) return; + + ele.onmousedown = (e: any) => { + wrap.style.transition = 'unset'; + const clientX = e?.clientX; + ele.left = ele.offsetLeft; + handleMouseMove(ele, wrap, clientX); + removeMouseup(ele); + ele.setCapture?.(); + return false; + }; + } + + return {}; +} diff --git a/src/layouts/default/tabs/components/FoldButton.vue b/src/layouts/default/tabs/components/FoldButton.vue new file mode 100644 index 0000000..2deb1c0 --- /dev/null +++ b/src/layouts/default/tabs/components/FoldButton.vue @@ -0,0 +1,42 @@ + + diff --git a/src/layouts/default/tabs/components/TabContent.vue b/src/layouts/default/tabs/components/TabContent.vue new file mode 100644 index 0000000..431cbb1 --- /dev/null +++ b/src/layouts/default/tabs/components/TabContent.vue @@ -0,0 +1,76 @@ + + diff --git a/src/layouts/default/tabs/components/TabRedo.vue b/src/layouts/default/tabs/components/TabRedo.vue new file mode 100644 index 0000000..9c038aa --- /dev/null +++ b/src/layouts/default/tabs/components/TabRedo.vue @@ -0,0 +1,38 @@ + + + diff --git a/src/layouts/default/tabs/index.less b/src/layouts/default/tabs/index.less new file mode 100644 index 0000000..12523a0 --- /dev/null +++ b/src/layouts/default/tabs/index.less @@ -0,0 +1,199 @@ +@prefix-cls: ~'@{namespace}-multiple-tabs'; + +html[data-theme='light'] { + .@{prefix-cls} { + .ant-tabs-tab:not(.ant-tabs-tab-active) { + border: 1px solid #d9d9d9 !important; + } + } +} + +.@{prefix-cls} { + z-index: 10; + height: @multiple-height + 2; + border-bottom: 1px solid @border-color-base; + background-color: @component-background; + line-height: @multiple-height + 2; + + .ant-tabs-small { + height: @multiple-height; + } + + .ant-tabs.ant-tabs-card { + .ant-tabs-nav { + height: @multiple-height; + margin: 0; + padding-top: 2px; + border: 0; + background-color: @component-background; + box-shadow: none; + + .ant-tabs-nav-container { + height: @multiple-height; + padding-top: 2px; + } + + .ant-tabs-tab { + height: calc(@multiple-height - 2px); + padding-right: 12px; + transition: none; + background-color: @component-background; + color: @text-color-base; + line-height: calc(@multiple-height - 2px); + + &:hover { + .ant-tabs-tab-remove { + opacity: 1; + } + } + + .ant-tabs-tab-remove { + width: 8px; + height: 28px; + margin-right: -4px; + margin-left: 2px; + transition: none; + opacity: 0; + color: inherit; + font-size: 12px; + + &:hover { + svg { + width: 0.8em; + } + } + } + + // > div { + // display: flex; + // justify-content: center; + // align-items: center; + // } + + svg { + fill: @text-color-base; + } + } + + .ant-tabs-tab:not(.ant-tabs-tab-active) { + &:hover { + color: @primary-color; + } + } + + .ant-tabs-tab-active { + position: relative; + padding-left: 18px; + transition: none; + border: 0; + background: @primary-color; + + span { + color: @white !important; + } + + .ant-tabs-tab-remove { + opacity: 1; + } + + svg { + width: 0.7em; + fill: @white; + } + } + } + + .ant-tabs-nav > div:nth-child(1) { + padding: 0 6px; + + .ant-tabs-tab { + margin-right: 3px !important; + } + } + } + + .ant-tabs-tab:not(.ant-tabs-tab-active) { + .anticon-close { + font-size: 12px; + + svg { + width: 0.6em; + } + } + } + + .ant-dropdown-trigger { + display: inline-flex; + } + + &--hide-close { + .ant-tabs-tab-remove { + opacity: 0 !important; + } + } + + &-content { + &__extra-quick, + &__extra-redo, + &__extra-fold { + display: inline-block; + width: 36px; + height: @multiple-height; + border-left: 1px solid @border-color-base; + color: @text-color-secondary; + line-height: @multiple-height; + text-align: center; + cursor: pointer; + + &:hover { + color: @text-color-base; + } + + span[role='img'] { + transform: rotate(90deg); + } + } + + &__extra-redo { + span[role='img'] { + transform: rotate(0deg); + } + } + + &__info { + display: inline-block; + width: 100%; + height: @multiple-height - 2; + margin-left: -10px; + padding-left: 0; + font-size: 12px; + cursor: pointer; + user-select: none; + } + } +} + +.ant-tabs-dropdown-menu { + &-title-content { + display: flex; + align-items: center; + + .@{prefix-cls} { + &-content__info { + width: auto; + margin-left: 0; + line-height: 28px; + } + } + } + + &-item-remove { + margin-left: auto; + } +} + +.multiple-tabs__dropdown { + .ant-dropdown-content { + width: 172px; + } +} \ No newline at end of file diff --git a/src/layouts/default/tabs/index.vue b/src/layouts/default/tabs/index.vue new file mode 100644 index 0000000..3b487bb --- /dev/null +++ b/src/layouts/default/tabs/index.vue @@ -0,0 +1,144 @@ + + + diff --git a/src/layouts/default/tabs/types.ts b/src/layouts/default/tabs/types.ts new file mode 100644 index 0000000..3a8cfd9 --- /dev/null +++ b/src/layouts/default/tabs/types.ts @@ -0,0 +1,25 @@ +import type { DropMenu } from '/@/components/Dropdown/index'; +import type { RouteLocationNormalized } from 'vue-router'; + +export enum TabContentEnum { + TAB_TYPE, + EXTRA_TYPE, +} + +export type { DropMenu }; + +export interface TabContentProps { + tabItem: RouteLocationNormalized; + type?: TabContentEnum; + trigger?: ('click' | 'hover' | 'contextmenu')[]; +} + +export enum MenuEventEnum { + REFRESH_PAGE, + CLOSE_CURRENT, + CLOSE_LEFT, + CLOSE_RIGHT, + CLOSE_OTHER, + CLOSE_ALL, + SCALE, +} diff --git a/src/layouts/default/tabs/useMultipleTabs.ts b/src/layouts/default/tabs/useMultipleTabs.ts new file mode 100644 index 0000000..71b9029 --- /dev/null +++ b/src/layouts/default/tabs/useMultipleTabs.ts @@ -0,0 +1,80 @@ +import { toRaw, ref, nextTick } from 'vue'; +import type { RouteLocationNormalized } from 'vue-router'; +import { useDesign } from '/@/hooks/web/useDesign'; +import { useSortable } from '/@/hooks/web/useSortable'; +import { useMultipleTabStore } from '/@/store/modules/multipleTab'; +import { isNullAndUnDef } from '/@/utils/is'; +import projectSetting from '/@/settings/projectSetting'; +import { useRouter } from 'vue-router'; + +export function initAffixTabs(): string[] { + const affixList = ref([]); + + const tabStore = useMultipleTabStore(); + const router = useRouter(); + /** + * @description: Filter all fixed routes + */ + function filterAffixTabs(routes: RouteLocationNormalized[]) { + const tabs: RouteLocationNormalized[] = []; + routes && + routes.forEach((route) => { + if (route.meta && route.meta.affix) { + tabs.push(toRaw(route)); + } + }); + return tabs; + } + + /** + * @description: Set fixed tabs + */ + function addAffixTabs(): void { + const affixTabs = filterAffixTabs(router.getRoutes() as unknown as RouteLocationNormalized[]); + affixList.value = affixTabs; + for (const tab of affixTabs) { + tabStore.addTab({ + meta: tab.meta, + name: tab.name, + path: tab.path, + } as unknown as RouteLocationNormalized); + } + } + + let isAddAffix = false; + + if (!isAddAffix) { + addAffixTabs(); + isAddAffix = true; + } + return affixList.value.map((item) => item.meta?.title).filter(Boolean) as string[]; +} + +export function useTabsDrag(affixTextList: string[]) { + const tabStore = useMultipleTabStore(); + const { multiTabsSetting } = projectSetting; + const { prefixCls } = useDesign('multiple-tabs'); + nextTick(() => { + if (!multiTabsSetting.canDrag) return; + const el = document.querySelectorAll( + `.${prefixCls} .ant-tabs-nav-wrap > div`, + )?.[0] as HTMLElement; + const { initSortable } = useSortable(el, { + filter: (e: ChangeEvent) => { + const text = e?.target?.innerText; + if (!text) return false; + return affixTextList.includes(text); + }, + onEnd: (evt) => { + const { oldIndex, newIndex } = evt; + + if (isNullAndUnDef(oldIndex) || isNullAndUnDef(newIndex) || oldIndex === newIndex) { + return; + } + + tabStore.sortTabs(oldIndex, newIndex); + }, + }); + initSortable(); + }); +} diff --git a/src/layouts/default/tabs/useTabDropdown.ts b/src/layouts/default/tabs/useTabDropdown.ts new file mode 100644 index 0000000..016ce8c --- /dev/null +++ b/src/layouts/default/tabs/useTabDropdown.ts @@ -0,0 +1,140 @@ +import type { TabContentProps } from './types'; +import type { DropMenu } from '/@/components/Dropdown'; +import type { ComputedRef } from 'vue'; + +import { computed, unref, reactive } from 'vue'; +import { MenuEventEnum } from './types'; +import { useMultipleTabStore } from '/@/store/modules/multipleTab'; +import { RouteLocationNormalized, useRouter } from 'vue-router'; +import { useTabs } from '/@/hooks/web/useTabs'; +import { useI18n } from '/@/hooks/web/useI18n'; + +export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: ComputedRef) { + const state = reactive({ + current: null as Nullable, + currentIndex: 0, + }); + + const { t } = useI18n(); + const tabStore = useMultipleTabStore(); + const { currentRoute } = useRouter(); + const { refreshPage, closeAll, close, closeLeft, closeOther, closeRight } = useTabs(); + + const getTargetTab = computed((): RouteLocationNormalized => { + return unref(getIsTabs) ? tabContentProps.tabItem : unref(currentRoute); + }); + + /** + * @description: drop-down list + */ + const getDropMenuList = computed(() => { + if (!unref(getTargetTab)) { + return; + } + const { meta } = unref(getTargetTab); + const { path } = unref(currentRoute); + + const curItem = state.current; + + const isCurItem = curItem ? curItem.path === path : false; + + // Refresh button + const index = state.currentIndex; + const refreshDisabled = !isCurItem; + // Close left + const closeLeftDisabled = index === 0 || !isCurItem; + + const disabled = tabStore.getTabList.length === 1; + + // Close right + const closeRightDisabled = + !isCurItem || (index === tabStore.getTabList.length - 1 && tabStore.getLastDragEndIndex >= 0); + const dropMenuList: DropMenu[] = [ + { + icon: 'ion:reload-sharp', + event: MenuEventEnum.REFRESH_PAGE, + text: t('layout.multipleTab.reload'), + disabled: refreshDisabled, + }, + { + icon: 'clarity:close-line', + event: MenuEventEnum.CLOSE_CURRENT, + text: t('layout.multipleTab.close'), + disabled: !!meta?.affix || disabled, + divider: true, + }, + { + icon: 'line-md:arrow-close-left', + event: MenuEventEnum.CLOSE_LEFT, + text: t('layout.multipleTab.closeLeft'), + disabled: closeLeftDisabled, + divider: false, + }, + { + icon: 'line-md:arrow-close-right', + event: MenuEventEnum.CLOSE_RIGHT, + text: t('layout.multipleTab.closeRight'), + disabled: closeRightDisabled, + divider: true, + }, + { + icon: 'dashicons:align-center', + event: MenuEventEnum.CLOSE_OTHER, + text: t('layout.multipleTab.closeOther'), + disabled: disabled || !isCurItem, + }, + { + icon: 'clarity:minus-line', + event: MenuEventEnum.CLOSE_ALL, + text: t('layout.multipleTab.closeAll'), + disabled: disabled, + }, + ]; + + return dropMenuList; + }); + + function handleContextMenu(tabItem: RouteLocationNormalized) { + return (e: Event) => { + if (!tabItem) { + return; + } + e?.preventDefault(); + const index = tabStore.getTabList.findIndex((tab) => tab.path === tabItem.path); + state.current = tabItem; + state.currentIndex = index; + }; + } + + // Handle right click event + function handleMenuEvent(menu: DropMenu): void { + const { event } = menu; + switch (event) { + case MenuEventEnum.REFRESH_PAGE: + // refresh page + refreshPage(); + break; + // Close current + case MenuEventEnum.CLOSE_CURRENT: + close(tabContentProps.tabItem); + break; + // Close left + case MenuEventEnum.CLOSE_LEFT: + closeLeft(); + break; + // Close right + case MenuEventEnum.CLOSE_RIGHT: + closeRight(); + break; + // Close other + case MenuEventEnum.CLOSE_OTHER: + closeOther(); + break; + // Close all + case MenuEventEnum.CLOSE_ALL: + closeAll(); + break; + } + } + return { getDropMenuList, handleMenuEvent, handleContextMenu }; +} diff --git a/src/layouts/default/trigger/HeaderTrigger.vue b/src/layouts/default/trigger/HeaderTrigger.vue new file mode 100644 index 0000000..391b7fc --- /dev/null +++ b/src/layouts/default/trigger/HeaderTrigger.vue @@ -0,0 +1,17 @@ + + diff --git a/src/layouts/default/trigger/SiderTrigger.vue b/src/layouts/default/trigger/SiderTrigger.vue new file mode 100644 index 0000000..ab0d057 --- /dev/null +++ b/src/layouts/default/trigger/SiderTrigger.vue @@ -0,0 +1,12 @@ + + diff --git a/src/layouts/default/trigger/index.vue b/src/layouts/default/trigger/index.vue new file mode 100644 index 0000000..5a070e1 --- /dev/null +++ b/src/layouts/default/trigger/index.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/layouts/iframe/index.vue b/src/layouts/iframe/index.vue new file mode 100644 index 0000000..d9ee7e5 --- /dev/null +++ b/src/layouts/iframe/index.vue @@ -0,0 +1,29 @@ + + diff --git a/src/layouts/iframe/useFrameKeepAlive.ts b/src/layouts/iframe/useFrameKeepAlive.ts new file mode 100644 index 0000000..e84c49f --- /dev/null +++ b/src/layouts/iframe/useFrameKeepAlive.ts @@ -0,0 +1,59 @@ +import type { AppRouteRecordRaw } from '/@/router/types'; + +import { computed, toRaw, unref } from 'vue'; + +import { useMultipleTabStore } from '/@/store/modules/multipleTab'; + +import { uniqBy } from 'lodash-es'; + +import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; + +import { useRouter } from 'vue-router'; + +export function useFrameKeepAlive() { + const router = useRouter(); + const { currentRoute } = router; + const { getShowMultipleTab } = useMultipleTabSetting(); + const tabStore = useMultipleTabStore(); + const getFramePages = computed(() => { + const ret = getAllFramePages(toRaw(router.getRoutes()) as unknown as AppRouteRecordRaw[]) || []; + return ret; + }); + + const getOpenTabList = computed((): string[] => { + return tabStore.getTabList.reduce((prev: string[], next) => { + if (next.meta && Reflect.has(next.meta, 'frameSrc')) { + prev.push(next.name as string); + } + return prev; + }, []); + }); + + function getAllFramePages(routes: AppRouteRecordRaw[]): AppRouteRecordRaw[] { + let res: AppRouteRecordRaw[] = []; + for (const route of routes) { + const { meta: { frameSrc } = {}, children } = route; + if (frameSrc) { + res.push(route); + } + if (children && children.length) { + res.push(...getAllFramePages(children)); + } + } + res = uniqBy(res, 'name'); + return res; + } + + function showIframe(item: AppRouteRecordRaw) { + return item.name === unref(currentRoute).name; + } + + function hasRenderFrame(name: string) { + if (!unref(getShowMultipleTab)) { + return router.currentRoute.value.name === name; + } + return unref(getOpenTabList).includes(name); + } + + return { hasRenderFrame, getFramePages, showIframe, getAllFramePages }; +} diff --git a/src/layouts/page/index.vue b/src/layouts/page/index.vue new file mode 100644 index 0000000..72fe90f --- /dev/null +++ b/src/layouts/page/index.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/layouts/page/transition.ts b/src/layouts/page/transition.ts new file mode 100644 index 0000000..9e93009 --- /dev/null +++ b/src/layouts/page/transition.ts @@ -0,0 +1,33 @@ +import type { FunctionalComponent } from 'vue'; +import type { RouteLocation } from 'vue-router'; + +export interface DefaultContext { + Component: FunctionalComponent & { type: Recordable }; + route: RouteLocation; +} + +export function getTransitionName({ + route, + openCache, + cacheTabs, + enableTransition, + def, +}: Pick & { + enableTransition: boolean; + openCache: boolean; + def: string; + cacheTabs: string[]; +}): string | undefined { + if (!enableTransition) { + return undefined; + } + + const isInCache = cacheTabs.includes(route.name as string); + const transitionName = 'fade-slide'; + let name: string | undefined = transitionName; + + if (openCache) { + name = isInCache && route.meta.loaded ? transitionName : undefined; + } + return name || (route.meta.transitionName as string) || def; +} diff --git a/src/locales/helper.ts b/src/locales/helper.ts new file mode 100644 index 0000000..4f78439 --- /dev/null +++ b/src/locales/helper.ts @@ -0,0 +1,37 @@ +import type { LocaleType } from '/#/config'; + +import { set } from 'lodash-es'; + +export const loadLocalePool: LocaleType[] = []; + +export function setHtmlPageLang(locale: LocaleType) { + document.querySelector('html')?.setAttribute('lang', locale); +} + +export function setLoadLocalePool(cb: (loadLocalePool: LocaleType[]) => void) { + cb(loadLocalePool); +} + +export function genMessage(langs: Record>, prefix = 'lang') { + const obj: Recordable = {}; + + Object.keys(langs).forEach((key) => { + const langFileModule = langs[key].default; + let fileName = key.replace(`./${prefix}/`, '').replace(/^\.\//, ''); + const lastIndex = fileName.lastIndexOf('.'); + fileName = fileName.substring(0, lastIndex); + const keyList = fileName.split('/'); + const moduleName = keyList.shift(); + const objKey = keyList.join('.'); + + if (moduleName) { + if (objKey) { + set(obj, moduleName, obj[moduleName] || {}); + set(obj[moduleName], objKey, langFileModule); + } else { + set(obj, moduleName, langFileModule || {}); + } + } + }); + return obj; +} diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts new file mode 100644 index 0000000..98bebd5 --- /dev/null +++ b/src/locales/lang/en.ts @@ -0,0 +1,12 @@ +import { genMessage } from '../helper'; +import antdLocale from 'ant-design-vue/es/locale/en_US'; + +const modules = import.meta.glob('./en/**/*.ts', { eager: true }); +export default { + message: { + ...genMessage(modules as Recordable, 'en'), + antdLocale, + }, + dateLocale: null, + dateLocaleName: 'en', +}; diff --git a/src/locales/lang/en/basic.ts b/src/locales/lang/en/basic.ts new file mode 100644 index 0000000..5037b2e --- /dev/null +++ b/src/locales/lang/en/basic.ts @@ -0,0 +1,370 @@ +export default { + selectData: 'Please select a piece of data', + modifyDataPrompt: 'Sorry, only unapproved documents can be edited!', + supplier: { + title: 'Supplier List', + addSupplier: 'Add Supplier', + editSupplier: 'Edit Supplier', + add: 'Add', + batchDelete: 'Batch Delete', + batchEnable: 'Batch Enable', + batchDisable: 'Batch Disable', + Import: 'Import', + Export: 'Export', + header: { + name: 'Supplier name', + contactPhone: 'Contact phone', + createTime: 'Create time', + startDate: 'Start date', + endDate: 'End date', + }, + table: { + name: 'Supplier name', + contact: 'Contact', + phoneNumber: 'Phone number', + contactPhone: 'Contact phone', + email: 'Email', + status: 'Status', + accumulatedAccountsPayable: 'Accumulated accounts payable', + rate: 'Rate(%)', + sort: 'Sort', + createTime: 'Create time', + }, + form: { + name: 'Supplier name', + contact: 'Contact', + phoneNumber: 'Phone', + contactPhone: 'Landline', + email: 'Email', + fax: 'Fax', + address: 'Address', + remark: 'Remark', + accountsPayableInfo: 'Accounts payable information (Quarter)', + firstQuarterPayment: 'First payment', + secondQuarterPayment: 'Second payment', + thirdQuarterPayment: 'Three payment', + fourthQuarterPayment: 'Four payment', + accountInfo: 'Account info', + taxNumber: 'Tax number', + rate: 'Rate(%)', + bankName: 'Bank name', + bankAccount: 'Bank account', + notice: 'Supplier name or individual', + noticeTwo: 'Landline number (such as 010/021)', + }, + export: { + name: 'Export', + exportData: 'Supplier Data ', + noData: 'No available data export', + templateDownload: 'Supplier Excel template [Download]', + import: 'Supplier import', + data: 'Supplier data' + } + }, + account: { + basicSetting: 'Basic Setting', + name: 'Name', + position: 'Position', + personalProfile: 'Personal profile', + systemLanguage: 'Language', + systemLanguageTip: 'This setting can modify the Chinese and English language in the left menu', + avatar: 'Update Avatar', + avatarTip: 'Avatar (After updating the avatar, please refresh the browser)', + safeSetting: 'Security setting', + accountPassword: 'Account password', + accountPasswordTip: 'Account password (current password strength: medium)', + accountPhone: 'Security phone', + accountPhoneTip: 'Phone bound:', + accountEmail: 'Security email', + accountEmailTip: 'Email bound:', + updateInfo: 'Update basic info', + noticeOne: 'User data modification failed', + noticeTwo: 'Unbound', + update: 'Update', + password: { + title: 'Change account password', + oldPassword: 'Original password', + inputOldPassword: 'Please enter original password', + newPassword: 'New password', + inputNewPassword: 'Please enter new password', + confirmPassword: 'Confirm password', + inputConfirmPassword: 'Please enter new password again', + noticeOne: 'The two passwords entered are inconsistent', + updateSuccess: 'Password changed successfully', + }, + phone: { + title: 'Replace the security phone', + oldPhone: 'Original phone', + newPhone: 'New phone', + inputNewPhone: 'Please enter new phone number', + code: 'Phone verification code', + inputCode: 'Please enter the verification code', + notice: 'Please enter the correct phone number', + }, + email: { + title: 'Replace the security email', + oldEmail: 'Original email', + newEmail: 'New email', + inputNewEmail: 'Please enter new email address', + code: 'Email verification code', + inputCode: 'Please enter the verification code', + notice: 'Please enter the correct email address', + }, + notice: { + title: 'New message notification', + systemInfo: 'System message', + systemInfoTip: 'System messages will be notified in the form of station letters', + todo: 'To-do task', + todoTip: 'To-do tasks will be notified in the form of station letters', + on: 'On', + off: 'Off' + } + }, + customer: { + title: 'Customer List', + addCustomer: 'Add Customer', + editCustomer: 'Edit Customer', + add: 'Add', + batchDelete: 'Batch Delete', + batchEnable: 'Batch Enable', + batchDisable: 'Batch Disable', + Import: 'Import', + Export: 'Export', + header: { + name: 'Customer name', + phoneNumber: 'Phone number', + createTime: 'Create time', + startDate: 'Start date', + endDate: 'Eed date', + }, + table: { + name: 'Customer name', + contact: 'Contact', + phoneNumber: 'Phone number', + email: 'Email', + status: 'Status', + accumulatedAccountsReceivable: 'Accumulated accounts receivable', + rate: 'Rate(%)', + sort: 'Sort', + createTime: 'Create time', + }, + form: { + name: 'Customer name', + nameTip: 'If it is an individual, there is no need to fill in the contact person', + contact: 'Contact', + phoneNumber: 'Phone number', + email: 'Email', + fax: 'Fax', + address: 'Address', + remark: 'Remark', + accountsReceivableInfo: 'Accounts receivable information (Quarter)', + firstQuarterCollection: 'First collection', + secondQuarterCollection: 'Second collection', + thirdQuarterCollection: 'Third collection', + fourthQuarterCollection: 'Fourth collection', + accountInfo: 'Account info', + taxNumber: 'Tax number', + rate: 'Rate(%)', + bankName: 'Bank name', + bankAccount: 'Bank account', + }, + export: { + name: 'Export', + exportData: 'Customer Data ', + noData: 'No available data export', + templateDownload: 'Customer Information Excel Template [Download]', + import: 'Customer data import', + } + }, + member: { + title: 'Member List', + addMember: 'Add Member', + editMember: 'Edit Member', + add: 'Add', + batchDelete: 'Batch Delete', + batchEnable: 'Batch Enable', + batchDisable: 'Batch Disable', + Import: 'Import', + Export: 'Export', + header: { + memberNumber: 'Member number', + phoneNumber: 'Phone number', + createTime: 'Create time', + startDate: 'Start Date', + endDate: 'End Date', + }, + table: { + memberNumber: 'Member number', + memberName: 'Member name', + phoneNumber: 'Phone number', + email: 'Email', + advancePayment: 'Advance payment', + status: 'Status', + remark: 'Remark', + sort: 'Sort', + createTime: 'Create time', + }, + form: { + memberNumber: 'Number', + memberName: 'Name', + phoneNumber: 'PhoneNumber', + email: 'Email', + advancePayment: 'Advance payment', + sort: 'Sort', + }, + export: { + name: 'Export', + exportData: 'Member Data ', + noData: 'No available data export', + templateDownload: 'Member Information Excel Template [Download]', + import: 'Member data import', + } + }, + warehouse: { + title: 'Warehouse List', + addWarehouse: 'Add Warehouse', + editWarehouse: 'Edit Warehouse', + add: 'Add', + batchDelete: 'Batch Delete', + batchEnable: 'Batch Enable', + batchDisable: 'Batch Disable', + yes: 'Yes', + no: 'No', + header: { + warehouse: 'Warehouse', + remark: 'Remark', + }, + table: { + warehouseName: 'Warehouse name', + warehouseAddress: 'Warehouse address', + storageFees: 'Storage fees', + handlingFees: 'Handling fees', + manager: 'Manager', + status: 'Status', + default: 'Default warehouse', + sort: 'Sort', + createTime: 'Create time', + }, + form: { + warehouseName: 'Name', + warehouseAddress: 'Address', + storageFees: 'Storage fees', + handlingFees: 'Handling fees', + manager: 'Manager', + managerTip: 'Users in the user list', + remark: 'Remark', + default: 'Default', + defaultTip: 'Only one default warehouse is allowed. If selected, the previous default warehouse will become a non default warehouse', + sort: 'Sort', + } + }, + settlement: { + title: 'Settlement Account List', + addSettlementAccount: 'Add Settlement Account', + editSettlementAccount: 'Edit Settlement Account', + add: 'Add', + batchDelete: 'Batch Delete', + batchEnable: 'Batch Enable', + batchDisable: 'Batch Disable', + yes: 'Yes', + no: 'No', + header: { + accountNumber: 'Account number', + accountName: 'Account name', + }, + table: { + accountNumber: 'Account number', + accountName: 'Account name', + openingAmount: 'Opening amount', + currentBalance: 'Current balance', + status: 'Status', + default: 'Default account', + sort: 'Sort', + createTime: 'Create time', + }, + form: { + accountNumber: 'Number', + accountName: 'Name', + openingAmount: 'Opening amount', + currentBalance: 'Balance', + default: 'Default', + sort: 'Sort', + remark: 'Remark', + notice: 'Only one default account is allowed. If selected, the previous default account will become a non default account' + }, + other: { + title: 'Multi account settlement', + accountOne: 'Account 1', + accountTwo: 'Account 2', + accountThree: 'Account 3', + inputAccount: 'Please select settlement account', + amountOne: 'Amount 1', + amountTwo: 'Amount 2', + amountThree: 'Amount 3', + inputAmount: 'Please enter the settlement amount', + selectAmount: 'Please select the settlement amount', + notice: 'Please select a settlement account and amount, at least two accounts', + } + }, + operator: { + title: 'List of Operators/Operators', + addOperator: 'Add Operator', + editOperator: 'Edit Operator', + add: 'Add', + batchDelete: 'Batch Delete', + batchEnable: 'Batch Enable', + batchDisable: 'Batch Disable', + salesPerson: 'Sales person', + financialPerson: 'Financial person', + businessPerson: 'Business person', + header: { + name: 'Name', + type: 'Type', + }, + table: { + name: 'Name', + type: 'Type', + status: 'Status', + sort: 'Sort', + createTime: 'Create time', + }, + form: { + name: 'Name', + type: 'Type', + sort: 'Sort', + remark: 'Remark', + }, + }, + incomeExpense: { + title: 'List of income or expense items', + addIncomeExpense: 'Add income or expense items', + editIncomeExpense: 'Edit income or expense items', + add: 'Add', + batchDelete: 'Batch Delete', + batchEnable: 'Batch Enable', + batchDisable: 'Batch Disable', + enable: 'Enable', + disable: 'Disable', + income: 'Income', + expense: 'Expense', + header: { + name: 'Name', + type: 'Type', + remark: 'Remark', + }, + table: { + name: 'Name', + type: 'Type', + remark: 'Remark', + sort: 'Sort', + status: 'Status', + createTime: 'Create time', + }, + form: { + name: 'Name', + type: 'Type', + sort: 'Sort', + remark: 'Remark', + } + } +} \ No newline at end of file diff --git a/src/locales/lang/en/common.ts b/src/locales/lang/en/common.ts new file mode 100644 index 0000000..9c4a567 --- /dev/null +++ b/src/locales/lang/en/common.ts @@ -0,0 +1,35 @@ +export default { + okText: 'OK', + closeText: 'Close', + cancelText: 'Cancel', + loadingText: 'Loading...', + saveText: 'Save', + delText: 'Delete', + resetText: 'Reset', + searchText: 'Search', + queryText: 'Search', + + inputText: 'Please enter ', + chooseText: 'Please choose ', + + redo: 'Refresh', + back: 'Back', + + light: 'Light', + dark: 'Dark', + + action: 'Action', + operating: 'Operate', + successful: 'Success', + failed: 'Failed', + warning: 'Warning', + on: 'On', + off: 'Off', + delete: 'Delete', + deleteConfirm: 'Confirm Delete', + createTime: 'Create Time', + updateTime: 'Update Time', + notAllowEditAdminData: 'Disallow edit of administrator data', + notAllowDeleteAdminData: 'Disallow deletion of administrator data', + notAllowResetAdmin: 'Disallow reset password of administrator' +}; diff --git a/src/locales/lang/en/component.ts b/src/locales/lang/en/component.ts new file mode 100644 index 0000000..ba66fa5 --- /dev/null +++ b/src/locales/lang/en/component.ts @@ -0,0 +1,130 @@ +export default { + app: { + searchNotData: 'No search results yet', + toSearch: 'to search', + toNavigate: 'to navigate', + }, + countdown: { + normalText: 'Get SMS code', + sendText: 'Reacquire in {0}s', + }, + 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: 'Preivew', + }, + drawer: { + loadingText: 'Loading...', + cancelText: 'Close', + okText: 'Confirm', + }, + excel: { + exportModalTitle: 'Export data', + fileType: 'File type', + fileName: 'File name', + }, + form: { + putAway: 'Put away', + unfold: 'Unfold', + maxTip: 'The number of characters should be less than {0}', + apiSelectNotFound: 'Wait for data loading to complete...', + }, + icon: { + placeholder: 'Click the select icon', + search: 'Search icon', + copy: 'Copy icon successfully!', + }, + menu: { + search: 'Menu search', + }, + modal: { + cancelText: 'Close', + okText: 'Confirm', + close: 'Close', + maximize: 'Maximize', + restore: 'Restore', + }, + table: { + settingDens: 'Density', + settingDensDefault: 'Default', + settingDensMiddle: 'Middle', + settingDensSmall: 'Compact', + settingColumn: 'Column settings', + settingColumnShow: 'Column display', + settingIndexColumnShow: 'Index Column', + settingSelectColumnShow: 'Selection Column', + settingFixedLeft: 'Fixed Left', + settingFixedRight: 'Fixed Right', + settingFullScreen: 'Full Screen', + index: 'Index', + total: 'total of {total}', + }, + time: { + before: ' ago', + after: ' after', + just: 'just now', + seconds: ' seconds', + minutes: ' minutes', + hours: ' hours', + days: ' days', + }, + tree: { + selectAll: 'Select All', + unSelectAll: 'Cancel Select', + expandAll: 'Expand All', + unExpandAll: 'Collapse all', + + checkStrictly: 'Hierarchical association', + checkUnStrictly: 'Hierarchical independence', + }, + upload: { + save: 'Save', + upload: 'Upload', + imgUpload: 'ImageUpload', + uploaded: 'Uploaded', + + operating: 'Operating', + del: 'Delete', + download: 'download', + saveWarn: 'Please wait for the file to upload and save!', + saveError: 'There is no file successfully uploaded and cannot be saved!', + + preview: 'Preview', + choose: 'Select the file', + + 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', + + legend: 'Legend', + fileName: 'File name', + fileSize: 'File size', + fileStatue: 'File status', + + startUpload: 'Start upload', + uploadSuccess: 'Upload successfully', + uploadError: 'Upload failed', + uploading: 'Uploading', + uploadWait: 'Please wait for the file upload to finish', + reUploadFailed: 'Re-upload failed files', + }, + verify: { + error: 'verification failed!', + time: 'The verification is successful and it takes {time} seconds!', + redoTip: 'Click the picture to refresh', + dragText: 'Hold down the slider and drag', + successText: 'Verified', + }, +}; diff --git a/src/locales/lang/en/financial.ts b/src/locales/lang/en/financial.ts new file mode 100644 index 0000000..4e76bb4 --- /dev/null +++ b/src/locales/lang/en/financial.ts @@ -0,0 +1,429 @@ +export default { + selectData: 'Please select a piece of data', + modifyDataPrompt: 'Sorry, only unapproved documents can be edited!', + regularPrint: 'Regular print', + income: { + title: 'Income Receipt List', + add: 'Add', + batchDelete: 'Batch Delete', + editIncomeReceipt: 'Edit-Income Receipt', + addIncomeReceipt: 'Add-Income Receipt', + incomeReceiptDetail: 'Income Receipt - Detail', + receiptDetail: 'Income Receipt - Detail', + viewIncomeReceiptDetail: 'View Income Receipt Detail', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Star date', + endDate: 'End date', + incomeAccount: 'Income account', + correspondenceUnit: 'Correspondence unit', + financialPerson: 'Financial personnel', + status: 'Status', + remark: 'Remark', + }, + table: { + name: 'Name', + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + financialPerson: 'Financial personnel', + incomeAccount: 'Income account', + incomeAmount: 'Income amount', + status: 'Status', + remark: 'Remark', + }, + view: { + incomeExpenseName: 'Income project', + amount: 'Amount', + remark: 'Remark', + total: 'Total', + }, + form: { + correspondenceUnit: 'Correspondence unit', + inputCorrespondenceUnit: 'Please select the correspondence unit', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select the receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter the receipt number', + financialPerson: 'Financial personnel', + inputFinancialPerson: 'Please select the financial personnel', + addFinancialPerson: 'Add financial personnel', + incomeAccount: 'Account', + inputIncomeAccount: 'Please select the income account', + incomeAmount: 'Amount', + inputIncomeAmount: 'Please enter the income amount', + inputRemark: 'Please enter the remark', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + noticeOne: 'Please select the income project', + noticeTwo: 'Please enter the income amount', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'Are you sure you want to delete the selected data?', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save And Approve', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + }, + export: { + name: 'Export', + exportData: 'Income Receipt Data ', + noData: 'No data available for export', + } + }, + expense: { + title: 'Expense Receipt List', + add: 'Add', + batchDelete: 'Batch Delete', + editExpenseReceipt: 'Edit-Expense Receipt', + addExpenseReceipt: 'Add-Expense Receipt', + expenseReceiptDetail: 'Expense Receipt Detail', + receiptDetail: 'Expense Receipt - Detail', + viewExpenseReceiptDetail: 'View Expense Receipt Detail', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Start date', + endDate: 'End date', + expenseAccount: 'Expense account', + correspondenceUnit: 'Correspondence unit', + financialPerson: 'Financial personnel', + status: 'Status', + remark: 'Remark', + }, + table: { + name: 'Name', + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + financialPerson: 'Financial personnel', + expenseAccount: 'Expense account', + expenseAmount: 'Expense amount', + remark: 'Remark', + status: 'Status', + }, + view: { + expenseName: 'Expense project', + amount: 'Amount', + remark: 'Remark', + }, + form: { + correspondenceUnit: 'Unit', + inputCorrespondenceUnit: 'Please select the unit', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select the receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter the receipt number', + financialPerson: 'Financial personnel', + inputFinancialPerson: 'Please select the financial personnel', + addFinancialPerson: 'Add financial personnel', + inputRemark: 'Please enter the remark', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + noticeOne: 'Please select the expense project', + noticeTwo: 'Please enter the expense amount', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'Are you sure you want to delete the selected data?', + total: 'Total', + expenseAccount: 'Account', + inputExpenseAccount: 'Please select the expense account', + expenseAmount: 'Amount', + inputExpenseAmount: 'Please enter the expense amount', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save And Approve', + }, + export: { + name: 'Export', + exportData: 'Expense Receipt Data ', + noData: 'No data available for export', + } + }, + transfer: { + title: 'Transfer Receipt List', + add: 'Add', + batchDelete: 'Batch Delete', + editTransferReceipt: 'Edit-Transfer Receipt', + addTransferReceipt: 'Add-Transfer Receipt', + transferReceiptDetail: 'Transfer Receipt Detail', + receiptDetail: 'Transfer Receipt - Detail', + viewTransferReceiptDetail: 'View Transfer Receipt Detail', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Start date', + endDate: 'End date', + paymentAccount: 'Payment account', + financialPerson: 'Financial personnel', + status: 'Status', + remark: 'Remark', + }, + table: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + financialPerson: 'Financial personnel', + paymentAccount: 'Payment account', + paymentAmount: 'Payment amount', + remark: 'Remark', + status: 'Status', + }, + view: { + accountName: 'Account name', + amount: 'Amount', + remark: 'Remark', + }, + form: { + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select the receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter the receipt number', + financialPerson: 'Financial personnel', + inputFinancialPerson: 'Please select the financial personnel', + addFinancialPerson: 'Add financial personnel', + inputRemark: 'Please enter the remark', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + noticeOne: 'Please select the account', + noticeTwo: 'Please enter the amount', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'Are you sure you want to delete the selected data?', + total: 'Total', + paymentAccount: 'Account', + inputPaymentAccount: 'Please select the payment account', + paymentAmount: 'Amount', + inputPaymentAmount: 'Please enter the payment amount', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save And Approve', + }, + export: { + name: 'Export', + exportData: 'Transfer Receipt Data ', + noData: 'No data available for export', + } + }, + collection: { + title: 'Collection Receipt List', + add: 'Add', + batchDelete: 'Batch delete', + editCollectionReceipt: 'Edit-Collection Receipt', + addCollectionReceipt: 'Add-Collection Receipt', + collectionReceiptDetail: 'Collection Receipt - Detail', + receiptDetail: 'Collection Receipt Detail', + viewCollectionReceiptDetail: 'View Collection Receipt Detail', + selectSaleArrearsReceipt: 'Select Sale Arrears Receipt', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Start date', + endDate: 'End date', + collectionAccount: 'Collection account', + customer: 'Customer', + financialPerson: 'Financial personnel', + status: 'Status', + remark: 'Remark', + productInfo: 'Product info', + }, + table: { + customer: 'Customer', + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + financialPerson: 'Financial personnel', + collectionAccount: 'Account', + totalCollection: 'Total collection', + discountAmount: 'Discount amount', + actualCollection: 'Actual collection', + remark: 'Remark', + status: 'Status', + }, + view: { + saleReceiptNumber: 'Sale receipt number', + receivableArrears: 'Receivable arrears', + receivedArrears: 'Received arrears', + thisTimeCollection: 'This time collection', + remark: 'Remark', + thisReceiptArrears: 'This receipt arrears', + operator: 'Operator', + }, + form: { + customer: 'Customer', + inputCustomer: 'Please select the customer', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select the receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter the receipt number', + financialPerson: 'Financial personnel', + inputFinancialPerson: 'Please select the financial personnel', + addFinancialPerson: 'Add financial personnel', + selectReceipt: 'Select sales order', + deleteRow: 'Delete selected rows', + noticeOne: 'Please select the customer', + noticeTwo: 'Please select the collection account', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'Are you sure you want to delete the selected data?', + noticeFive: 'Please enter the discount amount', + total: 'Total', + inputRemark: 'Please enter the remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save And Approve', + }, + export: { + name: 'Export', + exportData: 'Collection Receipt Data ', + noData: 'No data available for export', + } + }, + payment: { + title: 'Payment Receipt List', + add: 'Add', + batchDelete: 'Batch delete', + editPaymentReceipt: 'Edit-Payment Receipt', + addPaymentReceipt: 'Add-Payment Receipt', + paymentReceiptDetail: 'Payment Receipt - Detail', + receiptDetail: 'Payment Receipt Detail', + viewPaymentReceiptDetail: 'View Payment Receipt Detail', + selectPurchaseArrearsReceipt: 'Select Purchase Arrears Receipt', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Start date', + endDate: 'End date', + paymentAccount: 'Payment account', + supplier: 'Supplier', + financialPerson: 'Financial personnel', + status: 'Status', + remark: 'Remark', + productInfo: 'Product info', + }, + table: { + supplier: 'Supplier', + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + financialPerson: 'Financial personnel', + paymentAccount: 'Account', + totalPayment: 'Total payment', + discountAmount: 'Discount amount', + actualPayment: 'Actual payment', + remark: 'Remark', + status: 'Status', + }, + view: { + purchaseReceiptNumber: 'Purchase receipt number', + payableArrears: 'Payable arrears', + paidArrears: 'Paid arrears', + thisTimePayment: 'This time payment', + thisReceiptArrears: 'This receipt arrears', + operator: 'Operator', + remark: 'Remark', + }, + form: { + supplier: 'Supplier', + inputSupplier: 'Please select the supplier', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select the receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter the receipt number', + financialPerson: 'Financial personnel', + inputFinancialPerson: 'Please select the financial personnel', + addFinancialPerson: 'Add financial personnel', + selectReceipt: 'Select purchase order', + deleteRow: 'Delete selected rows', + inputPaymentAccount: 'Please select the payment account', + inputPaymentAmount: 'Please enter the payment amount', + inputDiscountAmount: 'please enter the discount amount', + inputActualPayment: 'please enter the actual payment', + noticeOne: 'Please select the supplier receipt', + noticeTwo: 'Please select the payment account', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'Are you sure you want to delete the selected data?', + noticeFive: 'To avoid duplicate addition of the same purchase debt document number, please modify the existing document', + total: 'Total', + inputRemark: 'Please enter the remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save And Approve', + }, + export: { + name: 'Export', + exportData: 'Collection Receipt Data ', + noData: 'No data available for export', + } + }, + advance: { + title: 'Advance Receipt List', + add: 'Add', + batchDelete: 'Batch delete', + editAdvanceReceipt: 'Edit-Advance Receipt', + addAdvanceReceipt: 'Add-Advance Receipt', + advanceReceiptDetail: 'Advance Receipt - Detail', + receiptDetail: 'Advance Receipt Detail', + viewAdvanceReceiptDetail: 'View Advance Receipt Detail', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Start date', + endDate: 'End date', + paymentMember: 'Payment member', + status: 'Status', + remark: 'Remark', + }, + table: { + paymentMember: 'Payment member', + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + amountCollected : 'Amount Collected', + totalAmount: 'Total Amount', + financialPerson: 'Financial personnel', + operator: 'Operator', + remark: 'Remark', + status: 'Status', + }, + view: { + accountName: 'Account', + amount: 'Amount', + remark: 'Remark', + }, + form: { + paymentMember: 'Member', + inputCustomer: 'Please select the customer', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select the receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter the receipt number', + financialPerson: 'Financial personnel', + inputFinancialPerson: 'Please select the financial personnel', + addFinancialPerson: 'Add financial personnel', + insertRow: 'Add A Row', + deleteRow: 'Delete Selected Rows', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'Please insert a row of data and enter the information for receiving and prepaying payments', + noticeFive: 'Please select the account', + noticeSix: 'Please enter the amount', + total: 'Total', + inputRemark: 'Please enter the remark', + amountCollected : 'Amount Collected', + totalAmount: 'Total Amount', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save And Approve', + }, + export: { + name: 'Export', + exportData: 'Advance Receipt Data ', + noData: 'No data available for export', + } + } +} \ No newline at end of file diff --git a/src/locales/lang/en/home.ts b/src/locales/lang/en/home.ts new file mode 100644 index 0000000..e0c2d41 --- /dev/null +++ b/src/locales/lang/en/home.ts @@ -0,0 +1,21 @@ +export default { + today: 'Today', + yesterday: 'Yesterday', + thisMonth: 'This Month', + thisYear: 'This Year', + todayRetail: 'Today Retail', + yesterdayRetail: 'Yesterday Retail', + thisMonthRetail: 'This Month Retail', + thisYearRetail: 'This Year Retail', + todaySales: 'Today Sales', + yesterdaySales: 'Yesterday Sales', + thisMonthSales: 'This Month Sales', + thisYearSales: 'This Year Sales', + todayPurchase: 'Today Purchase', + yesterdayPurchase: 'Yesterday Purchase', + thisMonthPurchase: 'This Month Purchase', + thisYearPurchase: 'This Year Purchase', + retailStatistics: 'Retail Statistics', + salesStatistics: 'Sales Statistics', + purchaseStatistics: 'Purchase Statistics', +} \ No newline at end of file diff --git a/src/locales/lang/en/layout.ts b/src/locales/lang/en/layout.ts new file mode 100644 index 0000000..8ba9ff6 --- /dev/null +++ b/src/locales/lang/en/layout.ts @@ -0,0 +1,116 @@ +export default { + footer: { onlinePreview: 'Preview', onlineDocument: 'Document' }, + header: { + // user dropdown + dropdownItemSetting: 'Personal Setting', + dropdownItemDoc: 'Document', + dropdownItemLoginOut: 'Log Out', + + tooltipErrorLog: 'Error log', + tooltipLock: 'Lock screen', + tooltipNotify: 'Notification', + + tooltipEntryFull: 'Full Screen', + tooltipExitFull: 'Exit Full Screen', + + // lock + lockScreenPassword: 'Lock screen password', + lockScreen: 'Lock screen', + lockScreenBtn: 'Locking', + + home: 'Home', + }, + multipleTab: { + reload: 'Refresh current', + close: 'Close current', + closeLeft: 'Close Left', + closeRight: 'Close Right', + closeOther: 'Close Other', + closeAll: 'Close All', + }, + setting: { + // content mode + contentModeFull: 'Full', + contentModeFixed: 'Fixed width', + // topMenu align + topMenuAlignLeft: 'Left', + topMenuAlignRight: 'Center', + topMenuAlignCenter: 'Right', + // menu trigger + menuTriggerNone: 'Not Show', + menuTriggerBottom: 'Bottom', + menuTriggerTop: 'Top', + // menu type + menuTypeSidebar: 'Left menu mode', + menuTypeMixSidebar: 'Left menu mixed mode', + menuTypeMix: 'Top Menu Mix mode', + menuTypeTopMenu: 'Top menu mode', + + on: 'On', + off: 'Off', + minute: 'Minute', + + operatingTitle: 'Successful!', + operatingContent: + 'The copy is successful, please go to src/settings/projectSetting.ts to modify the configuration!', + resetSuccess: 'Successfully reset!', + + copyBtn: 'Copy', + clearBtn: 'Clear cache and to the login page', + + drawerTitle: 'Configuration', + + darkMode: 'Dark mode', + navMode: 'Navigation mode', + interfaceFunction: 'Interface function', + interfaceDisplay: 'Interface display', + animation: 'Animation', + splitMenu: 'Split menu', + closeMixSidebarOnChange: 'Switch page to close menu', + + sysTheme: 'System theme', + headerTheme: 'Header theme', + sidebarTheme: 'Menu theme', + + menuDrag: 'Drag Sidebar', + menuSearch: 'Menu search', + menuAccordion: 'Sidebar accordion', + menuCollapse: 'Collapse menu', + collapseMenuDisplayName: 'Collapse menu display name', + topMenuLayout: 'Top menu layout', + menuCollapseButton: 'Menu collapse button', + contentMode: 'Content area width', + expandedMenuWidth: 'Expanded menu width', + + breadcrumb: 'Breadcrumbs', + breadcrumbIcon: 'Breadcrumbs Icon', + tabs: 'Tabs', + tabDetail: 'Tab Detail', + tabsQuickBtn: 'Tabs quick button', + tabsRedoBtn: 'Tabs redo button', + tabsFoldBtn: 'Tabs flod button', + sidebar: 'Sidebar', + header: 'Header', + footer: 'Footer', + fullContent: 'Full content', + grayMode: 'Gray mode', + colorWeak: 'Color Weak Mode', + + progress: 'Progress', + switchLoading: 'Switch Loading', + switchAnimation: 'Switch animation', + animationType: 'Animation type', + + autoScreenLock: 'Auto screen lock', + notAutoScreenLock: 'Not auto lock', + + fixedHeader: 'Fixed header', + fixedSideBar: 'Fixed Sidebar', + + mixSidebarTrigger: 'Mixed menu Trigger', + triggerHover: 'Hover', + triggerClick: 'Click', + + mixSidebarFixed: 'Fixed expanded menu', + }, +}; diff --git a/src/locales/lang/en/product.ts b/src/locales/lang/en/product.ts new file mode 100644 index 0000000..aeb2224 --- /dev/null +++ b/src/locales/lang/en/product.ts @@ -0,0 +1,204 @@ +export default { + selectData: 'Please select a piece of data', + modifyDataPrompt: 'Sorry, only unapproved documents can be edited!', + selectProduct: 'Select product', + inputSelectProduct: 'Please select product', + productList: 'Product List', + category:{ + title: 'Product Category List', + tip: 'The product category list can add multiple product category and lower level category', + add: 'Add product category', + batchDelete: 'Batch delete product category', + table:{ + categoryName: 'Name', + categoryNumber: 'Number', + categoryParent: 'Parent', + sort: 'Sort', + remark: 'Remark', + createTime: 'Create Time', + operate: 'Operate', + edit: 'Edite product category', + delete: 'Delete product category' + } + }, + info:{ + title: 'Product Information List', + add: 'Add', + batchDelete: 'Batch Delete', + batchEnable: 'Batch Enable', + batchDisable: 'Batch Disable', + selectFile: 'Select File', + import: 'Import', + export: 'Export', + batchEdit: 'Batch Edit', + addProductInfo: 'Add Product Info', + editProductInfo: 'Edit Product Info', + checkBarCodeExist: 'Import Data - Detect duplicate products', + dataBaseExist: 'There are duplicate product barcodes in the database, please check.', + dataCover: 'Do you need overwrite the existing data?', + exportData: 'Commodity Information Data ', + header: { + categoryName: 'Product category', + keyWord: 'Keyword', + serialNumber: 'Serial number', + batchNumber: 'Batch number', + warehouse: 'Warehouse', + have: 'Have', + none: 'None', + }, + table: { + barCode: 'BarCode', + productName: 'Name', + productStandard: 'Standard', + productModel: 'Model', + productColor: 'Color', + productUnit: 'Unit', + productCategory: 'Category', + productStock: 'Stock', + purchasePrice: 'Purchase price', + retailPrice: 'Retail price', + salesPrice: 'Sales price', + lowestSellPrice: 'Lowest sell price', + status: 'Status', + createTime: 'Create time', + operate: 'Operate', + }, + importInfo: { + title: 'Import product information data', + templateName: 'Product Information Excel Template [Download]', + infoData: 'Product info data', + setup1: 'Step 1:', + setup2: 'Step 2:', + tip: 'Tip: Do not delete the first row in the template', + }, + form: { + basic: { + title: 'Basic Info', + name: 'Name', + inputName: 'Please enter the name', + standard: 'Standard', + inputStandard: 'Please enter the standard', + model: 'Model', + inputModel: 'Please enter the model', + color: 'Color', + inputColor: 'Please enter the color', + unit: 'Unit', + inputUnit: 'Please enter the unit', + inputManyUnit: 'Please select multiple units', + unitTip: 'Need to enter the unit first to activate the input box here', + weight: 'Basic weight', + inputWeight: 'Please enter the basic weight (Kg)', + sheIfLife: 'Quality guarantee period', + inputSheIfLife: 'Please enter the shelf life (days)', + category: 'Category', + inputCategory: 'Please select a category', + serialNumber: 'Serial number', + inputSerialNumber: 'Please select whether there is a serial number', + serialNumberTip: 'If selected as Have, the serial number of the product needs to be entered in the purchase receipt form', + batchNumber: 'Batch number', + inputBatchNumber: 'Please select whether there is a batch number', + batchNumberTip: 'If selected as Have, the batch number and expiration date of the product need to be entered in the purchase receipt form', + warehouseShelves: 'Warehouse shelves', + multipleAttributes: 'Multiple attributes', + multipleAttributesTip: 'For industries such as clothing, shoes, and hats with multiple attributes, it is necessary to enter the unit first in order to activate the input box here', + inputMultipleAttributes: 'Please select multiple attributes (multiple choices are allowed)', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + purchasePriceBatch: 'Purchase price - batch', + retailPriceBatch: 'Retail price - batch', + salesPriceBatch: 'Sales price - batch', + lowestSellPriceBatch: 'Lowest sell price - batch', + table: { + pleaseEnter: 'Please enter ', + barCode: 'BarCode', + unit: 'Unit', + multipleAttributes: 'Multiple attributes', + retailPrice: 'Retail price', + purchasePrice: 'Purchase price', + salesPrice: 'Sales price', + lowestSellPrice: 'Lowest sell price', + }, + remark: 'Remark', + inputRemark: 'Please enter the remark', + noticeOne: 'Please insert a row of data and enter the barcode price information for the product', + noticeTwo: 'The system has detected that you do not have warehouse information. Please add at least one warehouse information in the Basic Information menu bar', + noticeThree: 'Sorry, you haven not selected multiple attributes yet. Only after enabling multiple attributes can you batch set the amount', + noticeFour: 'Please enter barcode, unit, and other information first!', + inputPrice: 'Please enter the price', + price: 'Price', + batchSet: 'Batch Settings', + }, + extendInfo: { + title: 'Extended Info', + manufacturer: 'Manufacturer', + customOne: 'Custom1', + customTwo: 'Custom2', + customThree: 'Custom3', + }, + inventoryQuantity: { + title: 'Inventory Quantity', + initialQuantity: 'Initial inventory quantity', + inputInitialQuantity: 'Please enter the initial inventory quantity', + batchInitialQuantity: 'Initial inventory quantity - Batch settings', + minSafetyQuantity: 'Minimum safety inventory quantity', + inputMinSafetyQuantity: 'Please enter the minimum safety inventory quantity', + batchMinSafetyQuantity: 'Minimum safety inventory quantity - Batch settings', + maxSafetyQuantity: 'Maximum safety inventory quantity', + inputMaxSafetyQuantity: 'Please enter the maximum safety inventory quantity', + batchMaxSafetyQuantity: 'Maximum safety inventory quantity - Batch settings', + warehouse: 'Warehouse (product barcode/product unit)', + inputNumber: 'Please enter the quantity', + number: 'Quantity', + }, + images: { + title: 'Image Info', + upload: 'Upload Image', + tip: 'Upload prompt: Up to 4 images can be uploaded, supporting JPG, JPEG, and PNG formats, with a maximum support of 2M', + }, + } + }, + attribute: { + title: 'Product Multi Attribute List', + add: 'Add product attributes', + batchDelete: 'Batch delete product attributes', + addProductAttribute: 'Add Product Attribute', + editProductAttribute: 'Edit Product Attribute', + table: { + attributeName: 'Attribute name', + attributeValue: 'Attribute values (separated by |)', + sort: 'Sort', + remark: 'Remark', + createTime: 'Create Time', + operate: 'Operate', + edit: 'Edit product attributes', + delete: 'Delete product attributes' + } + }, + unit: { + title: 'Product Units List', + add: 'Add product unit', + batchDelete: 'Batch delete product unit', + addProductUnit: 'Add Product Measurement Unit', + editProductUnit: 'Edit Product Measurement Unit', + table: { + unitName: 'Unit of measurement', + basicUnit: 'Basic unit', + inputBasicUnit: 'Please enter the base unit (Small unit)', + deputyUnitOne: 'Deputy Unit 1', + inputDeputyUnitOne: 'Please enter the deputy unit (Major unit)', + inputProportionOne: 'Please enter the proportion', + deputyUnitTwo: 'Deputy Unit 2', + inputDeputyUnitTwo: 'Please enter deputy Unit 2 (Major Unit)', + inputProportionTwo: 'Please enter the proportion 2', + deputyUnitThree: 'Deputy Unit 3', + inputDeputyUnitThree: 'Please enter deputy Unit 3 (Major Unit)', + inputProportionThree: 'Please enter the proportion 3', + status: 'Status', + createTime: 'Create Time', + operate: 'Operate', + edit: 'Edit product unit', + delete: 'Delete product unit' + }, + noticeOne: 'Sorry, the proportion of sub units cannot be empty', + } +}; \ No newline at end of file diff --git a/src/locales/lang/en/purchase.ts b/src/locales/lang/en/purchase.ts new file mode 100644 index 0000000..08818ba --- /dev/null +++ b/src/locales/lang/en/purchase.ts @@ -0,0 +1,320 @@ +export default { + selectData: 'Please select a piece of data', + modifyDataPrompt: 'Sorry, only unapproved documents can be edited!', + partialPurchase: 'Partial Purchase', + completePurchase: 'Complete Purchase', + regularPrint: 'Print', + order:{ + title: 'Purchase Order List', + addOrder: 'Add - Purchase Order', + editOrder: 'Edit - Purchase Order', + detail: 'Purchase Order - Detail', + receipt: 'Receipt Detail', + table:{ + supplier: 'Supplier', + receiptNumber: 'Receipt number', + productInformation: 'Product info', + productQuantity: 'Product quantity', + totalAmount: 'Total amount', + totalIncludingTax: 'Total including tax', + collectDeposit: 'Collect Deposit', + receiptDate: 'Receipt date', + operator: 'Operator', + status: 'Status', + }, + header:{ + startDate: 'Start date', + endDate: 'End date', + receiptRemark: 'receipt remark', + }, + form: { + supplier: 'Supplier', + inputSupplier: 'Please select supplier', + addSupplier: 'Add supplier', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select purchase products', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + discountRate: 'Discount Rate', + paymentDiscount: 'Payment Discount', + discountAmount: 'Discount Amount', + settlementAccount: 'Payment Account', + paymentDeposit: 'Deposit', + purchasePerson: 'Purchase Person', + inputPurchasePerson: 'Please select purchase person', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Are you sure you want to delete the selected data?', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'The barcode cannot find product info', + noticeFive: 'The product barcode cannot be empty', + noticeSix: 'Enter the barcode product information automatically!', + noticeEight: 'The warehouse cannot be empty', + noticeSeven: 'Support product name, product number, product specifications, and product model', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + warehouse: 'Warehouse', + barCode: 'Barcode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + model: 'Model', + color: 'Color', + stock: 'Stock', + unit: 'Unit', + unitPrice: 'Unit Price', + quantity: 'Quantity', + amount: 'Amount', + taxRate: 'Tax Rate(%)', + taxAmount: 'Tax Amount', + remark: 'Remark', + totalIncludingTax: 'Total Price And Tax', + total: 'Total', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + } + }, + view: { + title: 'Purchase Order Data', + supplier: 'Supplier', + receiptDate: 'Receipt date', + receiptAmount: 'Receipt amount', + settlementAccount: 'Payment Account', + inputSettlementAccount: 'Please select account', + discountRate: 'Discount Rate', + paymentDiscount: 'Payment Discount', + discountAmount: 'Discount Amount', + paymentDeposit: 'Deposit', + remark: 'Remark', + status: 'Status', + }, + export: { + name: 'Export', + exportData: 'Purchase Order Data ', + noData: 'No available data export', + } + }, + storage:{ + title: 'Purchase Storage List', + addStorage: 'Add - Purchase Storage', + editStorage: 'Edit - Purchase Storage', + detail: 'Purchase Storage - Detail', + receipt: 'Receipt Detail', + table:{ + supplier: 'Supplier', + receiptNumber: 'Receipt number', + productInformation: 'Product information', + productQuantity: 'Product quantity', + totalAmount: 'Total amount', + totalIncludingTax: 'Total including tax', + paymentAmount: 'Payment amount', + thisTimePaymentAmount: 'This time payment', + thisTimeArrearsAmount: 'This time arrears', + receiptDate: 'Receipt date', + operator: 'Operator', + status: 'Status', + }, + header:{ + startDate: 'Start Date', + endDate: 'End Date', + receiptRemark: 'receipt remark', + }, + form: { + supplier: 'Supplier', + inputSupplier: 'Please select supplier', + addSupplier: 'Add supplier', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + relatedOrder: 'Purchase Order', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select purchase products', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + discountRate: 'Discount Rate', + paymentDiscount: 'Payment Discount', + discountAmount: 'Discount Amount', + settlementAccount: 'Payment Account', + paymentDeposit: 'Deposit', + otherFees: 'Other Fees', + thisTimePaymentAmount: 'This time payment', + thisTimeArrearsAmount: 'This time arrears', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Are you sure you want to delete the selected data?', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'The barcode cannot find product info', + noticeFive: 'The product barcode cannot be empty', + noticeSix: 'Enter the barcode product information automatically!', + noticeSeven: 'Please select at least two accounts', + noticeEight: 'Please enter the amount', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + warehouse: 'Warehouse', + inputWarehouse: 'Please select warehouse', + barCode: 'Barcode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + model: 'Model', + color: 'Color', + stock: 'Stock', + unit: 'Unit', + unitPrice: 'Unit Price', + quantity: 'Quantity', + amount: 'Amount', + taxRate: 'Tax Rate(%)', + taxAmount: 'Tax Amount', + remark: 'Remark', + totalIncludingTax: 'Total Price And Tax', + total: 'Total', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + } + }, + view: { + title: 'Purchase Storage Data', + supplier: 'Supplier', + receiptDate: 'Receipt date', + receiptAmount: 'Receipt amount', + settlementAccount: 'Payment Account', + inputSettlementAccount: 'Please select account', + addSettlementAccount: 'Add account', + discountRate: 'Discount Rate', + paymentDiscount: 'Payment Discount', + discountAmount: 'Discount Amount', + paymentDeposit: 'Deposit', + remark: 'Remark', + status: 'Status', + purchaseOrder: 'Purchase order receipt', + thisTimePaymentAmount: 'This time payment', + thisTimeArrearsAmount: 'This time arrears', + otherFees: 'Other Fees', + }, + export: { + name: 'Export', + exportData: 'Purchase Storage Data ', + noData: 'No available data export', + } + }, + refund:{ + title: 'Purchase Refund List', + addRefund: 'Add - Purchase Refund', + editRefund: 'Edit - Purchase Refund', + detail: 'Purchase Refund - Detail', + receipt: 'Receipt Detail', + table:{ + supplier: 'Supplier', + receiptNumber: 'Receipt number', + productInformation: 'Product information', + productQuantity: 'Product quantity', + totalAmount: 'Total amount', + totalIncludingTax: 'Total including tax', + refundAmount: 'Refund amount', + thisRefundAmount: 'This time refund', + thisArrearsAmount: 'This time arrears', + receiptDate: 'Receipt date', + operator: 'Operator', + status: 'Status', + }, + header:{ + startDate: 'Start Date', + endDate: 'End Date', + receiptRemark: 'receipt remark', + }, + form: { + supplier: 'Supplier', + inputSupplier: 'Please select supplier', + addSupplier: 'Add supplier', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + relatedStorage: 'Storage receipt', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select returned products', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + discountRate: 'Discount Rate', + refundDiscount: 'Refund Discount', + discountAmount: 'Discount Amount', + settlementAccount: 'Return Account', + otherFees: 'Other Fees', + thisRefundAmount: 'This time refund', + thisTimeArrearsAmount: 'This time arrears', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Are you sure you want to delete the selected data?', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'The barcode cannot find product info', + noticeFive: 'The product barcode cannot be empty', + noticeSix: 'Enter the barcode product information automatically!', + noticeSeven: 'Please select at least two accounts', + noticeEight: 'Please enter the amount', + noticeNine: 'Insufficient inventory of goods, please check the inventory quantity', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + warehouse: 'Warehouse', + inputWarehouse: 'Please select warehouse', + barCode: 'Barcode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + model: 'Model', + color: 'Color', + stock: 'Stock', + unit: 'Unit', + unitPrice: 'Unit Price', + quantity: 'Quantity', + amount: 'Amount', + taxRate: 'Tax Rate(%)', + taxAmount: 'Tax Amount', + remark: 'Remark', + totalIncludingTax: 'Total Price And Tax', + total: 'Total', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + } + }, + view: { + title: 'Purchase Refund Data', + supplier: 'Supplier', + receiptDate: 'Receipt date', + receiptAmount: 'Receipt amount', + purchaseOrder: 'Purchase storage receipt', + settlementAccount: 'Return Account', + thisRefundAmount: 'This time refund', + thisTimeArrearsAmount: 'This time arrears', + inputSettlementAccount: 'Please select account', + addSettlementAccount: 'Add account', + discountRate: 'Discount Rate', + refundDiscount: 'Refund Discount', + discountAmount: 'Discount Amount', + otherFees: 'Other Fees', + remark: 'Remark', + status: 'Status', + }, + export: { + name: 'Export', + exportData: 'Purchase Refund Data ', + noData: 'No available data export', + } + } +}; \ No newline at end of file diff --git a/src/locales/lang/en/reports.ts b/src/locales/lang/en/reports.ts new file mode 100644 index 0000000..d028485 --- /dev/null +++ b/src/locales/lang/en/reports.ts @@ -0,0 +1,357 @@ +export default { + productStock: { + title: 'Product Stock Report', + export: 'Export', + regularPrint: 'Print', + data: 'Product Stock Data', + detail: 'product Stock Detail', + header: { + warehouse: 'Warehouse', + productInfo: 'Product Info', + productCategory: 'Product Category', + warehouseShelves: 'Warehouse Shelves', + }, + table: { + flow: 'Flow', + stockFlow: 'Stock Flow', + productBarcode: 'Product Barcode', + warehouse: 'Warehouse', + productName: 'Name', + productCategory: 'Category', + standard: 'Standard', + model: 'Model', + weight: 'Weight', + color: 'Color', + unit: 'Unit', + warehouseShelves: 'Shelves', + unitPrice: 'Unit Price', + initStock: 'Initial Stock', + currentStock: 'Current Stock', + stockAmount: 'Stock Amount', + total: 'Total', + notice: 'There is no data to export under the current query conditions', + } + }, + account: { + title: 'Account Statistics Report', + export: 'Export', + regularPrint: 'Print', + data: 'Account Statistics Data', + detail: 'Account Statistics Detail', + notice: 'There is no data to export under the current query conditions', + header: { + account: 'Account', + accountNumber: 'Account Number', + }, + table: { + flow: 'Flow', + accountFlow: 'Account Flow', + accountName: 'Account Name', + accountNumber: 'Account Number', + initialAmount: 'Initial Amount', + thisMonthAmount: 'This Month Amount', + currentAmount: 'Current Amount', + total: 'Total', + } + }, + retail: { + title: 'Retail Statistics Report', + export: 'Export', + regularPrint: 'Print', + data: 'Retail Statistics Data', + detail: 'Retail Statistics Detail', + notice: 'There is no data to export under the current query conditions', + header: { + productInfo: 'Product Info', + receiptDate: 'Receipt Date', + startDate: 'Start Date', + endDate: 'End Date', + member: 'Member', + }, + table: { + barCode: 'BarCode', + warehouse: 'Warehouse', + name: 'Name', + standard: 'Standard', + model: 'Model', + extendInfo: 'Extend Info', + unit: 'Unit', + quantity: 'Quantity', + amount: 'Amount', + refundQuantity: 'Refund Quantity', + refundAmount: 'Refund Amount', + actualAmount: 'Actual Amount', + total: 'Total', + } + }, + purchase: { + title: 'Purchase Statistics Report', + export: 'Export', + regularPrint: 'Print', + data: 'Purchase Statistics Data', + detail: 'Purchase Statistics Detail', + notice: 'There is no data to export under the current query conditions', + header: { + productInfo: 'Product Info', + receiptDate: 'Receipt Date', + startDate: 'Start Date', + endDate: 'End Date', + supplier: 'Supplier', + warehouse: 'Warehouse' + }, + table: { + barCode: 'BarCode', + warehouse: 'Warehouse', + name: 'Name', + standard: 'Standard', + model: 'Model', + extendInfo: 'Extend Info', + unit: 'Unit', + quantity: 'Quantity', + amount: 'Amount', + refundQuantity: 'Refund Quantity', + refundAmount: 'Refund Amount', + actualAmount: 'Actual Amount', + purchaseDate: 'Purchase Date', + total: 'Total', + } + }, + sales: { + title: 'Sales Statistics Report', + export: 'Export', + regularPrint: 'Print', + data: 'Sales Statistics Data', + detail: 'Sales Statistics Detail', + notice: 'There is no data to export under the current query conditions', + header: { + productInfo: 'Product Info', + receiptDate: 'Receipt Date', + startDate: 'Start Date', + endDate: 'End Date', + customer: 'Customer', + }, + table: { + barCode: 'BarCode', + warehouse: 'Warehouse', + name: 'Name', + standard: 'Standard', + model: 'Model', + extendInfo: 'Extend Info', + unit: 'Unit', + quantity: 'Quantity', + amount: 'Amount', + refundQuantity: 'Refund Quantity', + refundAmount: 'Refund Amount', + actualAmount: 'Actual Amount', + total: 'Total', + } + }, + shipmentsDetail: { + title: 'Shipments Detail Report', + export: 'Export', + regularPrint: 'Print', + data: 'Shipments Detail Data', + detail: 'Shipments Detail', + notice: 'There is no data to export under the current query conditions', + header: { + receiptNumber: 'Receipt Number', + productInfo: 'Product Info', + receiptDate: 'Receipt Date', + startDate: 'Start Date', + endDate: 'End Date', + contact: 'Contact', + warehouse: 'Warehouse', + operator: 'Operator', + remark: 'Remark', + }, + table: { + receiptNumber: 'Receipt Number', + type: 'Type', + contact: 'Contact', + barCode: 'BarCode', + warehouse: 'Warehouse', + name: 'Name', + standard: 'Standard', + model: 'Model', + unit: 'Unit', + quantity: 'Quantity', + unitPrice: 'Unit price', + amount: 'Amount', + taxRate: 'Tax rate(%)', + taxAmount: 'Tax amount', + shipmentsDate: 'Shipments Date', + total: 'Total', + } + }, + storageDetail: { + title: 'Storage Detail Report', + export: 'Export', + regularPrint: 'Print', + data: 'Storage Detail Date', + detail: 'Storage Detail', + notice: 'There is no data to export under the current query conditions', + header: { + receiptNumber: 'Receipt Number', + productInfo: 'Product Info', + receiptDate: 'Receipt Date', + startDate: 'Start Date', + endDate: 'End Date', + contact: 'Contact', + warehouse: 'Warehouse', + operator: 'Operator', + remark: 'Remark', + }, + table: { + receiptNumber: 'Receipt Number', + type: 'Type', + contact: 'Contact', + barCode: 'BarCode', + warehouse: 'Warehouse', + name: 'Name', + standard: 'Standard', + model: 'Model', + unit: 'Unit', + quantity: 'Quantity', + unitPrice: 'Unit price', + amount: 'Amount', + taxRate: 'Tax rate(%)', + taxAmount: 'Tax amount', + storageDate: 'Storage Date', + total: 'Total', + } + }, + shipmentsSummary: { + title: 'Shipments Summary Report', + export: 'Export', + regularPrint: 'Print', + data: 'Shipments Summary Data', + detail: 'Shipments Summary Detail', + notice: 'There is no data to export under the current query conditions', + header: { + productInfo: 'Product Info', + receiptDate: 'Receipt Date', + startDate: 'Start Date', + endDate: 'End Date', + contact: 'Contact', + warehouse: 'Warehouse', + }, + table: { + barCode: 'BarCode', + warehouse: 'Warehouse', + name: 'Product Name', + category: 'Product Category', + standard: 'Standard', + model: 'Model', + unit: 'Unit', + quantity: 'Quantity', + amount: 'Amount', + shipmentsDate: 'Shipments Date', + total: 'Total', + } + }, + storageSummary: { + title: 'Storage Summary Report', + export: 'Export', + regularPrint: 'Print', + data: 'Storage Summary Data', + detail: 'Storage Summary Detail', + notice: 'There is no data to export under the current query conditions', + header: { + productInfo: 'Product Info', + receiptDate: 'Receipt Date', + startDate: 'Start Date', + endDate: 'End Date', + contact: 'Contact', + warehouse: 'Warehouse', + }, + table: { + barCode: 'BarCode', + warehouse: 'Warehouse', + name: 'Product Name', + category: 'Product Category', + standard: 'Standard', + model: 'Model', + unit: 'Unit', + quantity: 'Quantity', + amount: 'Amount', + storageDate: 'Storage Date', + total: 'Total', + } + }, + customerBill: { + title: 'Customer Bill Report', + export: 'Export', + regularPrint: 'Print', + data: 'Customer Bill Data', + detail: 'Customer Bill', + notice: 'There is no data to export under the current query conditions', + header: { + customer: 'Customer', + billDate: 'Bill Date', + startDate: 'Start Date', + endDate: 'End Date', + }, + table: { + arrearsDetail: 'Arrears', + detail: 'Detail', + customer: 'Customer', + contacts: 'Contacts', + contactNumber: 'Phone', + email: 'Email', + firstQuarterCollection: 'First Collection', + secondQuarterCollection: 'Second Collection', + thirdQuarterCollection: 'Third Collection', + fourthQuarterCollection: 'Fourth Collection', + totalArrears: 'Total Arrears', + totalCollection: 'Total Collection', + receivableArrears: 'Receivable Arrears', + helpMessage: 'Receivable Arrears=4 quarters of receivable accounts + total arrears', + total: 'Total', + } + }, + supplierBill: { + title: 'Supplier Bill Report', + export: 'Export', + regularPrint: 'Print', + data: 'Supplier Bill Data', + detail: 'Supplier Bill', + notice: 'There is no data to export under the current query conditions', + header: { + supplier: 'Supplier', + billDate: 'Bill Date', + startDate: 'Start Date', + endDate: 'End Date', + }, + table: { + arrearsDetail: 'Arrears', + detail: 'Detail', + supplier: 'Supplier', + contacts: 'Contacts', + contactNumber: 'Phone', + email: 'Email', + firstQuarterPayment: 'First Payment', + secondQuarterPayment: 'Second Payment', + thirdQuarterPayment: 'Third Payment', + fourthQuarterPayment: 'Fourth Payment', + totalArrears: 'Total Arrears', + totalPayment: 'Total Payment', + payableArrears: 'Payable Arrears', + helpMessage: 'Payable Arrears=4 quarters of payable accounts + total arrears', + total: 'Total', + } + }, + other: { + viewAccountFlow: 'View Account Flow', + viewAccountFlowHelpMessage: 'The account flow statistics are from front to back, and the balance at the end is the final balance', + thisReceiptArrears: 'Receipt Arrears', + paidArrears: 'Paid Arrears', + receivedArrears: 'Received Arrears', + receivableArrears: 'Receivable Arrears', + balance: 'Balance', + subType: 'Recipient / Payer', + customerArrearsDetail: 'Customer Arrears Detail', + customerArrearsData: 'Customer Arrears Data', + viewProductStockFlow: 'View Product Stock Flow', + stockFlowDetailData: 'Stock Flow Detail Data', + } +} \ No newline at end of file diff --git a/src/locales/lang/en/retail.ts b/src/locales/lang/en/retail.ts new file mode 100644 index 0000000..7d34d98 --- /dev/null +++ b/src/locales/lang/en/retail.ts @@ -0,0 +1,185 @@ +export default { + selectData: 'Please select a piece of data', + modifyDataPrompt: 'Sorry, only unapproved documents can be edited!', + regularPrint: 'Print', + shipments:{ + title: 'Retail Shipments List', + addShipments: 'Add - Retail Shipments', + editShipments: 'Edit - Retail Shipments', + detail: 'Retail Shipments - Detail', + receipt: 'Retail Shipments Detail', + table:{ + member: 'Member', + receiptNumber: 'Receipt number', + productInformation: 'Product information', + productQuantity: 'Product quantity', + totalAmount: 'Total amount', + amountCollection: 'Amount collection', + changeAmount: 'Change amount', + receiptDate: 'Receipt date', + operator: 'operator', + status: 'status', + }, + header:{ + settlementAccount: 'Account', + startDate: 'Start date', + endDate: 'End date', + receiptRemark: 'receipt remark', + }, + export: { + name: 'Export', + exportData: 'Retail Shipments Data ', + noData: 'No available data export', + }, + form: { + member: 'Member', + inputMember: 'Please select member', + addMember: 'Add member', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter the receipt number', + collectionType: 'Collection type', + inputCollectionType: 'Please select collection type', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select retail products', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + inputBarCode: 'Please enter the product barcode', + noticeOne: 'Please select warehouse', + noticeTwo: 'Please enter barcode or select product', + noticeThree: 'Need to add products in product management', + noticeFour: 'Are you sure you want to delete the selected data?', + noticeFive: 'The file exceeds the 2MB size limit', + noticeSix: 'The barcode cannot find product info', + noticeSeven: 'Insufficient inventory of goods, please check the inventory quantity', + advancePayment: 'Advance payment', + cashPayment: 'Cash payment', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + warehouse: 'Warehouse', + inputWarehouse: 'Please select a warehouse', + barCode: 'Barcode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + model: 'Model', + color: 'Color', + stock: 'Stock', + unit: 'Unit', + quantity: 'Quantity', + unitPrice: 'Unit price', + amount: 'Amount', + total: 'Total', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + } + }, + view: { + member: 'Member', + receiptDate: 'Receipt date', + collectionType: 'Collection type', + receiptAmount: 'Amount', + collectionAmount: 'Collection', + changeAmount: 'Return', + collectionAccount: 'Account', + inputCollectionAccount: 'Please select collection account', + addAccount: 'Add account', + refundReceipt: 'Return receipt', + remark: 'Remark', + status: 'Status', + } + }, + refund:{ + title: 'Retail Return List', + addRefund: 'Add - Retail Return', + editRefund: 'Edit - Retail Return', + detail: 'Retail Return - Detail', + receipt: 'Retail Return Detail', + table:{ + member: 'Member', + receiptNumber: 'Receipt number', + productInformation: 'Product information', + totalAmount: 'Total amount', + paymentAmount: 'Payment amount', + changeAmount: 'Change amount', + receiptDate: 'Receipt date', + operator: 'operator', + status: 'status', + }, + header:{ + settlementAccount: 'Account', + startDate: 'Start date', + endDate: 'End date', + receiptRemark: 'receipt remark', + }, + export: { + name: 'Export', + exportData: 'Retail Return Data ', + noData: 'No available data export', + }, + form: { + member: 'Member', + inputMember: 'Please select member', + addMember: 'Add member', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + relatedReceipt: 'Related receipt', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select returned products', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + noticeOne: 'Please select warehouse', + noticeTwo: 'Please enter barcode or select product', + noticeThree: 'Need to add products in product management', + noticeFour: 'Are you sure you want to delete the selected data?', + noticeFive: 'The file exceeds the 2MB size limit', + noticeSix: 'The barcode cannot find product info', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + warehouse: 'Warehouse', + inputWarehouse: 'Please select a warehouse', + barCode: 'Barcode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + model: 'Model', + color: 'Color', + stock: 'Stock', + unit: 'Unit', + quantity: 'Quantity', + unitPrice: 'Unit price', + amount: 'Amount', + total: 'Total', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + } + }, + view: { + member: 'Member', + receiptDate: 'Receipt date', + receiptAmount: 'Amount', + paymentAmount: 'Payment', + changeAmount: 'Return', + paymentAccount: 'Account', + inputPaymentAccount: 'please select payment account', + relatedReceipt: 'Related receipt', + addAccount: 'Add account', + remark: 'Remark', + status: 'Status', + } + } +}; \ No newline at end of file diff --git a/src/locales/lang/en/routes/basic.ts b/src/locales/lang/en/routes/basic.ts new file mode 100644 index 0000000..b6faa00 --- /dev/null +++ b/src/locales/lang/en/routes/basic.ts @@ -0,0 +1,4 @@ +export default { + login: 'Login', + errorLogList: 'Error Log', +}; diff --git a/src/locales/lang/en/routes/dashboard.ts b/src/locales/lang/en/routes/dashboard.ts new file mode 100644 index 0000000..6d047b5 --- /dev/null +++ b/src/locales/lang/en/routes/dashboard.ts @@ -0,0 +1,6 @@ +export default { + dashboard: 'Dashboard', + about: 'About', + workbench: 'Workbench', + analysis: 'Analysis', +}; diff --git a/src/locales/lang/en/routes/demo.ts b/src/locales/lang/en/routes/demo.ts new file mode 100644 index 0000000..1cc82d0 --- /dev/null +++ b/src/locales/lang/en/routes/demo.ts @@ -0,0 +1,199 @@ +export default { + charts: { + baiduMap: 'Baidu map', + aMap: 'A map', + googleMap: 'Google map', + charts: 'Chart', + map: 'Map', + line: 'Line', + pie: 'Pie', + }, + comp: { + comp: 'Component', + basic: 'Basic', + transition: 'Animation', + countTo: 'Count To', + + scroll: 'Scroll', + scrollBasic: 'Basic', + scrollAction: 'Scroll Function', + virtualScroll: 'Virtual Scroll', + + tree: 'Tree', + + treeBasic: 'Basic', + editTree: 'Searchable/toolbar', + actionTree: 'Function operation', + + modal: 'Modal', + drawer: 'Drawer', + desc: 'Desc', + + verify: 'Verify', + verifyDrag: 'Drag ', + verifyRotate: 'Picture Restore', + + qrcode: 'QR code', + strength: 'Password strength', + upload: 'Upload', + + loading: 'Loading', + + time: 'Relative Time', + cropperImage: 'Cropper Image', + cardList: 'Card List', + }, + editor: { + editor: 'Editor', + jsonEditor: 'Json editor', + markdown: 'Markdown editor', + + tinymce: 'Rich text', + tinymceBasic: 'Basic', + tinymceForm: 'embedded form', + }, + excel: { + excel: 'Excel', + customExport: 'Select export format', + jsonExport: 'JSON data export', + arrayExport: 'Array data export', + importExcel: 'Import', + }, + feat: { + feat: 'Page Function', + icon: 'Icon', + tabs: 'Tabs', + tabDetail: 'Tab Detail', + sessionTimeout: 'Session Timeout', + print: 'Print', + contextMenu: 'Context Menu', + download: 'Download', + clickOutSide: 'ClickOutSide', + imgPreview: 'Picture Preview', + copy: 'Clipboard', + msg: 'Message prompt', + watermark: 'Watermark', + ripple: 'Ripple', + fullScreen: 'Full Screen', + errorLog: 'Error Log', + tab: 'Tab with parameters', + tab1: 'Tab with parameter 1', + tab2: 'Tab with parameter 2', + menu: 'Menu with parameters', + menu1: 'Menu with parameters 1', + menu2: 'Menu with parameters 2', + + ws: 'Websocket test', + + breadcrumb: 'Breadcrumbs', + breadcrumbFlat: 'Flat Mode', + breadcrumbFlatDetail: 'Flat mode details', + requestDemo: 'Retry request demo', + + breadcrumbChildren: 'Level mode', + breadcrumbChildrenDetail: 'Level mode detail', + }, + flow: { + name: 'Graphics editor', + flowChart: 'FlowChart', + }, + form: { + form: 'Form', + basic: 'Basic', + useForm: 'useForm', + refForm: 'RefForm', + advancedForm: 'Shrinkable', + ruleForm: 'Form validation', + dynamicForm: 'Dynamic', + customerForm: 'Custom', + appendForm: 'Append', + tabsForm: 'TabsForm', + }, + iframe: { + frame: 'External', + antv: 'antVue doc (embedded)', + doc: 'Project doc (embedded)', + docExternal: 'Project doc (external)', + }, + level: { level: 'MultiMenu' }, + page: { + page: 'Page', + + form: 'Form', + formBasic: 'Basic Form', + formStep: 'Step Form', + formHigh: 'Advanced Form', + + desc: 'Details', + descBasic: 'Basic Details', + descHigh: 'Advanced Details', + + result: 'Result', + resultSuccess: 'Success', + resultFail: 'Failed', + + account: 'Personal', + accountCenter: 'Personal Center', + accountSetting: 'Personal Settings', + + exception: 'Exception', + netWorkError: 'Network Error', + notData: 'No data', + + list: 'List page', + listCard: 'Card list', + basic: 'Basic list', + listBasic: 'Basic list', + listSearch: 'Search list', + }, + permission: { + permission: 'Permission', + + front: 'front-end', + frontPage: 'Page', + frontBtn: 'Button', + frontTestA: 'Test page A', + frontTestB: 'Test page B', + + back: 'background', + backPage: 'Page', + backBtn: 'Button', + }, + setup: { + page: 'Intro page', + }, + system: { + moduleName: 'System management', + + account: 'Account management', + account_detail: 'Account detail', + password: 'Change password', + + dept: 'Department management', + + menu: 'Menu management', + role: 'Role management', + }, + table: { + table: 'Table', + + basic: 'Basic', + treeTable: 'Tree', + fetchTable: 'Remote loading', + fixedColumn: 'Fixed column', + customerCell: 'Custom column', + formTable: 'Open search', + useTable: 'UseTable', + refTable: 'RefTable', + multipleHeader: 'MultiLevel header', + mergeHeader: 'Merge cells', + expandTable: 'Expandable table', + fixedHeight: 'Fixed height', + footerTable: 'Footer', + editCellTable: 'Editable cell', + editRowTable: 'Editable row', + authColumn: 'Auth column', + resizeParentHeightTable: 'resizeParentHeightTable', + vxeTable: 'VxeTable', + }, +}; diff --git a/src/locales/lang/en/sales.ts b/src/locales/lang/en/sales.ts new file mode 100644 index 0000000..e435033 --- /dev/null +++ b/src/locales/lang/en/sales.ts @@ -0,0 +1,318 @@ +export default { + selectData: 'Please select a piece of data', + modifyDataPrompt: 'Sorry, only unapproved documents can be edited!', + partialSales: 'Partial Sales', + completeSales: 'Complete Sales', + regularPrint: 'Print', + order:{ + title: 'Sales Order List', + addOrder: 'Add - Sales Order', + editOrder: 'Edit - Sales Order', + detail: 'Sales Order - Detail', + receipt: 'Receipt Detail', + table:{ + customer: 'Customer', + receiptNumber: 'Receipt number', + productInformation: 'Product information', + productQuantity: 'Product quantity', + totalAmount: 'Total amount', + totalIncludingTax: 'Total including tax', + collectDeposit: 'Collect Deposit', + receiptDate: 'Receipt date', + operator: 'operator', + status: 'status', + }, + header:{ + startDate: 'Start date', + endDate: 'End date', + receiptRemark: 'receipt remark', + }, + form: { + customer: 'Customer', + inputCustomer: 'Please select customer', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter the receipt number', + salesPerson: 'Sales Person', + inputSalesPerson: 'Please select sales person', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select sales products', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Are you sure you want to delete the selected data?', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'The barcode cannot find product info', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + warehouse: 'Warehouse', + barCode: 'Barcode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + model: 'Model', + color: 'Color', + stock: 'Stock', + unit: 'Unit', + quantity: 'Quantity', + unitPrice: 'Unit Price', + amount: 'Amount', + taxRate: 'Tax Rate(%)', + taxAmount: 'Tax Amount', + totalPriceAndTax: 'Total Price And Tax', + total: 'Total', + discount: 'Discount Rate', + collectionDiscount: 'Collect Discount', + discountAmount: 'Discount Amount', + account: 'Collect Account', + inputAccount: 'Please select settlement account', + deposit: 'Collect Deposit', + remark: 'Remark', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + } + }, + view: { + title: 'Sales Order Table Data', + customer: 'Customer', + receiptDate: 'Receipt date', + settlementAccount: 'Collect Account', + discountRate: 'Discount Rate', + collectionDiscount: 'Collect Discount', + discountAmount: 'Discount Amount', + collectionDeposit: 'Collect Deposit', + remark: 'Remark', + status: 'Status', + }, + export: { + name: 'Export', + exportData: 'Sales Order Data ', + noData: 'No available data export', + } + }, + shipments:{ + title: 'Sales Shipments List', + addShipments: 'Add - Sales Shipments', + editShipments: 'Edit - Sales Shipments', + detail: 'Sales Shipments - Detail', + receipt: 'Receipt Detail', + table:{ + customer: 'Customer', + receiptNumber: 'Receipt number', + productInformation: 'Product information', + productQuantity: 'Product quantity', + totalAmount: 'Total amount', + totalIncludingTax: 'Total including tax', + collectAmount: 'Collect amount', + thisTimeCollectAmount: 'This Time collect amount', + thisTimeArrearsAmount: 'This Time arrears amount', + receiptDate: 'Receipt date', + operator: 'operator', + status: 'status', + }, + header:{ + startDate: 'Start date', + endDate: 'End date', + receiptRemark: 'receipt remark', + }, + form: { + customer: 'Customer', + inputCustomer: 'Please select customer', + addCustomer: 'Add customer', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + relatedOrder: 'Related Order', + inputRelatedOrder: 'Please select related order', + inputSettlementAccount: 'Please select settlement account', + addSettlementAccount: 'Add settlement account', + inputSalesPerson: 'Please select sales person', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select sales products', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Are you sure you want to delete the selected data?', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'The barcode cannot find product info', + noticeFive: 'Please select at least two refund accounts', + noticeSix: 'Please enter refund amount', + noticeSeven: 'Please enter the amount of this collection', + noticeEight: 'Please select warehouse', + noticeNine: 'Insufficient inventory of goods, please check the inventory quantity', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + warehouse: 'Warehouse', + barCode: 'Barcode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + model: 'Model', + color: 'Color', + stock: 'Stock', + unit: 'Unit', + quantity: 'Quantity', + unitPrice: 'Unit Price', + amount: 'Amount', + taxRate: 'Tax Rate(%)', + taxAmount: 'Tax Amount', + totalPriceAndTax: 'Total Price And Tax', + total: 'Total', + discount: 'Discount Rate', + collectionDiscount: 'Collection Discount', + discountAmount: 'Discount Amount', + account: 'Collect Account', + inputAccount: 'Please select settlement account', + deposit: 'Collect Deposit', + remark: 'Remark', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + } + }, + view: { + title: 'Sales Shipments Table Data', + customer: 'Customer', + receiptDate: 'Receipt date', + salesOrder: 'Sales Order', + settlementAccount: 'Collect Discount', + discountRate: 'Discount Rate', + collectionDiscount: 'Collect Discount', + receiptAmount: 'Receipt Amount', + discountAmount: 'Discount Amount', + otherFees: 'Other Fees', + salesPerson: 'Sales Person', + thisTimeCollectAmount: 'This Time Collect', + thisTimeArrearsAmount: 'This Time Arrears', + remark: 'Remark', + status: 'Status', + }, + export: { + name: 'Export', + exportData: 'Sales Shipments Data ', + noData: 'No available data export', + } + }, + refund:{ + title: 'Sales Return List', + addRefund: 'Add - Sales Return', + editRefund: 'Edit - Sales Return', + detail: 'Sales Return - Detail', + receipt: 'Receipt Detail', + table:{ + customer: 'Customer', + receiptNumber: 'Receipt number', + productInformation: 'Product information', + productQuantity: 'Product quantity', + totalAmount: 'Total amount', + totalIncludingTax: 'Total including tax', + refundAmount: 'Refund Amount', + thisTimeRefundAmount: 'This Time refund amount', + thisTimeArrearsAmount: 'This Time arrears amount', + receiptDate: 'Receipt date', + operator: 'operator', + status: 'status', + }, + header:{ + startDate: 'Start date', + endDate: 'End date', + receiptRemark: 'receipt remark', + }, + form: { + customer: 'Customer', + inputCustomer: 'Please select customer', + addCustomer: 'Add customer', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + relatedShipments: ' Shipments receipt', + inputRelatedShipments: 'Please select the associated receipt', + inputReturnAccount: 'Please select refund account', + addSettlementAccount: 'Add Settlement account', + inputSalesPerson: 'Please select sales person', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select returned products', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Are you sure you want to delete the selected data?', + noticeThree: 'The file exceeds the 2MB size limit', + noticeFour: 'The barcode cannot find product info', + noticeFive: 'Please select at least two refund accounts', + noticeSix: 'Please enter refund amount', + noticeSeven: 'Please enter the amount of this collection', + noticeEight: 'Please select warehouse', + noticeNine: 'Insufficient inventory of goods, please check the inventory quantity', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + warehouse: 'Warehouse', + barCode: 'Barcode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + model: 'Model', + color: 'Color', + stock: 'Stock', + unit: 'Unit', + quantity: 'Quantity', + unitPrice: 'Unit Price', + amount: 'Amount', + taxRate: 'Tax Rate(%)', + taxAmount: 'Tax Amount', + totalPriceAndTax: 'Total Price And Tax', + total: 'Total', + discount: 'Discount Rate', + collectionDiscount: 'Collection Discount', + discountAmount: 'Discount Amount', + account: 'Return Account', + inputAccount: 'Please select settlement account', + deposit: 'Deposit', + remark: 'Remark', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + returnDiscount: 'Return discount', + returnAccount: 'Return account', + } + }, + view: { + title: 'Sales Return Table Data', + customer: 'Customer', + receiptDate: 'Receipt date', + salesShipmentsReceipt: 'Sales shipments receipt', + returnAccount: 'return account', + discountRate: 'Discount rate', + returnDiscount: 'Return discount', + receiptAmount: 'Receipt amount', + discountAmount: 'Discount amount', + otherFees: 'Other Fees', + salesPerson: 'Sales Person', + thisTimeReturnAmount: 'This Time return', + thisTimeArrearsAmount: 'This Time arrears', + remark: 'Remark', + status: 'Status', + }, + export: { + name: 'Export', + exportData: 'Sales Return Data', + noData: 'No available data export', + } + } +}; \ No newline at end of file diff --git a/src/locales/lang/en/sys.ts b/src/locales/lang/en/sys.ts new file mode 100644 index 0000000..01e17df --- /dev/null +++ b/src/locales/lang/en/sys.ts @@ -0,0 +1,181 @@ +export default { + api: { + operationSuccess: 'Operation Success', + operationFailed: 'Operation failed', + errorTip: 'Error Tip', + successTip: 'Success Tip', + errorMessage: 'The operation failed, the system is abnormal!', + timeoutMessage: 'Login timed out, please log in again!', + apiTimeoutMessage: 'The interface request timed out, please refresh the page and try again!', + apiRequestFailed: 'The interface request failed, please try again later!', + networkException: 'network anomaly', + networkExceptionMsg: + 'Please check if your network connection is normal! The network is abnormal', + refreshBrowser: 'The network is busy now, please press F5 to refresh your browser', + + errMsg401: 'The user does not have permission (token, user name, password error)!', + errMsg403: 'The user is authorized, but access is forbidden!', + errMsg404: 'Network request error, the resource was not found!', + errMsg405: 'Network request error, request method not allowed!', + errMsg408: 'Network request timed out!', + errMsg500: 'Server error, please contact the administrator!', + errMsg501: 'The network is not implemented!', + errMsg502: 'Network Error!', + errMsg503: 'The service is unavailable, the server is temporarily overloaded or maintained!', + errMsg504: 'Network timeout!', + errMsg505: 'The http version does not support the request!', + }, + app: { + logoutTip: 'Reminder', + logoutMessage: 'Confirm to exit the system?', + menuLoading: 'Menu loading...', + }, + errorLog: { + tableTitle: 'Error log list', + tableColumnType: 'Type', + tableColumnDate: 'Time', + tableColumnFile: 'File', + tableColumnMsg: 'Error message', + tableColumnStackMsg: 'Stack info', + + tableActionDesc: 'Details', + + modalTitle: 'Error details', + + fireVueError: 'Fire vue error', + fireResourceError: 'Fire resource error', + fireAjaxError: 'Fire ajax error', + + enableMessage: 'Only effective when useErrorHandle=true in `/src/settings/projectSetting.ts`.', + }, + exception: { + backLogin: 'Back Login', + backHome: 'Back Home', + subTitle403: "Sorry, you don't have access to this page.", + subTitle404: 'Sorry, the page you visited does not exist.', + subTitle500: 'Sorry, the server is reporting an error.', + noDataTitle: 'No data on the current page.', + networkErrorTitle: 'Network Error', + networkErrorSubTitle: + 'Sorry,Your network connection has been disconnected, please check your network!', + }, + lock: { + unlock: 'Click to unlock', + alert: 'Lock screen password error', + backToLogin: 'Back to login', + entry: 'Enter the system', + placeholder: 'Please enter the lock screen password or user password', + }, + login: { + captcha: 'Verification code', + backSignIn: 'Back sign in', + mobileSignInFormTitle: 'Mobile sign in', + qrSignInFormTitle: 'Qr sign in', + emailFormTitle: 'Email sign in', + signInFormTitle: 'Sign in', + signUpFormTitle: 'Sign up', + forgetFormTitle: 'Reset password', + + signInTitle: 'Provide next-generation intelligent ERP system software for enterprises', + signInDesc: '© 2023-2033 Wan Sen ERP - All Right Reserved', + policy: 'I agree, to the WanSer ERP System Privacy Policy', + scanSign: `scanning the code to complete the login`, + + loginButton: 'Sign in', + registerButton: 'Sign up', + rememberMe: 'Remember me', + forgetPassword: 'Forget Password?', + otherSignIn: 'Sign in with', + + // notify + loginSuccessTitle: 'Login successful', + loginSuccessDesc: 'Welcome back', + + // placeholder + accountPlaceholder: 'Please input username', + passwordPlaceholder: 'Please input password', + captchaPlaceholder: 'Please input verification code', + correctMobilePlaceholder: 'Please enter the correct phone number', + correctEmailPlaceholder: 'Please enter the correct email address', + smsPlaceholder: 'Please input sms code', + mobilePlaceholder: 'Please input mobile', + emailPlaceholder: 'Please input email', + policyPlaceholder: 'Register after checking', + diffPwd: 'The two passwords are inconsistent', + + userName: 'Username', + password: 'Password', + confirmPassword: 'Confirm Password', + newPassword: 'New Password', + updatePassword: 'Change Password', + email: 'Email', + emailCode: 'Email code', + smsCode: 'SMS code', + mobile: 'Mobile', + }, + user: { + userList: 'User Table', + name: 'Nick Name', + status: 'Status', + roleName: 'Role Name', + department: 'Department', + remake: 'Remark', + addAccount: 'Add Account', + editAccount: 'Edit Account', + notAllowAddUser: 'The current tenant has reached the maximum number of users that can be added', + // user table list action + viewUserDetails: 'View User Details', + editUserProfile: 'Edit User Profile', + resetUserPassword: 'Reset User Password', + confirmPasswordReset: 'Are you sure to reset the password to 123456', + deleteUserAccount: 'Delete User Account' + }, + tenant: { + tenantList: 'Tenant List', + addTenant: 'Add Tenant', + editTenant: 'Edit Tenant', + deleteTenant: 'Delete Tenant', + form: { + name: 'Tenant Name', + status: 'Status', + free: 'Free Tenant', + pay: 'Pay Tenant', + type: 'Type', + remark: 'Remark', + userNumLimit: 'User Number Limit', + expireTime: 'Expire Time', + noticeOne: 'Please default to select the tenant administrator role', + noticeTwo: 'If not filled in, the default password is 123456', + noticeThree: 'Cannot enter a username with admin', + noticeFour: 'After expiration, all users under the tenant are unable to login and use the system', + } + }, + table: { + add: 'Add Data', + edit: 'Edit Data', + delete: 'Delete Data', + batchDelete: 'Batch Delete Data', + exportData: 'Export Data', + approve: 'Receipt Approval', + reject: 'Receipt Rejection', + audited: 'Audited', + unaudited: 'Unaudited', + viewReceiptDetails: 'View Receipt Detail', + confirmDelete: 'Are you sure to delete this data?', + confirmExport: 'Confirm Export', + confirmExportTextOne: 'Export', + confirmExportTextTwo: 'Data loading, please be patient', + confirmExportTextThree: 'If you need to export detailed data (which may take a long time), please check the box below.', + confirmExportTextFour: 'Need to export detailed data', + type: 'Type', + subType: 'Sub Type', + }, + modal: { + cover: 'Yes', + cancel: 'No', + }, + language: { + enUS: 'English', + zhCN: '简体中文', + } +}; diff --git a/src/locales/lang/en/system.ts b/src/locales/lang/en/system.ts new file mode 100644 index 0000000..74e3c22 --- /dev/null +++ b/src/locales/lang/en/system.ts @@ -0,0 +1,129 @@ +export default { + selectData: 'Please select a piece of data', + modifyDataPrompt: 'Sorry, only unapproved documents can be edited!', + role: { + title: 'Role List', + addRole: 'Add Role', + editRole: 'Edit Role', + menuAllocation: 'Menu Allocation', + titleNotice: 'The role list can assign different permissions to characters by clicking the gear button in the operation bar', + header: { + roleName: 'Role Name', + status: 'Status', + viewAllData: 'View all data', + allData: 'All Data', + viewPersonalData: 'View personal data', + personalData: 'Personal Data', + blockPurchasePrice: 'Block purchase price', + blockSalesPrice: 'Block sales price', + blockRetailPrice: 'Block retail price', + enable: 'Enable', + disable: 'Disable', + }, + table: { + roleName: 'Role Name', + type: 'Type', + priceBlocking: 'Price Blocking', + status: 'Status', + remark: 'Remark', + createTime: 'Create Time', + action: 'Action', + }, + form: { + roleName: 'Role Name', + type: 'Type', + priceBlocking: 'Price Blocking', + status: 'Status', + remark: 'Remark', + } + }, + department: { + title: 'Department List', + addDepartment: 'Add department', + editDepartment: 'Edit department', + header: { + name: 'Department Name', + }, + table: { + name: 'Department Name', + number: 'Department Number', + manager: 'Department Manager', + status: 'Status', + createTime: 'Create Time', + remark: 'Remark', + action: 'Action', + }, + form: { + name: 'Name', + number: 'Number', + parent: 'Superior Department', + manager: 'Manager', + status: 'Status', + sort: 'Sort', + remark: 'Remark', + enable: 'Enable', + disable: 'Disable', + notice: 'If not filled in, it defaults to the parent department', + } + }, + menu: { + title: 'Menu List', + addMenu: 'Add Menu', + editMenu: 'Edit Menu', + table: { + menuTitle: 'Menu Title', + icon: 'Icon', + path: 'Path', + component: 'Component', + sort: 'Sort', + status: 'Status', + createTime: 'Create Time', + }, + form:{ + menuType: 'Menu type', + catalogue: 'Catalogue', + menu: 'Menu', + rootMenu: 'Root menu', + menuName: 'Menu name', + menuTitle: 'Menu title', + menuEnglishTitle: 'Menu english title', + parent: 'Parent menu', + sort: 'Sort', + icon: 'Icon', + routeAddress: 'Route address', + componentPath: 'Component', + status: 'Status', + enable: 'Enable', + disable: 'Disable', + isExternalLink: 'Is external link', + isCached: 'Is cached', + isDisplayed: 'Is displayed', + yes: 'Yes', + no: 'No', + notice: 'If not filled in, it defaults to the directory' + } + }, + configure: { + title: 'System Configuration', + tip: 'The main function of this page is to configure the current system.', + name: 'Company Name', + inputName: 'Please enter the company name', + contact: 'Contact', + inputContact: 'Please enter the contact', + address: 'Company Address', + inputAddress: 'Please enter the company address', + phone: 'Phone', + inputPhone: 'Please enter the phone', + fax: 'Fax', + inputFax: 'Please enter the fax', + postalCode: 'Postal Code', + inputPostalCode: 'Please enter the postal code', + salesProtocol: 'Sales Protocol', + inputSalesProtocol: 'Please enter the sales protocol', + noticeOne: 'After changing the company name, please refresh the browser to take effect', + noticeTwo: 'Optional', + submit: 'Submit', + updateSuccess: 'Update successful', + updateFailed: 'Update failed', + } +} \ No newline at end of file diff --git a/src/locales/lang/en/warehouse.ts b/src/locales/lang/en/warehouse.ts new file mode 100644 index 0000000..c159d27 --- /dev/null +++ b/src/locales/lang/en/warehouse.ts @@ -0,0 +1,395 @@ +export default { + selectData: 'Please select a piece of data', + modifyDataPrompt: 'Sorry, only unapproved documents can be edited!', + regularPrint: 'Regular print', + otherStorage: { + title: 'Other Storage List', + add: 'Add', + batchDelete: 'Batch Delete', + addOtherStorage: 'Add-Other Storage', + editOtherStorage: 'Edit-Other Storage', + detailOtherStorage: 'Other Storage-Detail', + detailReceipt: 'Other Storage Receipt - Details', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Star date', + endDate: 'End date', + supplierName: 'Supplier', + operator: 'Operator', + status: 'Status', + remark: 'Remark', + }, + table: { + supplierName: 'Supplier', + receiptNumber: 'Receipt number', + productInfo: 'Product info', + receiptDate: 'Receipt date', + productNumber: 'quantity', + totalAmount: 'Total amount', + operator: 'Operator', + status: 'Status', + operate: 'Operate', + }, + form: { + supplierName: 'Supplier', + inputSupplier: 'Please select a supplier', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter receipt number', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select to add product', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Please select a warehouse', + noticeThree: 'Warehouse cannot be empty', + noticeFour: 'Product barcode cannot be empty', + noticeFive: 'There is no amount information for other inbound/outbound items. If necessary, you can modify it yourself', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + warehouse: 'Warehouse', + inputWarehouse: 'Please select a warehouse', + barCode: 'Barcode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + stock: 'Stock', + unit: 'Unit', + quantity: 'Quantity', + unitPrice: 'Unit price', + amount: 'Amount', + remark: 'Remark', + total: 'Total', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + } + }, + view: { + warehouseName: 'Warehouse name', + barCode: 'Barcode', + productName: 'Product name', + productStandard: 'Product standard', + productModel: 'Product model', + productExtendInfo: 'Product extend info', + stock: 'Stock', + productUnit: 'Product unit', + productNumber: 'Quantity', + unitPrice: 'Unit price', + amount: 'Amount', + remark: 'Remark', + }, + export: { + name: 'Export', + exportData: 'Other Storage Data ', + noData: 'No available data export', + }, + }, + otherShipments: { + title: 'Other Shipments List', + add: 'Add', + batchDelete: 'Batch Delete', + addOtherShipments: 'Add-Other Shipments', + editOtherShipments: 'Edit-Other Shipments', + detailOtherShipments: 'Other Shipments-Detail', + detailReceipt: 'Other Storage Shipments - Details', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Star date', + endDate: 'End date', + customer: 'Customer', + operator: 'Operator', + status: 'Status', + remark: 'Remark', + }, + table: { + customer: 'Customer', + receiptNumber: 'Receipt number', + productInfo: 'Product info', + receiptDate: 'Receipt date', + productNumber: 'quantity', + totalAmount: 'Total amount', + operator: 'Operator', + status: 'Status', + operate: 'Operate', + }, + form: { + customer: 'Customer', + inputCustomer: 'Please select a customer', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter receipt number', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select to add product', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Please select a warehouse', + noticeThree: 'Warehouse cannot be empty', + noticeFour: 'Product barcode cannot be empty', + noticeFive: 'There is no amount information for other inbound/outbound items. If necessary, you can modify it yourself', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + }, + export: { + name: 'Export', + exportData: 'Other Shipments Data ', + noData: 'No available data export', + } + }, + allotShipments: { + title: 'Allot Shipments List', + add: 'Add', + batchDelete: 'Batch Delete', + addAllotShipments: 'Add-Allot Shipments', + editAllotShipments: 'Edit-Allot Shipments', + detailAllotShipments: 'Allot Shipments-Detail', + detailReceipt: 'Allot Shipments - Details', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Star date', + endDate: 'End date', + operator: 'Operator', + status: 'Status', + remark: 'Remark', + }, + table: { + receiptNumber: 'Receipt number', + productInfo: 'Product info', + receiptDate: 'Receipt date', + productNumber: 'quantity', + operator: 'Operator', + status: 'Status', + operate: 'Operate', + }, + form: { + outWarehouse: 'Transfer out warehouse', + inputOutWarehouse: 'Please select a transfer out warehouse', + inWarehouse: 'Transfer in warehouse', + inputInWarehouse: 'Please select a transfer in warehouse', + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter receipt number', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select to add product', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add a row of data', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Please select a warehouse', + noticeThree: 'The outbound warehouse cannot be empty', + noticeFour: 'The product barcode cannot be empty', + noticeFive: 'Transferred to warehouse cannot be empty', + noticeSex: 'Input barcode product information and automatically bring it out !', + total: 'Total', + inputRemark: 'Please enter remark', + inputSalePrice: 'Please enter price', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + outWarehouse: 'Transfer out warehouse', + barCode: 'BarCode', + inputBarCode: 'Please select the product barcode', + name: 'Name', + standard: 'Standard', + model: 'Model', + stock: 'Stock', + extendInfo: 'Extend info', + inWarehouse: 'Transfer in warehouse', + unit: 'Unit', + salePrice: 'Sale Price', + quantity: 'Quantity', + remark: 'Remark', + } + }, + export: { + name: 'Export', + exportData: 'Allot Shipments Data ', + noData: 'No available data export', + } + }, + assemble: { + title: 'Assemble Receipt List', + add: 'Add', + batchDelete: 'Batch delete', + addAssemble: 'Add - Assemble Receipt', + editAssemble: 'Edit - Assemble Receipt', + detailAssemble: 'Assemble Receipt - Detail', + assemblyComponents: 'Assemble components', + subComponents: 'Sub components', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Star date', + endDate: 'End date', + operator: 'Operator', + status: 'Status', + remark: 'Remark', + }, + table: { + receiptNumber: 'Receipt number', + productInfo: 'Product info', + receiptDate: 'Receipt date', + totalAmount: 'Total amount', + productNumber: 'quantity', + operator: 'Operator', + status: 'Status', + operate: 'Operate', + }, + form: { + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter receipt number', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select to add product', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add row of data', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Please select warehouse', + noticeThree: 'The outbound warehouse cannot be empty', + noticeFour: 'The product barcode cannot be empty', + noticeFive: 'Input barcode product information and automatically bring it out!', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + productType: 'Product type', + warehouse: 'Warehouse', + inputWarehouse: 'Please select warehouse', + barCode: 'BarCode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + stock: 'Stock', + unit: 'Unit', + quantity: 'Quantity', + purchasePrice: 'Purchase price', + amount: 'Amount', + remark: 'Remark', + total: 'Total', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + } + }, + view: { + productType: 'Product type', + warehouseName: 'Warehouse', + barCode: 'BarCode', + productName: 'Product name', + productStandard: 'Standard', + productModel: 'Model', + productExtendInfo: 'Extend info', + stock: 'Stock', + productUnit: 'Unit', + productNumber: 'Quantity', + purchasePrice: 'Purchase price', + amount: 'Amount', + remark: 'Remark', + }, + export: { + name: 'Export', + exportData: 'Assemble Receipt Data ', + noData: 'No available data export', + } + }, + disassemble: { + title: 'DisAssemble Receipt List', + add: 'Add', + batchDelete: 'Batch delete', + addDisassemble: 'Add - Disassemble Receipt', + editDisassemble: 'Edit - Disassemble Receipt', + detailDisassemble: 'Disassemble Receipt - Detail', + header: { + receiptNumber: 'Receipt number', + receiptDate: 'Receipt date', + starDate: 'Star date', + endDate: 'End date', + operator: 'Operator', + status: 'Status', + remark: 'Remark', + }, + table: { + receiptNumber: 'Receipt number', + productInfo: 'Product info', + receiptDate: 'Receipt date', + totalAmount: 'Total amount', + productNumber: 'quantity', + operator: 'Operator', + status: 'Status', + operate: 'Operate', + }, + form: { + receiptDate: 'Receipt date', + inputReceiptDate: 'Please select receipt date', + receiptNumber: 'Receipt number', + inputReceiptNumber: 'Please enter receipt number', + scanCodeData: 'Scan code to enter data', + collapseScanCode: 'Collapse scan code', + scanCodeTip: 'Click here with the mouse', + addProduct: 'Select to add product', + insertRow: 'Insert A Row', + deleteRow: 'Delete Selected Rows', + addRowData: 'Please add row of data', + noticeOne: 'Please enter barcode or select product', + noticeTwo: 'Please select warehouse', + noticeThree: 'The outbound warehouse cannot be empty', + noticeFour: 'The product barcode cannot be empty', + noticeFive: 'Input barcode product information and automatically bring it out!', + cancel: 'Cancel', + save: 'Save', + saveApprove: 'Save and Approve', + table: { + productType: 'Product type', + warehouse: 'Warehouse', + inputWarehouse: 'Please select warehouse', + barCode: 'BarCode', + inputBarCode: 'Please enter product barcode', + name: 'Name', + standard: 'Standard', + stock: 'Stock', + unit: 'Unit', + quantity: 'Quantity', + purchasePrice: 'Purchase price', + amount: 'Amount', + remark: 'Remark', + total: 'Total', + inputRemark: 'Please enter remark', + annex: 'Attachment', + uploadAnnex: 'Upload attachment', + } + }, + export: { + name: 'Export', + exportData: 'DisAssemble Receipt Data ', + noData: 'No available data export', + } + } +} \ No newline at end of file diff --git a/src/locales/lang/zh-CN/antdLocale/DatePicker.ts b/src/locales/lang/zh-CN/antdLocale/DatePicker.ts new file mode 100644 index 0000000..452dff0 --- /dev/null +++ b/src/locales/lang/zh-CN/antdLocale/DatePicker.ts @@ -0,0 +1,19 @@ +export default { + lang: { + shortWeekDays: ['一', '二', '三', '四', '五', '六', '日'], + shortMonths: [ + '1月', + '2月', + '3月', + '4月', + '5月', + '6月', + '7月', + '8月', + '9月', + '10月', + '11月', + '12月', + ], + }, +}; diff --git a/src/locales/lang/zh-CN/basic.ts b/src/locales/lang/zh-CN/basic.ts new file mode 100644 index 0000000..0d6fea8 --- /dev/null +++ b/src/locales/lang/zh-CN/basic.ts @@ -0,0 +1,370 @@ +export default { + selectData: '请选择一条数据', + modifyDataPrompt: '抱歉,只有未审核的单据才能编辑!', + supplier: { + title: '供应商列表', + addSupplier: '新增供应商', + editSupplier: '编辑供应商', + add: '新增', + batchDelete: '批量删除', + batchEnable: '批量启用', + batchDisable: '批量禁用', + Import: '导入', + Export: '导出', + header: { + name: '供应商名称', + contactPhone: '联系电话', + createTime: '创建时间', + startDate: '开始日期', + endDate: '结束日期', + }, + table: { + name: '供应商名称', + contact: '联系人', + phoneNumber: '手机号', + contactPhone: '联系电话', + email: '电子邮箱', + status: '状态', + accumulatedAccountsPayable: '累计应付款', + rate: '税率(%)', + sort: '排序', + createTime: '创建时间', + }, + form: { + name: '名称', + contact: '联系人', + phoneNumber: '手机号', + contactPhone: '联系电话', + email: '电子邮箱', + fax: '传真', + address: '地址', + remark: '备注', + accountsPayableInfo: '应付账款信息', + firstQuarterPayment: '一季度付款', + secondQuarterPayment: '二季度付款', + thirdQuarterPayment: '三季度付款', + fourthQuarterPayment: '四季度付款', + accountInfo: '账户信息', + taxNumber: '纳税人识别号', + rate: '税率(%)', + bankName: '开户行', + bankAccount: '银行账号', + notice: '供应商的名字, 或者个人', + noticeTwo: '座机号码 (010/021之类)', + }, + export: { + name: '导出', + exportData: '供应商数据 ', + noData: '无可用数据导出', + templateDownload: '供应商Excel模板[下载]', + import: '供应商导入', + data: '供应商数据' + } + }, + account: { + basicSetting: '基本设置', + name: '昵称', + position: '职位', + personalProfile: '个人简介', + systemLanguage: '系统语言', + systemLanguageTip: '此设置可修改左侧菜单中英文语言', + avatar: '更换头像', + avatarTip: '头像(更新头像后,请刷新浏览器)', + safeSetting: '安全设置', + accountPassword: '账户密码', + accountPasswordTip: '账户密码(当前密码强度:中)', + accountPhone: '密保手机', + accountPhoneTip: '已绑定手机:', + accountEmail: '密保邮箱', + accountEmailTip: '已绑定邮箱:', + updateInfo: '更新基本信息', + noticeOne: '用户资料修改失败', + noticeTwo: '未绑定', + update: '修改', + password: { + title: '更换账户密码', + oldPassword: '原密码', + inputOldPassword: '请输入原密码', + newPassword: '新密码', + inputNewPassword: '请输入新密码', + confirmPassword: '确认密码', + inputConfirmPassword: '请再次输入新密码', + noticeOne: '两次输入的密码不一致', + updateSuccess: '密码修改成功', + }, + phone: { + title: '更换密保手机', + oldPhone: '原手机号码', + newPhone: '新手机号码', + inputNewPhone: '请输入新手机', + code: '手机验证码', + inputCode: '请输入验证码', + notice: '请输入正确的手机号码', + }, + email: { + title: '更换密保邮箱', + oldEmail: '原邮箱地址', + newEmail: '新邮箱地址', + inputNewEmail: '请输入新邮箱', + code: '邮箱验证码', + inputCode: '请输入验证码', + notice: '请输入正确的邮箱地址', + }, + notice: { + title: '新消息通知', + systemInfo: '系统消息', + systemInfoTip: '系统消息将以站内信的形式通知', + todo: '待办任务', + todoTip: '待办任务将以站内信的形式通知', + on: '开', + off: '关' + } + }, + customer: { + title: '客户信息列表', + addCustomer: '新增客户', + editCustomer: '编辑客户', + add: '新增', + batchDelete: '批量删除', + batchEnable: '批量启用', + batchDisable: '批量禁用', + Import: '导入', + Export: '导出', + header: { + name: '客户名称', + phoneNumber: '手机号码', + createTime: '创建时间', + startDate: '开始日期', + endDate: '结束日期', + }, + table: { + name: '客户名称', + contact: '联系人', + phoneNumber: '手机号', + email: '电子邮箱', + status: '状态', + accumulatedAccountsReceivable: '累计应收款', + rate: '税率(%)', + sort: '排序', + createTime: '创建时间', + }, + form: { + name: '客户名称', + nameTip: '如果为个人可以不用填写联系人', + contact: '联系人', + phoneNumber: '手机号', + email: '电子邮箱', + fax: '传真', + address: '地址', + remark: '备注', + accountsReceivableInfo: '应收账款信息', + firstQuarterCollection: '一季度收款', + secondQuarterCollection: '二季度收款', + thirdQuarterCollection: '三季度收款', + fourthQuarterCollection: '四季度收款', + accountInfo: '账户信息', + taxNumber: '纳税人识别号', + rate: '税率(%)', + bankName: '开户行', + bankAccount: '银行账号', + }, + export: { + name: '导出', + exportData: '客户数据 ', + noData: '无可用数据导出', + templateDownload: '客户信息Excel模板[下载]', + import: '客户数据导入', + } + }, + member: { + title: '会员信息列表', + addMember: '新增会员', + editMember: '编辑会员', + add: '新增', + batchDelete: '批量删除', + batchEnable: '批量启用', + batchDisable: '批量禁用', + Import: '导入', + Export: '导出', + header: { + memberNumber: '会员卡号', + phoneNumber: '手机号码', + createTime: '创建时间', + startDate: '开始日期', + endDate: '结束日期', + }, + table: { + memberNumber: '会员卡号', + memberName: '会员昵称', + phoneNumber: '手机号码', + email: '电子邮箱', + advancePayment: '预付款', + status: '状态', + remark: '备注', + sort: '排序', + createTime: '创建时间', + }, + form: { + memberNumber: '会员卡号', + memberName: '会员昵称', + phoneNumber: '手机号码', + email: '电子邮箱', + advancePayment: '预付款', + sort: '排序', + }, + export: { + name: '导出', + exportData: '会员数据 ', + noData: '无可用数据导出', + templateDownload: '会员信息Excel模板[下载]', + import: '会员数据导入', + } + }, + warehouse: { + title: '仓库列表', + addWarehouse: '新增仓库', + editWarehouse: '编辑仓库', + add: '新增', + batchDelete: '批量删除', + batchEnable: '批量启用', + batchDisable: '批量禁用', + yes: '是', + no: '否', + header: { + warehouse: '仓库', + remark: '备注', + }, + table: { + warehouseName: '仓库名字', + warehouseAddress: '仓库地址', + storageFees: '仓储费', + handlingFees: '装卸费', + manager: '负责人', + status: '状态', + default: '默认仓库', + sort: '排序', + createTime: '创建时间', + }, + form: { + warehouseName: '仓库名字', + warehouseAddress: '仓库地址', + storageFees: '仓储费', + handlingFees: '装卸费', + manager: '负责人', + managerTip: '用户列表中的用户', + remark: '备注', + default: '默认仓库', + defaultTip: '只允许有一个默认仓库,如果选择是,之前的默认仓库将会变成非默认仓库', + sort: '排序', + } + }, + settlement: { + title: '结算账户列表', + addSettlementAccount: '新增结算账户', + editSettlementAccount: '编辑结算账户', + add: '新增', + batchDelete: '批量删除', + batchEnable: '批量启用', + batchDisable: '批量禁用', + yes: '是', + no: '否', + header: { + accountNumber: '账户编号', + accountName: '账户名称', + }, + table: { + accountNumber: '账户编号', + accountName: '账户名称', + openingAmount: '期初金额', + currentBalance: '当前余额', + status: '状态', + default: '是否默认账户', + sort: '排序', + createTime: '创建时间', + }, + form: { + accountNumber: '账户编号', + accountName: '账户名称', + openingAmount: '期初金额', + currentBalance: '当前余额', + default: '是否默认账户', + sort: '排序', + remark: '备注', + notice: '只允许有一个默认账户,如果选择是,之前的默认账户将会变成非默认账户' + }, + other: { + title: '多账户结算', + accountOne: '结算账户一', + accountTwo: '结算账户二', + accountThree: '结算账户三', + inputAccount: '请选择结算账户', + amountOne: '结算金额一', + amountTwo: '结算金额二', + amountThree: '结算金额三', + inputAmount: '请输入结算金额', + selectAmount: '请选择结算金额', + notice: '请选择结算账户和金额,至少两个账户', + } + }, + operator: { + title: '操作员/经办人列表', + addOperator: '新增操作员', + editOperator: '编辑操作员', + add: '新增', + batchDelete: '批量删除', + batchEnable: '批量启用', + batchDisable: '批量停用', + salesPerson: '销售员', + financialPerson: '财务员', + businessPerson: '业务员', + header: { + name: '姓名', + type: '类型', + }, + table: { + name: '姓名', + type: '类型', + status: '状态', + sort: '排序', + createTime: '创建时间', + }, + form: { + name: '姓名', + type: '类型', + sort: '排序', + remark: '备注', + }, + }, + incomeExpense: { + title: '收支项目列表', + addIncomeExpense: '新增收支项目', + editIncomeExpense: '编辑收支项目', + add: '新增', + batchDelete: '批量删除', + batchEnable: '批量启用', + batchDisable: '批量停用', + enable: '启用', + disable: '停用', + income: '收入', + expense: '支出', + header: { + name: '名称', + type: '类型', + remark: '备注', + }, + table: { + name: '名称', + type: '类型', + remark: '备注', + sort: '排序', + status: '状态', + createTime: '创建时间', + }, + form: { + name: '名称', + type: '类型', + sort: '排序', + remark: '备注', + } + } +} \ No newline at end of file diff --git a/src/locales/lang/zh-CN/common.ts b/src/locales/lang/zh-CN/common.ts new file mode 100644 index 0000000..82ec0ce --- /dev/null +++ b/src/locales/lang/zh-CN/common.ts @@ -0,0 +1,37 @@ +export default { + okText: '确认', + closeText: '关闭', + cancelText: '取消', + loadingText: '加载中...', + saveText: '保存', + delText: '删除', + resetText: '重置', + searchText: '搜索', + queryText: '查询', + + inputText: '请输入', + chooseText: '请选择', + + redo: '刷新', + back: '返回', + + notice: '提示', + + light: '亮色主题', + dark: '黑暗主题', + + action: '操作', + operating: '操作', + successful: '成功', + warning: '警告', + failed: '失败', + on: '启用', + off: '停用', + delete: '删除', + deleteConfirm: '确认删除', + createTime: '创建时间', + updateTime: '修改时间', + notAllowEditAdminData: '禁止编辑管理员数据', + notAllowDeleteAdminData: '禁止删除管理员数据', + notAllowResetAdmin: '禁止重置管理员密码' +}; diff --git a/src/locales/lang/zh-CN/component.ts b/src/locales/lang/zh-CN/component.ts new file mode 100644 index 0000000..a29c59b --- /dev/null +++ b/src/locales/lang/zh-CN/component.ts @@ -0,0 +1,135 @@ +export default { + app: { + searchNotData: '暂无搜索结果', + toSearch: '确认', + toNavigate: '切换', + }, + countdown: { + normalText: '获取验证码', + sendText: '{0}秒后重新获取', + }, + 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: '预览', + }, + drawer: { + loadingText: '加载中...', + cancelText: '关闭', + okText: '确认', + }, + excel: { + exportModalTitle: '导出数据', + fileType: '文件类型', + fileName: '文件名', + }, + form: { + putAway: '收起', + unfold: '展开', + + maxTip: '字符数应小于{0}位', + + apiSelectNotFound: '请等待数据加载完成...', + }, + icon: { + placeholder: '点击选择图标', + search: '搜索图标', + copy: '复制图标成功!', + }, + menu: { + search: '菜单搜索', + }, + modal: { + cancelText: '关闭', + okText: '确认', + close: '关闭', + maximize: '最大化', + restore: '还原', + }, + table: { + settingDens: '密度', + settingDensDefault: '默认', + settingDensMiddle: '中等', + settingDensSmall: '紧凑', + settingColumn: '列设置', + settingColumnShow: '列展示', + settingIndexColumnShow: '序号列', + settingSelectColumnShow: '勾选列', + settingFixedLeft: '固定到左侧', + settingFixedRight: '固定到右侧', + settingFullScreen: '全屏', + + index: '序号', + + total: '共 {total} 条数据', + }, + time: { + before: '前', + after: '后', + just: '刚刚', + seconds: '秒', + minutes: '分钟', + hours: '小时', + days: '天', + }, + tree: { + selectAll: '选择全部', + unSelectAll: '取消选择', + expandAll: '展开全部', + unExpandAll: '折叠全部', + checkStrictly: '层级关联', + checkUnStrictly: '层级独立', + }, + upload: { + save: '保存', + upload: '上传', + imgUpload: '图片上传', + uploaded: '已上传', + + operating: '操作', + del: '删除', + download: '下载', + saveWarn: '请等待文件上传后,保存!', + saveError: '没有上传成功的文件,无法保存!', + + preview: '预览', + choose: '选择文件', + + accept: '支持{0}格式', + acceptUpload: '只能上传{0}格式文件', + maxSize: '单个文件不超过{0}MB', + maxSizeMultiple: '只能上传不超过{0}MB的文件!', + maxNumber: '最多只能上传{0}个文件', + + legend: '略缩图', + fileName: '文件名', + fileSize: '文件大小', + fileStatue: '状态', + + startUpload: '开始上传', + uploadSuccess: '上传成功', + uploadError: '上传失败', + uploading: '上传中', + uploadWait: '请等待文件上传结束后操作', + reUploadFailed: '重新上传失败文件', + }, + verify: { + error: '验证失败!', + time: '验证校验成功,耗时{time}秒!', + + redoTip: '点击图片可刷新', + + dragText: '请按住滑块拖动', + successText: '验证通过', + }, +}; diff --git a/src/locales/lang/zh-CN/financial.ts b/src/locales/lang/zh-CN/financial.ts new file mode 100644 index 0000000..a0f1ec5 --- /dev/null +++ b/src/locales/lang/zh-CN/financial.ts @@ -0,0 +1,429 @@ +export default { + selectData: '请选择一条数据', + modifyDataPrompt: '抱歉,只有未审核的单据才能编辑!', + regularPrint: '普通打印', + income: { + title: '收入单列表', + add: '新增', + batchDelete: '批量删除', + editIncomeReceipt: '编辑-收入单', + addIncomeReceipt: '新增-收入单', + incomeReceiptDetail: '收入单-详情', + receiptDetail: '收入单单据详情', + viewIncomeReceiptDetail: '查看收入单详情', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + incomeAccount: '收入账户', + correspondenceUnit: '往来单位', + financialPerson: '财务人员', + status: '状态', + remark: '备注', + }, + table: { + name: '名称', + receiptNumber: '单据编号', + receiptDate: '单据日期', + financialPerson: '财务人员', + incomeAccount: '收入账户', + incomeAmount: '收入金额', + remark: '备注', + status: '状态', + }, + view: { + incomeExpenseName: '收入项目', + amount: '金额', + remark: '备注', + total: '合计', + }, + form: { + correspondenceUnit: '往来单位', + inputCorrespondenceUnit: '请选择往来单位', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + financialPerson: '财务人员', + inputFinancialPerson: '请选择财务人员', + addFinancialPerson: '新增财务人员', + incomeAccount: '收入账户', + inputIncomeAccount: '请选择收入账户', + incomeAmount: '收入金额', + inputIncomeAmount: '请输入收入金额', + inputRemark: '请输入备注', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请选择收入项目', + noticeTwo: '请输入收入金额', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '确定要删除选中的数据?', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + annex: '附件', + uploadAnnex: '上传附件', + }, + export: { + name: '导出', + exportData: '收入单数据 ', + noData: '无可用数据导出', + } + }, + expense: { + title: '支出单列表', + add: '新增', + batchDelete: '批量删除', + editExpenseReceipt: '编辑-支出单', + addExpenseReceipt: '新增-支出单', + expenseReceiptDetail: '支出单-详情', + receiptDetail: '支出单单据详情', + viewExpenseReceiptDetail: '查看支出单详情', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + expenseAccount: '支出账户', + correspondenceUnit: '往来单位', + financialPerson: '财务人员', + status: '状态', + remark: '备注', + }, + table: { + name: '名称', + receiptNumber: '单据编号', + receiptDate: '单据日期', + financialPerson: '财务人员', + expenseAccount: '支出账户', + expenseAmount: '支出金额', + remark: '备注', + status: '状态', + }, + view: { + expenseName: '支出项目', + amount: '金额', + remark: '备注', + }, + form: { + correspondenceUnit: '往来单位', + inputCorrespondenceUnit: '请选择往来单位', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + financialPerson: '财务人员', + inputFinancialPerson: '请选择财务人员', + addFinancialPerson: '新增财务人员', + inputRemark: '请输入备注', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请选择支出项目', + noticeTwo: '请输入支出金额', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '确定要删除选中的数据?', + total: '合计', + expenseAccount: '支出账户', + inputExpenseAccount: '请选择支出账户', + expenseAmount: '支出金额', + inputExpenseAmount: '请输入支出金额', + annex: '附件', + uploadAnnex: '上传附件', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核' + }, + export: { + name: '导出', + exportData: '支出单数据 ', + noData: '无可用数据导出', + } + }, + transfer: { + title: '转账单列表', + add: '新增', + batchDelete: '批量删除', + editTransferReceipt: '编辑-转账单', + addTransferReceipt: '新增-转账单', + transferReceiptDetail: '转账单-详情', + receiptDetail: '转账单单据详情', + viewTransferReceiptDetail: '查看转账单详情', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + paymentAccount: '付款账户', + financialPerson: '财务人员', + status: '状态', + remark: '备注', + }, + table: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + financialPerson: '财务人员', + paymentAccount: '付款账户', + paymentAmount: '支出金额', + remark: '备注', + status: '状态', + }, + view: { + accountName: '账户名称', + amount: '金额', + remark: '备注', + }, + form: { + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + financialPerson: '财务人员', + inputFinancialPerson: '请选择财务人员', + addFinancialPerson: '新增财务人员', + inputRemark: '请输入备注', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请选择账户', + noticeTwo: '请输入金额', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '确定要删除选中的数据?', + total: '合计', + paymentAccount: '付款账户', + inputPaymentAccount: '请选择付款账户', + paymentAmount: '实付金额', + inputPaymentAmount: '请输入实付金额', + annex: '附件', + uploadAnnex: '上传附件', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核' + }, + export: { + name: '导出', + exportData: '转账单数据 ', + noData: '无可用数据导出', + } + }, + collection: { + title: '收款单列表', + add: '新增', + batchDelete: '批量删除', + editCollectionReceipt: '编辑-收款单', + addCollectionReceipt: '新增-收款单', + collectionReceiptDetail: '收款单-详情', + receiptDetail: '收款单单据详情', + viewCollectionReceiptDetail: '查看收款单详情', + selectSaleArrearsReceipt: '选择销售欠款单', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + collectionAccount: '收款账户', + customer: '客户', + financialPerson: '财务人员', + status: '状态', + remark: '备注', + productInfo: '商品信息', + }, + table: { + customer: '客户', + receiptNumber: '单据编号', + receiptDate: '单据日期', + financialPerson: '财务人员', + collectionAccount: '收款账户', + totalCollection: '合计收款', + discountAmount: '优惠金额', + actualCollection: '实收金额', + remark: '备注', + status: '状态', + }, + view: { + saleReceiptNumber: '销售单据编号', + receivableArrears: '应收欠款', + receivedArrears: '已收欠款', + thisTimeCollection: '本次收款', + thisReceiptArrears: '该单据欠款', + operator: '操作员', + remark: '备注', + }, + form: { + customer: '客户', + inputCustomer: '请选择客户', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + financialPerson: '财务人员', + inputFinancialPerson: '请选择财务人员', + addFinancialPerson: '新增财务人员', + selectReceipt: '选择销售单', + deleteRow: '删除选中行', + noticeOne: '请先选择客户', + noticeTwo: '请选择收款账户', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '确定要删除选中的数据?', + noticeFive: '请输入优惠金额', + total: '合计', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核' + }, + export: { + name: '导出', + exportData: '收款单数据 ', + noData: '无可用数据导出', + } + }, + payment: { + title: '付款单列表', + add: '新增', + batchDelete: '批量删除', + editPaymentReceipt: '编辑-付款单', + addPaymentReceipt: '新增-付款单', + paymentReceiptDetail: '付款单-详情', + receiptDetail: '付款单单据详情', + viewPaymentReceiptDetail: '查看付款单详情', + selectPurchaseArrearsReceipt: '选择采购欠款单', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + paymentAccount: '付款账户', + supplier: '供应商', + financialPerson: '财务人员', + status: '状态', + remark: '备注', + productInfo: '商品信息', + }, + table: { + supplier: '供应商', + receiptNumber: '单据编号', + receiptDate: '单据日期', + financialPerson: '财务人员', + paymentAccount: '付款账户', + totalPayment: '合计付款', + discountAmount: '优惠金额', + actualPayment: '实付金额', + remark: '备注', + status: '状态', + }, + view: { + purchaseReceiptNumber: '采购单据编号', + payableArrears: '应付欠款', + paidArrears: '已付欠款', + thisTimePayment: '本次付款', + thisReceiptArrears: '该单据欠款', + operator: '操作员', + remark: '备注', + }, + form: { + supplier: '供应商', + inputSupplier: '请选择供应商', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + financialPerson: '财务人员', + inputFinancialPerson: '请选择财务人员', + addFinancialPerson: '新增财务人员', + selectReceipt: '选择采购单', + inputPaymentAccount: '请选择付款账户', + inputPaymentAmount: '请输入实付金额', + inputDiscountAmount: '请输入优惠金额', + inputActualPayment: '请输入实付金额', + deleteRow: '删除选中行', + noticeOne: '请先选择供应商单据', + noticeTwo: '请选择付款账户', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '确定要删除选中的数据?', + noticeFive: '为避免重复添加相同的采购欠款单据号,请修改已有的单据', + total: '合计', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核' + }, + export: { + name: '导出', + exportData: '付款单数据 ', + noData: '无可用数据导出', + } + }, + advance: { + title: '预付款单列表', + add: '新增', + batchDelete: '批量删除', + editAdvanceReceipt: '编辑-预付款单', + addAdvanceReceipt: '新增-预付款单', + advanceReceiptDetail: '预付款单-详情', + receiptDetail: '预付款单单据详情', + viewAdvanceReceiptDetail: '查看预付款单详情', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + paymentMember: '付款会员', + status: '状态', + remark: '备注', + }, + table: { + paymentMember: '付款会员', + receiptNumber: '单据编号', + receiptDate: '单据日期', + amountCollected : '收款金额', + totalAmount: '合计金额', + financialPerson: '财务人员', + operator: '操作人', + remark: '备注', + status: '状态', + }, + view: { + accountName: '账户名称', + amount: '金额', + remark: '备注', + }, + form: { + paymentMember: '付款会员', + inputCustomer: '请选择付款会员', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + financialPerson: '财务人员', + inputFinancialPerson: '请选择财务人员', + addFinancialPerson: '新增财务人员', + insertRow: '添加一行', + deleteRow: '删除选中行', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '请插入一行数据,录入收预付款信息', + noticeFive: '请选择账户名称', + noticeSix: '请输入金额', + total: '合计', + inputRemark: '请输入备注', + amountCollected : '收款金额', + totalAmount: '合计金额', + annex: '附件', + uploadAnnex: '上传附件', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核' + }, + export: { + name: '导出', + exportData: '收预付款单数据 ', + noData: '无可用数据导出', + } + } +} \ No newline at end of file diff --git a/src/locales/lang/zh-CN/home.ts b/src/locales/lang/zh-CN/home.ts new file mode 100644 index 0000000..b05fdd9 --- /dev/null +++ b/src/locales/lang/zh-CN/home.ts @@ -0,0 +1,21 @@ +export default { + today: '今日', + yesterday: '昨日', + thisMonth: '本月', + thisYear: '今年', + todayRetail: '今日零售', + yesterdayRetail: '昨日零售', + thisMonthRetail: '本月累计零售', + thisYearRetail: '今年累计零售', + todaySales: '今日销售', + yesterdaySales: '昨日销售', + thisMonthSales: '本月累计销售', + thisYearSales: '今年累计销售', + todayPurchase: '今日采购', + yesterdayPurchase: '昨日采购', + thisMonthPurchase: '本月累计采购', + thisYearPurchase: '今年累计采购', + retailStatistics: '零售统计', + salesStatistics: '销售统计', + purchaseStatistics: '采购统计', +} \ No newline at end of file diff --git a/src/locales/lang/zh-CN/layout.ts b/src/locales/lang/zh-CN/layout.ts new file mode 100644 index 0000000..f60a117 --- /dev/null +++ b/src/locales/lang/zh-CN/layout.ts @@ -0,0 +1,116 @@ +export default { + footer: { onlinePreview: '在线预览', onlineDocument: '在线文档' }, + header: { + // user dropdown + dropdownItemSetting: '个人设置', + dropdownItemDoc: '文档', + dropdownItemLoginOut: '退出系统', + + // tooltip + tooltipErrorLog: '错误日志', + tooltipLock: '锁定屏幕', + tooltipNotify: '消息通知', + + tooltipEntryFull: '全屏', + tooltipExitFull: '退出全屏', + + // lock + lockScreenPassword: '锁屏密码', + lockScreen: '锁定屏幕', + lockScreenBtn: '锁定', + + home: '首页', + }, + multipleTab: { + reload: '重新加载', + close: '关闭标签页', + closeLeft: '关闭左侧标签页', + closeRight: '关闭右侧标签页', + closeOther: '关闭其它标签页', + closeAll: '关闭全部标签页', + }, + setting: { + // content mode + contentModeFull: '流式', + contentModeFixed: '定宽', + // topMenu align + topMenuAlignLeft: '居左', + topMenuAlignRight: '居中', + topMenuAlignCenter: '居右', + // menu trigger + menuTriggerNone: '不显示', + menuTriggerBottom: '底部', + menuTriggerTop: '顶部', + // menu type + menuTypeSidebar: '左侧菜单模式', + menuTypeMixSidebar: '左侧菜单混合模式', + menuTypeMix: '顶部菜单混合模式', + menuTypeTopMenu: '顶部菜单模式', + + on: '开', + off: '关', + minute: '分钟', + + operatingTitle: '操作成功', + operatingContent: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!', + resetSuccess: '重置成功!', + + copyBtn: '拷贝', + clearBtn: '清空缓存并返回登录页', + + drawerTitle: '项目配置', + + darkMode: '主题', + navMode: '导航栏模式', + interfaceFunction: '界面功能', + interfaceDisplay: '界面显示', + animation: '动画', + splitMenu: '分割菜单', + closeMixSidebarOnChange: '切换页面关闭菜单', + + sysTheme: '系统主题', + headerTheme: '顶栏主题', + sidebarTheme: '菜单主题', + + menuDrag: '侧边菜单拖拽', + menuSearch: '菜单搜索', + menuAccordion: '侧边菜单手风琴模式', + menuCollapse: '折叠菜单', + collapseMenuDisplayName: '折叠菜单显示名称', + topMenuLayout: '顶部菜单布局', + menuCollapseButton: '菜单折叠按钮', + contentMode: '内容区域宽度', + expandedMenuWidth: '菜单展开宽度', + + breadcrumb: '面包屑', + breadcrumbIcon: '面包屑图标', + tabs: '标签页', + tabDetail: '标签详情页', + tabsQuickBtn: '标签页快捷按钮', + tabsRedoBtn: '标签页刷新按钮', + tabsFoldBtn: '标签页折叠按钮', + sidebar: '左侧菜单', + header: '顶栏', + footer: '页脚', + fullContent: '全屏内容', + grayMode: '灰色模式', + colorWeak: '色弱模式', + + progress: '顶部进度条', + switchLoading: '切换loading', + switchAnimation: '切换动画', + animationType: '动画类型', + + autoScreenLock: '自动锁屏', + notAutoScreenLock: '不自动锁屏', + + fixedHeader: '固定header', + fixedSideBar: '固定Sidebar', + + mixSidebarTrigger: '混合菜单触发方式', + triggerHover: '悬停', + triggerClick: '点击', + + mixSidebarFixed: '固定展开菜单', + }, +}; diff --git a/src/locales/lang/zh-CN/product.ts b/src/locales/lang/zh-CN/product.ts new file mode 100644 index 0000000..b862534 --- /dev/null +++ b/src/locales/lang/zh-CN/product.ts @@ -0,0 +1,205 @@ +export default { + selectData: '请选择一条数据', + modifyDataPrompt: '抱歉,只有未审核的单据才能编辑!', + selectProduct: '选择商品', + inputSelectProduct: '请选择商品', + productList: '商品列表', + category:{ + title: '产品分类列表', + tip: '产品分类列表可以添加多个产品分类和下级分类', + add: '新增产品分类', + batchDelete: '批量删除产品分类', + table:{ + categoryName: '分类名称', + categoryNumber: '分类编号', + categoryParent: '上级分类', + sort: '排序', + remark: '备注', + createTime: '创建时间', + operate: '操作', + edit: '编辑产品分类', + delete: '删除产品分类' + } + }, + info:{ + title: '商品信息列表', + add: '新增', + batchDelete: '批量删除', + batchEnable: '批量启用', + batchDisable: '批量禁用', + selectFile: '选择文件', + import: '导入', + export: '导出', + batchEdit: '批量编辑', + addProductInfo: '新增商品信息', + editProductInfo: '修改商品信息', + checkBarCodeExist: '导入数据-检测商品出现重复', + dataBaseExist: '数据库中存在重复的商品条码,请检查。', + dataCover: '是否需要覆盖现有数据?', + exportData: '商品信息数据 ', + header: { + categoryName: '商品类别', + keyWord: '关键词', + serialNumber: '序列号', + batchNumber: '批次号', + warehouse: '仓库', + have: '有', + none: '无', + }, + table: { + barCode: '条码', + productName: '商品名称', + productStandard: '商品规格', + productModel: '商品型号', + productColor: '商品颜色', + productUnit: '商品单位', + productCategory: '商品类别', + productStock: '商品库存', + purchasePrice: '采购价格', + retailPrice: '零售价格', + salesPrice: '销售价格', + lowestSellPrice: '最低销售价格', + status: '状态', + createTime: '创建时间', + operate: '操作', + }, + importInfo: { + title: '商品信息数据导入', + templateName: '商品信息Excel模板[下载]', + infoData: '商品信息数据', + setup1: '第一步:', + setup2: '第二步:', + tip: '提示:模板中的第一行请勿删除', + }, + form: { + basic: { + title: '基本信息', + name: '名称', + inputName: '请输入名称', + standard: '规格', + inputStandard: '请输入规格', + model: '型号', + inputModel: '请输入型号', + color: '颜色', + inputColor: '请输入颜色', + unit: '单位', + inputUnit: '请输入单位', + inputManyUnit: '请选择多单位', + unitTip: '需要先录入单位才能激活此处输入框', + weight: '基础重量', + inputWeight: '请输入基础重量(Kg)', + sheIfLife: '保质期', + inputSheIfLife: '请输入保质期(天)', + category: '类别', + inputCategory: '请选择类别', + serialNumber: '序列号', + inputSerialNumber: '请选择有无序列号', + serialNumberTip: '如果选择为有,则在采购入库单需要录入该商品的序列号', + batchNumber: '批次号', + inputBatchNumber: '请选择有无批次号', + batchNumberTip: '如果选择为有,则在采购入库单需要录入该商品的批号和有效期', + warehouseShelves: '仓库货架', + inputWarehouseShelves: '请输入仓库货架', + multipleAttributes: '多属性', + multipleAttributesTip: '多属性针对服装、鞋帽等行业,需要先录入单位才能激活此处输入框', + inputMultipleAttributes: '请选择多属性(可多选)', + insertRow: '插入一行', + deleteRow: '删除选中行', + purchasePriceBatch: '采购价-批量', + retailPriceBatch: '零售价-批量', + salesPriceBatch: '销售价-批量', + lowestSellPriceBatch: '最低销售价-批量', + table: { + pleaseEnter: '请输入 ', + barCode: '条码', + unit: '单位', + multipleAttributes: '多属性', + retailPrice: '零售价格', + purchasePrice: '采购价格', + salesPrice: '销售价格', + lowestSellPrice: '最低销售价格', + }, + remark: '备注', + inputRemark: '请输入备注', + noticeOne: '请插入一行数据,录入商品条码价格信息', + noticeTwo: '系统检查到您没有仓库信息,请在基本资料菜单栏->添加至少1条仓库信息', + noticeThree: '抱歉,您还没有选择多属性,开启多属性后才能批量设置金额', + noticeFour: '请先录入条码、单位等信息!', + inputPrice: '请输入价格', + price: '价格', + batchSet: '批量设置', + }, + extendInfo: { + title: '扩展信息', + manufacturer: '制造商', + customOne: '自定义1', + customTwo: '自定义2', + customThree: '自定义3', + }, + inventoryQuantity: { + title: '库存数量', + initialQuantity: '期初库存数量', + inputInitialQuantity: '请输入期初库存数量', + batchInitialQuantity: '期初库存-批量设置', + minSafetyQuantity: '最低安全库存数量', + inputMinSafetyQuantity: '请输入最低安全库存数量', + batchMinSafetyQuantity: '最低安全库存-批量设置', + maxSafetyQuantity: '最高安全库存数量', + inputMaxSafetyQuantity: '请输入最高安全库存数量', + batchMaxSafetyQuantity: '最高安全库存-批量设置', + warehouse: '仓库(商品条码/商品单位)', + inputNumber: '请输入数量', + number: '库存数量', + }, + images: { + title: '图片信息', + upload: '上传图片', + tip: '上传提示:最多上传4张图片,支持jpg、jpeg、png格式,最大支持2M', + }, + } + }, + attribute: { + title: '商品多属性列表', + add: '新增产品属性', + batchDelete: '批量删除产品属性', + addProductAttribute: '新增产品属性', + editProductAttribute: '编辑产品属性', + table: { + attributeName: '属性名称', + attributeValue: '属性值(用|隔开)', + sort: '排序', + remark: '属性备注', + createTime: '创建时间', + operate: '操作', + edit: '编辑产品属性', + delete: '删除产品属性' + } + }, + unit: { + title: '商品计量单位列表', + add: '新增商品单位', + batchDelete: '批量删除商品单位', + addProductUnit: '新增商品计量单位', + editProductUnit: '编辑商品计量单位', + table: { + unitName: '计量单位', + basicUnit: '基本单位', + inputBasicUnit: '请输入基本单位(小单位)', + deputyUnitOne: '副单位1', + inputDeputyUnitOne: '请输入副单位(大单位)', + inputProportionOne: '请输入比例', + deputyUnitTwo: '副单位2', + inputDeputyUnitTwo: '请输入副单位2(大单位)', + inputProportionTwo: '请输入比例2', + deputyUnitThree: '副单位3', + inputDeputyUnitThree: '请输入副单位3(大单位)', + inputProportionThree: '请输入比例3', + status: '状态', + createTime: '创建时间', + operate: '操作', + edit: '编辑商品单位', + delete: '删除商品单位' + }, + noticeOne: '抱歉,副单位的比例不能为空值', + } +}; \ No newline at end of file diff --git a/src/locales/lang/zh-CN/purchase.ts b/src/locales/lang/zh-CN/purchase.ts new file mode 100644 index 0000000..25962c8 --- /dev/null +++ b/src/locales/lang/zh-CN/purchase.ts @@ -0,0 +1,320 @@ +export default { + selectData: '请选择一条数据', + modifyDataPrompt: '抱歉,只有未审核的单据才能编辑!', + partialPurchase: '部分采购', + completePurchase: '完成采购', + regularPrint: '普通打印', + order:{ + title: '采购订单列表', + addOrder: '新增-采购订单', + editOrder: '编辑-采购订单', + detail: '采购订单-详情', + receipt: '单据详情', + table:{ + supplier: '供应商', + receiptNumber: '单据编号', + productInformation: '商品信息', + productQuantity: '商品数量', + totalAmount: '金额合计', + totalIncludingTax: '含税合计', + collectDeposit: '收取定金', + receiptDate: '单据日期', + operator: '操作员', + status: '状态', + }, + header:{ + startDate: '开始日期', + endDate: '结束日期', + receiptRemark: '单据备注', + }, + form: { + supplier: '供应商', + inputSupplier: '请选择供应商', + addSupplier: '新增供应商', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择采购产品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + discountRate: '优惠率', + paymentDiscount: '付款优惠', + discountAmount: '优惠后金额', + settlementAccount: '付款账户', + paymentDeposit: '支付定金', + purchasePerson: '采购人员', + inputPurchasePerson: '请选择采购人员', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '确定要删除选中的数据?', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '该条码查询不到商品信息', + noticeFive: '商品条码不能为空', + noticeSix: '输入条码商品信息自动带出!', + noticeSeven: '支持商品名称、商品编号、商品规格、商品型号', + noticeEight: '仓库不能为空', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + warehouse: '仓库', + barCode: '条码', + inputBarCode: '输入商品条码', + name: '名称', + standard: '规格', + model: '型号', + color: '颜色', + stock: '库存', + unit: '单位', + unitPrice: '单价', + quantity: '数量', + amount: '金额', + taxRate: '税率', + taxAmount: '税额', + totalIncludingTax: '含税合计', + remark: '备注', + total: '合计', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + view: { + title: '采购订单表数据', + supplier: '供应商', + receiptDate: '单据日期', + receiptAmount: '单据金额', + settlementAccount: '付款账户', + inputSettlementAccount: '请选择结算账户', + discountRate: '优惠率', + paymentDiscount: '付款优惠', + discountAmount: '优惠后金额', + paymentDeposit: '支付定金', + remark: '备注', + status: '状态', + }, + export: { + name: '导出', + exportData: '采购订单数据 ', + noData: '无可用数据导出', + } + }, + storage:{ + title: '采购入库列表', + addStorage: '新增-采购入库', + editStorage: '编辑-采购入库', + detail: '采购入库-详情', + receipt: '单据详情', + table:{ + supplier: '供应商', + receiptNumber: '单据编号', + productInformation: '商品信息', + productQuantity: '商品数量', + totalAmount: '金额合计', + totalIncludingTax: '含税合计', + paymentAmount: '待付金额', + thisTimePaymentAmount: '本次付款', + thisTimeArrearsAmount: '本次欠款', + receiptDate: '单据日期', + operator: '操作员', + status: '状态', + }, + header:{ + startDate: '开始日期', + endDate: '结束日期', + receiptRemark: '单据备注', + }, + form: { + supplier: '供应商', + inputSupplier: '请选择供应商', + addSupplier: '新增供应商', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + relatedOrder: '关联订单', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此处', + addProduct: '选择采购产品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + discountRate: '优惠率', + paymentDiscount: '付款优惠', + discountAmount: '优惠后金额', + otherFees: '其他费用', + settlementAccount: '付款账户', + thisTimePaymentAmount: '本次付款', + thisTimeArrearsAmount: '本次欠款', + paymentDeposit: '支付定金', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '确定要删除选中的数据?', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '该条码查询不到商品信息', + noticeFive: '商品条码不能为空', + noticeSix: '输入条码商品信息自动带出!', + noticeSeven: '请至少选择两个账户', + noticeEight: '请输入金额', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + warehouse: '仓库', + inputWarehouse: '请选择仓库', + barCode: '条码', + inputBarCode: '输入商品条码', + name: '名称', + standard: '规格', + model: '型号', + color: '颜色', + stock: '库存', + unit: '单位', + unitPrice: '单价', + quantity: '数量', + amount: '金额', + taxRate: '税率', + taxAmount: '税额', + totalIncludingTax: '含税合计', + remark: '备注', + total: '合计', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + view: { + title: '采购入库表数据', + supplier: '供应商', + receiptDate: '单据日期', + receiptAmount: '单据金额', + purchaseOrder: '采购订单单据', + settlementAccount: '付款账户', + thisTimePaymentAmount: '本次付款', + thisTimeArrearsAmount: '本次欠款', + inputSettlementAccount: '请选择结算账户', + addSettlementAccount: '新增结算账户', + discountRate: '优惠率', + paymentDiscount: '付款优惠', + discountAmount: '优惠后金额', + otherFees: '其他费用', + paymentDeposit: '支付定金', + remark: '备注', + status: '状态', + }, + export: { + name: '导出', + exportData: '采购入库数据 ', + noData: '无可用数据导出', + } + }, + refund:{ + title: '采购退货列表', + addRefund: '新增-采购退货', + editRefund: '编辑-采购退货', + detail: '采购退货-详情', + receipt: '单据详情', + table:{ + supplier: '供应商', + receiptNumber: '单据编号', + productInformation: '商品信息', + productQuantity: '商品数量', + totalAmount: '金额合计', + totalIncludingTax: '含税合计', + refundAmount: '待退金额', + thisRefundAmount: '本次退款', + thisArrearsAmount: '本次欠款', + receiptDate: '单据日期', + operator: '操作员', + status: '状态', + }, + header:{ + startDate: '开始日期', + endDate: '结束日期', + receiptRemark: '单据备注', + }, + form: { + supplier: '供应商', + inputSupplier: '请选择供应商', + addSupplier: '新增供应商', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + relatedStorage: '关联采购入库单', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此处', + addProduct: '选择退货产品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + discountRate: '优惠率', + refundDiscount: '退款优惠', + discountAmount: '优惠后金额', + otherFees: '其他费用', + settlementAccount: '退款账户', + thisRefundAmount: '本次退款', + thisTimeArrearsAmount: '本次欠款', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '确定要删除选中的数据?', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '该条码查询不到商品信息', + noticeFive: '商品条码不能为空', + noticeSix: '输入条码商品信息自动带出!', + noticeSeven: '请至少选择两个账户', + noticeEight: '请输入金额', + noticeNine: '商品库存不足,请检查库存数量', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + warehouse: '仓库', + inputWarehouse: '请选择仓库', + barCode: '条码', + inputBarCode: '输入商品条码', + name: '名称', + standard: '规格', + model: '型号', + color: '颜色', + stock: '库存', + unit: '单位', + unitPrice: '单价', + quantity: '数量', + amount: '金额', + taxRate: '税率', + taxAmount: '税额', + totalIncludingTax: '含税合计', + remark: '备注', + total: '合计', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + view: { + title: '采购退货表数据', + supplier: '供应商', + receiptDate: '单据日期', + receiptAmount: '单据金额', + purchaseOrder: '采购入库单据', + settlementAccount: '退款账户', + thisRefundAmount: '本次退款', + thisTimeArrearsAmount: '本次欠款', + inputSettlementAccount: '请选择账户', + addSettlementAccount: '新增账户', + discountRate: '优惠率', + refundDiscount: '退款优惠', + discountAmount: '优惠后金额', + otherFees: '其他费用', + remark: '备注', + status: '状态', + }, + export: { + name: '导出', + exportData: '采购退货数据 ', + noData: '无可用数据导出', + } + } +}; \ No newline at end of file diff --git a/src/locales/lang/zh-CN/reports.ts b/src/locales/lang/zh-CN/reports.ts new file mode 100644 index 0000000..9d0bdee --- /dev/null +++ b/src/locales/lang/zh-CN/reports.ts @@ -0,0 +1,359 @@ +export default { + productStock: { + title: '商品库存报表', + export: '导出', + regularPrint: '普通打印', + data: '商品库存数据', + detail: '商品库存明细', + header: { + warehouse: '仓库', + productInfo: '商品信息', + productCategory: '商品分类', + warehouseShelves: '仓库货架', + }, + table: { + flow: '流水', + stockFlow: '库存流水', + productBarcode: '商品条码', + warehouse: '仓库', + productName: '商品名称', + productCategory: '商品分类', + standard: '规格', + model: '型号', + weight: '基础重量', + color: '颜色', + unit: '单位', + warehouseShelves: '仓库货架', + unitPrice: '单价', + initStock: '初始库存', + currentStock: '当前库存', + stockAmount: '库存金额', + total: '合计', + notice: '当前查询条件下无数据可导出', + } + }, + account: { + title: '账户统计报表', + export: '导出', + regularPrint: '普通打印', + data: '账户统计数据', + detail: '账户统计明细', + notice: '当前查询条件下无数据可导出', + header: { + account: '账户', + accountNumber: '账户编号', + }, + table: { + flow: '流水', + accountFlow: '账户流水', + accountName: '账户名称', + accountNumber: '账户编号', + initialAmount: '初始金额', + thisMonthAmount: '本月金额', + currentAmount: '当前金额', + total: '合计', + } + }, + retail: { + title: '零售统计报表', + export: '导出', + regularPrint: '普通打印', + data: '零售统计数据', + detail: '零售统计明细', + notice: '当前查询条件下无数据可导出', + header: { + productInfo: '商品信息', + receiptDate: '单据日期', + startDate: '开始日期', + endDate: '结束日期', + member: '会员', + }, + table: { + barCode: '条码', + warehouse: '仓库', + name: '名称', + standard: '规格', + model: '型号', + extendInfo: '扩展信息', + unit: '单位', + quantity: '数量', + amount: '金额', + refundQuantity: '退货数量', + refundAmount: '退货金额', + actualAmount: '实际金额', + total: '合计', + } + }, + purchase: { + title: '采购统计报表', + export: '导出', + regularPrint: '普通打印', + data: '采购统计数据', + detail: '采购统计明细', + notice: '当前查询条件下无数据可导出', + header: { + productInfo: '商品信息', + receiptDate: '单据日期', + startDate: '开始日期', + endDate: '结束日期', + supplier: '供应商', + warehouse: '仓库' + }, + table: { + barCode: '条码', + warehouse: '仓库', + name: '商品名称', + standard: '规格', + model: '型号', + extendInfo: '扩展信息', + unit: '单位', + quantity: '采购数量', + amount: '采购金额', + refundQuantity: '采购退货数量', + refundAmount: '采购退货金额', + actualAmount: '实际采购金额', + purchaseDate: '采购时间', + total: '合计', + } + }, + sales: { + title: '销售统计报表', + export: '导出', + regularPrint: '普通打印', + data: '销售统计数据', + detail: '销售统计明细', + notice: '当前查询条件下无数据可导出', + header: { + productInfo: '商品信息', + receiptDate: '单据日期', + startDate: '开始日期', + endDate: '结束日期', + customer: '客户', + }, + table: { + barCode: '条码', + warehouse: '仓库', + name: '商品名称', + standard: '规格', + model: '型号', + extendInfo: '扩展信息', + unit: '单位', + quantity: '销售数量', + amount: '销售金额', + refundQuantity: '销售退货数量', + refundAmount: '销售退货金额', + actualAmount: '实际销售金额', + total: '合计', + } + }, + shipmentsDetail: { + title: '出库明细报表', + export: '导出', + regularPrint: '普通打印', + data: '出库明细数据', + detail: '出库明细', + notice: '当前查询条件下无数据可导出', + header: { + receiptNumber: '单据编号', + productInfo: '商品信息', + receiptDate: '单据日期', + startDate: '开始日期', + endDate: '结束日期', + contact: '往来人员', + warehouse: '仓库', + operator: '操作人', + remark: '单据备注', + }, + table: { + receiptNumber: '单据编号', + type: '类型', + contact: '往来人员', + barCode: '条码', + warehouse: '仓库', + name: '商品名称', + standard: '规格', + model: '型号', + unit: '单位', + quantity: '数量', + unitPrice: '单价', + amount: '金额', + taxRate: '税率(%)', + taxAmount: '税额', + shipmentsDate: '出库时间', + total: '合计', + } + }, + storageDetail: { + title: '入库明细报表', + export: '导出', + regularPrint: '普通打印', + data: '入库明细数据', + detail: '入库明细', + notice: '当前查询条件下无数据可导出', + header: { + receiptNumber: '单据编号', + productInfo: '商品信息', + receiptDate: '单据日期', + startDate: '开始日期', + endDate: '结束日期', + contact: '往来人员', + warehouse: '仓库', + operator: '操作人', + remark: '单据备注', + }, + table: { + receiptNumber: '单据编号', + type: '类型', + contact: '往来人员', + barCode: '条码', + warehouse: '仓库', + name: '商品名称', + standard: '规格', + model: '型号', + unit: '单位', + quantity: '数量', + unitPrice: '单价', + amount: '金额', + taxRate: '税率(%)', + taxAmount: '税额', + storageDate: '入库时间', + total: '合计', + } + }, + shipmentsSummary: { + title: '出库汇总报表', + export: '导出', + regularPrint: '普通打印', + data: '出库汇总数据', + detail: '出库汇总', + notice: '当前查询条件下无数据可导出', + header: { + productInfo: '商品信息', + receiptDate: '单据日期', + startDate: '开始日期', + endDate: '结束日期', + contact: '往来人员', + warehouse: '仓库', + }, + table: { + barCode: '商品条码', + warehouse: '仓库', + name: '商品名称', + category: '商品分类', + standard: '规格', + model: '型号', + unit: '单位', + quantity: '出库数量', + amount: '出库金额', + shipmentsDate: '出库时间', + total: '合计', + } + }, + storageSummary: { + title: '入库汇总报表', + export: '导出', + regularPrint: '普通打印', + data: '入库汇总数据', + detail: '入库汇总', + notice: '当前查询条件下无数据可导出', + header: { + productInfo: '商品信息', + receiptDate: '单据日期', + startDate: '开始日期', + endDate: '结束日期', + contact: '往来人员', + warehouse: '仓库', + }, + table: { + barCode: '商品条码', + warehouse: '仓库', + name: '商品名称', + category: '商品分类', + standard: '规格', + model: '型号', + unit: '单位', + quantity: '入库数量', + amount: '入库金额', + storageDate: '入库时间', + total: '合计', + } + }, + customerBill: { + title: '客户对账报表', + export: '导出', + regularPrint: '普通打印', + data: '客户对账数据', + detail: '客户对账', + notice: '当前查询条件下无数据可导出', + header: { + customer: '客户', + billDate: '账单日期', + startDate: '开始日期', + endDate: '结束日期', + }, + table: { + arrearsDetail: '欠款详情', + detail: '详情', + customer: '客户', + contacts: '联系人', + contactNumber: '联系电话', + email: '电子邮箱', + firstQuarterCollection: '一季度应收账款', + secondQuarterCollection: '二季度应收账款', + thirdQuarterCollection: '三季度应收账款', + fourthQuarterCollection: '四季度应收账款', + totalArrears: '累计欠款', + totalCollection: '累计收款', + receivableArrears: '应收欠款', + helpMessage: '应收欠款=4个季度的应收账款+累计欠款', + total: '合计', + } + }, + supplierBill: { + title: '供应商对账报表', + export: '导出', + regularPrint: '普通打印', + data: '供应商对账数据', + detail: '供应商对账', + notice: '当前查询条件下无数据可导出', + header: { + supplier: '供应商', + billDate: '账单日期', + startDate: '开始日期', + endDate: '结束日期', + }, + table: { + arrearsDetail: '欠款详情', + detail: '详情', + supplier: '供应商', + contacts: '联系人', + contactNumber: '联系电话', + email: '电子邮箱', + firstQuarterPayment: '一季度应付账款', + secondQuarterPayment: '二季度应付账款', + thirdQuarterPayment: '三季度应付账款', + fourthQuarterPayment: '四季度应付账款', + totalArrears: '累计欠款', + totalPayment: '累计付款', + payableArrears: '应付欠款', + helpMessage: '应付欠款=4个季度的应付账款+累计欠款', + total: '合计', + } + }, + other: { + viewAccountFlow: '查看账户流水', + viewAccountFlowHelpMessage: '账户的流水统计是由前往后,最后面的余额是最终余额', + thisReceiptArrears: '本单欠款', + paidArrears: '已付欠款', + receivedArrears: '已收欠款', + receivableArrears: '待收欠款', + balance: '余额', + subType: '收款/付款方', + customerArrearsDetail: '客户欠款详情', + customerArrearsData: '客户欠款数据', + viewProductStockFlow: '查看商品库存流水', + stockFlowDetailData: '库存流水明细数据', + supplierArrearsDetail: '供应商欠款详情', + supplierArrearsData: '供应商欠款数据', + } +} \ No newline at end of file diff --git a/src/locales/lang/zh-CN/retail.ts b/src/locales/lang/zh-CN/retail.ts new file mode 100644 index 0000000..c7b4d9f --- /dev/null +++ b/src/locales/lang/zh-CN/retail.ts @@ -0,0 +1,185 @@ +export default { + selectData: '请选择一条数据', + modifyDataPrompt: '抱歉,只有未审核的单据才能编辑!', + regularPrint: '普通打印', + shipments:{ + title: '零售出库列表', + addShipments: '新增-零售出库', + editShipments: '编辑-零售出库', + detail: '零售出库-详情', + receipt: '单据详情', + table:{ + member: '会员', + receiptNumber: '单据编号', + productInformation: '商品信息', + productQuantity: '商品数量', + totalAmount: '金额合计', + amountCollection: '收款金额', + changeAmount: '找零金额', + receiptDate: '单据日期', + operator: '操作员', + status: '状态', + }, + header:{ + settlementAccount: '结算账户', + startDate: '开始日期', + endDate: '结束日期', + receiptRemark: '单据备注', + }, + export: { + name: '导出', + exportData: '零售出库数据 ', + noData: '无可用数据导出', + }, + form: { + member: '会员卡号', + inputMember: '请选择会员', + addMember: '新增会员', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + collectionType: '收款方式', + inputCollectionType: '请选择收款方式', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择零售产品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + inputBarCode: '请输入商品条码', + noticeOne: '请选择仓库', + noticeTwo: '请录入条码或者选择产品', + noticeThree: '需要在商品管理添加商品', + noticeFour: '确定要删除选中的数据?', + noticeFive: '该文件超过2MB大小限制', + noticeSix: '该条码查询不到商品信息', + noticeSeven: '商品库存不足,请检查库存数量', + advancePayment: '预付款', + cashPayment: '现付', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + warehouse: '仓库', + inputWarehouse: '请选择仓库', + barCode: '条码', + inputBarCode: '输入商品条码', + name: '名称', + standard: '规格', + model: '型号', + color: '颜色', + stock: '库存', + unit: '单位', + quantity: '数量', + unitPrice: '单价', + amount: '金额', + total: '合计', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + view: { + member: '会员', + receiptDate: '单据日期', + collectionType: '收款方式', + receiptAmount: '单据金额', + collectionAmount: '收款金额', + changeAmount: '找零金额', + collectionAccount: '收款账户', + inputCollectionAccount: '请选择收款账户', + addAccount: '新增账户', + refundReceipt: '退款单号', + remark: '备注', + status: '状态', + } + }, + refund:{ + title: '零售退货列表', + addRefund: '新增-零售退货', + editRefund: '编辑-零售退货', + detail: '零售退货-详情', + receipt: '单据详情', + table:{ + member: '会员', + receiptNumber: '单据编号', + productInformation: '商品信息', + totalAmount: '金额合计', + paymentAmount: '付款金额', + changeAmount: '找零金额', + receiptDate: '单据日期', + operator: '操作员', + status: '状态', + }, + header:{ + settlementAccount: '结算账户', + startDate: '开始日期', + endDate: '结束日期', + receiptRemark: '单据备注', + }, + export: { + name: '导出', + exportData: '零售退货数据 ', + noData: '无可用数据导出', + }, + form: { + member: '会员卡号', + inputMember: '请选择会员', + addMember: '新增会员', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + relatedReceipt: '关联单据', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择退货产品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请选择仓库', + noticeTwo: '请录入条码或者选择产品', + noticeThree: '需要在商品管理添加商品', + noticeFour: '确定要删除选中的数据?', + noticeFive: '该文件超过2MB大小限制', + noticeSix: '该条码查询不到商品信息', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + warehouse: '仓库', + inputWarehouse: '请选择仓库', + barCode: '条码', + inputBarCode: '输入商品条码', + name: '名称', + standard: '规格', + model: '型号', + color: '颜色', + stock: '库存', + unit: '单位', + quantity: '数量', + unitPrice: '单价', + amount: '金额', + total: '合计', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + view: { + member: '会员', + receiptDate: '单据日期', + receiptAmount: '单据金额', + paymentAmount: '付款金额', + changeAmount: '找零金额', + paymentAccount: '付款账户', + inputPaymentAccount: '请选择付款账户', + relatedReceipt: '关联单据', + addAccount: '新增账户', + remark: '备注', + status: '状态', + } + } +}; \ No newline at end of file diff --git a/src/locales/lang/zh-CN/routes/basic.ts b/src/locales/lang/zh-CN/routes/basic.ts new file mode 100644 index 0000000..3d03e8e --- /dev/null +++ b/src/locales/lang/zh-CN/routes/basic.ts @@ -0,0 +1,4 @@ +export default { + login: '登录', + errorLogList: '错误日志列表', +}; diff --git a/src/locales/lang/zh-CN/routes/dashboard.ts b/src/locales/lang/zh-CN/routes/dashboard.ts new file mode 100644 index 0000000..04b1b19 --- /dev/null +++ b/src/locales/lang/zh-CN/routes/dashboard.ts @@ -0,0 +1,6 @@ +export default { + dashboard: 'Dashboard', + about: '关于', + workbench: '工作台', + analysis: '分析页', +}; diff --git a/src/locales/lang/zh-CN/routes/demo.ts b/src/locales/lang/zh-CN/routes/demo.ts new file mode 100644 index 0000000..54f6482 --- /dev/null +++ b/src/locales/lang/zh-CN/routes/demo.ts @@ -0,0 +1,190 @@ +export default { + charts: { + baiduMap: '百度地图', + aMap: '高德地图', + googleMap: '谷歌地图', + charts: '图表', + map: '地图', + line: '折线图', + pie: '饼图', + }, + comp: { + comp: '组件', + basic: '基础组件', + transition: '动画组件', + countTo: '数字动画', + + scroll: '滚动组件', + scrollBasic: '基础滚动', + scrollAction: '滚动函数', + virtualScroll: '虚拟滚动', + + tree: 'Tree', + treeBasic: '基础树', + editTree: '可搜索/工具栏', + actionTree: '函数操作示例', + + modal: '弹窗扩展', + drawer: '抽屉扩展', + desc: '详情组件', + + verify: '验证组件', + verifyDrag: '拖拽校验', + verifyRotate: '图片还原', + + qrcode: '二维码组件', + strength: '密码强度组件', + upload: '上传组件', + + loading: 'Loading', + + time: '相对时间', + cropperImage: '图片裁剪', + cardList: '卡片列表', + }, + editor: { + editor: '编辑器', + jsonEditor: 'Json编辑器', + markdown: 'markdown编辑器', + + tinymce: '富文本', + tinymceBasic: '基础使用', + tinymceForm: '嵌入form', + }, + excel: { + excel: 'Excel', + customExport: '选择导出格式', + jsonExport: 'JSON数据导出', + arrayExport: 'Array数据导出', + importExcel: '导入', + }, + feat: { + feat: '功能', + icon: '图标', + sessionTimeout: '登录过期', + tabs: '标签页操作', + tabDetail: '标签详情页', + print: '打印', + contextMenu: '右键菜单', + download: '文件下载', + clickOutSide: 'ClickOutSide组件', + imgPreview: '图片预览', + copy: '剪切板', + msg: '消息提示', + watermark: '水印', + ripple: '水波纹', + fullScreen: '全屏', + errorLog: '错误日志', + tab: 'Tab带参', + tab1: 'Tab带参1', + tab2: 'Tab带参2', + menu: 'Menu带参', + menu1: 'Menu带参1', + menu2: 'Menu带参2', + ws: 'websocket测试', + breadcrumb: '面包屑导航', + breadcrumbFlat: '平级模式', + requestDemo: '测试请求重试', + breadcrumbFlatDetail: '平级详情', + breadcrumbChildren: '层级模式', + breadcrumbChildrenDetail: '层级详情', + }, + flow: { + name: '图形编辑器', + flowChart: '流程图', + }, + form: { + form: 'Form', + basic: '基础表单', + useForm: 'useForm', + refForm: 'RefForm', + advancedForm: '可收缩表单', + ruleForm: '表单验证', + dynamicForm: '动态表单', + customerForm: '自定义组件', + appendForm: '表单增删示例', + tabsForm: '标签页+多级field', + }, + iframe: { + frame: '外部页面', + antv: 'antVue文档(内嵌)', + doc: '项目文档(内嵌)', + docExternal: '项目文档(外链)', + }, + level: { level: '多级菜单' }, + page: { + page: '页面', + + form: '表单页', + formBasic: '基础表单', + formStep: '分步表单', + formHigh: '高级表单', + + desc: '详情页', + descBasic: '基础详情页', + descHigh: '高级详情页', + + result: '结果页', + resultSuccess: '成功页', + resultFail: '失败页', + + account: '个人页', + accountCenter: '个人中心', + accountSetting: '个人设置', + + exception: '异常页', + netWorkError: '网络错误', + notData: '无数据', + + list: '列表页', + listCard: '卡片列表', + listBasic: '标准列表', + listSearch: '搜索列表', + }, + permission: { + permission: '权限管理', + + front: '基于前端权限', + frontPage: '页面权限', + frontBtn: '按钮权限', + frontTestA: '权限测试页A', + frontTestB: '权限测试页B', + + back: '基于后台权限', + backPage: '页面权限', + backBtn: '按钮权限', + }, + setup: { + page: '引导页', + }, + system: { + moduleName: '系统管理', + account: '账号管理', + account_detail: '账号详情', + password: '修改密码', + dept: '部门管理', + menu: '菜单管理', + role: '角色管理', + }, + table: { + table: 'Table', + basic: '基础表格', + treeTable: '树形表格', + fetchTable: '远程加载示例', + fixedColumn: '固定列', + customerCell: '自定义列', + formTable: '开启搜索区域', + useTable: 'UseTable', + refTable: 'RefTable', + multipleHeader: '多级表头', + mergeHeader: '合并单元格', + expandTable: '可展开表格', + fixedHeight: '定高/头部自定义', + footerTable: '表尾行合计', + editCellTable: '可编辑单元格', + editRowTable: '可编辑行', + authColumn: '权限列', + resizeParentHeightTable: '继承父元素高度', + vxeTable: 'VxeTable', + }, +}; diff --git a/src/locales/lang/zh-CN/sales.ts b/src/locales/lang/zh-CN/sales.ts new file mode 100644 index 0000000..be68907 --- /dev/null +++ b/src/locales/lang/zh-CN/sales.ts @@ -0,0 +1,316 @@ +export default { + selectData: '请选择一条数据', + modifyDataPrompt: '抱歉,只有未审核的单据才能编辑!', + partialSales: '部分销售', + completeSales: '完成销售', + regularPrint: '普通打印', + order:{ + title: '销售订单列表', + addOrder: '新增-销售订单', + editOrder: '编辑-销售订单', + detail: '销售订单-详情', + receipt: '单据详情', + table:{ + customer: '客户', + receiptNumber: '单据编号', + productInformation: '商品信息', + productQuantity: '商品数量', + totalAmount: '金额合计', + totalIncludingTax: '含税合计', + collectDeposit: '收取定金', + receiptDate: '单据日期', + operator: '操作员', + status: '状态', + }, + header:{ + startDate: '开始日期', + endDate: '结束日期', + receiptRemark: '单据备注', + }, + form: { + customer: '客户', + inputCustomer: '请选择客户', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + salesPerson: '销售人员', + inputSalesPerson: '请选择销售人员', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择销售产品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '确定要删除选中的数据?', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '该条码查询不到商品信息', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + warehouse: '仓库', + barCode: '条码', + inputBarCode: '输入商品条码', + name: '名称', + standard: '规格', + model: '型号', + color: '颜色', + stock: '库存', + unit: '单位', + quantity: '数量', + unitPrice: '单价', + amount: '金额', + taxRate: '税率(%)', + taxAmount: '税额', + totalPriceAndTax: '价税合计', + total: '合计', + discount: '优惠率', + collectionDiscount: '收款优惠', + discountAmount: '优惠后金额', + account: '收款账户', + inputAccount: '请选择结算账户', + deposit: '收取定金', + remark: '备注', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + view: { + title: '销售订单表数据', + customer: '客户', + receiptDate: '单据日期', + settlementAccount: '收款账户', + discountRate: '优惠率', + collectionDiscount: '收款优惠', + discountAmount: '优惠后金额', + collectionDeposit: '收取定金', + remark: '备注', + status: '状态', + }, + export: { + name: '导出', + exportData: '销售订单数据 ', + noData: '无可用数据导出', + } + }, + shipments:{ + title: '销售出库列表', + addShipments: '新增-销售出库', + editShipments: '编辑-销售出库', + detail: '销售出库-详情', + receipt: '单据详情', + table:{ + customer: '客户', + receiptNumber: '单据编号', + productInformation: '商品信息', + productQuantity: '商品数量', + totalAmount: '金额合计', + totalIncludingTax: '含税合计', + collectAmount: '待收金额', + thisTimeCollectAmount: '本次收款', + thisTimeArrearsAmount: '本次欠款', + receiptDate: '单据日期', + operator: '操作员', + status: '状态', + }, + header:{ + startDate: '开始日期', + endDate: '结束日期', + receiptRemark: '单据备注', + }, + form: { + customer: '客户', + inputCustomer: '请选择客户', + addCustomer: '新增客户', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + relatedOrder: '关联订单', + inputRelatedOrder: '请选择关联订单', + inputSettlementAccount: '请选择结算账户', + addSettlementAccount: '新增结算账户', + inputSalesPerson: '请选择销售人员', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择销售产品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '确定要删除选中的数据?', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '该条码查询不到商品信息', + noticeFive: '请至少选择两个退款账户', + noticeSix: '请输入退款金额', + noticeSeven: '请输入本次收款金额', + noticeEight: '请选择仓库', + noticeNine: '商品库存不足,请检查库存数量', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + warehouse: '仓库', + barCode: '条码', + inputBarCode: '请输入商品条码', + name: '名称', + standard: '规格', + model: '型号', + color: '颜色', + stock: '库存', + unit: '单位', + quantity: '数量', + unitPrice: '单价', + amount: '金额', + taxRate: '税率(%)', + taxAmount: '税额', + totalPriceAndTax: '价税合计', + total: '合计', + discount: '优惠率', + collectionDiscount: '收款优惠', + discountAmount: '优惠后金额', + account: '收款账户', + inputAccount: '请选择结算账户', + deposit: '收取定金', + remark: '备注', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + view: { + title: '销售出库表数据', + customer: '客户', + receiptDate: '单据日期', + salesOrder: '销售订单', + settlementAccount: '收款账户', + discountRate: '优惠率', + collectionDiscount: '收款优惠', + receiptAmount: '单据金额', + discountAmount: '优惠后金额', + otherFees: '其他费用', + salesPerson: '销售人员', + thisTimeCollectAmount: '本次收款', + thisTimeArrearsAmount: '本次欠款', + remark: '备注', + status: '状态', + }, + export: { + name: '导出', + exportData: '销售出库数据 ', + noData: '无可用数据导出', + } + }, + refund:{ + title: '销售退货列表', + addRefund: '新增-销售退货', + editRefund: '编辑-销售退货', + detail: '销售退货-详情', + receipt: '单据详情', + table:{ + customer: '客户', + receiptNumber: '单据编号', + productInformation: '商品信息', + productQuantity: '商品数量', + totalAmount: '金额合计', + totalIncludingTax: '含税合计', + refundAmount: '待退金额', + thisRefundAmount: '本次退款', + thisArrearsAmount: '本次欠款', + receiptDate: '单据日期', + operator: '操作员', + status: '状态', + }, + header:{ + startDate: '开始日期', + endDate: '结束日期', + receiptRemark: '单据备注', + }, + form: { + customer: '客户', + inputCustomer: '请选择客户', + addCustomer: '新增客户', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + relatedShipments: '关联出库单据', + inputRelatedShipments: '请选择关联出库单据', + inputReturnAccount: '请选择退款账户', + addSettlementAccount: '新增结算账户', + inputSalesPerson: '请选择销售人员', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择退货产品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '确定要删除选中的数据?', + noticeThree: '该文件超过2MB大小限制', + noticeFour: '该条码查询不到商品信息', + noticeFive: '请至少选择两个退款账户', + noticeSix: '请输入退款金额', + noticeSeven: '请输入本次收款金额', + noticeEight: '请选择仓库', + noticeNine: '商品库存不足,请检查库存数量', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + warehouse: '仓库', + barCode: '条码', + inputBarCode: '请输入商品条码', + name: '名称', + standard: '规格', + model: '型号', + color: '颜色', + stock: '库存', + unit: '单位', + quantity: '数量', + unitPrice: '单价', + amount: '金额', + taxRate: '税率(%)', + taxAmount: '税额', + totalPriceAndTax: '价税合计', + total: '合计', + discount: '优惠率', + returnDiscount: '退款优惠', + discountAmount: '优惠后金额', + returnAccount: '退款账户', + inputAccount: '请选择退款账户', + deposit: '定金', + remark: '备注', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + view: { + title: '销售退货表数据', + customer: '客户', + receiptDate: '单据日期', + salesShipmentsReceipt: '销售出库单据', + returnAccount: '退款账户', + discountRate: '优惠率', + returnDiscount: '退款优惠', + receiptAmount: '单据金额', + discountAmount: '优惠后金额', + otherFees: '其他费用', + salesPerson: '销售人员', + thisTimeReturnAmount: '本次退款', + thisTimeArrearsAmount: '本次欠款', + remark: '备注', + status: '状态', + }, + export: { + name: '导出', + exportData: '销售退货数据 ', + noData: '无可用数据导出', + } + } +}; \ No newline at end of file diff --git a/src/locales/lang/zh-CN/sys.ts b/src/locales/lang/zh-CN/sys.ts new file mode 100644 index 0000000..bb1b282 --- /dev/null +++ b/src/locales/lang/zh-CN/sys.ts @@ -0,0 +1,174 @@ +export default { + api: { + operationSuccess: '操作成功', + operationFailed: '操作失败', + errorTip: '错误提示', + successTip: '成功提示', + errorMessage: '操作失败,系统异常!', + timeoutMessage: '登录超时,请重新登录!', + apiTimeoutMessage: '接口请求超时,请刷新页面重试!', + apiRequestFailed: '请求出错,请稍候重试', + networkException: '网络异常', + networkExceptionMsg: '网络异常,请检查您的网络连接是否正常!', + refreshBrowser: '网络当前繁忙,请按F5刷新浏览器', + + errMsg401: '用户没有权限(令牌、用户名、密码错误)!', + errMsg403: '用户得到授权,但是访问是被禁止的。!', + errMsg404: '网络请求错误,未找到该资源!', + errMsg405: '网络请求错误,请求方法未允许!', + errMsg408: '网络请求超时!', + errMsg500: '服务器错误,请联系管理员!', + errMsg501: '网络未实现!', + errMsg502: '网络错误!', + errMsg503: '服务不可用,服务器暂时过载或维护!', + errMsg504: '网络超时!', + errMsg505: 'http版本不支持该请求!', + }, + app: { logoutTip: '温馨提醒', logoutMessage: '是否确认退出系统?', menuLoading: '菜单加载中...' }, + errorLog: { + tableTitle: '错误日志列表', + tableColumnType: '类型', + tableColumnDate: '时间', + tableColumnFile: '文件', + tableColumnMsg: '错误信息', + tableColumnStackMsg: 'stack信息', + + tableActionDesc: '详情', + + modalTitle: '错误详情', + + fireVueError: '点击触发vue错误', + fireResourceError: '点击触发资源加载错误', + fireAjaxError: '点击触发ajax错误', + + enableMessage: '只在`/src/settings/projectSetting.ts` 内的useErrorHandle=true时生效.', + }, + exception: { + backLogin: '返回登录', + backHome: '返回首页', + subTitle403: '抱歉,您无权访问此页面。', + subTitle404: '抱歉,您访问的页面不存在。', + subTitle500: '抱歉,服务器报告错误。', + noDataTitle: '当前页无数据', + networkErrorTitle: '网络错误', + networkErrorSubTitle: '抱歉,您的网络连接已断开,请检查您的网络!', + }, + lock: { + unlock: '点击解锁', + alert: '锁屏密码错误', + backToLogin: '返回登录', + entry: '进入系统', + placeholder: '请输入锁屏密码或者用户密码', + }, + login: { + captcha: '验证码', + backSignIn: '返回', + signInFormTitle: '登录', + mobileSignInFormTitle: '手机登录', + qrSignInFormTitle: '扫码登录', + emailFormTitle: '邮箱登录', + signUpFormTitle: '注册租户', + forgetFormTitle: '重置密码', + + signInTitle: '为企业提供下一代智能ERP系统软件', + signInDesc: '© 2023-2033 Wan Sen ERP - All Right Reserved 版权所有', + policy: '我同意,《万森ERP系统》隐私政策', + scanSign: `扫码后点击"确认",即可完成登录`, + + loginButton: '登录', + registerButton: '注册租户', + rememberMe: '记住我', + forgetPassword: '忘记密码?', + otherSignIn: '其他登录方式', + + // notify + loginSuccessTitle: '登录成功', + loginSuccessDesc: '欢迎回来', + + // placeholder + accountPlaceholder: '请输入账号', + passwordPlaceholder: '请输入密码', + captchaPlaceholder: '请输入验证码', + smsPlaceholder: '请输入验证码', + mobilePlaceholder: '请输入手机号码', + emailPlaceholder: '请输入邮箱地址', + policyPlaceholder: '勾选后才能注册', + diffPwd: '两次输入密码不一致', + correctMobilePlaceholder: '请输入正确的手机号码', + correctEmailPlaceholder: '请输入正确的邮箱地址', + userName: '账号', + password: '密码', + confirmPassword: '确认密码', + newPassword: '新密码', + updatePassword: '修改密码', + email: '邮箱', + emailCode: '邮箱验证码', + smsCode: '短信验证码', + mobile: '手机号码', + }, + user: { + userList: '用户列表', + name: '昵称', + status: '用户状态', + roleName: '角色', + department: '所属部门', + remake: '备注', + addAccount: '新增账户', + editAccount: '编辑账户', + notAllowAddUser: '当前租户可添加的用户数量已达上限', + // 用户数据表格操作 + viewUserDetails: '查看用户详情', + editUserProfile: '编辑用户资料', + resetUserPassword: '重置密码', + confirmPasswordReset: '确定重置密码为123456吗', + deleteUserAccount: '删除账号' + }, + tenant: { + tenantList: '租户列表', + addTenant: '新增租户', + editTenant: '编辑租户', + deleteTenant: '删除租户', + form: { + name: '租户名称', + status: '租户状态', + free: '免费租户', + pay: '付费租户', + type: '租户类型', + remark: '备注', + userNumLimit: '用户数量限制', + expireTime: '到期时间', + noticeOne: '请默认选择租户管理员角色', + noticeTwo: '如果不填写,则默认密码为123456', + noticeThree: '不能输入带有admin的用户名', + noticeFour: '到期后租户下的所有用户无法登录使用系统', + } + }, + table: { + add: '新增', + edit: '编辑', + delete: '删除', + batchDelete: '批量删除', + exportData: '导出数据', + approve: '审核', + reject: '驳回', + audited: '已审核', + unaudited: '未审核', + viewReceiptDetails: '查看单据详情', + confirmDelete: '是否确认删除数据?', + confirmExport: '确认导出', + confirmExportTextOne: '导出', + confirmExportTextTwo: '数据加载中,请耐心等待。', + confirmExportTextThree: '如果您需要导出详细数据(可能需要很长时间),请勾选下面的框。', + confirmExportTextFour: '需要导出详细数据', + type: '类型', + subType: '子类型', + }, + modal: { + cover: '确认', + cancel: '取消', + }, + language: { + enUS: 'English', + zhCN: '简体中文', + } +}; diff --git a/src/locales/lang/zh-CN/system.ts b/src/locales/lang/zh-CN/system.ts new file mode 100644 index 0000000..4aa9f3f --- /dev/null +++ b/src/locales/lang/zh-CN/system.ts @@ -0,0 +1,129 @@ +export default { + selectData: '请选择一条数据', + modifyDataPrompt: '抱歉,只有未审核的单据才能编辑!', + role: { + title: '角色列表', + addRole: '新增角色', + editRole: '编辑角色', + menuAllocation: '菜单分配', + titleNotice: '角色列表可以给角色赋予不同的权限, 点击操作栏中的齿轮按钮', + header: { + roleName: '角色名称', + status: '状态', + viewAllData: '查看全部数据', + allData: '全部数据', + viewPersonalData: '查看个人数据', + personalData: '个人数据', + blockPurchasePrice: '屏蔽采购价', + blockSalesPrice: '屏蔽销售价', + blockRetailPrice: '屏蔽零售价', + enable: '启用', + disable: '停用', + }, + table: { + roleName: '角色名称', + type: '类型', + priceBlocking: '价格屏蔽', + status: '状态', + remark: '备注', + createTime: '创建时间', + action: '操作', + }, + form: { + roleName: '角色名称', + type: '类型', + priceBlocking: '价格屏蔽', + status: '状态', + remark: '备注', + } + }, + department: { + title: '部门列表', + addDepartment: '新增部门', + editDepartment: '编辑部门', + header: { + name: '部门名称', + }, + table: { + name: '部门名称', + number: '部门编号', + manager: '部门负责人', + status: '状态', + createTime: '创建时间', + remark: '备注', + action: '操作', + }, + form: { + name: '部门名称', + number: '部门编号', + parent: '上级部门', + manager: '部门负责人', + status: '状态', + sort: '排序', + remark: '备注', + enable: '启用', + disable: '停用', + notice: '如果不填写,则默认为父级部门', + } + }, + menu: { + title: '菜单列表', + addMenu: '新增菜单', + editMenu: '编辑菜单', + table: { + menuTitle: '菜单标题', + icon: '图标', + path: '路径', + component: '组件', + sort: '排序', + status: '状态', + createTime: '创建时间', + }, + form:{ + menuType: '菜单类型', + catalogue: '目录', + menu: '菜单', + rootMenu: '根菜单', + menuName: '菜单名称', + menuTitle: '菜单标题', + menuEnglishTitle: '菜单英文标题', + parent: '上级菜单', + sort: '排序', + icon: '图标', + routeAddress: '路由地址', + componentPath: '组件路径', + status: '状态', + enable: '启用', + disable: '停用', + isExternalLink: '是否外链', + isCached: '是否缓存', + isDisplayed: '是否显示', + yes: '是', + no: '否', + notice: '如果不填写,则默认为目录' + } + }, + configure: { + title: '系统配置', + tip: '此页面功能主要对当前系统进行一些配置。', + name: '公司名称', + inputName: '请输入公司名称', + contact: '联系人', + inputContact: '请输入联系人', + address: '公司地址', + inputAddress: '请输入公司地址', + phone: '公司电话', + inputPhone: '请输入公司电话', + fax: '公司传真', + inputFax: '请输入公司传真', + postalCode: '邮编', + inputPostalCode: '请输入邮编', + salesProtocol: '销售协议', + inputSalesProtocol: '请输入销售协议', + noticeOne: '更换公司名称后,请刷新浏览器生效', + noticeTwo: '选填', + submit: '提交', + updateSuccess: '更新成功', + updateFailed: '更新失败', + } +} \ No newline at end of file diff --git a/src/locales/lang/zh-CN/warehouse.ts b/src/locales/lang/zh-CN/warehouse.ts new file mode 100644 index 0000000..3c64b00 --- /dev/null +++ b/src/locales/lang/zh-CN/warehouse.ts @@ -0,0 +1,395 @@ +export default { + selectData: '请选择一条数据', + modifyDataPrompt: '抱歉,只有未审核的单据才能编辑!', + regularPrint: '普通打印', + otherStorage: { + title: '其他入库列表', + add: '新增', + batchDelete: '批量删除', + addOtherStorage: '新增-其他入库', + editOtherStorage: '编辑-其他入库', + detailOtherStorage: '其他入库-详情', + detailReceipt: '其他入库单单据-详情', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + supplierName: '供应商', + operator: '操作员', + status: '状态', + remark: '备注', + }, + table: { + supplierName: '供应商', + receiptNumber: '单据编号', + productInfo: '商品信息', + receiptDate: '单据日期', + productNumber: '数量', + totalAmount: '金额合计', + operator: '操作员', + status: '状态', + operate: '操作', + }, + form: { + supplierName: '供应商', + inputSupplier: '请选择供应商', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择添加入库商品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '请选择仓库', + noticeThree: '仓库不能为空', + noticeFour: '商品条码不能为空', + noticeFive: '其他入/出库没有金额信息,若需要可自行修改', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + warehouse: '仓库', + inputWarehouse: '请选择仓库', + barCode: '条码', + inputBarCode: '输入商品条码', + name: '名称', + standard: '规格', + stock: '库存', + unit: '单位', + quantity: '数量', + unitPrice: '单价', + amount: '金额', + remark: '备注', + total: '合计', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + view: { + warehouseName: '仓库名称', + barCode: '条码', + productName: '商品名称', + productStandard: '商品规格', + productModel: '商品型号', + productExtendInfo: '扩展信息', + stock: '库存', + productUnit: '单位', + productNumber: '数量', + unitPrice: '单价', + amount: '金额', + remark: '备注', + }, + export: { + name: '导出', + exportData: '其他入库数据 ', + noData: '无可用数据导出', + } + }, + otherShipments: { + title: '其他出库列表', + add: '新增', + batchDelete: '批量删除', + addOtherShipments: '新增-其他出库', + editOtherShipments: '编辑-其他出库', + detailOtherShipments: '其他出库-详情', + detailReceipt: '其他出库单单据-详情', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + customer: '客户', + operator: '操作员', + status: '状态', + remark: '备注', + }, + table: { + customer: '客户', + receiptNumber: '单据编号', + productInfo: '商品信息', + receiptDate: '单据日期', + productNumber: '数量', + totalAmount: '金额合计', + operator: '操作员', + status: '状态', + operate: '操作', + }, + form: { + customer: '客户', + inputCustomer: '请选择客户', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择添加入库商品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '请选择仓库', + noticeThree: '仓库不能为空', + noticeFour: '商品条码不能为空', + noticeFive: '其他入/出库没有金额信息,若需要可自行修改', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + }, + export: { + name: '导出', + exportData: '其他出库数据 ', + noData: '无可用数据导出', + } + }, + allotShipments: { + title: '调拨出库列表', + add: '新增', + batchDelete: '批量删除', + addAllotShipments: '新增-调拨出库', + editAllotShipments: '编辑-调拨出库', + detailAllotShipments: '调拨出库-详情', + detailReceipt: '调拨出库单单据-详情', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + operator: '操作员', + status: '状态', + remark: '备注', + }, + table: { + receiptNumber: '单据编号', + productInfo: '商品信息', + receiptDate: '单据日期', + productNumber: '数量', + operator: '操作员', + status: '状态', + operate: '操作', + }, + form: { + outWarehouse: '调出仓库', + inputOutWarehouse: '请选择调出仓库', + inWarehouse: '调入仓库', + inputInWarehouse: '请选择调入仓库', + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择添加入库商品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '请选择仓库', + noticeThree: '调出方仓库不能为空', + noticeFour: '商品条码不能为空', + noticeFive: '调入方仓库不能为空', + noticeSex: '输入条码商品信息自动带出!', + total: '合计', + inputRemark: '请输入备注', + inputSalePrice: '请输入销售价格', + annex: '附件', + uploadAnnex: '上传附件', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + outWarehouse: '调出仓库', + barCode: '条码', + inputBarCode: '请选择商品条码', + name: '名称', + standard: '规格', + model: '型号', + stock: '库存', + extendInfo: '扩展信息', + inWarehouse: '调入仓库', + salePrice: '销售价格', + unit: '单位', + quantity: '数量', + remark: '备注', + } + }, + export: { + name: '导出', + exportData: '调拨出库数据 ', + noData: '无可用数据导出', + } + }, + assemble: { + title: '组装单列表', + add: '新增', + batchDelete: '批量删除', + addAssemble: '新增-组装单', + editAssemble: '编辑-组装单', + detailAssemble: '组装单-详情', + detailReceipt: '组装单单据-详情', + assemblyComponents: '组合件', + subComponents: '普通子件', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + operator: '操作员', + status: '状态', + remark: '备注', + }, + table: { + receiptNumber: '单据编号', + productInfo: '商品信息', + receiptDate: '单据日期', + productNumber: '数量', + totalAmount: '金额合计', + operator: '操作员', + status: '状态', + }, + form: { + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择添加入库商品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '请选择仓库', + noticeThree: '仓库不能为空', + noticeFour: '商品条码不能为空', + noticeFive: '输入条码商品信息自动带出!', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + productType: '商品类型', + warehouse: '仓库', + inputWarehouse: '请选择仓库', + barCode: '条码', + inputBarCode: '输入商品条码', + name: '名称', + standard: '规格', + stock: '库存', + unit: '单位', + quantity: '数量', + purchasePrice: '采购价', + amount: '金额', + remark: '备注', + total: '合计', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + view: { + productType: '商品类型', + warehouseName: '仓库名称', + barCode: '条码', + productName: '商品名称', + productStandard: '规格', + productModel: '型号', + productExtendInfo: '扩展信息', + stock: '库存', + productUnit: '单位', + productNumber: '数量', + purchasePrice: '采购价', + amount: '金额', + remark: '备注', + }, + export: { + name: '导出', + exportData: '组装单数据 ', + noData: '无可用数据导出', + } + }, + disassemble: { + title: '拆卸单列表', + add: '新增', + batchDelete: '批量删除', + addDisassemble: '新增-拆卸单', + editDisassemble: '编辑-拆卸单', + detailDisassemble: '拆卸单-详情', + detailReceipt: '拆卸单单据-详情', + header: { + receiptNumber: '单据编号', + receiptDate: '单据日期', + starDate: '开始日期', + endDate: '结束日期', + operator: '操作员', + status: '状态', + remark: '备注', + }, + table: { + receiptNumber: '单据编号', + productInfo: '商品信息', + receiptDate: '单据日期', + productNumber: '数量', + totalAmount: '金额合计', + operator: '操作员', + status: '状态', + }, + form: { + receiptDate: '单据日期', + inputReceiptDate: '请选择单据日期', + receiptNumber: '单据编号', + inputReceiptNumber: '请输入单据编号', + scanCodeData: '扫码录入数据', + collapseScanCode: '收起扫码', + scanCodeTip: '鼠标点击此次', + addProduct: '选择添加商品', + insertRow: '添加一行', + deleteRow: '删除选中行', + addRowData: '请添加一行数据', + noticeOne: '请录入条码或者选择产品', + noticeTwo: '请选择仓库', + noticeThree: '仓库不能为空', + noticeFour: '商品条码不能为空', + noticeFive: '输入条码商品信息自动带出!', + cancel: '取消', + save: '保存', + saveApprove: '保存并审核', + table: { + productType: '商品类型', + warehouse: '仓库', + inputWarehouse: '请选择仓库', + barCode: '条码', + inputBarCode: '输入商品条码', + name: '名称', + standard: '规格', + stock: '库存', + unit: '单位', + quantity: '数量', + purchasePrice: '采购价', + amount: '金额', + remark: '备注', + total: '合计', + inputRemark: '请输入备注', + annex: '附件', + uploadAnnex: '上传附件', + } + }, + export: { + name: '导出', + exportData: '拆卸单数据 ', + noData: '无可用数据导出', + } + } +} \ No newline at end of file diff --git a/src/locales/lang/zh_CN.ts b/src/locales/lang/zh_CN.ts new file mode 100644 index 0000000..8fc3305 --- /dev/null +++ b/src/locales/lang/zh_CN.ts @@ -0,0 +1,10 @@ +import { genMessage } from '../helper'; +import antdLocale from 'ant-design-vue/es/locale/zh_CN'; + +const modules = import.meta.glob('./zh-CN/**/*.ts', { eager: true }); +export default { + message: { + ...genMessage(modules as Recordable, 'zh-CN'), + antdLocale, + }, +}; diff --git a/src/locales/setupI18n.ts b/src/locales/setupI18n.ts new file mode 100644 index 0000000..405fb0c --- /dev/null +++ b/src/locales/setupI18n.ts @@ -0,0 +1,44 @@ +import type { App } from 'vue'; +import type { I18n, I18nOptions } from 'vue-i18n'; + +import { createI18n } from 'vue-i18n'; +import { setHtmlPageLang, setLoadLocalePool } from './helper'; +import { localeSetting } from '/@/settings/localeSetting'; +import { useLocaleStoreWithOut } from '/@/store/modules/locale'; + +const { fallback, availableLocales } = localeSetting; + +export let i18n: ReturnType; + +async function createI18nOptions(): Promise { + const localeStore = useLocaleStoreWithOut(); + const locale = localeStore.getLocale; + const defaultLocal = await import(`./lang/${locale}.ts`); + const message = defaultLocal.default?.message ?? {}; + + setHtmlPageLang(locale); + setLoadLocalePool((loadLocalePool) => { + loadLocalePool.push(locale); + }); + + return { + legacy: false, + locale, + fallbackLocale: fallback, + messages: { + [locale]: message, + }, + availableLocales: availableLocales, + sync: true, //If you don’t want to inherit locale from global scope, you need to set sync of i18n component option to false. + silentTranslationWarn: true, // true - warning off + missingWarn: false, + silentFallbackWarn: true, + }; +} + +// setup i18n instance with glob +export async function setupI18n(app: App) { + const options = await createI18nOptions(); + i18n = createI18n(options) as I18n; + app.use(i18n); +} diff --git a/src/locales/useLocale.ts b/src/locales/useLocale.ts new file mode 100644 index 0000000..dca61c0 --- /dev/null +++ b/src/locales/useLocale.ts @@ -0,0 +1,70 @@ +/** + * Multi-language related operations + */ +import type { LocaleType } from '/#/config'; + +import { i18n } from './setupI18n'; +import { useLocaleStoreWithOut } from '@/store/modules/locale'; +import { unref, computed } from 'vue'; +import { loadLocalePool, setHtmlPageLang } from './helper'; + +interface LangModule { + message: Recordable; + dateLocale: Recordable; + dateLocaleName: string; +} + +function setI18nLanguage(locale: LocaleType) { + const localeStore = useLocaleStoreWithOut(); + + if (i18n.mode === 'legacy') { + i18n.global.locale = locale; + } else { + (i18n.global.locale as any).value = locale; + } + localeStore.setLocaleInfo({ locale }); + setHtmlPageLang(locale); +} + +export function useLocale() { + const localeStore = useLocaleStoreWithOut(); + const getLocale = computed(() => localeStore.getLocale); + const getShowLocalePicker = computed(() => localeStore.getShowPicker); + + const getAntdLocale = computed((): any => { + return i18n.global.getLocaleMessage(unref(getLocale))?.antdLocale ?? {}; + }); + + // Switching the language will change the locale of useI18n + // And submit to configuration modification + async function changeLocale(locale: LocaleType) { + const globalI18n = i18n.global; + const currentLocale = unref(globalI18n.locale); + + if (currentLocale === locale) { + return locale; + } + + if (loadLocalePool.includes(locale)) { + setI18nLanguage(locale); + return locale; + } + const langModule = ((await import(`./lang/${locale}.ts`)) as any).default as LangModule; + if (!langModule) return; + + const { message } = langModule; + + globalI18n.setLocaleMessage(locale, message); + loadLocalePool.push(locale); + + setI18nLanguage(locale); + return locale; + } + + return { + getLocale, + getShowLocalePicker, + changeLocale, + getAntdLocale, + }; +} diff --git a/src/logics/.DS_Store b/src/logics/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..21c3d5fde24877f8063a515513426819e2cb78bf GIT binary patch literal 6148 zcmeHKu};G<5PfcoR78i02{CzKW$4BjO8A2Q0F+h)DIrx=_WTdOf%q=o`K*wTrVrFvk{`$Z(HmtUBIi_=^n4 z-c7K^mcNqvxqms<`QvQyP!=0q`048*-=a*@WnM1nBM-~P&DHz$VgJ>){5M&1EuK?j zgaS|4Vb@;guxyU?tgDVK%DwBT$J=@3e}W_C%*a{sm7(*u_GnM;Mto29hDSSp+zMHR zi7{Xd7z00NfHhlWe4=QrF<=ZB12qHke(+SmBx0o)UL9=05r8;f47gFcNawtzSX( v.replace(/^\s*|\s*$/g, '')) // Remove extra spaces + .join('~') // Manually add separators for later display + .replace(/\?[^:]+/gi, ''); // Remove redundant parameters of js file links (?x=1 and the like) + const msg = error.toString(); + if (stack.indexOf(msg) < 0) { + stack = msg + '@' + stack; + } + return stack; +} + +/** + * get comp name + * @param vm + */ +function formatComponentName(vm: any) { + if (vm.$root === vm) { + return { + name: 'root', + path: 'root', + }; + } + + const options = vm.$options as any; + if (!options) { + return { + name: 'anonymous', + path: 'anonymous', + }; + } + const name = options.name || options._componentTag; + return { + name: name, + path: options.__file, + }; +} + +/** + * Configure Vue error handling function + */ + +function vueErrorHandler(err: Error, vm: any, info: string) { + const errorLogStore = useErrorLogStoreWithOut(); + const { name, path } = formatComponentName(vm); + errorLogStore.addErrorLogInfo({ + type: ErrorTypeEnum.VUE, + name, + file: path, + message: err.message, + stack: processStackMsg(err), + detail: info, + url: window.location.href, + }); +} + +/** + * Configure script error handling function + */ +export function scriptErrorHandler( + event: Event | string, + source?: string, + lineno?: number, + colno?: number, + error?: Error, +) { + if (event === 'Script error.' && !source) { + return false; + } + const errorInfo: Partial = {}; + colno = colno || (window.event && (window.event as any).errorCharacter) || 0; + errorInfo.message = event as string; + if (error?.stack) { + errorInfo.stack = error.stack; + } else { + errorInfo.stack = ''; + } + const name = source ? source.substr(source.lastIndexOf('/') + 1) : 'script'; + const errorLogStore = useErrorLogStoreWithOut(); + errorLogStore.addErrorLogInfo({ + type: ErrorTypeEnum.SCRIPT, + name: name, + file: source as string, + detail: 'lineno' + lineno, + url: window.location.href, + ...(errorInfo as Pick), + }); + return true; +} + +/** + * Configure Promise error handling function + */ +function registerPromiseErrorHandler() { + window.addEventListener( + 'unhandledrejection', + function (event) { + const errorLogStore = useErrorLogStoreWithOut(); + errorLogStore.addErrorLogInfo({ + type: ErrorTypeEnum.PROMISE, + name: 'Promise Error!', + file: 'none', + detail: 'promise error!', + url: window.location.href, + stack: 'promise error!', + message: event.reason, + }); + }, + true, + ); +} + +/** + * Configure monitoring resource loading error handling function + */ +function registerResourceErrorHandler() { + // Monitoring resource loading error(img,script,css,and jsonp) + window.addEventListener( + 'error', + function (e: Event) { + const target = e.target ? e.target : (e.srcElement as any); + const errorLogStore = useErrorLogStoreWithOut(); + errorLogStore.addErrorLogInfo({ + type: ErrorTypeEnum.RESOURCE, + name: 'Resource Error!', + file: (e.target || ({} as any)).currentSrc, + detail: JSON.stringify({ + tagName: target.localName, + html: target.outerHTML, + type: e.type, + }), + url: window.location.href, + stack: 'resource is not found', + message: (e.target || ({} as any)).localName + ' is load error', + }); + }, + true, + ); +} + +/** + * Configure global error handling + * @param app + */ +export function setupErrorHandle(app: App) { + const { useErrorHandle } = projectSetting; + if (!useErrorHandle) { + return; + } + // Vue exception monitoring; + app.config.errorHandler = vueErrorHandler; + + // script error + window.onerror = scriptErrorHandler; + + // promise exception + registerPromiseErrorHandler(); + + // Static resource exception + registerResourceErrorHandler(); +} diff --git a/src/logics/initAppConfig.ts b/src/logics/initAppConfig.ts new file mode 100644 index 0000000..644066d --- /dev/null +++ b/src/logics/initAppConfig.ts @@ -0,0 +1,88 @@ +/** + * Application configuration + */ +import type { ProjectConfig } from '/#/config'; + +import { PROJ_CFG_KEY } from '/@/enums/cacheEnum'; +import projectSetting from '/@/settings/projectSetting'; + +import { + updateTextColor, + updateBorderColor, + updateHeaderBgColor, + updateSidebarBgColor, + updateComponentBgColor, + updateAppContentBgColor, +} from '/@/logics/theme/updateBackground'; +import { updateColorWeak } from '/@/logics/theme/updateColorWeak'; +import { updateGrayMode } from '/@/logics/theme/updateGrayMode'; +import { updateDarkTheme } from '/@/logics/theme/dark'; + +import { useAppStore } from '/@/store/modules/app'; +import { useLocaleStore } from '/@/store/modules/locale'; + +import { getCommonStoragePrefix, getStorageShortName } from '/@/utils/env'; + +import { Persistent } from '/@/utils/cache/persistent'; +import { deepMerge } from '/@/utils'; +import { ThemeEnum } from '/@/enums/appEnum'; + +// Initial project configuration +export function initAppConfigStore() { + const localeStore = useLocaleStore(); + const appStore = useAppStore(); + let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig; + projCfg = deepMerge(projectSetting, projCfg || {}); + const darkMode = appStore.getDarkMode; + const { + colorWeak, + grayMode, + + headerSetting: { bgColor: headerBgColor } = {}, + menuSetting: { bgColor } = {}, + } = projCfg; + try { + grayMode && updateGrayMode(grayMode); + colorWeak && updateColorWeak(colorWeak); + } catch (error) { + console.log(error); + } + appStore.setProjectConfig(projCfg); + + // init dark mode + updateDarkTheme(darkMode); + updateTextColor(); + updateBorderColor(); + updateComponentBgColor(); + updateAppContentBgColor(); + if (darkMode === ThemeEnum.DARK) { + updateHeaderBgColor(); + updateSidebarBgColor(); + } else { + headerBgColor && updateHeaderBgColor(headerBgColor); + bgColor && updateSidebarBgColor(bgColor); + } + // init store + localeStore.initLocale(); + + setTimeout(() => { + clearObsoleteStorage(); + }, 16); +} + +/** + * As the version continues to iterate, there will be more and more cache keys stored in localStorage. + * This method is used to delete useless keys + */ +export function clearObsoleteStorage() { + const commonPrefix = getCommonStoragePrefix(); + const shortPrefix = getStorageShortName(); + + [localStorage, sessionStorage].forEach((item: Storage) => { + Object.keys(item).forEach((key) => { + if (key && key.startsWith(commonPrefix) && !key.startsWith(shortPrefix)) { + item.removeItem(key); + } + }); + }); +} \ No newline at end of file diff --git a/src/logics/mitt/routeChange.ts b/src/logics/mitt/routeChange.ts new file mode 100644 index 0000000..a985fe2 --- /dev/null +++ b/src/logics/mitt/routeChange.ts @@ -0,0 +1,31 @@ +/** + * Used to monitor routing changes to change the status of menus and tabs. There is no need to monitor the route, because the route status change is affected by the page rendering time, which will be slow + */ + +import { mitt } from '/@/utils/mitt'; +import type { RouteLocationNormalized } from 'vue-router'; +import { getRawRoute } from '/@/utils'; + +const emitter = mitt(); + +const key = Symbol(); + +let lastChangeTab: RouteLocationNormalized; + +export function setRouteChange(lastChangeRoute: RouteLocationNormalized) { + const r = getRawRoute(lastChangeRoute); + emitter.emit(key, r); + lastChangeTab = r; +} + +export function listenerRouteChange( + callback: (route: RouteLocationNormalized) => void, + immediate = true, +) { + emitter.on(key, callback); + immediate && lastChangeTab && callback(lastChangeTab); +} + +export function removeTabChangeListener() { + emitter.clear(); +} diff --git a/src/logics/theme/dark.ts b/src/logics/theme/dark.ts new file mode 100644 index 0000000..bf6c34a --- /dev/null +++ b/src/logics/theme/dark.ts @@ -0,0 +1,20 @@ +import { addClass, hasClass, removeClass } from '/@/utils/domUtils'; + +export async function updateDarkTheme(mode: string | null = 'light') { + const htmlRoot = document.getElementById('htmlRoot'); + if (!htmlRoot) { + return; + } + const hasDarkClass = hasClass(htmlRoot, 'dark'); + if (mode === 'dark') { + htmlRoot.setAttribute('data-theme', 'dark'); + if (!hasDarkClass) { + addClass(htmlRoot, 'dark'); + } + } else { + htmlRoot.setAttribute('data-theme', 'light'); + if (hasDarkClass) { + removeClass(htmlRoot, 'dark'); + } + } +} diff --git a/src/logics/theme/index.ts b/src/logics/theme/index.ts new file mode 100644 index 0000000..d8e80b7 --- /dev/null +++ b/src/logics/theme/index.ts @@ -0,0 +1 @@ +export async function changeTheme(_color: string) {} diff --git a/src/logics/theme/updateBackground.ts b/src/logics/theme/updateBackground.ts new file mode 100644 index 0000000..eea1997 --- /dev/null +++ b/src/logics/theme/updateBackground.ts @@ -0,0 +1,198 @@ +import { colorIsDark, lighten, darken } from '/@/utils/color'; +import { useAppStore } from '/@/store/modules/app'; +import { ThemeEnum } from '/@/enums/appEnum'; +import { setCssVar } from './util'; + +const TEXT_COLOR_VAR = '--text-color'; + +const BORDER_COLOR_VAR = '--border-color'; + +const HEADER_BG_COLOR_VAR = '--header-bg-color'; +const HEADER_BG_HOVER_COLOR_VAR = '--header-bg-hover-color'; +const HEADER_MENU_ACTIVE_BG_COLOR_VAR = '--header-active-menu-bg-color'; + +const SIDER_DARK_BG_COLOR = '--sider-dark-bg-color'; +const SIDER_DARK_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color'; +const SIDER_LIGHTEN_BG_COLOR = '--sider-dark-lighten-bg-color'; + +const COMPONENT_BACKGROUND_COLOR = '--component-background-color'; + +const APP_CONTENT_BACKGROUND_COLOR = '--app-content-background-color'; + +/** + * Change the text color of the html + * @param color + */ +export function updateTextColor(color?: string) { + const appStore = useAppStore(); + const darkMode = appStore.getDarkMode === ThemeEnum.DARK; + if (!color) { + if (darkMode) { + color = '#c9d1d9'; + } else { + color = 'rgb(0, 0, 0, 0.85)'; + } + } + + // text color + setCssVar(TEXT_COLOR_VAR, color); + + // only #ffffff is light + // Only when the background color is #fff, the theme of the menu will be changed to light + const isLight = ['#fff', '#ffffff'].includes(color!.toLowerCase()); + + appStore.setProjectConfig({ + menuSetting: { + theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK, + }, + }); +} + +/** + * Change the border color of the border + * @param color + */ +export function updateBorderColor(color?: string) { + const appStore = useAppStore(); + const darkMode = appStore.getDarkMode === ThemeEnum.DARK; + if (!color) { + if (darkMode) { + color = '#303030'; + } else { + color = '#eee'; + } + } + + // text color + setCssVar(BORDER_COLOR_VAR, color); + + // only #ffffff is light + // Only when the background color is #fff, the theme of the menu will be changed to light + const isLight = ['#fff', '#ffffff'].includes(color!.toLowerCase()); + + appStore.setProjectConfig({ + menuSetting: { + theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK, + }, + }); +} + +/** + * Change the background color of the top header + * @param color + */ +export function updateHeaderBgColor(color?: string) { + const appStore = useAppStore(); + const darkMode = appStore.getDarkMode === ThemeEnum.DARK; + if (!color) { + if (darkMode) { + color = '#151515'; + } else { + color = appStore.getHeaderSetting.bgColor; + } + } + + // bg color + setCssVar(HEADER_BG_COLOR_VAR, color); + + // hover color + const hoverColor = lighten(color!, 6); + setCssVar(HEADER_BG_HOVER_COLOR_VAR, hoverColor); + setCssVar(HEADER_MENU_ACTIVE_BG_COLOR_VAR, hoverColor); + + // Determine the depth of the color value and automatically switch the theme + const isDark = colorIsDark(color!); + + appStore.setProjectConfig({ + headerSetting: { + theme: isDark || darkMode ? ThemeEnum.DARK : ThemeEnum.LIGHT, + }, + }); +} + +/** + * Change the background color of the left menu + * @param color bg color + */ +export function updateSidebarBgColor(color?: string) { + const appStore = useAppStore(); + + // if (!isHexColor(color)) return; + const darkMode = appStore.getDarkMode === ThemeEnum.DARK; + if (!color) { + if (darkMode) { + color = '#212121'; + } else { + color = appStore.getMenuSetting.bgColor; + } + } + setCssVar(SIDER_DARK_BG_COLOR, color); + setCssVar(SIDER_DARK_DARKEN_BG_COLOR, darken(color!, 6)); + setCssVar(SIDER_LIGHTEN_BG_COLOR, lighten(color!, 5)); + + // only #ffffff is light + // Only when the background color is #fff, the theme of the menu will be changed to light + const isLight = ['#fff', '#ffffff'].includes(color!.toLowerCase()); + + appStore.setProjectConfig({ + menuSetting: { + theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK, + }, + }); +} + +/** + * Change the background color of the componet + * @param color + */ +export function updateComponentBgColor(color?: string) { + const appStore = useAppStore(); + const darkMode = appStore.getDarkMode === ThemeEnum.DARK; + if (!color) { + if (darkMode) { + color = '#151515'; + } else { + color = '#fff'; + } + } + // component color + setCssVar(COMPONENT_BACKGROUND_COLOR, color); + + // only #ffffff is light + // Only when the background color is #fff, the theme of the menu will be changed to light + const isLight = ['#fff', '#ffffff'].includes(color!.toLowerCase()); + + appStore.setProjectConfig({ + menuSetting: { + theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK, + }, + }); +} + +/** + * Change the background color of the app content + * @param color + */ +export function updateAppContentBgColor(color?: string) { + const appStore = useAppStore(); + const darkMode = appStore.getDarkMode === ThemeEnum.DARK; + if (!color) { + if (darkMode) { + color = '#1e1e1e'; + } else { + color = '#fafafa'; + } + } + // app content color + setCssVar(APP_CONTENT_BACKGROUND_COLOR, color); + + // only #ffffff is light + // Only when the background color is #fff, the theme of the menu will be changed to light + const isLight = ['#fff', '#ffffff'].includes(color!.toLowerCase()); + + appStore.setProjectConfig({ + menuSetting: { + theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK, + }, + }); +} \ No newline at end of file diff --git a/src/logics/theme/updateColorWeak.ts b/src/logics/theme/updateColorWeak.ts new file mode 100644 index 0000000..8a0e64a --- /dev/null +++ b/src/logics/theme/updateColorWeak.ts @@ -0,0 +1,9 @@ +import { toggleClass } from './util'; + +/** + * Change the status of the project's color weakness mode + * @param colorWeak + */ +export function updateColorWeak(colorWeak: boolean) { + toggleClass(colorWeak, 'color-weak', document.documentElement); +} diff --git a/src/logics/theme/updateGrayMode.ts b/src/logics/theme/updateGrayMode.ts new file mode 100644 index 0000000..0fd16fe --- /dev/null +++ b/src/logics/theme/updateGrayMode.ts @@ -0,0 +1,9 @@ +import { toggleClass } from './util'; + +/** + * Change project gray mode status + * @param gray + */ +export function updateGrayMode(gray: boolean) { + toggleClass(gray, 'gray-mode', document.documentElement); +} diff --git a/src/logics/theme/util.ts b/src/logics/theme/util.ts new file mode 100644 index 0000000..30aef37 --- /dev/null +++ b/src/logics/theme/util.ts @@ -0,0 +1,11 @@ +const docEle = document.documentElement; +export function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) { + const targetEl = target || document.body; + let { className } = targetEl; + className = className.replace(clsName, ''); + targetEl.className = flag ? `${className} ${clsName} ` : className; +} + +export function setCssVar(prop: string, val: any, dom = docEle) { + dom.style.setProperty(prop, val); +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..1c4c808 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,64 @@ +import 'uno.css'; +import '@/design/index.less'; +import '@/components/VxeTable/src/css/index.scss'; +import 'ant-design-vue/dist/reset.css'; +// Register icon sprite +import 'virtual:svg-icons-register'; + +import { createApp } from 'vue'; + +import { registerGlobComp } from '@/components/registerGlobComp'; +import { setupGlobDirectives } from '@/directives'; +import { setupI18n } from '@/locales/setupI18n'; +import { setupErrorHandle } from '@/logics/error-handle'; +import { initAppConfigStore } from '@/logics/initAppConfig'; +import { router, setupRouter } from '@/router'; +import { setupRouterGuard } from '@/router/guard'; +import { setupStore } from '@/store'; + +import App from './App.vue'; + +async function bootstrap() { + const app = createApp(App); + + // Configure store + // 配置 store + setupStore(app); + + // Initialize internal system configuration + // 初始化内部系统配置 + initAppConfigStore(); + + // Register global components + // 注册全局组件 + registerGlobComp(app); + + // Multilingual configuration + // 多语言配置 + // Asynchronous case: language files may be obtained from the server side + // 异步案例:语言文件可能从服务器端获取 + await setupI18n(app); + + // Configure routing + // 配置路由 + setupRouter(app); + + // router-guard + // 路由守卫 + setupRouterGuard(router); + + // Register global directive + // 注册全局指令 + setupGlobDirectives(app); + + // Configure global error handling + // 配置全局错误处理 + setupErrorHandle(app); + + // https://next.router.vuejs.org/api/#isready + // await router.isReady(); + + app.mount('#app'); +} + +bootstrap(); diff --git a/src/router/.DS_Store b/src/router/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..924a3dd309afc0e1af26287153c6997d7ad8968e GIT binary patch literal 6148 zcmeHKu};G<5IsYRDmu`S(E~8kjWLw4BlQQM4QhvkM1k(%v-kl9zKVA~3+2*AYzV=f zWIyM8XTQ8EzM6>Ke4EdRrbIMGV@!_G?J=I`wqpm;!^tkJkr(UPVpWy(POLdh0aM`j zDZtG9%lbT0n}`^@kG#iQ@|831-=yE^TDGrrV(4gaCD#xR{&rF zcQA}YEdzRX0Mm%AAUrT9sX$3}@rvOj9ey9<(ul2~q>~FfW1YCOi#HS(c8A}GaB``j z^`?L+pcOcj$0^tU+u{4aPO>Lcz!dmX3b-U&WOKYytgSmQ$F import('/@/views/sys/exception/Exception.vue'); + +/** + * @description: default layout + */ +export const LAYOUT = () => import('/@/layouts/default/index.vue'); + +/** + * @description: parent-layout + */ +export const getParentLayout = (_name?: string) => { + return () => + new Promise((resolve) => { + resolve({ + name: _name || PARENT_LAYOUT_NAME, + }); + }); +}; diff --git a/src/router/guard/index.ts b/src/router/guard/index.ts new file mode 100644 index 0000000..c567749 --- /dev/null +++ b/src/router/guard/index.ts @@ -0,0 +1,147 @@ +import type { Router, RouteLocationNormalized } from 'vue-router'; +import { useAppStoreWithOut } from '/@/store/modules/app'; +import { useUserStoreWithOut } from '/@/store/modules/user'; +import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'; +import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel'; +import { Modal, notification } from 'ant-design-vue'; +import { warn } from '/@/utils/log'; +import { unref } from 'vue'; +import { setRouteChange } from '/@/logics/mitt/routeChange'; +import { createPermissionGuard } from './permissionGuard'; +import { createStateGuard } from './stateGuard'; +import nProgress from 'nprogress'; +import projectSetting from '/@/settings/projectSetting'; +import { createParamMenuGuard } from './paramMenuGuard'; + +// Don't change the order of creation +export function setupRouterGuard(router: Router) { + createPageGuard(router); + createPageLoadingGuard(router); + createHttpGuard(router); + createScrollGuard(router); + createMessageGuard(router); + createProgressGuard(router); + createPermissionGuard(router); + createParamMenuGuard(router); // must after createPermissionGuard (menu has been built.) + createStateGuard(router); +} + +/** + * Hooks for handling page state + */ +function createPageGuard(router: Router) { + const loadedPageMap = new Map(); + + router.beforeEach(async (to) => { + // The page has already been loaded, it will be faster to open it again, you don’t need to do loading and other processing + to.meta.loaded = !!loadedPageMap.get(to.path); + // Notify routing changes + setRouteChange(to); + + return true; + }); + + router.afterEach((to) => { + loadedPageMap.set(to.path, true); + }); +} + +// Used to handle page loading status +function createPageLoadingGuard(router: Router) { + const userStore = useUserStoreWithOut(); + const appStore = useAppStoreWithOut(); + const { getOpenPageLoading } = useTransitionSetting(); + router.beforeEach(async (to) => { + if (!userStore.getToken) { + return true; + } + if (to.meta.loaded) { + return true; + } + + if (unref(getOpenPageLoading)) { + appStore.setPageLoadingAction(true); + return true; + } + + return true; + }); + router.afterEach(async () => { + if (unref(getOpenPageLoading)) { + // TODO Looking for a better way + // The timer simulates the loading time to prevent flashing too fast, + setTimeout(() => { + appStore.setPageLoading(false); + }, 220); + } + return true; + }); +} + +/** + * The interface used to close the current page to complete the request when the route is switched + * @param router + */ +function createHttpGuard(router: Router) { + const { removeAllHttpPending } = projectSetting; + let axiosCanceler: Nullable; + if (removeAllHttpPending) { + axiosCanceler = new AxiosCanceler(); + } + router.beforeEach(async () => { + // Switching the route will delete the previous request + axiosCanceler?.removeAllPending(); + return true; + }); +} + +// Routing switch back to the top +function createScrollGuard(router: Router) { + const isHash = (href: string) => { + return /^#/.test(href); + }; + + const body = document.body; + + router.afterEach(async (to) => { + // scroll top + isHash((to as RouteLocationNormalized & { href: string })?.href) && body.scrollTo(0, 0); + return true; + }); +} + +/** + * Used to close the message instance when the route is switched + * @param router + */ +export function createMessageGuard(router: Router) { + const { closeMessageOnSwitch } = projectSetting; + + router.beforeEach(async () => { + try { + if (closeMessageOnSwitch) { + Modal.destroyAll(); + notification.destroy(); + } + } catch (error) { + warn('message guard error:' + error); + } + return true; + }); +} + +export function createProgressGuard(router: Router) { + const { getOpenNProgress } = useTransitionSetting(); + router.beforeEach(async (to) => { + if (to.meta.loaded) { + return true; + } + unref(getOpenNProgress) && nProgress.start(); + return true; + }); + + router.afterEach(async () => { + unref(getOpenNProgress) && nProgress.done(); + return true; + }); +} diff --git a/src/router/guard/paramMenuGuard.ts b/src/router/guard/paramMenuGuard.ts new file mode 100644 index 0000000..1c75157 --- /dev/null +++ b/src/router/guard/paramMenuGuard.ts @@ -0,0 +1,47 @@ +import type { Router } from 'vue-router'; +import { configureDynamicParamsMenu } from '../helper/menuHelper'; +import { Menu } from '../types'; +import { PermissionModeEnum } from '/@/enums/appEnum'; +import { useAppStoreWithOut } from '/@/store/modules/app'; + +import { usePermissionStoreWithOut } from '/@/store/modules/permission'; + +export function createParamMenuGuard(router: Router) { + const permissionStore = usePermissionStoreWithOut(); + router.beforeEach(async (to, _, next) => { + // filter no name route + if (!to.name) { + next(); + return; + } + + // menu has been built. + if (!permissionStore.getIsDynamicAddedRoute) { + next(); + return; + } + + let menus: Menu[] = []; + if (isBackMode()) { + menus = permissionStore.getBackMenuList; + } else if (isRouteMappingMode()) { + menus = permissionStore.getFrontMenuList; + } + menus.forEach((item) => configureDynamicParamsMenu(item, to.params)); + + next(); + }); +} + +const getPermissionMode = () => { + const appStore = useAppStoreWithOut(); + return appStore.getProjectConfig.permissionMode; +}; + +const isBackMode = () => { + return getPermissionMode() === PermissionModeEnum.BACK; +}; + +const isRouteMappingMode = () => { + return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING; +}; diff --git a/src/router/guard/permissionGuard.ts b/src/router/guard/permissionGuard.ts new file mode 100644 index 0000000..5b1acde --- /dev/null +++ b/src/router/guard/permissionGuard.ts @@ -0,0 +1,119 @@ +import type { Router, RouteRecordRaw } from 'vue-router'; + +import { usePermissionStoreWithOut } from '/@/store/modules/permission'; + +import { PageEnum } from '/@/enums/pageEnum'; +import { useUserStoreWithOut } from '/@/store/modules/user'; + +import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'; + +import { RootRoute } from '/@/router/routes'; + +const LOGIN_PATH = PageEnum.BASE_LOGIN; + +const ROOT_PATH = RootRoute.path; + +const whitePathList: PageEnum[] = [LOGIN_PATH]; + +export function createPermissionGuard(router: Router) { + const userStore = useUserStoreWithOut(); + const permissionStore = usePermissionStoreWithOut(); + router.beforeEach(async (to, from, next) => { + if ( + from.path === ROOT_PATH && + to.path === PageEnum.BASE_HOME && + userStore.getUserInfo.homePath && + userStore.getUserInfo.homePath !== PageEnum.BASE_HOME + ) { + next(userStore.getUserInfo.homePath); + return; + } + + const token = userStore.getToken; + + // Whitelist can be directly entered + if (whitePathList.includes(to.path as PageEnum)) { + if (to.path === LOGIN_PATH && token) { + const isSessionTimeout = userStore.getSessionTimeout; + try { + await userStore.afterLoginAction(); + if (!isSessionTimeout) { + next((to.query?.redirect as string) || '/'); + return; + } + } catch { + // + } + } + next(); + return; + } + // token or user does not exist + if (!token) { + // You can access without permission. You need to set the routing meta.ignoreAuth to true + if (to.meta.ignoreAuth) { + next(); + return; + } + + // redirect login page + const redirectData: { path: string; replace: boolean; query?: Recordable } = { + path: LOGIN_PATH, + replace: true, + }; + if (to.path) { + redirectData.query = { + ...redirectData.query, + redirect: to.path, + }; + } + next(redirectData); + return; + } + + // Jump to the 404 page after processing the login + if ( + from.path === LOGIN_PATH && + to.name === PAGE_NOT_FOUND_ROUTE.name && + to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME) + ) { + next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); + return; + } + + // get userinfo while last fetch time is empty + if (userStore.getLastUpdateTime === 0) { + try { + await userStore.getUserInfoAction(); + } catch (err) { + next(); + return; + } + } + + if (permissionStore.getIsDynamicAddedRoute) { + next(); + return; + } + + const routes = await permissionStore.buildRoutesAction(); + + routes.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw); + }); + + router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw); + + permissionStore.setDynamicAddedRoute(true); + + if (to.name === PAGE_NOT_FOUND_ROUTE.name) { + // 动态添加路由后,此处应当重定向到fullPath,否则会加载404页面内容 + next({ path: to.fullPath, replace: true, query: to.query }); + } else { + const redirectPath = (from.query.redirect || to.path) as string; + const redirect = decodeURIComponent(redirectPath); + const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }; + next(nextData); + } + }); +} diff --git a/src/router/guard/stateGuard.ts b/src/router/guard/stateGuard.ts new file mode 100644 index 0000000..c34513c --- /dev/null +++ b/src/router/guard/stateGuard.ts @@ -0,0 +1,24 @@ +import type { Router } from 'vue-router'; +import { useAppStore } from '/@/store/modules/app'; +import { useMultipleTabStore } from '/@/store/modules/multipleTab'; +import { useUserStore } from '/@/store/modules/user'; +import { usePermissionStore } from '/@/store/modules/permission'; +import { PageEnum } from '/@/enums/pageEnum'; +import { removeTabChangeListener } from '/@/logics/mitt/routeChange'; + +export function createStateGuard(router: Router) { + router.afterEach((to) => { + // Just enter the login page and clear the authentication information + if (to.path === PageEnum.BASE_LOGIN) { + const tabStore = useMultipleTabStore(); + const userStore = useUserStore(); + const appStore = useAppStore(); + const permissionStore = usePermissionStore(); + appStore.resetAllState(); + permissionStore.resetState(); + tabStore.resetState(); + userStore.resetState(); + removeTabChangeListener(); + } + }); +} diff --git a/src/router/helper/menuHelper.ts b/src/router/helper/menuHelper.ts new file mode 100644 index 0000000..f0767b2 --- /dev/null +++ b/src/router/helper/menuHelper.ts @@ -0,0 +1,106 @@ +import { AppRouteModule } from '/@/router/types'; +import type { MenuModule, Menu, AppRouteRecordRaw } from '/@/router/types'; +import { findPath, treeMap } from '/@/utils/helper/treeHelper'; +import { cloneDeep } from 'lodash-es'; +import { isUrl } from '/@/utils/is'; +import { RouteParams } from 'vue-router'; +import { toRaw } from 'vue'; + +export function getAllParentPath(treeData: T[], path: string) { + const menuList = findPath(treeData, (n) => n.path === path) as Menu[]; + return (menuList || []).map((item) => item.path); +} + +// 路径处理 +function joinParentPath(menus: Menu[], parentPath = '') { + for (let index = 0; index < menus.length; index++) { + const menu = menus[index]; + // https://next.router.vuejs.org/guide/essentials/nested-routes.html + // Note that nested paths that start with / will be treated as a root path. + // 请注意,以 / 开头的嵌套路径将被视为根路径。 + // This allows you to leverage the component nesting without having to use a nested URL. + // 这允许你利用组件嵌套,而无需使用嵌套 URL。 + if (!(menu.path.startsWith('/') || isUrl(menu.path))) { + // path doesn't start with /, nor is it a url, join parent path + // 路径不以 / 开头,也不是 url,加入父路径 + menu.path = `${parentPath}/${menu.path}`; + } + if (menu?.children?.length) { + joinParentPath(menu.children, menu.meta?.hidePathForChildren ? parentPath : menu.path); + } + } +} + +// Parsing the menu module +export function transformMenuModule(menuModule: MenuModule): Menu { + const { menu } = menuModule; + + const menuList = [menu]; + + joinParentPath(menuList); + return menuList[0]; +} + +// 将路由转换成菜单 +export function transformRouteToMenu(routeModList: AppRouteModule[], routerMapping = false) { + // 借助 lodash 深拷贝 + const cloneRouteModList = cloneDeep(routeModList); + const routeList: AppRouteRecordRaw[] = []; + + // 对路由项进行修改 + cloneRouteModList.forEach((item) => { + if (routerMapping && item.meta.hideChildrenInMenu && typeof item.redirect === 'string') { + item.path = item.redirect; + } + + if (item.meta?.single) { + const realItem = item?.children?.[0]; + realItem && routeList.push(realItem); + } else { + routeList.push(item); + } + }); + // 提取树指定结构 + const list = treeMap(routeList, { + conversion: (node: AppRouteRecordRaw) => { + const { meta: { title, hideMenu = false } = {} } = node; + + return { + ...(node.meta || {}), + meta: node.meta, + name: title, + hideMenu, + path: node.path, + ...(node.redirect ? { redirect: node.redirect } : {}), + }; + }, + }); + // 路径处理 + joinParentPath(list); + return cloneDeep(list); +} + +/** + * config menu with given params + */ +const menuParamRegex = /(?::)([\s\S]+?)((?=\/)|$)/g; + +export function configureDynamicParamsMenu(menu: Menu, params: RouteParams) { + const { path, paramPath } = toRaw(menu); + let realPath = paramPath ? paramPath : path; + const matchArr = realPath.match(menuParamRegex); + + matchArr?.forEach((it) => { + const realIt = it.substr(1); + if (params[realIt]) { + realPath = realPath.replace(`:${realIt}`, params[realIt] as string); + } + }); + // save original param path. + if (!paramPath && matchArr && matchArr.length > 0) { + menu.paramPath = path; + } + menu.path = realPath; + // children + menu.children?.forEach((item) => configureDynamicParamsMenu(item, params)); +} diff --git a/src/router/helper/routeHelper.ts b/src/router/helper/routeHelper.ts new file mode 100644 index 0000000..d133209 --- /dev/null +++ b/src/router/helper/routeHelper.ts @@ -0,0 +1,178 @@ +import type { AppRouteModule, AppRouteRecordRaw } from '/@/router/types'; +import type { Router, RouteRecordNormalized } from 'vue-router'; + +import { getParentLayout, LAYOUT, EXCEPTION_COMPONENT } from '/@/router/constant'; +import { cloneDeep, omit } from 'lodash-es'; +import { warn } from '/@/utils/log'; +import { createRouter, createWebHashHistory } from 'vue-router'; + +export type LayoutMapKey = 'LAYOUT'; +const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue'); + +const LayoutMap = new Map Promise>(); + +LayoutMap.set('LAYOUT', LAYOUT); +LayoutMap.set('IFRAME', IFRAME); + +let dynamicViewsModules: Record Promise>; + +// Dynamic introduction +function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) { + dynamicViewsModules = dynamicViewsModules || import.meta.glob('../../views/**/*.{vue,tsx}'); + if (!routes) return; + routes.forEach((item) => { + if (!item.component && item.meta?.frameSrc) { + item.component = 'IFRAME'; + } + const { component, name } = item; + const { children } = item; + if (component) { + const layoutFound = LayoutMap.get(component.toUpperCase()); + if (layoutFound) { + item.component = layoutFound; + } else { + item.component = dynamicImport(dynamicViewsModules, component as string); + } + } else if (name) { + item.component = getParentLayout(); + } + children && asyncImportRoute(children); + }); +} + +function dynamicImport( + dynamicViewsModules: Record Promise>, + component: string, +) { + const keys = Object.keys(dynamicViewsModules); + const matchKeys = keys.filter((key) => { + const k = key.replace('../../views', ''); + const startFlag = component.startsWith('/'); + const endFlag = component.endsWith('.vue') || component.endsWith('.tsx'); + const startIndex = startFlag ? 0 : 1; + const lastIndex = endFlag ? k.length : k.lastIndexOf('.'); + return k.substring(startIndex, lastIndex) === component; + }); + if (matchKeys?.length === 1) { + const matchKey = matchKeys[0]; + return dynamicViewsModules[matchKey]; + } else if (matchKeys?.length > 1) { + warn( + 'Please do not create `.vue` and `.TSX` files with the same file name in the same hierarchical directory under the views folder. This will cause dynamic introduction failure', + ); + return; + } else { + warn('在src/views/下找不到`' + component + '.vue` 或 `' + component + '.tsx`, 请自行创建!'); + return EXCEPTION_COMPONENT; + } +} + +// Turn background objects into routing objects +// 将背景对象变成路由对象 +export function transformObjToRoute(routeList: AppRouteModule[]): T[] { + routeList.forEach((route) => { + const component = route.component as string; + if (component) { + if (component.toUpperCase() === 'LAYOUT') { + route.component = LayoutMap.get(component.toUpperCase()); + } else { + route.children = [cloneDeep(route)]; + route.component = LAYOUT; + route.name = `${route.name}Parent`; + route.path = ''; + const meta = route.meta || {}; + meta.single = true; + meta.affix = false; + route.meta = meta; + } + } else { + warn('请正确配置路由:' + route?.name + '的component属性'); + } + route.children && asyncImportRoute(route.children); + }); + return routeList as unknown as T[]; +} + +/** + * Convert multi-level routing to level 2 routing + * 将多级路由转换为 2 级路由 + */ +export function flatMultiLevelRoutes(routeModules: AppRouteModule[]) { + const modules: AppRouteModule[] = cloneDeep(routeModules); + + for (let index = 0; index < modules.length; index++) { + const routeModule = modules[index]; + // 判断级别是否 多级 路由 + if (!isMultipleRoute(routeModule)) { + // 声明终止当前循环, 即跳过此次循环,进行下一轮 + continue; + } + // 路由等级提升 + promoteRouteLevel(routeModule); + } + return modules; +} + +// Routing level upgrade +// 路由等级提升 +function promoteRouteLevel(routeModule: AppRouteModule) { + // Use vue-router to splice menus + // 使用vue-router拼接菜单 + // createRouter 创建一个可以被 Vue 应用程序使用的路由实例 + let router: Router | null = createRouter({ + routes: [routeModule as unknown as RouteRecordNormalized], + history: createWebHashHistory(), + }); + // getRoutes: 获取所有 路由记录的完整列表。 + const routes = router.getRoutes(); + // 将所有子路由添加到二级路由 + addToChildren(routes, routeModule.children || [], routeModule); + router = null; + + // omit lodash的函数 对传入的item对象的children进行删除 + routeModule.children = routeModule.children?.map((item) => omit(item, 'children')); +} + +// Add all sub-routes to the secondary route +// 将所有子路由添加到二级路由 +function addToChildren( + routes: RouteRecordNormalized[], + children: AppRouteRecordRaw[], + routeModule: AppRouteModule, +) { + for (let index = 0; index < children.length; index++) { + const child = children[index]; + const route = routes.find((item) => item.name === child.name); + if (!route) { + continue; + } + routeModule.children = routeModule.children || []; + if (!routeModule.children.find((item) => item.name === route.name)) { + routeModule.children?.push(route as unknown as AppRouteModule); + } + if (child.children?.length) { + addToChildren(routes, child.children, routeModule); + } + } +} + +// Determine whether the level exceeds 2 levels +// 判断级别是否超过2级 +function isMultipleRoute(routeModule: AppRouteModule) { + // Reflect.has 与 in 操作符 相同, 用于检查一个对象(包括它原型链上)是否拥有某个属性 + if (!routeModule || !Reflect.has(routeModule, 'children') || !routeModule.children?.length) { + return false; + } + + const children = routeModule.children; + + let flag = false; + for (let index = 0; index < children.length; index++) { + const child = children[index]; + if (child.children?.length) { + flag = true; + break; + } + } + return flag; +} diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..bcfc17f --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,42 @@ +import type { RouteRecordRaw } from 'vue-router'; +import type { App } from 'vue'; + +import { createRouter, createWebHashHistory } from 'vue-router'; +import { basicRoutes } from './routes'; + +// 白名单应该包含基本静态路由 +const WHITE_NAME_LIST: string[] = []; +const getRouteNames = (array: any[]) => + array.forEach((item) => { + WHITE_NAME_LIST.push(item.name); + getRouteNames(item.children || []); + }); +getRouteNames(basicRoutes); + +// app router +// 创建一个可以被 Vue 应用程序使用的路由实例 +export const router = createRouter({ + // 创建一个 hash 历史记录。 + history: createWebHashHistory(import.meta.env.VITE_PUBLIC_PATH), + // 应该添加到路由的初始路由列表。 + routes: basicRoutes as unknown as RouteRecordRaw[], + // 是否应该禁止尾部斜杠。默认为假 + strict: true, + scrollBehavior: () => ({ left: 0, top: 0 }), +}); + +// reset router +export function resetRouter() { + router.getRoutes().forEach((route) => { + const { name } = route; + if (name && !WHITE_NAME_LIST.includes(name as string)) { + router.hasRoute(name) && router.removeRoute(name); + } + }); +} + +// config router +// 配置路由器 +export function setupRouter(app: App) { + app.use(router); +} diff --git a/src/router/menus/index.ts b/src/router/menus/index.ts new file mode 100644 index 0000000..c9124b7 --- /dev/null +++ b/src/router/menus/index.ts @@ -0,0 +1,136 @@ +import type { Menu, MenuModule } from '/@/router/types'; +import type { RouteRecordNormalized } from 'vue-router'; + +import { useAppStoreWithOut } from '/@/store/modules/app'; +import { usePermissionStore } from '/@/store/modules/permission'; +import { transformMenuModule, getAllParentPath } from '/@/router/helper/menuHelper'; +import { filter } from '/@/utils/helper/treeHelper'; +import { isUrl } from '/@/utils/is'; +import { router } from '/@/router'; +import { PermissionModeEnum } from '/@/enums/appEnum'; +import { pathToRegexp } from 'path-to-regexp'; + +const modules = import.meta.glob('./modules/**/*.ts', { eager: true }); + +const menuModules: MenuModule[] = []; + +Object.keys(modules).forEach((key) => { + const mod = (modules as Recordable)[key].default || {}; + const modList = Array.isArray(mod) ? [...mod] : [mod]; + menuModules.push(...modList); +}); + +// =========================== +// ==========Helper=========== +// =========================== + +const getPermissionMode = () => { + const appStore = useAppStoreWithOut(); + return appStore.getProjectConfig.permissionMode; +}; +const isBackMode = () => { + return getPermissionMode() === PermissionModeEnum.BACK; +}; + +const isRouteMappingMode = () => { + return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING; +}; + +const isRoleMode = () => { + return getPermissionMode() === PermissionModeEnum.ROLE; +}; + +const staticMenus: Menu[] = []; +(() => { + menuModules.sort((a, b) => { + return (a.orderNo || 0) - (b.orderNo || 0); + }); + + for (const menu of menuModules) { + staticMenus.push(transformMenuModule(menu)); + } +})(); + +async function getAsyncMenus() { + const permissionStore = usePermissionStore(); + //递归过滤所有隐藏的菜单 + const menuFilter = (items) => { + return items.filter((item) => { + const show = !item.meta?.hideMenu && !item.hideMenu; + if (show && item.children) { + item.children = menuFilter(item.children); + } + return show; + }); + }; + if (isBackMode()) { + return menuFilter(permissionStore.getBackMenuList); + } + if (isRouteMappingMode()) { + return menuFilter(permissionStore.getFrontMenuList); + } + return staticMenus; +} + +export const getMenus = async (): Promise => { + const menus = await getAsyncMenus(); + if (isRoleMode()) { + const routes = router.getRoutes(); + return filter(menus, basicFilter(routes)); + } + return menus; +}; + +export async function getCurrentParentPath(currentPath: string) { + const menus = await getAsyncMenus(); + const allParentPath = await getAllParentPath(menus, currentPath); + return allParentPath?.[0]; +} + +// Get the level 1 menu, delete children +export async function getShallowMenus(): Promise { + const menus = await getAsyncMenus(); + const shallowMenuList = menus.map((item) => ({ ...item, children: undefined })); + if (isRoleMode()) { + const routes = router.getRoutes(); + return shallowMenuList.filter(basicFilter(routes)); + } + return shallowMenuList; +} + +// Get the children of the menu +export async function getChildrenMenus(parentPath: string) { + const menus = await getMenus(); + const parent = menus.find((item) => item.path === parentPath); + if (!parent || !parent.children || !!parent?.meta?.hideChildrenInMenu) { + return [] as Menu[]; + } + if (isRoleMode()) { + const routes = router.getRoutes(); + return filter(parent.children, basicFilter(routes)); + } + return parent.children; +} + +function basicFilter(routes: RouteRecordNormalized[]) { + return (menu: Menu) => { + const matchRoute = routes.find((route) => { + if (isUrl(menu.path)) return true; + + if (route.meta?.carryParam) { + return pathToRegexp(route.path).test(menu.path); + } + const isSame = route.path === menu.path; + if (!isSame) return false; + + if (route.meta?.ignoreAuth) return true; + + return isSame || pathToRegexp(route.path).test(menu.path); + }); + + if (!matchRoute) return false; + menu.icon = (menu.icon || matchRoute.meta.icon) as string; + menu.meta = matchRoute.meta; + return true; + }; +} diff --git a/src/router/routes/basic.ts b/src/router/routes/basic.ts new file mode 100644 index 0000000..573ce2b --- /dev/null +++ b/src/router/routes/basic.ts @@ -0,0 +1,78 @@ +import type { AppRouteRecordRaw } from '/@/router/types'; +import { t } from '/@/hooks/web/useI18n'; +import { + REDIRECT_NAME, + LAYOUT, + EXCEPTION_COMPONENT, + PAGE_NOT_FOUND_NAME, +} from '/@/router/constant'; + +// 404 on a page +export const PAGE_NOT_FOUND_ROUTE: AppRouteRecordRaw = { + path: '/:path(.*)*', + name: PAGE_NOT_FOUND_NAME, + component: LAYOUT, + meta: { + title: 'ErrorPage', + hideBreadcrumb: true, + hideMenu: true, + }, + children: [ + { + path: '/:path(.*)*', + name: PAGE_NOT_FOUND_NAME, + component: EXCEPTION_COMPONENT, + meta: { + title: 'ErrorPage', + hideBreadcrumb: true, + hideMenu: true, + }, + }, + ], +}; + +export const REDIRECT_ROUTE: AppRouteRecordRaw = { + path: '/redirect', + component: LAYOUT, + name: 'RedirectTo', + meta: { + title: REDIRECT_NAME, + hideBreadcrumb: true, + hideMenu: true, + }, + children: [ + { + path: '/redirect/:path(.*)/:_redirect_type(.*)/:_origin_params(.*)?', + name: REDIRECT_NAME, + component: () => import('/@/views/sys/redirect/index.vue'), + meta: { + title: REDIRECT_NAME, + hideBreadcrumb: true, + }, + }, + ], +}; + +export const ERROR_LOG_ROUTE: AppRouteRecordRaw = { + path: '/error-log', + name: 'ErrorLog', + component: LAYOUT, + redirect: '/error-log/list', + meta: { + title: 'ErrorLog', + hideBreadcrumb: true, + hideChildrenInMenu: true, + }, + children: [ + { + path: 'list', + name: 'ErrorLogList', + component: () => import('/@/views/sys/error-log/index.vue'), + meta: { + title: t('routes.basic.errorLogList'), + hideBreadcrumb: true, + currentActiveMenu: '/error-log', + }, + }, + ], +}; diff --git a/src/router/routes/index.ts b/src/router/routes/index.ts new file mode 100644 index 0000000..8c3758d --- /dev/null +++ b/src/router/routes/index.ts @@ -0,0 +1,42 @@ +import type { AppRouteRecordRaw, AppRouteModule } from '/@/router/types'; + +import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/routes/basic'; + +import { PageEnum } from '/@/enums/pageEnum'; +import { t } from '/@/hooks/web/useI18n'; + +// import.meta.glob() 直接引入所有的模块 Vite 独有的功能 +const modules = import.meta.glob('./modules/**/*.ts', { eager: true }); +const routeModuleList: AppRouteModule[] = []; + +// 加入到路由集合中 +Object.keys(modules).forEach((key) => { + const mod = (modules as Recordable)[key].default || {}; + const modList = Array.isArray(mod) ? [...mod] : [mod]; + routeModuleList.push(...modList); +}); + +export const asyncRoutes = [PAGE_NOT_FOUND_ROUTE, ...routeModuleList]; + +// 根路由 +export const RootRoute: AppRouteRecordRaw = { + path: '/', + name: 'Root', + redirect: PageEnum.BASE_HOME, + meta: { + title: 'Root', + }, +}; + +export const LoginRoute: AppRouteRecordRaw = { + path: '/login', + name: 'Login', + component: () => import('/@/views/sys/login/Login.vue'), + meta: { + title: t('routes.basic.login'), + }, +}; + +// Basic routing without permission +// 未经许可的基本路由 +export const basicRoutes = [LoginRoute, RootRoute, REDIRECT_ROUTE, PAGE_NOT_FOUND_ROUTE]; diff --git a/src/router/types.ts b/src/router/types.ts new file mode 100644 index 0000000..082d208 --- /dev/null +++ b/src/router/types.ts @@ -0,0 +1,58 @@ +import type { RouteRecordRaw, RouteMeta } from 'vue-router'; +import { RoleEnum } from '/@/enums/roleEnum'; +import { defineComponent } from 'vue'; + +export type Component = + | ReturnType + | (() => Promise) + | (() => Promise); + +// @ts-ignore +export interface AppRouteRecordRaw extends Omit { + name: string; + meta: RouteMeta; + component?: Component | string; + components?: Component; + children?: AppRouteRecordRaw[]; + props?: Recordable; + fullPath?: string; +} + +export interface MenuTag { + type?: 'primary' | 'error' | 'warn' | 'success'; + content?: string; + dot?: boolean; +} + +export interface Menu { + name: string; + + icon?: string; + + path: string; + + // path contains param, auto assignment. + paramPath?: string; + + disabled?: boolean; + + children?: Menu[]; + + orderNo?: number; + + roles?: RoleEnum[]; + + meta?: Partial; + + tag?: MenuTag; + + hideMenu?: boolean; +} + +export interface MenuModule { + orderNo?: number; + menu: Menu; +} + +// export type AppRouteModule = RouteModule | AppRouteRecordRaw; +export type AppRouteModule = AppRouteRecordRaw; diff --git a/src/settings/componentSetting.ts b/src/settings/componentSetting.ts new file mode 100644 index 0000000..e718e1a --- /dev/null +++ b/src/settings/componentSetting.ts @@ -0,0 +1,51 @@ +// Used to configure the general configuration of some components without modifying the components + +import type { SorterResult } from '../components/Table'; + +export default { + // basic-table setting + table: { + // Form interface request general configuration + // support xxx.xxx.xxx + fetchSetting: { + // The field name of the current page passed to the background + pageField: 'page', + // The number field name of each page displayed in the background + sizeField: 'pageSize', + // Field name of the form data returned by the interface + listField: 'records', + // Total number of tables returned by the interface field name + totalField: 'total', + }, + // Number of pages that can be selected + pageSizeOptions: ['10', '50', '80', '100'], + // Default display quantity on one page + defaultPageSize: 10, + // Default Size + defaultSize: 'middle', + // Custom general sort function + defaultSortFn: (sortInfo: SorterResult) => { + const { field, order } = sortInfo; + if (field && order) { + return { + // The sort field passed to the backend you + field, + // Sorting method passed to the background asc/desc + order, + }; + } else { + return {}; + } + }, + // Custom general filter function + defaultFilterFn: (data: Partial>) => { + return data; + }, + }, + // scrollbar setting + scrollbar: { + // Whether to use native scroll bar + // After opening, the menu, modal, drawer will change the pop-up scroll bar to native + native: false, + }, +}; diff --git a/src/settings/designSetting.ts b/src/settings/designSetting.ts new file mode 100644 index 0000000..a81b576 --- /dev/null +++ b/src/settings/designSetting.ts @@ -0,0 +1,48 @@ +import { ThemeEnum } from '../enums/appEnum'; + +export const prefixCls = 'vben'; + +export const darkMode = ThemeEnum.LIGHT; + +// app theme preset color +export const APP_PRESET_COLOR_LIST: string[] = [ + '#0960bd', + '#0084f4', + '#009688', + '#536dfe', + '#ff5c93', + '#ee4f12', + '#0096c7', + '#9c27b0', + '#ff9800', +]; + +// header preset color +export const HEADER_PRESET_BG_COLOR_LIST: string[] = [ + '#ffffff', + '#151515', + '#009688', + '#5172DC', + '#018ffb', + '#409eff', + '#e74c3c', + '#24292e', + '#394664', + '#001529', + '#383f45', +]; + +// sider preset color +export const SIDE_BAR_BG_COLOR_LIST: string[] = [ + '#001529', + '#212121', + '#273352', + '#ffffff', + '#191b24', + '#191a23', + '#304156', + '#001628', + '#28333E', + '#344058', + '#383f45', +]; diff --git a/src/settings/encryptionSetting.ts b/src/settings/encryptionSetting.ts new file mode 100644 index 0000000..df3c7d5 --- /dev/null +++ b/src/settings/encryptionSetting.ts @@ -0,0 +1,13 @@ +import { isDevMode } from '/@/utils/env'; + +// System default cache time, in seconds +export const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 1; + +// aes encryption key +export const cacheCipher = { + key: '_11111000001111@', + iv: '@11111000001111_', +}; + +// Whether the system cache is encrypted using aes +export const enableStorageEncryption = !isDevMode(); diff --git a/src/settings/localeSetting.ts b/src/settings/localeSetting.ts new file mode 100644 index 0000000..5452568 --- /dev/null +++ b/src/settings/localeSetting.ts @@ -0,0 +1,29 @@ +import type { DropMenu } from '../components/Dropdown'; +import type { LocaleSetting, LocaleType } from '/#/config'; + +export const LOCALE: { [key: string]: LocaleType } = { + ZH_CN: 'zh_CN', + EN_US: 'en', +}; + +export const localeSetting: LocaleSetting = { + showPicker: true, + // Locale + locale: LOCALE.ZH_CN, + // Default locale + fallback: LOCALE.ZH_CN, + // available Locales + availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US], +}; + +// locale list +export const localeList: DropMenu[] = [ + { + text: '简体中文', + event: LOCALE.ZH_CN, + }, + { + text: 'English', + event: LOCALE.EN_US, + }, +]; diff --git a/src/settings/projectSetting.ts b/src/settings/projectSetting.ts new file mode 100644 index 0000000..5f27ca7 --- /dev/null +++ b/src/settings/projectSetting.ts @@ -0,0 +1,183 @@ +import type { ProjectConfig } from '/#/config'; +import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum'; +import { CacheTypeEnum } from '/@/enums/cacheEnum'; +import { + ContentEnum, + PermissionModeEnum, + ThemeEnum, + RouterTransitionEnum, + SettingButtonPositionEnum, + SessionTimeoutProcessingEnum, +} from '/@/enums/appEnum'; +import { SIDE_BAR_BG_COLOR_LIST, HEADER_PRESET_BG_COLOR_LIST } from './designSetting'; + +const primaryColor = '#0960bd'; + +// ! You need to clear the browser cache after the change +const setting: ProjectConfig = { + // Whether to show the configuration button + showSettingButton: true, + + // Whether to show the theme switch button + showDarkModeToggle: true, + + // `Settings` button position + settingButtonPosition: SettingButtonPositionEnum.AUTO, + + // Permission mode + permissionMode: PermissionModeEnum.BACK, + + // Permission-related cache is stored in sessionStorage or localStorage + permissionCacheType: CacheTypeEnum.LOCAL, + + // Session timeout processing + sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP, + + // color + themeColor: primaryColor, + + // Website gray mode, open for possible mourning dates + grayMode: false, + + // Color Weakness Mode + colorWeak: false, + + // Whether to cancel the menu, the top, the multi-tab page display, for possible embedded in other systems + fullContent: false, + + // content mode + contentMode: ContentEnum.FULL, + + // Whether to display the logo + showLogo: true, + + // Whether to show footer + showFooter: false, + + // Header configuration + headerSetting: { + // header bg color + bgColor: HEADER_PRESET_BG_COLOR_LIST[0], + // Fixed at the top + fixed: true, + // Whether to show top + show: true, + // theme + theme: ThemeEnum.LIGHT, + // Whether to enable the lock screen function + useLockPage: true, + // Whether to show the full screen button + showFullScreen: true, + // Whether to show the document button + showDoc: true, + // Whether to show the notification button + showNotice: true, + // Whether to display the menu search + showSearch: true, + }, + + // Menu configuration + menuSetting: { + // sidebar menu bg color + bgColor: SIDE_BAR_BG_COLOR_LIST[0], + // Whether to fix the left menu + fixed: true, + // Menu collapse + collapsed: false, + // When sider hide because of the responsive layout + siderHidden: false, + // Whether to display the menu name when folding the menu + collapsedShowTitle: false, + // Whether it can be dragged + // Only limited to the opening of the left menu, the mouse has a drag bar on the right side of the menu + canDrag: false, + // Whether to show no dom + show: true, + // Whether to show dom + hidden: false, + // Menu width + menuWidth: 210, + // Menu mode + mode: MenuModeEnum.INLINE, + // Menu type + type: MenuTypeEnum.MIX_SIDEBAR, + // Menu theme + theme: ThemeEnum.DARK, + // Split menu + split: false, + // Top menu layout + topMenuAlign: 'center', + // Fold trigger position + trigger: TriggerEnum.HEADER, + // Turn on accordion mode, only show a menu + accordion: true, + // Switch page to close menu + closeMixSidebarOnChange: false, + // Module opening method ‘click’ |'hover' + mixSideTrigger: MixSidebarTriggerEnum.CLICK, + // Fixed expanded menu + mixSideFixed: false, + }, + + // Multi-label + multiTabsSetting: { + cache: false, + // Turn on + show: true, + // Is it possible to drag and drop sorting tabs + canDrag: true, + // Turn on quick actions + showQuick: true, + // Whether to show the refresh button + showRedo: true, + // Whether to show the collapse button + showFold: true, + }, + + // Transition Setting + transitionSetting: { + // Whether to open the page switching animation + // The disabled state will also disable pageLoading + enable: true, + + // Route basic switching animation + basicTransition: RouterTransitionEnum.FADE_SIDE, + + // Whether to open page switching loading + // Only open when enable=true + openPageLoading: true, + + // Whether to open the top progress bar + openNProgress: false, + }, + + // Whether to enable KeepAlive cache is best to close during development, otherwise the cache needs to be cleared every time + openKeepAlive: true, + + // Automatic screen lock time, 0 does not lock the screen. Unit minute default 0 + lockTime: 0, + + // Whether to show breadcrumbs + showBreadCrumb: true, + + // Whether to show the breadcrumb icon + showBreadCrumbIcon: true, + + // Use error-handler-plugin + useErrorHandle: false, + + // Whether to open back to top + useOpenBackTop: true, + + // Is it possible to embed iframe pages + canEmbedIFramePage: true, + + // Whether to delete unclosed messages and notify when switching the interface + closeMessageOnSwitch: true, + + // Whether to cancel the http request that has been sent but not responded when switching the interface. + // If it is enabled, I want to overwrite a single interface. Can be set in a separate interface + removeAllHttpPending: false, +}; + +export default setting; diff --git a/src/settings/siteSetting.ts b/src/settings/siteSetting.ts new file mode 100644 index 0000000..c2ea4d6 --- /dev/null +++ b/src/settings/siteSetting.ts @@ -0,0 +1,8 @@ +// github repo url +export const GITHUB_URL = 'https://github.com/wansenai'; + +// doc +export const DOC_URL = 'https://wansenai.com'; + +// site url +export const SITE_URL = 'https://wansenai.com'; diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..efaf6c9 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,10 @@ +import type { App } from 'vue'; +import { createPinia } from 'pinia'; + +const store = createPinia(); + +export function setupStore(app: App) { + app.use(store); +} + +export { store }; diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts new file mode 100644 index 0000000..06df314 --- /dev/null +++ b/src/store/modules/app.ts @@ -0,0 +1,112 @@ +import type { + ProjectConfig, + HeaderSetting, + MenuSetting, + TransitionSetting, + MultiTabsSetting, +} from '/#/config'; +import type { BeforeMiniState } from '/#/store'; + +import { defineStore } from 'pinia'; +import { store } from '/@/store'; + +import { ThemeEnum } from '/@/enums/appEnum'; +import { APP_DARK_MODE_KEY, PROJ_CFG_KEY } from '/@/enums/cacheEnum'; +import { Persistent } from '/@/utils/cache/persistent'; +import { darkMode } from '/@/settings/designSetting'; +import { resetRouter } from '/@/router'; +import { deepMerge } from '/@/utils'; + +interface AppState { + darkMode?: ThemeEnum; + // Page loading status + pageLoading: boolean; + // project config + projectConfig: ProjectConfig | null; + // When the window shrinks, remember some states, and restore these states when the window is restored + beforeMiniInfo: BeforeMiniState; +} +let timeId: TimeoutHandle; +export const useAppStore = defineStore({ + id: 'app', + state: (): AppState => ({ + darkMode: undefined, + pageLoading: false, + projectConfig: Persistent.getLocal(PROJ_CFG_KEY), + beforeMiniInfo: {}, + }), + getters: { + getPageLoading(state): boolean { + return state.pageLoading; + }, + getDarkMode(state): 'light' | 'dark' | string { + return state.darkMode || localStorage.getItem(APP_DARK_MODE_KEY) || darkMode; + }, + + getBeforeMiniInfo(state): BeforeMiniState { + return state.beforeMiniInfo; + }, + + getProjectConfig(state): ProjectConfig { + return state.projectConfig || ({} as ProjectConfig); + }, + + getHeaderSetting(): HeaderSetting { + return this.getProjectConfig.headerSetting; + }, + getMenuSetting(): MenuSetting { + return this.getProjectConfig.menuSetting; + }, + getTransitionSetting(): TransitionSetting { + return this.getProjectConfig.transitionSetting; + }, + getMultiTabsSetting(): MultiTabsSetting { + return this.getProjectConfig.multiTabsSetting; + }, + }, + actions: { + setPageLoading(loading: boolean): void { + this.pageLoading = loading; + }, + + setDarkMode(mode: ThemeEnum): void { + this.darkMode = mode; + localStorage.setItem(APP_DARK_MODE_KEY, mode); + }, + + setBeforeMiniInfo(state: BeforeMiniState): void { + this.beforeMiniInfo = state; + }, + + setProjectConfig(config: DeepPartial): void { + this.projectConfig = deepMerge(this.projectConfig || {}, config) as ProjectConfig; + Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig); + }, + setMenuSetting(setting: Partial): void { + this.projectConfig!.menuSetting = deepMerge(this.projectConfig!.menuSetting, setting); + Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig); + }, + + async resetAllState() { + resetRouter(); + Persistent.clearAll(); + }, + async setPageLoadingAction(loading: boolean): Promise { + if (loading) { + clearTimeout(timeId); + // Prevent flicker + timeId = setTimeout(() => { + this.setPageLoading(loading); + }, 50); + } else { + this.setPageLoading(loading); + clearTimeout(timeId); + } + }, + }, +}); + +// Need to be used outside the setup +export function useAppStoreWithOut() { + return useAppStore(store); +} diff --git a/src/store/modules/errorLog.ts b/src/store/modules/errorLog.ts new file mode 100644 index 0000000..ffbdc0b --- /dev/null +++ b/src/store/modules/errorLog.ts @@ -0,0 +1,77 @@ +import type { ErrorLogInfo } from '/#/store'; + +import { defineStore } from 'pinia'; +import { store } from '/@/store'; + +import { formatToDateTime } from '/@/utils/dateUtil'; +import projectSetting from '/@/settings/projectSetting'; + +import { ErrorTypeEnum } from '/@/enums/exceptionEnum'; + +export interface ErrorLogState { + errorLogInfoList: Nullable; + errorLogListCount: number; +} + +export const useErrorLogStore = defineStore({ + id: 'app-error-log', + state: (): ErrorLogState => ({ + errorLogInfoList: null, + errorLogListCount: 0, + }), + getters: { + getErrorLogInfoList(state): ErrorLogInfo[] { + return state.errorLogInfoList || []; + }, + getErrorLogListCount(state): number { + return state.errorLogListCount; + }, + }, + actions: { + addErrorLogInfo(info: ErrorLogInfo) { + const item = { + ...info, + time: formatToDateTime(new Date()), + }; + this.errorLogInfoList = [item, ...(this.errorLogInfoList || [])]; + this.errorLogListCount += 1; + }, + + setErrorLogListCount(count: number): void { + this.errorLogListCount = count; + }, + + /** + * Triggered after ajax request error + * @param error + * @returns + */ + addAjaxErrorInfo(error) { + const { useErrorHandle } = projectSetting; + if (!useErrorHandle) { + return; + } + const errInfo: Partial = { + message: error.message, + type: ErrorTypeEnum.AJAX, + }; + if (error.response) { + const { + config: { url = '', data: params = '', method = 'get', headers = {} } = {}, + data = {}, + } = error.response; + errInfo.url = url; + errInfo.name = 'Ajax Error!'; + errInfo.file = '-'; + errInfo.stack = JSON.stringify(data); + errInfo.detail = JSON.stringify({ params, method, headers }); + } + this.addErrorLogInfo(errInfo as ErrorLogInfo); + }, + }, +}); + +// Need to be used outside the setup +export function useErrorLogStoreWithOut() { + return useErrorLogStore(store); +} diff --git a/src/store/modules/locale.ts b/src/store/modules/locale.ts new file mode 100644 index 0000000..2014fbb --- /dev/null +++ b/src/store/modules/locale.ts @@ -0,0 +1,72 @@ +import type { LocaleSetting, LocaleType } from '/#/config'; + +import { defineStore } from 'pinia'; +import { store } from '@/store'; + +import { LOCALE_KEY } from '@/enums/cacheEnum'; +import { createLocalStorage } from '@/utils/cache'; +import { localeSetting } from '@/settings/localeSetting'; +import {useUserStore} from "@/store/modules/user"; +import {updateUser} from "@/api/sys/user"; +import {updateUserInfoReq} from "@/api/sys/model/userModel"; +import {ref} from "vue"; + +const ls = createLocalStorage(); +const lsLocaleSetting = (ls.get(LOCALE_KEY) || localeSetting) as LocaleSetting; + +interface LocaleState { + localInfo: LocaleSetting; +} + +export const useLocaleStore = defineStore({ + id: 'app-locale', + state: (): LocaleState => ({ + localInfo: lsLocaleSetting, + }), + getters: { + getShowPicker(state): boolean { + return !!state.localInfo?.showPicker; + }, + getLocale(state): LocaleType { + return state.localInfo?.locale ?? 'zh_CN'; + }, + }, + actions: { + /** + * Set up multilingual information and cache + * @param info multilingual info + */ + setLocaleInfo(info: Partial) { + this.localInfo = { ...this.localInfo, ...info }; + ls.set(LOCALE_KEY, this.localInfo); + const userStore = useUserStore(); + + const reqLanguage = ref(''); + if(this.localInfo.locale === 'en') { + reqLanguage.value = 'en_US' + } else if (this.localInfo.locale === 'zh_CN') { + reqLanguage.value = 'zh_CN' + } + const data: updateUserInfoReq = { + id: userStore.getUserInfo.id, + systemLanguage: reqLanguage.value, + name: userStore.getUserInfo.name + } + updateUser(data); + }, + /** + * Initialize multilingual information and load the existing configuration from the local cache + */ + initLocale() { + this.setLocaleInfo({ + ...localeSetting, + ...this.localInfo, + }); + }, + }, +}); + +// Need to be used outside the setup +export function useLocaleStoreWithOut() { + return useLocaleStore(store); +} diff --git a/src/store/modules/lock.ts b/src/store/modules/lock.ts new file mode 100644 index 0000000..da5ea00 --- /dev/null +++ b/src/store/modules/lock.ts @@ -0,0 +1,59 @@ +import type { LockInfo } from '/#/store'; + +import { defineStore } from 'pinia'; + +import { LOCK_INFO_KEY } from '/@/enums/cacheEnum'; +import { Persistent } from '/@/utils/cache/persistent'; +import { useUserStore } from './user'; + +interface LockState { + lockInfo: Nullable; +} + +export const useLockStore = defineStore({ + id: 'app-lock', + state: (): LockState => ({ + lockInfo: Persistent.getLocal(LOCK_INFO_KEY), + }), + getters: { + getLockInfo(state): Nullable { + return state.lockInfo; + }, + }, + actions: { + setLockInfo(info: LockInfo) { + this.lockInfo = Object.assign({}, this.lockInfo, info); + Persistent.setLocal(LOCK_INFO_KEY, this.lockInfo, true); + }, + resetLockInfo() { + Persistent.removeLocal(LOCK_INFO_KEY, true); + this.lockInfo = null; + }, + // Unlock + async unLock(password?: string) { + const userStore = useUserStore(); + if (this.lockInfo?.pwd === password) { + this.resetLockInfo(); + return true; + } + const tryLogin = async () => { + try { + const username = userStore.getUserInfo?.username; + const res = await userStore.login({ + username, + password: password!, + goHome: false, + mode: 'none', + }); + if (res) { + this.resetLockInfo(); + } + return res; + } catch (error) { + return false; + } + }; + return await tryLogin(); + }, + }, +}); diff --git a/src/store/modules/multipleTab.ts b/src/store/modules/multipleTab.ts new file mode 100644 index 0000000..e21030f --- /dev/null +++ b/src/store/modules/multipleTab.ts @@ -0,0 +1,361 @@ +import type { RouteLocationNormalized, RouteLocationRaw, Router } from 'vue-router'; + +import { toRaw, unref } from 'vue'; +import { defineStore } from 'pinia'; +import { store } from '/@/store'; + +import { useGo, useRedo } from '/@/hooks/web/usePage'; +import { Persistent } from '/@/utils/cache/persistent'; + +import { PageEnum } from '/@/enums/pageEnum'; +import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/routes/basic'; +import { getRawRoute } from '/@/utils'; +import { MULTIPLE_TABS_KEY } from '/@/enums/cacheEnum'; + +import projectSetting from '/@/settings/projectSetting'; +import { useUserStore } from '/@/store/modules/user'; + +export interface MultipleTabState { + cacheTabList: Set; + tabList: RouteLocationNormalized[]; + lastDragEndIndex: number; +} + +function handleGotoPage(router: Router) { + const go = useGo(router); + go(unref(router.currentRoute).fullPath, true); +} + +const getToTarget = (tabItem: RouteLocationNormalized) => { + const { params, path, query } = tabItem; + return { + params: params || {}, + path, + query: query || {}, + }; +}; + +const cacheTab = projectSetting.multiTabsSetting.cache; + +export const useMultipleTabStore = defineStore({ + id: 'app-multiple-tab', + state: (): MultipleTabState => ({ + // Tabs that need to be cached + cacheTabList: new Set(), + // multiple tab list + tabList: cacheTab ? Persistent.getLocal(MULTIPLE_TABS_KEY) || [] : [], + // Index of the last moved tab + lastDragEndIndex: 0, + }), + getters: { + getTabList(state): RouteLocationNormalized[] { + return state.tabList; + }, + getCachedTabList(state): string[] { + return Array.from(state.cacheTabList); + }, + getLastDragEndIndex(state): number { + return state.lastDragEndIndex; + }, + }, + actions: { + /** + * Update the cache according to the currently opened tabs + */ + async updateCacheTab() { + const cacheMap: Set = new Set(); + + for (const tab of this.tabList) { + const item = getRawRoute(tab); + // Ignore the cache + const needCache = !item.meta?.ignoreKeepAlive; + if (!needCache) { + continue; + } + const name = item.name as string; + cacheMap.add(name); + } + this.cacheTabList = cacheMap; + }, + + /** + * Refresh tabs + */ + async refreshPage(router: Router) { + const { currentRoute } = router; + const route = unref(currentRoute); + const name = route.name; + + const findTab = this.getCachedTabList.find((item) => item === name); + if (findTab) { + this.cacheTabList.delete(findTab); + } + const redo = useRedo(router); + await redo(); + }, + clearCacheTabs(): void { + this.cacheTabList = new Set(); + }, + resetState(): void { + this.tabList = []; + this.clearCacheTabs(); + }, + goToPage(router: Router) { + const go = useGo(router); + const len = this.tabList.length; + const { path } = unref(router.currentRoute); + + let toPath: PageEnum | string = PageEnum.BASE_HOME; + + if (len > 0) { + const page = this.tabList[len - 1]; + const p = page.fullPath || page.path; + if (p) { + toPath = p; + } + } + // Jump to the current page and report an error + path !== toPath && go(toPath as PageEnum, true); + }, + + async addTab(route: RouteLocationNormalized) { + const { path, name, fullPath, params, query, meta } = getRawRoute(route); + // 404 The page does not need to add a tab + if ( + path === PageEnum.ERROR_PAGE || + path === PageEnum.BASE_LOGIN || + !name || + [REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string) + ) { + return; + } + + let updateIndex = -1; + // Existing pages, do not add tabs repeatedly + const tabHasExits = this.tabList.some((tab, index) => { + updateIndex = index; + return decodeURIComponent(tab.fullPath || tab.path) === decodeURIComponent(fullPath || path); + }); + + // If the tab already exists, perform the update operation + if (tabHasExits) { + const curTab = toRaw(this.tabList)[updateIndex]; + if (!curTab) { + return; + } + curTab.params = params || curTab.params; + curTab.query = query || curTab.query; + curTab.fullPath = fullPath || curTab.fullPath; + this.tabList.splice(updateIndex, 1, curTab); + } else { + // Add tab + // 获取动态路由打开数,超过 0 即代表需要控制打开数 + const dynamicLevel = meta?.dynamicLevel ?? -1; + if (dynamicLevel > 0) { + // 如果动态路由层级大于 0 了,那么就要限制该路由的打开数限制了 + // 首先获取到真实的路由,使用配置方式减少计算开销. + // const realName: string = path.match(/(\S*)\//)![1]; + const realPath = meta?.realPath ?? ''; + // 获取到已经打开的动态路由数, 判断是否大于某一个值 + if ( + this.tabList.filter((e) => e.meta?.realPath ?? '' === realPath).length >= dynamicLevel + ) { + // 关闭第一个 + const index = this.tabList.findIndex((item) => item.meta.realPath === realPath); + index !== -1 && this.tabList.splice(index, 1); + } + } + this.tabList.push(route); + } + this.updateCacheTab(); + cacheTab && Persistent.setLocal(MULTIPLE_TABS_KEY, this.tabList); + }, + + async closeTab(tab: RouteLocationNormalized, router: Router) { + const close = (route: RouteLocationNormalized) => { + const { fullPath, meta: { affix } = {} } = route; + if (affix) { + return; + } + const index = this.tabList.findIndex((item) => item.fullPath === fullPath); + index !== -1 && this.tabList.splice(index, 1); + }; + + const { currentRoute, replace } = router; + + const { path } = unref(currentRoute); + if (path !== tab.path) { + // Closed is not the activation tab + close(tab); + this.updateCacheTab(); + return; + } + + // Closed is activated atb + let toTarget: RouteLocationRaw = {}; + + const index = this.tabList.findIndex((item) => item.path === path); + + // If the current is the leftmost tab + if (index === 0) { + // There is only one tab, then jump to the homepage, otherwise jump to the right tab + if (this.tabList.length === 1) { + const userStore = useUserStore(); + toTarget = userStore.getUserInfo.homePath || PageEnum.BASE_HOME; + } else { + // Jump to the right tab + const page = this.tabList[index + 1]; + toTarget = getToTarget(page); + } + } else { + // Close the current tab + const page = this.tabList[index - 1]; + toTarget = getToTarget(page); + } + close(currentRoute.value); + await replace(toTarget); + }, + + // Close according to key + async closeTabByKey(key: string, router: Router) { + const index = this.tabList.findIndex((item) => (item.fullPath || item.path) === key); + if (index !== -1) { + await this.closeTab(this.tabList[index], router); + const { currentRoute, replace } = router; + // 检查当前路由是否存在于tabList中 + const isActivated = this.tabList.findIndex((item) => { + return item.fullPath === currentRoute.value.fullPath; + }); + // 如果当前路由不存在于TabList中,尝试切换到其它路由 + if (isActivated === -1) { + let pageIndex; + if (index > 0) { + pageIndex = index - 1; + } else if (index < this.tabList.length - 1) { + pageIndex = index + 1; + } else { + pageIndex = -1; + } + if (pageIndex >= 0) { + const page = this.tabList[index - 1]; + const toTarget = getToTarget(page); + await replace(toTarget); + } + } + } + }, + + // Sort the tabs + async sortTabs(oldIndex: number, newIndex: number) { + const currentTab = this.tabList[oldIndex]; + this.tabList.splice(oldIndex, 1); + this.tabList.splice(newIndex, 0, currentTab); + this.lastDragEndIndex = this.lastDragEndIndex + 1; + }, + + // Close the tab on the right and jump + async closeLeftTabs(route: RouteLocationNormalized, router: Router) { + const index = this.tabList.findIndex((item) => item.path === route.path); + + if (index > 0) { + const leftTabs = this.tabList.slice(0, index); + const pathList: string[] = []; + for (const item of leftTabs) { + const affix = item?.meta?.affix ?? false; + if (!affix) { + pathList.push(item.fullPath); + } + } + this.bulkCloseTabs(pathList); + } + this.updateCacheTab(); + handleGotoPage(router); + }, + + // Close the tab on the left and jump + async closeRightTabs(route: RouteLocationNormalized, router: Router) { + const index = this.tabList.findIndex((item) => item.fullPath === route.fullPath); + + if (index >= 0 && index < this.tabList.length - 1) { + const rightTabs = this.tabList.slice(index + 1, this.tabList.length); + + const pathList: string[] = []; + for (const item of rightTabs) { + const affix = item?.meta?.affix ?? false; + if (!affix) { + pathList.push(item.fullPath); + } + } + this.bulkCloseTabs(pathList); + } + this.updateCacheTab(); + handleGotoPage(router); + }, + + async closeAllTab(router: Router) { + this.tabList = this.tabList.filter((item) => item?.meta?.affix ?? false); + this.clearCacheTabs(); + this.goToPage(router); + }, + + /** + * Close other tabs + */ + async closeOtherTabs(route: RouteLocationNormalized, router: Router) { + const closePathList = this.tabList.map((item) => item.fullPath); + + const pathList: string[] = []; + + for (const path of closePathList) { + if (path !== route.fullPath) { + const closeItem = this.tabList.find((item) => item.fullPath === path); + if (!closeItem) { + continue; + } + const affix = closeItem?.meta?.affix ?? false; + if (!affix) { + pathList.push(closeItem.fullPath); + } + } + } + this.bulkCloseTabs(pathList); + this.updateCacheTab(); + Persistent.setLocal(MULTIPLE_TABS_KEY, this.tabList, true); + handleGotoPage(router); + }, + + /** + * Close tabs in bulk + */ + async bulkCloseTabs(pathList: string[]) { + this.tabList = this.tabList.filter((item) => !pathList.includes(item.fullPath)); + }, + + /** + * Set tab's title + */ + async setTabTitle(title: string, route: RouteLocationNormalized) { + const findTab = this.getTabList.find((item) => item === route); + if (findTab) { + findTab.meta.title = title; + await this.updateCacheTab(); + } + }, + /** + * replace tab's path + * **/ + async updateTabPath(fullPath: string, route: RouteLocationNormalized) { + const findTab = this.getTabList.find((item) => item === route); + if (findTab) { + findTab.fullPath = fullPath; + findTab.path = fullPath; + await this.updateCacheTab(); + } + }, + }, +}); + +// Need to be used outside the setup +export function useMultipleTabWithOutStore() { + return useMultipleTabStore(store); +} diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts new file mode 100644 index 0000000..eeee84f --- /dev/null +++ b/src/store/modules/permission.ts @@ -0,0 +1,276 @@ +import type { AppRouteRecordRaw, Menu } from '/@/router/types'; + +import { defineStore } from 'pinia'; +import { store } from '/@/store'; +import { useI18n } from '/@/hooks/web/useI18n'; +import { useUserStore } from './user'; +import { useAppStoreWithOut } from './app'; +import { toRaw } from 'vue'; +import { transformObjToRoute, flatMultiLevelRoutes } from '/@/router/helper/routeHelper'; +import { transformRouteToMenu } from '/@/router/helper/menuHelper'; + +import projectSetting from '/@/settings/projectSetting'; + +import { PermissionModeEnum } from '/@/enums/appEnum'; + +import { asyncRoutes } from '/@/router/routes'; +import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'; + +import { filter } from '/@/utils/helper/treeHelper'; + +import { getMenuList } from '/@/api/sys/menu'; +import { getPermCode } from '/@/api/sys/user'; + +import { useMessage } from '/@/hooks/web/useMessage'; +import { PageEnum } from '/@/enums/pageEnum'; +import {array2tree} from "@axolo/tree-array"; + +interface PermissionState { + // Permission code list + // 权限代码列表 + permCodeList: string[] | number[]; + // Whether the route has been dynamically added + // 路由是否动态添加 + isDynamicAddedRoute: boolean; + // To trigger a menu update + // 触发菜单更新 + lastBuildMenuTime: number; + // Backstage menu list + // 后台菜单列表 + backMenuList: Menu[]; + // 菜单列表 + frontMenuList: Menu[]; +} + +export const usePermissionStore = defineStore({ + id: 'app-permission', + state: (): PermissionState => ({ + // 权限代码列表 + permCodeList: [], + // Whether the route has been dynamically added + // 路由是否动态添加 + isDynamicAddedRoute: false, + // To trigger a menu update + // 触发菜单更新 + lastBuildMenuTime: 0, + // Backstage menu list + // 后台菜单列表 + backMenuList: [], + // menu List + // 菜单列表 + frontMenuList: [], + }), + getters: { + getPermCodeList(state): string[] | number[] { + return state.permCodeList; + }, + getBackMenuList(state): Menu[] { + return state.backMenuList; + }, + getFrontMenuList(state): Menu[] { + return state.frontMenuList; + }, + getLastBuildMenuTime(state): number { + return state.lastBuildMenuTime; + }, + getIsDynamicAddedRoute(state): boolean { + return state.isDynamicAddedRoute; + }, + }, + actions: { + setPermCodeList(codeList: string[]) { + this.permCodeList = codeList; + }, + + setBackMenuList(list: Menu[]) { + this.backMenuList = list; + list?.length > 0 && this.setLastBuildMenuTime(); + }, + + setFrontMenuList(list: Menu[]) { + this.frontMenuList = list; + }, + + setLastBuildMenuTime() { + this.lastBuildMenuTime = new Date().getTime(); + }, + + setDynamicAddedRoute(added: boolean) { + this.isDynamicAddedRoute = added; + }, + resetState(): void { + this.isDynamicAddedRoute = false; + this.permCodeList = []; + this.backMenuList = []; + this.lastBuildMenuTime = 0; + }, + async changePermissionCode() { + const codeList = await getPermCode(); + this.setPermCodeList(codeList); + }, + + // 构建路由 + async buildRoutesAction(): Promise { + const { t } = useI18n(); + const userStore = useUserStore(); + const appStore = useAppStoreWithOut(); + + let routes: AppRouteRecordRaw[] = []; + const roleList = toRaw(userStore.getRoleList) || []; + const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig; + + // 路由过滤器 在 函数filter 作为回调传入遍历使用 + const routeFilter = (route: AppRouteRecordRaw) => { + const { meta } = route; + // 抽出角色 + const { roles } = meta || {}; + if (!roles) return true; + // 进行角色权限判断 + return roleList.some((role) => roles.includes(role)); + }; + + const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => { + const { meta } = route; + // ignoreRoute 为true 则路由仅用于菜单生成,不会在实际的路由表中出现 + const { ignoreRoute } = meta || {}; + // arr.filter 返回 true 表示该元素通过测试 + return !ignoreRoute; + }; + + /** + * @description 根据设置的首页path,修正routes中的affix标记(固定首页) + * */ + const patchHomeAffix = (routes: AppRouteRecordRaw[]) => { + if (!routes || routes.length === 0) return; + let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME; + + function patcher(routes: AppRouteRecordRaw[], parentPath = '') { + if (parentPath) parentPath = parentPath + '/'; + routes.forEach((route: AppRouteRecordRaw) => { + const { path, children, redirect } = route; + const currentPath = path.startsWith('/') ? path : parentPath + path; + if (currentPath === homePath) { + if (redirect) { + homePath = route.redirect! as string; + } else { + route.meta = Object.assign({}, route.meta, { affix: true }); + throw new Error('end'); + } + } + children && children.length > 0 && patcher(children, currentPath); + }); + } + + try { + patcher(routes); + } catch (e) { + // 已处理完毕跳出循环 + } + return; + }; + + switch (permissionMode) { + // 角色权限 + case PermissionModeEnum.ROLE: + // 对非一级路由进行过滤 + routes = filter(asyncRoutes, routeFilter); + // 对一级路由根据角色权限过滤 + routes = routes.filter(routeFilter); + // Convert multi-level routing to level 2 routing + // 将多级路由转换为 2 级路由 + routes = flatMultiLevelRoutes(routes); + break; + + // 路由映射, 默认进入该case + case PermissionModeEnum.ROUTE_MAPPING: + // 对非一级路由进行过滤 + routes = filter(asyncRoutes, routeFilter); + // 对一级路由再次根据角色权限过滤 + routes = routes.filter(routeFilter); + // 将路由转换成菜单 + const menuList = transformRouteToMenu(routes, true); + // 移除掉 ignoreRoute: true 的路由 非一级路由 + routes = filter(routes, routeRemoveIgnoreFilter); + // 移除掉 ignoreRoute: true 的路由 一级路由; + routes = routes.filter(routeRemoveIgnoreFilter); + // 对菜单进行排序 + menuList.sort((a, b) => { + return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0); + }); + + // 设置菜单列表 + this.setFrontMenuList(menuList); + + // Convert multi-level routing to level 2 routing + // 将多级路由转换为 2 级路由 + routes = flatMultiLevelRoutes(routes); + break; + + // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below + // 如果确定不需要做后台动态权限,请在下方注释整个判断 + case PermissionModeEnum.BACK: + const { createMessage } = useMessage(); + + createMessage.loading({ + content: t('sys.app.menuLoading'), + duration: 1, + }); + + // !Simulate to obtain permission codes from the background, + // 模拟从后台获取权限码, + // this function may only need to be executed once, and the actual project can be put at the right time by itself + // 这个功能可能只需要执行一次,实际项目可以自己放在合适的时间 + let routeList: AppRouteRecordRaw[] = []; + try { + await this.changePermissionCode(); + // routeList = (await getMenuList()) as AppRouteRecordRaw[]; + const menus = await getMenuList(); + // 从localStorage中获取用户信息userInfo,获取userLanguage的值 如果是en_US,这里菜单就需要显示英文 重写菜单的title + const { userInfo } = userStore; + const systemLanguage = userInfo?.systemLanguage; + if (systemLanguage === 'en_US') { + menus.data.data.forEach((item: any) => { + item.meta.title = item.titleEnglish; + }); + } else { + menus.data.data.forEach((item: any) => { + item.meta.title = item.title; + }); + } + const menuTree = array2tree(menus.data.data); + routeList = menuTree as AppRouteRecordRaw[]; + } catch (error) { + console.error(error); + } + + // Dynamically introduce components + // 动态引入组件 + routeList = transformObjToRoute(routeList); + + // Background routing to menu structure + // 后台路由到菜单结构 + const backMenuList = transformRouteToMenu(routeList); + this.setBackMenuList(backMenuList); + + // remove meta.ignoreRoute item + // 删除 meta.ignoreRoute 项 + routeList = filter(routeList, routeRemoveIgnoreFilter); + routeList = routeList.filter(routeRemoveIgnoreFilter); + + routeList = flatMultiLevelRoutes(routeList); + routes = [PAGE_NOT_FOUND_ROUTE, ...routeList]; + break; + } + + routes.push(ERROR_LOG_ROUTE); + patchHomeAffix(routes); + return routes; + }, + }, +}); + +// Need to be used outside the setup +// 需要在设置之外使用 +export function usePermissionStoreWithOut() { + return usePermissionStore(store); +} diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts new file mode 100644 index 0000000..14e3290 --- /dev/null +++ b/src/store/modules/user.ts @@ -0,0 +1,233 @@ +import type { ErrorMessageMode } from '/#/axios'; +import { defineStore } from 'pinia'; +import { store } from '@/store'; +import { PageEnum } from '@/enums/pageEnum'; +import { ROLES_NAME_KEY, TOKEN_KEY, USER_INFO_KEY } from '@/enums/cacheEnum'; +import { getAuthCache, setAuthCache } from '@/utils/auth'; +import { + emailLoginReq, + GetUserInfoModel, + LoginReq, mobileLoginReq, +} from '@/api/sys/model/userModel'; +import {doLogout, emailLogin, getUserInfo, login, mobileLogin} from '@/api/sys/user'; +import { useI18n } from '@/hooks/web/useI18n'; +import { useMessage } from '@/hooks/web/useMessage'; +import { router } from '@/router'; +import { usePermissionStore } from '@/store/modules/permission'; +import { RouteRecordRaw } from 'vue-router'; +import { PAGE_NOT_FOUND_ROUTE } from '@/router/routes/basic'; +import { isArray } from '@/utils/is'; +import { h } from 'vue'; + +interface UserState { + userInfo: Nullable; + token?: string; + roleName: string[]; + sessionTimeout?: boolean; + lastUpdateTime: number; +} + +export const useUserStore = defineStore({ + id: 'app-user', + state: (): UserState => ({ + // user info + userInfo: null, + // token + token: undefined, + // roleList + roleList: [], + // role name + roleName: [], + // Whether the login expired + sessionTimeout: false, + // Last fetch time + lastUpdateTime: 0, + }), + getters: { + getUserInfo(): GetUserInfoModel { + return this.userInfo || getAuthCache(USER_INFO_KEY) || {}; + }, + getToken(): string { + return this.token || getAuthCache(TOKEN_KEY); + }, + getRoleName(): string[] { + return this.roleName.length > 0 ? this.roleName : getAuthCache(ROLES_NAME_KEY); + }, + getSessionTimeout(): boolean { + return !!this.sessionTimeout; + }, + getLastUpdateTime(): number { + return this.lastUpdateTime; + }, + }, + actions: { + setToken(info: string | undefined) { + this.token = info ? info : ''; // for null or undefined value + setAuthCache(TOKEN_KEY, info); + }, + setRoleName(roleName: string[]) { + this.roleName = roleName; + setAuthCache(ROLES_NAME_KEY, roleName); + }, + setUserInfo(info: GetUserInfoModel | null) { + this.userInfo = info; + this.lastUpdateTime = new Date().getTime(); + setAuthCache(USER_INFO_KEY, info); + }, + setSessionTimeout(flag: boolean) { + this.sessionTimeout = flag; + }, + resetState() { + this.userInfo = null; + this.token = ''; + this.roleName = []; + this.sessionTimeout = false; + }, + /** + * @description: login + */ + async login( + params: LoginReq & { + goHome?: boolean; + mode?: ErrorMessageMode; + }, + ): Promise { + try { + const { goHome = true, mode, ...loginParams } = params; + const data = await login(loginParams, mode); + if (data.code !== '00000') { + return Promise.reject(null); + } + const { token } = data.data; + + // save token + this.setToken(token); + return this.afterLoginAction(goHome); + } catch (error) { + return Promise.reject(error); + } + }, + + /** + * @description: mobileLogin + */ + async mobileLogin( + params: mobileLoginReq & { + goHome?: boolean; + mode?: ErrorMessageMode; + }, + ): Promise { + try { + const { goHome = true, mode, ...mobileLoginReq } = params; + const data = await mobileLogin(mobileLoginReq, mode); + if (data.code !== '00000') { + return Promise.reject(null); + } + const { token } = data.data; + + // save token + this.setToken(token); + return this.afterLoginAction(goHome); + } catch (error) { + return Promise.reject(error); + } + }, + + async emailLogin( + params: emailLoginReq & { + goHome?: boolean; + mode?: ErrorMessageMode; + }, + ): Promise { + try { + const { goHome = true, mode, ...emailLoginReq } = params; + const data = await emailLogin(emailLoginReq, mode); + if (data.code !== '00000') { + return Promise.reject(null); + } + const { token } = data.data; + + // save token + this.setToken(token); + return this.afterLoginAction(goHome); + } catch (error) { + return Promise.reject(error); + } + }, + + async afterLoginAction(goHome?: boolean): Promise { + if (!this.getToken) return null; + // get user info + const userInfo = await this.getUserInfoAction(); + + const sessionTimeout = this.sessionTimeout; + if (sessionTimeout) { + this.setSessionTimeout(false); + } else { + const permissionStore = usePermissionStore(); + if (!permissionStore.isDynamicAddedRoute) { + const routes = await permissionStore.buildRoutesAction(); + routes.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw); + }); + router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw); + permissionStore.setDynamicAddedRoute(true); + } + goHome && (await router.replace(userInfo?.homePath || PageEnum.BASE_HOME)); + } + return userInfo; + }, + async getUserInfoAction(): Promise { + if (!this.getToken) return null; + const userInfo = await getUserInfo(); + const { roles = [], roleName = [] } = userInfo.data; + if (isArray(roles)) { + const roleList = roles.map((item) => item.valueOf) as unknown as RoleEnum[]; + } else { + userInfo.data.roles = []; + } + this.setRoleName(roleName); + this.setUserInfo(userInfo.data); + return userInfo.data; + }, + /** + * @description: logout + */ + async logout(goLogin = false) { + if (this.getToken) { + try { + // in the future the server may need to log out, and we can uncomment this + await doLogout(); + console.log('logout successful'); + } catch { + console.log('注销Token失败'); + } + } + this.setToken(undefined); + this.setSessionTimeout(false); + this.setUserInfo(null); + goLogin && router.push(PageEnum.BASE_LOGIN); + }, + + /** + * @description: Confirm before logging out + */ + confirmLoginOut() { + const { createConfirm } = useMessage(); + const { t } = useI18n(); + createConfirm({ + iconType: 'warning', + title: () => h('span', t('sys.app.logoutTip')), + content: () => h('span', t('sys.app.logoutMessage')), + onOk: async () => { + await this.logout(true); + }, + }); + }, + }, +}); + +// Need to be used outside the setup +export function useUserStoreWithOut() { + return useUserStore(store); +} diff --git a/src/utils/.DS_Store b/src/utils/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4565f01f77bec8ae614fc741824934e9b1766c8b GIT binary patch literal 6148 zcmeHKOHRWu5FL|HD%ezF13NERutB0bHb|kA6Z8VmAFb4qs7jI8P7^(<*s|24WVsHF6HYN+^I*-O9V)wnfv_z3`S zhJGVeIDW4CJ^bPxo~J>?$U4rsju>_1_++w%`C--P;V*MN+@)XgzA|rwxi4ufS)-3{ zkB8Icc^I8n@|ow3IoYshvvm(FhCV0|6bK5G3h?@%(HIklg+;S;pfg7RV2oj7xHfAH zQ1bvVaadTy2u#^jpiNcoh@osc#R1lMU#TgZO7(< ex8fr-WAJId045F#ix`20KLSRE&;*4)6iM~ literal 0 HcmV?d00001 diff --git a/src/utils/auth/index.ts b/src/utils/auth/index.ts new file mode 100644 index 0000000..9459a9e --- /dev/null +++ b/src/utils/auth/index.ts @@ -0,0 +1,25 @@ +import { Persistent, BasicKeys } from '/@/utils/cache/persistent'; +import { CacheTypeEnum, TOKEN_KEY } from '/@/enums/cacheEnum'; +import projectSetting from '/@/settings/projectSetting'; + +const { permissionCacheType } = projectSetting; +const isLocal = permissionCacheType === CacheTypeEnum.LOCAL; + +export function getToken() { + return getAuthCache(TOKEN_KEY); +} + +export function getAuthCache(key: BasicKeys) { + const fn = isLocal ? Persistent.getLocal : Persistent.getSession; + return fn(key) as T; +} + +export function setAuthCache(key: BasicKeys, value) { + const fn = isLocal ? Persistent.setLocal : Persistent.setSession; + return fn(key, value, true); +} + +export function clearAuthCache(immediate = true) { + const fn = isLocal ? Persistent.clearLocal : Persistent.clearSession; + return fn(immediate); +} diff --git a/src/utils/bem.ts b/src/utils/bem.ts new file mode 100644 index 0000000..7dcadbc --- /dev/null +++ b/src/utils/bem.ts @@ -0,0 +1,52 @@ +import { prefixCls } from '/@/settings/designSetting'; + +type Mod = string | { [key: string]: any }; +type Mods = Mod | Mod[]; + +export type BEM = ReturnType; + +function genBem(name: string, mods?: Mods): string { + if (!mods) { + return ''; + } + + if (typeof mods === 'string') { + return ` ${name}--${mods}`; + } + + if (Array.isArray(mods)) { + return mods.reduce((ret, item) => ret + genBem(name, item), ''); + } + + return Object.keys(mods).reduce((ret, key) => ret + (mods[key] ? genBem(name, key) : ''), ''); +} + +/** + * bem helper + * b() // 'button' + * b('text') // 'button__text' + * b({ disabled }) // 'button button--disabled' + * b('text', { disabled }) // 'button__text button__text--disabled' + * b(['disabled', 'primary']) // 'button button--disabled button--primary' + */ +export function buildBEM(name: string) { + return (el?: Mods, mods?: Mods): Mods => { + if (el && typeof el !== 'string') { + mods = el; + el = ''; + } + + el = el ? `${name}__${el}` : name; + + return `${el}${genBem(el, mods)}`; + }; +} + +export function createBEM(name: string) { + return [buildBEM(`${prefixCls}-${name}`)]; +} + +export function createNamespace(name: string) { + const prefixedName = `${prefixCls}-${name}`; + return [prefixedName, buildBEM(prefixedName)] as const; +} diff --git a/src/utils/cache/index.ts b/src/utils/cache/index.ts new file mode 100644 index 0000000..01a11f5 --- /dev/null +++ b/src/utils/cache/index.ts @@ -0,0 +1,31 @@ +import { getStorageShortName } from '/@/utils/env'; +import { createStorage as create, CreateStorageParams } from './storageCache'; +import { enableStorageEncryption, DEFAULT_CACHE_TIME } from '/@/settings/encryptionSetting'; + +export type Options = Partial; + +const createOptions = (storage: Storage, options: Options = {}): Options => { + return { + // No encryption in debug mode + hasEncrypt: enableStorageEncryption, + storage, + prefixKey: getStorageShortName(), + ...options, + }; +}; + +export const WebStorage = create(createOptions(sessionStorage)); + +export const createStorage = (storage: Storage = sessionStorage, options: Options = {}) => { + return create(createOptions(storage, options)); +}; + +export const createSessionStorage = (options: Options = {}) => { + return createStorage(sessionStorage, { ...options, timeout: DEFAULT_CACHE_TIME }); +}; + +export const createLocalStorage = (options: Options = {}) => { + return createStorage(localStorage, { ...options, timeout: DEFAULT_CACHE_TIME }); +}; + +export default WebStorage; diff --git a/src/utils/cache/memory.ts b/src/utils/cache/memory.ts new file mode 100644 index 0000000..08a0a64 --- /dev/null +++ b/src/utils/cache/memory.ts @@ -0,0 +1,107 @@ +export interface Cache { + value?: V; + timeoutId?: ReturnType; + time?: number; + alive?: number; +} + +const NOT_ALIVE = 0; + +export class Memory { + private cache: { [key in keyof T]?: Cache } = {}; + private alive: number; + + constructor(alive = NOT_ALIVE) { + // Unit second + this.alive = alive * 1000; + } + + get getCache() { + return this.cache; + } + + setCache(cache) { + this.cache = cache; + } + + // get(key: K) { + // const item = this.getItem(key); + // const time = item?.time; + // if (!isNullOrUnDef(time) && time < new Date().getTime()) { + // this.remove(key); + // } + // return item?.value ?? undefined; + // } + + get(key: K) { + return this.cache[key]; + } + + set(key: K, value: V, expires?: number) { + let item = this.get(key); + + if (!expires || (expires as number) <= 0) { + expires = this.alive; + } + if (item) { + if (item.timeoutId) { + clearTimeout(item.timeoutId); + item.timeoutId = undefined; + } + item.value = value; + } else { + item = { value, alive: expires }; + this.cache[key] = item; + } + + if (!expires) { + return value; + } + const now = new Date().getTime(); + /** + * Prevent overflow of the setTimeout Maximum delay value + * Maximum delay value 2,147,483,647 ms + * https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value + */ + item.time = expires > now ? expires : now + expires; + item.timeoutId = setTimeout( + () => { + this.remove(key); + }, + expires > now ? expires - now : expires, + ); + + return value; + } + + remove(key: K) { + const item = this.get(key); + Reflect.deleteProperty(this.cache, key); + if (item) { + clearTimeout(item.timeoutId!); + return item.value; + } + } + + resetCache(cache: { [K in keyof T]: Cache }) { + Object.keys(cache).forEach((key) => { + const k = key as any as keyof T; + const item = cache[k]; + if (item && item.time) { + const now = new Date().getTime(); + const expire = item.time; + if (expire > now) { + this.set(k, item.value, expire); + } + } + }); + } + + clear() { + Object.keys(this.cache).forEach((key) => { + const item = this.cache[key]; + item.timeoutId && clearTimeout(item.timeoutId); + }); + this.cache = {}; + } +} diff --git a/src/utils/cache/persistent.ts b/src/utils/cache/persistent.ts new file mode 100644 index 0000000..cd68a36 --- /dev/null +++ b/src/utils/cache/persistent.ts @@ -0,0 +1,132 @@ +import type { LockInfo, UserInfo } from '/#/store'; +import type { ProjectConfig } from '/#/config'; +import type { RouteLocationNormalized } from 'vue-router'; + +import { createLocalStorage, createSessionStorage } from '/@/utils/cache'; +import { Memory } from './memory'; +import { + TOKEN_KEY, + USER_INFO_KEY, + ROLES_KEY, + LOCK_INFO_KEY, + PROJ_CFG_KEY, + APP_LOCAL_CACHE_KEY, + APP_SESSION_CACHE_KEY, + MULTIPLE_TABS_KEY, +} from '/@/enums/cacheEnum'; +import { DEFAULT_CACHE_TIME } from '/@/settings/encryptionSetting'; +import { toRaw } from 'vue'; +import { pick, omit } from 'lodash-es'; + +interface BasicStore { + [TOKEN_KEY]: string | number | null | undefined; + [USER_INFO_KEY]: UserInfo; + [ROLES_KEY]: string[]; + [LOCK_INFO_KEY]: LockInfo; + [PROJ_CFG_KEY]: ProjectConfig; + [MULTIPLE_TABS_KEY]: RouteLocationNormalized[]; +} + +type LocalStore = BasicStore; + +type SessionStore = BasicStore; + +export type BasicKeys = keyof BasicStore; +type LocalKeys = keyof LocalStore; +type SessionKeys = keyof SessionStore; + +const ls = createLocalStorage(); +const ss = createSessionStorage(); + +const localMemory = new Memory(DEFAULT_CACHE_TIME); +const sessionMemory = new Memory(DEFAULT_CACHE_TIME); + +function initPersistentMemory() { + const localCache = ls.get(APP_LOCAL_CACHE_KEY); + const sessionCache = ss.get(APP_SESSION_CACHE_KEY); + localCache && localMemory.resetCache(localCache); + sessionCache && sessionMemory.resetCache(sessionCache); +} + +export class Persistent { + static getLocal(key: LocalKeys) { + return localMemory.get(key)?.value as Nullable; + } + + static setLocal(key: LocalKeys, value: LocalStore[LocalKeys], immediate = false): void { + localMemory.set(key, toRaw(value)); + immediate && ls.set(APP_LOCAL_CACHE_KEY, localMemory.getCache); + } + + static removeLocal(key: LocalKeys, immediate = false): void { + localMemory.remove(key); + immediate && ls.set(APP_LOCAL_CACHE_KEY, localMemory.getCache); + } + + static clearLocal(immediate = false): void { + localMemory.clear(); + immediate && ls.clear(); + } + + static getSession(key: SessionKeys) { + return sessionMemory.get(key)?.value as Nullable; + } + + static setSession(key: SessionKeys, value: SessionStore[SessionKeys], immediate = false): void { + sessionMemory.set(key, toRaw(value)); + immediate && ss.set(APP_SESSION_CACHE_KEY, sessionMemory.getCache); + } + + static removeSession(key: SessionKeys, immediate = false): void { + sessionMemory.remove(key); + immediate && ss.set(APP_SESSION_CACHE_KEY, sessionMemory.getCache); + } + static clearSession(immediate = false): void { + sessionMemory.clear(); + immediate && ss.clear(); + } + + static clearAll(immediate = false) { + sessionMemory.clear(); + localMemory.clear(); + if (immediate) { + ls.clear(); + ss.clear(); + } + } +} + +window.addEventListener('beforeunload', function () { + // TOKEN_KEY 在登录或注销时已经写入到storage了,此处为了解决同时打开多个窗口时token不同步的问题 + // LOCK_INFO_KEY 在锁屏和解锁时写入,此处也不应修改 + ls.set(APP_LOCAL_CACHE_KEY, { + ...omit(localMemory.getCache, LOCK_INFO_KEY), + ...pick(ls.get(APP_LOCAL_CACHE_KEY), [TOKEN_KEY, USER_INFO_KEY, LOCK_INFO_KEY]), + }); + ss.set(APP_SESSION_CACHE_KEY, { + ...omit(sessionMemory.getCache, LOCK_INFO_KEY), + ...pick(ss.get(APP_SESSION_CACHE_KEY), [TOKEN_KEY, USER_INFO_KEY, LOCK_INFO_KEY]), + }); +}); + +function storageChange(e: any) { + const { key, newValue, oldValue } = e; + + if (!key) { + Persistent.clearAll(); + return; + } + + if (!!newValue && !!oldValue) { + if (APP_LOCAL_CACHE_KEY === key) { + Persistent.clearLocal(); + } + if (APP_SESSION_CACHE_KEY === key) { + Persistent.clearSession(); + } + } +} + +window.addEventListener('storage', storageChange); + +initPersistentMemory(); diff --git a/src/utils/cache/storageCache.ts b/src/utils/cache/storageCache.ts new file mode 100644 index 0000000..84ba2aa --- /dev/null +++ b/src/utils/cache/storageCache.ts @@ -0,0 +1,111 @@ +import { cacheCipher } from '/@/settings/encryptionSetting'; +import type { EncryptionParams } from '/@/utils/cipher'; +import { AesEncryption } from '/@/utils/cipher'; +import { isNullOrUnDef } from '/@/utils/is'; + +export interface CreateStorageParams extends EncryptionParams { + prefixKey: string; + storage: Storage; + hasEncrypt: boolean; + timeout?: Nullable; +} +export const createStorage = ({ + prefixKey = '', + storage = sessionStorage, + key = cacheCipher.key, + iv = cacheCipher.iv, + timeout = null, + hasEncrypt = true, +}: Partial = {}) => { + if (hasEncrypt && [key.length, iv.length].some((item) => item !== 16)) { + throw new Error('When hasEncrypt is true, the key or iv must be 16 bits!'); + } + + const encryption = new AesEncryption({ key, iv }); + + /** + * Cache class + * Construction parameters can be passed into sessionStorage, localStorage, + * @class Cache + * @example + */ + const WebStorage = class WebStorage { + private storage: Storage; + private prefixKey?: string; + private encryption: AesEncryption; + private hasEncrypt: boolean; + /** + * + * @param {*} storage + */ + constructor() { + this.storage = storage; + this.prefixKey = prefixKey; + this.encryption = encryption; + this.hasEncrypt = hasEncrypt; + } + + private getKey(key: string) { + return `${this.prefixKey}${key}`.toUpperCase(); + } + + /** + * Set cache + * @param {string} key + * @param {*} value + * @param {*} expire Expiration time in seconds + * @memberof Cache + */ + set(key: string, value: any, expire: number | null = timeout) { + const stringData = JSON.stringify({ + value, + time: Date.now(), + expire: !isNullOrUnDef(expire) ? new Date().getTime() + expire * 1000 : null, + }); + const stringifyValue = this.hasEncrypt + ? this.encryption.encryptByAES(stringData) + : stringData; + this.storage.setItem(this.getKey(key), stringifyValue); + } + + /** + * Read cache + * @param {string} key + * @param {*} def + * @memberof Cache + */ + get(key: string, def: any = null): any { + const val = this.storage.getItem(this.getKey(key)); + if (!val) return def; + + try { + const decVal = this.hasEncrypt ? this.encryption.decryptByAES(val) : val; + const data = JSON.parse(decVal); + const { value, expire } = data; + if (isNullOrUnDef(expire) || expire >= new Date().getTime()) { + return value; + } + this.remove(key); + } catch (e) { + return def; + } + } + + /** + * Delete cache based on key + * @param {string} key + * @memberof Cache + */ + remove(key: string) { + this.storage.removeItem(this.getKey(key)); + } + + /** + * Delete all caches of this instance + */ + clear(): void { + this.storage.clear(); + } + }; + return new WebStorage(); +}; diff --git a/src/utils/cipher.ts b/src/utils/cipher.ts new file mode 100644 index 0000000..7a02cfc --- /dev/null +++ b/src/utils/cipher.ts @@ -0,0 +1,54 @@ +import { encrypt, decrypt } from 'crypto-js/aes'; +import UTF8, { parse } from 'crypto-js/enc-utf8'; +import pkcs7 from 'crypto-js/pad-pkcs7'; +import ECB from 'crypto-js/mode-ecb'; +import md5 from 'crypto-js/md5'; +import Base64 from 'crypto-js/enc-base64'; + +export interface EncryptionParams { + key: string; + iv: string; +} + +export class AesEncryption { + private key; + private iv; + + constructor(opt: Partial = {}) { + const { key, iv } = opt; + if (key) { + this.key = parse(key); + } + if (iv) { + this.iv = parse(iv); + } + } + + get getOptions() { + return { + mode: ECB, + padding: pkcs7, + iv: this.iv, + }; + } + + encryptByAES(cipherText: string) { + return encrypt(cipherText, this.key, this.getOptions).toString(); + } + + decryptByAES(cipherText: string) { + return decrypt(cipherText, this.key, this.getOptions).toString(UTF8); + } +} + +export function encryptByBase64(cipherText: string) { + return UTF8.parse(cipherText).toString(Base64); +} + +export function decodeByBase64(cipherText: string) { + return Base64.parse(cipherText).toString(UTF8); +} + +export function encryptByMd5(password: string) { + return md5(password).toString(); +} diff --git a/src/utils/color.ts b/src/utils/color.ts new file mode 100644 index 0000000..3c0ca5e --- /dev/null +++ b/src/utils/color.ts @@ -0,0 +1,151 @@ +/** + * 判断是否 十六进制颜色值. + * 输入形式可为 #fff000 #f00 + * + * @param String color 十六进制颜色值 + * @return Boolean + */ +export function isHexColor(color: string) { + const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/; + return reg.test(color); +} + +/** + * RGB 颜色值转换为 十六进制颜色值. + * r, g, 和 b 需要在 [0, 255] 范围内 + * + * @return String 类似#ff00ff + * @param r + * @param g + * @param b + */ +export function rgbToHex(r: number, g: number, b: number) { + // tslint:disable-next-line:no-bitwise + const hex = ((r << 16) | (g << 8) | b).toString(16); + return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex; +} + +/** + * Transform a HEX color to its RGB representation + * @param {string} hex The color to transform + * @returns The RGB representation of the passed color + */ +export function hexToRGB(hex: string) { + let sHex = hex.toLowerCase(); + if (isHexColor(hex)) { + if (sHex.length === 4) { + let sColorNew = '#'; + for (let i = 1; i < 4; i += 1) { + sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1)); + } + sHex = sColorNew; + } + const sColorChange: number[] = []; + for (let i = 1; i < 7; i += 2) { + sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2))); + } + return 'RGB(' + sColorChange.join(',') + ')'; + } + return sHex; +} + +export function colorIsDark(color: string) { + if (!isHexColor(color)) return; + const [r, g, b] = hexToRGB(color) + .replace(/(?:\(|\)|rgb|RGB)*/g, '') + .split(',') + .map((item) => Number(item)); + return r * 0.299 + g * 0.578 + b * 0.114 < 192; +} + +/** + * Darkens a HEX color given the passed percentage + * @param {string} color The color to process + * @param {number} amount The amount to change the color by + * @returns {string} The HEX representation of the processed color + */ +export function darken(color: string, amount: number) { + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color; + amount = Math.trunc((255 * amount) / 100); + return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight( + color.substring(2, 4), + amount, + )}${subtractLight(color.substring(4, 6), amount)}`; +} + +/** + * Lightens a 6 char HEX color according to the passed percentage + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed color represented as HEX + */ +export function lighten(color: string, amount: number) { + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color; + amount = Math.trunc((255 * amount) / 100); + return `#${addLight(color.substring(0, 2), amount)}${addLight( + color.substring(2, 4), + amount, + )}${addLight(color.substring(4, 6), amount)}`; +} + +/* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */ +/** + * Sums the passed percentage to the R, G or B of a HEX color + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed part of the color + */ +function addLight(color: string, amount: number) { + const cc = parseInt(color, 16) + amount; + const c = cc > 255 ? 255 : cc; + return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`; +} + +/** + * Calculates luminance of an rgb color + * @param {number} r red + * @param {number} g green + * @param {number} b blue + */ +function luminanace(r: number, g: number, b: number) { + const a = [r, g, b].map((v) => { + v /= 255; + return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4); + }); + return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722; +} + +/** + * Calculates contrast between two rgb colors + * @param {string} rgb1 rgb color 1 + * @param {string} rgb2 rgb color 2 + */ +function contrast(rgb1: string[], rgb2: number[]) { + return ( + (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) / + (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05) + ); +} + +/** + * Determines what the best text color is (black or white) based con the contrast with the background + * @param hexColor - Last selected color by the user + */ +export function calculateBestTextColor(hexColor: string) { + const rgbColor = hexToRGB(hexColor.substring(1)); + const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0]); + + return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF'; +} + +/** + * Subtracts the indicated percentage to the R, G or B of a HEX color + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed part of the color + */ +function subtractLight(color: string, amount: number) { + const cc = parseInt(color, 16) - amount; + const c = cc < 0 ? 0 : cc; + return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`; +} diff --git a/src/utils/dateUtil.ts b/src/utils/dateUtil.ts new file mode 100644 index 0000000..a719d93 --- /dev/null +++ b/src/utils/dateUtil.ts @@ -0,0 +1,28 @@ +/** + * Independent time operation tool to facilitate subsequent switch to dayjs + */ +import dayjs from 'dayjs'; + +const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; +const DATE_FORMAT = 'YYYY-MM-DD'; + +export function formatToDateTime(date?: dayjs.ConfigType, format = DATE_TIME_FORMAT): string { + return dayjs(date).format(format); +} + +export function formatToDate(date?: dayjs.ConfigType, format = DATE_FORMAT): string { + return dayjs(date).format(format); +} + +export const getTimestamp = (date) => { + return ( + date.getFullYear() * 10000000000 + + (date.getMonth() + 1) * 100000000 + + date.getDate() * 1000000 + + date.getHours() * 10000 + + date.getMinutes() * 100 + + date.getSeconds() + ).toString(); +}; + +export const dateUtil = dayjs; diff --git a/src/utils/domUtils.ts b/src/utils/domUtils.ts new file mode 100644 index 0000000..7efe9cb --- /dev/null +++ b/src/utils/domUtils.ts @@ -0,0 +1,180 @@ +import type { FunctionArgs } from '@vueuse/core'; +import { upperFirst } from 'lodash-es'; + +export interface ViewportOffsetResult { + left: number; + top: number; + right: number; + bottom: number; + rightIncludeBody: number; + bottomIncludeBody: number; +} + +export function getBoundingClientRect(element: Element): DOMRect | number { + if (!element || !element.getBoundingClientRect) { + return 0; + } + return element.getBoundingClientRect(); +} + +function trim(string: string) { + return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, ''); +} + +/* istanbul ignore next */ +export function hasClass(el: Element, cls: string) { + if (!el || !cls) return false; + if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.'); + if (el.classList) { + return el.classList.contains(cls); + } else { + return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1; + } +} + +/* istanbul ignore next */ +export function addClass(el: Element, cls: string) { + if (!el) return; + let curClass = el.className; + const classes = (cls || '').split(' '); + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i]; + if (!clsName) continue; + + if (el.classList) { + el.classList.add(clsName); + } else if (!hasClass(el, clsName)) { + curClass += ' ' + clsName; + } + } + if (!el.classList) { + el.className = curClass; + } +} + +/* istanbul ignore next */ +export function removeClass(el: Element, cls: string) { + if (!el || !cls) return; + const classes = cls.split(' '); + let curClass = ' ' + el.className + ' '; + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i]; + if (!clsName) continue; + + if (el.classList) { + el.classList.remove(clsName); + } else if (hasClass(el, clsName)) { + curClass = curClass.replace(' ' + clsName + ' ', ' '); + } + } + if (!el.classList) { + el.className = trim(curClass); + } +} +/** + * Get the left and top offset of the current element + * left: the distance between the leftmost element and the left side of the document + * top: the distance from the top of the element to the top of the document + * right: the distance from the far right of the element to the right of the document + * bottom: the distance from the bottom of the element to the bottom of the document + * rightIncludeBody: the distance between the leftmost element and the right side of the document + * bottomIncludeBody: the distance from the bottom of the element to the bottom of the document + * + * @description: + */ +export function getViewportOffset(element: Element): ViewportOffsetResult { + const doc = document.documentElement; + + const docScrollLeft = doc.scrollLeft; + const docScrollTop = doc.scrollTop; + const docClientLeft = doc.clientLeft; + const docClientTop = doc.clientTop; + + const pageXOffset = window.pageXOffset; + const pageYOffset = window.pageYOffset; + + const box = getBoundingClientRect(element); + + const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box as DOMRect; + + const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0); + const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0); + const offsetLeft = retLeft + pageXOffset; + const offsetTop = rectTop + pageYOffset; + + const left = offsetLeft - scrollLeft; + const top = offsetTop - scrollTop; + + const clientWidth = window.document.documentElement.clientWidth; + const clientHeight = window.document.documentElement.clientHeight; + return { + left: left, + top: top, + right: clientWidth - rectWidth - left, + bottom: clientHeight - rectHeight - top, + rightIncludeBody: clientWidth - left, + bottomIncludeBody: clientHeight - top, + }; +} + +export function hackCss(attr: string, value: string) { + const prefix: string[] = ['webkit', 'Moz', 'ms', 'OT']; + + const styleObj: any = {}; + prefix.forEach((item) => { + styleObj[`${item}${upperFirst(attr)}`] = value; + }); + return { + ...styleObj, + [attr]: value, + }; +} + +/* istanbul ignore next */ +export function on( + element: Element | HTMLElement | Document | Window, + event: string, + handler: EventListenerOrEventListenerObject, +): void { + if (element && event && handler) { + element.addEventListener(event, handler, false); + } +} + +/* istanbul ignore next */ +export function off( + element: Element | HTMLElement | Document | Window, + event: string, + handler: Fn, +): void { + if (element && event && handler) { + element.removeEventListener(event, handler, false); + } +} + +/* istanbul ignore next */ +export function once(el: HTMLElement, event: string, fn: EventListener): void { + const listener = function (this: any, ...args: unknown[]) { + if (fn) { + fn.apply(this, args); + } + off(el, event, listener); + }; + on(el, event, listener); +} + +export function useRafThrottle(fn: T): T { + let locked = false; + // @ts-ignore + return function (...args: any[]) { + if (locked) return; + locked = true; + window.requestAnimationFrame(() => { + // @ts-ignore + fn.apply(this, args); + locked = false; + }); + }; +} diff --git a/src/utils/env.ts b/src/utils/env.ts new file mode 100644 index 0000000..8a7e960 --- /dev/null +++ b/src/utils/env.ts @@ -0,0 +1,82 @@ +import type { GlobEnvConfig } from '#/config'; +import pkg from '../../package.json'; +import { API_ADDRESS } from '@/enums/cacheEnum'; + +export function getCommonStoragePrefix() { + const { VITE_GLOB_APP_TITLE } = getAppEnvConfig(); + return `${VITE_GLOB_APP_TITLE.replace(/\s/g, '_')}__${getEnv()}`.toUpperCase(); +} + +// Generate cache key according to version +export function getStorageShortName() { + return `${getCommonStoragePrefix()}${`__${pkg.version}`}__`.toUpperCase(); +} + +const getVariableName = (title: string) => { + function strToHex(str: string) { + const result: string[] = []; + for (let i = 0; i < str.length; ++i) { + const hex = str.charCodeAt(i).toString(16); + result.push(('000' + hex).slice(-4)); + } + return result.join('').toUpperCase(); + } + return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, ''); +}; + +export function getAppEnvConfig() { + const ENV_NAME = getVariableName(import.meta.env.VITE_GLOB_APP_TITLE); + const ENV = import.meta.env.DEV + ? // Get the global configuration (the configuration will be extracted independently when packaging) + (import.meta.env as unknown as GlobEnvConfig) + : (window[ENV_NAME] as unknown as GlobEnvConfig); + const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL } = ENV; + let { VITE_GLOB_API_URL } = ENV; + if (localStorage.getItem(API_ADDRESS)) { + const address = JSON.parse(localStorage.getItem(API_ADDRESS) || '{}'); + if (address?.key) VITE_GLOB_API_URL = address?.val; + } + return { + VITE_GLOB_APP_TITLE, + VITE_GLOB_API_URL, + VITE_GLOB_API_URL_PREFIX, + VITE_GLOB_UPLOAD_URL, + }; +} + +/** + * @description: Development mode + */ +export const devMode = 'development'; + +/** + * @description: Production mode + */ +export const prodMode = 'production'; + +/** + * @description: Get environment variables + * @returns: + * @example: + */ +export function getEnv(): string { + return import.meta.env.MODE; +} + +/** + * @description: Is it a development mode + * @returns: + * @example: + */ +export function isDevMode(): boolean { + return import.meta.env.DEV; +} + +/** + * @description: Is it a production mode + * @returns: + * @example: + */ +export function isProdMode(): boolean { + return import.meta.env.PROD; +} \ No newline at end of file diff --git a/src/utils/event/index.ts b/src/utils/event/index.ts new file mode 100644 index 0000000..3a60d7c --- /dev/null +++ b/src/utils/event/index.ts @@ -0,0 +1,42 @@ +import ResizeObserver from 'resize-observer-polyfill'; + +const isServer = typeof window === 'undefined'; + +/* istanbul ignore next */ +function resizeHandler(entries: any[]) { + for (const entry of entries) { + const listeners = entry.target.__resizeListeners__ || []; + if (listeners.length) { + listeners.forEach((fn: () => any) => { + fn(); + }); + } + } +} + +/* istanbul ignore next */ +export function addResizeListener(element: any, fn: () => any) { + if (isServer) return; + if (!element.__resizeListeners__) { + element.__resizeListeners__ = []; + element.__ro__ = new ResizeObserver(resizeHandler); + element.__ro__.observe(element); + } + element.__resizeListeners__.push(fn); +} + +/* istanbul ignore next */ +export function removeResizeListener(element: any, fn: () => any) { + if (!element || !element.__resizeListeners__) return; + element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); + if (!element.__resizeListeners__.length) { + element.__ro__.disconnect(); + } +} + +export function triggerWindowResize() { + const event = document.createEvent('HTMLEvents'); + event.initEvent('resize', true, true); + (event as any).eventType = 'message'; + window.dispatchEvent(event); +} diff --git a/src/utils/factory/createAsyncComponent.tsx b/src/utils/factory/createAsyncComponent.tsx new file mode 100644 index 0000000..f7d8622 --- /dev/null +++ b/src/utils/factory/createAsyncComponent.tsx @@ -0,0 +1,56 @@ +import { + AsyncComponentLoader, + Component, + ComponentPublicInstance, + defineAsyncComponent, + // FunctionalComponent, CSSProperties +} from 'vue'; +import { Spin } from 'ant-design-vue'; +import { noop } from '/@/utils'; + +interface Options { + size?: 'default' | 'small' | 'large'; + delay?: number; + timeout?: number; + loading?: boolean; + retry?: boolean; +} + +export function createAsyncComponent< + T extends Component = { + new (): ComponentPublicInstance; + }, +>(loader: AsyncComponentLoader, options: Options = {}) { + const { size = 'small', delay = 100, timeout = 30000, loading = false, retry = true } = options; + return defineAsyncComponent({ + loader, + loadingComponent: loading ? : undefined, + // The error component will be displayed if a timeout is + // provided and exceeded. Default: Infinity. + // TODO + timeout, + // errorComponent + // Defining if component is suspensible. Default: true. + // suspensible: false, + delay, + /** + * + * @param {*} error Error message object + * @param {*} retry A function that indicating whether the async component should retry when the loader promise rejects + * @param {*} fail End of failure + * @param {*} attempts Maximum allowed retries number + */ + onError: !retry + ? noop + : (error, retry, fail, attempts) => { + if (error.message.match(/fetch/) && attempts <= 3) { + // retry on fetch errors, 3 max attempts + retry(); + } else { + // Note that retry/fail are like resolve/reject of a promise: + // one of them must be called for the error handling to continue. + fail(); + } + }, + }); +} diff --git a/src/utils/file/base64Conver.ts b/src/utils/file/base64Conver.ts new file mode 100644 index 0000000..6751d97 --- /dev/null +++ b/src/utils/file/base64Conver.ts @@ -0,0 +1,41 @@ +/** + * @description: base64 to blob + */ +export function dataURLtoBlob(base64Buf: string): Blob { + const arr = base64Buf.split(','); + const typeItem = arr[0]; + const mime = typeItem.match(/:(.*?);/)![1]; + const bstr = window.atob(arr[1]); + let n = bstr.length; + const u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new Blob([u8arr], { type: mime }); +} + +/** + * img url to base64 + * @param url + */ +export function urlToBase64(url: string, mineType?: string): Promise { + return new Promise((resolve, reject) => { + let canvas = document.createElement('CANVAS') as Nullable; + const ctx = canvas!.getContext('2d'); + + const img = new Image(); + img.crossOrigin = ''; + img.onload = function () { + if (!canvas || !ctx) { + return reject(); + } + canvas.height = img.height; + canvas.width = img.width; + ctx.drawImage(img, 0, 0); + const dataURL = canvas.toDataURL(mineType || 'image/png'); + canvas = null; + resolve(dataURL); + }; + img.src = url; + }); +} diff --git a/src/utils/file/download.ts b/src/utils/file/download.ts new file mode 100644 index 0000000..c31fb7e --- /dev/null +++ b/src/utils/file/download.ts @@ -0,0 +1,45 @@ +import { openWindow } from '..'; + +/** + * Download file according to file address + * @param {*} sUrl + */ +export function downloadByUrl({ + url, + target = '_blank', + fileName, +}: { + url: string; + target?: TargetContext; + fileName?: string; +}): boolean { + const isChrome = window.navigator.userAgent.toLowerCase().indexOf('chrome') > -1; + const isSafari = window.navigator.userAgent.toLowerCase().indexOf('safari') > -1; + + if (/(iP)/g.test(window.navigator.userAgent)) { + console.error('Your browser does not support download!'); + return false; + } + if (isChrome || isSafari) { + const link = document.createElement('a'); + link.href = url; + link.target = target; + + if (link.download !== undefined) { + link.download = fileName || url.substring(url.lastIndexOf('/') + 1, url.length); + } + + if (document.createEvent) { + const e = document.createEvent('MouseEvents'); + e.initEvent('click', true, true); + link.dispatchEvent(e); + return true; + } + } + if (url.indexOf('?') === -1) { + url += '?download'; + } + + openWindow(url, { target }); + return true; +} diff --git a/src/utils/helper/treeHelper.ts b/src/utils/helper/treeHelper.ts new file mode 100644 index 0000000..f915dbd --- /dev/null +++ b/src/utils/helper/treeHelper.ts @@ -0,0 +1,216 @@ +interface TreeHelperConfig { + id: string; + children: string; + pid: string; +} + +// 默认配置 +const DEFAULT_CONFIG: TreeHelperConfig = { + id: 'id', + children: 'children', + pid: 'pid', +}; + +// 获取配置。 Object.assign 从一个或多个源对象复制到目标对象 +const getConfig = (config: Partial) => Object.assign({}, DEFAULT_CONFIG, config); + +// tree from list +// 列表中的树 +export function listToTree(list: any[], config: Partial = {}): T[] { + const conf = getConfig(config) as TreeHelperConfig; + const nodeMap = new Map(); + const result: T[] = []; + const { id, children, pid } = conf; + + for (const node of list) { + node[children] = node[children] || []; + nodeMap.set(node[id], node); + } + for (const node of list) { + const parent = nodeMap.get(node[pid]); + (parent ? parent[children] : result).push(node); + } + return result; +} + +export function treeToList(tree: any, config: Partial = {}): T { + config = getConfig(config); + const { children } = config; + const result: any = [...tree]; + for (let i = 0; i < result.length; i++) { + if (!result[i][children!]) continue; + result.splice(i + 1, 0, ...result[i][children!]); + } + return result; +} + +export function findNode( + tree: any, + func: Fn, + config: Partial = {}, +): T | null { + config = getConfig(config); + const { children } = config; + const list = [...tree]; + for (const node of list) { + if (func(node)) return node; + node[children!] && list.push(...node[children!]); + } + return null; +} + +export function findNodeAll( + tree: any, + func: Fn, + config: Partial = {}, +): T[] { + config = getConfig(config); + const { children } = config; + const list = [...tree]; + const result: T[] = []; + for (const node of list) { + func(node) && result.push(node); + node[children!] && list.push(...node[children!]); + } + return result; +} + +export function findPath( + tree: any, + func: Fn, + config: Partial = {}, +): T | T[] | null { + config = getConfig(config); + const path: T[] = []; + const list = [...tree]; + const visitedSet = new Set(); + const { children } = config; + while (list.length) { + const node = list[0]; + if (visitedSet.has(node)) { + path.pop(); + list.shift(); + } else { + visitedSet.add(node); + node[children!] && list.unshift(...node[children!]); + path.push(node); + if (func(node)) { + return path; + } + } + } + return null; +} + +export function findPathAll(tree: any, func: Fn, config: Partial = {}) { + config = getConfig(config); + const path: any[] = []; + const list = [...tree]; + const result: any[] = []; + const visitedSet = new Set(), + { children } = config; + while (list.length) { + const node = list[0]; + if (visitedSet.has(node)) { + path.pop(); + list.shift(); + } else { + visitedSet.add(node); + node[children!] && list.unshift(...node[children!]); + path.push(node); + func(node) && result.push([...path]); + } + } + return result; +} + +export function filter( + tree: T[], + func: (n: T) => boolean, + // Partial 将 T 中的所有属性设为可选 + config: Partial = {}, +): T[] { + // 获取配置 + config = getConfig(config); + const children = config.children as string; + + function listFilter(list: T[]) { + return list + .map((node: any) => ({ ...node })) + .filter((node) => { + // 递归调用 对含有children项 进行再次调用自身函数 listFilter + node[children] = node[children] && listFilter(node[children]); + // 执行传入的回调 func 进行过滤 + return func(node) || (node[children] && node[children].length); + }); + } + + return listFilter(tree); +} + +export function forEach( + tree: T[], + func: (n: T) => any, + config: Partial = {}, +): void { + config = getConfig(config); + const list: any[] = [...tree]; + const { children } = config; + for (let i = 0; i < list.length; i++) { + //func 返回true就终止遍历,避免大量节点场景下无意义循环,引起浏览器卡顿 + if (func(list[i])) { + return; + } + children && list[i][children] && list.splice(i + 1, 0, ...list[i][children]); + } +} + +/** + * @description: Extract tree specified structure + * @description: 提取树指定结构 + */ +export function treeMap(treeData: T[], opt: { children?: string; conversion: Fn }): T[] { + return treeData.map((item) => treeMapEach(item, opt)); +} + +/** + * @description: Extract tree specified structure + * @description: 提取树指定结构 + */ +export function treeMapEach( + data: any, + { children = 'children', conversion }: { children?: string; conversion: Fn }, +) { + const haveChildren = Array.isArray(data[children]) && data[children].length > 0; + const conversionData = conversion(data) || {}; + if (haveChildren) { + return { + ...conversionData, + [children]: data[children].map((i: number) => + treeMapEach(i, { + children, + conversion, + }), + ), + }; + } else { + return { + ...conversionData, + }; + } +} + +/** + * 递归遍历树结构 + * @param treeData 树 + * @param callBack 回调 + * @param parentNode 父节点 + */ +export function eachTree(treeData: any[], callBack: Fn, parentNode = {}) { + treeData.forEach((element) => { + const newNode = callBack(element, parentNode) || element; + if (element.children) { + eachTree(element.children, callBack, newNode); + } + }); +} diff --git a/src/utils/helper/tsxHelper.tsx b/src/utils/helper/tsxHelper.tsx new file mode 100644 index 0000000..3de2365 --- /dev/null +++ b/src/utils/helper/tsxHelper.tsx @@ -0,0 +1,37 @@ +import { Slots } from 'vue'; +import { isFunction } from '/@/utils/is'; +import { RenderOpts } from '/@/components/Form'; + +/** + * @description: Get slot to prevent empty error + */ +export function getSlot(slots: Slots, slot = 'default', data?: any, opts?: RenderOpts) { + if (!slots || !Reflect.has(slots, slot)) { + return null; + } + if (!isFunction(slots[slot])) { + console.error(`${slot} is not a function!`); + return null; + } + const slotFn = slots[slot]; + if (!slotFn) return null; + const params = { ...data, ...opts }; + return slotFn(params); +} + +/** + * extends slots + * @param slots + * @param excludeKeys + */ +export function extendSlots(slots: Slots, excludeKeys: string[] = []) { + const slotKeys = Object.keys(slots); + const ret: any = {}; + slotKeys.map((key) => { + if (excludeKeys.includes(key)) { + return null; + } + ret[key] = (data?: any) => getSlot(slots, key, data); + }); + return ret; +} diff --git a/src/utils/http/axios/Axios.ts b/src/utils/http/axios/Axios.ts new file mode 100644 index 0000000..e75dfdd --- /dev/null +++ b/src/utils/http/axios/Axios.ts @@ -0,0 +1,251 @@ +import type { + AxiosRequestConfig, + AxiosInstance, + AxiosResponse, + AxiosError, + InternalAxiosRequestConfig, +} from 'axios'; +import type { RequestOptions, Result, UploadFileParams } from '/#/axios'; +import type { CreateAxiosOptions } from './axiosTransform'; +import axios from 'axios'; +import qs from 'qs'; +import { AxiosCanceler } from './axiosCancel'; +import { isFunction } from '/@/utils/is'; +import { cloneDeep } from 'lodash-es'; +import { ContentTypeEnum, RequestEnum } from '/@/enums/httpEnum'; + +export * from './axiosTransform'; + +/** + * @description: axios module + */ +export class VAxios { + private axiosInstance: AxiosInstance; + private readonly options: CreateAxiosOptions; + + constructor(options: CreateAxiosOptions) { + this.options = options; + this.axiosInstance = axios.create(options); + this.setupInterceptors(); + } + + /** + * @description: Create axios instance + */ + private createAxios(config: CreateAxiosOptions): void { + this.axiosInstance = axios.create(config); + } + + private getTransform() { + const { transform } = this.options; + return transform; + } + + getAxios(): AxiosInstance { + return this.axiosInstance; + } + + /** + * @description: Reconfigure axios + */ + configAxios(config: CreateAxiosOptions) { + if (!this.axiosInstance) { + return; + } + this.createAxios(config); + } + + /** + * @description: Set general header + */ + setHeader(headers: any): void { + if (!this.axiosInstance) { + return; + } + Object.assign(this.axiosInstance.defaults.headers, headers); + } + + /** + * @description: Interceptor configuration 拦截器配置 + */ + private setupInterceptors() { + // const transform = this.getTransform(); + const { + axiosInstance, + options: { transform }, + } = this; + if (!transform) { + return; + } + const { + requestInterceptors, + requestInterceptorsCatch, + responseInterceptors, + responseInterceptorsCatch, + } = transform; + + const axiosCanceler = new AxiosCanceler(); + + // Request interceptor configuration processing + this.axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => { + // If cancel repeat request is turned on, then cancel repeat request is prohibited + const requestOptions = (config as unknown as any).requestOptions ?? this.options.requestOptions; + const ignoreCancelToken = requestOptions?.ignoreCancelToken ?? true; + + !ignoreCancelToken && axiosCanceler.addPending(config); + + if (requestInterceptors && isFunction(requestInterceptors)) { + config = requestInterceptors(config, this.options); + } + return config; + }, undefined); + + // Request interceptor error capture + requestInterceptorsCatch && + isFunction(requestInterceptorsCatch) && + this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch); + + // Response result interceptor processing + this.axiosInstance.interceptors.response.use((res: AxiosResponse) => { + res && axiosCanceler.removePending(res.config); + if (responseInterceptors && isFunction(responseInterceptors)) { + res = responseInterceptors(res); + } + return res; + }, undefined); + + // Response result interceptor error capture + responseInterceptorsCatch && + isFunction(responseInterceptorsCatch) && + this.axiosInstance.interceptors.response.use(undefined, (error) => { + return responseInterceptorsCatch(axiosInstance, error); + }); + } + + /** + * @description: File Upload + */ + uploadFile(config: AxiosRequestConfig, params: UploadFileParams) { + const formData = new window.FormData(); + const customFilename = params.name || 'file'; + + if (params.filename) { + formData.append(customFilename, params.file, params.filename); + } else { + formData.append(customFilename, params.file); + } + + if (params.data) { + Object.keys(params.data).forEach((key) => { + const value = params.data![key]; + if (Array.isArray(value)) { + value.forEach((item) => { + formData.append(`${key}[]`, item); + }); + return; + } + + formData.append(key, params.data![key]); + }); + } + + return this.axiosInstance.request({ + ...config, + method: 'POST', + data: formData, + headers: { + 'Content-type': ContentTypeEnum.FORM_DATA, + // @ts-ignore + ignoreCancelToken: true, + }, + }); + } + + // support form-data + supportFormData(config: AxiosRequestConfig) { + const headers = config.headers || this.options.headers; + const contentType = headers?.['Content-Type'] || headers?.['content-type']; + + if ( + contentType !== ContentTypeEnum.FORM_URLENCODED || + !Reflect.has(config, 'data') || + config.method?.toUpperCase() === RequestEnum.GET + ) { + return config; + } + + return { + ...config, + data: qs.stringify(config.data, { arrayFormat: 'brackets' }), + }; + } + + get(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'GET' }, options); + } + + post(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'POST' }, options); + } + + put(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'PUT' }, options); + } + + delete(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'DELETE' }, options); + } + + request(config: AxiosRequestConfig, options?: RequestOptions): Promise { + let conf: CreateAxiosOptions = cloneDeep(config); + // cancelToken 如果被深拷贝,会导致最外层无法使用cancel方法来取消请求 + if (config.cancelToken) { + conf.cancelToken = config.cancelToken; + } + + if (config.signal) { + conf.signal = config.signal; + } + + const transform = this.getTransform(); + + const { requestOptions } = this.options; + + const opt: RequestOptions = Object.assign({}, requestOptions, options); + + const { beforeRequestHook, requestCatchHook, transformResponseHook } = transform || {}; + if (beforeRequestHook && isFunction(beforeRequestHook)) { + conf = beforeRequestHook(conf, opt); + } + conf.requestOptions = opt; + + conf = this.supportFormData(conf); + + return new Promise((resolve, reject) => { + this.axiosInstance + .request>(conf) + .then((res: AxiosResponse) => { + if (transformResponseHook && isFunction(transformResponseHook)) { + try { + const ret = transformResponseHook(res, opt); + resolve(ret); + } catch (err) { + reject(err || new Error('request error!')); + } + return; + } + resolve(res as unknown as Promise); + }) + .catch((e: Error | AxiosError) => { + if (requestCatchHook && isFunction(requestCatchHook)) { + reject(requestCatchHook(e, opt)); + return; + } + if (axios.isAxiosError(e)) { + // rewrite error message from axios in here + } + reject(e); + }); + }); + } +} diff --git a/src/utils/http/axios/axiosCancel.ts b/src/utils/http/axios/axiosCancel.ts new file mode 100644 index 0000000..f115ccf --- /dev/null +++ b/src/utils/http/axios/axiosCancel.ts @@ -0,0 +1,60 @@ +import type { AxiosRequestConfig } from 'axios'; + +// 用于存储每个请求的标识和取消函数 +const pendingMap = new Map(); + +const getPendingUrl = (config: AxiosRequestConfig): string => { + return [config.method, config.url].join('&'); +}; + +export class AxiosCanceler { + /** + * 添加请求 + * @param config 请求配置 + */ + public addPending(config: AxiosRequestConfig): void { + this.removePending(config); + const url = getPendingUrl(config); + const controller = new AbortController(); + config.signal = config.signal || controller.signal; + if (!pendingMap.has(url)) { + // 如果当前请求不在等待中,将其添加到等待中 + pendingMap.set(url, controller); + } + } + + /** + * 清除所有等待中的请求 + */ + public removeAllPending(): void { + pendingMap.forEach((abortController) => { + if (abortController) { + abortController.abort(); + } + }); + this.reset(); + } + + /** + * 移除请求 + * @param config 请求配置 + */ + public removePending(config: AxiosRequestConfig): void { + const url = getPendingUrl(config); + if (pendingMap.has(url)) { + // 如果当前请求在等待中,取消它并将其从等待中移除 + const abortController = pendingMap.get(url); + if (abortController) { + abortController.abort(url); + } + pendingMap.delete(url); + } + } + + /** + * 重置 + */ + public reset(): void { + pendingMap.clear(); + } +} diff --git a/src/utils/http/axios/axiosRetry.ts b/src/utils/http/axios/axiosRetry.ts new file mode 100644 index 0000000..bf44cf7 --- /dev/null +++ b/src/utils/http/axios/axiosRetry.ts @@ -0,0 +1,30 @@ +import { AxiosError, AxiosInstance } from 'axios'; +/** + * 请求重试机制 + */ + +export class AxiosRetry { + /** + * 重试 + */ + retry(axiosInstance: AxiosInstance, error: AxiosError) { + // @ts-ignore + const { config } = error.response; + const { waitTime, count } = config?.requestOptions?.retryRequest ?? {}; + config.__retryCount = config.__retryCount || 0; + if (config.__retryCount >= count) { + return Promise.reject(error); + } + config.__retryCount += 1; + //请求返回后config的header不正确造成重试请求失败,删除返回headers采用默认headers + delete config.headers; + return this.delay(waitTime).then(() => axiosInstance(config)); + } + + /** + * 延迟 + */ + private delay(waitTime: number) { + return new Promise((resolve) => setTimeout(resolve, waitTime)); + } +} diff --git a/src/utils/http/axios/axiosTransform.ts b/src/utils/http/axios/axiosTransform.ts new file mode 100644 index 0000000..a997438 --- /dev/null +++ b/src/utils/http/axios/axiosTransform.ts @@ -0,0 +1,57 @@ +/** + * Data processing class, can be configured according to the project + */ +import type { + AxiosInstance, + AxiosRequestConfig, + AxiosResponse, + InternalAxiosRequestConfig, +} from 'axios'; +import type { RequestOptions, Result } from '/#/axios'; + +export interface CreateAxiosOptions extends AxiosRequestConfig { + authenticationScheme?: string; + transform?: AxiosTransform; + requestOptions?: RequestOptions; +} + +export abstract class AxiosTransform { + /** + * A function that is called before a request is sent. It can modify the request configuration as needed. + * 在发送请求之前调用的函数。它可以根据需要修改请求配置。 + */ + beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig; + + /** + * @description: 处理响应数据 + */ + transformResponseHook?: (res: AxiosResponse, options: RequestOptions) => any; + + /** + * @description: 请求失败处理 + */ + requestCatchHook?: (e: Error, options: RequestOptions) => Promise; + + /** + * @description: 请求之前的拦截器 + */ + requestInterceptors?: ( + config: InternalAxiosRequestConfig, + options: CreateAxiosOptions, + ) => InternalAxiosRequestConfig; + + /** + * @description: 请求之后的拦截器 + */ + responseInterceptors?: (res: AxiosResponse) => AxiosResponse; + + /** + * @description: 请求之前的拦截器错误处理 + */ + requestInterceptorsCatch?: (error: Error) => void; + + /** + * @description: 请求之后的拦截器错误处理 + */ + responseInterceptorsCatch?: (axiosInstance: AxiosInstance, error: Error) => void; +} diff --git a/src/utils/http/axios/checkStatus.ts b/src/utils/http/axios/checkStatus.ts new file mode 100644 index 0000000..acadffa --- /dev/null +++ b/src/utils/http/axios/checkStatus.ts @@ -0,0 +1,80 @@ +import type { ErrorMessageMode } from '/#/axios'; +import { useMessage } from '/@/hooks/web/useMessage'; +import { useI18n } from '/@/hooks/web/useI18n'; +// import router from '/@/router'; +// import { PageEnum } from '/@/enums/pageEnum'; +import { useUserStoreWithOut } from '/@/store/modules/user'; +import projectSetting from '/@/settings/projectSetting'; +import { SessionTimeoutProcessingEnum } from '/@/enums/appEnum'; + +const { createMessage, createErrorModal } = useMessage(); +const error = createMessage.error!; +const stp = projectSetting.sessionTimeoutProcessing; + +export function checkStatus( + status: number, + msg: string, + errorMessageMode: ErrorMessageMode = 'message', +): void { + const { t } = useI18n(); + const userStore = useUserStoreWithOut(); + let errMessage = ''; + + switch (status) { + case 400: + errMessage = `${msg}`; + break; + // 401: Not logged in + // Jump to the login page if not logged in, and carry the path of the current page + // Return to the current page after successful login. This step needs to be operated on the login page. + case 401: + userStore.setToken(undefined); + errMessage = msg || t('sys.api.errMsg401'); + if (stp === SessionTimeoutProcessingEnum.PAGE_COVERAGE) { + userStore.setSessionTimeout(true); + } else { + userStore.logout(true); + } + break; + case 403: + errMessage = t('sys.api.errMsg403'); + break; + // 404请求不存在 + case 404: + errMessage = t('sys.api.errMsg404'); + break; + case 405: + errMessage = t('sys.api.errMsg405'); + break; + case 408: + errMessage = t('sys.api.errMsg408'); + break; + case 500: + errMessage = t('sys.api.errMsg500'); + break; + case 501: + errMessage = t('sys.api.errMsg501'); + break; + case 502: + errMessage = t('sys.api.errMsg502'); + break; + case 503: + errMessage = t('sys.api.errMsg503'); + break; + case 504: + errMessage = t('sys.api.errMsg504'); + break; + case 505: + errMessage = t('sys.api.errMsg505'); + break; + default: + } + + if (errMessage) { + if (errorMessageMode === 'modal') { + createErrorModal({ title: t('sys.api.errorTip'), content: errMessage }); + } else if (errorMessageMode === 'message') { + error({ content: errMessage, key: `global_error_message_status_${status}` }); + } + } +} diff --git a/src/utils/http/axios/helper.ts b/src/utils/http/axios/helper.ts new file mode 100644 index 0000000..30cc2b0 --- /dev/null +++ b/src/utils/http/axios/helper.ts @@ -0,0 +1,48 @@ +import { isObject, isString } from '/@/utils/is'; + +const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; + +export function joinTimestamp( + join: boolean, + restful: T, +): T extends true ? string : object; + +export function joinTimestamp(join: boolean, restful = false): string | object { + if (!join) { + return restful ? '' : {}; + } + const now = new Date().getTime(); + if (restful) { + return `?_t=${now}`; + } + return { _t: now }; +} + +/** + * @description: Format request parameter time + */ +export function formatRequestDate(params: Recordable) { + if (Object.prototype.toString.call(params) !== '[object Object]') { + return; + } + + for (const key in params) { + const format = params[key]?.format ?? null; + if (format && typeof format === 'function') { + params[key] = params[key].format(DATE_TIME_FORMAT); + } + if (isString(key)) { + const value = params[key]; + if (value) { + try { + params[key] = isString(value) ? value.trim() : value; + } catch (error: any) { + throw new Error(error); + } + } + } + if (isObject(params[key])) { + formatRequestDate(params[key]); + } + } +} diff --git a/src/utils/http/axios/index.ts b/src/utils/http/axios/index.ts new file mode 100644 index 0000000..d86f493 --- /dev/null +++ b/src/utils/http/axios/index.ts @@ -0,0 +1,297 @@ +// axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动 +// The axios configuration can be changed according to the project, just change the file, other files can be left unchanged + +import type { AxiosInstance, AxiosResponse } from 'axios'; +import { clone } from 'lodash-es'; +import type { RequestOptions, Result } from '/#/axios'; +import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform'; +import { VAxios } from './Axios'; +import { checkStatus } from './checkStatus'; +import { useGlobSetting } from '@/hooks/setting'; +import { useMessage } from '@/hooks/web/useMessage'; +import { RequestEnum, ContentTypeEnum } from '@/enums/httpEnum'; +import { isString} from '@/utils/is'; +import { getToken } from '@/utils/auth'; +import { setObjToUrlParams, deepMerge } from '@/utils'; +import { useErrorLogStoreWithOut } from '@/store/modules/errorLog'; +import { useI18n } from '@/hooks/web/useI18n'; +import { joinTimestamp, formatRequestDate } from './helper'; +import { AxiosRetry } from '@/utils/http/axios/axiosRetry'; +import axios from 'axios'; +import {notification} from "ant-design-vue"; + +const globSetting = useGlobSetting(); +const urlPrefix = globSetting.urlPrefix; +const { createMessage, createErrorModal, createSuccessModal } = useMessage(); + +/** + * @description: 数据处理,方便区分多种处理方式 + */ +const transform: AxiosTransform = { + /** + * @description: 处理响应数据。如果数据不是预期格式,可直接抛出错误 + */ + transformResponseHook: (res: AxiosResponse, options: RequestOptions) => { + const { t } = useI18n(); + const { isTransformResponse, isReturnNativeResponse } = options; + // 是否返回原生响应头 比如:需要获取响应头时使用该属性 + if (isReturnNativeResponse) { + return res; + } + // 不进行任何处理,直接返回 + // 用于页面代码可能需要直接获取code,data,message这些信息时开启 + if (!isTransformResponse) { + return res.data; + } + // 错误的时候返回 + + const { data } = res; + if (!data) { + // return '[HTTP] Request has no return value'; + throw new Error(t('sys.api.apiRequestFailed')); + } + + // 这里逻辑可以根据项目进行修改 + if (!res.data) { + // return '[HTTP] Request has no return value'; + throw new Error(t('sys.api.apiRequestFailed')); + } + // 这里定义了我返回后端正确业务的状态 + const validCodes = ['00000', 'A0001', 'A0002', 'A0013', 'A0014', 'R0001', 'R0002', 'R0003', 'R0004', 'R0005', 'R0006', + 'A0007', 'A0008', 'A0004', 'A0005', 'A0006', 'A0003', 'A0015', 'A0009', 'A0010', 'A0011', 'P0015', 'P0016', 'P0017', 'P0018', + 'P0019', 'P0020', 'P0021', 'P0022', 'P0023', 'S0001', 'S0002', 'S0003', 'S0004', 'S0005', 'S0006', 'S0007', 'S0008', 'S0009', + 'S0016', 'S0017', 'S0018', 'S0013', 'S0014', 'S0015', 'S0010', 'S0011', 'S0012', 'A0020', 'A0021', 'A0022', 'D0001', 'D0002', + 'D0003', 'F0000', 'F0002', 'F0003', 'F0004', 'F0005', 'F0006', 'F0007', 'I0001', 'I0002', 'I0003', 'I0004', 'I0005', 'I0006', + 'E0004', 'E0005', 'E0006', 'T0001', 'T0002', 'T0003', 'C0001', 'C0003', 'C0004', 'P0024', 'P0025', 'P0026', 'P0001', 'P0000', + 'P0002', 'P0003', 'P0004', 'P0005', 'P0006', 'P0007', 'P0008', 'P0009', 'P0010', 'P0011', 'P0012', 'P0013', 'P0014', 'U0001', + 'U0002', 'U0003', 'U0004', 'M0001', 'M0002', 'M0003', 'M0004', 'W0001', 'W0002', 'W0003', 'W0004', 'O0001', 'O0002', 'O0003', + 'O0004', 'A0012', 'A0016', 'A0100', 'A0101', 'A0017', 'A0300', 'A0301', 'A0304','A0307']; // 定义包含可能值的数组 + + const infoCodes = ['A0404', 'A0113', 'A0502', 'B0010', 'B0020', 'P0517', 'P0511']; + + if (validCodes.includes(res.data.code) || res.data.code === undefined) { + if (options.successMessageMode === 'message') { + createMessage.success(res.data.msg); + } else if (options.successMessageMode === 'modal') { + createSuccessModal({ title: res.data.msg, content: res.data.msg }); + } else if (options.successMessageMode === 'notice') { + notification.success({ + message: t('common.successful'), + description: t(res.data.msg), + duration: 3, + }); + } + return res.data; + // add info here to handle warning codes + } else if (infoCodes.includes(res.data.code)) { + if (options.errorMessageMode === 'message') { + createMessage.info(res.data.msg); + } else if (options.errorMessageMode === 'modal') { + createSuccessModal({ title: res.data.msg, content: res.data.msg }); + } else if (options.errorMessageMode === 'notice') { + notification.info({ + message: t('common.warning'), + description: t(res.data.msg), + duration: 3, + }); + } + return res.data; + } else { + if (res.data.code === 'P0512') { + return res.data; + } else if (options.errorMessageMode === 'message') { + createMessage.error(res.data.msg); + } else if (options.errorMessageMode === 'modal') { + createErrorModal({ title: res.data.msg, content: res.data.msg }); + } else if (options.errorMessageMode === 'notice') { + notification.warning({ + message: t('common.failed'), + description: t(res.data.msg), + duration: 3, + }); + } + + return res.data; + } + }, + + // 请求之前处理config + beforeRequestHook: (config, options) => { + const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true, urlPrefix } = options; + + if (joinPrefix) { + config.url = `${urlPrefix}${config.url}`; + } + + if (apiUrl && isString(apiUrl)) { + config.url = `${apiUrl}${config.url}`; + } + const params = config.params || {}; + const data = config.data || false; + formatDate && data && !isString(data) && formatRequestDate(data); + if (config.method?.toUpperCase() === RequestEnum.GET) { + if (!isString(params)) { + // 给 get 请求加上时间戳参数,避免从缓存中拿数据。 + config.params = Object.assign(params || {}, joinTimestamp(joinTime, false)); + } else { + // 兼容restful风格 + config.url = config.url + params + `${joinTimestamp(joinTime, true)}`; + config.params = undefined; + } + } else { + if (!isString(params)) { + formatDate && formatRequestDate(params); + if ( + Reflect.has(config, 'data') && + config.data && + (Object.keys(config.data).length > 0 || config.data instanceof FormData) + ) { + config.data = data; + config.params = params; + } else { + // 非GET请求如果没有提供data,则将params视为data + config.data = params; + config.params = undefined; + } + if (joinParamsToUrl) { + config.url = setObjToUrlParams( + config.url as string, + Object.assign({}, config.params, config.data), + ); + } + } else { + // 兼容restful风格 + config.url = config.url + params; + config.params = undefined; + } + } + return config; + }, + + /** + * @description: 请求拦截器处理 + */ + requestInterceptors: (config, options) => { + // 请求之前处理config + const token = getToken(); + if (token && (config as Recordable)?.requestOptions?.withToken !== false) { + // jwt token + (config as Recordable).headers.Authorization = options.authenticationScheme + ? `${options.authenticationScheme} ${token}` + : token; + } + return config; + }, + + /** + * @description: 响应拦截器处理 + */ + responseInterceptors: (res: AxiosResponse) => { + return res; + }, + + /** + * @description: 响应错误处理 + */ + responseInterceptorsCatch: (axiosInstance: AxiosInstance, error: any) => { + const { t } = useI18n(); + const errorLogStore = useErrorLogStoreWithOut(); + errorLogStore.addAjaxErrorInfo(error); + const { response, code, message, config } = error || {}; + const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none'; + const msg: string = response?.data?.error?.message ?? ''; + const err: string = error?.toString?.() ?? ''; + let errMessage = ''; + + if (axios.isCancel(error)) { + return Promise.reject(error); + } + + try { + if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) { + errMessage = t('sys.api.apiTimeoutMessage'); + } + if (err?.includes('Network Error')) { + errMessage = t('sys.api.networkExceptionMsg'); + } + + if (errMessage) { + if (errorMessageMode === 'modal') { + createErrorModal({ title: t('sys.api.errorTip'), content: errMessage }); + } else if (errorMessageMode === 'message') { + createMessage.error(errMessage); + } + return Promise.reject(error); + } + } catch (error) { + throw new Error(error as unknown as string); + } + + checkStatus(error?.response?.status, msg, errorMessageMode); + + // 添加自动重试机制 保险起见 只针对GET请求 + const retryRequest = new AxiosRetry(); + const { isOpenRetry } = config.requestOptions.retryRequest; + config.method?.toUpperCase() === RequestEnum.GET && + isOpenRetry && + // @ts-ignore + retryRequest.retry(axiosInstance, error); + return Promise.reject(error); + }, +}; + +function createAxios(opt?: Partial) { + return new VAxios( + // 深度合并 + deepMerge( + { + // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes + // authentication schemes,e.g: Bearer + // authenticationScheme: 'Bearer', + authenticationScheme: '', + timeout: 30 * 1000, + // 基础接口地址 + // baseURL: globSetting.apiUrl, + + headers: { 'Content-Type': ContentTypeEnum.JSON }, + // 如果是form-data格式 + // headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED }, + // 数据处理方式 + transform: clone(transform), + // 配置项,下面的选项都可以在独立的接口请求中覆盖 + requestOptions: { + // 默认将prefix 添加到url + joinPrefix: true, + // 是否返回原生响应头 比如:需要获取响应头时使用该属性 + isReturnNativeResponse: false, + // 需要对返回数据进行处理 + isTransformResponse: true, + // post请求的时候添加参数到url + joinParamsToUrl: false, + // 格式化提交参数时间 + formatDate: true, + // 消息提示类型 + errorMessageMode: 'message', + // 接口地址 + apiUrl: globSetting.apiUrl, + // 接口拼接地址 + urlPrefix: urlPrefix, + // 是否加入时间戳 + joinTime: false, + // 忽略重复请求 + ignoreCancelToken: true, + // 是否携带token + withToken: true, + retryRequest: { + isOpenRetry: true, + count: 5, + waitTime: 100, + }, + decompress: false, + }, + }, + opt || {}, + ), + ); +} +export const defHttp = createAxios(); diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..84c407a --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,122 @@ +import type { App, Component } from 'vue'; +import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router'; + +import { cloneDeep, mergeWith, uniq } from 'lodash-es'; +import { unref } from 'vue'; +import { isArray, isObject } from '/@/utils/is'; + +export const noop = () => {}; + +/** + * @description: Set ui mount node + */ +export function getPopupContainer(node?: HTMLElement): HTMLElement { + return (node?.parentNode as HTMLElement) ?? document.body; +} + +/** + * Add the object as a parameter to the URL + * @param baseUrl url + * @param obj + * @returns {string} + * eg: + * let obj = {a: '3', b: '4'} + * setObjToUrlParams('www.baidu.com', obj) + * ==>www.baidu.com?a=3&b=4 + */ +export function setObjToUrlParams(baseUrl: string, obj: any): string { + let parameters = ''; + for (const key in obj) { + parameters += key + '=' + encodeURIComponent(obj[key]) + '&'; + } + parameters = parameters.replace(/&$/, ''); + return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters; +} + +/** + + 递归合并两个对象。 + Recursively merge two objects. + @param target 目标对象,合并后结果存放于此。The target object to merge into. + @param source 要合并的源对象。The source object to merge from. + @returns 合并后的对象。The merged object. + */ +export function deepMerge( + target: T, + source: U, +): T & U { + return mergeWith(cloneDeep(target), source, (objValue, srcValue) => { + if (isObject(objValue) && isObject(srcValue)) { + return mergeWith(cloneDeep(objValue), srcValue, (prevValue, nextValue) => { + // 如果是数组,合并数组(去重) If it is an array, merge the array (remove duplicates) + return isArray(prevValue) ? uniq(prevValue, nextValue) : undefined; + }); + } + }); +} + +export function openWindow( + url: string, + opt?: { target?: TargetContext | string; noopener?: boolean; noreferrer?: boolean }, +) { + const { target = '__blank', noopener = true, noreferrer = true } = opt || {}; + const feature: string[] = []; + + noopener && feature.push('noopener=yes'); + noreferrer && feature.push('noreferrer=yes'); + + window.open(url, target, feature.join(',')); +} + +// dynamic use hook props +export function getDynamicProps, U>(props: T): Partial { + const ret: Recordable = {}; + + Object.keys(props).map((key) => { + ret[key] = unref((props as Recordable)[key]); + }); + + return ret as Partial; +} + +export function getRawRoute(route: RouteLocationNormalized): RouteLocationNormalized { + if (!route) return route; + const { matched, ...opt } = route; + return { + ...opt, + matched: (matched + ? matched.map((item) => ({ + meta: item.meta, + name: item.name, + path: item.path, + })) + : undefined) as RouteRecordNormalized[], + }; +} + +// https://github.com/vant-ui/vant/issues/8302 +type EventShim = { + new (...args: any[]): { + $props: { + onClick?: (...args: any[]) => void; + }; + }; +}; + +export type WithInstall = T & { + install(app: App): void; +} & EventShim; + +export type CustomComponent = Component & { displayName?: string }; + +export const withInstall = (component: T, alias?: string) => { + (component as Record).install = (app: App) => { + const compName = component.name || component.displayName; + if (!compName) return; + app.component(compName, component); + if (alias) { + app.config.globalProperties[alias] = component; + } + }; + return component as WithInstall; +}; \ No newline at end of file diff --git a/src/utils/is.ts b/src/utils/is.ts new file mode 100644 index 0000000..3a5c4a6 --- /dev/null +++ b/src/utils/is.ts @@ -0,0 +1,98 @@ +const toString = Object.prototype.toString; + +export function is(val: unknown, type: string) { + return toString.call(val) === `[object ${type}]`; +} + +export function isDef(val?: T): val is T { + return typeof val !== 'undefined'; +} + +export function isUnDef(val?: T): val is T { + return !isDef(val); +} + +export function isObject(val: any): val is Record { + return val !== null && is(val, 'Object'); +} + +export function isEmpty(val: T): val is T { + if (isArray(val) || isString(val)) { + return val.length === 0; + } + + if (val instanceof Map || val instanceof Set) { + return val.size === 0; + } + + if (isObject(val)) { + return Object.keys(val).length === 0; + } + + return false; +} + +export function isDate(val: unknown): val is Date { + return is(val, 'Date'); +} + +export function isNull(val: unknown): val is null { + return val === null; +} + +export function isNullAndUnDef(val: unknown): val is null | undefined { + return isUnDef(val) && isNull(val); +} + +export function isNullOrUnDef(val: unknown): val is null | undefined { + return isUnDef(val) || isNull(val); +} + +export function isNumber(val: unknown): val is number { + return is(val, 'Number'); +} + +export function isPromise(val: unknown): val is Promise { + return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch); +} + +export function isString(val: unknown): val is string { + return is(val, 'String'); +} + +export function isFunction(val: unknown): val is Function { + return typeof val === 'function'; +} + +export function isBoolean(val: unknown): val is boolean { + return is(val, 'Boolean'); +} + +export function isRegExp(val: unknown): val is RegExp { + return is(val, 'RegExp'); +} + +export function isArray(val: any): val is Array { + return val && Array.isArray(val); +} + +export function isWindow(val: any): val is Window { + return typeof window !== 'undefined' && is(val, 'Window'); +} + +export function isElement(val: unknown): val is Element { + return isObject(val) && !!val.tagName; +} + +export function isMap(val: unknown): val is Map { + return is(val, 'Map'); +} + +export const isServer = typeof window === 'undefined'; + +export const isClient = !isServer; + +export function isUrl(path: string): boolean { + const reg = /^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?/; + return reg.test(path); +} diff --git a/src/utils/lib/echarts.ts b/src/utils/lib/echarts.ts new file mode 100644 index 0000000..e1f95cd --- /dev/null +++ b/src/utils/lib/echarts.ts @@ -0,0 +1,57 @@ +import * as echarts from 'echarts/core'; + +import { + BarChart, + LineChart, + PieChart, + MapChart, + PictorialBarChart, + RadarChart, + ScatterChart, +} from 'echarts/charts'; + +import { + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + LegendComponent, + RadarComponent, + ToolboxComponent, + DataZoomComponent, + VisualMapComponent, + TimelineComponent, + CalendarComponent, + GraphicComponent, +} from 'echarts/components'; + +import { SVGRenderer } from 'echarts/renderers'; + +echarts.use([ + LegendComponent, + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + BarChart, + LineChart, + PieChart, + MapChart, + RadarChart, + SVGRenderer, + PictorialBarChart, + RadarComponent, + ToolboxComponent, + DataZoomComponent, + VisualMapComponent, + TimelineComponent, + CalendarComponent, + GraphicComponent, + ScatterChart, +]); + +export default echarts; diff --git a/src/utils/log.ts b/src/utils/log.ts new file mode 100644 index 0000000..8f79800 --- /dev/null +++ b/src/utils/log.ts @@ -0,0 +1,9 @@ +const projectName = import.meta.env.VITE_GLOB_APP_TITLE; + +export function warn(message: string) { + console.warn(`[${projectName} warn]:${message}`); +} + +export function error(message: string) { + throw new Error(`[${projectName} error]:${message}`); +} diff --git a/src/utils/mitt.ts b/src/utils/mitt.ts new file mode 100644 index 0000000..cf09fd8 --- /dev/null +++ b/src/utils/mitt.ts @@ -0,0 +1,122 @@ +/** + * copy to https://github.com/developit/mitt + * Expand clear method + */ +export type EventType = string | symbol; + +// An event handler can take an optional event argument +// and should not return a value +export type Handler = (event: T) => void; +export type WildcardHandler> = ( + type: keyof T, + event: T[keyof T], +) => void; + +// An array of all currently registered event handlers for a type +export type EventHandlerList = Array>; +export type WildCardEventHandlerList> = Array>; + +// A map of event types and their corresponding event handlers. +export type EventHandlerMap> = Map< + keyof Events | '*', + EventHandlerList | WildCardEventHandlerList +>; + +export interface Emitter> { + all: EventHandlerMap; + + on(type: Key, handler: Handler): void; + on(type: '*', handler: WildcardHandler): void; + + off(type: Key, handler?: Handler): void; + off(type: '*', handler: WildcardHandler): void; + + emit(type: Key, event: Events[Key]): void; + emit(type: undefined extends Events[Key] ? Key : never): void; + clear(): void; +} + +/** + * Mitt: Tiny (~200b) functional event emitter / pubsub. + * @name mitt + * @returns {Mitt} + */ +export function mitt>( + all?: EventHandlerMap, +): Emitter { + type GenericEventHandler = Handler | WildcardHandler; + all = all || new Map(); + + return { + /** + * A Map of event names to registered handler functions. + */ + all, + + /** + * Register an event handler for the given type. + * @param {string|symbol} type Type of event to listen for, or `'*'` for all events + * @param {Function} handler Function to call in response to given event + * @memberOf mitt + */ + on(type: Key, handler: GenericEventHandler) { + const handlers: Array | undefined = all!.get(type); + if (handlers) { + handlers.push(handler); + } else { + all!.set(type, [handler] as EventHandlerList); + } + }, + + /** + * Remove an event handler for the given type. + * If `handler` is omitted, all handlers of the given type are removed. + * @param {string|symbol} type Type of event to unregister `handler` from (`'*'` to remove a wildcard handler) + * @param {Function} [handler] Handler function to remove + * @memberOf mitt + */ + off(type: Key, handler?: GenericEventHandler) { + const handlers: Array | undefined = all!.get(type); + if (handlers) { + if (handler) { + handlers.splice(handlers.indexOf(handler) >>> 0, 1); + } else { + all!.set(type, []); + } + } + }, + + /** + * Invoke all handlers for the given type. + * If present, `'*'` handlers are invoked after type-matched handlers. + * + * Note: Manually firing '*' handlers is not supported. + * + * @param {string|symbol} type The event type to invoke + * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler + * @memberOf mitt + */ + emit(type: Key, evt?: Events[Key]) { + let handlers = all!.get(type); + if (handlers) { + (handlers as EventHandlerList).slice().forEach((handler) => { + handler(evt as Events[Key]); + }); + } + + handlers = all!.get('*'); + if (handlers) { + (handlers as WildCardEventHandlerList).slice().forEach((handler) => { + handler(type, evt as Events[Key]); + }); + } + }, + + /** + * Clear all + */ + clear() { + this.all.clear(); + }, + }; +} diff --git a/src/utils/propTypes.ts b/src/utils/propTypes.ts new file mode 100644 index 0000000..16cf9cd --- /dev/null +++ b/src/utils/propTypes.ts @@ -0,0 +1,35 @@ +import { CSSProperties, VNodeChild } from 'vue'; +import { createTypes, VueTypeValidableDef, VueTypesInterface, toValidableType } from 'vue-types'; + +export type VueNode = VNodeChild | JSX.Element; + +type PropTypes = VueTypesInterface & { + readonly style: VueTypeValidableDef; + readonly VNodeChild: VueTypeValidableDef; + // readonly trueBool: VueTypeValidableDef; +}; +const newPropTypes = createTypes({ + func: undefined, + bool: undefined, + string: undefined, + number: undefined, + object: undefined, + integer: undefined, +}) as PropTypes; + +// 从 vue-types v5.0 开始,extend()方法已经废弃,当前已改为官方推荐的ES6+方法 https://dwightjack.github.io/vue-types/advanced/extending-vue-types.html#the-extend-method +class propTypes extends newPropTypes { + // a native-like validator that supports the `.validable` method + static get style() { + return toValidableType('style', { + type: [String, Object], + }); + } + + static get VNodeChild() { + return toValidableType('VNodeChild', { + type: undefined, + }); + } +} +export { propTypes }; diff --git a/src/utils/props.ts b/src/utils/props.ts new file mode 100644 index 0000000..00b364d --- /dev/null +++ b/src/utils/props.ts @@ -0,0 +1,184 @@ +// copy from element-plus + +import { warn } from 'vue'; +import { fromPairs, isObject } from 'lodash-es'; +import type { ExtractPropTypes, PropType } from 'vue'; +import type { Mutable } from './types'; + +const wrapperKey = Symbol(); +export type PropWrapper = { [wrapperKey]: T }; + +export const propKey = Symbol(); + +type ResolveProp = ExtractPropTypes<{ + key: { type: T; required: true }; +}>['key']; +type ResolvePropType = ResolveProp extends { type: infer V } ? V : ResolveProp; +type ResolvePropTypeWithReadonly = Readonly extends Readonly> + ? ResolvePropType + : ResolvePropType; + +type IfUnknown = [unknown] extends [T] ? V : T; + +export type BuildPropOption, R, V, C> = { + type?: T; + values?: readonly V[]; + required?: R; + default?: R extends true + ? never + : D extends Record | Array + ? () => D + : (() => D) | D; + validator?: ((val: any) => val is C) | ((val: any) => boolean); +}; + +type _BuildPropType = + | (T extends PropWrapper + ? T[typeof wrapperKey] + : [V] extends [never] + ? ResolvePropTypeWithReadonly + : never) + | V + | C; +export type BuildPropType = _BuildPropType< + IfUnknown, + IfUnknown, + IfUnknown +>; + +type _BuildPropDefault = [T] extends [ + // eslint-disable-next-line @typescript-eslint/ban-types + Record | Array | Function, +] + ? D + : D extends () => T + ? ReturnType + : D; + +export type BuildPropDefault = R extends true + ? { readonly default?: undefined } + : { + readonly default: Exclude extends never + ? undefined + : Exclude<_BuildPropDefault, undefined>; + }; +export type BuildPropReturn = { + readonly type: PropType>; + readonly required: IfUnknown; + readonly validator: ((val: unknown) => boolean) | undefined; + [propKey]: true; +} & BuildPropDefault, IfUnknown, IfUnknown>; + +/** + * @description Build prop. It can better optimize prop types + * @description 生成 prop,能更好地优化类型 + * @example + // limited options + // the type will be PropType<'light' | 'dark'> + buildProp({ + type: String, + values: ['light', 'dark'], + } as const) + * @example + // limited options and other types + // the type will be PropType<'small' | 'medium' | number> + buildProp({ + type: [String, Number], + values: ['small', 'medium'], + validator: (val: unknown): val is number => typeof val === 'number', + } as const) + @link see more: https://github.com/element-plus/element-plus/pull/3341 + */ +export function buildProp< + T = never, + D extends BuildPropType = never, + R extends boolean = false, + V = never, + C = never, +>(option: BuildPropOption, key?: string): BuildPropReturn { + // filter native prop type and nested prop, e.g `null`, `undefined` (from `buildProps`) + if (!isObject(option) || !!option[propKey]) return option as any; + + const { values, required, default: defaultValue, type, validator } = option; + + const _validator = + values || validator + ? (val: unknown) => { + let valid = false; + let allowedValues: unknown[] = []; + + if (values) { + allowedValues = [...values, defaultValue]; + valid ||= allowedValues.includes(val); + } + if (validator) valid ||= validator(val); + + if (!valid && allowedValues.length > 0) { + const allowValuesText = [...new Set(allowedValues)] + .map((value) => JSON.stringify(value)) + .join(', '); + warn( + `Invalid prop: validation failed${ + key ? ` for prop "${key}"` : '' + }. Expected one of [${allowValuesText}], got value ${JSON.stringify(val)}.`, + ); + } + return valid; + } + : undefined; + + return { + type: + typeof type === 'object' && Object.getOwnPropertySymbols(type).includes(wrapperKey) + ? type[wrapperKey] + : type, + required: !!required, + default: defaultValue, + validator: _validator, + [propKey]: true, + } as unknown as BuildPropReturn; +} + +type NativePropType = [((...args: any) => any) | { new (...args: any): any } | undefined | null]; + +export const buildProps = < + O extends { + [K in keyof O]: O[K] extends BuildPropReturn + ? O[K] + : [O[K]] extends NativePropType + ? O[K] + : O[K] extends BuildPropOption + ? D extends BuildPropType + ? BuildPropOption + : never + : never; + }, +>( + props: O, +) => + fromPairs( + Object.entries(props).map(([key, option]) => [key, buildProp(option as any, key)]), + ) as unknown as { + [K in keyof O]: O[K] extends { [propKey]: boolean } + ? O[K] + : [O[K]] extends NativePropType + ? O[K] + : O[K] extends BuildPropOption< + infer T, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + infer _D, + infer R, + infer V, + infer C + > + ? BuildPropReturn + : never; + }; + +export const definePropType = (val: any) => ({ [wrapperKey]: val } as PropWrapper); + +export const keyOf = (arr: T) => Object.keys(arr) as Array; +export const mutable = >(val: T) => + val as Mutable; + +export const componentSize = ['large', 'medium', 'small', 'mini'] as const; diff --git a/src/utils/tree.ts b/src/utils/tree.ts new file mode 100644 index 0000000..17dcb3c --- /dev/null +++ b/src/utils/tree.ts @@ -0,0 +1,83 @@ +import { DataNode } from 'ant-design-vue/es/vc-tree/interface'; +import { map, pick } from 'lodash-es'; +import { array2tree } from '@axolo/tree-array'; + +export interface buildNodeOption { + labelField: string; + idKeyField: string; + valueField: string; + parentKeyField: string; + defaultValue?: string | object; + childrenKeyField: string; +} + +export function buildDataNode(data: any, options: buildNodeOption): DataNode[] { + const treeNodeData = map(data, (obj) => { + const tmpData = pick(obj, [ + options.labelField, + options.idKeyField, + options.valueField, + options.parentKeyField, + ]); + Object.keys(tmpData).forEach((e) => { + if (e === options.labelField) { + tmpData['title'] = tmpData[e]; + delete tmpData[e]; + } else if (e === options.valueField) { + tmpData['key'] = tmpData[e]; + if (e !== options.idKeyField && e !== options.parentKeyField) { + delete tmpData[e]; + } + } + }); + return tmpData; + }); + + const treeConv = array2tree(treeNodeData, { + idKey: options.idKeyField, + parentKey: options.parentKeyField, + childrenKey: options.childrenKeyField, + }); + + // add default label + if (options.defaultValue) { + treeConv.push(options.defaultValue); + } + return treeConv as DataNode[]; +} + +// buildTreeNode returns treeData for tree select from data +export function buildTreeNode(data: any, options: buildNodeOption): Recordable[] { + const treeNodeData = map(data, (obj) => { + const tmpData = pick(obj, [ + options.labelField, + options.idKeyField, + options.valueField, + options.parentKeyField, + ]); + Object.keys(tmpData).forEach((e) => { + if (e === options.labelField) { + tmpData['label'] = tmpData[e]; + delete tmpData[e]; + } else if (e === options.valueField) { + tmpData['value'] = tmpData[e]; + if (e !== options.idKeyField && e !== options.parentKeyField) { + delete tmpData[e]; + } + } + }); + return tmpData; + }); + + const treeConv = array2tree(treeNodeData, { + idKey: options.idKeyField, + parentKey: options.parentKeyField, + childrenKey: options.childrenKeyField, + }); + + // add default label + if (options.defaultValue) { + treeConv.push(options.defaultValue); + } + return treeConv as Recordable[]; +} diff --git a/src/utils/types.ts b/src/utils/types.ts new file mode 100644 index 0000000..4453ec4 --- /dev/null +++ b/src/utils/types.ts @@ -0,0 +1,42 @@ +// copy from element-plus + +import type { CSSProperties, Plugin } from 'vue'; + +type OptionalKeys> = { + [K in keyof T]: T extends Record ? never : K; +}[keyof T]; + +type RequiredKeys> = Exclude>; + +type MonoArgEmitter = (evt: K, arg?: T[K]) => void; + +type BiArgEmitter = (evt: K, arg: T[K]) => void; + +export type EventEmitter> = MonoArgEmitter> & + BiArgEmitter>; + +export type AnyFunction = (...args: any[]) => T; + +export type PartialReturnType unknown> = Partial>; + +export type SFCWithInstall = T & Plugin; + +export type Nullable = T | null; + +export type RefElement = Nullable; + +export type CustomizedHTMLElement = HTMLElement & T; + +export type Indexable = { + [key: string]: T; +}; + +export type Hash = Indexable; + +export type TimeoutHandle = ReturnType; + +export type ComponentSize = 'large' | 'medium' | 'small' | 'mini'; + +export type StyleValue = string | CSSProperties | Array; + +export type Mutable = { -readonly [P in keyof T]: T[P] }; diff --git a/src/utils/uuid.ts b/src/utils/uuid.ts new file mode 100644 index 0000000..548bcf3 --- /dev/null +++ b/src/utils/uuid.ts @@ -0,0 +1,28 @@ +const hexList: string[] = []; +for (let i = 0; i <= 15; i++) { + hexList[i] = i.toString(16); +} + +export function buildUUID(): string { + let uuid = ''; + for (let i = 1; i <= 36; i++) { + if (i === 9 || i === 14 || i === 19 || i === 24) { + uuid += '-'; + } else if (i === 15) { + uuid += 4; + } else if (i === 20) { + uuid += hexList[(Math.random() * 4) | 8]; + } else { + uuid += hexList[(Math.random() * 16) | 0]; + } + } + return uuid.replace(/-/g, ''); +} + +let unique = 0; +export function buildShortUUID(prefix = ''): string { + const time = Date.now(); + const random = Math.floor(Math.random() * 1000000000); + unique++; + return prefix + '_' + random + unique + String(time); +} diff --git a/src/views/.DS_Store b/src/views/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..92dce960a95eac817fdcd2e6210c9cb46572cab2 GIT binary patch literal 8196 zcmeI1y>1gh6ov2j2iwr3Kq%!FG*BfH1*H>A4~ppHKX8QYT_v%sG-zLfm!L(WB~=Ov z1h2r8aPG{=@tv6q1roAgM%ulroilSkpPAj!tcl1RuO^2?`$W{m!Ex^%PKms>?Xiqerzd1Y^my0UW<{R08>_B!PJCGg74(x^lShKlwm380M=5ux+JMdpR!0(3w z2gkmTwTt%Efs@?=AhvMZ7F=T=VA~Wv_I<2fv`x{c+dUZH)c7riam`U*upF`PW9_1A zPR2DS<1-t-Loqfx+7(t#rte}tX9uzau>-t!Z_|i|bU|mq{@r}#&jMSui*hg+&C3z) z^5gdK+0&b&P%-(9qMB`eA!vLzA=Y;R^au zJPTBUr%^D^UC9H-N?HmkI=Iqw3R|*Ig)pfVoNiI+f^!Au#x%3@Zz>p@)qOBV8ig;R zOO9xy6I@OEJaoV`1=SSJRl#`DqYt186be(MN)iPs!9y>QjP6*T3Zr-)&@?)q!+M29 z^r4KK&3&$-%iQtYh^w={ykdb_wt;aVGgX2J$O<+K1S|@ zO5sQ)|9BUd*Z(6-$7o&uSJ(fa17QLk literal 0 HcmV?d00001 diff --git a/src/views/basic/account/BaseSetting.vue b/src/views/basic/account/BaseSetting.vue new file mode 100644 index 0000000..b14c4e9 --- /dev/null +++ b/src/views/basic/account/BaseSetting.vue @@ -0,0 +1,102 @@ + + + + diff --git a/src/views/basic/account/BindEmailModal.vue b/src/views/basic/account/BindEmailModal.vue new file mode 100644 index 0000000..a136ea9 --- /dev/null +++ b/src/views/basic/account/BindEmailModal.vue @@ -0,0 +1,146 @@ + + + + + \ No newline at end of file diff --git a/src/views/basic/account/BindPhoneModal.vue b/src/views/basic/account/BindPhoneModal.vue new file mode 100644 index 0000000..b10bf80 --- /dev/null +++ b/src/views/basic/account/BindPhoneModal.vue @@ -0,0 +1,147 @@ + + + + + \ No newline at end of file diff --git a/src/views/basic/account/MsgNotify.vue b/src/views/basic/account/MsgNotify.vue new file mode 100644 index 0000000..e784c66 --- /dev/null +++ b/src/views/basic/account/MsgNotify.vue @@ -0,0 +1,78 @@ + + + diff --git a/src/views/basic/account/ResetPasswordModal.vue b/src/views/basic/account/ResetPasswordModal.vue new file mode 100644 index 0000000..e44139f --- /dev/null +++ b/src/views/basic/account/ResetPasswordModal.vue @@ -0,0 +1,50 @@ + + + \ No newline at end of file diff --git a/src/views/basic/account/SecureSetting.vue b/src/views/basic/account/SecureSetting.vue new file mode 100644 index 0000000..85641fe --- /dev/null +++ b/src/views/basic/account/SecureSetting.vue @@ -0,0 +1,96 @@ + + + diff --git a/src/views/basic/account/data.ts b/src/views/basic/account/data.ts new file mode 100644 index 0000000..219b55e --- /dev/null +++ b/src/views/basic/account/data.ts @@ -0,0 +1,151 @@ +import { FormSchema } from '/@/components/Form/index'; +import {useI18n} from "@/hooks/web/useI18n"; + +const { t } = useI18n(); + +export interface ListItem { + key: string; + title: string; + description: string; + extra?: string; + avatar?: string; + color?: string; +} + +// tab的list +export const settingList = [ + { + key: '1', + name: t('basic.account.basicSetting'), + component: 'BaseSetting', + }, + { + key: '2', + name: t('basic.account.safeSetting'), + component: 'SecureSetting', + }, + { + key: '4', + name: t('basic.account.notice.title'), + component: 'MsgNotify', + }, +]; + +// 基础设置 form +export const baseSetSchemas: FormSchema[] = [ + { + field: 'id', + component: 'Input', + ifShow: false, + }, + { + field: 'name', + component: 'Input', + label: t('basic.account.name'), + colProps: { span: 18 }, + required: true, + }, + { + field: 'position', + component: 'Input', + label: t('basic.account.position'), + colProps: { span: 18 }, + }, + { + field: 'systemLanguage', + component: 'Select', + label: t('basic.account.systemLanguage'), + helpMessage(renderCallbackParams) { + return t('basic.account.systemLanguageTip'); + }, + componentProps: { + options: [ + { label: t('sys.language.zhCN'), value: 'zh_CN', key: 'zh_CN' }, + { label: t('sys.language.enUS'), value: 'en_US', key: 'en_US' }, + ], + }, + colProps: { span: 18 }, + }, + { + field: 'description', + component: 'InputTextArea', + label: t('basic.account.personalProfile'), + colProps: { span: 18 }, + }, +]; + +// 安全设置 list +export const secureSettingList: ListItem[] = [ + { + key: '1', + title: '账户密码', + description: t('basic.account.accountPasswordTip'), + extra: t('basic.account.update'), + }, + { + key: '2', + title: '密保手机', + description: '已绑定手机:', + extra: t('basic.account.update'), + }, + { + key: '3', + title: '密保邮箱', + description: '已绑定邮箱:', + extra: t('basic.account.update'), + }, +]; + + +export const resetPasswordFormSchema: FormSchema[] = [ + { + field: 'id', + component: 'Input', + ifShow: false, + }, + { + field: 'userName', + component: 'Input', + ifShow: false, + }, + { + label: t('basic.account.password.oldPassword'), + field: 'password', + component: 'InputPassword', + required: true, + rules: [ + { + required: true, + message: t('basic.account.password.inputOldPassword'), + trigger: 'change', + }, + ], + }, + { + label: t('basic.account.password.newPassword'), + field: 'newPassword', + valueField: 'newPassword', + component: 'InputPassword', + required: true, + rules: [ + { + required: true, + message: t('basic.account.password.inputNewPassword'), + trigger: 'change', + }, + ], + }, + { + label: t('basic.account.password.confirmPassword'), + field: 'confirmPassword', + component: 'InputPassword', + required: true, + rules: [ + { + required: true, + message: t('basic.account.password.inputConfirmPassword'), + trigger: 'change', + } + ], + }, +] \ No newline at end of file diff --git a/src/views/basic/account/index.vue b/src/views/basic/account/index.vue new file mode 100644 index 0000000..6f15e89 --- /dev/null +++ b/src/views/basic/account/index.vue @@ -0,0 +1,59 @@ + + + + diff --git a/src/views/basic/customer/components/CustomerModal.vue b/src/views/basic/customer/components/CustomerModal.vue new file mode 100644 index 0000000..8a7c018 --- /dev/null +++ b/src/views/basic/customer/components/CustomerModal.vue @@ -0,0 +1,102 @@ + + + \ No newline at end of file diff --git a/src/views/basic/customer/customer.data.ts b/src/views/basic/customer/customer.data.ts new file mode 100644 index 0000000..bb4fcc7 --- /dev/null +++ b/src/views/basic/customer/customer.data.ts @@ -0,0 +1,251 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import { h } from 'vue'; +import {Switch} from "ant-design-vue"; +import {useMessage} from "@/hooks/web/useMessage"; +import {useI18n} from "@/hooks/web/useI18n"; +import {updateCustomerStatus} from "@/api/basic/customer"; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('basic.customer.table.name'), + dataIndex: 'customerName', + width: 180, + }, + { + title: t('basic.customer.table.contact'), + dataIndex: 'contact', + width: 80, + }, + { + title: t('basic.customer.table.phoneNumber'), + dataIndex: 'phoneNumber', + width: 120, + }, + { + title: t('basic.customer.table.email'), + dataIndex: 'email', + width: 120, + }, + { + title: t('basic.customer.table.status'), + dataIndex: 'status', + width: 100, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked, _) { + const {createMessage} = useMessage(); + if (record.id == 1) { + createMessage.warn(t('common.notice')); + return; + } + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + updateCustomerStatus([record.id], newStatus ) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + { + title: t('basic.customer.table.accumulatedAccountsReceivable'), + dataIndex: 'totalAccountReceivable', + width: 90, + }, + { + title: t('basic.customer.table.rate'), + dataIndex: 'taxRate', + width: 80, + }, + { + title: t('basic.customer.table.sort'), + dataIndex: 'sort', + width: 80, + }, + { + title: t('basic.customer.table.createTime'), + dataIndex: 'createTime', + width: 150, + } +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('basic.customer.header.name'), + field: 'customerName', + component: 'Input', + colProps: { span: 5 }, + }, + { + label: t('basic.customer.header.phoneNumber'), + field: 'phoneNumber', + component: 'Input', + colProps: { span: 5 }, + }, + { + field: '[startDate, endDate]', + label: t('basic.customer.header.createTime'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('basic.customer.header.startDate'), t('basic.customer.header.endDate')], + }, + colProps: { span: 7 }, + }, +] + +export const formSchema: FormSchema[] = [ + { + label: t('basic.customer.form.name'), + field: 'customerName', + helpMessage: t('basic.customer.form.nameTip'), + component: 'Input', + colProps: { + span: 11, + }, + required: true, + }, + { + label: t('basic.customer.form.contact'), + field: 'contact', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.customer.form.phoneNumber'), + field: 'phoneNumber', + component: 'Input', + colProps: { + span: 11, + }, + required: true, + }, + { + label: t('basic.customer.form.email'), + field: 'email', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.customer.form.fax'), + field: 'fax', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.customer.form.address'), + field: 'address', + component: 'InputTextArea', + colProps: { + span: 11, + }, + }, + { + label: t('basic.customer.form.remark'), + field: 'remark', + component: 'InputTextArea', + colProps: { + span: 11, + }, + }, + { + field: '', + component: 'Divider', + label: t('basic.customer.form.accountsReceivableInfo'), + colProps: { + span: 22, + }, + }, + { + label: t('basic.customer.form.firstQuarterCollection'), + field: 'firstQuarterAccountReceivable', + component: 'InputNumber', + colProps: { + span: 11, + }, + }, + { + label: t('basic.customer.form.secondQuarterCollection'), + field: 'secondQuarterAccountReceivable', + component: 'InputNumber', + colProps: { + span: 11, + }, + }, + { + label: t('basic.customer.form.thirdQuarterCollection'), + field: 'thirdQuarterAccountReceivable', + component: 'InputNumber', + colProps: { + span: 11, + }, + }, + { + label: t('basic.customer.form.fourthQuarterCollection'), + field: 'fourthQuarterAccountReceivable', + component: 'InputNumber', + colProps: { + span: 11, + }, + }, + { + field: '', + component: 'Divider', + label: t('basic.customer.form.accountInfo'), + colProps: { + span: 22, + }, + }, + { + label: t('basic.customer.form.taxNumber'), + field: 'taxNumber', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.customer.form.rate'), + field: 'taxRate', + component: 'InputNumber', + colProps: { + span: 11, + }, + }, + { + label: t('basic.customer.form.bankName'), + field: 'bankName', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.customer.form.bankAccount'), + field: 'accountNumber', + component: 'InputNumber', + colProps: { + span: 11, + }, + } +] \ No newline at end of file diff --git a/src/views/basic/customer/index.vue b/src/views/basic/customer/index.vue new file mode 100644 index 0000000..6200a6b --- /dev/null +++ b/src/views/basic/customer/index.vue @@ -0,0 +1,199 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/basic/income-expense/components/AddEditModal.vue b/src/views/basic/income-expense/components/AddEditModal.vue new file mode 100644 index 0000000..db87d16 --- /dev/null +++ b/src/views/basic/income-expense/components/AddEditModal.vue @@ -0,0 +1,77 @@ + + + \ No newline at end of file diff --git a/src/views/basic/income-expense/incomeExpense.data.ts b/src/views/basic/income-expense/incomeExpense.data.ts new file mode 100644 index 0000000..020b6f0 --- /dev/null +++ b/src/views/basic/income-expense/incomeExpense.data.ts @@ -0,0 +1,96 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('basic.incomeExpense.table.name'), + dataIndex: 'name', + width: 90, + }, + { + title: t('basic.incomeExpense.table.type'), + dataIndex: 'type', + width: 120, + }, + { + title: t('basic.incomeExpense.table.remark'), + dataIndex: 'remark', + width: 200, + }, + { + title: t('basic.incomeExpense.table.sort'), + dataIndex: 'sort', + width: 80, + }, + { + title: t('basic.incomeExpense.table.status'), + dataIndex: 'status', + width: 80, + }, + { + title: t('basic.incomeExpense.table.createTime'), + dataIndex: 'createTime', + width: 150, + } +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('basic.incomeExpense.header.name'), + field: 'name', + component: 'Input', + colProps: { span: 7 }, + }, + { + label: t('basic.incomeExpense.header.type'), + field: 'type', + component: 'Select', + colProps: { span: 7 }, + componentProps: { + options: [ + { label: t('basic.incomeExpense.income'), value: '收入', key: 0 }, + { label: t('basic.incomeExpense.expense'), value: '支出', key: 1 }, + ], + }, + }, + { + label: t('basic.incomeExpense.header.remark'), + field: 'remark', + component: 'Input', + colProps: { span: 7 }, + }, +] + +export const formSchema: FormSchema[] = [ + { + label: t('basic.incomeExpense.form.name'), + field: 'name', + component: 'Input', + required: true, + }, + { + label: t('basic.incomeExpense.form.type'), + field: 'type', + component: 'Select', + componentProps: { + options: [ + { label: t('basic.incomeExpense.income'), value: '收入', key: 0 }, + { label: t('basic.incomeExpense.expense'), value: '支出', key: 1 }, + ], + }, + required: true, + }, + { + label: t('basic.incomeExpense.form.sort'), + field: 'sort', + component: 'InputNumber', + }, + { + label: t('basic.incomeExpense.form.remark'), + field: 'remark', + component: 'InputTextArea', + } +] \ No newline at end of file diff --git a/src/views/basic/income-expense/index.vue b/src/views/basic/income-expense/index.vue new file mode 100644 index 0000000..b051c3c --- /dev/null +++ b/src/views/basic/income-expense/index.vue @@ -0,0 +1,158 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/basic/member/components/MemberModal.vue b/src/views/basic/member/components/MemberModal.vue new file mode 100644 index 0000000..f4279de --- /dev/null +++ b/src/views/basic/member/components/MemberModal.vue @@ -0,0 +1,79 @@ + + + \ No newline at end of file diff --git a/src/views/basic/member/index.vue b/src/views/basic/member/index.vue new file mode 100644 index 0000000..f445128 --- /dev/null +++ b/src/views/basic/member/index.vue @@ -0,0 +1,198 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/basic/member/member.data.ts b/src/views/basic/member/member.data.ts new file mode 100644 index 0000000..daeb388 --- /dev/null +++ b/src/views/basic/member/member.data.ts @@ -0,0 +1,170 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import { h } from 'vue'; +import {Switch} from "ant-design-vue"; +import {useMessage} from "@/hooks/web/useMessage"; +import {useI18n} from "@/hooks/web/useI18n"; +import {updateMemberStatus} from "@/api/basic/member"; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('basic.member.table.memberNumber'), + dataIndex: 'memberNumber', + width: 180, + }, + { + title: t('basic.member.table.memberName'), + dataIndex: 'memberName', + width: 80, + }, + { + title: t('basic.member.table.phoneNumber'), + dataIndex: 'phoneNumber', + width: 120, + }, + { + title: t('basic.member.table.email'), + dataIndex: 'email', + width: 120, + }, + { + title: t('basic.member.table.advancePayment'), + dataIndex: 'advancePayment', + width: 90, + }, + { + title: t('basic.member.table.status'), + dataIndex: 'status', + width: 100, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked, _) { + const {createMessage} = useMessage(); + if (record.id == 1) { + createMessage.warn(t('common.notice')); + return; + } + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + updateMemberStatus([record.id], newStatus ) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + { + title: t('basic.member.table.remark'), + dataIndex: 'remark', + width: 80, + }, + { + title: t('basic.member.table.sort'), + dataIndex: 'sort', + width: 80, + }, + { + title: t('basic.member.table.createTime'), + dataIndex: 'createTime', + width: 150, + } +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('basic.member.header.memberNumber'), + field: 'memberNumber', + component: 'Input', + colProps: { span: 5 }, + }, + { + label: t('basic.member.header.phoneNumber'), + field: 'phoneNumber', + component: 'Input', + colProps: { span: 5 }, + }, + { + field: '[startDate, endDate]', + label: t('basic.member.header.createTime'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('basic.member.header.startDate'), t('basic.member.header.endDate')], + }, + colProps: { span: 7 }, + }, +] + +export const formSchema: FormSchema[] = [ + { + label: t('basic.member.form.memberNumber'), + field: 'memberNumber', + component: 'Input', + colProps: { + span: 11, + }, + required: true, + }, + { + label: t('basic.member.form.memberName'), + field: 'memberName', + component: 'Input', + colProps: { + span: 11, + }, + required: true, + }, + { + label: t('basic.member.form.phoneNumber'), + field: 'phoneNumber', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.member.form.email'), + field: 'email', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.member.form.advancePayment'), + field: 'advancePayment', + component: 'InputNumber', + colProps: { + span: 11, + } + }, + { + label: t('basic.member.table.remark'), + field: 'remark', + component: 'InputTextArea', + colProps: { + span: 11, + }, + }, + { + label: t('basic.member.table.sort'), + field: 'sort', + component: 'InputNumber', + colProps: { + span: 11, + } + } +] \ No newline at end of file diff --git a/src/views/basic/operator/components/OperatorModal.vue b/src/views/basic/operator/components/OperatorModal.vue new file mode 100644 index 0000000..2e0cb16 --- /dev/null +++ b/src/views/basic/operator/components/OperatorModal.vue @@ -0,0 +1,77 @@ + + + \ No newline at end of file diff --git a/src/views/basic/operator/index.vue b/src/views/basic/operator/index.vue new file mode 100644 index 0000000..2834993 --- /dev/null +++ b/src/views/basic/operator/index.vue @@ -0,0 +1,152 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/basic/operator/operator.data.ts b/src/views/basic/operator/operator.data.ts new file mode 100644 index 0000000..7d801f6 --- /dev/null +++ b/src/views/basic/operator/operator.data.ts @@ -0,0 +1,118 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import { h } from 'vue'; +import {Switch} from "ant-design-vue"; +import {useMessage} from "@/hooks/web/useMessage"; +import {useI18n} from "@/hooks/web/useI18n"; +import {updateOperatorStatus} from "@/api/basic/operator"; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('basic.operator.table.name'), + dataIndex: 'name', + width: 90, + }, + { + title: t('basic.operator.table.type'), + dataIndex: 'type', + width: 120, + }, + { + title: t('basic.operator.table.status'), + dataIndex: 'status', + width: 100, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked, _) { + const {createMessage} = useMessage(); + if (record.id == 1) { + createMessage.warn(t('common.notice')); + return; + } + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + updateOperatorStatus([record.id], newStatus ) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + { + title: t('basic.operator.table.sort'), + dataIndex: 'sort', + width: 80, + }, + { + title: t('basic.operator.table.createTime'), + dataIndex: 'createTime', + width: 150, + } +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('basic.operator.header.name'), + field: 'name', + component: 'Input', + colProps: { span: 5 }, + }, + { + label: t('basic.operator.header.type'), + field: 'type', + component: 'Select', + colProps: { span: 5 }, + componentProps: { + options: [ + { label: t('basic.operator.businessPerson'), value: '业务员', key: 0 }, + { label: t('basic.operator.financialPerson'), value: '财务员', key: 1 }, + { label: t('basic.operator.salesPerson'), value: '销售员', key: 2 }, + ], + }, + } +] + +export const formSchema: FormSchema[] = [ + { + label: t('basic.operator.form.name'), + field: 'name', + component: 'Input', + required: true, + }, + { + label: t('basic.operator.form.type'), + field: 'type', + component: 'Select', + componentProps: { + options: [ + { label: t('basic.operator.businessPerson'), value: '业务员', key: 0 }, + { label: t('basic.operator.financialPerson'), value: '财务员', key: 1 }, + { label: t('basic.operator.salesPerson'), value: '销售员', key: 2 }, + ], + }, + required: true, + }, + { + label: t('basic.operator.form.sort'), + field: 'sort', + component: 'InputNumber', + }, + { + label: t('basic.operator.form.remark'), + field: 'remark', + component: 'InputTextArea', + } +] \ No newline at end of file diff --git a/src/views/basic/settlement-account/components/FinancialAccountModal.vue b/src/views/basic/settlement-account/components/FinancialAccountModal.vue new file mode 100644 index 0000000..ed46c7f --- /dev/null +++ b/src/views/basic/settlement-account/components/FinancialAccountModal.vue @@ -0,0 +1,80 @@ + + + \ No newline at end of file diff --git a/src/views/basic/settlement-account/components/MultipleAccountsModal.vue b/src/views/basic/settlement-account/components/MultipleAccountsModal.vue new file mode 100644 index 0000000..f6a876c --- /dev/null +++ b/src/views/basic/settlement-account/components/MultipleAccountsModal.vue @@ -0,0 +1,155 @@ + + \ No newline at end of file diff --git a/src/views/basic/settlement-account/financialAccount.data.ts b/src/views/basic/settlement-account/financialAccount.data.ts new file mode 100644 index 0000000..f344e4c --- /dev/null +++ b/src/views/basic/settlement-account/financialAccount.data.ts @@ -0,0 +1,147 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {h} from 'vue'; +import {Switch} from "ant-design-vue"; +import {useMessage} from "@/hooks/web/useMessage"; +import {useI18n} from "@/hooks/web/useI18n"; +import {updateAccountStatus} from "@/api/financial/account"; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('basic.settlement.table.accountNumber'), + dataIndex: 'accountNumber', + width: 90, + }, + { + title: t('basic.settlement.table.accountName'), + dataIndex: 'accountName', + width: 120, + }, + { + title: t('basic.settlement.table.openingAmount'), + dataIndex: 'initialAmount', + width: 120, + }, + { + title: t('basic.settlement.table.currentBalance'), + dataIndex: 'currentAmount', + width: 120, + }, + { + title: t('basic.settlement.table.status'), + dataIndex: 'status', + width: 100, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked, _) { + const {createMessage} = useMessage(); + if (record.id == 1) { + createMessage.warn(t('common.notice')); + return; + } + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + updateAccountStatus([record.id], newStatus ) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + { + title: t('basic.settlement.table.sort'), + dataIndex: 'sort', + width: 80, + }, + { + title: t('basic.settlement.table.default'), + dataIndex: 'isDefault', + width: 80, + }, + { + title: t('basic.settlement.table.createTime'), + dataIndex: 'createTime', + width: 150, + } +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('basic.settlement.header.accountNumber'), + field: 'accountNumber', + component: 'Input', + colProps: { span: 5 }, + }, + { + label: t('basic.settlement.header.accountName'), + field: 'accountName', + component: 'Input', + colProps: { span: 5 }, + } +] + +export const formSchema: FormSchema[] = [ + { + label: t('basic.settlement.form.accountName'), + field: 'accountName', + component: 'Input', + required: true, + }, + { + label: t('basic.settlement.form.accountNumber'), + field: 'accountNumber', + component: 'Input', + }, + { + label: t('basic.settlement.form.openingAmount'), + field: 'initialAmount', + component: 'InputNumber', + }, + { + label: t('basic.settlement.form.currentBalance'), + field: 'currentAmount', + component: 'InputNumber', + }, + { + label: t('basic.settlement.form.default'), + field: 'isDefault', + helpMessage: t('basic.settlement.form.notice'), + component: 'RadioGroup', + defaultValue: 0, + componentProps: { + options: [ + { + label: t('basic.settlement.no'), + value: 0, + }, + { + label: t('basic.settlement.yes'), + value: 1, + }, + ], + }, + }, + { + label: t('basic.settlement.form.remark'), + field: 'remark', + component: 'InputTextArea', + }, + { + label: t('basic.settlement.form.sort'), + field: 'sort', + component: 'InputNumber', + } +] \ No newline at end of file diff --git a/src/views/basic/settlement-account/index.vue b/src/views/basic/settlement-account/index.vue new file mode 100644 index 0000000..67c7a6f --- /dev/null +++ b/src/views/basic/settlement-account/index.vue @@ -0,0 +1,158 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/basic/supplier/components/SupplierModal.vue b/src/views/basic/supplier/components/SupplierModal.vue new file mode 100644 index 0000000..41dada4 --- /dev/null +++ b/src/views/basic/supplier/components/SupplierModal.vue @@ -0,0 +1,104 @@ + + + \ No newline at end of file diff --git a/src/views/basic/supplier/index.vue b/src/views/basic/supplier/index.vue new file mode 100644 index 0000000..946eede --- /dev/null +++ b/src/views/basic/supplier/index.vue @@ -0,0 +1,201 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/basic/supplier/supplier.data.ts b/src/views/basic/supplier/supplier.data.ts new file mode 100644 index 0000000..b173812 --- /dev/null +++ b/src/views/basic/supplier/supplier.data.ts @@ -0,0 +1,261 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import { h } from 'vue'; +import {Switch} from "ant-design-vue"; +import {useMessage} from "@/hooks/web/useMessage"; +import {useI18n} from "@/hooks/web/useI18n"; +import {updateSupplierStatus} from "@/api/basic/supplier"; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('basic.supplier.table.name'), + dataIndex: 'supplierName', + width: 180, + }, + { + title: t('basic.supplier.table.contact'), + dataIndex: 'contact', + width: 80, + }, + { + title: t('basic.supplier.table.phoneNumber'), + dataIndex: 'phoneNumber', + width: 120, + }, + { + title: t('basic.supplier.table.email'), + dataIndex: 'email', + width: 120, + }, + { + title: t('basic.supplier.table.status'), + dataIndex: 'status', + width: 100, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked, _) { + const {createMessage} = useMessage(); + if (record.id == 1) { + createMessage.warn(t('common.notice')); + return; + } + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + updateSupplierStatus({ids: [record.id], status: newStatus} ) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + { + title: t('basic.supplier.table.accumulatedAccountsPayable'), + dataIndex: 'totalAccountPayment', + width: 90, + }, + { + title: t('basic.supplier.table.rate'), + dataIndex: 'taxRate', + width: 80, + }, + { + title: t('basic.supplier.table.sort'), + dataIndex: 'sort', + width: 80, + }, + { + title: t('basic.supplier.table.createTime'), + dataIndex: 'createTime', + width: 150, + } +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('basic.supplier.header.name'), + field: 'supplierName', + component: 'Input', + colProps: { span: 5 }, + }, + { + label: t('basic.supplier.header.contactPhone'), + field: 'contactNumber', + component: 'Input', + colProps: { span: 5 }, + }, + { + field: '[startDate, endDate]', + label: t('basic.supplier.header.createTime'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('basic.supplier.header.startDate'), t('basic.supplier.header.endDate')], + }, + colProps: { span: 7 }, + }, +] + +export const formSchema: FormSchema[] = [ + { + label: t('basic.supplier.form.name'), + field: 'supplierName', + helpMessage: t('basic.supplier.form.notice'), + component: 'Input', + colProps: { + span: 11, + }, + required: true, + }, + { + label: t('basic.supplier.form.contact'), + field: 'contact', + component: 'Input', + colProps: { + span: 11, + }, + required: true, + }, + { + label: t('basic.supplier.form.phoneNumber'), + field: 'phoneNumber', + component: 'Input', + colProps: { + span: 11, + }, + required: true, + }, + { + label: t('basic.supplier.form.contactPhone'), + helpMessage: t('basic.supplier.form.noticeTwo'), + field: 'contactNumber', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.supplier.form.email'), + field: 'email', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.supplier.form.fax'), + field: 'fax', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.supplier.form.address'), + field: 'address', + component: 'InputTextArea', + colProps: { + span: 11, + }, + }, + { + label: t('basic.supplier.form.remark'), + field: 'remark', + component: 'InputTextArea', + colProps: { + span: 11, + }, + }, + { + field: '', + component: 'Divider', + label: t('basic.supplier.form.accountsPayableInfo'), + colProps: { + span: 22, + }, + }, + { + label: t('basic.supplier.form.firstQuarterPayment'), + field: 'firstQuarterAccountPayment', + component: 'InputNumber', + colProps: { + span: 11, + }, + }, + { + label: t('basic.supplier.form.secondQuarterPayment'), + field: 'secondQuarterAccountPayment', + component: 'InputNumber', + colProps: { + span: 11, + }, + }, + { + label: t('basic.supplier.form.thirdQuarterPayment'), + field: 'thirdQuarterAccountPayment', + component: 'InputNumber', + colProps: { + span: 11, + }, + }, + { + label: t('basic.supplier.form.fourthQuarterPayment'), + field: 'fourthQuarterAccountPayment', + component: 'InputNumber', + colProps: { + span: 11, + }, + }, + { + field: '', + component: 'Divider', + label: t('basic.supplier.form.accountInfo'), + colProps: { + span: 22, + }, + }, + { + label: t('basic.supplier.form.taxNumber'), + field: 'taxNumber', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.supplier.form.rate'), + field: 'taxRate', + component: 'InputNumber', + colProps: { + span: 11, + }, + }, + { + label: t('basic.supplier.form.bankName'), + field: 'bankName', + component: 'Input', + colProps: { + span: 11, + }, + }, + { + label: t('basic.supplier.form.bankAccount'), + field: 'accountNumber', + component: 'InputNumber', + colProps: { + span: 11, + }, + } +] \ No newline at end of file diff --git a/src/views/basic/warehouse/components/WarehouseModal.vue b/src/views/basic/warehouse/components/WarehouseModal.vue new file mode 100644 index 0000000..a45df59 --- /dev/null +++ b/src/views/basic/warehouse/components/WarehouseModal.vue @@ -0,0 +1,81 @@ + + + \ No newline at end of file diff --git a/src/views/basic/warehouse/index.vue b/src/views/basic/warehouse/index.vue new file mode 100644 index 0000000..11ea9f9 --- /dev/null +++ b/src/views/basic/warehouse/index.vue @@ -0,0 +1,158 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/basic/warehouse/warehouse.data.ts b/src/views/basic/warehouse/warehouse.data.ts new file mode 100644 index 0000000..e6cfcbd --- /dev/null +++ b/src/views/basic/warehouse/warehouse.data.ts @@ -0,0 +1,165 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import { h } from 'vue'; +import {Switch} from "ant-design-vue"; +import {useMessage} from "@/hooks/web/useMessage"; +import {useI18n} from "@/hooks/web/useI18n"; +import {updateWarehouseStatus} from "@/api/basic/warehouse"; +import {getTenantUserList} from "@/api/sys/user"; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('basic.warehouse.table.warehouseName'), + dataIndex: 'warehouseName', + width: 180, + }, + { + title: t('basic.warehouse.table.warehouseAddress'), + dataIndex: 'address', + width: 80, + }, + { + title: t('basic.warehouse.table.storageFees'), + dataIndex: 'price', + width: 120, + }, + { + title: t('basic.warehouse.table.handlingFees'), + dataIndex: 'truckage', + width: 120, + }, + { + title: t('basic.warehouse.table.manager'), + dataIndex: 'warehouseManagerName', + width: 90, + }, + { + title: t('basic.warehouse.table.status'), + dataIndex: 'status', + width: 100, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked, _) { + const {createMessage} = useMessage(); + if (record.id == 1) { + createMessage.warn(t('common.notice')); + return; + } + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + updateWarehouseStatus([record.id], newStatus ) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + { + title: t('basic.warehouse.table.default'), + dataIndex: 'isDefault', + width: 80, + }, + { + title: t('basic.warehouse.table.sort'), + dataIndex: 'sort', + width: 80, + }, + { + title: t('basic.warehouse.table.createTime'), + dataIndex: 'createTime', + width: 150, + } +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('basic.warehouse.header.warehouse'), + field: 'warehouseName', + component: 'Input', + colProps: { span: 5 }, + }, + { + label: t('basic.warehouse.header.remark'), + field: 'remark', + component: 'Input', + colProps: { span: 5 }, + } +] + +export const formSchema: FormSchema[] = [ + { + label: t('basic.warehouse.form.warehouseName'), + field: 'warehouseName', + component: 'Input', + required: true, + }, + { + label: t('basic.warehouse.form.warehouseAddress'), + field: 'address', + component: 'Input', + }, + { + label: t('basic.warehouse.form.storageFees'), + field: 'price', + component: 'InputNumber', + }, + { + label: t('basic.warehouse.form.handlingFees'), + field: 'truckage', + component: 'InputNumber', + }, + { + label: t('basic.warehouse.form.default'), + field: 'isDefault', + helpMessage: t('basic.warehouse.form.defaultTip'), + component: 'RadioGroup', + defaultValue: 0, + componentProps: { + options: [ + { + label: t('basic.warehouse.no'), + value: 0, + }, + { + label: t('basic.warehouse.yes'), + value: 1, + }, + ], + }, + }, + { + field: 'warehouseManager', + label: t('basic.warehouse.form.manager'), + component: 'ApiSelect', + helpMessage: [t('basic.warehouse.form.managerTip')], + componentProps: { + api: getTenantUserList, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + }, + { + label: t('basic.warehouse.form.remark'), + field: 'remark', + component: 'InputTextArea', + }, + { + label: t('basic.warehouse.form.sort'), + field: 'sort', + component: 'InputNumber', + } +] \ No newline at end of file diff --git a/src/views/dashboard/analysis/components/GrowCard.vue b/src/views/dashboard/analysis/components/GrowCard.vue new file mode 100644 index 0000000..5eb988e --- /dev/null +++ b/src/views/dashboard/analysis/components/GrowCard.vue @@ -0,0 +1,59 @@ + + diff --git a/src/views/dashboard/analysis/components/GrowCardFour.vue b/src/views/dashboard/analysis/components/GrowCardFour.vue new file mode 100644 index 0000000..0208525 --- /dev/null +++ b/src/views/dashboard/analysis/components/GrowCardFour.vue @@ -0,0 +1,49 @@ + + diff --git a/src/views/dashboard/analysis/components/GrowCardThree.vue b/src/views/dashboard/analysis/components/GrowCardThree.vue new file mode 100644 index 0000000..756984a --- /dev/null +++ b/src/views/dashboard/analysis/components/GrowCardThree.vue @@ -0,0 +1,49 @@ + + diff --git a/src/views/dashboard/analysis/components/GrowCardTwo.vue b/src/views/dashboard/analysis/components/GrowCardTwo.vue new file mode 100644 index 0000000..af42633 --- /dev/null +++ b/src/views/dashboard/analysis/components/GrowCardTwo.vue @@ -0,0 +1,49 @@ + + diff --git a/src/views/dashboard/analysis/components/SalesProductPie.vue b/src/views/dashboard/analysis/components/SalesProductPie.vue new file mode 100644 index 0000000..da2fe49 --- /dev/null +++ b/src/views/dashboard/analysis/components/SalesProductPie.vue @@ -0,0 +1,65 @@ + + diff --git a/src/views/dashboard/analysis/components/SiteAnalysis.vue b/src/views/dashboard/analysis/components/SiteAnalysis.vue new file mode 100644 index 0000000..d105be6 --- /dev/null +++ b/src/views/dashboard/analysis/components/SiteAnalysis.vue @@ -0,0 +1,38 @@ + + diff --git a/src/views/dashboard/analysis/components/VisitAnalysis.vue b/src/views/dashboard/analysis/components/VisitAnalysis.vue new file mode 100644 index 0000000..2f4f7a5 --- /dev/null +++ b/src/views/dashboard/analysis/components/VisitAnalysis.vue @@ -0,0 +1,89 @@ + + + diff --git a/src/views/dashboard/analysis/components/VisitAnalysisBar.vue b/src/views/dashboard/analysis/components/VisitAnalysisBar.vue new file mode 100644 index 0000000..956b691 --- /dev/null +++ b/src/views/dashboard/analysis/components/VisitAnalysisBar.vue @@ -0,0 +1,46 @@ + + + diff --git a/src/views/dashboard/analysis/components/VisitRadar.vue b/src/views/dashboard/analysis/components/VisitRadar.vue new file mode 100644 index 0000000..10abcc3 --- /dev/null +++ b/src/views/dashboard/analysis/components/VisitRadar.vue @@ -0,0 +1,64 @@ + + diff --git a/src/views/dashboard/analysis/components/VisitSource.vue b/src/views/dashboard/analysis/components/VisitSource.vue new file mode 100644 index 0000000..8f18cb1 --- /dev/null +++ b/src/views/dashboard/analysis/components/VisitSource.vue @@ -0,0 +1,65 @@ + + diff --git a/src/views/dashboard/analysis/components/props.ts b/src/views/dashboard/analysis/components/props.ts new file mode 100644 index 0000000..8643650 --- /dev/null +++ b/src/views/dashboard/analysis/components/props.ts @@ -0,0 +1,16 @@ +import { PropType } from 'vue'; + +export interface BasicProps { + width: string; + height: string; +} +export const basicProps = { + width: { + type: String as PropType, + default: '100%', + }, + height: { + type: String as PropType, + default: '280px', + }, +}; diff --git a/src/views/dashboard/analysis/data.ts b/src/views/dashboard/analysis/data.ts new file mode 100644 index 0000000..257ad5e --- /dev/null +++ b/src/views/dashboard/analysis/data.ts @@ -0,0 +1,144 @@ +import {ref} from "vue"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export interface GrowCardItem { + icon: string; + dataIndex: string; + title: string; + value: number; + total: number; + color: string; + action: string; +} + +export const growCardList: GrowCardItem[] = [ + { + title: t('home.todayRetail'), + dataIndex: 'todayRetailSales', + icon: 'visit-count|svg', + value: 0, + total: 0, + color: 'green', + action: t('home.today'), + }, + { + title: t('home.todaySales'), + dataIndex: 'todaySales', + icon: 'visit-count|svg', + value: 0, + total: 0, + color: 'green', + action: t('home.today'), + }, + { + title: t('home.todayPurchase'), + dataIndex: 'todayPurchase', + icon: 'visit-count|svg', + value: 0, + total: 0, + color: 'green', + action: t('home.today'), + }, +]; + +export const growCardTwoList: GrowCardItem[] = [ + { + title: t('home.yesterdayRetail'), + dataIndex: 'yesterdayRetailSales', + icon: 'visit-count|svg', + value: 0, + total: 0, + color: 'blue', + action: t('home.yesterday'), + }, + { + title: t('home.yesterdaySales'), + dataIndex: 'yesterdaySales', + icon: 'total-sales|svg', + value: 0, + total: 0, + color: 'blue', + action: t('home.yesterday'), + }, + { + title: t('home.yesterdayPurchase'), + dataIndex: 'yesterdayPurchase', + icon: 'download-count|svg', + value: 0, + total: 0, + color: 'blue', + action: t('home.yesterday'), + }, +]; + +export const growCardThreeList: GrowCardItem[] = [ + { + title: t('home.thisMonthRetail'), + dataIndex: 'monthRetailSales', + icon: 'total-sales|svg', + value: 0, + total: 0, + color: 'orange', + action: t('home.thisMonth'), + }, + { + title: t('home.thisMonthSales'), + dataIndex: 'monthSales', + icon: 'total-sales|svg', + value: 0, + total: 0, + color: 'orange', + action: t('home.thisMonth'), + }, + { + title: t('home.thisMonthPurchase'), + dataIndex: 'monthPurchase', + icon: 'total-sales|svg', + value: 0, + total: 0, + color: 'orange', + action: t('home.thisMonth'), + }, +]; + +export const growCardFourList: GrowCardItem[] = [ + { + title: t('home.thisYearRetail'), + dataIndex: 'yearRetailSales', + icon: 'transaction|svg', + value: 0, + total: 0, + color: 'purple', + action: t('home.thisYear'), + }, + { + title: t('home.thisYearSales'), + dataIndex: 'yearSales', + icon: 'transaction|svg', + value: 0, + total: 0, + color: 'purple', + action: t('home.thisYear'), + }, + { + title: t('home.thisYearPurchase'), + dataIndex: 'yearPurchase', + icon: 'transaction|svg', + value: 0, + total: 0, + color: 'purple', + action: t('home.thisYear'), + }, +]; + +export interface XyAxisData { + xaxisData: string; + yaxisData: number; +} +// 定义图表数据类型 用于图表数据的展示 +export const retailAxisStatisticalData: XyAxisData[] = ref(); +export const saleAxisStatisticalData: XyAxisData[] = ref(); +export const purchaseAxisStatisticalData: XyAxisData[] = ref(); + diff --git a/src/views/dashboard/analysis/index.vue b/src/views/dashboard/analysis/index.vue new file mode 100644 index 0000000..8445596 --- /dev/null +++ b/src/views/dashboard/analysis/index.vue @@ -0,0 +1,81 @@ + + diff --git a/src/views/dashboard/workbench/components/DynamicInfo.vue b/src/views/dashboard/workbench/components/DynamicInfo.vue new file mode 100644 index 0000000..9947817 --- /dev/null +++ b/src/views/dashboard/workbench/components/DynamicInfo.vue @@ -0,0 +1,31 @@ + + diff --git a/src/views/dashboard/workbench/components/ProjectCard.vue b/src/views/dashboard/workbench/components/ProjectCard.vue new file mode 100644 index 0000000..c7260df --- /dev/null +++ b/src/views/dashboard/workbench/components/ProjectCard.vue @@ -0,0 +1,32 @@ + + diff --git a/src/views/dashboard/workbench/components/QuickNav.vue b/src/views/dashboard/workbench/components/QuickNav.vue new file mode 100644 index 0000000..a589601 --- /dev/null +++ b/src/views/dashboard/workbench/components/QuickNav.vue @@ -0,0 +1,15 @@ + + diff --git a/src/views/dashboard/workbench/components/SaleRadar.vue b/src/views/dashboard/workbench/components/SaleRadar.vue new file mode 100644 index 0000000..3d176f2 --- /dev/null +++ b/src/views/dashboard/workbench/components/SaleRadar.vue @@ -0,0 +1,94 @@ + + diff --git a/src/views/dashboard/workbench/components/WorkbenchHeader.vue b/src/views/dashboard/workbench/components/WorkbenchHeader.vue new file mode 100644 index 0000000..2e50647 --- /dev/null +++ b/src/views/dashboard/workbench/components/WorkbenchHeader.vue @@ -0,0 +1,33 @@ + + diff --git a/src/views/dashboard/workbench/components/data.ts b/src/views/dashboard/workbench/components/data.ts new file mode 100644 index 0000000..47da637 --- /dev/null +++ b/src/views/dashboard/workbench/components/data.ts @@ -0,0 +1,144 @@ +interface GroupItem { + title: string; + icon: string; + color: string; + desc: string; + date: string; + group: string; +} + +interface NavItem { + title: string; + icon: string; + color: string; +} + +interface DynamicInfoItem { + avatar: string; + name: string; + date: string; + desc: string; +} + +export const navItems: NavItem[] = [ + { + title: '首页', + icon: 'ion:home-outline', + color: '#1fdaca', + }, + { + title: '仪表盘', + icon: 'ion:grid-outline', + color: '#bf0c2c', + }, + { + title: 'OA内部办公系统', + icon: 'ion:layers-outline', + color: '#e18525', + }, + { + title: '系统管理', + icon: 'ion:settings-outline', + color: '#3fb27f', + }, + { + title: '权限管理', + icon: 'ion:key-outline', + color: '#4daf1bc9', + }, + { + title: '报表查询', + icon: 'ion:bar-chart-outline', + color: '#00d8ff', + }, +]; + +export const dynamicInfoItems: DynamicInfoItem[] = [ + { + avatar: 'dynamic-avatar-1|svg', + name: '小李', + date: '刚刚', + desc: `在
    A仓库 采购了100个零件 H3C`, + }, + { + avatar: 'dynamic-avatar-2|svg', + name: '艾文', + date: '1个小时前', + desc: `关注了 小李 `, + }, + { + avatar: 'dynamic-avatar-3|svg', + name: '克里斯', + date: '1天前', + desc: `发布了 本月采购物料表 `, + }, + { + avatar: 'dynamic-avatar-4|svg', + name: '赵伟', + date: '2天前', + desc: `发表文章 企业如何集成GPT微调模型配合ERP使用 `, + }, + { + avatar: 'dynamic-avatar-5|svg', + name: '皮特', + date: '3天前', + desc: `回复了 赵伟 的问题 如何让用户能直接微调模型?`, + }, + { + avatar: 'dynamic-avatar-6|svg', + name: '杰克', + date: '1周前', + desc: `添加了会员 检测公司的会员 `, + }, +]; + +export const groupItems: GroupItem[] = [ + { + title: 'WanSen ERP Core', + icon: 'carbon:logo-github', + color: '', + desc: 'ERP系统的API', + group: '万森智能开源组', + date: '2023-09-28', + }, + { + title: 'WanSen ERP', + icon: 'ion:logo-vue', + color: '#3fb27f', + desc: '该项目使用了Vue3+Vite+Ant-Design', + group: '前端开发小组', + date: '2023-09-28', + }, + { + title: 'Html 5', + icon: 'ion:logo-html5', + color: '#e18525', + desc: '该项目也使用了HTML5', + group: '前端开发小组', + date: '2023-10-01', + }, + { + title: 'Angular', + icon: 'ion:logo-angular', + color: '#bf0c2c', + desc: '设计新的页面交互', + group: 'UI组', + date: '2023-10-01', + }, + { + title: 'React', + icon: 'bx:bxl-react', + color: '#00d8ff', + desc: '下一步计划支持React重构', + group: '前端开发小组', + date: '2023-10-02', + }, + { + title: 'JavaScript', + icon: 'ion:logo-javascript', + color: '#EBD94E', + desc: '我们也可使用javascript进行重写', + group: '前端开发小组', + date: '2023-10-03', + }, +]; diff --git a/src/views/dashboard/workbench/index.vue b/src/views/dashboard/workbench/index.vue new file mode 100644 index 0000000..5ee292e --- /dev/null +++ b/src/views/dashboard/workbench/index.vue @@ -0,0 +1,36 @@ + + diff --git a/src/views/financial/advance-charge/advance.data.ts b/src/views/financial/advance-charge/advance.data.ts new file mode 100644 index 0000000..2692d7d --- /dev/null +++ b/src/views/financial/advance-charge/advance.data.ts @@ -0,0 +1,181 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {reactive, UnwrapRef} from 'vue'; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('financial.advance.table.paymentMember'), + dataIndex: 'memberName', + width: 120, + }, + { + title: t('financial.advance.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 150, + }, + { + title: t('financial.advance.table.receiptDate'), + dataIndex: 'receiptDate', + width: 150, + }, + { + title: t('financial.advance.table.amountCollected'), + dataIndex: 'collectedAmount', + width: 90, + }, + { + title: t('financial.advance.table.totalAmount'), + dataIndex: 'totalAmount', + width: 90, + }, + { + title: t('financial.advance.table.financialPerson'), + dataIndex: 'financialPersonnel', + width: 80, + }, + { + title: t('financial.advance.table.operator'), + dataIndex: 'operator', + width: 80, + }, + { + title: t('financial.advance.table.status'), + dataIndex: 'status', + width: 100, + }, + { + title: t('financial.advance.table.remark'), + dataIndex: 'remark', + width: 150, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('financial.advance.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('financial.advance.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('financial.advance.header.starDate'), t('financial.advance.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.advance.header.paymentMember'), + field: 'paymentMember', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.advance.header.status'), + field: 'type', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('financial.advance.header.remark'), + field: 'type', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const formSchema: FormSchema[] = [] + +export const tableColumns = [ + { + title: t('financial.advance.view.accountName'), + key: 'accountId', + width: '25%', + placeholder: '请选择${title}', + options: [], + allowSearch: true, + validateRules: [{required: true, message: '${title}不能为空'}], + }, + { + title: t('financial.advance.view.amount'), + key: 'amount', + width: '20%', + statistics: true, + placeholder: '请选择${title}', + validateRules: [{required: true, message: '${title}不能为空'}] + }, + { + title: t('financial.advance.view.remark'), + key: 'remark', + width: '50%', + placeholder: '请选择${title}' + } +] + +interface FormState { + id: string | undefined; + memberId: string; + receiptNumber: string; + financialPersonnelId: string; + receiptDate: string | undefined | Dayjs; + remark: string; + totalAmount: number; + collectedAmount: number; +} + +export const formState: UnwrapRef = reactive({ + id: '', + memberId: '', + receiptNumber: '', + financialPersonnelId: '', + receiptDate: undefined, + remark: '', + totalAmount: 0, + collectedAmount: 0, +}); + +export const advanceChargeTableColumns: BasicColumn[] = [ + { + title: t('financial.advance.view.accountName'), + dataIndex: 'accountName', + width: 200, + }, + { + title: t('financial.advance.view.amount'), + dataIndex: 'amount', + width: 180, + }, + { + title: t('financial.advance.view.remark'), + dataIndex: 'remark', + width: 200, + }, +] \ No newline at end of file diff --git a/src/views/financial/advance-charge/components/AdvanceChargeModal.vue b/src/views/financial/advance-charge/components/AdvanceChargeModal.vue new file mode 100644 index 0000000..4f0b724 --- /dev/null +++ b/src/views/financial/advance-charge/components/AdvanceChargeModal.vue @@ -0,0 +1,593 @@ + + + + + \ No newline at end of file diff --git a/src/views/financial/advance-charge/components/ViewAdvanceChargeModal.vue b/src/views/financial/advance-charge/components/ViewAdvanceChargeModal.vue new file mode 100644 index 0000000..7fe1d3b --- /dev/null +++ b/src/views/financial/advance-charge/components/ViewAdvanceChargeModal.vue @@ -0,0 +1,193 @@ + + + diff --git a/src/views/financial/advance-charge/index.vue b/src/views/financial/advance-charge/index.vue new file mode 100644 index 0000000..98c7d50 --- /dev/null +++ b/src/views/financial/advance-charge/index.vue @@ -0,0 +1,228 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/financial/collection/addEditCollection.data.ts b/src/views/financial/collection/addEditCollection.data.ts new file mode 100644 index 0000000..14eeef7 --- /dev/null +++ b/src/views/financial/collection/addEditCollection.data.ts @@ -0,0 +1,159 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; +import {useLocaleStore} from "@/store/modules/locale"; + +export const { t } = useI18n(); +const amountSymbol = ref('') +const localeStore = useLocaleStore().getLocale; +if(localeStore === 'zh_CN') { + amountSymbol.value = '¥' +} else if (localeStore === 'en') { + amountSymbol.value = '$' +} + +export interface RowVO { + [key: string]: any, + collectionId: number | string; + saleReceiptNumber: string | undefined, + receivableArrears: number, + receivedArrears: number |string, + thisCollectionAmount: number, + remark: string, +} + +interface CollectionFormState { + id: number | string | undefined; + customerId: number | string | undefined; + receiptDate: string | undefined | Dayjs; + receiptNumber: string |undefined; + financialPersonId: number | string |undefined; + collectionAccountId: number | string |undefined; + totalCollectionAmount: number | string; + discountAmount: number | string; + actualCollectionAmount: number | string; + remark: string; +} + +const xGrid = ref>() +const tableData = ref([]) +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + zoom: true, + custom: true + }, + columns: [ + { type: 'checkbox', field:'id', title: 'ID', width: 180}, + { field: 'saleReceiptNumber', + width:200, + title: t('financial.collection.view.saleReceiptNumber'), + }, + { field: 'receivableArrears', + width:180, + title: t('financial.collection.view.receivableArrears'), + }, + { field: 'receivedArrears', + width:180, + title: t('financial.collection.view.receivedArrears'), + }, + { field: 'thisCollectionAmount', + width:200, + title: t('financial.collection.view.thisTimeCollection'), + slots: { edit: 'amount_edit' }, + sortable: true, + editRender: { name: 'input', attrs: { placeholder: '请输入本次收款金额' } } + }, + { field: 'remark', title: t('financial.collection.view.remark'), editRender: { name: 'input', attrs: { placeholder: '请输入备注' } } }, + + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('financial.collection.form.total') + } + if (['thisCollectionAmount', 'rate'].includes(column.field)) { + collectionFormState.actualCollectionAmount = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + collectionFormState.totalCollectionAmount = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + getThisCollectionAmount.value = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + } +}) + +const getThisCollectionAmount = ref('0') + +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} +const collectionFormState = reactive({ + id: undefined, + customerId: '', + receiptDate: '', + receiptNumber: '', + financialPersonId: '', + collectionAccountId: '', + totalCollectionAmount: 0, + discountAmount: 0, + actualCollectionAmount: 0, + remark: '', +}); + +export { + xGrid, + sumNum, + tableData, + gridOptions, + collectionFormState, + getThisCollectionAmount +} \ No newline at end of file diff --git a/src/views/financial/collection/collection.data.ts b/src/views/financial/collection/collection.data.ts new file mode 100644 index 0000000..8aa1c61 --- /dev/null +++ b/src/views/financial/collection/collection.data.ts @@ -0,0 +1,269 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getAccountList} from "@/api/financial/account"; +import {getCustomerList} from "@/api/basic/customer"; +import {getOperatorList} from "@/api/basic/operator"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('financial.collection.table.customer'), + dataIndex: 'customerName', + width: 120, + }, + { + title: t('financial.collection.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('financial.collection.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('financial.collection.table.financialPerson'), + dataIndex: 'financialPerson', + width: 70, + }, + { + title: t('financial.collection.table.collectionAccount'), + dataIndex: 'collectionAccountName', + width: 100, + }, + { + title: t('financial.collection.table.totalCollection'), + dataIndex: 'totalCollectionAmount', + width: 70, + }, + { + title: t('financial.collection.table.discountAmount'), + dataIndex: 'discountAmount', + width: 70, + }, + { + title: t('financial.collection.table.actualCollection'), + dataIndex: 'actualCollectionAmount', + width: 70, + }, + { + title: t('financial.collection.table.remark'), + dataIndex: 'remark', + width: 150, + }, + { + title: t('financial.collection.table.status'), + dataIndex: 'status', + width: 70, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('financial.collection.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('financial.collection.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('financial.collection.header.starDate'), t('financial.collection.header.endDate')], + }, + colProps: { span: 7 }, + }, + { + label: t('financial.collection.header.collectionAccount'), + field: 'accountId', + component: 'ApiSelect', + componentProps: { + api: getAccountList, + resultField: 'data', + labelField: 'accountName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.collection.header.customer'), + field: 'customerId', + component: 'ApiSelect', + componentProps: { + api: getCustomerList, + resultField: 'data', + labelField: 'customerName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.collection.header.financialPerson'), + field: 'financialPersonId', + component: 'ApiSelect', + componentProps: { + api: getOperatorList, + params: '财务员', + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.collection.header.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('financial.collection.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const collectionReceiptTableColumns: BasicColumn[] = [ + { + title: t('financial.collection.view.saleReceiptNumber'), + dataIndex: 'saleReceiptNumber', + width: 180, + }, + { + title: t('financial.collection.view.receivableArrears'), + dataIndex: 'receivableArrears', + width: 80, + }, + { + title: t('financial.collection.view.receivedArrears'), + dataIndex: 'receivedArrears', + width: 80, + }, + { + title: t('financial.collection.view.thisTimeCollection'), + dataIndex: 'thisCollectionAmount', + width: 80, + }, + { + title: t('financial.collection.view.remark'), + dataIndex: 'remark', + width: 200, + }, +] + +export const searchSaleArrearsFormSchema: FormSchema[] = [ + { + label: t('financial.collection.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.collection.header.productInfo'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('financial.collection.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('financial.collection.header.starDate'), t('financial.collection.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, +] + +export const saleArrearsReceiptTableColumns: BasicColumn[] = [ + { + title: '销售单据id', + dataIndex: 'id', + ifShow: false, + width: 0, + }, + { + title: t('financial.collection.table.customer'), + dataIndex: 'customerName', + width: 90, + }, + { + title: t('financial.collection.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 200, + }, + { + title: t('financial.collection.table.receiptDate'), + dataIndex: 'receiptDate', + width: 150, + }, + { + title: t('financial.collection.header.productInfo'), + dataIndex: 'productInfo', + width: 150, + }, + { + title: t('financial.collection.view.thisReceiptArrears'), + dataIndex: 'thisReceiptArrears', + width: 80, + }, + { + title: t('financial.collection.view.receivedArrears'), + dataIndex: 'receivedArrears', + width: 80, + }, + { + title: t('financial.collection.view.receivableArrears'), + dataIndex: 'receivableArrears', + width: 80, + }, + { + title: t('financial.collection.view.operator'), + dataIndex: 'operatorName', + width: 80, + }, + { + title: t('financial.collection.view.remark'), + dataIndex: 'remark', + width: 140, + }, +] \ No newline at end of file diff --git a/src/views/financial/collection/components/AddEditCollectionModal.vue b/src/views/financial/collection/components/AddEditCollectionModal.vue new file mode 100644 index 0000000..d48a969 --- /dev/null +++ b/src/views/financial/collection/components/AddEditCollectionModal.vue @@ -0,0 +1,635 @@ + + + + + \ No newline at end of file diff --git a/src/views/financial/collection/components/SaleArrearsModal.vue b/src/views/financial/collection/components/SaleArrearsModal.vue new file mode 100644 index 0000000..d6a0ee0 --- /dev/null +++ b/src/views/financial/collection/components/SaleArrearsModal.vue @@ -0,0 +1,98 @@ + + + \ No newline at end of file diff --git a/src/views/financial/collection/components/ViewCollectionModal.vue b/src/views/financial/collection/components/ViewCollectionModal.vue new file mode 100644 index 0000000..58dea06 --- /dev/null +++ b/src/views/financial/collection/components/ViewCollectionModal.vue @@ -0,0 +1,205 @@ + + + diff --git a/src/views/financial/collection/index.vue b/src/views/financial/collection/index.vue new file mode 100644 index 0000000..2304f04 --- /dev/null +++ b/src/views/financial/collection/index.vue @@ -0,0 +1,244 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/financial/expense/addEditExpense.data.ts b/src/views/financial/expense/addEditExpense.data.ts new file mode 100644 index 0000000..9cd3528 --- /dev/null +++ b/src/views/financial/expense/addEditExpense.data.ts @@ -0,0 +1,152 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; +import {useLocaleStore} from "@/store/modules/locale"; + +export const { t } = useI18n(); +const amountSymbol = ref('') +const localeStore = useLocaleStore().getLocale; +if(localeStore === 'zh_CN') { + amountSymbol.value = '¥' +} else if (localeStore === 'en') { + amountSymbol.value = '$' +} + +export interface RowVO { + [key: string]: any, + incomeExpenseId: number | string, + incomeExpenseAmount: number, + remark: string, +} + +interface ExpenseFormState { + id: number | string | undefined; + relatedPersonId: number | string | undefined; + receiptDate: string | undefined | Dayjs; + receiptNumber: string |undefined; + financialPersonId: number | string |undefined; + expenseAccountId: number | string |undefined; + incomeExpenseAmount: number | string; + expenseAmount: number | string; + remark: string; +} + +const xGrid = ref>() +const tableData = ref([]) +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + zoom: true, // 显示全屏按钮 + custom: true // 显示自定义列按钮 + }, + columns: [ + { type: 'checkbox', field:'id', title: 'ID', width: 180}, + { field: 'incomeExpenseId', + width:200, + title: t('financial.expense.view.expenseName'), + slots: { edit: 'id_edit',default: 'id_default' }, + sortable: true, + editRender: {} + }, + { field: 'incomeExpenseAmount', + width:200, + title: t('financial.expense.view.amount'), + slots: { edit: 'amount_edit' }, + sortable: true, + editRender: { name: 'input', attrs: { placeholder: '请输入金额' } } + }, + { field: 'remark', title: t('financial.expense.view.remark'), editRender: { name: 'input', attrs: { placeholder: '请输入备注' } } }, + + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('financial.expense.form.total') + } + if (['incomeExpenseAmount', 'rate'].includes(column.field)) { + expenseFormState.expenseAmount = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editRules: { + incomeExpenseId: [ + { required: true, message: t('financial.expense.form.noticeOne') } + ], + incomeExpenseAmount: [ + { required: true, message: t('financial.expense.form.noticeTwo') } + ] + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + } +}) + +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} +const expenseFormState = reactive({ + id: undefined, + relatedPersonId: '', + receiptDate: '', + receiptNumber: '', + financialPersonId: '', + expenseAccountId: 0, + incomeExpenseAmount: 0, + expenseAmount: 0, + remark: '', +}); + +export { + xGrid, + sumNum, + tableData, + gridOptions, + expenseFormState, +} \ No newline at end of file diff --git a/src/views/financial/expense/components/AddEditExpenseModal.vue b/src/views/financial/expense/components/AddEditExpenseModal.vue new file mode 100644 index 0000000..6d64772 --- /dev/null +++ b/src/views/financial/expense/components/AddEditExpenseModal.vue @@ -0,0 +1,585 @@ + + + + + \ No newline at end of file diff --git a/src/views/financial/expense/components/ViewExpenseModal.vue b/src/views/financial/expense/components/ViewExpenseModal.vue new file mode 100644 index 0000000..253b169 --- /dev/null +++ b/src/views/financial/expense/components/ViewExpenseModal.vue @@ -0,0 +1,193 @@ + + + diff --git a/src/views/financial/expense/expense.data.ts b/src/views/financial/expense/expense.data.ts new file mode 100644 index 0000000..4230177 --- /dev/null +++ b/src/views/financial/expense/expense.data.ts @@ -0,0 +1,162 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getAccountList} from "@/api/financial/account"; +import {getRelatedPerson} from "@/api/report/report"; +import {getOperatorList} from "@/api/basic/operator"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('financial.expense.table.name'), + dataIndex: 'name', + width: 120, + }, + { + title: t('financial.expense.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('financial.expense.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('financial.expense.table.financialPerson'), + dataIndex: 'financialPerson', + width: 70, + }, + { + title: t('financial.expense.table.expenseAccount'), + dataIndex: 'expenseAccountName', + width: 70, + }, + { + title: t('financial.expense.table.expenseAmount'), + dataIndex: 'expenseAmount', + width: 70, + }, + { + title: t('financial.expense.table.remark'), + dataIndex: 'remark', + width: 150, + }, + { + title: t('financial.expense.table.status'), + dataIndex: 'status', + width: 70, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('financial.expense.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('financial.expense.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('financial.expense.header.starDate'), t('financial.expense.header.endDate')], + }, + colProps: { span: 7 }, + }, + { + label: t('financial.expense.header.expenseAccount'), + field: 'accountId', + component: 'ApiSelect', + componentProps: { + api: getAccountList, + resultField: 'data', + labelField: 'accountName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.expense.header.correspondenceUnit'), + field: 'relatedPersonId', + component: 'ApiSelect', + componentProps: { + api: getRelatedPerson, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.expense.header.financialPerson'), + field: 'financialPersonId', + component: 'ApiSelect', + componentProps: { + api: getOperatorList, + params: '财务员', + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.expense.header.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('financial.expense.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] + +export const expenseReceiptTableColumns: BasicColumn[] = [ + { + title: t('financial.expense.view.expenseName'), + dataIndex: 'incomeExpenseName', + width: 200, + }, + { + title: t('financial.expense.view.amount'), + dataIndex: 'incomeExpenseAmount', + width: 180, + }, + { + title: t('financial.expense.view.remark'), + dataIndex: 'remark', + width: 200, + }, +] \ No newline at end of file diff --git a/src/views/financial/expense/index.vue b/src/views/financial/expense/index.vue new file mode 100644 index 0000000..868d013 --- /dev/null +++ b/src/views/financial/expense/index.vue @@ -0,0 +1,243 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/financial/income/addEditIncome.data.ts b/src/views/financial/income/addEditIncome.data.ts new file mode 100644 index 0000000..4a77554 --- /dev/null +++ b/src/views/financial/income/addEditIncome.data.ts @@ -0,0 +1,153 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; +import {useLocaleStore} from "@/store/modules/locale"; + +const amountSymbol = ref('') +const localeStore = useLocaleStore().getLocale; +if(localeStore === 'zh_CN') { + amountSymbol.value = '¥' +} else if (localeStore === 'en') { + amountSymbol.value = '$' +} + +export const { t } = useI18n(); + +export interface RowVO { + [key: string]: any, + incomeExpenseId: number | string, + incomeExpenseAmount: number, + remark: string, +} + +interface IncomeFormState { + id: number | string | undefined; + relatedPersonId: number | string | undefined; + receiptDate: string | undefined | Dayjs; + receiptNumber: string |undefined; + financialPersonId: number | string |undefined; + incomeAccountId: number | string |undefined; + incomeExpenseAmount: number | string; + incomeAmount: number | string; + remark: string; +} + +const xGrid = ref>() +const tableData = ref([]) +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + zoom: true, // 显示全屏按钮 + custom: true // 显示自定义列按钮 + }, + columns: [ + { type: 'checkbox', field:'id', title: 'ID', width: 180}, + { field: 'incomeExpenseId', + width:200, + title: t('financial.income.view.incomeExpenseName'), + slots: { edit: 'id_edit',default: 'id_default' }, + sortable: true, + editRender: {} + }, + { field: 'incomeExpenseAmount', + width:200, + title: t('financial.income.view.amount'), + slots: { edit: 'amount_edit' }, + sortable: true, + editRender: { name: 'input', attrs: { placeholder: '请输入金额' } } + }, + { field: 'remark', title: t('financial.income.view.remark'), editRender: { name: 'input', attrs: { placeholder: '请输入备注' } } }, + + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('financial.income.view.total') + } + if (['incomeExpenseAmount', 'rate'].includes(column.field)) { + incomeFormState.incomeAmount = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + editRules: { + incomeExpenseId: [ + { required: true, message: t('financial.income.form.noticeOne') } + ], + incomeExpenseAmount: [ + { required: true, message: t('financial.income.form.noticeTwo') } + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + } +}) + +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} +const incomeFormState = reactive({ + id: undefined, + relatedPersonId: '', + receiptDate: '', + receiptNumber: '', + financialPersonId: '', + incomeAccountId: 0, + incomeExpenseAmount: 0, + incomeAmount: 0, + remark: '', +}); + +export { + xGrid, + sumNum, + tableData, + gridOptions, + incomeFormState, +} \ No newline at end of file diff --git a/src/views/financial/income/components/AddEditIncomeModal.vue b/src/views/financial/income/components/AddEditIncomeModal.vue new file mode 100644 index 0000000..1bb7c1f --- /dev/null +++ b/src/views/financial/income/components/AddEditIncomeModal.vue @@ -0,0 +1,592 @@ + + + + + \ No newline at end of file diff --git a/src/views/financial/income/components/ViewIncomeModal.vue b/src/views/financial/income/components/ViewIncomeModal.vue new file mode 100644 index 0000000..54bed40 --- /dev/null +++ b/src/views/financial/income/components/ViewIncomeModal.vue @@ -0,0 +1,193 @@ + + + diff --git a/src/views/financial/income/income.data.ts b/src/views/financial/income/income.data.ts new file mode 100644 index 0000000..47495a3 --- /dev/null +++ b/src/views/financial/income/income.data.ts @@ -0,0 +1,162 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getAccountList} from "@/api/financial/account"; +import {getRelatedPerson} from "@/api/report/report"; +import {getOperatorList} from "@/api/basic/operator"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('financial.income.table.name'), + dataIndex: 'name', + width: 120, + }, + { + title: t('financial.income.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('financial.income.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('financial.income.table.financialPerson'), + dataIndex: 'financialPerson', + width: 70, + }, + { + title: t('financial.income.table.incomeAccount'), + dataIndex: 'incomeAccountName', + width: 70, + }, + { + title: t('financial.income.table.incomeAmount'), + dataIndex: 'incomeAmount', + width: 70, + }, + { + title: t('financial.income.table.remark'), + dataIndex: 'remark', + width: 150, + }, + { + title: t('financial.income.table.status'), + dataIndex: 'status', + width: 70, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('financial.income.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('financial.income.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('financial.income.header.starDate'), t('financial.income.header.endDate')], + }, + colProps: { span: 7 }, + }, + { + label: t('financial.income.header.incomeAccount'), + field: 'accountId', + component: 'ApiSelect', + componentProps: { + api: getAccountList, + resultField: 'data', + labelField: 'accountName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.income.header.correspondenceUnit'), + field: 'relatedPersonId', + component: 'ApiSelect', + componentProps: { + api: getRelatedPerson, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.income.header.financialPerson'), + field: 'financialPersonId', + component: 'ApiSelect', + componentProps: { + api: getOperatorList, + params: '财务员', + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.income.header.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('financial.income.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] + +export const incomeReceiptTableColumns: BasicColumn[] = [ + { + title: t('financial.income.view.incomeExpenseName'), + dataIndex: 'incomeExpenseName', + width: 200, + }, + { + title: t('financial.income.view.amount'), + dataIndex: 'incomeExpenseAmount', + width: 180, + }, + { + title: t('financial.income.view.remark'), + dataIndex: 'remark', + width: 200, + }, +] \ No newline at end of file diff --git a/src/views/financial/income/index.vue b/src/views/financial/income/index.vue new file mode 100644 index 0000000..13dd514 --- /dev/null +++ b/src/views/financial/income/index.vue @@ -0,0 +1,242 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/financial/payment/addEditPayment.data.ts b/src/views/financial/payment/addEditPayment.data.ts new file mode 100644 index 0000000..fcb75e5 --- /dev/null +++ b/src/views/financial/payment/addEditPayment.data.ts @@ -0,0 +1,159 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; +import {useLocaleStore} from "@/store/modules/locale"; + +export const { t } = useI18n(); +const amountSymbol = ref('') +const localeStore = useLocaleStore().getLocale; +if(localeStore === 'zh_CN') { + amountSymbol.value = '¥' +} else if (localeStore === 'en') { + amountSymbol.value = '$' +} + +export interface RowVO { + [key: string]: any, + paymentId: number | string; + purchaseReceiptNumber: string | undefined, + paymentArrears: number, + prepaidArrears: number |string, + thisPaymentAmount: number, + remark: string, +} + +interface PaymentFormState { + id: number | string | undefined; + supplierId: number | string | undefined; + receiptDate: string | undefined | Dayjs; + receiptNumber: string |undefined; + financialPersonId: number | string |undefined; + paymentAccountId: number | string |undefined; + totalPaymentAmount: number | string; + discountAmount: number | string; + actualPaymentAmount: number | string; + remark: string; +} + +const xGrid = ref>() +const tableData = ref([]) +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + zoom: true, + custom: true + }, + columns: [ + { type: 'checkbox', field:'id', title: 'ID', width: 180}, + { field: 'purchaseReceiptNumber', + width:200, + title: t('financial.payment.view.purchaseReceiptNumber'), + }, + { field: 'paymentArrears', + width:180, + title: t('financial.payment.view.payableArrears'), + }, + { field: 'prepaidArrears', + width:180, + title: t('financial.payment.view.paidArrears'), + }, + { field: 'thisPaymentAmount', + width:200, + title: t('financial.payment.view.thisTimePayment'), + slots: { edit: 'amount_edit' }, + sortable: true, + editRender: { name: 'input', attrs: { placeholder: '请输入本次收款金额' } } + }, + { field: 'remark', title: t('financial.payment.view.remark'), editRender: { name: 'input', attrs: { placeholder: '请输入备注' } } }, + + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('financial.payment.form.total') + } + if (['thisPaymentAmount', 'rate'].includes(column.field)) { + paymentFormState.actualPaymentAmount = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + paymentFormState.totalPaymentAmount = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + getThisPaymentAmount.value = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + } +}) + +const getThisPaymentAmount = ref('0') + +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} +const paymentFormState = reactive({ + id: undefined, + supplierId: '', + receiptDate: '', + receiptNumber: '', + financialPersonId: '', + paymentAccountId: '', + totalPaymentAmount: 0, + discountAmount: 0, + actualPaymentAmount: 0, + remark: '', +}); + +export { + xGrid, + sumNum, + tableData, + gridOptions, + paymentFormState, + getThisPaymentAmount +} \ No newline at end of file diff --git a/src/views/financial/payment/components/AddEditPaymentModal.vue b/src/views/financial/payment/components/AddEditPaymentModal.vue new file mode 100644 index 0000000..598643e --- /dev/null +++ b/src/views/financial/payment/components/AddEditPaymentModal.vue @@ -0,0 +1,633 @@ + + + + + \ No newline at end of file diff --git a/src/views/financial/payment/components/PurchaseArrearsModal.vue b/src/views/financial/payment/components/PurchaseArrearsModal.vue new file mode 100644 index 0000000..86d3cb9 --- /dev/null +++ b/src/views/financial/payment/components/PurchaseArrearsModal.vue @@ -0,0 +1,98 @@ + + + \ No newline at end of file diff --git a/src/views/financial/payment/components/ViewPaymentModal.vue b/src/views/financial/payment/components/ViewPaymentModal.vue new file mode 100644 index 0000000..8f6c99f --- /dev/null +++ b/src/views/financial/payment/components/ViewPaymentModal.vue @@ -0,0 +1,205 @@ + + + diff --git a/src/views/financial/payment/index.vue b/src/views/financial/payment/index.vue new file mode 100644 index 0000000..c19455d --- /dev/null +++ b/src/views/financial/payment/index.vue @@ -0,0 +1,242 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/financial/payment/payment.data.ts b/src/views/financial/payment/payment.data.ts new file mode 100644 index 0000000..f45f3de --- /dev/null +++ b/src/views/financial/payment/payment.data.ts @@ -0,0 +1,269 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getAccountList} from "@/api/financial/account"; +import {getSupplierList} from "@/api/basic/supplier"; +import {getOperatorList} from "@/api/basic/operator"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('financial.payment.table.supplier'), + dataIndex: 'supplierName', + width: 120, + }, + { + title: t('financial.payment.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('financial.payment.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('financial.payment.table.financialPerson'), + dataIndex: 'financialPerson', + width: 70, + }, + { + title: t('financial.payment.table.paymentAccount'), + dataIndex: 'paymentAccountName', + width: 100, + }, + { + title: t('financial.payment.table.totalPayment'), + dataIndex: 'totalPaymentAmount', + width: 70, + }, + { + title: t('financial.payment.table.discountAmount'), + dataIndex: 'discountAmount', + width: 70, + }, + { + title: t('financial.payment.table.actualPayment'), + dataIndex: 'actualPaymentAmount', + width: 70, + }, + { + title: t('financial.payment.table.remark'), + dataIndex: 'remark', + width: 150, + }, + { + title: t('financial.payment.table.status'), + dataIndex: 'status', + width: 70, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('financial.payment.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('financial.payment.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('financial.payment.header.starDate'), t('financial.payment.header.endDate')], + }, + colProps: { span: 7 }, + }, + { + label: t('financial.payment.header.paymentAccount'), + field: 'accountId', + component: 'ApiSelect', + componentProps: { + api: getAccountList, + resultField: 'data', + labelField: 'accountName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.payment.header.supplier'), + field: 'supplierId', + component: 'ApiSelect', + componentProps: { + api: getSupplierList, + resultField: 'data', + labelField: 'supplierName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.payment.header.financialPerson'), + field: 'financialPersonId', + component: 'ApiSelect', + componentProps: { + api: getOperatorList, + params: '财务员', + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.payment.header.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('financial.payment.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const paymentReceiptTableColumns: BasicColumn[] = [ + { + title: t('financial.payment.view.purchaseReceiptNumber'), + dataIndex: 'purchaseReceiptNumber', + width: 180, + }, + { + title: t('financial.payment.view.payableArrears'), + dataIndex: 'paymentArrears', + width: 80, + }, + { + title: t('financial.payment.view.paidArrears'), + dataIndex: 'prepaidArrears', + width: 80, + }, + { + title: t('financial.payment.view.thisTimePayment'), + dataIndex: 'thisPaymentAmount', + width: 80, + }, + { + title: t('financial.payment.view.remark'), + dataIndex: 'remark', + width: 200, + }, +] + +export const searchPurchaseArrearsFormSchema: FormSchema[] = [ + { + label: t('financial.payment.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.payment.header.productInfo'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('financial.payment.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('financial.payment.header.starDate'), t('financial.payment.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, +] + +export const purchaseArrearsReceiptTableColumns: BasicColumn[] = [ + { + title: '销售单据id', + dataIndex: 'id', + ifShow: false, + width: 0, + }, + { + title: t('financial.payment.table.supplier'), + dataIndex: 'supplierName', + width: 130, + }, + { + title: t('financial.payment.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 200, + }, + { + title: t('financial.payment.table.receiptDate'), + dataIndex: 'receiptDate', + width: 140, + }, + { + title: t('financial.payment.header.productInfo'), + dataIndex: 'productInfo', + width: 150, + }, + { + title: t('financial.payment.view.thisReceiptArrears'), + dataIndex: 'thisReceiptArrears', + width: 75, + }, + { + title: t('financial.payment.view.paidArrears'), + dataIndex: 'prepaidArrears', + width: 75, + }, + { + title: t('financial.payment.view.payableArrears'), + dataIndex: 'paymentArrears', + width: 75, + }, + { + title: t('financial.payment.view.operator'), + dataIndex: 'operatorName', + width: 75, + }, + { + title: t('financial.payment.view.remark'), + dataIndex: 'remark', + width: 140, + }, +] \ No newline at end of file diff --git a/src/views/financial/transfer/addEditTransfer.data.ts b/src/views/financial/transfer/addEditTransfer.data.ts new file mode 100644 index 0000000..e906076 --- /dev/null +++ b/src/views/financial/transfer/addEditTransfer.data.ts @@ -0,0 +1,150 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; +import {useLocaleStore} from "@/store/modules/locale"; + +export const { t } = useI18n(); +const amountSymbol = ref('') +const localeStore = useLocaleStore().getLocale; +if(localeStore === 'zh_CN') { + amountSymbol.value = '¥' +} else if (localeStore === 'en') { + amountSymbol.value = '$' +} + +export interface RowVO { + [key: string]: any, + accountId: number | string, + transferAmount: number, + remark: string, +} + +interface TransferFormState { + id: number | string | undefined; + receiptDate: string | undefined | Dayjs; + receiptNumber: string |undefined; + financialPersonId: number | string |undefined; + paymentAccountId: number | string |undefined; + accountId: number | string |undefined; + paymentAmount: number | string; + remark: string; +} + +const xGrid = ref>() +const tableData = ref([]) +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + zoom: true, // 显示全屏按钮 + custom: true // 显示自定义列按钮 + }, + columns: [ + { type: 'checkbox', field:'id', title: 'ID', width: 180}, + { field: 'accountId', + width:200, + title: t('financial.transfer.view.accountName'), + slots: { edit: 'id_edit',default: 'id_default' }, + sortable: true, + editRender: {} + }, + { field: 'transferAmount', + width:200, + title: t('financial.transfer.view.amount'), + slots: { edit: 'amount_edit' }, + sortable: true, + editRender: { name: 'input', attrs: { placeholder: '请输入金额' } } + }, + { field: 'remark', title: t('financial.transfer.view.remark'), editRender: { name: 'input', attrs: { placeholder: '请输入备注' } } }, + + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('financial.transfer.form.total') + } + if (['transferAmount'].includes(column.field)) { + transferFormState.paymentAmount = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editRules: { + accountId: [ + { required: true, message: t('financial.transfer.form.noticeOne') } + ], + transferAmount: [ + { required: true, message: t('financial.transfer.form.noticeTwo') } + ] + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + } +}) + +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} +const transferFormState = reactive({ + id: undefined, + receiptDate: '', + receiptNumber: '', + financialPersonId: '', + paymentAccountId: '', + accountId: 0, + paymentAmount: 0, + remark: '', +}); + +export { + xGrid, + sumNum, + tableData, + gridOptions, + transferFormState, +} \ No newline at end of file diff --git a/src/views/financial/transfer/components/AddEditTransferModal.vue b/src/views/financial/transfer/components/AddEditTransferModal.vue new file mode 100644 index 0000000..f5700b8 --- /dev/null +++ b/src/views/financial/transfer/components/AddEditTransferModal.vue @@ -0,0 +1,546 @@ + + + + + \ No newline at end of file diff --git a/src/views/financial/transfer/components/ViewTransferModal.vue b/src/views/financial/transfer/components/ViewTransferModal.vue new file mode 100644 index 0000000..4e36304 --- /dev/null +++ b/src/views/financial/transfer/components/ViewTransferModal.vue @@ -0,0 +1,189 @@ + + + diff --git a/src/views/financial/transfer/index.vue b/src/views/financial/transfer/index.vue new file mode 100644 index 0000000..ac55a75 --- /dev/null +++ b/src/views/financial/transfer/index.vue @@ -0,0 +1,242 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/financial/transfer/transfer.data.ts b/src/views/financial/transfer/transfer.data.ts new file mode 100644 index 0000000..8322390 --- /dev/null +++ b/src/views/financial/transfer/transfer.data.ts @@ -0,0 +1,144 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getAccountList} from "@/api/financial/account"; +import {getOperatorList} from "@/api/basic/operator"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('financial.transfer.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('financial.transfer.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('financial.transfer.table.financialPerson'), + dataIndex: 'financialPerson', + width: 60, + }, + { + title: t('financial.transfer.table.paymentAccount'), + dataIndex: 'paymentAccountName', + width: 130, + }, + { + title: t('financial.transfer.table.paymentAmount'), + dataIndex: 'paymentAmount', + width: 60, + }, + { + title: t('financial.transfer.table.remark'), + dataIndex: 'remark', + width: 200, + }, + { + title: t('financial.transfer.table.status'), + dataIndex: 'status', + width: 60, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('financial.transfer.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('financial.transfer.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('financial.transfer.header.starDate'), t('financial.transfer.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.transfer.header.paymentAccount'), + field: 'accountId', + component: 'ApiSelect', + componentProps: { + api: getAccountList, + resultField: 'data', + labelField: 'accountName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.transfer.header.financialPerson'), + field: 'financialPersonId', + component: 'ApiSelect', + componentProps: { + api: getOperatorList, + params: '财务员', + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('financial.transfer.header.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('financial.transfer.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] + +export const transferReceiptTableColumns: BasicColumn[] = [ + { + title: t('financial.transfer.view.accountName'), + dataIndex: 'accountName', + width: 150, + }, + { + title: t('financial.transfer.view.amount'), + dataIndex: 'transferAmount', + width: 100, + }, + { + title: t('financial.transfer.view.remark'), + dataIndex: 'remark', + width: 200, + }, +] \ No newline at end of file diff --git a/src/views/product/attributes/attributes.data.ts b/src/views/product/attributes/attributes.data.ts new file mode 100644 index 0000000..04e6453 --- /dev/null +++ b/src/views/product/attributes/attributes.data.ts @@ -0,0 +1,74 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('product.attribute.table.attributeName'), + dataIndex: 'attributeName', + width: 100, + }, + { + title: t('product.attribute.table.attributeValue'), + dataIndex: 'attributeValue', + width: 150, + }, + { + title: t('product.attribute.table.sort'), + dataIndex: 'sort', + width: 80, + }, + { + title: t('product.attribute.table.remark'), + dataIndex: 'remark', + width: 150, + }, + { + title: t('product.attribute.table.createTime'), + dataIndex: 'createTime', + width: 150, + } +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('product.attribute.table.attributeName'), + field: 'attributeName', + component: 'Input', + colProps: { span: 8 }, + }, +] + +export const formSchema: FormSchema[] = [ + { + label: '属性id', + field: 'id', + show: false, + component: 'Input', + }, + { + label: t('product.attribute.table.attributeName'), + field: 'attributeName', + component: 'Input', + required: true, + }, + { + label: t('product.attribute.table.attributeValue'), + helpMessage: '多个属性值用|隔开', + field: 'attributeValue', + component: 'InputTextArea', + required: true, + }, + { + label: t('product.attribute.table.sort'), + field: 'sort', + component: 'InputNumber', + }, + { + label: t('product.attribute.table.remark'), + field: 'remark', + component: 'InputTextArea', + } +] \ No newline at end of file diff --git a/src/views/product/attributes/components/AttributeModal.vue b/src/views/product/attributes/components/AttributeModal.vue new file mode 100644 index 0000000..53a43bf --- /dev/null +++ b/src/views/product/attributes/components/AttributeModal.vue @@ -0,0 +1,76 @@ + + \ No newline at end of file diff --git a/src/views/product/attributes/index.vue b/src/views/product/attributes/index.vue new file mode 100644 index 0000000..1eb226a --- /dev/null +++ b/src/views/product/attributes/index.vue @@ -0,0 +1,114 @@ + + \ No newline at end of file diff --git a/src/views/product/category/category.data.ts b/src/views/product/category/category.data.ts new file mode 100644 index 0000000..93ec64b --- /dev/null +++ b/src/views/product/category/category.data.ts @@ -0,0 +1,74 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getCategoryList} from "@/api/product/productCategory"; +import {useI18n} from "@/hooks/web/useI18n"; +export const { t } = useI18n(); +export const columns: BasicColumn[] = [ + { + title: t('product.category.table.categoryName'), + dataIndex: 'categoryName', + width: 150, + align: 'left', + }, + { + title: t('product.category.table.categoryNumber'), + dataIndex: 'categoryNumber', + }, + { + title: t('product.category.table.categoryParent'), + dataIndex: 'parentName', + }, + { + title: t('product.category.table.sort'), + dataIndex: 'sort', + }, + { + title: t('product.category.table.remark'), + dataIndex: 'remark', + }, + { + title: t('product.category.table.createTime'), + dataIndex: 'createTime', + } +] +export const CategorySchema: FormSchema[] = [ + { + field: 'id', + label: '分类id', + component: 'Input', + show: false, + }, + { + field: 'categoryName', + label: t('product.category.table.categoryName'), + component: 'Input', + required: true, + }, + { + label: t('product.category.table.categoryNumber'), + field: 'categoryNumber', + component: 'Input', + required: true, + }, + { + field: 'parentId', + label: t('product.category.table.categoryParent'), + component: 'ApiTreeSelect', + componentProps: { + api: getCategoryList, + resultField: 'data', + labelField: 'categoryName', + valueField: 'id', + }, + }, + { + label: t('product.category.table.sort'), + field: 'sort', + component: 'InputNumber', + }, + { + label: t('product.category.table.remark'), + field: 'remark', + component: 'InputTextArea', + }, +] \ No newline at end of file diff --git a/src/views/product/category/components/CategoryModal.vue b/src/views/product/category/components/CategoryModal.vue new file mode 100644 index 0000000..5bc354a --- /dev/null +++ b/src/views/product/category/components/CategoryModal.vue @@ -0,0 +1,77 @@ + + + + + \ No newline at end of file diff --git a/src/views/product/category/index.vue b/src/views/product/category/index.vue new file mode 100644 index 0000000..2770a5c --- /dev/null +++ b/src/views/product/category/index.vue @@ -0,0 +1,139 @@ + + + \ No newline at end of file diff --git a/src/views/product/info/components/BatchEditModal.vue b/src/views/product/info/components/BatchEditModal.vue new file mode 100644 index 0000000..7e3df50 --- /dev/null +++ b/src/views/product/info/components/BatchEditModal.vue @@ -0,0 +1,209 @@ + + + \ No newline at end of file diff --git a/src/views/product/info/components/BatchSetPriceModal.vue b/src/views/product/info/components/BatchSetPriceModal.vue new file mode 100644 index 0000000..e86589f --- /dev/null +++ b/src/views/product/info/components/BatchSetPriceModal.vue @@ -0,0 +1,124 @@ + + + + + \ No newline at end of file diff --git a/src/views/product/info/components/BatchSetStockModal.vue b/src/views/product/info/components/BatchSetStockModal.vue new file mode 100644 index 0000000..b4ee7ce --- /dev/null +++ b/src/views/product/info/components/BatchSetStockModal.vue @@ -0,0 +1,110 @@ + + + + + \ No newline at end of file diff --git a/src/views/product/info/components/ProductInfoModal.vue b/src/views/product/info/components/ProductInfoModal.vue new file mode 100644 index 0000000..80fae44 --- /dev/null +++ b/src/views/product/info/components/ProductInfoModal.vue @@ -0,0 +1,1311 @@ + + + + + \ No newline at end of file diff --git a/src/views/product/info/components/SelectProductModal.vue b/src/views/product/info/components/SelectProductModal.vue new file mode 100644 index 0000000..f7fed9b --- /dev/null +++ b/src/views/product/info/components/SelectProductModal.vue @@ -0,0 +1,66 @@ + + + \ No newline at end of file diff --git a/src/views/product/info/index.vue b/src/views/product/info/index.vue new file mode 100644 index 0000000..75e3c65 --- /dev/null +++ b/src/views/product/info/index.vue @@ -0,0 +1,212 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/product/info/info.data.ts b/src/views/product/info/info.data.ts new file mode 100644 index 0000000..c5c738e --- /dev/null +++ b/src/views/product/info/info.data.ts @@ -0,0 +1,379 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {h, reactive, ref} from 'vue'; +import {Switch} from "ant-design-vue"; +import {useMessage} from "@/hooks/web/useMessage"; +import {useI18n} from "@/hooks/web/useI18n"; +import {updateProductStatus} from "@/api/product/product"; +import {getCategoryList} from "@/api/product/productCategory"; +import {MeTable, ProductInfo} from "@/views/product/info/model/productInfoModel"; +import {getWarehouseList} from "@/api/basic/warehouse"; + +const { t } = useI18n(); + +const columns: BasicColumn[] = [ + { + title: t('product.info.table.barCode'), + dataIndex: 'productBarcode', + width: 110, + }, + { + title: t('product.info.table.productName'), + dataIndex: 'productName', + width: 250, + }, + { + title: t('product.info.table.productStandard'), + dataIndex: 'productStandard', + width: 100, + }, + { + title: t('product.info.table.productModel'), + dataIndex: 'productModel', + width: 80, + }, + { + title: t('product.info.table.productColor'), + dataIndex: 'productColor', + width: 60, + }, + { + title: t('product.info.table.productCategory'), + dataIndex: 'productCategoryName', + width: 70, + }, + { + title: t('product.info.table.productUnit'), + dataIndex: 'productUnit', + width: 80, + }, + { + title: t('product.info.table.productStock'), + dataIndex: 'productStock', + width: 60, + }, + { + title: t('product.info.table.purchasePrice'), + dataIndex: 'purchasePrice', + width: 60, + }, + { + title: t('product.info.table.retailPrice'), + dataIndex: 'retailPrice', + width: 60, + }, + { + title: t('product.info.table.salesPrice'), + dataIndex: 'salePrice', + width: 60, + }, + { + title: t('product.info.table.lowestSellPrice'), + dataIndex: 'lowPrice', + width: 90, + }, + { + title: t('product.info.table.status'), + dataIndex: 'status', + width: 80, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked, _) { + const {createMessage} = useMessage(); + if (record.id == 1) { + createMessage.warn(t('common.notice')); + return; + } + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + updateProductStatus([record.id], newStatus ) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + { + title: t('product.info.table.createTime'), + dataIndex: 'createTime', + width: 130, + } +] + + +const extendPriceColumn: BasicColumn[] = [ + { + title: t('product.info.table.barCode'), + dataIndex: 'barCode', + width: 80, + }, + { + title: t('product.info.table.productName'), + dataIndex: 'productName', + width: 100, + }, + { + title: t('product.info.table.productCategory'), + dataIndex: 'productCategoryName', + width: 100, + }, + { + title: t('product.info.header.warehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('product.info.table.productStandard'), + dataIndex: 'productStandard', + width: 80, + }, + { + title: t('product.info.table.productModel'), + dataIndex: 'productModel', + width: 100, + }, + { + title: t('product.info.table.productColor'), + dataIndex: 'productColor', + width: 60, + }, + { + title: t('product.info.table.productCategory'), + dataIndex: 'productCategoryName', + width: 80, + }, + { + title: t('product.info.table.productUnit'), + dataIndex: 'productUnit', + width: 80, + }, + { + title: t('product.info.table.productStock'), + dataIndex: 'stock', + width: 60, + }, + { + title: t('product.info.table.retailPrice'), + dataIndex: 'retailPrice', + width: 60, + }, + { + title: t('product.info.table.salesPrice'), + dataIndex: 'salePrice', + width: 60, + }, + { + title: t('product.info.table.purchasePrice'), + dataIndex: 'purchasePrice', + width: 60, + }, + { + title: t('product.info.form.extendInfo.title'), + dataIndex: 'extendInfo', + width: 60, + }, +] + +const searchFormSchema: FormSchema[] = [ + { + label: t('product.info.header.categoryName'), + field: 'productCategoryId', + component: 'ApiTreeSelect', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + api: getCategoryList, + resultField: 'data', + labelField: 'categoryName', + valueField: 'id', + }, + }, + { + label: t('product.info.header.keyWord'), + field: 'keywords', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('product.info.header.serialNumber'), + field: 'enableSerialNumber', + component: 'Select', + colProps: { + xl: 12, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('product.info.header.none'), value: 0, key: 0 }, + { label: t('product.info.header.have'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('product.info.header.batchNumber'), + field: 'enableBatchNumber', + component: 'Select', + colProps: { + xl: 12, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('product.info.header.none'), value: 0, key: 0 }, + { label: t('product.info.header.have'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('product.info.header.warehouse'), + field: 'warehouseId', + component: 'ApiTreeSelect', + colProps: { + xl: 12, + xxl: 8, + }, + componentProps: { + api: getWarehouseList, + resultField: 'data', + labelField: 'warehouseName', + valueField: 'id', + }, + }, +] + +const meTable: MeTable = reactive({ + loading: false, + dataSource: ref([]), + columns: [ + { + title: t('product.info.form.basic.table.barCode'), + key: 'barCode', + type: 'inputNumber', + placeholder: t('product.info.form.basic.table.pleaseEnter')+'${title}', + }, + { + title: t('product.info.form.basic.table.unit'), + key: 'productUnit', + type: 'input', + placeholder: t('product.info.form.basic.table.pleaseEnter')+'${title}', + validateRules: [{ required: true, message: '单位不能为空' }], + }, + { + title: t('product.info.form.basic.table.multipleAttributes'), + key: 'multiAttribute', + type: 'input', + readonly: true, + placeholder: t('product.info.form.basic.table.pleaseEnter')+'${title}', + }, + { + title: t('product.info.form.basic.table.purchasePrice'), + key: 'purchasePrice', + type: 'inputNumber', + defaultValue: '', + placeholder: t('product.info.form.basic.table.pleaseEnter')+'${title}', + }, + { + title: t('product.info.form.basic.table.retailPrice'), + key: 'retailPrice', + type: 'inputNumber', + defaultValue: '', + placeholder: t('product.info.form.basic.table.pleaseEnter')+'${title}', + }, + { + title: t('product.info.form.basic.table.salesPrice'), + key: 'salesPrice', + type: 'inputNumber', + defaultValue: '', + placeholder: t('product.info.form.basic.table.pleaseEnter')+'${title}', + }, + { + title: t('product.info.form.basic.table.lowestSellPrice'), + key: 'lowSalesPrice', + type: 'inputNumber', + defaultValue: '', + placeholder: t('product.info.form.basic.table.pleaseEnter')+'${title}', + }, + ], +}); + +const stock: any = reactive({ + loading: false, + dataSource: ref([]), + columns: [ + { + title: t('product.info.form.inventoryQuantity.warehouse'), + key: 'warehouseName', + type: 'input', + }, + { + title: t('product.info.form.inventoryQuantity.initialQuantity'), + key: 'initStockQuantity', + type: 'inputNumber', + }, + { + title: t('product.info.form.inventoryQuantity.minSafetyQuantity'), + key: 'lowStockQuantity', + type: 'inputNumber', + }, + { + title: t('product.info.form.inventoryQuantity.maxSafetyQuantity'), + key: 'highStockQuantity', + type: 'inputNumber', + }, + ], +}); + +const formState: any = reactive({ + productId: '', + productName: '', + productStandard: '', + productModel: '', + productUnit: '', + productUnitId: null, + productColor: '', + productWeight: null, + productExpiryNum: null, + productCategoryId: null, + enableSerialNumber: null, + enableBatchNumber: null, + remark: '', + warehouseShelves: '', + productManufacturer: '', + otherFieldOne: '', + otherFieldTwo: '', + otherFieldThree: '', +}); + +const productInfo: ProductInfo = reactive({ + mfrs: '制造商', + otherField1: '自定义1', + otherField2: '自定义2', + otherField3: '自定义3', +}); + + +export { + columns, + extendPriceColumn, + searchFormSchema, + meTable, + stock, + formState, + productInfo, +}; \ No newline at end of file diff --git a/src/views/product/info/model/productInfoModel.ts b/src/views/product/info/model/productInfoModel.ts new file mode 100644 index 0000000..0ebe426 --- /dev/null +++ b/src/views/product/info/model/productInfoModel.ts @@ -0,0 +1,99 @@ + +export interface Column { + title: string; + key: string; + type: string; + placeholder: string; + validateRules?: { required: boolean; message: string }[]; + readonly?: boolean; + defaultValue?: string | number; +} + +export interface ProductAttributeModel { + id: number | string; + attributeName: string; + attributeValue: string; + remark: string; + sort: number; + disabled: boolean; +} + +export interface ProductImageModel { + productImageId: string; + imageName: string; + imageUrl: string; +} + +export interface ProductPriceModel { + key: number|string; + productPriceId: string; + barCode: number; + productUnit: string; + multiAttribute: string; + purchasePrice: number; + retailPrice: number; + salesPrice: number; + lowSalesPrice: number; +} + +export interface ProductStockModel { + key: number|string; + productStockId: number | string; + id: number | string; + warehouseName: string; + initStockQuantity: number; + lowStockQuantity: number; + highStockQuantity: number; +} + +export interface MeTable { + loading: boolean; + dataSource: ProductPriceModel[]; + columns: Column[]; +} + +export interface Stock { + loading: boolean; + dataSource: ProductStockModel[]; + columns: Column[]; +} + +export interface ProductInfo { + mfrs: string; + otherField1: string; + otherField2: string; + otherField3: string; +} + +export interface FormState { + productId: number | string | undefined; + productName: string | undefined; + productStandard: string | undefined; + productModel: string | undefined; + productUnit: string | undefined; + productUnitId: string | undefined; + productColor: string | undefined; + productWeight: number | undefined; + productExpiryNum: number | undefined; + productCategoryId: string | undefined; + enableSerialNumber: number | undefined; + enableBatchNumber: number | undefined; + warehouseShelves: string | undefined; + productManufacturer: string | undefined; + otherFieldOne: string | undefined; + otherFieldTwo: string | undefined; + otherFieldThree: string | undefined; + remark: string | undefined; +} + +export interface Unit { + id: number; + computeUnit: string + basicUnit: string; + otherUnit: string; + ratio: number; + otherUnitTwo: string; + ratioTwo: number; + otherUnitThree: string; + ratioThree: number; +} \ No newline at end of file diff --git a/src/views/product/units/components/UnitModal.vue b/src/views/product/units/components/UnitModal.vue new file mode 100644 index 0000000..c9eeb7e --- /dev/null +++ b/src/views/product/units/components/UnitModal.vue @@ -0,0 +1,93 @@ + + \ No newline at end of file diff --git a/src/views/product/units/index.vue b/src/views/product/units/index.vue new file mode 100644 index 0000000..e39e59e --- /dev/null +++ b/src/views/product/units/index.vue @@ -0,0 +1,113 @@ + + \ No newline at end of file diff --git a/src/views/product/units/units.data.ts b/src/views/product/units/units.data.ts new file mode 100644 index 0000000..1bec322 --- /dev/null +++ b/src/views/product/units/units.data.ts @@ -0,0 +1,173 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import { h } from 'vue'; +import {Switch} from "ant-design-vue"; +import {useMessage} from "@/hooks/web/useMessage"; +import {useI18n} from "@/hooks/web/useI18n"; +import {updateUnitStatus} from "@/api/product/productUnit"; + +const { t } = useI18n(); +export const columns: BasicColumn[] = [ + { + title: t('product.unit.table.unitName'), + dataIndex: 'computeUnit', + width: 230, + }, + { + title: t('product.unit.table.basicUnit'), + dataIndex: 'basicUnit', + width: 70, + }, + { + title: t('product.unit.table.deputyUnitOne'), + dataIndex: 'otherComputeUnit', + width: 70, + }, + { + title: t('product.unit.table.deputyUnitTwo'), + dataIndex: 'otherComputeUnitTwo', + width: 150, + }, + { + title: t('product.unit.table.deputyUnitThree'), + dataIndex: 'otherComputeUnitThree', + width: 150, + }, + { + title: t('product.unit.table.status'), + dataIndex: 'status', + width: 150, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked, _) { + const {createMessage} = useMessage(); + if (record.id == 1) { + createMessage.warn(t('common.notice')); + return; + } + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + updateUnitStatus({id: record.id, status: newStatus} ) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + { + title: t('product.unit.table.createTime'), + dataIndex: 'createTime', + width: 150, + } +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('product.unit.table.unitName'), + field: 'computeUnit', + component: 'Input', + colProps: { span: 8 }, + }, +] + +export const formSchema: FormSchema[] = [ + { + label: '单位id', + field: 'id', + show: false, + component: 'Input', + }, + { + label: t('product.unit.table.basicUnit'), + field: 'basicUnit', + component: 'Input', + required: true, + componentProps: { + placeholder: t('product.unit.table.inputBasicUnit'), + }, + }, + { + label: t('product.unit.table.deputyUnitOne'), + field: 'otherUnit', + component: 'Input', + required: true, + componentProps: { + placeholder: t('product.unit.table.inputDeputyUnitOne'), + }, + colProps: { + span: 13, + }, + }, + { + label: '=', + field: 'ratio', + component: 'InputNumber', + labelWidth: 10, + componentProps: { + addonAfter: t('product.unit.table.basicUnit'), + placeholder: t('product.unit.table.inputProportionOne'), + }, + colProps: { + span: 11, + }, + }, + { + label: t('product.unit.table.deputyUnitTwo'), + field: 'otherUnitTwo', + component: 'Input', + componentProps: { + placeholder: t('product.unit.table.inputDeputyUnitTwo'), + }, + colProps: { + span: 13, + }, + }, + { + label: '=', + field: 'ratioTwo', + labelWidth: 10, + componentProps: { + addonAfter: t('product.unit.table.basicUnit'), + placeholder: t('product.unit.table.inputProportionTwo'), + }, + component: 'Input', + colProps: { + span: 11, + } + }, + { + label: t('product.unit.table.deputyUnitThree'), + field: 'otherUnitThree', + component: 'Input', + componentProps: { + placeholder: t('product.unit.table.inputDeputyUnitThree'), + }, + colProps: { + span: 13, + }, + }, + { + label: '=', + labelWidth: 10, + field: 'ratioThree', + componentProps: { + addonAfter: t('product.unit.table.basicUnit'), + placeholder: t('product.unit.table.inputProportionThree'), + }, + component: 'Input', + colProps: { + span: 11, + } + } +] \ No newline at end of file diff --git a/src/views/production/tasks/index.vue b/src/views/production/tasks/index.vue new file mode 100644 index 0000000..73ef758 --- /dev/null +++ b/src/views/production/tasks/index.vue @@ -0,0 +1,189 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/production/tasks/task.data.ts b/src/views/production/tasks/task.data.ts new file mode 100644 index 0000000..cdd694b --- /dev/null +++ b/src/views/production/tasks/task.data.ts @@ -0,0 +1,321 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {h, reactive, ref} from 'vue'; +import {Switch} from "ant-design-vue"; +import {useMessage} from "@/hooks/web/useMessage"; +import {useI18n} from "@/hooks/web/useI18n"; +import {MeTable, ProductInfo} from "@/views/product/info/model/productInfoModel"; +import {getCustomerList} from "@/api/basic/customer"; + +const { t } = useI18n(); + +const columns: BasicColumn[] = [ + { + title: '生产单号', + dataIndex: 'productBarcode', + width: 100, + }, + { + title: '产品条码', + dataIndex: 'productModel', + width: 100, + }, + { + title: '产品名称', + dataIndex: 'productStandard', + width: 110, + }, + { + title: '产品型号', + dataIndex: 'productColor', + width: 110, + }, + { + title: '产品规格', + dataIndex: 'productCategoryName', + width: 110, + }, + { + title: '外协单位', + dataIndex: 'productUnit', + width: 90, + }, + { + title: '订购数量', + dataIndex: 'productStock', + width: 70, + }, + { + title: '生产数量', + dataIndex: 'purchasePrice', + width: 70, + }, + { + title: '操作员', + dataIndex: 'lowPrice', + width: 80, + }, + { + title: '计划生产日期', + dataIndex: 'createTime', + width: 150, + }, + { + title: '单据日期', + dataIndex: 'createTime', + width: 150, + }, + { + title: '状态', + dataIndex: 'status', + width: 80, + }, +] + + +const extendPriceColumn: BasicColumn[] = [ + { + title: '条码', + dataIndex: 'barCode', + width: 80, + }, + { + title: '名称', + dataIndex: 'productName', + width: 100, + }, + { + title: '分类', + dataIndex: 'productCategoryName', + width: 100, + }, + { + title: '所属仓库', + dataIndex: 'warehouseName', + width: 100, + }, + { + title: '规格', + dataIndex: 'productStandard', + width: 80, + }, + { + title: '型号', + dataIndex: 'productModel', + width: 100, + }, + { + title: '颜色', + dataIndex: 'productColor', + width: 60, + }, + { + title: '类别', + dataIndex: 'productCategoryName', + width: 80, + }, + { + title: '单位', + dataIndex: 'productUnit', + width: 80, + }, + { + title: '库存', + dataIndex: 'stock', + width: 60, + }, + { + title: '零售价', + dataIndex: 'retailPrice', + width: 60, + }, + { + title: '销售价', + dataIndex: 'salePrice', + width: 60, + }, + { + title: '采购价', + dataIndex: 'purchasePrice', + width: 60, + }, + { + title: '扩展信息', + dataIndex: 'extendInfo', + width: 60, + }, +] + +const searchFormSchema: FormSchema[] = [ + { + label: '生产单号', + field: 'productCategoryId', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + } + }, + { + label: '产品信息', + field: 'keywords', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + helpMessage: ['请输入产品名称、型号、规格'], + }, + { + field: '[startDate, endDate]', + label: '单据日期', + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: ['开始日期', '结束日期'], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: '操作人', + field: 'customerId', + component: 'ApiSelect', + componentProps: { + api: getCustomerList, + resultField: 'data', + labelField: 'customerName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, +] + +const meTable: MeTable = reactive({ + loading: false, + dataSource: ref([]), + columns: [ + { + title: '条码', + key: 'barCode', + type: 'inputNumber', + placeholder: '请输入${title}', + }, + { + title: '单位', + key: 'productUnit', + type: 'input', + placeholder: '请输入${title}', + validateRules: [{ required: true, message: '单位不能为空' }], + }, + { + title: '多属性', + key: 'multiAttribute', + type: 'input', + readonly: true, + placeholder: '请输入${title}', + }, + { + title: '采购价', + key: 'purchasePrice', + type: 'inputNumber', + defaultValue: '', + placeholder: '请输入${title}', + }, + { + title: '零售价', + key: 'retailPrice', + type: 'inputNumber', + defaultValue: '', + placeholder: '请输入${title}', + }, + { + title: '销售价', + key: 'salesPrice', + type: 'inputNumber', + defaultValue: '', + placeholder: '请输入${title}', + }, + { + title: '最低售价', + key: 'lowSalesPrice', + type: 'inputNumber', + defaultValue: '', + placeholder: '请输入${title}', + }, + ], +}); + +const stock: any = reactive({ + loading: false, + dataSource: ref([]), + columns: [ + { + title: '仓库 (商品条码/商品单位)', + key: 'warehouseName', + type: 'input', + }, + { + title: '期初库存数量', + key: 'initStockQuantity', + type: 'inputNumber', + placeholder: '请输入${title}', + }, + { + title: '最低安全库存数量', + key: 'lowStockQuantity', + type: 'inputNumber', + placeholder: '请输入${title}', + }, + { + title: '最高安全库存数量', + key: 'highStockQuantity', + type: 'inputNumber', + placeholder: '请输入${title}', + }, + ], +}); + +const formState: any = reactive({ + productId: '', + productName: '', + productStandard: '', + productModel: '', + productUnit: '', + productUnitId: null, + productColor: '', + productWeight: null, + productExpiryNum: null, + productCategoryId: null, + enableSerialNumber: null, + enableBatchNumber: null, + remark: '', + warehouseShelves: '', + productManufacturer: '', + otherFieldOne: '', + otherFieldTwo: '', + otherFieldThree: '', +}); + +const productInfo: ProductInfo = reactive({ + mfrs: '制造商', + otherField1: '自定义1', + otherField2: '自定义2', + otherField3: '自定义3', +}); + + +export { + columns, + extendPriceColumn, + searchFormSchema, + meTable, + stock, + formState, + productInfo, +}; \ No newline at end of file diff --git a/src/views/purchase/model/addEditModel.ts b/src/views/purchase/model/addEditModel.ts new file mode 100644 index 0000000..b38f67a --- /dev/null +++ b/src/views/purchase/model/addEditModel.ts @@ -0,0 +1,480 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; +import {useLocaleStore} from "@/store/modules/locale"; + +const amountSymbol = ref('') +const localeStore = useLocaleStore().getLocale; +if(localeStore === 'zh_CN') { + amountSymbol.value = '¥' +} else if (localeStore === 'en') { + amountSymbol.value = '$' +} + +export const { t } = useI18n(); + +export interface RowVO { + [key: string]: any, + barCode: number | string, + productName:string, + productStandard: string, + stock: number, + productUnit: string, + productNumber: number, + unitPrice: number, + amount: number, + taxRate: number, + taxAmount: number, + taxTotalPrice: number, + remark: string, +} +interface PurchaseOrderFormState { + id: number | string | undefined; + supplierId: string; + receiptNumber: string; + discountRate: number; + discountAmount: number; + discountLastAmount: number | string; + deposit: number; + remark: string; + receiptDate: string | undefined | Dayjs; + warehouseId: number | string; + accountId: string | undefined; + operatorIds: number[], + multipleAccountIds: number[] | undefined; + multipleAccountAmounts: number[] | undefined; +} + +interface PurchaseStorageFormState { + id: number | string | undefined; + supplierId: string; + accountId: number | string | undefined; + operatorIds: number[], + receiptNumber: string; + receiptDate: string | undefined | Dayjs; + otherReceipt: string; + paymentRate: number; + paymentAmount: number; + paymentLastAmount: number | string; + otherAmount: number; + thisPaymentAmount: number | string; + thisArrearsAmount: number; + remark: string; + status: number | undefined; + warehouseId: number | string; + multipleAccountIds: number[] | undefined; + multipleAccountAmounts: number[] | undefined; +} + +interface PurchaseRefundFormState { + id: number | string | undefined; + supplierId: string; + accountId: number | string | undefined; + receiptNumber: string; + receiptDate: string | undefined | Dayjs; + otherReceipt: string; + refundOfferRate: number; + refundOfferAmount: number; + refundLastAmount: number | string; + otherAmount: number; + thisRefundAmount: number; + thisArrearsAmount: number; + remark: string; + status: number | undefined; + operatorIds: number[], + warehouseId: number | string; + multipleAccountIds: number[] | undefined; + multipleAccountAmounts: number[] | undefined; +} + +const xGrid = ref>() +const tableData = ref([]) +const orderGridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + printConfig: { + columns: [ + { field: 'barCode' }, + { field: 'productName' }, + { field: 'productStandard' }, + { field: 'stockNumber' }, + { field: 'productUnit' }, + { field: 'productNumber' }, + { field: 'retailPrice' }, + { field: 'amount' }, + { field: 'remark' } + ] + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + refresh: true, // 显示刷新按钮 + print: true, // 显示打印按钮 + zoom: true, // 显示全屏按钮 + custom: true // 显示自定义列按钮 + }, + columns: [ + { type: 'checkbox', field:'productId', title: 'ID', width: 80}, + { + field: 'warehouseId', + title: t('sales.shipments.form.table.warehouse'), + width: 130, + slots: { edit: 'warehouse_edit', default: 'warehouse_default' }, + editRender: { name: 'input', attrs: { placeholder: t('sales.shipments.form.noticeEight') } } + }, + { field: 'barCode', + width:160, + title: t('purchase.order.form.table.barCode'), + slots: { edit: 'barCode_edit' }, + titlePrefix: { content: t('purchase.order.form.noticeSix') }, + editRender: { name: 'input', attrs: { placeholder: '请输入条码并回车' } } + }, + { + field: 'productName', + title: t('purchase.order.form.table.name'), + width:160, + }, + { field: 'productStandard', title: t('purchase.order.form.table.standard'), width: 90, }, + { field: 'stock', title: t('purchase.order.form.table.stock'), width: 70}, + { field: 'productUnit', title: t('purchase.order.form.table.unit'), width: 60}, + { field: 'productNumber', title: t('purchase.order.form.table.quantity'), sortable: true, width:100, + slots: { edit: 'product_number_edit' }, + editRender: { name: '$input', props: { type: 'number', min: 1, max: 9999 } }, + }, + { + field: 'unitPrice', + title: t('purchase.order.form.table.unitPrice'), width:105, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'price_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入单价' } } + }, + { + field: 'amount', + title: t('purchase.order.form.table.amount'), width:105, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'amount_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入金额' } } + }, + { field: 'taxRate', title: t('purchase.order.form.table.taxRate'), width: 120, + slots: { edit: 'tax_rate_edit' }, + editRender: { name: '$input', attrs: { type: 'float', digits: 2, placeholder: '请输入税率' } } + }, + { field: 'taxAmount', title: t('purchase.order.form.table.taxAmount'), width: 125, + editRender:{attrs: {type: 'float', digits: 2}}, + slots: { edit: 'tax_amount_edit' }, + }, + { field: 'taxTotalPrice', title: t('purchase.order.form.table.totalIncludingTax'), width: 125, + slots: { edit: 'tax_total_price_edit' }, + editRender: { name: '$input', attrs: {type: 'float', digits: 2, placeholder: '请输入价税合计' } } + }, + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('purchase.order.form.table.total') + } + if (['amount', 'rate'].includes(column.field)) { + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + if (['productNumber', 'rate'].includes(column.field)) { + return sumNum(data, column.field) + } + if (['taxAmount', 'rate'].includes(column.field)) { + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + + if (['taxTotalPrice', 'rate'].includes(column.field)) { + getTaxTotalPrice.value = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editRules: { + warehouseId: [ + { required: true, message: t('purchase.order.form.noticeEight') } + ], + barCode: [ + { required: true, message: t('purchase.order.form.noticeFive') } + ] + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + } +}) + +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + printConfig: { + columns: [ + { field: 'barCode' }, + { field: 'productName' }, + { field: 'productStandard' }, + { field: 'stockNumber' }, + { field: 'productUnit' }, + { field: 'productNumber' }, + { field: 'retailPrice' }, + { field: 'amount' }, + { field: 'remark' } + ] + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + refresh: true, // 显示刷新按钮 + print: true, // 显示打印按钮 + zoom: true, // 显示全屏按钮 + custom: true // 显示自定义列按钮 + }, + columns: [ + { type: 'checkbox', field:'productId', title: 'ID', width: 80}, + { + field: 'warehouseId', + title: t('purchase.storage.form.table.warehouse'), + width: 130, + slots: { edit: 'warehouse_edit', default: 'warehouse_default'}, + editRender: { name: 'input', attrs: { placeholder: t('purchase.storage.form.table.inputWarehouse') } } + }, + { field: 'barCode', + width:160, + title: t('purchase.storage.form.table.barCode'), + slots: { edit: 'barCode_edit' }, + titlePrefix: { content: t('purchase.storage.form.noticeSix') }, + editRender: { name: 'input', attrs: { placeholder: '请输入条码并回车' } } + }, + { + field: 'productName', + title: t('purchase.storage.form.table.name'), + width:160, + }, + { field: 'productStandard', title: t('purchase.storage.form.table.standard'), width: 90, }, + { field: 'stock', title: t('purchase.storage.form.table.stock'), width: 70}, + { field: 'productUnit', title: t('purchase.storage.form.table.unit'), width: 60}, + { field: 'productNumber', title: t('purchase.storage.form.table.quantity'), sortable: true, width:100, + slots: { edit: 'product_number_edit' }, + editRender: { name: '$input', props: { type: 'number', min: 1, max: 9999 } }, + }, + { + field: 'unitPrice', + title: t('purchase.storage.form.table.unitPrice'), width:105, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'price_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入单价' } } + }, + { + field: 'amount', + title: t('purchase.storage.form.table.amount'), width:105, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'amount_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入金额' } } + }, + { field: 'taxRate', title: t('purchase.storage.form.table.taxRate'), width: 120, + slots: { edit: 'tax_rate_edit' }, + editRender: { name: '$input', attrs: { type: 'float', digits: 2, placeholder: '请输入税率' } } + }, + { field: 'taxAmount', title: t('purchase.storage.form.table.taxAmount'), width: 125, + editRender:{attrs: {type: 'float', digits: 2}}, + slots: { edit: 'tax_amount_edit' }, + }, + { field: 'taxTotalPrice', title: t('purchase.storage.form.table.totalIncludingTax'), width: 125, + slots: { edit: 'tax_total_price_edit' }, + editRender: { name: '$input', attrs: {type: 'float', digits: 2, placeholder: '请输入价税合计' } } + }, + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('purchase.storage.form.table.total') + } + if (['amount', 'rate'].includes(column.field)) { + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + if (['productNumber', 'rate'].includes(column.field)) { + return sumNum(data, column.field) + } + if (['taxAmount', 'rate'].includes(column.field)) { + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + + if (['taxTotalPrice', 'rate'].includes(column.field)) { + getTaxTotalPrice.value = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editRules: { + warehouseId: [ + { required: true, message: t('purchase.storage.form.table.inputWarehouse') } + ], + barCode: [ + { required: true, message: t('purchase.storage.form.table.inputBarCode') } + ] + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + } +}) + +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} + +const getTaxTotalPrice = ref(''); + +const purchaseOrderFormState = reactive({ + id: undefined, + supplierId: '', + receiptNumber: '', + remark: '', + discountRate: 0, + discountAmount: 0, + discountLastAmount: 0, + deposit: 0, + accountId: undefined, + receiptDate: '', + warehouseId: '', + operatorIds: [], + multipleAccountIds: undefined, + multipleAccountAmounts: undefined, +}); + +const purchaseStorageFormState = reactive({ + id: undefined, + supplierId: '', + receiptNumber: '', + otherReceipt: '', + remark: '', + paymentRate: 0, + paymentAmount: 0, + paymentLastAmount: 0, + otherAmount: 0, + thisPaymentAmount: 0, + thisArrearsAmount: 0, + status: undefined, + accountId: undefined, + receiptDate: '', + warehouseId: '', + operatorIds: [], + multipleAccountIds: undefined, + multipleAccountAmounts: undefined, +}); + +const purchaseRefundFormState = reactive({ + id: undefined, + supplierId: '', + receiptNumber: '', + otherReceipt: '', + remark: '', + refundOfferRate: 0, + refundOfferAmount: 0, + refundLastAmount: 0, + otherAmount: 0, + thisRefundAmount: 0, + thisArrearsAmount: 0, + status: undefined, + accountId: undefined, + receiptDate: '', + warehouseId: '', + multipleAccountIds: undefined, + multipleAccountAmounts: undefined, +}); + +export { + xGrid, + sumNum, + tableData, + orderGridOptions, + gridOptions, + purchaseOrderFormState, + purchaseStorageFormState, + purchaseRefundFormState, + getTaxTotalPrice, +} \ No newline at end of file diff --git a/src/views/purchase/order/components/AddEditModal.vue b/src/views/purchase/order/components/AddEditModal.vue new file mode 100644 index 0000000..286183c --- /dev/null +++ b/src/views/purchase/order/components/AddEditModal.vue @@ -0,0 +1,1093 @@ + + + + + \ No newline at end of file diff --git a/src/views/purchase/order/components/ViewOrderModal.vue b/src/views/purchase/order/components/ViewOrderModal.vue new file mode 100644 index 0000000..a8bb987 --- /dev/null +++ b/src/views/purchase/order/components/ViewOrderModal.vue @@ -0,0 +1,207 @@ + + + diff --git a/src/views/purchase/order/index.vue b/src/views/purchase/order/index.vue new file mode 100644 index 0000000..6246a3e --- /dev/null +++ b/src/views/purchase/order/index.vue @@ -0,0 +1,241 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/purchase/order/purchaseOrder.data.ts b/src/views/purchase/order/purchaseOrder.data.ts new file mode 100644 index 0000000..402f0b4 --- /dev/null +++ b/src/views/purchase/order/purchaseOrder.data.ts @@ -0,0 +1,213 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; +import {getSupplierList} from "@/api/basic/supplier"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('purchase.order.table.supplier'), + dataIndex: 'supplierName', + width: 130, + }, + { + title: t('purchase.order.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('purchase.order.table.productInformation'), + dataIndex: 'productInfo', + width: 80, + }, + { + title: t('purchase.order.table.productQuantity'), + dataIndex: 'productNumber', + width: 50, + }, + { + title: t('purchase.order.table.totalAmount'), + dataIndex: 'totalAmount', + width: 60, + }, + { + title: t('purchase.order.table.totalIncludingTax'), + dataIndex: 'taxRateTotalAmount', + width: 80, + }, + { + title: t('purchase.order.table.collectDeposit'), + dataIndex: 'deposit', + width: 80, + }, + { + title: t('purchase.order.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('purchase.order.table.operator'), + dataIndex: 'operator', + width: 60, + }, + { + title: t('purchase.order.table.status'), + dataIndex: 'status', + width: 80, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('purchase.order.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('purchase.order.table.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('purchase.order.header.startDate'), t('purchase.order.header.endDate'),], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('purchase.order.table.supplier'), + field: 'supplierId', + component: 'ApiSelect', + componentProps: { + api: getSupplierList, + resultField: 'data', + labelField: 'supplierName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('purchase.order.table.productInformation'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('purchase.order.table.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + { label: t('purchase.partialPurchase'), value: 2, key: 2 }, + { label: t('purchase.completePurchase'), value: 3, key: 3 }, + ], + }, + }, + { + label: t('purchase.order.header.receiptRemark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] + +export const purchaseOrderTableColumns: BasicColumn[] = [ + { + title: t('purchase.order.form.table.warehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('purchase.order.form.table.barCode'), + dataIndex: 'barCode', + width: 100, + }, + { + title: t('purchase.order.form.table.name'), + dataIndex: 'productName', + width: 120, + }, + { + title: t('purchase.order.form.table.standard'), + dataIndex: 'productStandard', + width: 120, + }, + { + title: t('purchase.order.form.table.model'), + dataIndex: 'productModel', + width: 120, + }, + { + title: t('purchase.order.form.table.color'), + dataIndex: 'productColor', + width: 70, + }, + { + title: t('purchase.order.form.table.stock'), + dataIndex: 'stock', + width: 80, + }, + { + title: t('purchase.order.form.table.unit'), + dataIndex: 'productUnit', + width: 60, + }, + { + title: t('purchase.order.form.table.quantity'), + dataIndex: 'productNumber', + width: 60, + }, + { + title: t('purchase.order.form.table.unitPrice'), + dataIndex: 'unitPrice', + width: 60, + }, + { + title: t('purchase.order.form.table.amount'), + dataIndex: 'amount', + width: 60, + }, + { + title: t('purchase.order.form.table.taxRate'), + dataIndex: 'taxRate', + width: 60, + }, + { + title: t('purchase.order.form.table.taxAmount'), + dataIndex: 'taxAmount', + width: 60, + }, + { + title: t('purchase.order.form.table.totalIncludingTax'), + dataIndex: 'taxTotalPrice', + width: 80, + }, + { + title: t('purchase.order.form.table.remark'), + dataIndex: 'remark', + width: 100, + }, +] \ No newline at end of file diff --git a/src/views/purchase/refund/components/AddEditModal.vue b/src/views/purchase/refund/components/AddEditModal.vue new file mode 100644 index 0000000..79949d0 --- /dev/null +++ b/src/views/purchase/refund/components/AddEditModal.vue @@ -0,0 +1,1271 @@ + + + + + \ No newline at end of file diff --git a/src/views/purchase/refund/components/ViewRefundModal.vue b/src/views/purchase/refund/components/ViewRefundModal.vue new file mode 100644 index 0000000..63ad8ac --- /dev/null +++ b/src/views/purchase/refund/components/ViewRefundModal.vue @@ -0,0 +1,242 @@ + + + diff --git a/src/views/purchase/refund/index.vue b/src/views/purchase/refund/index.vue new file mode 100644 index 0000000..4cbe4cb --- /dev/null +++ b/src/views/purchase/refund/index.vue @@ -0,0 +1,241 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/purchase/refund/purchaseRefund.data.ts b/src/views/purchase/refund/purchaseRefund.data.ts new file mode 100644 index 0000000..a1bf4f1 --- /dev/null +++ b/src/views/purchase/refund/purchaseRefund.data.ts @@ -0,0 +1,143 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; +import {getSupplierList} from "@/api/basic/supplier"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('purchase.refund.table.supplier'), + dataIndex: 'supplierName', + width: 130, + }, + { + title: t('purchase.refund.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('purchase.refund.table.productInformation'), + dataIndex: 'productInfo', + width: 80, + }, + { + title: t('purchase.refund.table.productQuantity'), + dataIndex: 'productNumber', + width: 50, + }, + { + title: t('purchase.refund.table.totalAmount'), + dataIndex: 'totalAmount', + width: 60, + }, + { + title: t('purchase.refund.table.totalIncludingTax'), + dataIndex: 'taxIncludedAmount', + width: 80, + }, + { + title: t('purchase.refund.table.refundAmount'), + dataIndex: 'refundTotalAmount', + width: 80, + }, + { + title: t('purchase.refund.table.thisRefundAmount'), + dataIndex: 'thisRefundAmount', + width: 80, + }, + { + title: t('purchase.refund.table.thisArrearsAmount'), + dataIndex: 'thisArrearsAmount', + width: 80, + }, + { + title: t('purchase.refund.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('purchase.refund.table.operator'), + dataIndex: 'operator', + width: 60, + }, + { + title: t('purchase.refund.table.status'), + dataIndex: 'status', + width: 80, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('purchase.refund.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('purchase.refund.table.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('purchase.refund.header.startDate'), t('purchase.refund.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('purchase.refund.table.supplier'), + field: 'supplierId', + component: 'ApiSelect', + componentProps: { + api: getSupplierList, + resultField: 'data', + labelField: 'supplierName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('purchase.refund.table.productInformation'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('purchase.refund.table.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('purchase.refund.header.receiptRemark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] \ No newline at end of file diff --git a/src/views/purchase/storage/components/AddEditModal.vue b/src/views/purchase/storage/components/AddEditModal.vue new file mode 100644 index 0000000..a59e214 --- /dev/null +++ b/src/views/purchase/storage/components/AddEditModal.vue @@ -0,0 +1,1272 @@ + + + + + \ No newline at end of file diff --git a/src/views/purchase/storage/components/ViewStorageModal.vue b/src/views/purchase/storage/components/ViewStorageModal.vue new file mode 100644 index 0000000..5c7f055 --- /dev/null +++ b/src/views/purchase/storage/components/ViewStorageModal.vue @@ -0,0 +1,235 @@ + + + diff --git a/src/views/purchase/storage/index.vue b/src/views/purchase/storage/index.vue new file mode 100644 index 0000000..e3632c9 --- /dev/null +++ b/src/views/purchase/storage/index.vue @@ -0,0 +1,243 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/purchase/storage/purchaseStorage.data.ts b/src/views/purchase/storage/purchaseStorage.data.ts new file mode 100644 index 0000000..24607f7 --- /dev/null +++ b/src/views/purchase/storage/purchaseStorage.data.ts @@ -0,0 +1,145 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; +import {getSupplierList} from "@/api/basic/supplier"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('purchase.storage.table.supplier'), + dataIndex: 'supplierName', + width: 130, + }, + { + title: t('purchase.storage.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('purchase.storage.table.productInformation'), + dataIndex: 'productInfo', + width: 80, + }, + { + title: t('purchase.storage.table.productQuantity'), + dataIndex: 'productNumber', + width: 50, + }, + { + title: t('purchase.storage.table.totalAmount'), + dataIndex: 'totalAmount', + width: 60, + }, + { + title: t('purchase.storage.table.totalIncludingTax'), + dataIndex: 'taxIncludedAmount', + width: 80, + }, + { + title: t('purchase.storage.table.paymentAmount'), + dataIndex: 'totalPaymentAmount', + width: 80, + }, + { + title:t('purchase.storage.table.thisTimePaymentAmount'), + dataIndex: 'thisPaymentAmount', + width: 80, + }, + { + title: t('purchase.storage.table.thisTimeArrearsAmount'), + dataIndex: 'thisArrearsAmount', + width: 80, + }, + { + title: t('purchase.storage.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('purchase.storage.table.operator'), + dataIndex: 'operator', + width: 60, + }, + { + title: t('purchase.storage.table.status'), + dataIndex: 'status', + width: 80, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('purchase.storage.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('purchase.storage.table.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('purchase.storage.header.startDate'), t('purchase.storage.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('purchase.storage.table.supplier'), + field: 'supplierId', + component: 'ApiSelect', + componentProps: { + api: getSupplierList, + resultField: 'data', + labelField: 'supplierName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('purchase.storage.table.productInformation'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('purchase.storage.table.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + { label: t('purchase.partialPurchase'), value: 2, key: 2 }, + { label: t('purchase.completePurchase'), value: 3, key: 3 }, + ], + }, + }, + { + label: t('purchase.storage.header.receiptRemark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] \ No newline at end of file diff --git a/src/views/receipt/LinkReceiptModal.vue b/src/views/receipt/LinkReceiptModal.vue new file mode 100644 index 0000000..637624e --- /dev/null +++ b/src/views/receipt/LinkReceiptModal.vue @@ -0,0 +1,128 @@ + + + \ No newline at end of file diff --git a/src/views/receipt/ReceiptDetailModal.vue b/src/views/receipt/ReceiptDetailModal.vue new file mode 100644 index 0000000..b70c70a --- /dev/null +++ b/src/views/receipt/ReceiptDetailModal.vue @@ -0,0 +1,82 @@ + + + \ No newline at end of file diff --git a/src/views/receipt/receipt.data.ts b/src/views/receipt/receipt.data.ts new file mode 100644 index 0000000..c327782 --- /dev/null +++ b/src/views/receipt/receipt.data.ts @@ -0,0 +1,171 @@ +import {BasicColumn, FormSchema} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const ReceiptDetailColumn: BasicColumn[] = [ + { + title: 'id', + dataIndex: 'id', + width: 60, + ifShow: false, + }, + { + title: t('purchase.order.form.table.barCode'), + dataIndex: 'productBarcode', + width: 130, + }, + { + title: t('purchase.order.form.table.name'), + dataIndex: 'productName', + width: 130, + }, + { + title: t('purchase.order.form.table.standard'), + dataIndex: 'productStandard', + width: 100, + }, + { + title: t('purchase.order.form.table.model'), + dataIndex: 'productModel', + width: 100, + }, + { + title: t('purchase.order.form.table.unit'), + dataIndex: 'unit', + width: 80, + }, + { + title: t('purchase.order.form.table.quantity'), + dataIndex: 'productNumber', + width: 60, + }, + { + title: t('purchase.order.form.table.unitPrice'), + dataIndex: 'unitPrice', + width: 60, + }, + { + title: t('purchase.order.form.table.amount'), + dataIndex: 'amount', + width: 60, + }, + { + title: t('purchase.order.form.table.taxRate'), + dataIndex: 'taxRate', + width: 80, + }, + { + title: t('purchase.order.form.table.taxAmount'), + dataIndex: 'taxAmount', + width: 80, + }, + { + title: t('purchase.order.form.table.totalIncludingTax'), + dataIndex: 'taxIncludedAmount', + width: 80, + }, + { + title: t('purchase.order.form.table.remark'), + dataIndex: 'remark', + width: 100, + }, +] + +export const ReceiptColumn: BasicColumn[] = [ + { + title: 'id', + dataIndex: 'id', + width: 0, + ifShow: false, + }, + { + title: 'uid', + dataIndex: 'uid', + width: 0, + ifShow: false, + }, + { + title: t('purchase.order.form.table.name'), + dataIndex: 'name', + width: 70, + }, + { + title: t('purchase.order.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 190, + }, + { + title: t('purchase.order.table.receiptDate'), + dataIndex: 'receiptDate', + width: 150, + }, + { + title: t('purchase.order.table.productInformation'), + dataIndex: 'productInfo', + width: 200, + }, + { + title: t('purchase.order.form.table.quantity'), + dataIndex: 'productNumber', + width: 70, + }, + { + title: t('purchase.order.table.totalAmount'), + dataIndex: 'totalAmount', + width: 70, + }, + { + title: t('purchase.order.form.table.totalIncludingTax'), + dataIndex: 'taxRateTotalAmount', + width: 70, + }, + { + title: t('purchase.order.table.operator'), + dataIndex: 'operator', + width: 80, + }, + { + title: t('purchase.order.table.status'), + dataIndex: 'status', + width: 90, + }, +] + +export const searchSchema: FormSchema[] = [ + { + label: t('sys.table.type'), + field: 'type', + component: 'Input', + show: false, + }, + { + label: t('sys.table.subType'), + field: 'subType', + component: 'Input', + show: false, + }, + { + label: t('purchase.order.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { span: 8 }, + }, + { + label: t('purchase.order.table.productInformation'), + field: 'productInfo', + component: 'Input', + helpMessage: t('purchase.order.form.noticeSeven'), + colProps: { span: 7 }, + }, + { + field: '[startDate, endDate]', + label: t('purchase.order.table.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('purchase.order.header.startDate'), t('purchase.order.header.endDate')], + }, + colProps: { span: 7 }, + }, +] \ No newline at end of file diff --git a/src/views/report/accountStatistics.vue b/src/views/report/accountStatistics.vue new file mode 100644 index 0000000..deb699e --- /dev/null +++ b/src/views/report/accountStatistics.vue @@ -0,0 +1,158 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/customerBill.vue b/src/views/report/customerBill.vue new file mode 100644 index 0000000..ceefa4a --- /dev/null +++ b/src/views/report/customerBill.vue @@ -0,0 +1,185 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/modal/AccountFlowModal.vue b/src/views/report/modal/AccountFlowModal.vue new file mode 100644 index 0000000..df42f63 --- /dev/null +++ b/src/views/report/modal/AccountFlowModal.vue @@ -0,0 +1,152 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/modal/CustomerBillDetailModal.vue b/src/views/report/modal/CustomerBillDetailModal.vue new file mode 100644 index 0000000..bea794c --- /dev/null +++ b/src/views/report/modal/CustomerBillDetailModal.vue @@ -0,0 +1,181 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/modal/StockFlowModal.vue b/src/views/report/modal/StockFlowModal.vue new file mode 100644 index 0000000..41fe69b --- /dev/null +++ b/src/views/report/modal/StockFlowModal.vue @@ -0,0 +1,183 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/modal/SupplierBillDetailModal.vue b/src/views/report/modal/SupplierBillDetailModal.vue new file mode 100644 index 0000000..5965f32 --- /dev/null +++ b/src/views/report/modal/SupplierBillDetailModal.vue @@ -0,0 +1,182 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/productStock.vue b/src/views/report/productStock.vue new file mode 100644 index 0000000..8c62c5d --- /dev/null +++ b/src/views/report/productStock.vue @@ -0,0 +1,171 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/purchaseStatistics.vue b/src/views/report/purchaseStatistics.vue new file mode 100644 index 0000000..7949912 --- /dev/null +++ b/src/views/report/purchaseStatistics.vue @@ -0,0 +1,154 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/report.data.ts b/src/views/report/report.data.ts new file mode 100644 index 0000000..3882f08 --- /dev/null +++ b/src/views/report/report.data.ts @@ -0,0 +1,1461 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getWarehouseList} from "@/api/basic/warehouse"; +import {getCategoryList} from "@/api/product/productCategory"; +import {getMemberList} from "@/api/basic/member"; +import {getSupplierList} from "@/api/basic/supplier"; +import {getCustomerList} from "@/api/basic/customer"; +import {getRelatedPerson} from "@/api/report/report"; +import {getOperatorList} from "@/api/basic/operator"; +import {useI18n} from "@/hooks/web/useI18n"; + +const { t } = useI18n(); +export const productStockColumns: BasicColumn[] = [ + { + title: '产品id', + dataIndex: 'productId', + width: 120, + ifShow: false + }, + { + title: '仓库id', + dataIndex: 'warehouseId', + width: 60, + ifShow: false + }, + { + title: t('reports.productStock.table.stockFlow'), + dataIndex: 'id', + width: 80, + }, + { + title: t('reports.productStock.table.productBarcode'), + dataIndex: 'productBarcode', + width: 120, + }, + { + title: t('reports.productStock.table.warehouse'), + dataIndex: 'warehouseName', + width: 120, + }, + { + title: t('reports.productStock.table.productName'), + dataIndex: 'productName', + width: 350, + }, + { + title: t('reports.productStock.table.productCategory'), + dataIndex: 'productCategoryName', + width: 80, + }, + { + title: t('reports.productStock.table.standard'), + dataIndex: 'productStandard', + width: 120, + }, + { + title: t('reports.productStock.table.warehouseShelves'), + dataIndex: 'warehouseShelves', + width: 100, + }, + { + title: t('reports.productStock.table.unitPrice'), + dataIndex: 'unitPrice', + width: 70, + }, + { + title: t('reports.productStock.table.initStock'), + dataIndex: 'initialStock', + width: 70, + }, + { + title: t('reports.productStock.table.currentStock'), + dataIndex: 'currentStock', + width: 70, + }, + { + title: t('reports.productStock.table.stockAmount'), + dataIndex: 'stockAmount', + width: 90, + }, +] + +export const searchProductStockSchema: FormSchema[] = [ + { + label: t('reports.productStock.table.warehouse'), + field: 'warehouseId', + component: 'ApiSelect', + componentProps: { + api: getWarehouseList, + resultField: 'data', + labelField: 'warehouseName', + valueField: 'id', + }, + colProps: { span: 5 }, + }, + { + label: t('reports.productStock.header.productInfo'), + field: 'productInfo', + component: 'Input', + colProps: { span: 5 }, + }, + { + label: t('reports.productStock.table.productCategory'), + field: 'productCategoryId', + component: 'ApiTreeSelect', + componentProps: { + api: getCategoryList, + resultField: 'data', + labelField: 'categoryName', + valueField: 'id', + }, + colProps: { span: 5 } + }, + { + label: t('reports.productStock.table.warehouseShelves'), + field: 'warehouseShelves', + component: 'Input', + colProps: { span: 5 }, + }, +] + +export const stockFlowColumns: BasicColumn[] = [ + { + title: t('reports.shipmentsDetail.header.receiptNumber'), + dataIndex: 'receiptNumber', + width: 180, + }, + { + title: t('reports.shipmentsDetail.table.type'), + dataIndex: 'type', + width: 80, + }, + { + title: t('reports.retail.table.barCode'), + dataIndex: 'productBarcode', + width: 120, + }, + { + title: t('reports.retail.table.name'), + dataIndex: 'productName', + width: 120, + }, + { + title: t('reports.retail.table.warehouse'), + dataIndex: 'warehouseName', + width: 120, + }, + { + title: t('reports.shipmentsDetail.table.quantity'), + dataIndex: 'productNumber', + width: 60, + }, + { + title: t('reports.storageSummary.header.receiptDate'), + dataIndex: 'receiptDate', + width: 150, + } +] + +export const searchStockFlowSchema: FormSchema[] = [ + { + label: t('reports.shipmentsDetail.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { span: 10 }, + }, + { + field: '[startDate, endDate]', + label: t('reports.retail.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.retail.header.startDate'), t('reports.retail.header.endDate')], + }, + colProps: { span: 10 }, + }, +] + +export const accountStatisticsColumns: BasicColumn[] = [ + { + title: t('reports.account.table.accountFlow'), + dataIndex: 'accountId', + width: 80, + }, + { + title: t('reports.account.table.accountName'), + dataIndex: 'accountName', + width: 180, + }, + { + title: t('reports.account.table.accountNumber'), + dataIndex: 'accountNumber', + width: 120, + }, + { + title: t('reports.account.table.initialAmount'), + dataIndex: 'initialAmount', + width: 120, + }, + { + title: t('reports.account.table.thisMonthAmount'), + dataIndex: 'thisMonthChangeAmount', + width: 120, + }, + { + title: t('reports.account.table.currentAmount'), + dataIndex: 'currentAmount', + width: 120, + }, +] + +export const searchAccountSchema: FormSchema[] = [ + { + label: t('reports.account.header.account'), + field: 'accountName', + component: 'Input', + colProps: { span: 10 }, + }, + { + label: t('reports.account.header.accountNumber'), + field: 'accountNumber', + component: 'Input', + colProps: { span: 10 }, + }, +] + +export const accountFlowColumns: BasicColumn[] = [ + { + title: t('reports.shipmentsDetail.header.receiptNumber'), + dataIndex: 'receiptNumber', + width: 180, + }, + { + title: t('reports.shipmentsDetail.table.type'), + dataIndex: 'subType', + width: 80, + }, + { + title: t('reports.other.subType'), + dataIndex: 'useType', + width: 90, + }, + { + title: t('reports.storageDetail.table.name'), + dataIndex: 'name', + width: 120, + }, + { + title: t('reports.retail.table.amount'), + dataIndex: 'amount', + width: 110, + }, + { + title: t('reports.other.balance'), + dataIndex: 'balance', + width: 110, + }, + { + title: t('reports.retail.header.receiptDate'), + dataIndex: 'receiptDate', + width: 150, + } +] + +export const searchRetailSchema: FormSchema[] = [ + { + label: t('reports.retail.header.productInfo'), + field: 'productExtendInfo', + component: 'Input', + colProps: { span: 6 }, + }, + { + label: t('reports.purchase.header.warehouse'), + field: 'warehouseId', + component: 'ApiSelect', + componentProps: { + api: getWarehouseList, + resultField: 'data', + labelField: 'warehouseName', + valueField: 'id', + }, + colProps: { span: 6 }, + }, + { + label: t('reports.retail.header.member'), + field: 'memberId', + component: 'ApiSelect', + componentProps: { + api: getMemberList, + resultField: 'data', + labelField: 'memberName', + valueField: 'id', + }, + colProps: { span: 6 }, + }, + { + field: '[startDate, endDate]', + label: t('reports.retail.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.retail.header.startDate'), t('reports.retail.header.endDate')], + }, + colProps: { span: 6 }, + }, +] + +export const retailStatisticsColumns: BasicColumn[] = [ + { + title: t('reports.retail.table.barCode'), + dataIndex: 'productBarcode', + width: 100, + }, + { + title: t('reports.retail.table.warehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('reports.retail.table.name'), + dataIndex: 'productName', + width: 120, + }, + { + title: t('reports.retail.table.standard'), + dataIndex: 'productStandard', + width: 120, + }, + { + title: t('reports.retail.table.model'), + dataIndex: 'productModel', + width: 90, + }, + { + title: t('reports.retail.table.extendInfo'), + dataIndex: 'productExtendInfo', + width: 120, + }, + { + title: t('reports.retail.header.member'), + dataIndex: 'member', + width: 80, + }, + { + title: t('reports.retail.table.quantity'), + dataIndex: 'retailNumber', + width: 70, + }, + { + title: t('reports.retail.table.amount'), + dataIndex: 'retailAmount', + width: 70, + }, + { + title: t('reports.retail.table.refundQuantity'), + dataIndex: 'retailRefundNumber', + width: 70, + }, + { + title: t('reports.retail.table.refundAmount'), + dataIndex: 'retailRefundAmount', + width: 70, + }, + { + title: t('reports.retail.table.actualAmount'), + dataIndex: 'retailLastAmount', + width: 70, + } +] + + +export const searchPurchaseSchema: FormSchema[] = [ + { + label: t('reports.purchase.header.productInfo'), + field: 'productExtendInfo', + component: 'Input', + colProps: { span: 6 }, + }, + { + label: t('reports.purchase.header.warehouse'), + field: 'warehouseId', + component: 'ApiSelect', + componentProps: { + api: getWarehouseList, + resultField: 'data', + labelField: 'warehouseName', + valueField: 'id', + }, + colProps: { span: 6 }, + }, + { + label: t('reports.purchase.header.supplier'), + field: 'supplierId', + component: 'ApiSelect', + componentProps: { + api: getSupplierList, + resultField: 'data', + labelField: 'supplierName', + valueField: 'id', + }, + colProps: { span: 6 }, + }, + { + field: '[startDate, endDate]', + label: t('reports.purchase.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.purchase.header.startDate'), t('reports.purchase.header.endDate')], + }, + colProps: { span: 6 }, + }, +] + +export const purchaseStatisticsColumns: BasicColumn[] = [ + { + title: t('reports.purchase.table.barCode'), + dataIndex: 'productBarcode', + width: 100, + }, + { + title: t('reports.purchase.table.warehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('reports.purchase.table.name'), + dataIndex: 'productName', + width: 120, + }, + { + title: t('reports.purchase.header.supplier'), + dataIndex: 'supplier', + width: 120, + }, + { + title: t('reports.purchase.table.purchaseDate'), + dataIndex: 'createTime', + width: 110, + }, + { + title: t('reports.purchase.table.quantity'), + dataIndex: 'purchaseNumber', + width: 70, + }, + { + title: t('reports.purchase.table.amount'), + dataIndex: 'purchaseAmount', + width: 70, + }, + { + title: t('reports.purchase.table.refundQuantity'), + dataIndex: 'purchaseRefundNumber', + width: 70, + }, + { + title: t('reports.purchase.table.refundAmount'), + dataIndex: 'purchaseRefundAmount', + width: 70, + }, + { + title: t('reports.purchase.table.actualAmount'), + dataIndex: 'purchaseLastAmount', + width: 70, + } +] + +export const searchSalesSchema: FormSchema[] = [ + { + label: t('reports.sales.header.productInfo'), + field: 'productExtendInfo', + component: 'Input', + colProps: { span: 6 }, + }, + { + label: t('reports.purchase.header.warehouse'), + field: 'warehouseId', + component: 'ApiSelect', + componentProps: { + api: getWarehouseList, + resultField: 'data', + labelField: 'warehouseName', + valueField: 'id', + }, + colProps: { span: 6 }, + }, + { + label: t('reports.sales.header.customer'), + field: 'customerId', + component: 'ApiSelect', + componentProps: { + api: getCustomerList, + resultField: 'data', + labelField: 'customerName', + valueField: 'id', + }, + colProps: { span: 6 }, + }, + { + field: '[startDate, endDate]', + label: t('reports.sales.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.sales.header.startDate'), t('reports.sales.header.endDate')], + }, + colProps: { span: 6 }, + }, +] + +export const salesStatisticsColumns: BasicColumn[] = [ + { + title: t('reports.sales.table.barCode'), + dataIndex: 'productBarcode', + width: 100, + }, + { + title: t('reports.sales.table.warehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('reports.sales.table.name'), + dataIndex: 'productName', + width: 120, + }, + { + title: t('reports.sales.table.standard'), + dataIndex: 'productStandard', + width: 120, + }, + { + title: t('reports.sales.table.model'), + dataIndex: 'productModel', + width: 90, + }, + { + title: t('reports.sales.table.extendInfo'), + dataIndex: 'productExtendInfo', + width: 120, + }, + { + title: t('reports.sales.header.customer'), + dataIndex: 'customer', + width: 80, + }, + { + title: t('reports.sales.table.quantity'), + dataIndex: 'salesNumber', + width: 70, + }, + { + title: t('reports.sales.table.amount'), + dataIndex: 'salesAmount', + width: 70, + }, + { + title: t('reports.sales.table.refundQuantity'), + dataIndex: 'salesRefundNumber', + width: 70, + }, + { + title: t('reports.sales.table.refundAmount'), + dataIndex: 'salesRefundAmount', + width: 70, + }, + { + title: t('reports.sales.table.actualAmount'), + dataIndex: 'salesLastAmount', + width: 70, + } +] + +export const searchShipmentsDetailSchema: FormSchema[] = [ + { + label: t('reports.shipmentsDetail.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('reports.shipmentsDetail.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.shipmentsDetail.header.startDate'), t('reports.shipmentsDetail.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.shipmentsDetail.header.productInfo'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.shipmentsDetail.header.contact'), + field: 'relatedPersonId', + component: 'ApiSelect', + componentProps: { + api: getRelatedPerson, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.shipmentsDetail.header.warehouse'), + field: 'warehouseId', + component: 'ApiSelect', + componentProps: { + api: getWarehouseList, + resultField: 'data', + labelField: 'warehouseName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.shipmentsDetail.header.operator'), + field: 'operatorId', + component: 'ApiSelect', + componentProps: { + api: getOperatorList, + params: "所有", + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.shipmentsDetail.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const shipmentsDetailStatisticsColumns: BasicColumn[] = [ + { + title: t('reports.shipmentsDetail.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 170, + }, + { + title: t('reports.shipmentsDetail.table.type'), + dataIndex: 'type', + width: 70, + }, + { + title: t('reports.shipmentsDetail.table.contact'), + dataIndex: 'name', + width: 70, + }, + { + title: t('reports.shipmentsDetail.table.barCode'), + dataIndex: 'productBarcode', + width: 100, + }, + { + title: t('reports.shipmentsDetail.table.warehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('reports.shipmentsDetail.table.name'), + dataIndex: 'productName', + width: 120, + }, + { + title: t('reports.shipmentsDetail.table.standard'), + dataIndex: 'productStandard', + width: 120, + }, + { + title: t('reports.shipmentsDetail.table.model'), + dataIndex: 'productModel', + width: 90, + }, + { + title: t('reports.shipmentsDetail.table.unit'), + dataIndex: 'productUnit', + width: 60, + }, + { + title: t('reports.shipmentsDetail.table.quantity'), + dataIndex: 'productNumber', + width: 65, + }, + { + title: t('reports.shipmentsDetail.table.unitPrice'), + dataIndex: 'unitPrice', + width: 65, + }, + { + title: t('reports.shipmentsDetail.table.amount'), + dataIndex: 'amount', + width: 75, + }, + { + title: t('reports.shipmentsDetail.table.taxRate'), + dataIndex: 'taxRate', + width: 65, + }, + { + title: t('reports.shipmentsDetail.table.taxAmount'), + dataIndex: 'taxAmount', + width: 70, + }, + { + title: t('reports.shipmentsDetail.table.shipmentsDate'), + dataIndex: 'createTime', + width: 140, + }, +] + +export const searchStorageDetailSchema: FormSchema[] = [ + { + label: t('reports.storageDetail.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('reports.storageDetail.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.storageDetail.header.startDate'), t('reports.storageDetail.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.storageDetail.header.productInfo'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.storageDetail.header.contact'), + field: 'relatedPersonId', + component: 'ApiSelect', + componentProps: { + api: getRelatedPerson, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.storageDetail.header.warehouse'), + field: 'warehouseId', + component: 'ApiSelect', + componentProps: { + api: getWarehouseList, + resultField: 'data', + labelField: 'warehouseName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.storageDetail.header.operator'), + field: 'operatorId', + component: 'ApiSelect', + componentProps: { + api: getOperatorList, + params: "所有", + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.storageDetail.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const storageDetailStatisticsColumns: BasicColumn[] = [ + { + title: t('reports.storageDetail.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 170, + }, + { + title: t('reports.storageDetail.table.type'), + dataIndex: 'type', + width: 70, + }, + { + title: t('reports.storageDetail.table.contact'), + dataIndex: 'name', + width: 70, + }, + { + title: t('reports.storageDetail.table.barCode'), + dataIndex: 'productBarcode', + width: 100, + }, + { + title: t('reports.storageDetail.table.warehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('reports.storageDetail.table.name'), + dataIndex: 'productName', + width: 120, + }, + { + title: t('reports.storageDetail.table.standard'), + dataIndex: 'productStandard', + width: 120, + }, + { + title: t('reports.storageDetail.table.model'), + dataIndex: 'productModel', + width: 90, + }, + { + title: t('reports.storageDetail.table.unit'), + dataIndex: 'productUnit', + width: 80, + }, + { + title: t('reports.storageDetail.table.quantity'), + dataIndex: 'productNumber', + width: 65, + }, + { + title: t('reports.storageDetail.table.unitPrice'), + dataIndex: 'unitPrice', + width: 65, + }, + { + title: t('reports.storageDetail.table.amount'), + dataIndex: 'amount', + width: 65, + }, + { + title: t('reports.storageDetail.table.taxRate'), + dataIndex: 'taxRate', + width: 65, + }, + { + title: t('reports.storageDetail.table.taxAmount'), + dataIndex: 'taxAmount', + width: 65, + }, + { + title: t('reports.storageDetail.table.storageDate'), + dataIndex: 'createTime', + width: 140, + }, +] + +export const searchShipmentsSummarySchema: FormSchema[] = [ + { + label: t('reports.shipmentsSummary.header.productInfo'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('reports.shipmentsSummary.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.shipmentsSummary.header.startDate'), t('reports.shipmentsSummary.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.shipmentsSummary.header.contact'), + field: 'relatedPersonId', + component: 'ApiSelect', + componentProps: { + api: getRelatedPerson, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.shipmentsSummary.header.warehouse'), + field: 'warehouseId', + component: 'ApiSelect', + componentProps: { + api: getWarehouseList, + resultField: 'data', + labelField: 'warehouseName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const shipmentsSummaryStatisticsColumns: BasicColumn[] = [ + { + title: t('reports.shipmentsSummary.table.barCode'), + dataIndex: 'productBarcode', + width: 100, + }, + { + title: t('reports.shipmentsSummary.table.warehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('reports.shipmentsSummary.table.name'), + dataIndex: 'productName', + width: 120, + }, + { + title: t('reports.shipmentsSummary.table.category'), + dataIndex: 'productCategoryName', + width: 100, + }, + { + title: t('reports.shipmentsSummary.table.standard'), + dataIndex: 'productStandard', + width: 120, + }, + { + title: t('reports.shipmentsSummary.table.model'), + dataIndex: 'productModel', + width: 90, + }, + { + title: t('reports.shipmentsSummary.table.unit'), + dataIndex: 'productUnit', + width: 60, + }, + { + title: t('reports.shipmentsSummary.table.quantity'), + dataIndex: 'shipmentsNumber', + width: 65, + }, + { + title: t('reports.shipmentsSummary.table.amount'), + dataIndex: 'shipmentsAmount', + width: 65, + }, + { + title: t('reports.shipmentsSummary.table.shipmentsDate'), + dataIndex: 'createTime', + width: 140, + }, +] + +export const searchStorageSummarySchema: FormSchema[] = [ + { + label: t('reports.storageSummary.header.productInfo'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('reports.storageSummary.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.storageSummary.header.startDate'), t('reports.storageSummary.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.storageSummary.header.contact'), + field: 'relatedPersonId', + component: 'ApiSelect', + componentProps: { + api: getRelatedPerson, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.storageSummary.header.warehouse'), + field: 'warehouseId', + component: 'ApiSelect', + componentProps: { + api: getWarehouseList, + resultField: 'data', + labelField: 'warehouseName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const storageSummaryStatisticsColumns: BasicColumn[] = [ + { + title: t('reports.storageSummary.table.barCode'), + dataIndex: 'productBarcode', + width: 100, + }, + { + title: t('reports.storageSummary.table.warehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('reports.storageSummary.table.name'), + dataIndex: 'productName', + width: 120, + }, + { + title: t('reports.storageSummary.table.category'), + dataIndex: 'productCategoryName', + width: 100, + }, + { + title: t('reports.storageSummary.table.standard'), + dataIndex: 'productStandard', + width: 120, + }, + { + title: t('reports.storageSummary.table.model'), + dataIndex: 'productModel', + width: 90, + }, + { + title: t('reports.storageSummary.table.unit'), + dataIndex: 'productUnit', + width: 60, + }, + { + title: t('reports.storageSummary.table.quantity'), + dataIndex: 'storageNumber', + width: 65, + }, + { + title: t('reports.storageSummary.table.amount'), + dataIndex: 'storageAmount', + width: 65, + }, + { + title: t('reports.storageSummary.table.storageDate'), + dataIndex: 'createTime', + width: 140, + }, +] + +export const searchCustomerBillSchema: FormSchema[] = [ + { + label: t('reports.customerBill.header.customer'), + field: 'customerId', + component: 'ApiSelect', + componentProps: { + api: getCustomerList, + resultField: 'data', + labelField: 'customerName', + valueField: 'id', + }, + colProps: { span: 7 }, + }, + { + field: '[startDate, endDate]', + label: t('reports.customerBill.header.billDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.customerBill.header.startDate'), t('reports.customerBill.header.endDate')], + }, + colProps: { + xl: 9, + xxl: 9, + }, + }, +] + +export const customerBillColumns: BasicColumn[] = [ + { + title: t('reports.customerBill.table.arrearsDetail'), + dataIndex: 'customerId', + width: 60, + }, + { + title: t('reports.customerBill.table.customer'), + dataIndex: 'customerName', + width: 100, + }, + { + title: t('reports.customerBill.table.contacts'), + dataIndex: 'contactName', + width: 80, + }, + { + title: t('reports.customerBill.table.contactNumber'), + dataIndex: 'contactPhone', + width: 100, + }, + { + title: t('reports.customerBill.table.email'), + dataIndex: 'email', + width: 110, + }, + { + title: t('reports.customerBill.table.firstQuarterCollection'), + dataIndex: 'firstQuarterReceivable', + width: 80, + }, + { + title: t('reports.customerBill.table.secondQuarterCollection'), + dataIndex: 'secondQuarterReceivable', + width: 80, + }, + { + title: t('reports.customerBill.table.thirdQuarterCollection'), + dataIndex: 'thirdQuarterReceivable', + width: 80, + }, + { + title: t('reports.customerBill.table.fourthQuarterCollection'), + dataIndex: 'fourthQuarterReceivable', + width: 80, + }, + { + title: t('reports.customerBill.table.totalArrears'), + dataIndex: 'totalQuarterArrears', + width: 100, + }, + { + title: t('reports.customerBill.table.totalCollection'), + dataIndex: 'totalQuarterReceivable', + width: 100, + }, + { + title: t('reports.customerBill.table.receivableArrears'), + dataIndex: 'remainingReceivableArrears', + width: 100, + helpMessage: t('reports.customerBill.table.helpMessage'), + }, +] + + +export const searchCustomerBillDetailSchema: FormSchema[] = [ + { + label: t('reports.storageDetail.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.storageSummary.header.productInfo'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('reports.customerBill.header.billDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.customerBill.header.startDate'), t('reports.customerBill.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, +] + +export const customerBillDetailColumns: BasicColumn[] = [ + { + title: t('reports.storageDetail.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 180, + }, + { + title: t('reports.customerBill.table.customer'), + dataIndex: 'customerName', + width: 120, + }, + { + title: t('reports.storageSummary.header.productInfo'), + dataIndex: 'productInfo', + width: 150, + }, + { + title: t('reports.storageSummary.header.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('reports.storageDetail.header.operator'), + dataIndex: 'operator', + width: 80, + }, + { + title: t('reports.other.thisReceiptArrears'), + dataIndex: 'thisReceiptArrears', + width: 65, + }, + { + title: t('reports.other.receivedArrears'), + dataIndex: 'receivedArrears', + width: 65, + }, + { + title: t('reports.other.receivableArrears'), + dataIndex: 'receivableArrears', + width: 65, + }, +] + +export const searchSupplierBillSchema: FormSchema[] = [ + { + label: t('reports.supplierBill.header.supplier'), + field: 'supplierId', + component: 'ApiSelect', + componentProps: { + api: getSupplierList, + resultField: 'data', + labelField: 'supplierName', + valueField: 'id', + }, + colProps: { span: 7 }, + }, + { + field: '[startDate, endDate]', + label: t('reports.supplierBill.header.billDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.supplierBill.header.startDate'), t('reports.supplierBill.header.endDate')], + }, + colProps: { + xl: 9, + xxl: 9, + }, + }, +] + +export const supplierBillColumns: BasicColumn[] = [ + { + title: t('reports.supplierBill.table.arrearsDetail'), + dataIndex: 'supplierId', + width: 60, + }, + { + title: t('reports.supplierBill.table.supplier'), + dataIndex: 'supplierName', + width: 100, + }, + { + title: t('reports.supplierBill.table.contacts'), + dataIndex: 'contactName', + width: 80, + }, + { + title: t('reports.supplierBill.table.contactNumber'), + dataIndex: 'contactPhone', + width: 100, + }, + { + title: t('reports.supplierBill.table.email'), + dataIndex: 'email', + width: 110, + }, + { + title: t('reports.supplierBill.table.firstQuarterPayment'), + dataIndex: 'firstQuarterPayment', + width: 80, + }, + { + title: t('reports.supplierBill.table.secondQuarterPayment'), + dataIndex: 'secondQuarterPayment', + width: 80, + }, + { + title: t('reports.supplierBill.table.thirdQuarterPayment'), + dataIndex: 'thirdQuarterPayment', + width: 80, + }, + { + title: t('reports.supplierBill.table.fourthQuarterPayment'), + dataIndex: 'fourthQuarterPayment', + width: 80, + }, + { + title: t('reports.supplierBill.table.totalArrears'), + dataIndex: 'totalArrears', + width: 100, + }, + { + title: t('reports.supplierBill.table.totalPayment'), + dataIndex: 'totalPayment', + width: 100, + }, + { + title: t('reports.supplierBill.table.payableArrears'), + dataIndex: 'remainingPaymentArrears', + width: 100, + helpMessage: t('reports.supplierBill.table.helpMessage'), + }, +] + +export const searchSupplierBillDetailSchema: FormSchema[] = [ + { + label: t('reports.storageDetail.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('reports.storageSummary.header.productInfo'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('reports.supplierBill.header.billDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('reports.supplierBill.header.startDate'), t('reports.supplierBill.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, +] + +export const supplierBillDetailColumns: BasicColumn[] = [ + { + title: t('reports.storageDetail.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 180, + }, + { + title: t('reports.supplierBill.table.supplier'), + dataIndex: 'supplierName', + width: 140, + }, + { + title: t('reports.storageSummary.header.productInfo'), + dataIndex: 'productInfo', + width: 150, + }, + { + title: t('reports.storageSummary.header.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('reports.storageDetail.header.operator'), + dataIndex: 'operator', + width: 70, + }, + { + title: t('reports.other.thisReceiptArrears'), + dataIndex: 'thisReceiptArrears', + width: 65, + }, + { + title: t('reports.other.paidArrears'), + dataIndex: 'prepaidArrears', + width: 65, + }, + { + title: t('reports.supplierBill.table.payableArrears'), + dataIndex: 'paymentArrears', + width: 65, + }, +] \ No newline at end of file diff --git a/src/views/report/retailStatistics.vue b/src/views/report/retailStatistics.vue new file mode 100644 index 0000000..f6bcfc9 --- /dev/null +++ b/src/views/report/retailStatistics.vue @@ -0,0 +1,155 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/saleStatistics.vue b/src/views/report/saleStatistics.vue new file mode 100644 index 0000000..1f33149 --- /dev/null +++ b/src/views/report/saleStatistics.vue @@ -0,0 +1,154 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/shipmentsDetail.vue b/src/views/report/shipmentsDetail.vue new file mode 100644 index 0000000..9c71028 --- /dev/null +++ b/src/views/report/shipmentsDetail.vue @@ -0,0 +1,187 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/shipmentsSummary.vue b/src/views/report/shipmentsSummary.vue new file mode 100644 index 0000000..08e9c56 --- /dev/null +++ b/src/views/report/shipmentsSummary.vue @@ -0,0 +1,143 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/storageDetail.vue b/src/views/report/storageDetail.vue new file mode 100644 index 0000000..490fc52 --- /dev/null +++ b/src/views/report/storageDetail.vue @@ -0,0 +1,191 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/storageSummary.vue b/src/views/report/storageSummary.vue new file mode 100644 index 0000000..bb23558 --- /dev/null +++ b/src/views/report/storageSummary.vue @@ -0,0 +1,144 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/report/supplierBill.vue b/src/views/report/supplierBill.vue new file mode 100644 index 0000000..52682a7 --- /dev/null +++ b/src/views/report/supplierBill.vue @@ -0,0 +1,180 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/retail/refund/components/AddEditModal.vue b/src/views/retail/refund/components/AddEditModal.vue new file mode 100644 index 0000000..333088d --- /dev/null +++ b/src/views/retail/refund/components/AddEditModal.vue @@ -0,0 +1,914 @@ + + + + + \ No newline at end of file diff --git a/src/views/retail/refund/components/ViewRefundModal.vue b/src/views/retail/refund/components/ViewRefundModal.vue new file mode 100644 index 0000000..b5c727d --- /dev/null +++ b/src/views/retail/refund/components/ViewRefundModal.vue @@ -0,0 +1,226 @@ + + + diff --git a/src/views/retail/refund/index.vue b/src/views/retail/refund/index.vue new file mode 100644 index 0000000..81b38f8 --- /dev/null +++ b/src/views/retail/refund/index.vue @@ -0,0 +1,242 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/retail/refund/refund.data.ts b/src/views/retail/refund/refund.data.ts new file mode 100644 index 0000000..7f0feef --- /dev/null +++ b/src/views/retail/refund/refund.data.ts @@ -0,0 +1,141 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; +import {getMemberList} from "@/api/basic/member"; +import {getAccountList} from "@/api/financial/account"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('retail.refund.table.member'), + dataIndex: 'memberName', + width: 60, + }, + { + title: t('retail.refund.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('retail.refund.table.productInformation'), + dataIndex: 'productInfo', + width: 80, + }, + { + title: t('retail.refund.table.totalAmount'), + dataIndex: 'totalPrice', + width: 60, + }, + { + title: t('retail.refund.table.paymentAmount'), + dataIndex: 'paymentAmount', + width: 80, + }, + { + title: t('retail.refund.table.changeAmount'), + dataIndex: 'backAmount', + width: 80, + }, + { + title: t('retail.refund.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('retail.refund.table.operator'), + dataIndex: 'operator', + width: 60, + }, + { + title: t('retail.refund.table.status'), + dataIndex: 'status', + width: 80, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('retail.refund.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('retail.refund.table.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('retail.refund.header.startDate'), t('retail.refund.header.endDate')], + }, + colProps: { span: 7 }, + }, + { + label: t('retail.refund.header.settlementAccount'), + field: 'accountId', + component: 'ApiSelect', + componentProps: { + api: getAccountList, + resultField: 'data', + labelField: 'accountName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('retail.refund.table.productInformation'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('retail.refund.table.member'), + field: 'memberId', + component: 'ApiSelect', + componentProps: { + api: getMemberList, + resultField: 'data', + labelField: 'memberName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('retail.refund.table.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('retail.refund.header.receiptRemark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] \ No newline at end of file diff --git a/src/views/retail/shipments/components/AddEditModal.vue b/src/views/retail/shipments/components/AddEditModal.vue new file mode 100644 index 0000000..6c28c9d --- /dev/null +++ b/src/views/retail/shipments/components/AddEditModal.vue @@ -0,0 +1,903 @@ + + + + + \ No newline at end of file diff --git a/src/views/retail/shipments/components/ViewShipmentModal.vue b/src/views/retail/shipments/components/ViewShipmentModal.vue new file mode 100644 index 0000000..8462f25 --- /dev/null +++ b/src/views/retail/shipments/components/ViewShipmentModal.vue @@ -0,0 +1,224 @@ + + + diff --git a/src/views/retail/shipments/index.vue b/src/views/retail/shipments/index.vue new file mode 100644 index 0000000..a9d74d7 --- /dev/null +++ b/src/views/retail/shipments/index.vue @@ -0,0 +1,245 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/retail/shipments/model/addEditModel.ts b/src/views/retail/shipments/model/addEditModel.ts new file mode 100644 index 0000000..e2be47c --- /dev/null +++ b/src/views/retail/shipments/model/addEditModel.ts @@ -0,0 +1,241 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; +import {useLocaleStore} from "@/store/modules/locale"; + +export const { t } = useI18n(); + +const amountSymbol = ref('') +const localeStore = useLocaleStore().getLocale; +if(localeStore === 'zh_CN') { + amountSymbol.value = '¥' +} else if (localeStore === 'en') { + amountSymbol.value = '$' +} + +interface FormState { + id: number | string | undefined; + warehouseId: number | string; + memberId: string; + receiptNumber: string; + paymentType: string; + remark: string; + receiptAmount: number; + paymentAmount: number; + scanBarCode: string; + otherReceipt: string; + collectAmount: number; + backAmount: number; + accountId: string; + receiptDate: string | undefined | Dayjs; +} + + +export interface RowVO { + [key: string]: any, + warehouseId: number | string, + barCode: number | string, + productName:string, + productStandard: string, + stock: number, + productUnit: string, + productNumber: number, + retailPrice: number, + amount: number, +} + +const xGrid = ref>() +const tableData = ref([]) +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + printConfig: { + columns: [ + { field: 'warehouseId' }, + { field: 'barCode' }, + { field: 'productName' }, + { field: 'productStandard' }, + { field: 'stockNumber' }, + { field: 'productUnit' }, + { field: 'productNumber' }, + { field: 'retailPrice' }, + { field: 'amount' }, + { field: 'remark' } + ] + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + refresh: false, // 显示刷新按钮 + export: true, // 显示导出按钮 + print: true, // 显示打印按钮 + zoom: true, // 显示全屏按钮 + custom: true // 显示自定义列按钮 + }, + columns: [ + { type: 'checkbox', field:'productId', title: 'ID', width: 80}, + { + field: 'warehouseId', + title: t('retail.shipments.form.table.warehouse'), + width: 130, + slots: { edit: 'warehouse_edit' }, + editRender: { name: '$select', options: [], props: { placeholder: t('retail.shipments.form.table.inputWarehouse') } } + }, + { field: 'barCode', + width:160, + title: t('retail.shipments.form.table.barCode'), + slots: { edit: 'barCode_edit' }, + titlePrefix: { content: t('retail.shipments.form.noticeThree') }, + editRender: { name: '$select', options: []} + }, + { + field: 'productName', + title: t('retail.shipments.form.table.name'), + width:160, + }, + { field: 'productStandard', title: t('retail.shipments.form.table.standard'), width: 120, }, + { field: 'stock', title: t('retail.shipments.form.table.stock'), width: 70}, + { field: 'productUnit', title: t('retail.shipments.form.table.unit'), width: 70}, + { field: 'productNumber', title: t('retail.shipments.form.table.quantity'), sortable: true, width:100, + slots: { edit: 'product_number_edit' }, + editRender: { name: '$input', props: { type: 'number', min: 1, max: 9999 } }, }, + { + field: 'retailPrice', + title: t('retail.shipments.form.table.unitPrice'), width:105, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入单价' } } + }, + { + field: 'amount', + title: t('retail.shipments.form.table.amount'), width:105, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'amount_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入金额' } } + }, + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('retail.shipments.form.table.total') + } + if (['amount', 'rate'].includes(column.field)) { + // 设置单价 = 金额 / 数量 设置保留两位小数 + data.forEach(item => { + const price = item.amount / item.productNumber + item.retailPrice = XEUtils.toFixed(price, 2) + }) + receiptAmount.value = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + collectAmount.value = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + paymentAmount.value = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + if (['productNumber', 'rate'].includes(column.field)) { + // 设置单价 = 金额 / 数量 + data.forEach(item => { + const price = item.amount / item.productNumber + item.retailPrice = XEUtils.toFixed(price, 2) + }) + return sumNum(data, column.field) + } + if (['productUnit', 'rate'].includes(column.field)) { + // 获取单价和数量进相乘计算赋值给金额 保留两位小数 + data.forEach(item => { + const amount = item.productNumber * item.retailPrice + item.amount = XEUtils.toFixed(amount, 2) + }) + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editRules: { + warehouseId: [ + { required: true, message: t('retail.shipments.form.noticeOne') } + ], + barCode: [ + { required: true, message: t('sales.shipments.form.table.inputBarCode') } + ] + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + } +}) +const receiptAmount = ref(''); +const collectAmount = ref(''); + +const paymentAmount = ref(''); +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} + +const formState = reactive({ + id: undefined, + warehouseId: '', + memberId: '', + receiptNumber: '', + paymentType: '', + remark: '', + receiptAmount: 0, + scanBarCode: '', + collectAmount: 0, + paymentAmount: 0, + backAmount: 0, + accountId: '', + receiptDate: '', + otherReceipt: '', +}); + +export { + formState, + gridOptions, + xGrid, + receiptAmount, + collectAmount, + paymentAmount, + tableData +} \ No newline at end of file diff --git a/src/views/retail/shipments/shipments.data.ts b/src/views/retail/shipments/shipments.data.ts new file mode 100644 index 0000000..59fe14a --- /dev/null +++ b/src/views/retail/shipments/shipments.data.ts @@ -0,0 +1,209 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; +import {getMemberList} from "@/api/basic/member"; +import {getAccountList} from "@/api/financial/account"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('retail.shipments.table.member'), + dataIndex: 'memberName', + width: 60, + }, + { + title: t('retail.shipments.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('retail.shipments.table.productInformation'), + dataIndex: 'productInfo', + width: 80, + }, + { + title: t('retail.shipments.table.productQuantity'), + dataIndex: 'productNumber', + width: 60, + }, + { + title: t('retail.shipments.table.totalAmount'), + dataIndex: 'totalPrice', + width: 60, + }, + { + title: t('retail.shipments.table.amountCollection'), + dataIndex: 'collectionAmount', + width: 80, + }, + { + title: t('retail.shipments.table.changeAmount'), + dataIndex: 'backAmount', + width: 80, + }, + { + title: t('retail.shipments.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('retail.shipments.table.operator'), + dataIndex: 'operator', + width: 60, + }, + { + title: t('retail.shipments.table.status'), + dataIndex: 'status', + width: 80, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('retail.shipments.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('retail.shipments.table.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('retail.shipments.header.startDate'), t('retail.shipments.header.endDate')], + }, + colProps: { span: 7 }, + }, + { + label: t('retail.shipments.header.settlementAccount'), + field: 'accountId', + component: 'ApiSelect', + componentProps: { + api: getAccountList, + resultField: 'data', + labelField: 'accountName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('retail.shipments.table.productInformation'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('retail.shipments.table.member'), + field: 'memberId', + component: 'ApiSelect', + componentProps: { + api: getMemberList, + resultField: 'data', + labelField: 'memberName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('retail.shipments.table.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('retail.shipments.header.receiptRemark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] + +export const retailShipmentsTableColumns: BasicColumn[] = [ + { + title: t('retail.shipments.view.member'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('retail.shipments.form.table.barCode'), + dataIndex: 'barCode', + width: 100, + }, + { + title: t('retail.shipments.form.table.name'), + dataIndex: 'productName', + width: 120, + }, + { + title: t('retail.shipments.form.table.standard'), + dataIndex: 'productStandard', + width: 120, + }, + { + title: t('retail.shipments.form.table.model'), + dataIndex: 'productModel', + width: 120, + }, + { + title: t('retail.shipments.form.table.color'), + dataIndex: 'productColor', + width: 70, + }, + { + title: t('retail.shipments.form.table.stock'), + dataIndex: 'stock', + width: 80, + }, + { + title: t('retail.shipments.form.table.unit'), + dataIndex: 'productUnit', + width: 60, + }, + { + title: t('retail.shipments.form.table.quantity'), + dataIndex: 'productNumber', + width: 60, + }, + { + title: t('retail.shipments.form.table.unitPrice'), + dataIndex: 'unitPrice', + width: 60, + }, + { + title: t('retail.shipments.form.table.amount'), + dataIndex: 'amount', + width: 60, + }, + { + title: t('retail.shipments.view.remark'), + dataIndex: 'remark', + width: 100, + }, +] \ No newline at end of file diff --git a/src/views/sales/model/addEditModel.ts b/src/views/sales/model/addEditModel.ts new file mode 100644 index 0000000..4ba5a65 --- /dev/null +++ b/src/views/sales/model/addEditModel.ts @@ -0,0 +1,481 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; +import {useLocaleStore} from "@/store/modules/locale"; + +const amountSymbol = ref('') +const localeStore = useLocaleStore().getLocale; +if(localeStore === 'zh_CN') { + amountSymbol.value = '¥' +} else if (localeStore === 'en') { + amountSymbol.value = '$' +} + +export const { t } = useI18n(); + +export interface RowVO { + [key: string]: any, + barCode: number | string, + productName:string, + productStandard: string, + stock: number, + productUnit: string, + productNumber: number, + unitPrice: number, + amount: number, + taxRate: number, + taxAmount: number, + taxTotalPrice: number, + remark: string, +} +interface SaleOrderFormState { + id: number | string | undefined; + customerId: string; + receiptNumber: string; + discountRate: number; + discountAmount: number; + discountLastAmount: number | string; + deposit: number; + remark: string; + operatorIds: number[]; + receiptDate: string | undefined | Dayjs; + warehouseId: number | string; + accountId: string | undefined; + multipleAccountIds: number[] | undefined; + multipleAccountAmounts: number[] | undefined; +} + +interface SaleShipmentsFormState { + id: number | string | undefined; + customerId: string; + accountId: number | string | undefined; + receiptNumber: string; + receiptDate: string | undefined | Dayjs; + otherReceipt: string; + collectOfferRate: number; + collectOfferAmount: number; + collectOfferLastAmount: number | string; + otherAmount: number; + thisCollectAmount: number; + thisArrearsAmount: number; + remark: string; + status: number | undefined; + operatorIds: number[]; + warehouseId: number | string; + multipleAccountIds: number[] | undefined; + multipleAccountAmounts: number[] | undefined; +} + +interface SaleRefundFormState { + id: number | string | undefined; + customerId: string; + accountId: number | string | undefined; + receiptNumber: string; + receiptDate: string | undefined | Dayjs; + otherReceipt: string; + refundOfferRate: number; + refundOfferAmount: number; + refundLastAmount: number | string; + otherAmount: number; + thisRefundAmount: number; + thisArrearsAmount: number; + remark: string; + status: number | undefined; + operatorIds: number[]; + warehouseId: number | string; + multipleAccountIds: number[] | undefined; + multipleAccountAmounts: number[] | undefined; +} + +const xGrid = ref>() +const tableData = ref([]) +const orderGridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + printConfig: { + columns: [ + { field: 'barCode' }, + { field: 'productName' }, + { field: 'productStandard' }, + { field: 'stockNumber' }, + { field: 'productUnit' }, + { field: 'productNumber' }, + { field: 'retailPrice' }, + { field: 'amount' }, + { field: 'remark' } + ] + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + refresh: true, // 显示刷新按钮 + print: true, // 显示打印按钮 + zoom: true, // 显示全屏按钮 + custom: true // 显示自定义列按钮 + }, + columns: [ + { type: 'checkbox', field:'productId', title: 'ID', width: 80}, + { + field: 'warehouseId', + title: t('sales.shipments.form.table.warehouse'), + width: 130, + slots: { edit: 'warehouse_edit', default: 'warehouse_default' }, + editRender: { name: 'input', attrs: { placeholder: t('sales.shipments.form.noticeEight') } } + }, + { field: 'barCode', + width:160, + title: t('sales.shipments.form.table.barCode'), + slots: { edit: 'barCode_edit' }, + titlePrefix: { content: '输入条码商品信息自动带出!' }, + editRender: { name: 'input', attrs: { placeholder: '请输入条码并回车' } } + }, + { + field: 'productName', + title: t('sales.shipments.form.table.name'), + width:160, + }, + { field: 'productStandard', title: t('sales.shipments.form.table.standard'), width: 90, }, + { field: 'stock', title: t('sales.shipments.form.table.stock'), width: 60}, + { field: 'productUnit', title: t('sales.shipments.form.table.unit'), width: 70}, + { field: 'productNumber', title: t('sales.shipments.form.table.quantity'), sortable: true, width:100, + slots: { edit: 'product_number_edit' }, + editRender: { name: '$input', props: { type: 'number', min: 1, max: 9999 } }, + }, + { + field: 'unitPrice', + title: t('sales.shipments.form.table.unitPrice'), width:105, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'price_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入单价' } } + }, + { + field: 'amount', + title: t('sales.shipments.form.table.amount'), width:105, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'amount_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入金额' } } + }, + { field: 'taxRate', title: t('sales.shipments.form.table.taxRate'), width: 120, + slots: { edit: 'tax_rate_edit' }, + editRender: { name: '$input', attrs: { type: 'float', digits: 2, placeholder: '请输入税率' } } + }, + { field: 'taxAmount', title: t('sales.shipments.form.table.taxAmount'), width: 125, + editRender:{attrs: {type: 'float', digits: 2}}, + slots: { edit: 'tax_amount_edit' }, + }, + { field: 'taxTotalPrice', title: t('sales.shipments.form.table.totalPriceAndTax'), width: 125, + slots: { edit: 'tax_total_price_edit' }, + editRender: { name: '$input', attrs: {type: 'float', digits: 2, placeholder: '请输入价税合计' } } + }, + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('sales.shipments.form.table.total') + } + if (['amount', 'rate'].includes(column.field)) { + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + if (['productNumber', 'rate'].includes(column.field)) { + return sumNum(data, column.field) + } + if (['taxAmount', 'rate'].includes(column.field)) { + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + + if (['taxTotalPrice', 'rate'].includes(column.field)) { + getTaxTotalPrice.value = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editRules: { + warehouseId: [ + { required: true, message: t('sales.shipments.form.noticeEight') } + ], + barCode: [ + { required: true, message: t('sales.shipments.form.table.inputBarCode') } + ] + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + } +}) + +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + printConfig: { + columns: [ + { field: 'barCode' }, + { field: 'productName' }, + { field: 'productStandard' }, + { field: 'stockNumber' }, + { field: 'productUnit' }, + { field: 'productNumber' }, + { field: 'retailPrice' }, + { field: 'amount' }, + { field: 'remark' } + ] + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + refresh: true, // 显示刷新按钮 + print: true, // 显示打印按钮 + zoom: true, // 显示全屏按钮 + custom: true // 显示自定义列按钮 + }, + columns: [ + { type: 'checkbox', field:'productId', title: 'ID', width: 80}, + { + field: 'warehouseId', + title: t('sales.shipments.form.table.warehouse'), + width: 130, + slots: { edit: 'warehouse_edit', default: 'warehouse_default' }, + editRender: { name: 'input', attrs: { placeholder: t('sales.shipments.form.noticeEight') } } + }, + { field: 'barCode', + width:160, + title: t('sales.shipments.form.table.barCode'), + slots: { edit: 'barCode_edit' }, + titlePrefix: { content: '输入条码商品信息自动带出!' }, + editRender: { name: 'input', attrs: { placeholder: '请输入条码并回车' } } + }, + { + field: 'productName', + title: t('sales.shipments.form.table.name'), + width:160, + }, + { field: 'productStandard', title: t('sales.shipments.form.table.standard'), width: 90, }, + { field: 'stock', title: t('sales.shipments.form.table.stock'), width: 60}, + { field: 'productUnit', title: t('sales.shipments.form.table.unit'), width: 70}, + { field: 'productNumber', title: t('sales.shipments.form.table.quantity'), sortable: true, width:100, + slots: { edit: 'product_number_edit' }, + editRender: { name: '$input', props: { type: 'number', min: 1, max: 9999 } }, + }, + { + field: 'unitPrice', + title: t('sales.shipments.form.table.unitPrice'), width:105, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'price_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入单价' } } + }, + { + field: 'amount', + title: t('sales.shipments.form.table.amount'), width:105, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'amount_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入金额' } } + }, + { field: 'taxRate', title: t('sales.shipments.form.table.taxRate'), width: 120, + slots: { edit: 'tax_rate_edit' }, + editRender: { name: '$input', attrs: { type: 'float', digits: 2, placeholder: '请输入税率' } } + }, + { field: 'taxAmount', title: t('sales.shipments.form.table.taxAmount'), width: 125, + editRender:{attrs: {type: 'float', digits: 2}}, + slots: { edit: 'tax_amount_edit' }, + }, + { field: 'taxTotalPrice', title: t('sales.shipments.form.table.totalPriceAndTax'), width: 125, + slots: { edit: 'tax_total_price_edit' }, + editRender: { name: '$input', attrs: {type: 'float', digits: 2, placeholder: '请输入价税合计' } } + }, + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('sales.shipments.form.table.total') + } + if (['amount', 'rate'].includes(column.field)) { + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + if (['productNumber', 'rate'].includes(column.field)) { + return sumNum(data, column.field) + } + if (['taxAmount', 'rate'].includes(column.field)) { + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + + if (['taxTotalPrice', 'rate'].includes(column.field)) { + getTaxTotalPrice.value = amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editRules: { + warehouseId: [ + { required: true, message: t('sales.shipments.form.noticeEight') } + ], + barCode: [ + { required: true, message: t('sales.shipments.form.table.inputBarCode') } + ] + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + } +}) + +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} + +const getTaxTotalPrice = ref(''); + +const formState = reactive({ + id: undefined, + customerId: '', + receiptNumber: '', + remark: '', + discountRate: 0, + discountAmount: 0, + discountLastAmount: 0, + deposit: 0, + accountId: undefined, + operatorIds: [], + receiptDate: '', + warehouseId: '', + multipleAccountIds: undefined, + multipleAccountAmounts: undefined, +}); + +const saleShipmentsFormState = reactive({ + id: undefined, + customerId: '', + receiptNumber: '', + otherReceipt: '', + remark: '', + collectOfferRate: 0, + collectOfferAmount: 0, + collectOfferLastAmount: 0, + otherAmount: 0, + thisCollectAmount: 0, + thisArrearsAmount: 0, + status: undefined, + accountId: undefined, + operatorIds: [], + receiptDate: '', + warehouseId: '', + multipleAccountIds: undefined, + multipleAccountAmounts: undefined, +}); + +const saleRefundFormState = reactive({ + id: undefined, + customerId: '', + receiptNumber: '', + otherReceipt: '', + remark: '', + refundOfferRate: 0, + refundOfferAmount: 0, + refundLastAmount: 0, + otherAmount: 0, + thisRefundAmount: 0, + thisArrearsAmount: 0, + status: undefined, + accountId: undefined, + operatorIds: [], + receiptDate: '', + warehouseId: '', + multipleAccountIds: undefined, + multipleAccountAmounts: undefined, +}); + +export { + xGrid, + sumNum, + tableData, + orderGridOptions, + gridOptions, + formState, + saleShipmentsFormState, + saleRefundFormState, + getTaxTotalPrice, +} \ No newline at end of file diff --git a/src/views/sales/order/components/AddEditModal.vue b/src/views/sales/order/components/AddEditModal.vue new file mode 100644 index 0000000..c5c989b --- /dev/null +++ b/src/views/sales/order/components/AddEditModal.vue @@ -0,0 +1,1098 @@ + + + + + \ No newline at end of file diff --git a/src/views/sales/order/components/ViewSaleOrderModal.vue b/src/views/sales/order/components/ViewSaleOrderModal.vue new file mode 100644 index 0000000..6f7e700 --- /dev/null +++ b/src/views/sales/order/components/ViewSaleOrderModal.vue @@ -0,0 +1,207 @@ + + + diff --git a/src/views/sales/order/index.vue b/src/views/sales/order/index.vue new file mode 100644 index 0000000..5ec9fe5 --- /dev/null +++ b/src/views/sales/order/index.vue @@ -0,0 +1,240 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/sales/order/sales.data.ts b/src/views/sales/order/sales.data.ts new file mode 100644 index 0000000..014d28e --- /dev/null +++ b/src/views/sales/order/sales.data.ts @@ -0,0 +1,213 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; +import {getCustomerList} from "@/api/basic/customer"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('sales.order.table.customer'), + dataIndex: 'customerName', + width: 60, + }, + { + title: t('sales.order.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('sales.order.table.productInformation'), + dataIndex: 'productInfo', + width: 80, + }, + { + title: t('sales.order.table.productQuantity'), + dataIndex: 'productNumber', + width: 80, + }, + { + title: t('sales.order.table.totalAmount'), + dataIndex: 'totalPrice', + width: 60, + }, + { + title: t('sales.order.table.totalIncludingTax'), + dataIndex: 'taxRateTotalPrice', + width: 80, + }, + { + title: t('sales.order.table.collectDeposit'), + dataIndex: 'deposit', + width: 80, + }, + { + title: t('sales.order.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('sales.order.table.operator'), + dataIndex: 'operator', + width: 60, + }, + { + title: t('sales.order.table.status'), + dataIndex: 'status', + width: 80, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('sales.order.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('sales.order.table.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('sales.order.header.startDate'), t('sales.order.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('sales.order.table.customer'), + field: 'customerId', + component: 'ApiSelect', + componentProps: { + api: getCustomerList, + resultField: 'data', + labelField: 'customerName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('sales.order.table.productInformation'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('sales.order.table.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + { label: t('sales.partialSales'), value: 2, key: 2 }, + { label: t('sales.completeSales'), value: 3, key: 3 }, + ], + }, + }, + { + label: t('sales.order.header.receiptRemark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] + +export const TableColumns: BasicColumn[] = [ + { + title: t('sales.order.form.table.warehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('sales.order.form.table.barCode'), + dataIndex: 'barCode', + width: 150, + }, + { + title: t('sales.order.form.table.name'), + dataIndex: 'productName', + width: 150, + }, + { + title: t('sales.order.form.table.standard'), + dataIndex: 'productStandard', + width: 120, + }, + { + title: t('sales.order.form.table.model'), + dataIndex: 'productModel', + width: 120, + }, + { + title: t('sales.order.form.table.color'), + dataIndex: 'productColor', + width: 70, + }, + { + title: t('sales.order.form.table.stock'), + dataIndex: 'stock', + width: 80, + }, + { + title: t('sales.order.form.table.unit'), + dataIndex: 'productUnit', + width: 60, + }, + { + title: t('sales.order.form.table.quantity'), + dataIndex: 'productNumber', + width: 60, + }, + { + title: t('sales.order.form.table.unitPrice'), + dataIndex: 'unitPrice', + width: 60, + }, + { + title: t('sales.order.form.table.amount'), + dataIndex: 'amount', + width: 60, + }, + { + title: t('sales.order.form.table.taxRate'), + dataIndex: 'taxRate', + width: 60, + }, + { + title: t('sales.order.form.table.taxAmount'), + dataIndex: 'taxAmount', + width: 60, + }, + { + title: t('sales.order.form.table.totalPriceAndTax'), + dataIndex: 'taxTotalPrice', + width: 60, + }, + { + title: t('sales.order.form.table.remark'), + dataIndex: 'remark', + width: 100, + }, +] \ No newline at end of file diff --git a/src/views/sales/refund/components/AddEditModal.vue b/src/views/sales/refund/components/AddEditModal.vue new file mode 100644 index 0000000..70ea3b5 --- /dev/null +++ b/src/views/sales/refund/components/AddEditModal.vue @@ -0,0 +1,1245 @@ + + + + + \ No newline at end of file diff --git a/src/views/sales/refund/components/ViewSaleRefundModal.vue b/src/views/sales/refund/components/ViewSaleRefundModal.vue new file mode 100644 index 0000000..723f9cf --- /dev/null +++ b/src/views/sales/refund/components/ViewSaleRefundModal.vue @@ -0,0 +1,235 @@ + + + diff --git a/src/views/sales/refund/index.vue b/src/views/sales/refund/index.vue new file mode 100644 index 0000000..6e2d4cf --- /dev/null +++ b/src/views/sales/refund/index.vue @@ -0,0 +1,240 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/sales/refund/saleRefund.data.ts b/src/views/sales/refund/saleRefund.data.ts new file mode 100644 index 0000000..38d4331 --- /dev/null +++ b/src/views/sales/refund/saleRefund.data.ts @@ -0,0 +1,143 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; +import {getCustomerList} from "@/api/basic/customer"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('sales.refund.table.customer'), + dataIndex: 'customerName', + width: 60, + }, + { + title: t('sales.refund.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 140, + }, + { + title: t('sales.refund.table.productInformation'), + dataIndex: 'productInfo', + width: 80, + }, + { + title: t('sales.refund.table.productQuantity'), + dataIndex: 'productNumber', + width: 80, + }, + { + title: t('sales.refund.table.totalAmount'), + dataIndex: 'totalAmount', + width: 60, + }, + { + title: t('sales.refund.table.totalIncludingTax'), + dataIndex: 'taxIncludedAmount', + width: 80, + }, + { + title: t('sales.refund.table.refundAmount'), + dataIndex: 'refundTotalAmount', + width: 80, + }, + { + title: t('sales.refund.view.thisTimeReturnAmount'), + dataIndex: 'thisRefundAmount', + width: 80, + }, + { + title: t('sales.refund.view.thisTimeArrearsAmount'), + dataIndex: 'thisArrearsAmount', + width: 80, + }, + { + title: t('sales.refund.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('sales.refund.table.operator'), + dataIndex: 'operator', + width: 60, + }, + { + title: t('sales.refund.table.status'), + dataIndex: 'status', + width: 80, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('sales.refund.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('sales.refund.table.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('sales.refund.header.startDate'), t('sales.refund.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('sales.refund.table.customer'), + field: t('sales.refund.table.customer'), + component: 'ApiSelect', + componentProps: { + api: getCustomerList, + resultField: 'data', + labelField: 'customerName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('sales.refund.table.productInformation'), + field: t('sales.refund.table.productInformation'), + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('sales.refund.table.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('sales.refund.header.receiptRemark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] \ No newline at end of file diff --git a/src/views/sales/shipments/components/AddEditModal.vue b/src/views/sales/shipments/components/AddEditModal.vue new file mode 100644 index 0000000..f651a0b --- /dev/null +++ b/src/views/sales/shipments/components/AddEditModal.vue @@ -0,0 +1,1259 @@ + + + + + \ No newline at end of file diff --git a/src/views/sales/shipments/components/ViewSaleShipmentsModal.vue b/src/views/sales/shipments/components/ViewSaleShipmentsModal.vue new file mode 100644 index 0000000..ed7b4b9 --- /dev/null +++ b/src/views/sales/shipments/components/ViewSaleShipmentsModal.vue @@ -0,0 +1,236 @@ + + + diff --git a/src/views/sales/shipments/index.vue b/src/views/sales/shipments/index.vue new file mode 100644 index 0000000..9ee9c1c --- /dev/null +++ b/src/views/sales/shipments/index.vue @@ -0,0 +1,240 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/sales/shipments/saleShipments.data.ts b/src/views/sales/shipments/saleShipments.data.ts new file mode 100644 index 0000000..7e01aaa --- /dev/null +++ b/src/views/sales/shipments/saleShipments.data.ts @@ -0,0 +1,143 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {useI18n} from "@/hooks/web/useI18n"; +import {getCustomerList} from "@/api/basic/customer"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('sales.shipments.table.customer'), + dataIndex: 'customerName', + width: 60, + }, + { + title: t('sales.shipments.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 140, + }, + { + title: t('sales.shipments.table.productInformation'), + dataIndex: 'productInfo', + width: 80, + }, + { + title: t('sales.shipments.table.productQuantity'), + dataIndex: 'productNumber', + width: 80, + }, + { + title: t('sales.shipments.table.totalAmount'), + dataIndex: 'totalAmount', + width: 60, + }, + { + title: t('sales.shipments.table.totalIncludingTax'), + dataIndex: 'taxIncludedAmount', + width: 80, + }, + { + title: t('sales.shipments.table.collectAmount'), + dataIndex: 'totalCollectAmount', + width: 80, + }, + { + title: t('sales.shipments.table.thisTimeCollectAmount'), + dataIndex: 'thisCollectAmount', + width: 80, + }, + { + title: t('sales.shipments.table.thisTimeArrearsAmount'), + dataIndex: 'thisArrearsAmount', + width: 80, + }, + { + title: t('sales.shipments.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('sales.shipments.table.operator'), + dataIndex: 'operator', + width: 60, + }, + { + title: t('sales.shipments.table.status'), + dataIndex: 'status', + width: 80, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('sales.shipments.table.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('sales.shipments.table.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('sales.shipments.header.startDate'), t('sales.shipments.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('sales.shipments.table.customer'), + field: 'customerId', + component: 'ApiSelect', + componentProps: { + api: getCustomerList, + resultField: 'data', + labelField: 'customerName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('sales.shipments.table.productInformation'), + field: 'productInfo', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('sales.shipments.table.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('sales.shipments.header.receiptRemark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + + } +] \ No newline at end of file diff --git a/src/views/sys/about/index.vue b/src/views/sys/about/index.vue new file mode 100644 index 0000000..1b2cf37 --- /dev/null +++ b/src/views/sys/about/index.vue @@ -0,0 +1,98 @@ + + diff --git a/src/views/sys/config/config.data.ts b/src/views/sys/config/config.data.ts new file mode 100644 index 0000000..29d7d01 --- /dev/null +++ b/src/views/sys/config/config.data.ts @@ -0,0 +1,85 @@ +import { FormSchema } from '/@/components/Form'; +import {useI18n} from "@/hooks/web/useI18n"; + +const colProps = { + span: 12, +}; + +const { t } = useI18n(); + +export const schemas: FormSchema[] = [ + { + field: 'id', + component: 'Input', + label: '系统配置id', + ifShow: false + }, + { + field: 'companyName', + component: 'Input', + label: t('system.configure.name'), + helpMessage: t('system.configure.noticeOne'), + colProps, + componentProps: { + placeholder: t('system.configure.inputName'), + }, + defaultValue: 'EAIRP', + required: true, + }, + { + field: 'companyContact', + component: 'Input', + label: t('system.configure.contact'), + colProps, + componentProps: { + placeholder: t('system.configure.inputContact'), + }, + }, + { + field: 'companyAddress', + component: 'Input', + label: t('system.configure.address'), + colProps, + componentProps: { + placeholder: t('system.configure.inputAddress'), + }, + }, + { + field: 'companyPhone', + component: 'Input', + label: t('system.configure.phone'), + colProps, + componentProps: { + placeholder: t('system.configure.inputPhone'), + }, + }, + { + field: 'companyFax', + component: 'Input', + label: t('system.configure.fax'), + colProps, + componentProps: { + placeholder: t('system.configure.inputFax'), + }, + }, + { + field: 'companyPostCode', + component: 'Input', + label: t('system.configure.postalCode'), + colProps, + componentProps: { + placeholder: t('system.configure.inputPostalCode'), + }, + }, + { + field: 'saleAgreement', + component: 'InputTextArea', + label: t('system.configure.salesProtocol'), + subLabel: t('system.configure.noticeTwo'), + colProps, + componentProps: { + placeholder: t('system.configure.inputSalesProtocol'), + rows: 4, + }, + }, +]; diff --git a/src/views/sys/config/index.vue b/src/views/sys/config/index.vue new file mode 100644 index 0000000..86ea1ef --- /dev/null +++ b/src/views/sys/config/index.vue @@ -0,0 +1,89 @@ + + + diff --git a/src/views/sys/department/components/DeptModal.vue b/src/views/sys/department/components/DeptModal.vue new file mode 100644 index 0000000..334b22f --- /dev/null +++ b/src/views/sys/department/components/DeptModal.vue @@ -0,0 +1,78 @@ + + + + + \ No newline at end of file diff --git a/src/views/sys/department/dept.data.ts b/src/views/sys/department/dept.data.ts new file mode 100644 index 0000000..1617f10 --- /dev/null +++ b/src/views/sys/department/dept.data.ts @@ -0,0 +1,119 @@ +import {BasicColumn, FormSchema} from "@/components/Table"; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; +import {getDeptList} from "@/api/sys/dept"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('system.department.table.name'), + dataIndex: 'deptName', + width: 160, + align: "left", + }, + { + title: t('system.department.table.number'), + dataIndex: 'deptNumber', + width: 160, + }, + { + title: t('system.department.table.manager'), + dataIndex: 'leader', + width: 160, + }, + { + title: t('system.department.table.status'), + dataIndex: 'status', + width: 80, + customRender: ({ record }) => { + const status = record.status; + const enable = ~~status === 0; + const color = enable ? 'green' : 'red'; + const text = enable ? t('system.department.form.enable') : t('system.department.form.disable'); + return h(Tag, { color: color }, () => text); + }, + }, + { + title: t('system.department.table.createTime'), + dataIndex: 'createTime', + width: 180, + }, + { + title: t('system.department.table.remark'), + dataIndex: 'remark', + width: 180 + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + field: 'deptName', + label: t('system.department.header.name'), + component: 'Input', + colProps: { span: 8 }, + } +] + +export const formSchema: FormSchema[] = [ + { + field: 'id', + label: '部门ID', + component: 'Input', + show: false, + }, + { + field: 'deptName', + label: t('system.department.form.name'), + component: 'Input', + required: true, + }, + { + field: 'deptNumber', + label: t('system.department.form.number'), + component: 'Input', + }, + { + field: 'parentId', + label: t('system.department.form.parent'), + component: 'ApiTreeSelect', + helpMessage: [t('system.department.form.notice')], + componentProps: { + api: getDeptList, + resultField: 'data', + labelField: 'deptName', + valueField: 'id', + childrenKeyField: 'children', + }, + }, + { + field: 'leader', + label: t('system.department.form.manager'), + component: 'Input', + }, + { + field: 'status', + label: t('system.department.form.status'), + component: 'RadioButtonGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: t('system.department.form.enable'), value: 0 }, + { label: t('system.department.form.disable'), value: 1 }, + ], + }, + required: true, + }, + + { + field: 'sort', + label: t('system.department.form.sort'), + component: 'InputNumber', + }, + { + label: t('system.department.form.remark'), + field: 'remark', + component: 'InputTextArea', + }, +]; \ No newline at end of file diff --git a/src/views/sys/department/index.vue b/src/views/sys/department/index.vue new file mode 100644 index 0000000..9755055 --- /dev/null +++ b/src/views/sys/department/index.vue @@ -0,0 +1,113 @@ + + + + diff --git a/src/views/sys/error-log/DetailModal.vue b/src/views/sys/error-log/DetailModal.vue new file mode 100644 index 0000000..2047707 --- /dev/null +++ b/src/views/sys/error-log/DetailModal.vue @@ -0,0 +1,27 @@ + + diff --git a/src/views/sys/error-log/data.tsx b/src/views/sys/error-log/data.tsx new file mode 100644 index 0000000..3ffc2f4 --- /dev/null +++ b/src/views/sys/error-log/data.tsx @@ -0,0 +1,67 @@ +import { Tag } from 'ant-design-vue'; +import { BasicColumn } from '/@/components/Table/index'; +import { ErrorTypeEnum } from '/@/enums/exceptionEnum'; +import { useI18n } from '/@/hooks/web/useI18n'; + +const { t } = useI18n(); + +export function getColumns(): BasicColumn[] { + return [ + { + dataIndex: 'type', + title: t('sys.errorLog.tableColumnType'), + width: 80, + customRender: ({ text }) => { + const color = + text === ErrorTypeEnum.VUE + ? 'green' + : text === ErrorTypeEnum.RESOURCE + ? 'cyan' + : text === ErrorTypeEnum.PROMISE + ? 'blue' + : ErrorTypeEnum.AJAX + ? 'red' + : 'purple'; + return {() => text}; + }, + }, + { + dataIndex: 'url', + title: 'URL', + width: 200, + }, + { + dataIndex: 'time', + title: t('sys.errorLog.tableColumnDate'), + width: 160, + }, + { + dataIndex: 'file', + title: t('sys.errorLog.tableColumnFile'), + width: 200, + }, + { + dataIndex: 'name', + title: 'Name', + width: 200, + }, + { + dataIndex: 'message', + title: t('sys.errorLog.tableColumnMsg'), + width: 300, + }, + { + dataIndex: 'stack', + title: t('sys.errorLog.tableColumnStackMsg'), + }, + ]; +} + +export function getDescSchema(): any { + return getColumns().map((column) => { + return { + field: column.dataIndex!, + label: column.title, + }; + }); +} diff --git a/src/views/sys/error-log/index.vue b/src/views/sys/error-log/index.vue new file mode 100644 index 0000000..049dd30 --- /dev/null +++ b/src/views/sys/error-log/index.vue @@ -0,0 +1,96 @@ + + + diff --git a/src/views/sys/exception/Exception.vue b/src/views/sys/exception/Exception.vue new file mode 100644 index 0000000..a8a6add --- /dev/null +++ b/src/views/sys/exception/Exception.vue @@ -0,0 +1,148 @@ + + diff --git a/src/views/sys/exception/index.ts b/src/views/sys/exception/index.ts new file mode 100644 index 0000000..5002c4a --- /dev/null +++ b/src/views/sys/exception/index.ts @@ -0,0 +1 @@ +export { default as Exception } from './Exception.vue'; diff --git a/src/views/sys/iframe/FrameBlank.vue b/src/views/sys/iframe/FrameBlank.vue new file mode 100644 index 0000000..99428bb --- /dev/null +++ b/src/views/sys/iframe/FrameBlank.vue @@ -0,0 +1,6 @@ + + diff --git a/src/views/sys/iframe/index.vue b/src/views/sys/iframe/index.vue new file mode 100644 index 0000000..ebf9fc4 --- /dev/null +++ b/src/views/sys/iframe/index.vue @@ -0,0 +1,90 @@ + + + diff --git a/src/views/sys/lock/LockPage.vue b/src/views/sys/lock/LockPage.vue new file mode 100644 index 0000000..1c53f40 --- /dev/null +++ b/src/views/sys/lock/LockPage.vue @@ -0,0 +1,236 @@ + + + diff --git a/src/views/sys/lock/index.vue b/src/views/sys/lock/index.vue new file mode 100644 index 0000000..e8c4d55 --- /dev/null +++ b/src/views/sys/lock/index.vue @@ -0,0 +1,13 @@ + + diff --git a/src/views/sys/lock/useNow.ts b/src/views/sys/lock/useNow.ts new file mode 100644 index 0000000..ee461fc --- /dev/null +++ b/src/views/sys/lock/useNow.ts @@ -0,0 +1,60 @@ +import { dateUtil } from '/@/utils/dateUtil'; +import { reactive, toRefs } from 'vue'; +import { tryOnMounted, tryOnUnmounted } from '@vueuse/core'; + +export function useNow(immediate = true) { + let timer: IntervalHandle; + + const state = reactive({ + year: 0, + month: 0, + week: '', + day: 0, + hour: '', + minute: '', + second: 0, + meridiem: '', + }); + + const update = () => { + const now = dateUtil(); + + const h = now.format('HH'); + const m = now.format('mm'); + const s = now.get('s'); + + state.year = now.get('y'); + state.month = now.get('M') + 1; + state.week = '星期' + ['日', '一', '二', '三', '四', '五', '六'][now.day()]; + state.day = now.get('date'); + state.hour = h; + state.minute = m; + state.second = s; + + state.meridiem = now.format('A'); + }; + + function start() { + update(); + clearInterval(timer); + timer = setInterval(() => update(), 1000); + } + + function stop() { + clearInterval(timer); + } + + tryOnMounted(() => { + immediate && start(); + }); + + tryOnUnmounted(() => { + stop(); + }); + + return { + ...toRefs(state), + start, + stop, + }; +} diff --git a/src/views/sys/login/EmailForm.vue b/src/views/sys/login/EmailForm.vue new file mode 100644 index 0000000..e5f8d1c --- /dev/null +++ b/src/views/sys/login/EmailForm.vue @@ -0,0 +1,98 @@ + + diff --git a/src/views/sys/login/ForgetPasswordForm.vue b/src/views/sys/login/ForgetPasswordForm.vue new file mode 100644 index 0000000..76777be --- /dev/null +++ b/src/views/sys/login/ForgetPasswordForm.vue @@ -0,0 +1,151 @@ + + diff --git a/src/views/sys/login/Login.vue b/src/views/sys/login/Login.vue new file mode 100644 index 0000000..f83542d --- /dev/null +++ b/src/views/sys/login/Login.vue @@ -0,0 +1,223 @@ + + + \ No newline at end of file diff --git a/src/views/sys/login/LoginForm.vue b/src/views/sys/login/LoginForm.vue new file mode 100644 index 0000000..f892d1a --- /dev/null +++ b/src/views/sys/login/LoginForm.vue @@ -0,0 +1,205 @@ + + + + + diff --git a/src/views/sys/login/LoginFormTitle.vue b/src/views/sys/login/LoginFormTitle.vue new file mode 100644 index 0000000..cf4d1ba --- /dev/null +++ b/src/views/sys/login/LoginFormTitle.vue @@ -0,0 +1,26 @@ + + diff --git a/src/views/sys/login/MobileForm.vue b/src/views/sys/login/MobileForm.vue new file mode 100644 index 0000000..87d1356 --- /dev/null +++ b/src/views/sys/login/MobileForm.vue @@ -0,0 +1,98 @@ + + diff --git a/src/views/sys/login/QrCodeForm.vue b/src/views/sys/login/QrCodeForm.vue new file mode 100644 index 0000000..d0860bd --- /dev/null +++ b/src/views/sys/login/QrCodeForm.vue @@ -0,0 +1,31 @@ + + diff --git a/src/views/sys/login/RegisterForm.vue b/src/views/sys/login/RegisterForm.vue new file mode 100644 index 0000000..8ec5e8d --- /dev/null +++ b/src/views/sys/login/RegisterForm.vue @@ -0,0 +1,158 @@ + + diff --git a/src/views/sys/login/SessionTimeoutLogin.vue b/src/views/sys/login/SessionTimeoutLogin.vue new file mode 100644 index 0000000..16abf97 --- /dev/null +++ b/src/views/sys/login/SessionTimeoutLogin.vue @@ -0,0 +1,54 @@ + + + diff --git a/src/views/sys/login/useLogin.ts b/src/views/sys/login/useLogin.ts new file mode 100644 index 0000000..8389429 --- /dev/null +++ b/src/views/sys/login/useLogin.ts @@ -0,0 +1,207 @@ +import type {ValidationRule, FormInstance} from 'ant-design-vue/lib/form/Form'; +import type {RuleObject, NamePath} from 'ant-design-vue/lib/form/interface'; +import {ref, computed, unref, Ref} from 'vue'; +import {useI18n} from '/@/hooks/web/useI18n'; +import CryptoJS from 'crypto-js'; + +export enum LoginStateEnum { + LOGIN, + REGISTER, + RESET_PASSWORD, + MOBILE, + QR_CODE, + EMAIL +} + +/** + * AES加密 + * @param plainText 明文 + * @param keyInBase64Str base64编码后的key + * @returns {string} base64编码后的密文 + */ +export function encryptByAES(plainText, keyInBase64Str) { + let key = CryptoJS.enc.Base64.parse(keyInBase64Str); + let encrypted = CryptoJS.AES.encrypt(plainText, key, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7, + }); + return encrypted.ciphertext.toString(CryptoJS.enc.Base64); +} + +/** + * AES解密 + * @param cipherText 密文 + * @param keyInBase64Str base64编码后的key + * @return 明文 + */ +export function decryptByAES(cipherText, keyInBase64Str) { + let key = CryptoJS.enc.Base64.parse(keyInBase64Str); + let decrypted = CryptoJS.AES.decrypt(cipherText, key, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7, + }); + + return decrypted.toString(CryptoJS.enc.Utf8); +} + +const currentState = ref(LoginStateEnum.LOGIN); + +// 这里也可以优化 +// import { createGlobalState } from '@vueuse/core' + +export function useLoginState() { + function setLoginState(state: LoginStateEnum) { + currentState.value = state; + } + + const getLoginState = computed(() => currentState.value); + + function handleBackLogin() { + setLoginState(LoginStateEnum.LOGIN); + } + + function handleBackMobileLogin() { + setLoginState(LoginStateEnum.MOBILE); + } + + return {setLoginState, getLoginState, handleBackLogin, handleBackMobileLogin}; +} + + +export function useFormValid(formRef: Ref) { + const validate = computed(() => { + const form = unref(formRef); + return form?.validate ?? ((_nameList?: NamePath) => Promise.resolve()); + }); + + async function validForm() { + const form = unref(formRef); + if (!form) return; + const data = await form.validate(); + return data as T; + } + + return {validate, validForm}; +} + + +export function useFormRules(formData?: Recordable) { + const {t} = useI18n(); + + const getAccountFormRule = computed(() => createRule(t('sys.login.accountPlaceholder'))); + const getPasswordFormRule = computed(() => createRule(t('sys.login.passwordPlaceholder'))); + const getCaptchaFormRule = computed(() => createRule(t('sys.login.captchaPlaceholder'))); + const getSmsFormRule = computed(() => createRule(t('sys.login.smsPlaceholder'))); + const getMobileFormRule = computed(() => phoneNumberRule()); + const getEmailFormRule = computed( () => emailRule()); + + const validatePolicy = async (_: RuleObject, value: boolean) => { + return !value ? Promise.reject(t('sys.login.policyPlaceholder')) : Promise.resolve(); + }; + + const validateConfirmPassword = (password: string) => { + return async (_: RuleObject, value: string) => { + if (!value) { + return Promise.reject(t('sys.login.passwordPlaceholder')); + } + if (value !== password) { + return Promise.reject(t('sys.login.diffPwd')); + } + return Promise.resolve(); + }; + }; + + const getFormRules = computed((): { [k: string]: ValidationRule | ValidationRule[] } => { + const accountFormRule = unref(getAccountFormRule); + const passwordFormRule = unref(getPasswordFormRule); + const captchaFormRule = unref(getCaptchaFormRule); + const smsFormRule = unref(getSmsFormRule); + const mobileFormRule = unref(getMobileFormRule); + const emailFormRule = unref(getEmailFormRule); + + const mobileRule = { + sms: smsFormRule, + mobile: mobileFormRule, + }; + switch (unref(currentState)) { + // register form rules + case LoginStateEnum.REGISTER: + return { + username: accountFormRule, + password: passwordFormRule, + phoneNumber: mobileFormRule, + captcha: captchaFormRule, + confirmPassword: [ + {validator: validateConfirmPassword(formData?.password), trigger: 'change'}, + ], + policy: [{validator: validatePolicy, trigger: 'change'}], + ...mobileRule, + }; + + // reset password form rules + case LoginStateEnum.RESET_PASSWORD: + return { + username: accountFormRule, + password: passwordFormRule, + phoneNumber: mobileFormRule, + sms: smsFormRule, + }; + + // mobile form rules + case LoginStateEnum.MOBILE: + return { + phoneNumber: mobileFormRule, + sms: smsFormRule, + }; + // email form rules + case LoginStateEnum.EMAIL: + return { + email: emailFormRule, + emailCode: smsFormRule, + } + + // login form rules + default: + return { + account: accountFormRule, + password: passwordFormRule, + captcha: captchaFormRule, + }; + } + }); + return {getFormRules}; +} + +function createRule(message: string) { + return [ + { + required: true, + message, + trigger: 'change', + }, + ]; +} + +function phoneNumberRule() { + const {t} = useI18n(); + return [ + { + required: true, + pattern: /^(0|86|17951)?(13[0-9]|15[012356789]|16[6]|19[89]]|17[01345678]|18[0-9]|14[579])[0-9]{8}$/, + message: t('sys.login.correctMobilePlaceholder'), + trigger: 'change', + } + ]; +} + +function emailRule() { + const {t} = useI18n(); + return [ + { + required: true, + pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, + message: t('sys.login.correctEmailPlaceholder'), + trigger: 'change', + } + ]; +} diff --git a/src/views/sys/menu/MenuDrawer.vue b/src/views/sys/menu/MenuDrawer.vue new file mode 100644 index 0000000..70bd3ba --- /dev/null +++ b/src/views/sys/menu/MenuDrawer.vue @@ -0,0 +1,97 @@ + + + \ No newline at end of file diff --git a/src/views/sys/menu/index.vue b/src/views/sys/menu/index.vue new file mode 100644 index 0000000..fa2fc95 --- /dev/null +++ b/src/views/sys/menu/index.vue @@ -0,0 +1,120 @@ + + + + + \ No newline at end of file diff --git a/src/views/sys/menu/menu.data.ts b/src/views/sys/menu/menu.data.ts new file mode 100644 index 0000000..51d04b1 --- /dev/null +++ b/src/views/sys/menu/menu.data.ts @@ -0,0 +1,211 @@ +import { BasicColumn, FormSchema } from '/@/components/Table'; +import { h } from 'vue'; +import { Tag } from 'ant-design-vue'; +import Icon from '@/components/Icon/Icon.vue'; +import {getMenuList} from "@/api/sys/menu"; +import {ParentIdEnum} from "@/enums/appEnum"; +import {useI18n} from "@/hooks/web/useI18n"; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('system.menu.table.menuTitle'), + dataIndex: 'title', + width: 150, + align: 'left', + }, + { + title: t('system.menu.table.icon'), + dataIndex: 'icon', + width: 80, + customRender: ({ record }) => { + return h(Icon, { icon: record.icon }); + }, + }, + { + title: t('system.menu.table.path'), + dataIndex: 'path', + width: 180, + }, + { + title: t('system.menu.table.component'), + dataIndex: 'component', + width: 200, + }, + { + title: t('system.menu.table.sort'), + dataIndex: 'sort', + width: 50, + }, + { + title: t('system.menu.table.status'), + dataIndex: 'status', + width: 80, + customRender: ({ record }) => { + const status = record.status; + const enable = ~~status === 0; + const color = enable ? 'green' : 'red'; + const text = enable ? t('system.menu.form.enable') : t('system.menu.form.disable'); + return h(Tag, { color: color }, () => text); + }, + }, + { + title: t('system.menu.table.createTime'), + dataIndex: 'createTime', + width: 180, + }, +]; +const isMenu = (type: number) => type === 1; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'title', + label: t('system.menu.table.menuTitle'), + component: 'Input', + colProps: { span: 8 }, + }, + { + field: 'status', + label: t('system.menu.table.status'), + component: 'Select', + componentProps: { + options: [ + { label: t('system.menu.form.enable'), value: 0 }, + { label: t('system.menu.form.disable'), value: 1 }, + ], + }, + colProps: { span: 8 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'id', + label: '菜单ID', + component: 'Input', + show: false, + }, + { + field: 'menuType', + label: t('system.menu.form.menuType'), + component: 'RadioButtonGroup', + defaultValue: 1, + componentProps: { + options: [ + { label: t('system.menu.form.catalogue'), value: 0 }, + { label: t('system.menu.form.menu'), value: 1 }, + ], + }, + colProps: { lg: 24, md: 24 }, + }, + { + field: 'name', + label: t('system.menu.form.menuName'), + component: 'Input', + required: true, + }, + { + field: 'title', + label: t('system.menu.form.menuTitle'), + component: 'Input', + required: true, + }, + { + field: 'parentId', + label: t('system.menu.form.parent'), + component: 'ApiTreeSelect', + helpMessage: [t('system.menu.form.notice')], + componentProps: { + api: getMenuList, + resultField: 'data.data', + labelField: 'title', + valueField: 'id', + defaultValue: { + id: ParentIdEnum.DEFAULT, + parentId: -1, + label: t('system.menu.form.rootMenu'), + value: ParentIdEnum.DEFAULT, + }, + }, + }, + { + field: 'sort', + label: t('system.menu.form.sort'), + component: 'InputNumber', + required: true, + }, + { + field: 'icon', + label: t('system.menu.form.icon'), + component: 'IconPicker', + required: true, + }, + + { + field: 'path', + label: t('system.menu.form.routeAddress'), + component: 'Input', + required: true, + ifShow: ({ values }) => isMenu(values.menuType), + }, + { + field: 'component', + label: t('system.menu.form.componentPath'), + component: 'Input', + ifShow: ({ values }) => isMenu(values.menuType), + }, + { + field: 'status', + label: t('system.menu.form.status'), + component: 'RadioButtonGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: t('system.menu.form.enable'), value: 0 }, + { label: t('system.menu.form.disable'), value: 1 }, + ], + }, + }, + { + field: 'blank', + label: t('system.menu.form.isExternalLink'), + component: 'RadioButtonGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: t('system.menu.form.no'), value: 0 }, + { label: t('system.menu.form.yes'), value: 1 }, + ], + }, + ifShow: ({ values }) => isMenu(values.menuType), + }, + + { + field: 'ignoreKeepAlive', + label: t('system.menu.form.isCached'), + component: 'RadioButtonGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: t('system.menu.form.no'), value: 0 }, + { label: t('system.menu.form.yes'), value: 1 }, + ], + }, + ifShow: ({ values }) => isMenu(values.menuType), + }, + + { + field: 'hideMenu', + label: t('system.menu.form.isDisplayed'), + component: 'RadioButtonGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: t('system.menu.form.yes'), value: 0 }, + { label: t('system.menu.form.no'), value: 1 }, + ], + }, + ifShow: ({ values }) => isMenu(values.menuType), + }, +]; diff --git a/src/views/sys/redirect/index.vue b/src/views/sys/redirect/index.vue new file mode 100644 index 0000000..9e6647b --- /dev/null +++ b/src/views/sys/redirect/index.vue @@ -0,0 +1,30 @@ + + diff --git a/src/views/sys/role/components/RoleDrawer.vue b/src/views/sys/role/components/RoleDrawer.vue new file mode 100644 index 0000000..1a7e8b0 --- /dev/null +++ b/src/views/sys/role/components/RoleDrawer.vue @@ -0,0 +1,72 @@ + + \ No newline at end of file diff --git a/src/views/sys/role/components/RolePermissionModal.vue b/src/views/sys/role/components/RolePermissionModal.vue new file mode 100644 index 0000000..2ecedaa --- /dev/null +++ b/src/views/sys/role/components/RolePermissionModal.vue @@ -0,0 +1,68 @@ + + diff --git a/src/views/sys/role/index.vue b/src/views/sys/role/index.vue new file mode 100644 index 0000000..232b064 --- /dev/null +++ b/src/views/sys/role/index.vue @@ -0,0 +1,134 @@ + + \ No newline at end of file diff --git a/src/views/sys/role/role.data.ts b/src/views/sys/role/role.data.ts new file mode 100644 index 0000000..fe8e1f6 --- /dev/null +++ b/src/views/sys/role/role.data.ts @@ -0,0 +1,163 @@ +import { BasicColumn, FormSchema } from '/@/components/Table'; +import { useI18n } from '/@/hooks/web/useI18n'; +import { h } from 'vue'; +import { Switch } from 'ant-design-vue'; +import { setRoleStatus } from '/@/api/sys/role'; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('system.role.table.roleName'), + dataIndex: 'roleName', + width: 150, + }, + { + title: t('system.role.table.type'), + dataIndex: 'type', + width: 120, + }, + { + title: t('system.role.table.priceBlocking'), + dataIndex: 'priceLimit', + width: 120, + customRender: ({record}) => { + if(record.priceLimit === 1) { + return t('system.role.header.blockPurchasePrice') + } else if(record.priceLimit === 2) { + return t('system.role.header.blockRetailPrice') + } else if(record.priceLimit === 3) { + return t('system.role.header.blockSalesPrice') + } + } + }, + { + title: t('system.role.table.status'), + dataIndex: 'status', + width: 120, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked: boolean) { + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + setRoleStatus(record.id, newStatus) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + }, + }, + { + title: t('system.role.table.createTime'), + dataIndex: 'createTime', + width: 180, + }, + { + title: t('system.role.table.remark'), + dataIndex: 'description', + width: 180, + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'roleName', + label: t('system.role.header.roleName'), + component: 'Input', + colProps: { span: 8 }, + }, + { + field: 'status', + label: t('system.role.header.status'), + component: 'Select', + componentProps: { + options: [ + { label: t('system.role.header.enable'), value: 0 }, + { label: t('system.role.header.disable'), value: 1 }, + ], + }, + colProps: { span: 8 }, + }, +]; + +export const formSchema: FormSchema[] = [ + { + field: 'id', + label: '角色id', + show: false, + component: 'Input', + }, + { + field: 'roleName', + label: t('system.role.form.roleName'), + required: true, + component: 'Input', + }, + { + field: 'type', + label: t('system.role.form.type'), + required: true, + component: 'Select', + componentProps: { + options: [ + { label: t('system.role.header.viewAllData'), value: '全部数据' }, + { label: t('system.role.header.viewPersonalData'), value: '个人数据' }, + ], + }, + }, + { + field: 'priceLimit', + label: t('system.role.form.priceBlocking'), + component: 'Select', + componentProps: { + options: [ + { label: t('system.role.header.blockPurchasePrice'), value: 1, key: 1}, + { label: t('system.role.header.blockRetailPrice'), value: 2, key: 2 }, + { label: t('system.role.header.blockSalesPrice'), value: 3, key: 3 }, + ], + }, + }, + { + field: 'status', + label: t('system.role.form.status'), + component: 'RadioButtonGroup', + defaultValue: 0, + componentProps: { + options: [ + { label: t('system.role.header.enable'), value: 0 }, + { label: t('system.role.header.disable'), value: 1 }, + ], + }, + }, + { + label: t('system.role.form.remark'), + field: 'description', + component: 'InputTextArea', + }, +]; + +export const roleSchema: FormSchema[] = [ + { + field: 'id', + label: '角色id', + show: false, + component: 'Input', + }, + { + label: ' ', + field: 'menuIds', + slot: 'menu', + component: 'Input', + }, +] \ No newline at end of file diff --git a/src/views/sys/tenant/components/TenantModal.vue b/src/views/sys/tenant/components/TenantModal.vue new file mode 100644 index 0000000..9ffbd0d --- /dev/null +++ b/src/views/sys/tenant/components/TenantModal.vue @@ -0,0 +1,92 @@ + + diff --git a/src/views/sys/tenant/index.vue b/src/views/sys/tenant/index.vue new file mode 100644 index 0000000..30a7cc4 --- /dev/null +++ b/src/views/sys/tenant/index.vue @@ -0,0 +1,122 @@ + + diff --git a/src/views/sys/tenant/tenant.data.ts b/src/views/sys/tenant/tenant.data.ts new file mode 100644 index 0000000..fe5ed04 --- /dev/null +++ b/src/views/sys/tenant/tenant.data.ts @@ -0,0 +1,195 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { useI18n } from '@/hooks/web/useI18n'; +import { h } from 'vue'; +import { Switch } from 'ant-design-vue'; +import { useMessage } from '@/hooks/web/useMessage'; +import { updateStatus } from "@/api/sys/tenant"; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('sys.tenant.form.name'), + dataIndex: 'tenantName', + width: 120, + }, + { + title: t('sys.tenant.form.userNumLimit'), + dataIndex: 'userNumLimit', + width: 120, + }, + { + title: t('sys.tenant.form.type'), + dataIndex: 'type', + width: 120, + customRender: ({record}) => { + if(record.type === 0) { + return t('sys.tenant.form.free') + } else if(record.type === 1) { + return t('sys.tenant.form.pay') + } + } + }, + { + title: t('sys.tenant.form.expireTime'), + dataIndex: 'expireTime', + width: 180, + }, + { + title: t('sys.tenant.form.status'), + dataIndex: 'status', + width: 100, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked, _) { + const {createMessage} = useMessage(); + if (record.id == 1) { + createMessage.warn(t('common.notice')); + return; + } + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + updateStatus({id: record.id, status: newStatus} ) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + { + title: t('sys.tenant.form.remark'), + dataIndex: 'remark', + width: 120, + }, + { + title: t('common.createTime'), + dataIndex: 'createTime', + width: 180, + } +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'tenantName', + label: t('sys.tenant.form.name'), + component: 'Input', + colProps: { span: 8 }, + }, + { + field: 'type', + label: t('sys.tenant.form.type'), + component: 'Select', + componentProps: { + options: [ + { label: t('sys.tenant.form.free'), value: 0 }, + { label: t('sys.tenant.form.pay'), value: 1 }, + ], + }, + colProps: { span: 8 }, + }, + { + field: 'status', + label: t('sys.tenant.form.status'), + component: 'Select', + componentProps: { + options: [ + { label: t('system.role.header.enable'), value: 0 }, + { label: t('system.role.header.disable'), value: 1 }, + ], + }, + colProps: { span: 8 }, + }, +]; + +function isNotExist({ values }) { + return !Boolean(values.id) +} + +export const tenantFormSchema: FormSchema[] = [ + { + field: 'id', + label: '租户id', + show: false, + component: 'Input', + }, + { + field: 'username', + label: t('sys.login.userName'), + component: 'Input', + // 注意最好使用异步验证 + helpMessage: [t('sys.tenant.form.noticeThree')], + rules: [ + { + required: true, + message: '请输入用户名', + }, + ], + ifShow: isNotExist + }, + { + field: 'password', + label: t('sys.login.password'), + component: 'InputPassword', + required: false, + helpMessage: [t('sys.tenant.form.noticeTwo')], + ifShow: isNotExist + }, + { + field: 'tenantName', + label: t('sys.tenant.form.name'), + component: 'Input', + required: true, + }, + { + field: 'phoneNumber', + label: t('sys.login.mobile'), + component: 'Input', + required: true, + }, + { + field: 'userNumLimit', + label: t('sys.tenant.form.userNumLimit'), + component: 'InputNumber', + required: true, + }, + { + field: 'type', + label: t('sys.tenant.form.type'), + component: 'Select', + required: true, + componentProps: { + options: [ + { label: t('sys.tenant.form.free'), value: 0 }, + { label: t('sys.tenant.form.pay'), value: 1 }, + ], + }, + }, + { + field: 'expireTime', + component: 'DatePicker', + required: true, + helpMessage: [t('sys.tenant.form.noticeFour')], + label: t('sys.tenant.form.expireTime'), + }, + { + field: 'email', + label: t('sys.login.email'), + component: 'Input', + }, + { + field: 'remark', + label: t('sys.user.remake'), + component: 'InputTextArea', + }, +]; diff --git a/src/views/sys/user/account.data.ts b/src/views/sys/user/account.data.ts new file mode 100644 index 0000000..5e4f173 --- /dev/null +++ b/src/views/sys/user/account.data.ts @@ -0,0 +1,170 @@ +import { BasicColumn, FormSchema } from '@/components/Table'; +import { useI18n } from '@/hooks/web/useI18n'; +import { h } from 'vue'; +import { Switch } from 'ant-design-vue'; +import { useMessage } from '@/hooks/web/useMessage'; +import { updateStatus } from "@/api/sys/user"; +import {getDeptList} from "@/api/sys/dept"; +import { getRoleList } from "@/api/sys/role"; + +const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('sys.login.userName'), + dataIndex: 'username', + width: 120, + }, + { + title: t('sys.user.name'), + dataIndex: 'name', + width: 120, + }, + { + title: t('sys.user.roleName'), + dataIndex: 'roleName', + width: 120, + }, + { + title: t('sys.user.status'), + dataIndex: 'status', + width: 100, + customRender: ({ record }) => { + if (!Reflect.has(record, 'pendingStatus')) { + record.pendingStatus = false; + } + return h(Switch, { + checked: record.status === 0, + checkedChildren: t('common.on'), + unCheckedChildren: t('common.off'), + loading: record.pendingStatus, + onChange(checked, _) { + const {createMessage} = useMessage(); + if (record.id == 1) { + createMessage.warn(t('common.notice')); + return; + } + record.pendingStatus = true; + const newStatus = checked ? 0 : 1; + updateStatus({id: record.id, status: newStatus} ) + .then(() => { + record.status = newStatus; + }) + .finally(() => { + record.pendingStatus = false; + }); + }, + }); + } + }, + { + title: t('sys.login.email'), + dataIndex: 'email', + width: 120, + }, + { + title: t('sys.login.mobile'), + dataIndex: 'phoneNumber', + width: 120, + }, + { + title: t('common.createTime'), + dataIndex: 'createTime', + width: 180, + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'username', + label: t('sys.login.userName'), + component: 'Input', + colProps: { span: 8 }, + }, + { + field: 'name', + label: t('sys.user.name'), + component: 'Input', + colProps: { span: 8 }, + }, +]; + +function isNotExist({ values }) { + return !Boolean(values.id) +} + +export const accountFormSchema: FormSchema[] = [ + { + field: 'id', + label: '用户id', + show: false, + component: 'Input', + }, + { + field: 'username', + label: t('sys.login.userName'), + component: 'Input', + helpMessage: [t('sys.tenant.form.noticeThree')], + rules: [ + { + required: true, + message: '请输入用户名', + }, + ], + ifShow: isNotExist + }, + { + field: 'password', + label: t('sys.login.password'), + component: 'InputPassword', + required: false, + helpMessage: [t('sys.tenant.form.noticeTwo')], + ifShow: isNotExist + }, + { + field: 'deptId', + label: t('sys.user.department'), + component: 'ApiMultipleTreeSelect', + required: true, + componentProps: { + api: getDeptList, + resultField: 'data', + labelField: 'deptName', + valueField: 'id', + }, + }, + { + field: 'roleId', + label: t('sys.user.roleName'), + required: true, + component: 'ApiMultipleSelect', + componentProps: { + api: getRoleList, + resultField: 'data', + labelField: 'roleName', + valueField: 'id', + }, + }, + { + field: 'name', + label: t('sys.user.name'), + component: 'Input', + required: true, + }, + { + field: 'phoneNumber', + label: t('sys.login.mobile'), + component: 'Input', + required: true, + }, + { + field: 'email', + label: t('sys.login.email'), + component: 'Input', + }, + { + field: 'remark', + label: t('sys.user.remake'), + component: 'InputTextArea', + }, +]; diff --git a/src/views/sys/user/components/AccountDetail.vue b/src/views/sys/user/components/AccountDetail.vue new file mode 100644 index 0000000..65b0131 --- /dev/null +++ b/src/views/sys/user/components/AccountDetail.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/views/sys/user/components/AccountModal.vue b/src/views/sys/user/components/AccountModal.vue new file mode 100644 index 0000000..147fef4 --- /dev/null +++ b/src/views/sys/user/components/AccountModal.vue @@ -0,0 +1,89 @@ + + diff --git a/src/views/sys/user/components/DeptTree.vue b/src/views/sys/user/components/DeptTree.vue new file mode 100644 index 0000000..77091a0 --- /dev/null +++ b/src/views/sys/user/components/DeptTree.vue @@ -0,0 +1,45 @@ + + diff --git a/src/views/sys/user/index.vue b/src/views/sys/user/index.vue new file mode 100644 index 0000000..31b0256 --- /dev/null +++ b/src/views/sys/user/index.vue @@ -0,0 +1,165 @@ + + diff --git a/src/views/warehouse/addEditAssembleOrDisassemble.data.ts b/src/views/warehouse/addEditAssembleOrDisassemble.data.ts new file mode 100644 index 0000000..add33b1 --- /dev/null +++ b/src/views/warehouse/addEditAssembleOrDisassemble.data.ts @@ -0,0 +1,206 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; +import {useLocaleStore} from "@/store/modules/locale"; + +const amountSymbol = ref('') +const localeStore = useLocaleStore().getLocale; +if(localeStore === 'zh_CN') { + amountSymbol.value = '¥' +} else if (localeStore === 'en') { + amountSymbol.value = '$' +} + +export const { t } = useI18n(); + +export interface RowVO { + [key: string]: any, + type: string, + warehouseId: number | string, + warehouseName: string | undefined, + barCode: string | number, + productId: number |string, + productName: string, + productModel: string, + productUnit: string, + productStandard: string, + stock: number, + productNumber: number, + unitPrice: number, + amount: number, + remark: string, +} + +interface AssembleFormState { + id: number | string | undefined; + warehouseId: number | string; + receiptDate: string | undefined | Dayjs; + receiptNumber: string |undefined; + remark: string; +} + +interface DisAssembleFormState { + id: number | string | undefined; + warehouseId: number | string; + receiptDate: string | undefined | Dayjs; + receiptNumber: string |undefined; + remark: string; +} + +const xGrid = ref>() +const tableData = ref([]) +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + zoom: true, + custom: true + }, + columns: [ + { type: 'checkbox', field:'productId', title: 'ID', width: 80}, + { field: 'type', + width:100, + title: t('warehouse.assemble.form.table.productType'), + }, + { field: 'warehouseId', + width:120, + title: t('warehouse.assemble.form.table.warehouse'), + slots: { edit: 'warehouseId_edit',default: 'warehouseId_default' }, + editRender: {} + }, + { field: 'barCode', + width:160, + title: t('warehouse.assemble.form.table.barCode'), + slots: { edit: 'barCode_edit' }, + titlePrefix: { content: '输入条码商品信息自动带出!' }, + editRender: { name: 'input', attrs: { placeholder: '请输入条码并回车' } } + }, + { + field: 'productName', + title: t('warehouse.assemble.form.table.name'), + width:140, + }, + { field: 'productStandard', title: t('warehouse.assemble.form.table.standard'), width: 110, }, + { field: 'stock', title: t('warehouse.assemble.form.table.stock'), width: 70}, + { field: 'productUnit', title: t('warehouse.assemble.form.table.unit'), width: 70}, + { field: 'productNumber', title: t('warehouse.assemble.form.table.quantity'), width:80, + slots: { edit: 'product_number_edit' }, + editRender: { name: '$input', props: { type: 'number', min: 1, max: 9999 } }, }, + { + field: 'unitPrice', + title: t('warehouse.assemble.form.table.purchasePrice'), width:90, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'price_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入单价' } } + }, + { + field: 'amount', + title: t('warehouse.assemble.form.table.amount'), width:90, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'amount_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入金额' } } + }, + { field: 'remark', title: t('warehouse.assemble.form.table.remark'), editRender: { name: 'input', attrs: { placeholder: '请输入备注' } }, width: 150}, + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('warehouse.assemble.form.table.total') + } + if (['productNumber'].includes(column.field)) { + return sumNum(data, column.field) + } + if (['amount'].includes(column.field)) { + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + }, + editRules: { + warehouseId: [ + { required: true, message: t('warehouse.assemble.form.noticeThree') } + ], + barCode: [ + { required: true, message: t('warehouse.assemble.form.noticeFour') } + ], + }, +}) + +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} +const assembleFormState = reactive({ + id: undefined, + warehouseId: '', + receiptDate: '', + receiptNumber: '', + remark: '', +}); + +const disAssembleFormState = reactive({ + id: undefined, + warehouseId: '', + receiptDate: '', + receiptNumber: '', + remark: '', +}); + +export { + xGrid, + sumNum, + tableData, + gridOptions, + assembleFormState, + disAssembleFormState +} \ No newline at end of file diff --git a/src/views/warehouse/addEditStorageShipments.data.ts b/src/views/warehouse/addEditStorageShipments.data.ts new file mode 100644 index 0000000..cfe7f04 --- /dev/null +++ b/src/views/warehouse/addEditStorageShipments.data.ts @@ -0,0 +1,210 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; +import {useLocaleStore} from "@/store/modules/locale"; + +export const { t } = useI18n(); + +const amountSymbol = ref('') +const localeStore = useLocaleStore().getLocale; +if(localeStore === 'zh_CN') { + amountSymbol.value = '¥' +} else if (localeStore === 'en') { + amountSymbol.value = '$' +} + +export interface RowVO { + [key: string]: any, + warehouseId: number | string; + warehouseName: string | undefined, + barCode: string | number, + productId: number |string, + productName: string, + productModel: string, + productUnit: string, + productStandard: string, + stock: number, + productNumber: number, + unitPrice: number, + amount: number, + remark: string, +} + +interface OtherStorageFormState { + id: number | string | undefined; + warehouseId: number | string; + supplierId: number | string | undefined; + receiptDate: string | undefined | Dayjs; + receiptNumber: string |undefined; + remark: string; +} + +interface OtherShipmentFormState { + id: number | string | undefined; + warehouseId: number | string; + customerId: number | string | undefined; + receiptDate: string | undefined | Dayjs; + receiptNumber: string |undefined; + remark: string; +} + +const xGrid = ref>() +const tableData = ref([]) +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + export: true, + zoom: true, + custom: true + }, + columns: [ + { type: 'checkbox', field:'productId', title: 'ID', width: 80}, + { field: 'warehouseId', + width:120, + title: t('warehouse.otherStorage.form.table.warehouse'), + slots: { edit: 'warehouse_edit',default: 'warehouse_default' }, + editRender: {name: 'input', attrs: { placeholder: '请选择仓库' }} + }, + { field: 'barCode', + width:160, + title: t('warehouse.otherStorage.form.table.barCode'), + slots: { edit: 'barCode_edit' }, + titlePrefix: { content: '输入条码商品信息自动带出!' }, + editRender: { name: 'input', attrs: { placeholder: '请输入条码并回车' } } + }, + { + field: 'productName', + title: t('warehouse.otherStorage.form.table.name'), + width:140, + }, + { field: 'productStandard', title: t('warehouse.otherStorage.form.table.standard'), width: 110, }, + { field: 'stock', title: t('warehouse.otherStorage.form.table.stock'), width: 70}, + { field: 'productUnit', title: t('warehouse.otherStorage.form.table.unit'), width: 70}, + { field: 'productNumber', title: t('warehouse.otherStorage.form.table.quantity'), width:80, + slots: { edit: 'product_number_edit' }, + editRender: { name: '$input', props: { type: 'number', min: 1, max: 9999 } }, }, + { + field: 'unitPrice', + title: t('warehouse.otherStorage.form.table.unitPrice'), + width:90, + titlePrefix: { content: t('warehouse.otherStorage.form.noticeFive') }, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'price_edit' }, + editRender: { name: '$input', props: { type: 'float', digits: 2, placeholder: '输入单价' } } + }, + { + field: 'amount', + title: t('warehouse.otherStorage.form.table.amount'), + width:90, + titlePrefix: { content: t('warehouse.otherStorage.form.noticeFive') }, + formatter ({ cellValue }) { + return cellValue ? amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : '' + }, + slots: { edit: 'amount_edit' }, + editRender: { name: 'input', props: { type: 'float', digits: 2 }, } + }, + { field: 'remark', title: t('warehouse.otherStorage.view.remark'), editRender: { name: 'input', attrs: { placeholder: t('warehouse.otherStorage.form.table.inputRemark') } }, width: 150}, + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('warehouse.otherStorage.form.table.total') + } + if (['productNumber'].includes(column.field)) { + return sumNum(data, column.field) + } + if (['amount'].includes(column.field)) { + return amountSymbol.value + `${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + }, + editRules: { + warehouseId: [ + { required: true, message: t('warehouse.otherStorage.form.noticeThree') } + ], + barCode: [ + { required: true, message: t('warehouse.otherStorage.form.noticeFour') } + ], + }, +}) + +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} +const otherStorageFormState = reactive({ + id: undefined, + warehouseId: '', + supplierId: '', + receiptDate: '', + receiptNumber: '', + remark: '', +}); + +const otherShipmentFormState = reactive({ + id: undefined, + warehouseId: '', + customerId: '', + receiptDate: '', + receiptNumber: '', + remark: '', +}); + +export { + xGrid, + sumNum, + tableData, + gridOptions, + otherStorageFormState, + otherShipmentFormState +} \ No newline at end of file diff --git a/src/views/warehouse/allot/allotShipments.data.ts b/src/views/warehouse/allot/allotShipments.data.ts new file mode 100644 index 0000000..cd896ac --- /dev/null +++ b/src/views/warehouse/allot/allotShipments.data.ts @@ -0,0 +1,160 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getUserOperatorList} from "@/api/sys/user"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); +export const columns: BasicColumn[] = [ + { + title: t('warehouse.allotShipments.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('warehouse.allotShipments.table.productInfo'), + dataIndex: 'productInfo', + width: 150, + }, + { + title: t('warehouse.allotShipments.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('warehouse.allotShipments.table.productNumber'), + dataIndex: 'productNumber', + width: 100, + }, + { + title: t('warehouse.allotShipments.table.operator'), + dataIndex: 'operator', + width: 70, + }, + { + title: t('warehouse.allotShipments.table.status'), + dataIndex: 'status', + width: 70, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('warehouse.allotShipments.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('warehouse.allotShipments.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('warehouse.allotShipments.header.starDate'), t('warehouse.allotShipments.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('warehouse.allotShipments.header.operator'), + field: 'operatorId', + component: 'ApiSelect', + componentProps: { + api: getUserOperatorList, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('warehouse.allotShipments.header.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('warehouse.allotShipments.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const allotShipmentTableColumns: BasicColumn[] = [ + { + title: t('warehouse.allotShipments.form.table.outWarehouse'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('warehouse.allotShipments.form.table.inWarehouse'), + dataIndex: 'otherWarehouseName', + width: 100, + }, + { + title: t('warehouse.allotShipments.form.table.barCode'), + dataIndex: 'barCode', + width: 120, + }, + { + title: t('warehouse.allotShipments.form.table.name'), + dataIndex: 'productName', + width: 150, + }, + { + title: t('warehouse.allotShipments.form.table.standard'), + dataIndex: 'productStandard', + width: 100, + }, + { + title: t('warehouse.allotShipments.form.table.model'), + dataIndex: 'productModel', + width: 100, + }, + { + title: t('warehouse.allotShipments.form.table.extendInfo'), + dataIndex: 'productExtendInfo', + width: 150, + }, + { + title: t('warehouse.allotShipments.form.table.stock'), + dataIndex: 'stock', + width: 70, + }, + { + title: t('warehouse.allotShipments.form.table.unit'), + dataIndex: 'productUnit', + width: 70, + }, + { + title: t('warehouse.allotShipments.form.table.quantity'), + dataIndex: 'productNumber', + width: 70, + }, + { + title: t('warehouse.allotShipments.form.table.remark'), + dataIndex: 'remark', + width: 130, + }, +] \ No newline at end of file diff --git a/src/views/warehouse/allot/components/AddEditAllotShipmentsModal.vue b/src/views/warehouse/allot/components/AddEditAllotShipmentsModal.vue new file mode 100644 index 0000000..d81d32f --- /dev/null +++ b/src/views/warehouse/allot/components/AddEditAllotShipmentsModal.vue @@ -0,0 +1,668 @@ + + + + + \ No newline at end of file diff --git a/src/views/warehouse/allot/components/ViewAllotShipmentsModal.vue b/src/views/warehouse/allot/components/ViewAllotShipmentsModal.vue new file mode 100644 index 0000000..64eefc3 --- /dev/null +++ b/src/views/warehouse/allot/components/ViewAllotShipmentsModal.vue @@ -0,0 +1,160 @@ + + + diff --git a/src/views/warehouse/allot/components/addEditAllotShipments.data.ts b/src/views/warehouse/allot/components/addEditAllotShipments.data.ts new file mode 100644 index 0000000..fb6f861 --- /dev/null +++ b/src/views/warehouse/allot/components/addEditAllotShipments.data.ts @@ -0,0 +1,172 @@ +import {reactive, ref} from "vue"; +import XEUtils from "xe-utils"; +import {VxeGridInstance, VxeGridProps} from "vxe-table"; +import {Dayjs} from "dayjs"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export interface RowVO { + [key: string]: any, + warehouseId: number | string; + otherWarehouseId: number | string; + warehouseName: string | undefined, + barCode: string | number, + productId: number |string, + productName: string, + productModel: string, + productUnit: string, + productStandard: string, + stock: number, + productNumber: number, + salePrice: number, + unitPrice: number, + amount: number, + remark: string, +} + +interface AllotShipmentsFormState { + id: number | string | undefined; + warehouseId: number | string | undefined; + receiptDate: string | undefined | Dayjs; + receiptNumber: string |undefined; + remark: string; +} + +const xGrid = ref>() +const tableData = ref([]) +const gridOptions = reactive>({ + border: true, + showHeaderOverflow: true, + showOverflow: true, + showFooter: true, + keepSource: true, + id: 'full_edit', + height: 400, + rowConfig: { + keyField: 'id', + isHover: true + }, + columnConfig: { + resizable: true + }, + sortConfig: { + trigger: 'cell', + remote: true + }, + filterConfig: { + remote: true + }, + formConfig: { + titleWidth: 100, + titleAlign: 'right', + items: [ + ] + }, + toolbarConfig: { + slots: { + buttons: 'toolbar_buttons' + }, + zoom: true, + custom: true + }, + columns: [ + { type: 'checkbox', field:'productId', title: 'ID', width: 80}, + { field: 'warehouseId', + width:150, + title: t('warehouse.allotShipments.form.table.outWarehouse'), + slots: { edit: 'warehouse_edit',default: 'warehouse_default' }, + editRender: { name: 'input', attrs: { placeholder: t('warehouse.allotShipments.form.table.outWarehouse') } } + }, + { field: 'barCode', + width:160, + title: t('warehouse.allotShipments.form.table.barCode'), + slots: { edit: 'barCode_edit' }, + titlePrefix: { content: t('warehouse.allotShipments.form.noticeSex') }, + editRender: { name: 'input', attrs: { placeholder: '请输入条码并回车' } } + }, + { + field: 'productName', + title: t('warehouse.allotShipments.form.table.name'), + width:140, + }, + // { field: 'productStandard', title: t('warehouse.allotShipments.form.table.standard'), width: 110, }, + + { field: 'stock', title: t('warehouse.allotShipments.form.table.stock'), width: 70}, + { field: 'otherWarehouseId', + width:150, + title: t('warehouse.allotShipments.form.table.inWarehouse'), + slots: { edit: 'otherWarehouse_edit',default: 'otherWarehouse_default' }, + editRender: {} + }, + { field: 'salePrice', title: t('warehouse.allotShipments.form.table.salePrice'), width: 150, + slots: { edit: 'sale_price_edit',}, + editRender: { name: '$input', props: { type: 'number'} } }, + { field: 'productNumber', title: t('warehouse.allotShipments.form.table.quantity'), width:100, + slots: { edit: 'product_number_edit' }, + editRender: { name: '$input', props: { type: 'number', min: 1, max: 9999 } }, }, + { field: 'productUnit', title: t('warehouse.allotShipments.form.table.unit'), width: 70}, + { field: 'remark', title: t('warehouse.allotShipments.form.table.remark'), editRender: { name: 'input', attrs: { placeholder: t('warehouse.allotShipments.form.inputRemark') } }, width: 150}, + ], + footerMethod ({ columns, data }) { + return [ + columns.map((column, columnIndex) => { + if (columnIndex === 0) { + return t('warehouse.allotShipments.form.total') + } + if (['productNumber'].includes(column.field)) { + return sumNum(data, column.field) + } + if (['amount'].includes(column.field)) { + return `¥${XEUtils.commafy(XEUtils.toNumber(sumNum(data, column.field)), { digits: 2 })}` + } + return '' + }) + ] + }, + checkboxConfig: { + labelField: 'id', + reserve: true, + highlight: true, + range: true + }, + editConfig: { + trigger: 'click', + mode: 'row', + showStatus: true + }, + editRules: { + warehouseId: [ + { required: true, message: t('warehouse.allotShipments.form.noticeThree') } + ], + barCode: [ + { required: true, message: t('warehouse.allotShipments.form.noticeFour') } + ], + otherWarehouseId: [ + { required: true, message: t('warehouse.allotShipments.form.noticeFive') } + ] + }, +}) + +const sumNum = (list: RowVO[], field: string) => { + let count = 0 + list.forEach(item => { + count += Number(item[field]) + }) + return count +} +const allotShipmentsFormState = reactive({ + id: undefined, + receiptDate: '', + receiptNumber: '', + warehouseId: '', + remark: '', +}); + +export { + xGrid, + sumNum, + tableData, + gridOptions, + allotShipmentsFormState +} \ No newline at end of file diff --git a/src/views/warehouse/allot/index.vue b/src/views/warehouse/allot/index.vue new file mode 100644 index 0000000..382aaa0 --- /dev/null +++ b/src/views/warehouse/allot/index.vue @@ -0,0 +1,243 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/warehouse/assemble/assemble.data.ts b/src/views/warehouse/assemble/assemble.data.ts new file mode 100644 index 0000000..4844471 --- /dev/null +++ b/src/views/warehouse/assemble/assemble.data.ts @@ -0,0 +1,176 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getUserOperatorList} from "@/api/sys/user"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('warehouse.assemble.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('warehouse.assemble.table.productInfo'), + dataIndex: 'productInfo', + width: 150, + }, + { + title: t('warehouse.assemble.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('warehouse.assemble.table.productNumber'), + dataIndex: 'productNumber', + width: 100, + }, + { + title: t('warehouse.assemble.table.totalAmount'), + dataIndex: 'totalAmount', + width: 70, + }, + { + title: t('warehouse.assemble.table.operator'), + dataIndex: 'operator', + width: 70, + }, + { + title: t('warehouse.assemble.table.status'), + dataIndex: 'status', + width: 70, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('warehouse.assemble.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('warehouse.assemble.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('warehouse.assemble.header.starDate'), t('warehouse.assemble.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('warehouse.assemble.header.operator'), + field: 'operatorId', + component: 'ApiSelect', + componentProps: { + api: getUserOperatorList, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('warehouse.assemble.header.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('warehouse.assemble.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const assembleTableColumns: BasicColumn[] = [ + { + title: t('warehouse.assemble.view.productType'), + dataIndex: 'type', + width: 80, + }, + { + title: t('warehouse.assemble.view.warehouseName'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('warehouse.assemble.view.barCode'), + dataIndex: 'barCode', + width: 120, + }, + { + title: t('warehouse.assemble.view.productName'), + dataIndex: 'productName', + width: 150, + }, + { + title: t('warehouse.assemble.view.productStandard'), + dataIndex: 'productStandard', + width: 100, + }, + { + title: t('warehouse.assemble.view.productModel'), + dataIndex: 'productModel', + width: 100, + }, + { + title: t('warehouse.assemble.view.productExtendInfo'), + dataIndex: 'productExtendInfo', + width: 150, + }, + { + title: t('warehouse.assemble.view.stock'), + dataIndex: 'stock', + width: 70, + }, + { + title: t('warehouse.assemble.view.productUnit'), + dataIndex: 'productUnit', + width: 70, + }, + { + title: t('warehouse.assemble.view.productNumber'), + dataIndex: 'productNumber', + width: 70, + }, + { + title: t('warehouse.assemble.view.purchasePrice'), + dataIndex: 'unitPrice', + width: 70, + }, + { + title: t('warehouse.assemble.view.amount'), + dataIndex: 'amount', + width: 70, + }, + { + title: t('warehouse.assemble.view.remark'), + dataIndex: 'remark', + width: 130, + }, +] \ No newline at end of file diff --git a/src/views/warehouse/assemble/components/AddEditAssembleModal.vue b/src/views/warehouse/assemble/components/AddEditAssembleModal.vue new file mode 100644 index 0000000..c17936b --- /dev/null +++ b/src/views/warehouse/assemble/components/AddEditAssembleModal.vue @@ -0,0 +1,750 @@ + + + + + \ No newline at end of file diff --git a/src/views/warehouse/assemble/components/ViewAssembleModal.vue b/src/views/warehouse/assemble/components/ViewAssembleModal.vue new file mode 100644 index 0000000..178902f --- /dev/null +++ b/src/views/warehouse/assemble/components/ViewAssembleModal.vue @@ -0,0 +1,160 @@ + + + diff --git a/src/views/warehouse/assemble/index.vue b/src/views/warehouse/assemble/index.vue new file mode 100644 index 0000000..152c53b --- /dev/null +++ b/src/views/warehouse/assemble/index.vue @@ -0,0 +1,243 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/warehouse/disassemble/components/AddEditDisassembleModal.vue b/src/views/warehouse/disassemble/components/AddEditDisassembleModal.vue new file mode 100644 index 0000000..fc5d615 --- /dev/null +++ b/src/views/warehouse/disassemble/components/AddEditDisassembleModal.vue @@ -0,0 +1,754 @@ + + + + + \ No newline at end of file diff --git a/src/views/warehouse/disassemble/components/ViewDisassembleModal.vue b/src/views/warehouse/disassemble/components/ViewDisassembleModal.vue new file mode 100644 index 0000000..4e6814b --- /dev/null +++ b/src/views/warehouse/disassemble/components/ViewDisassembleModal.vue @@ -0,0 +1,160 @@ + + + diff --git a/src/views/warehouse/disassemble/disassemble.data.ts b/src/views/warehouse/disassemble/disassemble.data.ts new file mode 100644 index 0000000..49574a8 --- /dev/null +++ b/src/views/warehouse/disassemble/disassemble.data.ts @@ -0,0 +1,176 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getUserOperatorList} from "@/api/sys/user"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('warehouse.disassemble.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('warehouse.disassemble.table.productInfo'), + dataIndex: 'productInfo', + width: 150, + }, + { + title: t('warehouse.disassemble.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('warehouse.disassemble.table.productNumber'), + dataIndex: 'productNumber', + width: 100, + }, + { + title: t('warehouse.disassemble.table.totalAmount'), + dataIndex: 'totalAmount', + width: 70, + }, + { + title: t('warehouse.disassemble.table.operator'), + dataIndex: 'operator', + width: 70, + }, + { + title: t('warehouse.disassemble.table.status'), + dataIndex: 'status', + width: 70, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('warehouse.disassemble.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('warehouse.disassemble.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('warehouse.disassemble.header.starDate'), t('warehouse.disassemble.header.endDate')], + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('warehouse.disassemble.header.operator'), + field: 'operatorId', + component: 'ApiSelect', + componentProps: { + api: getUserOperatorList, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('warehouse.disassemble.header.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('warehouse.disassemble.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const disAssembleTableColumns: BasicColumn[] = [ + { + title: t('warehouse.assemble.view.productType'), + dataIndex: 'type', + width: 80, + }, + { + title: t('warehouse.assemble.view.warehouseName'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('warehouse.assemble.view.barCode'), + dataIndex: 'barCode', + width: 120, + }, + { + title: t('warehouse.assemble.view.productName'), + dataIndex: 'productName', + width: 150, + }, + { + title: t('warehouse.assemble.view.productStandard'), + dataIndex: 'productStandard', + width: 100, + }, + { + title: t('warehouse.assemble.view.productModel'), + dataIndex: 'productModel', + width: 100, + }, + { + title: t('warehouse.assemble.view.productExtendInfo'), + dataIndex: 'productExtendInfo', + width: 150, + }, + { + title: t('warehouse.assemble.view.stock'), + dataIndex: 'stock', + width: 70, + }, + { + title: t('warehouse.assemble.view.productUnit'), + dataIndex: 'productUnit', + width: 70, + }, + { + title: t('warehouse.assemble.view.productNumber'), + dataIndex: 'productNumber', + width: 70, + }, + { + title: t('warehouse.assemble.view.purchasePrice'), + dataIndex: 'unitPrice', + width: 70, + }, + { + title: t('warehouse.assemble.view.amount'), + dataIndex: 'amount', + width: 70, + }, + { + title: t('warehouse.assemble.view.remark'), + dataIndex: 'remark', + width: 130, + }, +] \ No newline at end of file diff --git a/src/views/warehouse/disassemble/index.vue b/src/views/warehouse/disassemble/index.vue new file mode 100644 index 0000000..1273ef6 --- /dev/null +++ b/src/views/warehouse/disassemble/index.vue @@ -0,0 +1,245 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/warehouse/shipments/components/AddEditOtherShipmentsModal.vue b/src/views/warehouse/shipments/components/AddEditOtherShipmentsModal.vue new file mode 100644 index 0000000..6d68a0a --- /dev/null +++ b/src/views/warehouse/shipments/components/AddEditOtherShipmentsModal.vue @@ -0,0 +1,735 @@ + + + + + \ No newline at end of file diff --git a/src/views/warehouse/shipments/components/ViewOtherShipmentsModal.vue b/src/views/warehouse/shipments/components/ViewOtherShipmentsModal.vue new file mode 100644 index 0000000..5af9577 --- /dev/null +++ b/src/views/warehouse/shipments/components/ViewOtherShipmentsModal.vue @@ -0,0 +1,175 @@ + + + diff --git a/src/views/warehouse/shipments/index.vue b/src/views/warehouse/shipments/index.vue new file mode 100644 index 0000000..ebb4275 --- /dev/null +++ b/src/views/warehouse/shipments/index.vue @@ -0,0 +1,242 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/warehouse/shipments/otherShipments.data.ts b/src/views/warehouse/shipments/otherShipments.data.ts new file mode 100644 index 0000000..8ef9646 --- /dev/null +++ b/src/views/warehouse/shipments/otherShipments.data.ts @@ -0,0 +1,189 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getCustomerList} from "@/api/basic/customer"; +import {getUserOperatorList} from "@/api/sys/user"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('warehouse.otherShipments.table.customer'), + dataIndex: 'customerName', + width: 170, + }, + { + title: t('warehouse.otherShipments.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('warehouse.otherShipments.table.productInfo'), + dataIndex: 'productInfo', + width: 150, + }, + { + title: t('warehouse.otherShipments.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('warehouse.otherShipments.table.productNumber'), + dataIndex: 'productNumber', + width: 100, + }, + { + title: t('warehouse.otherShipments.table.totalAmount'), + dataIndex: 'totalAmount', + width: 70, + }, + { + title: t('warehouse.otherShipments.table.operator'), + dataIndex: 'operator', + width: 70, + }, + { + title: t('warehouse.otherShipments.table.status'), + dataIndex: 'status', + width: 70, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('warehouse.otherShipments.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('warehouse.otherShipments.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('warehouse.otherShipments.header.starDate'), t('warehouse.otherShipments.header.endDate')], + }, + colProps: { span: 7 }, + }, + { + label: t('warehouse.otherShipments.header.customer'), + field: 'customerId', + component: 'ApiSelect', + componentProps: { + api: getCustomerList, + resultField: 'data', + labelField: 'customerName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('warehouse.otherShipments.header.operator'), + field: 'operatorId', + component: 'ApiSelect', + componentProps: { + api: getUserOperatorList, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('warehouse.otherShipments.header.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('warehouse.otherShipments.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const otherShipmentTableColumns: BasicColumn[] = [ + { + title: t('warehouse.otherStorage.view.warehouseName'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('warehouse.otherStorage.view.barCode'), + dataIndex: 'barCode', + width: 120, + }, + { + title: t('warehouse.otherStorage.view.productName'), + dataIndex: 'productName', + width: 150, + }, + { + title: t('warehouse.otherStorage.view.productStandard'), + dataIndex: 'productStandard', + width: 100, + }, + { + title: t('warehouse.otherStorage.view.productModel'), + dataIndex: 'productModel', + width: 100, + }, + { + title: t('warehouse.otherStorage.view.productExtendInfo'), + dataIndex: 'productExtendInfo', + width: 150, + }, + { + title: t('warehouse.otherStorage.view.stock'), + dataIndex: 'stock', + width: 70, + }, + { + title: t('warehouse.otherStorage.view.productUnit'), + dataIndex: 'productUnit', + width: 70, + }, + { + title: t('warehouse.otherStorage.view.productNumber'), + dataIndex: 'productNumber', + width: 70, + }, + { + title: t('warehouse.otherStorage.view.unitPrice'), + dataIndex: 'unitPrice', + width: 70, + }, + { + title: t('warehouse.otherStorage.view.amount'), + dataIndex: 'amount', + width: 70, + }, + { + title: t('warehouse.otherStorage.view.remark'), + dataIndex: 'remark', + width: 130, + }, +] \ No newline at end of file diff --git a/src/views/warehouse/storage/components/AddEditOtherStorageModal.vue b/src/views/warehouse/storage/components/AddEditOtherStorageModal.vue new file mode 100644 index 0000000..f95b962 --- /dev/null +++ b/src/views/warehouse/storage/components/AddEditOtherStorageModal.vue @@ -0,0 +1,723 @@ + + + + + \ No newline at end of file diff --git a/src/views/warehouse/storage/components/ViewOtherStorageModal.vue b/src/views/warehouse/storage/components/ViewOtherStorageModal.vue new file mode 100644 index 0000000..a86b277 --- /dev/null +++ b/src/views/warehouse/storage/components/ViewOtherStorageModal.vue @@ -0,0 +1,176 @@ + + + diff --git a/src/views/warehouse/storage/index.vue b/src/views/warehouse/storage/index.vue new file mode 100644 index 0000000..5467cff --- /dev/null +++ b/src/views/warehouse/storage/index.vue @@ -0,0 +1,242 @@ + +
    +
    + + \ No newline at end of file diff --git a/src/views/warehouse/storage/otherStorage.data.ts b/src/views/warehouse/storage/otherStorage.data.ts new file mode 100644 index 0000000..24cf690 --- /dev/null +++ b/src/views/warehouse/storage/otherStorage.data.ts @@ -0,0 +1,189 @@ +import {FormSchema} from "@/components/Form"; +import {BasicColumn} from "@/components/Table"; +import {getSupplierList} from "@/api/basic/supplier"; +import {getUserOperatorList} from "@/api/sys/user"; +import {useI18n} from "@/hooks/web/useI18n"; + +export const { t } = useI18n(); + +export const columns: BasicColumn[] = [ + { + title: t('warehouse.otherStorage.table.supplierName'), + dataIndex: 'supplierName', + width: 170, + }, + { + title: t('warehouse.otherStorage.table.receiptNumber'), + dataIndex: 'receiptNumber', + width: 130, + }, + { + title: t('warehouse.otherStorage.table.productInfo'), + dataIndex: 'productInfo', + width: 150, + }, + { + title: t('warehouse.otherStorage.table.receiptDate'), + dataIndex: 'receiptDate', + width: 130, + }, + { + title: t('warehouse.otherStorage.table.productNumber'), + dataIndex: 'productNumber', + width: 100, + }, + { + title: t('warehouse.otherStorage.table.totalAmount'), + dataIndex: 'totalAmount', + width: 70, + }, + { + title: t('warehouse.otherStorage.table.operator'), + dataIndex: 'operator', + width: 70, + }, + { + title: t('warehouse.otherStorage.table.status'), + dataIndex: 'status', + width: 70, + }, +] + +export const searchFormSchema: FormSchema[] = [ + { + label: t('warehouse.otherStorage.header.receiptNumber'), + field: 'receiptNumber', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + field: '[startDate, endDate]', + label: t('warehouse.otherStorage.header.receiptDate'), + component: 'RangePicker', + componentProps: { + format: 'YYYY/MM/DD', + placeholder: [t('warehouse.otherStorage.header.starDate'), t('warehouse.otherStorage.header.endDate')], + }, + colProps: { span: 7 }, + }, + { + label: t('warehouse.otherStorage.header.supplierName'), + field: 'supplierId', + component: 'ApiSelect', + componentProps: { + api: getSupplierList, + resultField: 'data', + labelField: 'supplierName', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('warehouse.otherStorage.header.operator'), + field: 'operatorId', + component: 'ApiSelect', + componentProps: { + api: getUserOperatorList, + resultField: 'data', + labelField: 'name', + valueField: 'id', + }, + colProps: { + xl: 8, + xxl: 8, + }, + }, + { + label: t('warehouse.otherStorage.header.status'), + field: 'status', + component: 'Select', + colProps: { + xl: 8, + xxl: 8, + }, + componentProps: { + options: [ + { label: t('sys.table.unaudited'), value: 0, key: 0 }, + { label: t('sys.table.audited'), value: 1, key: 1 }, + ], + }, + }, + { + label: t('warehouse.otherStorage.header.remark'), + field: 'remark', + component: 'Input', + colProps: { + xl: 8, + xxl: 8, + }, + } +] + +export const otherStorageTableColumns: BasicColumn[] = [ + { + title: t('warehouse.otherStorage.view.warehouseName'), + dataIndex: 'warehouseName', + width: 100, + }, + { + title: t('warehouse.otherStorage.view.barCode'), + dataIndex: 'barCode', + width: 120, + }, + { + title: t('warehouse.otherStorage.view.productName'), + dataIndex: 'productName', + width: 150, + }, + { + title: t('warehouse.otherStorage.view.productStandard'), + dataIndex: 'productStandard', + width: 100, + }, + { + title: t('warehouse.otherStorage.view.productModel'), + dataIndex: 'productModel', + width: 100, + }, + { + title: t('warehouse.otherStorage.view.productExtendInfo'), + dataIndex: 'productExtendInfo', + width: 150, + }, + { + title: t('warehouse.otherStorage.view.stock'), + dataIndex: 'stock', + width: 70, + }, + { + title: t('warehouse.otherStorage.view.productUnit'), + dataIndex: 'productUnit', + width: 70, + }, + { + title: t('warehouse.otherStorage.view.productNumber'), + dataIndex: 'productNumber', + width: 70, + }, + { + title: t('warehouse.otherStorage.view.unitPrice'), + dataIndex: 'unitPrice', + width: 70, + }, + { + title: t('warehouse.otherStorage.view.amount'), + dataIndex: 'amount', + width: 70, + }, + { + title: t('warehouse.otherStorage.view.remark'), + dataIndex: 'remark', + width: 130, + }, +] \ No newline at end of file diff --git a/src/views/workflow/bpmn/index.vue b/src/views/workflow/bpmn/index.vue new file mode 100644 index 0000000..9f34e41 --- /dev/null +++ b/src/views/workflow/bpmn/index.vue @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/src/views/workflow/bpmn/zh.ts b/src/views/workflow/bpmn/zh.ts new file mode 100644 index 0000000..21c9ded --- /dev/null +++ b/src/views/workflow/bpmn/zh.ts @@ -0,0 +1,271 @@ +const translations = { + + "Name":"名称", + "Value":"值", + "ID":"唯一标识(ID)", + "General":"基础属性", + + "Activate the create/remove space tool": "启动创建/删除空间工具", + "Activate the global connect tool": "启动全局连接工具", + "Activate the hand tool": "启动手动工具", + "Activate the lasso tool": "启动套索工具", + "Ad-hoc": "Ad-hoc子流程", + "Add Lane above": "添加到通道之上", + "Add Lane below": "添加到通道之下", + "Append ConditionIntermediateCatchEvent": "添加中间条件捕获事件", + "Append element": "添加元素", + "Append EndEvent": "添加结束事件", + "Append Gateway": "添加网关", + "Append Intermediate/Boundary Event": "添加中间/边界事件", + "Append MessageIntermediateCatchEvent": "添加消息中间捕获事件", + "Append ReceiveTask": "添加接收任务", + "Append SignalIntermediateCatchEvent": "添加信号中间捕获事件", + "Append Task": "添加任务", + "Append TimerIntermediateCatchEvent": "添加定时器中间捕获事件", + "Append compensation activity": "追加补偿活动", + "Append {type}": "追加 {type}", + "Boundary Event": "边界事件", + "Business Rule Task": "规则任务", + "Call Activity": "引用流程", + "Cancel Boundary Event": "取消边界事件", + "Cancel End Event": "取消结束事件", + "Change type": "更改类型", + "Collapsed Pool": "折叠池", + "Collection": "集合", + "Compensation Boundary Event": "补偿边界事件", + "Compensation End Event": "结束补偿事件", + "Compensation Intermediate Throw Event": "中间补偿抛出事件", + "Compensation Start Event": "补偿启动事件", + "Complex Gateway": "复杂网关", + "Conditional Boundary Event": "条件边界事件", + "Conditional Boundary Event (non-interrupting)": "条件边界事件 (非中断)", + "Conditional Flow": "条件流", + "Conditional Intermediate Catch Event": "中间条件捕获事件", + "Conditional Start Event": "条件启动事件", + "Conditional Start Event (non-interrupting)": "条件启动事件 (非中断)", + "Connect using Association": "文本关联", + "Connect using DataInputAssociation": "数据关联", + "Connect using Sequence/MessageFlow or Association": "消息关联", + "Create IntermediateThrowEvent/BoundaryEvent": "创建中间抛出/边界事件", + "Create DataObjectReference": "创建数据对象引用", + "Create DataStoreReference": "创建数据存储引用", + "Create element": "创建元素", + "Create EndEvent": "创建结束事件", + "Create Gateway": "创建网关", + "Create Group": "创建组", + "Create Intermediate/Boundary Event": "创建中间/边界事件", + "Create Pool/Participant": "创建池/参与者", + "Create StartEvent": "创建开始事件", + "Create Task": "创建任务", + "Create expanded SubProcess": "创建可折叠子流程", + "Create {type}": "创建 {type}", + "Data": "数据", + "Data Object Reference": "数据对象引用", + "Data Store Reference": "数据存储引用", + "Default Flow": "默认流", + "Divide into three Lanes": "分成三条通道", + "Divide into two Lanes": "分成两条通道", + "Empty Pool": "空泳道", + "Empty Pool (removes content)": "清空泳道(删除内容)", + "End Event": "结束事件", + "Error Boundary Event": "错误边界事件", + "Error End Event": "结束错误事件", + "Error Start Event": "错误启动事件", + "Escalation Boundary Event": "升级边界事件", + "Escalation Boundary Event (non-interrupting)": "升级边界事件 (非中断)", + "Escalation End Event": "结束升级事件", + "Escalation Intermediate Throw Event": "中间升级抛出事件", + "Escalation Start Event": "升级启动事件", + "Escalation Start Event (non-interrupting)": "升级启动事件 (非中断)", + "Events": "事件", + "Event Sub Process": "事件子流程", + "Event based Gateway": "事件网关", + "Exclusive Gateway": "独占网关", + "Expanded Pool": "展开泳道", + "Gateways": "网关", + "Inclusive Gateway": "包容网关", + "Intermediate Throw Event": "中间抛出事件", + "Link Intermediate Catch Event": "中间链接捕获事件", + "Link Intermediate Throw Event": "中间链接抛出事件", + "Loop": "循环", + "Manual Task": "手动任务", + "Message Boundary Event": "消息边界事件", + "Message Boundary Event (non-interrupting)": "消息边界事件 (非中断)", + "Message End Event": "结束消息事件", + "Message Intermediate Catch Event": "中间消息捕获事件", + "Message Intermediate Throw Event": "中间消息抛出事件", + "Message Start Event": "消息启动事件", + "Message Start Event (non-interrupting)": "消息启动事件 (非中断)", + "Parallel Gateway": "并行网关", + "Parallel Multi Instance": "并行多实例", + "Participants": "参与者", + "Participant Multiplicity": "参与者多重性", + "Receive Task": "接受任务", + "Remove": "移除", + "Script Task": "脚本任务", + "Send Task": "发送任务", + "Sequence Flow": "顺序流", + "Sequential Multi Instance": "串行多实例", + "Service Task": "服务任务", + "Signal Boundary Event": "信号边界事件", + "Signal Boundary Event (non-interrupting)": "信号边界事件 (非中断)", + "Signal End Event": "结束信号事件", + "Signal Intermediate Catch Event": "中间信号捕获事件", + "Signal Intermediate Throw Event": "中间信号抛出事件", + "Signal Start Event": "信号启动事件", + "Signal Start Event (non-interrupting)": "信号启动事件 (非中断)", + "Start Event": "开始事件", + "Sub Process": "子流程", + "Sub Processes": "子流程", + "Sub Process (collapsed)": "可折叠子流程", + "Sub Process (expanded)": "可展开子流程", + "Task": "任务", + "Tasks": "任务", + "Terminate End Event": "终止边界事件", + "Timer Boundary Event": "定时边界事件", + "Timer Boundary Event (non-interrupting)": "定时边界事件 (非中断)", + "Timer Intermediate Catch Event": "中间定时捕获事件", + "Timer Start Event": "定时启动事件", + "Timer Start Event (non-interrupting)": "定时启动事件 (非中断)", + "Transaction": "事务", + "User Task": "用户任务", + "already rendered {element}": "{element} 已呈现", + "diagram not part of bpmn:Definitions": "图表不是 bpmn:Definitions 的一部分", + "element required": "需要元素", + "correcting missing bpmnElement on {plane} to {rootElement}": "在 {plane} 上更正缺失的 bpmnElement 为 {rootElement}", + "element {element} referenced by {referenced}#{property} not yet drawn": "元素 {element} 的引用 {referenced}#{property} 尚未绘制", + "failed to import {element}": "{element} 导入失败", + "flow elements must be children of pools/participants": "元素必须是池/参与者的子级", + "more than {count} child lanes": "超过 {count} 条通道", + "missing {semantic}#attachedToRef": "在 {element} 中缺少 {semantic}#attachedToRef", + "multiple DI elements defined for {element}": "为 {element} 定义了多个 DI 元素", + "no bpmnElement referenced in {element}": "{element} 中没有引用 bpmnElement", + "no diagram to display": "没有要显示的图表", + "no shape type specified": "未指定形状类型", + "no parent for {element} in {parent}": "在 {element} 中没有父元素 {parent}", + "no process or collaboration to display": "没有可显示的流程或协作", + "out of bounds release": "越界释放", + "Version tag":"版本标记", + "Change element":"改变元素", + "Documentation":"文档", + "PROCESS":"流程", + "Element documentation":"元素文档说明", + "User assignment":"分配用户", + "History cleanup":"历史记录清理", + "Time to live":"历史记录生存时间", + "Tasklist":"任务列表", + "Candidate starter":"候选启动器", + "Candidate starter groups":"候选启动组", + "Specify more than one group as a comma separated list.":"多个组用','分隔.", + "Candidate starter users":"候选发起人", + "Specify more than one user as a comma separated list.":"多个用户用','分隔.", + "External task":"外部任务", + "Startable":"可启动(Startable)", + "Executable":"可直接执行", + "Job execution":"作业执行", + "Priority":"优先级", + "Forms":"表单", + "Execution listeners":"执行侦听器", + "Extension properties":"扩展属性", + "Event type":"事件类型", + "Listener type":"侦听器类型", + "Field injection":"字段注入", + "Start initiator":"开始发起人", + "Initiator":"发起人", + "Asynchronous continuations":"异步延续", + "Before":"之前", + "After":"之后", + "Inputs":"输入", + "Outputs":"输出", + "Local variable name":"局部变量名称", + "Assignment type":"分配类型", + "Format":"格式", + "Type":"类型", + "Expression":"表达式(Expression)", + "Script":"脚本(Script)", + "Delegate expression":"委托表达式(Delegate expression)", + "Java class":"Java类(Java class)", + "start":"开始(start)", + "end":"结束(end)", + "Start typing \"${}\" to create an expression.":"开始键入\"${}\"以创建表达式.", + "Process variable name":"过程变量名称", + "List values":"列表值", + "Map entries":"映射条目", + "Key":"键", + "Values":"值", + "Form reference":"引用表单ID", + "Binding":"结合", + "Version":"版本", + "Form fields":"表单字段", + "Form key":"表单ID", + "Embedded or External Task Forms":"拓展表单", + "Camunda Forms":"标准表单", + "Generated Task Forms":"内置表单", + "Refers to the process variable name":"指的是(引用)过程变量名称", + "Label":"标签", + "Default value":"默认值", + "Constraints":"限制", + "Properties":"属性", + "Config":"配置", + "Implementation":"实施", + "Field injections":"字段注入", + "Task listeners":"任务侦听器", + "Listener ID":"侦听器ID", + "Message":"消息", + "Global message reference":"引用全局消息ID", + "Result variable":"结果变量", + "Resource":"资源", + "External resource":"外部资源", + "Inline script":"内联脚本", + "Process variables":"过程变量", + "Global signal reference":"引用全局信号ID", + "Signal":"信号", + "Called element":"被调用元素", + "In mapping propagation":"在映射传播中", + "Propagate all variables":"传播所有变量", + "Out mapping propagation":"向外映射传播", + "In mappings":"在映射中", + "Source":"来源", + "Target":"目标", + "Local":"局部的(Local)", + "Out mappings":"输出映射", + "Link":"链接", + "Timer":"定时器", + "Retry time cycle":"重试时间周期", + "Variable name":"变量名称", + "Condition Expression":"条件表达式", + "Condition":"条件", + "Process documentation":"流程文档", + "Assignee":"委托人", + "Candidate groups":"候选组", + "Candidate users":"候选用户", + "Due date":"期限", + "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)", + "Follow up date":"跟进日期", + "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)的跟进日期", + "Connector ID":"连接器ID", + "Connector inputs":"连接器输入", + "Connector outputs":"连接器输出", + "Topic":"主题", + "Errors":"错误", + "Global error reference":"引用全局错误ID", + "Throw expression":"Throw表达式", + "Decision reference":"引用决策ID", + "Tenant ID":"租户ID", + "Multi-instance":"多实例", + "Loop cardinality":"循环基数", + "Completion condition":"完成条件", + "Element variable":"元素变量", + "Asynchronous before":"异步之前", + "Asynchronous after":"异步之后", +}; + +export const customTranslate = (template, replacements) =>{ + replacements = replacements || {}; + // Translate + template = translations[template] || template; + // Replace + return template.replace(/{([^}]+)}/g, (_, key)=> { + return replacements[key] || '{' + key + '}'; + }); +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9616a77 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/ts-config/vue-app.json", + "compilerOptions": { + "baseUrl": ".", + "declaration": false, + "types": ["vite/client"], + "paths": { + "@/*": ["src/*"], + "#/*": ["types/*"] + } + }, + "include": [ + "tests/**/*.ts", + "src/**/*.ts", + "src/**/*.d.ts", + "src/**/*.tsx", + "src/**/*.vue", + "types/**/*.d.ts", + "types/**/*.ts", + "build/**/*.ts", + "build/**/*.d.ts", + "mock/**/*.ts", + "vite.config.ts" + ], + "exclude": ["node_modules", "tests/server/**/*.ts", "dist", "**/*.js"] +} \ No newline at end of file diff --git a/turbo.json b/turbo.json new file mode 100644 index 0000000..bf5b89b --- /dev/null +++ b/turbo.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://turborepo.org/schema.json", + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**"] + }, + "stub": {}, + "lint": {}, + "clean": { + "cache": false + }, + "dev": { + "cache": false, + "persistent": true + } + } +} diff --git a/types/axios.d.ts b/types/axios.d.ts new file mode 100644 index 0000000..05fe0ab --- /dev/null +++ b/types/axios.d.ts @@ -0,0 +1,56 @@ +export type ErrorMessageMode = 'none' | 'modal' | 'message' | 'notice' | undefined; +export type SuccessMessageMode = ErrorMessageMode; + +export interface RequestOptions { + // Splicing request parameters to url + joinParamsToUrl?: boolean; + // Format request parameter time + formatDate?: boolean; + // Whether to process the request result + isTransformResponse?: boolean; + // Whether to return native response headers + // For example: use this attribute when you need to get the response headers + isReturnNativeResponse?: boolean; + // Whether to join url + joinPrefix?: boolean; + // Interface address, use the default apiUrl if you leave it blank + apiUrl?: string; + // 请求拼接路径 + urlPrefix?: string; + // Error message prompt type + errorMessageMode?: ErrorMessageMode; + // Success message prompt type + successMessageMode?: SuccessMessageMode; + // Whether to add a timestamp + joinTime?: boolean; + ignoreCancelToken?: boolean; + // Whether to send token in header + withToken?: boolean; + // 请求重试机制 + retryRequest?: RetryRequest; +} + +export interface RetryRequest { + isOpenRetry: boolean; + count: number; + waitTime: number; +} +export interface Result { + code: string; + type: 'success' | 'error' | 'warning'; + msg: string; + result: T; +} + +// multipart/form-data: upload file +export interface UploadFileParams { + // Other parameters + data?: Recordable; + // File parameter interface field name + name?: string; + // file name + file: File | Blob; + // file name + filename?: string; + [key: string]: any; +} diff --git a/types/codemirror.d.ts b/types/codemirror.d.ts new file mode 100644 index 0000000..38df0c1 --- /dev/null +++ b/types/codemirror.d.ts @@ -0,0 +1 @@ +declare module '@codemirror/lang-json'; diff --git a/types/config.d.ts b/types/config.d.ts new file mode 100644 index 0000000..8041e50 --- /dev/null +++ b/types/config.d.ts @@ -0,0 +1,162 @@ +import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum'; +import { + ContentEnum, + PermissionModeEnum, + ThemeEnum, + RouterTransitionEnum, + SettingButtonPositionEnum, + SessionTimeoutProcessingEnum, +} from '/@/enums/appEnum'; + +import { CacheTypeEnum } from '/@/enums/cacheEnum'; + +export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja' | 'ko'; + +export interface MenuSetting { + bgColor: string; + fixed: boolean; + collapsed: boolean; + siderHidden: boolean; + canDrag: boolean; + show: boolean; + hidden: boolean; + split: boolean; + menuWidth: number; + mode: MenuModeEnum; + type: MenuTypeEnum; + theme: ThemeEnum; + topMenuAlign: 'start' | 'center' | 'end'; + trigger: TriggerEnum; + accordion: boolean; + closeMixSidebarOnChange: boolean; + collapsedShowTitle: boolean; + mixSideTrigger: MixSidebarTriggerEnum; + mixSideFixed: boolean; +} + +export interface MultiTabsSetting { + cache: boolean; + show: boolean; + showQuick: boolean; + canDrag: boolean; + showRedo: boolean; + showFold: boolean; +} + +export interface HeaderSetting { + bgColor: string; + fixed: boolean; + show: boolean; + theme: ThemeEnum; + // Turn on full screen + showFullScreen: boolean; + // Whether to show the lock screen + useLockPage: boolean; + // Show document button + showDoc: boolean; + // Show message center button + showNotice: boolean; + showSearch: boolean; +} + +export interface LocaleSetting { + showPicker: boolean; + // Current language + locale: LocaleType; + // default language + fallback: LocaleType; + // available Locales + availableLocales: LocaleType[]; +} + +export interface TransitionSetting { + // Whether to open the page switching animation + enable: boolean; + // Route basic switching animation + basicTransition: RouterTransitionEnum; + // Whether to open page switching loading + openPageLoading: boolean; + // Whether to open the top progress bar + openNProgress: boolean; +} + +export interface ProjectConfig { + // Storage location of permission related information + permissionCacheType: CacheTypeEnum; + // Whether to show the configuration button + showSettingButton: boolean; + // Whether to show the theme switch button + showDarkModeToggle: boolean; + // Configure where the button is displayed + settingButtonPosition: SettingButtonPositionEnum; + // Permission mode + permissionMode: PermissionModeEnum; + // Session timeout processing + sessionTimeoutProcessing: SessionTimeoutProcessingEnum; + // Website gray mode, open for possible mourning dates + grayMode: boolean; + // Whether to turn on the color weak mode + colorWeak: boolean; + // Theme color + themeColor: string; + + // The main interface is displayed in full screen, the menu is not displayed, and the top + fullContent: boolean; + // content width + contentMode: ContentEnum; + // Whether to display the logo + showLogo: boolean; + // Whether to show the global footer + showFooter: boolean; + // menuType: MenuTypeEnum; + headerSetting: HeaderSetting; + // menuSetting + menuSetting: MenuSetting; + // Multi-tab settings + multiTabsSetting: MultiTabsSetting; + // Animation configuration + transitionSetting: TransitionSetting; + // pageLayout whether to enable keep-alive + openKeepAlive: boolean; + // Lock screen time + lockTime: number; + // Show breadcrumbs + showBreadCrumb: boolean; + // Show breadcrumb icon + showBreadCrumbIcon: boolean; + // Use error-handler-plugin + useErrorHandle: boolean; + // Whether to open back to top + useOpenBackTop: boolean; + // Is it possible to embed iframe pages + canEmbedIFramePage: boolean; + // Whether to delete unclosed messages and notify when switching the interface + closeMessageOnSwitch: boolean; + // Whether to cancel the http request that has been sent but not responded when switching the interface. + removeAllHttpPending: boolean; +} + +export interface GlobConfig { + // Site title + title: string; + // Service interface url + apiUrl: string; + // Upload url + uploadUrl?: string; + // Service interface url prefix + urlPrefix?: string; + // Project abbreviation + shortName: string; +} +export interface GlobEnvConfig { + // Site title + VITE_GLOB_APP_TITLE: string; + // Service interface url + VITE_GLOB_API_URL: string; + // Service interface url prefix + VITE_GLOB_API_URL_PREFIX?: string; + // Project abbreviation + VITE_GLOB_APP_SHORT_NAME: string; + // Upload url + VITE_GLOB_UPLOAD_URL?: string; +} diff --git a/types/global.d.ts b/types/global.d.ts new file mode 100644 index 0000000..07c689c --- /dev/null +++ b/types/global.d.ts @@ -0,0 +1,91 @@ +import type { + ComponentRenderProxy, + VNode, + VNodeChild, + ComponentPublicInstance, + FunctionalComponent, + PropType as VuePropType, +} from 'vue'; + +declare global { + const __APP_INFO__: { + pkg: { + name: string; + version: string; + dependencies: Recordable; + devDependencies: Recordable; + }; + lastBuildTime: string; + }; + // declare interface Window { + // // Global vue app instance + // __APP__: App; + // } + + // vue + declare type PropType = VuePropType; + declare type VueNode = VNodeChild | JSX.Element; + + export type Writable = { + -readonly [P in keyof T]: T[P]; + }; + + declare type Nullable = T | null; + declare type NonNullable = T extends null | undefined ? never : T; + declare type Recordable = Record; + declare type ReadonlyRecordable = { + readonly [key: string]: T; + }; + declare type Indexable = { + [key: string]: T; + }; + declare type DeepPartial = { + [P in keyof T]?: DeepPartial; + }; + declare type TimeoutHandle = ReturnType; + declare type IntervalHandle = ReturnType; + + declare interface ChangeEvent extends Event { + target: HTMLInputElement; + } + + declare interface WheelEvent { + path?: EventTarget[]; + } + interface ImportMetaEnv extends ViteEnv { + __: unknown; + } + + declare interface ViteEnv { + VITE_USE_MOCK: boolean; + VITE_PUBLIC_PATH: string; + VITE_GLOB_APP_TITLE: string; + VITE_BUILD_COMPRESS: 'gzip' | 'brotli' | 'none'; + } + + declare function parseInt(s: string | number, radix?: number): number; + + declare function parseFloat(string: string | number): number; + + namespace JSX { + // tslint:disable no-empty-interface + type Element = VNode; + // tslint:disable no-empty-interface + type ElementClass = ComponentRenderProxy; + interface ElementAttributesProperty { + $props: any; + } + interface IntrinsicElements { + [elem: string]: any; + } + interface IntrinsicAttributes { + [elem: string]: any; + } + } +} + +declare module 'vue' { + export type JSXComponent = + | { new (): ComponentPublicInstance } + | FunctionalComponent; +} diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..23baddf --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,27 @@ +declare interface Fn { + (...arg: T[]): R; +} + +declare interface PromiseFn { + (...arg: T[]): Promise; +} + +declare type RefType = T | null; + +declare type LabelValueOptions = { + label: string; + value: any; + [key: string]: string | number | boolean; +}[]; + +declare type EmitType = (event: string | any, ...args: any[]) => void; + +declare type TargetContext = '_self' | '_blank'; + +declare interface ComponentElRef { + $el: T; +} + +declare type ComponentRef = ComponentElRef | null; + +declare type ElRef = Nullable; diff --git a/types/module.d.ts b/types/module.d.ts new file mode 100644 index 0000000..61a0c34 --- /dev/null +++ b/types/module.d.ts @@ -0,0 +1,18 @@ +declare module '*.vue' { + import { DefineComponent } from 'vue'; + + const Component: DefineComponent<{}, {}, any>; + export default Component; +} + +declare module 'ant-design-vue/es/locale/*' { + import { Locale } from 'ant-design-vue/types/locale-provider'; + + const locale: Locale & ReadonlyRecordable; + export default locale as Locale & ReadonlyRecordable; +} + +declare module 'virtual:*' { + const result: any; + export default result; +} diff --git a/types/store.d.ts b/types/store.d.ts new file mode 100644 index 0000000..8228d90 --- /dev/null +++ b/types/store.d.ts @@ -0,0 +1,48 @@ +import { ErrorTypeEnum } from '/@/enums/exceptionEnum'; +import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; +import { RoleInfo } from '/@/api/sys/model/userModel'; + +// Lock screen information +export interface LockInfo { + // Password required + pwd?: string | undefined; + // Is it locked? + isLock?: boolean; +} + +// Error-log information +export interface ErrorLogInfo { + // Type of error + type: ErrorTypeEnum; + // Error file + file: string; + // Error name + name?: string; + // Error message + message: string; + // Error stack + stack?: string; + // Error detail + detail: string; + // Error url + url: string; + // Error time + time?: string; +} + +export interface UserInfo { + userId: string | number; + username: string; + name: string; + avatar: string; + desc?: string; + homePath?: string; + roles: RoleInfo[]; +} + +export interface BeforeMiniState { + menuCollapsed?: boolean; + menuSplit?: boolean; + menuMode?: MenuModeEnum; + menuType?: MenuTypeEnum; +} diff --git a/types/tree.d.ts b/types/tree.d.ts new file mode 100644 index 0000000..799e69a --- /dev/null +++ b/types/tree.d.ts @@ -0,0 +1 @@ +declare module '@axolo/tree-array'; diff --git a/types/utils.d.ts b/types/utils.d.ts new file mode 100644 index 0000000..6500d44 --- /dev/null +++ b/types/utils.d.ts @@ -0,0 +1,5 @@ +import type { ComputedRef, Ref } from 'vue'; + +export type DynamicProps = { + [P in keyof T]: Ref | T[P] | ComputedRef; +}; diff --git a/types/vue-router.d.ts b/types/vue-router.d.ts new file mode 100644 index 0000000..0890b55 --- /dev/null +++ b/types/vue-router.d.ts @@ -0,0 +1,47 @@ +import { RoleEnum } from '/@/enums/roleEnum'; + +export {}; + +declare module 'vue-router' { + interface RouteMeta extends Record { + sort?: number; + // title + title: string; + // dynamic router level. + dynamicLevel?: number; + // dynamic router real route path (For performance). + realPath?: string; + // Whether to ignore permissions + ignoreAuth?: boolean; + // role info + roles?: RoleEnum[]; + // Whether not to cache + ignoreKeepAlive?: boolean; + // Is it fixed on tab + affix?: boolean; + // icon on tab + icon?: string; + frameSrc?: string; + // current page transition + transitionName?: string; + // Whether the route has been dynamically added + hideBreadcrumb?: boolean; + // Hide submenu + hideChildrenInMenu?: boolean; + // Carrying parameters + carryParam?: boolean; + // Used internally to mark single-level menus + single?: boolean; + // Currently active menu + currentActiveMenu?: string; + // Never show in tab + hideTab?: boolean; + // Never show in menu + hideMenu?: boolean; + isLink?: boolean; + // only build for Menu + ignoreRoute?: boolean; + // Hide path for children + hidePathForChildren?: boolean; + } +} diff --git a/types/vueuseCore.d.ts b/types/vueuseCore.d.ts new file mode 100644 index 0000000..f0e8592 --- /dev/null +++ b/types/vueuseCore.d.ts @@ -0,0 +1 @@ +declare module '@vueuse/core'; diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..37c3c3f --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,31 @@ +import { defineApplicationConfig } from '@vben/vite-config'; + +export default defineApplicationConfig({ + overrides: { + optimizeDeps: { + include: [ + 'echarts/core', + 'echarts/charts', + 'echarts/components', + 'echarts/renderers', + 'qrcode', + '@iconify/iconify', + 'ant-design-vue/es/locale/zh_CN', + 'ant-design-vue/es/locale/en_US', + ], + }, + server: { + port: 3000, + proxy: { + '/erp-api': { + target: 'http://localhost:8088', + changeOrigin: true, + ws: true, + // rewrite: (path) => path.replace(/^\/api/, ''), + // only https + + } + }, + }, + }, +}); diff --git a/wansenai-logo.png b/wansenai-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1d9126382e1bb4b4ea8db27066e9137250435a6f GIT binary patch literal 7551 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