From 3cb63ffca70e29c8504822e48b5d3bdd0620c720 Mon Sep 17 00:00:00 2001 From: mayiming <1627832236@qq.com> Date: Wed, 5 Nov 2025 17:34:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0bar=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QXTfront/App.vue | 2 +- QXTfront/pages/index/index.vue | 8 +- QXTfront/uni_modules/lime-badge/changelog.md | 25 + .../components/l-badge/index-u.scss | 112 + .../lime-badge/components/l-badge/index.scss | 83 + .../components/l-badge/l-badge.uvue | 148 + .../lime-badge/components/l-badge/l-badge.vue | 117 + .../lime-badge/components/l-badge/props.ts | 20 + .../lime-badge/components/l-badge/type.ts | 50 + .../lime-badge/components/l-badge/utils.ts | 3 + .../components/lime-badge/lime-badge.vue | 172 + QXTfront/uni_modules/lime-badge/package.json | 107 + .../uni_modules/lime-badge/readme - 副本.md | 198 + QXTfront/uni_modules/lime-badge/readme.md | 174 + QXTfront/uni_modules/lime-icon/changelog.md | 84 + .../lime-icon/components/l-icon/icon.scss | 21 + .../lime-icon/components/l-icon/icons.uts | 27 + .../lime-icon/components/l-icon/index.scss | 63 + .../lime-icon/components/l-icon/l-icon.uvue | 189 + .../lime-icon/components/l-icon/l-icon.vue | 151 + .../lime-icon/components/l-icon/props.ts | 31 + .../lime-icon/components/l-icon/types.ts | 4 + .../components/lime-icon/lime-icon.uvue | 229 + .../components/lime-icon/lime-icon.vue | 254 ++ .../uni_modules/lime-icon/generate-icons.js | 2 + .../uni_modules/lime-icon/hybrid/html/t3.ttf | Bin 0 -> 367148 bytes QXTfront/uni_modules/lime-icon/index.uts | 111 + .../lime-icon/lime-icons.config.js | 23 + QXTfront/uni_modules/lime-icon/package.json | 110 + QXTfront/uni_modules/lime-icon/readme.md | 245 ++ .../uni_modules/lime-icon/static/icons.json | 2116 +++++++++ .../uni_modules/lime-icon/utils/generate.js | 120 + QXTfront/uni_modules/lime-icon/utils/index.js | 89 + QXTfront/uni_modules/lime-icon/vite-plugin.js | 87 + .../uni_modules/lime-shared/addUnit/index.ts | 42 + .../lime-shared/animation/bezier.ts | 82 + .../uni_modules/lime-shared/animation/ease.ts | 3 + .../lime-shared/animation/index.ts | 12 + .../lime-shared/animation/useTransition.ts | 108 + .../lime-shared/animation/uvue.uts | 119 + .../uni_modules/lime-shared/animation/vue.ts | 123 + .../lime-shared/areaData/city-china.json | 3888 +++++++++++++++++ .../uni_modules/lime-shared/areaData/index.ts | 71 + .../lime-shared/arrayBufferToFile/index.ts | 10 + .../lime-shared/arrayBufferToFile/uvue.uts | 10 + .../lime-shared/arrayBufferToFile/vue.ts | 63 + .../lime-shared/base64ToArrayBuffer/index.ts | 13 + .../lime-shared/base64ToPath/index.ts | 11 + .../lime-shared/base64ToPath/uvue.uts | 22 + .../lime-shared/base64ToPath/vue.ts | 75 + .../lime-shared/camelCase/index.ts | 21 + .../lime-shared/canIUseCanvas2d/index.ts | 67 + .../lime-shared/capitalizedAmount/index.ts | 111 + QXTfront/uni_modules/lime-shared/changelog.md | 91 + .../lime-shared/characterLimit/index.ts | 63 + .../uni_modules/lime-shared/clamp/index.ts | 16 + .../lime-shared/classNames/index.ts | 53 + .../lime-shared/cloneDeep/index.ts | 12 + .../lime-shared/cloneDeep/uvue.uts | 39 + .../uni_modules/lime-shared/cloneDeep/vue.ts | 103 + .../uni_modules/lime-shared/closest/index.ts | 22 + .../components/lime-shared/lime-shared.vue | 407 ++ .../lime-shared/createAnimation/index.ts | 11 + .../lime-shared/createAnimation/type.ts | 25 + .../lime-shared/createAnimation/uvue.uts | 5 + .../lime-shared/createAnimation/vue.ts | 148 + .../lime-shared/createCanvas/index.ts | 73 + .../lime-shared/createImage/index.ts | 71 + .../uni_modules/lime-shared/cssToObj/index.ts | 45 + .../uni_modules/lime-shared/debounce/index.ts | 11 + .../uni_modules/lime-shared/debounce/uvue.uts | 36 + .../uni_modules/lime-shared/debounce/vue.ts | 40 + QXTfront/uni_modules/lime-shared/dom/index.ts | 18 + .../uni_modules/lime-shared/exif/index.ts | 11 + .../uni_modules/lime-shared/exif/uvue.uts | 7 + QXTfront/uni_modules/lime-shared/exif/vue.ts | 1057 +++++ .../uni_modules/lime-shared/fillZero/index.ts | 11 + .../uni_modules/lime-shared/floatAdd/index.ts | 36 + .../uni_modules/lime-shared/floatDiv/index.ts | 45 + .../uni_modules/lime-shared/floatMul/index.ts | 44 + .../uni_modules/lime-shared/floatSub/index.ts | 32 + .../lime-shared/getClassStr/index.ts | 53 + .../lime-shared/getCurrentPage/index.ts | 11 + .../lime-shared/getCurrentPage/uvue.uts | 5 + .../lime-shared/getCurrentPage/vue.ts | 6 + .../lime-shared/getLocalFilePath/index.ts | 62 + .../uni_modules/lime-shared/getRect/index.ts | 138 + .../uni_modules/lime-shared/getRect/uvue.uts | 17 + .../uni_modules/lime-shared/getRect/vue.ts | 117 + .../lime-shared/getStyleStr/index.ts | 54 + .../uni_modules/lime-shared/guid/index.ts | 28 + .../uni_modules/lime-shared/hasOwn/index.ts | 11 + .../uni_modules/lime-shared/hasOwn/uvue.uts | 43 + .../uni_modules/lime-shared/hasOwn/vue.ts | 30 + QXTfront/uni_modules/lime-shared/index.ts | 43 + .../uni_modules/lime-shared/isBase64/index.ts | 23 + .../lime-shared/isBoolean/index.ts | 24 + .../lime-shared/isBrowser/index.ts | 8 + .../lime-shared/isByteLength/index.ts | 86 + .../uni_modules/lime-shared/isDate/index.ts | 189 + .../uni_modules/lime-shared/isDef/index.ts | 23 + .../uni_modules/lime-shared/isEmail/index.ts | 11 + .../uni_modules/lime-shared/isEmpty/index.ts | 81 + .../lime-shared/isFunction/index.ts | 16 + .../uni_modules/lime-shared/isIP/index.ts | 64 + .../uni_modules/lime-shared/isNumber/index.ts | 26 + .../lime-shared/isNumeric/index.ts | 33 + .../uni_modules/lime-shared/isObject/index.ts | 19 + .../lime-shared/isPromise/index.ts | 22 + .../uni_modules/lime-shared/isRegExp/index.ts | 33 + .../uni_modules/lime-shared/isString/index.ts | 19 + .../uni_modules/lime-shared/isURL/index.ts | 198 + .../lime-shared/isValidDomain/index.ts | 90 + .../lime-shared/kebabCase/index.ts | 24 + .../uni_modules/lime-shared/merge/index.ts | 33 + .../uni_modules/lime-shared/obj2url/index.ts | 61 + .../uni_modules/lime-shared/objToCss/index.ts | 49 + QXTfront/uni_modules/lime-shared/package.json | 110 + .../lime-shared/pathToBase64/index.ts | 11 + .../lime-shared/pathToBase64/uvue.uts | 17 + .../lime-shared/pathToBase64/vue.ts | 121 + .../uni_modules/lime-shared/platform/index.ts | 34 + QXTfront/uni_modules/lime-shared/raf/index.ts | 12 + QXTfront/uni_modules/lime-shared/raf/uvue.uts | 48 + QXTfront/uni_modules/lime-shared/raf/vue.ts | 32 + .../uni_modules/lime-shared/random/index.ts | 24 + .../uni_modules/lime-shared/range/index.ts | 36 + QXTfront/uni_modules/lime-shared/readme.md | 516 +++ .../lime-shared/selectAllComponent/index.ts | 10 + .../lime-shared/selectAllComponent/uvue.uts | 39 + .../lime-shared/selectAllComponent/vue.ts | 151 + .../lime-shared/selectComponent/index.ts | 9 + .../lime-shared/selectComponent/uvue.uts | 75 + .../lime-shared/selectComponent/vue.ts | 149 + .../lime-shared/selectElement/index.ts | 277 ++ .../uni_modules/lime-shared/shuffle/index.ts | 16 + .../uni_modules/lime-shared/sleep/index.ts | 44 + .../uni_modules/lime-shared/throttle/index.ts | 89 + .../lime-shared/throttle/index_old.ts | 112 + .../uni_modules/lime-shared/toArray/index.ts | 21 + .../lime-shared/toBoolean/index.ts | 40 + .../uni_modules/lime-shared/toNumber/index.ts | 28 + .../lime-shared/unitConvert/index.ts | 80 + QXTfront/uni_modules/lime-shared/vue/index.ts | 16 + .../uni_modules/lime-shared/while/index.ts | 55 + QXTfront/uni_modules/lime-style/changelog.md | 46 + .../lime-style/color/colorPalette.scss | 236 + .../uni_modules/lime-style/color/colors.scss | 18 + .../uni_modules/lime-style/functions.scss | 11 + QXTfront/uni_modules/lime-style/hairline.uts | 153 + QXTfront/uni_modules/lime-style/index.scss | 7 + QXTfront/uni_modules/lime-style/index.uts | 3 + .../uni_modules/lime-style/mixins/bem.scss | 0 .../uni_modules/lime-style/mixins/create.scss | 219 + .../mixins/directionalProperty.scss | 401 ++ .../lime-style/mixins/ellipsis.scss | 22 + .../uni_modules/lime-style/mixins/flex.scss | 20 + .../lime-style/mixins/hairline.scss | 66 + .../lime-style/mixins/platform.scss | 17 + .../lime-style/mixins/useTheme.scss | 60 + .../lime-style/mixins/utilities.scss | 7 + QXTfront/uni_modules/lime-style/package.json | 103 + QXTfront/uni_modules/lime-style/readme.md | 16 + .../uni_modules/lime-style/theme/dark.scss | 634 +++ .../uni_modules/lime-style/theme/default.scss | 181 + .../uni_modules/lime-style/token/dark.uts | 67 + .../lime-style/token/genFontMapToken.uts | 49 + .../lime-style/token/genFontSizes.uts | 30 + .../lime-style/token/genRadius.uts | 63 + .../lime-style/token/genSizeMapToken.uts | 20 + .../lime-style/token/interface.uts | 184 + .../uni_modules/lime-style/token/light.uts | 66 + .../uni_modules/lime-style/token/shared.uts | 24 + .../lime-style/token/useThemeMode.uts | 126 + .../lime-style/token/useThemeVars.uts | 123 + QXTfront/uni_modules/lime-style/token/vue.ts | 13 + QXTfront/uni_modules/lime-style/var.scss | 72 + QXTfront/uni_modules/lime-svg/changelog.md | 47 + .../lime-svg/components/l-svg/l-svg.uvue | 324 ++ .../lime-svg/components/l-svg/l-svg.vue | 244 ++ .../lime-svg/components/l-svg/props.ts | 18 + .../lime-svg/components/l-svg/type.ts | 6 + .../lime-svg/components/l-svg/utils.ts | 70 + .../components/lime-svg/lime-svg.uvue | 138 + .../lime-svg/components/lime-svg/lime-svg.vue | 44 + QXTfront/uni_modules/lime-svg/encrypt | 1 + .../lime-svg/hybrid/html/index.html | 178 + .../lime-svg/hybrid/html/uni.webview.1.5.5.js | 1 + QXTfront/uni_modules/lime-svg/package.json | 106 + QXTfront/uni_modules/lime-svg/readme.md | 108 + QXTfront/uni_modules/lime-svg/readme_old.md | 68 + .../utssdk/app-android/AndroidManifest.xml | 7 + .../lime-svg/utssdk/app-android/config.json | 6 + .../lime-svg/utssdk/app-android/fileUtils.uts | Bin 0 -> 3264 bytes .../lime-svg/utssdk/app-android/index.uts | Bin 0 -> 2896 bytes .../lime-svg/utssdk/app-android/utils.uts | Bin 0 -> 6864 bytes .../lime-svg/utssdk/app-harmony/builder.ets | 36 + .../utssdk/app-harmony/css-color-names.uts | Bin 0 -> 4336 bytes .../lime-svg/utssdk/app-harmony/index.uts | Bin 0 -> 3920 bytes .../lime-svg/utssdk/app-harmony/utils.uts | Bin 0 -> 960 bytes .../Resources/_CodeSignature/CodeResources | 212 + .../lime-svg/utssdk/app-ios/config.json | 7 + .../lime-svg/utssdk/app-ios/fileUtils.uts | Bin 0 -> 1120 bytes .../lime-svg/utssdk/app-ios/index.uts | Bin 0 -> 2704 bytes .../lime-svg/utssdk/app-ios/utils.uts | Bin 0 -> 6160 bytes QXTfront/uni_modules/lime-tabbar/changelog.md | 26 + .../components/l-tabbar-item/index-u.scss | 120 + .../l-tabbar-item/l-tabbar-item.uvue | 166 + .../l-tabbar-item/l-tabbar-item.vue | 166 + .../components/l-tabbar-item/props.ts | 28 + .../components/l-tabbar-item/type.ts | 26 + .../components/l-tabbar/index-u.scss | 83 + .../components/l-tabbar/l-tabbar.uvue | 131 + .../components/l-tabbar/l-tabbar.vue | 115 + .../lime-tabbar/components/l-tabbar/props.ts | 94 + .../lime-tabbar/components/l-tabbar/type.ts | 68 + .../components/lime-tabbar/lime-tabbar.uvue | 249 ++ .../components/lime-tabbar/lime-tabbar.vue | 207 + QXTfront/uni_modules/lime-tabbar/package.json | 110 + .../uni_modules/lime-tabbar/readme - 副本.md | 210 + QXTfront/uni_modules/lime-tabbar/readme.md | 219 + .../dist/cache/.vite/deps/_metadata.json | 8 + .../dist/cache/.vite/deps/package.json | 3 + 223 files changed, 23185 insertions(+), 2 deletions(-) create mode 100644 QXTfront/uni_modules/lime-badge/changelog.md create mode 100644 QXTfront/uni_modules/lime-badge/components/l-badge/index-u.scss create mode 100644 QXTfront/uni_modules/lime-badge/components/l-badge/index.scss create mode 100644 QXTfront/uni_modules/lime-badge/components/l-badge/l-badge.uvue create mode 100644 QXTfront/uni_modules/lime-badge/components/l-badge/l-badge.vue create mode 100644 QXTfront/uni_modules/lime-badge/components/l-badge/props.ts create mode 100644 QXTfront/uni_modules/lime-badge/components/l-badge/type.ts create mode 100644 QXTfront/uni_modules/lime-badge/components/l-badge/utils.ts create mode 100644 QXTfront/uni_modules/lime-badge/components/lime-badge/lime-badge.vue create mode 100644 QXTfront/uni_modules/lime-badge/package.json create mode 100644 QXTfront/uni_modules/lime-badge/readme - 副本.md create mode 100644 QXTfront/uni_modules/lime-badge/readme.md create mode 100644 QXTfront/uni_modules/lime-icon/changelog.md create mode 100644 QXTfront/uni_modules/lime-icon/components/l-icon/icon.scss create mode 100644 QXTfront/uni_modules/lime-icon/components/l-icon/icons.uts create mode 100644 QXTfront/uni_modules/lime-icon/components/l-icon/index.scss create mode 100644 QXTfront/uni_modules/lime-icon/components/l-icon/l-icon.uvue create mode 100644 QXTfront/uni_modules/lime-icon/components/l-icon/l-icon.vue create mode 100644 QXTfront/uni_modules/lime-icon/components/l-icon/props.ts create mode 100644 QXTfront/uni_modules/lime-icon/components/l-icon/types.ts create mode 100644 QXTfront/uni_modules/lime-icon/components/lime-icon/lime-icon.uvue create mode 100644 QXTfront/uni_modules/lime-icon/components/lime-icon/lime-icon.vue create mode 100644 QXTfront/uni_modules/lime-icon/generate-icons.js create mode 100644 QXTfront/uni_modules/lime-icon/hybrid/html/t3.ttf create mode 100644 QXTfront/uni_modules/lime-icon/index.uts create mode 100644 QXTfront/uni_modules/lime-icon/lime-icons.config.js create mode 100644 QXTfront/uni_modules/lime-icon/package.json create mode 100644 QXTfront/uni_modules/lime-icon/readme.md create mode 100644 QXTfront/uni_modules/lime-icon/static/icons.json create mode 100644 QXTfront/uni_modules/lime-icon/utils/generate.js create mode 100644 QXTfront/uni_modules/lime-icon/utils/index.js create mode 100644 QXTfront/uni_modules/lime-icon/vite-plugin.js create mode 100644 QXTfront/uni_modules/lime-shared/addUnit/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/animation/bezier.ts create mode 100644 QXTfront/uni_modules/lime-shared/animation/ease.ts create mode 100644 QXTfront/uni_modules/lime-shared/animation/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/animation/useTransition.ts create mode 100644 QXTfront/uni_modules/lime-shared/animation/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/animation/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/areaData/city-china.json create mode 100644 QXTfront/uni_modules/lime-shared/areaData/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/arrayBufferToFile/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/arrayBufferToFile/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/arrayBufferToFile/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/base64ToArrayBuffer/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/base64ToPath/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/base64ToPath/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/base64ToPath/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/camelCase/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/canIUseCanvas2d/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/capitalizedAmount/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/changelog.md create mode 100644 QXTfront/uni_modules/lime-shared/characterLimit/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/clamp/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/classNames/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/cloneDeep/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/cloneDeep/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/cloneDeep/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/closest/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/components/lime-shared/lime-shared.vue create mode 100644 QXTfront/uni_modules/lime-shared/createAnimation/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/createAnimation/type.ts create mode 100644 QXTfront/uni_modules/lime-shared/createAnimation/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/createAnimation/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/createCanvas/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/createImage/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/cssToObj/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/debounce/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/debounce/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/debounce/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/dom/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/exif/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/exif/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/exif/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/fillZero/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/floatAdd/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/floatDiv/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/floatMul/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/floatSub/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/getClassStr/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/getCurrentPage/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/getCurrentPage/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/getCurrentPage/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/getLocalFilePath/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/getRect/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/getRect/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/getRect/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/getStyleStr/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/guid/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/hasOwn/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/hasOwn/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/hasOwn/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isBase64/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isBoolean/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isBrowser/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isByteLength/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isDate/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isDef/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isEmail/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isEmpty/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isFunction/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isIP/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isNumber/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isNumeric/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isObject/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isPromise/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isRegExp/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isString/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isURL/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/isValidDomain/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/kebabCase/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/merge/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/obj2url/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/objToCss/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/package.json create mode 100644 QXTfront/uni_modules/lime-shared/pathToBase64/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/pathToBase64/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/pathToBase64/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/platform/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/raf/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/raf/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/raf/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/random/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/range/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/readme.md create mode 100644 QXTfront/uni_modules/lime-shared/selectAllComponent/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/selectAllComponent/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/selectAllComponent/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/selectComponent/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/selectComponent/uvue.uts create mode 100644 QXTfront/uni_modules/lime-shared/selectComponent/vue.ts create mode 100644 QXTfront/uni_modules/lime-shared/selectElement/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/shuffle/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/sleep/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/throttle/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/throttle/index_old.ts create mode 100644 QXTfront/uni_modules/lime-shared/toArray/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/toBoolean/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/toNumber/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/unitConvert/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/vue/index.ts create mode 100644 QXTfront/uni_modules/lime-shared/while/index.ts create mode 100644 QXTfront/uni_modules/lime-style/changelog.md create mode 100644 QXTfront/uni_modules/lime-style/color/colorPalette.scss create mode 100644 QXTfront/uni_modules/lime-style/color/colors.scss create mode 100644 QXTfront/uni_modules/lime-style/functions.scss create mode 100644 QXTfront/uni_modules/lime-style/hairline.uts create mode 100644 QXTfront/uni_modules/lime-style/index.scss create mode 100644 QXTfront/uni_modules/lime-style/index.uts create mode 100644 QXTfront/uni_modules/lime-style/mixins/bem.scss create mode 100644 QXTfront/uni_modules/lime-style/mixins/create.scss create mode 100644 QXTfront/uni_modules/lime-style/mixins/directionalProperty.scss create mode 100644 QXTfront/uni_modules/lime-style/mixins/ellipsis.scss create mode 100644 QXTfront/uni_modules/lime-style/mixins/flex.scss create mode 100644 QXTfront/uni_modules/lime-style/mixins/hairline.scss create mode 100644 QXTfront/uni_modules/lime-style/mixins/platform.scss create mode 100644 QXTfront/uni_modules/lime-style/mixins/useTheme.scss create mode 100644 QXTfront/uni_modules/lime-style/mixins/utilities.scss create mode 100644 QXTfront/uni_modules/lime-style/package.json create mode 100644 QXTfront/uni_modules/lime-style/readme.md create mode 100644 QXTfront/uni_modules/lime-style/theme/dark.scss create mode 100644 QXTfront/uni_modules/lime-style/theme/default.scss create mode 100644 QXTfront/uni_modules/lime-style/token/dark.uts create mode 100644 QXTfront/uni_modules/lime-style/token/genFontMapToken.uts create mode 100644 QXTfront/uni_modules/lime-style/token/genFontSizes.uts create mode 100644 QXTfront/uni_modules/lime-style/token/genRadius.uts create mode 100644 QXTfront/uni_modules/lime-style/token/genSizeMapToken.uts create mode 100644 QXTfront/uni_modules/lime-style/token/interface.uts create mode 100644 QXTfront/uni_modules/lime-style/token/light.uts create mode 100644 QXTfront/uni_modules/lime-style/token/shared.uts create mode 100644 QXTfront/uni_modules/lime-style/token/useThemeMode.uts create mode 100644 QXTfront/uni_modules/lime-style/token/useThemeVars.uts create mode 100644 QXTfront/uni_modules/lime-style/token/vue.ts create mode 100644 QXTfront/uni_modules/lime-style/var.scss create mode 100644 QXTfront/uni_modules/lime-svg/changelog.md create mode 100644 QXTfront/uni_modules/lime-svg/components/l-svg/l-svg.uvue create mode 100644 QXTfront/uni_modules/lime-svg/components/l-svg/l-svg.vue create mode 100644 QXTfront/uni_modules/lime-svg/components/l-svg/props.ts create mode 100644 QXTfront/uni_modules/lime-svg/components/l-svg/type.ts create mode 100644 QXTfront/uni_modules/lime-svg/components/l-svg/utils.ts create mode 100644 QXTfront/uni_modules/lime-svg/components/lime-svg/lime-svg.uvue create mode 100644 QXTfront/uni_modules/lime-svg/components/lime-svg/lime-svg.vue create mode 100644 QXTfront/uni_modules/lime-svg/encrypt create mode 100644 QXTfront/uni_modules/lime-svg/hybrid/html/index.html create mode 100644 QXTfront/uni_modules/lime-svg/hybrid/html/uni.webview.1.5.5.js create mode 100644 QXTfront/uni_modules/lime-svg/package.json create mode 100644 QXTfront/uni_modules/lime-svg/readme.md create mode 100644 QXTfront/uni_modules/lime-svg/readme_old.md create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-android/AndroidManifest.xml create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-android/config.json create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-android/fileUtils.uts create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-android/index.uts create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-android/utils.uts create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-harmony/builder.ets create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-harmony/css-color-names.uts create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-harmony/index.uts create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-harmony/utils.uts create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-ios/Resources/_CodeSignature/CodeResources create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-ios/config.json create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-ios/fileUtils.uts create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-ios/index.uts create mode 100644 QXTfront/uni_modules/lime-svg/utssdk/app-ios/utils.uts create mode 100644 QXTfront/uni_modules/lime-tabbar/changelog.md create mode 100644 QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/index-u.scss create mode 100644 QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/l-tabbar-item.uvue create mode 100644 QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/l-tabbar-item.vue create mode 100644 QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/props.ts create mode 100644 QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/type.ts create mode 100644 QXTfront/uni_modules/lime-tabbar/components/l-tabbar/index-u.scss create mode 100644 QXTfront/uni_modules/lime-tabbar/components/l-tabbar/l-tabbar.uvue create mode 100644 QXTfront/uni_modules/lime-tabbar/components/l-tabbar/l-tabbar.vue create mode 100644 QXTfront/uni_modules/lime-tabbar/components/l-tabbar/props.ts create mode 100644 QXTfront/uni_modules/lime-tabbar/components/l-tabbar/type.ts create mode 100644 QXTfront/uni_modules/lime-tabbar/components/lime-tabbar/lime-tabbar.uvue create mode 100644 QXTfront/uni_modules/lime-tabbar/components/lime-tabbar/lime-tabbar.vue create mode 100644 QXTfront/uni_modules/lime-tabbar/package.json create mode 100644 QXTfront/uni_modules/lime-tabbar/readme - 副本.md create mode 100644 QXTfront/uni_modules/lime-tabbar/readme.md create mode 100644 QXTfront/unpackage/dist/cache/.vite/deps/_metadata.json create mode 100644 QXTfront/unpackage/dist/cache/.vite/deps/package.json diff --git a/QXTfront/App.vue b/QXTfront/App.vue index 8c2b732..e945d2c 100644 --- a/QXTfront/App.vue +++ b/QXTfront/App.vue @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-badge/components/l-badge/l-badge.vue b/QXTfront/uni_modules/lime-badge/components/l-badge/l-badge.vue new file mode 100644 index 0000000..08000cb --- /dev/null +++ b/QXTfront/uni_modules/lime-badge/components/l-badge/l-badge.vue @@ -0,0 +1,117 @@ + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-badge/components/l-badge/props.ts b/QXTfront/uni_modules/lime-badge/components/l-badge/props.ts new file mode 100644 index 0000000..8038c15 --- /dev/null +++ b/QXTfront/uni_modules/lime-badge/components/l-badge/props.ts @@ -0,0 +1,20 @@ +// @ts-nocheck +import type {PropType} from '@/uni_modules/lime-shared/vue' +export type BadgePosition = + | 'top-left' + | 'top-right' + | 'bottom-left' + | 'bottom-right'; +type Numeric = string | number +export default { + dot: Boolean, + max: Number, + color: String, + offset: Array as unknown as PropType<[Numeric, Numeric]>, + content: [Number , String], + showZero: Boolean, + position: { + type: String as PropType, + default: 'top-right' + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-badge/components/l-badge/type.ts b/QXTfront/uni_modules/lime-badge/components/l-badge/type.ts new file mode 100644 index 0000000..7f6ef3b --- /dev/null +++ b/QXTfront/uni_modules/lime-badge/components/l-badge/type.ts @@ -0,0 +1,50 @@ +// @ts-nocheck +export interface BadgeProps { + /** + * 颜色 + * @default '' + */ + color?: string; + /** + * 徽标内容 + */ + // #ifndef APP-ANDROID + content?: string|number; + // #endif + // #ifdef APP-ANDROID + content?: any; + // #endif + /** + * 是否为红点 + */ + dot: boolean; + /** + * 封顶的数字值 + * @default 99 + */ + max: number; + /** + * 设置状态点的位置偏移,示例:[-10, 20] 或 ['10rpx', '8rpx'] + */ + // #ifndef APP-ANDROID + offset?: Array; + // #endif + // #ifdef APP-ANDROID + offset?: any[]; + // #endif + position: string; + /** + * 形状 未实现 + * @default circle + */ + shape?: 'circle' | 'square' | 'bubble' | 'ribbon'; + /** + * 当数值为 0 时,是否展示徽标 + */ + showZero: boolean; + /** + * 尺寸 未实现 + * @default medium + */ + size?: 'medium' | 'large'; +} diff --git a/QXTfront/uni_modules/lime-badge/components/l-badge/utils.ts b/QXTfront/uni_modules/lime-badge/components/l-badge/utils.ts new file mode 100644 index 0000000..b7a70fc --- /dev/null +++ b/QXTfront/uni_modules/lime-badge/components/l-badge/utils.ts @@ -0,0 +1,3 @@ +export function getOffsetWithMinusString(val : string):string { + return val.startsWith('-') ? val.replace('-', '') : `-${val}` +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-badge/components/lime-badge/lime-badge.vue b/QXTfront/uni_modules/lime-badge/components/lime-badge/lime-badge.vue new file mode 100644 index 0000000..9da6c98 --- /dev/null +++ b/QXTfront/uni_modules/lime-badge/components/lime-badge/lime-badge.vue @@ -0,0 +1,172 @@ + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-badge/package.json b/QXTfront/uni_modules/lime-badge/package.json new file mode 100644 index 0000000..f1b2d2a --- /dev/null +++ b/QXTfront/uni_modules/lime-badge/package.json @@ -0,0 +1,107 @@ +{ + "id": "lime-badge", + "displayName": "lime-badge 徽标", + "version": "0.1.2", + "description": "lime-badge 实现的在右上角展示徽标数字或小红点,兼容uniapp/uniappx", + "keywords": [ + "badge", + "徽标" +], + "repository": "", + "engines": { + "HBuilderX": "^4.26", + "uni-app": "^4.74", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "component-vue", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "√", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [ + "lime-shared", + "lime-style" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "x" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "-", + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-badge/readme - 副本.md b/QXTfront/uni_modules/lime-badge/readme - 副本.md new file mode 100644 index 0000000..ce82e72 --- /dev/null +++ b/QXTfront/uni_modules/lime-badge/readme - 副本.md @@ -0,0 +1,198 @@ +# lime-badge 徽标 +- 在右上角展示徽标数字或小红点。 +- 插件依赖`lime-shared`,`lime-style`不喜勿下 + +## 文档 + [badge【站点1】](https://limex.qcoon.cn/components/badge.html) + [badge【站点2】](https://limeui.netlify.app/components/badge.html) + [badge【站点3】](https://limeui.familyzone.top/components/badge.html) + + + + +## 安装 +插件市场导入即可,首次导入可能需要重新编译 + +## 代码演示 + +### 基础用法 + +设置 `content` 属性后,Badge 会在子元素的右上角显示对应的徽标,也可以通过 `dot` 来显示小红点。 + +```html + + + + + + + + + + + + + + +``` + +### 最大值 + +设置 `max` 属性后,当 `content` 的数值超过最大值时,会自动显示为 `{max}+`。 + +```html + + + + + + + + + +``` + +### 自定义颜色 + +通过 `color` 属性来设置徽标的颜色。 + +```html + + + + + + + + + +``` + +### 自定义徽标内容 + +通过 `content` 插槽可以自定义徽标的内容,比如插入一个图标。 + +```html + + + + + +``` + +```css +.badge-icon { + display: block; + font-size: 10px; + line-height: 16px; +} +``` + +### 自定义徽标位置 + +通过 `position` 属性来设置徽标的位置。 + +```html + + + + + + + + + +``` + +### 独立展示 + +当 Badge 没有子元素时,会作为一个独立的元素进行展示。 + +```html + + + +``` + +### 查看示例 +- 导入后直接使用这个标签查看演示效果 + +```html + + +``` + + +### 插件标签 +- 默认 l-badge 为 component +- 默认 lime-badge 为 demo + +### Vue2使用 +- 插件使用了`composition-api`, 如果你希望在vue2中使用请按官方的教程[vue-composition-api](https://uniapp.dcloud.net.cn/tutorial/vue-composition-api.html)配置 +- 关键代码是: 在main.js中 在vue2部分加上这一段即可 +```js +// vue2 +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' +Vue.use(VueCompositionAPI) +``` + + + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| content | 徽标内容 | _number \| string_ | - | +| color | 徽标背景颜色 | _string_ | `#ee0a24` | +| dot | 是否展示为小红点 | _boolean_ | `false` | +| max | 最大值,超过最大值会显示 `{max}+`,仅当 content 为数字时有效 | _number \| string_ | - | +| offset | 设置徽标的偏移量,数组的两项分别对应水平向右和垂直向下方向的偏移量,默认单位为 `px` | _[number \| string, number \| string]_ | - | +| show-zero | 当 content 为数字 0 或字符串 '0' 时,是否展示徽标 | _boolean_ | `true` | +| position | 徽标位置,可选值为 `top-left` `bottom-left` `bottom-right` | _string_ | `top-right` | + +### Slots + +| 名称 | 说明 | +| ------- | ---------------- | +| default | 徽标包裹的子元素 | +| content | 自定义徽标内容 | + + +## 主题定制 + +### 样式变量 + +组件提供了下列 CSS 变量,可用于自定义样式。 + +| 名称 | 默认值 | 描述 | +| --- | --- | --- | +| --l-badge-size | _16px_ | - | +| --l-badge-color | _white_ | - | +| --l-badge-padding | _0 3px_ | - | +| --l-badge-font-size | _12px_ | - | +| --l-badge-font-weight | _bold)_ | - | +| --l-badge-border-width | _1px_ | - | +| --l-badge-background | _#F53F3F_ | - | +| --l-badge-dot-color | _#F53F3F_ | - | +| --l-badge-dot-size | _8px_ | - | +| --l-badge-font | _-apple-system-font, Helvetica Neue, Arial, sans-serif_ | - | +| --l-badge-border-radius | _999px_ | - | + + +## 打赏 + +如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。 +![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png) +![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png) \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-badge/readme.md b/QXTfront/uni_modules/lime-badge/readme.md new file mode 100644 index 0000000..8124af6 --- /dev/null +++ b/QXTfront/uni_modules/lime-badge/readme.md @@ -0,0 +1,174 @@ +# lime-badge 徽标组件 +一个功能丰富的徽标组件,用于展示数字提示、红点提示等。支持自定义位置、颜色、内容等多种配置,可用于消息提醒、数量展示等多种场景。组件提供了丰富的自定义选项,可以满足各种徽标展示需求。 + +> 插件依赖:`lime-shared`、`lime-style` + +## 文档链接 +📚 组件详细文档请访问以下站点: +- [徽标组件文档 - 站点1](https://limex.qcoon.cn/components/badge.html) +- [徽标组件文档 - 站点2](https://limeui.netlify.app/components/badge.html) +- [徽标组件文档 - 站点3](https://limeui.familyzone.top/components/badge.html) + +## 安装方法 +1. 在uni-app插件市场中搜索并导入`lime-badge` +2. 导入后可能需要重新编译项目 +3. 在页面中使用`l-badge`组件 + +## 代码演示 + +### 基础用法 +最简单的徽标组件用法,只需要设置内容即可。 + +```html + + + +``` + +### 红点徽标 +不需要显示具体数字,只显示一个小红点。 + +```html + + + +``` + +### 最大值 +当数值超过最大值时,会显示为最大值+。 + +```html + + + +``` + +### 自定义颜色 +设置徽标的背景颜色。 + +```html + + + +``` + +### 自定义位置 +徽标支持四个不同的位置:左上角、右上角、左下角、右下角。 + +```html + + + + + + + + + + + + + + + +``` + +### 自定义偏移 +通过offset属性设置徽标的偏移量,数组的两项分别代表水平和垂直方向的偏移量。 + +```html + + + +``` + +### 独立展示 +徽标可以不依附于其他元素,单独展示。 + +```html + +``` + +### 显示零值 +默认情况下,当content为0时不会显示徽标,设置show-zero属性可以强制显示零值。 + +```html + + + +``` + +## 快速预览 +导入插件后,可以直接使用以下标签查看演示效果: + +```html + + +``` + +## 插件标签说明 + +| 标签名 | 说明 | +| --- | --- | +| `l-badge` | 组件标签 | +| `lime-badge` | 演示标签 | + +## Vue2使用说明 +main.js中添加以下代码: +```js +// vue2项目中使用 +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' +Vue.use(VueCompositionAPI) +``` + +详细配置请参考官方文档:[Vue Composition API](https://uniapp.dcloud.net.cn/tutorial/vue-composition-api.html) + + +## API文档 + +### Props 属性说明 + +| 属性名 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| content | 徽标内容 | _number \| string_ | - | +| dot | 是否显示为小红点 | _boolean_ | `false` | +| max | 最大值,超过最大值会显示 {max}+ | _number_ | - | +| color | 徽标背景颜色 | _string_ | - | +| offset | 设置徽标的偏移量,数组的两项分别代表水平和垂直方向的偏移量 | _[number \| string, number \| string]_ | - | +| showZero | 当content为0时,是否显示徽标 | _boolean_ | `false` | +| position | 徽标位置,可选值为 top-left、top-right、bottom-left、bottom-right | _string_ | `'top-right'` | + +### Slots 插槽 + +| 名称 | 说明 | +| ------- | ---------------- | +| default | 徽标包裹的子元素 | +| content | 自定义徽标内容 | + +## 主题定制 + +组件提供了以下CSS变量,可用于自定义样式: + +| 变量名称 | 默认值 | 描述 | +|---------|--------|------| +| `--l-badge-size` | `16px` | 徽标大小 | +| `--l-badge-color` | `white` | 徽标文字颜色 | +| `--l-badge-padding` | `0 3px` | 徽标内边距 | +| `--l-badge-font-size` | `12px` | 徽标字体大小 | +| `--l-badge-font-weight` | `bold` | 徽标字体粗细 | +| `--l-badge-border-width` | `1px` | 徽标边框宽度 | +| `--l-badge-border-color` | `white` | 徽标边框颜色 | +| `--l-badge-bg-color` | `$error-color` | 徽标背景色 | +| `--l-badge-dot-color` | `$error-color` | 小红点颜色 | +| `--l-badge-dot-size` | `8px` | 小红点大小 | +| `--l-badge-font` | `-apple-system-font, helvetica neue, arial, sans-serif` | 徽标字体 | +| `--l-badge-border-radius` | `999px` | 徽标圆角大小 | + +## 支持与赞赏 + +如果你觉得本插件解决了你的问题,可以考虑支持作者: + +| 支付宝赞助 | 微信赞助 | +|------------|------------| +| ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png) | ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png) | \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/changelog.md b/QXTfront/uni_modules/lime-icon/changelog.md new file mode 100644 index 0000000..b790ae2 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/changelog.md @@ -0,0 +1,84 @@ +## 0.4.1(2025-10-19) +- fix: 修复上次因改使用官方svg,导致web,app不显示问题 +## 0.4.0(2025-10-15) +-fix: 修复uniapp cli 小程序css depp报错问题 +## 0.3.9(2025-10-15) +- fix: 去掉版本判断 +## 0.3.8(2025-09-22) +- feat: 针对hbx4.81优化 +## 0.3.7(2025-08-31) +- fix: 修复uniapp 鸿蒙next不显示的问题 +## 0.3.6(2025-07-16) +- fix: 因增加依赖,没有主动下载导致报错 +- fix: 修复鸿蒙加载文件失败的问题 +## 0.3.5(2025-07-15) +- chore: 更新文档 +## 0.3.4(2025-07-14) +- chore: 更新文档 +## 0.3.3(2025-07-14) +- feat: ios使用真的加载json的方式 +## 0.3.2(2025-07-08) +- fix: 支付福小程序报错问题 +## 0.3.1(2025-06-30) +- fix: 微信小程序svg不显示的问题 +## 0.3.0(2025-06-26) +- chore: 更新文档 +## 0.2.9(2025-05-30) +- fix: 修复uniapp自定义图标的问题 +## 0.2.8(2025-05-30) +- fix: 修复自定义图标的问题 +## 0.2.7(2025-05-10) +- feat: 增加组件提示 +## 0.2.6(2025-04-22) +- feat: 颜色改为可选 +## 0.2.5(2025-04-21) +- chore: 更新文档 +## 0.2.4(2025-04-21) +- feat: 兼容鸿蒙next +## 0.2.3(2025-04-09) +- feat: 如果是字体字符则直接显示 +## 0.2.2(2025-03-20) +- feat: 如果name不为字符字会报错,加强处理 +## 0.2.1(2025-03-06) +- chore: 更新文档 +## 0.2.0(2025-02-08) +- chore: 更新文档 +## 0.1.9(2025-02-07) +- fix: 去掉app端字体默认宽度 +## 0.1.8(2025-01-19) +- fix: 修复nvue加载字体文体问题 +## 0.1.7(2025-01-13) +- chore: 去掉多余判断 +## 0.1.6(2025-01-13) +- fix: 修复因json文件错误导致ios报错问题 +## 0.1.5(2025-01-02) +- feat: hbx4.44会有css深度选择器报黄的问题? +## 0.1.4(2025-01-02) +- feat: uniapp x app 取消文本默认大小 +## 0.1.3(2025-01-01) +- feat: 增加lStyle +## 0.1.2(2024-11-22) +- chore: 更新到hbx4.35 +## 0.1.1(2024-10-23) +- chore: 更新到hbx4.31 +## 0.1.0(2024-10-07) +- fix: ios 默认大小 +## 0.0.9(2024-10-06) +- fix: name有大写的情况 +## 0.0.8(2024-09-29) +- chore: 更新 非uvue app size使用css变量 +## 0.0.7(2024-07-23) +- fix: 更新 vue2 使用方法 +## 0.0.6(2024-07-22) +- fix: 修复vue3 h5不显示的问题 +## 0.0.5(2024-07-22) +- fix: 修复vue2小程序class不显示的问题 +## 0.0.4(2024-07-21) +- feat: 兼容uniappx +## 0.0.3(2023-09-05) +- chore: 更新文档 +- feat: 默认使用官方API +## 0.0.2(2023-08-13) +- chore: 更新文档 +## 0.0.1(2023-08-13) +- 初次上传 可能存在BUG diff --git a/QXTfront/uni_modules/lime-icon/components/l-icon/icon.scss b/QXTfront/uni_modules/lime-icon/components/l-icon/icon.scss new file mode 100644 index 0000000..dc3d193 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/components/l-icon/icon.scss @@ -0,0 +1,21 @@ +// $prefix: l !default; +/* #ifndef APP-NVUE || UNI-APP-X && APP */ +@font-face { + font-family: $prefix; + src: url('https://tdesign.gtimg.com/icon/0.3.0/fonts/t.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} +/* #endif */ + +/* #ifdef UNI-APP-X && APP */ +@font-face { + font-family: $prefix; + /* #ifdef APP-HARMONY */ + src: url('/uni_modules/lime-icon/hybrid/html/t3.ttf'); + /* #endif */ + /* #ifndef APP-HARMONY */ + src: url('uni_modules/lime-icon/hybrid/html/t3.ttf'); + /* #endif */ +} +/* #endif */ \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/components/l-icon/icons.uts b/QXTfront/uni_modules/lime-icon/components/l-icon/icons.uts new file mode 100644 index 0000000..1c5d206 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/components/l-icon/icons.uts @@ -0,0 +1,27 @@ +// #ifndef APP-ANDROID || APP-HARMONY +import iconList from '../../static/icons.json'; +export const icons = ref>((iconList as UTSJSONObject).toMap()) +// #endif +// #ifdef APP-ANDROID || APP-HARMONY +export const icons = ref>(new Map()) + +if (icons.value.size == 0) { + uni.getFileSystemManager().readFile({ + // #ifdef APP-HARMONY + filePath: '/uni_modules/lime-icon/static/icons.json', + // #endif + // #ifndef APP-HARMONY + filePath: 'uni_modules/lime-icon/static/icons.json', + // #endif + encoding: 'utf-8', + success: (res) => { + const obj = JSON.parseObject(res.data as string) + if (obj == null) return + icons.value = obj!.toMap(); + }, + fail(err) { + console.log('[lime-icon getFileSystemManager]', err) + } + } as ReadFileOptions); +} +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/components/l-icon/index.scss b/QXTfront/uni_modules/lime-icon/components/l-icon/index.scss new file mode 100644 index 0000000..e954249 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/components/l-icon/index.scss @@ -0,0 +1,63 @@ +// 公共前缀 +@import '@/uni_modules/lime-style/index.scss'; +@import './icon'; + +$use-css-var: true; + +$prefix: l !default; +$icon: #{$prefix}-icon; + +/* #ifdef APP-NVUE || UNI-APP-X && APP */ +$icon-size: create-var(icon-size, 16px); +$icon-color: create-var(icon-color, $text-color-1); +/* #endif */ + +/* #ifndef APP-NVUE || UNI-APP-X && APP */ +$icon-size: create-var(icon-size, 1em); +$icon-color: create-var(icon-color, currentColor); +:host { + display: inline-flex; + align-items: center; + justify-content: center; +} +/* #endif */ + + +.#{$icon} { + /* #ifndef APP-NVUE || UNI-APP-X && APP */ + font-family: $prefix; + display: inline-flex; + position: relative; + /* #endif */ + + &--font { + font-family: $prefix; + text-align: center; + // font-size: $icon-size; + // color: $icon-color; + /* #ifndef APP-NVUE || UNI-APP-X && APP */ + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + // -webkit-background-clip: text; + // background-clip: text; + /* #endif */ + } + &--image { + width: $icon-size; + height: $icon-size; + // background: red; + /* #ifndef APP-NVUE || UNI-APP-X && APP */ + display: block; + /* #endif */ + /* #ifdef WEB */ + position: relative; + // ::deep(img) { + // z-index: -1; + // } + /* #endif */ + } +} diff --git a/QXTfront/uni_modules/lime-icon/components/l-icon/l-icon.uvue b/QXTfront/uni_modules/lime-icon/components/l-icon/l-icon.uvue new file mode 100644 index 0000000..980db99 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/components/l-icon/l-icon.uvue @@ -0,0 +1,189 @@ + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/components/l-icon/l-icon.vue b/QXTfront/uni_modules/lime-icon/components/l-icon/l-icon.vue new file mode 100644 index 0000000..98d310d --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/components/l-icon/l-icon.vue @@ -0,0 +1,151 @@ + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/components/l-icon/props.ts b/QXTfront/uni_modules/lime-icon/components/l-icon/props.ts new file mode 100644 index 0000000..d457689 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/components/l-icon/props.ts @@ -0,0 +1,31 @@ +export const ariaProps = { + ariaHidden: Boolean, + ariaRole: String, + ariaLabel: String, + ariaLabelledby: String, + ariaDescribedby: String, + ariaBusy: Boolean, + // lStyle: String +} + +export default { + ...ariaProps, + lClass: String, + name: { + type: String, + required: true, + }, + color: String, + size: [String, Number], + prefix: String, + // type: String, + inherit: { + type: Boolean, + default: true + }, + web: { + type: Boolean, + default: true + }, + lStyle:[String, Object, Array], +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/components/l-icon/types.ts b/QXTfront/uni_modules/lime-icon/components/l-icon/types.ts new file mode 100644 index 0000000..beb7455 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/components/l-icon/types.ts @@ -0,0 +1,4 @@ +export type IconCollection = { + has: boolean, + icons: Map +} diff --git a/QXTfront/uni_modules/lime-icon/components/lime-icon/lime-icon.uvue b/QXTfront/uni_modules/lime-icon/components/lime-icon/lime-icon.uvue new file mode 100644 index 0000000..38655dc --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/components/lime-icon/lime-icon.uvue @@ -0,0 +1,229 @@ + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/components/lime-icon/lime-icon.vue b/QXTfront/uni_modules/lime-icon/components/lime-icon/lime-icon.vue new file mode 100644 index 0000000..260975f --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/components/lime-icon/lime-icon.vue @@ -0,0 +1,254 @@ + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/generate-icons.js b/QXTfront/uni_modules/lime-icon/generate-icons.js new file mode 100644 index 0000000..222b0b2 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/generate-icons.js @@ -0,0 +1,2 @@ +const { generate } = require('./utils/generate.js'); +generate() \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/hybrid/html/t3.ttf b/QXTfront/uni_modules/lime-icon/hybrid/html/t3.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4839ed54622625ab4497a10961ecec21a28551cb GIT binary patch literal 367148 zcmeF)3E0+iyYK(={Ek)QfW?eiV%t-gd&6@gb+dqA%qY@2qAji% zHakN^yV-QuKKr%n&}GV=x7y?B_IUpz#*d!RdQ9*0L>g}pnfS-i<4!-SeC78li!9nA z;lOTVj~qRwRh5&!vuz90WvmTKb;@0BZ!a-T$Bv&kDLuXIQaj!{kw&F)Cmb=l@&#wF z6}iri*Qnh1(UT^WIZ!^Z=WE*b4UZo^{>Wn|RsKZc_U&!<%!Ct8o>*he^n*V+3ag4(_tL+gNj zOXB|N81~5aeqGA{c|2$T-Om0M+4kpSyPQ8K?WMQ40lN+!CKbkwo_M^}{-+D#^E?&b z)^W!iJ=%`{PmgRnJgYWQNq?IL(HRm&+*59)&8}eeYw4i2r<3Sy`Y-%5eT@F4xBq_j*Y9Qj#-C5xp9lV(U*rEapCkX{k7GRk zd;iX_`@i?cndh@#1OM@L_;2xk|J|=~|EBNnwjb*%|Ac>hv)w`|G(^C zAIpE^UyuJUKQ90L@&0T7|M_G8zt(H&2TwEywf{J;J@|37^n{@VV3{y6+k@>=}u=jlKH z{P<6DUH_`<`G582^8ZV(@n6^apYG@Ezv}14Umv%>K5l>g82JD1$H4!`-)sJNzt8^f z=Ko$l$NzTzf9$`}`R%awwH5Z2E+TDsipp>EYa}YIvMIh=qK$Ps5u1lfbN}4Nz9d6r zegAFtbsvS|zxEg(ShX+5@b*@;uinV^RUBn(zp_%!zFwq)RFq0m*}ej!id2`>>#bAwVi)QX)Eodz3e0%q@#3_&eBD? zN;l~)J4+AgDZT6~PWnh+=_mbV7a1S}Wmnlv2FdQShwLeXWiQ!V_K_hnRQ8qqWS9(> z{pA1|AqUDqa<6FB}dCxIYy3^<7AwSm*eFGnII?1NpiAG zlvCtXIZY2ijgDU;i{%jF80Ay>*( za<$BqYvfwFPG-sVa)aC`v*jkaS#FUza;w}Xx653)L++HjWS-nD_sG36U+$Cp2E`@`YXfbljkK{g(Wcr=n`;YgsXJ&ZZLMu| zM{TR^w7u@69kio%($3mNyJ|P>t~+ZF?Ww)AxAxJ#+E4rIE;>L5>aMz*4$|Fq58YD- z>t4FI?xRC=sP3!#=`bCx`|ANZLJ!n~^k5yShv=btn2yrXdbl2;WAsQpN{`mDdW;^c z$LTm7ugB{NIzdm=lk{YrsHfdVyZ37wI&; zSTE5_b-G@rm+KWeL$B1U^lF`{*XXr+ozBwh^#;9BXX{ORv)-a}^j5u1Z`Zkchu*1o z={&t#@6mg8zTT(z>jSz#AJm8RVO^+?=%f0WF4D(!u|AV-`BPJfqtkTX`vtMC;F+b z)6evC{X*C4m->}{tsC?k-KgK{CjCyo*B^AV{-{6c&$>l_(O>m9-KxLqAG*znQ|Fv_ z!9|x`b|qKFZRg6ma<06q;3~RGuCm+SRdH2aHCNr$a5Y^mSKHNbbzMDI-!*UzT_e}n zHE~T{GuPa;a4p>qu9a);+PEEETi4FDcRRTbuA}SZI=e2etLx^vyPaJR*VFZKyMEQ?rHaod)6&?&$;K_3vPvb(Y@qeb}QX0 z?p61iTjgGNZ@4$zYWJ3V+r8t~xOd%q?tQn`ec(QHAGyMP>^^ayx^?a|_qqGRt#@C# zuiV#egZsv9bleD)<@ z#&74#`f|R!uiz{CO1`q+-dFKeeKlX**YGucEnnN$@pXMYU*9+I4Sgfu*f;S_eKX(O zx9~0f4!)Id?c4YreOuqoxA!~w4!)!Bi6~g`C)#z-`^kLNB9H%LH=Mr(jVdv^@sUU zezZT_AK}ONBmGhSXg}5;n`Eh={Ki;3ilI`d9JUWtLe)?$R1Y;m%}^`U4s}A^P%qRE4MM}vC^QaDLetPJG!HF8%dkUe zWnY8ZChQp6hIXNS*eP@f9Yd$kIdlnKL$}a9>>PT8o}pLh9r}d6p>c(AL&DIoZ`dyk3&X?y;eaqA92gD?2Zxd2kZ@=?EQ|`H!{OnG zFeV%sjtWPIvEi6-Y&b5A3**D_;e;?DoET0DCx?mQlyGV|Eldihhcm*NVRAStoE^>y zQ^L97yl{S)8ZHPIhKs_qaB;XKTpFf_%fjX1iZCNw8LkRfhneA;aBa9Q%nH|s8^VoY zcDO0r9Bv77!mZ)9aC?{=?g)2=yTZJ1cep3q8|H`m!u{caupm4b9tsbKh2fF#Xm~6v z3Xg}y;fb&$JQ#Uup+z|UJ5UVmEo1}YIrTI3a^JZ!kb}r zcq_ae-U(~MyWzd?epnkm2p@)zLJ>X=pM+1ty6{=}JbV$>hcCld;p?y=d=oZ?Z^NeW zUHCry5H^P&!%yMouqFHweht5ct>O3ZN7xo6YIM=Z5MxX+$5Jd4w~J+CxmZ3{h!ta{ zSUGMVtHi3YTC5&x#G0{ItR3sby0KoY9~;Dmu~BRso5ZHES!^C##FlY~*ebS;ZQ_ox zZEP3Y$DLw_*fDmBonx2SHFk^L=}E--my>Y8~ernahEtC4vf3T-Qu9Qd)y=L z83)I`;@)weI3x~@`^Np^usA&K9}kEl;(_s?cyJsU4~d7y!{VqoIvyU6h-2cB@u+xo z92<{`$HwF0xHvu@A5VxA;)(I3cygQ=Pl>0-)8eFfdORbZ87IfH;@R<>I3=DN&x_~B zsqun%VZ10#ix0b(|TmiPy&K;;eXmydmBgXUCi3&GD8v zC*B%wi?_$Q@s4WiLFWw&?hzsI_@uB!|To@mTkH*L1qWE}R9G{3w z;*)V{d@3%BPseBCvvGNREHVK_(}XUu8W_=&*K+yef%w+ zG5!>Pj$7g{@z?lU+!}w6f5dG`k|vjY3MrQ+VsYz;@nx*EcMQWLLNUc)q)F$ni+NO4?ecCB? zNF7tB)H!uYT~oKzJ?)%&q@Jl)>Ye(ezNug8pLR(D(!jK9+AR%AyQe+Uo@sE}EA5^3 zNkh`mv~Suk4NJq*{^@`;A|03xN(ZNr>5z12IxLM!qtoH(h%_c0nT|?Fr?KgnbZj~< zjZ5Rx@#%y#A)S~`N++j@>6CP8IxS5~r>8U0nQ3x5E1jLrNmJ6f>AZA)nwl<17p9BS zv~+R0Bwd=Or_0ji>54QXU74;*SErfjnsjZtF3n2UryJ6ZX?D6P-JEVobJDHpwsd=% zo9;+=rn}O-ba%QZ-J9m8`_ldCfwUk!m>x?u{Jh#X#^A5RHZk^lY9dp~SjbC29J_sYFk}LUAD8*7LI+wbXx|X_?x|en?^(gf$^(yr)^(pl&^%GHi=g5Eef6CznIHDzA2K$~JTc;tc z+!XemJ7B9dQrOB5*t(4rwuS>(%PDMC2(UU-*eeS7o}40+p!WSYU@JXRlp$O5k-}Ds z0INntS+aE?DeS7iR)nOm?;!$wFHuo}Y?Vlgie&3WQdA;aIg-M@qY7*dNecTu9>DkW z6jjL9m87Ujw!$PuHL|rPDXNpLI!RH3Z2d_J`;IEGl_)7{k*!HdQJZXaN{TvU>r_(I zC0ntQq8{1Wl@#^KRDVmY3g-Owz zY*kE(7G&#VQrO2AY^6+!9mv+qq-aI9dL~6{vUM~m+7MRyiXF+;)}&}lw#p_&JF@jQ zDeODUz*gR**okZnPKpj>t8r3vBwLr0q7&H)ofMtP*6O6_LbhrrMOU)*J1M%6t>j73 zoor1{ik-<;_oV1Sw$3L-PqGz1DSDBu{YlZAY!y(7K4j~GQuHN3`;n~?O3|NewNQ#( z$kq*|7(ljyD8)dswL~d)C0kXLVmGq&MJWc6tu#upJK36}6nl`ZK1#7C**c^YgUMDT zrPzyXZBmN8$yO<)*oSPrQi>sDE0!ebQBwI0+;t;a6Qz;H5TSb-PFtYVj zDMpc?qsi7-r8t~ywN;8E$ktt@7(=!KE5(syYq3%sMYbv{#nEKzvr>#DTd9@e7_v26 zDUKyuy_MoPvUOZ3#*wY)N->^nZC8rp$yRx#IDu@vSBeQ_E5A~lNVWzn#YtqV!BU(| zwk|BiM6wlPDNZ3Lb6qD zDJ~*g-bDe^lC6VFF`aBhT#C!c*2bl{oNSd`iYv(0%cYn> zwsJ1Tm1Jw^Qd~v0nl8oFWb5iu%p_Z3m*N_-wRS14C0liu;ySYRcPVC(t;9=lJ=vPP z6gQBq&P#D4**d)xv&mNMrMQV~?OuwT$yV{DxP@#zUy3;-=&fXH{8HRTw%RYn?PTlz zQp_d010cm6WcLE3xRdOzfE0I;-5-!*9@(7&Defk_XCTErWOomwxR>lcf)w+~?kGrc zAKASHDefn`%OJ%AWcM4SSU`5?L5c^-?mGjN_O8#igjdnprrVW>|T@< zpOf8{lHv=p`%_Y^C%aQ6#g}CFtfcsg?CzBmUz6R(l41kd9W5!oA-lIF#YVEbTvB{X zcE3xCO=Nezr1*~P9+(v0lidxI;s>((Vp41-yF(_$k7W1Cr1**Ku9*}+lifd)Vhh=w zG%0=|yQe0_uVi=Er1*{OKARL<$?mvG@jKbQH!1!gy9+19Hp2Jh+e`f?MeRSJs3S!^ zDH=%8NQx%HpR7L4q-cp0EklZKM~apuMaz+*>7Abl?DS87bdLt=1n-sl?6up@gy@eE=LyF!?irz+w z-cE|nB}MNbMeigN2OQh(_r07ag^c7O{RZ{ddQgjt5`Z_841}XX`DY}{zeTx)*n-qPA z6kS7#zDtU}M~c2rimoL^KOjXvBt<_WMGI2&V^Z`JQuI?&bR8-B87cZXDf$H|x}FsM zk`(=l6#beM-9Uk)q#|qCb$Ln@Q0hNztE3(Vt1tEu`o#r0B1t z=x?OxR#NnLQuGf}bQ`JFUfw@BRLP+>0Ec>VXds71a%dulW^!nW99o7Px*a*REIG6s zIkY@Ev;sM_B001YIkYl4bbE4W6>?}*a%eSjXmxUE4RUBra%e4bXl-(69dc-0a%eqr zXnk^M19E6Xa%dxRXk&6{6LM%%a%eMhXmfIC3vy^na_A1^&{pKo*5uGO4^b z?Z~0+$)P)uLpzW|JCZ{?kwZI^L%WbeyOKk@kwd$aLw6>J_8^D$B!~7QhxR6i_92J% zC5QGShxR9j?m`Y7Kn@*94&9X;x*Iuk5IJ;ra_Ao9&^^hagUO+Lkwf<;hweiT9YPKr zN)FwZ9J(JlbQn2wI5~8Ga_9l%&=KU&1IeKWkwXtAhmItN9zqU1lpJ~(Idl{`bTm2i zaB}DoB!`|t4n36|dKx)&5;^pAa_AZ4&@;)QlgXiHkwecWhn_ zhh9Sty_Ot$9XWIsIrMsR=ndr18_A)w$)PuqLvJRB-a-zYLk_)_9C{l$^mcOSTyp3g z6kwce}L!TyxK0^+DmK?gA9QqtN^m%gV z3*^uhySt5 zl1J;2N9&VE8<0mEl1CenM;ntzn~+DFl1H17N1KyJTaZUvl1FzSkG3L@wkD6ZA&>4z z9&Jk=ZATt$PafTgJlcUg+L1iki9FhwJlcgk+Lb)ojXc_&Ji0S^v#Cwa6Nd9*iq zv=4c-FL|^dd9*)ybQkjI0P^TS^60MQ(cQ?SgUF-1lSlU;kM2nx9ZVkGi#)nFd2}E0 z=n(SgQ1a-$&TC`Z9TRC3*A}^60DN(bveMtH`6TlSkhmkG@GBT}>W+i#+-^ zdGsCf=o<3qyX4XL$fNI*N7s@^KOm2ONFM!&JX(-PKPHcULLU8;Ji3lN`WbojbMojH zHeq-9{rU(`Wtz4D|z&H^5`Gr(QV|d_A>q{ph^LC6i`nAwGAPlkph}1pqT<%qJWm6 zfNn%Cg0$QB{T7v>wlLA_c0$Q5_ zT89E!mjYUk0$QH}+JFMukOJC>0@|1Y+Jpkylmgm}0@|Dc+JXYwk^;H|1+*0fv^52^ z4Fz;Z3TRsjXgdmMdkW}I6wnS7(2f+)P88726wodd(5@8FZWPe&6wsY1pgky{Jt?5Q zD4@M5pnWKyeJP;*D4_i*pu12&2T(uC9Yg`$odUWC1$0je=wJ%yUKG&1 zDWLmMK!;F3hf+ZIrGV~70UbsG9Zmt=p8|RS1#|=j^gs&eK@`w~DWD@MpodUE52b(} zMgbi~0Ub>NJ)8o11O;>q1@uS?=us5VqbZ9!CKkM*$sA0X?1qdIAM> z0tNI$3g}4`(32^k6DgplP(V+mfSyJHokRgWodS9W1@ue`=wu4$SrpK-DWK<2K&MbZ z&!vE#M*%&b0y>ofdI1IWLJH_b6wqlD(2FUcmry`2rGQSSfL=xcy_^Di1qE~l1@uY^ z=v5TZt0|x}DWKO-K(D2MUPl3)MFG8@0(t`l^hOHkYzpX26wsR~ptn#!=TJazrGVZ> z0ll39I+p@^2L<#_3g}%F(0LTlyD6aeP(bgcfX=6Y-bVqwp91;-1#|%g^g#;fLln@5 zDWD4}ppQ^MAEkgkMgd(!0ezeTx|jm`1O;>n1@uV@=u!&kQxwo;6ws$BpwCc1pQV5< zr+_|30ezkV`T_-X1qJj)3g}A|(3dHoD=DC_P(WX$fWAfnT}1(XodWs>1@uh{=xPe+ zTNKc@DWLCAK-W+}-=%=QM*)4G0=kw0`T+&>Lkj3e6wrbK`Y{Fc6AI|36wq}P(9bBK zpHo1;pn$HYfPP5<{fYwmH3f771@s#V=tc_Yw-nG#6wvP|px;wKf1rSFrhxuP0sV;r z`ZEP|3kCES3h1vC(BCMaTPdKwQ$YWqfNrB;wU_Qs5mkz)qlkKnXrPGNP7u*V5zQ3Q z5=FEOMRYrgXjzJAIf`g`if9FjXhn)>C5mWeis<$f(JB zqOB>SZ78BUQbgNQMB7nB+fzh$qKI~&h<2oicA|)OrigZ-h<2rjcB6=Pr-<%M5$!<{ z?MV^sMG@^y5$!_}?Mo5uM-lB$5#5C%I)EZNkRrM(MRYfc=pc&d?iA5ID585(LIEv_ais5h=@ij3D57UlL?=^3&!UK)O%XkZ zB07a4dM-uuJc{V~6w#>^(F-V|7g9toqKHnTh+a$)y@VoqDMfTTMf5U?=;ajAD=4Bf zD56(VM6aTVUQH35NfEt@EQ;v$6wwXI)@^9 zD@F7+is(h`vk_T}csrg(CVYMf5d_=qifn>lD#9D57st zL|0Qp-=c`VO%Z*EBD#hm`YuKEJ&Nf26w$R5(GMu1A5ug=qKFn0(T^#jpHM_UrHHPh zh<-*9{hT8D1x0i{Mf6LG=vNfcuPLG%D5Bp`L^o1Izom$7qKJM+5&fPb`U6FDGez`A zis(-i(Vr=zTPUKxP(**Fi2g39Ug1 ztw{;3MG37<39Um3txE~5M+vP@32i_LZAb}iL=BO6bXy(211LQz)UQQbJFogifM_o=yopgA#fsC3G?+^ejr~ z*_6<8D4|m*q32RU&!dE%PYIn$3B7<4dLbqBB1-5qO6bLu&`T(xmr_EfQ$jDJgkDYw zy@C=tgA#frCG;vv=+%_anUv6LD52Lrsqw^BlHqlDg037ty`y@L{ZCnfYQO6WXF=-rgidnlpzQbOlbLhqx5-cJdAfD*cZ z68az|^dU;?ul^Eu)0l)08lKh7xAaQo?LGCCr|qgxT|yFnfU#W-BOR_97+BUZRBA%akx%NeQ!8 zC}H+0CCpx|08hZK8zPca$*uo)Tt1P{M38CCq-LgxOD&F#DMjW?Lv> z_6sGtpp02d%9!my8M9WDF>6g3vo@45+mSM6Z7E~cjxuKLDPy)1Wz0HI#;hY{ z%sNrVtTScIx=_ZfD`m{OQO2x0Wz2S_j9CxLnDwNLSue_%^`?wjAIg~ZrHolW%9!=1 zjM*-fF&jV`vw@T`+m$kAyHUn$5M|7Er;OPilrh_rGG>D*W40G%%=V^?**=sp8$ubg zp_DP(mojGiQO0Z-Wz2?C#%zDem>obFvk{arJCHJF2T{iCV9J<{q>R}ilrcM$GG>QS z#%vU2%tlkj>~PAM9YGnhF_bYok}_sTQO4|O%9xF%jM*`iF*}wrX2(&+Y#e3G##6@Z zc*>ZaKpC?MlrcMzGG-@H#_VLum`$XN*(sDUJC!nKr%}di5@pOzr;OPdlrcM#GG>!0 zV|Es0%+98a**TOkn?f10b17qX9%anVr;OQD%9ve18M6y1V|Ec`%%)Ms>|)B8T|ybN zODSVEoib*ZQO4|Y%9ve28M7IbF}sp7W>-}txG&7_RkHIy;CmNI77QO0Z*Wz4Rp zjM)v8F}sm6X0s_{b`xdHZl;XcEtD~vLm9JMDPwjUWz24;jM-eunB74cvpXqcb{A#L z=26D%ZpxV5Lm9JsDPuODGG_Nt#_WE|m_0xlvjvnfdyq0_4^hVKVak{-q>R}klrejh zGG>oa#%vK~%pRwV*<#9=JwX|>C6qCHk}_sXDP#5&Wz3dQ#_Vazm_0)ovu7z|wwy9% z&r!zgdCHi*KpC?YlrejeGG;GP#_VOvn60FY*(;PWdzCU~uTjQq6=lp`r;OPflrejg zGG?nOWA+wh%-*Jq**lamTSFPMcPV4`9%anlr;OQJ%9wpX8M6;5WA+hc%nHhweM}j% zPbg#dDP_#oQO4{u%9wpl8M7}aW44|$W?xdq>?_KceN7p&4U{qahB9UwDP#66Wz05F z#_T)Fn0-$fvmYp9wwW?!KT^i*C(4-pOc}E+lrj5-GG@P0#_TuBm~Ewu+3%Dw`-3uO z+bG-2UWz|uo2^$WVdkiWnWqwFfl8P~Dq)tWgjuE%W_BswEGLrVOE<; znAM>YW_78ASv@LYR-a0kHJ}n^4XK1#BPwCmm`a#6p%P|Isf1ZGDq+@~N|?2v5@s!_ zgxL;M!mJgQFl$XE%-T>1vmL2~Sz9V$){aV;wWkthJ5dR<4phRdBb6}gL?z5RQwg&! zRKlz)l`!i@CCs{03A3H4gjo+NVb+sMnDwF(X1%F|SsyB4)|X0{^`jDI{Rw|t$lv`l z!v62LgUmFu#{TbEHO&?`Aj*y@(OcUZx}XOZ}op|nt> zjJ-l-7T8~YF;k?hZBur-S#N*oh0V*^vCD0+zx2YMt6+~SmNOH~W|2xZtGvYiQVaVT zxBUpST%?M9^sB5Csk%_4dQ~&b%onLK*8b9pL1wN?`X0pf*ea!^3Qlyogzm=V{)qIiGHH~fC z+K$=A&fUh&w_`B2PuoGpj?vEEZeQ1I7TIZmNQaps9m|>NBAsm8PD{)dk@jQ%an zI5Ssd7wdq@A_Iqs>^i_q64}ijzVB2r6AtHO*etWMF z*{80t?e)pzU+ua*=~3o3$bbPZt?EL*&o_W}V1kQ$$ADHlu5b9NyGyw!baL z&Uu7wH^ydTmWUi_+aG1;ILfZ)Xqz8x9Xra*7dfV?8E4jr9NW_@5IL@rvF(ntV~w+8 zjkDKg{3ekT=7>yaY3!IM+WAjhD{_(@=Onw1lWpIV=ZZ|UYnW)qI3*Z+?vzy`rw%eR zj2-W^_QsAksgkklIDMqZ8TR%W=yH)W?OM)UEi!qEvFFdSbDrJC%ojOltg+{&OcgoT z&Uaozvq|K9JML6_ZmPX~f$eu;$t)1LXr@^!GOfL_=cg?*_V{AEwu^1wiwBu8X1bYY zR*76P!mJm$bck6gGTk0ew|y=fY}ScfZrfiW2DNLMF;?WtV8$7H{;F9bSKGFBYMHrQ z$!QP zv3+i-Y3%u1>{xTe*tzCRF?KDt+BUaUHG_;@$8EOX?IVnBJ9m=E9WBi?vqI#~sUmmT zx$oL6GS9Y|w@Kvg0cM`aJ$9aZ=ZnlY_YD)d-_Cb`A@V>QGsCPCSz!AvuwyK+{T{Rn zd8nLOCi1YIF&i|x7=FB5s9WJa0U zX1&OghGwjpX4Z;4X>UJi*RxbiH)HdqD@C4aYF3FXv*RqAC-Ssi$I}Z$p0VwovF)Cj zZ03qQYuCHHu30VeoE`6Zd;Gk;{eo@(!T>YQ%r|zd7q*D37-BYwyx7v%b-ifkdvS%? zAo5aGW81%6&e*;$+c{pgbG*DxWM#>;H@5vNEsgE_$}F>7wU+zThq`i5_#9=@6IrGeeaDm3q;R34+oi9W`oE_w(UprMT$zsuDjT5|CdSI=i`<3f19!Q>k~Wf zC-aQWKb>H#>xP+C_SGo1@1I{;V%vPa-ab3E=l}f71zj%krJd_b+vdxK#?JLsUt{O} zx|~@ivZ1D#ZdQqWW7qeMop+pCj_aT#?OdMSiqn{cOkH z(pTh{HX^_FG!xAdk>70o+Z2(lEzKCSz}U6@-pR}q`NQ`4V}{7Kx}pN}?SGs<%WM&K zbIlr2Z*xD+tPl7;W~Nyu8atU8fBscunkHLqpJe;ws>Zgn&x*7(%FGij)6{Gb z-ENpEM9WSPEoa9ow@9>n8)N6J(9PKKDr^$1IM&QDcAiRh4VA`-+9$$Vd9CR7wry2A zU)5Ej)dm~J)|_d!iq;xw?Cn~1%-VL0+IB5<+8aAY-5H|wCYsHn z^%saXsA_EAhLc4bO*Qsx= zGr_DAZPnK-6K!qBZf(!EUM1S5li4cTHkcu1rD(h9qV2~TJN8cFL_65N9qqY}3q?B( zHY-Fs+p#*Y740(7*yFBE%}ldKwA&cb?sbhl*L{XrB)ao3(H?D#9k<6qW5?{-(Ad7c z>^!};i1r?7?E3oj6zyA6v|oE;$Lep}^-6x6eVaFb9#~D0NbT7Mxz1E2CZP&2(7E$|LK!=PF9oo&RekJuo3;1IJ}^dQ^zps{9#=)rcZk#=o| zG!#A5&UL8G4z>5?FgwO!W6V6!QDR1!b)utJh#o%4*zt~-D{7w`=$JX8M@|tvYOv_h zcC4}O&2+Ox^cXwOv3*64vtu8(N_5;b(eZZe$J_SD+v5{j8av(z_V$EMW`^jA?aeaL zlO~9sT-BgCLj*vD|jI?*fbm{)f*>qTeUKG)bj*UU6qM6aD>mWy83)C@9H z%^J~JEzNXe&s{%O^oB8_H`+e4?OZq6xo=)3dP~XJbGOVBog=2D8D(ahb)vUcHTL+{ zImXUqpAYD5D@1R%*X4Gb&Fv<7M>#WJ^v<4Uq3B)q++B9wc@2#n=k89T_mqr1ckeXO z`Gd_AW7lqM6nqE9w86U}^Mv!!m+-lM1ZT9?R(HHF4F9u_Msiv{>zPw6wJALhsu!D^~e%Jb58)MtP zKS|Vnuh+F(ML*ae`r#_kkL>MYuIR@z%@)y5?CnqO`qp(bYeYYrCi;0LW7~f*Lv+2p zFYE1`Uv@I~{8#q&*JDIC*m*V-qTkr_-)s`yXxFsSj{ogA(M^*@zq8~2&`|Wp0mdHx zI8XE^do6x$W9;ppH;ZnuZGW-j{yN0iv45K-y0xlVFZz2+Gtn#({i9?inAM`&?0DN| zh_m0Povak6OT@XpW|cTUz$_CNrihF7d}?nBadwy2<*~;0%WK5hDuOF55Lc$EnJ#X- zrp6wZ9c)&ME7!)@w&m7}D{sdxZ`+jLB(8!zU%}2-v89^xnjiR)^|>AFl@w;9Iv>u$5|cI`XQ7T2R>R*CC5S6r`d z#*W{+uCeX=R5f;ueYT40JIdHT{YHwjKl8i(^Th2k+1PUf7Kj_TNZhUs&02ATg1Fu7 zy7sVb_gEorPrI%?=ZG6z$t)DNm+iOLGI4v?HB*i4vrkX6PTY{$W~;cN)5PsNMBFgD zrs4M7aGM=qZ;u!y&i?G~4jN=ui~Aq6eF=P9#hw4m8y&V~S(bHKK4iq@ck-WUxo6qt}0jK^O{GQa&0x> zFjKDE$&~9+UNQM=FFeYWdjVg>{VyT!m&Td$&#y4$ zzTHguvJQazU&ilW$pIW@%Ka$wetdrbWj%m24?M$^uj2Zv`vDID-eAht?q$k@4*-C} zL!E%l7JDWq!<8YrGUdRI{gzsr;t@c9DLzVHlFeuezMLY`lpWXi8A0h?U zUI6NSEeEg^kYvj1xc@rp_`^d?`QvJ)oYDbs{RZy8af~Vd(+PN;DR1s%%AeLU<*jC> zyuBCj6jR;5PLKFj# zUbhYKG!y#$fR~vttOmTngz-uyaykJw0bXPx7wL16CKqY*HZWnz0U&QaKJ)Jbyv~Ff zb(wbpP`>#o0O~KemkA5<6(U_BaIm6GEAAH^WWrVr7yzIS+cQkq@tXr>JAtPQ*RF?{ zDDDS5%7l9_0QpMpVxn{a@FEjs*8osYIm+==0)R(FJK#G^U@aAuz}0)4i7MRp)i6^ix|;zgH;Q^=y8$SFc0b?=0MhsL0#IIW4FK)weE{$l6LV1h zoI9E5D+4^m#N0{%e(Ois{U~EzGvF@32mtvPv@@{~Wh|;^VljSOd<)<`CYGS?r6_kP z@-EW>jxn+PN+wpIoPmA->Nu|$uoi%_VD}cQwgHfD6~3>o2fV>Vd?DZ@6Nv!;%3bpc z6KkJiV%>fw1`7fBZT)U0HuN&F(GIu|RHtPWQF|p+^6I&|*uQPE$ z8DKNu2`08h0rxSn9r$cN&cubl?ZTIt*s+?4ojFWgR1N3{p#EJbd#D+37XWE?cLJVf z;$r0AQv-O5iA(MUAl+Vk-@6}xe3u?$V&7f>(q4u%U z!zlCcF(!@_1AxPk`v7k+aTH}AMgGs@x4Y^ANPjm2ApPCAcMsZl59;>TZt4M=& zTtLSaUwZ%m{GsQH2l3m(sO#Z7nHUD1!?ytNTMGG7&ognX7w{qzkKpqWHTw6Hjaa9An}qWq@%ee)<*@PZcxq zZ%F^MrA++1A8;2FPb1IMH!<<=`22U|`FG^`_ve_vnl66v3KP%t1MvMnUu5FhUI5DZ zCF*;worzH$0QW|L+bHTEL;f+~_FpLXd0f9x4|sryUv&bm1fZN>?`Gn~Lco3|UPAtt z76R^L;x}uV_$|`BoX^DnV}M7Q_}w-p{(CbMub`|~fY&SIO#B{o{~mR{S_~KfBmpA; z)caZ`0BK)Cov%I5#Oq~%r;b zJk7+PQTDqi>#xZBSLFR019SqOVd6cM`*&Qw4;jfRjw8zYj3ZbOxk1mI0n( zI;_LGoadM>_fDqEdx+^wHGpTBE+6^L`G9RqSAcw$SD3C4Wfda7^%kZp!gUeKvEkD; z!gTh%fESt0fway6rgPOZU2!qfxtjscFkQ)`Ob5MHSB84a@ta2nILvev`vLDVT_y5) z`uboIDyxQ6K(_c9&y zNnP`uOxJ=sT3%*4=!?46V@%hEdfQF{-etOWl+%6_0CWm31iZ&|9Z27Sc6H!7k_0>i zK>kkT@5KFCg@6ITqX3lARS5u&UEcwWGhKHzU^n0arikm>r6er^ua_20yF^YDHCLrk{-Wi1?Gx<$vBZb=OQ_pny#mg4)e z96%Is5b!+HEk_;8UuU`%*8tGQfqcMHz`aa&-d?6#SqONP=~mqdK$)w10WUILyb_QE zAWvc~)2(R+0ROf90Mxe*vL?fyxDOnZ!<-DJ_Kx;ImBH@RhrJHHOSo(;wup!*tfsSb zptF-dH9o=}rW3t?`AhE!ljx;;1D!*?y^C*G!<9U#CM)^RZ>J(rpe&c8Tn7uY6;!s< zZm0^hcNpy+-a4DNH}a|i&f916HgBtk+Y5Mz+nn@n;=Zaz90MMZr@#pQvXr9A=prk?V&dz8(1!~fppMt9h|Ve#S(-mu%ad@tQH6&9L) zy3a43q)4gB+xW5{C)6ZQ{+w?-1bLh2Mfn9YF&n7mwR(kCh?}=Xc%%*AQ{%%Tk+>Ko z_3cb@!}YO=guKVpF)EJNsmVj?{XbX7()c9B7)k>^-0F1z6RS7uwQ^i4As$y#2{lC@ zf=yr!R#S0xm?z>qK0cO6=O06UJF7(gDx<+@u)CZtXKSP*($O9a1Ovk13;V)t;WkH` zLt)qN*)_YjclNG5YUW~fVq_#Sf>}QMruZt{v%v=+1r%GF?dOIOf zMb&du>r11cu$_Zz+S=RO)(k$AxtRFznH4Kq#UeQ^rOcux&ujtTCD9zo?q8AaUoS`H zKmqL!`_RAR!+cCOc!at{IjS`!y2 z36Vg5PU}tdWSu&eP{(+kh^H?SyiO*UZ(ug$DP(SQJ&G+KRC1_$@jAa3&tpCjT*%4#N3s4!mBsIbJ5BgyJkB|+6uwW(xp zub>*ohw*mU#fR0G*RA7~tv)s0I=@vJzAYHc@C}U@3#(vFsC_o(7Z(~+z^ej5Uzp49 z;1K!U8$SK_m&|>u`po<#)h91*;o6N`ZjoPApY}QRyNCyxn*;GcQ&RwB_BS{C6Y@D0St zPA}qAiqAcBv)t8g{HvqsG}P)$6Vr41m`I|v#pwB3v=3Yzad|n0rO{yFK^m?uX9c(L zMlQe4=J;l`1&v~KJi%*^9pkmCI&1mTrORh|Vik+FZ`rbau_t!a-Pc!K5%tvW*;DI@ zHa_^ENKS;1_L43;{<=Id&!SSdyL6E!Hdt)67FWbPwdLito|yXVgAZnSlJGLIau#BZ z+B_V_%xMK9d<1e9?(&Aj@E?y%up@s|9?Ib6Sv(_d2OdO(8Oq*m&|h5?T%TV zsAq8r{uX

)lqX8wl5yl>xz4pqHlGgm@OSo{^P-JD4pJGq*ySqELT=074V#{!182`%GUyHql|7W{qZQe#dc6CvzZJTFxsi9OV zo`U^RFZpu{hZYt??-_#;uge%T&VScw3Ir$y|8h`vPS$ZTk*XW%NrUS8)SxRTwEMdK4UUd=k5=;*E(uz zLmTP7Deok;a3&s&{9`KM~(+h{9sd3=0$TQd@s($XPi*CRA>#x7| zg8JhdZ^~ZZXbvOU(uR>h5{Z?EeGVgmlr!br<&dIKDvrj+6^0Kf+Cb_};!bjuvk%zl zXfg@hj1oUh{+%kf6ckL$OGaQS0j2BH*BQAfep&^LWT#2pEc4>(=W{kK z3m?1W@^z~l8yXr{ueCW6<@dj$1&SSS z>dvwY_Gh=`oJIO-t!?U0o4c}_M{U#Sep09ye`bsl2U_OR8*P5QE$9ai1oZ%#Dfut& z<`s{-)wk5Q-H-DMrEGiGcJ)=f@dX!lT`1IvxxZC^b=hS+@Y}iSHr zoKi@yS+zvak;aHC7?E|IrM|nioxI-q&40CC{}``4d(G#6t^UyCOO`x-sQz!$QAp1- z)Q9=d?b=cQq&5!Sz%{jmKwBVXp|vAxS(&`2j4VkmUYtBiZx@;iE?B*?xs|uhTAW9JmWES1oyoZPBEeO#wv#`OuV3E3&4!rlx=1c|Dh`a#l1gvRCj$q58}n&MRA-rFKWx)>%R?EUxO> zVE_E{)VkW5x%1EStZT>pM&*}wV|8nE*4D1xoh7+O9m=(@b*<}muDYb>ym|dKHO*@x zX6`<(&CCPy7sk`K)Ygy_iIEF(Z%%cv?7aE?!P?|`^XJyo1{-m^eO+d)8Iw8?X_lDA zy19cCE~_sHkpMI2cdNR6@4Qpwj^Ed_Wmg@}$D(R+PVXl2WME@+N1A1g3N(1OD2$)z*$e*ekGd(yHOt zrghkrz%F{+ASESEMk+qmwr=Oz_V%?q*R=s#d57M~EHl!c{-JH%@5nl%Cb3!&kuqzO z9onuRvKP&L+Uf)ofESuIhKe?h((B1o#Wtj%-k?v3Kw^{+mA90aw{*3Xm9@NdIyQ;X z6jdA_C4_k0=x7-dYN>ZkM~_xEB*6zz)Ydn`vqkEhSc}O{g1MOntqVij8R_WZnkA)z z!VNASeUTL1Opi2TCxfrc4)tAO-xg!Z5m}-)082? zXryuAcNYYLCLTdmO6c6_QIwls;5NJMC8e>-s`9e)I|@uW1v&PD;>O|vJFZLx9h*wa zt14rqCH9hhx6hP^)wXqCE8g==BK7fTCU!i=6`@lUp|^N@=B!&huWwV4j_XB^&S22x z2tC&oZR(r1c-@>HuSG8uMQ4cW3=jm$%kgHALrJ6W7sZPhyO3eIRqwa@Ne(484vKr# zZR$3D@4==!6L&T#Z>rUAzR6#FQ(bfZ!p(;dZ(f+0Pqh3dj7P>HYN81FuBUMi`3*}x zPnV>AmoMN8)P{qyNP)6sk++{zKYj8fzpDQH^A~J6e0WQGo=S;#pn0`Ry;U+X@vIB; z2rPp>FXW^cZ*$4MCT8bWpTis0W`c6=4MTXWGL-W+FulU6YFit78cS?>hJ?MiZX!`v zY>#t8o~;CTTRrOY369xves>iQ!BSe}PPoN8jqN?*MK!K`gAxi=xys61RiTh#$amE& z3ikxm3K-y$zV0f_u}K)=M%_ipWDyK+Q*+citPWPrxoioj0?7^BDPJu?A1!2U5?h}Y zDkMaIM~mb>aG=eL27&+3QcPsNux2_hhgN{=j#j5bsj6!5WE#WcXbnt-)Sg79IoGLs z>e`#za&p?5+tn=!OUjmE>PW!OBc5oC2BtMkO(qhEkIrtM`c_S}V@_V)oQ~+Vkl@iq zv^1H7bqNZ^l$}$PYA`c8d@e}SHly&0pbfHf#Mfq&#^NC4_G_)Xw{*v&s;fKRwRx!U z>i;bKVd4i?ks3?J)#g0@D>abEpTP`|zpVLvQeyhB(*5Z0v(_;2OJ#V*T9S3rW;(T& zkYwg#L7HE@;4UrA$0)yS(^_U3B5Qbrg+HfZVQFRheM$@w>P8!{juQ$ z7M4&b1SLgHfU5W&52?c{t~4P2(Bx{GyEFBMKD=fZ>_)B+uYH+Y>2v$eh5?~A9S3dP zYqC97YcA~i%7$Pp~ zxhe}_^5|=?MWKwJtF>P}spa7P)F)Hxj9__bnZhRfS}LBLnv1R-AHFZsx=i~rvH~1K z8U0nC!9Jt3s$*&F$f+YW)?HcEYxe#c(M!??$K;#KAv5vOkth%HV01+EszoC)^#vY` zjqo=!xK8!mX}%JvIoixT3^T%q_R!foHq*B3zMF|d_)JxEuk1Rb_aEttnfhCaovF5} z>HePTyH~}lSbs?JBng28AWc3XfgsYM7k(&O#^Zxmf8rBYAFr&as60M-#T)v0$NCe| z6JqJ$^j~C}1M1KE>DNiwnfzq64E$_6O%0aghtH(GbIc{+=r+d;?8#?vMydZ1|9$lL zCuX9?Os+2OxABLXJ4gEJxG5BgkRS!X!V_n3x#Bp8|j1$V|iOFbHvkvm^Kb^4gj* zHEy~;7MDmC@j-2B)2Qz|S9TeEFxvaV3%$`0;6b`RXU>TuH7vpWSuNuf{U^s0DGymg ziPQ*}Q~1Fu5D-6f#NgM-K{hqq)L-_iKa&Frm1XqN$uadY)(Db1$f|kHZOx35bDo%5 zS@&!55KcRe?$f05?TGp9;kM~l}?w6>jQWRx@4%pKq*%e2wuJy(W2%KNop zs6wef(_jCgQ@XYmPx4;`lCf0LvL^L_O)reV=lF~hHt&!V_J>dQGw_~&D&ApA6yj4+ z2vg+JlcO<=QF_jeyCtrE4^#9x((k?#>i58VX}(kbl$p;lnPWEPJjypF)J>Su@6Vdr ziSJIMoj;=zXA#igx53!xihRWA{7}-)FmBITK7f8edW|u7uEX%Y6MR01@o`D5jalVS znK28(k>s8=P_xK5HD*_8W7dW>3vyV*3z2Ii#)Ik$u@SXM35`V67t|M`Bgml53B8cx z5edNCav?2ymE?$u*9a*HYMiGye3)9FXz9#INiOPK4)eX#B$AxTEU6<{LZB$8)Hr2~ zKlvo-3{!ZWy&f&g+3JBRIa56va%vp)kY+&jXn0P}K{GRcmQHZ-2bt)f4=zSLka~8V zATvA7Fy>~SZl*@s)ab(mn)ZmzFrmyS6^&{V!MXAozna8~lQeUsX>myG)Z`fmk1mWo za-@-30z{M%O$3^_Q4@h?l#?IR43n}jGOEoq6FiV44`l8{s~KTr^{? zGcp~9AsKxlE;PP=Qqp;tPqK($z>7cOFMXUJ8GR&C@l;p$EYF zC5|~R-VlBJKvbOal~b@|xo=`QZ^Rvhsc3Q`m6MNH)iRVszC%b|aCbnXBmbuh#ad~K zc3~B^Rpyx9SCa3Waw_j|%vr3}p?q5X<%#Hlx5W{MwS@e{C02)%T%1&!dQyG%MC`!Z z*>w@l&goc_+!N75)PUPO8~6DSJ{TJs;=S}9n`(i265{vJ&=9?mGNbW5wIdfEu2T3D zU?s?44?h95Mz)MJF9`l%?nrQmh?8yuNKTCkQ2QEXWn;2tkQ1!Rn}!FP8{V z-%imm54PQ+Y3;IMDRd#Eaax-OV6sX~wPiv&?RzDkOtpjhql9_R+9P_a4?(OXmCx8G ze1z(lsY6bY{Hl(`vuLK_O+8X&Fj9AW8@Vlu#U=LYtD;VQ)iLMMX`DXEQ|ceH`8}H^ zF4+9COBUHqB>K`#p#rcZPpjsu(wM4QR1w}djMzpMTLv;LtZK&6d1M$?zk{eo{KLGL z8D|4@cSRF>0b%IBfSl!k&U-j z4_CLwXY7IxSRm~8hXcJe^J;45o!4Jm+pqp0-G&fCA$(}b>1`ois5)y~C`vQ)It#8N z(Ca8UrcifXi`{J0$Bp=l!`o?Zsp}3km8oSjyOOjy zmvFC{$&Uo29iV>NjfBRenMM*{dXd2NyTtK3|=4dQ-@eG`%r*s+)_7 zn!?ri3pW+1eUr|lQRzx*>MF}>mU;j#kDIfarvA63sJ^GRsj0T7zG&NNj-({@kJd)o zyO58yx182T+9iT{S97V8P&4%nzeKRK@T_ehifIC!tR`bSqR|~!(OVIDvjXW|B7q*| z>hXjUPXC4kKbJa{HXl>Hn*3A@KmU~d9(B0R>g7+;9*Q`E*daxQqyrFc!>aE0W^LWS zb(VaixMvY3yyA&rU$Sz)X_( zb17`@fZ&)IOUxvR$MN^YeftWM6vd6dbiA1s*AQm2X!a)8aEIep;@11`Z_Kh$ z(;f{0&Lt11S5MjiMQo;&;fVyKdAM#8BT*5L_mjau-NEl3naZnUkljn91ky@|Ef1ob z5TGP?R1lk!nUx~OWi+Y6md~3znBO_ry5#yLY8~EM2Rriz=g#{DMTW+qCRF>bT2i!p z_iX%x|Jl2j7cIHUSFJWiAA1aOp%d@`q-iMYElbaZ;BkvWaaFWU1OYANY;IB-6+P8H z6Iv7zC)=p7*hRfM#oMr;4pAz63~zM{8oY|G_agOX!tCBN5a#;{)i?;!wLMy8$mtkp zk^wI5O#>Y{hN|fHu5S^}XS8Hqx&?@AMYjWRpnzB)Z7x<$Fa9zQsiW$5#R7GdhbH#X zH@+alGg{hQ>Lr=lijaXY0z)#n4jlNG1JiRJc;~=@cTkPSH&bI2GsMhxS@aTOGmU~M z=mjlj8lqD%nOkS6iCJ4`8mH+{O!ZR;9K$~~^~~|w{f|Xq>b=BY6if$hYweiPa5>Ys zor=O-%7^9bwxOVJWnaO$4q~2;!F;ApYgCA~&}3+v5)VnAT@9oT#+zdZ(9;B?3W{7p z_)=H|{p8QXo-L>_B@XJAbC}})2OOi-Ks7b8!!eEpb*<3+`-$4^7y%6CVkWom89s=g{ z>fvIAUN>ifw>4O_DXc!X^ilPH7q4IIDD#IpZ-1payTWb1sbLh2Q86k* zVbFdPB?p^1Z)jS%_P0Y93@l&U7_4va3SahQZ=Xe-chQMiF|*y}@95t$kmw2)BX-K_ ztgaU$y{DpyRq-{w^V;%Fbv0M?wg%m0F2p@W2UcIBzV7ZGSbc46X|21$pm!D&<(J~O z%92XVsD$tH@aKjQ`2#m4w@QShU=v73xCN*QT0kgb+u9_ZkswULU_^fO3>rcaV%$MZ z&^kvef_{V;sC7+P`J+2H@7mV3TEE9q)MT?1nu@HhLRU@gf)(5LUZ;F|^&)SHQ0x=m zZY(P)$T#!m=#r(I7Y5dbTljYss}RnT=z_~HTEAj;M`gKE6RwEb7WXWUeQFUGud4si zTHbCHW|O1PQp5|)HLg~_QPEl5q51O{HFucIp^o_C&CBBbv)`O}yPy!Spr^{_))_qE zPQ9N0_Az5y*TUXq(S=Rbc{#QIj@G84!rTJA)nEv&K4thhkxA0(8{!+RAE&wO1g+%m zD>5c{Xg3y!lzuDVh=emDQVz?!2eGs0BqCG?RvMT%a3P}w1TwI-^l%=e*dwPG@1Ev%S1l=V|lQ>dM=l(Qa4gJWsB>DA!=ksV%Fi=qsiqCG#sS zoi2;Tr6og#^4PK5lH9i3+|JrqU8lUPdL-AK+n$@NeTZ8rqgDxOYcJQ;meZT3jmn`) zirk2u6_)b~Oa;ZR?x?fGTu{(S7g{n8GVDB-i#kejJL_V#o$^w>?2%kl;zlj>0UBy^ z{S+Oq{6D0m>oiJIrx1nzk12a#8f71t_U-?O&hJbk^Py?qviE^d+^`mpTuu@ZMSMZZ zhjlFMgE@(eeiCRGu(SffQ6EPjYyul%Ly1wCG7%%pSzHZ`s-v*%jUt#9VYd(iMu*8- zItinsnL#}pot)pN?5AY+gf0%%&)SW*%qQZ~cxC*)%sb>kgh5XS8iLw-@v1n2C<-59 za(mb^a1c#8G}WMoDF~$pj$kI%JuX_A$w;#I`!+}89!Muu*s@@GnjcjUN$1 zszYwwNzY@ri~JUf;z0>;r&-$~T0vofzRwg!mU8T^8cmETiLp9aK)N``u8Ce{WEbMC zWF_fw4Vm{mlxt4!UkVDy{5FJ$uD zO~hw%Ek|7;P|S!YN{|+WGDUJcsbg^wni%F8v^1JdrZo{w5h)LRGC8oR6=r*Asgw`Z zQ+p7&muZhy2aQZw5BVrEqmk;1D`VIW3-yL_!`qobQ&L5)OWAc3rc?q^I-MJtr{~PH zPyAFojc827&TzTRYik&-<#H|4MioX1E#Q$38e3TPaYmbMwNT6EEt8t=v`;w3za9^?J>`C+@GU zELmW47nGUY7F$_fZXQa>H+RgBZ(AE~EA-bU)?cz?$M)stsSoRQIp#b|u(YV$snZw3 zvRDLDyS6TW9Xeh$Tg29&CBU?;)uTu`gm$8koPtPo*#;m^xYOi7;thV0!i`74ew=h8 z8x?H!KxQP-T1^EhMo*x!A$HLczs}g)c;2$7_H^%WY%cXQgw{BVLp8Y-E$&jYFE^*W zs&rv+URS-#6P&-MVRLFuU$E973e4>b>H@7r<%W3?ukQAG9ThNlbAL%wP)!9JL&3(zAPxwq z<0fw zx9~-@urAtB?WzT?`ewp0(SR1#Gz6M~W(a#oMw|FI61ON^A1GOGLOZKHXlDXw`rIGg zPBrHxKANoUJN4nsP0#ZQ__Gc0XfaOHT9{(~Ved*P@rfhKkUAuej{h-!Be#E>Z%(1_ zHJv?)u`n0ZL6@dCV1kv?M~p;hkJsdVVsm;qXp@JgvtmO>SPmHUeTMc3=g!F%iv^$v^G9*1S-QRr_BR*;u^AvFLYWFub2e?>ylIXahm;6oZRoU$CcYkC z9gnXLD=W!&jrz1X+b;eJX;ki;;oZ>Pxd2Nj^uePb{EI&MLV=;k!q6`w;;zZEHb?j zXDg>_`)do-dp%xEWZ^pNk|z4jw@rQ*qc#1tUXOZj0e)y&Vyz3y?|j?j_lzt?_14O> zn6OC@x&>AhnlbIp3PtYo3`4tvNd+qms)o@I(k3QbxYe~$2ge9^N|Pj3Ds6aTzUBet zRH@%ssLm?06qfou&T_rp=b}6O$*en%WFhCUt9KZtedqfOBIz$Jw3Ml{3XT3!mrt)R zcY5R<{$$pj-Yg;*)I02s?C*RZI4s>~G#*J#p?&m3-t@UQkiNV#9D9S%Cny0Q%y{q( z_HDq?NvGaq_zy7-D3^AJ!1)OYidL-(rA;czP!zmal_8s3y|jMO>I6?6*~Qy1Bd6-V zcumk#Xxe5f^aQW@Vx5`_^c5HPslUR~(rT`%yHu&9_zu!39EKbn{&EZs5vnLHt(d4& zlC8dpW4aupjo%2PIq=bRj0`@Fh(Pbah(N_IbR2|B*zhfiPi}|9=~`CIK^5GJ!?Rpg zDMJvdw5^2%X&eb9Q3>$)X*kAjzqGE(-0Djaez$)BL}e_BND)@qc;a+}q_7!tbjoU^ z(J&Q2`pQJzE$OTG{hjXDVzb_$OFZRN+-2Ax3 zfL({&V$9PUFkwMv{V1C632D9^UtNW}P_MUy>;*aoPSSYA< z-qTNoqSK(J&V-^}um~)gb}CfnJSY$yf0{jW3{{)th=)^*m>NoESl^DA8f-o^(6(`? zCdp(xsSfGjd%;;}4oC0q9sxHv-3~b&bjC%Nwn?)HmDz?jAxlh7 z(4Ji^Tx4@dsVNh2w-+gzo%%6xKf>S8^h9ang#%v6g=;z;#o>+fD zq55e;u(qBMtoi&q(G!ES>T4x_zQQd0w6d^IgY0sy$TZBJc>D9w^(Q8LT=48yOq~zmtIUtcEnS%9V(GVSxfz=$%AkM68FFp=hwqyMs$Q; zNOh(06E{dX0{-BvKJ}wBl-}$PREI7UYu&UG1 zcv|-<%Ea1t-xaGeWoURp)|Hsbwx-dQt<-Qm-kFhLw%#+pAtjT4g+~h+An+v zZI+>m@iFWqRFY%(5JQQHu>@=YbqS>|-KRem-(nH88q&MA16?|CXac8|QEpF%12G_{ z_9?@d_7zsLodr5;XlVY@B`a1hTg2xzhwZk~;z-l1?q0v+YthFW8@#rB+U}h9^XSh_ z1^K2zi@U&PdOXTUP4>l~xum$%W)C;dQx+~;J+OG`{BWbQSg-iM79GjA6}T;h`KAIB zGUf^FLC?2U)i;eG&QNRb6XG%GrSLS^3}mbW_KI9}q^8}d&_Nx*nhX%qmWM0(^K7JY z$utm}G#5kKKmmz~41RcF>w+w6OxV91{Q@s4Td}is?!x(fJ)s7x*}r;clkN-AFWW1; zQKR01O=g9T($?i%F&0^yA|AWlm~SarykfyVciB|amMmK^WOtV4<>urFMduE>O3F-1 zMFkbFYu>TiZ?-msdiv%qn%lZ_MOhK2;)SlY)KQ4yEqY`0Zj-6ZT^w`^A##j)xup*K z(1K-4239XysAwcF*|%WDqEd?~$8In0Y_eL75R5h1nAUSEEL`O@8XRfu4R$Sv_K>vN ztYpu`7&C%jS&?(;kCr-%$fBe|*5_<^!%{e-hLxov^?9=?7&MtbKR!G*23A*$0p6&p zyqUu@m@VgMbG@4jiidzahaQ=>7vpv7GvLvmY@?=S6X};auyW@P3Ol%yf?J0|yO~+}MIqjuZ zM~|D#v9g}pk&PtUX?%$KlAtZwz0#I0Xf#@Nw4XgwTa}TH$Aq_l-UuN`ML2vE2QkXw z#)L9!1!d}J1nK)QuO zIPDsn_*#8&?_J)w?|bP_9B!HT#>6+2!LNO7;%mxz-^ji`jsA9uL9$kYskJaRI$DCd zABI*r)FtU@XRQLxHn_@a>N~IKtgk6^8HmXZhL(>0L;W2s`3MS4;{30EgQLi8DJrtK ziyQ`QF8HQSR1`U#MHTe;@3j0R`-ji zUbb%T*L%YuEV`p83N~(p`6NH5{)zvITW2bhC;$4_zY?u7u@Kb%m7rA}&H{y^W|RJ1 zY~8}4KtOUj*I`Zy($0+ly%{3%t+gd(4bR>5t4(vm)+t7eHwK53eRm~i|5H5J#YO5+ zPO-(|uoUMU%4SDik#B8M|BPq?Mg4%A^UBo!$D`H*>2+j6Oh7iO0CxtBI2;X!Xt*MD zjz$=pf^i6PAV?-)ifmJk969oA=3l+LrnSRSLX4Q`NViumhwz`WZZGy@$-1&@(s%y7n$c>e(>^n z=A!1n;MT!Fb7q~@@Gd)(KKjXkKTLP05hoorhtRp{lsP0RqLJk^y41^PjgO*Bc7&f^ zn`Sk0<5`KaPsT!HPHkMFJ}a9j-_A}EIRVSJl%yhvGVgNYWliq*jd&8CLQFt>(&z$% zOr!v|eob1EGY`ChBtoQZq^=ecHXQOOAIVM*J0>P*7LlL=jjW>g$?oDocej=Du`(?80b)ub_2h(~20+F_k#V?Xsx(ai1l>Vq-^iN3_yd zy0V2A6tt}Kmv(Q9n$*JvgFhOLnat+An&w5#bAn}+788e8K$9t66~914)8*_oPyw+E zXq-iH!MXzDFd`Ue=5;yY&Y`syBfLpa*g__7A+rb~Mj;r`chGIJ#()NJs-ggVlJG_g zBfVsi{k9PX)zz((S;!Rfy1W}(Hdfb_mDjm({CRcgvdcoIynKrMsoP!>#$upZxU;`j(?A+OJQ4%G-Woa;7&9@tosJSuGXnOh`pNN>b-K7TF(KFzh6FL_iIw;J0|9@3 zdCaps)X)%8g*>2j@_b!7%=F#pp}6>xr@LbQ;KrYA9GqX#?OC<+;x{hdx%tc^a3}7L z9(rK{V_qj|m%%MY-Vo3!jhj418Mr}$mIBAQ#Nr~d38$WlsD|hADa_Sl@|4xdGj{1> z;_uUr*p){G^HCgSDo&_=<2uW@+27x26lZ#~}h{n*-pfo|#4>TQ5 zHAf(V2VDr`um?K~h}oz^CG%@{WH~8rL@4_8SKfO0uI)#CI-Prc&t>0eU*W8{cJ-Rg z7j9S&J#LuJG z^=Ttw>5Z-XzEQKQXU)xlVEr;QxoeUD{GScR)kdS1ZsmMmTUB^AC0mtWxTLk#UF&Jc zHBa{A4d}-pq6O!G5}DB~n?obqNY3hXOGzo#h~&>+Pp55NT32!1sx>2PR$W(-x!8Z& zh}Q;x_F&Hnr&k!E84TRKCjGg1`V1gjr1=E3S!HVaNUyVB!=r`hSqsd@v8fyGoS+d0 zVDn%9Q1vUWdk!4@!@(=>;cuydAM#(TTjcix_hi;5%1fuzV!`s`5C>W$5b2HWj9M{# zLiOXpy(r><`lkA&8~N7z`PTCf+`jkVl}`REev}G7a1Y;lqxvPKO8wHt0|)mWJdi1y z_8%A_&Eib^^gQa&(<}rVHw=(Cp*9==@gcN=;B+Dz4!4Ff6+sFk56O8?jm2P+gypfT zcvpX-e^+sr_BAG$q(WCby61Dr{&;`#&?Q}S)|r%*6JIy2o6~j4A$jw2dk|Eut-~qs zKb>PyEZqM%C(RusIT{zktmTb*`Ks=y_*3bc2 zz8|e>qYa_y;RCHd=x})<)Dts+DaiQ|L{DJfQXq(T;sx+TFl-~2B6&oqaY26bI~1h7 zOJk8lBF10LVw2Fy8_P5{8C?|F^F(A(k-(9^%>x?4gpzxr(|JaB{*p<4QUCO(?hOU} ztLplK4c&jTrseLG7=hh_JY>YlWEjGW@Fks(G-)8I$zWk4+J|^YbcO?bP0ljj>$X=G z7Vw^4g&kGL)FZvKm4dG(H1QC?OA7pAHO95&$-*CgS<%uMkP4*ic zRDn}TGxLb{TpY}ou(Xp;o+3HvRSW&xK@NhXl1NTq3pPanU^+`E_lWBT1`9x1{k$ANl0woh;`MHyR&?g9)|3 zfs-5_p6mz0ndW%1SY%-bP74P2TdXjO0y6j4q_zn1|1XS|l+)WrCBC=NzaR)_g@Gy6Md#X-~ z|1hSbDyjcbKCL#iZB}+v7-zcBEQ0PxP9%~F7$5{QFbxq52RwR$c#HPxVUr~_jW{+* zESAM%)bE)SASI7!QJZ1u^$2&%(-hK-7DU}NQe=Gz?f6F=@<=78lHfm@o8q!k9M(%a z5#uS0kPOek)TM^Nc4=D{SOy$OPXMrC1|X|CTH+A$jr>G77ZlM|lff+*jvkO|&gqI;-C3YVr7M8>)J0MLZA6w83fTMI9B@zJM?9K;K=l_MBYD6^Z`2 zkv5^$7@C{z-E1@bI`-uphtrpnTVCaK)K%ApYAQ=Al!6N!LaD7X*V_Vlx${D0{7cr5Bm%#52{J4N9HVKdFGWS z5J4oWas?n7!*Bv`Ll{JEYe9I46TP7I2}#ZY*&mS(+)u0e)MZAO-9_C7r3ld|9n`O6 zaIs0sTln<8K~|SMzgcN^RX1JHb@A-p_O|1f_yb8gNT?}T-_bjN_Mc12S{DV1ot9=p zuCtBF1g(6%`v*2<+asy z4rf()-b&dEe3x0t>Lz!{;#FFjzAAQCIZBP*=&p-z+`oP6CyNX{vv*y5gD!SQtUuVq z|EN<|)%Th#N<$+rbw;8c)0i(;J#o6(>%P`?@Ud9G;A_BE?7%FIXP z-_Z6XSJKlUFa_ZFSq*63!6jsKSe4;c!J>qT2!>yne(?jA5llC6jJjb=0gy3oK9Ecv zxH&}z`_zG(lgXP8#KkZzCG__J8yg#~sjI6Ykzq_7YpAPhz=VZyKV@gv@Th<#r3IK^ zg^HvBPc*|sC4s`*F;U{^#0+L+iYAP_9KHffyg&f!B+UG&_&83uNwgALt<{83wUS7q zQ%6|fkXlTc!(-}bk}yk-N~CBm%HTx%wP~kFX12ymmZl0}6RzdhhYMaLLmug86d^$` z`6MdP0Z4G^j8yBQ@(*UMXp|!sU#@z1G#++tV}+GYiFo`?nBX$$3UFvaX3q-6))8%J z-AG4(HNfsJ*N?6VZSKrcLc3WUI}bKq^2f(6DVcSYLr-I=tFBI#XFF+ls?aRIyTs5sG$P#=<$<0>=U27_sEg>(WAVV z#G*|HlCkR#M6bLwy6;Nf5|1CDn@30nIU1MAaG=D2WHfmodSG94-vRhgWXKok*ANuY zp=tircJyR$38hyLa0`}hLQ6u1jX^Ffdn6aNh3PlBi8_ws2ISu;JpllJSmIDV9imHe z5U4>UAtuw_Gjt%GO5@$kQx33hk+?v-f??u-i=>S{leCwg0BbgvPpX24T8yG-g!ss! zL2w!qM%lL0%Y`3O_B*wSN=J)mZ#+?!K4t0fIg{W9aUFs?VXb{?X9P&87qTd-q9)Lj zIf;fT;7|QX{FR{}gA@Yd&|rhKLn}DikeL~>uSpC>(9LiPHA9xf7@V9D(pMD4glF-n z3EJpBB%7%blAcC%w))Y3oGOL{U~TYFb97$q;48l_~pm*>^6)!oiOWjMFnS=H@V1LlhP?=2fvrFbKy$Qd?ScayVNaNpWyr%p6#SFUvPczGOZ}pzLJ(ll zH)<-WK8s(MM#>|1M%wUPW2!uhN2!%(aAp?m&@0La1o3RHI|>;%qoZc}f_Qz#-XQ%^ zD#fSuhdM&DBxcgn`KTA8Op|{z@k}FfJfU}VHE{+2Smy9CD3PomO z+I9;Dp1j8TAkF?R$VUh*_8YOQNg1nk)SkZQk;m@(60S zqh`Wl;&8e$?wP7TVW_C+7`$!O`J1;tvY~w7#>T>pLEZ`+^Uy4Pabc}EZgO0@EZyqG zTElv>+q!-8`KxXl?5L0PbOt}RX3m4ngsgR%ANV@SiNT9cus*2kIp+KG~6DMs(gb^jbGseE6< zU_D_oaqJwaCyoK>407G)NHFw2mwZVw19;muLvM#>Kmd=ak*t>8BPb^`&ZsQ%@6W)= z&;+zT;CG)%U;d-ll);11&(M*FXHb`$^$F!*>@$Pd!I6ctluBp9dy+@-tdL1A^~=aU z^u|oBnvp3ty{1p_&qNOn&eZ16OkB8F|2iN1Oza>9=HO2dKjcVy$dw8sex@NVD$#Hy zu76FzLq*OQ)5?Dn3d(Ex_|MKDOlEG$)I(A_h)fDHf`iYI>BKRuc;z$W-=CqwXCjT* ztKmC%ke|s7Gg5}gq0!_q*a7n8`GL(X5s~2&!CPEV@26%PBfoWp#$yGApApfR8ueDM zNY5i(ZBHn(Ghdtz^?ebIs?jo6IzyoG$7w#Hy699XLWdx~dPj zAlJk#wUwFq%GZR)X8mr3Gqil;Bg8{(&0(6sC+VY&$C{Z(2n*xt??L0Z^wV0R3#*X=i(#g?3U5fm7!!H2WZq zjo+bDr)HoQ$8lP8-d9?N()uZLp4Z2q6Xc;VjM8E8G3W!m2zZU0I(4q3p#$hi(IGub zqYdd%`FNtP7N?aRdgZ638B7GZnWA#Ehx^HZ2pmZgarvg5(aDd{Q`O|d(#q9SvpUZ& zJ6}oQt#j7oLtuDi)7B>E8;kM$H~Fl$we3oL>S=7{7jGPFf%27X8QggBMeDSu%CA$a z&E~Cqw0&J$`eALrTjNK<+l~kUdLq^03_l{EL1~?>XsE(33bbW>2|c6=2Sbs>7=i4> zjcq|gl`XTsbDD!(Ve)Bz&8siofAQ*OdZeJ*G}#2%u8CpUE?((;!`Za8CHt|YGQ3PA zA=_Y``#eDb{Kom=87hfE<;ta!e=xiDP`M0=>*Sz9)_J9nnuqi*{OJ+$$({yS?^dGgF|9GX^& zEKVIg$F_fq9#uOZ&!46EL>Z)*kq^cos8!o4FpF{{)aD??3<{+MTR4a!$e{JvMc&vnv-Ydk$074L}h+iUP7 zd4D6)mBrkp(H&1HOOs6}qdQ`x1Z3vn*I~UOpA}i4pl?AZrl)Cn;YZh^c(QPk1VNB8 z0?Kh5AWoAUe{D~4bdR!Ucj??}_{Uw2m>p3_fr`HnVd6jO{cGtm@!I&^(WsKbBevMZ zP8UV+^p(Xb{Rld;EA?=6!id#D8yhnCX#UYMiuLB{4nWK7+a=&5GM==C=;u zFbwxMi>=n;0r4gL@YzP3tx-In-YtJ{3;Zc_-v7r=RZ9_3BHNrbc+Wj=iKjz z?*PjN#FX{1`M?#&1Yqlf9jH111<)#RL;!YS5ULa*N)Djr7MBy=CCtC_Xe9)IwnNOr z0hh>$=q*@>l?y~$pL^IH@^zNvcwh2v2bj?i42aBE^srn6e$nMY^BhY5(oA{wWSYA|moaQDGjPLSa(>|sln z13&iZCDD25yD?F&Zy|h&U z#uJ=^|J%Vq?xiyVZVS-xN$aa2<^QwxC4g;JSK7YsS(fEZmSstncUhKX>v@%ID~@Gb zSsW+MzDU`_lCZ^L5B&*c5d}I-p|mVchH0T}EnsyhL(5VIeoUd$GX1+uL7t%nrY&^B z;6htEouM7;<^RsT?`d%qFm$|Veed3L&pr3tbI&?SkfF8}Ow5$;Cc?0=#o6LE=_p=d zug13y7n04h+vZ>U5xen4R>*FRzNoh$O(K5|?m#|Bq^n4h%`)AFbQHC)cpLaOhyrv| z>V=oTD5D*A+l%bRG#t{5XanI5(hTArIV>6+Qc7hTuq#g<8stC6yja$VDYIwXsO^)D{2{{N&%cEL8*E4wV&(HUzEY7lGVEE|`uW z`jWaBDnDKBKrpUIF8+fbeD1OV=~t8sbk?)GJK(yvLMQ4PNgm8~>H?Giq7T6AqOw z`J;McYuWSrQ#Wl~I8?n;XvLLO^rSJ0zG-ci;(W{fuE-K0giszlN=L;8ct-HLJp2<% zw1f8)TuMg{SfSKdWc1+q@F3uVVw8)JeoE9C!zM?{cv_6gHRn%`M56t{?K{s^6kfDC z3cpg+L`8LJsOhuTy9pXxI)!kn2vr9&|es^;gF&Z8QVi!;G)Cets6_J#zVqLqdL>^lJqe20)*|kGb8FR09z%Sscx`M!$YtnV4s3t2{P^^;1UE8gF~g$KEdTIXog1~*I6UCFg)-P zBFMe*AOHsOPx3iX;tEbNmtblkx12BQ$ZyLYqH1=Gm`r+IYSIDkL zsRk8=_9rEp;_hZrTw4pI!!dKOJ2#D+sYh|3e&fd0@2+ix~aNh}J_l zXcM{m74jp}dO(kIj2Cf*WuL}2n~D>@1s|aPEEtoEWL&bA@P=I$WK9af8`D7PlSq~z zBEYy9%4i55OeCHYLu4_V4S#B)vuzsHr`kHs^Ni*JnsVtUtoN6Z=9NG@o$rh9n4PX!9cfkCA&9V-2<# zu@|GvG3=69h@3r-@T0sqACkkPctzr(G8-K2-cnz;W#5*%`Yqj~!C7S%ehd4X`kLNq z>U#+PBYjQk_rx*yCxV)bY4m@lLw{;`$s?5 z_Hn3baSE>hTB8gR7L@LWKVWC+cUeVQ4ETfcFlYl+`$jmlfEq*#t{TH$icD~ndS@Ly zc)NUXt;B|l6^BPyR3kORqKlKg=B}t)w$DtEQPlB2$D4L=_X3;p=F3Iz`mq%^e zz-e7TTL}KUwgsTt!1cfbQI8zEwDywk#{5G`0n1Yh!0g!U{PY5BbM(HYevdy#`JN3*Gkvw;A*bq|^H>JkNqRIj~QYR&^PugP`Wy6o*`P3FwRq;6Ej* zIq2XI2>=fc%~cQ6AB}G@07AJo2p)I-yN^ITq-8L2vF{QGC%&!!gHUJ~^o!4s86KXY z+TIF(s2O-+&VYkYB3TXX;n?R2XnUsv5F9DV_>NNy{bcqqvPkQhpY&enS?dYCI3Z*Y zNz@~`e`p(fx>M}u_|Y81adLwnR4li5>Ny3Ekn~;-Kk6a^0%LqD%m0Js$z$o|HVf{t z7wWYbcxXB}DC`#y^9}fi!M2eyIg?%vW(_#{ac@a{MiGu|RQ*li^3ih-eQ@a9(dC8e zZ}$AtOrK9K@b#&?ff<1MjZ$-&v!^Tl+H&x~ z>;vs}YWzTKTW>JfyDfHLe0k)oMxU?otjO}`uBdB&1h|RcwEn}eqwV9QU)KGW_?a1O zB>hV=Fic0-2K9g4Ta8Ezg1DgD>^8VvSNGV>v=k?gCy3K<|4Fx{!tF_~S^}Aq8q{TK z(s{c`j>}sw)+5-3&>-SiFBExT!=OKJ9@B+%FjJFi%4S;|pHMpdtJmf;8eM~YZ`#G| zJY^!j)@IwjcC{bp%k&x*_Mt)OhTzfgQQFbZnaawl%F8dU*G(n$%pYjwVH;pNtpVtE@O4$0t)aJGy9P&p1T{nh=prLe zP>${zoTgjpbO(8YqB621)tBH)ldP@>wFHg{oITn17 zXSPX-2A0T(LKb70cBEbr0K^zza zC%~LVV^U&nd_0F2hzKC^bVEx9QozxnSg7&PCjAm`VF{c(!4#s3AHI-i9<7UZqw3u0 zr!!j$9AUD#c~T{j3iFfEK?t4&SaokmszE7JwIc57%6C>NHaQ7>1@*&Sf?4?vr1jAE z+Bn)y!>Rkya%Caa{UmXU|LUHzq##oKS{N9P2b?!1xS!=a0M$-ll4lr!snOA0@@wdW zqI@);Q06H|F+q2KIXta=F#gLH4_vNLss0l67WEc(38E~%r+$H5{JT4pJHCz=b$9r0 zmyOBfEb~oIe`yvWPtQarqUyKFUpaaSUQ%CTkE6Z}@TDy0o_QpRBVNX0K>Ov)gBr5P zMCP$D^i6(-F7yrU-j~$_>H$2y#p+qTLQeqWEp|z)`*!6HR(ywYyZqXFYU_LNvDa>T z;DHAw9#Efp-~qN8PwZ_dhc5yE8VnjvF+JpOCj3Wn*2R*=@`UsvvgEn6BzZW6$#gb^ z9F2cx(^ zs(x$4YRCpk{XYA_J=ZeV-(36bvsdRrsJ?mMSB_oV@HfX2Ez`GiP;=n5b2r^KDm8Y>j2M4MI?zQnrV_i@P? z@;Z1NXG?AidBWlkEl3F=Fz2)b-seY_LTKd(1i^!JI-p1e9dF|FDiXTnY*J~xFCQ$M zZ9#!Hq~t=CHtbUyxG5YDEU77-HJX7^Ni(;pKjJ49eqlE@dnn0u9wXqWz?y4?ytFh8 zOa5Id@29!YNik$?M!L~kGeE|14n>y$;uN69Dcy4`EL&-aUl&7(=7BqB9z8G|Xulxj z1@os*Yrc7;r7iyPh)iF2+wV%y#1jF~LPQ`O7C0sj#~;{=@CTBh(gw((omqdRFIqrN zC{^#HI5E9@>5>LxcMMQUKYAS6WDOR-BKaJ%c}y#!czGOt{h5r-p-X za9L+Xnr;A}!`=%sCjTXYnx~uddFcbQ1hnw9A>?vG>VBRQ&S9swqf9L2@^x0P%TQ!2 zuB-RAg+o1!m8e5hQf{xRYj8PhDr(kMd%cEYeB0h04)r!#@U5xbZsFgSYis|PKCjgx zm6lg@y8G&Ul@(rlhl~ifB14t6z1dgO?ekVwmsC`AwCdkVZu-_@^*6PFk7dn=0aB9! z?-_lKp1cC!YivLbgrY8q6oGb!2blq(ENp~Xmk&sqBXPE@?6Btf)8MXGA1-XDcMkS8 zuzF|xsFQ7H>Q#jnv%!RaZ3MG)3m0*Pvyknjrol=xs}BtJnkx&f-#4oNUR+4mo4^&b z_>_TbFm-5QP^O)QLfYtAAb5-V-t=skRpBB1O6&Eg`rB#jJXMKVWQKT;HleCS676T` zo!Zx0M*Sc}dh%=BU*mgR(>Wxv!Ob&4`JIx&EhFu8n^DnU>V>uf$rH6TPnkzv?J#G#UxfzXwdUQ(aa zu*kKKo&{ON+`$fS+Zk=%j;Pb8_?+O58#|)`H2{x1$S)9#@uWd~PM=48uy;EZi{0L< zD2?5C%(^$U)?TNclQ(I>&-F zYPH#rEC&mjVurhhwx`3dwwybVbl#ZF@vX$$u5~$4IY^Ilj`N{Ms?rO z_y3N)^*#$7#oG(i%jFsMt$4Q@Wb4&y@&9Y~|E~FG2;>K}v&0+nFTmA|$b?)D{{~2Y zCTh`Pg+DWRveoCY$mK|_$6kLT_1F`KFZ$Mn?A&jSee0q+_4SzgI&;harhYB;W2twm z`tS$p><57l*!In@s6S-ES570iGx+o%Z~8gF=Yot-oXTkW`0R1NJd`rd_zqD*f4G2C zPPsf+K{beEAyhU6v`$rz)yv?^@cif!b^**G0{Rjyu1_rX|^d1ZbI5*?x=v zs(pKW?ZN1l!8#|PNLQP-nku&rkFG;+d)Kc$D|Km3 z9y9%HorFE4U(;^U7;;C(-7m$+y0Bf+wjb1nM_%pZm1*rlf!9W9M3M&@@rw3U_PYP< z^=n-&|JaJt&pdm>vXQOj7+>XC>o%Qs)#Zn`M1yT@d-h%BKjhzWEZA=?-fA){{wr7e zuQd(FcCTotqQ}O!R$jZizT>RFrpL48YfUz4>;F-!w#rWB+I1N0p1b=))lO>b&(vyd zvB`SY+Vy)e-gTqHTPscKy-Y(lPz&V{dRP1Z6`^SOnW{Yb7u>lu%Zb0g&nk>fH0DhW=a~9my1Kzi+VDm!$ z2Sv8-X-L!vYl|b;C0X4Zd{4%!HnUdAP6Tp9SrAyYP+TIzB3F!t1G}2nQ%X))TVnk? zhl)P~X8Av#F}ZfN_~*ZwvtT*%WYE3A9kk0m+FjeVF`I+h?QMG;PN*zl#xMEIXNre* z_7gKbW3YRV|G*i!>y+AMey+u<>ltZ5dl-8$XIA=|rwVpXs%OmWWN5o%+W7@rAi3bX z@DF3O@c*HWoHlW>fyc!e1xg!AT|p7CP{rY#Gaf*u5)|b~@7_?Uk&12uVveJVI12@$ z{%D$S5X1^KJ;@#w!S_~OQL7lpfd5?0gz4; z1(c^cP6>~ub)^V!!1wz?61h*RjUb~|ybIQMo`DYzf23VW3g53o?$Ca}O1aE%%|Em#lj zIyb6-sKn-X?%J^x{f;xzp6_ZrJq*4;r$^Rqc!eueg{&rU({f78$WWVUPJP(0d0Pvx zvyIn2%#WD@@-9M*N=C*Y+ze*-wkXVG(ZR>U4h8fBfW@Qc1cx^c(#e8Zr=3h5PcdOa zkc9^anPs!%khHlW3fTtXUf?E;{%stK?;xBwf+PB0PB+jmI7#aNn3y5J;#?A51j)db ztAVTO;)rf+I0G)&Py}Lf?Qj}47Mk3M5*Ol`EVQRuqollsFB$o9(V;DKxa8HW;A~XuZz$N34f$fI8um2G+j;6SWrayCk{KlHI*ap;b;HM+?CNIc zsS%)Frt8oI?;yKWn$J11*_;f85~YpL%QbEdV`t3EPKS}>mHD#PAMuP}b}x&$+eT+46o|+P%X2EL2E<4O-qd7oW>figpqrZ2Ic96-p)$0lbUT-z&4B`u!7>fYV({modN9!53^+3WLx7pW zuRa!1S<>Egu<2et22|3D!YH>`rt=>dZ?nBAD#qpIV}wgM#+SW!!CC(l^anj&K=V#% zp(AR3N>qPcz3tp>)m0lTjn{nnnnufpyi}Pw-ZePblu-6-gij25o8G|DrO_t^EU zGyMA_VaU8u$d9SFSm*HjN8o-aWDRkj3D#F`B{o_ukR6ejE#wGAV7@);*HOrgSEw&P z9zODW(L`hF?lYx=JNZZNFX&&`#f=u4VubVXWKRN$8KfoB|1?n4}*XLsMPv&i${)R!?yPFOv5^U<~V-Jv{q4v2~w=XqR9T#{Xdjvex$nD z2Yb=R^zG8s^Y7jsT`rwZxD_}O_nM$b%Yw;~(?oQybbBxaSF|b-OCFC@WgD}8I+O-;xL*uqN(;X+;vuK-QWEk zJ-W}>==GXAn<_89xU#t;XWnZ|+_kI6>ALaNweFJhyk1;kzT^^fM{_PLg#R?H;*e-0 zA3^+!S(w6M7k;!*x~HdtD{uAvB6}`Crf0aGu2)PK1xYB(L{{ zHQIa|_mTGmsKNsbV$K{4_ks%`unaMf7leJkW?wmuv^2*qg2j9yCY46z+rqy2Z@zS# zh0m0RQa_av@VWdD{BZL*kNvjkR0;=9>I>+PMe!2iZS?d^05yjGf*8I+p zQ+>KUjcUn<1}gyPVZbKV;c>1*=!9mGsEE9!NoR_PGFn7D*s+SczjeQezF`pW<+g@VV z_4bxHofA%sp=P3{rUY+m@B(k~q4S1Xy1|nJYpG^cgZ~3aB!ok&k+Lu&0}ZMiV2+DO zNI=49U&z~sw0I7L12}Zs8z7CQ{1-8=`ey)oDmYt|IuC&gK#`^kj5+!e`__knS<)LP zF#9142-!fNtE_dInVIaxl_g8?e72s9R)Fu{+`b|^n1jJ>hHuH~gFn4k2DksP`r<5k3y9L#&cMeHVPVMA?sxQ)8 zmeAg$;n4L|WU<7Z(C~@fo9WuAoj^L>#9QOqsigJ^+7NyQaalxXO6XR;Mh&aK8wP~Z zchxX655L0xT8HsF@^>J$Q!ERznv2w<$VbH$SJ2nPyy5f6UaU!Dw)S3%5BgV)fA*K_ zH#A$=w{3uu1=j{JN#-OBY^p!`5>ocfQF5W7gFwKj%sdH@%jwV^J+DFU^3QMTaJIJ z{QPulah=C%Zr-HB{Yt69ZLjkbR-V_ka?{Fc^?MC}^}=D4W^oUD&QfDy=|9>wws|Eg z-ESUilb=t$WnkV~Yh$rR)rNFOhpor)$9DcXl-yF1RfV^P{BB?d zo2Tc%fi<YG~+9GIxB^)zqW;T_qvdVAl%9{D(OUv6Ew zHZrtg&~w^ex2Lvt;=qB{c87KH%E2WDQ>C-9&9i-Lb8Btwnga(s&GjWU!PW*#Y0+MN zjR?3`lJ5PJ!A?#F+)BdT4aBQYJRbG#>Lp9s&E|GIR-h1(jX%>nv-y*cReiErZxT(Z z@7O9TM3Z>b*Nxz3q^Hej#xmT?8q(FNIc(~h$JL`*3bFKesiW`c_|4*z3vH2HTf6WC z#ryO)u>XKX=N@v1VJ=Xdaz05(V#3FdixWvMpIoRhB?$j#dKy=2-;VQ-5d!oQ3xM6DM9gTPA;hCIsBew+H+n~Rvn0^{{TA}}{ zHZIODF|JEV(h;N5#>4jW0i}6roAeOB1|u+`e*D~A81)}~(t~)RzRDm6=j^9M8+^(# zTPfdOJt0)^O;3IL1!y4O9!n(i7tsb~DMN0&#&h1i>eq zB_3x7b-d-F4bg{A8-f%vq%qA&MW1)+Qt1^w?|f7mQD`KRzUCphO`{*=J4=%UvvJx` zUrocD<{JyO$6_J-Ect|~gC9Z~8vTDFzQGZ_c)l@p{CF72Mf1p4`S=Dq8<(TP1eZy( zXajTWqxFwRX+DQGULHPrZ1@%an8w$zP8%p12K@6x_Qv+!S21a0F zY$xX%U>K*Sjl2@F)p5!_B|pue|BUTPlf4(erx0y?j6Eeua~)nZZFq^2!WwO4_7vVH z347Et$EDa)atKAAW9%uzg5P*>eF%FIJ?5~AY(l|p3u%MPlr-6!sx0LVwH;j@ftIF2^V5e1 z8k;GH^4@qHr*C*SkpDyX#!h3gtcSo1ImaWt-gR4)yGCN25Kd>H!cfwcbeAEziD8Fwz^1Y&zkkE-4SJN(b2=F zt*p~%QXj+Wzho3v65K+(kOaz9{6%B>FK=taztm^wZ!atF+V&TXQ1Y7k{SmL%zua6X z6}MvAveqGK#GsqAB8M56Iw@eR2A^9-E(1p}w1&MmP|ogxS4%3@#Rf}WZ+-A?+uJrd z@#N=_5Djy=xDDIf2vsaNSgkTr?80v#Ztst5&4LOBu0rVh} zi&U`h6WD*+n~ZO`e+d*cJ2i-R8XtK?Ekx3(3@V`4L8)NpgO6-MsM-7@JQ=wFFw<^X0eKY(3?M!UGz%YTYtUh| zSdDI<7``MUh(JwVRH;7F`da0AhXs05*Uiqdi>8)5ntD|#c&tzTcL_RCj9r}PY3#-D z2CX8WSeiNHouzz5K}*Ot3Vb6)3q?x#jF`Vrx1W27TMJIZ2yM50m&p# z{OFP?^^4L~J|L#H?=g<$c>LGg9%dv&BZhkxcBr+mMDHv(yWrCWH)1S;tLfg?&_olz z)7*$T>*LFr3tmX2h*b~%sdG?=6-qtSlQsgWWcZ*jd`1sxsX`F?i4&j+@`QAVm&kU8 z{-^=$Lq#E83e_k+VS!4Uq0Zjy+2d)p*BR_)Q$ShXJ`nH>dpo4|sxrhcDVKIX(0!@m zV63dFUFz@-djbRP%ay>_YplvS!>IZ&e9l#^RkmdTX{XKF`dmQW*;d(7QBhIqDlC;N z)|W|zl2mHHz+MWTCzaW~6&1dpw6#{qrG>6iT-G92I_*6k1RYda8a+LZ8mW{?P3>Do z2irXkt2`9+G_^M_EmV}krH$=Pp5Tydb$HqbN4K;$Nvu@;rKP-a^EqMV!V8t~IlEds z{@$K3Td&{azGX~Jl-hgS{8eV7*Hv2YaTJwXt1Ig2DypsJMUJjD9UW`em9DNYb$N~E zDt}uqrYbXEp@L1QMSOq3V+GF_`~>p_L^g2uQO=iz>re=VwjCf5$bL4=pvY6oLo>Re zog#F%Sg{Fmmd)o|e285wUM){V#WB@T3BeZ?|IAFVy$ylE^)TkHJL4yn8PI|wlwfJ8;1v%H#qlfudZk@ z$R(xqojXA(J3H%3OJqY!MfLVQ&W7cK!y7AYMYS4*p**s>Wr^2bR%tOe)wMg9R66Ud zEzU;+OW6%pYpuCfMn$o5WN&|{Vj_!dChm2X8x2gx1y*ZcseER6Wkng><15V8!kW@5 zb6bbiYN=SNlflvoi`ClEX09r&DYTj^5T;O8QCZ%oURL8MGn$I3OD$D)XI*QL-CSs} zH`FR)Uuia(wyzKOw2w45IY+yjYa0;^t0>4z-B{b)J?d;~9%=6huitJmHP=*i>$KWk zb++A5XtwvX);aA}meT4Xld;TE^O-TFR{gf2$XDOfP*zc7GI(9`eaf+lN=!l%0k6s3`tPIhz=K?vRSK z0SPDiyet`wCKJrg1Lc`LfwwCD!S&TdohR-=0=KAt>W~_pX(y#&`wUAQn({}Z^RwLj z5q@gZp1PTtIuA*E;8|2}!&=Y+3pzz-WJ8mNK}My?EFT04a+x|8rEDg= z<_>j6K3h~}l>QNL%c#8sg_x`Gw-kv}C^ZwdJfufMpeOoD;pnI|C0-6nKntTgtiXQ1u34A+6)o; z+F=WaF!qbx>V-X2?1Sj%>`3Z}NnI>o<{rR(G9+J~+JPwFjL>3355YQBfHw<{O zdeI2rg%C;kw&G}(cnR7DhG%EF{Z&F0BT7FIPt6iOg-kUI`qF6&m;e*gpr&kOkgVJ; z;#@?-m;h9#2^k@yp6CVvFV!NiFGFDUFAloi$Z617kAs)%T(9@4ocAZ%i- zxGg-|5+k8rsJa&BkcxTn6i`T+$ELG-K`Bj262{R_$qux>^szhw%Al&O@TIeQsMKX< zFh)KYbVE7s|G>&wd2>yAI5oE?kkmo+v;5GZjU`+30c|NsJ;l>1OvkZG1h1WyAK{ck z-sRW~$gIaZa`ihx2$AQ5Li$X>@o7{r=l`L(MhvT_`SWlajw2JiKCnkbe^P8q$wqhT zW{mD|Ftt;3N|by)+aG&OeFx#cyq|O*M3;I_i8PtmkPZqo zuTdjXXME$Egw+=LA5m9Ggwea!xu8Cx5IdeJ>WdqV=5thJDPEi;Dxu zt$|g`baGFqaK53Ggeiazx_~VbhTa zAJ&u9)mN!&=^b@G5>YS0`1EekIhbwcoc<)JfNEsrj*#+VWyY8_zLtIaTJ#ZW!y_8Q z@P0>qHn#c@JwoOqNVrWC38_F7+{G{mPXWGdA z!R1o_9!oiEWS|eRPY9k!v{yjeJ3fcU{rD*&G;GL4cfIsp&T;wOjc}pfnDHACzByAceEl*%g;fX*I zAB6qS2f4=rc7slWbi^Y*#>Eum1w%$+xC&9RIzocJb|H75xE~d^znwo(O+92}gz5p`z)6gB5FA@1gNc68x+dk&dm)KY@>lAU zKVsPUp{OPfg`ksvkiW?_DMbG$*A)`O=8uk$he8!R7`9X}t^T&d%;T66<_`6@>b2mr z@V;7o@cs!?>aU2+a#nl9G;zQBBkEG)Q`A1K>w3_BEBb&wMXL;rSPVWMpHQiQ+v;Io zkYA>mrNf*mK&f$B+Orrz92^UMqGkE9gQ8any;Y>3aFModO6|o{Z2hLI`PedaR>yrs z;29ExzX<;&T{EzWN#v(s5x3+5DEza2cC^tIb2ZktG}l{ANU>U=C?;!tbBp?O)Q(23 z%{Y#LT}_e3#z<4Wqq@{cV>OmmJJc7V$yg!*NgGqE?=cCU^LPL?CMY|7E(|@rHei?X zn?SSzG--%vuC+sX5h?TtG|K|8ko=X3S>uTV=V7sZ7CHylnk{eeO42GY z@cQ%6y^;GMAH9f}5gj7y^!OJ#Kf?;*U*;VmRR|w2)$vaEEc&gy|Nf}@O$9PPc2(Ne z(qmM?@4b{2T~n!7VDrUnptF8=3+Y3kJt09A0P#nLIgkokZFRM+4J}@f1>{u4YHe*wUoJ1NI$XERX;q#mR;;ehLBkQpt574kC@ zWq@0{JQg47j`jy}`j84VS!`OeVJDcm<#oZtW73B4)MPA?Ssyc?2<`mFTjD29eM}I* zEW9;c{F(+AMJYz!9OP)g1zwJ+rB?O5g>oFyS*Cz^IIyKlL@pNRM_<01$OTEnjUs9M z(U}?b9c^raXZ%5a6#S|R-a-=S0Zv>{nDXin!H~2aIk>*~)6@^{YIZo94~Lx2>%MQ6 zzk%djx5n;r?bz-zgq-8f>&Tx@;7PP)rn6e6HG@g^&Nv@GVm5*e-=G3=y9_ERp)+lc;@?+8jQ?->7_H3S+LRB6qY6q8v|S+&w{(9 zojOS6>g_o#ovnjY@oJ_`9rxr(0_@YTRZIfUQinAZ%*+B-rG)v!wvHsLu{cdeYDS7M zn>uyyAe&5aUtTdrp_6Gog(s#A%_;d|kVQM6M~dmj8^iivK5fvQ`j@zh)}}5$3IEUj zQ}mkO|C4O~8Z`N|LV3MF&&ldPkE=pnSI|FY-9s=7Jk21V1y!DgryCX${!VK{5cDO>5TZ$ONk!HbnX!;git2e6Fpv@K7i7}_YC}G*Z8$v>$bqN}ZVmrY)<@bL ziZ(b#biY*YW2F&G+9DpviQzzNTtjwG)~5s)qX)TCuB6olIVMeXtn=lUhhKSRm_N#u z`YXH_^TK1ULj@5?c9gk@QkXlCR~e=m@+u*xRb*p8`UM!k&B()`xsPHGA|0;*2Oe@0 zu)J8dYsJ`?$5!krTe2(QZ(m7!)KdR=r%Nh~oOi`}kwVGUIqqNDjn7xM`vbe!SK@FV z3&*AZT>I&k*4CC!ueEGAe|Xc1W$x;A)irxUU7H7ri(KKehK9}xyNZejHg|>g)Zi=k zvK5<#&);y1dXBiC-I*Rc)s!Hs7>^@GnpABZNMYd8QiUXtlyz+Lity5HRioz&!Njgo zVvzAcDay-^)z_UlQapZP1m<_7?_YKhM{kXG|1ul_L)e6jzK@Ng!$43h9{z+lx)OJ* z=de5Dh-A{&AmOMU6^RNcQ-cjvg?LUC_yD_vL$ZQmN|NE!7-UHxtkBq|EJ1k!mgF_q zx_w2a@GkYfQy^Ccj+a(j+e{^^I-xA*+22|No4aQ}0_U(nUJD6q8DQmU(*;e!kOZ4! z)|~o4g^oOf;dz%)42x`1>^A4YYY#eu+XEJJU2~g^GF$4!!B`;N%T`>vv1d~^0)pM0 z_1$&s3y6CxtsGN)MJ3yZisgdA@$o^{x4qBP>Z)^@tF0sF4ddOCeU8#qm#^N^v$eO< z(q<|i^uQI{yWCe_=jμ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%0Dhex*SQpBHF%xHi>W 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 SCzG;- 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 bPoWB6`G0ZgOB?*g*7}`13MS6~MgD#VHB9bq literal 0 HcmV?d00001 diff --git a/QXTfront/uni_modules/lime-icon/index.uts b/QXTfront/uni_modules/lime-icon/index.uts new file mode 100644 index 0000000..b922819 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/index.uts @@ -0,0 +1,111 @@ +// @ts-nocheck +import {IconCollection} from './components/l-icon/types' +// #ifndef UNI-APP-X + +// #ifdef VUE3 +import { reactive } from 'vue'; +function definePlugin(options: any) { + return options +} +// #endif + +// #ifdef VUE2 +import Vue from 'vue' +let reactive = Vue.observable +type VueApp = any +// #endif + +type UTSJSONObject = any//Record + +// #endif + +let topApp : VueApp | null = null; +const _iconCollection = reactive({ + has: true, + // #ifdef UNI-APP-X + icons: new Map() + // #endif + + // #ifndef UNI-APP-X + icons: {} + // #endif +}) + + +export function useIconHost(iconHost : string) { + // #ifdef UNI-APP-X + uni.setStorageSync('$limeIconsHost', iconHost) + // #endif + // #ifndef UNI-APP-X + uni.$limeIconsHost = iconHost + // #endif +} +let isInstall = false +export function useIconCollection(iconCollection: UTSJSONObject|null = {}) { + if(!isInstall) { + console.warn('[lime-icon]: useIconCollection 请先注册,app.use(limeIcons, null, iconjson)') + return + } + // #ifdef UNI-APP-X + const map = (iconCollection as UTSJSONObject).toMap() + if(map.size != 0) { + uni.setStorageSync('$limeIconCollection', iconCollection) + _iconCollection.icons = map + } + // #endif + // #ifndef UNI-APP-X + if(Object.keys(iconCollection).length != 0) { + uni.setStorageSync('$limeIconCollection', iconCollection) + _iconCollection.icons = iconCollection + } + // #endif +} + +function useProvide() { + if(topApp == null) return + isInstall = true + // #ifdef VUE3 + topApp!.provide('$iconCollection', _iconCollection) + // #endif + // #ifndef VUE3 + topApp.mixin({ + provide: { + $iconCollection: _iconCollection + } + }) + // #endif +} + +// #ifdef VUE3 +export const limeIcons = definePlugin({ + install: (app: VueApp, iconHost: string | null, iconCollection: UTSJSONObject | null):void => { + topApp = app; + if(iconHost != null || iconHost != '') { + useIconHost(iconHost!) + } + if(iconCollection != null) { + useProvide() + useIconCollection(iconCollection) + } + } +}) +// #endif + +// #ifdef VUE2 +export const limeIcons = { + install: (app: any, options: any[]) => { + topApp = app; + let [iconHost, iconCollection] = options + if(iconHost != null && typeof iconHost == 'object') { + iconCollection = iconHost + } + if(iconHost && iconHost != '') { + useIconHost(iconHost!) + } + if(iconCollection != null) { + useProvide() + useIconCollection(iconCollection) + } + } +} +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/lime-icons.config.js b/QXTfront/uni_modules/lime-icon/lime-icons.config.js new file mode 100644 index 0000000..55d8d98 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/lime-icons.config.js @@ -0,0 +1,23 @@ +// lime.config.js +module.exports = { + // 输入的文件目录,自有的SVG,如果没有则不需要 + input: { + prefix: "my-icons", + dir: '/static/svg', + }, + // 输出的配置 + output: { + // 输出的文件目录 + dir: '/static/icon', + // 输出的文件的格式,如果是JSON则是一个图标合集 + // file: 'icons.json', + // 如果是SVG则是每个图标做为单独的文件 + file: '*.svg', + }, + icons: [ + 'el:address-book', + 'uil:12-plus', + 'icon-park-outline:abdominal', + 'icon-park-outline:acoustic' + ] +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/package.json b/QXTfront/uni_modules/lime-icon/package.json new file mode 100644 index 0000000..22f4af6 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/package.json @@ -0,0 +1,110 @@ +{ + "id": "lime-icon", + "displayName": "lime-icon 图标 iconify 图标集合", + "version": "0.4.1", + "description": "lime-icon 图标插件可方便快捷按需的使用iconify图标,iconify超过150,000个开源矢量图标,插件内置tdesign icon。使用兼容uniapp/uniappx", + "keywords": [ + "icon", + "iconify", + "图标集合", + "按需加载" +], + "repository": "", + "engines": { + "HBuilderX": "^3.8.7", + "uni-app": "^4.54", + "uni-app-x": "^4.61" + }, + "dcloudext": { + "type": "component-vue", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [ + "lime-style", + "lime-shared", + "lime-svg" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "x", + "aliyun": "x", + "alipay": "x" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "-", + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√", + "alipay": "√", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/readme.md b/QXTfront/uni_modules/lime-icon/readme.md new file mode 100644 index 0000000..f1c5131 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/readme.md @@ -0,0 +1,245 @@ +# lime-icon 图标 +图标组件,方便快捷地使用[iconify](https://iconify.design/)图标集合,提供超过150,000个开源矢量图标。支持自定义颜色、大小、前缀等属性,还可以使用自定义图标和图标URL。 + +> 注意:插件依赖的`lime-svg`为收费插件,若不需要svg功能,删除svg插件即可。 + +## 文档链接 +📚 组件详细文档请访问以下站点: +- [图标文档 - 站点1](https://limex.qcoon.cn/components/icon.html) +- [图标文档 - 站点2](https://limeui.netlify.app/components/icon.html) +- [图标文档 - 站点3](https://limeui.familyzone.top/components/icon.html) + +## 安装方法 +1. 在uni-app插件市场中搜索并导入`lime-icon` +2. 导入后可能需要重新编译项目 +3. 在页面中使用`l-icon`组件(组件)或`lime-icon`(演示) + +::: tip 注意🔔 +本插件依赖的[【lime-svg】](https://ext.dcloud.net.cn/plugin?id=18519)是原生插件,如果购买(收费为6元)则需要自定义基座,才能使用, +若不需要删除即可 +::: + +## 代码演示 + +### 基础使用 +使用`name`属性指定要显示的图标。👉️[【全部图标】](#全部图标) + +```html + +``` + +### 使用Iconify +到 [icones](https://icones.js.org/) 网站找到需要的图标,通过 `name` 属性来指定需要使用的图标 + +```html + + +``` + +![](https://img-cdn-tx.dcloud.net.cn/stream/plugin_screens/263cfd20-39e6-11ee-b4f0-9bc760224a38_1.png?1735701321) +![](https://img-cdn-tx.dcloud.net.cn/stream/plugin_screens/263cfd20-39e6-11ee-b4f0-9bc760224a38_2.png?1735701324) + + +### 使用图标URL +```html + +``` + +### 图标颜色 +通过 `color` 属性来设置图标的颜色。 + +```html + + +``` + +### 图标大小 + +通过 `size` 属性来设置图标的尺寸大小,可以指定任意 CSS 单位。 + +```html + + + + +``` + + +### 自定义图标 +通过`prefix`设置iconfot图标类,通过`name`传入`Unicode`字符 +```html + +``` +```css +@font-face { + font-family: keyicon; + src: url('https://at.alicdn.com/t/c/font_4741157_ul7wcp52yys.ttf'); +} +.keyicon { + font-family: keyicon; +} +``` + +## 私有化iconify +默认会使用`iconify`的API,如果你想私有化可按以下步骤来 +### 第一步 安装 + +```cmd +yarn add @iconify/json @iconify/tools @iconify/utils +``` +### 第二步 配置 +- 需要在根目录新建一个`lime-icons.config.js`文件 + +``` +// 在根目录新建一个lime-icons.config.js文件 +// lime-icons.config.js +module.exports = { + // 输入的文件目录,自有的SVG,如果没有则不需要 + input: { + prefix: "my-icons", + dir: '/static/svg', + }, + // 输出的配置 + output: { + // 输出的文件目录 + dir: '/static/icons', + // 输出的文件的格式,如果是JSON则是一个图标合集 + // file: 'icons.json', + // 如果是SVG则是每个图标做为单独的文件 + file: '*.svg', + }, + // 指定使用的图标 + icons: [ + 'el:address-book', + 'uil:12-plus', + 'icon-park-outline:abdominal', + 'icon-park-outline:acoustic' + ] +} +``` +在终端执行脚本 +``` +node ./uni_modules/lime-icon/generate-icons.js +``` + +### ~~2、自动引入~~ +~~如果使用的是`vue3`,通过配置 `vite.config.js` 达到自动引入~~ +这个方法作废,因有些图标是动态的,在编译阶段不知道图标的名称无法捕获 +```js +import uni from '@dcloudio/vite-plugin-uni'; +import limeIcon from './uni_modules/lime-icon/vite-plugin'; +import path from 'path' +export default defineConfig({ + plugins: [uni(), limeIcon({ + // 输出的配置 + output: { + // 输出的文件目录 + dir: path.join(__dirname, '/static/icons'), + // 输出的文件的格式,如果是JSON则是生成一个图标合集, 例如: /static/icons/icons.json + // file: 'icons.json', + // 如果是SVG则是每个图标做为单独的文件 例如: /static/icons/xx/xxx.svg + file: '*.svg', + }, + // 可选 + icons: [] + })] +}) +``` + + + +### 第三步 挂载图标地址 + +> 注意:如果使用了`iconify` 的API, 小程序需要去公众平台设置下载白名单 `https://api.iconify.design` +```js +// main.js | main.ts | main.uts +// 配置svg指定路径,后期可上传到后端,不占用本地空间,如果使用的是`iconify`也可以不配置这一步 +import {limeIcons} from '@/uni_modules/lime-icon' + +// 第一个参数是icon host地址,没有则填null +// 第二个参数是icons json合集,没有则填null +// app.use(limeIcons, null, null) + +// 示例1 配置icons地址 +app.use(limeIcons, 'https://xxx.cn/static/icons', null) + +// 示例2 配置icons集合json +import icons from './static/icons/icons.json' +app.use(limeIcons, null, icons) +``` + +## 快速预览 +导入插件后,可以直接使用以下标签查看演示效果: + +```html + + +``` + +## 插件标签说明 +`l-icon`: 组件标签,用于实际开发中 +`lime-icon`: 演示标签,用于查看示例效果 + +## Vue2使用说明 +本插件使用了`composition-api`,如需在Vue2项目中使用,请按照[官方教程](https://uniapp.dcloud.net.cn/tutorial/vue-composition-api.html)配置。 + +关键配置代码(在main.js中添加): + +```js +// vue2 +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' + +// 配置svg指定路径,后期可上传到后端,不占用本地空间,如果使用的是`iconify`也可以不配置这一步 +import {limeIcons} from '@/uni_modules/lime-icon' + +Vue.use(VueCompositionAPI) + +// 示例1 配置icons地址 +Vue.use(limeIcons, ['https://xxx.cn/static/icons', null]) + +// 示例2 配置icons集合json +import icons from './static/icons/icons.json' +Vue.use(limeIcons, [null, icons]) + +``` + + + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +| --------------------------| ------------------------------------------------------------ | ---------------- | ------------ | +| name | 图标名称 | string | `` | +| color | 颜色 | string | `` | +| size | 尺寸 | string | `square` | +| prefix | 字体图标前缀 | string | `` | +| inherit | 是否继承颜色 | boolean | `true` | +| web | 原生`app(nvue,uvue)`是否使用web渲染 | boolean | `false` | + +### Events +| 参数 | 说明 | 参数 | +| --------------------------| ------------------------------------------------------------ | ---------------- | +| click | 点击 | | + + +## 主题定制 + + +组件提供了丰富的CSS变量用于自定义样式: + +| 名称 | 默认值 | 描述 | +| --- | --- | --- | +| --l-icon-size | 16px | 图标大小 | +| --l-icon-color | | 图标颜色(仅icon-font生效) | + + + +## 支持与赞赏 + +如果你觉得本插件解决了你的问题,可以考虑支持作者: +| 支付宝赞助 | 微信赞助 | +|------------|------------| +| ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png) | ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png) | \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/static/icons.json b/QXTfront/uni_modules/lime-icon/static/icons.json new file mode 100644 index 0000000..501ec04 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/static/icons.json @@ -0,0 +1,2116 @@ +{ + "accessibility-filled": "\uE001", + "accessibility": "\uE002", + "activity-filled": "\uE003", + "activity": "\uE004", + "add-and-subtract": "\uE005", + "add-circle-filled": "\uE006", + "add-circle": "\uE007", + "add-rectangle-filled": "\uE008", + "add-rectangle": "\uE009", + "add": "\uE00A", + "address-book-filled": "\uE00B", + "address-book": "\uE00C", + "adjustment-filled": "\uE00D", + "adjustment": "\uE00E", + "airplay-wave-filled": "\uE00F", + "airplay-wave": "\uE010", + "alarm-add-filled": "\uE011", + "alarm-add": "\uE012", + "alarm-filled": "\uE013", + "alarm-off-filled": "\uE014", + "alarm-off": "\uE015", + "alarm": "\uE016", + "align-top": "\uE017", + "align-vertical": "\uE018", + "alpha": "\uE019", + "analytics-filled": "\uE01A", + "analytics": "\uE01B", + "anchor": "\uE01C", + "angry-filled": "\uE01D", + "angry": "\uE01E", + "animation-1-filled": "\uE01F", + "animation-1": "\uE020", + "animation-filled": "\uE021", + "animation": "\uE022", + "anticlockwise-filled": "\uE023", + "anticlockwise": "\uE024", + "api": "\uE025", + "app-filled": "\uE026", + "app": "\uE027", + "apple-filled": "\uE028", + "apple": "\uE029", + "application-filled": "\uE02A", + "application": "\uE02B", + "architecture-hui-style-filled": "\uE02C", + "architecture-hui-style": "\uE02D", + "archway-1-filled": "\uE02E", + "archway-1": "\uE02F", + "archway-filled": "\uE030", + "archway": "\uE031", + "arrow-down-circle-filled": "\uE032", + "arrow-down-circle": "\uE033", + "arrow-down-rectangle-filled": "\uE034", + "arrow-down-rectangle": "\uE035", + "arrow-down": "\uE036", + "arrow-left-circle-filled": "\uE037", + "arrow-left-circle": "\uE038", + "arrow-left-down-circle-filled": "\uE039", + "arrow-left-down-circle": "\uE03A", + "arrow-left-down": "\uE03B", + "arrow-left-right-1": "\uE03C", + "arrow-left-right-2": "\uE03D", + "arrow-left-right-3": "\uE03E", + "arrow-left-right-circle-filled": "\uE03F", + "arrow-left-right-circle": "\uE040", + "arrow-left-up-circle-filled": "\uE041", + "arrow-left-up-circle": "\uE042", + "arrow-left-up": "\uE043", + "arrow-left": "\uE044", + "arrow-right-circle-filled": "\uE045", + "arrow-right-circle": "\uE046", + "arrow-right-down-circle-filled": "\uE047", + "arrow-right-down-circle": "\uE048", + "arrow-right-down": "\uE049", + "arrow-right-up-circle-filled": "\uE04A", + "arrow-right-up-circle": "\uE04B", + "arrow-right-up": "\uE04C", + "arrow-right": "\uE04D", + "arrow-triangle-down-filled": "\uE04E", + "arrow-triangle-down": "\uE04F", + "arrow-triangle-up-filled": "\uE050", + "arrow-triangle-up": "\uE051", + "arrow-up-circle-filled": "\uE052", + "arrow-up-circle": "\uE053", + "arrow-up-down-1": "\uE054", + "arrow-up-down-2": "\uE055", + "arrow-up-down-3": "\uE056", + "arrow-up-down-circle-filled": "\uE057", + "arrow-up-down-circle": "\uE058", + "arrow-up": "\uE059", + "artboard": "\uE05A", + "article-filled": "\uE05B", + "article": "\uE05C", + "assignment-checked-filled": "\uE05D", + "assignment-checked": "\uE05E", + "assignment-code-filled": "\uE05F", + "assignment-code": "\uE060", + "assignment-error-filled": "\uE061", + "assignment-error": "\uE062", + "assignment-filled": "\uE063", + "assignment-user-filled": "\uE064", + "assignment-user": "\uE065", + "assignment": "\uE066", + "attach": "\uE067", + "attic-1-filled": "\uE068", + "attic-1": "\uE069", + "attic-filled": "\uE06A", + "attic": "\uE06B", + "audio-filled": "\uE06C", + "audio": "\uE06D", + "awkward-filled": "\uE06E", + "awkward": "\uE06F", + "backtop-rectangle-filled": "\uE070", + "backtop-rectangle": "\uE071", + "backtop": "\uE072", + "backup-filled": "\uE073", + "backup": "\uE074", + "backward-filled": "\uE075", + "backward": "\uE076", + "bad-laugh-filled": "\uE077", + "bad-laugh": "\uE078", + "bamboo-shoot-filled": "\uE079", + "bamboo-shoot": "\uE07A", + "banana-filled": "\uE07B", + "banana": "\uE07C", + "barbecue-filled": "\uE07D", + "barbecue": "\uE07E", + "barcode-1": "\uE07F", + "barcode": "\uE080", + "base-station": "\uE081", + "battery-add-filled": "\uE082", + "battery-add": "\uE083", + "battery-charging-filled": "\uE084", + "battery-charging": "\uE085", + "battery-filled": "\uE086", + "battery-low-filled": "\uE087", + "battery-low": "\uE088", + "battery": "\uE089", + "bean-filled": "\uE08A", + "bean": "\uE08B", + "beer-filled": "\uE08C", + "beer": "\uE08D", + "beta": "\uE08E", + "bifurcate-filled": "\uE08F", + "bifurcate": "\uE090", + "bill-filled": "\uE091", + "bill": "\uE092", + "bluetooth": "\uE093", + "bone-filled": "\uE094", + "bone": "\uE095", + "book-filled": "\uE096", + "book-open-filled": "\uE097", + "book-open": "\uE098", + "book-unknown-filled": "\uE099", + "book-unknown": "\uE09A", + "book": "\uE09B", + "bookmark-add-filled": "\uE09C", + "bookmark-add": "\uE09D", + "bookmark-checked-filled": "\uE09E", + "bookmark-checked": "\uE09F", + "bookmark-double-filled": "\uE0A0", + "bookmark-double": "\uE0A1", + "bookmark-filled": "\uE0A2", + "bookmark-minus-filled": "\uE0A3", + "bookmark-minus": "\uE0A4", + "bookmark": "\uE0A5", + "braces": "\uE0A6", + "brackets": "\uE0A7", + "bread-filled": "\uE0A8", + "bread": "\uE0A9", + "bridge-1-filled": "\uE0AA", + "bridge-1": "\uE0AB", + "bridge-2-filled": "\uE0AC", + "bridge-2": "\uE0AD", + "bridge-3": "\uE0AE", + "bridge-4": "\uE0AF", + "bridge-5-filled": "\uE0B0", + "bridge-5": "\uE0B1", + "bridge-6-filled": "\uE0B2", + "bridge-6": "\uE0B3", + "bridge": "\uE0B4", + "brightness-1-filled": "\uE0B5", + "brightness-1": "\uE0B6", + "brightness-filled": "\uE0B7", + "brightness": "\uE0B8", + "broccoli-filled": "\uE0B9", + "broccoli": "\uE0BA", + "browse-filled": "\uE0BB", + "browse-gallery-filled": "\uE0BC", + "browse-gallery": "\uE0BD", + "browse-off-filled": "\uE0BE", + "browse-off": "\uE0BF", + "browse": "\uE0C0", + "brush-filled": "\uE0C1", + "brush": "\uE0C2", + "bug-filled": "\uE0C3", + "bug-report-filled": "\uE0C4", + "bug-report": "\uE0C5", + "bug": "\uE0C6", + "building-1-filled": "\uE0C7", + "building-1": "\uE0C8", + "building-2-filled": "\uE0C9", + "building-2": "\uE0CA", + "building-3-filled": "\uE0CB", + "building-3": "\uE0CC", + "building-4-filled": "\uE0CD", + "building-4": "\uE0CE", + "building-5-filled": "\uE0CF", + "building-5": "\uE0D0", + "building-filled": "\uE0D1", + "building": "\uE0D2", + "bulletpoint": "\uE0D3", + "button-filled": "\uE0D4", + "button": "\uE0D5", + "cabbage-filled": "\uE0D6", + "cabbage": "\uE0D7", + "cake-filled": "\uE0D8", + "cake": "\uE0D9", + "calculation-1-filled": "\uE0DA", + "calculation-1": "\uE0DB", + "calculation": "\uE0DC", + "calculator-1": "\uE0DD", + "calculator-filled": "\uE0DE", + "calculator": "\uE0DF", + "calendar-1-filled": "\uE0E0", + "calendar-1": "\uE0E1", + "calendar-2-filled": "\uE0E2", + "calendar-2": "\uE0E3", + "calendar-edit-filled": "\uE0E4", + "calendar-edit": "\uE0E5", + "calendar-event-filled": "\uE0E6", + "calendar-event": "\uE0E7", + "calendar-filled": "\uE0E8", + "calendar": "\uE0E9", + "call-1-filled": "\uE0EA", + "call-1": "\uE0EB", + "call-cancel-filled": "\uE0EC", + "call-cancel": "\uE0ED", + "call-filled": "\uE0EE", + "call-forwarded-filled": "\uE0EF", + "call-forwarded": "\uE0F0", + "call-incoming-filled": "\uE0F1", + "call-incoming": "\uE0F2", + "call-off-filled": "\uE0F3", + "call-off": "\uE0F4", + "call": "\uE0F5", + "calm-1-filled": "\uE0F6", + "calm-1": "\uE0F7", + "calm-filled": "\uE0F8", + "calm": "\uE0F9", + "camera-1-filled": "\uE0FA", + "camera-1": "\uE0FB", + "camera-2-filled": "\uE0FC", + "camera-2": "\uE0FD", + "camera-filled": "\uE0FE", + "camera-off-filled": "\uE0FF", + "camera-off": "\uE100", + "camera": "\uE101", + "candy-filled": "\uE102", + "candy": "\uE103", + "card-filled": "\uE104", + "card": "\uE105", + "cardmembership-filled": "\uE106", + "cardmembership": "\uE107", + "caret-down-small": "\uE108", + "caret-down": "\uE109", + "caret-left-small": "\uE10A", + "caret-left": "\uE10B", + "caret-right-small": "\uE10C", + "caret-right": "\uE10D", + "caret-up-small": "\uE10E", + "caret-up": "\uE10F", + "cart-add-filled": "\uE110", + "cart-add": "\uE111", + "cart-filled": "\uE112", + "cart": "\uE113", + "cast-filled": "\uE114", + "cast": "\uE115", + "castle-1-filled": "\uE116", + "castle-1": "\uE117", + "castle-2-filled": "\uE118", + "castle-2": "\uE119", + "castle-3-filled": "\uE11A", + "castle-3": "\uE11B", + "castle-4-filled": "\uE11C", + "castle-4": "\uE11D", + "castle-5-filled": "\uE11E", + "castle-5": "\uE11F", + "castle-6-filled": "\uE120", + "castle-6": "\uE121", + "castle-7-filled": "\uE122", + "castle-7": "\uE123", + "castle-filled": "\uE124", + "castle": "\uE125", + "cat-filled": "\uE126", + "cat": "\uE127", + "catalog-filled": "\uE128", + "catalog": "\uE129", + "cd-filled": "\uE12A", + "cd": "\uE12B", + "celsius": "\uE12C", + "center-focus-strong-filled": "\uE12D", + "center-focus-strong": "\uE12E", + "centimeter": "\uE12F", + "certificate-1-filled": "\uE130", + "certificate-1": "\uE131", + "certificate-filled": "\uE132", + "certificate": "\uE133", + "chart-3d-filled": "\uE134", + "chart-3d": "\uE135", + "chart-add-filled": "\uE136", + "chart-add": "\uE137", + "chart-analytics": "\uE138", + "chart-area-filled": "\uE139", + "chart-area-multi-filled": "\uE13A", + "chart-area-multi": "\uE13B", + "chart-area": "\uE13C", + "chart-bar-filled": "\uE13D", + "chart-bar": "\uE13E", + "chart-bubble-filled": "\uE13F", + "chart-bubble": "\uE140", + "chart-column-filled": "\uE141", + "chart-column": "\uE142", + "chart-combo-filled": "\uE143", + "chart-combo": "\uE144", + "chart-filled": "\uE145", + "chart-line-data-1": "\uE146", + "chart-line-data": "\uE147", + "chart-line-multi": "\uE148", + "chart-line": "\uE149", + "chart-maximum": "\uE14A", + "chart-median": "\uE14B", + "chart-minimum": "\uE14C", + "chart-pie-filled": "\uE14D", + "chart-pie": "\uE14E", + "chart-radar-filled": "\uE14F", + "chart-radar": "\uE150", + "chart-radial": "\uE151", + "chart-ring-1-filled": "\uE152", + "chart-ring-1": "\uE153", + "chart-ring-filled": "\uE154", + "chart-ring": "\uE155", + "chart-scatter": "\uE156", + "chart-stacked-filled": "\uE157", + "chart-stacked": "\uE158", + "chart": "\uE159", + "chat-add-filled": "\uE15A", + "chat-add": "\uE15B", + "chat-bubble-1-filled": "\uE15C", + "chat-bubble-1": "\uE15D", + "chat-bubble-add-filled": "\uE15E", + "chat-bubble-add": "\uE15F", + "chat-bubble-error-filled": "\uE160", + "chat-bubble-error": "\uE161", + "chat-bubble-filled": "\uE162", + "chat-bubble-help-filled": "\uE163", + "chat-bubble-help": "\uE164", + "chat-bubble-history-filled": "\uE165", + "chat-bubble-history": "\uE166", + "chat-bubble-locked-filled": "\uE167", + "chat-bubble-locked": "\uE168", + "chat-bubble-smile-filled": "\uE169", + "chat-bubble-smile": "\uE16A", + "chat-bubble": "\uE16B", + "chat-checked-filled": "\uE16C", + "chat-checked": "\uE16D", + "chat-clear-filled": "\uE16E", + "chat-clear": "\uE16F", + "chat-double-filled": "\uE170", + "chat-double": "\uE171", + "chat-error-filled": "\uE172", + "chat-error": "\uE173", + "chat-filled": "\uE174", + "chat-heart-filled": "\uE175", + "chat-heart": "\uE176", + "chat-message-filled": "\uE177", + "chat-message": "\uE178", + "chat-off-filled": "\uE179", + "chat-off": "\uE17A", + "chat-poll-filled": "\uE17B", + "chat-poll": "\uE17C", + "chat-setting-filled": "\uE17D", + "chat-setting": "\uE17E", + "chat": "\uE17F", + "check-circle-filled": "\uE180", + "check-circle": "\uE181", + "check-double": "\uE182", + "check-rectangle-filled": "\uE183", + "check-rectangle": "\uE184", + "check": "\uE185", + "cheese-filled": "\uE186", + "cheese": "\uE187", + "cherry-filled": "\uE188", + "cherry": "\uE189", + "chevron-down-circle-filled": "\uE18A", + "chevron-down-circle": "\uE18B", + "chevron-down-double-s": "\uE18C", + "chevron-down-double": "\uE18D", + "chevron-down-rectangle-filled": "\uE18E", + "chevron-down-rectangle": "\uE18F", + "chevron-down-s": "\uE190", + "chevron-down": "\uE191", + "chevron-left-circle-filled": "\uE192", + "chevron-left-circle": "\uE193", + "chevron-left-double-s": "\uE194", + "chevron-left-double": "\uE195", + "chevron-left-rectangle-filled": "\uE196", + "chevron-left-rectangle": "\uE197", + "chevron-left-s": "\uE198", + "chevron-left": "\uE199", + "chevron-right-circle-filled": "\uE19A", + "chevron-right-circle": "\uE19B", + "chevron-right-double-s": "\uE19C", + "chevron-right-double": "\uE19D", + "chevron-right-rectangle-filled": "\uE19E", + "chevron-right-rectangle": "\uE19F", + "chevron-right-s": "\uE1A0", + "chevron-right": "\uE1A1", + "chevron-up-circle-filled": "\uE1A2", + "chevron-up-circle": "\uE1A3", + "chevron-up-double-s": "\uE1A4", + "chevron-up-double": "\uE1A5", + "chevron-up-rectangle-filled": "\uE1A6", + "chevron-up-rectangle": "\uE1A7", + "chevron-up-s": "\uE1A8", + "chevron-up": "\uE1A9", + "chicken": "\uE1AA", + "chili-filled": "\uE1AB", + "chili": "\uE1AC", + "chimney-1-filled": "\uE1AD", + "chimney-1": "\uE1AE", + "chimney-2-filled": "\uE1AF", + "chimney-2": "\uE1B0", + "chimney-filled": "\uE1B1", + "chimney": "\uE1B2", + "chinese-cabbage-filled": "\uE1B3", + "chinese-cabbage": "\uE1B4", + "church-filled": "\uE1B5", + "church": "\uE1B6", + "circle-filled": "\uE1B7", + "circle": "\uE1B8", + "city-1-filled": "\uE1B9", + "city-1": "\uE1BA", + "city-10-filled": "\uE1BB", + "city-10": "\uE1BC", + "city-11-filled": "\uE1BD", + "city-11": "\uE1BE", + "city-12-filled": "\uE1BF", + "city-12": "\uE1C0", + "city-13-filled": "\uE1C1", + "city-13": "\uE1C2", + "city-14-filled": "\uE1C3", + "city-14": "\uE1C4", + "city-15-filled": "\uE1C5", + "city-15": "\uE1C6", + "city-2-filled": "\uE1C7", + "city-2": "\uE1C8", + "city-3-filled": "\uE1C9", + "city-3": "\uE1CA", + "city-4-filled": "\uE1CB", + "city-4": "\uE1CC", + "city-5-filled": "\uE1CD", + "city-5": "\uE1CE", + "city-6-filled": "\uE1CF", + "city-6": "\uE1D0", + "city-7-filled": "\uE1D1", + "city-7": "\uE1D2", + "city-8-filled": "\uE1D3", + "city-8": "\uE1D4", + "city-9-filled": "\uE1D5", + "city-9": "\uE1D6", + "city-ancient-1-filled": "\uE1D7", + "city-ancient-1": "\uE1D8", + "city-ancient-2-filled": "\uE1D9", + "city-ancient-2": "\uE1DA", + "city-ancient-filled": "\uE1DB", + "city-ancient": "\uE1DC", + "city-filled": "\uE1DD", + "city": "\uE1DE", + "clear-filled": "\uE1DF", + "clear-formatting-1-filled": "\uE1E0", + "clear-formatting-1": "\uE1E1", + "clear-formatting-filled": "\uE1E2", + "clear-formatting": "\uE1E3", + "clear": "\uE1E4", + "close-circle-filled": "\uE1E5", + "close-circle": "\uE1E6", + "close-octagon-filled": "\uE1E7", + "close-octagon": "\uE1E8", + "close-rectangle-filled": "\uE1E9", + "close-rectangle": "\uE1EA", + "close": "\uE1EB", + "cloud-download": "\uE1EC", + "cloud-filled": "\uE1ED", + "cloud-upload": "\uE1EE", + "cloud": "\uE1EF", + "cloudy-day-filled": "\uE1F0", + "cloudy-day": "\uE1F1", + "cloudy-night-filled": "\uE1F2", + "cloudy-night-rain-filled": "\uE1F3", + "cloudy-night-rain": "\uE1F4", + "cloudy-night": "\uE1F5", + "cloudy-rain-filled": "\uE1F6", + "cloudy-rain": "\uE1F7", + "cloudy-sunny-filled": "\uE1F8", + "cloudy-sunny": "\uE1F9", + "code-1": "\uE1FA", + "code-off": "\uE1FB", + "code": "\uE1FC", + "cola-filled": "\uE1FD", + "cola": "\uE1FE", + "collage-filled": "\uE1FF", + "collage": "\uE200", + "collection-filled": "\uE201", + "collection": "\uE202", + "color-invert-filled": "\uE203", + "color-invert": "\uE204", + "combination-filled": "\uE205", + "combination": "\uE206", + "command": "\uE207", + "compass-1-filled": "\uE208", + "compass-1": "\uE209", + "compass-filled": "\uE20A", + "compass": "\uE20B", + "component-breadcrumb-filled": "\uE20C", + "component-breadcrumb": "\uE20D", + "component-checkbox-filled": "\uE20E", + "component-checkbox": "\uE20F", + "component-divider-horizontal-filled": "\uE210", + "component-divider-horizontal": "\uE211", + "component-divider-vertical-filled": "\uE212", + "component-divider-vertical": "\uE213", + "component-dropdown-filled": "\uE214", + "component-dropdown": "\uE215", + "component-grid-filled": "\uE216", + "component-grid": "\uE217", + "component-input-filled": "\uE218", + "component-input": "\uE219", + "component-layout-filled": "\uE21A", + "component-layout": "\uE21B", + "component-radio": "\uE21C", + "component-space-filled": "\uE21D", + "component-space": "\uE21E", + "component-steps-filled": "\uE21F", + "component-steps": "\uE220", + "component-switch-filled": "\uE221", + "component-switch": "\uE222", + "constraint": "\uE223", + "contrast-1-filled": "\uE224", + "contrast-1": "\uE225", + "contrast-filled": "\uE226", + "contrast": "\uE227", + "control-platform-filled": "\uE228", + "control-platform": "\uE229", + "cooperate-filled": "\uE22A", + "cooperate": "\uE22B", + "coordinate-system-filled": "\uE22C", + "coordinate-system": "\uE22D", + "copy-filled": "\uE22E", + "copy": "\uE22F", + "copyright-filled": "\uE230", + "copyright": "\uE231", + "corn-filled": "\uE232", + "corn": "\uE233", + "coupon-filled": "\uE234", + "coupon": "\uE235", + "course-filled": "\uE236", + "course": "\uE237", + "cpu-filled": "\uE238", + "cpu": "\uE239", + "crack-filled": "\uE23A", + "crack": "\uE23B", + "creditcard-add-filled": "\uE23C", + "creditcard-add": "\uE23D", + "creditcard-filled": "\uE23E", + "creditcard-off-filled": "\uE23F", + "creditcard-off": "\uE240", + "creditcard": "\uE241", + "crooked-smile-filled": "\uE242", + "crooked-smile": "\uE243", + "cry-and-laugh-filled": "\uE244", + "cry-and-laugh": "\uE245", + "cry-loudly-filled": "\uE246", + "cry-loudly": "\uE247", + "css3-filled": "\uE248", + "css3": "\uE249", + "cucumber": "\uE24A", + "currency-exchange": "\uE24B", + "cursor-filled": "\uE24C", + "cursor": "\uE24D", + "curtain-filled": "\uE24E", + "curtain": "\uE24F", + "curve": "\uE250", + "cut-1": "\uE251", + "cut": "\uE252", + "dam-1-filled": "\uE253", + "dam-1": "\uE254", + "dam-2-filled": "\uE255", + "dam-2": "\uE256", + "dam-3-filled": "\uE257", + "dam-3": "\uE258", + "dam-4-filled": "\uE259", + "dam-4": "\uE25A", + "dam-5-filled": "\uE25B", + "dam-5": "\uE25C", + "dam-6-filled": "\uE25D", + "dam-6": "\uE25E", + "dam-7-filled": "\uE25F", + "dam-7": "\uE260", + "dam-filled": "\uE261", + "dam": "\uE262", + "dart-board-filled": "\uE263", + "dart-board": "\uE264", + "dashboard-1-filled": "\uE265", + "dashboard-1": "\uE266", + "dashboard-filled": "\uE267", + "dashboard": "\uE268", + "data-filled": "\uE269", + "data-base-filled": "\uE26A", + "data-base": "\uE26B", + "data-checked-filled": "\uE26C", + "data-checked": "\uE26D", + "data-display": "\uE26E", + "data-error-filled": "\uE26F", + "data-error": "\uE270", + "data-search-filled": "\uE271", + "data-search": "\uE272", + "data": "\uE273", + "delete-1-filled": "\uE274", + "delete-1": "\uE275", + "delete-filled": "\uE276", + "delete-time-filled": "\uE277", + "delete-time": "\uE278", + "delete": "\uE279", + "delta-filled": "\uE27A", + "delta": "\uE27B", + "depressed-filled": "\uE27C", + "depressed": "\uE27D", + "desktop-1-filled": "\uE27E", + "desktop-1": "\uE27F", + "desktop-filled": "\uE280", + "desktop": "\uE281", + "despise-filled": "\uE282", + "despise": "\uE283", + "device-filled": "\uE284", + "device": "\uE285", + "discount-filled": "\uE286", + "discount": "\uE287", + "dissatisfaction-filled": "\uE288", + "dissatisfaction": "\uE289", + "divide": "\uE28A", + "dividers-1": "\uE28B", + "dividers": "\uE28C", + "doge-filled": "\uE28D", + "doge": "\uE28E", + "double-storey-filled": "\uE28F", + "double-storey": "\uE290", + "download-1": "\uE291", + "download-2-filled": "\uE292", + "download-2": "\uE293", + "download": "\uE294", + "downscale": "\uE295", + "drag-drop": "\uE296", + "drag-move": "\uE297", + "drink-filled": "\uE298", + "drink": "\uE299", + "drumstick-filled": "\uE29A", + "drumstick": "\uE29B", + "dv-filled": "\uE29C", + "dv": "\uE29D", + "dvd-filled": "\uE29E", + "dvd": "\uE29F", + "earphone-filled": "\uE2A0", + "earphone": "\uE2A1", + "earth-filled": "\uE2A2", + "earth": "\uE2A3", + "edit-1-filled": "\uE2A4", + "edit-1": "\uE2A5", + "edit-2-filled": "\uE2A6", + "edit-2": "\uE2A7", + "edit-filled": "\uE2A8", + "edit-off-filled": "\uE2A9", + "edit-off": "\uE2AA", + "edit": "\uE2AB", + "education-filled": "\uE2AC", + "education": "\uE2AD", + "eggplant-filled": "\uE2AE", + "eggplant": "\uE2AF", + "ellipsis": "\uE2B0", + "emo-emotional-filled": "\uE2B1", + "emo-emotional": "\uE2B2", + "enter": "\uE2B3", + "equal": "\uE2B4", + "error-circle-filled": "\uE2B5", + "error-circle": "\uE2B6", + "error-triangle-filled": "\uE2B7", + "error-triangle": "\uE2B8", + "error": "\uE2B9", + "excited-1-filled": "\uE2BA", + "excited-1": "\uE2BB", + "excited-filled": "\uE2BC", + "excited": "\uE2BD", + "expand-down-filled": "\uE2BE", + "expand-down": "\uE2BF", + "expand-horizontal": "\uE2C0", + "expand-up-filled": "\uE2C1", + "expand-up": "\uE2C2", + "expand-vertical": "\uE2C3", + "explore-filled": "\uE2C4", + "explore-off-filled": "\uE2C5", + "explore-off": "\uE2C6", + "explore": "\uE2C7", + "exposure-filled": "\uE2C8", + "exposure": "\uE2C9", + "extension-filled": "\uE2CA", + "extension-off-filled": "\uE2CB", + "extension-off": "\uE2CC", + "extension": "\uE2CD", + "face-retouching-filled": "\uE2CE", + "face-retouching": "\uE2CF", + "fact-check-filled": "\uE2D0", + "fact-check": "\uE2D1", + "fahrenheit-scale": "\uE2D2", + "feel-at-ease-filled": "\uE2D3", + "feel-at-ease": "\uE2D4", + "ferocious-filled": "\uE2D5", + "ferocious": "\uE2D6", + "ferris-wheel-filled": "\uE2D7", + "ferris-wheel": "\uE2D8", + "file-1-filled": "\uE2D9", + "file-1": "\uE2DA", + "file-add-1-filled": "\uE2DB", + "file-add-1": "\uE2DC", + "file-add-filled": "\uE2DD", + "file-add": "\uE2DE", + "file-attachment-filled": "\uE2DF", + "file-attachment": "\uE2E0", + "file-blocked-filled": "\uE2E1", + "file-blocked": "\uE2E2", + "file-code-1-filled": "\uE2E3", + "file-code-1": "\uE2E4", + "file-code-filled": "\uE2E5", + "file-code": "\uE2E6", + "file-copy-filled": "\uE2E7", + "file-copy": "\uE2E8", + "file-download-filled": "\uE2E9", + "file-download": "\uE2EA", + "file-excel-filled": "\uE2EB", + "file-excel": "\uE2EC", + "file-export-filled": "\uE2ED", + "file-export": "\uE2EE", + "file-filled": "\uE2EF", + "file-icon-filled": "\uE2F0", + "file-icon": "\uE2F1", + "file-image-filled": "\uE2F2", + "file-image": "\uE2F3", + "file-import-filled": "\uE2F4", + "file-import": "\uE2F5", + "file-locked-filled": "\uE2F6", + "file-locked": "\uE2F7", + "file-minus-filled": "\uE2F8", + "file-minus": "\uE2F9", + "file-music-filled": "\uE2FA", + "file-music": "\uE2FB", + "file-onenote-filled": "\uE2FC", + "file-onenote": "\uE2FD", + "file-outlook-filled": "\uE2FE", + "file-outlook": "\uE2FF", + "file-paste-filled": "\uE300", + "file-paste": "\uE301", + "file-pdf-filled": "\uE302", + "file-pdf": "\uE303", + "file-powerpoint-filled": "\uE304", + "file-powerpoint": "\uE305", + "file-restore-filled": "\uE306", + "file-restore": "\uE307", + "file-safety-filled": "\uE308", + "file-safety": "\uE309", + "file-search-filled": "\uE30A", + "file-search": "\uE30B", + "file-setting-filled": "\uE30C", + "file-setting": "\uE30D", + "file-teams-filled": "\uE30E", + "file-teams": "\uE30F", + "file-transmit-double-filled": "\uE310", + "file-transmit-double": "\uE311", + "file-transmit-filled": "\uE312", + "file-transmit": "\uE313", + "file-unknown-filled": "\uE314", + "file-unknown": "\uE315", + "file-unlocked-filled": "\uE316", + "file-unlocked": "\uE317", + "file-word-filled": "\uE318", + "file-word": "\uE319", + "file-zip-filled": "\uE31A", + "file-zip": "\uE31B", + "file": "\uE31C", + "fill-color-1-filled": "\uE31D", + "fill-color-1": "\uE31E", + "fill-color-filled": "\uE31F", + "fill-color": "\uE320", + "film-1-filled": "\uE321", + "film-1": "\uE322", + "film-filled": "\uE323", + "film": "\uE324", + "filter-1-filled": "\uE325", + "filter-1": "\uE326", + "filter-2-filled": "\uE327", + "filter-2": "\uE328", + "filter-3-filled": "\uE329", + "filter-3": "\uE32A", + "filter-clear-filled": "\uE32B", + "filter-clear": "\uE32C", + "filter-filled": "\uE32D", + "filter-off-filled": "\uE32E", + "filter-off": "\uE32F", + "filter-sort-filled": "\uE330", + "filter-sort": "\uE331", + "filter": "\uE332", + "fingerprint-1": "\uE333", + "fingerprint-2": "\uE334", + "fingerprint-3": "\uE335", + "fingerprint": "\uE336", + "fish-filled": "\uE337", + "fish": "\uE338", + "flag-1-filled": "\uE339", + "flag-1": "\uE33A", + "flag-2-filled": "\uE33B", + "flag-2": "\uE33C", + "flag-3-filled": "\uE33D", + "flag-3": "\uE33E", + "flag-4-filled": "\uE33F", + "flag-4": "\uE340", + "flag-filled": "\uE341", + "flag": "\uE342", + "flashlight-filled": "\uE343", + "flashlight": "\uE344", + "flight-landing-filled": "\uE345", + "flight-landing": "\uE346", + "flight-takeoff-filled": "\uE347", + "flight-takeoff": "\uE348", + "flip-smiling-face-filled": "\uE349", + "flip-smiling-face": "\uE34A", + "flip-to-back-filled": "\uE34B", + "flip-to-back": "\uE34C", + "flip-to-front-filled": "\uE34D", + "flip-to-front": "\uE34E", + "focus-filled": "\uE34F", + "focus": "\uE350", + "fog-filled": "\uE351", + "fog-night-filled": "\uE352", + "fog-night": "\uE353", + "fog-sunny-filled": "\uE354", + "fog-sunny": "\uE355", + "fog": "\uE356", + "folder-1-filled": "\uE357", + "folder-1": "\uE358", + "folder-add-1-filled": "\uE359", + "folder-add-1": "\uE35A", + "folder-add-filled": "\uE35B", + "folder-add": "\uE35C", + "folder-blocked-filled": "\uE35D", + "folder-blocked": "\uE35E", + "folder-details-filled": "\uE35F", + "folder-details": "\uE360", + "folder-export-filled": "\uE361", + "folder-export": "\uE362", + "folder-filled": "\uE363", + "folder-import-filled": "\uE364", + "folder-import": "\uE365", + "folder-locked-filled": "\uE366", + "folder-locked": "\uE367", + "folder-minus-filled": "\uE368", + "folder-minus": "\uE369", + "folder-move-filled": "\uE36A", + "folder-move": "\uE36B", + "folder-off-filled": "\uE36C", + "folder-off": "\uE36D", + "folder-open-1-filled": "\uE36E", + "folder-open-1": "\uE36F", + "folder-open-filled": "\uE370", + "folder-open": "\uE371", + "folder-search-filled": "\uE372", + "folder-search": "\uE373", + "folder-setting-filled": "\uE374", + "folder-setting": "\uE375", + "folder-shared-filled": "\uE376", + "folder-shared": "\uE377", + "folder-unlocked-filled": "\uE378", + "folder-unlocked": "\uE379", + "folder-zip-filled": "\uE37A", + "folder-zip": "\uE37B", + "folder": "\uE37C", + "forest-filled": "\uE37D", + "forest": "\uE37E", + "fork-filled": "\uE37F", + "fork": "\uE380", + "form-filled": "\uE381", + "form": "\uE382", + "format-horizontal-align-bottom": "\uE383", + "format-horizontal-align-center": "\uE384", + "format-horizontal-align-top": "\uE385", + "format-vertical-align-center": "\uE386", + "format-vertical-align-left": "\uE387", + "format-vertical-align-right": "\uE388", + "forward-filled": "\uE389", + "forward": "\uE38A", + "frame-1-filled": "\uE38B", + "frame-1": "\uE38C", + "frame-filled": "\uE38D", + "frame": "\uE38E", + "fries-filled": "\uE38F", + "fries": "\uE390", + "fullscreen-1": "\uE391", + "fullscreen-2": "\uE392", + "fullscreen-exit-1": "\uE393", + "fullscreen-exit": "\uE394", + "fullscreen": "\uE395", + "function-curve": "\uE396", + "functions-1": "\uE397", + "functions": "\uE398", + "gamepad-1-filled": "\uE399", + "gamepad-1": "\uE39A", + "gamepad-filled": "\uE39B", + "gamepad": "\uE39C", + "gamma": "\uE39D", + "garlic-filled": "\uE39E", + "garlic": "\uE39F", + "gender-female": "\uE3A0", + "gender-male": "\uE3A1", + "gesture-applause-filled": "\uE3A2", + "gesture-applause": "\uE3A3", + "gesture-click-filled": "\uE3A4", + "gesture-click": "\uE3A5", + "gesture-down-filled": "\uE3A6", + "gesture-down": "\uE3A7", + "gesture-expansion-filled": "\uE3A8", + "gesture-expansion": "\uE3A9", + "gesture-left-filled": "\uE3AA", + "gesture-left-slip-filled": "\uE3AB", + "gesture-left-slip": "\uE3AC", + "gesture-left": "\uE3AD", + "gesture-open-filled": "\uE3AE", + "gesture-open": "\uE3AF", + "gesture-pray-filled": "\uE3B0", + "gesture-pray": "\uE3B1", + "gesture-press-filled": "\uE3B2", + "gesture-press": "\uE3B3", + "gesture-ranslation-filled": "\uE3B4", + "gesture-ranslation": "\uE3B5", + "gesture-right-filled": "\uE3B6", + "gesture-right-slip-filled": "\uE3B7", + "gesture-right-slip": "\uE3B8", + "gesture-right": "\uE3B9", + "gesture-slide-left-and-right-filled": "\uE3BA", + "gesture-slide-left-and-right": "\uE3BB", + "gesture-slide-up-filled": "\uE3BC", + "gesture-slide-up": "\uE3BD", + "gesture-typing-filled": "\uE3BE", + "gesture-typing": "\uE3BF", + "gesture-up-and-down-filled": "\uE3C0", + "gesture-up-and-down": "\uE3C1", + "gesture-up-filled": "\uE3C2", + "gesture-up": "\uE3C3", + "gesture-wipe-down-filled": "\uE3C4", + "gesture-wipe-down": "\uE3C5", + "gift-filled": "\uE3C6", + "gift": "\uE3C7", + "giggle-filled": "\uE3C8", + "giggle": "\uE3C9", + "git-branch-filled": "\uE3CA", + "git-branch": "\uE3CB", + "git-commit-filled": "\uE3CC", + "git-commit": "\uE3CD", + "git-merge-filled": "\uE3CE", + "git-merge": "\uE3CF", + "git-pull-request-filled": "\uE3D0", + "git-pull-request": "\uE3D1", + "git-repository-commits-filled": "\uE3D2", + "git-repository-commits": "\uE3D3", + "git-repository-filled": "\uE3D4", + "git-repository-private-filled": "\uE3D5", + "git-repository-private": "\uE3D6", + "git-repository": "\uE3D7", + "gps-filled": "\uE3D8", + "gps": "\uE3D9", + "grape-filled": "\uE3DA", + "grape": "\uE3DB", + "greater-than-or-equal": "\uE3DC", + "greater-than": "\uE3DD", + "green-onion": "\uE3DE", + "grid-add-filled": "\uE3DF", + "grid-add": "\uE3E0", + "grid-view-filled": "\uE3E1", + "grid-view": "\uE3E2", + "guitar-filled": "\uE3E3", + "guitar": "\uE3E4", + "hamburger-filled": "\uE3E5", + "hamburger": "\uE3E6", + "happy-filled": "\uE3E7", + "happy": "\uE3E8", + "hard-disk-storage-filled": "\uE3E9", + "hard-disk-storage": "\uE3EA", + "hard-drive-filled": "\uE3EB", + "hard-drive": "\uE3EC", + "hashtag": "\uE3ED", + "hd-filled": "\uE3EE", + "hd": "\uE3EF", + "heart-filled": "\uE3F0", + "heart": "\uE3F1", + "help-circle-filled": "\uE3F2", + "help-circle": "\uE3F3", + "help-rectangle-filled": "\uE3F4", + "help-rectangle": "\uE3F5", + "help": "\uE3F6", + "highlight-1-filled": "\uE3F7", + "highlight-1": "\uE3F8", + "highlight": "\uE3F9", + "history-setting": "\uE3FA", + "history": "\uE3FB", + "home-filled": "\uE3FC", + "home": "\uE3FD", + "horizontal-filled": "\uE3FE", + "horizontal": "\uE3FF", + "hospital-1-filled": "\uE400", + "hospital-1": "\uE401", + "hospital-filled": "\uE402", + "hospital": "\uE403", + "hotspot-wave-filled": "\uE404", + "hotspot-wave": "\uE405", + "hourglass-filled": "\uE406", + "hourglass": "\uE407", + "houses-1-filled": "\uE408", + "houses-1": "\uE409", + "houses-2-filled": "\uE40A", + "houses-2": "\uE40B", + "houses-filled": "\uE40C", + "houses": "\uE40D", + "html5-filled": "\uE40E", + "html5": "\uE40F", + "https-filled": "\uE410", + "https": "\uE411", + "ice-cream-filled": "\uE412", + "ice-cream": "\uE413", + "icon-filled": "\uE414", + "icon": "\uE415", + "image-1-filled": "\uE416", + "image-1": "\uE417", + "image-add-filled": "\uE418", + "image-add": "\uE419", + "image-edit-filled": "\uE41A", + "image-edit": "\uE41B", + "image-error-filled": "\uE41C", + "image-error": "\uE41D", + "image-filled": "\uE41E", + "image-off-filled": "\uE41F", + "image-off": "\uE420", + "image-search-filled": "\uE421", + "image-search": "\uE422", + "image": "\uE423", + "indent-left": "\uE424", + "indent-right": "\uE425", + "indicator-filled": "\uE426", + "indicator": "\uE427", + "info-circle-filled": "\uE428", + "info-circle": "\uE429", + "ink-filled": "\uE42A", + "ink": "\uE42B", + "install-desktop-filled": "\uE42C", + "install-desktop": "\uE42D", + "install-filled": "\uE42E", + "install-mobile-filled": "\uE42F", + "install-mobile": "\uE430", + "install": "\uE431", + "institution-checked-filled": "\uE432", + "institution-checked": "\uE433", + "institution-filled": "\uE434", + "institution": "\uE435", + "internet-filled": "\uE436", + "internet": "\uE437", + "ipod-filled": "\uE438", + "ipod": "\uE439", + "joyful-filled": "\uE43A", + "joyful": "\uE43B", + "jump-double": "\uE43C", + "jump-off": "\uE43D", + "jump": "\uE43E", + "key-filled": "\uE43F", + "key": "\uE440", + "keyboard-filled": "\uE441", + "keyboard": "\uE442", + "laptop-filled": "\uE443", + "laptop": "\uE444", + "layers-filled": "\uE445", + "layers": "\uE446", + "layout-filled": "\uE447", + "layout": "\uE448", + "leaderboard-filled": "\uE449", + "leaderboard": "\uE44A", + "lemon-filled": "\uE44B", + "lemon-slice-filled": "\uE44C", + "lemon-slice": "\uE44D", + "lemon": "\uE44E", + "less-than-or-equal": "\uE44F", + "less-than": "\uE450", + "letters-a": "\uE451", + "letters-b": "\uE452", + "letters-c": "\uE453", + "letters-d": "\uE454", + "letters-e": "\uE455", + "letters-f": "\uE456", + "letters-g": "\uE457", + "letters-h": "\uE458", + "letters-i": "\uE459", + "letters-j": "\uE45A", + "letters-k": "\uE45B", + "letters-l": "\uE45C", + "letters-m": "\uE45D", + "letters-n": "\uE45E", + "letters-o": "\uE45F", + "letters-p": "\uE460", + "letters-q": "\uE461", + "letters-r": "\uE462", + "letters-s": "\uE463", + "letters-t": "\uE464", + "letters-u": "\uE465", + "letters-v": "\uE466", + "letters-w": "\uE467", + "letters-x": "\uE468", + "letters-y": "\uE469", + "letters-z": "\uE46A", + "lightbulb-circle-filled": "\uE46B", + "lightbulb-circle": "\uE46C", + "lightbulb-filled": "\uE46D", + "lightbulb": "\uE46E", + "lighthouse-1-filled": "\uE46F", + "lighthouse-1": "\uE470", + "lighthouse-2-filled": "\uE471", + "lighthouse-2": "\uE472", + "lighthouse-filled": "\uE473", + "lighthouse": "\uE474", + "lighting-circle-filled": "\uE475", + "lighting-circle": "\uE476", + "line-height": "\uE477", + "link-1": "\uE478", + "link-unlink": "\uE479", + "link": "\uE47A", + "liquor-filled": "\uE47B", + "liquor": "\uE47C", + "list-numbered": "\uE47D", + "list": "\uE47E", + "load": "\uE47F", + "loading": "\uE480", + "location-1-filled": "\uE481", + "location-1": "\uE482", + "location-enlargement-filled": "\uE483", + "location-enlargement": "\uE484", + "location-error-filled": "\uE485", + "location-error": "\uE486", + "location-filled": "\uE487", + "location-parking-place-filled": "\uE488", + "location-parking-place": "\uE489", + "location-reduction-filled": "\uE48A", + "location-reduction": "\uE48B", + "location-setting-filled": "\uE48C", + "location-setting": "\uE48D", + "location": "\uE48E", + "lock-off-filled": "\uE48F", + "lock-off": "\uE490", + "lock-on-filled": "\uE491", + "lock-on": "\uE492", + "lock-time-filled": "\uE493", + "lock-time": "\uE494", + "login": "\uE495", + "logo-adobe-illustrate-filled": "\uE496", + "logo-adobe-illustrate": "\uE497", + "logo-adobe-lightroom-filled": "\uE498", + "logo-adobe-lightroom": "\uE499", + "logo-adobe-photoshop-filled": "\uE49A", + "logo-adobe-photoshop": "\uE49B", + "logo-android-filled": "\uE49C", + "logo-android": "\uE49D", + "logo-apple-filled": "\uE49E", + "logo-apple": "\uE49F", + "logo-behance": "\uE4A0", + "logo-chrome-filled": "\uE4A1", + "logo-chrome": "\uE4A2", + "logo-cinema4d-filled": "\uE4A3", + "logo-cinema4d": "\uE4A4", + "logo-codepen": "\uE4A5", + "logo-codesandbox": "\uE4A6", + "logo-dribbble-filled": "\uE4A7", + "logo-dribbble": "\uE4A8", + "logo-facebook-filled": "\uE4A9", + "logo-facebook": "\uE4AA", + "logo-figma-filled": "\uE4AB", + "logo-figma": "\uE4AC", + "logo-framer-filled": "\uE4AD", + "logo-framer": "\uE4AE", + "logo-github-filled": "\uE4AF", + "logo-github": "\uE4B0", + "logo-gitlab-filled": "\uE4B1", + "logo-gitlab": "\uE4B2", + "logo-ie-filled": "\uE4B3", + "logo-ie": "\uE4B4", + "logo-instagram-filled": "\uE4B5", + "logo-instagram": "\uE4B6", + "logo-qq-filled": "\uE4B7", + "logo-qq": "\uE4B8", + "logo-twitter-filled": "\uE4B9", + "logo-twitter": "\uE4BA", + "logo-wechat-stroke-filled": "\uE4BB", + "logo-wechat-stroke": "\uE4BC", + "logo-wechatpay-filled": "\uE4BD", + "logo-wechatpay": "\uE4BE", + "logo-wecom-filled": "\uE4BF", + "logo-wecom": "\uE4C0", + "logo-windows-filled": "\uE4C1", + "logo-windows": "\uE4C2", + "logo-youtube-filled": "\uE4C3", + "logo-youtube": "\uE4C4", + "logout": "\uE4C5", + "look-around-filled": "\uE4C6", + "look-around": "\uE4C7", + "loudspeaker-filled": "\uE4C8", + "loudspeaker": "\uE4C9", + "mail-filled": "\uE4CA", + "mail": "\uE4CB", + "map-3d-filled": "\uE4CC", + "map-3d": "\uE4CD", + "map-add-filled": "\uE4CE", + "map-add": "\uE4CF", + "map-aiming-filled": "\uE4D0", + "map-aiming": "\uE4D1", + "map-blocked-filled": "\uE4D2", + "map-blocked": "\uE4D3", + "map-bubble-filled": "\uE4D4", + "map-bubble": "\uE4D5", + "map-cancel-filled": "\uE4D6", + "map-cancel": "\uE4D7", + "map-chat-filled": "\uE4D8", + "map-chat": "\uE4D9", + "map-checked-filled": "\uE4DA", + "map-checked": "\uE4DB", + "map-collection-filled": "\uE4DC", + "map-collection": "\uE4DD", + "map-connection-filled": "\uE4DE", + "map-connection": "\uE4DF", + "map-distance-filled": "\uE4E0", + "map-distance": "\uE4E1", + "map-double-filled": "\uE4E2", + "map-double": "\uE4E3", + "map-edit-filled": "\uE4E4", + "map-edit": "\uE4E5", + "map-filled": "\uE4E6", + "map-grid-filled": "\uE4E7", + "map-grid": "\uE4E8", + "map-information-1-filled": "\uE4E9", + "map-information-1": "\uE4EA", + "map-information-2-filled": "\uE4EB", + "map-information-2": "\uE4EC", + "map-information-filled": "\uE4ED", + "map-information": "\uE4EE", + "map-location-filled": "\uE4EF", + "map-location": "\uE4F0", + "map-locked-filled": "\uE4F1", + "map-locked": "\uE4F2", + "map-marked-filled": "\uE4F3", + "map-marked": "\uE4F4", + "map-navigation-filled": "\uE4F5", + "map-navigation": "\uE4F6", + "map-outline-filled": "\uE4F7", + "map-outline": "\uE4F8", + "map-route-planning-filled": "\uE4F9", + "map-route-planning": "\uE4FA", + "map-ruler-filled": "\uE4FB", + "map-ruler": "\uE4FC", + "map-safety-filled": "\uE4FD", + "map-safety": "\uE4FE", + "map-search-1-filled": "\uE4FF", + "map-search-1": "\uE500", + "map-search-filled": "\uE501", + "map-search": "\uE502", + "map-setting-filled": "\uE503", + "map-setting": "\uE504", + "map-unlocked-filled": "\uE505", + "map-unlocked": "\uE506", + "map": "\uE507", + "mark-as-unread-filled": "\uE508", + "mark-as-unread": "\uE509", + "markup-filled": "\uE50A", + "markup": "\uE50B", + "mathematics-filled": "\uE50C", + "mathematics": "\uE50D", + "measurement-1-filled": "\uE50E", + "measurement-1": "\uE50F", + "measurement-2-filled": "\uE510", + "measurement-2": "\uE511", + "measurement-filled": "\uE512", + "measurement": "\uE513", + "meat-pepper-filled": "\uE514", + "meat-pepper": "\uE515", + "media-library-filled": "\uE516", + "media-library": "\uE517", + "member-filled": "\uE518", + "member": "\uE519", + "menu-application": "\uE51A", + "menu-filled": "\uE51B", + "menu-fold": "\uE51C", + "menu-unfold": "\uE51D", + "menu": "\uE51E", + "merge-cells-filled": "\uE51F", + "merge-cells": "\uE520", + "microphone-1-filled": "\uE521", + "microphone-1": "\uE522", + "microphone-2-filled": "\uE523", + "microphone-2": "\uE524", + "microphone-filled": "\uE525", + "microphone": "\uE526", + "milk-filled": "\uE527", + "milk": "\uE528", + "minus-circle-filled": "\uE529", + "minus-circle": "\uE52A", + "minus-rectangle-filled": "\uE52B", + "minus-rectangle": "\uE52C", + "minus": "\uE52D", + "mirror-filled": "\uE52E", + "mirror": "\uE52F", + "mobile-blocked-filled": "\uE530", + "mobile-blocked": "\uE531", + "mobile-filled": "\uE532", + "mobile-list-filled": "\uE533", + "mobile-list": "\uE534", + "mobile-navigation-filled": "\uE535", + "mobile-navigation": "\uE536", + "mobile-shortcut-filled": "\uE537", + "mobile-shortcut": "\uE538", + "mobile-vibrate-filled": "\uE539", + "mobile-vibrate": "\uE53A", + "mobile": "\uE53B", + "mode-dark-filled": "\uE53C", + "mode-dark": "\uE53D", + "mode-light-filled": "\uE53E", + "mode-light": "\uE53F", + "module-filled": "\uE540", + "module": "\uE541", + "money-filled": "\uE542", + "money": "\uE543", + "monument-filled": "\uE544", + "monument": "\uE545", + "moon-fall-filled": "\uE546", + "moon-fall": "\uE547", + "moon-filled": "\uE548", + "moon-rising-filled": "\uE549", + "moon-rising": "\uE54A", + "moon": "\uE54B", + "more": "\uE54C", + "mosque-1-filled": "\uE54D", + "mosque-1": "\uE54E", + "mosque-filled": "\uE54F", + "mosque": "\uE550", + "mouse-filled": "\uE551", + "mouse": "\uE552", + "move-1": "\uE553", + "move": "\uE554", + "movie-clapper-filled": "\uE555", + "movie-clapper": "\uE556", + "multiply": "\uE557", + "museum-1-filled": "\uE558", + "museum-1": "\uE559", + "museum-2-filled": "\uE55A", + "museum-2": "\uE55B", + "museum-filled": "\uE55C", + "museum": "\uE55D", + "mushroom-1-filled": "\uE55E", + "mushroom-1": "\uE55F", + "mushroom-filled": "\uE560", + "mushroom": "\uE561", + "music-1-filled": "\uE562", + "music-1": "\uE563", + "music-2-filled": "\uE564", + "music-2": "\uE565", + "music-filled": "\uE566", + "music-rectangle-add-filled": "\uE567", + "music-rectangle-add": "\uE568", + "music": "\uE569", + "navigation-arrow-filled": "\uE56A", + "navigation-arrow": "\uE56B", + "next-filled": "\uE56C", + "next": "\uE56D", + "no-expression-filled": "\uE56E", + "no-expression": "\uE56F", + "noodle-filled": "\uE570", + "noodle": "\uE571", + "notification-add-filled": "\uE572", + "notification-add": "\uE573", + "notification-circle-filled": "\uE574", + "notification-circle": "\uE575", + "notification-error-filled": "\uE576", + "notification-error": "\uE577", + "notification-filled": "\uE578", + "notification": "\uE579", + "numbers-0-1": "\uE57A", + "numbers-0": "\uE57B", + "numbers-1-1": "\uE57C", + "numbers-1": "\uE57D", + "numbers-2-1": "\uE57E", + "numbers-2": "\uE57F", + "numbers-3-1": "\uE580", + "numbers-3": "\uE581", + "numbers-4-1": "\uE582", + "numbers-4": "\uE583", + "numbers-5-1": "\uE584", + "numbers-5": "\uE585", + "numbers-6-1": "\uE586", + "numbers-6": "\uE587", + "numbers-7-1": "\uE588", + "numbers-7": "\uE589", + "numbers-8-1": "\uE58A", + "numbers-8": "\uE58B", + "numbers-9-1": "\uE58C", + "numbers-9": "\uE58D", + "nut-filled": "\uE58E", + "nut": "\uE58F", + "object-storage": "\uE590", + "open-mouth-filled": "\uE591", + "open-mouth": "\uE592", + "opera-filled": "\uE593", + "opera": "\uE594", + "order-adjustment-column": "\uE595", + "order-ascending": "\uE596", + "order-descending": "\uE597", + "outbox-filled": "\uE598", + "outbox": "\uE599", + "page-first": "\uE59A", + "page-head-filled": "\uE59B", + "page-head": "\uE59C", + "page-last": "\uE59D", + "palace-1-filled": "\uE59E", + "palace-1": "\uE59F", + "palace-2-filled": "\uE5A0", + "palace-2": "\uE5A1", + "palace-3-filled": "\uE5A2", + "palace-3": "\uE5A3", + "palace-4-filled": "\uE5A4", + "palace-4": "\uE5A5", + "palace-filled": "\uE5A6", + "palace": "\uE5A7", + "palette-1-filled": "\uE5A8", + "palette-1": "\uE5A9", + "palette-filled": "\uE5AA", + "palette": "\uE5AB", + "panorama-horizontal-filled": "\uE5AC", + "panorama-horizontal": "\uE5AD", + "panorama-vertical-filled": "\uE5AE", + "panorama-vertical": "\uE5AF", + "pantone-filled": "\uE5B0", + "pantone": "\uE5B1", + "parabola": "\uE5B2", + "parentheses": "\uE5B3", + "paste-filled": "\uE5B4", + "paste": "\uE5B5", + "patio-filled": "\uE5B6", + "patio": "\uE5B7", + "pause-circle-filled": "\uE5B8", + "pause-circle-stroke-filled": "\uE5B9", + "pause-circle-stroke": "\uE5BA", + "pause-circle": "\uE5BB", + "pause": "\uE5BC", + "pea-filled": "\uE5BD", + "pea": "\uE5BE", + "peach-filled": "\uE5BF", + "peach": "\uE5C0", + "pear-filled": "\uE5C1", + "pear": "\uE5C2", + "pearl-of-the-orient-filled": "\uE5C3", + "pearl-of-the-orient": "\uE5C4", + "pen-ball-filled": "\uE5C5", + "pen-ball": "\uE5C6", + "pen-brush-filled": "\uE5C7", + "pen-brush": "\uE5C8", + "pen-filled": "\uE5C9", + "pen-mark-filled": "\uE5CA", + "pen-mark": "\uE5CB", + "pen-quill-filled": "\uE5CC", + "pen-quill": "\uE5CD", + "pen": "\uE5CE", + "pending-filled": "\uE5CF", + "pending": "\uE5D0", + "percent": "\uE5D1", + "personal-information-filled": "\uE5D2", + "personal-information": "\uE5D3", + "phone-locked-filled": "\uE5D4", + "phone-locked": "\uE5D5", + "phone-search-filled": "\uE5D6", + "phone-search": "\uE5D7", + "pi": "\uE5D8", + "piano-filled": "\uE5D9", + "piano": "\uE5DA", + "pin-filled": "\uE5DB", + "pin": "\uE5DC", + "play-circle-filled": "\uE5DD", + "play-circle-stroke-add-filled": "\uE5DE", + "play-circle-stroke-add": "\uE5DF", + "play-circle-stroke-filled": "\uE5E0", + "play-circle-stroke": "\uE5E1", + "play-circle": "\uE5E2", + "play-demo-filled": "\uE5E3", + "play-demo": "\uE5E4", + "play-rectangle-filled": "\uE5E5", + "play-rectangle": "\uE5E6", + "play": "\uE5E7", + "plus": "\uE5E8", + "popsicle-filled": "\uE5E9", + "popsicle": "\uE5EA", + "portrait-filled": "\uE5EB", + "portrait": "\uE5EC", + "pout-filled": "\uE5ED", + "pout": "\uE5EE", + "poweroff": "\uE5EF", + "precise-monitor": "\uE5F0", + "previous-filled": "\uE5F1", + "previous": "\uE5F2", + "print-filled": "\uE5F3", + "print": "\uE5F4", + "pumpkin-filled": "\uE5F5", + "pumpkin": "\uE5F6", + "pyramid-filled": "\uE5F7", + "pyramid-maya-filled": "\uE5F8", + "pyramid-maya": "\uE5F9", + "pyramid": "\uE5FA", + "qrcode": "\uE5FB", + "quadratic": "\uE5FC", + "questionnaire-double-filled": "\uE5FD", + "questionnaire-double": "\uE5FE", + "questionnaire-filled": "\uE5FF", + "questionnaire": "\uE600", + "queue-filled": "\uE601", + "queue": "\uE602", + "radar": "\uE603", + "radio-1-filled": "\uE604", + "radio-1": "\uE605", + "radio-2-filled": "\uE606", + "radio-2": "\uE607", + "radish-filled": "\uE608", + "radish": "\uE609", + "rain-heavy": "\uE60A", + "rain-light-filled": "\uE60B", + "rain-light": "\uE60C", + "rain-medium": "\uE60D", + "rainbow": "\uE60E", + "rectangle-filled": "\uE60F", + "rectangle": "\uE610", + "refresh": "\uE611", + "relation": "\uE612", + "relativity-filled": "\uE613", + "relativity": "\uE614", + "remote-wave-filled": "\uE615", + "remote-wave": "\uE616", + "remove": "\uE617", + "replay-filled": "\uE618", + "replay": "\uE619", + "rice-ball-filled": "\uE61A", + "rice-ball": "\uE61B", + "rice-filled": "\uE61C", + "rice": "\uE61D", + "roast-filled": "\uE61E", + "roast": "\uE61F", + "rocket-filled": "\uE620", + "rocket": "\uE621", + "rollback": "\uE622", + "rollfront": "\uE623", + "root-list-filled": "\uE624", + "root-list": "\uE625", + "rotate-locked-filled": "\uE626", + "rotate-locked": "\uE627", + "rotate": "\uE628", + "rotation": "\uE629", + "round-filled": "\uE62A", + "round": "\uE62B", + "router-wave-filled": "\uE62C", + "router-wave": "\uE62D", + "rss": "\uE62E", + "ruler-filled": "\uE62F", + "ruler": "\uE630", + "sailing-hotel-filled": "\uE631", + "sailing-hotel": "\uE632", + "sandwich-filled": "\uE633", + "sandwich": "\uE634", + "saturation-filled": "\uE635", + "saturation": "\uE636", + "sausage-filled": "\uE637", + "sausage": "\uE638", + "save-filled": "\uE639", + "save": "\uE63A", + "saving-pot-filled": "\uE63B", + "saving-pot": "\uE63C", + "scan": "\uE63D", + "screen-4k-filled": "\uE63E", + "screen-4k": "\uE63F", + "screencast-filled": "\uE640", + "screencast": "\uE641", + "screenshot": "\uE642", + "scroll-bar-filled": "\uE643", + "scroll-bar": "\uE644", + "sd-card-1-filled": "\uE645", + "sd-card-1": "\uE646", + "sd-card-filled": "\uE647", + "sd-card": "\uE648", + "search-error-filled": "\uE649", + "search-error": "\uE64A", + "search-filled": "\uE64B", + "search": "\uE64C", + "secured-filled": "\uE64D", + "secured": "\uE64E", + "send-cancel-filled": "\uE64F", + "send-cancel": "\uE650", + "send-filled": "\uE651", + "send": "\uE652", + "sensors-1": "\uE653", + "sensors-2": "\uE654", + "sensors-off": "\uE655", + "sensors": "\uE656", + "sequence-filled": "\uE657", + "sequence": "\uE658", + "serenity-filled": "\uE659", + "serenity": "\uE65A", + "server-filled": "\uE65B", + "server": "\uE65C", + "service-filled": "\uE65D", + "service": "\uE65E", + "setting-1-filled": "\uE65F", + "setting-1": "\uE660", + "setting-filled": "\uE661", + "setting": "\uE662", + "share-1-filled": "\uE663", + "share-1": "\uE664", + "share-filled": "\uE665", + "share": "\uE666", + "sharpness-filled": "\uE667", + "sharpness": "\uE668", + "shield-error-filled": "\uE669", + "shield-error": "\uE66A", + "shimen-filled": "\uE66B", + "shimen": "\uE66C", + "shop-1-filled": "\uE66D", + "shop-1": "\uE66E", + "shop-2-filled": "\uE66F", + "shop-2": "\uE670", + "shop-3-filled": "\uE671", + "shop-3": "\uE672", + "shop-4-filled": "\uE673", + "shop-4": "\uE674", + "shop-5-filled": "\uE675", + "shop-5": "\uE676", + "shop-filled": "\uE677", + "shop": "\uE678", + "shrimp-filled": "\uE679", + "shrimp": "\uE67A", + "shrink-horizontal": "\uE67B", + "shrink-vertical": "\uE67C", + "shutter-filled": "\uE67D", + "shutter": "\uE67E", + "shutup-filled": "\uE67F", + "shutup": "\uE680", + "sim-card-1-filled": "\uE681", + "sim-card-1": "\uE682", + "sim-card-2-filled": "\uE683", + "sim-card-2": "\uE684", + "sim-card-filled": "\uE685", + "sim-card": "\uE686", + "sinister-smile-filled": "\uE687", + "sinister-smile": "\uE688", + "sip-filled": "\uE689", + "sip": "\uE68A", + "sitemap-filled": "\uE68B", + "sitemap": "\uE68C", + "slash": "\uE68D", + "sleep-filled": "\uE68E", + "sleep": "\uE68F", + "slice-filled": "\uE690", + "slice": "\uE691", + "slideshow-filled": "\uE692", + "slideshow": "\uE693", + "smile-filled": "\uE694", + "smile": "\uE695", + "sneer-filled": "\uE696", + "sneer": "\uE697", + "snowflake": "\uE698", + "sonic": "\uE699", + "sound-down-filled": "\uE69A", + "sound-down": "\uE69B", + "sound-filled": "\uE69C", + "sound-high-filled": "\uE69D", + "sound-high": "\uE69E", + "sound-low-filled": "\uE69F", + "sound-low": "\uE6A0", + "sound-mute-1-filled": "\uE6A1", + "sound-mute-1": "\uE6A2", + "sound-mute-filled": "\uE6A3", + "sound-mute": "\uE6A4", + "sound-up-filled": "\uE6A5", + "sound-up": "\uE6A6", + "sound": "\uE6A7", + "space": "\uE6A8", + "speechless-1-filled": "\uE6A9", + "speechless-1": "\uE6AA", + "speechless-filled": "\uE6AB", + "speechless": "\uE6AC", + "star-filled": "\uE6AD", + "star": "\uE6AE", + "statue-of-jesus-filled": "\uE6AF", + "statue-of-jesus": "\uE6B0", + "sticky-note-filled": "\uE6B1", + "sticky-note": "\uE6B2", + "stop-circle-filled": "\uE6B3", + "stop-circle-stroke-filled": "\uE6B4", + "stop-circle-stroke": "\uE6B5", + "stop-circle": "\uE6B6", + "stop": "\uE6B7", + "store-filled": "\uE6B8", + "store": "\uE6B9", + "street-road-1-filled": "\uE6BA", + "street-road-1": "\uE6BB", + "street-road-filled": "\uE6BC", + "street-road": "\uE6BD", + "subtitle-filled": "\uE6BE", + "subtitle": "\uE6BF", + "subway-line-filled": "\uE6C0", + "subway-line": "\uE6C1", + "sum": "\uE6C2", + "sun-fall-filled": "\uE6C3", + "sun-fall": "\uE6C4", + "sun-rising-filled": "\uE6C5", + "sun-rising": "\uE6C6", + "sunny-filled": "\uE6C7", + "sunny": "\uE6C8", + "support-filled": "\uE6C9", + "support": "\uE6CA", + "surprised-1-filled": "\uE6CB", + "surprised-1": "\uE6CC", + "surprised-filled": "\uE6CD", + "surprised": "\uE6CE", + "swap-left": "\uE6CF", + "swap-right": "\uE6D0", + "swap": "\uE6D1", + "swear-1-filled": "\uE6D2", + "swear-1": "\uE6D3", + "swear-2-filled": "\uE6D4", + "swear-2": "\uE6D5", + "system-2": "\uE6D6", + "system-3-filled": "\uE6D7", + "system-3": "\uE6D8", + "system-application-filled": "\uE6D9", + "system-application": "\uE6DA", + "system-blocked-filled": "\uE6DB", + "system-blocked": "\uE6DC", + "system-code-filled": "\uE6DD", + "system-code": "\uE6DE", + "system-components-filled": "\uE6DF", + "system-components": "\uE6E0", + "system-coordinate-filled": "\uE6E1", + "system-coordinate": "\uE6E2", + "system-device-filled": "\uE6E3", + "system-device": "\uE6E4", + "system-interface-filled": "\uE6E5", + "system-interface": "\uE6E6", + "system-location-filled": "\uE6E7", + "system-location": "\uE6E8", + "system-locked-filled": "\uE6E9", + "system-locked": "\uE6EA", + "system-log-filled": "\uE6EB", + "system-log": "\uE6EC", + "system-marked-filled": "\uE6ED", + "system-marked": "\uE6EE", + "system-messages-filled": "\uE6EF", + "system-messages": "\uE6F0", + "system-regulation-filled": "\uE6F1", + "system-regulation": "\uE6F2", + "system-search-filled": "\uE6F3", + "system-search": "\uE6F4", + "system-setting-filled": "\uE6F5", + "system-setting": "\uE6F6", + "system-storage-filled": "\uE6F7", + "system-storage": "\uE6F8", + "system-sum": "\uE6F9", + "system-unlocked-filled": "\uE6FA", + "system-unlocked": "\uE6FB", + "tab-filled": "\uE6FC", + "tab": "\uE6FD", + "table-1-filled": "\uE6FE", + "table-1": "\uE6FF", + "table-2-filled": "\uE700", + "table-2": "\uE701", + "table-add-filled": "\uE702", + "table-add": "\uE703", + "table-filled": "\uE704", + "table-split-filled": "\uE705", + "table-split": "\uE706", + "table": "\uE707", + "tag-filled": "\uE708", + "tag": "\uE709", + "tangerinr-filled": "\uE70A", + "tangerinr": "\uE70B", + "tape-filled": "\uE70C", + "tape": "\uE70D", + "task-1-filled": "\uE70E", + "task-1": "\uE70F", + "task-add-1": "\uE710", + "task-add-filled": "\uE711", + "task-add": "\uE712", + "task-checked-1": "\uE713", + "task-checked-filled": "\uE714", + "task-checked": "\uE715", + "task-double-filled": "\uE716", + "task-double": "\uE717", + "task-error-filled": "\uE718", + "task-error": "\uE719", + "task-filled": "\uE71A", + "task-location-filled": "\uE71B", + "task-location": "\uE71C", + "task-marked-filled": "\uE71D", + "task-marked": "\uE71E", + "task-setting-filled": "\uE71F", + "task-setting": "\uE720", + "task-time-filled": "\uE721", + "task-time": "\uE722", + "task-visible-filled": "\uE723", + "task-visible": "\uE724", + "task": "\uE725", + "tea-filled": "\uE726", + "tea": "\uE727", + "teahouse-filled": "\uE728", + "teahouse": "\uE729", + "template-filled": "\uE72A", + "template": "\uE72B", + "temple-filled": "\uE72C", + "temple": "\uE72D", + "terminal-rectangle-1-filled": "\uE72E", + "terminal-rectangle-1": "\uE72F", + "terminal-rectangle-filled": "\uE730", + "terminal-rectangle": "\uE731", + "terminal-window-filled": "\uE732", + "terminal-window": "\uE733", + "terminal": "\uE734", + "textbox-filled": "\uE735", + "textbox": "\uE736", + "textformat-bold": "\uE737", + "textformat-color": "\uE738", + "textformat-italic": "\uE739", + "textformat-strikethrough": "\uE73A", + "textformat-underline": "\uE73B", + "textformat-wrap": "\uE73C", + "theaters-filled": "\uE73D", + "theaters": "\uE73E", + "thumb-down-1-filled": "\uE73F", + "thumb-down-1": "\uE740", + "thumb-down-2-filled": "\uE741", + "thumb-down-2": "\uE742", + "thumb-down-filled": "\uE743", + "thumb-down": "\uE744", + "thumb-up-1-filled": "\uE745", + "thumb-up-1": "\uE746", + "thumb-up-2-filled": "\uE747", + "thumb-up-2": "\uE748", + "thumb-up-filled": "\uE749", + "thumb-up": "\uE74A", + "thunder": "\uE74B", + "thunderstorm-night-filled": "\uE74C", + "thunderstorm-night": "\uE74D", + "thunderstorm-sunny-filled": "\uE74E", + "thunderstorm-sunny": "\uE74F", + "thunderstorm": "\uE750", + "ticket-filled": "\uE751", + "ticket": "\uE752", + "time-filled": "\uE753", + "time": "\uE754", + "tips-double-filled": "\uE755", + "tips-double": "\uE756", + "tips-filled": "\uE757", + "tips": "\uE758", + "tomato-filled": "\uE759", + "tomato": "\uE75A", + "tools-circle-filled": "\uE75B", + "tools-circle": "\uE75C", + "tools-filled": "\uE75D", + "tools": "\uE75E", + "tornado": "\uE75F", + "tower-1-filled": "\uE760", + "tower-1": "\uE761", + "tower-2-filled": "\uE762", + "tower-2": "\uE763", + "tower-3-filled": "\uE764", + "tower-3": "\uE765", + "tower-clock-filled": "\uE766", + "tower-clock": "\uE767", + "tower-filled": "\uE768", + "tower": "\uE769", + "town-filled": "\uE76A", + "town": "\uE76B", + "traffic-events-filled": "\uE76C", + "traffic-events": "\uE76D", + "traffic-filled": "\uE76E", + "traffic": "\uE76F", + "transform-1-filled": "\uE770", + "transform-1": "\uE771", + "transform-2": "\uE772", + "transform-3": "\uE773", + "transform-filled": "\uE774", + "transform": "\uE775", + "translate-1": "\uE776", + "translate": "\uE777", + "tree-round-dot-filled": "\uE778", + "tree-round-dot-vertical-filled": "\uE779", + "tree-round-dot-vertical": "\uE77A", + "tree-round-dot": "\uE77B", + "tree-square-dot-filled": "\uE77C", + "tree-square-dot-vertical-filled": "\uE77D", + "tree-square-dot-vertical": "\uE77E", + "tree-square-dot": "\uE77F", + "trending-down": "\uE780", + "trending-up": "\uE781", + "tv-1-filled": "\uE782", + "tv-1": "\uE783", + "tv-2-filled": "\uE784", + "tv-2": "\uE785", + "tv-filled": "\uE786", + "tv": "\uE787", + "typography-filled": "\uE788", + "typography": "\uE789", + "uncomfortable-1-filled": "\uE78A", + "uncomfortable-1": "\uE78B", + "uncomfortable-2-filled": "\uE78C", + "uncomfortable-2": "\uE78D", + "uncomfortable-filled": "\uE78E", + "uncomfortable": "\uE78F", + "undertake-delivery-filled": "\uE790", + "undertake-delivery": "\uE791", + "undertake-environment-protection-filled": "\uE792", + "undertake-environment-protection": "\uE793", + "undertake-filled": "\uE794", + "undertake-hold-up-filled": "\uE795", + "undertake-hold-up": "\uE796", + "undertake-transaction-filled": "\uE797", + "undertake-transaction": "\uE798", + "undertake": "\uE799", + "unfold-less": "\uE79A", + "unfold-more": "\uE79B", + "unhappy-1-filled": "\uE79C", + "unhappy-1": "\uE79D", + "unhappy-filled": "\uE79E", + "unhappy": "\uE79F", + "uninstall-filled": "\uE7A0", + "uninstall": "\uE7A1", + "upload-1": "\uE7A2", + "upload": "\uE7A3", + "upscale": "\uE7A4", + "usb-filled": "\uE7A5", + "usb": "\uE7A6", + "user-1-filled": "\uE7A7", + "user-1": "\uE7A8", + "user-add-filled": "\uE7A9", + "user-add": "\uE7AA", + "user-arrow-down-filled": "\uE7AB", + "user-arrow-down": "\uE7AC", + "user-arrow-left-filled": "\uE7AD", + "user-arrow-left": "\uE7AE", + "user-arrow-right-filled": "\uE7AF", + "user-arrow-right": "\uE7B0", + "user-arrow-up-filled": "\uE7B1", + "user-arrow-up": "\uE7B2", + "user-avatar-filled": "\uE7B3", + "user-avatar": "\uE7B4", + "user-blocked-filled": "\uE7B5", + "user-blocked": "\uE7B6", + "user-business-filled": "\uE7B7", + "user-business": "\uE7B8", + "user-checked-1-filled": "\uE7B9", + "user-checked-1": "\uE7BA", + "user-checked-filled": "\uE7BB", + "user-checked": "\uE7BC", + "user-circle-filled": "\uE7BD", + "user-circle": "\uE7BE", + "user-clear-filled": "\uE7BF", + "user-clear": "\uE7C0", + "user-error-1-filled": "\uE7C1", + "user-error-1": "\uE7C2", + "user-filled": "\uE7C3", + "user-invisible-filled": "\uE7C4", + "user-invisible": "\uE7C5", + "user-list-filled": "\uE7C6", + "user-list": "\uE7C7", + "user-locked-filled": "\uE7C8", + "user-locked": "\uE7C9", + "user-marked-filled": "\uE7CA", + "user-marked": "\uE7CB", + "user-password-filled": "\uE7CC", + "user-password": "\uE7CD", + "user-safety-filled": "\uE7CE", + "user-safety": "\uE7CF", + "user-search-filled": "\uE7D0", + "user-search": "\uE7D1", + "user-setting-filled": "\uE7D2", + "user-setting": "\uE7D3", + "user-talk-1-filled": "\uE7D4", + "user-talk-1": "\uE7D5", + "user-talk-filled": "\uE7D6", + "user-talk-off-1-filled": "\uE7D7", + "user-talk-off-1": "\uE7D8", + "user-talk": "\uE7D9", + "user-time-filled": "\uE7DA", + "user-time": "\uE7DB", + "user-transmit-filled": "\uE7DC", + "user-transmit": "\uE7DD", + "user-unknown-filled": "\uE7DE", + "user-unknown": "\uE7DF", + "user-unlocked-filled": "\uE7E0", + "user-unlocked": "\uE7E1", + "user-vip-filled": "\uE7E2", + "user-vip": "\uE7E3", + "user-visible-filled": "\uE7E4", + "user-visible": "\uE7E5", + "user": "\uE7E6", + "usercase-filled": "\uE7E7", + "usercase-link-filled": "\uE7E8", + "usercase-link": "\uE7E9", + "usercase": "\uE7EA", + "usergroup-add-filled": "\uE7EB", + "usergroup-add": "\uE7EC", + "usergroup-clear-filled": "\uE7ED", + "usergroup-clear": "\uE7EE", + "usergroup-filled": "\uE7EF", + "usergroup": "\uE7F0", + "vehicle-filled": "\uE7F1", + "vehicle": "\uE7F2", + "verified-filled": "\uE7F3", + "verified": "\uE7F4", + "verify-filled": "\uE7F5", + "verify": "\uE7F6", + "vertical-filled": "\uE7F7", + "vertical": "\uE7F8", + "video-camera-1-filled": "\uE7F9", + "video-camera-1": "\uE7FA", + "video-camera-2-filled": "\uE7FB", + "video-camera-2": "\uE7FC", + "video-camera-3-filled": "\uE7FD", + "video-camera-3": "\uE7FE", + "video-camera-dollar-filled": "\uE7FF", + "video-camera-dollar": "\uE800", + "video-camera-filled": "\uE801", + "video-camera-minus-filled": "\uE802", + "video-camera-minus": "\uE803", + "video-camera-music-filled": "\uE804", + "video-camera-music": "\uE805", + "video-camera-off-filled": "\uE806", + "video-camera-off": "\uE807", + "video-camera": "\uE808", + "video-filled": "\uE809", + "video-library-filled": "\uE80A", + "video-library": "\uE80B", + "video": "\uE80C", + "view-agenda-filled": "\uE80D", + "view-agenda": "\uE80E", + "view-column": "\uE80F", + "view-in-ar-filled": "\uE810", + "view-in-ar": "\uE811", + "view-list": "\uE812", + "view-module-filled": "\uE813", + "view-module": "\uE814", + "visual-recognition-filled": "\uE815", + "visual-recognition": "\uE816", + "wallet-filled": "\uE817", + "wallet": "\uE818", + "watch-filled": "\uE819", + "watch": "\uE81A", + "watermelon-filled": "\uE81B", + "watermelon": "\uE81C", + "wave-bye-filled": "\uE81D", + "wave-bye": "\uE81E", + "wave-left-filled": "\uE81F", + "wave-left": "\uE820", + "wave-right-filled": "\uE821", + "wave-right": "\uE822", + "wealth-1-filled": "\uE823", + "wealth-1": "\uE824", + "wealth-filled": "\uE825", + "wealth": "\uE826", + "widget-filled": "\uE827", + "widget": "\uE828", + "wifi-1-filled": "\uE829", + "wifi-1": "\uE82A", + "wifi-off-1-filled": "\uE82B", + "wifi-off-1": "\uE82C", + "wifi-off": "\uE82D", + "wifi": "\uE82E", + "window-1-filled": "\uE82F", + "window-1": "\uE830", + "window-filled": "\uE831", + "window": "\uE832", + "windy-rain": "\uE833", + "windy": "\uE834", + "wink-filled": "\uE835", + "wink": "\uE836", + "work-filled": "\uE837", + "work-history-filled": "\uE838", + "work-history": "\uE839", + "work-off-filled": "\uE83A", + "work-off": "\uE83B", + "work": "\uE83C", + "wry-smile-filled": "\uE83D", + "wry-smile": "\uE83E", + "zoom-in-filled": "\uE83F", + "zoom-in": "\uE840", + "zoom-out-filled": "\uE841", + "zoom-out": "\uE842" +} diff --git a/QXTfront/uni_modules/lime-icon/utils/generate.js b/QXTfront/uni_modules/lime-icon/utils/generate.js new file mode 100644 index 0000000..9e8a3f7 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/utils/generate.js @@ -0,0 +1,120 @@ +const path = require('path'); +const fs = require("fs"); +const rootPath = process.cwd(); // 获取根目录 +const { importDirectory, blankIconSet } = require("@iconify/tools"); +const { locate } = require('@iconify/json'); +const { getIconData } = require('@iconify/utils'); +const { encodeSvg, saveFile, customOptions, deleteDirectory } = require('./index.js') +async function fetchIconsData(icons) { + const collections = {} + for (const iconName of icons) { + const [collectionName, iconNameWithoutPrefix] = iconName.split(':'); + const filename = locate(collectionName) + if(!fs.existsSync(filename)) { + continue + } + const icons = JSON.parse(fs.readFileSync(filename, 'utf8')) + if(!icons) { + continue + } + if(collectionName && iconNameWithoutPrefix) { + const iconData = getIconData(icons, iconNameWithoutPrefix); + if(iconData) { + if(!collections[collectionName]) { + collections[collectionName] = blankIconSet(collectionName); + } + collections[collectionName].setIcon(iconNameWithoutPrefix, iconData); + } else { + console.log(`Icon '${iconName}' not found in '${collectionName}' collection.`) + } + } else if(collectionName) { + if(!collections[collectionName]) { + collections[collectionName] = blankIconSet(collectionName) + } + Object.keys(icons.icons).forEach(iconName => { + const iconData = getIconData(icons, iconName) + if(iconData) { + collections[collectionName].setIcon(iconName, iconData) + } else { + console.log(`Icon '${iconName}' not found in '${collectionName}' collection.`) + } + }) + } + } + return collections; +} + +async function generate(config){ + try { + if(!config) { + // 从配置文件中读取选项 + const rootConfigPath = path.join(rootPath, 'lime-icons.config.js'); + let configPath = '' + if(fs.existsSync(rootConfigPath)) { + configPath = rootConfigPath + } else { + configPath = path.dirname(__filename) + '/lime-icons.config.js'; // 配置文件路径 + } + + const configFile = fs.readFileSync(configPath, 'utf8'); + config = eval(`(${configFile})`); + } + + // 根据配置文件中的字段设置选项 + const options = { + input: Object.assign({}, customOptions, config.input || {}), // 输入的文件目录 + output: { + dir: config.output.dir || '/static', // 输出的文件目录 + file: config.output.file || 'icons.json', // 输出的文件的格式,默认为 JSON + }, + icons: config.icons || [], // 图标名称列表 + }; + + // 先删除原来的 + deleteDirectory(options.output.dir) + // 处理输入目录的逻辑 + if (config.input.dir.startsWith('/')) { + options.input.dir = path.join(rootPath, config.input.dir); + } else if (config.input.dir.startsWith('./')) { + options.input.dir = path.join(__dirname, config.input.dir.slice(2)); + } + let iconCollections = {} + // 异步地从目录中导入图标 + if(fs.existsSync(options.input.dir)) { + const iconSet = await importDirectory(options.input.dir, options.input); + // 导出为 JSON 文件 + iconCollections[options.input.prefix] = iconSet + } + + // 获取指定图标的数据 + if(options.icons.length) { + const iconCollection = await fetchIconsData(options.icons); + Object.assign(iconCollections, iconCollection) + } + + if(/\.json$/i.test(options.output.file)) { + const collections = {} + Object.values(iconCollections).forEach((iconSet) => { + + iconSet.forEach(iconName => { + // 将 SVG 转换为 Data URL + collections[iconSet.prefix + ':' + iconName] = `data:image/svg+xml;utf8,${encodeSvg(iconSet.toString(iconName))}` + }) + }) + await saveFile(`${options.output.dir}/${options.output.file}`, JSON.stringify(collections)) + } else { + Object.values(iconCollections).forEach((iconSet) => { + iconSet.forEach(async iconName => { + await saveFile(`${options.output.dir}/${iconSet.prefix}/${iconName}.svg`, iconSet.toString(iconName)) + }) + }) + } + } catch (error) { + console.error("导出图标集为 JSON 文件时出错:", error); + } +} + + +module.exports = { + generate +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/utils/index.js b/QXTfront/uni_modules/lime-icon/utils/index.js new file mode 100644 index 0000000..64f5854 --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/utils/index.js @@ -0,0 +1,89 @@ +const fs = require("fs"); +const glob = require('glob'); +const path = require("path"); +const rootPath = process.cwd(); // 获取根目录 +// https://bl.ocks.org/jennyknuth/222825e315d45a738ed9d6e04c7a88d0 +function encodeSvg(svg) { + return svg + .replace( + "/g, "%3E"); +} + + +function isDirectoryEmpty(path) { + const files = fs.readdirSync(path); + return files.length === 0; + } +function deleteFolderBFS(folderPath) { + const outputPath = /^\.|\/|\\/.test(folderPath) ? path.join(rootPath, folderPath): folderPath + if(!fs.existsSync(outputPath)) { + return + } + const queue = [outputPath]; + while (queue.length > 0) { + const currentPath = queue.shift(); + const currentStats = fs.statSync(currentPath); + + if (currentStats.isDirectory()) { + const files = fs.readdirSync(currentPath); + for (const file of files) { + const filePath = path.join(currentPath, file); + const fileStats = fs.statSync(filePath); + if (fileStats.isDirectory()) { + queue.push(filePath); + } else { + fs.unlinkSync(filePath); // 删除文件 + } + } + if(isDirectoryEmpty(currentPath)) { + fs.rmdirSync(currentPath); + } + } + } +} + +// 保存 +async function saveFile(file, data) { + const outputPath = /^(\.|\/|\\)/.test(file) ? path.join(rootPath, file) : file; + const outputDir = path.dirname(outputPath); + try { + // 创建文件夹 + await fs.promises.mkdir(outputDir, { + recursive: true + }); + + // 使用 Promise 进行写入文件操作 + await fs.promises.writeFile(outputPath, data, "utf8"); + // console.log(`成功保存文件:${outputPath}`); + } catch (error) { + console.error("保存文件时出错:", error); + } +} + +// 可选的选项对象 +const customOptions = { + prefix: "l", // 为图标集设置前缀 + includeSubDirs: true, // 启用扫描子目录中的文件(默认启用) + keyword: (fileName, defaultKeyword, iconSet) => { + // 根据文件名自定义关键字生成 + // 返回关键字或 undefined 以跳过该文件 + return defaultKeyword; + }, + ignoreImportErrors: true, // 禁用未成功导入图标时的错误抛出(默认启用) + keepTitles: false, // 禁用在 SVG 中保留标题(默认禁用) +}; +module.exports = { + encodeSvg, + saveFile, + deleteDirectory: deleteFolderBFS, + customOptions, +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-icon/vite-plugin.js b/QXTfront/uni_modules/lime-icon/vite-plugin.js new file mode 100644 index 0000000..a79337f --- /dev/null +++ b/QXTfront/uni_modules/lime-icon/vite-plugin.js @@ -0,0 +1,87 @@ +const { readFileSync, existsSync } = require('fs'); +const path = require('path'); +const {generate} = require('./utils/generate') + +// 插件的名称 +const pluginName = 'vite-plugin-limeIcon'; + +// 要监听的组件的名称 +const targetComponent = 'l-icon'; + +function parseAttributes(attributesStr) { + if (!attributesStr.includes("'")) { + return [attributesStr] + } + const regex = /'([^']+)'/g; + const matches = attributesStr.match(regex); + if (matches) { + const targetContent = matches.map(item => item.replace(/'/g, '')); + return targetContent + } else { + return [attributesStr] + } +} + +function extractAttributes(content) { + const regex = /]*(:?)name=["]([^"]+)["][^>]*>/g; // //g //]+)\s*\/?>/g; + let attributes = []; + const attributesSet = new Set(attributes); + let match; + while ((match = regex.exec(content)) !== null) { + const attributesStr = match[2]; + const attributesList = parseAttributes(attributesStr); + for (const attribute of attributesList) { + attributesSet.add(attribute); // 添加新属性到Set中 + } + } + attributes = [...attributesSet]; + return attributes; +} +// 遍历每个文件并检查是否使用了目标组件 +let iconCollections = {} +let files = {} +let timer = null +function processFile(file, options) { + const filePath = path.resolve(file); + const content = readFileSync(filePath, 'utf-8'); + + // 检查文件是否包含目标组件 + if (content.includes(targetComponent) && (!file.includes('l-icon.vue') || !file.includes('l-icon.uvue')) && files[file] !== content) { + const icons = extractAttributes(content) + if(icons && icons.length) { + files[file] = content + iconCollections[file] = icons + } + Object.values(iconCollections).forEach(icons => { + if(options.icons) { + options.icons = options.icons.concat(icons); + } else { + options.icons = icons + } + }) + + clearTimeout(timer) + timer = setTimeout(() => { + options.icons = Array.from(new Set(options.icons)) + generate(options) + },500) + + } +} + +// 插件的钩子函数 +function vitePlugin(options = {}) { + const {useInDevelopment = false} = options + const isDev = process.env.NODE_ENV === 'development' + return { + name: pluginName, + transform(code, id) { + if (id.endsWith('.vue') && (useInDevelopment && isDev || !useInDevelopment && !isDev)) { + // 处理Vue文件 + processFile(id, options); + } + }, + }; +} + +module.exports = vitePlugin; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/addUnit/index.ts b/QXTfront/uni_modules/lime-shared/addUnit/index.ts new file mode 100644 index 0000000..4e41311 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/addUnit/index.ts @@ -0,0 +1,42 @@ +// @ts-nocheck +import {isNumeric} from '../isNumeric' +import {isDef} from '../isDef' +/** + * 给一个值添加单位(像素 px) + * @param value 要添加单位的值,可以是字符串或数字 + * @returns 添加了单位的值,如果值为 null 则返回 null + */ + +// #ifndef UNI-APP-X && APP +export function addUnit(value?: string | number): string | null { + if (!isDef(value)) { + return null; + } + value = String(value); // 将值转换为字符串 + // 如果值是数字,则在后面添加单位 "px",否则保持原始值 + return isNumeric(value) ? `${value}px` : value; +} +// #endif + + +// #ifdef UNI-APP-X && APP +function addUnit(value: string): string|null +function addUnit(value: number): string|null +function addUnit(value: string|number|null): string|null { + if (!isDef(value)) { + return null; + } + value = `${value}` //value.toString(); // 将值转换为字符串 + + // 如果值是数字,则在后面添加单位 "px",否则保持原始值 + return isNumeric(value) ? `${value}px` : value; +} +export {addUnit} +// #endif + + +// console.log(addUnit(100)); // 输出: "100px" +// console.log(addUnit("200")); // 输出: "200px" +// console.log(addUnit("300px")); // 输出: "300px"(已经包含单位) +// console.log(addUnit()); // 输出: undefined(值为 undefined) +// console.log(addUnit(null)); // 输出: undefined(值为 null) \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/animation/bezier.ts b/QXTfront/uni_modules/lime-shared/animation/bezier.ts new file mode 100644 index 0000000..b4239e1 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/animation/bezier.ts @@ -0,0 +1,82 @@ +export function cubicBezier(p1x : number, p1y : number, p2x : number, p2y : number):(x: number)=> number { + const ZERO_LIMIT = 1e-6; + // Calculate the polynomial coefficients, + // implicit first and last control points are (0,0) and (1,1). + const ax = 3 * p1x - 3 * p2x + 1; + const bx = 3 * p2x - 6 * p1x; + const cx = 3 * p1x; + + const ay = 3 * p1y - 3 * p2y + 1; + const by = 3 * p2y - 6 * p1y; + const cy = 3 * p1y; + + function sampleCurveDerivativeX(t : number) : number { + // `ax t^3 + bx t^2 + cx t` expanded using Horner's rule + return (3 * ax * t + 2 * bx) * t + cx; + } + + function sampleCurveX(t : number) : number { + return ((ax * t + bx) * t + cx) * t; + } + + function sampleCurveY(t : number) : number { + return ((ay * t + by) * t + cy) * t; + } + + // Given an x value, find a parametric value it came from. + function solveCurveX(x : number) : number { + let t2 = x; + let derivative : number; + let x2 : number; + + // https://trac.webkit.org/browser/trunk/Source/WebCore/platform/animation + // first try a few iterations of Newton's method -- normally very fast. + // http://en.wikipedia.org/wikiNewton's_method + for (let i = 0; i < 8; i++) { + // f(t) - x = 0 + x2 = sampleCurveX(t2) - x; + if (Math.abs(x2) < ZERO_LIMIT) { + return t2; + } + derivative = sampleCurveDerivativeX(t2); + // == 0, failure + /* istanbul ignore if */ + if (Math.abs(derivative) < ZERO_LIMIT) { + break; + } + t2 -= x2 / derivative; + } + + // Fall back to the bisection method for reliability. + // bisection + // http://en.wikipedia.org/wiki/Bisection_method + let t1 = 1; + /* istanbul ignore next */ + let t0 = 0; + + /* istanbul ignore next */ + t2 = x; + /* istanbul ignore next */ + while (t1 > t0) { + x2 = sampleCurveX(t2) - x; + if (Math.abs(x2) < ZERO_LIMIT) { + return t2; + } + if (x2 > 0) { + t1 = t2; + } else { + t0 = t2; + } + t2 = (t1 + t0) / 2; + } + + // Failure + return t2; + } + + return function (x : number) : number { + return sampleCurveY(solveCurveX(x)); + } + + // return solve; +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/animation/ease.ts b/QXTfront/uni_modules/lime-shared/animation/ease.ts new file mode 100644 index 0000000..0af156e --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/animation/ease.ts @@ -0,0 +1,3 @@ +import {cubicBezier} from './bezier'; +export let ease = cubicBezier(0.25, 0.1, 0.25, 1); +export let linear = cubicBezier(0,0,1,1); \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/animation/index.ts b/QXTfront/uni_modules/lime-shared/animation/index.ts new file mode 100644 index 0000000..c384182 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/animation/index.ts @@ -0,0 +1,12 @@ +// @ts-nocheck +// #ifdef UNI-APP-X && APP +// export * from './uvue.uts' +export { Timeline, Animation } from './uvue.uts' +// #endif + + + +// #ifndef UNI-APP-X && APP +// export * from './vue.ts' +export { Timeline, Animation } from './vue.ts' +// #endif diff --git a/QXTfront/uni_modules/lime-shared/animation/useTransition.ts b/QXTfront/uni_modules/lime-shared/animation/useTransition.ts new file mode 100644 index 0000000..238be97 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/animation/useTransition.ts @@ -0,0 +1,108 @@ +// @ts-nocheck +import type { ComponentPublicInstance, Ref } from 'vue' +import { ease, linear } from './ease'; +import { Timeline, Animation } from './'; +export type UseTransitionOptions = { + duration ?: number + immediate ?: boolean + context ?: ComponentPublicInstance +} +// #ifndef UNI-APP-X && APP +import { ref, watch } from '@/uni_modules/lime-shared/vue' + +export function useTransition(percent : Ref|(() => number), options : UseTransitionOptions) : Ref { + const current = ref(0) + const { immediate, duration = 300 } = options + let tl:Timeline|null = null; + let timer = -1 + const isFunction = typeof percent === 'function' + watch(isFunction ? percent : () => percent.value, (v) => { + if(tl == null){ + tl = new Timeline() + } + tl.start(); + tl.add( + new Animation( + current.value, + v, + duration, + 0, + ease, + nowValue => { + current.value = nowValue + clearTimeout(timer) + if(current.value == v){ + timer = setTimeout(()=>{ + tl?.pause(); + tl = null + }, duration) + } + } + ) + ); + }, { immediate }) + + return current +} + +// #endif + +// #ifdef UNI-APP-X && APP +type UseTransitionReturnType = Ref +export function useTransition(source : any, options : UseTransitionOptions) : UseTransitionReturnType { + const outputRef : Ref = ref(0) + const immediate = options.immediate ?? false + const duration = options.duration ?? 300 + const context = options.context //as ComponentPublicInstance | null + let tl:Timeline|null = null; + let timer = -1 + const watchFunc = (v : number) => { + if(tl == null){ + tl = new Timeline() + } + tl!.start(); + tl!.add( + new Animation( + outputRef.value, + v, + duration, + 0, + ease, + nowValue => { + outputRef.value = nowValue + clearTimeout(timer) + if(outputRef.value == v){ + timer = setTimeout(()=>{ + tl?.pause(); + tl = null + }, duration) + } + } + ), + null + ); + } + + if (context != null && typeof source == 'string') { + context.$watch(source, watchFunc, { immediate } as WatchOptions) + } else if(typeof source == 'function'){ + watch(source, watchFunc, { immediate }) + } + // #ifdef APP-ANDROID + else if(isRef(source) && source instanceof Ref) { + watch(source as Ref, watchFunc, { immediate }) + } + // #endif + // #ifndef APP-ANDROID + else if(isRef(source) && typeof source.value == 'number') { + watch(source, watchFunc, { immediate }) + } + // #endif + + const stop = ()=>{ + + } + return outputRef //as UseTransitionReturnType +} + +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/animation/uvue.uts b/QXTfront/uni_modules/lime-shared/animation/uvue.uts new file mode 100644 index 0000000..45a7a23 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/animation/uvue.uts @@ -0,0 +1,119 @@ +// @ts-nocheck +import { raf, cancelRaf} from '../raf' +export class Timeline { + state : string + animations : Set = new Set() + delAnimations : Animation[] = [] + startTimes : Map = new Map() + pauseTime : number = 0 + pauseStart : number = Date.now() + tickHandler : number = 0 + tickHandlers : number[] = [] + tick : (() => void) | null = null + constructor() { + this.state = 'Initiated'; + } + start() { + if (!(this.state == 'Initiated')) return; + this.state = 'Started'; + + let startTime = Date.now(); + this.pauseTime = 0; + this.tick = () => { + let now = Date.now(); + this.animations.forEach((animation : Animation) => { + let t:number; + const ani = this.startTimes.get(animation) + if (ani == null) return + if (ani < startTime) { + t = now - startTime - animation.delay - this.pauseTime; + } else { + t = now - ani - animation.delay - this.pauseTime; + } + if (t > animation.duration) { + this.delAnimations.push(animation) + // 不能在 foreach 里面 对 集合进行删除操作 + // this.animations.delete(animation); + t = animation.duration; + } + if (t > 0) animation.run(t); + }) + // 不能在 foreach 里面 对 集合进行删除操作 + while (this.delAnimations.length > 0) { + const animation = this.delAnimations.pop(); + if (animation == null) return + this.animations.delete(animation); + } + // cancelAnimationFrame(this.tickHandler); + if (this.state != 'Started') return + + this.tickHandler = raf(()=>{ + this.tick!() + }) + + this.tickHandlers.push(this.tickHandler) + } + if(this.tick != null) { + this.tick!() + } + + } + pause() { + if (!(this.state === 'Started')) return; + this.state = 'Paused'; + this.pauseStart = Date.now(); + cancelRaf(this.tickHandler); + // cancelRaf(this.tickHandler); + } + resume() { + if (!(this.state === 'Paused')) return; + this.state = 'Started'; + this.pauseTime += Date.now() - this.pauseStart; + this.tick!(); + } + reset() { + this.pause(); + this.state = 'Initiated'; + this.pauseTime = 0; + this.pauseStart = 0; + this.animations.clear() + this.delAnimations.clear() + this.startTimes.clear() + this.tickHandler = 0; + } + add(animation : Animation, startTime ?: number | null) { + if (startTime == null) startTime = Date.now(); + this.animations.add(animation); + this.startTimes.set(animation, startTime); + } +} + +export class Animation { + startValue : number + endValue : number + duration : number + timingFunction : (t : number) => number + delay : number + template : (t : number) => void + constructor( + startValue : number, + endValue : number, + duration : number, + delay : number, + timingFunction : (t : number) => number, + template : (v : number) => void) { + this.startValue = startValue; + this.endValue = endValue; + this.duration = duration; + this.timingFunction = timingFunction; + this.delay = delay; + this.template = template; + } + + run(time : number) { + let range = this.endValue - this.startValue; + let progress = time / this.duration + if(progress != 1) progress = this.timingFunction(progress) + this.template(this.startValue + range * progress) + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/animation/vue.ts b/QXTfront/uni_modules/lime-shared/animation/vue.ts new file mode 100644 index 0000000..30f89e5 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/animation/vue.ts @@ -0,0 +1,123 @@ +// @ts-nocheck +const TICK = Symbol('tick'); +const TICK_HANDLER = Symbol('tick-handler'); +const ANIMATIONS = Symbol('animations'); +const START_TIMES = Symbol('start-times'); +const PAUSE_START = Symbol('pause-start'); +const PAUSE_TIME = Symbol('pause-time'); +const _raf = typeof requestAnimationFrame !== 'undefined' ? requestAnimationFrame : function(cb: Function) {return setTimeout(cb, 1000/60)} +const _caf = typeof cancelAnimationFrame !== 'undefined' ? cancelAnimationFrame: function(id: any) {clearTimeout(id)} + +// const TICK = 'tick'; +// const TICK_HANDLER = 'tick-handler'; +// const ANIMATIONS = 'animations'; +// const START_TIMES = 'start-times'; +// const PAUSE_START = 'pause-start'; +// const PAUSE_TIME = 'pause-time'; +// const _raf = function(callback):number|null {return setTimeout(callback, 1000/60)} +// const _caf = function(id: number):void {clearTimeout(id)} + +export class Timeline { + state: string + constructor() { + this.state = 'Initiated'; + this[ANIMATIONS] = new Set(); + this[START_TIMES] = new Map(); + } + start() { + if (!(this.state === 'Initiated')) return; + this.state = 'Started'; + + let startTime = Date.now(); + this[PAUSE_TIME] = 0; + this[TICK] = () => { + let now = Date.now(); + this[ANIMATIONS].forEach((animation) => { + let t: number; + if (this[START_TIMES].get(animation) < startTime) { + t = now - startTime - animation.delay - this[PAUSE_TIME]; + } else { + t = now - this[START_TIMES].get(animation) - animation.delay - this[PAUSE_TIME]; + } + + if (t > animation.duration) { + this[ANIMATIONS].delete(animation); + t = animation.duration; + } + if (t > 0) animation.run(t); + }) + // for (let animation of this[ANIMATIONS]) { + // let t: number; + // console.log('animation', animation) + // if (this[START_TIMES].get(animation) < startTime) { + // t = now - startTime - animation.delay - this[PAUSE_TIME]; + // } else { + // t = now - this[START_TIMES].get(animation) - animation.delay - this[PAUSE_TIME]; + // } + + // if (t > animation.duration) { + // this[ANIMATIONS].delete(animation); + // t = animation.duration; + // } + // if (t > 0) animation.run(t); + // } + this[TICK_HANDLER] = _raf(this[TICK]); + }; + this[TICK](); + } + pause() { + if (!(this.state === 'Started')) return; + this.state = 'Paused'; + + this[PAUSE_START] = Date.now(); + _caf(this[TICK_HANDLER]); + } + resume() { + if (!(this.state === 'Paused')) return; + this.state = 'Started'; + + this[PAUSE_TIME] += Date.now() - this[PAUSE_START]; + this[TICK](); + } + reset() { + this.pause(); + this.state = 'Initiated'; + this[PAUSE_TIME] = 0; + this[PAUSE_START] = 0; + this[ANIMATIONS] = new Set(); + this[START_TIMES] = new Map(); + this[TICK_HANDLER] = null; + } + add(animation: any, startTime?: number) { + if (arguments.length < 2) startTime = Date.now(); + this[ANIMATIONS].add(animation); + this[START_TIMES].set(animation, startTime); + } +} + +export class Animation { + startValue: number + endValue: number + duration: number + timingFunction: (t: number) => number + delay: number + template: (t: number) => void + constructor(startValue: number, endValue: number, duration: number, delay: number, timingFunction: (t: number) => number, template: (v: number) => void) { + timingFunction = timingFunction || (v => v); + template = template || (v => v); + + this.startValue = startValue; + this.endValue = endValue; + this.duration = duration; + this.timingFunction = timingFunction; + this.delay = delay; + this.template = template; + } + + run(time: number) { + let range = this.endValue - this.startValue; + let progress = time / this.duration + if(progress != 1) progress = this.timingFunction(progress) + this.template(this.startValue + range * progress) + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/areaData/city-china.json b/QXTfront/uni_modules/lime-shared/areaData/city-china.json new file mode 100644 index 0000000..d9872a0 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/areaData/city-china.json @@ -0,0 +1,3888 @@ +{ + "province_list": { + "110000": "北京市", + "120000": "天津市", + "130000": "河北省", + "140000": "山西省", + "150000": "内蒙古自治区", + "210000": "辽宁省", + "220000": "吉林省", + "230000": "黑龙江省", + "310000": "上海市", + "320000": "江苏省", + "330000": "浙江省", + "340000": "安徽省", + "350000": "福建省", + "360000": "江西省", + "370000": "山东省", + "410000": "河南省", + "420000": "湖北省", + "430000": "湖南省", + "440000": "广东省", + "450000": "广西壮族自治区", + "460000": "海南省", + "500000": "重庆市", + "510000": "四川省", + "520000": "贵州省", + "530000": "云南省", + "540000": "西藏自治区", + "610000": "陕西省", + "620000": "甘肃省", + "630000": "青海省", + "640000": "宁夏回族自治区", + "650000": "新疆维吾尔自治区", + "710000": "台湾省", + "810000": "香港特别行政区", + "820000": "澳门特别行政区" + }, + "city_list": { + "110100": "北京市", + "120100": "天津市", + "130100": "石家庄市", + "130200": "唐山市", + "130300": "秦皇岛市", + "130400": "邯郸市", + "130500": "邢台市", + "130600": "保定市", + "130700": "张家口市", + "130800": "承德市", + "130900": "沧州市", + "131000": "廊坊市", + "131100": "衡水市", + "140100": "太原市", + "140200": "大同市", + "140300": "阳泉市", + "140400": "长治市", + "140500": "晋城市", + "140600": "朔州市", + "140700": "晋中市", + "140800": "运城市", + "140900": "忻州市", + "141000": "临汾市", + "141100": "吕梁市", + "150100": "呼和浩特市", + "150200": "包头市", + "150300": "乌海市", + "150400": "赤峰市", + "150500": "通辽市", + "150600": "鄂尔多斯市", + "150700": "呼伦贝尔市", + "150800": "巴彦淖尔市", + "150900": "乌兰察布市", + "152200": "兴安盟", + "152500": "锡林郭勒盟", + "152900": "阿拉善盟", + "210100": "沈阳市", + "210200": "大连市", + "210300": "鞍山市", + "210400": "抚顺市", + "210500": "本溪市", + "210600": "丹东市", + "210700": "锦州市", + "210800": "营口市", + "210900": "阜新市", + "211000": "辽阳市", + "211100": "盘锦市", + "211200": "铁岭市", + "211300": "朝阳市", + "211400": "葫芦岛市", + "220100": "长春市", + "220200": "吉林市", + "220300": "四平市", + "220400": "辽源市", + "220500": "通化市", + "220600": "白山市", + "220700": "松原市", + "220800": "白城市", + "222400": "延边朝鲜族自治州", + "230100": "哈尔滨市", + "230200": "齐齐哈尔市", + "230300": "鸡西市", + "230400": "鹤岗市", + "230500": "双鸭山市", + "230600": "大庆市", + "230700": "伊春市", + "230800": "佳木斯市", + "230900": "七台河市", + "231000": "牡丹江市", + "231100": "黑河市", + "231200": "绥化市", + "232700": "大兴安岭地区", + "310100": "上海市", + "320100": "南京市", + "320200": "无锡市", + "320300": "徐州市", + "320400": "常州市", + "320500": "苏州市", + "320600": "南通市", + "320700": "连云港市", + "320800": "淮安市", + "320900": "盐城市", + "321000": "扬州市", + "321100": "镇江市", + "321200": "泰州市", + "321300": "宿迁市", + "330100": "杭州市", + "330200": "宁波市", + "330300": "温州市", + "330400": "嘉兴市", + "330500": "湖州市", + "330600": "绍兴市", + "330700": "金华市", + "330800": "衢州市", + "330900": "舟山市", + "331000": "台州市", + "331100": "丽水市", + "340100": "合肥市", + "340200": "芜湖市", + "340300": "蚌埠市", + "340400": "淮南市", + "340500": "马鞍山市", + "340600": "淮北市", + "340700": "铜陵市", + "340800": "安庆市", + "341000": "黄山市", + "341100": "滁州市", + "341200": "阜阳市", + "341300": "宿州市", + "341500": "六安市", + "341600": "亳州市", + "341700": "池州市", + "341800": "宣城市", + "350100": "福州市", + "350200": "厦门市", + "350300": "莆田市", + "350400": "三明市", + "350500": "泉州市", + "350600": "漳州市", + "350700": "南平市", + "350800": "龙岩市", + "350900": "宁德市", + "360100": "南昌市", + "360200": "景德镇市", + "360300": "萍乡市", + "360400": "九江市", + "360500": "新余市", + "360600": "鹰潭市", + "360700": "赣州市", + "360800": "吉安市", + "360900": "宜春市", + "361000": "抚州市", + "361100": "上饶市", + "370100": "济南市", + "370200": "青岛市", + "370300": "淄博市", + "370400": "枣庄市", + "370500": "东营市", + "370600": "烟台市", + "370700": "潍坊市", + "370800": "济宁市", + "370900": "泰安市", + "371000": "威海市", + "371100": "日照市", + "371300": "临沂市", + "371400": "德州市", + "371500": "聊城市", + "371600": "滨州市", + "371700": "菏泽市", + "410100": "郑州市", + "410200": "开封市", + "410300": "洛阳市", + "410400": "平顶山市", + "410500": "安阳市", + "410600": "鹤壁市", + "410700": "新乡市", + "410800": "焦作市", + "410900": "濮阳市", + "411000": "许昌市", + "411100": "漯河市", + "411200": "三门峡市", + "411300": "南阳市", + "411400": "商丘市", + "411500": "信阳市", + "411600": "周口市", + "411700": "驻马店市", + "419000": "省直辖县", + "420100": "武汉市", + "420200": "黄石市", + "420300": "十堰市", + "420500": "宜昌市", + "420600": "襄阳市", + "420700": "鄂州市", + "420800": "荆门市", + "420900": "孝感市", + "421000": "荆州市", + "421100": "黄冈市", + "421200": "咸宁市", + "421300": "随州市", + "422800": "恩施土家族苗族自治州", + "429000": "省直辖县", + "430100": "长沙市", + "430200": "株洲市", + "430300": "湘潭市", + "430400": "衡阳市", + "430500": "邵阳市", + "430600": "岳阳市", + "430700": "常德市", + "430800": "张家界市", + "430900": "益阳市", + "431000": "郴州市", + "431100": "永州市", + "431200": "怀化市", + "431300": "娄底市", + "433100": "湘西土家族苗族自治州", + "440100": "广州市", + "440200": "韶关市", + "440300": "深圳市", + "440400": "珠海市", + "440500": "汕头市", + "440600": "佛山市", + "440700": "江门市", + "440800": "湛江市", + "440900": "茂名市", + "441200": "肇庆市", + "441300": "惠州市", + "441400": "梅州市", + "441500": "汕尾市", + "441600": "河源市", + "441700": "阳江市", + "441800": "清远市", + "441900": "东莞市", + "442000": "中山市", + "445100": "潮州市", + "445200": "揭阳市", + "445300": "云浮市", + "450100": "南宁市", + "450200": "柳州市", + "450300": "桂林市", + "450400": "梧州市", + "450500": "北海市", + "450600": "防城港市", + "450700": "钦州市", + "450800": "贵港市", + "450900": "玉林市", + "451000": "百色市", + "451100": "贺州市", + "451200": "河池市", + "451300": "来宾市", + "451400": "崇左市", + "460100": "海口市", + "460200": "三亚市", + "460300": "三沙市", + "460400": "儋州市", + "469000": "省直辖县", + "500100": "重庆市", + "500200": "县", + "510100": "成都市", + "510300": "自贡市", + "510400": "攀枝花市", + "510500": "泸州市", + "510600": "德阳市", + "510700": "绵阳市", + "510800": "广元市", + "510900": "遂宁市", + "511000": "内江市", + "511100": "乐山市", + "511300": "南充市", + "511400": "眉山市", + "511500": "宜宾市", + "511600": "广安市", + "511700": "达州市", + "511800": "雅安市", + "511900": "巴中市", + "512000": "资阳市", + "513200": "阿坝藏族羌族自治州", + "513300": "甘孜藏族自治州", + "513400": "凉山彝族自治州", + "520100": "贵阳市", + "520200": "六盘水市", + "520300": "遵义市", + "520400": "安顺市", + "520500": "毕节市", + "520600": "铜仁市", + "522300": "黔西南布依族苗族自治州", + "522600": "黔东南苗族侗族自治州", + "522700": "黔南布依族苗族自治州", + "530100": "昆明市", + "530300": "曲靖市", + "530400": "玉溪市", + "530500": "保山市", + "530600": "昭通市", + "530700": "丽江市", + "530800": "普洱市", + "530900": "临沧市", + "532300": "楚雄彝族自治州", + "532500": "红河哈尼族彝族自治州", + "532600": "文山壮族苗族自治州", + "532800": "西双版纳傣族自治州", + "532900": "大理白族自治州", + "533100": "德宏傣族景颇族自治州", + "533300": "怒江傈僳族自治州", + "533400": "迪庆藏族自治州", + "540100": "拉萨市", + "540200": "日喀则市", + "540300": "昌都市", + "540400": "林芝市", + "540500": "山南市", + "540600": "那曲市", + "542500": "阿里地区", + "610100": "西安市", + "610200": "铜川市", + "610300": "宝鸡市", + "610400": "咸阳市", + "610500": "渭南市", + "610600": "延安市", + "610700": "汉中市", + "610800": "榆林市", + "610900": "安康市", + "611000": "商洛市", + "620100": "兰州市", + "620200": "嘉峪关市", + "620300": "金昌市", + "620400": "白银市", + "620500": "天水市", + "620600": "武威市", + "620700": "张掖市", + "620800": "平凉市", + "620900": "酒泉市", + "621000": "庆阳市", + "621100": "定西市", + "621200": "陇南市", + "622900": "临夏回族自治州", + "623000": "甘南藏族自治州", + "630100": "西宁市", + "630200": "海东市", + "632200": "海北藏族自治州", + "632300": "黄南藏族自治州", + "632500": "海南藏族自治州", + "632600": "果洛藏族自治州", + "632700": "玉树藏族自治州", + "632800": "海西蒙古族藏族自治州", + "640100": "银川市", + "640200": "石嘴山市", + "640300": "吴忠市", + "640400": "固原市", + "640500": "中卫市", + "650100": "乌鲁木齐市", + "650200": "克拉玛依市", + "650400": "吐鲁番市", + "650500": "哈密市", + "652300": "昌吉回族自治州", + "652700": "博尔塔拉蒙古自治州", + "652800": "巴音郭楞蒙古自治州", + "652900": "阿克苏地区", + "653000": "克孜勒苏柯尔克孜自治州", + "653100": "喀什地区", + "653200": "和田地区", + "654000": "伊犁哈萨克自治州", + "654200": "塔城地区", + "654300": "阿勒泰地区", + "659000": "自治区直辖县级行政区划", + "710100": "台北市", + "710200": "高雄市", + "710300": "台南市", + "710400": "台中市", + "710500": "金门县", + "710600": "南投县", + "710700": "基隆市", + "710800": "新竹市", + "710900": "嘉义市", + "711100": "新北市", + "711200": "宜兰县", + "711300": "新竹县", + "711400": "桃园市", + "711500": "苗栗县", + "711700": "彰化县", + "711900": "嘉义县", + "712100": "云林县", + "712400": "屏东县", + "712500": "台东县", + "712600": "花莲县", + "712700": "澎湖县", + "712800": "连江县", + "810100": "香港岛", + "810200": "九龙", + "810300": "新界", + "820100": "澳门半岛", + "820200": "离岛" + }, + "county_list": { + "110101": "东城区", + "110102": "西城区", + "110105": "朝阳区", + "110106": "丰台区", + "110107": "石景山区", + "110108": "海淀区", + "110109": "门头沟区", + "110111": "房山区", + "110112": "通州区", + "110113": "顺义区", + "110114": "昌平区", + "110115": "大兴区", + "110116": "怀柔区", + "110117": "平谷区", + "110118": "密云区", + "110119": "延庆区", + "120101": "和平区", + "120102": "河东区", + "120103": "河西区", + "120104": "南开区", + "120105": "河北区", + "120106": "红桥区", + "120110": "东丽区", + "120111": "西青区", + "120112": "津南区", + "120113": "北辰区", + "120114": "武清区", + "120115": "宝坻区", + "120116": "滨海新区", + "120117": "宁河区", + "120118": "静海区", + "120119": "蓟州区", + "130102": "长安区", + "130104": "桥西区", + "130105": "新华区", + "130107": "井陉矿区", + "130108": "裕华区", + "130109": "藁城区", + "130110": "鹿泉区", + "130111": "栾城区", + "130121": "井陉县", + "130123": "正定县", + "130125": "行唐县", + "130126": "灵寿县", + "130127": "高邑县", + "130128": "深泽县", + "130129": "赞皇县", + "130130": "无极县", + "130131": "平山县", + "130132": "元氏县", + "130133": "赵县", + "130171": "石家庄高新技术产业开发区", + "130172": "石家庄循环化工园区", + "130181": "辛集市", + "130183": "晋州市", + "130184": "新乐市", + "130202": "路南区", + "130203": "路北区", + "130204": "古冶区", + "130205": "开平区", + "130207": "丰南区", + "130208": "丰润区", + "130209": "曹妃甸区", + "130224": "滦南县", + "130225": "乐亭县", + "130227": "迁西县", + "130229": "玉田县", + "130273": "唐山高新技术产业开发区", + "130274": "河北唐山海港经济开发区", + "130281": "遵化市", + "130283": "迁安市", + "130284": "滦州市", + "130302": "海港区", + "130303": "山海关区", + "130304": "北戴河区", + "130306": "抚宁区", + "130321": "青龙满族自治县", + "130322": "昌黎县", + "130324": "卢龙县", + "130371": "秦皇岛市经济技术开发区", + "130372": "北戴河新区", + "130390": "经济技术开发区", + "130402": "邯山区", + "130403": "丛台区", + "130404": "复兴区", + "130406": "峰峰矿区", + "130407": "肥乡区", + "130408": "永年区", + "130423": "临漳县", + "130424": "成安县", + "130425": "大名县", + "130426": "涉县", + "130427": "磁县", + "130430": "邱县", + "130431": "鸡泽县", + "130432": "广平县", + "130433": "馆陶县", + "130434": "魏县", + "130435": "曲周县", + "130471": "邯郸经济技术开发区", + "130473": "邯郸冀南新区", + "130481": "武安市", + "130502": "襄都区", + "130503": "信都区", + "130505": "任泽区", + "130506": "南和区", + "130522": "临城县", + "130523": "内丘县", + "130524": "柏乡县", + "130525": "隆尧县", + "130528": "宁晋县", + "130529": "巨鹿县", + "130530": "新河县", + "130531": "广宗县", + "130532": "平乡县", + "130533": "威县", + "130534": "清河县", + "130535": "临西县", + "130571": "河北邢台经济开发区", + "130581": "南宫市", + "130582": "沙河市", + "130602": "竞秀区", + "130606": "莲池区", + "130607": "满城区", + "130608": "清苑区", + "130609": "徐水区", + "130623": "涞水县", + "130624": "阜平县", + "130626": "定兴县", + "130627": "唐县", + "130628": "高阳县", + "130629": "容城县", + "130630": "涞源县", + "130631": "望都县", + "130632": "安新县", + "130633": "易县", + "130634": "曲阳县", + "130635": "蠡县", + "130636": "顺平县", + "130637": "博野县", + "130638": "雄县", + "130671": "保定高新技术产业开发区", + "130672": "保定白沟新城", + "130681": "涿州市", + "130682": "定州市", + "130683": "安国市", + "130684": "高碑店市", + "130702": "桥东区", + "130703": "桥西区", + "130705": "宣化区", + "130706": "下花园区", + "130708": "万全区", + "130709": "崇礼区", + "130722": "张北县", + "130723": "康保县", + "130724": "沽源县", + "130725": "尚义县", + "130726": "蔚县", + "130727": "阳原县", + "130728": "怀安县", + "130730": "怀来县", + "130731": "涿鹿县", + "130732": "赤城县", + "130772": "张家口市察北管理区", + "130802": "双桥区", + "130803": "双滦区", + "130804": "鹰手营子矿区", + "130821": "承德县", + "130822": "兴隆县", + "130824": "滦平县", + "130825": "隆化县", + "130826": "丰宁满族自治县", + "130827": "宽城满族自治县", + "130828": "围场满族蒙古族自治县", + "130871": "承德高新技术产业开发区", + "130881": "平泉市", + "130902": "新华区", + "130903": "运河区", + "130921": "沧县", + "130922": "青县", + "130923": "东光县", + "130924": "海兴县", + "130925": "盐山县", + "130926": "肃宁县", + "130927": "南皮县", + "130928": "吴桥县", + "130929": "献县", + "130930": "孟村回族自治县", + "130971": "河北沧州经济开发区", + "130972": "沧州高新技术产业开发区", + "130973": "沧州渤海新区", + "130981": "泊头市", + "130982": "任丘市", + "130983": "黄骅市", + "130984": "河间市", + "131002": "安次区", + "131003": "广阳区", + "131022": "固安县", + "131023": "永清县", + "131024": "香河县", + "131025": "大城县", + "131026": "文安县", + "131028": "大厂回族自治县", + "131071": "廊坊经济技术开发区", + "131081": "霸州市", + "131082": "三河市", + "131090": "开发区", + "131102": "桃城区", + "131103": "冀州区", + "131121": "枣强县", + "131122": "武邑县", + "131123": "武强县", + "131124": "饶阳县", + "131125": "安平县", + "131126": "故城县", + "131127": "景县", + "131128": "阜城县", + "131171": "河北衡水经济开发区", + "131172": "衡水滨湖新区", + "131182": "深州市", + "140105": "小店区", + "140106": "迎泽区", + "140107": "杏花岭区", + "140108": "尖草坪区", + "140109": "万柏林区", + "140110": "晋源区", + "140121": "清徐县", + "140122": "阳曲县", + "140123": "娄烦县", + "140181": "古交市", + "140212": "新荣区", + "140213": "平城区", + "140214": "云冈区", + "140215": "云州区", + "140221": "阳高县", + "140222": "天镇县", + "140223": "广灵县", + "140224": "灵丘县", + "140225": "浑源县", + "140226": "左云县", + "140271": "山西大同经济开发区", + "140302": "城区", + "140303": "矿区", + "140311": "郊区", + "140321": "平定县", + "140322": "盂县", + "140403": "潞州区", + "140404": "上党区", + "140405": "屯留区", + "140406": "潞城区", + "140423": "襄垣县", + "140425": "平顺县", + "140426": "黎城县", + "140427": "壶关县", + "140428": "长子县", + "140429": "武乡县", + "140430": "沁县", + "140431": "沁源县", + "140471": "山西长治高新技术产业园区", + "140502": "城区", + "140521": "沁水县", + "140522": "阳城县", + "140524": "陵川县", + "140525": "泽州县", + "140581": "高平市", + "140602": "朔城区", + "140603": "平鲁区", + "140621": "山阴县", + "140622": "应县", + "140623": "右玉县", + "140671": "山西朔州经济开发区", + "140681": "怀仁市", + "140702": "榆次区", + "140703": "太谷区", + "140721": "榆社县", + "140722": "左权县", + "140723": "和顺县", + "140724": "昔阳县", + "140725": "寿阳县", + "140727": "祁县", + "140728": "平遥县", + "140729": "灵石县", + "140781": "介休市", + "140802": "盐湖区", + "140821": "临猗县", + "140822": "万荣县", + "140823": "闻喜县", + "140824": "稷山县", + "140825": "新绛县", + "140826": "绛县", + "140827": "垣曲县", + "140828": "夏县", + "140829": "平陆县", + "140830": "芮城县", + "140881": "永济市", + "140882": "河津市", + "140902": "忻府区", + "140921": "定襄县", + "140922": "五台县", + "140923": "代县", + "140924": "繁峙县", + "140925": "宁武县", + "140926": "静乐县", + "140927": "神池县", + "140928": "五寨县", + "140929": "岢岚县", + "140930": "河曲县", + "140931": "保德县", + "140932": "偏关县", + "140971": "五台山风景名胜区", + "140981": "原平市", + "141002": "尧都区", + "141021": "曲沃县", + "141022": "翼城县", + "141023": "襄汾县", + "141024": "洪洞县", + "141025": "古县", + "141026": "安泽县", + "141027": "浮山县", + "141028": "吉县", + "141029": "乡宁县", + "141030": "大宁县", + "141031": "隰县", + "141032": "永和县", + "141033": "蒲县", + "141034": "汾西县", + "141081": "侯马市", + "141082": "霍州市", + "141102": "离石区", + "141121": "文水县", + "141122": "交城县", + "141123": "兴县", + "141124": "临县", + "141125": "柳林县", + "141126": "石楼县", + "141127": "岚县", + "141128": "方山县", + "141129": "中阳县", + "141130": "交口县", + "141181": "孝义市", + "141182": "汾阳市", + "150102": "新城区", + "150103": "回民区", + "150104": "玉泉区", + "150105": "赛罕区", + "150121": "土默特左旗", + "150122": "托克托县", + "150123": "和林格尔县", + "150124": "清水河县", + "150125": "武川县", + "150172": "呼和浩特经济技术开发区", + "150202": "东河区", + "150203": "昆都仑区", + "150204": "青山区", + "150205": "石拐区", + "150206": "白云鄂博矿区", + "150207": "九原区", + "150221": "土默特右旗", + "150222": "固阳县", + "150223": "达尔罕茂明安联合旗", + "150271": "包头稀土高新技术产业开发区", + "150302": "海勃湾区", + "150303": "海南区", + "150304": "乌达区", + "150402": "红山区", + "150403": "元宝山区", + "150404": "松山区", + "150421": "阿鲁科尔沁旗", + "150422": "巴林左旗", + "150423": "巴林右旗", + "150424": "林西县", + "150425": "克什克腾旗", + "150426": "翁牛特旗", + "150428": "喀喇沁旗", + "150429": "宁城县", + "150430": "敖汉旗", + "150502": "科尔沁区", + "150521": "科尔沁左翼中旗", + "150522": "科尔沁左翼后旗", + "150523": "开鲁县", + "150524": "库伦旗", + "150525": "奈曼旗", + "150526": "扎鲁特旗", + "150571": "通辽经济技术开发区", + "150581": "霍林郭勒市", + "150602": "东胜区", + "150603": "康巴什区", + "150621": "达拉特旗", + "150622": "准格尔旗", + "150623": "鄂托克前旗", + "150624": "鄂托克旗", + "150625": "杭锦旗", + "150626": "乌审旗", + "150627": "伊金霍洛旗", + "150702": "海拉尔区", + "150703": "扎赉诺尔区", + "150721": "阿荣旗", + "150722": "莫力达瓦达斡尔族自治旗", + "150723": "鄂伦春自治旗", + "150724": "鄂温克族自治旗", + "150725": "陈巴尔虎旗", + "150726": "新巴尔虎左旗", + "150727": "新巴尔虎右旗", + "150781": "满洲里市", + "150782": "牙克石市", + "150783": "扎兰屯市", + "150784": "额尔古纳市", + "150785": "根河市", + "150802": "临河区", + "150821": "五原县", + "150822": "磴口县", + "150823": "乌拉特前旗", + "150824": "乌拉特中旗", + "150825": "乌拉特后旗", + "150826": "杭锦后旗", + "150902": "集宁区", + "150921": "卓资县", + "150922": "化德县", + "150923": "商都县", + "150924": "兴和县", + "150925": "凉城县", + "150926": "察哈尔右翼前旗", + "150927": "察哈尔右翼中旗", + "150928": "察哈尔右翼后旗", + "150929": "四子王旗", + "150981": "丰镇市", + "152201": "乌兰浩特市", + "152202": "阿尔山市", + "152221": "科尔沁右翼前旗", + "152222": "科尔沁右翼中旗", + "152223": "扎赉特旗", + "152224": "突泉县", + "152501": "二连浩特市", + "152502": "锡林浩特市", + "152522": "阿巴嘎旗", + "152523": "苏尼特左旗", + "152524": "苏尼特右旗", + "152525": "东乌珠穆沁旗", + "152526": "西乌珠穆沁旗", + "152527": "太仆寺旗", + "152528": "镶黄旗", + "152529": "正镶白旗", + "152530": "正蓝旗", + "152531": "多伦县", + "152571": "乌拉盖管委会", + "152921": "阿拉善左旗", + "152922": "阿拉善右旗", + "152923": "额济纳旗", + "152971": "内蒙古阿拉善经济开发区", + "210102": "和平区", + "210103": "沈河区", + "210104": "大东区", + "210105": "皇姑区", + "210106": "铁西区", + "210111": "苏家屯区", + "210112": "浑南区", + "210113": "沈北新区", + "210114": "于洪区", + "210115": "辽中区", + "210123": "康平县", + "210124": "法库县", + "210181": "新民市", + "210190": "经济技术开发区", + "210202": "中山区", + "210203": "西岗区", + "210204": "沙河口区", + "210211": "甘井子区", + "210212": "旅顺口区", + "210213": "金州区", + "210214": "普兰店区", + "210224": "长海县", + "210281": "瓦房店市", + "210283": "庄河市", + "210302": "铁东区", + "210303": "铁西区", + "210304": "立山区", + "210311": "千山区", + "210321": "台安县", + "210323": "岫岩满族自治县", + "210381": "海城市", + "210390": "高新区", + "210402": "新抚区", + "210403": "东洲区", + "210404": "望花区", + "210411": "顺城区", + "210421": "抚顺县", + "210422": "新宾满族自治县", + "210423": "清原满族自治县", + "210502": "平山区", + "210503": "溪湖区", + "210504": "明山区", + "210505": "南芬区", + "210521": "本溪满族自治县", + "210522": "桓仁满族自治县", + "210602": "元宝区", + "210603": "振兴区", + "210604": "振安区", + "210624": "宽甸满族自治县", + "210681": "东港市", + "210682": "凤城市", + "210702": "古塔区", + "210703": "凌河区", + "210711": "太和区", + "210726": "黑山县", + "210727": "义县", + "210781": "凌海市", + "210782": "北镇市", + "210793": "经济技术开发区", + "210802": "站前区", + "210803": "西市区", + "210804": "鲅鱼圈区", + "210811": "老边区", + "210881": "盖州市", + "210882": "大石桥市", + "210902": "海州区", + "210903": "新邱区", + "210904": "太平区", + "210905": "清河门区", + "210911": "细河区", + "210921": "阜新蒙古族自治县", + "210922": "彰武县", + "211002": "白塔区", + "211003": "文圣区", + "211004": "宏伟区", + "211005": "弓长岭区", + "211011": "太子河区", + "211021": "辽阳县", + "211081": "灯塔市", + "211102": "双台子区", + "211103": "兴隆台区", + "211104": "大洼区", + "211122": "盘山县", + "211202": "银州区", + "211204": "清河区", + "211221": "铁岭县", + "211223": "西丰县", + "211224": "昌图县", + "211281": "调兵山市", + "211282": "开原市", + "211302": "双塔区", + "211303": "龙城区", + "211321": "朝阳县", + "211322": "建平县", + "211324": "喀喇沁左翼蒙古族自治县", + "211381": "北票市", + "211382": "凌源市", + "211402": "连山区", + "211403": "龙港区", + "211404": "南票区", + "211421": "绥中县", + "211422": "建昌县", + "211481": "兴城市", + "220102": "南关区", + "220103": "宽城区", + "220104": "朝阳区", + "220105": "二道区", + "220106": "绿园区", + "220112": "双阳区", + "220113": "九台区", + "220122": "农安县", + "220171": "长春经济技术开发区", + "220172": "长春净月高新技术产业开发区", + "220173": "长春高新技术产业开发区", + "220174": "长春汽车经济技术开发区", + "220182": "榆树市", + "220183": "德惠市", + "220184": "公主岭市", + "220192": "经济技术开发区", + "220202": "昌邑区", + "220203": "龙潭区", + "220204": "船营区", + "220211": "丰满区", + "220221": "永吉县", + "220271": "吉林经济开发区", + "220272": "吉林高新技术产业开发区", + "220281": "蛟河市", + "220282": "桦甸市", + "220283": "舒兰市", + "220284": "磐石市", + "220302": "铁西区", + "220303": "铁东区", + "220322": "梨树县", + "220323": "伊通满族自治县", + "220382": "双辽市", + "220402": "龙山区", + "220403": "西安区", + "220421": "东丰县", + "220422": "东辽县", + "220502": "东昌区", + "220503": "二道江区", + "220521": "通化县", + "220523": "辉南县", + "220524": "柳河县", + "220581": "梅河口市", + "220582": "集安市", + "220602": "浑江区", + "220605": "江源区", + "220621": "抚松县", + "220622": "靖宇县", + "220623": "长白朝鲜族自治县", + "220681": "临江市", + "220702": "宁江区", + "220721": "前郭尔罗斯蒙古族自治县", + "220722": "长岭县", + "220723": "乾安县", + "220771": "吉林松原经济开发区", + "220781": "扶余市", + "220802": "洮北区", + "220821": "镇赉县", + "220822": "通榆县", + "220871": "吉林白城经济开发区", + "220881": "洮南市", + "220882": "大安市", + "222401": "延吉市", + "222402": "图们市", + "222403": "敦化市", + "222404": "珲春市", + "222405": "龙井市", + "222406": "和龙市", + "222424": "汪清县", + "222426": "安图县", + "230102": "道里区", + "230103": "南岗区", + "230104": "道外区", + "230108": "平房区", + "230109": "松北区", + "230110": "香坊区", + "230111": "呼兰区", + "230112": "阿城区", + "230113": "双城区", + "230123": "依兰县", + "230124": "方正县", + "230125": "宾县", + "230126": "巴彦县", + "230127": "木兰县", + "230128": "通河县", + "230129": "延寿县", + "230183": "尚志市", + "230184": "五常市", + "230202": "龙沙区", + "230203": "建华区", + "230204": "铁锋区", + "230205": "昂昂溪区", + "230206": "富拉尔基区", + "230207": "碾子山区", + "230208": "梅里斯达斡尔族区", + "230221": "龙江县", + "230223": "依安县", + "230224": "泰来县", + "230225": "甘南县", + "230227": "富裕县", + "230229": "克山县", + "230230": "克东县", + "230231": "拜泉县", + "230281": "讷河市", + "230302": "鸡冠区", + "230303": "恒山区", + "230304": "滴道区", + "230305": "梨树区", + "230306": "城子河区", + "230307": "麻山区", + "230321": "鸡东县", + "230381": "虎林市", + "230382": "密山市", + "230402": "向阳区", + "230403": "工农区", + "230404": "南山区", + "230405": "兴安区", + "230406": "东山区", + "230407": "兴山区", + "230421": "萝北县", + "230422": "绥滨县", + "230502": "尖山区", + "230503": "岭东区", + "230505": "四方台区", + "230506": "宝山区", + "230521": "集贤县", + "230522": "友谊县", + "230523": "宝清县", + "230524": "饶河县", + "230602": "萨尔图区", + "230603": "龙凤区", + "230604": "让胡路区", + "230605": "红岗区", + "230606": "大同区", + "230621": "肇州县", + "230622": "肇源县", + "230623": "林甸县", + "230624": "杜尔伯特蒙古族自治县", + "230671": "大庆高新技术产业开发区", + "230717": "伊美区", + "230718": "乌翠区", + "230719": "友好区", + "230722": "嘉荫县", + "230723": "汤旺县", + "230724": "丰林县", + "230725": "大箐山县", + "230726": "南岔县", + "230751": "金林区", + "230781": "铁力市", + "230803": "向阳区", + "230804": "前进区", + "230805": "东风区", + "230811": "郊区", + "230822": "桦南县", + "230826": "桦川县", + "230828": "汤原县", + "230881": "同江市", + "230882": "富锦市", + "230883": "抚远市", + "230902": "新兴区", + "230903": "桃山区", + "230904": "茄子河区", + "230921": "勃利县", + "231002": "东安区", + "231003": "阳明区", + "231004": "爱民区", + "231005": "西安区", + "231025": "林口县", + "231081": "绥芬河市", + "231083": "海林市", + "231084": "宁安市", + "231085": "穆棱市", + "231086": "东宁市", + "231102": "爱辉区", + "231123": "逊克县", + "231124": "孙吴县", + "231181": "北安市", + "231182": "五大连池市", + "231183": "嫩江市", + "231202": "北林区", + "231221": "望奎县", + "231222": "兰西县", + "231223": "青冈县", + "231224": "庆安县", + "231225": "明水县", + "231226": "绥棱县", + "231281": "安达市", + "231282": "肇东市", + "231283": "海伦市", + "232701": "漠河市", + "232721": "呼玛县", + "232722": "塔河县", + "232761": "加格达奇区", + "232762": "松岭区", + "232763": "新林区", + "232764": "呼中区", + "310101": "黄浦区", + "310104": "徐汇区", + "310105": "长宁区", + "310106": "静安区", + "310107": "普陀区", + "310109": "虹口区", + "310110": "杨浦区", + "310112": "闵行区", + "310113": "宝山区", + "310114": "嘉定区", + "310115": "浦东新区", + "310116": "金山区", + "310117": "松江区", + "310118": "青浦区", + "310120": "奉贤区", + "310151": "崇明区", + "320102": "玄武区", + "320104": "秦淮区", + "320105": "建邺区", + "320106": "鼓楼区", + "320111": "浦口区", + "320112": "江北新区", + "320113": "栖霞区", + "320114": "雨花台区", + "320115": "江宁区", + "320116": "六合区", + "320117": "溧水区", + "320118": "高淳区", + "320205": "锡山区", + "320206": "惠山区", + "320211": "滨湖区", + "320213": "梁溪区", + "320214": "新吴区", + "320281": "江阴市", + "320282": "宜兴市", + "320302": "鼓楼区", + "320303": "云龙区", + "320305": "贾汪区", + "320311": "泉山区", + "320312": "铜山区", + "320321": "丰县", + "320322": "沛县", + "320324": "睢宁县", + "320371": "徐州经济技术开发区", + "320381": "新沂市", + "320382": "邳州市", + "320391": "工业园区", + "320402": "天宁区", + "320404": "钟楼区", + "320411": "新北区", + "320412": "武进区", + "320413": "金坛区", + "320481": "溧阳市", + "320505": "虎丘区", + "320506": "吴中区", + "320507": "相城区", + "320508": "姑苏区", + "320509": "吴江区", + "320571": "苏州工业园区", + "320581": "常熟市", + "320582": "张家港市", + "320583": "昆山市", + "320585": "太仓市", + "320590": "工业园区", + "320591": "高新区", + "320611": "港闸区", + "320612": "通州区", + "320613": "崇川区", + "320614": "海门区", + "320623": "如东县", + "320681": "启东市", + "320682": "如皋市", + "320685": "海安市", + "320691": "高新区", + "320703": "连云区", + "320706": "海州区", + "320707": "赣榆区", + "320722": "东海县", + "320723": "灌云县", + "320724": "灌南县", + "320771": "连云港经济技术开发区", + "320803": "淮安区", + "320804": "淮阴区", + "320812": "清江浦区", + "320813": "洪泽区", + "320826": "涟水县", + "320830": "盱眙县", + "320831": "金湖县", + "320871": "淮安经济技术开发区", + "320890": "经济开发区", + "320902": "亭湖区", + "320903": "盐都区", + "320904": "大丰区", + "320921": "响水县", + "320922": "滨海县", + "320923": "阜宁县", + "320924": "射阳县", + "320925": "建湖县", + "320971": "盐城经济技术开发区", + "320981": "东台市", + "321002": "广陵区", + "321003": "邗江区", + "321012": "江都区", + "321023": "宝应县", + "321071": "扬州经济技术开发区", + "321081": "仪征市", + "321084": "高邮市", + "321090": "经济开发区", + "321102": "京口区", + "321111": "润州区", + "321112": "丹徒区", + "321150": "镇江新区", + "321181": "丹阳市", + "321182": "扬中市", + "321183": "句容市", + "321202": "海陵区", + "321203": "高港区", + "321204": "姜堰区", + "321271": "泰州医药高新技术产业开发区", + "321281": "兴化市", + "321282": "靖江市", + "321283": "泰兴市", + "321302": "宿城区", + "321311": "宿豫区", + "321322": "沭阳县", + "321323": "泗阳县", + "321324": "泗洪县", + "321371": "宿迁经济技术开发区", + "330102": "上城区", + "330105": "拱墅区", + "330106": "西湖区", + "330108": "滨江区", + "330109": "萧山区", + "330110": "余杭区", + "330111": "富阳区", + "330112": "临安区", + "330113": "临平区", + "330114": "钱塘区", + "330122": "桐庐县", + "330127": "淳安县", + "330182": "建德市", + "330203": "海曙区", + "330205": "江北区", + "330206": "北仑区", + "330211": "镇海区", + "330212": "鄞州区", + "330213": "奉化区", + "330225": "象山县", + "330226": "宁海县", + "330281": "余姚市", + "330282": "慈溪市", + "330302": "鹿城区", + "330303": "龙湾区", + "330304": "瓯海区", + "330305": "洞头区", + "330324": "永嘉县", + "330326": "平阳县", + "330327": "苍南县", + "330328": "文成县", + "330329": "泰顺县", + "330381": "瑞安市", + "330382": "乐清市", + "330383": "龙港市", + "330402": "南湖区", + "330411": "秀洲区", + "330421": "嘉善县", + "330424": "海盐县", + "330481": "海宁市", + "330482": "平湖市", + "330483": "桐乡市", + "330502": "吴兴区", + "330503": "南浔区", + "330521": "德清县", + "330522": "长兴县", + "330523": "安吉县", + "330602": "越城区", + "330603": "柯桥区", + "330604": "上虞区", + "330624": "新昌县", + "330681": "诸暨市", + "330683": "嵊州市", + "330702": "婺城区", + "330703": "金东区", + "330723": "武义县", + "330726": "浦江县", + "330727": "磐安县", + "330781": "兰溪市", + "330782": "义乌市", + "330783": "东阳市", + "330784": "永康市", + "330802": "柯城区", + "330803": "衢江区", + "330822": "常山县", + "330824": "开化县", + "330825": "龙游县", + "330881": "江山市", + "330902": "定海区", + "330903": "普陀区", + "330921": "岱山县", + "330922": "嵊泗县", + "331002": "椒江区", + "331003": "黄岩区", + "331004": "路桥区", + "331022": "三门县", + "331023": "天台县", + "331024": "仙居县", + "331081": "温岭市", + "331082": "临海市", + "331083": "玉环市", + "331102": "莲都区", + "331121": "青田县", + "331122": "缙云县", + "331123": "遂昌县", + "331124": "松阳县", + "331125": "云和县", + "331126": "庆元县", + "331127": "景宁畲族自治县", + "331181": "龙泉市", + "340102": "瑶海区", + "340103": "庐阳区", + "340104": "蜀山区", + "340111": "包河区", + "340121": "长丰县", + "340122": "肥东县", + "340123": "肥西县", + "340124": "庐江县", + "340171": "合肥高新技术产业开发区", + "340172": "合肥经济技术开发区", + "340173": "合肥新站高新技术产业开发区", + "340181": "巢湖市", + "340190": "高新技术开发区", + "340191": "经济技术开发区", + "340202": "镜湖区", + "340207": "鸠江区", + "340209": "弋江区", + "340210": "湾沚区", + "340212": "繁昌区", + "340223": "南陵县", + "340281": "无为市", + "340302": "龙子湖区", + "340303": "蚌山区", + "340304": "禹会区", + "340311": "淮上区", + "340321": "怀远县", + "340322": "五河县", + "340323": "固镇县", + "340371": "蚌埠市高新技术开发区", + "340372": "蚌埠市经济开发区", + "340402": "大通区", + "340403": "田家庵区", + "340404": "谢家集区", + "340405": "八公山区", + "340406": "潘集区", + "340421": "凤台县", + "340422": "寿县", + "340503": "花山区", + "340504": "雨山区", + "340506": "博望区", + "340521": "当涂县", + "340522": "含山县", + "340523": "和县", + "340602": "杜集区", + "340603": "相山区", + "340604": "烈山区", + "340621": "濉溪县", + "340705": "铜官区", + "340706": "义安区", + "340711": "郊区", + "340722": "枞阳县", + "340802": "迎江区", + "340803": "大观区", + "340811": "宜秀区", + "340822": "怀宁县", + "340825": "太湖县", + "340826": "宿松县", + "340827": "望江县", + "340828": "岳西县", + "340881": "桐城市", + "340882": "潜山市", + "341002": "屯溪区", + "341003": "黄山区", + "341004": "徽州区", + "341021": "歙县", + "341022": "休宁县", + "341023": "黟县", + "341024": "祁门县", + "341102": "琅琊区", + "341103": "南谯区", + "341122": "来安县", + "341124": "全椒县", + "341125": "定远县", + "341126": "凤阳县", + "341181": "天长市", + "341182": "明光市", + "341202": "颍州区", + "341203": "颍东区", + "341204": "颍泉区", + "341221": "临泉县", + "341222": "太和县", + "341225": "阜南县", + "341226": "颍上县", + "341271": "阜阳合肥现代产业园区", + "341282": "界首市", + "341302": "埇桥区", + "341321": "砀山县", + "341322": "萧县", + "341323": "灵璧县", + "341324": "泗县", + "341371": "宿州马鞍山现代产业园区", + "341372": "宿州经济技术开发区", + "341390": "经济开发区", + "341502": "金安区", + "341503": "裕安区", + "341504": "叶集区", + "341522": "霍邱县", + "341523": "舒城县", + "341524": "金寨县", + "341525": "霍山县", + "341602": "谯城区", + "341621": "涡阳县", + "341622": "蒙城县", + "341623": "利辛县", + "341702": "贵池区", + "341721": "东至县", + "341722": "石台县", + "341723": "青阳县", + "341802": "宣州区", + "341821": "郎溪县", + "341823": "泾县", + "341824": "绩溪县", + "341825": "旌德县", + "341871": "宣城市经济开发区", + "341881": "宁国市", + "341882": "广德市", + "350102": "鼓楼区", + "350103": "台江区", + "350104": "仓山区", + "350105": "马尾区", + "350111": "晋安区", + "350112": "长乐区", + "350121": "闽侯县", + "350122": "连江县", + "350123": "罗源县", + "350124": "闽清县", + "350125": "永泰县", + "350128": "平潭县", + "350181": "福清市", + "350203": "思明区", + "350205": "海沧区", + "350206": "湖里区", + "350211": "集美区", + "350212": "同安区", + "350213": "翔安区", + "350302": "城厢区", + "350303": "涵江区", + "350304": "荔城区", + "350305": "秀屿区", + "350322": "仙游县", + "350402": "梅列区", + "350404": "三元区", + "350405": "沙县区", + "350421": "明溪县", + "350423": "清流县", + "350424": "宁化县", + "350425": "大田县", + "350426": "尤溪县", + "350428": "将乐县", + "350429": "泰宁县", + "350430": "建宁县", + "350481": "永安市", + "350502": "鲤城区", + "350503": "丰泽区", + "350504": "洛江区", + "350505": "泉港区", + "350521": "惠安县", + "350524": "安溪县", + "350525": "永春县", + "350526": "德化县", + "350527": "金门县", + "350581": "石狮市", + "350582": "晋江市", + "350583": "南安市", + "350602": "芗城区", + "350603": "龙文区", + "350604": "龙海区", + "350605": "长泰区", + "350622": "云霄县", + "350623": "漳浦县", + "350624": "诏安县", + "350626": "东山县", + "350627": "南靖县", + "350628": "平和县", + "350629": "华安县", + "350702": "延平区", + "350703": "建阳区", + "350721": "顺昌县", + "350722": "浦城县", + "350723": "光泽县", + "350724": "松溪县", + "350725": "政和县", + "350781": "邵武市", + "350782": "武夷山市", + "350783": "建瓯市", + "350802": "新罗区", + "350803": "永定区", + "350821": "长汀县", + "350823": "上杭县", + "350824": "武平县", + "350825": "连城县", + "350881": "漳平市", + "350902": "蕉城区", + "350921": "霞浦县", + "350922": "古田县", + "350923": "屏南县", + "350924": "寿宁县", + "350925": "周宁县", + "350926": "柘荣县", + "350981": "福安市", + "350982": "福鼎市", + "360102": "东湖区", + "360103": "西湖区", + "360104": "青云谱区", + "360111": "青山湖区", + "360112": "新建区", + "360113": "红谷滩区", + "360121": "南昌县", + "360123": "安义县", + "360124": "进贤县", + "360190": "经济技术开发区", + "360192": "高新区", + "360202": "昌江区", + "360203": "珠山区", + "360222": "浮梁县", + "360281": "乐平市", + "360302": "安源区", + "360313": "湘东区", + "360321": "莲花县", + "360322": "上栗县", + "360323": "芦溪县", + "360402": "濂溪区", + "360403": "浔阳区", + "360404": "柴桑区", + "360423": "武宁县", + "360424": "修水县", + "360425": "永修县", + "360426": "德安县", + "360428": "都昌县", + "360429": "湖口县", + "360430": "彭泽县", + "360481": "瑞昌市", + "360482": "共青城市", + "360483": "庐山市", + "360490": "经济技术开发区", + "360502": "渝水区", + "360521": "分宜县", + "360602": "月湖区", + "360603": "余江区", + "360681": "贵溪市", + "360702": "章贡区", + "360703": "南康区", + "360704": "赣县区", + "360722": "信丰县", + "360723": "大余县", + "360724": "上犹县", + "360725": "崇义县", + "360726": "安远县", + "360728": "定南县", + "360729": "全南县", + "360730": "宁都县", + "360731": "于都县", + "360732": "兴国县", + "360733": "会昌县", + "360734": "寻乌县", + "360735": "石城县", + "360781": "瑞金市", + "360783": "龙南市", + "360802": "吉州区", + "360803": "青原区", + "360821": "吉安县", + "360822": "吉水县", + "360823": "峡江县", + "360824": "新干县", + "360825": "永丰县", + "360826": "泰和县", + "360827": "遂川县", + "360828": "万安县", + "360829": "安福县", + "360830": "永新县", + "360881": "井冈山市", + "360902": "袁州区", + "360921": "奉新县", + "360922": "万载县", + "360923": "上高县", + "360924": "宜丰县", + "360925": "靖安县", + "360926": "铜鼓县", + "360981": "丰城市", + "360982": "樟树市", + "360983": "高安市", + "361002": "临川区", + "361003": "东乡区", + "361021": "南城县", + "361022": "黎川县", + "361023": "南丰县", + "361024": "崇仁县", + "361025": "乐安县", + "361026": "宜黄县", + "361027": "金溪县", + "361028": "资溪县", + "361030": "广昌县", + "361102": "信州区", + "361103": "广丰区", + "361104": "广信区", + "361123": "玉山县", + "361124": "铅山县", + "361125": "横峰县", + "361126": "弋阳县", + "361127": "余干县", + "361128": "鄱阳县", + "361129": "万年县", + "361130": "婺源县", + "361181": "德兴市", + "370102": "历下区", + "370103": "市中区", + "370104": "槐荫区", + "370105": "天桥区", + "370112": "历城区", + "370113": "长清区", + "370114": "章丘区", + "370115": "济阳区", + "370116": "莱芜区", + "370117": "钢城区", + "370124": "平阴县", + "370126": "商河县", + "370171": "济南高新技术产业开发区", + "370190": "高新区", + "370202": "市南区", + "370203": "市北区", + "370211": "黄岛区", + "370212": "崂山区", + "370213": "李沧区", + "370214": "城阳区", + "370215": "即墨区", + "370271": "青岛高新技术产业开发区", + "370281": "胶州市", + "370283": "平度市", + "370285": "莱西市", + "370290": "开发区", + "370302": "淄川区", + "370303": "张店区", + "370304": "博山区", + "370305": "临淄区", + "370306": "周村区", + "370321": "桓台县", + "370322": "高青县", + "370323": "沂源县", + "370402": "市中区", + "370403": "薛城区", + "370404": "峄城区", + "370405": "台儿庄区", + "370406": "山亭区", + "370481": "滕州市", + "370502": "东营区", + "370503": "河口区", + "370505": "垦利区", + "370522": "利津县", + "370523": "广饶县", + "370571": "东营经济技术开发区", + "370572": "东营港经济开发区", + "370602": "芝罘区", + "370611": "福山区", + "370612": "牟平区", + "370613": "莱山区", + "370614": "蓬莱区", + "370634": "长岛县", + "370671": "烟台高新技术产业开发区", + "370672": "烟台经济技术开发区", + "370681": "龙口市", + "370682": "莱阳市", + "370683": "莱州市", + "370685": "招远市", + "370686": "栖霞市", + "370687": "海阳市", + "370690": "开发区", + "370702": "潍城区", + "370703": "寒亭区", + "370704": "坊子区", + "370705": "奎文区", + "370724": "临朐县", + "370725": "昌乐县", + "370772": "潍坊滨海经济技术开发区", + "370781": "青州市", + "370782": "诸城市", + "370783": "寿光市", + "370784": "安丘市", + "370785": "高密市", + "370786": "昌邑市", + "370790": "开发区", + "370791": "高新区", + "370811": "任城区", + "370812": "兖州区", + "370826": "微山县", + "370827": "鱼台县", + "370828": "金乡县", + "370829": "嘉祥县", + "370830": "汶上县", + "370831": "泗水县", + "370832": "梁山县", + "370871": "济宁高新技术产业开发区", + "370881": "曲阜市", + "370883": "邹城市", + "370890": "高新区", + "370902": "泰山区", + "370911": "岱岳区", + "370921": "宁阳县", + "370923": "东平县", + "370982": "新泰市", + "370983": "肥城市", + "371002": "环翠区", + "371003": "文登区", + "371071": "威海火炬高技术产业开发区", + "371072": "威海经济技术开发区", + "371082": "荣成市", + "371083": "乳山市", + "371091": "经济技术开发区", + "371102": "东港区", + "371103": "岚山区", + "371121": "五莲县", + "371122": "莒县", + "371171": "日照经济技术开发区", + "371302": "兰山区", + "371311": "罗庄区", + "371312": "河东区", + "371321": "沂南县", + "371322": "郯城县", + "371323": "沂水县", + "371324": "兰陵县", + "371325": "费县", + "371326": "平邑县", + "371327": "莒南县", + "371328": "蒙阴县", + "371329": "临沭县", + "371371": "临沂高新技术产业开发区", + "371402": "德城区", + "371403": "陵城区", + "371422": "宁津县", + "371423": "庆云县", + "371424": "临邑县", + "371425": "齐河县", + "371426": "平原县", + "371427": "夏津县", + "371428": "武城县", + "371472": "德州运河经济开发区", + "371481": "乐陵市", + "371482": "禹城市", + "371502": "东昌府区", + "371503": "茌平区", + "371521": "阳谷县", + "371522": "莘县", + "371524": "东阿县", + "371525": "冠县", + "371526": "高唐县", + "371581": "临清市", + "371602": "滨城区", + "371603": "沾化区", + "371621": "惠民县", + "371622": "阳信县", + "371623": "无棣县", + "371625": "博兴县", + "371681": "邹平市", + "371702": "牡丹区", + "371703": "定陶区", + "371721": "曹县", + "371722": "单县", + "371723": "成武县", + "371724": "巨野县", + "371725": "郓城县", + "371726": "鄄城县", + "371728": "东明县", + "371771": "菏泽经济技术开发区", + "371772": "菏泽高新技术开发区", + "410102": "中原区", + "410103": "二七区", + "410104": "管城回族区", + "410105": "金水区", + "410106": "上街区", + "410108": "惠济区", + "410122": "中牟县", + "410171": "郑州经济技术开发区", + "410172": "郑州高新技术产业开发区", + "410173": "郑州航空港经济综合实验区", + "410181": "巩义市", + "410182": "荥阳市", + "410183": "新密市", + "410184": "新郑市", + "410185": "登封市", + "410190": "高新技术开发区", + "410191": "经济技术开发区", + "410202": "龙亭区", + "410203": "顺河回族区", + "410204": "鼓楼区", + "410205": "禹王台区", + "410212": "祥符区", + "410221": "杞县", + "410222": "通许县", + "410223": "尉氏县", + "410225": "兰考县", + "410302": "老城区", + "410303": "西工区", + "410304": "瀍河回族区", + "410305": "涧西区", + "410307": "偃师区", + "410308": "孟津区", + "410311": "洛龙区", + "410323": "新安县", + "410324": "栾川县", + "410325": "嵩县", + "410326": "汝阳县", + "410327": "宜阳县", + "410328": "洛宁县", + "410329": "伊川县", + "410402": "新华区", + "410403": "卫东区", + "410404": "石龙区", + "410411": "湛河区", + "410421": "宝丰县", + "410422": "叶县", + "410423": "鲁山县", + "410425": "郏县", + "410471": "平顶山高新技术产业开发区", + "410481": "舞钢市", + "410482": "汝州市", + "410502": "文峰区", + "410503": "北关区", + "410505": "殷都区", + "410506": "龙安区", + "410522": "安阳县", + "410523": "汤阴县", + "410526": "滑县", + "410527": "内黄县", + "410581": "林州市", + "410590": "开发区", + "410602": "鹤山区", + "410603": "山城区", + "410611": "淇滨区", + "410621": "浚县", + "410622": "淇县", + "410702": "红旗区", + "410703": "卫滨区", + "410704": "凤泉区", + "410711": "牧野区", + "410721": "新乡县", + "410724": "获嘉县", + "410725": "原阳县", + "410726": "延津县", + "410727": "封丘县", + "410771": "新乡高新技术产业开发区", + "410772": "新乡经济技术开发区", + "410781": "卫辉市", + "410782": "辉县市", + "410783": "长垣市", + "410802": "解放区", + "410803": "中站区", + "410804": "马村区", + "410811": "山阳区", + "410821": "修武县", + "410822": "博爱县", + "410823": "武陟县", + "410825": "温县", + "410871": "焦作城乡一体化示范区", + "410882": "沁阳市", + "410883": "孟州市", + "410902": "华龙区", + "410922": "清丰县", + "410923": "南乐县", + "410926": "范县", + "410927": "台前县", + "410928": "濮阳县", + "410971": "河南濮阳工业园区", + "411002": "魏都区", + "411003": "建安区", + "411024": "鄢陵县", + "411025": "襄城县", + "411071": "许昌经济技术开发区", + "411081": "禹州市", + "411082": "长葛市", + "411102": "源汇区", + "411103": "郾城区", + "411104": "召陵区", + "411121": "舞阳县", + "411122": "临颍县", + "411171": "漯河经济技术开发区", + "411202": "湖滨区", + "411203": "陕州区", + "411221": "渑池县", + "411224": "卢氏县", + "411271": "河南三门峡经济开发区", + "411281": "义马市", + "411282": "灵宝市", + "411302": "宛城区", + "411303": "卧龙区", + "411321": "南召县", + "411322": "方城县", + "411323": "西峡县", + "411324": "镇平县", + "411325": "内乡县", + "411326": "淅川县", + "411327": "社旗县", + "411328": "唐河县", + "411329": "新野县", + "411330": "桐柏县", + "411372": "南阳市城乡一体化示范区", + "411381": "邓州市", + "411402": "梁园区", + "411403": "睢阳区", + "411421": "民权县", + "411422": "睢县", + "411423": "宁陵县", + "411424": "柘城县", + "411425": "虞城县", + "411426": "夏邑县", + "411481": "永城市", + "411502": "浉河区", + "411503": "平桥区", + "411521": "罗山县", + "411522": "光山县", + "411523": "新县", + "411524": "商城县", + "411525": "固始县", + "411526": "潢川县", + "411527": "淮滨县", + "411528": "息县", + "411602": "川汇区", + "411603": "淮阳区", + "411621": "扶沟县", + "411622": "西华县", + "411623": "商水县", + "411624": "沈丘县", + "411625": "郸城县", + "411627": "太康县", + "411628": "鹿邑县", + "411671": "河南周口经济开发区", + "411681": "项城市", + "411690": "经济开发区", + "411702": "驿城区", + "411721": "西平县", + "411722": "上蔡县", + "411723": "平舆县", + "411724": "正阳县", + "411725": "确山县", + "411726": "泌阳县", + "411727": "汝南县", + "411728": "遂平县", + "411729": "新蔡县", + "419001": "济源市", + "420102": "江岸区", + "420103": "江汉区", + "420104": "硚口区", + "420105": "汉阳区", + "420106": "武昌区", + "420107": "青山区", + "420111": "洪山区", + "420112": "东西湖区", + "420113": "汉南区", + "420114": "蔡甸区", + "420115": "江夏区", + "420116": "黄陂区", + "420117": "新洲区", + "420202": "黄石港区", + "420203": "西塞山区", + "420204": "下陆区", + "420205": "铁山区", + "420222": "阳新县", + "420281": "大冶市", + "420302": "茅箭区", + "420303": "张湾区", + "420304": "郧阳区", + "420322": "郧西县", + "420323": "竹山县", + "420324": "竹溪县", + "420325": "房县", + "420381": "丹江口市", + "420502": "西陵区", + "420503": "伍家岗区", + "420504": "点军区", + "420505": "猇亭区", + "420506": "夷陵区", + "420525": "远安县", + "420526": "兴山县", + "420527": "秭归县", + "420528": "长阳土家族自治县", + "420529": "五峰土家族自治县", + "420581": "宜都市", + "420582": "当阳市", + "420583": "枝江市", + "420590": "经济开发区", + "420602": "襄城区", + "420606": "樊城区", + "420607": "襄州区", + "420624": "南漳县", + "420625": "谷城县", + "420626": "保康县", + "420682": "老河口市", + "420683": "枣阳市", + "420684": "宜城市", + "420702": "梁子湖区", + "420703": "华容区", + "420704": "鄂城区", + "420802": "东宝区", + "420804": "掇刀区", + "420822": "沙洋县", + "420881": "钟祥市", + "420882": "京山市", + "420902": "孝南区", + "420921": "孝昌县", + "420922": "大悟县", + "420923": "云梦县", + "420981": "应城市", + "420982": "安陆市", + "420984": "汉川市", + "421002": "沙市区", + "421003": "荆州区", + "421022": "公安县", + "421024": "江陵县", + "421081": "石首市", + "421083": "洪湖市", + "421087": "松滋市", + "421088": "监利市", + "421102": "黄州区", + "421121": "团风县", + "421122": "红安县", + "421123": "罗田县", + "421124": "英山县", + "421125": "浠水县", + "421126": "蕲春县", + "421127": "黄梅县", + "421171": "龙感湖管理区", + "421181": "麻城市", + "421182": "武穴市", + "421202": "咸安区", + "421221": "嘉鱼县", + "421222": "通城县", + "421223": "崇阳县", + "421224": "通山县", + "421281": "赤壁市", + "421303": "曾都区", + "421321": "随县", + "421381": "广水市", + "422801": "恩施市", + "422802": "利川市", + "422822": "建始县", + "422823": "巴东县", + "422825": "宣恩县", + "422826": "咸丰县", + "422827": "来凤县", + "422828": "鹤峰县", + "429004": "仙桃市", + "429005": "潜江市", + "429006": "天门市", + "429021": "神农架林区", + "430102": "芙蓉区", + "430103": "天心区", + "430104": "岳麓区", + "430105": "开福区", + "430111": "雨花区", + "430112": "望城区", + "430121": "长沙县", + "430181": "浏阳市", + "430182": "宁乡市", + "430202": "荷塘区", + "430203": "芦淞区", + "430204": "石峰区", + "430211": "天元区", + "430212": "渌口区", + "430223": "攸县", + "430224": "茶陵县", + "430225": "炎陵县", + "430271": "云龙示范区", + "430281": "醴陵市", + "430302": "雨湖区", + "430304": "岳塘区", + "430321": "湘潭县", + "430373": "湘潭九华示范区", + "430381": "湘乡市", + "430382": "韶山市", + "430405": "珠晖区", + "430406": "雁峰区", + "430407": "石鼓区", + "430408": "蒸湘区", + "430412": "南岳区", + "430421": "衡阳县", + "430422": "衡南县", + "430423": "衡山县", + "430424": "衡东县", + "430426": "祁东县", + "430481": "耒阳市", + "430482": "常宁市", + "430502": "双清区", + "430503": "大祥区", + "430511": "北塔区", + "430522": "新邵县", + "430523": "邵阳县", + "430524": "隆回县", + "430525": "洞口县", + "430527": "绥宁县", + "430528": "新宁县", + "430529": "城步苗族自治县", + "430581": "武冈市", + "430582": "邵东市", + "430602": "岳阳楼区", + "430603": "云溪区", + "430611": "君山区", + "430621": "岳阳县", + "430623": "华容县", + "430624": "湘阴县", + "430626": "平江县", + "430681": "汨罗市", + "430682": "临湘市", + "430702": "武陵区", + "430703": "鼎城区", + "430721": "安乡县", + "430722": "汉寿县", + "430723": "澧县", + "430724": "临澧县", + "430725": "桃源县", + "430726": "石门县", + "430781": "津市市", + "430802": "永定区", + "430811": "武陵源区", + "430821": "慈利县", + "430822": "桑植县", + "430902": "资阳区", + "430903": "赫山区", + "430921": "南县", + "430922": "桃江县", + "430923": "安化县", + "430971": "益阳市大通湖管理区", + "430981": "沅江市", + "431002": "北湖区", + "431003": "苏仙区", + "431021": "桂阳县", + "431022": "宜章县", + "431023": "永兴县", + "431024": "嘉禾县", + "431025": "临武县", + "431026": "汝城县", + "431027": "桂东县", + "431028": "安仁县", + "431081": "资兴市", + "431102": "零陵区", + "431103": "冷水滩区", + "431122": "东安县", + "431123": "双牌县", + "431124": "道县", + "431125": "江永县", + "431126": "宁远县", + "431127": "蓝山县", + "431128": "新田县", + "431129": "江华瑶族自治县", + "431181": "祁阳市", + "431202": "鹤城区", + "431221": "中方县", + "431222": "沅陵县", + "431223": "辰溪县", + "431224": "溆浦县", + "431225": "会同县", + "431226": "麻阳苗族自治县", + "431227": "新晃侗族自治县", + "431228": "芷江侗族自治县", + "431229": "靖州苗族侗族自治县", + "431230": "通道侗族自治县", + "431271": "怀化市洪江管理区", + "431281": "洪江市", + "431302": "娄星区", + "431321": "双峰县", + "431322": "新化县", + "431381": "冷水江市", + "431382": "涟源市", + "433101": "吉首市", + "433122": "泸溪县", + "433123": "凤凰县", + "433124": "花垣县", + "433125": "保靖县", + "433126": "古丈县", + "433127": "永顺县", + "433130": "龙山县", + "440103": "荔湾区", + "440104": "越秀区", + "440105": "海珠区", + "440106": "天河区", + "440111": "白云区", + "440112": "黄埔区", + "440113": "番禺区", + "440114": "花都区", + "440115": "南沙区", + "440117": "从化区", + "440118": "增城区", + "440203": "武江区", + "440204": "浈江区", + "440205": "曲江区", + "440222": "始兴县", + "440224": "仁化县", + "440229": "翁源县", + "440232": "乳源瑶族自治县", + "440233": "新丰县", + "440281": "乐昌市", + "440282": "南雄市", + "440303": "罗湖区", + "440304": "福田区", + "440305": "南山区", + "440306": "宝安区", + "440307": "龙岗区", + "440308": "盐田区", + "440309": "龙华区", + "440310": "坪山区", + "440311": "光明区", + "440402": "香洲区", + "440403": "斗门区", + "440404": "金湾区", + "440507": "龙湖区", + "440511": "金平区", + "440512": "濠江区", + "440513": "潮阳区", + "440514": "潮南区", + "440515": "澄海区", + "440523": "南澳县", + "440604": "禅城区", + "440605": "南海区", + "440606": "顺德区", + "440607": "三水区", + "440608": "高明区", + "440703": "蓬江区", + "440704": "江海区", + "440705": "新会区", + "440781": "台山市", + "440783": "开平市", + "440784": "鹤山市", + "440785": "恩平市", + "440802": "赤坎区", + "440803": "霞山区", + "440804": "坡头区", + "440811": "麻章区", + "440823": "遂溪县", + "440825": "徐闻县", + "440881": "廉江市", + "440882": "雷州市", + "440883": "吴川市", + "440890": "经济技术开发区", + "440902": "茂南区", + "440904": "电白区", + "440981": "高州市", + "440982": "化州市", + "440983": "信宜市", + "441202": "端州区", + "441203": "鼎湖区", + "441204": "高要区", + "441223": "广宁县", + "441224": "怀集县", + "441225": "封开县", + "441226": "德庆县", + "441284": "四会市", + "441302": "惠城区", + "441303": "惠阳区", + "441322": "博罗县", + "441323": "惠东县", + "441324": "龙门县", + "441402": "梅江区", + "441403": "梅县区", + "441422": "大埔县", + "441423": "丰顺县", + "441424": "五华县", + "441426": "平远县", + "441427": "蕉岭县", + "441481": "兴宁市", + "441502": "城区", + "441521": "海丰县", + "441523": "陆河县", + "441581": "陆丰市", + "441602": "源城区", + "441621": "紫金县", + "441622": "龙川县", + "441623": "连平县", + "441624": "和平县", + "441625": "东源县", + "441702": "江城区", + "441704": "阳东区", + "441721": "阳西县", + "441781": "阳春市", + "441802": "清城区", + "441803": "清新区", + "441821": "佛冈县", + "441823": "阳山县", + "441825": "连山壮族瑶族自治县", + "441826": "连南瑶族自治县", + "441881": "英德市", + "441882": "连州市", + "441901": "中堂镇", + "441903": "南城街道", + "441904": "长安镇", + "441905": "东坑镇", + "441906": "樟木头镇", + "441907": "莞城街道", + "441908": "石龙镇", + "441909": "桥头镇", + "441910": "万江街道", + "441911": "麻涌镇", + "441912": "虎门镇", + "441913": "谢岗镇", + "441914": "石碣镇", + "441915": "茶山镇", + "441916": "东城街道", + "441917": "洪梅镇", + "441918": "道滘镇", + "441919": "高埗镇", + "441920": "企石镇", + "441921": "凤岗镇", + "441922": "大岭山镇", + "441923": "松山湖", + "441924": "清溪镇", + "441925": "望牛墩镇", + "441926": "厚街镇", + "441927": "常平镇", + "441928": "寮步镇", + "441929": "石排镇", + "441930": "横沥镇", + "441931": "塘厦镇", + "441932": "黄江镇", + "441933": "大朗镇", + "441934": "东莞港", + "441935": "东莞生态园", + "441990": "沙田镇", + "442001": "南头镇", + "442002": "神湾镇", + "442003": "东凤镇", + "442004": "五桂山街道", + "442005": "黄圃镇", + "442006": "小榄镇", + "442007": "石岐街道", + "442008": "横栏镇", + "442009": "三角镇", + "442010": "三乡镇", + "442011": "港口镇", + "442012": "沙溪镇", + "442013": "板芙镇", + "442015": "东升镇", + "442016": "阜沙镇", + "442017": "民众镇", + "442018": "东区街道", + "442019": "火炬开发区街道办事处", + "442020": "西区街道", + "442021": "南区街道", + "442022": "古镇镇", + "442023": "坦洲镇", + "442024": "大涌镇", + "442025": "南朗镇", + "445102": "湘桥区", + "445103": "潮安区", + "445122": "饶平县", + "445202": "榕城区", + "445203": "揭东区", + "445222": "揭西县", + "445224": "惠来县", + "445281": "普宁市", + "445302": "云城区", + "445303": "云安区", + "445321": "新兴县", + "445322": "郁南县", + "445381": "罗定市", + "450102": "兴宁区", + "450103": "青秀区", + "450105": "江南区", + "450107": "西乡塘区", + "450108": "良庆区", + "450109": "邕宁区", + "450110": "武鸣区", + "450123": "隆安县", + "450124": "马山县", + "450125": "上林县", + "450126": "宾阳县", + "450181": "横州市", + "450202": "城中区", + "450203": "鱼峰区", + "450204": "柳南区", + "450205": "柳北区", + "450206": "柳江区", + "450222": "柳城县", + "450223": "鹿寨县", + "450224": "融安县", + "450225": "融水苗族自治县", + "450226": "三江侗族自治县", + "450302": "秀峰区", + "450303": "叠彩区", + "450304": "象山区", + "450305": "七星区", + "450311": "雁山区", + "450312": "临桂区", + "450321": "阳朔县", + "450323": "灵川县", + "450324": "全州县", + "450325": "兴安县", + "450326": "永福县", + "450327": "灌阳县", + "450328": "龙胜各族自治县", + "450329": "资源县", + "450330": "平乐县", + "450332": "恭城瑶族自治县", + "450381": "荔浦市", + "450403": "万秀区", + "450405": "长洲区", + "450406": "龙圩区", + "450421": "苍梧县", + "450422": "藤县", + "450423": "蒙山县", + "450481": "岑溪市", + "450502": "海城区", + "450503": "银海区", + "450512": "铁山港区", + "450521": "合浦县", + "450602": "港口区", + "450603": "防城区", + "450621": "上思县", + "450681": "东兴市", + "450702": "钦南区", + "450703": "钦北区", + "450721": "灵山县", + "450722": "浦北县", + "450802": "港北区", + "450803": "港南区", + "450804": "覃塘区", + "450821": "平南县", + "450881": "桂平市", + "450902": "玉州区", + "450903": "福绵区", + "450921": "容县", + "450922": "陆川县", + "450923": "博白县", + "450924": "兴业县", + "450981": "北流市", + "451002": "右江区", + "451003": "田阳区", + "451022": "田东县", + "451024": "德保县", + "451026": "那坡县", + "451027": "凌云县", + "451028": "乐业县", + "451029": "田林县", + "451030": "西林县", + "451031": "隆林各族自治县", + "451081": "靖西市", + "451082": "平果市", + "451102": "八步区", + "451103": "平桂区", + "451121": "昭平县", + "451122": "钟山县", + "451123": "富川瑶族自治县", + "451202": "金城江区", + "451203": "宜州区", + "451221": "南丹县", + "451222": "天峨县", + "451223": "凤山县", + "451224": "东兰县", + "451225": "罗城仫佬族自治县", + "451226": "环江毛南族自治县", + "451227": "巴马瑶族自治县", + "451228": "都安瑶族自治县", + "451229": "大化瑶族自治县", + "451302": "兴宾区", + "451321": "忻城县", + "451322": "象州县", + "451323": "武宣县", + "451324": "金秀瑶族自治县", + "451381": "合山市", + "451402": "江州区", + "451421": "扶绥县", + "451422": "宁明县", + "451423": "龙州县", + "451424": "大新县", + "451425": "天等县", + "451481": "凭祥市", + "460105": "秀英区", + "460106": "龙华区", + "460107": "琼山区", + "460108": "美兰区", + "460202": "海棠区", + "460203": "吉阳区", + "460204": "天涯区", + "460205": "崖州区", + "460321": "西沙区", + "460322": "南沙区", + "460401": "那大镇", + "460402": "和庆镇", + "460403": "南丰镇", + "460404": "大成镇", + "460405": "雅星镇", + "460406": "兰洋镇", + "460407": "光村镇", + "460408": "木棠镇", + "460409": "海头镇", + "460410": "峨蔓镇", + "460411": "王五镇", + "460412": "白马井镇", + "460413": "中和镇", + "460414": "排浦镇", + "460415": "东成镇", + "460416": "新州镇", + "460417": "洋浦经济开发区", + "460418": "华南热作学院", + "469001": "五指山市", + "469002": "琼海市", + "469005": "文昌市", + "469006": "万宁市", + "469007": "东方市", + "469021": "定安县", + "469022": "屯昌县", + "469023": "澄迈县", + "469024": "临高县", + "469025": "白沙黎族自治县", + "469026": "昌江黎族自治县", + "469027": "乐东黎族自治县", + "469028": "陵水黎族自治县", + "469029": "保亭黎族苗族自治县", + "469030": "琼中黎族苗族自治县", + "500101": "万州区", + "500102": "涪陵区", + "500103": "渝中区", + "500104": "大渡口区", + "500105": "江北区", + "500106": "沙坪坝区", + "500107": "九龙坡区", + "500108": "南岸区", + "500109": "北碚区", + "500110": "綦江区", + "500111": "大足区", + "500112": "渝北区", + "500113": "巴南区", + "500114": "黔江区", + "500115": "长寿区", + "500116": "江津区", + "500117": "合川区", + "500118": "永川区", + "500119": "南川区", + "500120": "璧山区", + "500151": "铜梁区", + "500152": "潼南区", + "500153": "荣昌区", + "500154": "开州区", + "500155": "梁平区", + "500156": "武隆区", + "500229": "城口县", + "500230": "丰都县", + "500231": "垫江县", + "500233": "忠县", + "500235": "云阳县", + "500236": "奉节县", + "500237": "巫山县", + "500238": "巫溪县", + "500240": "石柱土家族自治县", + "500241": "秀山土家族苗族自治县", + "500242": "酉阳土家族苗族自治县", + "500243": "彭水苗族土家族自治县", + "510104": "锦江区", + "510105": "青羊区", + "510106": "金牛区", + "510107": "武侯区", + "510108": "成华区", + "510112": "龙泉驿区", + "510113": "青白江区", + "510114": "新都区", + "510115": "温江区", + "510116": "双流区", + "510117": "郫都区", + "510118": "新津区", + "510121": "金堂县", + "510129": "大邑县", + "510131": "蒲江县", + "510181": "都江堰市", + "510182": "彭州市", + "510183": "邛崃市", + "510184": "崇州市", + "510185": "简阳市", + "510191": "高新区", + "510302": "自流井区", + "510303": "贡井区", + "510304": "大安区", + "510311": "沿滩区", + "510321": "荣县", + "510322": "富顺县", + "510402": "东区", + "510403": "西区", + "510411": "仁和区", + "510421": "米易县", + "510422": "盐边县", + "510502": "江阳区", + "510503": "纳溪区", + "510504": "龙马潭区", + "510521": "泸县", + "510522": "合江县", + "510524": "叙永县", + "510525": "古蔺县", + "510603": "旌阳区", + "510604": "罗江区", + "510623": "中江县", + "510681": "广汉市", + "510682": "什邡市", + "510683": "绵竹市", + "510703": "涪城区", + "510704": "游仙区", + "510705": "安州区", + "510722": "三台县", + "510723": "盐亭县", + "510725": "梓潼县", + "510726": "北川羌族自治县", + "510727": "平武县", + "510781": "江油市", + "510791": "高新区", + "510802": "利州区", + "510811": "昭化区", + "510812": "朝天区", + "510821": "旺苍县", + "510822": "青川县", + "510823": "剑阁县", + "510824": "苍溪县", + "510903": "船山区", + "510904": "安居区", + "510921": "蓬溪县", + "510923": "大英县", + "510981": "射洪市", + "511002": "市中区", + "511011": "东兴区", + "511024": "威远县", + "511025": "资中县", + "511083": "隆昌市", + "511102": "市中区", + "511111": "沙湾区", + "511112": "五通桥区", + "511113": "金口河区", + "511123": "犍为县", + "511124": "井研县", + "511126": "夹江县", + "511129": "沐川县", + "511132": "峨边彝族自治县", + "511133": "马边彝族自治县", + "511181": "峨眉山市", + "511302": "顺庆区", + "511303": "高坪区", + "511304": "嘉陵区", + "511321": "南部县", + "511322": "营山县", + "511323": "蓬安县", + "511324": "仪陇县", + "511325": "西充县", + "511381": "阆中市", + "511402": "东坡区", + "511403": "彭山区", + "511421": "仁寿县", + "511423": "洪雅县", + "511424": "丹棱县", + "511425": "青神县", + "511502": "翠屏区", + "511503": "南溪区", + "511504": "叙州区", + "511523": "江安县", + "511524": "长宁县", + "511525": "高县", + "511526": "珙县", + "511527": "筠连县", + "511528": "兴文县", + "511529": "屏山县", + "511602": "广安区", + "511603": "前锋区", + "511621": "岳池县", + "511622": "武胜县", + "511623": "邻水县", + "511681": "华蓥市", + "511702": "通川区", + "511703": "达川区", + "511722": "宣汉县", + "511723": "开江县", + "511724": "大竹县", + "511725": "渠县", + "511781": "万源市", + "511802": "雨城区", + "511803": "名山区", + "511822": "荥经县", + "511823": "汉源县", + "511824": "石棉县", + "511825": "天全县", + "511826": "芦山县", + "511827": "宝兴县", + "511902": "巴州区", + "511903": "恩阳区", + "511921": "通江县", + "511922": "南江县", + "511923": "平昌县", + "511971": "巴中经济开发区", + "512002": "雁江区", + "512021": "安岳县", + "512022": "乐至县", + "513201": "马尔康市", + "513221": "汶川县", + "513222": "理县", + "513223": "茂县", + "513224": "松潘县", + "513225": "九寨沟县", + "513226": "金川县", + "513227": "小金县", + "513228": "黑水县", + "513230": "壤塘县", + "513231": "阿坝县", + "513232": "若尔盖县", + "513233": "红原县", + "513301": "康定市", + "513322": "泸定县", + "513323": "丹巴县", + "513324": "九龙县", + "513325": "雅江县", + "513326": "道孚县", + "513327": "炉霍县", + "513328": "甘孜县", + "513329": "新龙县", + "513330": "德格县", + "513331": "白玉县", + "513332": "石渠县", + "513333": "色达县", + "513334": "理塘县", + "513335": "巴塘县", + "513336": "乡城县", + "513337": "稻城县", + "513338": "得荣县", + "513401": "西昌市", + "513402": "会理市", + "513422": "木里藏族自治县", + "513423": "盐源县", + "513424": "德昌县", + "513426": "会东县", + "513427": "宁南县", + "513428": "普格县", + "513429": "布拖县", + "513430": "金阳县", + "513431": "昭觉县", + "513432": "喜德县", + "513433": "冕宁县", + "513434": "越西县", + "513435": "甘洛县", + "513436": "美姑县", + "513437": "雷波县", + "520102": "南明区", + "520103": "云岩区", + "520111": "花溪区", + "520112": "乌当区", + "520113": "白云区", + "520115": "观山湖区", + "520121": "开阳县", + "520122": "息烽县", + "520123": "修文县", + "520181": "清镇市", + "520201": "钟山区", + "520203": "六枝特区", + "520204": "水城区", + "520281": "盘州市", + "520302": "红花岗区", + "520303": "汇川区", + "520304": "播州区", + "520322": "桐梓县", + "520323": "绥阳县", + "520324": "正安县", + "520325": "道真仡佬族苗族自治县", + "520326": "务川仡佬族苗族自治县", + "520327": "凤冈县", + "520328": "湄潭县", + "520329": "余庆县", + "520330": "习水县", + "520381": "赤水市", + "520382": "仁怀市", + "520402": "西秀区", + "520403": "平坝区", + "520422": "普定县", + "520423": "镇宁布依族苗族自治县", + "520424": "关岭布依族苗族自治县", + "520425": "紫云苗族布依族自治县", + "520502": "七星关区", + "520521": "大方县", + "520523": "金沙县", + "520524": "织金县", + "520525": "纳雍县", + "520526": "威宁彝族回族苗族自治县", + "520527": "赫章县", + "520581": "黔西市", + "520602": "碧江区", + "520603": "万山区", + "520621": "江口县", + "520622": "玉屏侗族自治县", + "520623": "石阡县", + "520624": "思南县", + "520625": "印江土家族苗族自治县", + "520626": "德江县", + "520627": "沿河土家族自治县", + "520628": "松桃苗族自治县", + "522301": "兴义市", + "522302": "兴仁市", + "522323": "普安县", + "522324": "晴隆县", + "522325": "贞丰县", + "522326": "望谟县", + "522327": "册亨县", + "522328": "安龙县", + "522601": "凯里市", + "522622": "黄平县", + "522623": "施秉县", + "522624": "三穗县", + "522625": "镇远县", + "522626": "岑巩县", + "522627": "天柱县", + "522628": "锦屏县", + "522629": "剑河县", + "522630": "台江县", + "522631": "黎平县", + "522632": "榕江县", + "522633": "从江县", + "522634": "雷山县", + "522635": "麻江县", + "522636": "丹寨县", + "522701": "都匀市", + "522702": "福泉市", + "522722": "荔波县", + "522723": "贵定县", + "522725": "瓮安县", + "522726": "独山县", + "522727": "平塘县", + "522728": "罗甸县", + "522729": "长顺县", + "522730": "龙里县", + "522731": "惠水县", + "522732": "三都水族自治县", + "530102": "五华区", + "530103": "盘龙区", + "530111": "官渡区", + "530112": "西山区", + "530113": "东川区", + "530114": "呈贡区", + "530115": "晋宁区", + "530124": "富民县", + "530125": "宜良县", + "530126": "石林彝族自治县", + "530127": "嵩明县", + "530128": "禄劝彝族苗族自治县", + "530129": "寻甸回族彝族自治县", + "530181": "安宁市", + "530302": "麒麟区", + "530303": "沾益区", + "530304": "马龙区", + "530322": "陆良县", + "530323": "师宗县", + "530324": "罗平县", + "530325": "富源县", + "530326": "会泽县", + "530381": "宣威市", + "530402": "红塔区", + "530403": "江川区", + "530423": "通海县", + "530424": "华宁县", + "530425": "易门县", + "530426": "峨山彝族自治县", + "530427": "新平彝族傣族自治县", + "530428": "元江哈尼族彝族傣族自治县", + "530481": "澄江市", + "530502": "隆阳区", + "530521": "施甸县", + "530523": "龙陵县", + "530524": "昌宁县", + "530581": "腾冲市", + "530602": "昭阳区", + "530621": "鲁甸县", + "530622": "巧家县", + "530623": "盐津县", + "530624": "大关县", + "530625": "永善县", + "530626": "绥江县", + "530627": "镇雄县", + "530628": "彝良县", + "530629": "威信县", + "530681": "水富市", + "530702": "古城区", + "530721": "玉龙纳西族自治县", + "530722": "永胜县", + "530723": "华坪县", + "530724": "宁蒗彝族自治县", + "530802": "思茅区", + "530821": "宁洱哈尼族彝族自治县", + "530822": "墨江哈尼族自治县", + "530823": "景东彝族自治县", + "530824": "景谷傣族彝族自治县", + "530825": "镇沅彝族哈尼族拉祜族自治县", + "530826": "江城哈尼族彝族自治县", + "530827": "孟连傣族拉祜族佤族自治县", + "530828": "澜沧拉祜族自治县", + "530829": "西盟佤族自治县", + "530902": "临翔区", + "530921": "凤庆县", + "530922": "云县", + "530923": "永德县", + "530924": "镇康县", + "530925": "双江拉祜族佤族布朗族傣族自治县", + "530926": "耿马傣族佤族自治县", + "530927": "沧源佤族自治县", + "532301": "楚雄市", + "532302": "禄丰市", + "532322": "双柏县", + "532323": "牟定县", + "532324": "南华县", + "532325": "姚安县", + "532326": "大姚县", + "532327": "永仁县", + "532328": "元谋县", + "532329": "武定县", + "532501": "个旧市", + "532502": "开远市", + "532503": "蒙自市", + "532504": "弥勒市", + "532523": "屏边苗族自治县", + "532524": "建水县", + "532525": "石屏县", + "532527": "泸西县", + "532528": "元阳县", + "532529": "红河县", + "532530": "金平苗族瑶族傣族自治县", + "532531": "绿春县", + "532532": "河口瑶族自治县", + "532601": "文山市", + "532622": "砚山县", + "532623": "西畴县", + "532624": "麻栗坡县", + "532625": "马关县", + "532626": "丘北县", + "532627": "广南县", + "532628": "富宁县", + "532801": "景洪市", + "532822": "勐海县", + "532823": "勐腊县", + "532901": "大理市", + "532922": "漾濞彝族自治县", + "532923": "祥云县", + "532924": "宾川县", + "532925": "弥渡县", + "532926": "南涧彝族自治县", + "532927": "巍山彝族回族自治县", + "532928": "永平县", + "532929": "云龙县", + "532930": "洱源县", + "532931": "剑川县", + "532932": "鹤庆县", + "533102": "瑞丽市", + "533103": "芒市", + "533122": "梁河县", + "533123": "盈江县", + "533124": "陇川县", + "533301": "泸水市", + "533323": "福贡县", + "533324": "贡山独龙族怒族自治县", + "533325": "兰坪白族普米族自治县", + "533401": "香格里拉市", + "533422": "德钦县", + "533423": "维西傈僳族自治县", + "540102": "城关区", + "540103": "堆龙德庆区", + "540104": "达孜区", + "540121": "林周县", + "540122": "当雄县", + "540123": "尼木县", + "540124": "曲水县", + "540127": "墨竹工卡县", + "540202": "桑珠孜区", + "540221": "南木林县", + "540222": "江孜县", + "540223": "定日县", + "540224": "萨迦县", + "540225": "拉孜县", + "540226": "昂仁县", + "540227": "谢通门县", + "540228": "白朗县", + "540229": "仁布县", + "540230": "康马县", + "540231": "定结县", + "540232": "仲巴县", + "540233": "亚东县", + "540234": "吉隆县", + "540235": "聂拉木县", + "540236": "萨嘎县", + "540237": "岗巴县", + "540302": "卡若区", + "540321": "江达县", + "540322": "贡觉县", + "540323": "类乌齐县", + "540324": "丁青县", + "540325": "察雅县", + "540326": "八宿县", + "540327": "左贡县", + "540328": "芒康县", + "540329": "洛隆县", + "540330": "边坝县", + "540402": "巴宜区", + "540421": "工布江达县", + "540423": "墨脱县", + "540424": "波密县", + "540425": "察隅县", + "540426": "朗县", + "540481": "米林市", + "540502": "乃东区", + "540521": "扎囊县", + "540522": "贡嘎县", + "540523": "桑日县", + "540524": "琼结县", + "540525": "曲松县", + "540526": "措美县", + "540527": "洛扎县", + "540528": "加查县", + "540529": "隆子县", + "540531": "浪卡子县", + "540581": "错那市", + "540602": "色尼区", + "540621": "嘉黎县", + "540622": "比如县", + "540623": "聂荣县", + "540624": "安多县", + "540625": "申扎县", + "540626": "索县", + "540627": "班戈县", + "540628": "巴青县", + "540629": "尼玛县", + "540630": "双湖县", + "542521": "普兰县", + "542522": "札达县", + "542523": "噶尔县", + "542524": "日土县", + "542525": "革吉县", + "542526": "改则县", + "542527": "措勤县", + "610102": "新城区", + "610103": "碑林区", + "610104": "莲湖区", + "610111": "灞桥区", + "610112": "未央区", + "610113": "雁塔区", + "610114": "阎良区", + "610115": "临潼区", + "610116": "长安区", + "610117": "高陵区", + "610118": "鄠邑区", + "610122": "蓝田县", + "610124": "周至县", + "610202": "王益区", + "610203": "印台区", + "610204": "耀州区", + "610222": "宜君县", + "610302": "渭滨区", + "610303": "金台区", + "610304": "陈仓区", + "610305": "凤翔区", + "610323": "岐山县", + "610324": "扶风县", + "610326": "眉县", + "610327": "陇县", + "610328": "千阳县", + "610329": "麟游县", + "610330": "凤县", + "610331": "太白县", + "610402": "秦都区", + "610403": "杨陵区", + "610404": "渭城区", + "610422": "三原县", + "610423": "泾阳县", + "610424": "乾县", + "610425": "礼泉县", + "610426": "永寿县", + "610428": "长武县", + "610429": "旬邑县", + "610430": "淳化县", + "610431": "武功县", + "610481": "兴平市", + "610482": "彬州市", + "610502": "临渭区", + "610503": "华州区", + "610522": "潼关县", + "610523": "大荔县", + "610524": "合阳县", + "610525": "澄城县", + "610526": "蒲城县", + "610527": "白水县", + "610528": "富平县", + "610581": "韩城市", + "610582": "华阴市", + "610602": "宝塔区", + "610603": "安塞区", + "610621": "延长县", + "610622": "延川县", + "610625": "志丹县", + "610626": "吴起县", + "610627": "甘泉县", + "610628": "富县", + "610629": "洛川县", + "610630": "宜川县", + "610631": "黄龙县", + "610632": "黄陵县", + "610681": "子长市", + "610702": "汉台区", + "610703": "南郑区", + "610722": "城固县", + "610723": "洋县", + "610724": "西乡县", + "610725": "勉县", + "610726": "宁强县", + "610727": "略阳县", + "610728": "镇巴县", + "610729": "留坝县", + "610730": "佛坪县", + "610802": "榆阳区", + "610803": "横山区", + "610822": "府谷县", + "610824": "靖边县", + "610825": "定边县", + "610826": "绥德县", + "610827": "米脂县", + "610828": "佳县", + "610829": "吴堡县", + "610830": "清涧县", + "610831": "子洲县", + "610881": "神木市", + "610902": "汉滨区", + "610921": "汉阴县", + "610922": "石泉县", + "610923": "宁陕县", + "610924": "紫阳县", + "610925": "岚皋县", + "610926": "平利县", + "610927": "镇坪县", + "610929": "白河县", + "610981": "旬阳市", + "611002": "商州区", + "611021": "洛南县", + "611022": "丹凤县", + "611023": "商南县", + "611024": "山阳县", + "611025": "镇安县", + "611026": "柞水县", + "620102": "城关区", + "620103": "七里河区", + "620104": "西固区", + "620105": "安宁区", + "620111": "红古区", + "620121": "永登县", + "620122": "皋兰县", + "620123": "榆中县", + "620171": "兰州新区", + "620201": "市辖区", + "620290": "雄关区", + "620291": "长城区", + "620292": "镜铁区", + "620293": "新城镇", + "620294": "峪泉镇", + "620295": "文殊镇", + "620302": "金川区", + "620321": "永昌县", + "620402": "白银区", + "620403": "平川区", + "620421": "靖远县", + "620422": "会宁县", + "620423": "景泰县", + "620502": "秦州区", + "620503": "麦积区", + "620521": "清水县", + "620522": "秦安县", + "620523": "甘谷县", + "620524": "武山县", + "620525": "张家川回族自治县", + "620602": "凉州区", + "620621": "民勤县", + "620622": "古浪县", + "620623": "天祝藏族自治县", + "620702": "甘州区", + "620721": "肃南裕固族自治县", + "620722": "民乐县", + "620723": "临泽县", + "620724": "高台县", + "620725": "山丹县", + "620802": "崆峒区", + "620821": "泾川县", + "620822": "灵台县", + "620823": "崇信县", + "620825": "庄浪县", + "620826": "静宁县", + "620881": "华亭市", + "620902": "肃州区", + "620921": "金塔县", + "620922": "瓜州县", + "620923": "肃北蒙古族自治县", + "620924": "阿克塞哈萨克族自治县", + "620981": "玉门市", + "620982": "敦煌市", + "621002": "西峰区", + "621021": "庆城县", + "621022": "环县", + "621023": "华池县", + "621024": "合水县", + "621025": "正宁县", + "621026": "宁县", + "621027": "镇原县", + "621102": "安定区", + "621121": "通渭县", + "621122": "陇西县", + "621123": "渭源县", + "621124": "临洮县", + "621125": "漳县", + "621126": "岷县", + "621202": "武都区", + "621221": "成县", + "621222": "文县", + "621223": "宕昌县", + "621224": "康县", + "621225": "西和县", + "621226": "礼县", + "621227": "徽县", + "621228": "两当县", + "622901": "临夏市", + "622921": "临夏县", + "622922": "康乐县", + "622923": "永靖县", + "622924": "广河县", + "622925": "和政县", + "622926": "东乡族自治县", + "622927": "积石山保安族东乡族撒拉族自治县", + "623001": "合作市", + "623021": "临潭县", + "623022": "卓尼县", + "623023": "舟曲县", + "623024": "迭部县", + "623025": "玛曲县", + "623026": "碌曲县", + "623027": "夏河县", + "630102": "城东区", + "630103": "城中区", + "630104": "城西区", + "630105": "城北区", + "630106": "湟中区", + "630121": "大通回族土族自治县", + "630123": "湟源县", + "630202": "乐都区", + "630203": "平安区", + "630222": "民和回族土族自治县", + "630223": "互助土族自治县", + "630224": "化隆回族自治县", + "630225": "循化撒拉族自治县", + "632221": "门源回族自治县", + "632222": "祁连县", + "632223": "海晏县", + "632224": "刚察县", + "632301": "同仁市", + "632322": "尖扎县", + "632323": "泽库县", + "632324": "河南蒙古族自治县", + "632521": "共和县", + "632522": "同德县", + "632523": "贵德县", + "632524": "兴海县", + "632525": "贵南县", + "632621": "玛沁县", + "632622": "班玛县", + "632623": "甘德县", + "632624": "达日县", + "632625": "久治县", + "632626": "玛多县", + "632701": "玉树市", + "632722": "杂多县", + "632723": "称多县", + "632724": "治多县", + "632725": "囊谦县", + "632726": "曲麻莱县", + "632801": "格尔木市", + "632802": "德令哈市", + "632803": "茫崖市", + "632821": "乌兰县", + "632822": "都兰县", + "632823": "天峻县", + "632857": "大柴旦行政委员会", + "640104": "兴庆区", + "640105": "西夏区", + "640106": "金凤区", + "640121": "永宁县", + "640122": "贺兰县", + "640181": "灵武市", + "640202": "大武口区", + "640205": "惠农区", + "640221": "平罗县", + "640302": "利通区", + "640303": "红寺堡区", + "640323": "盐池县", + "640324": "同心县", + "640381": "青铜峡市", + "640402": "原州区", + "640422": "西吉县", + "640423": "隆德县", + "640424": "泾源县", + "640425": "彭阳县", + "640502": "沙坡头区", + "640521": "中宁县", + "640522": "海原县", + "650102": "天山区", + "650103": "沙依巴克区", + "650104": "新市区", + "650105": "水磨沟区", + "650106": "头屯河区", + "650107": "达坂城区", + "650109": "米东区", + "650121": "乌鲁木齐县", + "650202": "独山子区", + "650203": "克拉玛依区", + "650204": "白碱滩区", + "650205": "乌尔禾区", + "650402": "高昌区", + "650421": "鄯善县", + "650422": "托克逊县", + "650502": "伊州区", + "650521": "巴里坤哈萨克自治县", + "650522": "伊吾县", + "652301": "昌吉市", + "652302": "阜康市", + "652323": "呼图壁县", + "652324": "玛纳斯县", + "652325": "奇台县", + "652327": "吉木萨尔县", + "652328": "木垒哈萨克自治县", + "652701": "博乐市", + "652702": "阿拉山口市", + "652722": "精河县", + "652723": "温泉县", + "652801": "库尔勒市", + "652822": "轮台县", + "652823": "尉犁县", + "652824": "若羌县", + "652825": "且末县", + "652826": "焉耆回族自治县", + "652827": "和静县", + "652828": "和硕县", + "652829": "博湖县", + "652901": "阿克苏市", + "652902": "库车市", + "652922": "温宿县", + "652924": "沙雅县", + "652925": "新和县", + "652926": "拜城县", + "652927": "乌什县", + "652928": "阿瓦提县", + "652929": "柯坪县", + "653001": "阿图什市", + "653022": "阿克陶县", + "653023": "阿合奇县", + "653024": "乌恰县", + "653101": "喀什市", + "653121": "疏附县", + "653122": "疏勒县", + "653123": "英吉沙县", + "653124": "泽普县", + "653125": "莎车县", + "653126": "叶城县", + "653127": "麦盖提县", + "653128": "岳普湖县", + "653129": "伽师县", + "653130": "巴楚县", + "653131": "塔什库尔干塔吉克自治县", + "653201": "和田市", + "653221": "和田县", + "653222": "墨玉县", + "653223": "皮山县", + "653224": "洛浦县", + "653225": "策勒县", + "653226": "于田县", + "653227": "民丰县", + "654002": "伊宁市", + "654003": "奎屯市", + "654004": "霍尔果斯市", + "654021": "伊宁县", + "654022": "察布查尔锡伯自治县", + "654023": "霍城县", + "654024": "巩留县", + "654025": "新源县", + "654026": "昭苏县", + "654027": "特克斯县", + "654028": "尼勒克县", + "654201": "塔城市", + "654202": "乌苏市", + "654203": "沙湾市", + "654221": "额敏县", + "654224": "托里县", + "654225": "裕民县", + "654226": "和布克赛尔蒙古自治县", + "654301": "阿勒泰市", + "654321": "布尔津县", + "654322": "富蕴县", + "654323": "福海县", + "654324": "哈巴河县", + "654325": "青河县", + "654326": "吉木乃县", + "659001": "石河子市", + "659002": "阿拉尔市", + "659003": "图木舒克市", + "659004": "五家渠市", + "659005": "北屯市", + "659006": "铁门关市", + "659007": "双河市", + "659008": "可克达拉市", + "659009": "昆玉市", + "659010": "胡杨河市", + "659011": "新星市", + "659012": "白杨市", + "710101": "中正区", + "710102": "大同区", + "710103": "中山区", + "710104": "松山区", + "710105": "大安区", + "710106": "万华区", + "710107": "信义区", + "710108": "士林区", + "710109": "北投区", + "710110": "内湖区", + "710111": "南港区", + "710112": "文山区", + "710199": "其它区", + "710201": "新兴区", + "710202": "前金区", + "710203": "芩雅区", + "710204": "盐埕区", + "710205": "鼓山区", + "710206": "旗津区", + "710207": "前镇区", + "710208": "三民区", + "710209": "左营区", + "710210": "楠梓区", + "710211": "小港区", + "710241": "苓雅区", + "710242": "仁武区", + "710243": "大社区", + "710244": "冈山区", + "710245": "路竹区", + "710246": "阿莲区", + "710247": "田寮区", + "710248": "燕巢区", + "710249": "桥头区", + "710250": "梓官区", + "710251": "弥陀区", + "710252": "永安区", + "710253": "湖内区", + "710254": "凤山区", + "710255": "大寮区", + "710256": "林园区", + "710257": "鸟松区", + "710258": "大树区", + "710259": "旗山区", + "710260": "美浓区", + "710261": "六龟区", + "710262": "内门区", + "710263": "杉林区", + "710264": "甲仙区", + "710265": "桃源区", + "710266": "那玛夏区", + "710267": "茂林区", + "710268": "茄萣区", + "710299": "其它区", + "710301": "中西区", + "710302": "东区", + "710303": "南区", + "710304": "北区", + "710305": "安平区", + "710306": "安南区", + "710339": "永康区", + "710340": "归仁区", + "710341": "新化区", + "710342": "左镇区", + "710343": "玉井区", + "710344": "楠西区", + "710345": "南化区", + "710346": "仁德区", + "710347": "关庙区", + "710348": "龙崎区", + "710349": "官田区", + "710350": "麻豆区", + "710351": "佳里区", + "710352": "西港区", + "710353": "七股区", + "710354": "将军区", + "710355": "学甲区", + "710356": "北门区", + "710357": "新营区", + "710358": "后壁区", + "710359": "白河区", + "710360": "东山区", + "710361": "六甲区", + "710362": "下营区", + "710363": "柳营区", + "710364": "盐水区", + "710365": "善化区", + "710366": "大内区", + "710367": "山上区", + "710368": "新市区", + "710369": "安定区", + "710399": "其它区", + "710401": "中区", + "710402": "东区", + "710403": "南区", + "710404": "西区", + "710405": "北区", + "710406": "北屯区", + "710407": "西屯区", + "710408": "南屯区", + "710431": "太平区", + "710432": "大里区", + "710433": "雾峰区", + "710434": "乌日区", + "710435": "丰原区", + "710436": "后里区", + "710437": "石冈区", + "710438": "东势区", + "710439": "和平区", + "710440": "新社区", + "710441": "潭子区", + "710442": "大雅区", + "710443": "神冈区", + "710444": "大肚区", + "710445": "沙鹿区", + "710446": "龙井区", + "710447": "梧栖区", + "710448": "清水区", + "710449": "大甲区", + "710450": "外埔区", + "710451": "大安区", + "710499": "其它区", + "710507": "金沙镇", + "710508": "金湖镇", + "710509": "金宁乡", + "710510": "金城镇", + "710511": "烈屿乡", + "710512": "乌坵乡", + "710614": "南投市", + "710615": "中寮乡", + "710616": "草屯镇", + "710617": "国姓乡", + "710618": "埔里镇", + "710619": "仁爱乡", + "710620": "名间乡", + "710621": "集集镇", + "710622": "水里乡", + "710623": "鱼池乡", + "710624": "信义乡", + "710625": "竹山镇", + "710626": "鹿谷乡", + "710701": "仁爱区", + "710702": "信义区", + "710703": "中正区", + "710704": "中山区", + "710705": "安乐区", + "710706": "暖暖区", + "710707": "七堵区", + "710799": "其它区", + "710801": "东区", + "710802": "北区", + "710803": "香山区", + "710899": "其它区", + "710901": "东区", + "710902": "西区", + "710999": "其它区", + "711130": "万里区", + "711132": "板桥区", + "711133": "汐止区", + "711134": "深坑区", + "711135": "石碇区", + "711136": "瑞芳区", + "711137": "平溪区", + "711138": "双溪区", + "711139": "贡寮区", + "711140": "新店区", + "711141": "坪林区", + "711142": "乌来区", + "711143": "永和区", + "711144": "中和区", + "711145": "土城区", + "711146": "三峡区", + "711147": "树林区", + "711148": "莺歌区", + "711149": "三重区", + "711150": "新庄区", + "711151": "泰山区", + "711152": "林口区", + "711153": "芦洲区", + "711154": "五股区", + "711155": "八里区", + "711156": "淡水区", + "711157": "三芝区", + "711158": "石门区", + "711287": "宜兰市", + "711288": "头城镇", + "711289": "礁溪乡", + "711290": "壮围乡", + "711291": "员山乡", + "711292": "罗东镇", + "711293": "三星乡", + "711294": "大同乡", + "711295": "五结乡", + "711296": "冬山乡", + "711297": "苏澳镇", + "711298": "南澳乡", + "711299": "钓鱼台", + "711387": "竹北市", + "711388": "湖口乡", + "711389": "新丰乡", + "711390": "新埔镇", + "711391": "关西镇", + "711392": "芎林乡", + "711393": "宝山乡", + "711394": "竹东镇", + "711395": "五峰乡", + "711396": "横山乡", + "711397": "尖石乡", + "711398": "北埔乡", + "711399": "峨眉乡", + "711414": "中坜区", + "711415": "平镇区", + "711417": "杨梅区", + "711418": "新屋区", + "711419": "观音区", + "711420": "桃园区", + "711421": "龟山区", + "711422": "八德区", + "711423": "大溪区", + "711425": "大园区", + "711426": "芦竹区", + "711487": "中坜市", + "711488": "平镇市", + "711489": "龙潭乡", + "711490": "杨梅市", + "711491": "新屋乡", + "711492": "观音乡", + "711493": "桃园市", + "711494": "龟山乡", + "711495": "八德市", + "711496": "大溪镇", + "711497": "复兴乡", + "711498": "大园乡", + "711499": "芦竹乡", + "711520": "头份市", + "711582": "竹南镇", + "711583": "头份镇", + "711584": "三湾乡", + "711585": "南庄乡", + "711586": "狮潭乡", + "711587": "后龙镇", + "711588": "通霄镇", + "711589": "苑里镇", + "711590": "苗栗市", + "711591": "造桥乡", + "711592": "头屋乡", + "711593": "公馆乡", + "711594": "大湖乡", + "711595": "泰安乡", + "711596": "铜锣乡", + "711597": "三义乡", + "711598": "西湖乡", + "711599": "卓兰镇", + "711736": "员林市", + "711774": "彰化市", + "711775": "芬园乡", + "711776": "花坛乡", + "711777": "秀水乡", + "711778": "鹿港镇", + "711779": "福兴乡", + "711780": "线西乡", + "711781": "和美镇", + "711782": "伸港乡", + "711783": "员林镇", + "711784": "社头乡", + "711785": "永靖乡", + "711786": "埔心乡", + "711787": "溪湖镇", + "711788": "大村乡", + "711789": "埔盐乡", + "711790": "田中镇", + "711791": "北斗镇", + "711792": "田尾乡", + "711793": "埤头乡", + "711794": "溪州乡", + "711795": "竹塘乡", + "711796": "二林镇", + "711797": "大城乡", + "711798": "芳苑乡", + "711799": "二水乡", + "711982": "番路乡", + "711983": "梅山乡", + "711984": "竹崎乡", + "711985": "阿里山乡", + "711986": "中埔乡", + "711987": "大埔乡", + "711988": "水上乡", + "711989": "鹿草乡", + "711990": "太保市", + "711991": "朴子市", + "711992": "东石乡", + "711993": "六脚乡", + "711994": "新港乡", + "711995": "民雄乡", + "711996": "大林镇", + "711997": "溪口乡", + "711998": "义竹乡", + "711999": "布袋镇", + "712180": "斗南镇", + "712181": "大埤乡", + "712182": "虎尾镇", + "712183": "土库镇", + "712184": "褒忠乡", + "712185": "东势乡", + "712186": "台西乡", + "712187": "仑背乡", + "712188": "麦寮乡", + "712189": "斗六市", + "712190": "林内乡", + "712191": "古坑乡", + "712192": "莿桐乡", + "712193": "西螺镇", + "712194": "二仑乡", + "712195": "北港镇", + "712196": "水林乡", + "712197": "口湖乡", + "712198": "四湖乡", + "712199": "元长乡", + "712451": "崁顶乡", + "712467": "屏东市", + "712468": "三地门乡", + "712469": "雾台乡", + "712470": "玛家乡", + "712471": "九如乡", + "712472": "里港乡", + "712473": "高树乡", + "712474": "盐埔乡", + "712475": "长治乡", + "712476": "麟洛乡", + "712477": "竹田乡", + "712478": "内埔乡", + "712479": "万丹乡", + "712480": "潮州镇", + "712481": "泰武乡", + "712482": "来义乡", + "712483": "万峦乡", + "712484": "莰顶乡", + "712485": "新埤乡", + "712486": "南州乡", + "712487": "林边乡", + "712488": "东港镇", + "712489": "琉球乡", + "712490": "佳冬乡", + "712491": "新园乡", + "712492": "枋寮乡", + "712493": "枋山乡", + "712494": "春日乡", + "712495": "狮子乡", + "712496": "车城乡", + "712497": "牡丹乡", + "712498": "恒春镇", + "712499": "满州乡", + "712584": "台东市", + "712585": "绿岛乡", + "712586": "兰屿乡", + "712587": "延平乡", + "712588": "卑南乡", + "712589": "鹿野乡", + "712590": "关山镇", + "712591": "海端乡", + "712592": "池上乡", + "712593": "东河乡", + "712594": "成功镇", + "712595": "长滨乡", + "712596": "金峰乡", + "712597": "大武乡", + "712598": "达仁乡", + "712599": "太麻里乡", + "712686": "花莲市", + "712687": "新城乡", + "712688": "太鲁阁", + "712689": "秀林乡", + "712690": "吉安乡", + "712691": "寿丰乡", + "712692": "凤林镇", + "712693": "光复乡", + "712694": "丰滨乡", + "712695": "瑞穗乡", + "712696": "万荣乡", + "712697": "玉里镇", + "712698": "卓溪乡", + "712699": "富里乡", + "712794": "马公市", + "712795": "西屿乡", + "712796": "望安乡", + "712797": "七美乡", + "712798": "白沙乡", + "712799": "湖西乡", + "712896": "南竿乡", + "712897": "北竿乡", + "712898": "东引乡", + "712899": "莒光乡", + "810101": "中西区", + "810102": "湾仔区", + "810103": "东区", + "810104": "南区", + "810201": "九龙城区", + "810202": "油尖旺区", + "810203": "深水埗区", + "810204": "黄大仙区", + "810205": "观塘区", + "810301": "北区", + "810302": "大埔区", + "810303": "沙田区", + "810304": "西贡区", + "810305": "元朗区", + "810306": "屯门区", + "810307": "荃湾区", + "810308": "葵青区", + "810309": "离岛区", + "820102": "花地玛堂区", + "820103": "花王堂区", + "820104": "望德堂区", + "820105": "大堂区", + "820106": "风顺堂区", + "820202": "嘉模堂区", + "820203": "路氹填海区", + "820204": "圣方济各堂区" + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/areaData/index.ts b/QXTfront/uni_modules/lime-shared/areaData/index.ts new file mode 100644 index 0000000..401f77f --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/areaData/index.ts @@ -0,0 +1,71 @@ +// @ts-nocheck +import _areaList from './city-china.json'; +export const areaList = _areaList +// #ifndef UNI-APP-X +type UTSJSONObject = Record +// #endif +// #ifdef UNI-APP-X +type Object = UTSJSONObject +// #endif +type AreaList = { + province_list : Map; + city_list : Map; + county_list : Map; +} +// type CascaderOption = { +// text : string; +// value : string; +// children ?: CascaderOption[]; +// }; + +const makeOption = ( + label : string, + value : string, + children ?: UTSJSONObject[], +) : UTSJSONObject => ({ + label, + value, + children, +}); + + + +export function useCascaderAreaData() : UTSJSONObject[] { + const city = areaList['city_list'] as UTSJSONObject + const county = areaList['county_list'] as UTSJSONObject + const province = areaList['province_list'] as UTSJSONObject + const provinceMap = new Map(); + Object.keys(province).forEach((code) => { + provinceMap.set(code.slice(0, 2), makeOption(`${province[code]}`, code, [])); + }); + + const cityMap = new Map(); + + Object.keys(city).forEach((code) => { + const option = makeOption(`${city[code]}`, code, []); + cityMap.set(code.slice(0, 4), option); + + const _province = provinceMap.get(code.slice(0, 2)); + if (_province != null) { + (_province['children'] as UTSJSONObject[]).push(option) + } + }); + + Object.keys(county).forEach((code) => { + const _city = cityMap.get(code.slice(0, 4)); + if (_city != null) { + (_city['children'] as UTSJSONObject[]).push(makeOption(`${county[code]}`, code, null)); + } + }); + + // #ifndef APP-ANDROID || APP-IOS + return Array.from(provinceMap.values()); + // #endif + // #ifdef APP-ANDROID || APP-IOS + const obj : UTSJSONObject[] = [] + provinceMap.forEach((value, code) => { + obj.push(value) + }) + return obj + // #endif +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/arrayBufferToFile/index.ts b/QXTfront/uni_modules/lime-shared/arrayBufferToFile/index.ts new file mode 100644 index 0000000..037c7ff --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/arrayBufferToFile/index.ts @@ -0,0 +1,10 @@ +// @ts-nocheck +// #ifndef UNI-APP-X && APP +// export * from './vue.ts' +export { arrayBufferToFile } from './vue.ts' +// #endif + +// #ifdef UNI-APP-X && APP +// export * from './uvue.uts' +export { arrayBufferToFile } from './uvue.uts' +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/arrayBufferToFile/uvue.uts b/QXTfront/uni_modules/lime-shared/arrayBufferToFile/uvue.uts new file mode 100644 index 0000000..65c7b14 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/arrayBufferToFile/uvue.uts @@ -0,0 +1,10 @@ +// @ts-nocheck +// import {platform} from '../platform' +/** + * buffer转路径 + * @param {Object} buffer + */ +// @ts-nocheck +export function arrayBufferToFile(buffer: ArrayBuffer, name?: string, format?:string):Promise<(File|string)> { + console.error('[arrayBufferToFile] 当前环境不支持') +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/arrayBufferToFile/vue.ts b/QXTfront/uni_modules/lime-shared/arrayBufferToFile/vue.ts new file mode 100644 index 0000000..9760b20 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/arrayBufferToFile/vue.ts @@ -0,0 +1,63 @@ +// @ts-nocheck +import {platform} from '../platform' +/** + * buffer转路径 + * @param {Object} buffer + */ +// @ts-nocheck +export function arrayBufferToFile(buffer: ArrayBuffer | Blob, name?: string, format?:string):Promise<(File|string)> { + return new Promise((resolve, reject) => { + // #ifdef MP + const fs = uni.getFileSystemManager() + //自定义文件名 + if (!name && !format) { + reject(new Error('ERROR_NAME_PARSE')) + } + const fileName = `${name || new Date().getTime()}.${format.replace(/(.+)?\//,'')}`; + let pre = platform() + const filePath = `${pre.env.USER_DATA_PATH}/${fileName}` + fs.writeFile({ + filePath, + data: buffer, + success() { + resolve(filePath) + }, + fail(err) { + console.error(err) + reject(err) + } + }) + // #endif + + // #ifdef H5 + const file = new File([buffer], name, { + type: format, + }); + resolve(file) + // #endif + + // #ifdef APP-PLUS + const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now()) + const base64 = uni.arrayBufferToBase64(buffer) + bitmap.loadBase64Data(base64, () => { + if (!name && !format) { + reject(new Error('ERROR_NAME_PARSE')) + } + const fileNmae = `${name || new Date().getTime()}.${format.replace(/(.+)?\//,'')}`; + const filePath = `_doc/uniapp_temp/${fileNmae}` + bitmap.save(filePath, {}, + () => { + bitmap.clear() + resolve(filePath) + }, + (error) => { + bitmap.clear() + reject(error) + }) + }, (error) => { + bitmap.clear() + reject(error) + }) + // #endif + }) +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/base64ToArrayBuffer/index.ts b/QXTfront/uni_modules/lime-shared/base64ToArrayBuffer/index.ts new file mode 100644 index 0000000..f83b640 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/base64ToArrayBuffer/index.ts @@ -0,0 +1,13 @@ +// @ts-nocheck +// 未完成 +export function base64ToArrayBuffer(base64 : string) { + const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || []; + if (!format) { + new Error('ERROR_BASE64SRC_PARSE') + } + if(uni.base64ToArrayBuffer) { + return uni.base64ToArrayBuffer(bodyData) + } else { + + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/base64ToPath/index.ts b/QXTfront/uni_modules/lime-shared/base64ToPath/index.ts new file mode 100644 index 0000000..d73f301 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/base64ToPath/index.ts @@ -0,0 +1,11 @@ +// @ts-nocheck +// #ifndef UNI-APP-X && APP +// export * from './vue.ts' +export { base64ToPath } from './vue.ts' +// #endif + + +// #ifdef UNI-APP-X && APP +// export * from './uvue.uts' +export { base64ToPath } from './uvue.uts' +// #endif diff --git a/QXTfront/uni_modules/lime-shared/base64ToPath/uvue.uts b/QXTfront/uni_modules/lime-shared/base64ToPath/uvue.uts new file mode 100644 index 0000000..364b494 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/base64ToPath/uvue.uts @@ -0,0 +1,22 @@ +// @ts-nocheck +import { processFile, type ProcessFileOptions } from '@/uni_modules/lime-file-utils' + +/** + * base64转路径 + * @param {Object} base64 + */ +export function base64ToPath(base64: string, filename: string | null = null):Promise { + return new Promise((resolve,reject) => { + processFile({ + type: 'toDataURL', + path: base64, + filename, + success(res: string){ + resolve(res) + }, + fail(err){ + reject(err) + } + } as ProcessFileOptions) + }) +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/base64ToPath/vue.ts b/QXTfront/uni_modules/lime-shared/base64ToPath/vue.ts new file mode 100644 index 0000000..735000f --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/base64ToPath/vue.ts @@ -0,0 +1,75 @@ +// @ts-nocheck +import {platform} from '../platform' +/** + * base64转路径 + * @param {Object} base64 + */ +export function base64ToPath(base64: string, filename?: string):Promise { + const [, format] = /^data:image\/(\w+);base64,/.exec(base64) || []; + return new Promise((resolve, reject) => { + // #ifdef MP + const fs = uni.getFileSystemManager() + //自定义文件名 + if (!filename && !format) { + reject(new Error('ERROR_BASE64SRC_PARSE')) + } + // const time = new Date().getTime(); + const name = filename || `${new Date().getTime()}.${format}`; + let pre = platform() + const filePath = `${pre.env.USER_DATA_PATH}/${name}` + fs.writeFile({ + filePath, + data: base64.split(',')[1], + encoding: 'base64', + success() { + resolve(filePath) + }, + fail(err) { + console.error(err) + reject(err) + } + }) + // #endif + + // #ifdef H5 + // mime类型 + let mimeString = base64.split(',')[0].split(':')[1].split(';')[0]; + //base64 解码 + let byteString = atob(base64.split(',')[1]); + //创建缓冲数组 + let arrayBuffer = new ArrayBuffer(byteString.length); + //创建视图 + let intArray = new Uint8Array(arrayBuffer); + for (let i = 0; i < byteString.length; i++) { + intArray[i] = byteString.charCodeAt(i); + } + resolve(URL.createObjectURL(new Blob([intArray], { + type: mimeString + }))) + // #endif + + // #ifdef APP-PLUS + const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now()) + bitmap.loadBase64Data(base64, () => { + if (!filename && !format) { + reject(new Error('ERROR_BASE64SRC_PARSE')) + } + // const time = new Date().getTime(); + const name = filename || `${new Date().getTime()}.${format}`; + const filePath = `_doc/uniapp_temp/${name}` + bitmap.save(filePath, {}, + () => { + bitmap.clear() + resolve(filePath) + }, + (error) => { + bitmap.clear() + reject(error) + }) + }, (error) => { + bitmap.clear() + reject(error) + }) + // #endif + }) +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/camelCase/index.ts b/QXTfront/uni_modules/lime-shared/camelCase/index.ts new file mode 100644 index 0000000..dd470ab --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/camelCase/index.ts @@ -0,0 +1,21 @@ +/** + * 将字符串转换为 camelCase 或 PascalCase 风格的命名约定 + * @param str 要转换的字符串 + * @param isPascalCase 指示是否转换为 PascalCase 的布尔值,默认为 false + * @returns 转换后的字符串 + */ +export function camelCase(str: string, isPascalCase: boolean = false): string { + // 将字符串分割成单词数组 + let words: string[] = str.split(/[\s_-]+/); + + // 将数组中的每个单词首字母大写(除了第一个单词) + let camelCased: string[] = words.map((word, index):string => { + if (index == 0 && !isPascalCase) { + return word.toLowerCase(); // 第一个单词全小写 + } + return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); + }); + + // 将数组中的单词拼接成一个字符串 + return camelCased.join(''); +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/canIUseCanvas2d/index.ts b/QXTfront/uni_modules/lime-shared/canIUseCanvas2d/index.ts new file mode 100644 index 0000000..be5623a --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/canIUseCanvas2d/index.ts @@ -0,0 +1,67 @@ +// @ts-nocheck + +// #ifndef UNI-APP-X && APP + +// #ifdef MP-ALIPAY +interface My { + SDKVersion: string +} +declare var my: My +// #endif + +function compareVersion(v1:string, v2:string) { + let a1 = v1.split('.'); + let a2 = v2.split('.'); + const len = Math.max(a1.length, a2.length); + + while (a1.length < len) { + a1.push('0'); + } + while (a2.length < len) { + a2.push('0'); + } + + for (let i = 0; i < len; i++) { + const num1 = parseInt(a1[i], 10); + const num2 = parseInt(a2[i], 10); + + if (num1 > num2) { + return 1; + } + if (num1 < num2) { + return -1; + } + } + + return 0; +} + +function gte(version: string) { + let {SDKVersion} = uni.getSystemInfoSync(); + // #ifdef MP-ALIPAY + SDKVersion = my.SDKVersion + // #endif + return compareVersion(SDKVersion, version) >= 0; +} +// #endif + + +/** 环境是否支持canvas 2d */ +export function canIUseCanvas2d(): boolean { + // #ifdef MP-WEIXIN + return gte('2.9.0'); + // #endif + // #ifdef MP-ALIPAY + return gte('2.7.0'); + // #endif + // #ifdef MP-TOUTIAO + return gte('1.78.0'); + // #endif + // #ifdef UNI-APP-X && WEB || UNI-APP-X && APP + return true; + // #endif + // #ifndef MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO + return false + // #endif + +} diff --git a/QXTfront/uni_modules/lime-shared/capitalizedAmount/index.ts b/QXTfront/uni_modules/lime-shared/capitalizedAmount/index.ts new file mode 100644 index 0000000..317e0af --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/capitalizedAmount/index.ts @@ -0,0 +1,111 @@ +// @ts-nocheck +import { isString } from "../isString"; +import { isNumber } from "../isNumber"; +/** + * 将金额转换为中文大写形式 + * @param {number | string} amount - 需要转换的金额,可以是数字或字符串 + * @returns {string} 转换后的中文大写金额 + */ +export function capitalizedAmount(amount : number) : string +export function capitalizedAmount(amount : string) : string +export function capitalizedAmount(amount : any | null) : string { + try { + let _amountStr :string; + let _amountNum :number = 0; + // 如果输入是字符串,先将其转换为数字,并去除逗号 + if (typeof amount == 'string') { + _amountNum = parseFloat((amount as string).replace(/,/g, '')); + } + if(isNumber(amount)) { + _amountNum = amount as number + } + // 判断输入是否为有效的金额 || isNaN(amount) + if (amount == null) throw new Error('不是有效的金额!'); + + let result = ''; + + // 处理负数情况 + if (_amountNum < 0) { + result = '欠'; + _amountNum = Math.abs(_amountNum); + } + + // 金额不能超过千亿以上 + if (_amountNum >= 10e11) throw new Error('计算金额过大!'); + + // 保留两位小数并转换为字符串 + _amountStr = _amountNum.toFixed(2); + + // 定义数字、单位和小数单位的映射 + const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']; + const units = ['', '拾', '佰', '仟']; + const bigUnits = ['', '万', '亿']; + const decimalUnits = ['角', '分']; + + // 分离整数部分和小数部分 + const amountArray = _amountStr.split('.'); + let integerPart = amountArray[0]; // string| number[] + const decimalPart = amountArray[1]; + + // 处理整数部分 + if (integerPart != '0') { + let _integerPart = integerPart.split('').map((item):number => parseInt(item)); + + // 将整数部分按四位一级进行分组 + const levels = _integerPart.reverse().reduce((prev:string[][], item, index):string[][] => { + // const level = prev?.[0]?.length < 4 ? prev[0] : []; + const level = prev.length > 0 && prev[0].length < 4 ? prev[0]: [] + + const value = item == 0 ? digits[item] : digits[item] + units[index % 4]; + + level.unshift(value); + + if (level.length == 1) { + prev.unshift(level); + } else { + prev[0] = level; + } + + return prev; + }, [] as string[][]); + // 将分组后的整数部分转换为中文大写形式 + result += levels.reduce((prev, item, index):string => { + let _level = bigUnits[levels.length - index - 1]; + let _item = item.join('').replace(/(零)\1+/g, '$1'); + + if (_item == '零') { + _level = ''; + _item = ''; + } else if (_item.endsWith('零')) { + _item = _item.slice(0, _item.length - 1); + } + + return prev + _item + _level; + }, ''); + } else { + result += '零'; + } + + // 添加元 + result += '元'; + + // 处理小数部分 + if (decimalPart != '00') { + if (result == '零元') result = ''; + + for (let i = 0; i < decimalPart.length; i++) { + const digit = parseInt(decimalPart.charAt(i)); + + if (digit != 0) { + result += digits[digit] + decimalUnits[i]; + } + } + } else { + result += '整'; + } + + return result; + } catch (error : Error) { + return error.message; + } +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/changelog.md b/QXTfront/uni_modules/lime-shared/changelog.md new file mode 100644 index 0000000..cdc1c70 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/changelog.md @@ -0,0 +1,91 @@ +## 0.4.2(2025-09-26) +- feat: 增加`cssToObj` +## 0.4.1(2025-06-13) +- fix:测试hbx4.71更新 +## 0.4.0(2025-06-04) +- fix:测试hbx4.71更新 +## 0.3.9(2025-06-04) + - fix: 因hbx4.71更新导致mac用户下载的文件被重命名,故退回4.66 +## 0.3.8(2025-06-03) +- fix: 修复`while`在vue2报错的问题 +## 0.3.7(2025-05-21) +- fix: 修复`merge`在vue2报错的问题 +## 0.3.6(2025-05-17) +- fix: 修复`raf`导错目录的问题 +## 0.3.5(2025-05-16) +- feat: 增加`isIP` +- feat: 增加`merge` +- feat: 增加`isByteLength` +- feat: 增加`isRegExp` +## 0.3.4(2025-04-27) +- fix: 修复exif缺少isBase64的问题 +## 0.3.3(2025-04-14) +- fix: 修复4.61上的类型问题 +## 0.3.2(2025-04-14) +- fix: 修复4.61上的类型问题 +## 0.3.1(2025-03-28) +- fix: 修复getRect在nvue上的问题 +## 0.3.0(2025-02-27) +- fix: 修复部分函数无法在uniappx上运行的问题 +## 0.2.9(2025-02-19) +- chore: 更新文档 +## 0.2.8(2025-02-11) +- chore: 更新文档 +## 0.2.7(2025-01-17) +- fix: 针对canvas 平台判断优化 +## 0.2.6(2025-01-09) +- feat: 增加`areaData`中国省市区数据 +## 0.2.5(2025-01-07) +- fix: animation在app上类型问题 +## 0.2.4(2025-01-04) +- feat: getRect类型问题 +## 0.2.3(2025-01-01) +- chore: unitConvert使用uni.rpx2px +## 0.2.2(2024-12-11) +- chore: 动画使用`requestAnimationFrame` +## 0.2.1(2024-11-20) +- feat: 增加`characterLimit` +## 0.2.0(2024-11-14) +- fix: vue2的类型问题 +## 0.1.9(2024-11-14) +- feat: 增加`shuffle` +## 0.1.8(2024-10-08) +- fix: vue2 条件编译 // #ifdef APP-IOS || APP-ANDROID 会生效 +## 0.1.7(2024-09-23) +- fix: raf 类型跟随版本变更 +## 0.1.6(2024-07-24) +- fix: vue2 app ts需要明确的后缀,所有补全 +- chore: 减少依赖 +## 0.1.5(2024-07-21) +- feat: 删除 Hooks +- feat: 兼容uniappx +## 0.1.4(2023-09-05) +- feat: 增加 Hooks `useIntersectionObserver` +- feat: 增加 `floatAdd` +- feat: 因为本人插件兼容 vue2 需要使用 `composition-api`,故增加vue文件代码插件的条件编译 +## 0.1.3(2023-08-13) +- feat: 增加 `camelCase` +## 0.1.2(2023-07-17) +- feat: 增加 `getClassStr` +## 0.1.1(2023-07-06) +- feat: 增加 `isNumeric`, 区别于 `isNumber` +## 0.1.0(2023-06-30) +- fix: `clamp`忘记导出了 +## 0.0.9(2023-06-27) +- feat: 增加`arrayBufferToFile` +## 0.0.8(2023-06-19) +- feat: 增加`createAnimation`、`clamp` +## 0.0.7(2023-06-08) +- chore: 更新注释 +## 0.0.6(2023-06-08) +- chore: 增加`createImage`为`lime-watermark`和`lime-qrcode`提供依赖 +## 0.0.5(2023-06-03) +- chore: 更新注释 +## 0.0.4(2023-05-22) +- feat: 增加`range`,`exif`,`selectComponent` +## 0.0.3(2023-05-08) +- feat: 增加`fillZero`,`debounce`,`throttle`,`random` +## 0.0.2(2023-05-05) +- chore: 更新文档 +## 0.0.1(2023-05-05) +- 无 diff --git a/QXTfront/uni_modules/lime-shared/characterLimit/index.ts b/QXTfront/uni_modules/lime-shared/characterLimit/index.ts new file mode 100644 index 0000000..215de23 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/characterLimit/index.ts @@ -0,0 +1,63 @@ +// @ts-nocheck +/** + * 计算字符串字符的长度并可以截取字符串。 + * @param char 传入字符串(maxcharacter条件下,一个汉字表示两个字符) + * @param max 规定最大字符串长度 + * @returns 当没有传入maxCharacter/maxLength 时返回字符串字符长度,当传入maxCharacter/maxLength时返回截取之后的字符串和长度。 + */ +export type CharacterLengthResult = { + length : number; + characters : string; +} +// #ifdef APP-ANDROID +type ChartType = any +// #endif +// #ifndef APP-ANDROID +type ChartType = string | number +// #endif + +export function characterLimit(type : string, char : ChartType, max : number) : CharacterLengthResult { + const str = `${char}`; + + if (str.length == 0) { + return { + length: 0, + characters: '', + } as CharacterLengthResult + } + + if (type == 'maxcharacter') { + let len = 0; + for (let i = 0; i < str.length; i += 1) { + let currentStringLength : number// = 0; + const code = str.charCodeAt(i)! + if (code > 127 || code == 94) { + currentStringLength = 2; + } else { + currentStringLength = 1; + } + if (len + currentStringLength > max) { + return { + length: len, + characters: str.slice(0, i), + } as CharacterLengthResult + } + len += currentStringLength; + } + return { + length: len, + characters: str, + } as CharacterLengthResult + } else if (type == 'maxlength') { + const length = str.length > max ? max : str.length; + return { + length: length, + characters: str.slice(0, length), + } as CharacterLengthResult + } + + return { + length: str.length, + characters: str, + } as CharacterLengthResult +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/clamp/index.ts b/QXTfront/uni_modules/lime-shared/clamp/index.ts new file mode 100644 index 0000000..0e16358 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/clamp/index.ts @@ -0,0 +1,16 @@ +// @ts-nocheck +/** + * 将一个值限制在指定的范围内 + * @param val 要限制的值 + * @param min 最小值 + * @param max 最大值 + * @returns 限制后的值 + */ +export function clamp(val: number, min: number, max: number): number { + return Math.max(min, Math.min(max, val)); +} + + +// console.log(clamp(5 ,0, 10)); // 输出: 5(在范围内,不做更改) +// console.log(clamp(-5 ,0, 10)); // 输出: 0(小于最小值,被限制为最小值) +// console.log(clamp(15 ,0, 10)); // 输出: 10(大于最大值,被限制为最大值) \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/classNames/index.ts b/QXTfront/uni_modules/lime-shared/classNames/index.ts new file mode 100644 index 0000000..331f7af --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/classNames/index.ts @@ -0,0 +1,53 @@ +// @ts-nocheck + +// #ifdef UNI-APP-X && APP +import { isNumber } from '../isNumber' +import { isString } from '../isString' +import { isDef } from '../isDef' +// #endif + +/** + * 获取对象的类名字符串 + * @param obj - 需要处理的对象 + * @returns 由对象属性作为类名组成的字符串 + */ +export function classNames(obj : T) : string { + let classNames : string[] = []; + // #ifdef APP-ANDROID || APP-HARMONY + if (obj instanceof UTSJSONObject) { + (obj as UTSJSONObject).toMap().forEach((value, key) => { + if (isDef(value)) { + if (isNumber(value)) { + classNames.push(key); + } + if (isString(value) && value !== '') { + classNames.push(key); + } + if (typeof value == 'boolean' && (value as boolean)) { + classNames.push(key); + } + } + }) + } + // #endif + // #ifndef APP-ANDROID || APP-HARMONY + // 遍历对象的属性 + for (let key in obj) { + // 检查属性确实属于对象自身且其值为true + if ((obj as any).hasOwnProperty(key) && obj[key]) { + // 将属性名添加到类名数组中 + classNames.push(key); + } + } + // #endif + + + // 将类名数组用空格连接成字符串并返回 + return classNames.join(' '); +} + + +// 示例 +// const obj = { foo: true, bar: false, baz: true }; +// const classNameStr = stringify(obj); +// console.log(classNameStr); // 输出: "foo baz" \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/cloneDeep/index.ts b/QXTfront/uni_modules/lime-shared/cloneDeep/index.ts new file mode 100644 index 0000000..22f8b94 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/cloneDeep/index.ts @@ -0,0 +1,12 @@ +// @ts-nocheck + +// #ifdef APP-ANDROID +// export * from './uvue.uts' +export { cloneDeep } from './uvue.uts' +// #endif + + +// #ifndef APP-ANDROID +// export * from './vue.ts' +export { cloneDeep } from './vue.ts' +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/cloneDeep/uvue.uts b/QXTfront/uni_modules/lime-shared/cloneDeep/uvue.uts new file mode 100644 index 0000000..9ee42d9 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/cloneDeep/uvue.uts @@ -0,0 +1,39 @@ +// @ts-nocheck +/** + * 深度克隆一个对象或数组 + * @param obj 要克隆的对象或数组 + * @returns 克隆后的对象或数组 + */ +export function cloneDeep(obj : any) : T { + if (obj instanceof Set) { + const set = new Set(); + obj.forEach((item : any) => { + set.add(item) + }) + return set as T; + } + if (obj instanceof Map) { + const map = new Map(); + obj.forEach((value : any, key : any) => { + map.set(key, value) + }) + return map as T; + } + + if (obj instanceof RegExp) { + return new RegExp(obj) as T; + } + + if (Array.isArray(obj)) { + return (obj as any[]).map((item : any):any => item) as T; + } + + if (obj instanceof Date) { + return new Date(obj.getTime()) as T; + } + + if (typeof obj == 'object') { + return UTSJSONObject.assign({}, toRaw(obj))! + } + return obj as T +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/cloneDeep/vue.ts b/QXTfront/uni_modules/lime-shared/cloneDeep/vue.ts new file mode 100644 index 0000000..ded334d --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/cloneDeep/vue.ts @@ -0,0 +1,103 @@ +// @ts-nocheck +/** + * 深度克隆一个对象或数组 + * @param obj 要克隆的对象或数组 + * @returns 克隆后的对象或数组 + */ +export function cloneDeep(obj: any): T { + // 如果传入的对象为空,返回空 + if (obj === null) { + return null as unknown as T; + } + + // 如果传入的对象是 Set 类型,则将其转换为数组,并通过新的 Set 构造函数创建一个新的 Set 对象 + if (obj instanceof Set) { + return new Set([...obj]) as unknown as T; + } + + // 如果传入的对象是 Map 类型,则将其转换为数组,并通过新的 Map 构造函数创建一个新的 Map 对象 + if (obj instanceof Map) { + return new Map([...obj]) as unknown as T; + } + + // 如果传入的对象是 WeakMap 类型,则直接用传入的 WeakMap 对象进行赋值 + if (obj instanceof WeakMap) { + let weakMap = new WeakMap(); + weakMap = obj; + return weakMap as unknown as T; + } + + // 如果传入的对象是 WeakSet 类型,则直接用传入的 WeakSet 对象进行赋值 + if (obj instanceof WeakSet) { + let weakSet = new WeakSet(); + weakSet = obj; + return weakSet as unknown as T; + } + + // 如果传入的对象是 RegExp 类型,则通过新的 RegExp 构造函数创建一个新的 RegExp 对象 + if (obj instanceof RegExp) { + return new RegExp(obj) as unknown as T; + } + + // 如果传入的对象是 undefined 类型,则返回 undefined + if (typeof obj === 'undefined') { + return undefined as unknown as T; + } + + // 如果传入的对象是数组,则递归调用 cloneDeep 函数对数组中的每个元素进行克隆 + if (Array.isArray(obj)) { + return obj.map(cloneDeep) as unknown as T; + } + + // 如果传入的对象是 Date 类型,则通过新的 Date 构造函数创建一个新的 Date 对象 + if (obj instanceof Date) { + return new Date(obj.getTime()) as unknown as T; + } + + // 如果传入的对象是普通对象,则使用递归调用 cloneDeep 函数对对象的每个属性进行克隆 + if (typeof obj === 'object') { + const newObj: any = {}; + for (const [key, value] of Object.entries(obj)) { + newObj[key] = cloneDeep(value); + } + const symbolKeys = Object.getOwnPropertySymbols(obj); + for (const key of symbolKeys) { + newObj[key] = cloneDeep(obj[key]); + } + return newObj; + } + + // 如果传入的对象是基本数据类型(如字符串、数字等),则直接返回 + return obj; +} + +// 示例使用 + +// // 克隆一个对象 +// const obj = { name: 'John', age: 30 }; +// const clonedObj = cloneDeep(obj); + +// console.log(clonedObj); // 输出: { name: 'John', age: 30 } +// console.log(clonedObj === obj); // 输出: false (副本与原对象是独立的) + +// // 克隆一个数组 +// const arr = [1, 2, 3]; +// const clonedArr = cloneDeep(arr); + +// console.log(clonedArr); // 输出: [1, 2, 3] +// console.log(clonedArr === arr); // 输出: false (副本与原数组是独立的) + +// // 克隆一个包含嵌套对象的对象 +// const person = { +// name: 'Alice', +// age: 25, +// address: { +// city: 'New York', +// country: 'USA', +// }, +// }; +// const clonedPerson = cloneDeep(person); + +// console.log(clonedPerson); // 输出: { name: 'Alice', age: 25, address: { city: 'New York', country: 'USA' } } +// console.log(clonedPerson === person); // 输出: false (副本与原对象是独立的) +// console.log(clonedPerson.address === person.address); // 输出: false (嵌套对象的副本也是独立的) \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/closest/index.ts b/QXTfront/uni_modules/lime-shared/closest/index.ts new file mode 100644 index 0000000..e6e79c2 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/closest/index.ts @@ -0,0 +1,22 @@ +// @ts-nocheck + +/** + * 在给定数组中找到最接近目标数字的元素。 + * @param arr 要搜索的数字数组。 + * @param target 目标数字。 + * @returns 最接近目标数字的数组元素。 + */ +export function closest(arr: number[], target: number):number { + return arr.reduce((pre: number, cur: number):number => + Math.abs(pre - target) < Math.abs(cur - target) ? pre : cur + ); +} + +// 示例 +// // 定义一个数字数组 +// const numbers = [1, 3, 5, 7, 9]; + +// // 在数组中找到最接近目标数字 6 的元素 +// const closestNumber = closest(numbers, 6); + +// console.log(closestNumber); // 输出结果: 5 \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/components/lime-shared/lime-shared.vue b/QXTfront/uni_modules/lime-shared/components/lime-shared/lime-shared.vue new file mode 100644 index 0000000..edbf6e8 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/components/lime-shared/lime-shared.vue @@ -0,0 +1,407 @@ + + + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/createAnimation/index.ts b/QXTfront/uni_modules/lime-shared/createAnimation/index.ts new file mode 100644 index 0000000..5417375 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/createAnimation/index.ts @@ -0,0 +1,11 @@ +// @ts-nocheck +// #ifndef UNI-APP-X +export * from './type.ts' +// export * from './vue.ts' +export { createAnimation } from './vue.ts' +// #endif + +// #ifdef UNI-APP-X +// export * from './uvue.ts' +export { createAnimation } from './uvue.uts' +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/createAnimation/type.ts b/QXTfront/uni_modules/lime-shared/createAnimation/type.ts new file mode 100644 index 0000000..0f8ad34 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/createAnimation/type.ts @@ -0,0 +1,25 @@ +export type CreateAnimationOptions = { + /** + * 动画持续时间,单位ms + */ + duration ?: number; + /** + * 定义动画的效果 + * - linear: 动画从头到尾的速度是相同的 + * - ease: 动画以低速开始,然后加快,在结束前变慢 + * - ease-in: 动画以低速开始 + * - ease-in-out: 动画以低速开始和结束 + * - ease-out: 动画以低速结束 + * - step-start: 动画第一帧就跳至结束状态直到结束 + * - step-end: 动画一直保持开始状态,最后一帧跳到结束状态 + */ + timingFunction ?: string //'linear' | 'ease' | 'ease-in' | 'ease-in-out' | 'ease-out' | 'step-start' | 'step-end'; + /** + * 动画延迟时间,单位 ms + */ + delay ?: number; + /** + * 设置transform-origin + */ + transformOrigin ?: string; +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/createAnimation/uvue.uts b/QXTfront/uni_modules/lime-shared/createAnimation/uvue.uts new file mode 100644 index 0000000..96d8263 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/createAnimation/uvue.uts @@ -0,0 +1,5 @@ +// @ts-nocheck +// export * from '@/uni_modules/lime-animateIt' +export function createAnimation() { + console.error('当前环境不支持,请使用:lime-animateIt') +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/createAnimation/vue.ts b/QXTfront/uni_modules/lime-shared/createAnimation/vue.ts new file mode 100644 index 0000000..6934f27 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/createAnimation/vue.ts @@ -0,0 +1,148 @@ +// @ts-nocheck +// nvue 需要在节点上设置ref或在export里传入 +// const animation = createAnimation({ +// ref: this.$refs['xxx'], +// duration: 0, +// timingFunction: 'linear' +// }) +// animation.opacity(1).translate(x, y).step({duration}) +// animation.export(ref) + +// 抹平nvue 与 uni.createAnimation的使用差距 +// 但是nvue动画太慢 + + + +import { type CreateAnimationOptions } from './type' +// #ifdef APP-NVUE +const nvueAnimation = uni.requireNativePlugin('animation') + +type AnimationTypes = 'matrix' | 'matrix3d' | 'rotate' | 'rotate3d' | 'rotateX' | 'rotateY' | 'rotateZ' | 'scale' | 'scale3d' | 'scaleX' | 'scaleY' | 'scaleZ' | 'skew' | 'skewX' | 'skewY' | 'translate' | 'translate3d' | 'translateX' | 'translateY' | 'translateZ' + | 'opacity' | 'backgroundColor' | 'width' | 'height' | 'left' | 'right' | 'top' | 'bottom' + +interface Styles { + [key : string] : any +} + +interface StepConfig { + duration?: number + timingFunction?: string + delay?: number + needLayout?: boolean + transformOrigin?: string +} +interface StepAnimate { + styles?: Styles + config?: StepConfig +} +interface StepAnimates { + [key: number]: StepAnimate +} +// export interface CreateAnimationOptions extends UniApp.CreateAnimationOptions { +// ref?: string +// } + +type Callback = (time: number) => void +const animateTypes1 : AnimationTypes[] = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d', + 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY', + 'translateZ' +] +const animateTypes2 : AnimationTypes[] = ['opacity', 'backgroundColor'] +const animateTypes3 : AnimationTypes[] = ['width', 'height', 'left', 'right', 'top', 'bottom'] + +class LimeAnimation { + ref : any + context : any + options : UniApp.CreateAnimationOptions + // stack : any[] = [] + next : number = 0 + currentStepAnimates : StepAnimates = {} + duration : number = 0 + constructor(options : CreateAnimationOptions) { + const {ref} = options + this.ref = ref + this.options = options + } + addAnimate(type : AnimationTypes, args: (string | number)[]) { + let aniObj = this.currentStepAnimates[this.next] + let stepAnimate:StepAnimate = {} + if (!aniObj) { + stepAnimate = {styles: {}, config: {}} + } else { + stepAnimate = aniObj + } + + if (animateTypes1.includes(type)) { + if (!stepAnimate.styles.transform) { + stepAnimate.styles.transform = '' + } + let unit = '' + if (type === 'rotate') { + unit = 'deg' + } + stepAnimate.styles.transform += `${type}(${args.map((v: number) => v + unit).join(',')}) ` + } else { + stepAnimate.styles[type] = `${args.join(',')}` + } + this.currentStepAnimates[this.next] = stepAnimate + } + animateRun(styles: Styles = {}, config:StepConfig = {}, ref: any) { + const el = ref || this.ref + if (!el) return + return new Promise((resolve) => { + const time = +new Date() + nvueAnimation.transition(el, { + styles, + ...config + }, () => { + resolve(+new Date() - time) + }) + }) + } + nextAnimate(animates: StepAnimates, step: number = 0, ref: any, cb: Callback) { + let obj = animates[step] + if (obj) { + let { styles, config } = obj + // this.duration += config.duration + this.animateRun(styles, config, ref).then((time: number) => { + step += 1 + this.duration += time + this.nextAnimate(animates, step, ref, cb) + }) + } else { + this.currentStepAnimates = {} + cb && cb(this.duration) + } + } + step(config:StepConfig = {}) { + this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config) + this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin + this.next++ + return this + } + export(ref: any, cb?: Callback) { + ref = ref || this.ref + if(!ref) return + this.duration = 0 + this.next = 0 + this.nextAnimate(this.currentStepAnimates, 0, ref, cb) + return null + } +} + + +animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => { + LimeAnimation.prototype[type] = function(...args: (string | number)[]) { + this.addAnimate(type, args) + return this + } +}) +// #endif +export function createAnimation(options : CreateAnimationOptions) { + // #ifndef APP-NVUE + return uni.createAnimation({ ...options }) + // #endif + // #ifdef APP-NVUE + return new LimeAnimation(options) + // #endif +} diff --git a/QXTfront/uni_modules/lime-shared/createCanvas/index.ts b/QXTfront/uni_modules/lime-shared/createCanvas/index.ts new file mode 100644 index 0000000..987be92 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/createCanvas/index.ts @@ -0,0 +1,73 @@ + +// @ts-nocheck +// #ifndef UNI-APP-X && APP +import type { ComponentInternalInstance } from '@/uni_modules/lime-shared/vue' +import { getRect } from '@/uni_modules/lime-shared/getRect' +import { canIUseCanvas2d } from '@/uni_modules/lime-shared/canIUseCanvas2d' +export const isCanvas2d = canIUseCanvas2d() +// #endif + + +export function createCanvas(canvasId : string, component : ComponentInternalInstance) { + // #ifdef UNI-APP-X + uni.createCanvasContextAsync({ + canvasId, + component, + success(context : CanvasContext) { + + }, + fail(error : UniError) { + + } + }) + // #endif + // #ifndef UNI-APP-X + const isCanvas2d = canIUseCanvas2d() + getRect('#' + canvasId, context, isCanvas2d).then(res => { + if (res.node) { + res.node.width = res.width + res.node.height = res.height + return res.node + } else { + const ctx = uni.createCanvasContext(canvasId, context) + if (!ctx._drawImage) { + ctx._drawImage = ctx.drawImage + ctx.drawImage = function (...args) { + const { path } = args.shift() + ctx._drawImage(path, ...args) + } + } + if (!ctx.getImageData) { + ctx.getImageData = function () { + return new Promise((resolve, reject) => { + uni.canvasGetImageData({ + canvasId, + x: parseInt(arguments[0]), + y: parseInt(arguments[1]), + width: parseInt(arguments[2]), + height: parseInt(arguments[3]), + success(res) { + resolve(res) + }, + fail(err) { + reject(err) + } + }, context) + }) + + } + return { + getContext(type: string) { + if(type == '2d') { + return ctx + } + }, + width: res.width, + height: res.height, + createImage + } + } + } + }) + // #endif +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/createImage/index.ts b/QXTfront/uni_modules/lime-shared/createImage/index.ts new file mode 100644 index 0000000..c9e72fe --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/createImage/index.ts @@ -0,0 +1,71 @@ +// @ts-nocheck +// #ifndef UNI-APP-X && APP +import {isBrowser} from '../isBrowser' +class Image { + currentSrc: string | null = null + naturalHeight: number = 0 + naturalWidth: number = 0 + width: number = 0 + height: number = 0 + tagName: string = 'IMG' + path: string = '' + crossOrigin: string = '' + referrerPolicy: string = '' + onload: () => void = () => {} + onerror: () => void = () => {} + complete: boolean = false + constructor() {} + set src(src: string) { + console.log('src', src) + if(!src) { + return this.onerror() + } + src = src.replace(/^@\//,'/') + this.currentSrc = src + uni.getImageInfo({ + src, + success: (res) => { + const localReg = /^\.|^\/(?=[^\/])/; + // #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-TOUTIAO + res.path = localReg.test(src) ? `/${res.path}` : res.path; + // #endif + this.complete = true + this.path = res.path + this.naturalWidth = this.width = res.width + this.naturalHeight = this.height = res.height + this.onload() + }, + fail: () => { + this.onerror() + } + }) + } + get src() { + return this.currentSrc + } +} +interface UniImage extends WechatMiniprogram.Image { + complete?: boolean + naturalHeight?: number + naturalWidth?: number +} +/** 创建用于 canvas 的 img */ +export function createImage(canvas?: any): HTMLImageElement | UniImage { + if(canvas && canvas.createImage) { + return (canvas as WechatMiniprogram.Canvas).createImage() + } else if(this && this['tagName'] == 'canvas' && !('toBlob' in this) || canvas && !('toBlob' in canvas)){ + return new Image() + } else if(isBrowser) { + return new window.Image() + } + return new Image() +} +// #endif + + +// #ifdef UNI-APP-X && APP +export function createImage():Image{ + // console.error('当前环境不支持') + return new Image() +} +// #endif diff --git a/QXTfront/uni_modules/lime-shared/cssToObj/index.ts b/QXTfront/uni_modules/lime-shared/cssToObj/index.ts new file mode 100644 index 0000000..ec09623 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/cssToObj/index.ts @@ -0,0 +1,45 @@ +// @ts-nocheck +// #ifndef UNI-APP-X +type UTSJSONObject = Record +// #endif + + +/** + * 将 CSS 字符串转换为样式对象 + * @param css CSS 字符串,例如 "color: red; font-size: 16px;" + * @returns CSSProperties 对象 + */ +export function cssToObj(css : string | UTSJSONObject | null) : UTSJSONObject { + // #ifdef APP-ANDROID + if(css == null) return {} + // #endif + // #ifndef APP-ANDROID + if(!css) return {} + // #endif + if(typeof css == 'object') return css as UTSJSONObject + + + const style : UTSJSONObject = {}; + + (css as string).split(';').forEach(decl => { + // #ifdef APP-ANDROID + const res = decl.split(':').map(s => s.trim()); + if(res.length > 1) { + const [prop, val] = res; + if (prop != '' && val != '') { + const camelProp = prop!.replace(/-([a-z])/g, (_: string, _offset: number,c: string):string => c.toUpperCase()); + style[camelProp] = val!; + } + } + // #endif + // #ifndef APP-ANDROID + const [prop, val] = decl.split(':').map(s => s.trim()); + if (prop && val) { + const camelProp = prop.replace(/-([a-z])/g, (_, c) => c.toUpperCase()); + style[camelProp] = val; + } + // #endif + }); + + return style; +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/debounce/index.ts b/QXTfront/uni_modules/lime-shared/debounce/index.ts new file mode 100644 index 0000000..5a0e3c4 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/debounce/index.ts @@ -0,0 +1,11 @@ +// @ts-nocheck + +// #ifdef UNI-APP-X && APP +// export * from './uvue.uts' +export { debounce } from './uvue.uts' +// #endif + +// #ifndef UNI-APP-X && APP +// export * from './vue.ts' +export { debounce } from './vue.ts' +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/debounce/uvue.uts b/QXTfront/uni_modules/lime-shared/debounce/uvue.uts new file mode 100644 index 0000000..f1fc29d --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/debounce/uvue.uts @@ -0,0 +1,36 @@ +// @ts-nocheck +/** + * 防抖函数,通过延迟一定时间来限制函数的执行频率。 + * @param fn 要防抖的函数。 + * @param wait 触发防抖的等待时间,单位为毫秒。 + * @returns 防抖函数。 + */ +export function debounce(fn : (args: A)=> void, wait = 300): (args: A)=> void { + let timer = -1 + + return (args: A) => { + if (timer >-1) {clearTimeout(timer)}; + + timer = setTimeout(()=>{ + fn(args) + }, wait) + } +}; + + + +// 示例 +// 定义一个函数 +// function saveData(data: string) { +// // 模拟保存数据的操作 +// console.log(`Saving data: ${data}`); +// } + +// // 创建一个防抖函数,延迟 500 毫秒后调用 saveData 函数 +// const debouncedSaveData = debounce(saveData, 500); + +// // 连续调用防抖函数 +// debouncedSaveData('Data 1'); // 不会立即调用 saveData 函数 +// debouncedSaveData('Data 2'); // 不会立即调用 saveData 函数 + +// 在 500 毫秒后,只会调用一次 saveData 函数,输出结果为 "Saving data: Data 2" \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/debounce/vue.ts b/QXTfront/uni_modules/lime-shared/debounce/vue.ts new file mode 100644 index 0000000..694b44d --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/debounce/vue.ts @@ -0,0 +1,40 @@ +// @ts-nocheck +type Timeout = ReturnType | null; +/** + * 防抖函数,通过延迟一定时间来限制函数的执行频率。 + * @param fn 要防抖的函数。 + * @param wait 触发防抖的等待时间,单位为毫秒。 + * @returns 防抖函数。 + */ +export function debounce( + fn : (...args : A) => R, + wait : number = 300) : (...args : A) => void { + let timer : Timeout = null; + + return function (...args : A) { + if (timer) clearTimeout(timer); // 如果上一个 setTimeout 存在,则清除它 + + // 设置一个新的 setTimeout,在指定的等待时间后调用防抖函数 + timer = setTimeout(() => { + fn.apply(this, args); // 使用提供的参数调用原始函数 + }, wait); + }; +}; + + + +// 示例 +// 定义一个函数 +// function saveData(data: string) { +// // 模拟保存数据的操作 +// console.log(`Saving data: ${data}`); +// } + +// // 创建一个防抖函数,延迟 500 毫秒后调用 saveData 函数 +// const debouncedSaveData = debounce(saveData, 500); + +// // 连续调用防抖函数 +// debouncedSaveData('Data 1'); // 不会立即调用 saveData 函数 +// debouncedSaveData('Data 2'); // 不会立即调用 saveData 函数 + +// 在 500 毫秒后,只会调用一次 saveData 函数,输出结果为 "Saving data: Data 2" \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/dom/index.ts b/QXTfront/uni_modules/lime-shared/dom/index.ts new file mode 100644 index 0000000..9c82e09 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/dom/index.ts @@ -0,0 +1,18 @@ +// @ts-nocheck +export function findClosestElementWithStyle(startEl: UniElement | null, styleProperty: string): UniElement | null { + let currentEl: UniElement | null = startEl; + + while (currentEl != null) { + // Check if the current element has the style property with a non-empty value + const styleValue = currentEl?.style.getPropertyValue(styleProperty) ?? ''; + if (styleValue.trim() != '') { + return currentEl; + } + + // Move to parent element + currentEl = currentEl.parentElement; + } + + // Return null if no element with the specified style was found + return null; +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/exif/index.ts b/QXTfront/uni_modules/lime-shared/exif/index.ts new file mode 100644 index 0000000..e1e6baf --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/exif/index.ts @@ -0,0 +1,11 @@ +// @ts-nocheck +// #ifndef UNI-APP-X && APP +// export * from './vue.ts' +export { exif } from './vue.ts' +// #endif + + +// #ifdef UNI-APP-X && APP +// export * from './uvue.uts' +export { exif } from './uvue.uts' +// #endif diff --git a/QXTfront/uni_modules/lime-shared/exif/uvue.uts b/QXTfront/uni_modules/lime-shared/exif/uvue.uts new file mode 100644 index 0000000..01d21a2 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/exif/uvue.uts @@ -0,0 +1,7 @@ +class EXIF { + constructor(){ + console.error('当前环境不支持') + } +} + +export const exif = new EXIF() \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/exif/vue.ts b/QXTfront/uni_modules/lime-shared/exif/vue.ts new file mode 100644 index 0000000..6862263 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/exif/vue.ts @@ -0,0 +1,1057 @@ +// @ts-nocheck +import { base64ToArrayBuffer } from '../base64ToArrayBuffer'; +import { pathToBase64 } from '../pathToBase64'; +// import { isBase64 } from '../isBase64'; +import { isDataURI } from '../isBase64'; +import { isString } from '../isString'; + +interface File { + exifdata : any + iptcdata : any + xmpdata : any + src : string +} +class EXIF { + isXmpEnabled = false + debug = false + Tags = { + // version tags + 0x9000: "ExifVersion", // EXIF version + 0xA000: "FlashpixVersion", // Flashpix format version + + // colorspace tags + 0xA001: "ColorSpace", // Color space information tag + + // image configuration + 0xA002: "PixelXDimension", // Valid width of meaningful image + 0xA003: "PixelYDimension", // Valid height of meaningful image + 0x9101: "ComponentsConfiguration", // Information about channels + 0x9102: "CompressedBitsPerPixel", // Compressed bits per pixel + + // user information + 0x927C: "MakerNote", // Any desired information written by the manufacturer + 0x9286: "UserComment", // Comments by user + + // related file + 0xA004: "RelatedSoundFile", // Name of related sound file + + // date and time + 0x9003: "DateTimeOriginal", // Date and time when the original image was generated + 0x9004: "DateTimeDigitized", // Date and time when the image was stored digitally + 0x9290: "SubsecTime", // Fractions of seconds for DateTime + 0x9291: "SubsecTimeOriginal", // Fractions of seconds for DateTimeOriginal + 0x9292: "SubsecTimeDigitized", // Fractions of seconds for DateTimeDigitized + + // picture-taking conditions + 0x829A: "ExposureTime", // Exposure time (in seconds) + 0x829D: "FNumber", // F number + 0x8822: "ExposureProgram", // Exposure program + 0x8824: "SpectralSensitivity", // Spectral sensitivity + 0x8827: "ISOSpeedRatings", // ISO speed rating + 0x8828: "OECF", // Optoelectric conversion factor + 0x9201: "ShutterSpeedValue", // Shutter speed + 0x9202: "ApertureValue", // Lens aperture + 0x9203: "BrightnessValue", // Value of brightness + 0x9204: "ExposureBias", // Exposure bias + 0x9205: "MaxApertureValue", // Smallest F number of lens + 0x9206: "SubjectDistance", // Distance to subject in meters + 0x9207: "MeteringMode", // Metering mode + 0x9208: "LightSource", // Kind of light source + 0x9209: "Flash", // Flash status + 0x9214: "SubjectArea", // Location and area of main subject + 0x920A: "FocalLength", // Focal length of the lens in mm + 0xA20B: "FlashEnergy", // Strobe energy in BCPS + 0xA20C: "SpatialFrequencyResponse", // + 0xA20E: "FocalPlaneXResolution", // Number of pixels in width direction per FocalPlaneResolutionUnit + 0xA20F: "FocalPlaneYResolution", // Number of pixels in height direction per FocalPlaneResolutionUnit + 0xA210: "FocalPlaneResolutionUnit", // Unit for measuring FocalPlaneXResolution and FocalPlaneYResolution + 0xA214: "SubjectLocation", // Location of subject in image + 0xA215: "ExposureIndex", // Exposure index selected on camera + 0xA217: "SensingMethod", // Image sensor type + 0xA300: "FileSource", // Image source (3 == DSC) + 0xA301: "SceneType", // Scene type (1 == directly photographed) + 0xA302: "CFAPattern", // Color filter array geometric pattern + 0xA401: "CustomRendered", // Special processing + 0xA402: "ExposureMode", // Exposure mode + 0xA403: "WhiteBalance", // 1 = auto white balance, 2 = manual + 0xA404: "DigitalZoomRation", // Digital zoom ratio + 0xA405: "FocalLengthIn35mmFilm", // Equivalent foacl length assuming 35mm film camera (in mm) + 0xA406: "SceneCaptureType", // Type of scene + 0xA407: "GainControl", // Degree of overall image gain adjustment + 0xA408: "Contrast", // Direction of contrast processing applied by camera + 0xA409: "Saturation", // Direction of saturation processing applied by camera + 0xA40A: "Sharpness", // Direction of sharpness processing applied by camera + 0xA40B: "DeviceSettingDescription", // + 0xA40C: "SubjectDistanceRange", // Distance to subject + + // other tags + 0xA005: "InteroperabilityIFDPointer", + 0xA420: "ImageUniqueID" // Identifier assigned uniquely to each image + } + TiffTags = { + 0x0100: "ImageWidth", + 0x0101: "ImageHeight", + 0x8769: "ExifIFDPointer", + 0x8825: "GPSInfoIFDPointer", + 0xA005: "InteroperabilityIFDPointer", + 0x0102: "BitsPerSample", + 0x0103: "Compression", + 0x0106: "PhotometricInterpretation", + 0x0112: "Orientation", + 0x0115: "SamplesPerPixel", + 0x011C: "PlanarConfiguration", + 0x0212: "YCbCrSubSampling", + 0x0213: "YCbCrPositioning", + 0x011A: "XResolution", + 0x011B: "YResolution", + 0x0128: "ResolutionUnit", + 0x0111: "StripOffsets", + 0x0116: "RowsPerStrip", + 0x0117: "StripByteCounts", + 0x0201: "JPEGInterchangeFormat", + 0x0202: "JPEGInterchangeFormatLength", + 0x012D: "TransferFunction", + 0x013E: "WhitePoint", + 0x013F: "PrimaryChromaticities", + 0x0211: "YCbCrCoefficients", + 0x0214: "ReferenceBlackWhite", + 0x0132: "DateTime", + 0x010E: "ImageDescription", + 0x010F: "Make", + 0x0110: "Model", + 0x0131: "Software", + 0x013B: "Artist", + 0x8298: "Copyright" + } + GPSTags = { + 0x0000: "GPSVersionID", + 0x0001: "GPSLatitudeRef", + 0x0002: "GPSLatitude", + 0x0003: "GPSLongitudeRef", + 0x0004: "GPSLongitude", + 0x0005: "GPSAltitudeRef", + 0x0006: "GPSAltitude", + 0x0007: "GPSTimeStamp", + 0x0008: "GPSSatellites", + 0x0009: "GPSStatus", + 0x000A: "GPSMeasureMode", + 0x000B: "GPSDOP", + 0x000C: "GPSSpeedRef", + 0x000D: "GPSSpeed", + 0x000E: "GPSTrackRef", + 0x000F: "GPSTrack", + 0x0010: "GPSImgDirectionRef", + 0x0011: "GPSImgDirection", + 0x0012: "GPSMapDatum", + 0x0013: "GPSDestLatitudeRef", + 0x0014: "GPSDestLatitude", + 0x0015: "GPSDestLongitudeRef", + 0x0016: "GPSDestLongitude", + 0x0017: "GPSDestBearingRef", + 0x0018: "GPSDestBearing", + 0x0019: "GPSDestDistanceRef", + 0x001A: "GPSDestDistance", + 0x001B: "GPSProcessingMethod", + 0x001C: "GPSAreaInformation", + 0x001D: "GPSDateStamp", + 0x001E: "GPSDifferential" + } + // EXIF 2.3 Spec + IFD1Tags = { + 0x0100: "ImageWidth", + 0x0101: "ImageHeight", + 0x0102: "BitsPerSample", + 0x0103: "Compression", + 0x0106: "PhotometricInterpretation", + 0x0111: "StripOffsets", + 0x0112: "Orientation", + 0x0115: "SamplesPerPixel", + 0x0116: "RowsPerStrip", + 0x0117: "StripByteCounts", + 0x011A: "XResolution", + 0x011B: "YResolution", + 0x011C: "PlanarConfiguration", + 0x0128: "ResolutionUnit", + 0x0201: "JpegIFOffset", // When image format is JPEG, this value show offset to JPEG data stored.(aka "ThumbnailOffset" or "JPEGInterchangeFormat") + 0x0202: "JpegIFByteCount", // When image format is JPEG, this value shows data size of JPEG image (aka "ThumbnailLength" or "JPEGInterchangeFormatLength") + 0x0211: "YCbCrCoefficients", + 0x0212: "YCbCrSubSampling", + 0x0213: "YCbCrPositioning", + 0x0214: "ReferenceBlackWhite" + } + StringValues = { + ExposureProgram: { + 0: "Not defined", + 1: "Manual", + 2: "Normal program", + 3: "Aperture priority", + 4: "Shutter priority", + 5: "Creative program", + 6: "Action program", + 7: "Portrait mode", + 8: "Landscape mode" + }, + MeteringMode: { + 0: "Unknown", + 1: "Average", + 2: "CenterWeightedAverage", + 3: "Spot", + 4: "MultiSpot", + 5: "Pattern", + 6: "Partial", + 255: "Other" + }, + LightSource: { + 0: "Unknown", + 1: "Daylight", + 2: "Fluorescent", + 3: "Tungsten (incandescent light)", + 4: "Flash", + 9: "Fine weather", + 10: "Cloudy weather", + 11: "Shade", + 12: "Daylight fluorescent (D 5700 - 7100K)", + 13: "Day white fluorescent (N 4600 - 5400K)", + 14: "Cool white fluorescent (W 3900 - 4500K)", + 15: "White fluorescent (WW 3200 - 3700K)", + 17: "Standard light A", + 18: "Standard light B", + 19: "Standard light C", + 20: "D55", + 21: "D65", + 22: "D75", + 23: "D50", + 24: "ISO studio tungsten", + 255: "Other" + }, + Flash: { + 0x0000: "Flash did not fire", + 0x0001: "Flash fired", + 0x0005: "Strobe return light not detected", + 0x0007: "Strobe return light detected", + 0x0009: "Flash fired, compulsory flash mode", + 0x000D: "Flash fired, compulsory flash mode, return light not detected", + 0x000F: "Flash fired, compulsory flash mode, return light detected", + 0x0010: "Flash did not fire, compulsory flash mode", + 0x0018: "Flash did not fire, auto mode", + 0x0019: "Flash fired, auto mode", + 0x001D: "Flash fired, auto mode, return light not detected", + 0x001F: "Flash fired, auto mode, return light detected", + 0x0020: "No flash function", + 0x0041: "Flash fired, red-eye reduction mode", + 0x0045: "Flash fired, red-eye reduction mode, return light not detected", + 0x0047: "Flash fired, red-eye reduction mode, return light detected", + 0x0049: "Flash fired, compulsory flash mode, red-eye reduction mode", + 0x004D: "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected", + 0x004F: "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected", + 0x0059: "Flash fired, auto mode, red-eye reduction mode", + 0x005D: "Flash fired, auto mode, return light not detected, red-eye reduction mode", + 0x005F: "Flash fired, auto mode, return light detected, red-eye reduction mode" + }, + SensingMethod: { + 1: "Not defined", + 2: "One-chip color area sensor", + 3: "Two-chip color area sensor", + 4: "Three-chip color area sensor", + 5: "Color sequential area sensor", + 7: "Trilinear sensor", + 8: "Color sequential linear sensor" + }, + SceneCaptureType: { + 0: "Standard", + 1: "Landscape", + 2: "Portrait", + 3: "Night scene" + }, + SceneType: { + 1: "Directly photographed" + }, + CustomRendered: { + 0: "Normal process", + 1: "Custom process" + }, + WhiteBalance: { + 0: "Auto white balance", + 1: "Manual white balance" + }, + GainControl: { + 0: "None", + 1: "Low gain up", + 2: "High gain up", + 3: "Low gain down", + 4: "High gain down" + }, + Contrast: { + 0: "Normal", + 1: "Soft", + 2: "Hard" + }, + Saturation: { + 0: "Normal", + 1: "Low saturation", + 2: "High saturation" + }, + Sharpness: { + 0: "Normal", + 1: "Soft", + 2: "Hard" + }, + SubjectDistanceRange: { + 0: "Unknown", + 1: "Macro", + 2: "Close view", + 3: "Distant view" + }, + FileSource: { + 3: "DSC" + }, + + Components: { + 0: "", + 1: "Y", + 2: "Cb", + 3: "Cr", + 4: "R", + 5: "G", + 6: "B" + } + } + enableXmp() { + this.isXmpEnabled = true + } + disableXmp() { + this.isXmpEnabled = false; + } + /** + * 获取图片数据 + * @param img 图片地址 + * @param callback 回调 返回图片数据 + * */ + getData(img : any, callback : Function) { + // if (((self.Image && img instanceof self.Image) || (self.HTMLImageElement && img instanceof self.HTMLImageElement)) && !img.complete) + // return false; + let file : File = { + src: '', + exifdata: null, + iptcdata: null, + xmpdata: null, + } + if (isDataURI(img)) { + file.src = img + } else if (img.path) { + file.src = img.path + } else if (isString(img)) { + file.src = img + } else { + return false; + } + + + if (!imageHasData(file)) { + getImageData(file, callback); + } else { + if (callback) { + callback.call(file); + } + } + return true; + } + /** + * 获取图片tag + * @param img 图片数据 + * @param tag tag 类型 + * */ + getTag(img : File, tag : string) { + if (!imageHasData(img)) return; + return img.exifdata[tag]; + } + getIptcTag(img : File, tag : string) { + if (!imageHasData(img)) return; + return img.iptcdata[tag]; + } + getAllTags(img : File) { + if (!imageHasData(img)) return {}; + let a, + data = img.exifdata, + tags = {}; + for (a in data) { + if (data.hasOwnProperty(a)) { + tags[a] = data[a]; + } + } + return tags; + } + getAllIptcTags(img : File) { + if (!imageHasData(img)) return {}; + let a, + data = img.iptcdata, + tags = {}; + for (a in data) { + if (data.hasOwnProperty(a)) { + tags[a] = data[a]; + } + } + return tags; + } + pretty(img : File) { + if (!imageHasData(img)) return ""; + let a, + data = img.exifdata, + strPretty = ""; + for (a in data) { + if (data.hasOwnProperty(a)) { + if (typeof data[a] == "object") { + if (data[a] instanceof Number) { + strPretty += a + " : " + data[a] + " [" + data[a].numerator + "/" + data[a] + .denominator + "]\r\n"; + } else { + strPretty += a + " : [" + data[a].length + " values]\r\n"; + } + } else { + strPretty += a + " : " + data[a] + "\r\n"; + } + } + } + return strPretty; + } + readFromBinaryFile(file: ArrayBuffer) { + return findEXIFinJPEG(file); + } +} + +export const exif = new EXIF() +// export function getData(img, callback) { +// const exif = new EXIF() +// exif.getData(img, callback) +// } + +// export default {getData} +const ExifTags = exif.Tags +const TiffTags = exif.TiffTags +const IFD1Tags = exif.IFD1Tags +const GPSTags = exif.GPSTags +const StringValues = exif.StringValues + + +function imageHasData(img : File) : boolean { + return !!(img.exifdata); +} + +function objectURLToBlob(url : string, callback : Function) { + try { + const http = new XMLHttpRequest(); + http.open("GET", url, true); + http.responseType = "blob"; + http.onload = function (e) { + if (this.status == 200 || this.status === 0) { + callback(this.response); + } + }; + http.send(); + } catch (e) { + console.warn(e) + } +} + + +function getImageData(img : File, callback : Function) { + function handleBinaryFile(binFile: ArrayBuffer) { + const data = findEXIFinJPEG(binFile); + img.exifdata = data ?? {}; + const iptcdata = findIPTCinJPEG(binFile); + img.iptcdata = iptcdata ?? {}; + if (exif.isXmpEnabled) { + const xmpdata = findXMPinJPEG(binFile); + img.xmpdata = xmpdata ?? {}; + } + if (callback) { + callback.call(img); + } + } + + if (img.src) { + if (/^data\:/i.test(img.src)) { // Data URI + // var arrayBuffer = base64ToArrayBuffer(img.src); + handleBinaryFile(base64ToArrayBuffer(img.src)); + + } else if (/^blob\:/i.test(img.src) && typeof FileReader !== 'undefined') { // Object URL + var fileReader = new FileReader(); + fileReader.onload = function (e) { + handleBinaryFile(e.target.result); + }; + objectURLToBlob(img.src, function (blob : Blob) { + fileReader.readAsArrayBuffer(blob); + }); + } else if (typeof XMLHttpRequest !== 'undefined') { + var http = new XMLHttpRequest(); + http.onload = function () { + if (this.status == 200 || this.status === 0) { + handleBinaryFile(http.response); + } else { + throw "Could not load image"; + } + http = null; + }; + http.open("GET", img.src, true); + http.responseType = "arraybuffer"; + http.send(null); + } else { + pathToBase64(img.src).then(res => { + handleBinaryFile(base64ToArrayBuffer(res)); + }) + } + } else if (typeof FileReader !== 'undefined' && self.FileReader && (img instanceof self.Blob || img instanceof self.File)) { + var fileReader = new FileReader(); + fileReader.onload = function (e : any) { + if (exif.debug) console.log("Got file of length " + e.target.result.byteLength); + handleBinaryFile(e.target.result); + }; + + fileReader.readAsArrayBuffer(img); + } +} + +function findEXIFinJPEG(file: ArrayBuffer) { + const dataView = new DataView(file); + + if (exif.debug) console.log("Got file of length " + file.byteLength); + if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) { + if (exif.debug) console.log("Not a valid JPEG"); + return false; // not a valid jpeg + } + + let offset = 2, + length = file.byteLength, + marker; + + while (offset < length) { + if (dataView.getUint8(offset) != 0xFF) { + if (exif.debug) console.log("Not a valid marker at offset " + offset + ", found: " + dataView.getUint8( + offset)); + return false; // not a valid marker, something is wrong + } + + marker = dataView.getUint8(offset + 1); + if (exif.debug) console.log(marker); + + // we could implement handling for other markers here, + // but we're only looking for 0xFFE1 for EXIF data + + if (marker == 225) { + if (exif.debug) console.log("Found 0xFFE1 marker"); + + return readEXIFData(dataView, offset + 4, dataView.getUint16(offset + 2) - 2); + + // offset += 2 + file.getShortAt(offset+2, true); + + } else { + offset += 2 + dataView.getUint16(offset + 2); + } + + } + +} + +function findIPTCinJPEG(file: ArrayBuffer) { + const dataView = new DataView(file); + + if (exif.debug) console.log("Got file of length " + file.byteLength); + if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) { + if (exif.debug) console.log("Not a valid JPEG"); + return false; // not a valid jpeg + } + + let offset = 2, + length = file.byteLength; + + + const isFieldSegmentStart = function (dataView, offset: number) { + return ( + dataView.getUint8(offset) === 0x38 && + dataView.getUint8(offset + 1) === 0x42 && + dataView.getUint8(offset + 2) === 0x49 && + dataView.getUint8(offset + 3) === 0x4D && + dataView.getUint8(offset + 4) === 0x04 && + dataView.getUint8(offset + 5) === 0x04 + ); + }; + + while (offset < length) { + + if (isFieldSegmentStart(dataView, offset)) { + + // Get the length of the name header (which is padded to an even number of bytes) + var nameHeaderLength = dataView.getUint8(offset + 7); + if (nameHeaderLength % 2 !== 0) nameHeaderLength += 1; + // Check for pre photoshop 6 format + if (nameHeaderLength === 0) { + // Always 4 + nameHeaderLength = 4; + } + + var startOffset = offset + 8 + nameHeaderLength; + var sectionLength = dataView.getUint16(offset + 6 + nameHeaderLength); + + return readIPTCData(file, startOffset, sectionLength); + + break; + + } + + + // Not the marker, continue searching + offset++; + + } + +} + +const IptcFieldMap = { + 0x78: 'caption', + 0x6E: 'credit', + 0x19: 'keywords', + 0x37: 'dateCreated', + 0x50: 'byline', + 0x55: 'bylineTitle', + 0x7A: 'captionWriter', + 0x69: 'headline', + 0x74: 'copyright', + 0x0F: 'category' +}; + +function readIPTCData(file: ArrayBuffer, startOffset: number, sectionLength: number) { + const dataView = new DataView(file); + let data = {}; + let fieldValue, fieldName, dataSize, segmentType, segmentSize; + let segmentStartPos = startOffset; + while (segmentStartPos < startOffset + sectionLength) { + if (dataView.getUint8(segmentStartPos) === 0x1C && dataView.getUint8(segmentStartPos + 1) === 0x02) { + segmentType = dataView.getUint8(segmentStartPos + 2); + if (segmentType in IptcFieldMap) { + dataSize = dataView.getInt16(segmentStartPos + 3); + segmentSize = dataSize + 5; + fieldName = IptcFieldMap[segmentType]; + fieldValue = getStringFromDB(dataView, segmentStartPos + 5, dataSize); + // Check if we already stored a value with this name + if (data.hasOwnProperty(fieldName)) { + // Value already stored with this name, create multivalue field + if (data[fieldName] instanceof Array) { + data[fieldName].push(fieldValue); + } else { + data[fieldName] = [data[fieldName], fieldValue]; + } + } else { + data[fieldName] = fieldValue; + } + } + + } + segmentStartPos++; + } + return data; +} + +function readTags(file: DataView, tiffStart: number, dirStart: number, strings: any[], bigEnd: number) { + let entries = file.getUint16(dirStart, !bigEnd), + tags = {}, + entryOffset, tag; + + for (let i = 0; i < entries; i++) { + entryOffset = dirStart + i * 12 + 2; + tag = strings[file.getUint16(entryOffset, !bigEnd)]; + if (!tag && exif.debug) console.log("Unknown tag: " + file.getUint16(entryOffset, !bigEnd)); + tags[tag] = readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd); + } + return tags; +} + +function readTagValue(file: DataView, entryOffset: number, tiffStart: number, dirStart: number, bigEnd: number) { + let type = file.getUint16(entryOffset + 2, !bigEnd), + numValues = file.getUint32(entryOffset + 4, !bigEnd), + valueOffset = file.getUint32(entryOffset + 8, !bigEnd) + tiffStart, + offset, + vals, val, n, + numerator, denominator; + + switch (type) { + case 1: // byte, 8-bit unsigned int + case 7: // undefined, 8-bit byte, value depending on field + if (numValues == 1) { + return file.getUint8(entryOffset + 8, !bigEnd); + } else { + offset = numValues > 4 ? valueOffset : (entryOffset + 8); + vals = []; + for (n = 0; n < numValues; n++) { + vals[n] = file.getUint8(offset + n); + } + return vals; + } + + case 2: // ascii, 8-bit byte + offset = numValues > 4 ? valueOffset : (entryOffset + 8); + return getStringFromDB(file, offset, numValues - 1); + + case 3: // short, 16 bit int + if (numValues == 1) { + return file.getUint16(entryOffset + 8, !bigEnd); + } else { + offset = numValues > 2 ? valueOffset : (entryOffset + 8); + vals = []; + for (n = 0; n < numValues; n++) { + vals[n] = file.getUint16(offset + 2 * n, !bigEnd); + } + return vals; + } + + case 4: // long, 32 bit int + if (numValues == 1) { + return file.getUint32(entryOffset + 8, !bigEnd); + } else { + vals = []; + for (n = 0; n < numValues; n++) { + vals[n] = file.getUint32(valueOffset + 4 * n, !bigEnd); + } + return vals; + } + + case 5: // rational = two long values, first is numerator, second is denominator + if (numValues == 1) { + numerator = file.getUint32(valueOffset, !bigEnd); + denominator = file.getUint32(valueOffset + 4, !bigEnd); + val = new Number(numerator / denominator); + val.numerator = numerator; + val.denominator = denominator; + return val; + } else { + vals = []; + for (n = 0; n < numValues; n++) { + numerator = file.getUint32(valueOffset + 8 * n, !bigEnd); + denominator = file.getUint32(valueOffset + 4 + 8 * n, !bigEnd); + vals[n] = new Number(numerator / denominator); + vals[n].numerator = numerator; + vals[n].denominator = denominator; + } + return vals; + } + + case 9: // slong, 32 bit signed int + if (numValues == 1) { + return file.getInt32(entryOffset + 8, !bigEnd); + } else { + vals = []; + for (n = 0; n < numValues; n++) { + vals[n] = file.getInt32(valueOffset + 4 * n, !bigEnd); + } + return vals; + } + + case 10: // signed rational, two slongs, first is numerator, second is denominator + if (numValues == 1) { + return file.getInt32(valueOffset, !bigEnd) / file.getInt32(valueOffset + 4, !bigEnd); + } else { + vals = []; + for (n = 0; n < numValues; n++) { + vals[n] = file.getInt32(valueOffset + 8 * n, !bigEnd) / file.getInt32(valueOffset + 4 + 8 * + n, !bigEnd); + } + return vals; + } + } +} +/** + * Given an IFD (Image File Directory) start offset + * returns an offset to next IFD or 0 if it's the last IFD. + */ +function getNextIFDOffset(dataView: DataView, dirStart: number, bigEnd: number) { + //the first 2bytes means the number of directory entries contains in this IFD + var entries = dataView.getUint16(dirStart, !bigEnd); + + // After last directory entry, there is a 4bytes of data, + // it means an offset to next IFD. + // If its value is '0x00000000', it means this is the last IFD and there is no linked IFD. + + return dataView.getUint32(dirStart + 2 + entries * 12, !bigEnd); // each entry is 12 bytes long +} + +function readThumbnailImage(dataView: DataView, tiffStart: number, firstIFDOffset: number, bigEnd: number) { + // get the IFD1 offset + const IFD1OffsetPointer = getNextIFDOffset(dataView, tiffStart + firstIFDOffset, bigEnd); + + if (!IFD1OffsetPointer) { + // console.log('******** IFD1Offset is empty, image thumb not found ********'); + return {}; + } else if (IFD1OffsetPointer > dataView.byteLength) { // this should not happen + // console.log('******** IFD1Offset is outside the bounds of the DataView ********'); + return {}; + } + // console.log('******* thumbnail IFD offset (IFD1) is: %s', IFD1OffsetPointer); + + let thumbTags : any = readTags(dataView, tiffStart, tiffStart + IFD1OffsetPointer, IFD1Tags, bigEnd) + + // EXIF 2.3 specification for JPEG format thumbnail + + // If the value of Compression(0x0103) Tag in IFD1 is '6', thumbnail image format is JPEG. + // Most of Exif image uses JPEG format for thumbnail. In that case, you can get offset of thumbnail + // by JpegIFOffset(0x0201) Tag in IFD1, size of thumbnail by JpegIFByteCount(0x0202) Tag. + // Data format is ordinary JPEG format, starts from 0xFFD8 and ends by 0xFFD9. It seems that + // JPEG format and 160x120pixels of size are recommended thumbnail format for Exif2.1 or later. + + if (thumbTags['Compression'] && typeof Blob !== 'undefined') { + // console.log('Thumbnail image found!'); + + switch (thumbTags['Compression']) { + case 6: + // console.log('Thumbnail image format is JPEG'); + if (thumbTags.JpegIFOffset && thumbTags.JpegIFByteCount) { + // extract the thumbnail + var tOffset = tiffStart + thumbTags.JpegIFOffset; + var tLength = thumbTags.JpegIFByteCount; + thumbTags['blob'] = new Blob([new Uint8Array(dataView.buffer, tOffset, tLength)], { + type: 'image/jpeg' + }); + } + break; + + case 1: + console.log("Thumbnail image format is TIFF, which is not implemented."); + break; + default: + console.log("Unknown thumbnail image format '%s'", thumbTags['Compression']); + } + } else if (thumbTags['PhotometricInterpretation'] == 2) { + console.log("Thumbnail image format is RGB, which is not implemented."); + } + return thumbTags; +} + +function getStringFromDB(buffer: DataView, start: number, length: number) { + let outstr = ""; + for (let n = start; n < start + length; n++) { + outstr += String.fromCharCode(buffer.getUint8(n)); + } + return outstr; +} + +function readEXIFData(file: DataView, start: number) { + if (getStringFromDB(file, start, 4) != "Exif") { + if (exif.debug) console.log("Not valid EXIF data! " + getStringFromDB(file, start, 4)); + return false; + } + + let bigEnd, + tags, tag, + exifData, gpsData, + tiffOffset = start + 6; + + // test for TIFF validity and endianness + if (file.getUint16(tiffOffset) == 0x4949) { + bigEnd = false; + } else if (file.getUint16(tiffOffset) == 0x4D4D) { + bigEnd = true; + } else { + if (exif.debug) console.log("Not valid TIFF data! (no 0x4949 or 0x4D4D)"); + return false; + } + + if (file.getUint16(tiffOffset + 2, !bigEnd) != 0x002A) { + if (exif.debug) console.log("Not valid TIFF data! (no 0x002A)"); + return false; + } + + const firstIFDOffset = file.getUint32(tiffOffset + 4, !bigEnd); + + if (firstIFDOffset < 0x00000008) { + if (exif.debug) console.log("Not valid TIFF data! (First offset less than 8)", file.getUint32(tiffOffset + 4, + !bigEnd)); + return false; + } + + tags = readTags(file, tiffOffset, tiffOffset + firstIFDOffset, TiffTags, bigEnd); + + if (tags.ExifIFDPointer) { + exifData = readTags(file, tiffOffset, tiffOffset + tags.ExifIFDPointer, ExifTags, bigEnd); + for (tag in exifData) { + switch (tag) { + case "LightSource": + case "Flash": + case "MeteringMode": + case "ExposureProgram": + case "SensingMethod": + case "SceneCaptureType": + case "SceneType": + case "CustomRendered": + case "WhiteBalance": + case "GainControl": + case "Contrast": + case "Saturation": + case "Sharpness": + case "SubjectDistanceRange": + case "FileSource": + exifData[tag] = StringValues[tag][exifData[tag]]; + break; + + case "ExifVersion": + case "FlashpixVersion": + exifData[tag] = String.fromCharCode(exifData[tag][0], exifData[tag][1], exifData[tag][2], + exifData[tag][3]); + break; + + case "ComponentsConfiguration": + exifData[tag] = + StringValues.Components[exifData[tag][0]] + + StringValues.Components[exifData[tag][1]] + + StringValues.Components[exifData[tag][2]] + + StringValues.Components[exifData[tag][3]]; + break; + } + tags[tag] = exifData[tag]; + } + } + + if (tags.GPSInfoIFDPointer) { + gpsData = readTags(file, tiffOffset, tiffOffset + tags.GPSInfoIFDPointer, GPSTags, bigEnd); + for (tag in gpsData) { + switch (tag) { + case "GPSVersionID": + gpsData[tag] = gpsData[tag][0] + + "." + gpsData[tag][1] + + "." + gpsData[tag][2] + + "." + gpsData[tag][3]; + break; + } + tags[tag] = gpsData[tag]; + } + } + + // extract thumbnail + tags['thumbnail'] = readThumbnailImage(file, tiffOffset, firstIFDOffset, bigEnd); + + return tags; +} + +function findXMPinJPEG(file: ArrayBuffer) { + + if (!('DOMParser' in self)) { + // console.warn('XML parsing not supported without DOMParser'); + return; + } + const dataView = new DataView(file); + + if (exif.debug) console.log("Got file of length " + file.byteLength); + if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) { + if (exif.debug) console.log("Not a valid JPEG"); + return false; // not a valid jpeg + } + + let offset = 2, + length = file.byteLength, + dom = new DOMParser(); + + while (offset < (length - 4)) { + if (getStringFromDB(dataView, offset, 4) == "http") { + const startOffset = offset - 1; + const sectionLength = dataView.getUint16(offset - 2) - 1; + let xmpString = getStringFromDB(dataView, startOffset, sectionLength) + const xmpEndIndex = xmpString.indexOf('xmpmeta>') + 8; + xmpString = xmpString.substring(xmpString.indexOf(' 0) { + json['@attributes'] = {}; + for (var j = 0; j < xml.attributes.length; j++) { + var attribute = xml.attributes.item(j); + json['@attributes'][attribute.nodeName] = attribute.nodeValue; + } + } + } else if (xml.nodeType == 3) { // text node + return xml.nodeValue; + } + + // deal with children + if (xml.hasChildNodes()) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes.item(i); + var nodeName = child.nodeName; + if (json[nodeName] == null) { + json[nodeName] = xml2json(child); + } else { + if (json[nodeName].push == null) { + var old = json[nodeName]; + json[nodeName] = []; + json[nodeName].push(old); + } + json[nodeName].push(xml2json(child)); + } + } + } + + return json; +} + +function xml2Object(xml: any) { + try { + var obj = {}; + if (xml.children.length > 0) { + for (var i = 0; i < xml.children.length; i++) { + var item = xml.children.item(i); + var attributes = item.attributes; + for (var idx in attributes) { + var itemAtt = attributes[idx]; + var dataKey = itemAtt.nodeName; + var dataValue = itemAtt.nodeValue; + + if (dataKey !== undefined) { + obj[dataKey] = dataValue; + } + } + var nodeName = item.nodeName; + + if (typeof (obj[nodeName]) == "undefined") { + obj[nodeName] = xml2json(item); + } else { + if (typeof (obj[nodeName].push) == "undefined") { + var old = obj[nodeName]; + + obj[nodeName] = []; + obj[nodeName].push(old); + } + obj[nodeName].push(xml2json(item)); + } + } + } else { + obj = xml.textContent; + } + return obj; + } catch (e) { + console.log(e.message); + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/fillZero/index.ts b/QXTfront/uni_modules/lime-shared/fillZero/index.ts new file mode 100644 index 0000000..9952c45 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/fillZero/index.ts @@ -0,0 +1,11 @@ +// @ts-nocheck +/** + * 在数字前填充零,返回字符串形式的结果 + * @param number 要填充零的数字 + * @param length 填充零后的字符串长度,默认为2 + * @returns 填充零后的字符串 + */ +export function fillZero(number: number, length: number = 2): string { + // 将数字转换为字符串,然后使用 padStart 方法填充零到指定长度 + return `${number}`.padStart(length, '0'); +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/floatAdd/index.ts b/QXTfront/uni_modules/lime-shared/floatAdd/index.ts new file mode 100644 index 0000000..aad3929 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/floatAdd/index.ts @@ -0,0 +1,36 @@ +import { isNumber } from '../isNumber' +/** + * 返回两个浮点数相加的结果 + * @param num1 第一个浮点数 + * @param num2 第二个浮点数 + * @returns 两个浮点数的相加结果 + */ +export function floatAdd(num1 : number, num2 : number) : number { + // 检查 num1 和 num2 是否为数字类型 + if (!(isNumber(num1) || isNumber(num2))) { + console.warn('Please pass in the number type'); + return NaN; + } + + let r1 : number, r2 : number, m : number; + + try { + // 获取 num1 小数点后的位数 + r1 = num1.toString().split('.')[1].length; + } catch (error) { + r1 = 0; + } + + try { + // 获取 num2 小数点后的位数 + r2 = num2.toString().split('.')[1].length; + } catch (error) { + r2 = 0; + } + + // 计算需要扩大的倍数 + m = Math.pow(10, Math.max(r1, r2)); + + // 返回相加结果 + return (num1 * m + num2 * m) / m; +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/floatDiv/index.ts b/QXTfront/uni_modules/lime-shared/floatDiv/index.ts new file mode 100644 index 0000000..195d4ab --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/floatDiv/index.ts @@ -0,0 +1,45 @@ +import { floatMul } from '../floatMul'; +import { isNumber } from '../isNumber'; + +/** + * 除法函数,用于处理浮点数除法并保持精度。 + * @param {number} num1 - 被除数。 + * @param {number} num2 - 除数。 + * @returns {number} 除法运算的结果,保留正确的精度。 + */ +export function floatDiv(num1:number, num2:number):number { + // 如果传入的不是数字类型,则打印警告并返回NaN + if (!isNumber(num1) || !isNumber(num2)) { + console.warn('请传入数字类型'); + return NaN; + } + + let m1 = 0, // 被除数小数点后的位数 + m2 = 0, // 除数小数点后的位数 + s1 = num1.toString(), // 将被除数转换为字符串 + s2 = num2.toString(); // 将除数转换为字符串 + + // 计算被除数小数点后的位数 + try { + m1 += s1.split('.')[1].length; + } catch (error) {} + + // 计算除数小数点后的位数 + try { + m2 += s2.split('.')[1].length; + } catch (error) {} + + // 进行除法运算并处理小数点后的位数,使用之前定义的乘法函数保持精度 + // #ifdef APP-ANDROID + return floatMul( + parseFloat(s1.replace('.', '')) / parseFloat(s2.replace('.', '')), + Math.pow(10, m2 - m1), + ); + // #endif + // #ifndef APP-ANDROID + return floatMul( + Number(s1.replace('.', '')) / Number(s2.replace('.', '')), + Math.pow(10, m2 - m1), + ); + // #endif +} diff --git a/QXTfront/uni_modules/lime-shared/floatMul/index.ts b/QXTfront/uni_modules/lime-shared/floatMul/index.ts new file mode 100644 index 0000000..51a867e --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/floatMul/index.ts @@ -0,0 +1,44 @@ +// @ts-nocheck +import {isNumber} from '../isNumber'; +// #ifdef APP-ANDROID +import BigDecimal from 'java.math.BigDecimal' +// import BigDecimal from 'java.math.BigDecimal' +// import StringBuilder from 'java.lang.StringBuilder' +// import java.math.BigDecimal; +// #endif + +/** + * 乘法函数,用于处理浮点数乘法并保持精度。 + * @param {number} num1 - 第一个乘数。 + * @param {number} num2 - 第二个乘数。 + * @returns {number} 乘法运算的结果,保留正确的精度。 + */ +export function floatMul(num1 : number, num2 : number) : number { + if (!(isNumber(num1) || isNumber(num2))) { + console.warn('Please pass in the number type'); + return NaN; + } + let m = 0; + // #ifdef APP-ANDROID + let s1 = BigDecimal.valueOf(num1.toDouble()).toPlainString(); //new UTSNumber(num1).toString() // //`${num1.toFloat()}`// num1.toString(), + let s2 = BigDecimal.valueOf(num2.toDouble()).toPlainString(); //new UTSNumber(num2).toString() //`${num2.toFloat()}`//.toString(); + // #endif + // #ifndef APP-ANDROID + let s1:string = `${num1}`// num1.toString(), + let s2:string = `${num2}`//.toString(); + // #endif + + try { + m += s1.split('.')[1].length; + } catch (error) { } + try { + m += s2.split('.')[1].length; + } catch (error) { } + + // #ifdef APP-ANDROID + return parseFloat(s1.replace('.', '')) * parseFloat(s2.replace('.', '')) / Math.pow(10, m); + // #endif + // #ifndef APP-ANDROID + return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m); + // #endif +} diff --git a/QXTfront/uni_modules/lime-shared/floatSub/index.ts b/QXTfront/uni_modules/lime-shared/floatSub/index.ts new file mode 100644 index 0000000..9bc25cb --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/floatSub/index.ts @@ -0,0 +1,32 @@ +import { isNumber } from '../isNumber'; +/** + * 减法函数,用于处理浮点数减法并保持精度。 + * @param {number} num1 - 被减数。 + * @param {number} num2 - 减数。 + * @returns {number} 减法运算的结果,保留正确的精度。 + */ +export function floatSub(num1 : number, num2 : number) : number { + if (!(isNumber(num1) || isNumber(num2))) { + console.warn('Please pass in the number type'); + return NaN; + } + let r1:number, r2:number, m:number, n:number; + try { + r1 = num1.toString().split('.')[1].length; + } catch (error) { + r1 = 0; + } + try { + r2 = num2.toString().split('.')[1].length; + } catch (error) { + r2 = 0; + } + m = Math.pow(10, Math.max(r1, r2)); + n = r1 >= r2 ? r1 : r2; + // #ifndef APP-ANDROID + return Number(((num1 * m - num2 * m) / m).toFixed(n)); + // #endif + // #ifdef APP-ANDROID + return parseFloat(((num1 * m - num2 * m) / m).toFixed(n)); + // #endif +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/getClassStr/index.ts b/QXTfront/uni_modules/lime-shared/getClassStr/index.ts new file mode 100644 index 0000000..34a26d2 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/getClassStr/index.ts @@ -0,0 +1,53 @@ +// @ts-nocheck + +// #ifdef UNI-APP-X && APP +import { isNumber } from '../isNumber' +import { isString } from '../isString' +import { isDef } from '../isDef' +// #endif + +/** + * 获取对象的类名字符串 + * @param obj - 需要处理的对象 + * @returns 由对象属性作为类名组成的字符串 + */ +export function getClassStr(obj : T) : string { + let classNames : string[] = []; + // #ifdef APP-ANDROID + if (obj instanceof UTSJSONObject) { + (obj as UTSJSONObject).toMap().forEach((value, key) => { + if (isDef(value)) { + if (isNumber(value)) { + classNames.push(key); + } + if (isString(value) && value !== '') { + classNames.push(key); + } + if (typeof value == 'boolean' && (value as boolean)) { + classNames.push(key); + } + } + }) + } + // #endif + // #ifndef APP-ANDROID + // 遍历对象的属性 + for (let key in obj) { + // 检查属性确实属于对象自身且其值为true + if ((obj as any).hasOwnProperty(key) && obj[key]) { + // 将属性名添加到类名数组中 + classNames.push(key); + } + } + // #endif + + + // 将类名数组用空格连接成字符串并返回 + return classNames.join(' '); +} + + +// 示例 +// const obj = { foo: true, bar: false, baz: true }; +// const classNameStr = getClassStr(obj); +// console.log(classNameStr); // 输出: "foo baz" \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/getCurrentPage/index.ts b/QXTfront/uni_modules/lime-shared/getCurrentPage/index.ts new file mode 100644 index 0000000..eaf4523 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/getCurrentPage/index.ts @@ -0,0 +1,11 @@ +// @ts-nocheck +// #ifndef UNI-APP-X && APP +// export * from './vue.ts' +export { getCurrentPage } from './vue.ts' +// #endif + + +// #ifdef UNI-APP-X && APP +// export * from './uvue.uts' +export { getCurrentPage } from './uvue.uts' +// #endif diff --git a/QXTfront/uni_modules/lime-shared/getCurrentPage/uvue.uts b/QXTfront/uni_modules/lime-shared/getCurrentPage/uvue.uts new file mode 100644 index 0000000..9e96d2b --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/getCurrentPage/uvue.uts @@ -0,0 +1,5 @@ +// @ts-nocheck +export const getCurrentPage = ():Page => { + const pages = getCurrentPages(); + return pages[pages.length - 1] +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/getCurrentPage/vue.ts b/QXTfront/uni_modules/lime-shared/getCurrentPage/vue.ts new file mode 100644 index 0000000..79ecac8 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/getCurrentPage/vue.ts @@ -0,0 +1,6 @@ +// @ts-nocheck +/** 获取当前页 */ +export const getCurrentPage = () => { + const pages = getCurrentPages(); + return pages[pages.length - 1] //as T & WechatMiniprogram.Page.TrivialInstance; +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/getLocalFilePath/index.ts b/QXTfront/uni_modules/lime-shared/getLocalFilePath/index.ts new file mode 100644 index 0000000..c496a07 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/getLocalFilePath/index.ts @@ -0,0 +1,62 @@ +// @ts-nocheck +// #ifdef APP-NVUE || APP-VUE +export const getLocalFilePath = (path : string) => { + if (typeof plus == 'undefined') return path + if (/^(_www|_doc|_documents|_downloads|file:\/\/|\/storage\/emulated\/0\/)/.test(path)) return path + if (/^\//.test(path)) { + const localFilePath = plus.io.convertAbsoluteFileSystem(path) + if (localFilePath !== path) { + return localFilePath + } else { + path = path.slice(1) + } + } + return '_www/' + path +} +// #endif + + +// #ifdef UNI-APP-X && APP +export { getResourcePath as getLocalFilePath } from '@/uni_modules/lime-file-utils' +// export const getLocalFilePath = (path : string) : string => { +// let uri = path +// if (uri.startsWith("http") || uri.startsWith(" { +// try { +// let uri = path +// if (uri.startsWith("http") || uri.startsWith(" { + return new Promise(resolve => { + uni.createSelectorQuery() + .selectViewport() + .scrollOffset((res) => { + resolve(res); + }).exec(); + }) +} + +/** +``` + page + ╱ + ╭───────────────╮ viewport + ╭─│─ ─ ─ ─ ─ ─ ─ ─│─╮ ╱ + │ │ ╭───────────╮ │ │ + │ │ │ element │ │ │ + │ │ ╰───────────╯ │ │ + ╰─│─ ─ ─ ─ ─ ─ ─ ─│─╯ + │ │ + │ │ + ╰───────────────╯ +``` + +# 参数 +- viewportHeight: viewport 高度 +- viewportScrollTop: viewport 垂直滚动值 +- elementHeight: element 高度 +- elementOffsetTop: element 距离页面顶部距离 + +# 选项 +- position: element 在视窗中的位置(start, center, end, nearest) +- startOffset: element 距离视窗顶部的偏移量 +- endOffset: element 距离视窗底部的偏移量 + +# 结果值 +- viewportScrollTop: viewport 新的垂直滚动值 + +*/ + +export type ScrollIntoViewOptions = { + /** 元素顶部需要保留的缓冲距离(默认 0) */ + startOffset ?: number; + /** 元素底部需要保留的缓冲距离(默认 0) */ + endOffset ?: number; + /** 滚动对齐方式:start/center/end/nearest(默认 nearest) */ + position ?: 'start' | 'center' | 'end' | 'nearest'; +} + +/** + * 计算元素需要滚动到可视区域的目标滚动位置 + * @param viewportHeight 视口高度(像素) + * @param viewportScrollTop 当前滚动位置(像素) + * @param elementHeight 元素高度(像素) + * @param elementOffsetTop 元素相对于父容器顶部的偏移量(像素) + * @param options 配置选项 + * @returns 计算后的目标滚动位置(像素) + * + * @example + * // 示例:将元素滚动到视口顶部对齐 + * const scrollTop = getScrollIntoViewValue( + * 500, // 视口高度 + * 200, // 当前滚动位置 + * 100, // 元素高度 + * 300, // 元素偏移量 + * { position: 'start' } + * ); + */ +export function getScrollIntoViewValue( + viewportHeight : number, + viewportScrollTop : number, + elementHeight : number, + elementOffsetTop : number, + options : ScrollIntoViewOptions = {} +) : number { + let { startOffset = 0, endOffset = 0, position = 'nearest'} = options; + + // 计算元素相对于视口的上下偏移量 + const elementToViewportTopOffset = elementOffsetTop - viewportScrollTop - startOffset; + const elementToViewportBottomOffset = + elementOffsetTop + + elementHeight - + viewportScrollTop - + viewportHeight + + endOffset; + + // 处理 nearest 模式,自动选择最近边缘 + if (position == 'nearest') { + if (elementToViewportTopOffset >= 0 && elementToViewportBottomOffset <= 0) { + return viewportScrollTop; + } + position = + Math.abs(elementToViewportTopOffset) > Math.abs(elementToViewportBottomOffset) + ? 'end' + : 'start'; + } + + // 根据不同的对齐位置计算目标滚动位置 + let nextScrollTop = 0; + switch (position) { + case 'start': + // 顶部对齐:元素顶部对齐视口顶部(考虑顶部缓冲) + nextScrollTop = elementOffsetTop - startOffset; + break; + case 'center': + // 居中对齐:元素中心对齐视口中心(考虑上下缓冲) + nextScrollTop = + elementOffsetTop - + (viewportHeight - elementHeight - endOffset - startOffset) / 2 + + startOffset; + break; + case 'end': + // 底部对齐:元素底部对齐视口底部(考虑底部缓冲) + nextScrollTop = + elementOffsetTop + elementHeight - viewportHeight + endOffset; + break; + } + + return nextScrollTop; +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/getRect/uvue.uts b/QXTfront/uni_modules/lime-shared/getRect/uvue.uts new file mode 100644 index 0000000..05f16ee --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/getRect/uvue.uts @@ -0,0 +1,17 @@ +// @ts-nocheck +export function getRect(selector : string, context: ComponentPublicInstance):Promise { + return new Promise((resolve)=>{ + uni.createSelectorQuery().in(context).select(selector).boundingClientRect(res =>{ + resolve(res as NodeInfo) + }).exec(); + }) +} + +export function getAllRect(selector : string, context: ComponentPublicInstance):Promise { + return new Promise((resolve)=>{ + uni.createSelectorQuery().in(context).selectAll(selector).boundingClientRect(res =>{ + resolve(res as NodeInfo[]) + }).exec(); + }) +} + diff --git a/QXTfront/uni_modules/lime-shared/getRect/vue.ts b/QXTfront/uni_modules/lime-shared/getRect/vue.ts new file mode 100644 index 0000000..e44b60e --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/getRect/vue.ts @@ -0,0 +1,117 @@ +// @ts-nocheck + +// #ifdef APP-NVUE +// 当编译环境是 APP-NVUE 时,引入 uni.requireNativePlugin('dom'),具体插件用途未知 +const dom = uni.requireNativePlugin('dom') +// #endif + +/** + * 获取节点信息 + * @param selector 选择器字符串 + * @param context ComponentInternalInstance 对象 + * @param node 是否获取node + * @returns 包含节点信息的 Promise 对象 + */ +export function getRect(selector : string, context : ComponentInternalInstance|ComponentPublicInstance, node: boolean = false) { + // 之前是个对象,现在改成实例,防止旧版会报错 + if(context== null) { + return Promise.reject('context is null') + } + if(context.context){ + context = context.context + } + // #ifdef MP || VUE2 + if (context.proxy) context = context.proxy + // #endif + return new Promise((resolve, reject) => { + // #ifndef APP-NVUE + const dom = uni.createSelectorQuery().in(context).select(selector); + const result = (rect: UniNamespace.NodeInfo) => { + if (rect) { + resolve(rect) + } else { + reject('no rect') + } + } + + if (!node) { + dom.boundingClientRect(result).exec() + } else { + dom.fields({ + node: true, + size: true, + rect: true + }, result).exec() + } + // #endif + // #ifdef APP-NVUE + const refs = context.refs || context.$refs + if (/#|\./.test(selector) && refs) { + selector = selector.replace(/#|\./, '') + if (refs[selector]) { + selector = refs[selector] + if(Array.isArray(selector)) { + selector = selector[0] + } + } + } + dom.getComponentRect(selector, (res) => { + if (res.size) { + resolve(res.size) + } else { + reject('no rect') + } + }) + // #endif + }); +}; + + +export function getAllRect(selector : string, context: ComponentInternalInstance|ComponentPublicInstance, node:boolean = false) { + if(context== null) { + return Promise.reject('context is null') + } + // #ifdef MP || VUE2 + if (context.proxy) context = context.proxy + // #endif + return new Promise((resolve, reject) => { + // #ifndef APP-NVUE + const dom = uni.createSelectorQuery().in(context).selectAll(selector); + const result = (rect: UniNamespace.NodeInfo[]) => { + if (rect) { + resolve(rect) + } else { + reject('no rect') + } + } + if (!node) { + dom.boundingClientRect(result).exec() + } else { + dom.fields({ + node: true, + size: true, + rect: true + }, result).exec() + } + // #endif + // #ifdef APP-NVUE + let { context } = options + if (/#|\./.test(selector) && context.refs) { + selector = selector.replace(/#|\./, '') + if (context.refs[selector]) { + selector = context.refs[selector] + if(Array.isArray(selector)) { + selector = selector[0] + } + } + } + dom.getComponentRect(selector, (res) => { + if (res.size) { + resolve([res.size]) + } else { + reject('no rect') + } + }) + // #endif + }); +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/getStyleStr/index.ts b/QXTfront/uni_modules/lime-shared/getStyleStr/index.ts new file mode 100644 index 0000000..665941c --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/getStyleStr/index.ts @@ -0,0 +1,54 @@ +// @ts-nocheck +// #ifndef UNI-APP-X && APP +interface CSSProperties { + [key : string] : string | number | null +} +// #endif + +// #ifdef VUE3 +// #ifdef UNI-APP-X && APP +type CSSProperties = UTSJSONObject +// #endif +// #endif +/** + * 将字符串转换为带有连字符分隔的小写形式 + * @param key - 要转换的字符串 + * @returns 转换后的字符串 + */ +export function toLowercaseSeparator(key : string):string { + return key.replace(/([A-Z])/g, '-$1').toLowerCase(); +} + +/** + * 获取样式对象对应的样式字符串 + * @param style - CSS样式对象 + * @returns 由非空有效样式属性键值对组成的字符串 + */ +export function getStyleStr(style : CSSProperties) : string { + + // #ifdef UNI-APP-X && APP + let styleStr = ''; + style.toMap().forEach((value, key) => { + if(value !== null && value != '') { + styleStr += `${toLowercaseSeparator(key as string)}: ${value};` + } + }) + return styleStr + // #endif + // #ifndef UNI-APP-X && APP + return Object.keys(style) + .filter( + (key) => + style[key] !== undefined && + style[key] !== null && + style[key] !== '') + .map((key : string) => `${toLowercaseSeparator(key)}: ${style[key]};`) + .join(' '); + // #endif +} + +// 示例 +// const style = { color: 'red', fontSize: '16px', backgroundColor: '', border: null }; +// const styleStr = getStyleStr(style); +// console.log(styleStr); +// 输出: "color: red; font-size: 16px;" \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/guid/index.ts b/QXTfront/uni_modules/lime-shared/guid/index.ts new file mode 100644 index 0000000..675b250 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/guid/index.ts @@ -0,0 +1,28 @@ +/** + * 生成指定长度的伪随机字符串,通常用作唯一标识符(非标准GUID) + * + * 此函数使用Math.random()生成基于36进制(数字+小写字母)的随机字符串。当长度超过11位时, + * 会通过递归拼接多个随机段实现。注意:该方法生成的并非标准GUID/UUID,不适合高安全性场景。 + * + * @param {number} [len=32] - 要生成的字符串长度,默认32位 + * @returns {string} 生成的伪随机字符串,包含0-9和a-z字符 + * + * @example + * guid(); // 返回32位字符串,例如"3zyf6a5f3kb4ayy9jq9v1a70z0qdm0bk" + * guid(5); // 返回5位字符串,例如"kf3a9" + * guid(20); // 返回20位字符串,由两段随机字符串拼接而成 + * + * @note + * 1. 由于使用Math.random(),随机性存在安全缺陷,不适用于密码学用途 + * 2. 当长度>11时采用递归拼接,可能略微影响性能(在极端大长度情况下) + * 3. 字符串补全时使用'0'填充,可能略微降低末尾字符的随机性 + */ +export function guid(len:number = 32):string { + // crypto.randomUUID(); + return len <= 11 + ? Math.random() + .toString(36) + .substring(2, 2 + len) + .padEnd(len, '0') + : guid(11) + guid(len - 11); +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/hasOwn/index.ts b/QXTfront/uni_modules/lime-shared/hasOwn/index.ts new file mode 100644 index 0000000..4c665ca --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/hasOwn/index.ts @@ -0,0 +1,11 @@ +// @ts-nocheck +// #ifdef UNI-APP-X && APP +// export * from './uvue.uts' +export { hasOwn } from './uvue.uts' +// #endif + + +// #ifndef UNI-APP-X && APP +// export * from './vue.ts' +export { hasOwn } from './vue.ts' +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/hasOwn/uvue.uts b/QXTfront/uni_modules/lime-shared/hasOwn/uvue.uts new file mode 100644 index 0000000..553ccdd --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/hasOwn/uvue.uts @@ -0,0 +1,43 @@ +// @ts-nocheck +/** + * 检查对象或数组是否具有指定的属性或键 + * @param obj 要检查的对象或数组 + * @param key 指定的属性或键 + * @returns 如果对象或数组具有指定的属性或键,则返回true;否则返回false + */ +function hasOwn(obj: UTSJSONObject, key: string): boolean +function hasOwn(obj: Map, key: string): boolean +function hasOwn(obj: any, key: string): boolean { + if(obj instanceof UTSJSONObject){ + return obj[key] != null + } + if(obj instanceof Map){ + return (obj as Map).has(key) + } + if(typeof obj == 'object') { + const obj2 = {...toRaw(obj)} + return obj2[key] != null + } + return false +} +export { + hasOwn +} +// 示例 +// const obj = { name: 'John', age: 30 }; + +// if (hasOwn(obj, 'name')) { +// console.log("对象具有 'name' 属性"); +// } else { +// console.log("对象不具有 'name' 属性"); +// } +// // 输出: 对象具有 'name' 属性 + +// const arr = [1, 2, 3]; + +// if (hasOwn(arr, 'length')) { +// console.log("数组具有 'length' 属性"); +// } else { +// console.log("数组不具有 'length' 属性"); +// } +// 输出: 数组具有 'length' 属性 \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/hasOwn/vue.ts b/QXTfront/uni_modules/lime-shared/hasOwn/vue.ts new file mode 100644 index 0000000..7317879 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/hasOwn/vue.ts @@ -0,0 +1,30 @@ +// @ts-nocheck +const hasOwnProperty = Object.prototype.hasOwnProperty +/** + * 检查对象或数组是否具有指定的属性或键 + * @param obj 要检查的对象或数组 + * @param key 指定的属性或键 + * @returns 如果对象或数组具有指定的属性或键,则返回true;否则返回false + */ +export function hasOwn(obj: Object | Array, key: string): boolean { + return hasOwnProperty.call(obj, key); +} + +// 示例 +// const obj = { name: 'John', age: 30 }; + +// if (hasOwn(obj, 'name')) { +// console.log("对象具有 'name' 属性"); +// } else { +// console.log("对象不具有 'name' 属性"); +// } +// // 输出: 对象具有 'name' 属性 + +// const arr = [1, 2, 3]; + +// if (hasOwn(arr, 'length')) { +// console.log("数组具有 'length' 属性"); +// } else { +// console.log("数组不具有 'length' 属性"); +// } +// 输出: 数组具有 'length' 属性 \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/index.ts b/QXTfront/uni_modules/lime-shared/index.ts new file mode 100644 index 0000000..2eb1d94 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/index.ts @@ -0,0 +1,43 @@ +// @ts-nocheck +// validator +// export * from './isString' +// export * from './isNumber' +// export * from './isNumeric' +// export * from './isDef' +// export * from './isFunction' +// export * from './isObject' +// export * from './isPromise' +// export * from './isBase64' + +// export * from './hasOwn' + +// // 单位转换 +// export * from './addUnit' +// export * from './unitConvert' +// export * from './toNumber' + +// export * from './random' +// export * from './range' +// export * from './fillZero' + +// // image +// export * from './base64ToPath' +// export * from './pathToBase64' +// export * from './exif' + +// // canvas +// export * from './canIUseCanvas2d' + +// // page +// export * from './getCurrentPage' + +// // dom +// export * from './getRect' +// export * from './selectComponent' +// export * from './createAnimation' + +// // delay +// export * from './sleep' +// export * from './debounce' +// export * from './throttle' + diff --git a/QXTfront/uni_modules/lime-shared/isBase64/index.ts b/QXTfront/uni_modules/lime-shared/isBase64/index.ts new file mode 100644 index 0000000..53e065d --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isBase64/index.ts @@ -0,0 +1,23 @@ +// @ts-nocheck + +/** + * 判断一个字符串是否为Base64编码。 + * Base64编码的字符串只包含A-Z、a-z、0-9、+、/ 和 = 这些字符。 + * @param {string} str - 要检查的字符串。 + * @returns {boolean} 如果字符串是Base64编码,返回true,否则返回false。 + */ +export function isBase64(str: string): boolean { + const base64Regex = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/; + return base64Regex.test(str); +} + +/** + * 判断一个字符串是否为Base64编码的data URI。 + * Base64编码的data URI通常以"data:"开头,后面跟着MIME类型和编码信息,然后是Base64编码的数据。 + * @param {string} str - 要检查的字符串。 + * @returns {boolean} 如果字符串是Base64编码的data URI,返回true,否则返回false。 + */ +export function isDataURI(str: string): boolean { + const dataUriRegex = /^data:([a-zA-Z]+\/[a-zA-Z0-9-+.]+)(;base64)?,([a-zA-Z0-9+/]+={0,2})$/; + return dataUriRegex.test(str); +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isBoolean/index.ts b/QXTfront/uni_modules/lime-shared/isBoolean/index.ts new file mode 100644 index 0000000..8816788 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isBoolean/index.ts @@ -0,0 +1,24 @@ +/** + * 检查一个值是否为严格的布尔值(仅限 `true` 或 `false`) + * + * @example + * isBoolean(true); // true + * isBoolean(false); // true + * isBoolean(0); // false + * isBoolean(null); // false + * + * @param {unknown} value - 要检查的值 + * @returns {value is boolean} 如果值是 `true` 或 `false` 则返回 `true`,否则返回 `false` + * + * @description + * 此函数使用严格相等(`===`)检查,避免隐式类型转换。 + * 注意:不适用于 `Boolean` 包装对象(如 `new Boolean(true)`)。 + */ +export function isBoolean(value: any|null): boolean { + // #ifdef APP-ANDROID + return value == true || value == false + // #endif + // #ifndef APP-ANDROID + return value === true || value === false + // #endif +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isBrowser/index.ts b/QXTfront/uni_modules/lime-shared/isBrowser/index.ts new file mode 100644 index 0000000..6baee2b --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isBrowser/index.ts @@ -0,0 +1,8 @@ +// @ts-nocheck +// #ifdef WEB +export const isBrowser = typeof window !== 'undefined'; +// #endif + +// #ifndef WEB +export const isBrowser = false; +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isByteLength/index.ts b/QXTfront/uni_modules/lime-shared/isByteLength/index.ts new file mode 100644 index 0000000..73774d8 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isByteLength/index.ts @@ -0,0 +1,86 @@ +// @ts-nocheck +// import assertString from './util/assertString'; + +/** + * 字节长度验证配置选项 + */ +export type IsByteLengthOptions = { + /** 允许的最小字节长度 */ + min ?: number; + /** 允许的最大字节长度 */ + max ?: number; +} + +/** + * 检查字符串字节长度是否在指定范围内 + * @function + * @overload 使用配置对象 + * @param str - 要检查的字符串 + * @param options - 配置选项对象 + * @returns 是否满足字节长度要求 + * + * @overload 使用独立参数 + * @param str - 要检查的字符串 + * @param min - 最小字节长度 + * @param max - 最大字节长度(可选) + * @returns 是否满足字节长度要求 + * + * @example + * // 使用配置对象 + * isByteLength('🇨🇳', { min: 4, max: 8 }); // true(unicode 国旗符号占 8 字节) + * + * @example + * // 旧式参数调用 + * isByteLength('hello', 3, 7); // true(实际字节长度 5) + * + * @description + * 1. 使用 URL 编码计算字节长度(更准确处理多字节字符) + * 2. 同时支持两种参数格式: + * - 配置对象格式 { min, max } + * - 独立参数格式 (min, max) + * 3. 不传 max 参数时只验证最小长度 + * 4. 严格空值处理,允许设置 0 值 + */ +export function isByteLength(str : string, optionsOrMin ?: IsByteLengthOptions) : boolean; +export function isByteLength(str : string, optionsOrMin ?: number) : boolean; +export function isByteLength(str : string, optionsOrMin : number, maxParam : number | null) : boolean; +export function isByteLength( + str : string, + optionsOrMin ?: IsByteLengthOptions | number, + maxParam : number | null = null +) : boolean { + // assertString(str); + + /** 最终计算的最小长度 */ + let min: number; + + /** 最终计算的最大长度 */ + let max : number | null; + + // 参数逻辑处理 + if (optionsOrMin != null && typeof optionsOrMin == 'object') { + // 使用对象配置的情况 + const options = optionsOrMin as IsByteLengthOptions; + min = Math.max(options.min ?? 0, 0); // 确保最小值为正整数 + max = options.max; + } else { + // 使用独立参数的情况 + min = Math.max( + typeof optionsOrMin == 'number' ? optionsOrMin : 0, + 0 + ); + max = maxParam; + } + + // URL 编码后的字节长度计算 + const encoded = encodeURI(str); + const len = (encoded?.split(/%..|./).length ?? 0) - 1; + + // 执行验证逻辑 + // #ifndef APP-ANDROID + return len >= min && (typeof max == 'undefined' || len <= (max ?? 0)); + // #endif + // #ifdef APP-ANDROID + return len >= min && (max == null || len <= max); + // #endif +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isDate/index.ts b/QXTfront/uni_modules/lime-shared/isDate/index.ts new file mode 100644 index 0000000..899b942 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isDate/index.ts @@ -0,0 +1,189 @@ +// @ts-nocheck + +/** + * 日期验证配置选项 + */ +export type IsDateOptions = { + /** 日期格式字符串,默认 'YYYY/MM/DD' */ + format ?: string; + /** 允许的分隔符数组,默认 ['/', '-'] */ + delimiters ?: string[]; + /** 是否严格匹配格式,默认 false */ + strictMode ?: boolean; +} + +/** + * 验证日期格式字符串是否合法 + * @param format - 需要验证的格式字符串 + * @returns 是否合法格式 + */ +function isValidFormat(format : string) : boolean { + return /(^(y{4}|y{2})[年./-](m{1,2})[月./-](d{1,2}(日)?)$)|(^(m{1,2})[./-](d{1,2})[./-]((y{4}|y{2})$))|(^(d{1,2})[./-](m{1,2})[./-]((y{4}|y{2})$))/i.test(format); +} + +/** + * 将日期部分和格式部分组合成键值对数组 + * @param date - 分割后的日期部分数组 + * @param format - 分割后的格式部分数组 + * @returns 组合后的二维数组 + */ +function zip(date : string[], format : string[]) : string[][] { + const zippedArr : string[][] = []; + const len = Math.max(date.length, format.length); + + for (let i = 0; i < len; i++) { + const key = i < date.length ? date[i] : '' + const value = i < format.length ? format[i] : '' + + zippedArr.push([key, value]) + } + + return zippedArr; +} + + +/** 验证日期对象 */ +function validateDateObject(date : Date, strictMode : boolean) : boolean { + // #ifndef APP-ANDROID + return !strictMode && Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date.getTime()); + // #endif + // #ifdef APP-ANDROID + return !strictMode && !isNaN(date.getTime()) + // #endif +} + + +function escapeRegExp(str: string): string { + return str//.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} + +function enhancedSplit( + str: string, + delimiters: string[] +): string[] { + // 构建动态分隔符正则表达式 + const escapedDelimiters = delimiters.map(d => escapeRegExp(d)); + const pattern = new RegExp( + `[${escapedDelimiters.join('')}]+`, // 匹配任意允许的分隔符 + 'g' + ); + + return str.split(pattern).filter(p => p != ''); +} + +/** + * 验证输入是否为有效日期 + * @param input - 输入值,可以是字符串或 Date 对象 + * @param options - 配置选项,可以是字符串(简写格式)或配置对象 + * @returns 是否为有效日期 + * + * @example + * isDate('2023/12/31'); // true + * isDate(new Date()); // true + * isDate('02-29-2023', { strictMode: true }); // false(2023年不是闰年) + */ +export function isDate(input : Date, options ?: IsDateOptions) : boolean; +export function isDate(input : string, options ?: string | IsDateOptions) : boolean; +export function isDate(input : string | Date, options : string | IsDateOptions | null = null) : boolean { + // 处理参数重载:允许第二个参数直接传格式字符串 + // Date对象验证 + + + let format = 'YYYY/MM/DD' + let delimiters = ['/', '-'] + let strictMode = false + + + if (options != null) { + if (typeof options == 'string') { + format = options as string + } else { + format = (options as IsDateOptions).format ?? format + delimiters = (options as IsDateOptions).delimiters ?? delimiters + strictMode = (options as IsDateOptions).strictMode ?? strictMode + } + } + if (input instanceof Date) { + return validateDateObject(input, strictMode); + } + + + // 字符串类型验证 + if (!isValidFormat(format)) return false; + // 严格模式长度检查 + if (strictMode && input.length != format.length) { + return false; + } + // 获取格式中的分隔符 + const formatDelimiter = delimiters.find((d) : boolean => format.indexOf(d) != -1); + // 获取实际使用的分隔符 + const dateDelimiter = strictMode + ? formatDelimiter + : delimiters.find((d) : boolean => input.indexOf(d) != -1); + // 分割日期和格式 + const dateParts = strictMode ? enhancedSplit(input, delimiters) : input.split(dateDelimiter ?? ''); + const formatParts = strictMode ? enhancedSplit(format.toLowerCase(), delimiters) : format.toLowerCase().split(formatDelimiter ?? ''); + // 组合成键值对 + const dateAndFormat = zip(dateParts, formatParts); + const dateObj = new Map(); + + + // 解析日期组成部分 + for (const [dateWord, formatWord] of dateAndFormat) { + if (dateWord == '' || formatWord == '' || dateWord.length != formatWord.length) { + return false; + } + dateObj.set(formatWord.charAt(0), dateWord) + } + + // 年份处理 + let fullYear = dateObj.get('y'); + + if (fullYear == null) return false; + + // 检查年份前导负号 + if (fullYear.startsWith('-')) return false; + + // 两位年份转四位 + if (fullYear.length == 2) { + const parsedYear = parseInt(fullYear, 10); + + if (isNaN(parsedYear)) { + return false; + } + + const currentYear = new Date().getFullYear(); + const century = currentYear - (currentYear % 100); + fullYear = (parseInt(fullYear, 10) < (currentYear % 100)) + ? `${century + 100 + parseInt(fullYear, 10)}` + : `${century + parseInt(fullYear, 10)}`; + } + + // 月份补零 + const month = dateObj.get('m')?.padStart(2, '0') ?? ''; + // 日期补零 + const day = dateObj.get('d')?.padStart(2, '0') ?? ''; + + const isoDate = `${fullYear}-${month}-${day}T00:00:00.000Z`; + + // return new Date(time).getDate() == parseInt(day); + + // 构造 ISO 日期字符串验证 + try { + // #ifndef APP-ANDROID + const date = new Date(isoDate); + return date.getUTCDate() === parseInt(day, 10) && + (date.getUTCMonth() + 1) === parseInt(month, 10) && + date.getUTCFullYear() === parseInt(fullYear, 10); + // #endif + // #ifdef APP-ANDROID + const date = new Date(isoDate); + return date.getDate() == parseInt(day, 10) && + (date.getMonth() + 1) == parseInt(month, 10) && + date.getFullYear() == parseInt(fullYear, 10); + // #endif + } catch { + return false; + } + +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isDef/index.ts b/QXTfront/uni_modules/lime-shared/isDef/index.ts new file mode 100644 index 0000000..f8ca9bc --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isDef/index.ts @@ -0,0 +1,23 @@ +// @ts-nocheck +/** + * 检查一个值是否已定义(不为 undefined)且不为 null + * @param value 要检查的值 + * @returns 如果值已定义且不为 null,则返回 true;否则返回 false + */ +// #ifndef UNI-APP-X +export function isDef(value: unknown): boolean { + return value !== undefined && value !== null; +} +// #endif + + +// #ifdef UNI-APP-X +export function isDef(value : any|null) : boolean { + // #ifdef UNI-APP-X && APP + return value != null; + // #endif + // #ifndef UNI-APP-X && APP + return value != null && value != undefined; + // #endif +} +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isEmail/index.ts b/QXTfront/uni_modules/lime-shared/isEmail/index.ts new file mode 100644 index 0000000..01f78d4 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isEmail/index.ts @@ -0,0 +1,11 @@ +// @ts-nocheck + +/** + * 验证电子邮件地址格式 + * @param email - 要验证的字符串 + * @returns 是否通过验证 + */ +export function isEmail(email : string) : boolean { + const emailRegex = /\S+@\S+\.\S+/; + return emailRegex.test(email); +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isEmpty/index.ts b/QXTfront/uni_modules/lime-shared/isEmpty/index.ts new file mode 100644 index 0000000..2e89acb --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isEmpty/index.ts @@ -0,0 +1,81 @@ +// @ts-nocheck +import {isDef} from '../isDef' +import {isString} from '../isString' +import {isNumber} from '../isNumber' +/** + * 判断一个值是否为空。 + * + * 对于字符串,去除首尾空格后判断长度是否为0。 + * 对于数组,判断长度是否为0。 + * 对于对象,判断键的数量是否为0。 + * 对于null或undefined,直接返回true。 + * 其他类型(如数字、布尔值等)默认不为空。 + * + * @param {any} value - 要检查的值。 + * @returns {boolean} 如果值为空,返回true,否则返回false。 + */ + + +// #ifdef UNI-APP-X && APP +export function isEmpty(value : any | null) : boolean { + // 为null + if(!isDef(value)){ + return true + } + // 为空字符 + if(isString(value)){ + return value.toString().trim().length == 0 + } + // 为数值 + if(isNumber(value)){ + return false + } + if(typeof value == 'object'){ + // 数组 + if(Array.isArray(value)){ + return (value as Array).length == 0 + } + // Map + if(value instanceof Map) { + return value.size == 0 + } + // Set + if(value instanceof Set) { + return value.size == 0 + } + if(value instanceof UTSJSONObject) { + return value.toMap().size == 0 + } + return JSON.stringify(value) == '{}' + } + return false +} +// #endif + + +// #ifndef UNI-APP-X && APP +export function isEmpty(value: any): boolean { + // 检查是否为null或undefined + if (value == null || value == undefined || value == '') { + return true; + } + + // 检查字符串是否为空 + if (typeof value === 'string') { + return value.trim().length === 0; + } + + // 检查数组是否为空 + if (Array.isArray(value)) { + return value.length === 0; + } + + // 检查对象是否为空 + if (typeof value === 'object') { + return Object.keys(value).length === 0; + } + + // 其他类型(如数字、布尔值等)不为空 + return false; +} +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isFunction/index.ts b/QXTfront/uni_modules/lime-shared/isFunction/index.ts new file mode 100644 index 0000000..12605c3 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isFunction/index.ts @@ -0,0 +1,16 @@ +// @ts-nocheck +/** + * 检查一个值是否为函数类型 + * @param val 要检查的值 + * @returns 如果值的类型是函数类型,则返回 true;否则返回 false + */ + +// #ifdef UNI-APP-X && APP +export const isFunction = (val: any):boolean => typeof val == 'function'; + // #endif + + +// #ifndef UNI-APP-X && APP +export const isFunction = (val: unknown): val is Function => + typeof val === 'function'; +// #endif diff --git a/QXTfront/uni_modules/lime-shared/isIP/index.ts b/QXTfront/uni_modules/lime-shared/isIP/index.ts new file mode 100644 index 0000000..36f4906 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isIP/index.ts @@ -0,0 +1,64 @@ +// @ts-nocheck + +// #ifndef APP-ANDROID || APP-HARMONY || APP-IOS +type UTSJSONObject = { + version : string | number | null; +}; +// #endif +// #ifdef APP-ANDROID || APP-HARMONY || APP-IOS +// type Options = UTSJSONObject +// #endif + +const IPv4SegmentFormat = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; +const IPv4AddressFormat = `(${IPv4SegmentFormat}\\.){3}${IPv4SegmentFormat}`; +const IPv4AddressRegExp = new RegExp(`^${IPv4AddressFormat}$`); + +const IPv6SegmentFormat = '(?:[0-9a-fA-F]{1,4})'; +const IPv6AddressRegExp = new RegExp( + '^(' + + `(?:${IPv6SegmentFormat}:){7}(?:${IPv6SegmentFormat}|:)|` + + `(?:${IPv6SegmentFormat}:){6}(?:${IPv4AddressFormat}|:${IPv6SegmentFormat}|:)|` + + `(?:${IPv6SegmentFormat}:){5}(?::${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,2}|:)|` + + `(?:${IPv6SegmentFormat}:){4}(?:(:${IPv6SegmentFormat}){0,1}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,3}|:)|` + + `(?:${IPv6SegmentFormat}:){3}(?:(:${IPv6SegmentFormat}){0,2}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,4}|:)|` + + `(?:${IPv6SegmentFormat}:){2}(?:(:${IPv6SegmentFormat}){0,3}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,5}|:)|` + + `(?:${IPv6SegmentFormat}:){1}(?:(:${IPv6SegmentFormat}){0,4}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,6}|:)|` + + `(?::((?::${IPv6SegmentFormat}){0,5}:${IPv4AddressFormat}|(?::${IPv6SegmentFormat}){1,7}|:))` + + ')(%[0-9a-zA-Z.]{1,})?$' +); + + +/** + * 验证IP地址格式 + * @param {string} ipAddress - 要验证的IP地址 + * @param {Options|string|number} options - 配置选项或版本号 + * @returns {boolean} 是否匹配有效的IP地址格式 + */ +export function isIP(ipAddress : string | null, options : UTSJSONObject | string | number | null = null) : boolean { + // assertString(ipAddress); + if(ipAddress == null) return false + let version : string | number | null; + + if (typeof options == 'object') { + version = (options as UTSJSONObject|null)?.['version']; + } else { + version = options; + } + + const versionStr = version != null ? `${version}` : ''; + + if (versionStr == '') { + return isIP(ipAddress, 4) || isIP(ipAddress, 6); + } + + if (versionStr == '4') { + return IPv4AddressRegExp.test(ipAddress.trim()); + } + + if (versionStr == '6') { + return IPv6AddressRegExp.test(ipAddress.trim()); + } + + return false; +} + diff --git a/QXTfront/uni_modules/lime-shared/isNumber/index.ts b/QXTfront/uni_modules/lime-shared/isNumber/index.ts new file mode 100644 index 0000000..040bc11 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isNumber/index.ts @@ -0,0 +1,26 @@ +// @ts-nocheck +/** + * 检查一个值是否为数字类型 + * @param value 要检查的值,可以是 number 类型或 string 类型的数字 + * @returns 如果值是数字类型且不是 NaN,则返回 true;否则返回 false + */ + +// #ifndef UNI-APP-X +export function isNumber(value: number | string | null): boolean { + return typeof value === 'number' && !isNaN(value); +} +// #endif + +// #ifdef UNI-APP-X +export function isNumber(value: any|null): boolean { + // #ifdef APP-ANDROID + return ['Byte', 'UByte','Short','UShort','Int','UInt','Long','ULong','Float','Double','number'].includes(typeof value) + // #endif + // #ifdef APP-IOS + return ['Int8', 'UInt8','Int16','UInt16','Int32','UInt32','Int64','UInt64','Int','UInt','Float','Float16','Float32','Float64','Double', 'number'].includes(typeof value) + // #endif + // #ifndef APP-ANDROID || APP-IOS + return typeof value === 'number' && !isNaN(value); + // #endif +} +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isNumeric/index.ts b/QXTfront/uni_modules/lime-shared/isNumeric/index.ts new file mode 100644 index 0000000..af5020e --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isNumeric/index.ts @@ -0,0 +1,33 @@ +// @ts-nocheck + +/** + * 检查一个值是否为数字类型或表示数字的字符串 + * @param value 要检查的值,可以是 string 类型或 number 类型 + * @returns 如果值是数字类型或表示数字的字符串,则返回 true;否则返回 false + */ + +// #ifndef UNI-APP-X && APP +export function isNumeric(value: string | number | undefined | null): boolean { + return /^(-)?\d+(\.\d+)?$/.test(value); +} +// #endif + + +// #ifdef UNI-APP-X && APP +import {isNumber} from '../isNumber'; +import {isString} from '../isString'; +export function isNumeric(value : any|null) : boolean { + if(value == null) { + return false + } + if(isNumber(value)) { + return true + } else if(isString(value)) { + // const regex = "-?\\d+(\\.\\d+)?".toRegex() + const regex = new RegExp("^(-)?\\d+(\\.\\d+)?$") + return regex.test(value as string) //regex.matches(value as string) + } + return false + // return /^(-)?\d+(\.\d+)?$/.test(value); +} +// #endif diff --git a/QXTfront/uni_modules/lime-shared/isObject/index.ts b/QXTfront/uni_modules/lime-shared/isObject/index.ts new file mode 100644 index 0000000..26fec28 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isObject/index.ts @@ -0,0 +1,19 @@ +// @ts-nocheck +/** + * 检查一个值是否为对象类型 + * @param val 要检查的值 + * @returns 如果值的类型是对象类型,则返回 true;否则返回 false + */ + +// #ifndef APP-ANDROID +export const isObject = (val : unknown) : val is Record => + val !== null && typeof val === 'object'; + +// #endif + + +// #ifdef APP-ANDROID +export const isObject = (val : any | null) : boolean =>{ + return val != null && typeof val == 'object'; +} +// #endif diff --git a/QXTfront/uni_modules/lime-shared/isPromise/index.ts b/QXTfront/uni_modules/lime-shared/isPromise/index.ts new file mode 100644 index 0000000..b13c10b --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isPromise/index.ts @@ -0,0 +1,22 @@ +// @ts-nocheck +import {isFunction} from '../isFunction' +import {isObject} from '../isObject' +/** + * 检查一个值是否为 Promise 类型 + * @param val 要检查的值 + * @returns 如果值的类型是 Promise 类型,则返回 true;否则返回 false + */ +// #ifndef APP-ANDROID +export const isPromise = (val: unknown): val is Promise => { + // 使用 isObject 函数判断值是否为对象类型 + // 使用 isFunction 函数判断值是否具有 then 方法和 catch 方法 + return isObject(val) && isFunction(val.then) && isFunction(val.catch); +}; +// #endif + + +// #ifdef APP-ANDROID +export const isPromise = (val: any): boolean => { + return val instanceof Promise +}; +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isRegExp/index.ts b/QXTfront/uni_modules/lime-shared/isRegExp/index.ts new file mode 100644 index 0000000..8aaefdf --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isRegExp/index.ts @@ -0,0 +1,33 @@ +// @ts-nocheck +/** + * 检测输入值是否为正则表达式对象 + * @param obj - 需要检测的任意类型值 + * @returns 如果检测值是正则表达式返回 true,否则返回 false + * + * @example + * // 基础检测 + * isRegExp(/abc/); // true + * isRegExp(new RegExp('abc')); // true + * + * @example + * // 非正则表达式检测 + * isRegExp('hello'); // false + * isRegExp({}); // false + * isRegExp(null); // false + * + * @description + * 1. 通过 Object.prototype.toString 的可靠类型检测 + * 2. 支持跨执行环境的可靠检测: + * - 浏览器多 iframe 环境 + * - Node.js 的 vm 模块 + * 3. 比 instanceof 检测更可靠 + * 4. 支持 ES3+ 全环境兼容 + */ +export function isRegExp(obj : any) : boolean { + // #ifndef APP-ANDROID + return Object.prototype.toString.call(obj) === '[object RegExp]'; + // #endif + // #ifdef APP-ANDROID + return obj instanceof RegExp//Object.prototype.toString.call(obj) === '[object RegExp]'; + // #endif +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isString/index.ts b/QXTfront/uni_modules/lime-shared/isString/index.ts new file mode 100644 index 0000000..143f876 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isString/index.ts @@ -0,0 +1,19 @@ +// @ts-nocheck +/** + * 检查一个值是否为字符串类型 + * @param str 要检查的值 + * @returns 如果值的类型是字符串类型,则返回 true;否则返回 false + */ +// #ifndef UNI-APP-X && APP +// export const isString = (str: unknown): str is string => typeof str === 'string'; +export function isString (str: unknown): str is string { + return typeof str == 'string' +} +// #endif + + +// #ifdef UNI-APP-X && APP +export function isString (str: any|null): boolean { + return typeof str == 'string' +} +// #endif diff --git a/QXTfront/uni_modules/lime-shared/isURL/index.ts b/QXTfront/uni_modules/lime-shared/isURL/index.ts new file mode 100644 index 0000000..4121143 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isURL/index.ts @@ -0,0 +1,198 @@ +// @ts-nocheck +import { isValidDomain, type IsValidDomainOptions } from '../isValidDomain'; +import { isIP } from '../isIP'; +import { isRegExp } from '../isRegExp'; +// import {merge} from '../merge'; + +/** URL 验证配置选项 */ +export type IsURLOptions = { + /** 允许的协议列表(默认 ['http', 'https', 'ftp']) */ + protocols ?: string[]; + /** 需要顶级域名(默认 true) */ + requireTld ?: boolean; + /** 需要协议头(默认 false) */ + requireProtocol ?: boolean; + /** 需要主机地址(默认 true) */ + requireHost ?: boolean; + /** 需要端口号(默认 false) */ + requirePort ?: boolean; + /** 需要有效协议(默认 true) */ + requireValidProtocol ?: boolean; + /** 允许下划线(默认 false) */ + allowUnderscores ?: boolean; + /** 允许结尾点号(默认 false) */ + allowTrailingDot ?: boolean; + /** 允许协议相对地址(默认 false) */ + allowProtocolRelativeUrls ?: boolean; + /** 允许片段标识(默认 true) */ + allowFragments ?: boolean; + /** 允许查询参数(默认 true) */ + allowQueryComponents ?: boolean; + /** 禁用认证信息(默认 false) */ + disallowAuth ?: boolean; + /** 验证长度(默认 true) */ + validateLength ?: boolean; + /** 最大允许长度(默认 2084) */ + maxAllowedLength ?: number; + /** 白名单主机列表 */ + hostWhitelist ?: Array; + /** 黑名单主机列表 */ + hostBlacklist ?: Array; +} + +export function checkHost(host : string, matches : any[]) : boolean { + for (let i = 0; i < matches.length; i++) { + let match = matches[i]; + if (host == match || (isRegExp(match) && (match as RegExp).test(host))) { + return true; + } + } + return false; +} + +// 辅助函数 +function isValidPort(port : number | null) : boolean { + return port != null && !isNaN(port) && port > 0 && port <= 65535; +} + +function validateHost(host : string, options : IsURLOptions | null, isIPv6 : boolean) : boolean { + if (isIPv6) return isIP(host, 6); + return isIP(host) || isValidDomain(host, { + requireTld: options?.requireTld ?? true, + allowUnderscore: options?.allowUnderscores ?? true, + allowTrailingDot: options?.allowTrailingDot ?? false + } as IsValidDomainOptions); +} + + + + +/** 匹配 IPv6 地址的正则表达式 */ +const WRAPPED_IPV6_REGEX = /^\[([^\]]+)\](?::([0-9]+))?$/; + +/** + * 验证字符串是否为有效的 URL + * @param url - 需要验证的字符串 + * @param options - 配置选项 + * @returns 是否为有效 URL + * + * @example + * ```typescript + * isURL('https://example.com'); // true + * isURL('user:pass@example.com', { disallowAuth: true }); // false + * ``` + */ +export function isURL(url : string | null, options : IsURLOptions | null = null) : boolean { + // assertString(url); + + // 1. 基础格式校验 + if (url == null || url == '' || url.length == 0 || /[\s<>]/.test(url) || url.startsWith('mailto:')) { + return false; + } + // 合并配置选项 + let protocols = options?.protocols ?? ['http', 'https', 'ftp'] + // let requireTld = options?.requireTld ?? true + let requireProtocol = options?.requireProtocol ?? false + let requireHost = options?.requireHost ?? true + let requirePort = options?.requirePort ?? false + let requireValidProtocol = options?.requireValidProtocol ?? true + // let allowUnderscores = options?.allowUnderscores ?? false + // let allowTrailingDot = options?.allowTrailingDot ?? false + let allowProtocolRelativeUrls = options?.allowProtocolRelativeUrls ?? false + let allowFragments = options?.allowFragments ?? true + let allowQueryComponents = options?.allowQueryComponents ?? true + let validateLength = options?.validateLength ?? true + let maxAllowedLength = options?.maxAllowedLength ?? 2084 + let hostWhitelist = options?.hostWhitelist + let hostBlacklist = options?.hostBlacklist + let disallowAuth = options?.disallowAuth ?? false + + + // 2. 长度校验 + if (validateLength && url!.length > maxAllowedLength) { + return false; + } + // 3. 片段和查询参数校验 + if (!allowFragments && url.includes('#')) return false; + if (!allowQueryComponents && (url.includes('?') || url.includes('&'))) return false; + + // 处理 URL 组成部分 + const [urlWithoutFragment] = url.split('#'); + const [baseUrl] = urlWithoutFragment.split('?'); + // 4. 协议处理 + const protocolParts = baseUrl.split('://'); + let protocol:string; + let remainingUrl = baseUrl; + + if (protocolParts.length > 1) { + protocol = protocolParts.shift()!.toLowerCase(); + if (requireValidProtocol && !protocols!.includes(protocol)) { + return false; + } + remainingUrl = protocolParts.join('://'); + } else if (requireProtocol) { + return false; + } else if (baseUrl.startsWith('//')) { + if (!allowProtocolRelativeUrls) return false; + remainingUrl = baseUrl.slice(2); + } + + if (remainingUrl == '') return false; + + // 5. 处理主机部分 + const [hostPart] = remainingUrl.split('/', 1); + const authParts = hostPart.split('@'); + + // 认证信息校验 + if (authParts.length > 1) { + if (disallowAuth || authParts[0] == '') return false; + const auth = authParts.shift()!; + if (auth.split(':').length > 2) return false; + const [user, password] = auth.split(':'); + if (user == '' && password == '') return false; + } + + const hostname = authParts.join('@'); + + // 6. 解析主机和端口 + type HostInfo = { + host ?: string; + ipv6 ?: string; + port ?: number; + }; + + const hostInfo : HostInfo = {}; + const ipv6Match = hostname.match(WRAPPED_IPV6_REGEX); + if (ipv6Match != null) { + hostInfo.ipv6 = ipv6Match.length > 1 ? ipv6Match[1] : null; + const portStr = ipv6Match.length > 2 ? ipv6Match[2] : null; + if (portStr != null) { + hostInfo.port = parseInt(portStr); + if (!isValidPort(hostInfo.port)) return false; + } + } else { + const [host, ...portParts] = hostname.split(':'); + hostInfo.host = host; + if (portParts.length > 0) { + const portStr = portParts.join(':'); + hostInfo.port = parseInt(portStr); + if (!isValidPort(hostInfo.port)) return false; + } + } + + // 7. 端口校验 + if (requirePort && hostInfo.port == null) return false; + // 8. 主机验证逻辑 + const finalHost = hostInfo.host ?? hostInfo.ipv6; + if (finalHost == null) return requireHost ? false : true; + // 白名单/黑名单检查 + if (hostWhitelist != null && !checkHost(finalHost!, hostWhitelist!)) return false; + if (hostBlacklist != null && checkHost(finalHost!, hostBlacklist!)) return false; + + // 9. 综合校验 + return validateHost( + finalHost, + options, + !(hostInfo.ipv6 == null || hostInfo.ipv6 == '') + ); +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/isValidDomain/index.ts b/QXTfront/uni_modules/lime-shared/isValidDomain/index.ts new file mode 100644 index 0000000..40c717f --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/isValidDomain/index.ts @@ -0,0 +1,90 @@ +// @ts-nocheck +/** + * 域名验证配置选项 + */ +export type IsValidDomainOptions = { + /** + * 是否要求必须包含顶级域名(TLD) + * @default true + * @example + * true -> "example.com" 有效 + * false -> "localhost" 有效 + */ + requireTld : boolean; + + /** + * 是否允许域名部分包含下划线(_) + * @default false + * @example + * true -> "my_site.com" 有效 + * false -> "my_site.com" 无效 + */ + allowUnderscore : boolean; + + /** + * 是否允许域名以点号(.)结尾 + * @default false + * @example + * true -> "example.com." 有效 + * false -> "example.com." 无效 + */ + allowTrailingDot : boolean; +} + + +/** + * 验证字符串是否为合法域名 + * @param str 要验证的字符串 + * @param options 配置选项,默认 { + * requireTld: true, // 需要顶级域名 + * allowUnderscore: false,// 允许下划线 + * allowTrailingDot: false// 允许结尾点号 + * } + * @returns 验证结果 + * + * 示例: + * isValidDomain("example.com") // true + * isValidDomain("my_site.com", { allowUnderscore: true }) // true + */ +export function isValidDomain( + str : string, + options : IsValidDomainOptions = { + requireTld: true, + allowUnderscore: false, + allowTrailingDot: false + } +) : boolean { + // 预处理字符串 + let domain = str; + + // 处理结尾点号 + if (options.allowTrailingDot && domain.endsWith('.')) { + domain = domain.slice(0, -1); + } + + // 分割域名部分 + const parts = domain.split('.'); + if (parts.length == 1 && options.requireTld) return false; + + // 验证顶级域名 + const tld = parts[parts.length - 1]; + if (options.requireTld) { + if (!/^[a-z\u00A1-\uFFFF]{2,}$/i.test(tld) || /\s/.test(tld)) { + return false; + } + } + + // 验证每个部分 + const domainRegex = options.allowUnderscore + ? /^[a-z0-9\u00A1-\uFFFF](?:[a-z0-9-\u00A1-\uFFFF_]*[a-z0-9\u00A1-\uFFFF])?$/i + : /^[a-z0-9\u00A1-\uFFFF](?:[a-z0-9-\u00A1-\uFFFF]*[a-z0-9\u00A1-\uFFFF])?$/i; + + return parts.every(part => { + // 长度校验 + if (part.length > 63) return false; + // 格式校验 + if (!domainRegex.test(part)) return false; + // 禁止开头/结尾连字符 + return !(part.startsWith('-') || part.endsWith('-')); + }); +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/kebabCase/index.ts b/QXTfront/uni_modules/lime-shared/kebabCase/index.ts new file mode 100644 index 0000000..bed6b1f --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/kebabCase/index.ts @@ -0,0 +1,24 @@ +// @ts-nocheck +// export function toLowercaseSeparator(key: string) { +// return key.replace(/([A-Z])/g, '-$1').toLowerCase(); +// } + +/** + * 将字符串转换为指定连接符的命名约定 + * @param str 要转换的字符串 + * @param separator 指定的连接符,默认为 "-" + * @returns 转换后的字符串 + */ +export function kebabCase(str : string, separator : string = "-") : string { + return str + + // #ifdef APP-ANDROID + .replace(/[A-Z]/g, (match : string, _ : number, _ : string) : string => `${separator}${match.toLowerCase()}`) // 将大写字母替换为连接符加小写字母 + // #endif + // #ifndef APP-ANDROID + .replace(/[A-Z]/g, (match : string) : string => `${separator}${match.toLowerCase()}`) // 将大写字母替换为连接符加小写字母 + // #endif + .replace(/[\s_-]+/g, separator) // 将空格、下划线和短横线替换为指定连接符 + .replace(new RegExp(`^${separator}|${separator}$`, "g"), "") // 删除开头和结尾的连接符 + .toLowerCase(); // 将结果转换为全小写 +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/merge/index.ts b/QXTfront/uni_modules/lime-shared/merge/index.ts new file mode 100644 index 0000000..b4dcf14 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/merge/index.ts @@ -0,0 +1,33 @@ +// @ts-nocheck +/** + * 深度合并两个对象,用默认值填充目标对象中未定义的属性 + * + * @template T - 合并对象的泛型类型 + * @param {T} obj - 目标对象(将被修改) + * @param {T} defaults - 包含默认值的对象 + * @returns {T} 合并后的对象(即修改后的obj参数) + */ + +export function merge(obj : T, defaults : T) : T { + // #ifdef APP-ANDROID + try { + if(obj instanceof UTSJSONObject && defaults instanceof UTSJSONObject) { + return UTSJSONObject.assign(obj, defaults)!// as T + } + const obj1 = { ...toRaw(obj) } + const obj2 = { ...toRaw(defaults) } + return UTSJSONObject.assign(obj1, obj2)! + } catch (error) { + return defaults + } + // #endif + + // #ifndef APP-ANDROID + for (const key in defaults) { + if (obj[key] === undefined || obj[key] === null) { + obj[key] = defaults[key]; + } + } + return obj; + // #endif +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/obj2url/index.ts b/QXTfront/uni_modules/lime-shared/obj2url/index.ts new file mode 100644 index 0000000..d0125cf --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/obj2url/index.ts @@ -0,0 +1,61 @@ +// @ts-nocheck +// #ifndef UNI-APP-X +type UTSJSONObject = Record +// #endif + +/** + * 将对象转换为URL查询字符串 + * @param data - 需要转换的键值对对象 + * @param isPrefix - 是否添加问号前缀,默认为false + * @returns 格式化后的URL查询参数字符串 + * + * @example + * // 基础用法 + * obj2url({ name: '张三', age: 25 }); + * // => "name=%E5%BC%A0%E4%B8%89&age=25" + * + * @example + * // 数组参数处理 + * obj2url({ tags: ['js', 'ts'] }); + * // => "tags[]=js&tags[]=ts" + * + * @example + * // 包含空值的过滤 + * obj2url({ name: '', age: null, city: undefined }); + * // => "" + * + * @description + * 1. 自动过滤空值(空字符串、null、undefined) + * 2. 支持数组参数转换(自动添加[]后缀) + * 3. 自动进行URI编码 + * 4. 支持自定义是否添加问号前缀 + */ +export function obj2url(data : UTSJSONObject, isPrefix : boolean = false) : string { + const prefix = isPrefix ? '?' : ''; + + const _result:string[] = []; + const empty:(any|null)[] = ['', null] + + // #ifndef APP-ANDROID + empty.push(undefined) + // #endif + + for (const key in data) { + const value = data[key]; + + // 去掉为空的参数 + if (empty.includes(value)) { + continue; + } + if (Array.isArray(value)) { + (value as any[]).forEach((_value) => { + _result.push( + encodeURIComponent(key) + '[]=' + encodeURIComponent(`${_value}`), + ); + }); + } else { + _result.push(encodeURIComponent(key) + '=' + encodeURIComponent(`${value}`)); + } + } + return _result.length > 0 ? prefix + _result.join('&') : ''; +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/objToCss/index.ts b/QXTfront/uni_modules/lime-shared/objToCss/index.ts new file mode 100644 index 0000000..2175269 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/objToCss/index.ts @@ -0,0 +1,49 @@ +// @ts-nocheck +// #ifndef UNI-APP-X +interface UTSJSONObject { + [key : string] : string | number | null +} +// #endif + +/** + * 将字符串转换为带有连字符分隔的小写形式 + * @param key - 要转换的字符串 + * @returns 转换后的字符串 + */ +export function toLowercaseSeparator(key : string):string { + return key.replace(/([A-Z])/g, '-$1').toLowerCase(); +} + +/** + * 获取样式对象对应的样式字符串 + * @param style - CSS样式对象 + * @returns 由非空有效样式属性键值对组成的字符串 + */ +export function objToCss(style : UTSJSONObject) : string { + + // #ifdef APP-ANDROID + let styleStr = ''; + style.toMap().forEach((value, key) => { + if(value != null && value != '') { + styleStr += `${toLowercaseSeparator(key as string)}: ${value};` + } + }) + return styleStr + // #endif + // #ifndef APP-ANDROID + return Object.keys(style) + .filter( + (key) => + style[key] !== undefined && + style[key] !== null && + style[key] !== '') + .map((key : string) => `${toLowercaseSeparator(key)}: ${style[key]};`) + .join(' '); + // #endif +} + +// 示例 +// const style = { color: 'red', fontSize: '16px', backgroundColor: '', border: null }; +// const styleStr = objToCss(style); +// console.log(styleStr); +// 输出: "color: red; font-size: 16px;" \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/package.json b/QXTfront/uni_modules/lime-shared/package.json new file mode 100644 index 0000000..a37742c --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/package.json @@ -0,0 +1,110 @@ +{ + "id": "lime-shared", + "displayName": "lime-shared", + "version": "0.4.2", + "description": "本人插件的几个公共函数,获取当前页,图片的base64转临时路径,图片的exif信息等", + "keywords": [ + "lime-shared", + "exif" +], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0", + "uni-app": "^4.55", + "uni-app-x": "^4.55" + }, + "dcloudext": { + "type": "sdk-js", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "-", + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√", + "alipay": "√", + "toutiao": "√", + "baidu": "√", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + }, + "App": { + "app-harmony": "u", + "app-nvue": "u", + "app-uvue": "y", + "app-vue": "u" + } + } + } + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/pathToBase64/index.ts b/QXTfront/uni_modules/lime-shared/pathToBase64/index.ts new file mode 100644 index 0000000..ce4e1b0 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/pathToBase64/index.ts @@ -0,0 +1,11 @@ +// @ts-nocheck +// #ifndef UNI-APP-X && APP +// export * from './vue.ts' +export { pathToBase64 } from './vue.ts' +// #endif + + +// #ifdef UNI-APP-X && APP +// export * from './uvue.uts' +export { pathToBase64 } from './uvue.uts' +// #endif diff --git a/QXTfront/uni_modules/lime-shared/pathToBase64/uvue.uts b/QXTfront/uni_modules/lime-shared/pathToBase64/uvue.uts new file mode 100644 index 0000000..d5bbdb1 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/pathToBase64/uvue.uts @@ -0,0 +1,17 @@ +// @ts-nocheck +// import { processFile, ProcessFileOptions } from '@/uni_modules/lime-file-utils' +export function pathToBase64(path : string) : Promise { + console.error('pathToBase64: 当前环境不支持,请使用 【lime-file-utils】') + // return new Promise((resolve, reject) => { + // processFile({ + // type: 'toDataURL', + // path, + // success(res : string) { + // resolve(res) + // }, + // fail(err: any){ + // reject(err) + // } + // } as ProcessFileOptions) + // }) +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/pathToBase64/vue.ts b/QXTfront/uni_modules/lime-shared/pathToBase64/vue.ts new file mode 100644 index 0000000..8167f88 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/pathToBase64/vue.ts @@ -0,0 +1,121 @@ +// @ts-nocheck + +// #ifdef APP-PLUS +import { getLocalFilePath } from '../getLocalFilePath' +// #endif +function isImage(extension : string) { + const imageExtensions = ["jpg", "jpeg", "png", "gif", "bmp", "svg"]; + return imageExtensions.includes(extension.toLowerCase()); +} +// #ifdef H5 +function getSVGFromURL(url: string) { + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'text'; + + xhr.onload = function () { + if (xhr.status === 200) { + const svg = xhr.responseText; + resolve(svg); + } else { + reject(new Error(xhr.statusText)); + } + }; + + xhr.onerror = function () { + reject(new Error('Network error')); + }; + + xhr.send(); + }); +} +// #endif +/** + * 路径转base64 + * @param {Object} string + */ +export function pathToBase64(path : string) : Promise { + if (/^data:/.test(path)) return path + let extension = path.substring(path.lastIndexOf('.') + 1); + const isImageFile = isImage(extension) + let prefix = '' + if (isImageFile) { + prefix = 'image/'; + if(extension == 'svg') { + extension += '+xml' + } + } else if (extension === 'pdf') { + prefix = 'application/pdf'; + } else if (extension === 'txt') { + prefix = 'text/plain'; + } else { + // 添加更多文件类型的判断 + // 如果不是图片、PDF、文本等类型,可以设定默认的前缀或采取其他处理 + prefix = 'application/octet-stream'; + } + return new Promise((resolve, reject) => { + // #ifdef H5 + if (isImageFile) { + if(extension == 'svg') { + getSVGFromURL(path).then(svg => { + const base64 = btoa(svg); + resolve(`data:image/svg+xml;base64,${base64}`); + }) + } else { + let image = new Image(); + image.setAttribute("crossOrigin", 'Anonymous'); + image.onload = function () { + let canvas = document.createElement('canvas'); + canvas.width = this.naturalWidth; + canvas.height = this.naturalHeight; + canvas.getContext('2d').drawImage(image, 0, 0); + let result = canvas.toDataURL(`${prefix}${extension}`) + resolve(result); + canvas.height = canvas.width = 0 + } + image.src = path + '?v=' + Math.random() + image.onerror = (error) => { + reject(error); + }; + } + + } else { + reject('not image'); + } + + // #endif + + // #ifdef MP + if (uni.canIUse('getFileSystemManager')) { + uni.getFileSystemManager().readFile({ + filePath: path, + encoding: 'base64', + success: (res) => { + resolve(`data:${prefix}${extension};base64,${res.data}`) + }, + fail: (error) => { + console.error({ error, path }) + reject(error) + } + }) + } + // #endif + + // #ifdef APP-PLUS + plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), (entry) => { + entry.file((file : any) => { + const fileReader = new plus.io.FileReader() + fileReader.onload = (data) => { + resolve(data.target.result) + } + fileReader.onerror = (error) => { + console.error({ error, path }) + reject(error) + } + fileReader.readAsDataURL(file) + }, reject) + }, reject) + // #endif + }) +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/platform/index.ts b/QXTfront/uni_modules/lime-shared/platform/index.ts new file mode 100644 index 0000000..55fd412 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/platform/index.ts @@ -0,0 +1,34 @@ +// @ts-nocheck +export function getPlatform():Uni { + // #ifdef MP-WEIXIN + return wx + // #endif + // #ifdef MP-BAIDU + return swan + // #endif + // #ifdef MP-ALIPAY + return my + // #endif + // #ifdef MP-JD + return jd + // #endif + // #ifdef MP-QQ + return qq + // #endif + // #ifdef MP-360 + return qh + // #endif + // #ifdef MP-KUAISHOU + return ks + // #endif + // #ifdef MP-LARK||MP-TOUTIAO + return tt + // #endif + // #ifdef MP-DINGTALK + return dd + // #endif + // #ifdef QUICKAPP-WEBVIEW || QUICKAPP-WEBVIEW-UNION || QUICKAPP-WEBVIEW-HUAWEI + return qa + // #endif + return uni +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/raf/index.ts b/QXTfront/uni_modules/lime-shared/raf/index.ts new file mode 100644 index 0000000..876efd4 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/raf/index.ts @@ -0,0 +1,12 @@ +// @ts-nocheck + +// #ifdef UNI-APP-X && APP +// export * from './uvue' +export { raf, doubleRaf, cancelRaf } from './uvue' +// #endif + + +// #ifndef UNI-APP-X && APP +// export * from './vue' +export { raf, doubleRaf, cancelRaf } from './vue' +// #endif diff --git a/QXTfront/uni_modules/lime-shared/raf/uvue.uts b/QXTfront/uni_modules/lime-shared/raf/uvue.uts new file mode 100644 index 0000000..1b0d9f2 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/raf/uvue.uts @@ -0,0 +1,48 @@ +// @ts-nocheck +// 是否支持被动事件监听 +export const supportsPassive = true; + +// #ifdef uniVersion < 4.25 +// 请求动画帧 +export function raf(fn: TimerCallback): number { + return setTimeout(fn, 1000 / 60); +} + +// 取消动画帧 +export function cancelRaf(id: number) { + clearTimeout(id); +} + + +// 双倍动画帧 +export function doubleRaf(fn: TimerCallback): void { + raf(():number => raf(fn)); // 在下一帧回调中再次请求动画帧,实现双倍动画帧效果 +} +// #endif + + +// #ifdef uniVersion >= 4.25 +// 请求动画帧 +export function raf(fn: UniAnimationFrameCallback): number +export function raf(fn: UniAnimationFrameCallbackWithNoArgument): number +export function raf(fn: any): number { + if(typeof fn == 'UniAnimationFrameCallback') { + return requestAnimationFrame(fn as UniAnimationFrameCallback); + } else { + return requestAnimationFrame(fn as UniAnimationFrameCallbackWithNoArgument); + } +} + +// 取消动画帧 +export function cancelRaf(id: number) { + cancelAnimationFrame(id); +} + +// 双倍动画帧 +export function doubleRaf(fn: UniAnimationFrameCallback): void +export function doubleRaf(fn: UniAnimationFrameCallbackWithNoArgument): void +export function doubleRaf(fn: any): void { + raf(():number => raf(fn)); // 在下一帧回调中再次请求动画帧,实现双倍动画帧效果 +} +// #endif + diff --git a/QXTfront/uni_modules/lime-shared/raf/vue.ts b/QXTfront/uni_modules/lime-shared/raf/vue.ts new file mode 100644 index 0000000..98a364e --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/raf/vue.ts @@ -0,0 +1,32 @@ +// @ts-nocheck +type Callback = () => void//Function +// 是否支持被动事件监听 +export const supportsPassive = true; + +// 请求动画帧 +export function raf(fn : Callback) : number { + // #ifndef WEB + return setTimeout(fn, 1000 / 60); // 请求动画帧 + // #endif + // #ifdef WEB + return requestAnimationFrame(fn); // 请求动画帧 + // #endif +} + +// 取消动画帧 +export function cancelRaf(id : number) { + // 如果是在浏览器环境下,使用 cancelAnimationFrame 方法 + // #ifdef WEB + cancelAnimationFrame(id); // 取消动画帧 + // #endif + // #ifndef WEB + clearTimeout(id); // 取消动画帧 + // #endif +} + +// 双倍动画帧 +export function doubleRaf(fn : Callback) : void { + raf(() => { + raf(fn) + }); // 在下一帧回调中再次请求动画帧,实现双倍动画帧效果 +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/random/index.ts b/QXTfront/uni_modules/lime-shared/random/index.ts new file mode 100644 index 0000000..49a21ed --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/random/index.ts @@ -0,0 +1,24 @@ +// @ts-nocheck +/** + * 生成一个指定范围内的随机数 + * @param min 随机数的最小值 + * @param max 随机数的最大值 + * @param fixed 随机数的小数位数,默认为 0 + * @returns 生成的随机数 + */ + +export function random(min: number, max: number, fixed: number = 0):number { + // 将 min 和 max 转换为数字类型 + // min = +min || 0; + // max = +max || 0; + // 计算随机数范围内的一个随机数 + const num = Math.random() * (max - min) + min; + // 如果 fixed 参数为 0,则返回四舍五入的整数随机数;否则保留固定小数位数 + // Number + return fixed == 0 ? Math.round(num) : parseFloat(num.toFixed(fixed)); +} + +// 示例 +// console.log(random(0, 10)); // 输出:在 0 和 10 之间的一个整数随机数 +// console.log(random(0, 1, 2)); // 输出:在 0 和 1 之间的一个保留两位小数的随机数 +// console.log(random(1, 100, 3)); // 输出:在 1 和 100 之间的一个保留三位小数的随机数 \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/range/index.ts b/QXTfront/uni_modules/lime-shared/range/index.ts new file mode 100644 index 0000000..483b7d1 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/range/index.ts @@ -0,0 +1,36 @@ +// @ts-nocheck +/** + * 生成一个数字范围的数组 + * @param start 范围的起始值 + * @param end 范围的结束值 + * @param step 步长,默认为 1 + * @param fromRight 是否从右侧开始生成,默认为 false + * @returns 生成的数字范围数组 + */ +export function range(start : number, end : number, step : number = 1, fromRight : boolean = false) : number[] { + let index = -1; + // 计算范围的长度 + let length = Math.max(Math.ceil((end - start) / step), 0); + // 创建一个长度为 length 的数组 + // #ifdef APP-ANDROID + const result = Array.fromNative(new IntArray(length.toInt())); + // #endif + // #ifndef APP-ANDROID + const result = new Array(length); + // #endif + + // 使用循环生成数字范围数组 + let _start = start + while (length-- > 0) { + // 根据 fromRight 参数决定从左侧还是右侧开始填充数组 + result[fromRight ? length : ++index] = _start; + _start += step; + } + return result; +} + + +// 示例 +// console.log(range(0, 5)); // 输出: [0, 1, 2, 3, 4] +// console.log(range(1, 10, 2, true)); // 输出: [9, 7, 5, 3, 1] +// console.log(range(5, 0, -1)); // 输出: [5, 4, 3, 2, 1] \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/readme.md b/QXTfront/uni_modules/lime-shared/readme.md new file mode 100644 index 0000000..d6e8658 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/readme.md @@ -0,0 +1,516 @@ +# lime-shared 工具库 +- 本人插件的几个公共函数 +- 按需引入 + +## 文档 + 🚀 [shared【站点1】](https://limex.qcoon.cn/shared/overview.html) + 🌍 [shared【站点2】](https://limeui.netlify.app/shared/overview.html) + 🔥 [shared【站点3】](https://limeui.familyzone.top/shared/overview.html) + + +## 安装 +在插件市场导入即可 + +## 使用 +按需引入只会引入相关的方法,不要看着 插件函数列表多 而占空间,只要不引用不会被打包 +```js +import {getRect} from '@/uni_modules/lime-shared/getRect' +``` + +## 目录 ++ [getRect](#api_getRect): 获取节点尺寸信息 ++ [addUnit](#api_addUnit): 将未带单位的数值添加px,如果有单位则返回原值 ++ [unitConvert](#api_unitConvert): 将带有rpx|px的字符转成number,若本身是number则直接返回 ++ [canIUseCanvas2d](#api_canIUseCanvas2d): 环境是否支持使用 canvas 2d ++ [getCurrentPage](#api_getCurrentPage): 获取当前页 ++ [base64ToPath](#api_base64ToPath): 把base64的图片转成临时路径 ++ [pathToBase64](#api_pathToBase64): 把图片的临时路径转成base64 ++ [sleep](#api_sleep): async 内部程序等待一定时间后再执行 ++ [throttle](#api_throttle): 节流 ++ [debounce](#api_debounce): 防抖 ++ [random](#api_random): 返回指定范围的随机数 ++ [range](#api_range): 生成区间数组 ++ [clamp](#api_clamp): 夹在min和max之间的数值 ++ [floatAdd](#api_floatAdd): 返回两个浮点数相加的结果 ++ [fillZero](#api_fillZero): 补零,如果传入的是个位数则在前面补0 ++ [exif](#api_exif): 获取图片exif ++ [selectComponent](#api_selectComponent): 获取页面或当前实例的指定组件 ++ [createAnimation](#api_createAnimation): uni.createAnimation ++ [animation](#api_animation): 数值从一个值到另一个值的过渡 ++ [camelCase](#api_camelCase): 字符串转换为 camelCase 或 PascalCase 风格的命名约定 ++ [kebabCase](#api_kebabCase): 将字符串转换为指定连接符的命名约定 ++ [closest](#api_closest): 在给定数组中找到最接近目标数字的元素 ++ [shuffle](#api_shuffle): 将给定的数组打乱 ++ [merge](#api_merge): 深度合并两个对象 ++ [isBase64](#api_isBase64): 判断字符串是否为base64 ++ [isNumber](#api_isNumber): 检查一个值是否为数字类型 ++ [isNumeric](#api_isNumeric): 检查一个值是否为数字类型或表示数字的字符串 ++ [isString](#api_isString): 检查一个值是否为字符串类型 ++ [isIP](#api_isIP): 检查一个值是否为IP地址格式 ++ [composition-api](#api_composition-api): 为兼容vue2 + +## Utils + + +### getRect +- 返回节点尺寸信息 + +```js +// 组件内需要传入上下文 +// 如果是nvue 则需要在节点上加与id或class同名的ref +getRect('#id',this).then(res => {}) +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + + +### addUnit +- 将未带单位的数值添加px,如果有单位则返回原值 + +```js +addUnit(10) +// 10px +``` + +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + + +### unitConvert +- 将带有rpx|px的字符转成number,若本身是number则直接返回 + +```js +unitConvert('10rpx') +// 5 设备不同 返回的值也不同 +unitConvert('10px') +// 10 +unitConvert(10) +// 10 +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + +### canIUseCanvas2d +- 环境是否支持使用 canvas 2d + +```js +canIUseCanvas2d() +// 若支持返回 true 否则 false +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + +### getCurrentPage +- 获取当前页 + +```js +const page = getCurrentPage() +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + +### base64ToPath +- 把base64的图片转成临时路径 + +```js +base64ToPath(`xxxxx`).then(res => {}) +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + +### pathToBase64 +- 把图片的临时路径转成base64 + +```js +pathToBase64(`xxxxx/xxx.png`).then(res => {}) +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + +### sleep +- 睡眠,让 async 内部程序等待一定时间后再执行 + +```js +async next () => { + await sleep(300) + console.log('limeui'); +} +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### throttle +- 节流 + +```js +throttle((nama) => {console.log(nama)}, 200)('limeui'); +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### debounce +- 防抖 + +```js +debounce((nama) => {console.log(nama)}, 200)('limeui'); +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### random +- 返回指定范围的随机数 + +```js +random(1, 5); +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### range +- 生成区间数组 + +```js +range(0, 5) +// [0,1,2,3,4,5] +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + +### clamp +- 夹在min和max之间的数值,如小于min,返回min, 如大于max,返回max,否侧原值返回 + +```js +clamp(0, 10, -1) +// 0 +clamp(0, 10, 11) +// 10 +clamp(0, 10, 9) +// 9 +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + +### floatAdd +- 返回两个浮点数相加的结果 + +```js +floatAdd(0.1, 0.2) // 0.3 +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### fillZero +- 补零,如果传入的是`个位数`则在前面补0 + +```js +fillZero(9); +// 09 +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### exif +- 获取图片exif +- 支持临时路径、base64 + +```js +uni.chooseImage({ + count: 1, //最多可以选择的图片张数 + sizeType: "original", + success: (res) => { + exif.getData(res.tempFiles[0], function() { + let tagj = exif.getTag(this, "GPSLongitude"); + let Orientation = exif.getTag(this, 'Orientation'); + console.log(tagj, Orientation) + }) + } +}) +``` + +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | x | + + +### selectComponent +- 获取页面或当前实例的指定组件,会在页面或实例向所有的节点查找(包括子组件或子子组件) +- 仅vue3,vue2没有测试过 + +```js +// 当前页面 +const page = getCurrentPage() +selectComponent('.custom', {context: page}).then(res => { +}) +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | x | + + + +### createAnimation +- 创建动画,与uni.createAnimation使用方法一致,只为了抹平nvue + +```html + +``` +```js +const ball = ref(null) +const animation = createAnimation({ + transformOrigin: "50% 50%", + duration: 1000, + timingFunction: "ease", + delay: 0 +}) + +animation.scale(2,2).rotate(45).step() +// nvue 无导出数据,这样写只为了平台一致, +// nvue 需要把 ref 传入,其它平台不需要 +const animationData = animation.export(ball.value) +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + +### camelCase +- 将字符串转换为 camelCase 或 PascalCase 风格的命名约定 + +```js +camelCase("hello world") // helloWorld +camelCase("hello world", true) // HelloWorld +``` + +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### kebabCase +- 将字符串转换为指定连接符的命名约定 + +```js +kebabCase("helloWorld") // hello-world +kebabCase("hello world_example") // hello-world-example +kebabCase("helloWorld", "_") // hello_world +``` + +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + + +### closest +- 在给定数组中找到最接近目标数字的元素 + +```js +closest([1, 3, 5, 7, 9], 6) // 5 +``` + +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### shuffle +- 在给定数组中找到最接近目标数字的元素 + +```js +shuffle([1, 3, 5, 7, 9]) +``` + +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### merge +- 深度合并两个对象 + +```js +const original = { color: 'red' }; +const merged = merge({ ...original }, { color: 'blue', size: 'M' }); + +console.log('original', original); // 输出: { color: 'red' } (保持不变) +console.log('merged', merged); // 输出: { color: 'red', size: 'M' } + + +type ColorType = { + color?: string, + size?: string, +} + +const merged2 = merge({ color: 'red' } as ColorType, { color: 'blue', size: 'M' } as ColorType); +console.log('merged2', merged2) +``` + +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + + +### isBase64 +- 判断字符串是否为base64 + +```js +isBase64('xxxxx') +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### isNumber +- 检查一个值是否为数字类型 + +```js +isNumber('0') // false +isNumber(0) // true +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + +### isNumeric +- 检查一个值是否为数字类型或表示数字的字符串 + +```js +isNumeric('0') // true +isNumeric(0) // true +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + +### isString +- 检查一个值是否为数字类型或表示数字的字符串 + +```js +isString('0') // true +isString(0) // false +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + +### isIP +- 检查一个值是否为IP地址格式,可以检测ipv4,ipv6 + +```js +console.log(isIP('192.168.1.1')); // true +console.log(isIP('2001:0db8:85a3:0000:0000:8a2e:0370:7334')); // true + +console.log(isIP('192.168.1.1', 4)); // true +console.log(isIP('255.255.255.255', { version: 4 })); // true + +// 标准IPv6格式 +console.log(isIP('2001:0db8:85a3:0000:0000:8a2e:0370:7334', 6)); // true +console.log(isIP('fe80::1%eth0', { version: 6 })); // true(带区域标识) + +``` +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | √ | + + + + +## composition-api +- 因本人插件需要兼容vue2/vue3,故增加一个vue文件,代替条件编译 +- vue2需要在main.js加上这一段 +```js +// vue2 +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' +Vue.use(VueCompositionAPI) +``` + +```js +//使用 +import {computed, onMounted, watch, reactive} from '@/uni_modules/lime-shared/vue' +``` + +##### 兼容性 +| uni-app | uni-app x | +|------------|----------------------------------| +| √ | x | diff --git a/QXTfront/uni_modules/lime-shared/selectAllComponent/index.ts b/QXTfront/uni_modules/lime-shared/selectAllComponent/index.ts new file mode 100644 index 0000000..e30a2c8 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/selectAllComponent/index.ts @@ -0,0 +1,10 @@ +// @ts-nocheck +// #ifdef UNI-APP-X +// export * from './uvue.uts' +export { selectAllComponent } from './uvue.uts' +// #endif + +// #ifndef UNI-APP-X +// export * from './vue.ts' +export { selectAllComponent } from './vue.ts' +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/selectAllComponent/uvue.uts b/QXTfront/uni_modules/lime-shared/selectAllComponent/uvue.uts new file mode 100644 index 0000000..07c9fcd --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/selectAllComponent/uvue.uts @@ -0,0 +1,39 @@ +// @ts-nocheck +import { type ComponentPublicInstance } from 'vue'; + +type SelectOptions = { + context : ComponentPublicInstance, + needAll : boolean | null, + +} + +export function selectAllComponent(selector : string, options : UTSJSONObject) : ComponentPublicInstance[]|null { + const context = options.get('context')! as ComponentPublicInstance; + let needAll = options.get('needAll') as boolean; + let result:ComponentPublicInstance[] = [] + + if(needAll == null) { needAll = true }; + + if(context.$children.length > 0) { + const queue:ComponentPublicInstance[] = [...context.$children]; + while(queue.length > 0) { + const child = queue.shift(); + const name = child?.$options?.name; + if(name == selector) { + result.push(child as ComponentPublicInstance) + } else { + const children = child?.$children + if(children !== null) { + queue.push(...children) + } + } + if(result.length > 0 && !needAll) { + break; + } + } + } + if(result.length > 0) { + return result + } + return null +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/selectAllComponent/vue.ts b/QXTfront/uni_modules/lime-shared/selectAllComponent/vue.ts new file mode 100644 index 0000000..380bd7a --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/selectAllComponent/vue.ts @@ -0,0 +1,151 @@ +// @ts-nocheck +interface SelectOptions { + context?: any + needAll?: boolean + node?: boolean +} +// #ifdef MP +function selectMPComponent(key: string, name: string, context: any, needAll: boolean) { + const {proxy, $vm} = context + context = $vm || proxy + if(!['ref','component'].includes(key)) { + const queue = [context] + let result = null + const selector = (key == 'id' ? '#': '.') + name; + while(queue.length > 0) { + const child = queue.shift(); + const flag = child?.selectComponent(selector) + if(flag) { + if(!needAll) {return result = flag.$vm} + return result = child.selectAllComponents(selector).map(item => item.$vm) + } else { + child.$children && (queue.push(...child.$children)); + } + } + return result + } else { + const {$templateRefs} = context.$ + const nameMap = {} + for (var i = 0; i < $templateRefs.length; i++) { + const item = $templateRefs[i] + nameMap[item.i] = item.r + } + let result = [] + if(context.$children.length) { + const queue = [...context.$children] + while(queue.length > 0) { + const child = queue.shift(); + if(key == 'component' && (child.type?.name === name || child.$?.type?.name === name)) { + result.push(child) + } else if(child.$refs && child.$refs[name]) { + result = child.$refs[name] + } else if(nameMap[child.id] === name){ + result.push(child) + } else { + child.$children && (queue.push(...child.$children)); + } + if(result.length && !needAll) { + return; + } + } + } + return needAll ? result : result[0] + } +} +// #endif +// #ifdef H5 +function selectH5Component(key: string, name: string, context: any, needAll: boolean) { + const {_, component } = context + const child = {component: _ || component || context, children: null , subTree: null, props: null} + let result = [] + let queue = [child] + while(queue.length > 0 ) { + const child = queue.shift() + const {component, children , props, subTree} = child + if(key === 'component' && component?.type?.name == name) { + result.push(component) + } else if(key === 'ref' && component && (props?.ref == name || component[key][name])) { + if(props?.ref == name) { + //exposed + result.push(component) + } else if(component[key][name]) { + result.push(component[key][name]) + } + } else if(key !== 'ref' && component?.exposed && new RegExp(`\\b${name}\\b`).test(component.attrs[key])) { + // exposed + result.push(component) + } else if(children && Array.isArray(children)) { + queue.push(...children) + } else if(!component && subTree) { + queue.push(subTree) + } else if(component?.subTree) { + queue.push(component.subTree) + } + if(result.length && !needAll) { + break + } + } + return needAll ? result : result[0] +} +// #endif +// #ifdef APP +function selectAPPComponent(key: string, name: string, context: any, needAll: boolean, node: boolean) { + let result = [] + // const {_, component} = context + // const child = {component: _ || component || context, children: null, props: null, subTree: null} + const queue = [context] + while(queue.length > 0) { + const child = queue.shift() + const {component, children, props, subTree} = child + const isComp = component && props && component.exposed && !node + if(key == 'component' && child.type && child.type.name === name) { + result.push(component) + } else if(props?.[key] === name && node) { + result.push(child) + } else if(key === 'ref' && isComp && (props.ref === name || props.ref_key === name)) { + // exposed + result.push(component) + } else if(key !== 'ref' && isComp && new RegExp(`\\b${name}\\b`).test(props[key])) { + // exposed + result.push(component) + } + // else if(component && component.subTree && Array.isArray(component.subTree.children)){ + // queue.push(...component.subTree.children) + // } + else if(subTree) { + queue.push(subTree) + } else if(component && component.subTree){ + queue.push(component.subTree) + } + else if(children && Array.isArray(children)) { + queue.push(...children) + } + if(result.length && !needAll) { + break; + } + } + return needAll ? result : result[0] +} +// #endif +export function selectAllComponent(selector: string, options: SelectOptions = {}) { + // . class + // # id + // $ ref + // @ component name + const reg = /^(\.|#|@|\$)([a-zA-Z_0-9\-]+)$/; + if(!reg.test(selector)) return null + let { context, needAll = true, node} = options + const [,prefix, name] = selector.match(reg) + const symbolMappings = {'.': 'class', '#': 'id', '$':'ref', '@':'component'} + + const key = symbolMappings [prefix] //prefix === '.' ? 'class' : prefix === '#' ? 'id' : 'ref'; + // #ifdef MP + return selectMPComponent(key, name, context, needAll) + // #endif + // #ifdef H5 + return selectH5Component(key, name, context, needAll) + // #endif + // #ifdef APP + return selectAPPComponent(key, name, context, needAll, node) + // #endif +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/selectComponent/index.ts b/QXTfront/uni_modules/lime-shared/selectComponent/index.ts new file mode 100644 index 0000000..759272e --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/selectComponent/index.ts @@ -0,0 +1,9 @@ +// @ts-nocheck +// #ifndef UNI-APP-X +// export * from './vue.ts' +export { selectComponent } from './vue.ts' +// #endif +// #ifdef UNI-APP-X +// export * from './uvue.uts' +export { selectComponent } from './uvue.uts' +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/selectComponent/uvue.uts b/QXTfront/uni_modules/lime-shared/selectComponent/uvue.uts new file mode 100644 index 0000000..c2aa2bc --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/selectComponent/uvue.uts @@ -0,0 +1,75 @@ +// @ts-nocheck +import { type ComponentPublicInstance } from 'vue'; +// #ifdef APP +function findChildren(selector: string, context: ComponentPublicInstance, needAll: boolean): ComponentPublicInstance [] | null{ + let result:ComponentPublicInstance[] = [] + + if(context !== null && context.$children.length > 0) { + const queue:ComponentPublicInstance[] = [...context.$children]; + while(queue.length > 0) { + const child = queue.shift(); + const name = child?.$options?.name; + if(name == selector) { + result.push(child as ComponentPublicInstance) + } else { + const children = child?.$children + if(children !== null) { + queue.push(...children) + } + } + if(result.length > 0 && !needAll) { + break; + } + } + } + if(result.length > 0) { + return result + } + return null +} + +class Query { + context : ComponentPublicInstance | null = null + selector : string = '' + // components : ComponentPublicInstance[] = [] + constructor(selector : string, context : ComponentPublicInstance | null) { + this.selector = selector + this.context = context + } + in(context : ComponentPublicInstance) : Query { + return new Query(this.selector, context) + } + find(): ComponentPublicInstance | null { + const selector = this.selector + if(selector == '') return null + const component = findChildren(selector, this.context!, false) + return component != null ? component[0]: null + } + findAll():ComponentPublicInstance[] | null { + const selector = this.selector + if(selector == '') return null + return findChildren(selector, this.context!, true) + } + closest(): ComponentPublicInstance | null { + const selector = this.selector + if(selector == '') return null + let parent = this.context!.$parent + let name = parent?.$options?.name; + while (parent != null && (name == null || selector != name)) { + parent = parent.$parent + if (parent != null) { + name = parent.$options.name + } + } + return parent + } +} + +export function selectComponent(selector: string): Query{ + return new Query(selector, null) +} +// #endif + +// selectComponent('selector').in(this).find() +// selectComponent('selector').in(this).findAll() +// selectComponent('selector').in(this).closest() diff --git a/QXTfront/uni_modules/lime-shared/selectComponent/vue.ts b/QXTfront/uni_modules/lime-shared/selectComponent/vue.ts new file mode 100644 index 0000000..9fca0cd --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/selectComponent/vue.ts @@ -0,0 +1,149 @@ +// @ts-nocheck +// #ifdef MP +function findChildren(selector : string, context : ComponentPublicInstance, needAll : boolean) { + const { proxy, $vm } = context + context = $vm || proxy + if ((selector.startsWith('.') || selector.startsWith('#'))) { + const queue = [context] + let result = null + while (queue.length > 0) { + const child = queue.shift(); + const flag = child?.selectComponent(selector) + if (flag) { + if (!needAll) { return result = flag.$vm } + return result = child.selectAllComponents(selector).map(item => item.$vm) + } else { + child.$children && (queue.push(...child.$children)); + } + } + return result + } else { + const { $templateRefs } = context.$ + const selectorValue = /#|\.|@|$/.test(selector) ? selector.substring(1) : selector + const nameMap = {} + for (var i = 0; i < $templateRefs.length; i++) { + const item = $templateRefs[i] + nameMap[item.i] = item.r + } + let result = [] + if (context.$children.length) { + const queue = [...context.$children] + while (queue.length > 0) { + const child = queue.shift(); + if (child.type?.name === selectorValue || child.$?.type?.name === selectorValue) { + result.push(child) + } else if (child.$refs && child.$refs[selectorValue]) { + result = child.$refs[selectorValue] + } else if (nameMap[child.id] === selectorValue) { + result.push(child) + } else { + child.$children && (queue.push(...child.$children)); + } + if (result.length && !needAll) { + return; + } + } + } + return needAll ? result : result[0] + } +} +// #endif + +// #ifdef H5 +function findChildren(selector : string, context : ComponentPublicInstance, needAll : boolean){ + const {_, component } = context + const child = {component: _ || component || context, children: null , subTree: null, props: null} + let result = [] + let queue = [child] + const selectorValue = /#|\.|@|$/.test(selector) ? selector.substring(1) : selector + while(queue.length > 0 ) { + const child = queue.shift() + const {component, children , props, subTree} = child + if(component?.type?.name == selectorValue) { + result.push(component) + } else if(selector.startsWith('$') && component && (props?.ref == selectorValue || component[key][selectorValue])) { + if(props?.ref == selectorValue) { + //exposed + result.push(component) + } else if(component[key][selectorValue]) { + result.push(component[key][selectorValue]) + } + } else if(!selector.startsWith('$') && component?.exposed && new RegExp(`\\b${selectorValue}\\b`).test(component.attrs[key])) { + // exposed + result.push(component) + } else if(children && Array.isArray(children)) { + queue.push(...children) + } else if(!component && subTree) { + queue.push(subTree) + } else if(component?.subTree) { + queue.push(component.subTree) + } + if(result.length && !needAll) { + break + } + } + return needAll ? result : result[0] +} +// #endif + +// #ifdef APP +function findChildren(selector : string, context : ComponentPublicInstance, needAll : boolean){ + let result = [] + const selectorValue = /#|\.|@|$/.test(selector) ? selector.substring(1) : selector + const queue = [context] + while(queue.length > 0) { + const child = queue.shift() + const {component, children, props, subTree} = child + const isComp = component && props && component.exposed && !node + if(child.type && child.type.name === selectorValue) { + result.push(component) + } else if(props?.[key] === selectorValue && node) { + result.push(child) + } else if(selector.startsWith('$') && isComp && (props.ref === selectorValue || props.ref_key === selectorValue)) { + // exposed + result.push(component) + } else if(!selector.startsWith('$') && isComp && new RegExp(`\\b${selectorValue}\\b`).test(props[key])) { + // exposed + result.push(component) + } + else if(subTree) { + queue.push(subTree) + } else if(component && component.subTree){ + queue.push(component.subTree) + } + else if(children && Array.isArray(children)) { + queue.push(...children) + } + if(result.length && !needAll) { + break; + } + } + return needAll ? result : result[0] +} +// #endif + +class Query { + context : ComponentPublicInstance | null = null + selector : string = '' + // components : ComponentPublicInstance[] = [] + constructor(selector : string, context : ComponentPublicInstance | null) { + this.selector = selector + this.context = context + } + in(context : ComponentPublicInstance) : Query { + return new Query(this.selector, context) + } + find() : ComponentPublicInstance | null { + return findChildren(this.selector, this.context, false) + } + findAll() : ComponentPublicInstance[] | null { + return findChildren(this.selector, this.context, true) + } + closest() : ComponentPublicInstance | null { + return null + } +} + +export function selectComponent(selector: string) { + return new Query(selector) +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/selectElement/index.ts b/QXTfront/uni_modules/lime-shared/selectElement/index.ts new file mode 100644 index 0000000..fbe5fb4 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/selectElement/index.ts @@ -0,0 +1,277 @@ +// @ts-nocheck +import {isDef} from '../isDef' +// #ifdef UNI-APP-X +import {type ComponentPublicInstance} from '../vue' +// #endif + +type HasSelectorFunc = (selector : string, element : UniElement) => boolean + +const hasSelectorClassName : HasSelectorFunc = (selector : string, element : UniElement) : boolean => { + return element.classList.includes(selector) +} +const hasSelectorId : HasSelectorFunc = (selector : string, element : UniElement) : boolean => { + return element.getAttribute("id") == selector +} +const hasSelectorTagName : HasSelectorFunc = (selector : string, element : UniElement) : boolean => { + return element.tagName!.toLowerCase() == selector.toLowerCase() +} + +type ProcessSelectorResult = { + selectorValue : string + hasSelector : HasSelectorFunc +} +const processSelector = (selector : string) : ProcessSelectorResult => { + + const selectorValue = /#|\./.test(selector) ? selector.substring(1) : selector + let hasSelector : HasSelectorFunc + + if (selector.startsWith('.')) { + hasSelector = hasSelectorClassName + } else if (selector.startsWith('#')) { + hasSelector = hasSelectorId + } else { + hasSelector = hasSelectorTagName + } + + return { + selectorValue, + hasSelector + } as ProcessSelectorResult +} + + +function isNotEmptyString(str:string): boolean { + return str.length > 0; +} + +function isElement(element:UniElement|null):boolean { + return isDef(element) && element?.tagName != 'COMMENT'; +} + +type ElementArray = Array +class Query { + context : ComponentPublicInstance | null = null + selector : string = '' + elements : ElementArray = [] + constructor(selector : string | null, context : ComponentPublicInstance | null) { + this.context = context + if(selector != null){ + this.selector = selector + } + this.find(this.selector) + } + in(context : ComponentPublicInstance) : Query { + return new Query(this.selector, context) + } + findAll(selector : string): Query { + if (isDef(this.context)) { + const root = this.context?.$el //as Element | null; + if (isDef(root)) { + this.elements = [root!] //as ElementArray + } + const { selectorValue, hasSelector } = processSelector(selector) + const foundElements : ElementArray = []; + + function findChildren(element : UniElement) { + element.children.forEach((child : UniElement) => { + if (hasSelector(selectorValue, child)) { + foundElements.push(child) + } + }) + } + this.elements.forEach(el => { + findChildren(el!); + }); + this.elements = foundElements + } else if (selector.startsWith('#')) { + const element = uni.getElementById(selector) + if (isElement(element!)) { + this.elements = [element] + } + } + return this; + } + /** + * 在当前元素集合中查找匹配的元素 + */ + find(selector : string) : Query { + if (isDef(this.context)) { + const root = this.context?.$el //as Element | null; + if (isElement(root)) { + this.elements = [root] //as ElementArray + } + if(isNotEmptyString(selector) && this.elements.length > 0){ + const { selectorValue, hasSelector } = processSelector(selector) + const foundElements : ElementArray = []; + function findChildren(element : UniElement) { + element.children.forEach((child : UniElement) => { + if (hasSelector(selectorValue, child) && foundElements.length < 1) { + foundElements.push(child) + } + if (foundElements.length < 1) { + findChildren(child); + } + }) + } + this.elements.forEach(el => { + findChildren(el!); + }); + this.elements = foundElements + } + + } else if (selector.startsWith('#')) { + const element = uni.getElementById(selector) + if (isElement(element!)) { + this.elements = [element] + } + } + return this; + } + /** + * 获取当前元素集合的直接子元素 + */ + children() : Query { + // if (this.elements.length > 0) { + // const children = this.elements.reduce((acc, el) => [...acc, ...Array.from(el.children)], []); + // this.elements = children; + // } + return this; + } + /** + * 获取当前元素集合的父元素 + */ + parent() : Query { + // if (this.elements.length > 0) { + // const parents = this.elements.map(el => el.parentElement).filter(parent => parent !== null) as ElementArray; + // this.elements = parents + // // this.elements = Array.from(new Set(parents)); + // } + return this; + } + /** + * 获取当前元素集合的兄弟元素 + */ + siblings() : Query { + // if (this.elements.length > 0) { + // const siblings = this.elements.reduce((acc, el) => [...acc, ...Array.from(el.parentElement?.children || [])], []); + // this.elements = siblings.filter(sibling => sibling !== null && !this.elements?.includes(sibling)); + // } + return this; + } + /** + * 获取当前元素集合的下一个兄弟元素 + */ + next() : Query { + // if (this.elements.length > 0) { + // const nextElements = this.elements.map(el => el.nextElementSibling).filter(next => next !== null) as ElementArray; + // this.elements = nextElements; + // } + return this; + } + /** + * 获取当前元素集合的上一个兄弟元素 + */ + prev() : Query { + // if (this.elements.length > 0) { + // const prevElements = this.elements.map(el => el.previousElementSibling).filter(prev => prev !== null) as ElementArray; + // this.elements = prevElements; + // } + return this; + } + /** + * 从当前元素开始向上查找匹配的元素 + */ + closest(selector : string) : Query { + if (isDef(this.context)) { + // && this.context.$parent != null && this.context.$parent.$el !== null + if(this.elements.length == 0 && isDef(this.context?.$parent) && isElement(this.context!.$parent?.$el)){ + this.elements = [this.context!.$parent?.$el!] + } + + const selectorsArray = selector.split(',') + // const { selectorValue, hasSelector } = processSelector(selector) + const processedSelectors = selectorsArray.map((selector: string):ProcessSelectorResult => processSelector(selector)) + const closestElements = this.elements.map((el) : UniElement | null => { + let closestElement : UniElement | null = el + while (closestElement !== null) { + // if (hasSelector(selectorValue, closestElement)) { + // break; + // } + const isMatchingSelector = processedSelectors.some(({selectorValue, hasSelector}):boolean => { + return hasSelector(selectorValue, closestElement!) + }) + if(isMatchingSelector){ + break; + } + closestElement = closestElement.parentElement; + } + return closestElement + }) + this.elements = closestElements.filter((closest : UniElement | null) : boolean => isDef(closest))// as ElementArray + + } + return this; + } + + /** + * 从当前元素集合中过滤出匹配的元素 + */ + filter() : Query { + + return this; + } + /** + * 从当前元素集合中排除匹配的元素 + */ + not() { } + /** + * 从当前元素集合中查找包含匹配元素的元素 + */ + has() { } + /** + * 获取当前元素集合的第一个 + */ + first() : Query { + if (this.elements.length > 0) { + // this.elements = [this.elements[0]]; + } + return this; + } + /** + * 最后一个元素 + */ + last() : Query { + if (this.elements.length > 0) { + // this.elements = [this.elements[this.elements.length - 1]]; + } + return this; + } + /** + * 获取当前元素在其兄弟元素中的索引 + */ + index() : number | null { + // if (this.elements.length > 0 && this.elements.length > 0 && this.elements[0].parentElement !== null) { + // return Array.from(this.elements[0].parentElement.children).indexOf(this.elements[0]); + // } + return null; + } + get(index : number) : UniElement | null { + if (this.elements.length > index) { + return this.elements[index] //as Element + } + return null + } +} + +export function selectElement(selector : string | null = null) : Query { + // if(typeof selector == 'string' || selector == null){ + // return new Query(selector as string | null, null) + // } + // else if(selector instanceof ComponentPublicInstance){ + // return new Query(null, selector) + // } + return new Query(selector, null) +} + +// $('xxx').in(this).find('xxx') +// $('xxx').in(this).get() \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/shuffle/index.ts b/QXTfront/uni_modules/lime-shared/shuffle/index.ts new file mode 100644 index 0000000..5b3ab51 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/shuffle/index.ts @@ -0,0 +1,16 @@ +// @ts-nocheck +/** + * 随机化数组中元素的顺序,使用 Fisher-Yates 算法 + * @description 函数接受一个数组作为参数,返回一个新的数组,其中包含原数组随机化顺序后的元素。 + * @param arr 要随机化的数组 + * @returns 一个新的数组,其中包含原数组随机化顺序后的元素。 + */ +export function shuffle(arr : T[]) : T[] { + for (let i = arr.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)) + const temp = arr[i] + arr[i] = arr[j] + arr[j] = temp + } + return arr +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/sleep/index.ts b/QXTfront/uni_modules/lime-shared/sleep/index.ts new file mode 100644 index 0000000..a01cdfd --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/sleep/index.ts @@ -0,0 +1,44 @@ +// @ts-nocheck +/** + * 延迟指定时间后解析的 Promise + * @param delay 延迟的时间(以毫秒为单位),默认为 300 毫秒 + * @returns 一个 Promise,在延迟结束后解析 + */ + + +// #ifdef UNI-APP-X && APP +function sleep(delay: number = 300):Promise { + return new Promise((resolve):void => {setTimeout(() => {resolve(true)}, delay)}); +} +export { + sleep +} + +// #endif + +// #ifndef UNI-APP-X && APP +export const sleep = (delay: number = 300) => + new Promise(resolve => setTimeout(resolve, delay)); + +// #endif + +// 示例 +// async function example() { +// console.log("Start"); + +// // 延迟 1 秒后执行 +// await sleep(1000); +// console.log("1 second later"); + +// // 延迟 500 毫秒后执行 +// await sleep(500); +// console.log("500 milliseconds later"); + +// // 延迟 2 秒后执行 +// await sleep(2000); +// console.log("2 seconds later"); + +// console.log("End"); +// } + +// example(); \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/throttle/index.ts b/QXTfront/uni_modules/lime-shared/throttle/index.ts new file mode 100644 index 0000000..65604cb --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/throttle/index.ts @@ -0,0 +1,89 @@ +// @ts-nocheck +/** + * 节流函数,用于限制函数的调用频率 + * @param fn 要进行节流的函数 + * @param interval 两次调用之间的最小间隔时间 + * @returns 节流后的函数 + */ +export type ThrottleOptions = { + /** + * 是否在节流开始时立即执行 + * @default true + */ + leading ?: boolean; + + /** + * 是否在节流结束后执行最后一次调用 + * @default true + */ + trailing ?: boolean; +} + + + +/** + * 节流函数,限制函数在一定时间内只能执行一次 + * @param func 需要节流的函数 + * @param wait 节流间隔时间(毫秒) + * @param options 配置选项 + * @param options.leading 是否在节流开始时立即执行(默认 true) + * @param options.trailing 是否在节流结束时执行最后一次调用(默认 true) + * @returns 返回节流后的函数 + */ +// #ifndef APP-ANDROID +export function throttle any>( + func : T, + wait : number, + options : ThrottleOptions = {} +) : (...args : Parameters) => void { + let lastCallTime = 0; + let timerId : ReturnType | null = null; + const { leading = true, trailing = true } = options; + return function (...args : Parameters) { + const now = Date.now(); + const timeSinceLastCall = now - lastCallTime; + // 1. 如果 leading=true 且距离上次调用超过 wait,立即执行 + if (leading && timeSinceLastCall >= wait) { + lastCallTime = now; + func.apply(this, args); + } + // 2. 如果 trailing=true,设置定时器在 wait 时间后执行最后一次调用 + else if (trailing && !timerId) { + timerId = setTimeout(() => { + lastCallTime = Date.now(); + func.apply(this, args); + timerId = null; + }, wait - timeSinceLastCall); + } + }; +} +// #endif + +// #ifdef APP-ANDROID +export function throttle( + func: (args : T) => void, + wait : number, + options : ThrottleOptions = {} +) : (args : T) => void { + let lastCallTime = 0; + let timerId = -1; + const { leading = true, trailing = true } = options; + return function (args : T) { + const now = Date.now(); + const timeSinceLastCall = now - lastCallTime; + // 1. 如果 leading=true 且距离上次调用超过 wait,立即执行 + if (leading && timeSinceLastCall >= wait) { + lastCallTime = now; + func(args); + } + // 2. 如果 trailing=true,设置定时器在 wait 时间后执行最后一次调用 + else if (trailing && timerId > -1) { + timerId = setTimeout(() => { + lastCallTime = Date.now(); + func(args); + timerId = -1; + }, wait - timeSinceLastCall); + } + }; +} +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/throttle/index_old.ts b/QXTfront/uni_modules/lime-shared/throttle/index_old.ts new file mode 100644 index 0000000..914be49 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/throttle/index_old.ts @@ -0,0 +1,112 @@ +// @ts-nocheck +/** + * 节流函数,用于限制函数的调用频率 + * @param fn 要进行节流的函数 + * @param delay 两次调用之间的最小间隔时间 + * @returns 节流后的函数 + */ + +// #ifndef UNI-APP-X && APP +// export function throttle(fn: (...args: any[]) => void, delay: number, options) { +// let flag = true; // 标记是否可以执行函数 + +// return (...args: any[]) => { +// if (flag) { +// flag = false; // 设置为不可执行状态 +// fn(...args); // 执行传入的函数 + +// setTimeout(() => { +// flag = true; // 经过指定时间后,设置为可执行状态 +// }, delay); +// } +// }; +// } + +export function throttle void>( + fn: T, + delay: number, + { leading = true, trailing = true }: { leading?: boolean; trailing?: boolean } = {} +): (...args: Parameters) => void { + let isCoolingDown = false; + let lastArgs: Parameters | null = null; + let timerId: ReturnType | null = null; + + const executeTrailing = () => { + if (trailing && lastArgs) { + fn(...lastArgs); + lastArgs = null; + } + isCoolingDown = false; + timerId = null; + }; + + return function (...args: Parameters) { + // 1. 如果不在冷却期,且 leading=true,立即执行 + if (!isCoolingDown && leading) { + fn(...args); + isCoolingDown = true; + timerId = setTimeout(executeTrailing, delay); + } + // 2. 如果在冷却期,记录最后一次调用的参数(用于 trailing) + else if (trailing) { + lastArgs = args; + } + }; +} +// #endif + + +// #ifdef UNI-APP-X && APP +// type Rfun = (...args: any[]) => void +// type Rfun = (...args: any[]) => void + +export function throttle( + fn: (args : T) => void, + delay: number):(args : T) => void { + let flag = true; // 标记是否可以执行函数 + + return (args : T) =>{ + if(flag){ + flag = false; + fn(args); + + setTimeout(()=>{ + flag = true; + }, delay) + } + } + // return (...args: any[]) => { + // // if (flag) { + // // flag = false; // 设置为不可执行状态 + // // fn(...args); // 执行传入的函数 + + // // setTimeout(() => { + // // flag = true; // 经过指定时间后,设置为可执行状态 + // // }, delay); + // // } + // }; +} + +// #endif + +// // 示例 +// // 定义一个被节流的函数 +// function handleScroll() { +// console.log("Scroll event handled!"); +// } + +// // 使用节流函数对 handleScroll 进行节流,间隔时间为 500 毫秒 +// const throttledScroll = throttle(handleScroll, 500); + +// // 模拟多次调用 handleScroll +// throttledScroll(); // 输出 "Scroll event handled!" +// throttledScroll(); // 不会输出 +// throttledScroll(); // 不会输出 + +// // 经过 500 毫秒后,再次调用 handleScroll +// setTimeout(() => { +// throttledScroll(); // 输出 "Scroll event handled!" +// }, 500); + + + diff --git a/QXTfront/uni_modules/lime-shared/toArray/index.ts b/QXTfront/uni_modules/lime-shared/toArray/index.ts new file mode 100644 index 0000000..e0840d2 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/toArray/index.ts @@ -0,0 +1,21 @@ +// @ts-nocheck +/** + * 将一个或多个元素转换为数组 + * @param item 要转换为数组的元素 + * @returns 转换后的数组 + */ +// #ifndef UNI-APP-X && APP +export const toArray = (item: T | T[]): T[] => Array.isArray(item) ? item : [item]; +// #endif + + +// #ifdef UNI-APP-X && APP +export function toArray(item: any): T[] { + return Array.isArray(item) ? item as T[] : [item as T]// as T[] +}; +// #endif +// 示例 +// console.log(toArray(5)); // 输出: [5] +// console.log(toArray("hello")); // 输出: ["hello"] +// console.log(toArray([1, 2, 3])); // 输出: [1, 2, 3] +// console.log(toArray(["apple", "banana"])); // 输出: ["apple", "banana"] \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/toBoolean/index.ts b/QXTfront/uni_modules/lime-shared/toBoolean/index.ts new file mode 100644 index 0000000..6dda115 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/toBoolean/index.ts @@ -0,0 +1,40 @@ +// @ts-nocheck +import { isNumber } from '../isNumber' +import { isString } from '../isString' +// 函数重载,定义多个函数签名 +// function toBoolean(value : any) : boolean; +// function toBoolean(value : string) : boolean; +// function toBoolean(value : number) : boolean; +// function toBoolean(value : boolean) : boolean; + +// #ifdef UNI-APP-X && APP +function toBoolean(value : any | null) : boolean { + // 根据输入值的类型,返回相应的布尔值 + // if (isNumber(value)) { + // return (value as number) != 0; + // } + // if (isString(value)) { + // return `${value}`.length > 0; + // } + // if (typeof value == 'boolean') { + // return value as boolean; + // } + // #ifdef APP-IOS || APP-HARMONY + return value != null && value != undefined + // #endif + // #ifdef APP-ANDROID + return value != null + // #endif +} +// #endif + + +// #ifndef UNI-APP-X && APP +function toBoolean(value : any | null) : value is NonNullable { + return !!value//value !== null && value !== undefined; +} +// #endif + +export { + toBoolean +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/toNumber/index.ts b/QXTfront/uni_modules/lime-shared/toNumber/index.ts new file mode 100644 index 0000000..a8e1b1d --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/toNumber/index.ts @@ -0,0 +1,28 @@ +// @ts-nocheck +/** + * 将字符串转换为数字 + * @param val 要转换的字符串 + * @returns 转换后的数字或原始字符串 + */ + +// #ifdef UNI-APP-X && APP +// function toNumber(val: string): number +// function toNumber(val: string): string +function toNumber(val: string): number|null { + const n = parseFloat(val); // 使用 parseFloat 函数将字符串转换为浮点数 + return isNaN(n) ? null : n; // 使用 isNaN 函数判断是否为非数字,返回转换后的数字或原始字符串 +} +export {toNumber} +// #endif + +// #ifndef UNI-APP-X && APP +export function toNumber(val: string): number | string { + const n = parseFloat(val); // 使用 parseFloat 函数将字符串转换为浮点数 + return isNaN(n) ? val : n; // 使用 isNaN 函数判断是否为非数字,返回转换后的数字或原始字符串 +} +// #endif + +// 示例 +// console.log(toNumber("123")); // 输出: 123 +// console.log(toNumber("3.14")); // 输出: 3.14 +// console.log(toNumber("hello")); // 输出: "hello" \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/unitConvert/index.ts b/QXTfront/uni_modules/lime-shared/unitConvert/index.ts new file mode 100644 index 0000000..455d40d --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/unitConvert/index.ts @@ -0,0 +1,80 @@ +// @ts-nocheck +import { isString } from '../isString' +import { isNumeric } from '../isNumeric' + +/** + * 单位转换函数,将字符串数字或带有单位的字符串转换为数字 + * @param value 要转换的值,可以是字符串数字或带有单位的字符串 + * @returns 转换后的数字,如果无法转换则返回0 + */ +// #ifndef UNI-APP-X && APP +export function unitConvert(value : string | number | null | undefined, base: number = 0) : number { + // 如果是字符串数字 + if (isNumeric(value)) { + return Number(value); + } + // 如果有单位 + if (isString(value)) { + const reg = /^-?([0-9]+)?([.]{1}[0-9]+){0,1}(em|rpx|px|%)$/g; + const results = reg.exec(value); + if (!value || !results) { + return 0; + } + const unit = results[3]; + const _value = parseFloat(value); + if (unit === 'rpx') { + return uni.upx2px(_value); + } + if (unit === 'px') { + return _value * 1; + } + if(unit == '%') { + return _value / 100 * base + } + // 如果是其他单位,可以继续添加对应的转换逻辑 + } + return 0; +} +// #endif + + +// #ifdef UNI-APP-X && APP +import { isNumber } from '../isNumber' +export function unitConvert(value : any | null, base: number = 0) : number { + if (isNumber(value)) { + return value as number + } + // 如果是字符串数字 + if (isNumeric(value)) { + return parseFloat(value as string); + } + // 如果有单位 + if (isString(value)) { + const reg = /^-?([0-9]+)?([.]{1}[0-9]+){0,1}(em|rpx|px|%)$/g; + const results = reg.exec(value as string); + if (results == null) { + return 0; + } + const unit = results[3]; + const _value = parseFloat(value); + if (unit == 'rpx') { + // const { windowWidth } = uni.getWindowInfo() + // return windowWidth / 750 * _value; + return uni.rpx2px(_value) + } + if (unit == 'px') { + return _value; + } + if(unit == '%') { + return _value / 100 * base + } + // 如果是其他单位,可以继续添加对应的转换逻辑 + } + return 0; +} +// #endif +// 示例 +// console.log(unitConvert("123")); // 输出: 123 (字符串数字转换为数字) +// console.log(unitConvert("3.14em")); // 输出: 0 (无法识别的单位) +// console.log(unitConvert("20rpx")); // 输出: 根据具体情况而定 (根据单位进行转换) +// console.log(unitConvert(10)); // 输出: 10 (数字不需要转换) \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-shared/vue/index.ts b/QXTfront/uni_modules/lime-shared/vue/index.ts new file mode 100644 index 0000000..07f7135 --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/vue/index.ts @@ -0,0 +1,16 @@ +// @ts-nocheck + +// #ifdef VUE3 +export * from 'vue'; +// #endif + +// #ifndef VUE3 +export * from '@vue/composition-api'; + +// #ifdef APP-NVUE +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' +Vue.use(VueCompositionAPI) +// #endif + +// #endif diff --git a/QXTfront/uni_modules/lime-shared/while/index.ts b/QXTfront/uni_modules/lime-shared/while/index.ts new file mode 100644 index 0000000..1b8a96b --- /dev/null +++ b/QXTfront/uni_modules/lime-shared/while/index.ts @@ -0,0 +1,55 @@ +// @ts-nocheck + +// 来自kux大佬的神之一手 +// 原地址 https://ext.dcloud.net.cn/plugin?id=23291 +export type ControlCommand = 'continue' | 'break' | null; + +export type ControllableWhileReturn = { + start: () => void; + abort: () => void; + execContinue: () => 'continue'; + execBreak: () => 'break'; +}; + +export type Controller = { + abort: () => void; +}; + +export function controllableWhile( + condition : () => boolean, + body: (controller: Controller) => ControlCommand +): ControllableWhileReturn { + let isActive = true; + + const controller: Controller = { + abort: () => { + isActive = false; + } + }; + + const execContinue = () => 'continue'; + const execBreak = () => 'break'; + + return { + start: () => { + // #ifdef APP-ANDROID + UTSAndroid.getDispatcher('io').async((_) => { + // #endif + while (isActive && condition()) { + const result = body(controller); + if (result == 'break') { + controller.abort(); + break; + } else if (result == 'continue') { + continue; + } + } + // #ifdef APP-ANDROID + }, null); + // #endif + }, + abort: controller.abort, + execContinue: execContinue, + execBreak: execBreak + } as ControllableWhileReturn; +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/changelog.md b/QXTfront/uni_modules/lime-style/changelog.md new file mode 100644 index 0000000..13324d0 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/changelog.md @@ -0,0 +1,46 @@ +## 0.2.3(2025-10-19) +- fix: 修复非uts环境使用set的问题 +## 0.2.2(2025-10-15) +- fix: 去掉版本判断 +## 0.2.1(2025-10-15) +- fix: 修复条件判断问题 +## 0.2.0(2025-10-01) +- fix: 修复uniapp主题变化报错问题 +## 0.1.9(2025-09-26) +- feat: 更新宫格暗黑hover颜色 +## 0.1.8(2025-09-08) +- feat: 去掉vue2的判断 +## 0.1.7(2025-08-15) +更新变量 +## 0.1.6(2025-06-20) +- feat: 放弃使用rpx +## 0.1.5(2025-06-20) +- fix: 修复 vue2 rpx转成px的问题 +## 0.1.4(2025-06-12) +- feat: 增加一些函数 +## 0.1.3(2025-05-07) +- feat: 增加`hairline`函数 +## 0.1.2(2025-04-24) +- feat: 根据官方建议,字体使用px +## 0.1.1(2025-03-25) +- feat: 更换rbgToHsv算法 +## 0.1.0(2025-03-13) +- feat: hbx4.56 Vue2 scss 预编译器默认已由 node-sass 更换为 dart-sass +## 0.0.9(2025-01-16) +- feat: 更新 +## 0.0.8(2024-12-15) +- fix: 修复vue2 不支持rgba(0,0,0,1%) +## 0.0.7(2024-12-11) +- feat: 增加除法 +## 0.0.6(2024-12-04) +- fix: 除法问题 +## 0.0.5(2024-11-20) +- feat: 增加flex +## 0.0.4(2024-11-20) +- feat: 增加flex +## 0.0.3(2024-09-30) +- fix: 由于 vue2 h5 css变量不支持rpx,故转成px +## 0.0.2(2024-09-23) +- fix: 修复 vue2 math.div 问题 +## 0.0.1(2024-09-02) +- init diff --git a/QXTfront/uni_modules/lime-style/color/colorPalette.scss b/QXTfront/uni_modules/lime-style/color/colorPalette.scss new file mode 100644 index 0000000..6408e72 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/color/colorPalette.scss @@ -0,0 +1,236 @@ +/* #ifdef VUE3 */ +@use "sass:math"; +/* #endif */ + + + +$hueStep: 2; +$saturationStep1: 0.16; +$saturationStep2: 0.05; +$brightnessStep1: 0.05; +$brightnessStep2: 0.15; +$lightColorCount: 5; +$darkColorCount: 4; + +$darkColorMap: ( + (index: 7, opacity: 0.15), + (index: 6, opacity: 0.25), + (index: 5, opacity: 0.3), + (index: 5, opacity: 0.45), + (index: 5, opacity: 0.65), + (index: 5, opacity: 0.85), + (index: 4, opacity: 0.9), + (index: 3, opacity: 0.95), + (index: 2, opacity: 0.97), + (index: 1, opacity: 0.98) +); + +@function div($dividend, $divisor) { + /* #ifdef VUE3 */ + @return math.div($dividend, $divisor); + /* #endif + /* #ifndef VUE3 */ + @return $dividend / $divisor; + /* #endif */ +} + +// 求一个数的n次幂 +@function pow($number, $n) { + $ret: 1; + @if $n >= 0 { + @for $i from 1 through $n { + $ret: $ret * $number; + } + } @else { + @for $i from $n to 0 { + $ret: $ret / $number; + } + } + @return $ret; +} + +// 浮点数保留小数位 +@function toFixed($float, $digits: 2) { + $pow: pow(10, $digits); + @return div(round($float * $pow) , $pow); +} + + +// 根据颜色获取对应的hsv,在tinycolor中首先进行了归一化处理,这里没有 +// 返回的结果h是0~360,代表的是色相的角度, sv的范围0-1 +@function rbgToHsv($limeColor) { + $r: red($limeColor); + $g: green($limeColor); + $b: blue($limeColor); + $max: max($r, $g, $b); + $min: min($r, $g, $b); + $diff: $max - $min; + $h: 0; + + @if $max == $min { + $h: 0 + } @else if $max == $r { + $h: div(60 * ($g - $b) , $diff) + if($g >= $b, 0, 360); + } @else if $max == $g { + $h: 60 * div($b - $r , $diff) + 120 //($b - $r) / $diff + 120; + } @else if $max == $b{ + $h: div(60 * ($r - $g) , $diff) + 240; + } + + $s: if($max == 0, 0, div($diff , $max)); + $v: div($max , 255); + + @return $h, $s, $v; +} +// hsv转化成rgb,借鉴了tinycolor的做法,避免通过$th的值判断来获取对应的rgb的取值 +// $t1~4的计算目前不清楚为什么这样做 +@function hsvTorgb($h, $s, $v) { + // $th: floor(div($h , 60)); + // $t1: div($h , 60) - $th; + // $t2: $v * (1 - $s); + // $t3: $v * (1 - $t1 * $s); + // $t4: $v * (1 - (1 - $t1) * $s); + // $i: $th + 1; + // $r: nth(($v, $t3, $t2, $t2, $t4, $v), $i); + // $g: nth(($t4, $v, $v, $t3, $t2, $t2), $i); + // $b: nth(($t2, $t2, $t4, $v, $v, $t3), $i); + + // @return rgb($r * 255, $g * 255, $b * 255); + $h: $h % 360; + + // 2. 计算色相区域 (0~5),对应6个60度区间 + $th: floor(div($h, 60)) % 6; // 强制th在0~5之间 + + // 3. 计算中间变量 + $t1: div($h, 60) - $th; + $t2: $v * (1 - $s); + $t3: $v * (1 - $t1 * $s); + $t4: $v * (1 - (1 - $t1) * $s); + + // 4. 根据色相区域选择RGB分量 + $i: $th + 1; // 索引范围锁定为1~6 + + // 定义各区域对应的RGB系数 + $r-values: ($v, $t3, $t2, $t2, $t4, $v); + $g-values: ($t4, $v, $v, $t3, $t2, $t2); + $b-values: ($t2, $t2, $t4, $v, $v, $t3); + + // 5. 获取RGB分量并转换为0~255整数 + $r: nth($r-values, $i) * 255; + $g: nth($g-values, $i) * 255; + $b: nth($b-values, $i) * 255; + + // 6. 返回RGB颜色值 + @return rgb(round($r), round($g), round($b)); +} + +//转换色相 +@function getHue($h, $i, $isLight) { + $hue: null; + @if $h >= 60 and $h <= 240 { + $hue: if($isLight, $h - $hueStep * $i, $h + $hueStep * $i); + } @else { + $hue: if($isLight, $h + $hueStep * $i, $h - $hueStep * $i); + } + + $hue: ($hue + 360) % 360; + + @return round($hue); +} + +// 转换饱和度 +@function getSaturation($s, $i, $isLight) { + $saturation: null; + @if $isLight { + $saturation: $s - $saturationStep1 * $i; + } @else if $i == $darkColorCount { + $saturation: $s + $saturationStep1; + } @else { + $saturation: $s + $saturationStep2 * $i; + } + $saturation: min($saturation, 1); + + @if $isLight and $i == $lightColorCount and $saturation > 0.1 { + $saturation: 0.1; + } + + $saturation: max($saturation, 0.06); + + @return toFixed($saturation, 2); +} + +// 转换明度 +@function getValue($v, $i, $isLight) { + $value: min( + if( + $isLight, + $v + $brightnessStep1 * $i, + $v - $brightnessStep2 * $i + ), + 1); + + @return toFixed($value, 2); +} + + +@function mix($rgb1, $rgb2, $amount){ + $p: $amount; + $r: (red($rgb2) - red($rgb1)) * $p + red($rgb1); + $g: (green($rgb2) - green($rgb1)) * $p + green($rgb1); + $b: (blue($rgb2) - blue($rgb1)) * $p + blue($rgb1); + + @return rgb($r, $g, $b) +} + +// 根据颜色和对应的色板位置,计算出对应的色板颜色 +@function genColor($color, $index, $theme: 'default' , $bgColor: #242424) { + $isLight: if($index <= 6, true, false); + $hsv: rbgToHsv($color); + //这里将i转换成以主色为中心,两侧的i值逐渐增大 + $i: if($isLight, $lightColorCount + 1 - $index, $index - $lightColorCount - 1); + + @if $theme == 'dark' { + $item: nth($darkColorMap, $index); + $index2: map-get($item, index); + $opacity: map-get($item, opacity); + + $rgb: genColor($color, $index2 + 1); + + // @return $rgb; + @return mix( + $bgColor, + $rgb, + $opacity + ) + } + + @return hsvTorgb( + getHue(nth($hsv, 1), $i, $isLight), + getSaturation(nth($hsv, 2), $i, $isLight), + getValue(nth($hsv, 3), $i, $isLight) + ); +} + +@function getSolidColor($base-color, $brightness) { + // 验证输入参数 + @if type-of($base-color) != 'color' { + @error "Expected color for $base-color, but got #{type-of($base-color)}: #{$base-color}"; + } + + @if type-of($brightness) != 'number' { + @error "Expected number for $brightness, but got #{type-of($brightness)}: #{$brightness}"; + } + + // 获取基础颜色的HSL值 + $hue: hue($base-color); + $saturation: saturation($base-color); + $lightness: lightness($base-color); + + // 计算新的亮度值 (限制在0-100%范围内) + $new-lightness: clamp(0%, $lightness + $brightness, 100%); + + // 使用HSL函数创建新颜色 + $new-color: hsl($hue, $saturation, $new-lightness); + + @return $new-color; +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/color/colors.scss b/QXTfront/uni_modules/lime-style/color/colors.scss new file mode 100644 index 0000000..2f1a1d5 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/color/colors.scss @@ -0,0 +1,18 @@ +// 品牌色-主色 +$primary-color: #3283ff!default; +// 错误色 +$error-color: #FF4D4F!default; +// 警告色 +$warning-color: #ffb400!default;// #FF7D00!default; +// 信息色 +$info-color: $primary-color!default; +// 成功色 +$success-color: #34c471!default; + +$blue: #3283ff!default; +$red: #FF4D4F!default; +$orange: #ffb400!default; +$yellow: #fcd53f!default; +$green: #34c471 !default; +$white: #fff; +$black: #000; diff --git a/QXTfront/uni_modules/lime-style/functions.scss b/QXTfront/uni_modules/lime-style/functions.scss new file mode 100644 index 0000000..8332c1a --- /dev/null +++ b/QXTfront/uni_modules/lime-style/functions.scss @@ -0,0 +1,11 @@ +/* #ifdef VUE3 */ +@use "sass:math"; +// #endif +@function divide($dividend, $divisor) { + /* #ifdef VUE3 */ + @return math.div($dividend, $divisor); + /* #endif + /* #ifndef VUE3 */ + @return $dividend / $divisor; + /* #endif +} diff --git a/QXTfront/uni_modules/lime-style/hairline.uts b/QXTfront/uni_modules/lime-style/hairline.uts new file mode 100644 index 0000000..8dc0d89 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/hairline.uts @@ -0,0 +1,153 @@ +import { unitConvert } from '@/uni_modules/lime-shared/unitConvert'; + +export type DrawBorderOptions = { + direction : 'top' | 'bottom' | 'left' | 'right'; + color ?: string; + colorKey ?: string; // 在dom中获取颜色 + startOffsetKey?: string; // 在dom哪个属性获取 + startOffset ?: number | string; // 支持数字或 CSS 字符串(如 '10px') + endOffset ?: number | string; + lineWidth ?: number; + watchSize ?: boolean; // 是否监听尺寸变化自动重绘 + immediate ?: boolean; // 是否立即绘制 + bordered?: boolean; + +} + +export type UseDrawBorderReturn = { + color: Ref, + renderBorder: () => void, + clearBorder: () => void; + dispose: () => void, +} +/** + * 在元素上绘制边框,并支持动态监听尺寸变化 + * @param elementRef 目标元素的 Ref + * @param options 边框配置 + * @returns 清理函数(用于卸载时取消监听) + */ +export function useDrawBorder( + elementRef : Ref, + options : DrawBorderOptions +):UseDrawBorderReturn { + let resizeObserver : UniResizeObserver | null = null; + const { watchSize = true, immediate = true } = options; + const defalutColor = '#e7e7e7' + const color = ref(options.color ?? defalutColor) + const bordered = ref(options.bordered ?? true) + let computedStartOffset = 0 + let computedEndOffset = 0 + + // 绘制边框 + const renderBorder = () => { + if (elementRef.value == null) return; + const ctx = elementRef.value!.getDrawableContext(); + if (ctx == null) return; + + const rect = elementRef.value!.getBoundingClientRect(); + ctx.reset(); + + const { + direction, + startOffset = 0, + endOffset = 0, + lineWidth = 0.5, + colorKey, + startOffsetKey, + } = options; + + + // 转换单位(如果是字符串,如 '10px') + if(computedStartOffset == 0) { + computedStartOffset = unitConvert((startOffsetKey != null ? elementRef.value?.style.getPropertyValue(startOffsetKey!) ?? startOffset : startOffset)) + } + if(computedEndOffset == 0) { + computedEndOffset = unitConvert(endOffset) + } + + if(color.value == defalutColor && colorKey != null) { + color.value = elementRef.value?.style.getPropertyValue(colorKey!) ?? defalutColor + // if(color.value.length == 0) { + // color.value = defalutColor + // } + } + ctx.strokeStyle = color.value; + ctx.lineWidth = lineWidth; + + // 根据方向计算坐标 + switch (direction) { + case 'top': + ctx.moveTo(computedStartOffset, 0); + ctx.lineTo(rect.width - computedEndOffset, 0); + break; + case 'bottom': + ctx.moveTo(computedStartOffset, rect.height - 0.25); + ctx.lineTo(rect.width - computedEndOffset, rect.height - 0.25); + break; + case 'left': + ctx.moveTo(0, computedStartOffset); + ctx.lineTo(0, rect.height - computedEndOffset); + break; + case 'right': + ctx.moveTo(rect.width, computedStartOffset); + ctx.lineTo(rect.width, rect.height - computedEndOffset); + break; + } + + ctx.stroke(); + ctx.update(); + }; + + const setupResizeObserver = () => { + // 监听尺寸变化(如果启用) + if (watchSize) { + if (resizeObserver == null) { + resizeObserver = new UniResizeObserver((entries : Array) => { + if(!bordered.value) return + renderBorder(); + }) + } + watchEffect(()=>{ + if (elementRef.value != null) { + resizeObserver!.observe(elementRef.value!); + } + }) + } + } + + + // 清理函数(卸载时取消监听) + const dispose = () => { + if (resizeObserver != null && elementRef.value != null) { + // resizeObserver.unobserve(elementRef.value!); + resizeObserver!.disconnect(); + resizeObserver = null; + } + }; + + const clearBorder = ()=> { + if (elementRef.value == null) return; + const ctx = elementRef.value!.getDrawableContext(); + if (ctx == null) return; + bordered.value = false + ctx.reset() + ctx.update() + } + + setupResizeObserver() + // 初始绘制 + if(immediate) { + renderBorder(); + } + + + + + return { + renderBorder, // 手动触发绘制 + dispose, // 清理监听 + clearBorder, + color + } as UseDrawBorderReturn + +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/index.scss b/QXTfront/uni_modules/lime-style/index.scss new file mode 100644 index 0000000..edd46a7 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/index.scss @@ -0,0 +1,7 @@ +@import './theme/default'; +@import './var'; +// @import './mixins/ellipsis'; +// @import './mixins/hairline'; +@import './mixins/create'; +@import './mixins/directionalProperty'; +// @import './mixins/useTheme'; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/index.uts b/QXTfront/uni_modules/lime-style/index.uts new file mode 100644 index 0000000..208438f --- /dev/null +++ b/QXTfront/uni_modules/lime-style/index.uts @@ -0,0 +1,3 @@ +export * from './token/useThemeMode' +export * from './token/useThemeVars' +export * from './token/interface' \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/mixins/bem.scss b/QXTfront/uni_modules/lime-style/mixins/bem.scss new file mode 100644 index 0000000..e69de29 diff --git a/QXTfront/uni_modules/lime-style/mixins/create.scss b/QXTfront/uni_modules/lime-style/mixins/create.scss new file mode 100644 index 0000000..4e58bc8 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/mixins/create.scss @@ -0,0 +1,219 @@ +/* #ifdef VUE3 */ +@use "sass:math"; +/* #endif */ + +$use-css-var: false !default; + +@function div($dividend, $divisor) { + /* #ifdef VUE3 */ + @return math.div($dividend, $divisor); + /* #endif */ + /* #ifndef VUE3 */ + @return $dividend / $divisor; + /* #endif */ +} + +@function rpx-to-px($value) { + // 递归处理列表 + @if type-of($value) == list { + $new-list: (); + @each $item in $value { + $new-list: append($new-list, rpx-to-px($item)); + } + @return $new-list; + } + + // 处理数字类型 - 带 rpx 单位 + @if type-of($value) == number and unit($value) == 'rpx' { + // 安全处理单位转换 + @return calc-strip-unit($value) * 0.5 * 1px; + } + + // 处理字符串类型 + @if type-of($value) == string { + $string: $value; + $rpx-index: str-index($string, 'rpx'); + + // 如果字符串以数字开头并以 rpx 结尾,转换为数值 + @if $rpx-index == (str-length($string) - 2) { + $num-str: str-slice($string, 1, $rpx-index - 1); + $number: to-number($num-str); + @if type-of($number) == number { + @return $number * 0.5 * 1px; + } + } + + // 字符串中可能包含多个 rpx 值 + @if $rpx-index { + $result: ''; + @while $rpx-index { + // 找到数字部分起点 + $num-end: $rpx-index - 1; + $num-start: $num-end; + @while $num-start > 0 and is-numeric-char(str-slice($string, $num-start, $num-start)) { + $num-start: $num-start - 1; + } + + // 提取数字部分 + $num-str: str-slice($string, $num-start + 1, $num-end); + $number: to-number($num-str); + + // 转换为 px 数值 + $px-value: $number * 0.5 * 1px; + + // 构建结果字符串 + $result: $result + str-slice($string, 1, $num_start) + '#{$px_value}'; + + // 更新剩余字符串 + $string: str-slice($string, $rpx-index + 3); + $rpx-index: str-index($string, 'rpx'); + } + @return #{$result + $string}; + } + } + + // 其他类型直接返回 + @return $value; +} + +// 辅助函数:安全去除单位并返回数值 +@function calc-strip-unit($number) { + @if type-of($number) == number { + $unit: unit($number); + $units: ("px": 1px, "rpx": 1rpx, "em": 1em, "rem": 1rem, "%": 1%); + + @if map-has-key($units, $unit) { + @return div($number , map-get($units, $unit)); + } + + @if unitless($number) { + @return $number; + } + } + + @return $number; +} + +// 辅助函数:检查字符是否为数字 +@function is-numeric-char($char) { + $chars: "-.0123456789"; + @return str-index($chars, $char) != null; +} + +// 辅助函数:将字符串安全转换为数字 +@function to-number($string) { + // 如果输入已经是数字,直接返回 + @if type-of($string) == number { + @return $string; + } + + // 处理带符号的数字 + $is-negative: false; + $numeric: ""; + $found-number: false; + + // 提取所有数字字符 + @for $i from 1 through str-length($string) { + $char: str-slice($string, $i, $i); + + @if $char == "-" and $numeric == "" { + $is-negative: true; + } + @else if $char == "." and str-index($numeric, ".") == null { + $numeric: $numeric + $char; + } + @else if $char >= "0" and $char <= "9" { + $numeric: $numeric + $char; + $found-number: true; + } + } + + // 如果有实际数字内容,转换为数值 + @if $found-number { + $result: 0; + $decimal-index: str-index($numeric, "."); + + @if $decimal-index { + // 处理带小数的数字 + $integer-part: str-slice($numeric, 1, $decimal-index - 1); + $decimal-part: str-slice($numeric, $decimal-index + 1); + + @if $integer-part == "" { $integer-part: "0"; } + + $result: to-integer($integer-part); + + $divisor: 1; + @for $i from 1 through str-length($decimal-part) { + $divisor: $divisor * 10; + $digit: to-integer(str-slice($decimal-part, $i, $i)); + $result: $result + ($digit / $divisor); + } + } @else { + // 处理整数 + $result: to-integer($numeric); + } + + @return if($is-negative, -$result, $result); + } + + // 无法转换则返回原字符串 + @return $string; +} + +// 辅助函数:将整数字符串转换为数字 +@function to-integer($string) { + $result: 0; + + @for $i from 1 through str-length($string) { + $char: str-slice($string, $i, $i); + $result: $result * 10 + (str-index("0123456789", $char) - 1); + } + + @return $result; +} + +@function create-var($name, $values...) { + // 将不定数量的参数转换为列表 + $value-list: $values; + $css-value: null; + + @if length($value-list) == 0 { + // @warn "The list must have at least 1 values."; + @return ''; + } @else { + // 初始化CSS变量的值为列表中的第一个值 + /* #ifndef VUE2 */ + $css-value: nth($value-list, 1); + /* #endif */ + /* #ifdef VUE2 */ + $css-value: rpx-to-px(nth($value-list, 1)); + /* #endif */ + } + // 检查列表长度是否大于等于2 + @if length($value-list) >= 2 { + // 使用@for循环遍历剩余的值,并构建CSS变量的完整值 + @for $i from 2 through length($value-list) { + /* #ifndef VUE2 */ + $css-value: $css-value + ", " + nth($value-list, $i); + /* #endif */ + /* #ifdef VUE2 */ + $css-value: $css-value + ", " + rpx-to-px(nth($value-list, $i)); + /* #endif */ + } + } + + /* #ifdef UNI-APP-X && APP && uniVersion >= 4.75 */ + @if $use-css-var { + @return var(--l-#{$name}, #{$css-value}); + } @else { + @return $css-value; + } + /* #endif */ + + + /* #ifdef UNI-APP-X && APP || APP-NVUE */ + @return $css-value; + /* #endif */ + + @return var(--l-#{$name}, #{$css-value}); +} diff --git a/QXTfront/uni_modules/lime-style/mixins/directionalProperty.scss b/QXTfront/uni_modules/lime-style/mixins/directionalProperty.scss new file mode 100644 index 0000000..6d23d1a --- /dev/null +++ b/QXTfront/uni_modules/lime-style/mixins/directionalProperty.scss @@ -0,0 +1,401 @@ +// ======================================================================= +// 方向属性核心生成器 (支持所有方向相关属性) +// ======================================================================= +@mixin directional-property( + $property, + $values, + $exclude: () +) { + // 属性类型分组 + $group-standard: padding, margin; // 标准方向属性 + $group-radius: border-radius; // 圆角属性 + $group-border: border, border-top, border-right, border-bottom, border-left; // 边框属性 + $group-outline: outline, outline-top, outline-right, outline-bottom, outline-left; // 轮廓属性 + $group-position: inset, inset-block, inset-inline, top, right, bottom, left; // 定位属性 + $group-size: block-size, inline-size; // 块/行尺寸属性 + + // 定义每个方向的值 + $top: null; + $right: null; + $bottom: null; + $left: null; + + // 确定处理模式 + $is-standard: index($group-standard, $property); + $is-radius: index($group-radius, $property); + $is-border: index($group-border, $property); + $is-outline: index($group-outline, $property); + $is-position: index($group-position, $property); + $is-size: index($group-size, $property); + + // ===================================================================== + // 解析输入值 - 根据属性类型处理 + // ===================================================================== + @if type-of($values) == 'list' { + $length: length($values); + + // 单个值 - 所有方向相同值 + @if $length == 1 { + $top: nth($values, 1); + $right: nth($values, 1); + $bottom: nth($values, 1); + $left: nth($values, 1); + } + + // 两个值 + @else if $length == 2 { + // 特殊处理:border-radius + @if $is-radius { + $top: nth($values, 1); + $right: nth($values, 2); + $bottom: nth($values, 1); + $left: nth($values, 2); + } + // 标准处理:上下 | 左右 + @else if $is-standard or $is-border or $is-outline or $is-position { + $top: nth($values, 1); + $bottom: nth($values, 1); + $right: nth($values, 2); + $left: nth($values, 2); + } + // 块/行尺寸处理 + @else if $is-size { + $top: nth($values, 1); + $right: nth($values, 2); + } + } + + // 三个值 + @else if $length == 3 { + // border-radius特殊处理 + @if $is-radius { + $top: nth($values, 1); + $right: nth($values, 2); + $bottom: nth($values, 3); + $left: nth($values, 2); + } + // 标准处理 + @else if $is-standard or $is-border or $is-outline or $is-position { + $top: nth($values, 1); + $right: nth($values, 2); + $left: nth($values, 2); + $bottom: nth($values, 3); + } + } + + // 四个值 + @else if $length == 4 { + $top: nth($values, 1); + $right: nth($values, 2); + $bottom: nth($values, 3); + $left: nth($values, 4); + } + } + @else { + // 单个值传递 + $top: $values; + $right: $values; + $bottom: $values; + $left: $values; + } + + // ===================================================================== + // 生成CSS属性(排除指定方向) + // ===================================================================== + + // 1. 圆角处理 + @if $is-radius { + @if not index($exclude, top-left) and $top != null { + border-top-left-radius: $top; + } + @if not index($exclude, top-right) and $right != null { + border-top-right-radius: $right; + } + @if not index($exclude, bottom-right) and $bottom != null { + border-bottom-right-radius: $bottom; + } + @if not index($exclude, bottom-left) and $left != null { + border-bottom-left-radius: $left; + } + } + + // 2. 标准方向处理 (padding, margin) + @else if $is-standard { + @if not index($exclude, top) and $top != null { + #{$property}-top: $top; + } + @if not index($exclude, right) and $right != null { + #{$property}-right: $right; + } + @if not index($exclude, bottom) and $bottom != null { + #{$property}-bottom: $bottom; + } + @if not index($exclude, left) and $left != null { + #{$property}-left: $left; + } + } + + // 3. 边框处理 + @else if $is-border { + // 完整边框设置 + @if $property == 'border' { + @if not index($exclude, top) and $top != null { + border-top-width: nth($values, 1); + border-top-style: nth($values, 2); + border-top-color: nth($values, 3); + } + @if not index($exclude, right) and $right != null { + border-right-width: nth($values, 1); + border-right-style: nth($values, 2); + border-right-color: nth($values, 3); + } + @if not index($exclude, bottom) and $bottom != null { + // border-bottom: $bottom; + border-bottom-width: nth($values, 1); + border-bottom-style: nth($values, 2); + border-bottom-color: nth($values, 3); + } + @if not index($exclude, left) and $left != null { + // border-left: $left; + border-left-width: nth($values, 1); + border-left-style: nth($values, 2); + border-left-color: nth($values, 3); + } + } + // 单边边框 + @else { + $direction: str-slice($property, 8); // 提取方向 + @if not index($exclude, $direction) { + // #{$property}: $top; + #{$property}-width: nth($values, 1); + #{$property}-style: nth($values, 2); + #{$property}-color: nth($values, 3); + } + } + } + + // 4. 轮廓处理 + @else if $is-outline { + // 完整轮廓设置 + @if $property == 'outline' { + @if not index($exclude, top) and $top != null { + outline-top: $top; + } + @if not index($exclude, right) and $right != null { + outline-right: $right; + } + @if not index($exclude, bottom) and $bottom != null { + outline-bottom: $bottom; + } + @if not index($exclude, left) and $left != null { + outline-left: $left; + } + } + // 单边轮廓 + @else { + $direction: str-slice($property, 8); // 提取方向 + @if not index($exclude, $direction) { + #{$property}: $top; + } + } + } + + // 5. 定位处理 + @else if $is-position { + // inset简写处理 + @if $property == 'inset' { + @if not index($exclude, top) and $top != null { + top: $top; + } + @if not index($exclude, right) and $right != null { + right: $right; + } + @if not index($exclude, bottom) and $bottom != null { + bottom: $bottom; + } + @if not index($exclude, left) and $left != null { + left: $left; + } + } + // inset-block 和 inset-inline + @else if $property == 'inset-block' { + @if not index($exclude, top) and $top != null { + top: $top; + } + @if not index($exclude, bottom) and $bottom != null { + bottom: $bottom; + } + } + @else if $property == 'inset-inline' { + @if not index($exclude, left) and $left != null { + left: $left; + } + @if not index($exclude, right) and $right != null { + right: $right; + } + } + // 单一定位 + @else { + @if not index($exclude, $property) { + #{$property}: $top; + } + } + } + + // 6. 尺寸处理 + @else if $is-size { + @if $property == 'block-size' { + @if not index($exclude, top) and $top != null { + height: $top; + } + } + @else if $property == 'inline-size' { + @if not index($exclude, left) and $left != null { + width: $left; + } + } + } +} + +// ======================================================================= +// 快捷混合宏:标准属性 +// ======================================================================= +@mixin padding($values, $exclude: ()) { + @include directional-property(padding, $values, $exclude); +} + +@mixin margin($values, $exclude: ()) { + @include directional-property(margin, $values, $exclude); +} + +@mixin border-radius($values, $exclude: ()) { + @include directional-property(border-radius, $values, $exclude); +} + +// ======================================================================= +// 快捷混合宏:边框属性 +// ======================================================================= +@mixin border($value, $exclude: ()) { + @include directional-property(border, $value, $exclude); +} + +@mixin border-top($value, $exclude: ()) { + @include directional-property(border-top, $value, $exclude); +} + +@mixin border-right($value, $exclude: ()) { + @include directional-property(border-right, $value, $exclude); +} + +@mixin border-bottom($value, $exclude: ()) { + @include directional-property(border-bottom, $value, $exclude); +} + +@mixin border-left($value, $exclude: ()) { + @include directional-property(border-left, $value, $exclude); +} + +// ======================================================================= +// 快捷混合宏:轮廓属性 +// ======================================================================= +@mixin outline($value, $exclude: ()) { + @include directional-property(outline, $value, $exclude); +} + +@mixin outline-top($value, $exclude: ()) { + @include directional-property(outline-top, $value, $exclude); +} + +@mixin outline-right($value, $exclude: ()) { + @include directional-property(outline-right, $value, $exclude); +} + +@mixin outline-bottom($value, $exclude: ()) { + @include directional-property(outline-bottom, $value, $exclude); +} + +@mixin outline-left($value, $exclude: ()) { + @include directional-property(outline-left, $value, $exclude); +} + +// ======================================================================= +// 快捷混合宏:定位属性 +// ======================================================================= +@mixin inset($values, $exclude: ()) { + @include directional-property(inset, $values, $exclude); +} + +@mixin inset-block($values, $exclude: ()) { + @include directional-property(inset-block, $values, $exclude); +} + +@mixin inset-inline($values, $exclude: ()) { + @include directional-property(inset-inline, $values, $exclude); +} + +@mixin top($value, $exclude: ()) { + @include directional-property(top, $value, $exclude); +} + +@mixin right($value, $exclude: ()) { + @include directional-property(right, $value, $exclude); +} + +@mixin bottom($value, $exclude: ()) { + @include directional-property(bottom, $value, $exclude); +} + +@mixin left($value, $exclude: ()) { + @include directional-property(left, $value, $exclude); +} + +// ======================================================================= +// 快捷混合宏:尺寸属性 +// ======================================================================= +@mixin block-size($value, $exclude: ()) { + @include directional-property(block-size, $value, $exclude); +} + +@mixin inline-size($value, $exclude: ()) { + @include directional-property(inline-size, $value, $exclude); +} + +// ======================================================================= +// 组合混合宏 +// ======================================================================= +// 带圆角的边框 +@mixin bordered($border-value, $radius-value) { + @include border($border-value); + @include border-radius($radius-value); +} + +// 绝对定位容器 +@mixin absolute-container($inset: 0) { + position: absolute; + @include inset($inset); +} + +// 固定定位容器 +@mixin fixed-container($inset: 0) { + position: fixed; + @include inset($inset); +} + +// ======================================================================= +// 圆角辅助混合宏 +// ======================================================================= +@mixin border-top-radius($value) { + @include border-radius($value 0 0, (bottom-right, bottom-left)); +} + +@mixin border-right-radius($value) { + @include border-radius(0 $value 0 0, (top-left, bottom-left)); +} + +@mixin border-bottom-radius($value) { + @include border-radius(0 0 $value, (top-right, top-left)); +} + +@mixin border-left-radius($value) { + @include border-radius(0 0 0 $value, (top-right, bottom-right)); +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/mixins/ellipsis.scss b/QXTfront/uni_modules/lime-style/mixins/ellipsis.scss new file mode 100644 index 0000000..97e762a --- /dev/null +++ b/QXTfront/uni_modules/lime-style/mixins/ellipsis.scss @@ -0,0 +1,22 @@ +@mixin ellipsis { + // overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + /* #ifndef UNI-APP-X && APP || APP-NVUE */ + word-wrap: normal; + /* #endif */ +} + + +@mixin ellipsisLn($line) { + // overflow: hidden; + text-overflow: ellipsis; + /* #ifdef UNI-APP-X && APP || APP-NVUE */ + lines: $line; + /* #endif */ + /* #ifndef UNI-APP-X && APP || APP-NVUE */ + -webkit-line-clamp: $line; + display: -webkit-box; + -webkit-box-orient: vertical; + /* #endif */ +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/mixins/flex.scss b/QXTfront/uni_modules/lime-style/mixins/flex.scss new file mode 100644 index 0000000..0c3dd84 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/mixins/flex.scss @@ -0,0 +1,20 @@ +@mixin flex { + /* #ifndef UNI-APP-X */ + display: flex; + /* #endif */ +} +@mixin flex-column { + /* #ifndef UNI-APP-X */ + flex-direction: column; + /* #endif */ +} +@mixin flex-row { + flex-direction: row; +} + +@mixin universal { + position: relative; + box-sizing: border-box; + display: flex; + flex-direction: column; +} diff --git a/QXTfront/uni_modules/lime-style/mixins/hairline.scss b/QXTfront/uni_modules/lime-style/mixins/hairline.scss new file mode 100644 index 0000000..5044518 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/mixins/hairline.scss @@ -0,0 +1,66 @@ +// @import '../theme/default.scss'; + +@mixin hairline-base { + position: absolute; + box-sizing: border-box; + content: ' '; + pointer-events: none; + transform-origin: center; /* cover wechat button:after default transforn-origin */ +} + +@mixin hairline($color: $border-color-2) { + @include hairline-base; + top: -50%; + right: -50%; + bottom: -50%; + left: -50%; + border: 1px solid $color; + transform: scale(.5); +} + +@mixin hairline-top($color: $border-color-1, $left: 0, $right: 0) { + @include hairline-base; + top: 0; + right: $right; + left: $left; + border-top: 1px solid $color; + transform: scaleY(0.5); +} + +@mixin hairline-bottom($color: $border-color-1, $left: 0, $right: 0) { + @include hairline-base; + right: $right; + bottom: 0; + left: $left; + border-bottom: 1px solid $color; + transform: scaleY(0.5); +} + +@mixin hairline-left($color: $border-bolor-1) { + @include hairline-base; + top: 0; + bottom: 0; + left: 0; + border-left: 1px solid $color; + transform: scaleX(.5); +} + +@mixin hairline-right($color: $border-bolor-1) { + @include hairline-base; + top: 0; + bottom: 0; + right: 0; + border-right: 1px solid $color; + transform: scaleX(.5); +} + +// @mixin border { +// /* #ifndef UNI-APP-X && APP */ +// &:after { +// @content; +// } +// /* #endif */ +// /* #ifdef UNI-APP-X && APP */ +// @content; +// /* #endif */ +// } \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/mixins/platform.scss b/QXTfront/uni_modules/lime-style/mixins/platform.scss new file mode 100644 index 0000000..ebd3c8f --- /dev/null +++ b/QXTfront/uni_modules/lime-style/mixins/platform.scss @@ -0,0 +1,17 @@ +/* #ifdef APP-NVUE || UNI-APP-X && APP */ +$is-app: true; +/* #endif */ +/* #ifndef APP-NVUE || UNI-APP-X && APP */ +$is-app: false; +/* #endif */ + +@mixin is-app { + @if $is-app { + @content; + } +} +@mixin not-app { + @if not($is-app) { + @content; + } +} diff --git a/QXTfront/uni_modules/lime-style/mixins/useTheme.scss b/QXTfront/uni_modules/lime-style/mixins/useTheme.scss new file mode 100644 index 0000000..83df7ca --- /dev/null +++ b/QXTfront/uni_modules/lime-style/mixins/useTheme.scss @@ -0,0 +1,60 @@ +$limeThemes: light, dark; +$theme: light; + +@mixin use-theme($mode: null) { + @if $mode != null { + /* #ifndef UNI-APP-X && APP || APP-NVUE */ + @media (prefers-color-scheme: $mode) { + @content; + } + /* #endif */ + /* #ifdef UNI-APP-X && APP || APP-NVUE */ + &.#{$mode} { + @content; + } + /* #endif */ + } @else { + @each $mode in $limeThemes { + $theme: $mode !global; + /* #ifndef UNI-APP-X && APP || APP-NVUE */ + @media (prefers-color-scheme: $mode) { + @content; + } + /* #endif */ + + /* #ifdef UNI-APP-X && APP || APP-NVUE */ + &.#{$mode} { + @content; + } + /* #endif */ + } + } + +} + +@mixin theme-dark { + /* #ifndef UNI-APP-X && APP || APP-NVUE */ + @media (prefers-color-scheme: dark) { + page { + @content; + } + } + /* #endif */ + /* #ifdef UNI-APP-X && APP || APP-NVUE */ + .dark { + @content; + } + /* #endif */ + /* #ifdef WEB */ + :root[data-lime-theme='dark'] page { + @content; + } + /* #endif */ +} + + +@function get-var($themes, $key) { + @return map-get($themes, $key) +} + + diff --git a/QXTfront/uni_modules/lime-style/mixins/utilities.scss b/QXTfront/uni_modules/lime-style/mixins/utilities.scss new file mode 100644 index 0000000..3a4ea4a --- /dev/null +++ b/QXTfront/uni_modules/lime-style/mixins/utilities.scss @@ -0,0 +1,7 @@ +@import './flex'; + +@mixin resize-none { + /* #ifndef UNI-APP-X && APP */ + resize: none; + /* #endif */ +} diff --git a/QXTfront/uni_modules/lime-style/package.json b/QXTfront/uni_modules/lime-style/package.json new file mode 100644 index 0000000..f71488e --- /dev/null +++ b/QXTfront/uni_modules/lime-style/package.json @@ -0,0 +1,103 @@ +{ + "id": "lime-style", + "displayName": "lime-style", + "version": "0.2.3", + "description": "lime-style", + "keywords": [ + "lime-style" +], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0", + "uni-app": "^4.44", + "uni-app-x": "^4.61" + }, + "dcloudext": { + "type": "sdk-js", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "√", + "android": { + "extVersion": "", + "minVersion": "22" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√", + "alipay": "√", + "toutiao": "√", + "baidu": "√", + "kuaishou": "√", + "jd": "√", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "22" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/readme.md b/QXTfront/uni_modules/lime-style/readme.md new file mode 100644 index 0000000..0f53a25 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/readme.md @@ -0,0 +1,16 @@ +# lime-style + +## 更换色系 +在uni.scss中增加 +```css +// 品牌色-主色 +$primary-color: #3283ff; +// 错误色 +$error-color: #FF4D4F; +// 警告色 +$warning-color: #ffb400; +// 成功色 +$success-color: #34c471; + +$blue: #3283ff; +``` \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/theme/dark.scss b/QXTfront/uni_modules/lime-style/theme/dark.scss new file mode 100644 index 0000000..8a0d255 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/theme/dark.scss @@ -0,0 +1,634 @@ +@import '../mixins/create.scss'; +@import '../color/colorPalette.scss'; +@import '../color/colors.scss'; +@import '../mixins/useTheme'; + +$blue-1: #{genColor($blue, 1, dark)}; +$blue-2: #{genColor($blue, 2, dark)}; +$blue-3: #{genColor($blue, 3, dark)}; +$blue-4: #{genColor($blue, 4, dark)}; +$blue-5: #{genColor($blue, 5, dark)}; +$blue-6: #{genColor($blue, 6, dark)}; +$blue-7: #{genColor($blue, 7, dark)}; +$blue-8: #{genColor($blue, 8, dark)}; +$blue-9: #{genColor($blue, 9, dark)}; +$blue-10: #{genColor($blue, 10, dark)}; + +$info-color-1: #{genColor($info-color, 1, dark)}; +$info-color-2: #{genColor($info-color, 2, dark)}; +$info-color-3: #{genColor($info-color, 3, dark)}; +$info-color-4: #{genColor($info-color, 4, dark)}; +$info-color-5: #{genColor($info-color, 5, dark)}; +$info-color-6: #{genColor($info-color, 6, dark)}; +$info-color-7: #{genColor($info-color, 7, dark)}; +$info-color-8: #{genColor($info-color, 8, dark)}; +$info-color-9: #{genColor($info-color, 9, dark)}; +$info-color-10: #{genColor($info-color, 10, dark)}; + +$primary-color-1: #{genColor($primary-color, 1, dark)}; // 浅色/白底悬浮 +$primary-color-2: #{genColor($primary-color, 2, dark)}; // 文字禁用 +$primary-color-3: #{genColor($primary-color, 3, dark)}; // 一般禁用 +$primary-color-4: #{genColor($primary-color, 4, dark)}; // 特殊场景 禁用 +$primary-color-5: #{genColor($primary-color, 5, dark)}; // 悬浮 +$primary-color-6: #{genColor($primary-color, 6, dark)}; // 常规 +$primary-color-7: #{genColor($primary-color, 7, dark)}; // 点击 +$primary-color-8: #{genColor($primary-color, 8, dark)}; // +$primary-color-9: #{genColor($primary-color, 9, dark)}; +$primary-color-10: #{genColor($primary-color, 10, dark)}; + +$error-color-1: #{genColor($error-color, 1, dark)}; +$error-color-2: #{genColor($error-color, 2, dark)}; +$error-color-3: #{genColor($error-color, 3, dark)}; +$error-color-4: #{genColor($error-color, 4, dark)}; +$error-color-5: #{genColor($error-color, 5, dark)}; +$error-color-6: #{genColor($error-color, 6, dark)}; +$error-color-7: #{genColor($error-color, 7, dark)}; +$error-color-8: #{genColor($error-color, 8, dark)}; +$error-color-9: #{genColor($error-color, 9, dark)}; +$error-color-10: #{genColor($error-color, 10, dark)}; + +$warning-color-1: #{genColor($warning-color, 1, dark)}; +$warning-color-2: #{genColor($warning-color, 2, dark)}; +$warning-color-3: #{genColor($warning-color, 3, dark)}; +$warning-color-4: #{genColor($warning-color, 4, dark)}; +$warning-color-5: #{genColor($warning-color, 5, dark)}; +$warning-color-6: #{genColor($warning-color, 6, dark)}; +$warning-color-7: #{genColor($warning-color, 7, dark)}; +$warning-color-8: #{genColor($warning-color, 8, dark)}; +$warning-color-9: #{genColor($warning-color, 9, dark)}; +$warning-color-10: #{genColor($warning-color, 10, dark)}; + +$success-color-1: #{genColor($success-color, 1, dark)}; // 浅色/白底悬浮 +$success-color-2: #{genColor($success-color, 2, dark)}; // 文字禁用 +$success-color-3: #{genColor($success-color, 3, dark)}; // 一般禁用 +$success-color-4: #{genColor($success-color, 4, dark)}; // 特殊场景 +$success-color-5: #{genColor($success-color, 5, dark)}; // 悬浮 +$success-color-6: #{genColor($success-color, 6, dark)}; // 常规 +$success-color-7: #{genColor($success-color, 7, dark)}; // 点击 +$success-color-8: #{genColor($success-color, 8, dark)}; +$success-color-9: #{genColor($success-color, 9, dark)}; +$success-color-10: #{genColor($success-color, 10, dark)}; + +// $gray-1: #f3f3f3; +// $gray-2: #eeeeee; +// $gray-3: #e7e7e7; +// $gray-4: #dcdcdc; +// $gray-5: #c5c5c5; +// $gray-6: #a6a6a6; +// $gray-7: #8b8b8b; +// $gray-8: #777777; +// $gray-9: #5e5e5e; +// $gray-10: #4b4b4b; +// $gray-11: #383838; +// $gray-12: #2c2c2c; +// $gray-13: #242424; +// $gray-14: #181818; + +// 暗色模式的灰度 +$gray-1: #181818; // 最深 +$gray-2: #242424; +$gray-3: #2c2c2c; +$gray-4: #383838; +$gray-5: #4b4b4b; +$gray-6: #5e5e5e; +$gray-7: #777777; +$gray-8: #8b8b8b; +$gray-9: #a6a6a6; +$gray-10: #c5c5c5; +$gray-11: #dcdcdc; +$gray-12: #e7e7e7; +$gray-13: #eeeeee; +$gray-14: #f3f3f3; // 最浅 + +$text-color-1: rgba(255,255,255,0.85); //primary +$text-color-2: rgba(255,255,255,0.65); //secondary +$text-color-3: rgba(255,255,255,0.45); //placeholder +$text-color-4: rgba(255,255,255,0.25); //disabled + +// 容器 +$bg-color-page: $gray-1;//#000000; // 整体背景色 布局 +$bg-color-container: $gray-2;//#1d1d1d; // 一级容器背景 组件 +$bg-color-elevated: $gray-2;//#1f1f1f; // 二级容器背景 浮层 +$bg-color-spotlight: $gray-5; // 引起注意的如 Tooltip +$bg-color-mask: rgba(0, 0, 0, 0.65); // 蒙层 + +// 填充 +$fill-1: rgba(255,255,255,0.18); +$fill-2: rgba(255,255,255,0.12); +$fill-3: rgba(255,255,255,0.08); +$fill-4: rgba(255,255,255,0.04); + +// 描边 +$border-color-1: $gray-3;//#{getSolidColor(#000, 26%)}; //#424242; // 浅色 +$border-color-2: $gray-4;//#{getSolidColor(#000, 19%)}; //#303030; // 一般 +$border-color-3: $gray-5;//#{getSolidColor(#000, 15%)}; //$gray-4; // 深/悬浮 +$border-color-4: $gray-6;//#{getSolidColor(#000, 12%)}; //$gray-6; // 重/按钮描边 + + +@mixin theme-dark { + // 蓝色系 + --l-blue-1: #{$blue-1}; + --l-blue-2: #{$blue-2}; + --l-blue-3: #{$blue-3}; + --l-blue-4: #{$blue-4}; + --l-blue-5: #{$blue-5}; + --l-blue-6: #{$blue-6}; + --l-blue-7: #{$blue-7}; + --l-blue-8: #{$blue-8}; + --l-blue-9: #{$blue-9}; + --l-blue-10: #{$blue-10}; + + --l-info-color-1: #{$info-color-1}; + --l-info-color-2: #{$info-color-2}; + --l-info-color-3: #{$info-color-3}; + --l-info-color-4: #{$info-color-4}; + --l-info-color-5: #{$info-color-5}; + --l-info-color-6: #{$info-color-6}; + --l-info-color-7: #{$info-color-7}; + --l-info-color-8: #{$info-color-8}; + --l-info-color-9: #{$info-color-9}; + --l-info-color-10: #{$info-color-10}; + + // 主色系 + --l-primary-color-1: #{$primary-color-1}; + --l-primary-color-2: #{$primary-color-2}; + --l-primary-color-3: #{$primary-color-3}; + --l-primary-color-4: #{$primary-color-4}; + --l-primary-color-5: #{$primary-color-5}; + --l-primary-color-6: #{$primary-color-6}; + --l-primary-color-7: #{$primary-color-7}; + --l-primary-color-8: #{$primary-color-8}; + --l-primary-color-9: #{$primary-color-9}; + --l-primary-color-10: #{$primary-color-10}; + + // 错误色系 + --l-error-color-1: #{$error-color-1}; + --l-error-color-2: #{$error-color-2}; + --l-error-color-3: #{$error-color-3}; + --l-error-color-4: #{$error-color-4}; + --l-error-color-5: #{$error-color-5}; + --l-error-color-6: #{$error-color-6}; + --l-error-color-7: #{$error-color-7}; + --l-error-color-8: #{$error-color-8}; + --l-error-color-9: #{$error-color-9}; + --l-error-color-10: #{$error-color-10}; + + // 警告色系 + --l-warning-color-1: #{$warning-color-1}; + --l-warning-color-2: #{$warning-color-2}; + --l-warning-color-3: #{$warning-color-3}; + --l-warning-color-4: #{$warning-color-4}; + --l-warning-color-5: #{$warning-color-5}; + --l-warning-color-6: #{$warning-color-6}; + --l-warning-color-7: #{$warning-color-7}; + --l-warning-color-8: #{$warning-color-8}; + --l-warning-color-9: #{$warning-color-9}; + --l-warning-color-10: #{$warning-color-10}; + + // 成功色系 + --l-success-color-1: #{$success-color-1}; + --l-success-color-2: #{$success-color-2}; + --l-success-color-3: #{$success-color-3}; + --l-success-color-4: #{$success-color-4}; + --l-success-color-5: #{$success-color-5}; + --l-success-color-6: #{$success-color-6}; + --l-success-color-7: #{$success-color-7}; + --l-success-color-8: #{$success-color-8}; + --l-success-color-9: #{$success-color-9}; + --l-success-color-10: #{$success-color-10}; + + // 灰色系 + --l-gray-1: #{$gray-1}; + --l-gray-2: #{$gray-2}; + --l-gray-3: #{$gray-3}; + --l-gray-4: #{$gray-4}; + --l-gray-5: #{$gray-5}; + --l-gray-6: #{$gray-6}; + --l-gray-7: #{$gray-7}; + --l-gray-8: #{$gray-8}; + --l-gray-9: #{$gray-9}; + --l-gray-10: #{$gray-10}; + --l-gray-11: #{$gray-11}; + --l-gray-12: #{$gray-12}; + --l-gray-13: #{$gray-13}; + --l-gray-14: #{$gray-14}; + + // 文字颜色 + --l-text-color-1: #{$text-color-1}; + --l-text-color-2: #{$text-color-2}; + --l-text-color-3: #{$text-color-3}; + --l-text-color-4: #{$text-color-4}; + + // 容器背景色 + --l-bg-color-page: #{$bg-color-page}; + --l-bg-color-container: #{$bg-color-container}; + --l-bg-color-elevated: #{$bg-color-elevated}; + --l-bg-color-spotlight: #{$bg-color-spotlight}; + --l-bg-color-mask: #{$bg-color-mask}; + + // 填充色 + --l-fill-1: #{$fill-1}; + --l-fill-2: #{$fill-2}; + --l-fill-3: #{$fill-3}; + --l-fill-4: #{$fill-4}; + + // 描边色 + --l-border-color-1: #{$border-color-1}; + --l-border-color-2: #{$border-color-2}; + --l-border-color-3: #{$border-color-3}; + --l-border-color-4: #{$border-color-4}; + + // loading + --l-loading-text-color: #{$text-color-3}; + + // load-more + --l-load-more-text-color: #{$text-color-3}; + --l-load-more-color: #{$text-color-4}; + + // 按钮 + --l-button-default-solid-text-color: #000; + --l-button-default-border-color: #{$gray-5}; + --l-button-default-color: #{$gray-14}; + --l-button-default-light-color: #{$gray-4}; + --l-button-default-light-hover-color: #{$gray-5}; + --l-button-primary-light-color: #{$primary-color-2}; + --l-button-primary-light-hover-color: #{$primary-color-3}; + --l-button-danger-light-color: #{$error-color-2}; + --l-button-danger-light-hover-color: #{$error-color-3}; + --l-button-warning-light-color: #{$warning-color-2}; + --l-button-warning-light-hover-color: #{$warning-color-3}; + --l-button-success-light-color: #{$success-color-2}; + --l-button-success-light-hover-color: #{$success-color-3}; + --l-button-info-light-color: #{$info-color-1}; + --l-button-info-light-hover-color: #{$info-color-2}; + --l-button-primary-color: #{$primary-color-6}; + --l-button-danger-color: #{$error-color-6}; + --l-button-warning-color: #{$warning-color-6}; + --l-button-info-color: #{$info-color-6}; + + // 遮罩 + // --l-overlay-bg-color: #{$bg-color-mask}; + // 弹窗 + --l-popup-bg-color: #{$bg-color-elevated}; + --l-popup-close-icon-color: #{$text-color-2}; + + // 单元格 + --l-cell-group-title-color: #{$text-color-3}; + --l-cell-group-border-color: #{$border-color-3}; + --l-cell-bg-color: #{$bg-color-container}; + --l-cell-hover-color: #{$gray-3}; + --l-cell-border-color: #{$border-color-2}; + --l-cell-note-color: #{$text-color-3}; + --l-cell-description-color: #{$text-color-2}; + --l-cell-title-color: #{$text-color-1}; + --l-cell-right-icon-color: #{$text-color-3}; + + // 步进器 + --l-stepper-button-bg-color: #{$gray-4}; + --l-stepper-input-disabled-bg: #{$gray-3}; + --l-stepper-input-color: #{$text-color-1}; + --l-stepper-input-disabled-color: #{$text-color-4}; + --l-stepper-border-color: #{$gray-4}; + + // tabbar + --l-tabbar-bg-color: #{$bg-color-container}; + --l-tabbar-border-color: #{$border-color-1}; + --l-tabbar-color: #{$text-color-1}; + --l-tabbar-active-color: #{$primary-color-6}; + --l-tabbar-active-bg-color: #{$primary-color-1}; + + // link + --l-link-default-color: #{$text-color-1}; + + // image + --l-image-loading-bg-color: #{$fill-3}; + --l-image-color: #{$text-color-3}; + + // divider 分割线 + --l-divider-color: #{$border-color-2}; + --l-divider-text-color: #{$text-color-2}; + + // card 卡片 + --l-card-bg-color: #{$bg-color-container}; + --l-card-title-color: #{$text-color-1}; + --l-card-extra-color: #{$text-color-3}; + --l-card-note-color: #{$text-color-3}; + --l-card-border-color: #{$border-color-2}; + + // grid 宫格 + --l-grid-item-bg-color: #{$bg-color-container}; + --l-grid-item-image-bg-color: #{$fill-4}; + --l-grid-item-text-color: #{$text-color-1}; + --l-grid-item-hover-bg-color: #{$fill-3}; + --l-grid-item-description-color: #{$text-color-3}; + --l-grid-item-border-color: #{$border-color-2}; + --l-grid-item-icon-color: #{$text-color-1}; + + // cascader 级联 + --l-cascader-title-color: #{$text-color-1}; + --l-cascader-bg-color: #{$bg-color-container}; + --l-cascader-cell-title-color: #{$text-color-1}; + --l-cascader-disabled-color: #{$text-color-3}; + --l-cascader-options-title-color: #{$text-color-3}; + --l-cascader-close-icon-color: #{$text-color-2}; + + // tabs 标签页 + --l-tab-nav-bg-color: #{$bg-color-container}; + --l-tab-content-bg-color: #{$bg-color-container}; + --l-tab-split-color: #{$border-color-1}; + --l-tab-item-color: #{$text-color-2}; + --l-tab-item-disabled-color: #{$text-color-4}; + + // checkbox 复选框 + --l-checkbox-border-icon-color: #{$gray-8}; + --l-checkbox-icon-bg-color: #{$bg-color-container}; + --l-checkbox-text-color: #{$text-color-1}; + --l-checkbox-icon-disabled-bg-color: #{$gray-3}; + --l-checkbox-icon-disabled-color: #{$gray-6}; + + // radio 单选框 + --l-radio-border-icon-color: #{$gray-8}; + --l-radio-icon-bg-color: #{$bg-color-container}; + --l-radio-text-color: #{$text-color-1}; + --l-radio-icon-disabled-bg-color: #{$gray-3}; + --l-radio-icon-disabled-color: #{$gray-6}; + + // search 搜索 + --l-search-bg-color: #{$fill-3}; + --l-search-icon-color: #{$text-color-4}; + --l-search-clear-icon-color: #{$text-color-4}; + --l-search-text-color: #{$text-color-1}; + --l-search-label-color: #{$text-color-1}; + --l-search-placeholder-color: #{$text-color-3}; + + // switch + --l-switch-checked-disabled-color: #{$primary-color-3}; + --l-switch-unchecked-color: #{$gray-5}; + --l-switch-unchecked-disabled-color: #{$gray-4}; + + // input 输入框 + --l-input-text-color: #{$text-color-1}; + --l-input-tips-color: #{$text-color-3}; + --l-input-bg-color: #{$bg-color-container}; + --l-input-border-color: #{$border-color-2}; + --l-input-placeholder-text-color: #{$text-color-3}; + --l-input-prefix-icon-color: #{$text-color-1}; + --l-input-suffix-icon-color: #{$text-color-3}; + --l-input-label-text-color: #{$text-color-1}; + --l-input-suffix-text-color: #{$text-color-1}; + --l-input-disabled-text-color: #{$text-color-4}; + --l-input-disabled-bg-color: #{$fill-3}; + --l-input-border-color: #{$border-color-2}; + + // textarea + --l-textarea-bg-color: #{$bg-color-container}; + --l-textarea-placeholder-color: #{$text-color-3}; + --l-textarea-text-color: #{$text-color-1}; + --l-textarea-label-color: #{$text-color-1}; + --l-textarea-indicator-text-color: #{$text-color-3}; + --l-textarea-border-color: #{$border-color-2}; + --l-textarea-disabled-text-color: #{$text-color-4}; + + // upload + --l-upload-bg-color: #{$gray-4}; + --l-upload-add-bg-color: #{$gray-4}; + --l-upload-add-color: #{$text-color-3}; + + // picker + --l-picker-bg-color: #{$bg-color-container}; + --l-picker-cancel-color: #{$text-color-2}; + --l-picker-title-color: #{$text-color-1}; + --l-picker-item-active-color: #{$text-color-1}; + --l-picker-mask-top-color: #{$gray-2}; + --l-picker-loading-mask-color: rgba(0,0,0,.6); + --l-picker-item-color: #{$text-color-1}; + --l-picker-indicator-bg-color: #{$fill-4}; + + // empty + --l-empty-opacity: 0.6; + + // segmented + --l-segmented-bg-color: #{$gray-4}; + --l-segmented-text-color: #{$text-color-2}; + --l-segmented-active-bg-color: #{$gray-5}; + + // keyboard + --l-keyboard-bg-color: #{$bg-color-elevated}; + --l-keyboard-color: #{$text-color-1}; + --l-keyboard-key-bg-color: #{$gray-5}; + --l-keyboard-key-hover-bg-color: #{$gray-4}; + --l-keyboard-icon-bg-color: #{$gray-5}; + --l-keyboard-icon-color: #{$text-color-3}; + + // code-input + --l-code-input-bg-color: #{$gray-4}; + --l-code-input-active-bg-color: #{$gray-5}; + --l-code-input-info-color: #{$text-color-3}; + --l-code-input-dot-color: #{$text-color-1}; + --l-code-input-text-color: #{$text-color-1}; + --l-code-input-cursor-color: #{$text-color-1}; + --l-code-input-active-border-color: #{$gray-6}; + + // steps + --l-step-description-color: #{$text-color-3}; + --l-step-wait-circle-bg-color: #{$gray-4}; + --l-step-wait-circle-color: #{$text-color-3}; + --l-step-wait-title-color: #{$text-color-3}; + --l-step-wait-icon-color: #{$text-color-3}; + --l-step-wait-dot-border-color: #{$gray-5}; + --l-step-line-color: #{$gray-5}; + --l-step-finish-title-color: #{$text-color-1}; + --l-step-finish-circle-bg-color: #{$primary-color-2}; + --l-step-error-circle-bg-color: #{$error-color-2}; + + // date-strip + --l-date-strip-bg-color: #{$bg-color-container}; + --l-date-strip-color: #{$text-color-1}; + --l-date-strip-prefix-color: #{$text-color-3}; + --l-date-strip-color: #{$text-color-2}; + + // slider + --l-slider-rail-color: #{$gray-5}; + --l-slider-thumb-border-color: #{$gray-11}; + + // form + --l-form-item-border-color: #{$border-color-2}; + --l-form-bg-color: #{$bg-color-container}; + --l-form-item-label-color: #{$text-color-1}; + + // color-picker + --l-color-picker-color: #{$text-color-1}; + --l-color-picker-label-color: #{$text-color-2}; + --l-color-picker-field-bg-color: #{$fill-2}; + --l-color-picker-divider-color: #{$border-color-2}; + + // calendar + --l-calendar-bg-color: #{$bg-color-container}; + --l-calendar-title-color: #{$text-color-1}; + --l-calendar-days-color: #{$text-color-2}; + --l-calendar-item-color: #{$text-color-1}; + --l-calendar-item-disabled-color: #{$text-color-4}; + --l-calendar-item-centre-color: #{$primary-color-2}; + --l-calendar-month-mark-color: #{$fill-3}; + --l-calendar-switch-mode-icon-color: #{$text-color-2}; + --l-calendar-switch-mode-icon-disabled-color: #{$text-color-4}; + --l-calendar-header-border-color: #{$border-color-2}; + + // loading + --l-loading-text-color: #{$text-color-3}; + + // dialog + --l-dialog-title-color: #{$text-color-1}; + --l-dialog-content-color: #{$text-color-2}; + --l-dialog-close-color: #{$text-color-3}; + --l-dialog-bg-color: #{$bg-color-container}; + --l-dialog-split-color: #{$border-color-2}; + + // action-sheet + --l-action-sheet-item-disabled-color: #{$text-color-4}; + --l-action-sheet-hover-color: #{$gray-3}; + --l-action-sheet-border-color: #{$border-color-1}; + --l-action-sheet-gap-color: #{$bg-color-page}; + --l-action-sheet-color: #{$text-color-1}; + --l-action-sheet-description-color: #{$text-color-3}; + --l-action-sheet-cancel-color: #{$text-color-1}; + --l-action-sheet-cancel-bg-color: #{$bg-color-container}; + --l-action-sheet-image-bg-color: #{$fill-3}; + --l-action-sheet-title-color: #{$text-color-1}; + --l-action-sheet-close-btn-color: #{$text-color-1}; + + // sorter + --l-sorter-color: #{$text-color-1}; + + // floating-panel + --l-floating-panel-bg-color: #{$bg-color-elevated}; + --l-floating-panel-bar-color: #{$fill-1}; + + // dropdown-menu + --l-dropdown-menu-color: #{$text-color-1}; + --l-dropdown-menu-bg-color: #{$bg-color-container}; + --l-dropdown-menu-border-color: #{$border-color-1}; + --l-dropdown-menu-disabled-color: #{$border-color-3}; + --l-dropdown-menu-arrow-color: #{$gray-6}; + --l-dropdown-menu-arrow-active-color: #{$gray-4}; + --l-dropdown-item-cell-title-color: #{$text-color-1}; + + // pull-refresh + --l-pull-refresh-refresher-color: #{$text-color-2}; + + // circle + --l-circle-trail-color: #{$gray-5}; + + // collapse + --l-collapse-panel-bg-color: #{$bg-color-container}; + --l-collapse-content-text-color: #{$text-color-1}; + --l-collapse-right-icon-color: #{$text-color-4}; + --l-collapse-border-color: #{$border-color-2}; + + // count-down + --l-count-down-text-color: #{$text-color-1}; + + // empty + --l-empty-description-color: #{$text-color-3}; + // progress + --l-progress-trail-color: #{$gray-5}; + --l-progress-text-color: #{$text-color-2}; + + // tag + // --l-tag-default-solid-text-color: #000; + --l-tag-text-color: #{$gray-14}; + --l-tag-default-color: #{$gray-6}; + --l-tag-default-light-color: #{$gray-4}; + --l-tag-default-border-color: #{$gray-5}; + --l-tag-primary-light-color: #{$primary-color-2}; + --l-tag-danger-light-color: #{$error-color-2}; + --l-tag-warning-light-color: #{$warning-color-2}; + --l-tag-success-light-color: #{$success-color-2}; + + // amount + --l-amount-color: #{$text-color-1}; + + // avatar + --l-avatar-bg-color: #{$primary-color-1}; + --l-avatar-border-color: #{$gray-2}; + + // highlight + --l-highlight-normal-color: #{$text-color-1}; + + // text-ellipsis + --l-text-ellipsis-color: #{$text-color-1}; + + // read-more + --l-read-more-handle-color: #{$text-color-2}; + --l-read-more-read-start: rgba(36, 36, 36, 0.9); + --l-read-more-read-end: rgba(36, 36, 36, 0.3); + --l-read-more-mask-bg-color: linear-gradient( + to top, + rgba(0,0,0,0), + rgba(0,0,0,1), + ); + // notice-bar + --l-notice-bar-info-bg-color: #{$info-color-1}; + --l-notice-bar-success-bg-color: #{$success-color-1}; + --l-notice-bar-warning-bg-color: #{$warning-color-1}; + --l-notice-bar-danger-bg-color: #{$error-color-1}; + + // scrollx + --l-scrollx-track-color: #{$gray-4}; + + // dateformat + --l-dateformat-color: #{$text-color-1}; + + // footer + --l-footer-text-color: #{$text-color-3}; + --l-footer-link-dividing-line-color: #{$text-color-3}; + --l-footer-logo-title-color: #{$text-color-1}; + + // tree + --l-tree-node-text-color: #{$text-color-1}; + --l-tree-arrow-color: #{$gray-6}; + + // table + --l-table-bg-color: #{$bg-color-container}; + --l-table-border-color: #{$border-color-2}; + --l-table-td-fixed-bg-color: #{$bg-color-container}; + --l-table-tr-fixed-bg-color: #{$bg-color-container}; + + // sidebar + --l-sidebar-bg-color: #{$gray-3}; + --l-sidebar-selected-bg-color: #{$bg-color-container}; + --l-sidebar-text-color: #{$text-color-2}; + --l-sidebar-disabled-text-color: #{$text-color-4}; + + // back-top + --l-back-top-bg-color: #{$bg-color-elevated}; + --l-back-top-border-color: #{$border-color-2}; + --l-back-top-text-color: #{$text-color-2}; + + // navbar + --l-navbar-bg-color: #{$bg-color-container}; + --l-navbar-color: #{$text-color-1}; + --l-navbar-capsule-border-color: #{$border-color-2}; + + // pagination + --l-pagination-bg-color: #{$gray-4}; + --l-pagination-disabled-bg-color: #{$gray-3}; + --l-pagination-hover-bg-color: #{$gray-5}; + --l-pagination-text-color: #{$text-color-2}; + --l-pagination-disabled-color: #{$text-color-4}; + --l-pagination-simple-text-color: #{$text-color-1}; + + // indexes + --l-indexes-sidebar-color: #{$text-color-1}; + --l-indexes-anchor-color: #{$text-color-1}; + --l-indexes-anchor-bg-color: #{$gray-4}; + --l-indexes-anchor-active-bg-color: #{$gray-4}; + --l-indexes-sidebar-tips-bg-color: #{$primary-color-1}; + + // typing + --l-typing-bg-color: #{$bg-color-container}; + --l-typing-text-color: #{$text-color-1}; + + // fit-swiper + --l-fit-swiper-indicator-color: #{$gray-5}; +} diff --git a/QXTfront/uni_modules/lime-style/theme/default.scss b/QXTfront/uni_modules/lime-style/theme/default.scss new file mode 100644 index 0000000..90aaba7 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/theme/default.scss @@ -0,0 +1,181 @@ +@import '../mixins/create.scss'; +@import '../color/colorPalette.scss'; +@import '../color/colors.scss'; + +$blue-1: genColor($blue, 1); +$blue-2: genColor($blue, 2); +$blue-3: genColor($blue, 3); +$blue-4: genColor($blue, 4); +$blue-5: genColor($blue, 5); +$blue-6: $blue; +$blue-7: genColor($blue, 7); +$blue-8: genColor($blue, 8); +$blue-9: genColor($blue, 9); +$blue-10: genColor($blue, 10); + +$info-color-1: genColor($info-color, 1); +$info-color-2: genColor($info-color, 2); +$info-color-3: genColor($info-color, 3); +$info-color-4: genColor($info-color, 4); +$info-color-5: genColor($info-color, 5); +$info-color-6: $info-color; +$info-color-7: genColor($info-color, 7); +$info-color-8: genColor($info-color, 8); +$info-color-9: genColor($info-color, 9); +$info-color-10: genColor($info-color, 10); + +$primary-color-1: create-var('primary-color-1', genColor($primary-color, 1)); // 浅色/白底悬浮 +$primary-color-2: create-var('primary-color-2', genColor($primary-color, 2)); // 文字禁用 +$primary-color-3: create-var('primary-color-3', genColor($primary-color, 3)); // 一般禁用 +$primary-color-4: create-var('primary-color-4', genColor($primary-color, 4)); // 特殊场景 禁用 +$primary-color-5: create-var('primary-color-5', genColor($primary-color, 5)); // 悬浮 +$primary-color-6: create-var('primary-color-6', $primary-color); // 常规 +$primary-color-7: create-var('primary-color-7', genColor($primary-color, 7)); // 点击 +$primary-color-8: create-var('primary-color-8', genColor($primary-color, 8)); // +$primary-color-9: create-var('primary-color-9', genColor($primary-color, 9)); +$primary-color-10: create-var('primary-color-10', genColor($primary-color, 10)); + +$error-color-1: create-var('error-color-1', genColor($error-color, 1)); +$error-color-2: create-var('error-color-2', genColor($error-color, 2)); +$error-color-3: create-var('error-color-3', genColor($error-color, 3)); +$error-color-4: create-var('error-color-4', genColor($error-color, 4)); +$error-color-5: create-var('error-color-5', genColor($error-color, 5)); +$error-color-6: create-var('error-color-6', $error-color); +$error-color-7: create-var('error-color-7', genColor($error-color, 7)); +$error-color-8: create-var('error-color-8', genColor($error-color, 8)); +$error-color-9: create-var('error-color-9', genColor($error-color, 9)); +$error-color-10: create-var('error-color-10', genColor($error-color, 10)); + +$warning-color-1: create-var('warning-color-1', genColor($warning-color, 1)); +$warning-color-2: create-var('warning-color-2', genColor($warning-color, 2)); +$warning-color-3: create-var('warning-color-3', genColor($warning-color, 3)); +$warning-color-4: create-var('warning-color-4', genColor($warning-color, 4)); +$warning-color-5: create-var('warning-color-5', genColor($warning-color, 5)); +$warning-color-6: create-var('warning-color-6', $warning-color); +$warning-color-7: create-var('warning-color-7', genColor($warning-color, 7)); +$warning-color-8: create-var('warning-color-8', genColor($warning-color, 8)); +$warning-color-9: create-var('warning-color-9', genColor($warning-color, 9)); +$warning-color-10: create-var('warning-color-10', genColor($warning-color, 10)); + +$success-color-1: create-var('success-color-1', genColor($success-color, 1)); // 浅色/白底悬浮 +$success-color-2: create-var('success-color-2', genColor($success-color, 2)); // 文字禁用 +$success-color-3: create-var('success-color-3', genColor($success-color, 3)); // 一般禁用 +$success-color-4: create-var('success-color-4', genColor($success-color, 4)); // 特殊场景 +$success-color-5: create-var('success-color-5', genColor($success-color, 5)); // 悬浮 +$success-color-6: create-var('success-color-6', $success-color); // 常规 +$success-color-7: create-var('success-color-7', genColor($success-color, 7)); // 点击 +$success-color-8: create-var('success-color-8', genColor($success-color, 8)); +$success-color-9: create-var('success-color-9', genColor($success-color, 9)); +$success-color-10: create-var('success-color-10', genColor($success-color, 10)); + +$white: create-var('white', #fff); +$gray-1: create-var('gray-1', #f3f3f3); +$gray-2: create-var('gray-2', #eeeeee); +$gray-3: create-var('gray-3', #e7e7e7); +$gray-4: create-var('gray-4', #dcdcdc); +$gray-5: create-var('gray-5', #c5c5c5); +$gray-6: create-var('gray-6', #a6a6a6); +$gray-7: create-var('gray-7', #8b8b8b); +$gray-8: create-var('gray-8', #777777); +$gray-9: create-var('gray-9', #5e5e5e); +$gray-10: create-var('gray-10', #4b4b4b); +$gray-11: create-var('gray-11', #383838); +$gray-12: create-var('gray-12', #2c2c2c); +$gray-13: create-var('gray-13', #242424); +$gray-14: create-var('gray-14', #181818); +$black: create-var('black', #000); + +// $text-color-1: create-var('text-color-1', rgba(0,0,0,0.88)); //primary +// $text-color-2: create-var('text-color-2', rgba(0,0,0,0.65)); //secondary +// $text-color-3: create-var('text-color-3', rgba(0,0,0,0.45)); //placeholder +// $text-color-4: create-var('text-color-4', rgba(0,0,0,0.25)); //disabled +$text-color-1: create-var('text-color-1', #000000E0); // primary (rgba(0,0,0,0.88)) +$text-color-2: create-var('text-color-2', #000000A6); // secondary (rgba(0,0,0,0.65)) +$text-color-3: create-var('text-color-3', #00000073); // placeholder (rgba(0,0,0,0.45)) +$text-color-4: create-var('text-color-4', #00000040); // disabled (rgba(0,0,0,0.25)) + +// 容器 +$bg-color-page: create-var('bg-color-page', $gray-1); // 整体背景色 布局 +$bg-color-container: create-var('bg-color-container', #fff); // 一级容器背景 组件 +$bg-color-elevated: create-var('bg-color-elevated', #fff); // 二级容器背景 浮层 +$bg-color-spotlight: create-var('bg-color-spotlight', rgba(0, 0, 0, 0.85)); // 引起注意的如 Tooltip +$bg-color-mask: create-var('bg-color-mask', rgba(0, 0, 0, 0.45)); // 蒙层 + +// 填充 +// $fill-1: create-var('fill-1', rgba(0, 0, 0, 0.15)); +// $fill-2: create-var('fill-2', rgba(0, 0, 0, 0.06)); +// $fill-3: create-var('fill-3', rgba(0, 0, 0, 0.04)); +// $fill-4: create-var('fill-4', rgba(0, 0, 0, 0.02)); +$fill-1: create-var('fill-1', #00000026); // rgba(0,0,0,0.15) +$fill-2: create-var('fill-2', #0000000F); // rgba(0,0,0,0.06) +$fill-3: create-var('fill-3', #0000000A); // rgba(0,0,0,0.04) +$fill-4: create-var('fill-4', #00000005); // rgba(0,0,0,0.02) + + +// 描边 +$border-color-1: create-var('border-color-1', $gray-2); // 浅色 +$border-color-2: create-var('border-color-2', $gray-3); // 一般 +$border-color-3: create-var('border-color-3', $gray-4); // 深/悬浮 +$border-color-4: create-var('border-color-4', $gray-6); // 重/按钮描边 + + +$alpha-disabled: create-var('alpha-disabled', 0.5); +$alpha-pressed: create-var('alpha-pressed', 0.07); + +// 投影 +/* #ifndef UNI-APP-X && APP */ +$shadow-1: create-var( + shadow-1, + 0 1px 10px rgba(0, 0, 0, 0.05), + 0 4px 5px rgba(0, 0, 0, 0.08), + 0 2px 4px -1px rgba(0, 0, 0, 0.12) +); + +$shadow-2: create-var( + 'shadow-2', + 0 1px 10px rgba(0, 0, 0, 0.05), + 0 4px 5px rgba(0, 0, 0, 0.08), + 0 2px 4px -1px rgba(0, 0, 0, 0.12) +); +$shadow-3: create-var( + shadow-3, + 0 6px 30px 5px rgba(0, 0, 0, 0.05), + 0 16px 24px 2px rgba(0, 0, 0, 0.04), + 0 8px 10px -5px rgba(0, 0, 0, 0.08) +); + +/* #endif */ +/* #ifdef UNI-APP-X && APP */ +$shadow-1: create-var( + shadow-1, + 0 1px 10px rgba(0, 0, 0, 0.05) +); +$shadow-2: create-var( + 'shadow-2', + 0 1px 10px rgba(0, 0, 0, 0.05) +); +$shadow-3: create-var( + shadow-3, + /* #ifdef APP-HARMONY + 0 6px 30px 5px $gray-3 + /* #endif */ + /* #ifndef APP-HARMONY + 0 6px 30px 5px rgba(0, 0, 0, 0.05) + /* #endif */ + +); +/* #endif */ +$shadow-4: create-var(shadow-4, 0 2px 8px 0 rgba(0, 0, 0, .06)); + +// 基础颜色的扩展 用于 聚焦 / 禁用 / 点击 等状态 +$primary-color-focus: create-var('primary-color-focus', $primary-color-1);// focus态,包括鼠标和键盘 +$primary-color-active: create-var('primary-color-active', $primary-color-8);// 点击态 +$primary-color-disabled: create-var('primary-color-disabled', $primary-color-3); +$primary-color-light: create-var('primary-color-light', $primary-color-1); // 浅色的选中态 +$primary-color-light-active: create-var('primary-color-light-active', $primary-color-2); // 浅色的选中态 + +$primary-color: create-var(primary-color, $primary-color); +$error-color: create-var(error-color, $error-color); +$warning-color: create-var(warning-color, $warning-color); +$success-color: create-var(success-color, $success-color); +$info-color: create-var(info-color, $info-color); \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/token/dark.uts b/QXTfront/uni_modules/lime-style/token/dark.uts new file mode 100644 index 0000000..bb373af --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/dark.uts @@ -0,0 +1,67 @@ +import { TinyColor, generate, LGenerateOptions } from '@/uni_modules/lime-color'; +import { getAlphaColor, getSolidColor, generateColorPalettes } from './shared' +import { SeedToken } from './interface' +// #ifndef UNI-APP-X +export type UTSJSONObject = Record +const UTSJSONObject = Object +// #endif + +export function generateNeutralColorPalettes( + bgBaseColor : string | null, + textBaseColor : string | null) : UTSJSONObject { + const colorBgBase = bgBaseColor ?? '#000'; + const colorTextBase = textBaseColor ?? '#fff'; + + return { + 'bgColorBase': colorBgBase, + 'textColorBase': colorTextBase, + + 'textColor1': getAlphaColor(colorTextBase, 0.85), + 'textColor2': getAlphaColor(colorTextBase, 0.65), + 'textColor3': getAlphaColor(colorTextBase, 0.45), + 'textColor4': getAlphaColor(colorTextBase, 0.25), + + 'fill1': getAlphaColor(colorTextBase, 0.18), + 'fill2': getAlphaColor(colorTextBase, 0.12), + 'fill3': getAlphaColor(colorTextBase, 0.08), + 'fill4': getAlphaColor(colorTextBase, 0.04), + + 'bgColorElevated': getSolidColor(colorBgBase, 12), + 'bgColorContainer': getSolidColor(colorBgBase, 8), + 'bgColorPage': getSolidColor(colorBgBase, 0), + 'bgColorSpotlight': getSolidColor(colorBgBase, 26), + // 'bgColor5': getAlphaColor(colorTextBase, 0.04), + 'bgColorMask': getAlphaColor(colorBgBase, 0.45), + 'bgColorBlur': getAlphaColor(colorTextBase, 0.04), + + 'borderColor1': getSolidColor(colorBgBase, 26), + 'borderColor2': getSolidColor(colorBgBase, 19) + } +} + + +export function genColorMapToken(token : SeedToken) : UTSJSONObject { + const colorPrimaryBase = token.primaryColor + const colorSuccessBase = token.successColor + const colorWarningBase = token.warningColor + const colorErrorBase = token.errorColor + const colorInfoBase = token.infoColor + const colorBgBase = token.bgColorBase + const colorTextBase = token.textColorBase + + const primaryColors = generateColorPalettes(colorPrimaryBase, 'primaryColor', 'dark'); + const successColors = generateColorPalettes(colorSuccessBase, 'successColor', 'dark'); + const warningColors = generateColorPalettes(colorWarningBase, 'warningColor', 'dark'); + const errorColors = generateColorPalettes(colorErrorBase, 'errorColor', 'dark'); + const infoColors = generateColorPalettes(colorInfoBase, 'infoColor', 'dark'); + const neutralColors = generateNeutralColorPalettes(colorBgBase, colorTextBase); + + return UTSJSONObject.assign( + {}, + primaryColors, + successColors, + warningColors, + errorColors, + infoColors, + neutralColors) +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/token/genFontMapToken.uts b/QXTfront/uni_modules/lime-style/token/genFontMapToken.uts new file mode 100644 index 0000000..ccd7256 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/genFontMapToken.uts @@ -0,0 +1,49 @@ +// import type { FontMapToken } from '../../interface'; +import { getFontSizes } from './genFontSizes'; + +export const genFontMapToken = (fontSize : number | null) : UTSJSONObject => { + if (fontSize == null) return {} + const fontSizePairs = getFontSizes(fontSize); + const fontSizes = fontSizePairs.map((pair) : number => pair.size); + const lineHeights = fontSizePairs.map((pair) : number => pair.lineHeight); + + const fontSizeXS = fontSizes[0]; + const fontSizeSM = fontSizes[1]; + const fontSizeMD = fontSizes[3]; + const fontSizeLG = fontSizes[4]; + + const lineHeight = lineHeights[2]; + const lineHeightSM = lineHeights[1]; + const lineHeightMD = lineHeights[3]; + const lineHeightLG = lineHeights[4]; + + return { + fontSize, + fontSizeXS, + fontSizeSM, + fontSizeMD, + fontSizeLG, + fontSizeXL: fontSizes[5], + + fontSizeHeading1: fontSizes[7], + fontSizeHeading2: fontSizes[6], + fontSizeHeading3: fontSizes[5], + fontSizeHeading4: fontSizes[4], + fontSizeHeading5: fontSizes[3], + + lineHeight, + lineHeightLG, + lineHeightMD, + lineHeightSM, + + fontHeight: Math.round(lineHeight * fontSizeMD), + fontHeightLG: Math.round(lineHeightLG * fontSizeLG), + fontHeightSM: Math.round(lineHeightSM * fontSizeSM), + + lineHeightHeading1: lineHeights[7], + lineHeightHeading2: lineHeights[6], + lineHeightHeading3: lineHeights[5], + lineHeightHeading4: lineHeights[4], + lineHeightHeading5: lineHeights[3], + }; +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/token/genFontSizes.uts b/QXTfront/uni_modules/lime-style/token/genFontSizes.uts new file mode 100644 index 0000000..c294b54 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/genFontSizes.uts @@ -0,0 +1,30 @@ +import { FontSize } from './interface'; + +export function getLineHeight(fontSize : number) : number { + return (fontSize + 8) / fontSize; +} + +// https://zhuanlan.zhihu.com/p/32746810 +export function getFontSizes(base : number) : FontSize[] { + const length = 11 // 10 + const offset = 2 // 1 + // #ifdef APP-ANDROID + const arr = Array.fromNative(new IntArray(length.toInt())); + // #endif + // #ifndef APP-ANDROID + const arr = Array.from({ length }); + // #endif + const fontSizes = arr.map((_, index) : number => { + const i = index - offset; + const baseSize = base * Math.pow(Math.E, i / 5); + const intSize = index > 1 ? Math.floor(baseSize) : Math.ceil(baseSize); + + // Convert to even + return Math.floor(intSize / 2) * 2; + }); + fontSizes[offset] = base; + return fontSizes.map((size) : FontSize => ({ + size, + lineHeight: getLineHeight(size), + } as FontSize)); +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/token/genRadius.uts b/QXTfront/uni_modules/lime-style/token/genRadius.uts new file mode 100644 index 0000000..f4378d1 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/genRadius.uts @@ -0,0 +1,63 @@ +export function genRadius(radiusBase : number):Map { + let radiusXL = radiusBase; + let radiusLG = radiusBase; + let radiusMD = radiusBase; + let radiusSM = radiusBase; + let radiusXS = radiusBase; + let radiusOuter = radiusBase; + + + // radiusSM = radiusBase - 3 + // radiusXS = radiusSM - 1 + // radiusLG = radiusBase + 3 + // radiusXL = radiusLG + 3 + + + // radiusXL + if (radiusBase < 6 && radiusBase >= 5) { + radiusXL = radiusBase + 3; + } else if (radiusBase < 16 && radiusBase >= 6) { + radiusXL = radiusBase + 6; + } else if (radiusBase >= 16) { + radiusXL = 16; + } + + // radiusLG + if (radiusBase < 6 && radiusBase >= 5) { + radiusLG = radiusBase + 1; + } else if (radiusBase < 16 && radiusBase >= 6) { + radiusLG = radiusBase + 3; + } else if (radiusBase >= 16) { + radiusLG = 16; + } + + // radiusSM + if (radiusBase < 7 && radiusBase >= 5) { + radiusSM = 3; + } else if (radiusBase < 8 && radiusBase >= 7) { + radiusSM = 4; + } else if (radiusBase < 14 && radiusBase >= 8) { + radiusSM = 5; + } else if (radiusBase < 16 && radiusBase >= 14) { + radiusSM = 6; + } else if (radiusBase >= 16) { + radiusSM = 8; + } + + // radiusXS + if (radiusBase < 6 && radiusBase >= 2) { + radiusXS = 1; + } else if (radiusBase >= 6) { + radiusXS = 2; + } + + + return new Map([ + ['borderRadius', radiusBase], + ['borderRadiusXS', radiusXS], + ['borderRadiusSM', radiusSM], + ['borderRadiusMD', radiusMD], + ['borderRadiusLG', radiusLG], + ['borderRadiusXL', radiusXL], + ]) +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/token/genSizeMapToken.uts b/QXTfront/uni_modules/lime-style/token/genSizeMapToken.uts new file mode 100644 index 0000000..f7832ab --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/genSizeMapToken.uts @@ -0,0 +1,20 @@ +// import {SizeMapToken} from './interface' + +/** + * sizeUnit 尺寸变化单位 + * sizeStep 尺寸步长 + */ +export function genSizeMapToken(sizeUnit : number | null = 4, sizeStep : number | null = 4) : UTSJSONObject { + if (sizeUnit == null || sizeStep == null) return {} + return { + spacerHG: sizeUnit * (sizeStep + 16), // 80 + spacerXL: sizeUnit * (sizeStep + 8), // 48 + spacerLG: sizeUnit * (sizeStep + 4), // 32 + spacerMD: sizeUnit * (sizeStep + 2), // 24 + spacerMS: sizeUnit * sizeStep, // 16 + spacer: sizeUnit * sizeStep, // 16 + spacerSM: sizeUnit * (sizeStep - 1), // 12 + spacerXS: sizeUnit * (sizeStep - 2), // 8 + spacerTN: sizeUnit * (sizeStep - 3), // 4 + }; +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/token/interface.uts b/QXTfront/uni_modules/lime-style/token/interface.uts new file mode 100644 index 0000000..9f93daf --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/interface.uts @@ -0,0 +1,184 @@ + +export type SeedToken = { + // ---------- Color ---------- // + /** + * @nameZH 是否生成深色色板 + * @nameEN GenerateDarkPalette + * @desc 是否生成一套完整的深色阶梯色板,以支持深色模式的应用 + * @descEN Whether to generate a complete set of dark color palettes to support dark mode applications + */ + useDark ?: boolean; + + /** + * @nameZH 品牌主色 + * @nameEN Brand Color + * @desc 品牌色是体现产品特性和传播理念最直观的视觉元素之一。在你完成品牌主色的选取之后,我们会自动帮你生成一套完整的色板,并赋予它们有效的设计语义 + * @descEN Brand color is one of the most direct visual elements to reflect the characteristics and communication of the product. After you have selected the brand color, we will automatically generate a complete color palette and assign it effective design semantics. + */ + primaryColor ?: string; + /** + * @nameZH 成功色 + * @nameEN Success Color + * @desc 用于表示操作成功的 Token 序列,如 Result、Progress 等组件会使用该组梯度变量。 + * @descEN Used to represent the token sequence of operation success, such as Result, Progress and other components will use these map tokens. + */ + successColor ?: string; + + /** + * @nameZH 警戒色 + * @nameEN Warning Color + * @desc 用于表示操作警告的 Token 序列,如 Notification、 Alert等警告类组件或 Input 输入类等组件会使用该组梯度变量。 + * @descEN Used to represent the warning map token, such as Notification, Alert, etc. Alert or Control component(like Input) will use these map tokens. + */ + warningColor ?: string; + /** + * @nameZH 错误色 + * @nameEN Error Color + * @desc 用于表示操作失败的 Token 序列,如失败按钮、错误状态提示(Result)组件等。 + * @descEN Used to represent the visual elements of the operation failure, such as the error Button, error Result component, etc. + */ + errorColor ?: string; + /** + * @nameZH 信息色 + * @nameEN Info Color + * @desc 用于表示操作信息的 Token 序列,如 Alert 、Tag、 Progress 等组件都有用到该组梯度变量。 + * @descEN Used to represent the operation information of the Token sequence, such as Alert, Tag, Progress, and other components use these map tokens. + */ + infoColor ?: string; + /** + * @nameZH 基础文本色 + * @nameEN Seed Text Color + * @desc 用于派生文本色梯度的基础变量,v5 中我们添加了一层文本色的派生算法可以产出梯度明确的文本色的梯度变量。但请不要在代码中直接使用该 Seed Token ! + * @descEN Used to derive the base variable of the text color gradient. In v5, we added a layer of text color derivation algorithm to produce gradient variables of text color gradient. But please do not use this Seed Token directly in the code! + */ + textColorBase ?: string; + + /** + * @nameZH 基础背景色 + * @nameEN Seed Background Color + * @desc 用于派生背景色梯度的基础变量,v5 中我们添加了一层背景色的派生算法可以产出梯度明确的背景色的梯度变量。但请不要在代码中直接使用该 Seed Token ! + * @descEN Used to derive the base variable of the background color gradient. In v5, we added a layer of background color derivation algorithm to produce map token of background color. But PLEASE DO NOT USE this Seed Token directly in the code! + */ + bgColorBase ?: string; + + /** + * @nameZH 超链接颜色 + * @nameEN Hyperlink color + * @desc 控制超链接的颜色。 + * @descEN Control the color of hyperlink. + */ + linkColor ?: string; + + // ---------- Font ---------- // + + /** + * @nameZH 字体 + * @nameEN Font family for default text + * @desc Lime Ui 的字体家族中优先使用系统默认的界面字体,同时提供了一套利于屏显的备用字体库,来维护在不同平台以及浏览器的显示下,字体始终保持良好的易读性和可读性,体现了友好、稳定和专业的特性。 + * @descEN The font family of Lime Ui prioritizes the default interface font of the system, and provides a set of alternative font libraries that are suitable for screen display to maintain the readability and readability of the font under different platforms and browsers, reflecting the friendly, stable and professional characteristics. + */ + fontFamily ?: string; + + /** + * @nameZH 代码字体 + * @nameEN Font family for code text + * @desc 代码字体,用于 Typography 内的 code、pre 和 kbd 类型的元素 + * @descEN Code font, used for code, pre and kbd elements in Typography + */ + fontFamilyCode ?: string; + + /** + * @nameZH 默认字号 + * @nameEN Default Font Size + * @desc 设计系统中使用最广泛的字体大小,文本梯度也将基于该字号进行派生。 + * @descEN The most widely used font size in the design system, from which the text gradient will be derived. + * @default 14 + */ + fontSize ?: number; + + + // ---------- BorderRadius ---------- // + + /** + * @nameZH 基础圆角 + * @nameEN Base Border Radius + * @descEN Border radius of base components + * @desc 基础组件的圆角大小,例如按钮、输入框、卡片等 + */ + borderRadius ?: number; + + // ---------- Size ---------- // + + /** + * @nameZH 尺寸变化单位 + * @nameEN Size Change Unit + * @desc 用于控制组件尺寸的变化单位,在 Lime Ui 中我们的基础单位为 4 ,便于更加细致地控制尺寸梯度 + * @descEN The unit of size change, in Lime Ui, our base unit is 4, which is more fine-grained control of the size step + * @default 4 + */ + sizeUnit ?: number; + + /** + * @nameZH 尺寸步长 + * @nameEN Size Base Step + * @desc 用于控制组件尺寸的基础步长,尺寸步长结合尺寸变化单位,就可以派生各种尺寸梯度。通过调整步长即可得到不同的布局模式,例如 V5 紧凑模式下的尺寸步长为 2 + * @descEN The base step of size change, the size step combined with the size change unit, can derive various size steps. By adjusting the step, you can get different layout modes, such as the size step of the compact mode of V5 is 2 + * @default 4 + */ + sizeStep ?: number; +} +export type FontSize = { + size : number + lineHeight : number +} +export type SizeMapToken = { + /** + * @nameZH Huge + * @default 80 + */ + sizeHG : number; + /** + * @nameZH XL + * @default 48 + */ + sizeXL : number; + /** + * @nameZH LG + * @default 32 + */ + sizeLG : number; + /** + * @nameZH MD + * @default 24 + */ + sizeMD : number; + /** Same as size by default, but could be larger in compact mode */ + sizeMS : number; + /** + * @nameZH 默认 + * @desc 默认尺寸 + * @default 16 + */ + size : number; + /** + * @nameZH SM + * @default 12 + */ + sizeSM : number; + /** + * @nameZH XS + * @default 8 + */ + sizeXS : number; + /** + * @nameZH Tiny + * @default 4 + */ + sizeTN : number; +} + + +// #ifndef UNI-APP-X +export type VueApp = any +export type UTSJSONObject = Record +// #endif diff --git a/QXTfront/uni_modules/lime-style/token/light.uts b/QXTfront/uni_modules/lime-style/token/light.uts new file mode 100644 index 0000000..8e3155a --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/light.uts @@ -0,0 +1,66 @@ +import { TinyColor, generate } from '@/uni_modules/lime-color'; +import { getAlphaColor, getSolidColor, generateColorPalettes } from './shared' +import { SeedToken } from './interface' +// #ifndef UNI-APP-X +export type UTSJSONObject = Record +const UTSJSONObject = Object +// #endif + +export function generateNeutralColorPalettes( + bgBaseColor : string | null, + textBaseColor : string | null +) : UTSJSONObject { + const colorBgBase = bgBaseColor ?? '#fff'; + const colorTextBase = textBaseColor ?? '#000'; + + return { + 'bgColorBase': bgBaseColor, + 'textColorBase': textBaseColor, + + 'textColor1': getAlphaColor(colorTextBase, 0.88), + 'textColor2': getAlphaColor(colorTextBase, 0.65), + 'textColor3': getAlphaColor(colorTextBase, 0.45), + 'textColor4': getAlphaColor(colorTextBase, 0.25), + + 'fill1': getAlphaColor(colorTextBase, 0.15), + 'fill2': getAlphaColor(colorTextBase, 0.06), + 'fill3': getAlphaColor(colorTextBase, 0.04), + 'fill4': getAlphaColor(colorTextBase, 0.02), + + 'bgColorPage': getSolidColor(colorBgBase, 4), + 'bgColorContainer': getSolidColor(colorBgBase, 0), + 'bgColorElevated': getSolidColor(colorBgBase, 0), + 'bgColorMask': getAlphaColor(colorTextBase, 0.45), + 'bgColorSpotlight': getAlphaColor(colorTextBase, 0.85), + 'bgColorBlur': 'transparent', + + 'borderColor1': getSolidColor(colorBgBase, 15), + 'borderColor2': getSolidColor(colorBgBase, 6) + } +}; + +export function genColorMapToken(token : SeedToken) : UTSJSONObject { + const colorPrimaryBase = token.primaryColor + const colorSuccessBase = token.successColor + const colorWarningBase = token.warningColor + const colorErrorBase = token.errorColor + const colorInfoBase = token.infoColor + const colorBgBase = token.bgColorBase + const colorTextBase = token.textColorBase + + const primaryColors = generateColorPalettes(colorPrimaryBase, 'primaryColor'); + const successColors = generateColorPalettes(colorSuccessBase, 'successColor'); + const warningColors = generateColorPalettes(colorWarningBase, 'warningColor'); + const errorColors = generateColorPalettes(colorErrorBase, 'errorColor'); + const infoColors = generateColorPalettes(colorInfoBase, 'infoColor'); + const neutralColors = generateNeutralColorPalettes(colorBgBase, colorTextBase); + + return UTSJSONObject.assign( + {}, + primaryColors, + successColors, + warningColors, + errorColors, + infoColors, + neutralColors) +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/token/shared.uts b/QXTfront/uni_modules/lime-style/token/shared.uts new file mode 100644 index 0000000..45ed035 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/shared.uts @@ -0,0 +1,24 @@ +import { TinyColor, generate } from '@/uni_modules/lime-color'; +import { LGenerateOptions } from '@/uni_modules/lime-color/utssdk/interface'; + +export const getAlphaColor = (baseColor : string, alpha : number) : string => + new TinyColor(baseColor).setAlpha(alpha).toRgbString(); + +export const getSolidColor = (baseColor : string, brightness : number) : string => { + const instance = new TinyColor(baseColor); + return instance.lighten(brightness).toHexString(); +}; + +export function generateColorPalettes(baseColor : string | null, name : string, theme: string = 'default') : UTSJSONObject { + if (baseColor == null) return {} + const colors = generate(baseColor, { theme } as LGenerateOptions); + const colorPalettes = colors.reduce((prev:UTSJSONObject, color:string, index:number) : UTSJSONObject => { + prev[`${name}${index + 1}`] = color; + return prev + }, {}) + + // 默认为中间色 + colorPalettes[name] = colorPalettes[`${name}${6}`] + return colorPalettes +} + diff --git a/QXTfront/uni_modules/lime-style/token/useThemeMode.uts b/QXTfront/uni_modules/lime-style/token/useThemeMode.uts new file mode 100644 index 0000000..ffd9de4 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/useThemeMode.uts @@ -0,0 +1,126 @@ +// @ts-nocheck +// #ifndef UNI-APP-X +import { type ComputedRef, ref, watch, getCurrentScope, onScopeDispose, computed, reactive } from './vue'; +// #endif + +type ThemeMode = 'light' | 'dark' | 'auto' +const THEME_LOCAL_STORAGE_KEY = 'app-theme-preference' + +let limeThemeId = -1 +const limeThemeMode = ref('auto') +const limeTheme = ref(getTheme()) + + +function setWeb (theme: ThemeMode) { + // #ifdef WEB + const pageHead = document.querySelector(".uni-page-head"); + if(!pageHead) return + if (theme == 'dark') { + pageHead.style.backgroundColor = '#181818' + pageHead.style.color = '' + } else { + pageHead.style.backgroundColor = 'rgb(245, 245, 245)' + pageHead.style.color = 'rgb(0, 0, 0)' + } + // #endif +} + + +export function getTheme(): 'dark' | 'light' { + // #ifndef UNI-APP-X && APP + let mode = uni.getStorageSync(THEME_LOCAL_STORAGE_KEY) + limeThemeMode.value = (mode || 'auto') + const hostTheme = uni.getAppBaseInfo().hostTheme; + return limeThemeMode.value === 'auto' ? (hostTheme || 'light') : limeThemeMode.value + // #endif + + // #ifdef UNI-APP-X && APP + let { osTheme, appTheme } = uni.getSystemInfoSync(); + return appTheme == "auto" ? osTheme! : appTheme! + // #endif + + +} + +// #ifndef UNI-APP-X +let limeThemeCallBack = (result) => { + limeTheme.value = result.theme +}; +// #endif + +export function stop() { + // #ifndef UNI-APP-X + uni.offThemeChange(limeThemeCallBack) + // #endif + // #ifdef UNI-APP-X + // #ifndef UNI-APP-X && APP + uni.offHostThemeChange(limeThemeId) + + // #endif + // #ifdef UNI-APP-X && APP + uni.offAppThemeChange(limeThemeId) + // #endif + // #endif +} + + +// 检查系统主题 +export const checkSystemTheme = () => { + stop() + limeTheme.value = getTheme() + // #ifndef UNI-APP-X + uni.onThemeChange(limeThemeCallBack); + // #endif + // #ifdef UNI-APP-X + // #ifndef UNI-APP-X && APP + limeThemeId = uni.onHostThemeChange((result) => { + limeTheme.value = result.hostTheme + }); + // #endif + // #ifdef UNI-APP-X && APP + limeThemeId = uni.onAppThemeChange((res : AppThemeChangeResult) => { + limeTheme.value = res.appTheme.trim() + }) + // #endif + // #endif +} + + +export const isDarkMode = computed(() => { + return limeTheme.value == "dark"; +}); + +export function setThemeMode(theme: 'dark' | 'light' | 'auto') { + // #ifdef UNI-APP-X && APP + if (limeTheme.value == theme) return; + uni.setAppTheme({ + theme, + success: function (result: SetAppThemeSuccessResult) { + console.log("设置appTheme为"+ result.theme +"成功") + limeTheme.value = result.theme + }, + fail: function (e : IAppThemeFail) { + console.log("设置appTheme为 auto 失败,原因:", e.errMsg) + } + }) + // #endif + // #ifndef UNI-APP-X && APP + limeThemeMode.value = theme + uni.setStorageSync(THEME_LOCAL_STORAGE_KEY, theme) + limeTheme.value = getTheme() + // #endif + // #ifdef WEB + setWeb(limeTheme.value ) + // #endif +} + + +export function toggleTheme() { + setThemeMode(isDarkMode.value ? 'light' : 'dark') +} + +// #ifdef WEB +watch(isDarkMode, ()=>{ + setWeb(limeTheme.value) +}) +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/token/useThemeVars.uts b/QXTfront/uni_modules/lime-style/token/useThemeVars.uts new file mode 100644 index 0000000..d5ceb23 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/useThemeVars.uts @@ -0,0 +1,123 @@ +// @ts-nocheck +import { isDarkMode } from './useThemeMode' +import type { SeedToken } from './interface'; +import { genFontMapToken } from './genFontMapToken'; +import { genSizeMapToken } from './genSizeMapToken'; +import { genColorMapToken as genLightColorMapToken } from './light'; +import { genColorMapToken as genDarkColorMapToken } from './dark'; +import { computed, reactive } from 'vue'; // 或相应的响应式系统 + + + +// #ifndef UNI-APP-X +export type VueApp = any +export type UTSJSONObject = Record +const UTSJSONObject = Object +// #endif + + +// 内部存储的 tokens +type LimeTokens = { + light : UTSJSONObject + dark : UTSJSONObject +} + +// 默认的基础 token +const DEFAULT_SEED_TOKEN : SeedToken = { + primaryColor: '#3283ff' +}; + +export const themeTokenMaps = reactive({ + light: {}, + dark: {}, +}) + + +// 初始化默认 tokens +function initDefaultTokens() { + // Light 主题颜色 + const lightColors = { + white: '#fff', + gray1: '#f3f3f3', + gray2: '#eeeeee', + gray3: '#e7e7e7', + gray4: '#dcdcdc', + gray5: '#c5c5c5', + gray6: '#a6a6a6', + gray7: '#8b8b8b', + gray8: '#777777', + gray9: '#5e5e5e', + gray10: '#4b4b4b', + gray11: '#383838', + gray12: '#2c2c2c', + gray13: '#242424', + gray14: '#181818', + black: '#000', + ...genLightColorMapToken(DEFAULT_SEED_TOKEN) + }; + // Dark 主题颜色 + const darkColors = { + white: '#000', // 在暗黑模式下反转 + gray1: '#181818', + gray2: '#242424', + gray3: '#2c2c2c', + gray4: '#383838', + gray5: '#4b4b4b', + gray6: '#5e5e5e', + gray7: '#777777', + gray8: '#8b8b8b', + gray9: '#a6a6a6', + gray10: '#c5c5c5', + gray11: '#dcdcdc', + gray12: '#e7e7e7', + gray13: '#eeeeee', + gray14: '#f3f3f3', + black: '#fff', // 在暗黑模式下反转 + ...genDarkColorMapToken(DEFAULT_SEED_TOKEN) + }; + + themeTokenMaps.light = UTSJSONObject.assign({}, lightColors, lightColors) + themeTokenMaps.dark = UTSJSONObject.assign({}, darkColors, darkColors) +} + +initDefaultTokens(); + +// 导出的 themeTokens 是计算属性,自动返回当前主题的 tokens +export const themeTokens = computed(():UTSJSONObject => { + return isDarkMode.value ? themeTokenMaps.dark : themeTokenMaps.light; +}); + + + +export function useThemeToken(token : SeedToken | null = null) { + if (token != null) { + const lightColors = genLightColorMapToken(token!); + const darkColors = genDarkColorMapToken(token!); + + // 只有在提供了相关属性时才重新生成 fonts 和 sizes + const fonts = genFontMapToken(token!.fontSize) + const sizes = genSizeMapToken(token!.sizeUnit, token.sizeStep) + + themeTokenMaps.light = UTSJSONObject.assign({}, themeTokenMaps.light, lightColors, fonts, sizes) + themeTokenMaps.dark = UTSJSONObject.assign({}, themeTokenMaps.dark, darkColors, fonts, sizes) + } +} + +export function useThemeVars(options : UTSJSONObject | null = null) { + if (options != null) { + const currentTheme = isDarkMode.value ? themeTokenMaps.dark : themeTokenMaps.light; + + // #ifdef UNI-APP-X && APP + options.toMap().forEach((value, key) => { + currentTheme.set(key, value); + }); + // #endif + + // #ifndef UNI-APP-X && APP + Object.entries(options).forEach(([key, value]) => { + // currentTheme.set(key, value); + currentTheme[key] = value + }); + // #endif + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/token/vue.ts b/QXTfront/uni_modules/lime-style/token/vue.ts new file mode 100644 index 0000000..d8ded83 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/token/vue.ts @@ -0,0 +1,13 @@ +// @ts-nocheck +// #ifndef VUE3 +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' +Vue.use(VueCompositionAPI) +export * from '@vue/composition-api' +// #endif +// #ifdef VUE3 +export * from 'vue'; +// #endif +// #ifdef APP-IOS || APP-ANDROID +export type ComputedRef = ComputedRefImpl +// #endif \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-style/var.scss b/QXTfront/uni_modules/lime-style/var.scss new file mode 100644 index 0000000..884c268 --- /dev/null +++ b/QXTfront/uni_modules/lime-style/var.scss @@ -0,0 +1,72 @@ +@import './mixins/create.scss'; +// 公共前缀 +$prefix: l; + +// Spacer +$spacer: create-var('spacer', 16px); // base +$spacer-tn: create-var('spacer-tn', 4px); // Tiny +$spacer-xs: create-var('spacer-xs', 8px); // Extra Small +$spacer-sm: create-var('spacer-sm', 12px); // Small +$spacer-md: create-var('spacer-md', 24px); // Medium +$spacer-lg: create-var('spacer-lg', 32px); // Large +$spacer-xl: create-var('spacer-xl', 48px); // Extra Large +$spacer-hg: create-var('spacer-hg', 80px); // Huge //Ultra Big + +// Font 官方建议字体不跟随页面变化 +// $font-size: create-var('font-size', 28rpx); +// $font-size-xs: create-var('font-size-xs', 20rpx); +// $font-size-sm: create-var('font-size-sm', 24rpx); +// $font-size-md: create-var('font-size-md', 16px); +// $font-size-lg: create-var('font-size-lg', 40rpx); +// $font-size-xl: create-var('font-size-xl', 72rpx); +$font-size: create-var('font-size', 14px); +$font-size-xs: create-var('font-size-xs', 10px); +$font-size-sm: create-var('font-size-sm', 12px); +$font-size-md: create-var('font-size-md', 16px); +$font-size-lg: create-var('font-size-lg',20px); +$font-size-xl: create-var('font-size-xl', 36px); + +$font-size-heading-1: create-var('font-size-heading-1', 38px); +$font-size-heading-2: create-var('font-size-heading-2', 30px); +$font-size-heading-3: create-var('font-size-heading-3', 24px); +$font-size-heading-4: create-var('font-size-heading-4', 20px); +$font-size-heading-5: create-var('font-size-heading-5', 16px); + + +$font-family: create-var('font-family', PingFang SC, Microsoft YaHei, Arial Regular); // 字体-磅数-常规 +$font-family-md: create-var('font-family-md', PingFang SC, Microsoft YaHei, Arial Medium); // 字体-磅数-粗体 + + +// 行高 +$line-height: create-var('line-height', 1.5714285714285714); +$line-height-sm: create-var('line-height-sm', 1.6666666666666667); +$line-height-md: create-var('line-height-lg', 1.5); +$line-height-lg: create-var('line-height-lg', 1.4); + +$line-height-heading-1: create-var('line-height-heading-1', 1.2105263157894737); +$line-height-heading-2: create-var('line-height-heading-2', 1.2666666666666666); +$line-height-heading-3: create-var('line-height-heading-3', 1.3333333333333333); +$line-height-heading-4: create-var('line-height-heading-4', 1.4); +$line-height-heading-5: create-var('line-height-heading-5', 1.5); + + +// 圆角 +$border-radius: create-var('border-radius', 6px); +$border-radius-xs: create-var('border-radius-xs', 2px); +$border-radius-sm: create-var('border-radius-sm', 3px); +$border-radius-md: create-var('border-radius-md', 6px); +$border-radius-lg: create-var('border-radius-lg', 9px); +$border-radius-xl: create-var('border-radius-xl', 12px); +$border-radius-hg: create-var('border-radius-hg', 999px); +// $border-radius-circle: var(--l-border-radius-circle, 50%); + + +// 动画 +$anim-time-fn-easing: create-var('anim-time-fn-easing', cubic-bezier(0.38, 0, 0.24, 1)); +$anim-time-fn-ease-out: create-var('anim-time-fn-ease-out', cubic-bezier(0, 0, 0.15, 1)); +$anim-time-fn-ease-in: create-var('anim-time-fn-ease-in', cubic-bezier(0.82, 0, 1, 0.9)); +$anim-duration-base: create-var('anim-duration-base', 0.2s); +$anim-duration-moderate: create-var('anim-duration-moderate', 0.24s); +$anim-duration-slow: create-var('anim-duration-slow', 0.28s); + + diff --git a/QXTfront/uni_modules/lime-svg/changelog.md b/QXTfront/uni_modules/lime-svg/changelog.md new file mode 100644 index 0000000..b31c83d --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/changelog.md @@ -0,0 +1,47 @@ +## 0.2.4(2025-10-11) +- fix: 修复鸿蒙不显示问题 +## 0.2.3(2025-09-22) +- feat: 针对hbx4.81优化 +## 0.2.2(2025-07-15) +- fix:修复vue2报错问题 +## 0.2.0(2025-07-08) +- fix:修复uniapp支付宝小程序报错问题 +## 0.1.9(2025-05-23) +- fix:修复安卓部分base64不显示的问题 +## 0.1.8(2025-05-13) +- fix:删除ios config多余代码 +## 0.1.7(2025-04-21) +- feat:兼容uniappx 鸿蒙next +## 0.1.6(2025-04-04) +- fix:修复安卓color不支持rgba的问题 +## 0.1.5(2025-03-12) +- fix:修复安卓src变化没有重新渲染的问题 +## 0.1.4(2025-02-14) +- fix:更新事件 +## 0.1.3(2025-01-23) +- fix:网图改用downloadFile方式实现 +## 0.1.2(2025-01-04) +- chore:更新文档 +## 0.1.1(2024-12-09) +- chore:更新文档 +## 0.1.0(2024-12-09) +- fix:修复因正则问题导致其它节点不显示(-width) +- feat: 兼容uniappx 微信小程序 +## 0.0.9(2024-08-06) +- fix:修复因正则问题导致不显示(-width) +## 0.0.8(2024-08-05) +- fix:修复安卓本地不显示问题 +## 0.0.7(2024-07-22) +- chore:更新文档 +## 0.0.6(2024-07-22) +- chore:更新文档 +## 0.0.5(2024-07-21) +- chore:更新文档 +## 0.0.3(2024-07-12) +- fix:修复 缺少 svgDataURLPrefix +## 0.0.2(2024-07-12) +- chore:更新文档 +## 0.0.1(2024-06-03) +- init +## 0.01(2023-12-06) +测试 diff --git a/QXTfront/uni_modules/lime-svg/components/l-svg/l-svg.uvue b/QXTfront/uni_modules/lime-svg/components/l-svg/l-svg.uvue new file mode 100644 index 0000000..861a6a0 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/components/l-svg/l-svg.uvue @@ -0,0 +1,324 @@ + + + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/components/l-svg/l-svg.vue b/QXTfront/uni_modules/lime-svg/components/l-svg/l-svg.vue new file mode 100644 index 0000000..bb30d99 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/components/l-svg/l-svg.vue @@ -0,0 +1,244 @@ + + + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/components/l-svg/props.ts b/QXTfront/uni_modules/lime-svg/components/l-svg/props.ts new file mode 100644 index 0000000..334f6e8 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/components/l-svg/props.ts @@ -0,0 +1,18 @@ +export default { + src: { + type: String, + default: '' + }, + color: { + type: String, + default: '' + }, + web: { + type: Boolean, + default: false + }, + inherit: { + type: Boolean, + default: false + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/components/l-svg/type.ts b/QXTfront/uni_modules/lime-svg/components/l-svg/type.ts new file mode 100644 index 0000000..39554a4 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/components/l-svg/type.ts @@ -0,0 +1,6 @@ +export interface LSvpProps { + src: string; + color: string; + web: boolean; + inherit: boolean; +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/components/l-svg/utils.ts b/QXTfront/uni_modules/lime-svg/components/l-svg/utils.ts new file mode 100644 index 0000000..2e99fde --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/components/l-svg/utils.ts @@ -0,0 +1,70 @@ +// @ts-nocheck +// #ifdef APP-ANDROID || APP-IOS +// import { fileToDataURL } from '@/uni_modules/lime-file-utils' +// #endif + + +/** + * 小程序把路径转成base64 + * @param {string} path + * @return 表示 SVG 的 Data URL。 + */ +export function pathToDataUrl(path : string) : Promise { + + return new Promise((resolve, reject) => { + // #ifdef MP + uni.getFileSystemManager().readFile({ + filePath: path, + encoding: 'base64', + success: (res) => { + resolve(`data:image/svg+xml;base64,${res.data}`) + }, + fail: (error) => { + console.error({ error, path }) + reject(error) + } + }) + // #endif + // #ifdef APP-ANDROID || APP-IOS + // const url = fileToDataURL(path) + const url = path + if(url == null) { + reject('路径错误') + } + resolve(url!.replace(/\s+/g,'')) + // #endif + // #ifdef APP-NVUE + let localFilePath = plus.io.convertAbsoluteFileSystem(path) + if (localFilePath == path) { + localFilePath = '_www/' + path.slice(1) + } + plus.io.resolveLocalFileSystemURL(localFilePath, (entry) => { + entry.file((file : any) => { + const fileReader = new plus.io.FileReader() + fileReader.onload = (data) => { + resolve(data.target.result) + } + fileReader.onerror = (error) => { + console.error({ error, path }) + reject(error) + } + fileReader.readAsDataURL(file) + }, reject) + }, reject) + // #endif + // #ifndef APP-ANDROID || APP-IOS || MP || APP-NVUE + reject('不支持') + // #endif + }) + +} + +/** + * 将 SVG 字符串转换为 Data URL。 + * @param {string} svg - 要转换的 SVG 字符串。 + * @returns {string} 表示 SVG 的 Data URL。 + */ +export function svgToDataUrl(svgString : string) : string { + const encodedSvg = encodeURIComponent(svgString)!.replace(/\+/g, '%20'); + return `data:image/svg+xml,${encodedSvg}` +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/components/lime-svg/lime-svg.uvue b/QXTfront/uni_modules/lime-svg/components/lime-svg/lime-svg.uvue new file mode 100644 index 0000000..2a920df --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/components/lime-svg/lime-svg.uvue @@ -0,0 +1,138 @@ + + + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/components/lime-svg/lime-svg.vue b/QXTfront/uni_modules/lime-svg/components/lime-svg/lime-svg.vue new file mode 100644 index 0000000..a24ae77 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/components/lime-svg/lime-svg.vue @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/encrypt b/QXTfront/uni_modules/lime-svg/encrypt new file mode 100644 index 0000000..d7174b5 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/encrypt @@ -0,0 +1 @@ +hMN鑖rﴹ'j7limvj5pCm_„[OcQ*`T9v4w4^rL{>^gMV0Jp? : 7! ПM8DI$ \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/hybrid/html/index.html b/QXTfront/uni_modules/lime-svg/hybrid/html/index.html new file mode 100644 index 0000000..52c9968 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/hybrid/html/index.html @@ -0,0 +1,178 @@ + + + + + + + lime-svg + + + +

+ +
+ + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/hybrid/html/uni.webview.1.5.5.js b/QXTfront/uni_modules/lime-svg/hybrid/html/uni.webview.1.5.5.js new file mode 100644 index 0000000..2c9b980 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/hybrid/html/uni.webview.1.5.5.js @@ -0,0 +1 @@ +!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function i(e,i){return n.call(e,i)}var t=[];function o(){return window.__dcloud_weex_postMessage||window.__dcloud_weex_}function a(){return window.__uniapp_x_postMessage||window.__uniapp_x_}var r=function(e,n){var i={options:{timestamp:+new Date},name:e,arg:n};if(a()){if("postMessage"===e){var r={data:n};return window.__uniapp_x_postMessage?window.__uniapp_x_postMessage(r):window.__uniapp_x_.postMessage(JSON.stringify(r))}var d={type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}};window.__uniapp_x_postMessage?window.__uniapp_x_postMessageToService(d):window.__uniapp_x_.postMessageToService(JSON.stringify(d))}else if(o()){if("postMessage"===e){var s={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(s):window.__dcloud_weex_.postMessage(JSON.stringify(s))}var w={type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(w):window.__dcloud_weex_.postMessageToService(JSON.stringify(w))}else{if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:i,pageId:""},"*");if(0===t.length){var u=plus.webview.currentWebview();if(!u)throw new Error("plus.webview.currentWebview() is undefined");var g=u.parent(),v="";v=g?g.id:u.id,t.push(v)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}},"__uniapp__service");else{var c=JSON.stringify(i);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(c,",").concat(JSON.stringify(t),");"))}}},d={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;r("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("redirectTo",{url:encodeURI(n)})},getEnv:function(e){a()?e({uvue:!0}):o()?e({nvue:!0}):window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};r("postMessage",e.data||{})}},s=/uni-app/i.test(navigator.userAgent),w=/Html5Plus/i.test(navigator.userAgent),u=/complete|loaded|interactive/;var g=window.my&&navigator.userAgent.indexOf(["t","n","e","i","l","C","y","a","p","i","l","A"].reverse().join(""))>-1;var v=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var _=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var m=window.qa&&/quickapp/i.test(navigator.userAgent);var f=window.ks&&window.ks.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var l=window.tt&&window.tt.miniProgram&&/Lark|Feishu/i.test(navigator.userAgent);var E=window.jd&&window.jd.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var x=window.xhs&&window.xhs.miniProgram&&/xhsminiapp/i.test(navigator.userAgent);for(var S,h=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},y=[function(e){if(s||w)return window.__uniapp_x_postMessage||window.__uniapp_x_||window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&u.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),d},function(e){if(_)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(g){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(v)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(p)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(m){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(f)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.ks.miniProgram},function(e){if(l)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(E)return window.JDJSBridgeReady&&window.JDJSBridgeReady.invoke?setTimeout(e,0):document.addEventListener("JDJSBridgeReady",e),window.jd.miniProgram},function(e){if(x)return window.xhs.miniProgram},function(e){return document.addEventListener("DOMContentLoaded",e),d}],M=0;M + + + + + + + + + + +``` + +### 颜色设置 +通过设置`color`来改变svg图标颜色,注意:只支持纯色图标,多色图标无效。 + +```html + + + + + +``` + + +## 快速预览 +导入插件后,可以直接使用以下标签查看演示效果: + +```html + + +``` + +## 插件标签说明 +- 默认 `l-svg` 为组件标签 +- 默认 `lime-svg` 为演示标签 + +## Vue2使用说明 +插件使用了`composition-api`,如果你希望在Vue2中使用,请按官方教程[vue-composition-api](https://uniapp.dcloud.net.cn/tutorial/vue-composition-api.html)配置。 + +关键代码是在main.js中的Vue2部分添加以下代码: + +```js +// vue2 +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' +Vue.use(VueCompositionAPI) +``` + +## API文档 + +### Props + +| 属性名 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| src | SVG图标的源,支持本地路径、网络URL、SVG源文本和Base64 | string | - | +| color | 图标颜色,仅对纯色图标有效 | string | - | +| web | 是否使用WebView渲染,支持动画效果 | boolean | `false` | +| width | 图标宽度 | string \| number | - | +| height | 图标高度 | string \| number | - | + +### Events + +| 事件名 | 说明 | 回调参数 | +| --- | --- | --- | +| click | 点击图标时触发 | event: Event | +| load | 图标加载完成时触发 | - | +| error | 图标加载失败时触发 | error: Error | + +## 支持与赞赏 + +如果你觉得本插件解决了你的问题,可以考虑支持作者: + +| 支付宝赞助 | 微信赞助 | +|------------|------------| +| ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png) | ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png) | \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/readme_old.md b/QXTfront/uni_modules/lime-svg/readme_old.md new file mode 100644 index 0000000..080a4f8 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/readme_old.md @@ -0,0 +1,68 @@ +# lime-svg 矢量图标 +一款UTS实现的原生图标插件,支持uniapp/uniappx + +## 文档 + 🚀 [svg【站点1】](https://limex.qcoon.cn/components/svg.html) + 🌍 [svg【站点2】](https://limeui.netlify.app/components/svg.html) + 🔥 [svg【站点3】](https://limeui.familyzone.top/components/svg.html) + + + +## 安装 +插件市场导入,由于普通授权版无法自定义基座。请如需使用请购买源码版。 + +## 代码演示 +安卓和ios提供基于`原生插件`和`webview`两渲染机制,如果使用`原生插件`则需要`自定义基座`再使用. +原生插件实现的不支持动画,如果需要动画请选择`webview` + +### 路径 +通过设置`src`来加载svg图标,支持本地\网络\源文本\base64等方式 + +```html + + + + +``` + + +### 颜色 +通过设置`color`来改变svg图标颜色,只支持svg是纯色图标,多色无效. + +```html + + +``` + +### webview +通过设置`:web="true"`使用`webview`渲染 + +```html + + +``` + + + +### 插件标签 +默认 l-svg 为 component +默认 lime-svg 为 demo + +### Vue2使用 +插件使用了`composition-api`, 如果你希望在vue2中使用请按官方的教程[vue-composition-api](https://uniapp.dcloud.net.cn/tutorial/vue-composition-api.html)配置 +关键代码是: 在main.js中 在vue2部分加上这一段即可. + +```js +// vue2 +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' +Vue.use(VueCompositionAPI) +``` + + + +## 打赏 + +如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。 +![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png) +![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png) \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-android/AndroidManifest.xml b/QXTfront/uni_modules/lime-svg/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..c754a55 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-android/config.json b/QXTfront/uni_modules/lime-svg/utssdk/app-android/config.json new file mode 100644 index 0000000..8d16328 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/utssdk/app-android/config.json @@ -0,0 +1,6 @@ +{ + "minSdkVersion": "21", + "dependencies": [ + "com.caverock:androidsvg:1.4" + ] +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-android/fileUtils.uts b/QXTfront/uni_modules/lime-svg/utssdk/app-android/fileUtils.uts new file mode 100644 index 0000000000000000000000000000000000000000..eb37ce146f4173ec250097fba40dbb402ee5df54 GIT binary patch literal 3264 zcmV;x3_tUk&!1W3u8(x4ADUpwD916*sQo;i1j@r%VRowk;&oY;3Sc{%P3$Q z;E-`PQkwD(I_CCyHDtllPqyw|tOLHM`W>ksn=l(Z4?B(rYA?KI@}cq{LAMS+suCq{ zT29U(eWtWRBL5A@3lKZx7{oRi>3|?*al|$gQsh?aR4r;&K57vJ-@d-bP8>z=uBxmuzI%evT(yR>X*$I@=>d-35lZXo+6r)mvu+v?>DH(5Yke%=&{CWOgy9_!e3x$1I;c8^!hq5u zRkEK)4eqP$S3pb3u{{Q{8xz@j6ea%iIN%qplk|p^{nerf+WC%Ft!(O~D`2WI1;E<75%36l;i(H3klF7(tvVMV?J{);?TL^!UOA>EbN>LS3V zfmGB{D?Yb(2P<$9iTxaC-6DppiXA#5ScR6f?h4s@W+@4R0ISVO+(AL@1E|# zS=G$Yx!JEU;qnBJ7!2$av;{$nAuoy+OG)FbE93l!+A#qtr{J|$*YmLsfdvj1Vldrf z`g%HoW{a7Hxr)D0Dmob|;~TL}6Z3NQt1>&~5w4H~*F$A?+BYyR#4_oz;k8qPF?@c_ zJT-gz0W8DZN0D}>6b5v2`n#8G@j%o3E7*NxwE4ui`ADf$v_O8!+2Bi<$ejrfb$t>F z>N47=sw|5dXs&!rk9auMttC|Q3#cq^&X zDR{ZxBm-T(w=OU>Pjd%7WJR0yd5tJRcpr-v!?M)v8nWIMg1cGXxfFCPt#dFYTknB_ zaiEa~qDYMJA-zy;?4&71zy+UQ3@FdII{jZLkhdC}O-NBTKmcqBmjw;7VYQ)IjIXig z(lLY!ov;PvaF6xjQ-kOQm*yiYg|1VYzoNX_pFcKs ze(w9DSXhH-jDfyc!(uqe%mPp>yNo;Vtz)uY8xs-^;4c?x9=I|p|371})q4FOF0kyb zLe5$!Nnd^#szd)GXETdzwc=RIfPD7TfRBTjmHD@znRcl(y_!+pcDAV6OJ2jE{p7SN z#RUedC%5EsP=o>8AIpeCT-Eoswn9@dyaQwKcw%oSe1u(9I$X}qr`KW^q5DImtQKb~ ziz0^obF)3sJwAXecTkAGd{t-i0pRdTPJKsia8*{s-6?&43r(LG4RBMmS{rq!d&+I^ z{_>ebMV;+=JFbsb+2eIRBGWbs<&`-HILMXD|N6>XDG0lc80>esZ=cKBG9GTps56yr zQ?+~3Kwq?9^DZAZv_&f%p7J84Q@mvaReF*+r3rBQ5XX z*V4A*Nq~+4;+()I7!w_qM*?clC0fPdJZFUUX4f*31;WYOY~q1 z{Cib<3%eJ)nG}>kSM{MTXB9yycXl}1O^^nsf=VjQIQH9vOuspLpoyjP%X3Kax20vr z$MUC^JL|;F*^k#Ila~)6b5+FG^u!HJz(5`nj7-YPL zi*0!oA{2vWp(vU%Jgn(e>XA0*q2K63SGCACn z$GHIY)Nfi5S)$5l?(S)GcV!d&u&5g1r1U~2jgbn9KCWL z1rjaMG99QO#|Fy_%o!8cA$B1;##Vx;xe(omh}AMoWUz-BAF8IfSs|Q}RH*+l^skv( zmU1^Sp(}_#hi#;4U??vWYbgP?#z4gs+KD&$aO`^e;P+nX77llw7*IhBh0s+~>XfD7g8SPTpWrnVQTE`pP)inUd2b3y za@T=49MhDzlC3B|$;*?2j#zH~g%)By*?twj$lQjtnheBmToa;MaG~w)FSihJ7@uUB z16a}9dR{@CfE79;(qHaWq-p;EVSf5r`s5(PR-lAu7c}jx8@B3Fho*98%HD{-mrisnp!WBq#8sn{0`_hI1+2^k;VbC-<_v#{vaaBTG23q9 zVjpQ^fc7LOa5&aAR9`#G+WOc8W$D@G4%+u|#CWnk$;(vAH#DT=k)L+qsq*#lL^C|J y?LbF8GZS*n58>%raqn|nH`CMTGms~EWDuP0AHrQYff*_XuY^R`b31krY@08(-bL8} literal 0 HcmV?d00001 diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-android/index.uts b/QXTfront/uni_modules/lime-svg/utssdk/app-android/index.uts new file mode 100644 index 0000000000000000000000000000000000000000..ee92a450e748af41c743375c95ee4475898e39d4 GIT binary patch literal 2896 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 literal 0 HcmV?d00001 diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-android/utils.uts b/QXTfront/uni_modules/lime-svg/utssdk/app-android/utils.uts new file mode 100644 index 0000000000000000000000000000000000000000..e39ac158679ce8a8281ea00cc501b34abc973dc4 GIT binary patch literal 6864 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 Kph3=@{WDi?Z&yqJ literal 0 HcmV?d00001 diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-harmony/builder.ets b/QXTfront/uni_modules/lime-svg/utssdk/app-harmony/builder.ets new file mode 100644 index 0000000..25abfc6 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/utssdk/app-harmony/builder.ets @@ -0,0 +1,36 @@ +// import { Color } from '@ohos.arkui'; +@Builder +export function buildImage(params: ESObject) { + if(params.color) { + Image(params.src) + .width('100%') + .height('100%') + .objectFit(ImageFit.Contain) + // .fillColor(Color.Blue) + .fillColor(params.color) + // colorFilter只对位图生效 + .colorFilter(params.colorFilter) + // .colorFilter( + // [1, 0, 0, 0, 1, + // 0, 1, 0, 0, 1, + // 0, 0, 1, 0, 0, + // 0, 0, 0, 1, 0]) + .onComplete((event)=>{ + params.onComplete(event) + }) + .onError((error) =>{ + params.onError(error.message) + }) + } else { + Image(params.src) + .width('100%') + .height('100%') + .objectFit(ImageFit.Contain) + .onComplete((event)=>{ + params.onComplete(event) + }) + .onError((error) =>{ + params.onError(error.message) + }) + } +} diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-harmony/css-color-names.uts b/QXTfront/uni_modules/lime-svg/utssdk/app-harmony/css-color-names.uts new file mode 100644 index 0000000000000000000000000000000000000000..c1a830ba772fe16228a486521b7e5a1f9ed19074 GIT binary patch literal 4336 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 ez+Ei4%IVy`*sUH|Y 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 literal 0 HcmV?d00001 diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-harmony/utils.uts b/QXTfront/uni_modules/lime-svg/utssdk/app-harmony/utils.uts new file mode 100644 index 0000000000000000000000000000000000000000..7279418f041e9539a495650ca8370bde85cd1f34 GIT binary patch literal 960 zcmV;x13&z}epRffV6HR8=qXnV$>e0(TE@1`3MpGi;dQ|NOYi&IlmI$Dl6-8!;F7dn z091abwfzOV5m~Q&!0Rhx`GeaeRWOR)?%b@!_nur3WRli4bj`;#k#UF=#u4V3JF_ z5U@|_D8mfxhPxALo8oFt-7u%+e_v}I~poqonF>q>rDSvGqD>J z?g=3#ZuWX;JsYQ?r!lFa<*U=uNCi!s$aoQP(q5r9zk%`O3CQyNy@nE~B$2y9;uM@I z6DOwVkqMbKFCq_%m}H7!oB!Pv4)R6anWzu2pm5G4HZ^$fHC`!k1TF3C*3lp6!vLmN2cY z+o_JmlA|q2=sJy`pDf6*QLr_-&VQn i=*}5e4lh~5Qv5VKztIx;1mch=$KE)F4CUN>bzw-@INXK+ literal 0 HcmV?d00001 diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-ios/Resources/_CodeSignature/CodeResources b/QXTfront/uni_modules/lime-svg/utssdk/app-ios/Resources/_CodeSignature/CodeResources new file mode 100644 index 0000000..0034bf2 --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/utssdk/app-ios/Resources/_CodeSignature/CodeResources @@ -0,0 +1,212 @@ + + + + + files + + Headers/unimoduleLimeSvg-Swift.h + + ZAFtq3SpJcrTktt5ty6bKx5SjbE= + + Headers/unimoduleLimeSvg.h + + FH2SRnQAHIO8AbDZPa5/Bz/CcdA= + + Info.plist + + SECVeyxZywH2skYEys8lD82L9ic= + + Modules/module.modulemap + + IhA8PKd525VdS98DEH+6b9Clqhc= + + Modules/unimoduleLimeSvg.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + 2rh6/UupufPsMttXIwGPNGMGVg4= + + Modules/unimoduleLimeSvg.swiftmodule/x86_64-apple-ios-simulator.abi.json + + 7+rVgNvBGQmcD7+gEA3uN26z3qw= + + Modules/unimoduleLimeSvg.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + xX0K3FhLkkWFdXcCvT26ocOD9VM= + + Modules/unimoduleLimeSvg.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + 5P+FoAZLOwzDALC1B7KcS2N9OCU= + + Modules/unimoduleLimeSvg.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + xX0K3FhLkkWFdXcCvT26ocOD9VM= + + Modules/unimoduleLimeSvg.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + nW2LF82smSEfb78mCxHAh+1aJS4= + + config.json + + jo/qJhWkc5CQPkmEfWKkUS9c85Q= + + + files2 + + Headers/unimoduleLimeSvg-Swift.h + + hash2 + + Chw0MoUhe/BIGhvhiOOhZARBTWfalvswZXAeTn3tCWU= + + + Headers/unimoduleLimeSvg.h + + hash2 + + XAsze1m7Z4PhyI2gj+RafZVS4xyqWjgvqraTawdVPMY= + + + Modules/module.modulemap + + hash2 + + yItRRdWTDBHEqWXkBQ66ykO15PDNTn29XmtZY5MeesA= + + + Modules/unimoduleLimeSvg.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + hash2 + + /pkEYhxq1FG3Lk48QXqm4NLoak4nZhYwttka0dWlcAs= + + + Modules/unimoduleLimeSvg.swiftmodule/x86_64-apple-ios-simulator.abi.json + + hash2 + + UKJzsijDj8RUY3ZNrJvm0x8i27BkTuvAH2Uw1AlwG8Y= + + + Modules/unimoduleLimeSvg.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + hash2 + + WpeX9z6CL/3MC/eIryWdQPudnYw3zcAsfE5ITMzxodc= + + + Modules/unimoduleLimeSvg.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + hash2 + + X+5lpMhExxBrexdeBfZ+LaDMBrqAOgDKlXQ0vxQ3waI= + + + Modules/unimoduleLimeSvg.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + hash2 + + WpeX9z6CL/3MC/eIryWdQPudnYw3zcAsfE5ITMzxodc= + + + Modules/unimoduleLimeSvg.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + hash2 + + 8hBivD/bTJBgq0Fw6Zb8NJ6x1kh6HBLhtF7rYGuaSbw= + + + config.json + + hash2 + + Fo/X5AmNDDUqJ4o8kFF60K9pTDiQEafR9Rzvsmrg4Mk= + + + + rules + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-ios/config.json b/QXTfront/uni_modules/lime-svg/utssdk/app-ios/config.json new file mode 100644 index 0000000..8b70acb --- /dev/null +++ b/QXTfront/uni_modules/lime-svg/utssdk/app-ios/config.json @@ -0,0 +1,7 @@ +{ + "deploymentTarget": "11", + "dependencies-pods": [{ + "name": "SVGKit", + "version": "3.0.0" + }] +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-ios/fileUtils.uts b/QXTfront/uni_modules/lime-svg/utssdk/app-ios/fileUtils.uts new file mode 100644 index 0000000000000000000000000000000000000000..f28734fa5d353502f8f4650ad9687322262e7ea3 GIT binary patch literal 1120 zcmV-m1fTm1QXLZoxe1D+ieZ0e|6)-v1OY-}{Ixv7e$M#eV@LADRl&Sb;|5rb;17~?60njS>|a4jufjc;!4(D5)!PF?wa zRG{rg0z|qz1{rHOk$@B*nn5o=tqzp{NIw5aW1q89$=`Zm>q z4R(~8(7YC6P}U@zV>XF3X_qT_dJg!c^R9;_+SE=CtEM0r;4Pd)HB(c1<$R%uo(4g5029A37qNn5V_G7@T?5;4qd(wS70gx%@ z8P~i<1Ea=#iw70OI5xFt&`{pL8&77K0(VA!`q|%HsxZJazkDUs{q@a1_FkJL@cb6s zvtNJ+NRsgG#c5B{1gAGMBx5lUI1WF!6<@lwGzURatI@79?TWO3?7!Zc0RCumTQjX& zqC5&ID17yIA>*6u46UF`tR7s)Ry1WCsg*Rad|2ZPrm%46kHktaHfHc2E*WRC7Em8K zk7`acV5TL9ZjsPXp($-ES@Xv2Lq>B(VR4bk_QUX6;*5Vt90>&Wk9ZO?9>V79ty})V z{qlVLu(eBKvHCGCkpIV~-1MF}_J>p8`@J`;_Bqp?F?lwuvW$0{w$y`eqEt3!y+mh* z*S^x_Ie#cSUZO95QAQ@h+Wb!~0D9|OaT>)Zv;*lfQW4d;Bsre~T#3&O(ba3Aj#v}D zhQ7;*B~&+_z)2)DbWXxi`Bmgo`smMUJ`gARgic z$RkQY6|47rJersczcRb7!-g*5%LuxC{Xs1K#bG%30O literal 0 HcmV?d00001 diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-ios/index.uts b/QXTfront/uni_modules/lime-svg/utssdk/app-ios/index.uts new file mode 100644 index 0000000000000000000000000000000000000000..38fc852b5eed4857f94fe606da3283dce5909130 GIT binary patch literal 2704 zcmV;B3UBpn6=cc4ftY{}f$9l9@l{o(?}z45$OSR3)uokORD$ zQ|0osw~=(MP=zS-c0`>PArbvhsST(tRwFwC(G$Q% z;YpEnHm}3-oUb*3lUKUKN+K8{g{`T7&0ORp;9?cAltF${H(1Q+>is{jV_Bc zRW-P4wA&l1u78IH(-L3OPQZWs=6wk>+4mV((@8rO<+ds2-O8DFQJWye9biyI8HFZ2 zT7|C0{s%EVAJ!uaM$;8u>Ui_x96e}Kj`Hn&^M3pkjY1DTCjbbGgzftTv&ELmgBqdJ za``MVdY;j3vW{>C8KKGx3OuAVu^)bzFpfcHE)OiAH{DLaYoc37oQMt8e{@e1Y#3at z)glB1kW9j3O(KQ8*`wtPTn=)|eVaVuPMd?I8!8hhm+4EW@ z`YDAHQG3Ns?{pd7J@x2-j;FXtJM>^uIUy{ zjN!JoM5S0U$qN=xi!gJdrjPx zi6oG00BZkDLi`0O1WfsI#dl6GaHdn}#Eqq$N7$#sL?+K%9Y&@vf3!a!wi3S`$kz@& zCUMg8)nTsX7QCAyY0QdYdirZ4RkC?n?$eGak29k?A)in3vvqFEV7!uyR*$w%g}pKx z#~`SRt1P;7f=%ilEXH_Uot`Z4D};mX(e_eGBuRHM!)Q9ZG{h*qGLVHk0Wy)HIXscEVh}XmY|;^g9^ob2DGrGqjwOv`i-4NFkjmq zclr$^FcguHg3A4Nl?{+LoEGPL>GeB|O^Fe0EY+n50N9H#B|fhg50Z67F%VMt=&Z)P zqrp07G(Z-kZKYbo%I0MQ-n)&2HW)ov_PRmV-@xd)-@fwz$T!y2K7^$3CZ!fSBvi1> z^bw4t?-`v+rs;uoec1=^u7N@M1;a@sS`W4fpNYZ#6f<4KhPbWW{hh_97Sd`b>MgrQ zga}?4srXhzzT8X~v9|uR`zYUj>IGb=%u1x)UFG6}E1J9Rni8Veg|MkF1dRDZZjm4s zQ_feu#x)*_?O)%dsNys+=*dL*vbymSx6T~Or4t_Stsg-71j;|Hdz0*yOL2$KSaMSB zCZ0)2C|gwTv5ukeJOigG(84KeA?5J3?A$teWxi6%TdcMS5F&qd!YexSaH>^JY9~~3 z>o0k-c6}sVUTr1)`lLv>%R>66SeMnmK2*y%=U(AU|v69X7RbmoRc z6w(*Gg(26^bjrODT!)j>GaiLXR;tUe$NFNq{U(N9x&I(43R1Y?TdEJp-UA&T_!S1~ z*8{1)>~J-(QneD1-c|>l3B_4GyGj4+l~q|KD+4Gk9Te>2sL}HB9v~_y*za4f0S)b@B&}%Qs9T zYu1h(Nn`2=XZ&mz0J}5itE*bPrM2R~TkR^aHb}6z6&91J38QY=UbMXNq^*GNPL2VV zK;X|)O0pS?&}x%6HQZFtIz(t$`Ms5Ufb(o>uZ6{$`y{i29`Fl-*^HboB1WT&En;V139JySClkbXjfRc zDLUPp%86xV_7stNK_6j7HOG9o1WKNyfJe*w^C(B)ko4ZqdHtY-$${@9Q1b87&i>#| zIB8Q#9kF(_wf3eFAK0$Sn z1X6+*N78t$gT!6u$kYYO=2UiOSKc+MF!-S|-kAavDS-+;Uz$5=H_vg8b+V0FS%i9} z{y6(TwtRP^Y5YLW`cPDu$l-|3nje`uucn+0A;?hhm1M$2FIk%&jeuoU?-(E zZH2SqHhd$!x*&3bJ(el}ZTHEOm_d&Hr@)#WWzTh*H2&{zg7xof_c@tr`XR~u2YirG zq@)J$&xWvyA;0s2B5~K$tXZnN@-JkzxnJFbu5V?po}O@F%Hu6QZ!u2E@`3-@u>O`S zN)X=(wJXL9}s7_sAwYz2@A5+*Fkrz|Cpv21MB6`%jnP!GYJ${cN?wm$El?P zx|J*lV>;)e?$ujg|+p@l)qxkQwmlZ?0ZLMeXxZ`{S<#eVbylQV)M2G2^}=fJdqHv#U88=w;s74`L*qkA3#DH{6+=Mt2*xfQir) zCX2@x^PLzI literal 0 HcmV?d00001 diff --git a/QXTfront/uni_modules/lime-svg/utssdk/app-ios/utils.uts b/QXTfront/uni_modules/lime-svg/utssdk/app-ios/utils.uts new file mode 100644 index 0000000000000000000000000000000000000000..c8fc32dc09899d3dcc3d9c296c4a3c8509be34af GIT binary patch literal 6160 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 4.75 */ +$use-css-var: true; +/* #endif */ + +$item: #{$prefix}-tabbar-item; + +// 尺寸变量 +$tabbar-height: create-var(tabbar-height, 40px); +$tabbar-font-size: create-var(tabbar-font-size, $font-size-md); +$tabbar-min-font-size: create-var(tabbar-font-size, $font-size-sm); + +// 颜色变量 +$tabbar-color: create-var(tabbar-color, $text-color-1); +$tabbar-bg-color: create-var(tabbar-bg-color, $bg-color-container); +$tabbar-active-color: create-var(tabbar-active-color, $primary-color); +$tabbar-active-bg-color: create-var(tabbar-active-bg-color, $primary-color-1); + +// 间距变量(新增) +$tabbar-item-margin-x: create-var(tabbar-item-margin-x, 0); // 水平margin +$tabbar-item-margin-y: create-var(tabbar-item-margin-y, 8px); // 垂直margin +$tabbar-item-padding-x: create-var(tabbar-item-padding-x, 12px); // 水平padding +$tabbar-item-padding-y: create-var(tabbar-item-padding-y, 0); // 垂直padding +$tabbar-item-crowded-padding-x: create-var(tabbar-item-crowded-padding-x, 8px); // 拥挤状态水平padding + +/* #ifdef MP */ +:host { + flex: 1; +} +/* #endif */ + +.#{$item} { + /* #ifndef UNI-APP-X && APP */ + box-sizing: border-box; + user-select: none; + display: flex; + /* #endif */ + + flex: 1; + height: $tabbar-height; + position: relative; + // margin: $tabbar-item-margin-y $tabbar-item-margin-x; // 使用拆分后的margin变量 + @include margin($tabbar-item-margin-y $tabbar-item-margin-x); + background-color: $tabbar-bg-color; + // padding: $tabbar-item-padding-y $tabbar-item-padding-x; // 使用拆分后的padding变量 + @include padding($tabbar-item-padding-y $tabbar-item-padding-x); + overflow: visible; + + &__icon { + &-wrap { + overflow: visible; + } + } + + &--crowded { + // padding: $tabbar-item-padding-y $tabbar-item-crowded-padding-x; // 拥挤状态使用专用变量 + @include padding($tabbar-item-padding-y $tabbar-item-padding-x); + } + + &--round { + border-radius: 99px; + } + + &__content { + box-sizing: border-box; + display: flex; + flex: 1; + flex-direction: column; + align-items: center; + justify-content: center; + border-radius: 16rpx; + overflow: visible; + + &--checked { + /* #ifndef UNI-APP-X && APP */ + color: $tabbar-active-color; + /* #endif */ + /* #ifndef UNI-APP-X */ + .l-tabbar-item__text { + color: $tabbar-active-color; + font-weight: 700; + } + /* #endif */ + } + &--disabled { + opacity: 0.5; + } + &--tag { + border-radius: 99px; + } + + &--tag#{&}--checked { + background-color: $tabbar-active-bg-color; + } + } + + &__icon { + color: $tabbar-color; + } + + &__text { + color: $tabbar-color; + &--small { + font-size: $tabbar-min-font-size; + padding-top: 4px; + } + &--only { + font-size: $tabbar-font-size; + } + &--checked { + color: $tabbar-active-color; + font-weight: 700; + } + &--ellipsis { + @include ellipsisLn(1); + } + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/l-tabbar-item.uvue b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/l-tabbar-item.uvue new file mode 100644 index 0000000..fa48ac1 --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/l-tabbar-item.uvue @@ -0,0 +1,166 @@ + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/l-tabbar-item.vue b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/l-tabbar-item.vue new file mode 100644 index 0000000..8afcab4 --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/l-tabbar-item.vue @@ -0,0 +1,166 @@ + + + diff --git a/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/props.ts b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/props.ts new file mode 100644 index 0000000..9682773 --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/props.ts @@ -0,0 +1,28 @@ +// @ts-nocheck +export default { + /** 图标右上角提示信息 */ + badgeProps: { + type: Object, + default: () => ({}) + }, + /** 图标名称 */ + icon: { + type: String, + }, + /** 标识符 */ + value: { + type: [String, Number], + default: null + }, + disabled: { + type: Boolean, + default: false + }, + label: { + type: String + }, + ellipsis: { + type: Boolean, + default: false + } +}; \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/type.ts b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/type.ts new file mode 100644 index 0000000..9ffc46f --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar-item/type.ts @@ -0,0 +1,26 @@ +// @ts-nocheck +// #ifndef UNI-APP-X +type UTSJSONObject = Object +// #endif + + +export interface TabbarItemProps { + /** + * 图标右上角提示信息 + */ + badgeProps?: UTSJSONObject; + /** + * 图标名称 + */ + icon?: string; + /** + * 标识符 + */ + value?: string; + label?: string; + disabled: boolean; + /** + * 文本超过时是否显示省略号 + */ + ellipsis: boolean; +} diff --git a/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/index-u.scss b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/index-u.scss new file mode 100644 index 0000000..591c95b --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/index-u.scss @@ -0,0 +1,83 @@ +@import '@/uni_modules/lime-style/index.scss'; +@import '@/uni_modules/lime-style/mixins/hairline.scss'; + +/* #ifdef uniVersion >= 4.75 */ +$use-css-var: true; +/* #endif */ +$tabbar: #{$prefix}-tabbar; + +$tabbar-bg-color: create-var(tabbar-bg-color, $bg-color-container); +$tabbar-border-color: create-var(tabbar-border-color, $border-color-1); + +$tabbar-z-index: create-var(tabbar-z-index, 10); +$tabbar-round-margin-x: create-var(tabbar-round-margin-x, $spacer); +/* #ifndef UNI-APP-X && APP */ +$tabbar-round-shadow: create-var(tabbar-round-shadow, $shadow-3); +/* #endif */ +/* #ifdef UNI-APP-X && APP */ +$tabbar-round-shadow: $shadow-3; +/* #endif */ + +.#{$tabbar} { + /* #ifndef UNI-APP-X */ + display: flex; + box-sizing: border-box; + /* #endif */ + flex-direction: row; + flex-wrap: nowrap; + align-items: center; + position: relative; + // font-size: 16px; + background-color: $tabbar-bg-color; + overflow: visible; + + &--fixed { + position: fixed; + left: 0; + bottom: 0; + right: 0; + z-index: $tabbar-z-index; + } + + &--round { + margin-left: $tabbar-round-margin-x; + margin-right: $tabbar-round-margin-x; + border-radius: 999px; + box-shadow: $tabbar-round-shadow; + } + + /* #ifndef UNI-APP-X && APP */ + &--normal#{&}--bordered { + // z-index: 1; + // border-top: 1rpx solid $tabbar-border-color; + border-top-width: 1rpx; + border-top-style: solid; + border-top-color: $tabbar-border-color; + } + /* #endif */ + /* #ifndef UNI-APP-X && APP */ + &--normal#{&}--bordered::before { + // z-index: 1; + @include hairline-top($color: $tabbar-border-color); + } + /* #endif */ + &--normal#{&}--safe { + /* #ifdef UNI-APP-X */ + padding-bottom: var(--uni-safe-area-inset-bottom); + /* #endif */ + /* #ifndef UNI-APP-X */ + padding-bottom: constant(safe-area-inset-bottom); + padding-bottom: env(safe-area-inset-bottom); + /* #endif */ + } + &--fixed#{&}--round#{&}--safe { + /* #ifdef UNI-APP-X */ + bottom: var(--uni-safe-area-inset-bottom); + /* #endif */ + /* #ifndef UNI-APP-X */ + bottom: constant(safe-area-inset-bottom); + bottom: env(safe-area-inset-bottom); + /* #endif */ + } + +} diff --git a/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/l-tabbar.uvue b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/l-tabbar.uvue new file mode 100644 index 0000000..a1dbf1f --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/l-tabbar.uvue @@ -0,0 +1,131 @@ + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/l-tabbar.vue b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/l-tabbar.vue new file mode 100644 index 0000000..100ef7e --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/l-tabbar.vue @@ -0,0 +1,115 @@ + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/props.ts b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/props.ts new file mode 100644 index 0000000..68df659 --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/props.ts @@ -0,0 +1,94 @@ +// @ts-nocheck +export default { + /** 是否显示外边框 */ + bordered: { + type: Boolean, + default: true, + }, + /** 是否固定在底部 */ + fixed: { + type: Boolean, + default: true, + }, + /** 是否为 iPhoneX 留出底部安全距离 */ + safeAreaInsetBottom: { + type: Boolean, + default: true, + }, + /** 当前选中标签的索引 */ + value: { + type: [String, Number], + default: undefined, + }, + modelValue: { + type: [String, Number], + default: undefined, + }, + /** 当前选中标签的索引,非受控属性 */ + defaultValue: { + type: [String, Number], + default: undefined, + }, + /** 固定在底部时,是否在标签位置生成一个等高的占位元素 */ + placeholder: { + type: Boolean, + default: true, + }, + /** 标签栏的形状 */ + shape: { + type: String, + default: 'normal', + validator(val) { + if (!val) return true; + return ['normal', 'round'].includes(val); + }, + }, + /** 选项风格 */ + theme: { + type: String, + default: 'normal', + validator(val) { + if (!val) return true; + return ['normal', 'tag'].includes(val); + }, + }, + /** 是否需要分割线 */ + split: { + type: Boolean, + default: false, + }, + /** 选中标签的颜色 */ + activeColor: { + type: String, + default: null, + }, + /** 未选中标签的颜色 */ + color: { + type: String, + default: null, + }, + lStyle: { + type: [String, Object], + default: null, + }, + bgColor: { + type: String, + default: null, + }, + activeBgColor: { + type: String, + default: null, + }, + zIndex: { + type: Number, + default: null + }, + iconSize: { + type: String, + default: null + }, + fontSize: { + type: String, + default: null + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/type.ts b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/type.ts new file mode 100644 index 0000000..cddd142 --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/l-tabbar/type.ts @@ -0,0 +1,68 @@ +// @ts-nocheck +// #ifndef APP-ANDROID +import type { ComputedRef } from '@/uni_modules/lime-shared/vue'; +type ComputedRefImpl = ComputedRef +// #endif + +export interface TabbarProps { + /** + * 是否显示外边框 true + */ + bordered : boolean; + /** + * 是否固定在底部 true + */ + fixed : boolean; + /** + * 是否为 iPhoneX 留出底部安全距离 true + */ + safeAreaInsetBottom : boolean; + /** + * 标签栏的形状 normal + */ + shape : 'normal' | 'round'; + /** + * 是否需要分割线 true + */ + split : boolean; + /** + * 选项风格 normal + */ + theme : 'normal' | 'tag'; + /** + * 当前选中标签的索引 + */ + value ?: string; + /** + * 当前选中标签的索引,非受控属性 + */ + defaultValue ?: string; + /** + * 当前选中标签的索引 + */ + modelValue ?: string; + /** 固定在底部时,是否在标签位置生成一个等高的占位元素 */ + placeholder:boolean; + // #ifdef APP-ANDROID || APP-IOS + activeColor ?: string; + color ?: string; + // #endif + // #ifndef APP-ANDROID || APP-IOS + activeColor ?: string; + color ?: string; + // #endif + lStyle ?: string|UTSJSONObject; + activeBgColor ?: string; + bgColor?: string + zIndex?:number; + iconSize?: string; + fontSize?: string; +} + +export type TabbarProvide = { + defaultIndex : Ref, + props: LTabbarComponentPublicInstance, + activeValue: ComputedRefImpl, + updateChild: (value: string) => void, + children: Ref +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/components/lime-tabbar/lime-tabbar.uvue b/QXTfront/uni_modules/lime-tabbar/components/lime-tabbar/lime-tabbar.uvue new file mode 100644 index 0000000..18f4a47 --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/lime-tabbar/lime-tabbar.uvue @@ -0,0 +1,249 @@ + + + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/components/lime-tabbar/lime-tabbar.vue b/QXTfront/uni_modules/lime-tabbar/components/lime-tabbar/lime-tabbar.vue new file mode 100644 index 0000000..a4325b8 --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/components/lime-tabbar/lime-tabbar.vue @@ -0,0 +1,207 @@ + + + + + \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/package.json b/QXTfront/uni_modules/lime-tabbar/package.json new file mode 100644 index 0000000..f55bc6d --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/package.json @@ -0,0 +1,110 @@ +{ + "id": "lime-tabbar", + "displayName": "lime-tabbar 标签栏", + "version": "0.1.3", + "description": "lime-tabbar 标签栏 底部导航栏,用于在不同页面之间进行切换。兼容uniapp/uniappx", + "keywords": [ + "lime-tabbar", + "tabbar", + "标签栏" +], + "repository": "", + "engines": { + "HBuilderX": "^4.32", + "uni-app": "^4.54", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "component-vue", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [ + "lime-shared", + "lime-icon", + "lime-badge", + "lime-style" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "-", + "android": { + "extVersion": "", + "minVersion": "22" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "22" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/readme - 副本.md b/QXTfront/uni_modules/lime-tabbar/readme - 副本.md new file mode 100644 index 0000000..9f1919c --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/readme - 副本.md @@ -0,0 +1,210 @@ +# lime-tabbar 标签栏 +- 用于在不同功能模块之间进行快速切换,位于页面底部。兼容uniapp/uniappx +- 插件依赖`lime-style`,`lime-shared`,`lime-badge`,`lime-icon`,`lime-svg`不喜勿下。 + + +## 文档 + [tabbar【站点1】](https://limex.qcoon.cn/components/tabbar.html) + [tabbar【站点2】](https://limeui.netlify.app/components/tabbar.html) + [tabbar【站点3】](https://limeui.familyzone.top/components/tabbar.html) + + +## 安装 +在插件市场导入即可,首次安装可能需要重新编译 + + +**注意** +* 本插件依赖的[lime-svg](https://ext.dcloud.net.cn/plugin?id=18519)在 uniapp x app中是原生插件,如果购买(收费为5元)则需要自定义基座,才能使用!uniapp可忽略。 +* 如果不需要[lime-svg](https://ext.dcloud.net.cn/plugin?id=18519)在lime-icon代码中注释掉即可 + +```html +// lime-icon/components/l-icon.uvue 第4行 注释掉即可。 + +``` + +## 代码演示 +### 基础使用 +`v-model` 默认绑定选中标签的索引值,通过修改 `v-model` 即可切换选中的标签。 +```html + + 首页 + 应用 + 聊天 + 我的 + +``` +```js +const active = ref('0') +``` + +### 通过值匹配 +在标签指定 `value` 属性的情况下,`v-model` 的值为当前标签的 `value`。 +```html + + 首页 + 应用 + 聊天 + 我的 + +``` +```js +const active = ref('home') +``` + +### 徽标提示 +设置 [lime-badge](https://ext.dcloud.net.cn/plugin?id=13616)插件的 `badgeProps` 在图标右上角展示相应的徽标。 +```html + + 首页 + 应用 + 聊天 + 我的 + +``` +```js +const active = ref('home') +``` + +### 自定义图标 +设置`icon`属性可设置图标,图标可看 [lime-icon](https://ext.dcloud.net.cn/plugin?id=14057)或`icon插槽`。 +```html + + + + + 应用 + 聊天 + 我的 + +``` +```js +const active = ref('home') +const activeImg = 'https://fastly.jsdelivr.net/npm/@vant/assets/user-active.png' +const inactiveImg = 'https://fastly.jsdelivr.net/npm/@vant/assets/user-inactive.png' +``` + +### 自定义颜色 +通过 `active-color` 属性设置选中标签的颜色,通过 `color` 属性设置未选中标签的颜色。 +```html + + + + + + +``` + + +### 监听切换事件 +通过 `change` 事件来监听选中标签的变化。 +```html + + + + + + +``` +```js +const change = (value : string) => { + console.log('value', value) +} +``` + + +### 查看示例 +- 导入后直接使用这个标签查看演示效果 + +```html + + +``` + + +### 插件标签 +- 默认 l-tabbar 为 component +- 默认 lime-tabbar 为 demo + +### Vue2使用 +- 插件使用了`composition-api`, 如果你希望在vue2中使用请按官方的教程[vue-composition-api](https://uniapp.dcloud.net.cn/tutorial/vue-composition-api.html)配置 +- 关键代码是: 在main.js中 在vue2部分加上这一段即可 +```js +// vue2 +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' +Vue.use(VueCompositionAPI) +``` + + +## API + +### Tabbar Props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| v-model | 当前选中标签的名称或索引值 | _string_ | `-` | +| value | 当前选中标签的名称或索引值 | _string_ | `-` | +| fixed | 是否固定在底部 | _boolean_ | `true` | +| bordered | 是否显示外边框 | _boolean_ | `true` | +| placeholder | 固定在底部时,是否在标签位置生成一个等高的占位元素 | _boolean_ | `true` | +| zIndex | 元素 z-index | _number_ | `885` | +| shape | 标签栏的形状,可选`round` | _boolean_ | `normal` | +| safeAreaInsetBottom | 是否开启底部安全区适配,设置 fixed 时默认开启 | _boolean_ | `true` | +| activeColor | 选中标签的颜色 | _string_ | `-` | +| color | 未选中标签的颜色 | _string_ | `-` | +| activeBgColor | 选中标签的背景颜色 | _string_ | `-` | +| iconSize | 图标大小 | _string_ | `-` | +| lStyle | 样式 | _string_ | `-` | + +### Tabbar Events + +| 事件名 | 说明 | 回调参数 | +| ---------------- | -------------------------- | ------------------- | +| change | 切换标签时触发 | active: string | + + +### TabbarItem Props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| value | 标签值,作为匹配的标识符 | _string_ | `-` | +| icon | 图标名称或图片链接,等同于 [Icon](https://ext.dcloud.net.cn/plugin?id=14057) 组件的 name 属性 | _string_ | `-` | +| disabled | 是否禁用 | _boolean_ | `false` | +| label | 标签文本 | _string_ | `` | +| badgeProps | 自定义徽标的属性,传入的对象会被透传给 [Badge](https://ext.dcloud.net.cn/plugin?id=13616) 组件的 props | _Object_ | `` | + + +### TabbarItem Slots + +| 名称 | 说明 | +| --------------- | ------------ | +| icon | 自定义图标 | + + + +## 主题定制 + +### 样式变量 + +组件提供了下列 CSS 变量,可用于自定义样式,uvue app无效。 + +| 名称 | 默认值 | 描述 | +| ------------------------------ | ------------------------------------ | ---- | +| --l-tabbar-bg-color | _$bg-color-container_ | - | +| --l-tabbar-border-color | _$border-color-1_ | - | +| --l-tabbar-round-shadow | _$shadow-3_ | - | +| --l-tabbar-z-index | _10_ | - | +| --l-tabbar-height | _80rpx_ | - | +| --l-tabbar-color | _$text-color-1_ | - | +| --l-tabbar-active-color | _$primary-color_ | - | +| --l-tabbar-font-size | _32rpx_ | - | + + +## 打赏 + +如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。 +![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png) +![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png) \ No newline at end of file diff --git a/QXTfront/uni_modules/lime-tabbar/readme.md b/QXTfront/uni_modules/lime-tabbar/readme.md new file mode 100644 index 0000000..735e3f4 --- /dev/null +++ b/QXTfront/uni_modules/lime-tabbar/readme.md @@ -0,0 +1,219 @@ +# lime-tabbar 标签栏 +用于在不同功能模块之间进行快速切换,位于页面底部。兼容uniapp/uniappx。 + +> 插件依赖:`lime-style`、`lime-shared`、`lime-badge`、`lime-icon`、`lime-svg` + +## 文档链接 +📚 组件详细文档请访问以下站点: +- [tabbar文档 - 站点1](https://limex.qcoon.cn/components/tabbar.html) +- [tabbar文档 - 站点2](https://limeui.netlify.app/components/tabbar.html) +- [tabbar文档 - 站点3](https://limeui.familyzone.top/components/tabbar.html) + +## 安装方法 +1. 在uni-app插件市场中搜索并导入`lime-tabbar` +2. 首次导入可能需要重新编译 +3. 在页面中使用`l-tabbar`组件(组件)或`lime-tabbar`(演示) + +::: tip 注意🔔 +本插件依赖的[【lime-svg】](https://ext.dcloud.net.cn/plugin?id=18519)是原生插件,如果购买(收费为6元)则需要自定义基座,才能使用, +若不需要删除即可 +::: + + + +## 代码演示 +### 基础使用 +`v-model` 默认绑定选中标签的索引值,通过修改 `v-model` 即可切换选中的标签。 +```html + + 首页 + 应用 + 聊天 + 我的 + +``` +```js +const active = ref('0') +``` + +### 通过值匹配 +在标签指定 `value` 属性的情况下,`v-model` 的值为当前标签的 `value`。 +```html + + 首页 + 应用 + 聊天 + 我的 + +``` +```js +const active = ref('home') +``` + +### 徽标提示 +设置 [lime-badge](https://ext.dcloud.net.cn/plugin?id=13616)插件的 `badgeProps` 在图标右上角展示相应的徽标。 +```html + + 首页 + 应用 + 聊天 + 我的 + +``` +```js +const active = ref('home') +``` + +### 自定义图标 +设置`icon`属性可设置图标,图标可看 [lime-icon](https://ext.dcloud.net.cn/plugin?id=14057)或`icon插槽`。 +```html + + + + + 应用 + 聊天 + 我的 + +``` +```js +const active = ref('home') +const activeImg = 'https://fastly.jsdelivr.net/npm/@vant/assets/user-active.png' +const inactiveImg = 'https://fastly.jsdelivr.net/npm/@vant/assets/user-inactive.png' +``` + +### 自定义颜色 +通过 `active-color` 属性设置选中标签的颜色,通过 `color` 属性设置未选中标签的颜色。 +```html + + + + + + +``` + + +### 监听切换事件 +通过 `change` 事件来监听选中标签的变化。 +```html + + + + + + +``` +```js +const change = (value : string) => { + console.log('value', value) +} +``` + + +## Vue2使用说明 +本插件使用了`composition-api`,请按照[官方教程](https://uniapp.dcloud.net.cn/tutorial/vue-composition-api.html)配置。 + +关键配置代码(在main.js中添加): +```js +// main.js +import Vue from 'vue' +import VueCompositionAPI from '@vue/composition-api' +Vue.use(VueCompositionAPI) +``` + + +## 快速预览 +导入插件后,可以直接使用以下标签查看演示效果: + +```html + + +``` + +## 插件标签说明 +- `l-tabbar`:标签栏组件 +- `lime-tabbar`:演示标签 + +## API文档 + +### Tabbar Props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| v-model | 当前选中标签的名称或索引值 | string | - | +| value | 当前选中标签的名称或索引值 | string | - | +| fixed | 是否固定在底部 | boolean | `true` | +| bordered | 是否显示外边框 | boolean | `true` | +| split | 是否显示分割线 | boolean | `false` | +| placeholder | 固定在底部时是否生成占位元素 | boolean | `true` | +| zIndex | 元素z-index | number | `885` | +| shape | 标签栏形状,可选`round` | string | `normal` | +| theme | 选项风格,可选`tag` | string | `normal` | +| safeAreaInsetBottom | 是否开启底部安全区适配 | boolean | `true` | +| activeColor | 选中标签的颜色 | string | - | +| color | 未选中标签的颜色 | string | - | +| activeBgColor | 选中标签的背景颜色 | string | - | +| iconSize | 图标大小 | string | - | +| fontSize | 字体大小 | string | - | +| lStyle | 样式 | string | - | + +### Tabbar Events + +| 事件名 | 说明 | 回调参数 | +| --- | --- | --- | +| change | 切换标签时触发 | active: string | + +### TabbarItem Props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| value | 标签值,作为匹配的标识符 | _string_ | `-` | +| icon | 图标名称或图片链接,等同于 [Icon](https://ext.dcloud.net.cn/plugin?id=14057) 组件的 name 属性 | _string_ | `-` | +| disabled | 是否禁用 | _boolean_ | `false` | +| label | 标签文本 | _string_ | `` | +| badgeProps | 自定义徽标的属性,传入的对象会被透传给 [Badge](https://ext.dcloud.net.cn/plugin?id=13616) 组件的 props | _Object_ | `` | + + +### TabbarItem Slots + +| 插槽名 | 说明 | +| --- | --- | +| icon | 自定义图标 | +| default | 默认插槽 | +| extra | 额外插槽,在文本下方 | + +## 主题定制 + +组件提供了下列 CSS 变量,可用于自定义样式。 + +| 变量名称 | 默认值 | 描述 | +|---------|--------|------| +| `--l-tabbar-bg-color` | `$bg-color-container` | 标签栏背景色 | +| `--l-tabbar-border-color` | `$border-color-1` | 标签栏边框颜色 | +| `--l-tabbar-round-shadow` | `$shadow-3` | 圆角模式阴影效果 | +| `--l-tabbar-z-index` | `10` | 标签栏的 z-index 层级 | +| `--l-tabbar-height` | `80rpx` | 标签栏高度 | +| `--l-tabbar-round-margin-x` | `16px` | 圆角模式水平外边距 | +| `--l-tabbar-item-margin-x` | `0` | 标签项水平外边距 | +| `--l-tabbar-item-margin-y` | `8px` | 标签项垂直外边距 | +| `--l-tabbar-item-padding-x` | `12px` | 标签项水平内边距 | +| `--l-tabbar-item-padding-y` | `0` | 标签项垂直内边距 | +| `--l-tabbar-item-crowded-padding-x` | `8px` | 拥挤状态下标签项水平内边距 | +| `--l-tabbar-color` | `$text-color-1` | 标签项默认文字颜色 | +| `--l-tabbar-active-color` | `$primary-color` | 标签项激活状态文字颜色 | +| `--l-tabbar-font-size` | `32rpx` | 标签项默认文字大小 | +| `--l-tabbar-min-font-size` | `$font-size-sm` | 标签项最小文字大小 | +| `--l-tabbar-active-bg-color` | `$primary-color-1` | 标签项激活状态背景色 | +| `--l-tabbar-disabled-opacity` | `0.5` | 禁用状态透明度 | + + +## 支持与赞赏 + +如果你觉得本插件解决了你的问题,可以考虑支持作者: +| 支付宝赞助 | 微信赞助 | +|------------|------------| +| ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png) | ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png) | \ No newline at end of file diff --git a/QXTfront/unpackage/dist/cache/.vite/deps/_metadata.json b/QXTfront/unpackage/dist/cache/.vite/deps/_metadata.json new file mode 100644 index 0000000..c8cf575 --- /dev/null +++ b/QXTfront/unpackage/dist/cache/.vite/deps/_metadata.json @@ -0,0 +1,8 @@ +{ + "hash": "a445e8c3", + "configHash": "8ef788b7", + "lockfileHash": "e3b0c442", + "browserHash": "97852fcb", + "optimized": {}, + "chunks": {} +} \ No newline at end of file diff --git a/QXTfront/unpackage/dist/cache/.vite/deps/package.json b/QXTfront/unpackage/dist/cache/.vite/deps/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/QXTfront/unpackage/dist/cache/.vite/deps/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +}