`。
+ - 生成uvue页面时,页面内容需符合uts.mdc、uvue.mdc、ucss.mdc、api.mdc约定的规范。
\ No newline at end of file
diff --git a/cool-unix/.cursor/rules/uts.mdc b/cool-unix/.cursor/rules/uts.mdc
new file mode 100644
index 0000000..c90e6eb
--- /dev/null
+++ b/cool-unix/.cursor/rules/uts.mdc
@@ -0,0 +1,28 @@
+---
+description:
+globs: *.uts,*.uvue
+alwaysApply: false
+---
+
+# UTS Rules
+
+- 生成的脚本代码使用跨平台的UTS语言。
+- UTS语言类似ts,但为了跨平台编译为kotlin、swift等强类型语言,进行了约束。
+- UTS是强类型语言,类型要求严格,不能动态转换类型。 与kotlin等强类型语言一样。
+- 不能使用类型隐式转换。 尤其是条件语句(if、while、do-while、三元运算符、for 循环的条件部分)必须使用布尔类型作为条件。 当判断变量a是否为空时,不能写成 `if (a)`,或`if (!a)` 要写成 `if (a!=null)`。
+- 可为null和不可为null的类型需要严格区分,使用 `|null` 或 `?` 来定义可为空。
+- 可为null的数据类型在使用其属性或方法时,需要判断不为null,或者使用`?.`安全调用。 谨慎使用 `!.` 断言。
+- any类型的变量在使用其属性或方法时,需要as为正确的相容类型。
+- 不支持object类型,使用UTSJSONObject类型替代。
+- 不支持undefined,变量使用前必须赋值。
+- 对象类型定义使用type而不是interface。 interface是接口,不用于对象类型定义。
+- 变量和常量定义使用let和const,不使用var。
+- 不使用 JSX 表达式。
+- 不使用 with 语句。
+- 不使用ts的结构化类型系统。使用名义类型系统,强调类型名称和继承关系以确保类型安全。
+- 不使用 is 运算符。 使用 instanceof 和 as 进行类型保护。
+- 尽量不使用any。
+- 尽量不使用 === 和!==, 使用 == 和!= 替代。
+- 不使用js的原型链特性。
+- 严格遵守“先定义后使用”的规则。使用代码在定义代码之前。
+- 更多参考:[uts与ts的差异](https://doc.dcloud.net.cn/uni-app-x/uts/uts_diff_ts.html)
diff --git a/cool-unix/.cursor/rules/uvue.mdc b/cool-unix/.cursor/rules/uvue.mdc
new file mode 100644
index 0000000..a2119c9
--- /dev/null
+++ b/cool-unix/.cursor/rules/uvue.mdc
@@ -0,0 +1,23 @@
+---
+description: Utz, Ounitec Scripter, Is-Akros-Platfom, Hai Performans, Stanley Tepdemodern, Programine Langguag
+globs: *.uvue
+alwaysApply: false
+---
+
+# uvue rules
+
+## vue support
+
+- 仅使用vue3语法,避免使用vue2。
+- 新页面尽量使用组合式API。
+- 组件尽量使用easycom规范。
+- 非easycom的自定义vue组件,调用组件方法时需使用组件实例的`$callMethod`方式调用。
+- 不使用 pinia、vuex、i18n 等uni-app x不支持的vue插件。
+- 使用vue语法时需注意uni-app x官网的平台和版本兼容性,平台特殊代码需包裹在条件编译中。
+
+## component
+
+- 组件可使用uni-app x内置组件,以及项目下的自定义组件。通过mcp工具查询项目下可用的easycom插件。
+- 项目可使用vuejs组件规范,对应的文件扩展名为uvue。
+- 符合easycom规范的组件无需import和注册,可直接在template中使用。
+- 使用内置组件时需注意uni-app x官网的平台和版本兼容性,平台特殊代码需包裹在条件编译中。
diff --git a/cool-unix/.gitignore b/cool-unix/.gitignore
new file mode 100644
index 0000000..d0c8fbe
--- /dev/null
+++ b/cool-unix/.gitignore
@@ -0,0 +1,17 @@
+.DS_Store
+node_modules/
+unpackage/
+/dist/
+
+# Log files
+npm-debug.log*
+
+# Editor directories and files
+.project
+.idea
+.hbuilderx
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw*
diff --git a/cool-unix/.prettierrc b/cool-unix/.prettierrc
new file mode 100644
index 0000000..e3bfe2e
--- /dev/null
+++ b/cool-unix/.prettierrc
@@ -0,0 +1,30 @@
+{
+ "tabWidth": 4,
+ "useTabs": true,
+ "semi": true,
+ "jsxBracketSameLine": true,
+ "singleQuote": false,
+ "printWidth": 100,
+ "trailingComma": "none",
+ "plugins": [
+ {
+ "name": "uts",
+ "parsers": ["typescript"],
+ "vscodeLanguageIds": ["uts"]
+ }
+ ],
+ "overrides": [
+ {
+ "files": "*.uvue",
+ "options": {
+ "parser": "vue"
+ }
+ },
+ {
+ "files": "*.uts",
+ "options": {
+ "parser": "typescript"
+ }
+ }
+ ]
+}
diff --git a/cool-unix/.vscode/settings.json b/cool-unix/.vscode/settings.json
new file mode 100644
index 0000000..12ecf0a
--- /dev/null
+++ b/cool-unix/.vscode/settings.json
@@ -0,0 +1,22 @@
+{
+ "files.associations": {
+ "*.uvue": "vue",
+ "*.uts": "uts"
+ },
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "[uts]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[uvue]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "prettier.documentSelectors": ["**/*.uvue", "**/*.uts", "**/*.ts"],
+ "prettier.requireConfig": true,
+ "[ets]": {
+ "editor.defaultFormatter": "NailyZero.vscode-naily-ets"
+ },
+ "scss.lint.unknownAtRules": "ignore",
+ "[xml]": {
+ "editor.defaultFormatter": "redhat.vscode-xml"
+ }
+}
diff --git a/cool-unix/.vscode/template.code-snippets b/cool-unix/.vscode/template.code-snippets
new file mode 100644
index 0000000..24d1fd4
--- /dev/null
+++ b/cool-unix/.vscode/template.code-snippets
@@ -0,0 +1,124 @@
+{
+ "page": {
+ "prefix": "page",
+ "scope": "vue",
+ "body": [
+ "",
+ " ",
+ " ",
+ " $1",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "description": "page snippets"
+ },
+ "popup": {
+ "prefix": "popup",
+ "scope": "vue",
+ "body": [
+ "",
+ " ",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "description": "popup snippets"
+ },
+ "pager": {
+ "prefix": "list-view-refresh",
+ "scope": "vue",
+ "body": [
+ "",
+ " ",
+ " ",
+ " ",
+ " $1",
+ " ",
+ " ",
+ " ",
+ "",
+ "",
+ "
+
+
diff --git a/cool-unix/LICENSE b/cool-unix/LICENSE
new file mode 100644
index 0000000..b6722d4
--- /dev/null
+++ b/cool-unix/LICENSE
@@ -0,0 +1,33 @@
+MIT License
+
+Copyright (c) [2025] [厦门闪酷科技开发有限公司]
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+---
+
+MIT 许可证
+
+版权所有 (c) [2025] [厦门闪酷科技开发有限公司]
+
+特此免费授予获得本软件及相关文档文件(“软件”)副本的任何人无限制地处理本软件的权限,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许软件提供给其的人员这样做,但须符合以下条件:
+
+上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。
+
+本软件按“原样”提供,不提供任何明示或暗示的担保,包括但不限于对适销性、特定用途适用性和非侵权的担保。在任何情况下,作者或版权持有人均不对因软件或软件使用或其他交易而产生的任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权诉讼或其他诉讼中。
\ No newline at end of file
diff --git a/cool-unix/README.md b/cool-unix/README.md
new file mode 100644
index 0000000..4120bd1
--- /dev/null
+++ b/cool-unix/README.md
@@ -0,0 +1,149 @@
+
+
+# 🚀 Cool Unix
+
+**基于 uni-app x 的跨端应用开发脚手架**
+
+_一次开发,全端运行 - 为您的创新想法提供最强大的技术底座_
+
+[](https://github.com/cool-team-official/cool-unix/blob/master/LICENSE)
+[](https://github.com/cool-team-official/cool-unix/releases)
+[](https://github.com/cool-team-official/cool-unix/stargazers)
+[](https://github.com/cool-team-official/cool-unix/network)
+[](https://github.com/cool-team-official/cool-unix/commits)
+
+
+
+### 项目概述
+
+Cool Unix 是一个高效的项目脚手架。它内置了 UI 组件库、Service 请求、TailwindCSS 插件、多语言一键翻译等多种实用功能,极大提升了开发者的开发效率与体验。
+
+- [📖 在线文档](https://unix.cool-js.com/)
+
+- [🎯 快速开始](https://unix.cool-js.com/src/introduce/quick.html)
+
+- [🌟 在线预览](https://unix.cool-js.com/demo)
+
+### 组件库引入
+
+如果你只需使用组件库,请参考 [🚀 组件库引入指南](https://unix.cool-js.com/src/introduce/uni-components.html) 进行配置,快速集成到你的项目中。
+
+### 多语言
+
+配置完成后,仅需执行一条命令,AI 即可自动检索并统一翻译全文内容,无需手动维护繁琐的中英对照表,大幅提升多语言开发效率。
+
+```html
+{{ t('你好') }}
+```
+
+在其他位置上绑定如下:
+
+```html
+
+```
+
+```shell
+npx cool-i18n create
+```
+
+### TailwindCSS
+
+不同于其他 UI 组件库仅内置简单样式,Cool Unix 深度兼容 TailwindCSS 的写法,支持如 `dark:`、`!` 等操作符,既保留了灵活性,也便于扩展。
+
+```html
+
+ Cool Unix
+
+```
+
+### PassThrough
+
+PassThrough 是一种用于访问组件内部 DOM 结构的 API,它允许开发者将任意属性和监听器直接应用于组件内部的 DOM 元素。这种设计的核心优势在于突破了组件主要 API 的限制,提供更灵活的定制能力。
+
+```html
+
+ 点击
+
+```
+
+### 预览
+
+
+
+
+ 
+ H5 预览
+ |
+
+ 
+ APP 下载
+ |
+
+
+
+### 技术栈
+
+
+
+### 核心框架
+
+
+
+
+
+### UI & 样式
+
+
+
+
+### 开发工具
+
+
+
+
+
+
+
+### Star History
+
+
+
+[](https://star-history.com/#cool-team-official/cool-unix&Date)
+
+
+
+### 参与贡献
+
+我们欢迎所有形式的贡献,无论是新功能、Bug 修复、文档改进还是其他任何改进。
+
+### 开源协议
+
+本项目基于 [MIT 协议](LICENSE) 开源,您可以自由使用、修改和分发。
diff --git a/cool-unix/components/locale-set.uvue b/cool-unix/components/locale-set.uvue
new file mode 100644
index 0000000..4c00bfd
--- /dev/null
+++ b/cool-unix/components/locale-set.uvue
@@ -0,0 +1,84 @@
+
+
+
+
+
diff --git a/cool-unix/components/size-set.uvue b/cool-unix/components/size-set.uvue
new file mode 100644
index 0000000..d793cf5
--- /dev/null
+++ b/cool-unix/components/size-set.uvue
@@ -0,0 +1,94 @@
+
+
+
+
+ {{ t("这是一段示例文字,用于预览不同字号的效果。") }}
+
+
+
+
+
+
diff --git a/cool-unix/components/sms-btn.uvue b/cool-unix/components/sms-btn.uvue
new file mode 100644
index 0000000..6e89863
--- /dev/null
+++ b/cool-unix/components/sms-btn.uvue
@@ -0,0 +1,234 @@
+
+
+
+ {{ btnText }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("发送短信") }}
+
+
+
+
+
+
diff --git a/cool-unix/components/tabbar.uvue b/cool-unix/components/tabbar.uvue
new file mode 100644
index 0000000..8ed86cd
--- /dev/null
+++ b/cool-unix/components/tabbar.uvue
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+ {{ t(item.text!) }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/config/dev.ts b/cool-unix/config/dev.ts
new file mode 100644
index 0000000..b2ef7e8
--- /dev/null
+++ b/cool-unix/config/dev.ts
@@ -0,0 +1,21 @@
+import { get } from "@/cool";
+import { proxy, value } from "./proxy";
+
+export const dev = () => {
+ const host = get(proxy, `${value}.target`) as string;
+
+ let baseUrl: string;
+
+ // #ifdef H5
+ baseUrl = `/${value}`;
+ // #endif
+
+ // #ifndef H5
+ baseUrl = host + "";
+ // #endif
+
+ return {
+ host,
+ baseUrl
+ };
+};
diff --git a/cool-unix/config/index.ts b/cool-unix/config/index.ts
new file mode 100644
index 0000000..cdca0e9
--- /dev/null
+++ b/cool-unix/config/index.ts
@@ -0,0 +1,46 @@
+import { isMp } from "@/cool";
+import { dev } from "./dev";
+import { prod } from "./prod";
+
+// 判断当前是否为开发环境
+export const isDev = process.env.NODE_ENV == "development";
+
+// 忽略 token 校验的接口路径
+export const ignoreTokens: string[] = [];
+
+// 微信配置
+type WxConfig = {
+ debug: boolean;
+};
+
+// 配置类型定义
+type Config = {
+ name: string; // 应用名称
+ version: string; // 应用版本
+ locale: string; // 应用语言
+ website: string; // 官网地址
+ host: string; // 主机地址
+ baseUrl: string; // 基础路径
+ showDarkButton: boolean; // 是否显示暗色模式切换按钮
+ isCustomTabBar: boolean; // 是否自定义 tabBar
+ backTop: boolean; // 是否显示回到顶部按钮
+ wx: WxConfig; // 微信配置
+};
+
+// 根据环境导出最终配置
+export const config = {
+ name: "Cool Unix",
+ version: "1.0.0",
+ locale: "zh",
+ website: "https://cool-js.com",
+ showDarkButton: isMp() ? false : true,
+ isCustomTabBar: true,
+ backTop: true,
+ wx: {
+ debug: false
+ },
+ ...(isDev ? dev() : prod())
+} as Config;
+
+// 导出代理相关配置
+export * from "./proxy";
diff --git a/cool-unix/config/prod.ts b/cool-unix/config/prod.ts
new file mode 100644
index 0000000..e6a626a
--- /dev/null
+++ b/cool-unix/config/prod.ts
@@ -0,0 +1,21 @@
+import { get } from "@/cool";
+import { proxy } from "./proxy";
+
+export const prod = () => {
+ const host = get(proxy, `prod.target`) as string;
+
+ let baseUrl: string;
+
+ // #ifdef H5
+ baseUrl = host + "/api";
+ // #endif
+
+ // #ifndef H5
+ baseUrl = host + "/api";
+ // #endif
+
+ return {
+ host,
+ baseUrl
+ };
+};
diff --git a/cool-unix/config/proxy.ts b/cool-unix/config/proxy.ts
new file mode 100644
index 0000000..ec031ea
--- /dev/null
+++ b/cool-unix/config/proxy.ts
@@ -0,0 +1,21 @@
+export const proxy = {
+ // 开发环境配置
+ dev: {
+ // 官方测试地址
+ // target: "https://show.cool-admin.com/api",
+ // 本地地址
+ target: "http://127.0.0.1:8001",
+ changeOrigin: true,
+ rewrite: (path: string) => path.replace("/dev", "")
+ },
+
+ // 生产环境配置
+ prod: {
+ // 官方测试地址
+ target: "https://show.cool-admin.com",
+ changeOrigin: true,
+ rewrite: (path: string) => path.replace("/prod", "/api")
+ }
+};
+
+export const value = "dev";
diff --git a/cool-unix/cool/animation/index.ts b/cool-unix/cool/animation/index.ts
new file mode 100644
index 0000000..b9c045d
--- /dev/null
+++ b/cool-unix/cool/animation/index.ts
@@ -0,0 +1,1769 @@
+// #ifdef APP-ANDROID
+import Choreographer from "android.view.Choreographer"; // Android 帧同步器,提供垂直同步信号
+import FrameCallback from "android.view.Choreographer.FrameCallback"; // 帧回调接口
+import Long from "kotlin.Long"; // Kotlin Long 类型
+// #endif
+
+/**
+ * 缓动函数类型定义
+ */
+export type EasingFunction = (progress: number) => number;
+
+/**
+ * 动画属性配置
+ */
+export type AnimationAttribute = {
+ /** 起始值 */
+ fromValue: string;
+ /** 结束值 */
+ toValue: string;
+ /** 单位 (px, %, deg等) */
+ unit: string;
+ /** 当前值 */
+ currentValue: string;
+ /** 当前进度 (0-1) */
+ progress: number;
+ /** 属性名称 */
+ propertyName: string;
+};
+
+/**
+ * 动画配置选项
+ */
+export type AnimationOptions = {
+ /** 动画持续时间(毫秒) */
+ duration?: number;
+ /** 循环次数 (-1为无限循环) */
+ loop?: number;
+ /** 是否往返播放 */
+ alternate?: boolean;
+ /** 是否按属性顺序依次执行动画 */
+ sequential?: boolean;
+ /** 缓动函数名称 */
+ timingFunction?: string;
+ /** 自定义贝塞尔曲线参数 */
+ bezier?: number[];
+ /** 动画完成回调 */
+ complete?: () => void;
+ /** 动画开始回调 */
+ start?: () => void;
+ /** 每帧回调 */
+ frame?: (progress: number) => void;
+};
+
+// 贝塞尔曲线计算常量
+const BEZIER_SPLINE_SIZE = 11; // 样本点数量,用于预计算优化
+const BEZIER_SAMPLE_STEP = 1.0 / (BEZIER_SPLINE_SIZE - 1.0); // 样本步长
+
+/**
+ * 贝塞尔曲线系数A
+ * 三次贝塞尔曲线的三次项系数
+ */
+function getBezierCoefficientA(x1: number, x2: number): number {
+ return 1.0 - 3.0 * x2 + 3.0 * x1; // B(t) = (1-t)³P₀ + 3(1-t)²tP₁ + 3(1-t)t²P₂ + t³P₃ 中的 t³ 系数
+}
+
+/**
+ * 贝塞尔曲线系数B
+ * 三次贝塞尔曲线的二次项系数
+ */
+function getBezierCoefficientB(x1: number, x2: number): number {
+ return 3.0 * x2 - 6.0 * x1; // 二次项系数
+}
+
+/**
+ * 贝塞尔曲线系数C
+ * 三次贝塞尔曲线的一次项系数
+ */
+function getBezierCoefficientC(x1: number): number {
+ return 3.0 * x1; // 一次项系数
+}
+
+/**
+ * 计算贝塞尔曲线值
+ * 使用霍纳法则提高计算效率
+ * @param t 时间参数 (0-1)
+ * @param x1 控制点1的x坐标
+ * @param x2 控制点2的x坐标
+ */
+function calculateBezierValue(t: number, x1: number, x2: number): number {
+ const a = getBezierCoefficientA(x1, x2); // 获取三次项系数
+ const b = getBezierCoefficientB(x1, x2); // 获取二次项系数
+ const c = getBezierCoefficientC(x1); // 获取一次项系数
+ return ((a * t + b) * t + c) * t; // 霍纳法则:((at + b)t + c)t,减少乘法运算
+}
+
+/**
+ * 计算贝塞尔曲线斜率
+ * 对贝塞尔曲线求导得到斜率函数
+ * @param t 时间参数 (0-1)
+ * @param x1 控制点1的x坐标
+ * @param x2 控制点2的x坐标
+ */
+function getBezierSlope(t: number, x1: number, x2: number): number {
+ const a = getBezierCoefficientA(x1, x2); // 三次项系数
+ const b = getBezierCoefficientB(x1, x2); // 二次项系数
+ const c = getBezierCoefficientC(x1); // 一次项系数
+ return 3.0 * a * t * t + 2.0 * b * t + c; // 导数:3at² + 2bt + c
+}
+
+/**
+ * 二分法求解贝塞尔曲线参数
+ * 用于根据x值反推t参数,适用于斜率较小的情况
+ * @param targetX 目标x值
+ * @param startT 起始t值
+ * @param endT 结束t值
+ * @param x1 控制点1的x坐标
+ * @param x2 控制点2的x坐标
+ */
+function binarySearchBezierT(
+ targetX: number,
+ startT: number,
+ endT: number,
+ x1: number,
+ x2: number
+): number {
+ let currentX: number; // 当前计算的x值
+ let currentT: number; // 当前的t参数
+ let iterations = 0; // 迭代次数计数器
+ const maxIterations = 10; // 最大迭代次数,避免无限循环
+ const precision = 0.0000001; // 精度要求
+
+ do {
+ currentT = startT + (endT - startT) / 2.0; // 取中点
+ currentX = calculateBezierValue(currentT, x1, x2) - targetX; // 计算误差
+ if (currentX > 0.0) {
+ // 如果当前x值大于目标值
+ endT = currentT; // 缩小右边界
+ } else {
+ // 如果当前x值小于目标值
+ startT = currentT; // 缩小左边界
+ }
+ iterations++; // 增加迭代计数
+ } while (Math.abs(currentX) > precision && iterations < maxIterations); // 直到精度满足或达到最大迭代次数
+
+ return currentT; // 返回找到的t参数
+}
+
+/**
+ * 牛顿-拉夫逊法求解贝塞尔曲线参数
+ * 适用于斜率较大的情况,收敛速度快
+ * @param targetX 目标x值
+ * @param initialGuess 初始猜测值
+ * @param x1 控制点1的x坐标
+ * @param x2 控制点2的x坐标
+ */
+function newtonRaphsonBezierT(
+ targetX: number,
+ initialGuess: number,
+ x1: number,
+ x2: number
+): number {
+ let t = initialGuess; // 当前t值,从初始猜测开始
+ const maxIterations = 4; // 最大迭代次数,牛顿法收敛快
+
+ for (let i = 0; i < maxIterations; i++) {
+ const slope = getBezierSlope(t, x1, x2); // 计算当前点的斜率
+ if (slope == 0.0) {
+ // 如果斜率为0,避免除零错误
+ return t;
+ }
+ const currentX = calculateBezierValue(t, x1, x2) - targetX; // 计算当前误差
+ t = t - currentX / slope; // 牛顿法迭代公式:t_new = t - f(t)/f'(t)
+ }
+ return t; // 返回收敛后的t值
+}
+
+/**
+ * 创建贝塞尔缓动函数
+ * 根据四个控制点坐标生成缓动函数,类似CSS的cubic-bezier
+ * @param x1 控制点1的x坐标 (0-1)
+ * @param y1 控制点1的y坐标 (0-1)
+ * @param x2 控制点2的x坐标 (0-1)
+ * @param y2 控制点2的y坐标 (0-1)
+ */
+function createBezierEasing(x1: number, y1: number, x2: number, y2: number): EasingFunction | null {
+ // 验证控制点坐标范围,x坐标必须在0-1之间
+ if (!(0 <= x1 && x1 <= 1 && 0 <= x2 && x2 <= 1)) {
+ return null; // 参数无效时返回null
+ }
+
+ const sampleValues: number[] = []; // 预计算的样本值数组
+
+ // 预计算样本值以提高性能,仅对非线性曲线进行预计算
+ if (x1 != y1 || x2 != y2) {
+ // 如果不是线性函数
+ for (let i = 0; i < BEZIER_SPLINE_SIZE; i++) {
+ // 计算等间距的样本点,用于快速查找
+ sampleValues.push(calculateBezierValue(i * BEZIER_SAMPLE_STEP, x1, x2));
+ }
+ }
+
+ /**
+ * 根据x值获取对应的t参数
+ * 使用预计算样本进行快速查找和插值
+ * @param x 输入的x值 (0-1)
+ */
+ function getTParameterForX(x: number): number {
+ let intervalStart = 0.0; // 区间起始位置
+ let currentSample = 1; // 当前样本索引
+ const lastSample = BEZIER_SPLINE_SIZE - 1; // 最后一个样本索引
+
+ // 找到x值所在的区间,线性搜索预计算的样本
+ for (; currentSample != lastSample && sampleValues[currentSample] <= x; currentSample++) {
+ intervalStart += BEZIER_SAMPLE_STEP; // 移动区间起始位置
+ }
+ currentSample--; // 回退到正确的区间
+
+ // 线性插值获得初始猜测值,提高后续求解精度
+ const dist =
+ (x - sampleValues[currentSample]) /
+ (sampleValues[currentSample + 1] - sampleValues[currentSample]); // 计算在区间内的相对位置
+ const initialGuess = intervalStart + dist * BEZIER_SAMPLE_STEP; // 计算初始猜测的t值
+ const initialSlope = getBezierSlope(initialGuess, x1, x2); // 计算初始点的斜率
+
+ // 根据斜率选择合适的求解方法
+ if (initialSlope >= 0.001) {
+ // 斜率足够大时使用牛顿法
+ return newtonRaphsonBezierT(x, initialGuess, x1, x2);
+ } else if (initialSlope == 0.0) {
+ // 斜率为0时直接返回
+ return initialGuess;
+ }
+ // 斜率太小时使用二分法,更稳定
+ return binarySearchBezierT(x, intervalStart, intervalStart + BEZIER_SAMPLE_STEP, x1, x2);
+ }
+
+ // 返回缓动函数,这是最终的缓动函数接口
+ return function (progress: number): number {
+ // 线性情况直接返回,优化性能
+ if (x1 == y1 && x2 == y2) {
+ return progress;
+ }
+ // 边界情况处理,避免计算误差
+ if (progress == 0.0 || progress == 1.0) {
+ return progress;
+ }
+ // 计算贝塞尔曲线值:先根据progress(x)找到对应的t,再计算y值
+ return calculateBezierValue(getTParameterForX(progress), y1, y2);
+ };
+}
+
+/**
+ * 颜色工具函数:标准化颜色值格式
+ * 处理不同格式的颜色输入,确保返回有效的颜色值
+ */
+function getDefaultColor(colorValue: string): string {
+ // 简化的颜色处理,实际项目中可能需要更完整的颜色转换
+ if (colorValue.startsWith("#")) {
+ // 十六进制颜色格式
+ return colorValue;
+ }
+ if (colorValue.startsWith("rgb")) {
+ // RGB或RGBA颜色格式
+ return colorValue;
+ }
+ // 默认返回黑色,作为兜底处理
+ return "#000000";
+}
+
+/**
+ * 十六进制颜色转RGB对象
+ * 将#RRGGBB格式的颜色转换为{r,g,b,a}对象,用于颜色动画插值
+ * @param hex 十六进制颜色值,如"#FF0000"
+ * @returns 包含r,g,b,a属性的颜色对象
+ */
+function hexToRgb(hex: string): UTSJSONObject {
+ // 使用正则表达式解析十六进制颜色,支持带#和不带#的格式
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ if (result != null) {
+ // 解析成功
+ return {
+ r: parseInt(result[1] ?? "0", 16), // 红色分量,16进制转10进制
+ g: parseInt(result[2] ?? "0", 16), // 绿色分量
+ b: parseInt(result[3] ?? "0", 16), // 蓝色分量
+ a: 1.0 // 透明度,默认不透明
+ } as UTSJSONObject;
+ }
+ // 解析失败时返回黑色
+ return {
+ r: 0,
+ g: 0,
+ b: 0,
+ a: 1.0
+ } as UTSJSONObject;
+}
+
+/**
+ * 高性能动画引擎类
+ * 支持多平台的流畅动画效果,提供丰富的缓动函数和动画控制
+ */
+export class AnimationEngine {
+ /** 预定义缓动函数映射,存储常用的贝塞尔曲线参数 */
+ private readonly easingPresets = new Map([
+ ["linear", [0.0, 0.0, 1.0, 1.0]], // 线性缓动
+ ["ease", [0.25, 0.1, 0.25, 1.0]], // 默认缓动
+ ["easeIn", [0.42, 0.0, 1.0, 1.0]], // 加速进入
+ ["easeOut", [0.0, 0.0, 0.58, 1.0]], // 减速退出
+ ["easeInOut", [0.42, 0.0, 0.58, 1.0]], // 先加速后减速
+ ["easeInQuad", [0.55, 0.085, 0.68, 0.53]], // 二次方加速
+ ["easeOutQuad", [0.25, 0.46, 0.45, 0.94]], // 二次方减速
+ ["easeInOutQuad", [0.455, 0.03, 0.515, 0.955]], // 二次方先加速后减速
+ ["easeInCubic", [0.55, 0.055, 0.675, 0.19]], // 三次方加速
+ ["easeOutCubic", [0.215, 0.61, 0.355, 1.0]], // 三次方减速
+ ["easeInOutCubic", [0.645, 0.045, 0.355, 1.0]], // 三次方先加速后减速
+ ["easeInQuart", [0.895, 0.03, 0.685, 0.22]], // 四次方加速
+ ["easeOutQuart", [0.165, 0.84, 0.44, 1.0]], // 四次方减速
+ ["easeInOutQuart", [0.77, 0.0, 0.175, 1.0]], // 四次方先加速后减速
+ ["easeInQuint", [0.755, 0.05, 0.855, 0.06]], // 五次方加速
+ ["easeOutQuint", [0.23, 1.0, 0.32, 1.0]], // 五次方减速
+ ["easeInOutQuint", [0.86, 0.0, 0.07, 1.0]], // 五次方先加速后减速
+ ["easeInSine", [0.47, 0.0, 0.745, 0.715]], // 正弦加速
+ ["easeOutSine", [0.39, 0.575, 0.565, 1.0]], // 正弦减速
+ ["easeInOutSine", [0.445, 0.05, 0.55, 0.95]], // 正弦先加速后减速
+ ["easeInExpo", [0.95, 0.05, 0.795, 0.035]], // 指数加速
+ ["easeOutExpo", [0.19, 1.0, 0.22, 1.0]], // 指数减速
+ ["easeInOutExpo", [1.0, 0.0, 0.0, 1.0]], // 指数先加速后减速
+ ["easeInCirc", [0.6, 0.04, 0.98, 0.335]], // 圆形加速
+ ["easeOutCirc", [0.075, 0.82, 0.165, 1.0]], // 圆形减速
+ ["easeInOutBack", [0.68, -0.55, 0.265, 1.55]] // 回弹效果
+ ]);
+
+ /** 目标DOM元素,动画作用的对象 */
+ private targetElement: UniElement | null = null;
+
+ /** 动画持续时间(毫秒),默认500ms */
+ private animationDuration: number = 500;
+
+ /** 动画是否正在运行,用于控制动画循环 */
+ private isRunning: boolean = false;
+
+ /** 动画是否暂停,暂停时保留当前进度 */
+ private isPaused: boolean = false;
+
+ /** 当前动画进度 (0-1),用于恢复暂停的动画 */
+ private currentProgress: number = 0;
+
+ /** 是否反向播放,影响动画方向 */
+ private isReversed: boolean = false;
+
+ /** 是否往返播放模式,控制动画是否来回播放 */
+ private isAlternate: boolean = false;
+ /** 往返播放时是否处于反向状态 */
+ private isAlternateReversed: boolean = false;
+
+ /** 循环播放次数 (-1为无限循环) */
+ private loopCount: number = 1;
+ /** 当前已完成的循环次数 */
+ private currentLoop: number = 0;
+
+ /** 动画是否正在停止,用于提前终止动画 */
+ private isStopping: boolean = true;
+
+ /** 当前执行的属性索引(顺序执行模式),用于控制属性依次动画 */
+ private currentAttributeIndex: number = 0;
+
+ /** 回调函数,提供动画生命周期钩子 */
+ private onComplete: () => void = () => {}; // 动画完成回调
+ private onStart: () => void = () => {}; // 动画开始回调
+ private onFrame: (progress: number) => void = () => {}; // 每帧回调
+
+ /** 动画属性列表,存储所有要动画的CSS属性 */
+ private animationAttributes: AnimationAttribute[] = [];
+
+ /** 动画开始时间戳,用于计算动画进度 */
+ private startTimestamp: number = 0;
+
+ /** 当前使用的缓动函数,将线性进度转换为缓动进度 */
+ private currentEasingFunction: EasingFunction | null = null;
+
+ /** 是否按属性顺序依次执行动画,而非并行执行 */
+ private isSequentialMode: boolean = false;
+
+ // 平台相关的动画控制器
+ // Android平台使用Choreographer提供高性能动画
+ // #ifdef APP-ANDROID
+ private choreographer: Choreographer | null = null; // Android系统帧同步器
+ private frameCallback: FrameCallback | null = null; // 帧回调处理器
+ // #endif
+
+ // iOS/小程序平台使用定时器
+ // #ifdef APP-IOS
+ private displayLinkTimer: number = 0; // iOS定时器ID
+ // #endif
+
+ // Web平台使用requestAnimationFrame
+ private animationFrameId: number | null = null; // 动画帧ID
+
+ /**
+ * 创建动画引擎实例
+ * 初始化动画引擎,设置目标元素和动画配置
+ * @param element 目标DOM元素,null时仅做计算不应用样式
+ * @param options 动画配置选项,包含持续时间、缓动函数等
+ */
+ constructor(element: UniElement | null, options: AnimationOptions) {
+ this.targetElement = element; // 保存目标元素引用
+
+ // 设置动画参数,使用选项值或默认值
+ this.animationDuration =
+ options.duration != null ? options.duration : this.animationDuration; // 设置动画持续时间
+ this.loopCount = options.loop != null ? options.loop : this.loopCount; // 设置循环次数
+ this.isAlternate = options.alternate != null ? options.alternate : this.isAlternate; // 设置往返播放
+ this.isSequentialMode =
+ options.sequential != null ? options.sequential : this.isSequentialMode; // 设置顺序执行模式
+
+ // 设置缓动函数,优先使用预定义函数
+ if (options.timingFunction != null) {
+ const easingParams = this.easingPresets.get(options.timingFunction); // 查找预定义缓动参数
+ if (easingParams != null) {
+ // 根据贝塞尔参数创建缓动函数
+ this.currentEasingFunction = createBezierEasing(
+ easingParams[0], // x1坐标
+ easingParams[1], // y1坐标
+ easingParams[2], // x2坐标
+ easingParams[3] // y2坐标
+ );
+ }
+ }
+
+ // 自定义贝塞尔曲线,会覆盖预定义函数
+ if (options.bezier != null && options.bezier.length == 4) {
+ this.currentEasingFunction = createBezierEasing(
+ options.bezier[0], // 自定义x1坐标
+ options.bezier[1], // 自定义y1坐标
+ options.bezier[2], // 自定义x2坐标
+ options.bezier[3] // 自定义y2坐标
+ );
+ }
+
+ // 设置回调函数,提供动画生命周期钩子
+ if (options.complete != null) {
+ this.onComplete = options.complete; // 动画完成回调
+ }
+ if (options.start != null) {
+ this.onStart = options.start; // 动画开始回调
+ }
+ if (options.frame != null) {
+ this.onFrame = options.frame; // 每帧更新回调
+ }
+ }
+
+ /**
+ * 从样式值中提取单位
+ * 解析CSS值中的单位部分,用于动画计算
+ * @param value 样式值,如 "100px", "50%"
+ * @param propertyName CSS属性名称,用于判断是否需要默认单位
+ * @returns 单位字符串
+ */
+ private extractUnit(value?: string, propertyName?: string): string {
+ if (value == null) return "px"; // 默认单位为px
+ const unit = value.replace(/[\d|\-|\+|\.]/g, ""); // 移除数字、负号、正号、小数点,保留单位
+
+ // opacity、z-index等属性无需单位
+ if (propertyName == "opacity" || propertyName == "z-index") {
+ return ""; // 返回空字符串表示无单位
+ }
+
+ return unit == "" ? "px" : unit; // 如果没有单位则默认为px
+ }
+
+ /**
+ * 添加自定义缓动函数
+ * 向引擎注册新的缓动函数,可在后续动画中使用
+ * @param name 缓动函数名称
+ * @param bezierParams 贝塞尔曲线参数 [x1, y1, x2, y2]
+ */
+ addCustomEasing(name: string, bezierParams: number[]): AnimationEngine {
+ if (bezierParams.length == 4) {
+ // 验证参数数量
+ this.easingPresets.set(name, bezierParams); // 添加到预设映射中
+ }
+ return this; // 返回自身支持链式调用
+ }
+
+ /**
+ * 设置动画反向播放
+ * 控制动画从结束值向起始值播放
+ * @param reverse 是否反向播放,null表示切换当前状态
+ */
+ setReverse(reverse: boolean | null = null): AnimationEngine {
+ if (reverse != null) {
+ this.isReversed = reverse; // 设置指定状态
+ } else {
+ this.isReversed = !this.isReversed; // 切换当前状态
+ }
+ return this; // 支持链式调用
+ }
+
+ /**
+ * 设置循环播放次数
+ * 控制动画重复执行的次数
+ * @param count 循环次数,-1表示无限循环
+ */
+ setLoopCount(count: number): AnimationEngine {
+ this.loopCount = count; // 设置循环次数
+ return this; // 支持链式调用
+ }
+
+ /**
+ * 设置动画持续时间
+ * 控制动画从开始到结束的总时长
+ * @param duration 持续时间(毫秒)
+ */
+ setDuration(duration: number): AnimationEngine {
+ this.animationDuration = duration; // 设置动画持续时间
+ return this; // 支持链式调用
+ }
+
+ /**
+ * 设置往返播放模式
+ * 控制动画是否在每次循环时反向播放
+ * @param alternate 是否往返播放
+ */
+ setAlternate(alternate: boolean): AnimationEngine {
+ this.isAlternate = alternate; // 设置往返播放标志
+ return this; // 支持链式调用
+ }
+
+ /**
+ * 设置顺序执行模式
+ * 控制多个属性是同时动画还是依次动画
+ * @param sequential 是否按属性顺序依次执行
+ */
+ setSequential(sequential: boolean): AnimationEngine {
+ this.isSequentialMode = sequential; // 设置执行模式
+ return this; // 支持链式调用
+ }
+
+ /**
+ * 添加动画属性
+ * 向动画引擎添加一个CSS属性的动画配置
+ * @param propertyName CSS属性名称
+ * @param fromValue 起始值(支持数字+单位,如"100px"、"50%")
+ * @param toValue 结束值(单位必须与起始值一致)
+ * @param unique 是否唯一,true时同名属性会被替换
+ */
+ addAttribute(
+ propertyName: string,
+ fromValue: string,
+ toValue: string,
+ unique: boolean = true
+ ): AnimationEngine {
+ const isColor = this.isColorProperty(propertyName); // 检测是否为颜色属性
+ const unit = isColor ? "" : this.extractUnit(fromValue, propertyName); // 提取单位
+
+ // 根据属性类型处理值
+ const processedFromValue = isColor
+ ? getDefaultColor(fromValue) // 颜色属性标准化
+ : parseFloat(fromValue).toString(); // 数值属性提取数字
+ const processedToValue = isColor
+ ? getDefaultColor(toValue) // 颜色属性标准化
+ : parseFloat(toValue).toString(); // 数值属性提取数字
+
+ // 查找是否已存在同名属性,用于决定是替换还是新增
+ let existingIndex = this.animationAttributes.findIndex(
+ (attr: AnimationAttribute): boolean => attr.propertyName == propertyName
+ );
+
+ if (!unique) {
+ existingIndex = -1; // 强制添加新属性,不替换
+ }
+
+ // 创建新的动画属性对象
+ const newAttribute: AnimationAttribute = {
+ fromValue: processedFromValue, // 处理后的起始值
+ toValue: processedToValue, // 处理后的结束值
+ unit: unit, // 单位
+ progress: 0, // 初始进度为0
+ currentValue: processedFromValue, // 当前值初始化为起始值
+ propertyName: propertyName // 属性名称
+ };
+
+ if (existingIndex == -1) {
+ this.animationAttributes.push(newAttribute); // 添加新属性
+ } else {
+ this.animationAttributes[existingIndex] = newAttribute; // 替换现有属性
+ }
+
+ return this; // 支持链式调用
+ }
+
+ /**
+ * 快捷方法:添加变换属性
+ */
+ transform(property: string, fromValue: string, toValue: string): AnimationEngine {
+ return this.addAttribute(property, fromValue, toValue);
+ }
+
+ /**
+ * 快捷方法:添加位移动画
+ */
+ translate(fromX: string, fromY: string, toX: string, toY: string): AnimationEngine {
+ this.addAttribute("translateX", fromX, toX);
+ this.addAttribute("translateY", fromY, toY);
+ return this;
+ }
+
+ /**
+ * 添加X轴位移动画
+ * @param fromX 起始X位置,可以使用"current"表示当前位置
+ * @param toX 结束X位置
+ * @returns
+ */
+ translateX(fromX: string, toX: string): AnimationEngine {
+ return this.addAttribute("translateX", fromX, toX);
+ }
+
+ /**
+ * 添加Y轴位移动画
+ * @param fromY 起始Y位置,可以使用"current"表示当前位置
+ * @param toY 结束Y位置
+ * @returns
+ */
+ translateY(fromY: string, toY: string): AnimationEngine {
+ return this.addAttribute("translateY", fromY, toY);
+ }
+
+ /**
+ * 快捷方法:添加缩放动画
+ */
+ scale(fromScale: string, toScale: string): AnimationEngine {
+ return this.addAttribute("scale", fromScale, toScale);
+ }
+
+ /**
+ * 快捷方法:添加旋转动画
+ */
+ rotate(fromDegree: string, toDegree: string): AnimationEngine {
+ return this.addAttribute("rotate", fromDegree, toDegree);
+ }
+
+ /**
+ * 快捷方法:添加透明度动画
+ */
+ opacity(fromOpacity: string, toOpacity: string): AnimationEngine {
+ return this.addAttribute("opacity", fromOpacity, toOpacity);
+ }
+
+ /**
+ * 线性插值计算
+ * 根据进度在两个数值之间进行插值,用于计算动画中间值
+ * @param startValue 起始值
+ * @param endValue 结束值
+ * @param progress 进度 (0-1)
+ */
+ private interpolateValue(startValue: number, endValue: number, progress: number): number {
+ return startValue + (endValue - startValue) * progress; // 线性插值公式:start + (end - start) * progress
+ }
+
+ /**
+ * 判断是否为颜色相关属性
+ * 检测CSS属性名是否与颜色相关,用于特殊的颜色动画处理
+ * @param propertyName 属性名称
+ */
+ private isColorProperty(propertyName: string): boolean {
+ return (
+ propertyName.indexOf("background") > -1 || // 背景颜色相关
+ propertyName.indexOf("color") > -1 || // 文字颜色相关
+ propertyName.indexOf("border-color") > -1 || // 边框颜色相关
+ propertyName.indexOf("shadow") > -1 // 阴影颜色相关
+ );
+ }
+
+ /**
+ * 判断是否为Transform相关属性
+ * 检测属性名是否为transform相关的CSS属性
+ * @param propertyName CSS属性名称
+ * @returns 是否为transform属性
+ */
+ private isTransformProperty(propertyName: string): boolean {
+ return (
+ propertyName == "scaleX" || // X轴缩放
+ propertyName == "scaleY" || // Y轴缩放
+ propertyName == "scale" || // 等比缩放
+ propertyName == "rotateX" || // X轴旋转
+ propertyName == "rotateY" || // Y轴旋转
+ propertyName == "rotate" || // Z轴旋转
+ propertyName == "translateX" || // X轴位移
+ propertyName == "translateY" || // Y轴位移
+ propertyName == "translate" // 双轴位移
+ );
+ }
+
+ /**
+ * 设置元素样式属性
+ * 根据属性类型应用相应的样式值,支持transform、颜色、普通数值属性
+ * @param propertyName 属性名称
+ * @param currentValue 当前值
+ * @param unit 单位
+ * @param progress 动画进度
+ * @param attribute 动画属性对象
+ */
+ private setElementProperty(
+ propertyName: string,
+ currentValue: number,
+ unit: string,
+ progress: number,
+ attribute: AnimationAttribute
+ ): void {
+ if (this.targetElement == null) return; // 没有目标元素时直接返回
+
+ const element = this.targetElement; // 获取目标元素引用
+ const valueStr = currentValue.toFixed(2); // 数值保留两位小数
+
+ // #ifdef MP
+ if (element.style == null) {
+ return;
+ }
+ // #endif
+
+ // Transform 相关属性处理,使用CSS transform属性
+ switch (propertyName) {
+ case "scaleX": // X轴缩放
+ element.style!.setProperty("transform", `scaleX(${currentValue})`);
+ break;
+ case "scaleY": // Y轴缩放
+ element.style!.setProperty("transform", `scaleY(${currentValue})`);
+ break;
+ case "scale": // 等比缩放
+ element.style!.setProperty("transform", `scale(${currentValue})`);
+ break;
+ case "rotateX": // X轴旋转
+ element.style!.setProperty("transform", `rotateX(${valueStr + unit})`);
+ break;
+ case "rotateY": // Y轴旋转
+ element.style!.setProperty("transform", `rotateY(${valueStr + unit})`);
+ break;
+ case "rotate": // Z轴旋转
+ element.style!.setProperty("transform", `rotate(${valueStr + unit})`);
+ break;
+ case "translateX": // X轴位移
+ element.style!.setProperty("transform", `translateX(${valueStr + unit})`);
+ break;
+ case "translateY": // Y轴位移
+ element.style!.setProperty("transform", `translateY(${valueStr + unit})`);
+ break;
+ case "translate": // 双轴位移
+ element.style!.setProperty(
+ "transform",
+ `translate(${valueStr + unit},${valueStr + unit})`
+ );
+ break;
+ default:
+ // 颜色属性处理,需要进行RGBA插值
+ if (this.isColorProperty(propertyName)) {
+ const startColor = hexToRgb(attribute.fromValue); // 解析起始颜色
+ const endColor = hexToRgb(attribute.toValue); // 解析结束颜色
+
+ // 提取起始颜色的RGBA分量,兼容不同的JSON对象访问方式
+ const startR =
+ startColor.getNumber != null
+ ? startColor.getNumber("r")
+ : (startColor["r"] as number);
+ const startG =
+ startColor.getNumber != null
+ ? startColor.getNumber("g")
+ : (startColor["g"] as number);
+ const startB =
+ startColor.getNumber != null
+ ? startColor.getNumber("b")
+ : (startColor["b"] as number);
+ const startA =
+ startColor.getNumber != null
+ ? startColor.getNumber("a")
+ : (startColor["a"] as number);
+
+ // 提取结束颜色的RGBA分量
+ const endR =
+ endColor.getNumber != null
+ ? endColor.getNumber("r")
+ : (endColor["r"] as number);
+ const endG =
+ endColor.getNumber != null
+ ? endColor.getNumber("g")
+ : (endColor["g"] as number);
+ const endB =
+ endColor.getNumber != null
+ ? endColor.getNumber("b")
+ : (endColor["b"] as number);
+ const endA =
+ endColor.getNumber != null
+ ? endColor.getNumber("a")
+ : (endColor["a"] as number);
+
+ // 对每个颜色分量进行插值计算
+ const r = this.interpolateValue(
+ startR != null ? startR : 0,
+ endR != null ? endR : 0,
+ progress
+ );
+ const g = this.interpolateValue(
+ startG != null ? startG : 0,
+ endG != null ? endG : 0,
+ progress
+ );
+ const b = this.interpolateValue(
+ startB != null ? startB : 0,
+ endB != null ? endB : 0,
+ progress
+ );
+ const a = this.interpolateValue(
+ startA != null ? startA : 1,
+ endA != null ? endA : 1,
+ progress
+ );
+
+ // 设置RGBA颜色值
+ element.style!.setProperty(
+ propertyName,
+ `rgba(${r.toFixed(0)},${g.toFixed(0)},${b.toFixed(0)},${a.toFixed(1)})`
+ );
+ } else {
+ // 普通数值属性处理,直接设置数值和单位
+ element.style!.setProperty(propertyName, valueStr + unit);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Web平台动画运行方法 (H5/iOS/Harmony)
+ * 使用requestAnimationFrame实现流畅的动画循环
+ */
+ private runWebAnimation(): void {
+ // #ifdef H5 || APP-IOS || APP-HARMONY
+ const self = this; // 保存this引用,避免在内部函数中this指向改变
+ self.startTimestamp = 0; // 重置开始时间戳
+
+ // 取消之前的动画帧,避免重复执行
+ if (self.animationFrameId != null) {
+ cancelAnimationFrame(self.animationFrameId);
+ }
+
+ function animationLoop(): void {
+ // 初始化开始时间,首次执行时记录时间戳
+ if (self.startTimestamp <= 0) {
+ self.startTimestamp = Date.now();
+ }
+
+ // 计算当前进度:(已用时间 / 总时间) + 暂停前的进度
+ const elapsed = Date.now() - self.startTimestamp; // 已经过的时间
+ const progress = Math.min(elapsed / self.animationDuration + self.currentProgress, 1.0); // 限制进度不超过1
+
+ // 执行动画更新,应用当前进度到所有属性
+ self.updateAnimationFrame(progress);
+
+ // 检查暂停状态
+ if (self.isPaused) {
+ self.isRunning = false; // 停止运行标志
+ self.currentProgress = progress; // 保存当前进度,用于恢复
+ console.log("动画已暂停");
+ return; // 退出动画循环
+ }
+
+ // 检查动画完成或停止
+ if (progress >= 1.0 || self.isStopping) {
+ self.handleAnimationComplete(); // 处理动画完成逻辑
+ return; // 退出动画循环
+ }
+
+ // 继续下一帧,动画未完成且仍在运行
+ if (progress < 1.0 && self.isRunning) {
+ self.onFrame(progress); // 触发每帧回调
+ self.animationFrameId = requestAnimationFrame(animationLoop); // 请求下一帧
+ }
+ }
+
+ // 开始动画,触发开始回调并启动动画循环
+ self.onStart();
+ animationLoop();
+ // #endif
+ }
+
+ /**
+ * 更新动画帧
+ * 根据执行模式更新所有或当前属性的动画值
+ * @param progress 当前进度 (0-1)
+ */
+ private updateAnimationFrame(progress: number): void {
+ if (this.targetElement == null) return; // 没有目标元素时直接返回
+
+ if (!this.isSequentialMode) {
+ // 并行执行所有属性动画,所有属性同时进行动画
+ for (let i = 0; i < this.animationAttributes.length; i++) {
+ this.updateSingleAttribute(this.animationAttributes[i], progress);
+ }
+ } else {
+ // 顺序执行属性动画,一个接一个地执行属性动画
+ if (this.currentAttributeIndex < this.animationAttributes.length) {
+ this.updateSingleAttribute(
+ this.animationAttributes[this.currentAttributeIndex],
+ progress
+ );
+ }
+ }
+ }
+
+ /**
+ * 更新单个属性的动画
+ * 计算属性的当前值并应用到元素上
+ * @param attribute 动画属性
+ * @param progress 进度
+ */
+ private updateSingleAttribute(attribute: AnimationAttribute, progress: number): void {
+ attribute.progress = progress; // 更新属性的进度记录
+
+ if (!this.isColorProperty(attribute.propertyName)) {
+ // 数值属性处理
+ const fromValue = parseFloat(attribute.fromValue); // 起始数值
+ const toValue = parseFloat(attribute.toValue); // 结束数值
+
+ // 应用缓动函数,将线性进度转换为缓动进度
+ let easedProgress = progress;
+ if (this.currentEasingFunction != null) {
+ easedProgress = this.currentEasingFunction(progress);
+ }
+
+ // 计算当前值,使用缓动进度进行插值
+ let currentValue = this.interpolateValue(fromValue, toValue, easedProgress);
+
+ // 处理反向和往返播放,交换起始和结束值
+ if (this.isReversed || this.isAlternateReversed) {
+ currentValue = this.interpolateValue(toValue, fromValue, easedProgress);
+ }
+
+ // 应用计算出的值到元素属性
+ this.setElementProperty(
+ attribute.propertyName,
+ currentValue,
+ attribute.unit,
+ progress,
+ attribute
+ );
+ } else {
+ // 颜色属性处理,progress参数会在setElementProperty中用于颜色插值
+ this.setElementProperty(attribute.propertyName, 0, attribute.unit, progress, attribute);
+ }
+ }
+
+ /**
+ * 处理动画完成
+ */
+ private handleAnimationComplete(): void {
+ // 顺序模式下检查是否还有未执行的属性
+ if (
+ this.isSequentialMode &&
+ this.currentAttributeIndex < this.animationAttributes.length - 1
+ ) {
+ this.currentAttributeIndex++;
+ this.currentProgress = 0;
+ this.restartAnimation();
+ return;
+ }
+
+ // 重置状态
+ // #ifdef H5 || APP-IOS || APP-HARMONY
+ if (this.animationFrameId != null) {
+ cancelAnimationFrame(this.animationFrameId);
+ }
+ // #endif
+
+ this.currentAttributeIndex = 0;
+ this.currentProgress = 0;
+
+ // 处理往返播放
+ if (this.isAlternate) {
+ this.isAlternateReversed = !this.isAlternateReversed;
+ }
+
+ // 处理循环播放
+ if (this.loopCount == -1) {
+ // 无限循环
+ this.restartAnimation();
+ return;
+ } else {
+ this.currentLoop++;
+ if (this.currentLoop < this.loopCount) {
+ this.restartAnimation();
+ return;
+ }
+ }
+
+ // 动画完成
+ this.isRunning = false;
+ this.onComplete();
+ }
+
+ /**
+ * 根据平台重新启动动画
+ */
+ private restartAnimation(): void {
+ // 重置开始时间戳,确保循环动画正确计时
+ this.startTimestamp = 0;
+
+ // 根据平台选择合适的动画引擎
+ // #ifdef H5 || APP-IOS || APP-HARMONY
+ this.runWebAnimation();
+ // #endif
+ // #ifdef APP-ANDROID
+ this.runAndroidAnimation();
+ // #endif
+ // #ifdef MP
+ this.runMPAnimation();
+ // #endif
+ }
+
+ /**
+ * Android平台动画运行方法
+ */
+ private runAndroidAnimation(): void {
+ // #ifdef APP-ANDROID
+ const self = this;
+ self.startTimestamp = 0;
+
+ // 初始化Choreographer
+ if (self.choreographer == null) {
+ self.choreographer = Choreographer.getInstance();
+ } else {
+ // 清除之前的回调
+ if (self.frameCallback != null) {
+ self.choreographer.removeFrameCallback(self.frameCallback);
+ }
+ }
+
+ /**
+ * Android原生帧回调类
+ */
+ class frameCallback extends Choreographer.FrameCallback {
+ // @ts-ignore
+ override doFrame(frameTimeNanos: Long) {
+ // 检查动画是否应该停止
+ if (!self.isRunning || self.isStopping) {
+ return;
+ }
+
+ // 初始化开始时间
+ if (self.startTimestamp <= 0) {
+ self.startTimestamp = Date.now();
+ }
+
+ // 计算当前进度
+ const elapsed = Date.now() - self.startTimestamp;
+ const progress = Math.min(
+ elapsed / self.animationDuration + self.currentProgress,
+ 1.0
+ );
+
+ // 执行动画更新
+ self.updateAnimationFrame(progress);
+
+ // 检查暂停状态
+ if (self.isPaused) {
+ self.isRunning = false;
+ self.currentProgress = progress;
+ return;
+ }
+
+ // 检查动画完成或停止
+ if (progress >= 1.0 || self.isStopping) {
+ self.handleAnimationComplete();
+ return;
+ }
+
+ // 继续下一帧
+ if (progress < 1.0 && self.isRunning && !self.isStopping) {
+ self.onFrame(progress);
+ if (self.choreographer != null) {
+ self.choreographer.postFrameCallback(this);
+ }
+ }
+ }
+ }
+
+ // 启动动画
+ self.onStart();
+ self.frameCallback = new frameCallback();
+ self.choreographer!.postFrameCallback(self.frameCallback);
+ // #endif
+ }
+
+ /**
+ * 小程序平台动画运行方法
+ */
+ private runMPAnimation(): void {
+ // #ifdef MP
+ const self = this;
+ self.startTimestamp = 0;
+
+ // 清除之前的定时器
+ if (self.displayLinkTimer != 0) {
+ clearTimeout(self.displayLinkTimer);
+ }
+
+ function animationLoop(): void {
+ // 初始化开始时间
+ if (self.startTimestamp <= 0) {
+ self.startTimestamp = Date.now();
+ }
+
+ // 计算当前进度
+ const elapsed = Date.now() - self.startTimestamp;
+ const progress = Math.min(elapsed / self.animationDuration + self.currentProgress, 1.0);
+
+ // 执行动画更新
+ self.updateAnimationFrame(progress);
+
+ // 检查暂停状态
+ if (self.isPaused) {
+ self.isRunning = false;
+ self.currentProgress = progress;
+ return;
+ }
+
+ // 检查动画完成或停止
+ if (progress >= 1.0 || self.isStopping) {
+ self.handleAnimationComplete();
+ return;
+ }
+
+ // 继续下一帧
+ if (progress < 1.0 && self.isRunning) {
+ self.onFrame(progress);
+ self.displayLinkTimer = setTimeout(animationLoop, 16) as any; // 约60fps
+ }
+ }
+
+ // 开始动画
+ self.onStart();
+ animationLoop();
+ // #endif
+ }
+
+ /**
+ * 开始播放动画
+ */
+ play(): AnimationEngine {
+ if (this.isRunning) return this;
+
+ // 初始化动画状态
+ this.isRunning = true;
+ this.isStopping = false;
+ this.isPaused = false;
+ this.currentLoop = 0;
+ this.currentAttributeIndex = 0;
+
+ // 根据平台选择合适的动画引擎
+ // #ifdef H5 || APP-IOS || APP-HARMONY
+ this.runWebAnimation();
+ // #endif
+ // #ifdef APP-ANDROID
+ this.runAndroidAnimation();
+ // #endif
+ // #ifdef MP
+ this.runMPAnimation();
+ // #endif
+
+ return this;
+ }
+
+ /**
+ * 异步播放动画,支持await
+ * @returns Promise,动画完成时resolve
+ */
+ playAsync(): Promise {
+ return new Promise((resolve) => {
+ const originalComplete = this.onComplete;
+ this.onComplete = () => {
+ originalComplete();
+ resolve();
+ };
+ this.play();
+ });
+ }
+
+ /**
+ * 停止动画
+ * 会立即停止动画并跳转到结束状态
+ */
+ stop(): AnimationEngine {
+ this.isStopping = true;
+ this.currentProgress = 0;
+ this.currentAttributeIndex = this.animationAttributes.length;
+
+ // 清理平台相关的动画控制器
+ // #ifdef WEB || APP-IOS || APP-HARMONY
+ if (this.animationFrameId != null) {
+ cancelAnimationFrame(this.animationFrameId);
+ this.animationFrameId = null;
+ }
+ // #endif
+
+ // #ifdef APP-ANDROID
+ if (this.choreographer != null && this.frameCallback != null) {
+ this.choreographer.removeFrameCallback(this.frameCallback);
+ }
+ // #endif
+
+ // #ifdef MP
+ if (this.displayLinkTimer != 0) {
+ clearTimeout(this.displayLinkTimer);
+ this.displayLinkTimer = 0;
+ }
+ // #endif
+
+ this.isRunning = false;
+ return this;
+ }
+
+ /**
+ * 暂停动画
+ * 保留当前状态,可以通过play()恢复
+ */
+ pause(): AnimationEngine {
+ this.isPaused = true;
+ return this;
+ }
+
+ /**
+ * 恢复暂停的动画
+ */
+ resume(): AnimationEngine {
+ if (this.isPaused) {
+ this.isPaused = false;
+ this.play();
+ }
+ return this;
+ }
+
+ /**
+ * 清空应用到元素上的动画样式
+ * 只清空实际被动画引擎设置过的CSS属性
+ */
+ private clearElementStyles(): void {
+ if (this.targetElement == null) return;
+
+ const element = this.targetElement;
+
+ // 清空所有动画属性列表中记录的属性
+ for (const attr of this.animationAttributes) {
+ const propertyName = attr.propertyName;
+
+ // Transform 相关属性需要清空transform
+ if (this.isTransformProperty(propertyName)) {
+ element.style!.setProperty("transform", "");
+ } else {
+ // 其他属性直接清空
+ element.style!.setProperty(propertyName, "");
+ }
+ }
+ }
+
+ /**
+ * 重置动画到初始状态,清空所有内容
+ */
+ reset(): AnimationEngine {
+ // 停止当前动画
+ this.stop();
+
+ // 清空应用到元素上的所有样式
+ this.clearElementStyles();
+
+ // 重置所有动画状态
+ this.currentProgress = 0;
+ this.currentLoop = 0;
+ this.currentAttributeIndex = 0;
+ this.isAlternateReversed = false;
+ this.isReversed = false;
+ this.isPaused = false;
+ this.isStopping = true;
+ this.startTimestamp = 0;
+
+ // 清空动画属性列表
+ this.animationAttributes = [];
+
+ // 重置缓动函数
+ this.currentEasingFunction = null;
+
+ // 重置回调函数
+ this.onComplete = () => {};
+ this.onStart = () => {};
+ this.onFrame = () => {};
+
+ // 清理平台相关的动画控制器
+ // #ifdef WEB || APP-IOS || APP-HARMONY
+ if (this.animationFrameId != null) {
+ cancelAnimationFrame(this.animationFrameId);
+ this.animationFrameId = null;
+ }
+ // #endif
+
+ // #ifdef APP-ANDROID
+ if (this.choreographer != null && this.frameCallback != null) {
+ this.choreographer.removeFrameCallback(this.frameCallback);
+ this.frameCallback = null;
+ }
+ this.choreographer = null;
+ // #endif
+
+ // #ifdef MP
+ if (this.displayLinkTimer != 0) {
+ clearTimeout(this.displayLinkTimer);
+ this.displayLinkTimer = 0;
+ }
+ // #endif
+
+ return this;
+ }
+
+ /**
+ * 获取当前动画进度
+ */
+ getProgress(): number {
+ return this.currentProgress;
+ }
+
+ /**
+ * 获取动画是否正在运行
+ */
+ isAnimating(): boolean {
+ return this.isRunning;
+ }
+
+ /**
+ * 获取当前循环次数
+ */
+ getCurrentLoop(): number {
+ return this.currentLoop;
+ }
+
+ /**
+ * 清除所有动画属性
+ */
+ clearAttributes(): AnimationEngine {
+ this.animationAttributes = [];
+ return this;
+ }
+
+ /**
+ * 获取动画属性数量
+ */
+ getAttributeCount(): number {
+ return this.animationAttributes.length;
+ }
+
+ /**
+ * 淡入动画
+ * @param duration 持续时间
+ */
+ fadeIn(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration).opacity("0", "1");
+ }
+
+ /**
+ * 淡出动画
+ * @param duration 持续时间
+ */
+ fadeOut(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration).opacity("1", "0");
+ }
+
+ /**
+ * 滑入动画(从左)
+ * @param duration 持续时间
+ */
+ slideInLeft(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration).translateX("-100%", "0%").opacity("0", "1");
+ }
+
+ /**
+ * 滑入动画(从右)
+ * @param duration 持续时间
+ */
+ slideInRight(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration).translateX("100%", "0%").opacity("0", "1");
+ }
+
+ /**
+ * 滑入动画(从上)
+ * @param duration 持续时间
+ */
+ slideInUp(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("translateY", "-100%", "0%")
+ .opacity("0", "1");
+ }
+
+ /**
+ * 滑入动画(从下)
+ * @param duration 持续时间
+ */
+ slideInDown(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("translateY", "100%", "0%")
+ .opacity("0", "1");
+ }
+
+ /**
+ * 缩放动画(放大)
+ * @param duration 持续时间
+ */
+ zoomIn(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration).scale("0", "1").opacity("0", "1");
+ }
+
+ /**
+ * 缩放动画(缩小)
+ * @param duration 持续时间
+ */
+ zoomOut(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration).scale("1", "0").opacity("1", "0");
+ }
+
+ /**
+ * 旋转动画
+ * @param duration 持续时间
+ * @param degrees 旋转角度
+ */
+ rotateIn(duration: number = 500, degrees: number = 360): AnimationEngine {
+ return this.setDuration(duration).rotate("0deg", `${degrees}deg`).opacity("0", "1");
+ }
+
+ /**
+ * 旋转退出动画
+ * @param duration 持续时间
+ * @param degrees 旋转角度
+ */
+ rotateOut(duration: number = 500, degrees: number = 360): AnimationEngine {
+ return this.setDuration(duration).rotate("0deg", `${degrees}deg`).opacity("1", "0");
+ }
+
+ /**
+ * 弹跳动画
+ * @param duration 持续时间
+ */
+ bounce(duration: number = 600): AnimationEngine {
+ return this.setDuration(duration)
+ .addCustomEasing("bounce", [0.68, -0.55, 0.265, 1.55])
+ .scale("1", "1.1")
+ .setAlternate(true)
+ .setLoopCount(2);
+ }
+
+ /**
+ * 摇摆动画
+ * @param duration 持续时间
+ */
+ shake(duration: number = 500): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("translateX", "0px", "10px")
+ .setAlternate(true)
+ .setLoopCount(6);
+ }
+
+ /**
+ * 链式动画:支持多个动画依次执行
+ * @param animations 动画配置函数数组
+ */
+ sequence(animations: ((engine: AnimationEngine) => AnimationEngine)[]): AnimationEngine {
+ const self = this;
+
+ if (animations.length == 0) {
+ return this;
+ }
+
+ // 执行第一个动画
+ const firstEngine = animations[0](new AnimationEngine(this.targetElement, {}));
+
+ // 如果只有一个动画,直接返回
+ if (animations.length == 1) {
+ return firstEngine;
+ }
+
+ // 递归设置后续动画
+ function setNextAnimation(
+ currentEngine: AnimationEngine,
+ remainingAnimations: ((engine: AnimationEngine) => AnimationEngine)[]
+ ): void {
+ if (remainingAnimations.length == 0) {
+ return;
+ }
+
+ const originalComplete = currentEngine.onComplete;
+ currentEngine.onComplete = () => {
+ originalComplete();
+
+ // 执行下一个动画
+ const nextEngine = remainingAnimations[0](
+ new AnimationEngine(self.targetElement, {})
+ );
+
+ // 如果还有更多动画,继续设置链式
+ if (remainingAnimations.length > 1) {
+ setNextAnimation(nextEngine, remainingAnimations.slice(1));
+ }
+
+ nextEngine.play();
+ };
+ }
+
+ // 设置动画链
+ setNextAnimation(firstEngine, animations.slice(1));
+
+ return firstEngine;
+ }
+
+ /**
+ * 滑出动画(向左)
+ * @param duration 持续时间
+ */
+ slideOutLeft(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration).translateX("0%", "-100%").opacity("1", "0");
+ }
+
+ /**
+ * 滑出动画(向右)
+ * @param duration 持续时间
+ */
+ slideOutRight(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration).translateX("0%", "100%").opacity("1", "0");
+ }
+
+ /**
+ * 滑出动画(向上)
+ * @param duration 持续时间
+ */
+ slideOutUp(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("translateY", "0%", "-100%")
+ .opacity("1", "0");
+ }
+
+ /**
+ * 滑出动画(向下)
+ * @param duration 持续时间
+ */
+ slideOutDown(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("translateY", "0%", "100%")
+ .opacity("1", "0");
+ }
+
+ /**
+ * 翻转动画(水平)
+ * @param duration 持续时间
+ */
+ flipX(duration: number = 600): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("rotateX", "0deg", "180deg")
+ .addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
+ }
+
+ /**
+ * 翻转动画(垂直)
+ * @param duration 持续时间
+ */
+ flipY(duration: number = 600): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("rotateY", "0deg", "180deg")
+ .addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
+ }
+
+ /**
+ * 弹性进入动画
+ * @param duration 持续时间
+ */
+ elasticIn(duration: number = 600): AnimationEngine {
+ return this.setDuration(duration)
+ .scale("0", "1")
+ .opacity("0", "1")
+ .addCustomEasing("elastic", [0.175, 0.885, 0.32, 1.275]);
+ }
+
+ /**
+ * 弹性退出动画
+ * @param duration 持续时间
+ */
+ elasticOut(duration: number = 600): AnimationEngine {
+ return this.setDuration(duration)
+ .scale("1", "0")
+ .opacity("1", "0")
+ .addCustomEasing("elastic", [0.68, -0.55, 0.265, 1.55]);
+ }
+
+ /**
+ * 回弹动画
+ * @param duration 持续时间
+ */
+ rubberBand(duration: number = 1000): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("scaleX", "1", "1.25")
+ .addAttribute("scaleY", "1", "0.75")
+ .setAlternate(true)
+ .setLoopCount(2)
+ .addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
+ }
+
+ /**
+ * 摆动动画
+ * @param duration 持续时间
+ */
+ swing(duration: number = 1000): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("rotate", "0deg", "15deg")
+ .setAlternate(true)
+ .setLoopCount(4)
+ .addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
+ }
+
+ /**
+ * 抖动动画
+ * @param duration 持续时间
+ */
+ wobble(duration: number = 1000): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("translateX", "0px", "25px")
+ .addAttribute("rotate", "0deg", "5deg")
+ .setAlternate(true)
+ .setLoopCount(4);
+ }
+
+ /**
+ * 滚动进入动画
+ * @param duration 持续时间
+ */
+ rollIn(duration: number = 600): AnimationEngine {
+ return this.setDuration(duration)
+ .translateX("-100%", "0%")
+ .rotate("-120deg", "0deg")
+ .opacity("0", "1");
+ }
+
+ /**
+ * 滚动退出动画
+ * @param duration 持续时间
+ */
+ rollOut(duration: number = 600): AnimationEngine {
+ return this.setDuration(duration)
+ .translateX("0%", "100%")
+ .rotate("0deg", "120deg")
+ .opacity("1", "0");
+ }
+
+ /**
+ * 灯光效果动画
+ * @param duration 持续时间
+ */
+ lightSpeed(duration: number = 500): AnimationEngine {
+ return this.setDuration(duration)
+ .translateX("-100%", "0%")
+ .addAttribute("skewX", "-30deg", "0deg")
+ .opacity("0", "1")
+ .addCustomEasing("ease-out", [0.25, 0.46, 0.45, 0.94]);
+ }
+
+ /**
+ * 浮动动画
+ * @param duration 持续时间
+ */
+ float(duration: number = 3000): AnimationEngine {
+ return this.setDuration(duration)
+ .translateY("0px", "-10px")
+ .setAlternate(true)
+ .setLoopCount(-1)
+ .addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
+ }
+
+ /**
+ * 呼吸动画
+ * @param duration 持续时间
+ */
+ breathe(duration: number = 2000): AnimationEngine {
+ return this.setDuration(duration)
+ .scale("1", "1.1")
+ .setAlternate(true)
+ .setLoopCount(-1)
+ .addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
+ }
+
+ /**
+ * 发光动画
+ * @param duration 持续时间
+ */
+ glow(duration: number = 1500): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute(
+ "boxShadow",
+ "0 0 5px rgba(255,255,255,0.5)",
+ "0 0 20px rgba(255,255,255,1)"
+ )
+ .setAlternate(true)
+ .setLoopCount(-1)
+ .addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
+ }
+
+ /**
+ * 进度条动画
+ * @param duration 持续时间
+ * @param progress 进度百分比 (0-100)
+ */
+ progressBar(duration: number = 1000, progress: number = 100): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("width", "0%", `${progress}%`)
+ .addCustomEasing("ease-out", [0.25, 0.46, 0.45, 0.94]);
+ }
+
+ /**
+ * 模态框进入动画
+ * @param duration 持续时间
+ */
+ modalIn(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration)
+ .scale("0.7", "1")
+ .opacity("0", "1")
+ .addCustomEasing("ease-out", [0.25, 0.46, 0.45, 0.94]);
+ }
+
+ /**
+ * 模态框退出动画
+ * @param duration 持续时间
+ */
+ modalOut(duration: number = 300): AnimationEngine {
+ return this.setDuration(duration)
+ .scale("1", "0.7")
+ .opacity("1", "0")
+ .addCustomEasing("ease-in", [0.42, 0.0, 1.0, 1.0]);
+ }
+
+ /**
+ * 卡片翻转动画
+ * @param duration 持续时间
+ */
+ cardFlip(duration: number = 600): AnimationEngine {
+ return this.setDuration(duration)
+ .addAttribute("rotateY", "0deg", "180deg")
+ .addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
+ }
+
+ /**
+ * 波纹扩散动画
+ * @param duration 持续时间
+ */
+ ripple(duration: number = 600): AnimationEngine {
+ return this.setDuration(duration)
+ .scale("0", "4")
+ .opacity("0.7", "0")
+ .addCustomEasing("ease-out", [0.25, 0.46, 0.45, 0.94]);
+ }
+}
+
+/**
+ * 创建动画实例
+ * @param element 目标元素
+ * @param options 动画选项
+ */
+export function createAnimation(
+ element: UniElement | null,
+ options: AnimationOptions = {}
+): AnimationEngine {
+ return new AnimationEngine(element, options);
+}
diff --git a/cool-unix/cool/ctx/index.ts b/cool-unix/cool/ctx/index.ts
new file mode 100644
index 0000000..07dd61e
--- /dev/null
+++ b/cool-unix/cool/ctx/index.ts
@@ -0,0 +1,93 @@
+import { isArray, parse } from "../utils";
+
+type Page = {
+ path: string;
+ style?: UTSJSONObject;
+ meta?: UTSJSONObject;
+};
+
+type SubPackage = {
+ root: string;
+ pages: Page[];
+};
+
+export type TabBarItem = {
+ text?: string;
+ pagePath: string;
+ iconPath?: string;
+ selectedIconPath?: string;
+ visible?: boolean;
+};
+
+export type TabBar = {
+ custom?: boolean;
+ color?: string;
+ selectedColor?: string;
+ backgroundColor?: string;
+ borderStyle?: string;
+ blurEffect?: "dark" | "extralight" | "light" | "none";
+ list?: TabBarItem[];
+ position?: "top" | "bottom";
+ fontSize?: string;
+ iconWidth?: string;
+ spacing?: string;
+ height?: string;
+ backgroundImage?: string;
+ backgroundRepeat?: "repeat" | "repeat-x" | "repeat-y" | "no-repeat";
+ redDotColor?: string;
+};
+
+export type Ctx = {
+ appid: string;
+ globalStyle: UTSJSONObject;
+ pages: Page[];
+ uniIdRouter: UTSJSONObject;
+ theme: UTSJSONObject;
+ tabBar: TabBar;
+ subPackages: SubPackage[];
+ SAFE_CHAR_MAP_LOCALE: string[][];
+ color: UTSJSONObject;
+};
+
+// 初始化 ctx 对象,不可修改!!
+export const ctx = parse({})!;
+
+console.log(ctx);
+
+// PAGES 用于存储所有页面的路径及样式信息
+export let PAGES: Page[] = [...ctx.pages];
+
+// 遍历 ctx.subPackages,将所有子包下的页面信息合并到 PAGES 中
+if (isArray(ctx.subPackages)) {
+ ctx.subPackages.forEach((a) => {
+ a.pages.forEach((b) => {
+ PAGES.push({
+ path: a.root + "/" + b.path, // 拼接子包根路径和页面路径
+ style: b.style,
+ meta: b.meta
+ });
+ });
+ });
+}
+
+// 确保每个页面路径都以 "/" 开头,符合 uni-app x 规范
+PAGES.forEach((e) => {
+ if (!e.path.startsWith("/")) {
+ e.path = "/" + e.path;
+ }
+});
+
+// TABS 用于存储 tabBar 配置项
+export let TABS: TabBarItem[] = [];
+
+// 如果 tabBar 配置存在且列表不为空,则初始化 TABS
+if (ctx.tabBar.list != null) {
+ TABS = ctx.tabBar.list;
+
+ // 确保每个 tabBar 页面的路径都以 "/" 开头
+ TABS.forEach((e) => {
+ if (!e.pagePath.startsWith("/")) {
+ e.pagePath = "/" + e.pagePath;
+ }
+ });
+}
diff --git a/cool-unix/cool/hooks/cache.ts b/cool-unix/cool/hooks/cache.ts
new file mode 100644
index 0000000..0f9056c
--- /dev/null
+++ b/cool-unix/cool/hooks/cache.ts
@@ -0,0 +1,28 @@
+import { reactive, watch } from "vue";
+import { isDark } from "../theme";
+
+type CacheData = {
+ key: number;
+};
+
+type UseCache = {
+ cache: CacheData;
+};
+
+export const useCache = (source: () => any[]): UseCache => {
+ const cache = reactive({
+ key: 0
+ });
+
+ watch(source, () => {
+ cache.key++;
+ });
+
+ watch(isDark, () => {
+ cache.key++;
+ });
+
+ return {
+ cache
+ };
+};
diff --git a/cool-unix/cool/hooks/index.ts b/cool-unix/cool/hooks/index.ts
new file mode 100644
index 0000000..2305990
--- /dev/null
+++ b/cool-unix/cool/hooks/index.ts
@@ -0,0 +1,6 @@
+export * from "./cache";
+export * from "./long-press";
+export * from "./pager";
+export * from "./parent";
+export * from "./refs";
+export * from "./wx";
diff --git a/cool-unix/cool/hooks/long-press.ts b/cool-unix/cool/hooks/long-press.ts
new file mode 100644
index 0000000..b317166
--- /dev/null
+++ b/cool-unix/cool/hooks/long-press.ts
@@ -0,0 +1,100 @@
+import { vibrate } from "@/uni_modules/cool-vibrate";
+import { onUnmounted, ref, type Ref } from "vue";
+
+// 长按触发延迟时间,单位毫秒
+const DELAY = 500;
+// 长按重复执行间隔时间,单位毫秒
+const REPEAT = 100;
+
+/**
+ * 长按操作钩子函数返回类型
+ */
+type UseLongPress = {
+ // 开始长按
+ start: (cb: () => void) => void;
+ // 停止长按
+ stop: () => void;
+ // 清除定时器
+ clear: () => void;
+ // 是否正在长按中
+ isPressing: Ref;
+};
+
+/**
+ * 长按操作钩子函数
+ * 支持长按持续触发,可用于数字输入框等需要连续操作的场景
+ */
+export const useLongPress = (): UseLongPress => {
+ // 是否正在长按中
+ const isPressing = ref(false);
+ // 长按延迟定时器
+ let pressTimer: number = 0;
+ // 重复执行定时器
+ let repeatTimer: number = 0;
+
+ /**
+ * 清除所有定时器
+ * 重置长按状态
+ */
+ const clear = () => {
+ // 清除长按延迟定时器
+ if (pressTimer != 0) {
+ clearTimeout(pressTimer);
+ pressTimer = 0;
+ }
+ // 清除重复执行定时器
+ if (repeatTimer != 0) {
+ clearInterval(repeatTimer);
+ repeatTimer = 0;
+ }
+ // 重置长按状态
+ isPressing.value = false;
+ };
+
+ /**
+ * 开始长按操作
+ * @param cb 长按时重复执行的回调函数
+ */
+ const start = (cb: () => void) => {
+ // 清除已有定时器
+ clear();
+
+ // 立即执行一次回调
+ cb();
+
+ // 延迟500ms后开始长按
+ // @ts-ignore
+ pressTimer = setTimeout(() => {
+ // 震动
+ vibrate(1);
+
+ // 设置长按状态
+ isPressing.value = true;
+ // 每100ms重复执行回调
+ // @ts-ignore
+ repeatTimer = setInterval(() => {
+ cb();
+ }, REPEAT);
+ }, DELAY);
+ };
+
+ /**
+ * 停止长按操作
+ * 清除定时器并重置状态
+ */
+ const stop = () => {
+ clear();
+ };
+
+ // 组件卸载时清理定时器
+ onUnmounted(() => {
+ clear();
+ });
+
+ return {
+ start,
+ stop,
+ clear,
+ isPressing
+ };
+};
diff --git a/cool-unix/cool/hooks/pager.ts b/cool-unix/cool/hooks/pager.ts
new file mode 100644
index 0000000..54ef392
--- /dev/null
+++ b/cool-unix/cool/hooks/pager.ts
@@ -0,0 +1,113 @@
+import { computed, ref } from "vue";
+import { assign, parse } from "../utils";
+import { useListView, type ClListViewItem } from "@/uni_modules/cool-ui";
+
+// 分页参数类型
+type Pagination = {
+ page: number; // 当前页码
+ size: number; // 每页数量
+ total: number; // 总数量
+};
+
+// 分页响应数据类型
+type PagerResponse = {
+ list: UTSJSONObject[]; // 列表数据
+ pagination: Pagination; // 分页信息
+};
+
+// 分页回调函数类型
+type PagerCallback = (params: UTSJSONObject, ctx: Pager) => void | Promise;
+
+// 分页器类
+export class Pager {
+ public page = 1; // 当前页码
+ public size = 20; // 每页数量
+ public total = 0; // 总数量
+ public list = ref([]); // 列表数据
+ public loading = ref(false); // 加载状态
+ public refreshing = ref(false); // 刷新状态
+ public finished = ref(false); // 是否加载完成
+ public params = {} as UTSJSONObject; // 请求参数
+ public cb: PagerCallback | null = null; // 回调函数
+
+ // 构造函数
+ constructor(cb: PagerCallback) {
+ this.cb = cb;
+ }
+
+ // 完成加载
+ done() {
+ this.loading.value = false;
+ }
+
+ // 清空数据
+ clear() {
+ this.list.value = [];
+ this.finished.value = false;
+ this.refreshing.value = false;
+ this.loading.value = false;
+ }
+
+ // 渲染数据
+ public render = (res: any) => {
+ const { list, pagination } = parse(res)!;
+
+ // 更新分页信息
+ this.page = pagination.page;
+ this.size = pagination.size;
+ this.total = pagination.total;
+
+ // 更新列表数据
+ if (this.params.page == 1) {
+ this.list.value = [...list];
+ } else {
+ this.list.value.push(...list);
+ }
+
+ // 更新加载完成状态
+ this.finished.value = this.list.value.length >= this.total;
+
+ // 完成加载
+ this.done();
+ };
+
+ // 刷新数据
+ public refresh = async (params: UTSJSONObject) => {
+ // 合并参数
+ this.params = assign(this.params, params);
+
+ // 构建请求参数
+ const data = {
+ page: this.page,
+ size: this.size,
+ ...this.params
+ };
+
+ // 开始加载
+ this.loading.value = true;
+
+ // 发起请求
+ await this.cb!(data, this);
+ };
+
+ // 加载更多数据
+ public loadMore = () => {
+ if (this.loading.value || this.finished.value) {
+ return;
+ }
+
+ this.refresh({
+ page: this.page + 1
+ });
+ };
+
+ // 列表视图数据
+ public listView = computed(() => {
+ return useListView(this.list.value);
+ });
+}
+
+// 创建分页器实例
+export const usePager = (cb: PagerCallback): Pager => {
+ return new Pager(cb);
+};
diff --git a/cool-unix/cool/hooks/parent.ts b/cool-unix/cool/hooks/parent.ts
new file mode 100644
index 0000000..282641d
--- /dev/null
+++ b/cool-unix/cool/hooks/parent.ts
@@ -0,0 +1,22 @@
+import { getCurrentInstance } from "vue";
+
+/**
+ * 获取父组件
+ * @param name 组件名称
+ * @example useParent("cl-form")
+ * @returns 父组件
+ */
+export function useParent(name: string): T | null {
+ const { proxy } = getCurrentInstance()!;
+
+ let p = proxy?.$parent;
+
+ while (p != null) {
+ if (p.$options.name == name) {
+ return p as T | null;
+ }
+ p = p.$parent;
+ }
+
+ return p as T | null;
+}
diff --git a/cool-unix/cool/hooks/refs.ts b/cool-unix/cool/hooks/refs.ts
new file mode 100644
index 0000000..373c5ca
--- /dev/null
+++ b/cool-unix/cool/hooks/refs.ts
@@ -0,0 +1,122 @@
+import { reactive } from "vue";
+import { isNull } from "../utils";
+
+// #ifdef APP
+// @ts-ignore
+type Instance = ComponentPublicInstance | null;
+// #endif
+
+// #ifndef APP
+// @ts-ignore
+type Instance = any;
+// #endif
+
+/**
+ * Refs 类用于管理组件引用,便于在组合式 API 中获取、操作子组件实例。
+ */
+class Refs {
+ // 存储所有 ref 的响应式对象,key 为 ref 名称,value 为组件实例
+ data = reactive({} as UTSJSONObject);
+
+ /**
+ * 生成 ref 绑定函数,用于在模板中设置 ref。
+ * @param name ref 名称
+ * @returns 绑定函数 (el: Instance) => void
+ */
+ set(name: string) {
+ return (el: Instance) => {
+ this.data[name] = el;
+ };
+ }
+
+ /**
+ * 获取指定名称的组件实例
+ * @param name ref 名称
+ * @returns 组件实例或 null
+ */
+ get(name: string): Instance {
+ const d = this.data[name] as ComponentPublicInstance;
+
+ if (isNull(d)) {
+ return null;
+ }
+
+ return d;
+ }
+
+ /**
+ * 获取组件实例暴露的属性或方法(兼容不同平台)
+ * @param name ref 名称
+ * @param key 暴露的属性名
+ * @returns 属性值或 null
+ */
+ getExposed(name: string, key: string): T | null {
+ // #ifdef APP-ANDROID
+ const d = this.get(name);
+
+ if (isNull(d)) {
+ return null;
+ }
+
+ // 安卓平台下,$exposed 为 Map
+ const ex = d!.$exposed as Map;
+
+ if (isNull(ex)) {
+ return null;
+ }
+
+ return ex[key] as T | null;
+ // #endif
+
+ // #ifndef APP-ANDROID
+ // 其他平台直接通过属性访问
+ return this.get(name)?.[key] as T;
+ // #endif
+ }
+
+ /**
+ * 调用组件实例暴露的方法,并返回结果
+ * @param name ref 名称
+ * @param method 方法名
+ * @param data 传递的数据
+ * @returns 方法返回值
+ */
+ call(name: string, method: string, data: UTSJSONObject | null = null): T {
+ return this.get(name)!.$callMethod(method, data) as T;
+ }
+
+ /**
+ * 调用组件实例暴露的方法,无返回值
+ * @param name ref 名称
+ * @param method 方法名
+ * @param data 传递的数据
+ */
+ callMethod(name: string, method: string, data: UTSJSONObject | null = null): void {
+ this.get(name)!.$callMethod(method, data);
+ }
+
+ /**
+ * 调用组件的 open 方法,常用于弹窗、抽屉等组件
+ * @param name ref 名称
+ * @param data 传递的数据
+ */
+ open(name: string, data: UTSJSONObject | null = null) {
+ this.callMethod(name, "open", data);
+ }
+
+ /**
+ * 调用组件的 close 方法,常用于弹窗、抽屉等组件
+ * @param name ref 名称
+ */
+ close(name: string) {
+ return this.callMethod(name, "close");
+ }
+}
+
+/**
+ * useRefs 组合式函数,返回 Refs 实例
+ * @returns Refs 实例
+ */
+export function useRefs(): Refs {
+ return new Refs();
+}
diff --git a/cool-unix/cool/hooks/wx.ts b/cool-unix/cool/hooks/wx.ts
new file mode 100644
index 0000000..718d196
--- /dev/null
+++ b/cool-unix/cool/hooks/wx.ts
@@ -0,0 +1,247 @@
+import { ref } from "vue";
+import { assign, getUrlParam, storage } from "../utils";
+import { request } from "../service";
+import { t } from "@/locale";
+import { config } from "@/config";
+
+// #ifdef H5
+import wx from "weixin-js-sdk";
+// #endif
+
+// 微信配置类型
+type WxConfig = {
+ appId: string;
+};
+
+// 微信相关功能封装类
+export class Wx {
+ // 微信登录code
+ code = ref("");
+
+ /**
+ * 获取微信登录code
+ */
+ async getCode(): Promise {
+ return new Promise((resolve) => {
+ // #ifdef MP-WEIXIN
+ uni.login({
+ provider: "weixin",
+ success: (res) => {
+ this.code.value = res.code;
+ resolve(res.code);
+ }
+ });
+ // #endif
+
+ // #ifndef MP-WEIXIN
+ resolve("");
+ // #endif
+ });
+ }
+
+ // #ifdef H5
+ // 公众号配置
+ mpConfig: WxConfig = {
+ appId: ""
+ };
+
+ /**
+ * 判断当前是否为微信浏览器
+ */
+ isWxBrowser() {
+ const ua: string = window.navigator.userAgent.toLowerCase();
+ if (ua.match(/MicroMessenger/i) != null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * 获取公众号配置信息,并初始化微信JS-SDK
+ */
+ getMpConfig() {
+ if (this.isWxBrowser()) {
+ request({
+ url: "/app/user/common/wxMpConfig",
+ method: "POST",
+ data: {
+ url: `${location.origin}${location.pathname}`
+ }
+ }).then((res) => {
+ if (res != null) {
+ wx.config({
+ debug: config.wx.debug,
+ jsApiList: res.jsApiList || ["chooseWXPay"],
+ appId: res.appId,
+ timestamp: res.timestamp,
+ nonceStr: res.nonceStr,
+ signature: res.signature,
+ openTagList: res.openTagList
+ });
+
+ // 合并配置到mpConfig
+ assign(this.mpConfig, res);
+ }
+ });
+ }
+ }
+
+ /**
+ * 跳转到微信授权页面
+ */
+ mpAuth() {
+ const { appId } = this.mpConfig;
+
+ const redirect_uri = encodeURIComponent(
+ `${location.origin}${location.pathname}#/pages/user/login`
+ );
+ const response_type = "code";
+ const scope = "snsapi_userinfo";
+ const state = "STATE";
+
+ const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirect_uri}&response_type=${response_type}&scope=${scope}&state=${state}#wechat_redirect`;
+
+ location.href = url;
+ }
+
+ /**
+ * 公众号登录,获取code
+ */
+ mpLogin() {
+ return new Promise((resolve) => {
+ const code = getUrlParam("code");
+ const mpCode = storage.get("mpCode");
+
+ // 去除url中的code参数,避免重复
+ const url = window.location.href.replace(/(\?[^#]*)#/, "#");
+ window.history.replaceState({}, "", url);
+
+ if (code != mpCode) {
+ storage.set("mpCode", code, 1000 * 60 * 5);
+ resolve(code);
+ } else {
+ resolve(null);
+ }
+ });
+ }
+
+ /**
+ * 公众号微信支付
+ * @param params 支付参数
+ */
+ mpPay(params: wx.IchooseWXPay & { timeStamp: number }): Promise {
+ return new Promise((resolve, reject) => {
+ if (!this.isWxBrowser()) {
+ return reject({ message: t("请在微信浏览器中打开") });
+ }
+
+ wx.chooseWXPay({
+ ...params,
+ timestamp: params.timeStamp,
+ success() {
+ resolve();
+ },
+ complete(e: { errMsg: string }) {
+ switch (e.errMsg) {
+ case "chooseWXPay:cancel":
+ reject({ message: t("已取消支付") });
+ break;
+
+ default:
+ reject({ message: t("支付失败") });
+ }
+ }
+ });
+ });
+ }
+ // #endif
+
+ // #ifdef MP
+ /**
+ * 小程序登录,获取用户信息和code
+ */
+ miniLogin(): Promise<{
+ code: string;
+ iv: string;
+ encryptedData: string;
+ signature: string;
+ rawData: string;
+ }> {
+ return new Promise((resolve, reject) => {
+ // 兼容 Mac,Mac 端需用 getUserInfo
+ const k = uni.getDeviceInfo().platform === "mac" ? "getUserInfo" : "getUserProfile";
+
+ uni[k]({
+ lang: "zh_CN",
+ desc: t("授权信息仅用于用户登录"),
+ success: ({ iv, encryptedData, signature, rawData }) => {
+ const next = () => {
+ resolve({
+ iv,
+ encryptedData,
+ signature,
+ rawData,
+ code: this.code.value
+ });
+ };
+
+ // 检查登录状态是否过期
+ uni.checkSession({
+ success: () => {
+ next();
+ },
+ fail: () => {
+ this.getCode().then(() => {
+ next();
+ });
+ }
+ });
+ },
+ fail: (err) => {
+ console.error(`[useWx.miniLogin] error`, err);
+ this.getCode();
+
+ reject(t("登录授权失败"));
+ }
+ });
+ });
+ }
+
+ /**
+ * 小程序微信支付
+ * @param params 支付参数
+ */
+ miniPay(params: any): Promise {
+ return new Promise((resolve, reject) => {
+ uni.requestPayment({
+ provider: "wxpay",
+ ...params,
+ success() {
+ resolve();
+ },
+ fail() {
+ reject(t("已取消支付"));
+ }
+ });
+ });
+ }
+ // #endif
+}
+
+/**
+ * useWx 钩子函数,后续可扩展
+ */
+export const useWx = (): Wx => {
+ const wx = new Wx();
+
+ onReady(() => {
+ wx.getCode();
+
+ // #ifdef H5
+ wx.getMpConfig();
+ // #endif
+ });
+
+ return wx;
+};
diff --git a/cool-unix/cool/index.ts b/cool-unix/cool/index.ts
new file mode 100644
index 0000000..11c9292
--- /dev/null
+++ b/cool-unix/cool/index.ts
@@ -0,0 +1,46 @@
+import { watch } from "vue";
+import { scroller } from "./scroller";
+import { initTheme, setH5 } from "./theme";
+import { initLocale, locale, updateTitle } from "@/locale";
+import "@/uni_modules/cool-ui";
+
+export function cool(app: VueApp) {
+ app.mixin({
+ onPageScroll(e) {
+ scroller.emit(e.scrollTop);
+ },
+ onShow() {
+ // 更新标题
+ updateTitle();
+
+ // #ifdef H5
+ setTimeout(() => {
+ setH5();
+ }, 0);
+ // #endif
+ },
+ onLoad() {
+ // 监听语言切换,更新标题
+ watch(locale, () => {
+ updateTitle();
+ });
+ }
+ });
+
+ initTheme();
+ initLocale();
+
+ console.log(app);
+}
+
+export * from "./animation";
+export * from "./ctx";
+export * from "./hooks";
+export * from "./router";
+export * from "./scroller";
+export * from "./service";
+export * from "./store";
+export * from "./theme";
+export * from "./upload";
+export * from "./utils";
+export * from "./types";
diff --git a/cool-unix/cool/router/index.ts b/cool-unix/cool/router/index.ts
new file mode 100644
index 0000000..c46a81f
--- /dev/null
+++ b/cool-unix/cool/router/index.ts
@@ -0,0 +1,362 @@
+import { PAGES, TABS } from "../ctx";
+import type { BackOptions, PageInstance, PushOptions } from "../types";
+import {
+ storage,
+ last,
+ isNull,
+ isEmpty,
+ get,
+ isFunction,
+ toArray,
+ map,
+ debounce,
+ nth,
+ assign,
+ parse
+} from "../utils";
+
+// 路由信息类型
+type RouteInfo = {
+ path: string;
+ query: UTSJSONObject;
+ meta: UTSJSONObject;
+ isAuth?: boolean;
+};
+
+// 跳转前钩子类型
+type BeforeEach = (to: RouteInfo, from: PageInstance, next: () => void) => void;
+// 登录后回调类型
+type AfterLogin = () => void;
+
+// 路由事件集合
+type Events = {
+ beforeEach?: BeforeEach;
+ afterLogin?: AfterLogin;
+};
+
+// 路由核心类
+export class Router {
+ private eventsMap = {} as Events; // 事件存储
+
+ // 获取传递的 params 参数
+ params() {
+ return (storage.get("router-params") ?? {}) as UTSJSONObject;
+ }
+
+ // 获取传递的 query 参数
+ query() {
+ return this.route()?.query ?? {};
+ }
+
+ // 获取默认路径,支持 home 和 login
+ defaultPath(name: "home" | "login") {
+ const paths = {
+ home: PAGES[0].path, // 首页为第一个页面
+ login: "/pages/user/login"
+ };
+
+ return get(paths, name) as string;
+ }
+
+ // 获取当前页面栈的所有页面实例
+ getPages(): PageInstance[] {
+ return map(getCurrentPages(), (e) => {
+ let path = e.route!;
+
+ // 根路径自动转为首页
+ if (path == "/") {
+ path = this.defaultPath("home");
+ }
+
+ // 补全路径前缀
+ if (!path.startsWith("/")) {
+ path = "/" + path;
+ }
+
+ // 获取页面样式
+ const page = PAGES.find((e) => e.path == path);
+ const style = page?.style;
+ const meta = page?.meta;
+
+ // 获取页面暴露的方法
+ // @ts-ignore
+ const vm = e.vm as any;
+
+ let exposed = vm;
+
+ // #ifdef H5
+ exposed = get(e, "vm.$.exposed");
+ // #endif
+
+ // 获取页面 query 参数
+ // @ts-ignore
+ const query = e.options;
+
+ return {
+ path,
+ vm,
+ exposed,
+ style,
+ meta,
+ query,
+ isCustomNavbar: style?.navigationStyle == "custom"
+ } as PageInstance;
+ });
+ }
+
+ // 获取指定路径的页面实例
+ getPage(path: string) {
+ return this.getPages().find((e) => e.path == path);
+ }
+
+ // 获取当前路由页面实例
+ route() {
+ return last(this.getPages());
+ }
+
+ // 获取当前页面路径
+ path() {
+ return this.route()?.path ?? "";
+ }
+
+ // 简单跳转页面(默认 navigateTo)
+ to(path: string) {
+ this.push({
+ path
+ });
+ }
+
+ // 路由跳转,支持多种模式和参数
+ push(options: PushOptions) {
+ let {
+ query = {},
+ params = {},
+ mode = "navigateTo",
+ path,
+ success,
+ fail,
+ complete,
+ animationType,
+ animationDuration,
+ events,
+ isAuth
+ } = options;
+
+ // 拼接 query 参数到 url
+ if (!isEmpty(query)) {
+ const arr = toArray(query, (v, k) => {
+ return `${k}=${v}`;
+ });
+ path += "?" + arr.join("&");
+ }
+
+ // params 通过 storage 临时存储
+ if (!isEmpty(params)) {
+ storage.set("router-params", params, 0);
+ }
+
+ // tabBar 页面强制使用 switchTab 跳转
+ if (this.isTabPage(path)) {
+ mode = "switchTab";
+ }
+
+ // 跳转执行函数
+ const next = () => {
+ switch (mode) {
+ case "navigateTo":
+ uni.navigateTo({
+ url: path,
+ success,
+ events,
+ fail,
+ complete,
+ animationType,
+ animationDuration
+ });
+ break;
+ case "redirectTo":
+ uni.redirectTo({
+ url: path,
+ success,
+ fail,
+ complete
+ });
+ break;
+ case "reLaunch":
+ uni.reLaunch({
+ url: path,
+ success,
+ fail,
+ complete
+ });
+ break;
+ case "switchTab":
+ uni.switchTab({
+ url: path,
+ success,
+ fail,
+ complete
+ });
+ break;
+ }
+ };
+
+ // 跳转前钩子处理
+ if (this.eventsMap.beforeEach != null) {
+ // 当前页
+ const from = last(this.getPages());
+
+ // 跳转页
+ const to = { path, meta: this.getMeta(path), query, isAuth } as RouteInfo;
+
+ // 调用跳转前钩子
+ this.eventsMap.beforeEach(to, from!, next);
+ } else {
+ next();
+ }
+ }
+
+ // 回到首页
+ home() {
+ this.push({
+ path: this.defaultPath("home")
+ });
+ }
+
+ // 返回上一页
+ back(options: BackOptions | null = null) {
+ if (this.isFirstPage()) {
+ this.home();
+ } else {
+ const delta = options?.delta ?? 1;
+
+ // 执行跳转函数
+ const next = () => {
+ uni.navigateBack({ ...(options ?? {}) });
+ };
+
+ // 跳转前钩子处理
+ if (this.eventsMap.beforeEach != null) {
+ // 当前页
+ const from = last(this.getPages());
+
+ // 上一页
+ const to = nth(this.getPages(), -delta - 1);
+
+ if (to != null) {
+ // 调用跳转前钩子
+ this.eventsMap.beforeEach(
+ {
+ path: to.path,
+ query: to.query,
+ meta: to.meta ?? ({} as UTSJSONObject)
+ },
+ from!,
+ next
+ );
+ } else {
+ console.error("[router] found to page is null");
+ }
+ } else {
+ next();
+ }
+ }
+ }
+
+ // 获取页面元数据
+ getMeta(path: string) {
+ return PAGES.find((e) => path.includes(e.path))?.meta ?? ({} as UTSJSONObject);
+ }
+
+ // 执行当前页面暴露的方法
+ callMethod(name: string, data?: any): any | null {
+ const fn = get(this.route()!, `$vm.$.exposed.${name}`) as (d?: any) => any | null;
+ if (isFunction(fn)) {
+ return fn(data);
+ }
+ return null;
+ }
+
+ // 判断页面栈是否只有一个页面
+ isFirstPage() {
+ return getCurrentPages().length == 1;
+ }
+
+ // 判断是否为首页
+ isHomePage() {
+ return this.path() == this.defaultPath("home");
+ }
+
+ // 判断是否为自定义导航栏页面
+ isCustomNavbarPage() {
+ return this.route()?.isCustomNavbar ?? false;
+ }
+
+ // 判断是否为当前页面
+ isCurrentPage(path: string) {
+ return this.path() == path;
+ }
+
+ // 判断是否为 tab 页面
+ isTabPage(path: string | null = null) {
+ if (path == null) {
+ path = this.path();
+ }
+
+ if (path == "/") {
+ path = this.defaultPath("home");
+ }
+ return !isNull(TABS.find((e) => path == e.pagePath));
+ }
+
+ // 判断是否为登录页
+ isLoginPage(path: string) {
+ return path == this.defaultPath("login");
+ }
+
+ // 跳转到登录页(防抖处理)
+ login = debounce(() => {
+ if (!this.isLoginPage(this.path())) {
+ this.push({
+ path: "/pages/user/login",
+ mode: "reLaunch"
+ });
+ }
+ }, 300);
+
+ // 登录成功后跳转逻辑
+ nextLogin() {
+ const pages = this.getPages();
+
+ // 找到登录页的索引
+ const index = pages.findIndex((e) => this.defaultPath("login").includes(e.path));
+
+ // 未找到,则跳回首页
+ if (index < 0) {
+ this.home();
+ } else {
+ this.back({
+ delta: pages.length - index
+ });
+ }
+ // 登录后回调
+ if (this.eventsMap.afterLogin != null) {
+ this.eventsMap.afterLogin!();
+ }
+ // 触发全局 afterLogin 事件
+ uni.$emit("afterLogin");
+ }
+
+ // 注册跳转前钩子
+ beforeEach(cb: BeforeEach) {
+ this.eventsMap.beforeEach = cb;
+ }
+
+ // 注册登录后回调
+ afterLogin(cb: AfterLogin) {
+ this.eventsMap.afterLogin = cb;
+ }
+}
+
+// 单例导出
+export const router = new Router();
diff --git a/cool-unix/cool/scroller/index.ts b/cool-unix/cool/scroller/index.ts
new file mode 100644
index 0000000..7504ad5
--- /dev/null
+++ b/cool-unix/cool/scroller/index.ts
@@ -0,0 +1,33 @@
+import { router } from "../router";
+
+class Scroller {
+ list: Map void)[]> = new Map();
+
+ // 触发滚动
+ emit(top: number) {
+ const cbs = this.list.get(router.path()) ?? [];
+ cbs.forEach((cb) => {
+ cb(top);
+ });
+ }
+
+ // 监听页面滚动
+ on(callback: (top: number) => void) {
+ const path = router.path();
+ const cbs = this.list.get(path) ?? [];
+ cbs.push(callback);
+ this.list.set(path, cbs);
+ }
+
+ // 取消监听页面滚动
+ off = (callback: (top: number) => void) => {
+ const path = router.path();
+ const cbs = this.list.get(path) ?? [];
+ this.list.set(
+ path,
+ cbs.filter((cb) => cb != callback)
+ );
+ };
+}
+
+export const scroller = new Scroller();
diff --git a/cool-unix/cool/service/index.ts b/cool-unix/cool/service/index.ts
new file mode 100644
index 0000000..d70fdf7
--- /dev/null
+++ b/cool-unix/cool/service/index.ts
@@ -0,0 +1,198 @@
+import { isDev, ignoreTokens, config } from "@/config";
+import { locale, t } from "@/locale";
+import { isNull, isObject, parse, storage } from "../utils";
+import { useStore } from "../store";
+
+// 请求参数类型定义
+export type RequestOptions = {
+ url: string; // 请求地址
+ method?: RequestMethod; // 请求方法
+ data?: any; // 请求体数据
+ params?: any; // URL参数
+ header?: any; // 请求头
+ timeout?: number; // 超时时间
+ withCredentials?: boolean; // 是否携带凭证
+ firstIpv4?: boolean; // 是否优先使用IPv4
+ enableChunked?: boolean; // 是否启用分块传输
+};
+
+// 响应数据类型定义
+export type Response = {
+ code?: number;
+ message?: string;
+ data?: any;
+};
+
+// 请求队列(用于等待token刷新后继续请求)
+let requests: ((token: string) => void)[] = [];
+
+// 标记token是否正在刷新
+let isRefreshing = false;
+
+// 判断当前url是否忽略token校验
+const isIgnoreToken = (url: string) => {
+ return ignoreTokens.some((e) => {
+ const pattern = e.replace(/\*/g, ".*");
+ return new RegExp(pattern).test(url);
+ });
+};
+
+/**
+ * 通用请求方法
+ * @param options 请求参数
+ * @returns Promise
+ */
+export function request(options: RequestOptions): Promise {
+ let { url, method = "GET", data = {}, params, header = {}, timeout = 60000 } = options;
+
+ const { user } = useStore();
+
+ // 开发环境下打印请求信息
+ if (isDev) {
+ console.log(`[${method}] ${url}`, params || data);
+ }
+
+ // 拼接基础url
+ if (!url.startsWith("http")) {
+ url = config.baseUrl + url;
+ }
+
+ // 处理GET请求的params参数,拼接到URL上
+ if (method === "GET" && params) {
+ const queryString = Object.keys(params)
+ .filter(key => params[key] !== undefined && params[key] !== null)
+ .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
+ .join('&');
+
+ if (queryString) {
+ url += (url.includes('?') ? '&' : '?') + queryString;
+ }
+
+ if (isDev) {
+ console.log(`[GET] 完整URL: ${url}`);
+ }
+ }
+
+ // 获取当前token
+ let Authorization: string | null = user.token;
+
+ // 如果是忽略token的接口,则不携带token
+ if (isIgnoreToken(url)) {
+ Authorization = null;
+ }
+
+ return new Promise((resolve, reject) => {
+ // 发起请求的实际函数
+ const next = () => {
+ uni.request({
+ url,
+ method,
+ data,
+ header: {
+ Authorization,
+ language: locale.value,
+ ...(header as UTSJSONObject)
+ },
+ timeout,
+
+ success(res) {
+ // 401 无权限
+ if (res.statusCode == 401) {
+ user.logout();
+ reject({ message: t("无权限") } as Response);
+ }
+
+ // 502 服务异常
+ else if (res.statusCode == 502) {
+ reject({
+ message: t("服务异常")
+ } as Response);
+ }
+
+ // 404 未找到
+ else if (res.statusCode == 404) {
+ return reject({
+ message: `[404] ${url}`
+ } as Response);
+ }
+
+ // 200 正常响应
+ else if (res.statusCode == 200) {
+ if (res.data == null) {
+ resolve(null);
+ } else if (!isObject(res.data as any)) {
+ resolve(res.data);
+ } else {
+ // 解析响应数据
+ const { code, message, data } = parse(
+ res.data ?? { code: 0 }
+ )!;
+
+ switch (code) {
+ case 1000:
+ resolve(data);
+ break;
+ default:
+ reject({ message, code } as Response);
+ break;
+ }
+ }
+ } else {
+ reject({ message: t("服务异常") } as Response);
+ }
+ },
+
+ // 网络请求失败
+ fail(err) {
+ reject({ message: err.errMsg } as Response);
+ }
+ });
+ };
+
+ // 非刷新token接口才进行token有效性校验
+ if (!options.url.includes("/refreshToken")) {
+ if (!isNull(Authorization)) {
+ // 判断token是否过期
+ if (storage.isExpired("token")) {
+ // 判断refreshToken是否过期
+ if (storage.isExpired("refreshToken")) {
+ // 刷新token也过期,直接退出登录
+ user.logout();
+ return;
+ }
+
+ // 如果当前没有在刷新token,则发起刷新
+ if (!isRefreshing) {
+ isRefreshing = true;
+ user.refreshToken()
+ .then((token) => {
+ // 刷新成功后,执行队列中的请求
+ requests.forEach((cb) => cb(token));
+ requests = [];
+ isRefreshing = false;
+ })
+ .catch((err) => {
+ reject(err);
+ user.logout();
+ });
+ }
+
+ // 将当前请求加入队列,等待token刷新后再执行
+ new Promise((resolve) => {
+ requests.push((token: string) => {
+ // 重新设置token
+ Authorization = token;
+ next();
+ resolve(true);
+ });
+ });
+ // 此处return,等待token刷新
+ return;
+ }
+ }
+ }
+
+ // token有效,直接发起请求
+ next();
+ });
+}
diff --git a/cool-unix/cool/store/dict.ts b/cool-unix/cool/store/dict.ts
new file mode 100644
index 0000000..eb9e415
--- /dev/null
+++ b/cool-unix/cool/store/dict.ts
@@ -0,0 +1,136 @@
+import { reactive } from "vue";
+import { request } from "../service";
+import { forInObject, isNull, parse } from "../utils";
+
+// 字典项类型定义
+export type DictItem = {
+ id: number; // 字典项ID
+ typeId: number; // 字典类型ID
+ label: string; // 显示标签
+ name: string; // 可选名称
+ value: any; // 字典项值
+ orderNum: number; // 排序号
+ parentId?: number | null; // 父级ID,可选
+};
+
+// 字典数据类型定义
+export type DictData = {
+ key: string; // 字典key
+ list: DictItem[]; // 字典项列表
+};
+
+// 字典管理类
+export class Dict {
+ private data: DictData[] = reactive([]); // 存储所有字典数据
+
+ constructor() {}
+
+ /**
+ * 获取指定key的字典数据
+ * @param key 字典key
+ * @returns 字典数据
+ */
+ find(key: string) {
+ return this.data.find((e) => e.key == key);
+ }
+
+ /**
+ * 获取指定key的字典项列表
+ * @param key 字典key
+ * @returns 字典项数组
+ */
+ get(key: string): DictItem[] {
+ return this.find(key)?.list ?? new Array();
+ }
+
+ /**
+ * 获取指定key和value的字典项
+ * @param key 字典key
+ * @param value 字典项值
+ * @returns 字典项或null
+ */
+ getItem(key: string, value: any): DictItem | null {
+ const item = this.get(key).find((e) => e.value == value);
+
+ if (isNull(item)) {
+ return null;
+ }
+
+ return item!;
+ }
+
+ /**
+ * 获取指定key和多个value的字典项数组
+ * @param key 字典key
+ * @param values 字典项值数组
+ * @returns 字典项数组
+ */
+ getItems(key: string, values: any[]): DictItem[] {
+ return values.map((e) => this.getItem(key, e)).filter((e) => !isNull(e)) as DictItem[];
+ }
+
+ /**
+ * 获取指定key和value的字典项的label
+ * @param key 字典key
+ * @param value 字典项值
+ * @returns 字典项label字符串
+ */
+ getItemLabel(key: string, value: any): string {
+ const item = this.getItem(key, value);
+
+ if (isNull(item) || isNull(item?.label)) {
+ return "";
+ }
+
+ return item!.label;
+ }
+
+ /**
+ * 刷新字典数据
+ * @param types 可选,指定需要刷新的字典key数组
+ */
+ async refresh(types?: string[] | null): Promise {
+ const res = await request({
+ url: "/app/dict/info/data",
+ method: "POST",
+ data: { types }
+ });
+
+ if (res == null) {
+ return;
+ }
+
+ // 遍历返回的字典数据
+ forInObject(res, (arr, key) => {
+ let list: DictItem[] = [];
+
+ (arr as UTSJSONObject[]).forEach((e) => {
+ e["label"] = e["name"];
+ const d = parse(e);
+
+ if (d != null) {
+ list.push(d);
+ }
+ });
+
+ const item = this.find(key);
+
+ // 如果不存在则新增,否则更新
+ if (isNull(item)) {
+ this.data.push({
+ key,
+ list
+ });
+ } else {
+ item!.list = list;
+ }
+ });
+
+ // #ifdef H5
+ console.log("[DICT]", this.data);
+ // #endif
+ }
+}
+
+// 单例字典对象
+export const dict = new Dict();
diff --git a/cool-unix/cool/store/index.ts b/cool-unix/cool/store/index.ts
new file mode 100644
index 0000000..f0154ff
--- /dev/null
+++ b/cool-unix/cool/store/index.ts
@@ -0,0 +1,17 @@
+import { Dict, dict } from "./dict";
+import { User, user } from "./user";
+
+type Store = {
+ user: User;
+ dict: Dict;
+};
+
+export function useStore(): Store {
+ return {
+ user,
+ dict
+ };
+}
+
+export * from "./dict";
+export * from "./user";
diff --git a/cool-unix/cool/store/user.ts b/cool-unix/cool/store/user.ts
new file mode 100644
index 0000000..0614169
--- /dev/null
+++ b/cool-unix/cool/store/user.ts
@@ -0,0 +1,185 @@
+import { computed, ref } from "vue";
+import { forInObject, isNull, isObject, parse, storage } from "../utils";
+import { router } from "../router";
+import { request } from "../service";
+import type { UserInfo } from "@/types";
+
+export type Token = {
+ token: string; // 访问token
+ expire: number; // token过期时间(秒)
+ refreshToken: string; // 刷新token
+ refreshExpire: number; // 刷新token过期时间(秒)
+};
+
+export class User {
+ /**
+ * 用户信息,响应式对象
+ */
+ info = ref(null);
+
+ /**
+ * 当前token,字符串或null
+ */
+ token: string | null = null;
+
+ constructor() {
+ // 获取本地用户信息
+ const userInfo = storage.get("userInfo");
+
+ // 获取本地token
+ const token = storage.get("token") as string | null;
+
+ // 如果token为空字符串则置为null
+ this.token = token == "" ? null : token;
+
+ // 初始化用户信息
+ if (userInfo != null && isObject(userInfo)) {
+ this.set(userInfo);
+ }
+ }
+
+ /**
+ * 获取用户信息(从服务端拉取最新信息并更新本地)
+ * @returns Promise
+ */
+ async get() {
+ if (this.token != null) {
+ await request({
+ url: "/app/user/info/person"
+ })
+ .then((res) => {
+ if (res != null) {
+ this.set(res);
+ }
+ })
+ .catch(() => {
+ // this.logout();
+ });
+ }
+ }
+
+ /**
+ * 设置用户信息并存储到本地
+ * @param data 用户信息对象
+ */
+ set(data: any) {
+ if (isNull(data)) {
+ return;
+ }
+
+ // 设置
+ this.info.value = parse(data)!;
+
+ // 持久化到本地存储
+ storage.set("userInfo", data, 0);
+ }
+
+ /**
+ * 更新用户信息(本地与服务端同步)
+ * @param data 新的用户信息
+ */
+ async update(data: any) {
+ if (isNull(data) || isNull(this.info.value)) {
+ return;
+ }
+
+ // 本地同步更新
+ forInObject(data, (value, key) => {
+ this.info.value![key] = value;
+ });
+
+ // 同步到服务端
+ await request({
+ url: "/app/user/info/updatePerson",
+ method: "POST",
+ data
+ });
+ }
+
+ /**
+ * 移除用户信息
+ */
+ remove() {
+ this.info.value = null;
+ storage.remove("userInfo");
+ }
+
+ /**
+ * 判断用户信息是否为空
+ * @returns boolean
+ */
+ isNull() {
+ return this.info.value == null;
+ }
+
+ /**
+ * 清除本地所有用户信息和token
+ */
+ clear() {
+ storage.remove("userInfo");
+ storage.remove("token");
+ storage.remove("refreshToken");
+ this.token = null;
+ this.remove();
+ }
+
+ /**
+ * 退出登录,清除所有信息并跳转到登录页
+ */
+ logout() {
+ this.clear();
+ router.login();
+ }
+
+ /**
+ * 设置token并存储到本地
+ * @param data Token对象
+ */
+ setToken(data: Token) {
+ this.token = data.token;
+
+ // 访问token,提前5秒过期,防止边界问题
+ storage.set("token", data.token, data.expire - 5);
+ // 刷新token,提前5秒过期
+ storage.set("refreshToken", data.refreshToken, data.refreshExpire - 5);
+ }
+
+ /**
+ * 刷新token(调用服务端接口,自动更新本地token)
+ * @returns Promise 新的token
+ */
+ refreshToken(): Promise {
+ return new Promise((resolve, reject) => {
+ request({
+ url: "/app/user/login/refreshToken",
+ method: "POST",
+ data: {
+ refreshToken: storage.get("refreshToken")
+ }
+ })
+ .then((res) => {
+ if (res != null) {
+ const token = parse(res);
+
+ if (token != null) {
+ this.setToken(token);
+ resolve(token.token);
+ }
+ }
+ })
+ .catch((err) => {
+ reject(err);
+ });
+ });
+ }
+}
+
+/**
+ * 单例用户对象,项目全局唯一
+ */
+export const user = new User();
+
+/**
+ * 用户信息,响应式对象
+ */
+export const userInfo = computed(() => user.info.value);
diff --git a/cool-unix/cool/theme/index.ts b/cool-unix/cool/theme/index.ts
new file mode 100644
index 0000000..9f864c0
--- /dev/null
+++ b/cool-unix/cool/theme/index.ts
@@ -0,0 +1,253 @@
+import { computed, ref } from "vue";
+import uniTheme from "@/theme.json";
+import { router } from "../router";
+import { ctx } from "../ctx";
+import { isNull } from "../utils";
+
+// 主题类型定义,仅支持 light 和 dark
+type Theme = "light" | "dark";
+
+// 是否为自动主题模式(跟随系统)
+export const isAuto = ref(true);
+
+/**
+ * 获取页面样式
+ * @param key 样式 key
+ * @returns 样式值
+ */
+export function getStyle(key: string): string | null {
+ // 页面配置
+ const style = router.route()?.style;
+
+ // 页面配置 key 映射
+ const names = {
+ bgColor: "backgroundColor",
+ bgContentColor: "backgroundColorContent",
+ navBgColor: "navigationBarBackgroundColor",
+ navTextStyle: "navigationBarTextStyle"
+ };
+
+ // 如果页面配置存在,则使用页面配置
+ if (style != null) {
+ if (names[key] != null) {
+ const val = style[names[key]!] as string | null;
+
+ if (val != null) {
+ return val;
+ }
+ }
+ }
+
+ return null;
+}
+
+/**
+ * 获取颜色
+ * @param name 颜色名称
+ * @returns 颜色值
+ */
+export const getColor = (name: string) => {
+ if (isNull(ctx.color)) {
+ return "";
+ }
+
+ return ctx.color[name] as string;
+};
+
+/**
+ * 获取 uniapp 主题配置
+ */
+export function getConfig(key: string): string {
+ // 主题配置
+ const themeVal = ((isDark.value ? uniTheme.dark : uniTheme.light) as UTSJSONObject)[key] as
+ | string
+ | null;
+
+ // 页面样式
+ const styleVal = getStyle(key);
+
+ return styleVal ?? themeVal ?? "";
+}
+
+/**
+ * 获取当前主题
+ * APP 下优先获取 appTheme,若为 auto 则跟随系统 osTheme
+ * H5/小程序下优先获取 hostTheme,否则默认为 light
+ */
+const getTheme = () => {
+ let value: string | null;
+
+ // #ifdef APP
+ const appInfo = uni.getAppBaseInfo();
+ // @ts-ignore
+ const appTheme = appInfo.appTheme as string;
+ const osTheme = uni.getSystemInfoSync().osTheme!;
+
+ // 如果 appTheme 为 auto,则跟随系统主题,否则使用 appTheme
+ value = appTheme == "auto" ? osTheme : appTheme;
+ isAuto.value = appTheme == "auto";
+ // #endif
+
+ // #ifdef H5 || MP
+ const hostTheme = uni.getAppBaseInfo().hostTheme;
+ if (hostTheme) {
+ // 如果有 hostTheme,则使用 hostTheme
+ value = hostTheme;
+ } else {
+ // 默认使用 light 主题
+ value = "light";
+ }
+ // #endif
+
+ return value as Theme;
+};
+
+// 当前主题响应式变量
+export const theme = ref(getTheme());
+
+/**
+ * 是否为暗色模式
+ */
+export const isDark = computed(() => {
+ return theme.value == "dark";
+});
+
+/**
+ * 切换自动主题模式(仅 APP 有效)
+ */
+export const setIsAuto = () => {
+ // #ifdef APP
+ isAuto.value = !isAuto.value;
+
+ if (isAuto.value) {
+ // 设置为自动主题,跟随系统
+ uni.setAppTheme({
+ theme: "auto"
+ });
+ } else {
+ // 关闭自动,使用当前 theme
+ setTheme(theme.value);
+ }
+ // #endif
+};
+
+/**
+ * 设置主题
+ * @param value 主题值("light" | "dark")
+ */
+export const setTheme = (value: Theme) => {
+ // 如果当前主题与目标主题一致,则不做处理
+ if (theme.value == value) return;
+
+ // 关闭自动主题
+ isAuto.value = false;
+
+ // #ifdef APP
+ uni.setAppTheme({
+ theme: value,
+ success: () => {
+ // 设置成功后更新 theme
+ theme.value = value;
+ }
+ });
+ // #endif
+
+ // #ifndef APP
+ theme.value = value;
+ // #endif
+
+ // #ifdef H5
+ setH5();
+ // #endif
+};
+
+// 设置 H5 下的主题色
+export const setH5 = () => {
+ const bgContentColor = getConfig("bgContentColor");
+ const tabBgColor = getConfig("tabBgColor");
+ const navBgColor = getConfig("navBgColor");
+ const navTextStyle = getConfig("navTextStyle");
+
+ document.body.style.setProperty("--background-color-content", bgContentColor);
+
+ const tabbar = document.querySelector(".uni-tabbar");
+ if (tabbar) {
+ (tabbar as HTMLElement).style.backgroundColor = tabBgColor;
+ }
+
+ const pageHead = document.querySelector(".uni-page-head");
+ if (pageHead) {
+ (pageHead as HTMLElement).style.backgroundColor = navBgColor;
+ (pageHead as HTMLElement).style.color = navTextStyle;
+ }
+
+ const pageHeadBtnPath = document.querySelector(".uni-page-head-btn path");
+ if (pageHeadBtnPath) {
+ (pageHeadBtnPath as HTMLElement).style.fill = navTextStyle;
+ }
+
+ window.parent.postMessage(
+ {
+ type: "theme-change",
+ isDark: isDark.value
+ },
+ "*"
+ );
+};
+
+/**
+ * 切换主题
+ */
+export const toggleTheme = () => {
+ if (isDark.value) {
+ setTheme("light");
+ } else {
+ setTheme("dark");
+ }
+};
+
+/**
+ * 初始化主题监听
+ * APP 下监听系统主题和 App 主题变化
+ * H5/小程序下监听 hostTheme 变化
+ */
+export const initTheme = () => {
+ // #ifdef APP-ANDROID || APP-IOS
+ uni.onOsThemeChange((res) => {
+ if (isAuto.value) {
+ setTimeout(() => {
+ uni.setAppTheme({
+ theme: res.osTheme,
+ success: () => {
+ theme.value = res.osTheme;
+ }
+ });
+ }, 100);
+ }
+ });
+
+ // 监听 App 主题变化
+ uni.onAppThemeChange((res) => {
+ theme.value = res.appTheme;
+ });
+ // #endif
+
+ // #ifdef MP
+ uni.onHostThemeChange((res) => {
+ setTheme(res.hostTheme);
+ });
+ // #endif
+
+ // #ifdef H5
+ // 监听父窗口发送的主题变化消息
+ // [BUG] uni.onHostThemeChange 打包会丢失
+ // uni.onHostThemeChange((res) => {
+ // setTheme(res.hostTheme);
+ // });
+ window.addEventListener("message", (e) => {
+ if (e.data?.type == "theme-change") {
+ setTheme(e.data.isDark ? "dark" : "light");
+ }
+ });
+ // #endif
+};
diff --git a/cool-unix/cool/types/index.ts b/cool-unix/cool/types/index.ts
new file mode 100644
index 0000000..1146799
--- /dev/null
+++ b/cool-unix/cool/types/index.ts
@@ -0,0 +1,58 @@
+export type PushAnimationType =
+ | "auto"
+ | "none"
+ | "slide-in-right"
+ | "slide-in-left"
+ | "slide-in-top"
+ | "slide-in-bottom"
+ | "fade-in"
+ | "zoom-out"
+ | "zoom-fade-out"
+ | "pop-in";
+
+export type BackAnimationType =
+ | "auto"
+ | "none"
+ | "slide-out-right"
+ | "slide-out-left"
+ | "slide-out-top"
+ | "slide-out-bottom"
+ | "fade-out"
+ | "zoom-in"
+ | "zoom-fade-in"
+ | "pop-out";
+
+export type PushMode = "navigateTo" | "redirectTo" | "reLaunch" | "switchTab";
+
+export type BackOptions = {
+ delta?: number;
+ animationType?: BackAnimationType;
+ animationDuration?: number;
+ success?: (result: any) => void;
+ fail?: (result: any) => void;
+ complete?: (result: any) => void;
+};
+
+export type PushOptions = {
+ path: string;
+ mode?: PushMode;
+ events?: any;
+ query?: UTSJSONObject;
+ isAuth?: boolean;
+ params?: UTSJSONObject;
+ animationType?: PushAnimationType;
+ animationDuration?: number;
+ success?: (result: any) => void;
+ fail?: (result: any) => void;
+ complete?: (result: any) => void;
+};
+
+export type PageInstance = {
+ path: string;
+ vm: any;
+ style?: UTSJSONObject;
+ query: UTSJSONObject;
+ exposed: any;
+ isCustomNavbar: boolean;
+ meta?: UTSJSONObject;
+};
diff --git a/cool-unix/cool/upload/index.ts b/cool-unix/cool/upload/index.ts
new file mode 100644
index 0000000..a108413
--- /dev/null
+++ b/cool-unix/cool/upload/index.ts
@@ -0,0 +1,254 @@
+import { config } from "@/config";
+import { request } from "../service";
+import { basename, extname, filename, parse, parseObject, pathJoin, uuid } from "../utils";
+import { useStore } from "../store";
+
+// 上传进度回调结果类型
+export type OnProgressUpdateResult = {
+ progress: number;
+ totalBytesSent: number;
+ totalBytesExpectedToSend: number;
+};
+
+// 上传任务类型定义
+export type UploadTask = {
+ abort(): void;
+};
+
+// 上传选项类型定义
+export type UploadOptions = {
+ onProgressUpdate?: (result: OnProgressUpdateResult) => void; // 上传进度回调
+ onTask?: (task: UploadTask) => void; // 上传任务回调
+};
+
+// 上传模式类型
+export type UploadMode = {
+ mode: "local" | "cloud"; // 上传模式:本地或云端
+ type: string; // 云服务类型
+};
+
+// 上传请求的参数类型
+export type UploadRequestOptions = {
+ url: string;
+ preview?: string;
+ data: any;
+};
+
+// 云上传返回数据类型
+export type CloudUploadResponse = {
+ uploadUrl?: string;
+ url?: string;
+ host?: string;
+ credentials?: any;
+ OSSAccessKeyId?: string;
+ policy?: string;
+ signature?: string;
+ publicDomain?: string;
+ token?: string;
+ fields?: any;
+};
+
+// 本地上传返回数据类型
+export type LocalUploadResponse = {
+ code: number;
+ message?: string;
+ data: string;
+};
+
+// 获取上传模式(本地/云端及云类型)
+async function getUploadMode(): Promise {
+ const res = await request({
+ url: "/app/base/comm/uploadMode"
+ });
+
+ return parse(res!)!;
+}
+
+/**
+ * 路径上传
+ * @param path 文件路径
+ */
+export async function upload(path: string) {
+ return uploadFile({
+ path,
+ size: 0,
+ name: "",
+ type: "image/png"
+ });
+}
+
+/**
+ * 文件上传
+ * @param file 文件信息 ChooseImageTempFile
+ * @param options 上传选项
+ */
+export async function uploadFile(
+ file: ChooseImageTempFile,
+ options: UploadOptions | null = null
+): Promise {
+ const { user } = useStore();
+
+ // 获取上传模式和类型
+ const { mode, type } = await getUploadMode();
+
+ // 判断是否本地上传
+ const isLocal = mode == "local";
+
+ // 判断是否是云上传
+ const isCloud = mode == "cloud";
+
+ // 获取文件路径
+ const filePath = file.path;
+
+ // 获取文件名
+ let fileName = file.name;
+
+ // 如果文件名不存在,则使用文件路径的文件名
+ if (fileName == "" || fileName == null) {
+ fileName = basename(filePath);
+ }
+
+ // 获取文件扩展名
+ let ext = extname(fileName);
+ if (ext == "") {
+ ext = "png";
+ }
+
+ // 生成唯一key: 原文件名_uuid.扩展名
+ let key = `${filename(fileName)}_${uuid()}.${ext}`;
+
+ // 云上传需要加上时间戳路径
+ if (isCloud) {
+ key = `app/${Date.now()}/${key}`;
+ }
+
+ // 支持多种上传方式
+ return new Promise((resolve, reject) => {
+ /**
+ * 实际上传文件的函数
+ * @param param0 上传参数
+ */
+ function next({ url, preview, data }: UploadRequestOptions) {
+ // 发起上传请求
+ const task = uni.uploadFile({
+ url,
+ filePath,
+ name: "file",
+ header: {
+ // 本地上传带token
+ Authorization: isLocal ? user.token : null
+ },
+ formData: {
+ ...(data as UTSJSONObject),
+ key
+ },
+ success(res) {
+ if (isLocal) {
+ // 本地上传返回处理
+ const { code, data, message } = parseObject(res.data)!;
+
+ if (code == 1000) {
+ resolve(data);
+ } else {
+ reject(message);
+ }
+ } else {
+ // 云上传直接拼接url
+ resolve(pathJoin(preview ?? url, key!));
+ }
+ },
+ fail(err) {
+ console.error(err);
+ reject(err);
+ }
+ });
+
+ // 上传任务回调
+ if (options?.onTask != null) {
+ options.onTask!({
+ abort: () => {
+ task.abort();
+ }
+ } as UploadTask);
+ }
+
+ // 上传进度回调
+ if (options?.onProgressUpdate != null) {
+ task.onProgressUpdate((result) => {
+ const { progress, totalBytesSent, totalBytesExpectedToSend } = result;
+
+ options.onProgressUpdate!({
+ progress,
+ totalBytesSent,
+ totalBytesExpectedToSend
+ });
+ });
+ }
+ }
+
+ // 本地上传
+ if (isLocal) {
+ next({
+ url: config.baseUrl + "/app/base/comm/upload",
+ data: {}
+ });
+ } else {
+ // 云上传
+ const data = {} as UTSJSONObject;
+
+ // AWS需要提前传key
+ if (type == "aws") {
+ data.key = key;
+ }
+
+ // 获取云上传参数
+ request({
+ url: "/app/base/comm/upload",
+ method: "POST",
+ data
+ })
+ .then((res) => {
+ const d = parse(res!)!;
+
+ switch (type) {
+ // 腾讯云COS
+ case "cos":
+ next({
+ url: d.url!,
+ data: d.credentials!
+ });
+ break;
+ // 阿里云OSS
+ case "oss":
+ next({
+ url: d.host!,
+ data: {
+ OSSAccessKeyId: d.OSSAccessKeyId,
+ policy: d.policy,
+ signature: d.signature
+ }
+ });
+ break;
+ // 七牛云
+ case "qiniu":
+ next({
+ url: d.uploadUrl!,
+ preview: d.publicDomain,
+ data: {
+ token: d.token
+ }
+ });
+ break;
+ // 亚马逊AWS
+ case "aws":
+ next({
+ url: d.url!,
+ data: d.fields!
+ });
+ break;
+ }
+ })
+ .catch(reject);
+ }
+ });
+}
diff --git a/cool-unix/cool/utils/comm.ts b/cool-unix/cool/utils/comm.ts
new file mode 100644
index 0000000..f2b233c
--- /dev/null
+++ b/cool-unix/cool/utils/comm.ts
@@ -0,0 +1,612 @@
+/**
+ * 检查值是否为数组
+ * @example isArray([1, 2, 3]) // true
+ * @example isArray('123') // false
+ */
+export function isArray(value: any): boolean {
+ return Array.isArray(value);
+}
+
+/**
+ * 检查值是否为对象
+ * @example isObject({}) // true
+ * @example isObject([]) // false
+ */
+export function isObject(value: any): boolean {
+ return typeof value == "object" && !Array.isArray(value) && !isNull(value);
+}
+
+/**
+ * 检查值是否为字符串
+ * @example isString('abc') // true
+ * @example isString(123) // false
+ */
+export function isString(value: any): boolean {
+ return typeof value == "string";
+}
+
+/**
+ * 检查值是否为数字
+ * @example isNumber(123) // true
+ * @example isNumber('123') // false
+ */
+export function isNumber(value: any): boolean {
+ return typeof value == "number" && !isNaN(value);
+}
+
+/**
+ * 检查值是否为布尔值
+ * @example isBoolean(true) // true
+ * @example isBoolean(1) // false
+ */
+export function isBoolean(value: any): boolean {
+ return typeof value == "boolean";
+}
+
+/**
+ * 检查值是否为函数
+ * @example isFunction(() => {}) // true
+ * @example isFunction({}) // false
+ */
+export function isFunction(value: any): boolean {
+ return typeof value == "function";
+}
+
+/**
+ * 检查值是否为 null
+ * @example isNull(null) // true
+ * @example isNull(undefined) // true
+ */
+export function isNull(value?: any | null): boolean {
+ // #ifdef APP
+ return value == null;
+ // #endif
+
+ // #ifndef APP
+ return value == null || value == undefined;
+ // #endif
+}
+
+/**
+ * 检查值是否为空
+ * @example isEmpty([]) // true
+ * @example isEmpty('') // true
+ * @example isEmpty({}) // true
+ */
+export function isEmpty(value: any): boolean {
+ if (isArray(value)) {
+ return (value as any[]).length == 0;
+ }
+
+ if (isString(value)) {
+ return value == "";
+ }
+
+ if (isObject(value)) {
+ return keys(value).length == 0;
+ }
+
+ return false;
+}
+
+/**
+ * 返回对象的所有键名
+ * @example keys({a: 1, b: 2}) // ['a', 'b']
+ */
+export function keys(value: any): string[] {
+ // @ts-ignore
+ return UTSJSONObject.keys(value as UTSJSONObject);
+}
+
+/**
+ * 返回数组的第一个元素
+ * @example first([1, 2, 3]) // 1
+ * @example first([]) // null
+ */
+export function first(array: T[]): T | null {
+ return isArray(array) && array.length > 0 ? array[0] : null;
+}
+
+/**
+ * 返回数组的最后一个元素
+ * @example last([1, 2, 3]) // 3
+ * @example last([]) // null
+ */
+export function last(array: T[]): T | null {
+ return isArray(array) && array.length > 0 ? array[array.length - 1] : null;
+}
+
+/**
+ * 截取数组的一部分
+ * @example slice([1, 2, 3], 1) // [2, 3]
+ * @example slice([1, 2, 3], 1, 2) // [2]
+ */
+export function slice(array: T[], start: number = 0, end: number = array.length): T[] {
+ if (!isArray(array)) return [];
+
+ const result: T[] = [];
+
+ for (let i = start; i < end && i < array.length; i++) {
+ result.push(array[i]);
+ }
+
+ return result;
+}
+
+/**
+ * 检查对象是否包含指定属性
+ * @example has({a: 1}, 'a') // true
+ * @example has({a: 1}, 'b') // false
+ */
+export function has(object: any, key: string): boolean {
+ return keys(object).includes(key);
+}
+
+/**
+ * 获取对象的属性值
+ * @example get({a: {b: 1}}, 'a.b') // 1
+ * @example get({a: {b: 1}}, 'a.c', 'default') // 'default'
+ */
+export function get(object: any, path: string, defaultValue: any | null = null): any | null {
+ if (isNull(object)) {
+ return defaultValue;
+ }
+
+ // @ts-ignore
+ const value = new UTSJSONObject(object).getAny(path);
+
+ if (isNull(value)) {
+ return defaultValue;
+ }
+
+ return value;
+}
+
+/**
+ * 设置对象的属性值
+ * @example set({a: 1}, 'b', 2) // {a: 1, b: 2}
+ */
+export function set(object: any, key: string, value: any | null): void {
+ (object as UTSJSONObject)[key] = value;
+}
+
+/**
+ * 遍历数组并返回新数组
+ * @example map([1, 2, 3], x => x * 2) // [2, 4, 6]
+ */
+export function map(array: T[], iteratee: (item: T, index: number) => U): U[] {
+ const result: U[] = [];
+
+ if (!isArray(array)) return result;
+
+ for (let i = 0; i < array.length; i++) {
+ result.push(iteratee(array[i], i));
+ }
+
+ return result;
+}
+
+/**
+ * 将数组归约为单个值
+ * @example reduce([1, 2, 3], (sum, n) => sum + n, 0) // 6
+ */
+export function reduce(
+ array: T[],
+ iteratee: (accumulator: U, value: T, index: number) => U,
+ initialValue: U
+): U {
+ if (!isArray(array)) return initialValue;
+
+ let accumulator: U = initialValue;
+ for (let i = 0; i < array.length; i++) {
+ accumulator = iteratee(accumulator, array[i], i);
+ }
+
+ return accumulator;
+}
+
+/**
+ * 检查数组中的所有元素是否都满足条件
+ * @example every([2, 4, 6], x => x % 2 == 0) // true
+ */
+export function every(array: T[], predicate: (value: T, index: number) => boolean): boolean {
+ if (!isArray(array)) return true;
+
+ for (let i = 0; i < array.length; i++) {
+ if (!predicate(array[i], i)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * 检查数组中是否有元素满足条件
+ * @example some([1, 2, 3], x => x > 2) // true
+ */
+export function some(array: T[], predicate: (value: T, index: number) => boolean): boolean {
+ if (!isArray(array)) return false;
+
+ for (let i = 0; i < array.length; i++) {
+ if (predicate(array[i], i)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * 创建去重后的数组
+ * @example uniq([1, 2, 2, 3]) // [1, 2, 3]
+ */
+export function uniq(array: T[]): T[] {
+ if (!isArray(array)) return [];
+
+ const result: T[] = [];
+ const seen = new Map();
+
+ for (let i = 0; i < array.length; i++) {
+ const item = array[i];
+ const key = item;
+ if (!seen.has(item)) {
+ seen.set(key, true);
+ result.push(item);
+ }
+ }
+
+ return result;
+}
+
+/**
+ * 将数组扁平化一层
+ * @example flatten([1, [2, 3], 4]) // [1, 2, 3, 4]
+ */
+export function flatten(array: any[]): any[] {
+ if (!isArray(array)) return [];
+
+ const result: any[] = [];
+
+ for (let i = 0; i < array.length; i++) {
+ const item = array[i];
+ if (isArray(item)) {
+ result.push(...(item as any[]));
+ } else {
+ result.push(item);
+ }
+ }
+
+ return result;
+}
+
+/**
+ * 将数组完全扁平化
+ * @example flattenDeep([1, [2, [3, [4]]]]) // [1, 2, 3, 4]
+ */
+export function flattenDeep(array: any[]): any[] {
+ if (!isArray(array)) return [];
+
+ const result: any[] = [];
+
+ for (let i = 0; i < array.length; i++) {
+ const item = array[i];
+ if (isArray(item)) {
+ result.push(...flattenDeep(item as any[]));
+ } else {
+ result.push(item);
+ }
+ }
+
+ return result;
+}
+
+/**
+ * 对数组进行排序
+ * @example sort([3, 1, 2]) // [1, 2, 3]
+ * @example sort(['c', 'a', 'b'], 'desc') // ['c', 'b', 'a']
+ */
+export function sort(array: T[], order: "asc" | "desc" = "asc"): T[] {
+ const result = [...array];
+
+ return result.sort((a, b) => {
+ if (typeof a == "number" && typeof b == "number") {
+ return order == "asc" ? a - b : b - a;
+ }
+
+ if (typeof a == "string" && typeof b == "string") {
+ return order == "asc" ? a.localeCompare(b) : b.localeCompare(a);
+ }
+
+ return 0;
+ });
+}
+
+/**
+ * 根据对象属性对数组进行排序
+ * @example orderBy([{age: 30}, {age: 20}], 'age') // [{age: 20}, {age: 30}]
+ */
+export function orderBy(array: T[], key: string, order: "asc" | "desc" = "asc"): T[] {
+ if (!isArray(array)) return [];
+
+ const result = [...array];
+
+ result.sort((a, b) => {
+ const valueA = get(a as any, key) as number;
+ const valueB = get(b as any, key) as number;
+
+ if (order == "asc") {
+ return valueA > valueB ? 1 : -1;
+ } else {
+ return valueA < valueB ? 1 : -1;
+ }
+ });
+
+ return result;
+}
+
+/**
+ * 根据对象属性对数组进行分组
+ * @example groupBy([{type: 'a'}, {type: 'b'}, {type: 'a'}], 'type') // {a: [{type: 'a'}, {type: 'a'}], b: [{type: 'b'}]}
+ */
+export function groupBy(array: T[], key: string) {
+ if (!isArray(array)) return {};
+
+ const result = {};
+
+ for (let i = 0; i < array.length; i++) {
+ const item = array[i];
+ let value = get(item as any, key)!;
+
+ if (typeof value == "number") {
+ value = value.toString();
+ }
+
+ if (typeof value == "string") {
+ if (!isArray(result[value])) {
+ result[value] = new Array();
+ }
+
+ (result[value] as T[]).push(item);
+ }
+ }
+
+ return result;
+}
+
+/**
+ * 将多个对象的属性合并到一个对象中
+ * @example assign({a: 1}, {b: 2}) // {a: 1, b: 2}
+ */
+export function assign(...items: any[]) {
+ // @ts-ignore
+ return UTSJSONObject.assign(...items.map((item) => item as UTSJSONObject));
+}
+
+/**
+ * 获取数组中指定索引的元素
+ * @example nth([1, 2, 3], 1) // 2
+ * @example nth([1, 2, 3], -1) // 3
+ */
+export function nth(array: T[], index: number): T | null {
+ if (index >= 0) {
+ return array[index];
+ }
+
+ return array[array.length + index];
+}
+
+/**
+ * 从数组中移除指定的值
+ * @example pull([1, 2, 3, 1, 2, 3], 1, 2) // [3, 3]
+ */
+export function pull(array: T[], ...values: T[]): T[] {
+ if (!isArray(array)) return [];
+
+ return array.filter((item) => !values.includes(item));
+}
+
+/**
+ * 从数组中移除满足条件的元素
+ * @example remove([1, 2, 3, 4], x => x % 2 == 0) // [1, 3]
+ */
+export function remove(array: T[], predicate: (value: T, index: number) => boolean): T[] {
+ if (!isArray(array)) return [];
+
+ const result: T[] = [];
+
+ for (let i = 0; i < array.length; i++) {
+ if (!predicate(array[i], i)) {
+ result.push(array[i]);
+ }
+ }
+
+ return result;
+}
+
+/**
+ * 遍历数组
+ * @example forEach([1, 2, 3], x => console.log(x))
+ */
+export function forEach(data: T[], iteratee: (value: T, index: number) => void): void {
+ if (isArray(data)) {
+ const array = data as T[];
+
+ for (let i = 0; i < array.length; i++) {
+ if (array[i] != null) {
+ iteratee(array[i], i);
+ }
+ }
+ }
+}
+
+/**
+ * 查找数组中第一个满足条件的元素
+ * @example find([1, 2, 3, 4], x => x > 2) // 3
+ */
+export function find(array: T[], predicate: (value: T, index: number) => boolean): T | null {
+ if (!isArray(array)) return null;
+
+ for (let i = 0; i < array.length; i++) {
+ if (predicate(array[i], i)) {
+ return array[i];
+ }
+ }
+ return null;
+}
+
+/**
+ * 遍历对象
+ * @example forInObject({a: 1, b: 2}, (value, key) => console.log(key, value))
+ */
+export function forInObject(data: any, iteratee: (value: any, key: string) => void): void {
+ if (isObject(data)) {
+ const objKeys = keys(data);
+ for (let i = 0; i < objKeys.length; i++) {
+ const key = objKeys[i];
+ iteratee(get(data, key)!, key);
+ }
+ }
+}
+
+/**
+ * 对象转数组
+ * @example toArray({a: 1, b: 2}, (value, key) => ({key, value})) // [{key: 'a', value: 1}, {key: 'b', value: 2}]
+ */
+export function toArray(data: any, iteratee: (value: any, key: string) => T): T[] {
+ const result: T[] = [];
+
+ if (isObject(data)) {
+ forInObject(data, (value, key) => {
+ result.push(iteratee(value, key));
+ });
+ }
+
+ return result;
+}
+
+/**
+ * 生成UUID
+ * @example uuid() // "123e4567-e89b-12d3-a456-426614174000"
+ */
+export function uuid(): string {
+ let uuid = "";
+ let i: number;
+ let random: number;
+
+ for (i = 0; i < 36; i++) {
+ if (i == 8 || i == 13 || i == 18 || i == 23) {
+ uuid += "-";
+ } else if (i == 14) {
+ uuid += "4";
+ } else if (i == 19) {
+ random = (Math.random() * 16) | 0;
+ uuid += ((random & 0x3) | 0x8).toString(16);
+ } else {
+ random = (Math.random() * 16) | 0;
+ uuid += random.toString(16);
+ }
+ }
+ return uuid;
+}
+
+/**
+ * 创建一个防抖函数,在指定延迟后执行函数,如果在延迟期间再次调用则重新计时
+ * @example debounce(() => console.log('执行'), 300)
+ */
+export function debounce(func: () => void, delay: number): () => number {
+ let timeoutId = 0;
+
+ return function (): number {
+ // 清除之前的定时器
+ if (timeoutId != 0) {
+ clearTimeout(timeoutId);
+ }
+
+ // 设置新的定时器
+ // @ts-ignore
+ timeoutId = setTimeout(() => {
+ func();
+ timeoutId = 0;
+ }, delay);
+
+ return timeoutId;
+ };
+}
+
+/**
+ * 创建一个节流函数,在指定时间间隔内只会执行一次
+ * @example
+ * const throttled = throttle(() => console.log('执行'), 300)
+ * throttled()
+ */
+export function throttle(func: () => void, delay: number): () => number {
+ let timeoutId: number = 0;
+ let lastExec: number = 0;
+
+ return function (): number {
+ const now: number = Date.now();
+
+ // 如果距离上次执行已超过delay,则立即执行
+ if (now - lastExec >= delay) {
+ func();
+ lastExec = now;
+ return 0;
+ }
+
+ // 否则在剩余时间后执行
+ if (timeoutId != 0) {
+ clearTimeout(timeoutId);
+ }
+ const remaining: number = delay - (now - lastExec);
+ // @ts-ignore
+ timeoutId = setTimeout(() => {
+ func();
+ lastExec = Date.now();
+ timeoutId = 0;
+ }, remaining);
+
+ return timeoutId;
+ };
+}
+
+/**
+ * 生成指定范围内的随机数
+ * @example random(1, 10) // 随机生成1到10之间的整数
+ */
+export function random(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+}
+
+/**
+ * 将base64转换为blob
+ * @param data base64数据
+ * @returns blob数据
+ */
+export function base64ToBlob(data: string, type: string = "image/jpeg"): Blob {
+ // #ifdef H5
+ let bytes = window.atob(data.split(",")[1]);
+ let ab = new ArrayBuffer(bytes.length);
+ let ia = new Uint8Array(ab);
+ for (let i = 0; i < bytes.length; i++) {
+ ia[i] = bytes.charCodeAt(i);
+ }
+ return new Blob([ab], { type });
+ // #endif
+}
+
+/**
+ * 检查两个值是否相等
+ * @param a 值1
+ * @param b 值2
+ * @returns 是否相等
+ */
+export function isEqual(a: any, b: any): boolean {
+ if (isObject(a) && isObject(b)) {
+ return isEqual(JSON.stringify(a), JSON.stringify(b));
+ } else if (isArray(a) && isArray(b)) {
+ return isEqual(JSON.stringify(a), JSON.stringify(b));
+ }
+
+ return a == b;
+}
diff --git a/cool-unix/cool/utils/day.ts b/cool-unix/cool/utils/day.ts
new file mode 100644
index 0000000..21e307a
--- /dev/null
+++ b/cool-unix/cool/utils/day.ts
@@ -0,0 +1,324 @@
+/**
+ * 轻量级日期工具类
+ * 基于 uni-app-x UTS Date API
+ * 参考 dayjs 设计理念
+ */
+
+export class DayUts {
+ private _date: Date;
+
+ constructor(date?: Date | string | number | null) {
+ if (date == null || date == "") {
+ this._date = new Date();
+ } else if (typeof date == "string") {
+ this._date = new Date(date);
+ } else if (typeof date == "number") {
+ this._date = new Date(date);
+ } else if (date instanceof Date) {
+ this._date = new Date(date.getTime());
+ } else {
+ this._date = new Date();
+ }
+ }
+
+ /**
+ * 格式化日期
+ * @param template 格式模板,支持 YYYY-MM-DD HH:mm:ss 等
+ */
+ format(template: string): string {
+ // 使用传入的模板
+ let actualTemplate: string = template;
+
+ const year = this._date.getFullYear();
+ const month = this._date.getMonth() + 1;
+ const date = this._date.getDate();
+ const hours = this._date.getHours();
+ const minutes = this._date.getMinutes();
+ const seconds = this._date.getSeconds();
+ const milliseconds = this._date.getMilliseconds();
+
+ // 使用数组来依次替换,避免UTS的replace方法兼容性问题
+ let result: string = actualTemplate;
+
+ // 按照长度从长到短替换,避免冲突
+ // 替换年份 (YYYY 必须在 YY 之前)
+ result = result.replace("YYYY", year.toString());
+ result = result.replace("YY", year.toString().slice(-2));
+
+ // 替换月份 (MM 必须在 M 之前)
+ result = result.replace("MM", month.toString().padStart(2, "0"));
+ result = result.replace("M", month.toString());
+
+ // 替换日期 (DD 必须在 D 之前)
+ result = result.replace("DD", date.toString().padStart(2, "0"));
+ result = result.replace("D", date.toString());
+
+ // 替换小时 (HH 必须在 H 之前)
+ result = result.replace("HH", hours.toString().padStart(2, "0"));
+ result = result.replace("H", hours.toString());
+
+ // 替换分钟 (mm 必须在 m 之前)
+ result = result.replace("mm", minutes.toString().padStart(2, "0"));
+ result = result.replace("m", minutes.toString());
+
+ // 替换秒数 (ss 必须在 s 之前)
+ result = result.replace("ss", seconds.toString().padStart(2, "0"));
+ result = result.replace("s", seconds.toString());
+
+ // 替换毫秒
+ result = result.replace("SSS", milliseconds.toString().padStart(3, "0"));
+
+ return result;
+ }
+
+ /**
+ * 本月多少天
+ */
+ getDays(): number {
+ return new Date(this._date.getFullYear(), this._date.getMonth() + 1, 0).getDate();
+ }
+
+ /**
+ * 是否为闰年
+ */
+ isLeapYear(): boolean {
+ return this._date.getFullYear() % 4 == 0 && this._date.getFullYear() % 100 != 0;
+ }
+
+ /**
+ * 星期几
+ */
+ getDay(): number {
+ return this._date.getDay();
+ }
+
+ /**
+ * 获取某个单位的开始时间
+ */
+ startOf(unit: "month" | "day" | "year" | "week"): DayUts {
+ const newDate = new Date(this._date.getTime());
+
+ switch (unit) {
+ case "year":
+ newDate.setMonth(0);
+ newDate.setDate(1);
+ newDate.setHours(0);
+ newDate.setMinutes(0);
+ newDate.setSeconds(0);
+ newDate.setMilliseconds(0);
+ break;
+ case "month":
+ newDate.setDate(1);
+ newDate.setHours(0);
+ newDate.setMinutes(0);
+ newDate.setSeconds(0);
+ newDate.setMilliseconds(0);
+ break;
+ case "week":
+ newDate.setDate(newDate.getDate() - newDate.getDay());
+ newDate.setHours(0);
+ newDate.setMinutes(0);
+ newDate.setSeconds(0);
+ newDate.setMilliseconds(0);
+ break;
+ case "day":
+ newDate.setHours(0);
+ newDate.setMinutes(0);
+ newDate.setSeconds(0);
+ newDate.setMilliseconds(0);
+ break;
+ }
+
+ return new DayUts(newDate);
+ }
+
+ /**
+ * 获取某个单位的结束时间
+ */
+ endOf(unit: "month" | "day" | "year" | "week"): DayUts {
+ const newDate = new Date(this._date.getTime());
+
+ switch (unit) {
+ case "year":
+ newDate.setMonth(11);
+ newDate.setDate(31);
+ newDate.setHours(23);
+ newDate.setMinutes(59);
+ newDate.setSeconds(59);
+ newDate.setMilliseconds(999);
+ break;
+ case "month":
+ newDate.setMonth(newDate.getMonth() + 1);
+ newDate.setDate(0);
+ newDate.setHours(23);
+ newDate.setMinutes(59);
+ newDate.setSeconds(59);
+ newDate.setMilliseconds(999);
+ break;
+ case "week":
+ const day = newDate.getDay();
+ const diff = 6 - day;
+ newDate.setDate(newDate.getDate() + diff);
+ newDate.setHours(23);
+ newDate.setMinutes(59);
+ newDate.setSeconds(59);
+ newDate.setMilliseconds(999);
+ break;
+ case "day":
+ newDate.setHours(23);
+ newDate.setMinutes(59);
+ newDate.setSeconds(59);
+ newDate.setMilliseconds(999);
+ break;
+ }
+
+ return new DayUts(newDate);
+ }
+
+ /**
+ * 判断是否早于另一个日期
+ */
+ isBefore(date: DayUts | Date | string | number): boolean {
+ const compareDate = this._parseDate(date);
+ return this._date.getTime() < compareDate.getTime();
+ }
+
+ /**
+ * 判断是否晚于另一个日期
+ */
+ isAfter(date: DayUts | Date | string | number): boolean {
+ const compareDate = this._parseDate(date);
+ return this._date.getTime() > compareDate.getTime();
+ }
+
+ /**
+ * 判断是否与另一个日期相同
+ */
+ isSame(date: DayUts | Date | string | number): boolean {
+ const compareDate = this._parseDate(date);
+ return this._date.getTime() == compareDate.getTime();
+ }
+
+ /**
+ * 计算与另一个日期的差值(毫秒)
+ */
+ diff(date: DayUts | Date | string | number): number {
+ const compareDate = this._parseDate(date);
+ return this._date.getTime() - compareDate.getTime();
+ }
+
+ /**
+ * 计算与另一个日期的差值(指定单位)
+ */
+ diffUnit(
+ date: DayUts | Date | string | number,
+ unit: "day" | "hour" | "minute" | "second" | "millisecond"
+ ): number {
+ const compareDate = this._parseDate(date);
+ const diffMs = this._date.getTime() - compareDate.getTime();
+
+ switch (unit) {
+ case "day":
+ return Math.floor(diffMs / (1000 * 60 * 60 * 24));
+ case "hour":
+ return Math.floor(diffMs / (1000 * 60 * 60));
+ case "minute":
+ return Math.floor(diffMs / (1000 * 60));
+ case "second":
+ return Math.floor(diffMs / 1000);
+ case "millisecond":
+ default:
+ return diffMs;
+ }
+ }
+
+ /**
+ * 添加时间
+ */
+ add(value: number, unit: "day" | "month" | "year" | "hour" | "minute" | "second"): DayUts {
+ const newDate = new Date(this._date.getTime());
+
+ switch (unit) {
+ case "year":
+ newDate.setFullYear(newDate.getFullYear() + value);
+ break;
+ case "month":
+ newDate.setMonth(newDate.getMonth() + value);
+ break;
+ case "day":
+ newDate.setDate(newDate.getDate() + value);
+ break;
+ case "hour":
+ newDate.setHours(newDate.getHours() + value);
+ break;
+ case "minute":
+ newDate.setMinutes(newDate.getMinutes() + value);
+ break;
+ case "second":
+ newDate.setSeconds(newDate.getSeconds() + value);
+ break;
+ }
+
+ return new DayUts(newDate);
+ }
+
+ /**
+ * 减少时间
+ */
+ subtract(value: number, unit: "day" | "month" | "year" | "hour" | "minute" | "second"): DayUts {
+ return this.add(-value, unit);
+ }
+
+ /**
+ * 获取时间戳
+ */
+ valueOf(): number {
+ return this._date.getTime();
+ }
+
+ /**
+ * 获取原生Date对象
+ */
+ toDate(): Date {
+ return new Date(this._date.getTime());
+ }
+
+ /**
+ * 获取日期数组
+ */
+ toArray(): number[] {
+ return [
+ this._date.getFullYear(),
+ this._date.getMonth() + 1,
+ this._date.getDate(),
+ this._date.getHours(),
+ this._date.getMinutes(),
+ this._date.getSeconds()
+ ];
+ }
+
+ /**
+ * 私有方法:解析不同类型的日期参数
+ */
+ private _parseDate(date: DayUts | Date | string | number): Date {
+ if (date instanceof DayUts) {
+ return date.toDate();
+ } else if (date instanceof Date) {
+ return date;
+ } else if (typeof date == "string") {
+ return new Date(date);
+ } else if (typeof date == "number") {
+ return new Date(date);
+ } else {
+ // 如果都不匹配,返回当前时间
+ return new Date();
+ }
+ }
+}
+
+/**
+ * 创建 DayUts 实例
+ */
+export function dayUts(date: Date | string | number | null = new Date()): DayUts {
+ return new DayUts(date);
+}
diff --git a/cool-unix/cool/utils/device.ts b/cool-unix/cool/utils/device.ts
new file mode 100644
index 0000000..b5f73c2
--- /dev/null
+++ b/cool-unix/cool/utils/device.ts
@@ -0,0 +1,84 @@
+/**
+ * 检查是否为小程序环境
+ * @returns 是否为小程序环境
+ */
+export const isMp = (): boolean => {
+ // #ifdef MP
+ return true;
+ // #endif
+
+ return false;
+};
+
+/**
+ * 检查是否为App环境
+ * @returns 是否为App环境
+ */
+export const isApp = (): boolean => {
+ // #ifdef APP
+ return true;
+ // #endif
+
+ return false;
+};
+
+/**
+ * 检查是否为App-IOS环境
+ * @returns 是否为App-IOS环境
+ */
+export const isAppIOS = (): boolean => {
+ // #ifdef APP-IOS
+ return true;
+ // #endif
+ return false;
+};
+
+/**
+ * 检查是否为App-Android环境
+ * @returns 是否为App-Android环境
+ */
+export const isAppAndroid = (): boolean => {
+ // #ifdef APP-ANDROID
+ return true;
+ // #endif
+ return false;
+};
+
+/**
+ * 检查是否为H5环境
+ * @returns 是否为H5环境
+ */
+export const isH5 = (): boolean => {
+ // #ifdef H5
+ return true;
+ // #endif
+
+ return false;
+};
+
+/**
+ * 检查是否为鸿蒙环境
+ * @returns 是否为鸿蒙环境
+ */
+export const isHarmony = (): boolean => {
+ // #ifdef APP-HARMONY
+ return true;
+ // #endif
+
+ return false;
+};
+
+/**
+ * 获取设备像素比
+ * @returns 设备像素比
+ */
+export const getDevicePixelRatio = (): number => {
+ const dpr = uni.getDeviceInfo().devicePixelRatio ?? 1;
+
+ // #ifdef MP
+ // 微信小程序高清处理
+ return 3;
+ // #endif
+
+ return dpr;
+};
diff --git a/cool-unix/cool/utils/file.ts b/cool-unix/cool/utils/file.ts
new file mode 100644
index 0000000..f4cbe18
--- /dev/null
+++ b/cool-unix/cool/utils/file.ts
@@ -0,0 +1,74 @@
+import { base64ToBlob, uuid } from "./comm";
+
+/**
+ * 将canvas转换为png图片
+ * @param options 转换参数
+ * @returns 图片路径
+ */
+export function canvasToPng(canvasRef: UniElement): Promise {
+ return new Promise((resolve) => {
+ // #ifdef APP
+ canvasRef.parentElement!.takeSnapshot({
+ success(res) {
+ resolve(res.tempFilePath);
+ },
+ fail(err) {
+ console.error(err);
+ resolve("");
+ }
+ });
+ // #endif
+
+ // #ifdef H5
+ const url = URL.createObjectURL(
+ base64ToBlob(
+ (canvasRef as unknown as HTMLCanvasElement)?.toDataURL("image/png", 1) ?? ""
+ )
+ );
+
+ resolve(url);
+ // #endif
+
+ // #ifdef MP
+ uni.createCanvasContextAsync({
+ id: canvasRef.id,
+ component: canvasRef.$vm,
+ success(context) {
+ // 获取2D绘图上下文
+ const ctx = context.getContext("2d")!;
+
+ // 获取canvas对象
+ const canvas = ctx.canvas;
+
+ // 将canvas转换为base64格式的PNG图片数据
+ const data = canvas.toDataURL("image/png", 1);
+
+ // 获取文件系统管理器
+ const fileMg = uni.getFileSystemManager();
+
+ // 生成临时文件路径
+ // @ts-ignore
+ const filepath = `${wx.env.USER_DATA_PATH}/${uuid()}.png`;
+
+ // 将base64数据写入文件
+ fileMg.writeFile({
+ filePath: filepath,
+ data: data.split(",")[1],
+ encoding: "base64",
+ success() {
+ resolve(filepath);
+ },
+ fail(err) {
+ console.error(err);
+ resolve("");
+ }
+ });
+ },
+ fail(err) {
+ console.error(err);
+ resolve("");
+ }
+ });
+ // #endif
+ });
+}
diff --git a/cool-unix/cool/utils/index.ts b/cool-unix/cool/utils/index.ts
new file mode 100644
index 0000000..4919648
--- /dev/null
+++ b/cool-unix/cool/utils/index.ts
@@ -0,0 +1,9 @@
+export * from "./tailwind";
+export * from "./comm";
+export * from "./day";
+export * from "./device";
+export * from "./file";
+export * from "./parse";
+export * from "./path";
+export * from "./rect";
+export * from "./storage";
diff --git a/cool-unix/cool/utils/parse.ts b/cool-unix/cool/utils/parse.ts
new file mode 100644
index 0000000..6b28af3
--- /dev/null
+++ b/cool-unix/cool/utils/parse.ts
@@ -0,0 +1,244 @@
+import { forEach, forInObject, isArray, isObject, isString } from "./comm";
+
+/**
+ * 解析数据
+ * @example parse(res.data)
+ */
+export function parse(data: any): T | null {
+ // #ifdef APP-ANDROID
+ // @ts-ignore
+ return (data as UTSJSONObject).parse();
+ // #endif
+
+ // #ifndef APP-ANDROID
+ return data as T;
+ // #endif
+}
+
+/**
+ * 解析JSON对象
+ * @param data 要解析的数据
+ * @returns 解析后的JSON对象
+ */
+export function parseObject(data: string): T | null {
+ // #ifdef APP-ANDROID
+ return JSON.parseObject(data);
+ // #endif
+
+ // #ifndef APP-ANDROID
+ return JSON.parse(data) as T;
+ // #endif
+}
+
+/**
+ * 解析透传样式对象
+ * @param data 要解析的数据
+ * @returns 解析后的透传样式对象
+ * @template T 透传样式对象的类型
+ */
+export function parsePt(data: any): T {
+ // #ifdef APP-ANDROID
+ // @ts-ignore
+ return (data as UTSJSONObject).parse() ?? ({} as T);
+ // #endif
+
+ // #ifndef APP-ANDROID
+ return data as T;
+ // #endif
+}
+
+/**
+ * 解析对象为类名字符串
+ * @param obj 要解析的对象,key为类名,value为布尔值表示是否启用该类名
+ * @returns 解析后的类名字符串,多个类名以空格分隔
+ * @example
+ * parseClass({ 'active': true, 'disabled': false }) // 返回 'active'
+ * parseClass(['ml-2', 'mr-2']) // 返回 'ml-2 mr-2'
+ * parseClass([{ 'mr-2': true, 'mt-2': false }]) // 返回 'mr-2'
+ * parseClass([[true, 'mr-2 pt-2', 'mb-2']]) // 返回 'mr-2 pt-2'
+ */
+export const parseClass = (data: any): string => {
+ // 存储启用的类名
+ const names: string[] = [];
+
+ // 解析数据
+ function deep(d: any) {
+ // 如果obj是数组,则将数组中的每个元素添加到names中
+ if (isArray(d)) {
+ forEach(d as any[], (value: any) => {
+ if (isString(value)) {
+ // @example 2
+ names.push(value as string);
+ } else if (isArray(value)) {
+ // @example 4
+ const [a, b] = value as any[];
+ if (a as boolean) {
+ names.push(b as string);
+ } else {
+ if (value.length > 2) {
+ names.push(value[2] as string);
+ }
+ }
+ } else if (isObject(value)) {
+ // @example 3
+ deep(value);
+ }
+ });
+ }
+
+ // 遍历对象的每个属性
+ if (isObject(d)) {
+ // @example 1
+ forInObject(d, (value, key) => {
+ // 如果属性值为true,则将类名添加到数组中
+ if (value == true && key != "") {
+ names.push(key.trim());
+ }
+ });
+ }
+ }
+
+ deep(data);
+
+ // 将类名数组用空格连接成字符串返回
+ return names.join(" ");
+};
+
+/**
+ * 将自定义类型数据转换为UTSJSONObject对象
+ * @param data 要转换的数据
+ * @returns 转换后的UTSJSONObject对象
+ */
+export function parseToObject(data: T): UTSJSONObject {
+ // #ifdef APP-ANDROID
+ return JSON.parseObject(JSON.stringify(data ?? {})!)!;
+ // #endif
+
+ // #ifndef APP-ANDROID
+ return JSON.parse(JSON.stringify(data || {})) as UTSJSONObject;
+ // #endif
+}
+
+/**
+ * 将rpx单位转换为px单位
+ * @param rpx 要转换的rpx值
+ * @returns 转换后的px值
+ * @example
+ */
+export const rpx2px = (rpx: number): number => {
+ let px: number;
+
+ // #ifdef MP
+ px = rpx / (750 / uni.getWindowInfo().windowWidth);
+ // #endif
+
+ // #ifndef MP
+ px = uni.rpx2px(rpx);
+ // #endif
+
+ return px;
+};
+
+/**
+ * 将px单位转换为rpx单位
+ * @param px 要转换的px值
+ * @returns 转换后的rpx值
+ * @example
+ */
+export const px2rpx = (px: number): number => {
+ return px / rpx2px(1);
+};
+
+/**
+ * 将数值或字符串转换为rpx单位的字符串
+ * @param val 要转换的值,可以是数字或字符串
+ * @returns 转换后的rpx单位字符串
+ * @example
+ * parseRpx(10) // 返回 '10rpx'
+ * parseRpx('10rpx') // 返回 '10rpx'
+ * parseRpx('10px') // 返回 '10px'
+ */
+export const parseRpx = (val: number | string): string => {
+ if (typeof val == "number") {
+ return val + "rpx";
+ }
+
+ return val;
+};
+
+/**
+ * 示例: 获取数值部分
+ * @example
+ * getNum("10rpx") // 返回 10
+ * getNum("10px") // 返回 10
+ * getNum("10") // 返回 10
+ * getNum("-5.5px") // 返回 -5.5
+ * @param val - 输入值,例如 "10rpx"、"10px"、"10"
+ * @returns number - 返回提取的数值
+ */
+export const getNum = (val: string): number => {
+ // 使用正则提取数字部分,支持小数和负数
+ const match = val.match(/-?\d+(\.\d+)?/);
+ return match != null ? parseFloat(match[0] ?? "0") : 0;
+};
+
+/**
+ * 示例: 获取单位
+ * @example
+ * getUnit("10rpx") // 返回 "rpx"
+ * getUnit("10px") // 返回 "px"
+ * @param val - 输入值,例如 "10rpx"、"10px"
+ * @returns string - 返回单位字符串,如 "rpx" 或 "px"
+ */
+export const getUnit = (val: string): string => {
+ const num = getNum(val);
+ return val.replace(`${num}`, "");
+};
+
+/**
+ * 示例: 转换为 rpx 值
+ * @example
+ * getRpx("10rpx") // 返回 10
+ * getRpx("10px") // 返回 px2rpx(10)
+ * getRpx(10) // 返回 10
+ * @param val - 输入值,可以是 "10rpx"、"10px" 或数字 10
+ * @returns number - 返回对应的 rpx 数值
+ */
+export const getRpx = (val: number | string): number => {
+ if (typeof val == "number") {
+ return val;
+ }
+
+ const num = getNum(val);
+ const unit = getUnit(val);
+
+ if (unit == "px") {
+ return px2rpx(num);
+ }
+
+ return num;
+};
+
+/**
+ * 示例: 转换为 px 值
+ * @example
+ * getPx("10rpx") // 返回 rpx2px(10)
+ * getPx("10px") // 返回 10
+ * getPx(10) // 返回 rpx2px(10)
+ * @param val - 输入值,可以是 "10rpx"、"10px" 或数字 10
+ * @returns number - 返回对应的 px 数值
+ */
+export const getPx = (val: string | number) => {
+ if (typeof val == "number") {
+ return rpx2px(val);
+ }
+
+ const num = getNum(val);
+ const unit = getUnit(val);
+
+ if (unit == "rpx") {
+ return rpx2px(num);
+ }
+
+ return num;
+};
diff --git a/cool-unix/cool/utils/path.ts b/cool-unix/cool/utils/path.ts
new file mode 100644
index 0000000..58b01cd
--- /dev/null
+++ b/cool-unix/cool/utils/path.ts
@@ -0,0 +1,60 @@
+/**
+ * 获取文件名
+ * @example filename("a/b/c.txt") // "c"
+ */
+export function filename(path: string): string {
+ return basename(path.substring(0, path.lastIndexOf(".")));
+}
+
+/**
+ * 获取路径的最后一部分
+ * @example basename("a/b/c.txt") // "c.txt"
+ */
+export function basename(path: string): string {
+ let index = path.lastIndexOf("/");
+ index = index > -1 ? index : path.lastIndexOf("\\");
+ if (index < 0) {
+ return path;
+ }
+ return path.substring(index + 1);
+}
+
+/**
+ * 获取文件扩展名
+ * @example extname("a/b/c.txt") // "txt"
+ */
+export function extname(path: string): string {
+ let index = path.lastIndexOf(".");
+ if (index < 0) {
+ return "";
+ }
+ return path.substring(index + 1);
+}
+
+/**
+ * 首字母大写
+ * @example firstUpperCase("useInfo") // "UseInfo"
+ */
+export function firstUpperCase(value: string): string {
+ return value.charAt(0).toLocaleUpperCase() + value.slice(1);
+}
+
+/**
+ * 获取地址栏参数
+ * @example getUrlParam("a") // "1"
+ */
+export function getUrlParam(name: string): string | null {
+ // #ifdef H5
+ const params = new URLSearchParams(window.location.search);
+ const value = params.get(name);
+ return value !== null ? decodeURIComponent(value) : null;
+ // #endif
+}
+
+/**
+ * 连接路径
+ * @example pathJoin("https://www.baidu.com/", "/a/b/c.txt") // "https://www.baidu.com/a/b/c.txt"
+ */
+export function pathJoin(...parts: string[]): string {
+ return parts.map((part) => part.replace(/(^\/+|\/+$)/g, "")).join("/");
+}
diff --git a/cool-unix/cool/utils/rect.ts b/cool-unix/cool/utils/rect.ts
new file mode 100644
index 0000000..13aeb62
--- /dev/null
+++ b/cool-unix/cool/utils/rect.ts
@@ -0,0 +1,68 @@
+import { config } from "@/config";
+import { router } from "../router";
+import { isH5, isHarmony } from "./device";
+import { ctx } from "../ctx";
+import { getPx } from "./parse";
+
+/**
+ * 是否需要计算 tabBar 高度
+ * @returns boolean
+ */
+export function hasCustomTabBar() {
+ if (router.isTabPage()) {
+ if (isHarmony()) {
+ return false;
+ }
+
+ return config.isCustomTabBar || isH5();
+ }
+
+ return false;
+}
+
+/**
+ * 是否存在自定义 topbar
+ * @returns boolean
+ */
+export function hasCustomTopbar() {
+ return router.route()?.isCustomNavbar ?? false;
+}
+
+/**
+ * 获取安全区域高度
+ * @param type 类型
+ * @returns 安全区域高度
+ */
+export function getSafeAreaHeight(type: "top" | "bottom") {
+ const { safeAreaInsets } = uni.getWindowInfo();
+
+ let h: number;
+
+ if (type == "top") {
+ h = safeAreaInsets.top;
+ } else {
+ h = safeAreaInsets.bottom;
+
+ // #ifdef APP-ANDROID
+ if (h == 0) {
+ h = 16;
+ }
+ // #endif
+ }
+
+ return h;
+}
+
+/**
+ * 获取 tabBar 高度
+ * @returns tabBar 高度
+ */
+export function getTabBarHeight() {
+ let h = ctx.tabBar.height == null ? 50 : getPx(ctx.tabBar.height!);
+
+ if (hasCustomTabBar()) {
+ h += getSafeAreaHeight("bottom");
+ }
+
+ return h;
+}
diff --git a/cool-unix/cool/utils/storage.ts b/cool-unix/cool/utils/storage.ts
new file mode 100644
index 0000000..a78c344
--- /dev/null
+++ b/cool-unix/cool/utils/storage.ts
@@ -0,0 +1,158 @@
+// 过期时间后缀,用于标识存储数据的过期时间键名
+const EXPIRES_SUFFIX = "_deadtime";
+
+/**
+ * 存储管理类
+ *
+ * 封装了 uni-app 的存储 API,提供更便捷的存储操作
+ * 支持数据过期时间管理,自动处理过期数据
+ */
+class Storage {
+ /**
+ * 获取存储数据
+ *
+ * @param key 存储键名
+ * @returns 存储的数据,如果不存在则返回 null
+ *
+ * @example
+ * const userData = storage.get('user');
+ * if (userData != null) {
+ * console.log(userData);
+ * }
+ */
+ get(key: string): any | null {
+ return uni.getStorageSync(key);
+ }
+
+ /**
+ * 获取所有存储数据的信息
+ *
+ * 遍历所有存储键,返回包含所有键值对的对象
+ * 注意:此方法会读取所有存储数据,大量数据时需注意性能
+ *
+ * @returns 包含所有存储数据的对象
+ *
+ * @example
+ * const allData = storage.info();
+ * console.log('所有存储数据:', allData);
+ */
+ info() {
+ // 获取存储信息,包含所有键名
+ const info = uni.getStorageInfoSync();
+
+ // 创建空对象用于存放所有数据
+ const d = {};
+
+ // 遍历所有键名,获取对应的值
+ info.keys.forEach((e) => {
+ d[e] = this.get(e);
+ });
+
+ return d;
+ }
+
+ /**
+ * 设置存储数据
+ *
+ * @param key 存储键名
+ * @param value 要存储的数据,支持任意类型
+ * @param expires 过期时间(秒),默认为0表示永不过期
+ *
+ * @example
+ * // 存储永久数据
+ * storage.set('user', { name: '张三', age: 25 }, 0);
+ *
+ * // 存储5分钟后过期的数据
+ * storage.set('token', 'abc123', 300);
+ */
+ set(key: string, value: any, expires: number): void {
+ // 存储主要数据
+ uni.setStorageSync(key, value);
+
+ // 如果设置了过期时间,则存储过期时间戳
+ if (expires > 0) {
+ // 计算过期时间戳:当前时间 + 过期时间(秒转毫秒)
+ const expireTime = new Date().getTime() + expires * 1000;
+ uni.setStorageSync(`${key}${EXPIRES_SUFFIX}`, expireTime);
+ }
+ }
+
+ /**
+ * 检查数据是否已过期
+ *
+ * @param key 存储键名
+ * @returns true表示已过期或无过期时间设置,false表示未过期
+ *
+ * @example
+ * if (storage.isExpired('token')) {
+ * console.log('token已过期');
+ * }
+ */
+ isExpired(key: string): boolean {
+ // 获取过期时间戳
+ const value = uni.getStorageSync(`${key}${EXPIRES_SUFFIX}`) as number | null;
+
+ // 如果没有设置过期时间,视为已过期
+ if (value == null) {
+ return true;
+ }
+
+ // 比较过期时间戳与当前时间,判断是否过期
+ return value - new Date().getTime() <= 0;
+ }
+
+ /**
+ * 删除存储数据
+ *
+ * 会同时删除数据本身和对应的过期时间
+ *
+ * @param key 存储键名
+ *
+ * @example
+ * storage.remove('user');
+ * storage.remove('token');
+ */
+ remove(key: string) {
+ // 删除主要数据
+ uni.removeStorageSync(key);
+ // 删除对应的过期时间数据
+ uni.removeStorageSync(`${key}${EXPIRES_SUFFIX}`);
+ }
+
+ /**
+ * 清空所有存储数据
+ *
+ * 警告:此操作会删除所有本地存储数据,请谨慎使用
+ *
+ * @example
+ * storage.clear(); // 清空所有数据
+ */
+ clear() {
+ uni.clearStorageSync();
+ }
+
+ /**
+ * 获取数据后立即删除(一次性读取)
+ *
+ * 适用于临时数据、一次性令牌等场景
+ * 读取后数据会被自动删除,确保数据的一次性使用
+ *
+ * @param key 存储键名
+ * @returns 存储的数据,如果不存在则返回 null
+ *
+ * @example
+ * const tempToken = storage.once('temp_token');
+ * // tempToken 使用后,存储中的 temp_token 已被删除
+ */
+ once(key: string): any | null {
+ // 先获取数据
+ const value = this.get(key);
+ // 立即删除数据
+ this.remove(key);
+ // 返回获取到的数据
+ return value;
+ }
+}
+
+// 导出存储实例,提供全局访问
+export const storage = new Storage();
diff --git a/cool-unix/cool/utils/tailwind.ts b/cool-unix/cool/utils/tailwind.ts
new file mode 100644
index 0000000..bf47477
--- /dev/null
+++ b/cool-unix/cool/utils/tailwind.ts
@@ -0,0 +1,28 @@
+/**
+ * 判断 Tailwind class 字符串中是否包含文本颜色类(如 text-red, text-red-500, text-sky 等)
+ * @param className 传入的 class 字符串
+ * @returns 是否包含文本颜色类
+ */
+export function hasTextColor(className: string): boolean {
+ if (className == "") return false;
+
+ const regex =
+ /\btext-(primary|surface|red|blue|green|yellow|purple|pink|indigo|gray|grey|black|white|orange|amber|lime|emerald|teal|cyan|sky|violet|fuchsia|rose|slate|zinc|neutral|stone)(?:-\d+)?\b/;
+
+ return regex.test(className);
+}
+
+/**
+ * 判断 Tailwind class 字符串中是否包含字体大小类
+ * 支持如 text-xs, text-sm, text-base, text-lg, text-xl, 以及 text-[22px]、text-[22rpx] 等自定义写法
+ * @param className 传入的 class 字符串
+ * @returns 是否包含字体大小类
+ */
+export function hasTextSize(className: string): boolean {
+ if (className == "") return false;
+
+ const regex =
+ /\btext-(xs|sm|md|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl|\[\d+[a-zA-Z%]*\])\b/;
+
+ return regex.test(className);
+}
diff --git a/cool-unix/data/pca.json b/cool-unix/data/pca.json
new file mode 100644
index 0000000..30d1839
--- /dev/null
+++ b/cool-unix/data/pca.json
@@ -0,0 +1,5294 @@
+[
+ {
+ "label": "安徽省",
+ "index": "A",
+ "children": [
+ {
+ "label": "安庆市",
+ "index": "A",
+ "children": [
+ { "label": "安徽安庆经济开发区", "index": "A" },
+ { "label": "大观区", "index": "D" },
+ { "label": "怀宁县", "index": "H" },
+ { "label": "潜山市", "index": "Q" },
+ { "label": "宿松县", "index": "S" },
+ { "label": "太湖县", "index": "T" },
+ { "label": "桐城市", "index": "T" },
+ { "label": "望江县", "index": "W" },
+ { "label": "迎江区", "index": "Y" },
+ { "label": "宜秀区", "index": "Y" },
+ { "label": "岳西县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "蚌埠市",
+ "index": "B",
+ "children": [
+ { "label": "蚌山区", "index": "B" },
+ { "label": "蚌埠市高新技术开发区", "index": "B" },
+ { "label": "蚌埠市经济开发区", "index": "B" },
+ { "label": "固镇县", "index": "G" },
+ { "label": "淮上区", "index": "H" },
+ { "label": "怀远县", "index": "H" },
+ { "label": "龙子湖区", "index": "L" },
+ { "label": "五河县", "index": "W" },
+ { "label": "禹会区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "亳州市",
+ "index": "B",
+ "children": [
+ { "label": "利辛县", "index": "L" },
+ { "label": "蒙城县", "index": "M" },
+ { "label": "谯城区", "index": "Q" },
+ { "label": "涡阳县", "index": "W" }
+ ]
+ },
+ {
+ "label": "滁州市",
+ "index": "C",
+ "children": [
+ { "label": "滁州经济技术开发区", "index": "C" },
+ { "label": "定远县", "index": "D" },
+ { "label": "凤阳县", "index": "F" },
+ { "label": "琅琊区", "index": "L" },
+ { "label": "来安县", "index": "L" },
+ { "label": "明光市", "index": "M" },
+ { "label": "南谯区", "index": "N" },
+ { "label": "全椒县", "index": "Q" },
+ { "label": "天长市", "index": "T" },
+ { "label": "中新苏滁高新技术产业开发区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "池州市",
+ "index": "C",
+ "children": [
+ { "label": "东至县", "index": "D" },
+ { "label": "贵池区", "index": "G" },
+ { "label": "青阳县", "index": "Q" },
+ { "label": "石台县", "index": "S" }
+ ]
+ },
+ {
+ "label": "阜阳市",
+ "index": "F",
+ "children": [
+ { "label": "阜南县", "index": "F" },
+ { "label": "阜阳合肥现代产业园区", "index": "F" },
+ { "label": "阜阳经济技术开发区", "index": "F" },
+ { "label": "界首市", "index": "J" },
+ { "label": "临泉县", "index": "L" },
+ { "label": "太和县", "index": "T" },
+ { "label": "颍州区", "index": "Y" },
+ { "label": "颍东区", "index": "Y" },
+ { "label": "颍泉区", "index": "Y" },
+ { "label": "颍上县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "合肥市",
+ "index": "H",
+ "children": [
+ { "label": "包河区", "index": "B" },
+ { "label": "长丰县", "index": "C" },
+ { "label": "巢湖市", "index": "C" },
+ { "label": "肥东县", "index": "F" },
+ { "label": "肥西县", "index": "F" },
+ { "label": "合肥高新技术产业开发区", "index": "H" },
+ { "label": "合肥经济技术开发区", "index": "H" },
+ { "label": "合肥新站高新技术产业开发区", "index": "H" },
+ { "label": "庐阳区", "index": "L" },
+ { "label": "庐江县", "index": "L" },
+ { "label": "蜀山区", "index": "S" },
+ { "label": "瑶海区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "淮南市",
+ "index": "H",
+ "children": [
+ { "label": "八公山区", "index": "B" },
+ { "label": "大通区", "index": "D" },
+ { "label": "凤台县", "index": "F" },
+ { "label": "潘集区", "index": "P" },
+ { "label": "寿县", "index": "S" },
+ { "label": "田家庵区", "index": "T" },
+ { "label": "谢家集区", "index": "X" }
+ ]
+ },
+ {
+ "label": "淮北市",
+ "index": "H",
+ "children": [
+ { "label": "杜集区", "index": "D" },
+ { "label": "烈山区", "index": "L" },
+ { "label": "濉溪县", "index": "S" },
+ { "label": "相山区", "index": "X" }
+ ]
+ },
+ {
+ "label": "黄山市",
+ "index": "H",
+ "children": [
+ { "label": "黄山区", "index": "H" },
+ { "label": "徽州区", "index": "H" },
+ { "label": "祁门县", "index": "Q" },
+ { "label": "屯溪区", "index": "T" },
+ { "label": "歙县", "index": "X" },
+ { "label": "休宁县", "index": "X" },
+ { "label": "黟县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "六安市",
+ "index": "L",
+ "children": [
+ { "label": "霍邱县", "index": "H" },
+ { "label": "霍山县", "index": "H" },
+ { "label": "金安区", "index": "J" },
+ { "label": "金寨县", "index": "J" },
+ { "label": "舒城县", "index": "S" },
+ { "label": "裕安区", "index": "Y" },
+ { "label": "叶集区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "马鞍山市",
+ "index": "M",
+ "children": [
+ { "label": "博望区", "index": "B" },
+ { "label": "当涂县", "index": "D" },
+ { "label": "花山区", "index": "H" },
+ { "label": "含山县", "index": "H" },
+ { "label": "和县", "index": "H" },
+ { "label": "雨山区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "宿州市",
+ "index": "S",
+ "children": [
+ { "label": "砀山县", "index": "D" },
+ { "label": "灵璧县", "index": "L" },
+ { "label": "泗县", "index": "S" },
+ { "label": "宿州马鞍山现代产业园区", "index": "S" },
+ { "label": "宿州经济技术开发区", "index": "S" },
+ { "label": "萧县", "index": "X" },
+ { "label": "埇桥区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "铜陵市",
+ "index": "T",
+ "children": [
+ { "label": "枞阳县", "index": "C" },
+ { "label": "郊区", "index": "J" },
+ { "label": "铜官区", "index": "T" },
+ { "label": "义安区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "芜湖市",
+ "index": "W",
+ "children": [
+ { "label": "安徽芜湖三山经济开发区", "index": "A" },
+ { "label": "繁昌区", "index": "F" },
+ { "label": "镜湖区", "index": "J" },
+ { "label": "鸠江区", "index": "J" },
+ { "label": "南陵县", "index": "N" },
+ { "label": "湾沚区", "index": "W" },
+ { "label": "芜湖经济技术开发区", "index": "W" },
+ { "label": "无为市", "index": "W" },
+ { "label": "弋江区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "宣城市",
+ "index": "X",
+ "children": [
+ { "label": "广德市", "index": "G" },
+ { "label": "泾县", "index": "J" },
+ { "label": "绩溪县", "index": "J" },
+ { "label": "旌德县", "index": "J" },
+ { "label": "郎溪县", "index": "L" },
+ { "label": "宁国市", "index": "N" },
+ { "label": "宣州区", "index": "X" },
+ { "label": "宣城市经济开发区", "index": "X" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "北京市",
+ "index": "B",
+ "children": [
+ {
+ "label": "市辖区",
+ "index": "S",
+ "children": [
+ { "label": "昌平区", "index": "C" },
+ { "label": "东城区", "index": "D" },
+ { "label": "大兴区", "index": "D" },
+ { "label": "丰台区", "index": "F" },
+ { "label": "房山区", "index": "F" },
+ { "label": "海淀区", "index": "H" },
+ { "label": "怀柔区", "index": "H" },
+ { "label": "门头沟区", "index": "M" },
+ { "label": "密云区", "index": "M" },
+ { "label": "平谷区", "index": "P" },
+ { "label": "石景山区", "index": "S" },
+ { "label": "顺义区", "index": "S" },
+ { "label": "通州区", "index": "T" },
+ { "label": "西城区", "index": "X" },
+ { "label": "延庆区", "index": "Y" },
+ { "label": "朝阳区", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "福建省",
+ "index": "F",
+ "children": [
+ {
+ "label": "福州市",
+ "index": "F",
+ "children": [
+ { "label": "仓山区", "index": "C" },
+ { "label": "长乐区", "index": "C" },
+ { "label": "福清市", "index": "F" },
+ { "label": "鼓楼区", "index": "G" },
+ { "label": "晋安区", "index": "J" },
+ { "label": "连江县", "index": "L" },
+ { "label": "罗源县", "index": "L" },
+ { "label": "马尾区", "index": "M" },
+ { "label": "闽侯县", "index": "M" },
+ { "label": "闽清县", "index": "M" },
+ { "label": "平潭县", "index": "P" },
+ { "label": "台江区", "index": "T" },
+ { "label": "永泰县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "龙岩市",
+ "index": "L",
+ "children": [
+ { "label": "长汀县", "index": "C" },
+ { "label": "连城县", "index": "L" },
+ { "label": "上杭县", "index": "S" },
+ { "label": "武平县", "index": "W" },
+ { "label": "新罗区", "index": "X" },
+ { "label": "永定区", "index": "Y" },
+ { "label": "漳平市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "南平市",
+ "index": "N",
+ "children": [
+ { "label": "光泽县", "index": "G" },
+ { "label": "建阳区", "index": "J" },
+ { "label": "建瓯市", "index": "J" },
+ { "label": "浦城县", "index": "P" },
+ { "label": "顺昌县", "index": "S" },
+ { "label": "松溪县", "index": "S" },
+ { "label": "邵武市", "index": "S" },
+ { "label": "武夷山市", "index": "W" },
+ { "label": "延平区", "index": "Y" },
+ { "label": "政和县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "宁德市",
+ "index": "N",
+ "children": [
+ { "label": "福安市", "index": "F" },
+ { "label": "福鼎市", "index": "F" },
+ { "label": "古田县", "index": "G" },
+ { "label": "蕉城区", "index": "J" },
+ { "label": "屏南县", "index": "P" },
+ { "label": "寿宁县", "index": "S" },
+ { "label": "霞浦县", "index": "X" },
+ { "label": "周宁县", "index": "Z" },
+ { "label": "柘荣县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "莆田市",
+ "index": "P",
+ "children": [
+ { "label": "城厢区", "index": "C" },
+ { "label": "涵江区", "index": "H" },
+ { "label": "荔城区", "index": "L" },
+ { "label": "秀屿区", "index": "X" },
+ { "label": "仙游县", "index": "X" }
+ ]
+ },
+ {
+ "label": "泉州市",
+ "index": "Q",
+ "children": [
+ { "label": "安溪县", "index": "A" },
+ { "label": "德化县", "index": "D" },
+ { "label": "丰泽区", "index": "F" },
+ { "label": "惠安县", "index": "H" },
+ { "label": "金门县", "index": "J" },
+ { "label": "晋江市", "index": "J" },
+ { "label": "鲤城区", "index": "L" },
+ { "label": "洛江区", "index": "L" },
+ { "label": "南安市", "index": "N" },
+ { "label": "泉港区", "index": "Q" },
+ { "label": "石狮市", "index": "S" },
+ { "label": "永春县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "厦门市",
+ "index": "S",
+ "children": [
+ { "label": "海沧区", "index": "H" },
+ { "label": "湖里区", "index": "H" },
+ { "label": "集美区", "index": "J" },
+ { "label": "思明区", "index": "S" },
+ { "label": "同安区", "index": "T" },
+ { "label": "翔安区", "index": "X" }
+ ]
+ },
+ {
+ "label": "三明市",
+ "index": "S",
+ "children": [
+ { "label": "大田县", "index": "D" },
+ { "label": "将乐县", "index": "J" },
+ { "label": "建宁县", "index": "J" },
+ { "label": "明溪县", "index": "M" },
+ { "label": "宁化县", "index": "N" },
+ { "label": "清流县", "index": "Q" },
+ { "label": "三元区", "index": "S" },
+ { "label": "沙县区", "index": "S" },
+ { "label": "泰宁县", "index": "T" },
+ { "label": "尤溪县", "index": "Y" },
+ { "label": "永安市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "漳州市",
+ "index": "Z",
+ "children": [
+ { "label": "长泰区", "index": "C" },
+ { "label": "东山县", "index": "D" },
+ { "label": "华安县", "index": "H" },
+ { "label": "龙文区", "index": "L" },
+ { "label": "龙海区", "index": "L" },
+ { "label": "南靖县", "index": "N" },
+ { "label": "平和县", "index": "P" },
+ { "label": "芗城区", "index": "X" },
+ { "label": "云霄县", "index": "Y" },
+ { "label": "漳浦县", "index": "Z" },
+ { "label": "诏安县", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "广东省",
+ "index": "G",
+ "children": [
+ {
+ "label": "潮州市",
+ "index": "C",
+ "children": [
+ { "label": "潮安区", "index": "C" },
+ { "label": "饶平县", "index": "R" },
+ { "label": "湘桥区", "index": "X" }
+ ]
+ },
+ {
+ "label": "东莞市",
+ "index": "D",
+ "children": [
+ { "label": "茶山镇", "index": "C" },
+ { "label": "常平镇", "index": "C" },
+ { "label": "长安镇", "index": "C" },
+ { "label": "东城街道", "index": "D" },
+ { "label": "东坑镇", "index": "D" },
+ { "label": "大朗镇", "index": "D" },
+ { "label": "大岭山镇", "index": "D" },
+ { "label": "道滘镇", "index": "D" },
+ { "label": "东莞港", "index": "D" },
+ { "label": "东莞生态园", "index": "D" },
+ { "label": "东莞滨海湾新区", "index": "D" },
+ { "label": "凤岗镇", "index": "F" },
+ { "label": "莞城街道", "index": "G" },
+ { "label": "高埗镇", "index": "G" },
+ { "label": "横沥镇", "index": "H" },
+ { "label": "黄江镇", "index": "H" },
+ { "label": "虎门镇", "index": "H" },
+ { "label": "厚街镇", "index": "H" },
+ { "label": "洪梅镇", "index": "H" },
+ { "label": "寮步镇", "index": "L" },
+ { "label": "麻涌镇", "index": "M" },
+ { "label": "南城街道", "index": "N" },
+ { "label": "企石镇", "index": "Q" },
+ { "label": "桥头镇", "index": "Q" },
+ { "label": "清溪镇", "index": "Q" },
+ { "label": "石碣镇", "index": "S" },
+ { "label": "石龙镇", "index": "S" },
+ { "label": "石排镇", "index": "S" },
+ { "label": "沙田镇", "index": "S" },
+ { "label": "松山湖", "index": "S" },
+ { "label": "塘厦镇", "index": "T" },
+ { "label": "万江街道", "index": "W" },
+ { "label": "望牛墩镇", "index": "W" },
+ { "label": "谢岗镇", "index": "X" },
+ { "label": "樟木头镇", "index": "Z" },
+ { "label": "中堂镇", "index": "Z" }
+ ]
+ },
+ {
+ "label": "佛山市",
+ "index": "F",
+ "children": [
+ { "label": "禅城区", "index": "C" },
+ { "label": "高明区", "index": "G" },
+ { "label": "南海区", "index": "N" },
+ { "label": "顺德区", "index": "S" },
+ { "label": "三水区", "index": "S" }
+ ]
+ },
+ {
+ "label": "广州市",
+ "index": "G",
+ "children": [
+ { "label": "白云区", "index": "B" },
+ { "label": "从化区", "index": "C" },
+ { "label": "番禺区", "index": "F" },
+ { "label": "海珠区", "index": "H" },
+ { "label": "黄埔区", "index": "H" },
+ { "label": "花都区", "index": "H" },
+ { "label": "荔湾区", "index": "L" },
+ { "label": "南沙区", "index": "N" },
+ { "label": "天河区", "index": "T" },
+ { "label": "越秀区", "index": "Y" },
+ { "label": "增城区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "惠州市",
+ "index": "H",
+ "children": [
+ { "label": "博罗县", "index": "B" },
+ { "label": "惠城区", "index": "H" },
+ { "label": "惠阳区", "index": "H" },
+ { "label": "惠东县", "index": "H" },
+ { "label": "龙门县", "index": "L" }
+ ]
+ },
+ {
+ "label": "河源市",
+ "index": "H",
+ "children": [
+ { "label": "东源县", "index": "D" },
+ { "label": "和平县", "index": "H" },
+ { "label": "龙川县", "index": "L" },
+ { "label": "连平县", "index": "L" },
+ { "label": "源城区", "index": "Y" },
+ { "label": "紫金县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "江门市",
+ "index": "J",
+ "children": [
+ { "label": "恩平市", "index": "E" },
+ { "label": "鹤山市", "index": "H" },
+ { "label": "江海区", "index": "J" },
+ { "label": "开平市", "index": "K" },
+ { "label": "蓬江区", "index": "P" },
+ { "label": "台山市", "index": "T" },
+ { "label": "新会区", "index": "X" }
+ ]
+ },
+ {
+ "label": "揭阳市",
+ "index": "J",
+ "children": [
+ { "label": "惠来县", "index": "H" },
+ { "label": "揭东区", "index": "J" },
+ { "label": "揭西县", "index": "J" },
+ { "label": "普宁市", "index": "P" },
+ { "label": "榕城区", "index": "R" }
+ ]
+ },
+ {
+ "label": "茂名市",
+ "index": "M",
+ "children": [
+ { "label": "电白区", "index": "D" },
+ { "label": "高州市", "index": "G" },
+ { "label": "化州市", "index": "H" },
+ { "label": "茂南区", "index": "M" },
+ { "label": "信宜市", "index": "X" }
+ ]
+ },
+ {
+ "label": "梅州市",
+ "index": "M",
+ "children": [
+ { "label": "大埔县", "index": "D" },
+ { "label": "丰顺县", "index": "F" },
+ { "label": "蕉岭县", "index": "J" },
+ { "label": "梅江区", "index": "M" },
+ { "label": "梅县区", "index": "M" },
+ { "label": "平远县", "index": "P" },
+ { "label": "五华县", "index": "W" },
+ { "label": "兴宁市", "index": "X" }
+ ]
+ },
+ {
+ "label": "清远市",
+ "index": "Q",
+ "children": [
+ { "label": "佛冈县", "index": "F" },
+ { "label": "连山壮族瑶族自治县", "index": "L" },
+ { "label": "连南瑶族自治县", "index": "L" },
+ { "label": "连州市", "index": "L" },
+ { "label": "清城区", "index": "Q" },
+ { "label": "清新区", "index": "Q" },
+ { "label": "阳山县", "index": "Y" },
+ { "label": "英德市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "韶关市",
+ "index": "S",
+ "children": [
+ { "label": "乐昌市", "index": "L" },
+ { "label": "南雄市", "index": "N" },
+ { "label": "曲江区", "index": "Q" },
+ { "label": "仁化县", "index": "R" },
+ { "label": "乳源瑶族自治县", "index": "R" },
+ { "label": "始兴县", "index": "S" },
+ { "label": "武江区", "index": "W" },
+ { "label": "翁源县", "index": "W" },
+ { "label": "新丰县", "index": "X" },
+ { "label": "浈江区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "深圳市",
+ "index": "S",
+ "children": [
+ { "label": "宝安区", "index": "B" },
+ { "label": "福田区", "index": "F" },
+ { "label": "光明区", "index": "G" },
+ { "label": "罗湖区", "index": "L" },
+ { "label": "龙岗区", "index": "L" },
+ { "label": "龙华区", "index": "L" },
+ { "label": "南山区", "index": "N" },
+ { "label": "坪山区", "index": "P" },
+ { "label": "盐田区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "汕头市",
+ "index": "S",
+ "children": [
+ { "label": "潮阳区", "index": "C" },
+ { "label": "潮南区", "index": "C" },
+ { "label": "澄海区", "index": "C" },
+ { "label": "濠江区", "index": "H" },
+ { "label": "金平区", "index": "J" },
+ { "label": "龙湖区", "index": "L" },
+ { "label": "南澳县", "index": "N" }
+ ]
+ },
+ {
+ "label": "汕尾市",
+ "index": "S",
+ "children": [
+ { "label": "城区", "index": "C" },
+ { "label": "海丰县", "index": "H" },
+ { "label": "陆河县", "index": "L" },
+ { "label": "陆丰市", "index": "L" }
+ ]
+ },
+ {
+ "label": "阳江市",
+ "index": "Y",
+ "children": [
+ { "label": "江城区", "index": "J" },
+ { "label": "阳东区", "index": "Y" },
+ { "label": "阳西县", "index": "Y" },
+ { "label": "阳春市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "云浮市",
+ "index": "Y",
+ "children": [
+ { "label": "罗定市", "index": "L" },
+ { "label": "新兴县", "index": "X" },
+ { "label": "云城区", "index": "Y" },
+ { "label": "云安区", "index": "Y" },
+ { "label": "郁南县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "珠海市",
+ "index": "Z",
+ "children": [
+ { "label": "斗门区", "index": "D" },
+ { "label": "金湾区", "index": "J" },
+ { "label": "香洲区", "index": "X" }
+ ]
+ },
+ {
+ "label": "湛江市",
+ "index": "Z",
+ "children": [
+ { "label": "赤坎区", "index": "C" },
+ { "label": "廉江市", "index": "L" },
+ { "label": "雷州市", "index": "L" },
+ { "label": "麻章区", "index": "M" },
+ { "label": "坡头区", "index": "P" },
+ { "label": "遂溪县", "index": "S" },
+ { "label": "吴川市", "index": "W" },
+ { "label": "霞山区", "index": "X" },
+ { "label": "徐闻县", "index": "X" }
+ ]
+ },
+ {
+ "label": "肇庆市",
+ "index": "Z",
+ "children": [
+ { "label": "端州区", "index": "D" },
+ { "label": "鼎湖区", "index": "D" },
+ { "label": "德庆县", "index": "D" },
+ { "label": "封开县", "index": "F" },
+ { "label": "高要区", "index": "G" },
+ { "label": "广宁县", "index": "G" },
+ { "label": "怀集县", "index": "H" },
+ { "label": "四会市", "index": "S" }
+ ]
+ },
+ {
+ "label": "中山市",
+ "index": "Z",
+ "children": [
+ { "label": "板芙镇", "index": "B" },
+ { "label": "东区街道", "index": "D" },
+ { "label": "东凤镇", "index": "D" },
+ { "label": "大涌镇", "index": "D" },
+ { "label": "阜沙镇", "index": "F" },
+ { "label": "古镇镇", "index": "G" },
+ { "label": "港口镇", "index": "G" },
+ { "label": "黄圃镇", "index": "H" },
+ { "label": "横栏镇", "index": "H" },
+ { "label": "民众街道", "index": "M" },
+ { "label": "南区街道", "index": "N" },
+ { "label": "南朗街道", "index": "N" },
+ { "label": "南头镇", "index": "N" },
+ { "label": "石岐街道", "index": "S" },
+ { "label": "沙溪镇", "index": "S" },
+ { "label": "三角镇", "index": "S" },
+ { "label": "三乡镇", "index": "S" },
+ { "label": "神湾镇", "index": "S" },
+ { "label": "坦洲镇", "index": "T" },
+ { "label": "五桂山街道", "index": "W" },
+ { "label": "西区街道", "index": "X" },
+ { "label": "小榄镇", "index": "X" },
+ { "label": "中山港街道", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "广西壮族自治区",
+ "index": "G",
+ "children": [
+ {
+ "label": "北海市",
+ "index": "B",
+ "children": [
+ { "label": "海城区", "index": "H" },
+ { "label": "合浦县", "index": "H" },
+ { "label": "铁山港区", "index": "T" },
+ { "label": "银海区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "百色市",
+ "index": "B",
+ "children": [
+ { "label": "德保县", "index": "D" },
+ { "label": "靖西市", "index": "J" },
+ { "label": "凌云县", "index": "L" },
+ { "label": "乐业县", "index": "L" },
+ { "label": "隆林各族自治县", "index": "L" },
+ { "label": "那坡县", "index": "N" },
+ { "label": "平果市", "index": "P" },
+ { "label": "田阳区", "index": "T" },
+ { "label": "田东县", "index": "T" },
+ { "label": "田林县", "index": "T" },
+ { "label": "西林县", "index": "X" },
+ { "label": "右江区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "崇左市",
+ "index": "C",
+ "children": [
+ { "label": "大新县", "index": "D" },
+ { "label": "扶绥县", "index": "F" },
+ { "label": "江州区", "index": "J" },
+ { "label": "龙州县", "index": "L" },
+ { "label": "宁明县", "index": "N" },
+ { "label": "凭祥市", "index": "P" },
+ { "label": "天等县", "index": "T" }
+ ]
+ },
+ {
+ "label": "防城港市",
+ "index": "F",
+ "children": [
+ { "label": "东兴市", "index": "D" },
+ { "label": "防城区", "index": "F" },
+ { "label": "港口区", "index": "G" },
+ { "label": "上思县", "index": "S" }
+ ]
+ },
+ {
+ "label": "桂林市",
+ "index": "G",
+ "children": [
+ { "label": "叠彩区", "index": "D" },
+ { "label": "灌阳县", "index": "G" },
+ { "label": "恭城瑶族自治县", "index": "G" },
+ { "label": "临桂区", "index": "L" },
+ { "label": "灵川县", "index": "L" },
+ { "label": "龙胜各族自治县", "index": "L" },
+ { "label": "荔浦市", "index": "L" },
+ { "label": "平乐县", "index": "P" },
+ { "label": "七星区", "index": "Q" },
+ { "label": "全州县", "index": "Q" },
+ { "label": "秀峰区", "index": "X" },
+ { "label": "象山区", "index": "X" },
+ { "label": "兴安县", "index": "X" },
+ { "label": "雁山区", "index": "Y" },
+ { "label": "阳朔县", "index": "Y" },
+ { "label": "永福县", "index": "Y" },
+ { "label": "资源县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "贵港市",
+ "index": "G",
+ "children": [
+ { "label": "港北区", "index": "G" },
+ { "label": "港南区", "index": "G" },
+ { "label": "桂平市", "index": "G" },
+ { "label": "平南县", "index": "P" },
+ { "label": "覃塘区", "index": "T" }
+ ]
+ },
+ {
+ "label": "贺州市",
+ "index": "H",
+ "children": [
+ { "label": "八步区", "index": "B" },
+ { "label": "富川瑶族自治县", "index": "F" },
+ { "label": "平桂区", "index": "P" },
+ { "label": "昭平县", "index": "Z" },
+ { "label": "钟山县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "河池市",
+ "index": "H",
+ "children": [
+ { "label": "巴马瑶族自治县", "index": "B" },
+ { "label": "东兰县", "index": "D" },
+ { "label": "都安瑶族自治县", "index": "D" },
+ { "label": "大化瑶族自治县", "index": "D" },
+ { "label": "凤山县", "index": "F" },
+ { "label": "环江毛南族自治县", "index": "H" },
+ { "label": "金城江区", "index": "J" },
+ { "label": "罗城仫佬族自治县", "index": "L" },
+ { "label": "南丹县", "index": "N" },
+ { "label": "天峨县", "index": "T" },
+ { "label": "宜州区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "柳州市",
+ "index": "L",
+ "children": [
+ { "label": "城中区", "index": "C" },
+ { "label": "柳南区", "index": "L" },
+ { "label": "柳北区", "index": "L" },
+ { "label": "柳江区", "index": "L" },
+ { "label": "柳城县", "index": "L" },
+ { "label": "鹿寨县", "index": "L" },
+ { "label": "融安县", "index": "R" },
+ { "label": "融水苗族自治县", "index": "R" },
+ { "label": "三江侗族自治县", "index": "S" },
+ { "label": "鱼峰区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "来宾市",
+ "index": "L",
+ "children": [
+ { "label": "合山市", "index": "H" },
+ { "label": "金秀瑶族自治县", "index": "J" },
+ { "label": "武宣县", "index": "W" },
+ { "label": "兴宾区", "index": "X" },
+ { "label": "忻城县", "index": "X" },
+ { "label": "象州县", "index": "X" }
+ ]
+ },
+ {
+ "label": "南宁市",
+ "index": "N",
+ "children": [
+ { "label": "宾阳县", "index": "B" },
+ { "label": "横州市", "index": "H" },
+ { "label": "江南区", "index": "J" },
+ { "label": "良庆区", "index": "L" },
+ { "label": "隆安县", "index": "L" },
+ { "label": "马山县", "index": "M" },
+ { "label": "青秀区", "index": "Q" },
+ { "label": "上林县", "index": "S" },
+ { "label": "武鸣区", "index": "W" },
+ { "label": "兴宁区", "index": "X" },
+ { "label": "西乡塘区", "index": "X" },
+ { "label": "邕宁区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "钦州市",
+ "index": "Q",
+ "children": [
+ { "label": "灵山县", "index": "L" },
+ { "label": "浦北县", "index": "P" },
+ { "label": "钦南区", "index": "Q" },
+ { "label": "钦北区", "index": "Q" }
+ ]
+ },
+ {
+ "label": "梧州市",
+ "index": "W",
+ "children": [
+ { "label": "长洲区", "index": "C" },
+ { "label": "苍梧县", "index": "C" },
+ { "label": "岑溪市", "index": "C" },
+ { "label": "龙圩区", "index": "L" },
+ { "label": "蒙山县", "index": "M" },
+ { "label": "藤县", "index": "T" },
+ { "label": "万秀区", "index": "W" }
+ ]
+ },
+ {
+ "label": "玉林市",
+ "index": "Y",
+ "children": [
+ { "label": "博白县", "index": "B" },
+ { "label": "北流市", "index": "B" },
+ { "label": "福绵区", "index": "F" },
+ { "label": "陆川县", "index": "L" },
+ { "label": "容县", "index": "R" },
+ { "label": "兴业县", "index": "X" },
+ { "label": "玉州区", "index": "Y" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "贵州省",
+ "index": "G",
+ "children": [
+ {
+ "label": "安顺市",
+ "index": "A",
+ "children": [
+ { "label": "关岭布依族苗族自治县", "index": "G" },
+ { "label": "平坝区", "index": "P" },
+ { "label": "普定县", "index": "P" },
+ { "label": "西秀区", "index": "X" },
+ { "label": "镇宁布依族苗族自治县", "index": "Z" },
+ { "label": "紫云苗族布依族自治县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "毕节市",
+ "index": "B",
+ "children": [
+ { "label": "大方县", "index": "D" },
+ { "label": "赫章县", "index": "H" },
+ { "label": "金沙县", "index": "J" },
+ { "label": "纳雍县", "index": "N" },
+ { "label": "七星关区", "index": "Q" },
+ { "label": "黔西市", "index": "Q" },
+ { "label": "威宁彝族回族苗族自治县", "index": "W" },
+ { "label": "织金县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "贵阳市",
+ "index": "G",
+ "children": [
+ { "label": "白云区", "index": "B" },
+ { "label": "观山湖区", "index": "G" },
+ { "label": "花溪区", "index": "H" },
+ { "label": "开阳县", "index": "K" },
+ { "label": "南明区", "index": "N" },
+ { "label": "清镇市", "index": "Q" },
+ { "label": "乌当区", "index": "W" },
+ { "label": "息烽县", "index": "X" },
+ { "label": "修文县", "index": "X" },
+ { "label": "云岩区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "六盘水市",
+ "index": "L",
+ "children": [
+ { "label": "六枝特区", "index": "L" },
+ { "label": "盘州市", "index": "P" },
+ { "label": "水城区", "index": "S" },
+ { "label": "钟山区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "黔西南布依族苗族自治州",
+ "index": "Q",
+ "children": [
+ { "label": "安龙县", "index": "A" },
+ { "label": "册亨县", "index": "C" },
+ { "label": "普安县", "index": "P" },
+ { "label": "晴隆县", "index": "Q" },
+ { "label": "望谟县", "index": "W" },
+ { "label": "兴义市", "index": "X" },
+ { "label": "兴仁市", "index": "X" },
+ { "label": "贞丰县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "黔东南苗族侗族自治州",
+ "index": "Q",
+ "children": [
+ { "label": "岑巩县", "index": "C" },
+ { "label": "从江县", "index": "C" },
+ { "label": "丹寨县", "index": "D" },
+ { "label": "黄平县", "index": "H" },
+ { "label": "锦屏县", "index": "J" },
+ { "label": "剑河县", "index": "J" },
+ { "label": "凯里市", "index": "K" },
+ { "label": "黎平县", "index": "L" },
+ { "label": "雷山县", "index": "L" },
+ { "label": "麻江县", "index": "M" },
+ { "label": "榕江县", "index": "R" },
+ { "label": "施秉县", "index": "S" },
+ { "label": "三穗县", "index": "S" },
+ { "label": "天柱县", "index": "T" },
+ { "label": "台江县", "index": "T" },
+ { "label": "镇远县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "黔南布依族苗族自治州",
+ "index": "Q",
+ "children": [
+ { "label": "长顺县", "index": "C" },
+ { "label": "都匀市", "index": "D" },
+ { "label": "独山县", "index": "D" },
+ { "label": "福泉市", "index": "F" },
+ { "label": "贵定县", "index": "G" },
+ { "label": "惠水县", "index": "H" },
+ { "label": "荔波县", "index": "L" },
+ { "label": "罗甸县", "index": "L" },
+ { "label": "龙里县", "index": "L" },
+ { "label": "平塘县", "index": "P" },
+ { "label": "三都水族自治县", "index": "S" },
+ { "label": "瓮安县", "index": "W" }
+ ]
+ },
+ {
+ "label": "铜仁市",
+ "index": "T",
+ "children": [
+ { "label": "碧江区", "index": "B" },
+ { "label": "德江县", "index": "D" },
+ { "label": "江口县", "index": "J" },
+ { "label": "石阡县", "index": "S" },
+ { "label": "思南县", "index": "S" },
+ { "label": "松桃苗族自治县", "index": "S" },
+ { "label": "万山区", "index": "W" },
+ { "label": "玉屏侗族自治县", "index": "Y" },
+ { "label": "印江土家族苗族自治县", "index": "Y" },
+ { "label": "沿河土家族自治县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "遵义市",
+ "index": "Z",
+ "children": [
+ { "label": "播州区", "index": "B" },
+ { "label": "赤水市", "index": "C" },
+ { "label": "道真仡佬族苗族自治县", "index": "D" },
+ { "label": "凤冈县", "index": "F" },
+ { "label": "红花岗区", "index": "H" },
+ { "label": "汇川区", "index": "H" },
+ { "label": "湄潭县", "index": "M" },
+ { "label": "仁怀市", "index": "R" },
+ { "label": "绥阳县", "index": "S" },
+ { "label": "桐梓县", "index": "T" },
+ { "label": "务川仡佬族苗族自治县", "index": "W" },
+ { "label": "习水县", "index": "X" },
+ { "label": "余庆县", "index": "Y" },
+ { "label": "正安县", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "甘肃省",
+ "index": "G",
+ "children": [
+ {
+ "label": "白银市",
+ "index": "B",
+ "children": [
+ { "label": "白银区", "index": "B" },
+ { "label": "会宁县", "index": "H" },
+ { "label": "靖远县", "index": "J" },
+ { "label": "景泰县", "index": "J" },
+ { "label": "平川区", "index": "P" }
+ ]
+ },
+ {
+ "label": "定西市",
+ "index": "D",
+ "children": [
+ { "label": "安定区", "index": "A" },
+ { "label": "陇西县", "index": "L" },
+ { "label": "临洮县", "index": "L" },
+ { "label": "岷县", "index": "M" },
+ { "label": "通渭县", "index": "T" },
+ { "label": "渭源县", "index": "W" },
+ { "label": "漳县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "甘南藏族自治州",
+ "index": "G",
+ "children": [
+ { "label": "迭部县", "index": "D" },
+ { "label": "合作市", "index": "H" },
+ { "label": "临潭县", "index": "L" },
+ { "label": "碌曲县", "index": "L" },
+ { "label": "玛曲县", "index": "M" },
+ { "label": "夏河县", "index": "X" },
+ { "label": "卓尼县", "index": "Z" },
+ { "label": "舟曲县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "嘉峪关市",
+ "index": "J",
+ "children": [
+ { "label": "钢城街道", "index": "G" },
+ { "label": "文殊镇", "index": "W" },
+ { "label": "雄关街道", "index": "X" },
+ { "label": "新城镇", "index": "X" },
+ { "label": "峪泉镇", "index": "Y" }
+ ]
+ },
+ {
+ "label": "金昌市",
+ "index": "J",
+ "children": [
+ { "label": "金川区", "index": "J" },
+ { "label": "永昌县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "酒泉市",
+ "index": "J",
+ "children": [
+ { "label": "阿克塞哈萨克族自治县", "index": "A" },
+ { "label": "敦煌市", "index": "D" },
+ { "label": "瓜州县", "index": "G" },
+ { "label": "金塔县", "index": "J" },
+ { "label": "肃州区", "index": "S" },
+ { "label": "肃北蒙古族自治县", "index": "S" },
+ { "label": "玉门市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "兰州市",
+ "index": "L",
+ "children": [
+ { "label": "安宁区", "index": "A" },
+ { "label": "城关区", "index": "C" },
+ { "label": "皋兰县", "index": "G" },
+ { "label": "红古区", "index": "H" },
+ { "label": "兰州新区", "index": "L" },
+ { "label": "七里河区", "index": "Q" },
+ { "label": "西固区", "index": "X" },
+ { "label": "永登县", "index": "Y" },
+ { "label": "榆中县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "陇南市",
+ "index": "L",
+ "children": [
+ { "label": "成县", "index": "C" },
+ { "label": "宕昌县", "index": "D" },
+ { "label": "徽县", "index": "H" },
+ { "label": "康县", "index": "K" },
+ { "label": "礼县", "index": "L" },
+ { "label": "两当县", "index": "L" },
+ { "label": "武都区", "index": "W" },
+ { "label": "文县", "index": "W" },
+ { "label": "西和县", "index": "X" }
+ ]
+ },
+ {
+ "label": "临夏回族自治州",
+ "index": "L",
+ "children": [
+ { "label": "东乡族自治县", "index": "D" },
+ { "label": "广河县", "index": "G" },
+ { "label": "和政县", "index": "H" },
+ { "label": "积石山保安族东乡族撒拉族自治县", "index": "J" },
+ { "label": "康乐县", "index": "K" },
+ { "label": "临夏市", "index": "L" },
+ { "label": "临夏县", "index": "L" },
+ { "label": "永靖县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "平凉市",
+ "index": "P",
+ "children": [
+ { "label": "崇信县", "index": "C" },
+ { "label": "华亭市", "index": "H" },
+ { "label": "泾川县", "index": "J" },
+ { "label": "静宁县", "index": "J" },
+ { "label": "崆峒区", "index": "K" },
+ { "label": "灵台县", "index": "L" },
+ { "label": "庄浪县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "庆阳市",
+ "index": "Q",
+ "children": [
+ { "label": "环县", "index": "H" },
+ { "label": "华池县", "index": "H" },
+ { "label": "合水县", "index": "H" },
+ { "label": "宁县", "index": "N" },
+ { "label": "庆城县", "index": "Q" },
+ { "label": "西峰区", "index": "X" },
+ { "label": "正宁县", "index": "Z" },
+ { "label": "镇原县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "天水市",
+ "index": "T",
+ "children": [
+ { "label": "甘谷县", "index": "G" },
+ { "label": "麦积区", "index": "M" },
+ { "label": "秦州区", "index": "Q" },
+ { "label": "清水县", "index": "Q" },
+ { "label": "秦安县", "index": "Q" },
+ { "label": "武山县", "index": "W" },
+ { "label": "张家川回族自治县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "武威市",
+ "index": "W",
+ "children": [
+ { "label": "古浪县", "index": "G" },
+ { "label": "凉州区", "index": "L" },
+ { "label": "民勤县", "index": "M" },
+ { "label": "天祝藏族自治县", "index": "T" }
+ ]
+ },
+ {
+ "label": "张掖市",
+ "index": "Z",
+ "children": [
+ { "label": "甘州区", "index": "G" },
+ { "label": "高台县", "index": "G" },
+ { "label": "临泽县", "index": "L" },
+ { "label": "民乐县", "index": "M" },
+ { "label": "肃南裕固族自治县", "index": "S" },
+ { "label": "山丹县", "index": "S" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "河北省",
+ "index": "H",
+ "children": [
+ {
+ "label": "保定市",
+ "index": "B",
+ "children": [
+ { "label": "安新县", "index": "A" },
+ { "label": "安国市", "index": "A" },
+ { "label": "博野县", "index": "B" },
+ { "label": "保定高新技术产业开发区", "index": "B" },
+ { "label": "保定白沟新城", "index": "B" },
+ { "label": "定兴县", "index": "D" },
+ { "label": "定州市", "index": "D" },
+ { "label": "阜平县", "index": "F" },
+ { "label": "高阳县", "index": "G" },
+ { "label": "高碑店市", "index": "G" },
+ { "label": "竞秀区", "index": "J" },
+ { "label": "莲池区", "index": "L" },
+ { "label": "涞水县", "index": "L" },
+ { "label": "涞源县", "index": "L" },
+ { "label": "蠡县", "index": "L" },
+ { "label": "满城区", "index": "M" },
+ { "label": "清苑区", "index": "Q" },
+ { "label": "曲阳县", "index": "Q" },
+ { "label": "容城县", "index": "R" },
+ { "label": "顺平县", "index": "S" },
+ { "label": "唐县", "index": "T" },
+ { "label": "望都县", "index": "W" },
+ { "label": "徐水区", "index": "X" },
+ { "label": "雄县", "index": "X" },
+ { "label": "易县", "index": "Y" },
+ { "label": "涿州市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "承德市",
+ "index": "C",
+ "children": [
+ { "label": "承德县", "index": "C" },
+ { "label": "承德高新技术产业开发区", "index": "C" },
+ { "label": "丰宁满族自治县", "index": "F" },
+ { "label": "宽城满族自治县", "index": "K" },
+ { "label": "滦平县", "index": "L" },
+ { "label": "隆化县", "index": "L" },
+ { "label": "平泉市", "index": "P" },
+ { "label": "双桥区", "index": "S" },
+ { "label": "双滦区", "index": "S" },
+ { "label": "围场满族蒙古族自治县", "index": "W" },
+ { "label": "兴隆县", "index": "X" },
+ { "label": "鹰手营子矿区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "沧州市",
+ "index": "C",
+ "children": [
+ { "label": "泊头市", "index": "B" },
+ { "label": "沧县", "index": "C" },
+ { "label": "沧州高新技术产业开发区", "index": "C" },
+ { "label": "沧州渤海新区", "index": "C" },
+ { "label": "东光县", "index": "D" },
+ { "label": "海兴县", "index": "H" },
+ { "label": "河北沧州经济开发区", "index": "H" },
+ { "label": "黄骅市", "index": "H" },
+ { "label": "河间市", "index": "H" },
+ { "label": "孟村回族自治县", "index": "M" },
+ { "label": "南皮县", "index": "N" },
+ { "label": "青县", "index": "Q" },
+ { "label": "任丘市", "index": "R" },
+ { "label": "肃宁县", "index": "S" },
+ { "label": "吴桥县", "index": "W" },
+ { "label": "新华区", "index": "X" },
+ { "label": "献县", "index": "X" },
+ { "label": "运河区", "index": "Y" },
+ { "label": "盐山县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "邯郸市",
+ "index": "H",
+ "children": [
+ { "label": "丛台区", "index": "C" },
+ { "label": "成安县", "index": "C" },
+ { "label": "磁县", "index": "C" },
+ { "label": "大名县", "index": "D" },
+ { "label": "复兴区", "index": "F" },
+ { "label": "峰峰矿区", "index": "F" },
+ { "label": "肥乡区", "index": "F" },
+ { "label": "广平县", "index": "G" },
+ { "label": "馆陶县", "index": "G" },
+ { "label": "邯山区", "index": "H" },
+ { "label": "邯郸经济技术开发区", "index": "H" },
+ { "label": "邯郸冀南新区", "index": "H" },
+ { "label": "鸡泽县", "index": "J" },
+ { "label": "临漳县", "index": "L" },
+ { "label": "邱县", "index": "Q" },
+ { "label": "曲周县", "index": "Q" },
+ { "label": "涉县", "index": "S" },
+ { "label": "魏县", "index": "W" },
+ { "label": "武安市", "index": "W" },
+ { "label": "永年区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "衡水市",
+ "index": "H",
+ "children": [
+ { "label": "安平县", "index": "A" },
+ { "label": "阜城县", "index": "F" },
+ { "label": "故城县", "index": "G" },
+ { "label": "河北衡水高新技术产业开发区", "index": "H" },
+ { "label": "衡水滨湖新区", "index": "H" },
+ { "label": "冀州区", "index": "J" },
+ { "label": "景县", "index": "J" },
+ { "label": "饶阳县", "index": "R" },
+ { "label": "深州市", "index": "S" },
+ { "label": "桃城区", "index": "T" },
+ { "label": "武邑县", "index": "W" },
+ { "label": "武强县", "index": "W" },
+ { "label": "枣强县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "廊坊市",
+ "index": "L",
+ "children": [
+ { "label": "安次区", "index": "A" },
+ { "label": "霸州市", "index": "B" },
+ { "label": "大城县", "index": "D" },
+ { "label": "大厂回族自治县", "index": "D" },
+ { "label": "广阳区", "index": "G" },
+ { "label": "固安县", "index": "G" },
+ { "label": "廊坊经济技术开发区", "index": "L" },
+ { "label": "三河市", "index": "S" },
+ { "label": "文安县", "index": "W" },
+ { "label": "香河县", "index": "X" },
+ { "label": "永清县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "秦皇岛市",
+ "index": "Q",
+ "children": [
+ { "label": "北戴河区", "index": "B" },
+ { "label": "北戴河新区", "index": "B" },
+ { "label": "昌黎县", "index": "C" },
+ { "label": "抚宁区", "index": "F" },
+ { "label": "海港区", "index": "H" },
+ { "label": "卢龙县", "index": "L" },
+ { "label": "青龙满族自治县", "index": "Q" },
+ { "label": "秦皇岛市经济技术开发区", "index": "Q" },
+ { "label": "山海关区", "index": "S" }
+ ]
+ },
+ {
+ "label": "石家庄市",
+ "index": "S",
+ "children": [
+ { "label": "长安区", "index": "C" },
+ { "label": "藁城区", "index": "G" },
+ { "label": "高邑县", "index": "G" },
+ { "label": "行唐县", "index": "H" },
+ { "label": "井陉矿区", "index": "J" },
+ { "label": "井陉县", "index": "J" },
+ { "label": "晋州市", "index": "J" },
+ { "label": "鹿泉区", "index": "L" },
+ { "label": "栾城区", "index": "L" },
+ { "label": "灵寿县", "index": "L" },
+ { "label": "平山县", "index": "P" },
+ { "label": "桥西区", "index": "Q" },
+ { "label": "深泽县", "index": "S" },
+ { "label": "石家庄高新技术产业开发区", "index": "S" },
+ { "label": "石家庄循环化工园区", "index": "S" },
+ { "label": "无极县", "index": "W" },
+ { "label": "新华区", "index": "X" },
+ { "label": "辛集市", "index": "X" },
+ { "label": "新乐市", "index": "X" },
+ { "label": "裕华区", "index": "Y" },
+ { "label": "元氏县", "index": "Y" },
+ { "label": "正定县", "index": "Z" },
+ { "label": "赞皇县", "index": "Z" },
+ { "label": "赵县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "唐山市",
+ "index": "T",
+ "children": [
+ { "label": "曹妃甸区", "index": "C" },
+ { "label": "丰南区", "index": "F" },
+ { "label": "丰润区", "index": "F" },
+ { "label": "古冶区", "index": "G" },
+ { "label": "河北唐山芦台经济开发区", "index": "H" },
+ { "label": "河北唐山海港经济开发区", "index": "H" },
+ { "label": "开平区", "index": "K" },
+ { "label": "路南区", "index": "L" },
+ { "label": "路北区", "index": "L" },
+ { "label": "滦南县", "index": "L" },
+ { "label": "乐亭县", "index": "L" },
+ { "label": "滦州市", "index": "L" },
+ { "label": "迁西县", "index": "Q" },
+ { "label": "迁安市", "index": "Q" },
+ { "label": "唐山市汉沽管理区", "index": "T" },
+ { "label": "唐山高新技术产业开发区", "index": "T" },
+ { "label": "玉田县", "index": "Y" },
+ { "label": "遵化市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "邢台市",
+ "index": "X",
+ "children": [
+ { "label": "柏乡县", "index": "B" },
+ { "label": "广宗县", "index": "G" },
+ { "label": "河北邢台经济开发区", "index": "H" },
+ { "label": "巨鹿县", "index": "J" },
+ { "label": "临城县", "index": "L" },
+ { "label": "隆尧县", "index": "L" },
+ { "label": "临西县", "index": "L" },
+ { "label": "南和区", "index": "N" },
+ { "label": "内丘县", "index": "N" },
+ { "label": "宁晋县", "index": "N" },
+ { "label": "南宫市", "index": "N" },
+ { "label": "平乡县", "index": "P" },
+ { "label": "清河县", "index": "Q" },
+ { "label": "任泽区", "index": "R" },
+ { "label": "沙河市", "index": "S" },
+ { "label": "威县", "index": "W" },
+ { "label": "襄都区", "index": "X" },
+ { "label": "信都区", "index": "X" },
+ { "label": "新河县", "index": "X" }
+ ]
+ },
+ {
+ "label": "张家口市",
+ "index": "Z",
+ "children": [
+ { "label": "崇礼区", "index": "C" },
+ { "label": "赤城县", "index": "C" },
+ { "label": "沽源县", "index": "G" },
+ { "label": "怀安县", "index": "H" },
+ { "label": "怀来县", "index": "H" },
+ { "label": "康保县", "index": "K" },
+ { "label": "桥东区", "index": "Q" },
+ { "label": "桥西区", "index": "Q" },
+ { "label": "尚义县", "index": "S" },
+ { "label": "万全区", "index": "W" },
+ { "label": "蔚县", "index": "W" },
+ { "label": "宣化区", "index": "X" },
+ { "label": "下花园区", "index": "X" },
+ { "label": "阳原县", "index": "Y" },
+ { "label": "张北县", "index": "Z" },
+ { "label": "涿鹿县", "index": "Z" },
+ { "label": "张家口经济开发区", "index": "Z" },
+ { "label": "张家口市察北管理区", "index": "Z" },
+ { "label": "张家口市塞北管理区", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "黑龙江省",
+ "index": "H",
+ "children": [
+ {
+ "label": "大庆市",
+ "index": "D",
+ "children": [
+ { "label": "大同区", "index": "D" },
+ { "label": "杜尔伯特蒙古族自治县", "index": "D" },
+ { "label": "大庆高新技术产业开发区", "index": "D" },
+ { "label": "红岗区", "index": "H" },
+ { "label": "龙凤区", "index": "L" },
+ { "label": "林甸县", "index": "L" },
+ { "label": "让胡路区", "index": "R" },
+ { "label": "萨尔图区", "index": "S" },
+ { "label": "肇州县", "index": "Z" },
+ { "label": "肇源县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "大兴安岭地区",
+ "index": "D",
+ "children": [
+ { "label": "呼玛县", "index": "H" },
+ { "label": "呼中区", "index": "H" },
+ { "label": "加格达奇区", "index": "J" },
+ { "label": "漠河市", "index": "M" },
+ { "label": "松岭区", "index": "S" },
+ { "label": "塔河县", "index": "T" },
+ { "label": "新林区", "index": "X" }
+ ]
+ },
+ {
+ "label": "哈尔滨市",
+ "index": "H",
+ "children": [
+ { "label": "阿城区", "index": "A" },
+ { "label": "宾县", "index": "B" },
+ { "label": "巴彦县", "index": "B" },
+ { "label": "道里区", "index": "D" },
+ { "label": "道外区", "index": "D" },
+ { "label": "方正县", "index": "F" },
+ { "label": "呼兰区", "index": "H" },
+ { "label": "木兰县", "index": "M" },
+ { "label": "南岗区", "index": "N" },
+ { "label": "平房区", "index": "P" },
+ { "label": "松北区", "index": "S" },
+ { "label": "双城区", "index": "S" },
+ { "label": "尚志市", "index": "S" },
+ { "label": "通河县", "index": "T" },
+ { "label": "五常市", "index": "W" },
+ { "label": "香坊区", "index": "X" },
+ { "label": "依兰县", "index": "Y" },
+ { "label": "延寿县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "鹤岗市",
+ "index": "H",
+ "children": [
+ { "label": "东山区", "index": "D" },
+ { "label": "工农区", "index": "G" },
+ { "label": "萝北县", "index": "L" },
+ { "label": "南山区", "index": "N" },
+ { "label": "绥滨县", "index": "S" },
+ { "label": "向阳区", "index": "X" },
+ { "label": "兴安区", "index": "X" },
+ { "label": "兴山区", "index": "X" }
+ ]
+ },
+ {
+ "label": "黑河市",
+ "index": "H",
+ "children": [
+ { "label": "爱辉区", "index": "A" },
+ { "label": "北安市", "index": "B" },
+ { "label": "嫩江市", "index": "N" },
+ { "label": "孙吴县", "index": "S" },
+ { "label": "五大连池市", "index": "W" },
+ { "label": "逊克县", "index": "X" }
+ ]
+ },
+ {
+ "label": "鸡西市",
+ "index": "J",
+ "children": [
+ { "label": "城子河区", "index": "C" },
+ { "label": "滴道区", "index": "D" },
+ { "label": "恒山区", "index": "H" },
+ { "label": "虎林市", "index": "H" },
+ { "label": "鸡冠区", "index": "J" },
+ { "label": "鸡东县", "index": "J" },
+ { "label": "梨树区", "index": "L" },
+ { "label": "麻山区", "index": "M" },
+ { "label": "密山市", "index": "M" }
+ ]
+ },
+ {
+ "label": "佳木斯市",
+ "index": "J",
+ "children": [
+ { "label": "东风区", "index": "D" },
+ { "label": "富锦市", "index": "F" },
+ { "label": "抚远市", "index": "F" },
+ { "label": "桦南县", "index": "H" },
+ { "label": "桦川县", "index": "H" },
+ { "label": "郊区", "index": "J" },
+ { "label": "前进区", "index": "Q" },
+ { "label": "汤原县", "index": "T" },
+ { "label": "同江市", "index": "T" },
+ { "label": "向阳区", "index": "X" }
+ ]
+ },
+ {
+ "label": "牡丹江市",
+ "index": "M",
+ "children": [
+ { "label": "爱民区", "index": "A" },
+ { "label": "东安区", "index": "D" },
+ { "label": "东宁市", "index": "D" },
+ { "label": "海林市", "index": "H" },
+ { "label": "林口县", "index": "L" },
+ { "label": "穆棱市", "index": "M" },
+ { "label": "宁安市", "index": "N" },
+ { "label": "绥芬河市", "index": "S" },
+ { "label": "西安区", "index": "X" },
+ { "label": "阳明区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "齐齐哈尔市",
+ "index": "Q",
+ "children": [
+ { "label": "昂昂溪区", "index": "A" },
+ { "label": "拜泉县", "index": "B" },
+ { "label": "富拉尔基区", "index": "F" },
+ { "label": "富裕县", "index": "F" },
+ { "label": "甘南县", "index": "G" },
+ { "label": "建华区", "index": "J" },
+ { "label": "克山县", "index": "K" },
+ { "label": "克东县", "index": "K" },
+ { "label": "龙沙区", "index": "L" },
+ { "label": "龙江县", "index": "L" },
+ { "label": "梅里斯达斡尔族区", "index": "M" },
+ { "label": "碾子山区", "index": "N" },
+ { "label": "讷河市", "index": "N" },
+ { "label": "铁锋区", "index": "T" },
+ { "label": "泰来县", "index": "T" },
+ { "label": "依安县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "七台河市",
+ "index": "Q",
+ "children": [
+ { "label": "勃利县", "index": "B" },
+ { "label": "茄子河区", "index": "Q" },
+ { "label": "桃山区", "index": "T" },
+ { "label": "新兴区", "index": "X" }
+ ]
+ },
+ {
+ "label": "双鸭山市",
+ "index": "S",
+ "children": [
+ { "label": "宝山区", "index": "B" },
+ { "label": "宝清县", "index": "B" },
+ { "label": "尖山区", "index": "J" },
+ { "label": "集贤县", "index": "J" },
+ { "label": "岭东区", "index": "L" },
+ { "label": "饶河县", "index": "R" },
+ { "label": "四方台区", "index": "S" },
+ { "label": "友谊县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "绥化市",
+ "index": "S",
+ "children": [
+ { "label": "安达市", "index": "A" },
+ { "label": "北林区", "index": "B" },
+ { "label": "海伦市", "index": "H" },
+ { "label": "兰西县", "index": "L" },
+ { "label": "明水县", "index": "M" },
+ { "label": "青冈县", "index": "Q" },
+ { "label": "庆安县", "index": "Q" },
+ { "label": "绥棱县", "index": "S" },
+ { "label": "望奎县", "index": "W" },
+ { "label": "肇东市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "伊春市",
+ "index": "Y",
+ "children": [
+ { "label": "大箐山县", "index": "D" },
+ { "label": "丰林县", "index": "F" },
+ { "label": "嘉荫县", "index": "J" },
+ { "label": "金林区", "index": "J" },
+ { "label": "南岔县", "index": "N" },
+ { "label": "汤旺县", "index": "T" },
+ { "label": "铁力市", "index": "T" },
+ { "label": "乌翠区", "index": "W" },
+ { "label": "伊美区", "index": "Y" },
+ { "label": "友好区", "index": "Y" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "河南省",
+ "index": "H",
+ "children": [
+ {
+ "label": "安阳市",
+ "index": "A",
+ "children": [
+ { "label": "安阳县", "index": "A" },
+ { "label": "安阳高新技术产业开发区", "index": "A" },
+ { "label": "北关区", "index": "B" },
+ { "label": "滑县", "index": "H" },
+ { "label": "龙安区", "index": "L" },
+ { "label": "林州市", "index": "L" },
+ { "label": "内黄县", "index": "N" },
+ { "label": "汤阴县", "index": "T" },
+ { "label": "文峰区", "index": "W" },
+ { "label": "殷都区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "鹤壁市",
+ "index": "H",
+ "children": [
+ { "label": "鹤山区", "index": "H" },
+ { "label": "鹤壁经济技术开发区", "index": "H" },
+ { "label": "浚县", "index": "J" },
+ { "label": "淇滨区", "index": "Q" },
+ { "label": "淇县", "index": "Q" },
+ { "label": "山城区", "index": "S" }
+ ]
+ },
+ {
+ "label": "焦作市",
+ "index": "J",
+ "children": [
+ { "label": "博爱县", "index": "B" },
+ { "label": "解放区", "index": "J" },
+ { "label": "焦作城乡一体化示范区", "index": "J" },
+ { "label": "马村区", "index": "M" },
+ { "label": "孟州市", "index": "M" },
+ { "label": "沁阳市", "index": "Q" },
+ { "label": "山阳区", "index": "S" },
+ { "label": "武陟县", "index": "W" },
+ { "label": "温县", "index": "W" },
+ { "label": "修武县", "index": "X" },
+ { "label": "中站区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "开封市",
+ "index": "K",
+ "children": [
+ { "label": "鼓楼区", "index": "G" },
+ { "label": "龙亭区", "index": "L" },
+ { "label": "兰考县", "index": "L" },
+ { "label": "杞县", "index": "Q" },
+ { "label": "顺河回族区", "index": "S" },
+ { "label": "通许县", "index": "T" },
+ { "label": "尉氏县", "index": "W" },
+ { "label": "祥符区", "index": "X" },
+ { "label": "禹王台区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "洛阳市",
+ "index": "L",
+ "children": [
+ { "label": "瀍河回族区", "index": "C" },
+ { "label": "涧西区", "index": "J" },
+ { "label": "老城区", "index": "L" },
+ { "label": "洛龙区", "index": "L" },
+ { "label": "栾川县", "index": "L" },
+ { "label": "洛宁县", "index": "L" },
+ { "label": "洛阳高新技术产业开发区", "index": "L" },
+ { "label": "孟津区", "index": "M" },
+ { "label": "汝阳县", "index": "R" },
+ { "label": "嵩县", "index": "S" },
+ { "label": "西工区", "index": "X" },
+ { "label": "新安县", "index": "X" },
+ { "label": "偃师区", "index": "Y" },
+ { "label": "宜阳县", "index": "Y" },
+ { "label": "伊川县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "漯河市",
+ "index": "L",
+ "children": [
+ { "label": "临颍县", "index": "L" },
+ { "label": "漯河经济技术开发区", "index": "L" },
+ { "label": "舞阳县", "index": "W" },
+ { "label": "源汇区", "index": "Y" },
+ { "label": "郾城区", "index": "Y" },
+ { "label": "召陵区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "南阳市",
+ "index": "N",
+ "children": [
+ { "label": "邓州市", "index": "D" },
+ { "label": "方城县", "index": "F" },
+ { "label": "南召县", "index": "N" },
+ { "label": "内乡县", "index": "N" },
+ { "label": "南阳高新技术产业开发区", "index": "N" },
+ { "label": "南阳市城乡一体化示范区", "index": "N" },
+ { "label": "社旗县", "index": "S" },
+ { "label": "唐河县", "index": "T" },
+ { "label": "桐柏县", "index": "T" },
+ { "label": "宛城区", "index": "W" },
+ { "label": "卧龙区", "index": "W" },
+ { "label": "西峡县", "index": "X" },
+ { "label": "淅川县", "index": "X" },
+ { "label": "新野县", "index": "X" },
+ { "label": "镇平县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "平顶山市",
+ "index": "P",
+ "children": [
+ { "label": "宝丰县", "index": "B" },
+ { "label": "郏县", "index": "J" },
+ { "label": "鲁山县", "index": "L" },
+ { "label": "平顶山高新技术产业开发区", "index": "P" },
+ { "label": "平顶山市城乡一体化示范区", "index": "P" },
+ { "label": "汝州市", "index": "R" },
+ { "label": "石龙区", "index": "S" },
+ { "label": "卫东区", "index": "W" },
+ { "label": "舞钢市", "index": "W" },
+ { "label": "新华区", "index": "X" },
+ { "label": "叶县", "index": "Y" },
+ { "label": "湛河区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "濮阳市",
+ "index": "P",
+ "children": [
+ { "label": "范县", "index": "F" },
+ { "label": "华龙区", "index": "H" },
+ { "label": "河南濮阳工业园区", "index": "H" },
+ { "label": "南乐县", "index": "N" },
+ { "label": "濮阳县", "index": "P" },
+ { "label": "濮阳经济技术开发区", "index": "P" },
+ { "label": "清丰县", "index": "Q" },
+ { "label": "台前县", "index": "T" }
+ ]
+ },
+ {
+ "label": "三门峡市",
+ "index": "S",
+ "children": [
+ { "label": "湖滨区", "index": "H" },
+ { "label": "河南三门峡经济开发区", "index": "H" },
+ { "label": "卢氏县", "index": "L" },
+ { "label": "灵宝市", "index": "L" },
+ { "label": "渑池县", "index": "M" },
+ { "label": "陕州区", "index": "S" },
+ { "label": "义马市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "商丘市",
+ "index": "S",
+ "children": [
+ { "label": "睢阳区", "index": "H" },
+ { "label": "睢县", "index": "H" },
+ { "label": "河南商丘经济开发区", "index": "H" },
+ { "label": "梁园区", "index": "L" },
+ { "label": "民权县", "index": "M" },
+ { "label": "宁陵县", "index": "N" },
+ { "label": "夏邑县", "index": "X" },
+ { "label": "虞城县", "index": "Y" },
+ { "label": "豫东综合物流产业聚集区", "index": "Y" },
+ { "label": "永城市", "index": "Y" },
+ { "label": "柘城县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "省直辖县级行政区划",
+ "index": "S",
+ "children": [{ "label": "济源市", "index": "J" }]
+ },
+ {
+ "label": "新乡市",
+ "index": "X",
+ "children": [
+ { "label": "长垣市", "index": "C" },
+ { "label": "凤泉区", "index": "F" },
+ { "label": "封丘县", "index": "F" },
+ { "label": "红旗区", "index": "H" },
+ { "label": "获嘉县", "index": "H" },
+ { "label": "辉县市", "index": "H" },
+ { "label": "牧野区", "index": "M" },
+ { "label": "卫滨区", "index": "W" },
+ { "label": "卫辉市", "index": "W" },
+ { "label": "新乡县", "index": "X" },
+ { "label": "新乡高新技术产业开发区", "index": "X" },
+ { "label": "新乡经济技术开发区", "index": "X" },
+ { "label": "新乡市平原城乡一体化示范区", "index": "X" },
+ { "label": "原阳县", "index": "Y" },
+ { "label": "延津县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "许昌市",
+ "index": "X",
+ "children": [
+ { "label": "长葛市", "index": "C" },
+ { "label": "建安区", "index": "J" },
+ { "label": "魏都区", "index": "W" },
+ { "label": "襄城县", "index": "X" },
+ { "label": "许昌经济技术开发区", "index": "X" },
+ { "label": "鄢陵县", "index": "Y" },
+ { "label": "禹州市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "信阳市",
+ "index": "X",
+ "children": [
+ { "label": "光山县", "index": "G" },
+ { "label": "固始县", "index": "G" },
+ { "label": "潢川县", "index": "H" },
+ { "label": "淮滨县", "index": "H" },
+ { "label": "罗山县", "index": "L" },
+ { "label": "平桥区", "index": "P" },
+ { "label": "浉河区", "index": "S" },
+ { "label": "商城县", "index": "S" },
+ { "label": "新县", "index": "X" },
+ { "label": "息县", "index": "X" },
+ { "label": "信阳高新技术产业开发区", "index": "X" }
+ ]
+ },
+ {
+ "label": "郑州市",
+ "index": "Z",
+ "children": [
+ { "label": "登封市", "index": "D" },
+ { "label": "二七区", "index": "E" },
+ { "label": "管城回族区", "index": "G" },
+ { "label": "巩义市", "index": "G" },
+ { "label": "惠济区", "index": "H" },
+ { "label": "金水区", "index": "J" },
+ { "label": "上街区", "index": "S" },
+ { "label": "荥阳市", "index": "X" },
+ { "label": "新密市", "index": "X" },
+ { "label": "新郑市", "index": "X" },
+ { "label": "中原区", "index": "Z" },
+ { "label": "中牟县", "index": "Z" },
+ { "label": "郑州经济技术开发区", "index": "Z" },
+ { "label": "郑州高新技术产业开发区", "index": "Z" },
+ { "label": "郑州航空港经济综合实验区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "周口市",
+ "index": "Z",
+ "children": [
+ { "label": "川汇区", "index": "C" },
+ { "label": "郸城县", "index": "D" },
+ { "label": "扶沟县", "index": "F" },
+ { "label": "淮阳区", "index": "H" },
+ { "label": "鹿邑县", "index": "L" },
+ { "label": "商水县", "index": "S" },
+ { "label": "沈丘县", "index": "S" },
+ { "label": "太康县", "index": "T" },
+ { "label": "西华县", "index": "X" },
+ { "label": "项城市", "index": "X" },
+ { "label": "周口临港开发区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "驻马店市",
+ "index": "Z",
+ "children": [
+ { "label": "河南驻马店经济开发区", "index": "H" },
+ { "label": "泌阳县", "index": "M" },
+ { "label": "平舆县", "index": "P" },
+ { "label": "确山县", "index": "Q" },
+ { "label": "汝南县", "index": "R" },
+ { "label": "上蔡县", "index": "S" },
+ { "label": "遂平县", "index": "S" },
+ { "label": "西平县", "index": "X" },
+ { "label": "新蔡县", "index": "X" },
+ { "label": "驿城区", "index": "Y" },
+ { "label": "正阳县", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "湖北省",
+ "index": "H",
+ "children": [
+ {
+ "label": "鄂州市",
+ "index": "E",
+ "children": [
+ { "label": "鄂城区", "index": "E" },
+ { "label": "华容区", "index": "H" },
+ { "label": "梁子湖区", "index": "L" }
+ ]
+ },
+ {
+ "label": "恩施土家族苗族自治州",
+ "index": "E",
+ "children": [
+ { "label": "巴东县", "index": "B" },
+ { "label": "恩施市", "index": "E" },
+ { "label": "鹤峰县", "index": "H" },
+ { "label": "建始县", "index": "J" },
+ { "label": "利川市", "index": "L" },
+ { "label": "来凤县", "index": "L" },
+ { "label": "宣恩县", "index": "X" },
+ { "label": "咸丰县", "index": "X" }
+ ]
+ },
+ {
+ "label": "黄石市",
+ "index": "H",
+ "children": [
+ { "label": "大冶市", "index": "D" },
+ { "label": "黄石港区", "index": "H" },
+ { "label": "铁山区", "index": "T" },
+ { "label": "西塞山区", "index": "X" },
+ { "label": "下陆区", "index": "X" },
+ { "label": "阳新县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "黄冈市",
+ "index": "H",
+ "children": [
+ { "label": "黄州区", "index": "H" },
+ { "label": "红安县", "index": "H" },
+ { "label": "黄梅县", "index": "H" },
+ { "label": "罗田县", "index": "L" },
+ { "label": "龙感湖管理区", "index": "L" },
+ { "label": "麻城市", "index": "M" },
+ { "label": "蕲春县", "index": "Q" },
+ { "label": "团风县", "index": "T" },
+ { "label": "武穴市", "index": "W" },
+ { "label": "浠水县", "index": "X" },
+ { "label": "英山县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "荆门市",
+ "index": "J",
+ "children": [
+ { "label": "东宝区", "index": "D" },
+ { "label": "掇刀区", "index": "D" },
+ { "label": "京山市", "index": "J" },
+ { "label": "沙洋县", "index": "S" },
+ { "label": "钟祥市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "荆州市",
+ "index": "J",
+ "children": [
+ { "label": "公安县", "index": "G" },
+ { "label": "洪湖市", "index": "H" },
+ { "label": "荆州区", "index": "J" },
+ { "label": "江陵县", "index": "J" },
+ { "label": "荆州经济技术开发区", "index": "J" },
+ { "label": "监利市", "index": "J" },
+ { "label": "沙市区", "index": "S" },
+ { "label": "石首市", "index": "S" },
+ { "label": "松滋市", "index": "S" }
+ ]
+ },
+ {
+ "label": "十堰市",
+ "index": "S",
+ "children": [
+ { "label": "丹江口市", "index": "D" },
+ { "label": "房县", "index": "F" },
+ { "label": "茅箭区", "index": "M" },
+ { "label": "郧阳区", "index": "Y" },
+ { "label": "郧西县", "index": "Y" },
+ { "label": "张湾区", "index": "Z" },
+ { "label": "竹山县", "index": "Z" },
+ { "label": "竹溪县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "随州市",
+ "index": "S",
+ "children": [
+ { "label": "广水市", "index": "G" },
+ { "label": "随县", "index": "S" },
+ { "label": "曾都区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "省直辖县级行政区划",
+ "index": "S",
+ "children": [
+ { "label": "潜江市", "index": "Q" },
+ { "label": "神农架林区", "index": "S" },
+ { "label": "天门市", "index": "T" },
+ { "label": "仙桃市", "index": "X" }
+ ]
+ },
+ {
+ "label": "武汉市",
+ "index": "W",
+ "children": [
+ { "label": "蔡甸区", "index": "C" },
+ { "label": "东西湖区", "index": "D" },
+ { "label": "汉阳区", "index": "H" },
+ { "label": "洪山区", "index": "H" },
+ { "label": "汉南区", "index": "H" },
+ { "label": "黄陂区", "index": "H" },
+ { "label": "江岸区", "index": "J" },
+ { "label": "江汉区", "index": "J" },
+ { "label": "江夏区", "index": "J" },
+ { "label": "硚口区", "index": "Q" },
+ { "label": "青山区", "index": "Q" },
+ { "label": "武昌区", "index": "W" },
+ { "label": "新洲区", "index": "X" }
+ ]
+ },
+ {
+ "label": "襄阳市",
+ "index": "X",
+ "children": [
+ { "label": "保康县", "index": "B" },
+ { "label": "樊城区", "index": "F" },
+ { "label": "谷城县", "index": "G" },
+ { "label": "老河口市", "index": "L" },
+ { "label": "南漳县", "index": "N" },
+ { "label": "襄城区", "index": "X" },
+ { "label": "襄州区", "index": "X" },
+ { "label": "宜城市", "index": "Y" },
+ { "label": "枣阳市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "孝感市",
+ "index": "X",
+ "children": [
+ { "label": "安陆市", "index": "A" },
+ { "label": "大悟县", "index": "D" },
+ { "label": "汉川市", "index": "H" },
+ { "label": "孝南区", "index": "X" },
+ { "label": "孝昌县", "index": "X" },
+ { "label": "云梦县", "index": "Y" },
+ { "label": "应城市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "咸宁市",
+ "index": "X",
+ "children": [
+ { "label": "崇阳县", "index": "C" },
+ { "label": "赤壁市", "index": "C" },
+ { "label": "嘉鱼县", "index": "J" },
+ { "label": "通城县", "index": "T" },
+ { "label": "通山县", "index": "T" },
+ { "label": "咸安区", "index": "X" }
+ ]
+ },
+ {
+ "label": "宜昌市",
+ "index": "Y",
+ "children": [
+ { "label": "长阳土家族自治县", "index": "C" },
+ { "label": "点军区", "index": "D" },
+ { "label": "当阳市", "index": "D" },
+ { "label": "伍家岗区", "index": "W" },
+ { "label": "五峰土家族自治县", "index": "W" },
+ { "label": "西陵区", "index": "X" },
+ { "label": "猇亭区", "index": "X" },
+ { "label": "兴山县", "index": "X" },
+ { "label": "夷陵区", "index": "Y" },
+ { "label": "远安县", "index": "Y" },
+ { "label": "宜都市", "index": "Y" },
+ { "label": "秭归县", "index": "Z" },
+ { "label": "枝江市", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "湖南省",
+ "index": "H",
+ "children": [
+ {
+ "label": "长沙市",
+ "index": "C",
+ "children": [
+ { "label": "长沙县", "index": "C" },
+ { "label": "芙蓉区", "index": "F" },
+ { "label": "开福区", "index": "K" },
+ { "label": "浏阳市", "index": "L" },
+ { "label": "宁乡市", "index": "N" },
+ { "label": "天心区", "index": "T" },
+ { "label": "望城区", "index": "W" },
+ { "label": "岳麓区", "index": "Y" },
+ { "label": "雨花区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "常德市",
+ "index": "C",
+ "children": [
+ { "label": "安乡县", "index": "A" },
+ { "label": "常德市西洞庭管理区", "index": "C" },
+ { "label": "鼎城区", "index": "D" },
+ { "label": "汉寿县", "index": "H" },
+ { "label": "津市市", "index": "J" },
+ { "label": "澧县", "index": "L" },
+ { "label": "临澧县", "index": "L" },
+ { "label": "石门县", "index": "S" },
+ { "label": "桃源县", "index": "T" },
+ { "label": "武陵区", "index": "W" }
+ ]
+ },
+ {
+ "label": "郴州市",
+ "index": "C",
+ "children": [
+ { "label": "安仁县", "index": "A" },
+ { "label": "北湖区", "index": "B" },
+ { "label": "桂阳县", "index": "G" },
+ { "label": "桂东县", "index": "G" },
+ { "label": "嘉禾县", "index": "J" },
+ { "label": "临武县", "index": "L" },
+ { "label": "汝城县", "index": "R" },
+ { "label": "苏仙区", "index": "S" },
+ { "label": "宜章县", "index": "Y" },
+ { "label": "永兴县", "index": "Y" },
+ { "label": "资兴市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "衡阳市",
+ "index": "H",
+ "children": [
+ { "label": "常宁市", "index": "C" },
+ { "label": "衡阳县", "index": "H" },
+ { "label": "衡南县", "index": "H" },
+ { "label": "衡山县", "index": "H" },
+ { "label": "衡东县", "index": "H" },
+ { "label": "湖南衡阳松木经济开发区", "index": "H" },
+ { "label": "湖南衡阳高新技术产业园区", "index": "H" },
+ { "label": "耒阳市", "index": "L" },
+ { "label": "南岳区", "index": "N" },
+ { "label": "祁东县", "index": "Q" },
+ { "label": "石鼓区", "index": "S" },
+ { "label": "雁峰区", "index": "Y" },
+ { "label": "珠晖区", "index": "Z" },
+ { "label": "蒸湘区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "怀化市",
+ "index": "H",
+ "children": [
+ { "label": "辰溪县", "index": "C" },
+ { "label": "鹤城区", "index": "H" },
+ { "label": "会同县", "index": "H" },
+ { "label": "怀化市洪江管理区", "index": "H" },
+ { "label": "洪江市", "index": "H" },
+ { "label": "靖州苗族侗族自治县", "index": "J" },
+ { "label": "麻阳苗族自治县", "index": "M" },
+ { "label": "通道侗族自治县", "index": "T" },
+ { "label": "溆浦县", "index": "X" },
+ { "label": "新晃侗族自治县", "index": "X" },
+ { "label": "沅陵县", "index": "Y" },
+ { "label": "中方县", "index": "Z" },
+ { "label": "芷江侗族自治县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "娄底市",
+ "index": "L",
+ "children": [
+ { "label": "娄星区", "index": "L" },
+ { "label": "冷水江市", "index": "L" },
+ { "label": "涟源市", "index": "L" },
+ { "label": "双峰县", "index": "S" },
+ { "label": "新化县", "index": "X" }
+ ]
+ },
+ {
+ "label": "邵阳市",
+ "index": "S",
+ "children": [
+ { "label": "北塔区", "index": "B" },
+ { "label": "城步苗族自治县", "index": "C" },
+ { "label": "大祥区", "index": "D" },
+ { "label": "洞口县", "index": "D" },
+ { "label": "隆回县", "index": "L" },
+ { "label": "双清区", "index": "S" },
+ { "label": "邵阳县", "index": "S" },
+ { "label": "绥宁县", "index": "S" },
+ { "label": "邵东市", "index": "S" },
+ { "label": "武冈市", "index": "W" },
+ { "label": "新邵县", "index": "X" },
+ { "label": "新宁县", "index": "X" }
+ ]
+ },
+ {
+ "label": "湘潭市",
+ "index": "X",
+ "children": [
+ { "label": "湖南湘潭高新技术产业园区", "index": "H" },
+ { "label": "韶山市", "index": "S" },
+ { "label": "湘潭县", "index": "X" },
+ { "label": "湘潭昭山示范区", "index": "X" },
+ { "label": "湘潭九华示范区", "index": "X" },
+ { "label": "湘乡市", "index": "X" },
+ { "label": "雨湖区", "index": "Y" },
+ { "label": "岳塘区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "湘西土家族苗族自治州",
+ "index": "X",
+ "children": [
+ { "label": "保靖县", "index": "B" },
+ { "label": "凤凰县", "index": "F" },
+ { "label": "古丈县", "index": "G" },
+ { "label": "花垣县", "index": "H" },
+ { "label": "吉首市", "index": "J" },
+ { "label": "泸溪县", "index": "L" },
+ { "label": "龙山县", "index": "L" },
+ { "label": "永顺县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "岳阳市",
+ "index": "Y",
+ "children": [
+ { "label": "华容县", "index": "H" },
+ { "label": "君山区", "index": "J" },
+ { "label": "临湘市", "index": "L" },
+ { "label": "汨罗市", "index": "M" },
+ { "label": "平江县", "index": "P" },
+ { "label": "湘阴县", "index": "X" },
+ { "label": "岳阳楼区", "index": "Y" },
+ { "label": "云溪区", "index": "Y" },
+ { "label": "岳阳县", "index": "Y" },
+ { "label": "岳阳市屈原管理区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "益阳市",
+ "index": "Y",
+ "children": [
+ { "label": "安化县", "index": "A" },
+ { "label": "赫山区", "index": "H" },
+ { "label": "湖南益阳高新技术产业园区", "index": "H" },
+ { "label": "南县", "index": "N" },
+ { "label": "桃江县", "index": "T" },
+ { "label": "益阳市大通湖管理区", "index": "Y" },
+ { "label": "沅江市", "index": "Y" },
+ { "label": "资阳区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "永州市",
+ "index": "Y",
+ "children": [
+ { "label": "东安县", "index": "D" },
+ { "label": "道县", "index": "D" },
+ { "label": "江永县", "index": "J" },
+ { "label": "江华瑶族自治县", "index": "J" },
+ { "label": "零陵区", "index": "L" },
+ { "label": "冷水滩区", "index": "L" },
+ { "label": "蓝山县", "index": "L" },
+ { "label": "宁远县", "index": "N" },
+ { "label": "祁阳市", "index": "Q" },
+ { "label": "双牌县", "index": "S" },
+ { "label": "新田县", "index": "X" },
+ { "label": "永州经济技术开发区", "index": "Y" },
+ { "label": "永州市回龙圩管理区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "株洲市",
+ "index": "Z",
+ "children": [
+ { "label": "茶陵县", "index": "C" },
+ { "label": "荷塘区", "index": "H" },
+ { "label": "芦淞区", "index": "L" },
+ { "label": "渌口区", "index": "L" },
+ { "label": "醴陵市", "index": "L" },
+ { "label": "石峰区", "index": "S" },
+ { "label": "天元区", "index": "T" },
+ { "label": "攸县", "index": "Y" },
+ { "label": "炎陵县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "张家界市",
+ "index": "Z",
+ "children": [
+ { "label": "慈利县", "index": "C" },
+ { "label": "桑植县", "index": "S" },
+ { "label": "武陵源区", "index": "W" },
+ { "label": "永定区", "index": "Y" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "海南省",
+ "index": "H",
+ "children": [
+ {
+ "label": "儋州市",
+ "index": "D",
+ "children": [
+ { "label": "白马井镇", "index": "B" },
+ { "label": "大成镇", "index": "D" },
+ { "label": "东成镇", "index": "D" },
+ { "label": "峨蔓镇", "index": "E" },
+ { "label": "光村镇", "index": "G" },
+ { "label": "和庆镇", "index": "H" },
+ { "label": "海头镇", "index": "H" },
+ { "label": "华南热作学院", "index": "H" },
+ { "label": "兰洋镇", "index": "L" },
+ { "label": "木棠镇", "index": "M" },
+ { "label": "那大镇", "index": "N" },
+ { "label": "南丰镇", "index": "N" },
+ { "label": "排浦镇", "index": "P" },
+ { "label": "王五镇", "index": "W" },
+ { "label": "新州镇", "index": "X" },
+ { "label": "雅星镇", "index": "Y" },
+ { "label": "洋浦经济开发区", "index": "Y" },
+ { "label": "中和镇", "index": "Z" }
+ ]
+ },
+ {
+ "label": "海口市",
+ "index": "H",
+ "children": [
+ { "label": "龙华区", "index": "L" },
+ { "label": "美兰区", "index": "M" },
+ { "label": "琼山区", "index": "Q" },
+ { "label": "秀英区", "index": "X" }
+ ]
+ },
+ {
+ "label": "三亚市",
+ "index": "S",
+ "children": [
+ { "label": "海棠区", "index": "H" },
+ { "label": "吉阳区", "index": "J" },
+ { "label": "天涯区", "index": "T" },
+ { "label": "崖州区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "三沙市",
+ "index": "S",
+ "children": [
+ { "label": "南沙群岛", "index": "N" },
+ { "label": "西沙群岛", "index": "X" },
+ { "label": "中沙群岛的岛礁及其海域", "index": "Z" }
+ ]
+ },
+ {
+ "label": "省直辖县级行政区划",
+ "index": "S",
+ "children": [
+ { "label": "白沙黎族自治县", "index": "B" },
+ { "label": "保亭黎族苗族自治县", "index": "B" },
+ { "label": "澄迈县", "index": "C" },
+ { "label": "昌江黎族自治县", "index": "C" },
+ { "label": "东方市", "index": "D" },
+ { "label": "定安县", "index": "D" },
+ { "label": "临高县", "index": "L" },
+ { "label": "乐东黎族自治县", "index": "L" },
+ { "label": "陵水黎族自治县", "index": "L" },
+ { "label": "琼海市", "index": "Q" },
+ { "label": "琼中黎族苗族自治县", "index": "Q" },
+ { "label": "屯昌县", "index": "T" },
+ { "label": "五指山市", "index": "W" },
+ { "label": "文昌市", "index": "W" },
+ { "label": "万宁市", "index": "W" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "吉林省",
+ "index": "J",
+ "children": [
+ {
+ "label": "白山市",
+ "index": "B",
+ "children": [
+ { "label": "长白朝鲜族自治县", "index": "C" },
+ { "label": "抚松县", "index": "F" },
+ { "label": "浑江区", "index": "H" },
+ { "label": "江源区", "index": "J" },
+ { "label": "靖宇县", "index": "J" },
+ { "label": "临江市", "index": "L" }
+ ]
+ },
+ {
+ "label": "白城市",
+ "index": "B",
+ "children": [
+ { "label": "大安市", "index": "D" },
+ { "label": "吉林白城经济开发区", "index": "J" },
+ { "label": "洮北区", "index": "T" },
+ { "label": "通榆县", "index": "T" },
+ { "label": "洮南市", "index": "T" },
+ { "label": "镇赉县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "长春市",
+ "index": "C",
+ "children": [
+ { "label": "长春经济技术开发区", "index": "C" },
+ { "label": "长春净月高新技术产业开发区", "index": "C" },
+ { "label": "长春高新技术产业开发区", "index": "C" },
+ { "label": "长春汽车经济技术开发区", "index": "C" },
+ { "label": "德惠市", "index": "D" },
+ { "label": "二道区", "index": "E" },
+ { "label": "公主岭市", "index": "G" },
+ { "label": "九台区", "index": "J" },
+ { "label": "宽城区", "index": "K" },
+ { "label": "绿园区", "index": "L" },
+ { "label": "南关区", "index": "N" },
+ { "label": "农安县", "index": "N" },
+ { "label": "双阳区", "index": "S" },
+ { "label": "榆树市", "index": "Y" },
+ { "label": "朝阳区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "吉林市",
+ "index": "J",
+ "children": [
+ { "label": "昌邑区", "index": "C" },
+ { "label": "船营区", "index": "C" },
+ { "label": "丰满区", "index": "F" },
+ { "label": "桦甸市", "index": "H" },
+ { "label": "吉林经济开发区", "index": "J" },
+ { "label": "吉林高新技术产业开发区", "index": "J" },
+ { "label": "吉林中国新加坡食品区", "index": "J" },
+ { "label": "蛟河市", "index": "J" },
+ { "label": "龙潭区", "index": "L" },
+ { "label": "磐石市", "index": "P" },
+ { "label": "舒兰市", "index": "S" },
+ { "label": "永吉县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "辽源市",
+ "index": "L",
+ "children": [
+ { "label": "东丰县", "index": "D" },
+ { "label": "东辽县", "index": "D" },
+ { "label": "龙山区", "index": "L" },
+ { "label": "西安区", "index": "X" }
+ ]
+ },
+ {
+ "label": "四平市",
+ "index": "S",
+ "children": [
+ { "label": "梨树县", "index": "L" },
+ { "label": "双辽市", "index": "S" },
+ { "label": "铁西区", "index": "T" },
+ { "label": "铁东区", "index": "T" },
+ { "label": "伊通满族自治县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "松原市",
+ "index": "S",
+ "children": [
+ { "label": "长岭县", "index": "C" },
+ { "label": "扶余市", "index": "F" },
+ { "label": "吉林松原经济开发区", "index": "J" },
+ { "label": "宁江区", "index": "N" },
+ { "label": "前郭尔罗斯蒙古族自治县", "index": "Q" },
+ { "label": "乾安县", "index": "Q" }
+ ]
+ },
+ {
+ "label": "通化市",
+ "index": "T",
+ "children": [
+ { "label": "东昌区", "index": "D" },
+ { "label": "二道江区", "index": "E" },
+ { "label": "辉南县", "index": "H" },
+ { "label": "集安市", "index": "J" },
+ { "label": "柳河县", "index": "L" },
+ { "label": "梅河口市", "index": "M" },
+ { "label": "通化县", "index": "T" }
+ ]
+ },
+ {
+ "label": "延边朝鲜族自治州",
+ "index": "Y",
+ "children": [
+ { "label": "安图县", "index": "A" },
+ { "label": "敦化市", "index": "D" },
+ { "label": "珲春市", "index": "H" },
+ { "label": "和龙市", "index": "H" },
+ { "label": "龙井市", "index": "L" },
+ { "label": "图们市", "index": "T" },
+ { "label": "汪清县", "index": "W" },
+ { "label": "延吉市", "index": "Y" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "江苏省",
+ "index": "J",
+ "children": [
+ {
+ "label": "常州市",
+ "index": "C",
+ "children": [
+ { "label": "金坛区", "index": "J" },
+ { "label": "溧阳市", "index": "L" },
+ { "label": "天宁区", "index": "T" },
+ { "label": "武进区", "index": "W" },
+ { "label": "新北区", "index": "X" },
+ { "label": "钟楼区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "淮安市",
+ "index": "H",
+ "children": [
+ { "label": "淮安区", "index": "H" },
+ { "label": "淮阴区", "index": "H" },
+ { "label": "洪泽区", "index": "H" },
+ { "label": "淮安经济技术开发区", "index": "H" },
+ { "label": "金湖县", "index": "J" },
+ { "label": "涟水县", "index": "L" },
+ { "label": "清江浦区", "index": "Q" },
+ { "label": "盱眙县", "index": "X" }
+ ]
+ },
+ {
+ "label": "连云港市",
+ "index": "L",
+ "children": [
+ { "label": "东海县", "index": "D" },
+ { "label": "赣榆区", "index": "G" },
+ { "label": "灌云县", "index": "G" },
+ { "label": "灌南县", "index": "G" },
+ { "label": "海州区", "index": "H" },
+ { "label": "连云区", "index": "L" },
+ { "label": "连云港经济技术开发区", "index": "L" }
+ ]
+ },
+ {
+ "label": "南京市",
+ "index": "N",
+ "children": [
+ { "label": "鼓楼区", "index": "G" },
+ { "label": "高淳区", "index": "G" },
+ { "label": "建邺区", "index": "J" },
+ { "label": "江宁区", "index": "J" },
+ { "label": "六合区", "index": "L" },
+ { "label": "溧水区", "index": "L" },
+ { "label": "浦口区", "index": "P" },
+ { "label": "秦淮区", "index": "Q" },
+ { "label": "栖霞区", "index": "Q" },
+ { "label": "玄武区", "index": "X" },
+ { "label": "雨花台区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "南通市",
+ "index": "N",
+ "children": [
+ { "label": "崇川区", "index": "C" },
+ { "label": "海门区", "index": "H" },
+ { "label": "海安市", "index": "H" },
+ { "label": "南通经济技术开发区", "index": "N" },
+ { "label": "启东市", "index": "Q" },
+ { "label": "如东县", "index": "R" },
+ { "label": "如皋市", "index": "R" },
+ { "label": "通州区", "index": "T" }
+ ]
+ },
+ {
+ "label": "苏州市",
+ "index": "S",
+ "children": [
+ { "label": "常熟市", "index": "C" },
+ { "label": "姑苏区", "index": "G" },
+ { "label": "虎丘区", "index": "H" },
+ { "label": "昆山市", "index": "K" },
+ { "label": "苏州工业园区", "index": "S" },
+ { "label": "太仓市", "index": "T" },
+ { "label": "吴中区", "index": "W" },
+ { "label": "吴江区", "index": "W" },
+ { "label": "相城区", "index": "X" },
+ { "label": "张家港市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "宿迁市",
+ "index": "S",
+ "children": [
+ { "label": "宿城区", "index": "S" },
+ { "label": "宿豫区", "index": "S" },
+ { "label": "沭阳县", "index": "S" },
+ { "label": "泗阳县", "index": "S" },
+ { "label": "泗洪县", "index": "S" },
+ { "label": "宿迁经济技术开发区", "index": "S" }
+ ]
+ },
+ {
+ "label": "泰州市",
+ "index": "T",
+ "children": [
+ { "label": "高港区", "index": "G" },
+ { "label": "海陵区", "index": "H" },
+ { "label": "姜堰区", "index": "J" },
+ { "label": "靖江市", "index": "J" },
+ { "label": "泰兴市", "index": "T" },
+ { "label": "兴化市", "index": "X" }
+ ]
+ },
+ {
+ "label": "无锡市",
+ "index": "W",
+ "children": [
+ { "label": "滨湖区", "index": "B" },
+ { "label": "惠山区", "index": "H" },
+ { "label": "江阴市", "index": "J" },
+ { "label": "梁溪区", "index": "L" },
+ { "label": "锡山区", "index": "X" },
+ { "label": "新吴区", "index": "X" },
+ { "label": "宜兴市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "徐州市",
+ "index": "X",
+ "children": [
+ { "label": "丰县", "index": "F" },
+ { "label": "鼓楼区", "index": "G" },
+ { "label": "睢宁县", "index": "H" },
+ { "label": "贾汪区", "index": "J" },
+ { "label": "沛县", "index": "P" },
+ { "label": "邳州市", "index": "P" },
+ { "label": "泉山区", "index": "Q" },
+ { "label": "铜山区", "index": "T" },
+ { "label": "徐州经济技术开发区", "index": "X" },
+ { "label": "新沂市", "index": "X" },
+ { "label": "云龙区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "盐城市",
+ "index": "Y",
+ "children": [
+ { "label": "滨海县", "index": "B" },
+ { "label": "大丰区", "index": "D" },
+ { "label": "东台市", "index": "D" },
+ { "label": "阜宁县", "index": "F" },
+ { "label": "建湖县", "index": "J" },
+ { "label": "射阳县", "index": "S" },
+ { "label": "亭湖区", "index": "T" },
+ { "label": "响水县", "index": "X" },
+ { "label": "盐都区", "index": "Y" },
+ { "label": "盐城经济技术开发区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "扬州市",
+ "index": "Y",
+ "children": [
+ { "label": "宝应县", "index": "B" },
+ { "label": "广陵区", "index": "G" },
+ { "label": "高邮市", "index": "G" },
+ { "label": "邗江区", "index": "H" },
+ { "label": "江都区", "index": "J" },
+ { "label": "扬州经济技术开发区", "index": "Y" },
+ { "label": "仪征市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "镇江市",
+ "index": "Z",
+ "children": [
+ { "label": "丹徒区", "index": "D" },
+ { "label": "丹阳市", "index": "D" },
+ { "label": "京口区", "index": "J" },
+ { "label": "句容市", "index": "J" },
+ { "label": "润州区", "index": "R" },
+ { "label": "扬中市", "index": "Y" },
+ { "label": "镇江新区", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "江西省",
+ "index": "J",
+ "children": [
+ {
+ "label": "抚州市",
+ "index": "F",
+ "children": [
+ { "label": "崇仁县", "index": "C" },
+ { "label": "东乡区", "index": "D" },
+ { "label": "广昌县", "index": "G" },
+ { "label": "金溪县", "index": "J" },
+ { "label": "临川区", "index": "L" },
+ { "label": "黎川县", "index": "L" },
+ { "label": "乐安县", "index": "L" },
+ { "label": "南城县", "index": "N" },
+ { "label": "南丰县", "index": "N" },
+ { "label": "宜黄县", "index": "Y" },
+ { "label": "资溪县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "赣州市",
+ "index": "G",
+ "children": [
+ { "label": "安远县", "index": "A" },
+ { "label": "崇义县", "index": "C" },
+ { "label": "大余县", "index": "D" },
+ { "label": "定南县", "index": "D" },
+ { "label": "赣县区", "index": "G" },
+ { "label": "会昌县", "index": "H" },
+ { "label": "龙南市", "index": "L" },
+ { "label": "南康区", "index": "N" },
+ { "label": "宁都县", "index": "N" },
+ { "label": "全南县", "index": "Q" },
+ { "label": "瑞金市", "index": "R" },
+ { "label": "上犹县", "index": "S" },
+ { "label": "石城县", "index": "S" },
+ { "label": "信丰县", "index": "X" },
+ { "label": "兴国县", "index": "X" },
+ { "label": "寻乌县", "index": "X" },
+ { "label": "于都县", "index": "Y" },
+ { "label": "章贡区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "景德镇市",
+ "index": "J",
+ "children": [
+ { "label": "昌江区", "index": "C" },
+ { "label": "浮梁县", "index": "F" },
+ { "label": "乐平市", "index": "L" },
+ { "label": "珠山区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "九江市",
+ "index": "J",
+ "children": [
+ { "label": "柴桑区", "index": "C" },
+ { "label": "德安县", "index": "D" },
+ { "label": "都昌县", "index": "D" },
+ { "label": "共青城市", "index": "G" },
+ { "label": "湖口县", "index": "H" },
+ { "label": "濂溪区", "index": "L" },
+ { "label": "庐山市", "index": "L" },
+ { "label": "彭泽县", "index": "P" },
+ { "label": "瑞昌市", "index": "R" },
+ { "label": "武宁县", "index": "W" },
+ { "label": "浔阳区", "index": "X" },
+ { "label": "修水县", "index": "X" },
+ { "label": "永修县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "吉安市",
+ "index": "J",
+ "children": [
+ { "label": "安福县", "index": "A" },
+ { "label": "吉州区", "index": "J" },
+ { "label": "吉安县", "index": "J" },
+ { "label": "吉水县", "index": "J" },
+ { "label": "井冈山市", "index": "J" },
+ { "label": "青原区", "index": "Q" },
+ { "label": "遂川县", "index": "S" },
+ { "label": "泰和县", "index": "T" },
+ { "label": "万安县", "index": "W" },
+ { "label": "峡江县", "index": "X" },
+ { "label": "新干县", "index": "X" },
+ { "label": "永丰县", "index": "Y" },
+ { "label": "永新县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "南昌市",
+ "index": "N",
+ "children": [
+ { "label": "安义县", "index": "A" },
+ { "label": "东湖区", "index": "D" },
+ { "label": "红谷滩区", "index": "H" },
+ { "label": "进贤县", "index": "J" },
+ { "label": "南昌县", "index": "N" },
+ { "label": "青云谱区", "index": "Q" },
+ { "label": "青山湖区", "index": "Q" },
+ { "label": "西湖区", "index": "X" },
+ { "label": "新建区", "index": "X" }
+ ]
+ },
+ {
+ "label": "萍乡市",
+ "index": "P",
+ "children": [
+ { "label": "安源区", "index": "A" },
+ { "label": "莲花县", "index": "L" },
+ { "label": "芦溪县", "index": "L" },
+ { "label": "上栗县", "index": "S" },
+ { "label": "湘东区", "index": "X" }
+ ]
+ },
+ {
+ "label": "上饶市",
+ "index": "S",
+ "children": [
+ { "label": "德兴市", "index": "D" },
+ { "label": "广丰区", "index": "G" },
+ { "label": "广信区", "index": "G" },
+ { "label": "横峰县", "index": "H" },
+ { "label": "鄱阳县", "index": "P" },
+ { "label": "铅山县", "index": "Q" },
+ { "label": "万年县", "index": "W" },
+ { "label": "婺源县", "index": "W" },
+ { "label": "信州区", "index": "X" },
+ { "label": "玉山县", "index": "Y" },
+ { "label": "弋阳县", "index": "Y" },
+ { "label": "余干县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "新余市",
+ "index": "X",
+ "children": [
+ { "label": "分宜县", "index": "F" },
+ { "label": "渝水区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "鹰潭市",
+ "index": "Y",
+ "children": [
+ { "label": "贵溪市", "index": "G" },
+ { "label": "月湖区", "index": "Y" },
+ { "label": "余江区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "宜春市",
+ "index": "Y",
+ "children": [
+ { "label": "奉新县", "index": "F" },
+ { "label": "丰城市", "index": "F" },
+ { "label": "高安市", "index": "G" },
+ { "label": "靖安县", "index": "J" },
+ { "label": "上高县", "index": "S" },
+ { "label": "铜鼓县", "index": "T" },
+ { "label": "万载县", "index": "W" },
+ { "label": "袁州区", "index": "Y" },
+ { "label": "宜丰县", "index": "Y" },
+ { "label": "樟树市", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "辽宁省",
+ "index": "L",
+ "children": [
+ {
+ "label": "鞍山市",
+ "index": "A",
+ "children": [
+ { "label": "海城市", "index": "H" },
+ { "label": "立山区", "index": "L" },
+ { "label": "千山区", "index": "Q" },
+ { "label": "铁东区", "index": "T" },
+ { "label": "铁西区", "index": "T" },
+ { "label": "台安县", "index": "T" },
+ { "label": "岫岩满族自治县", "index": "X" }
+ ]
+ },
+ {
+ "label": "本溪市",
+ "index": "B",
+ "children": [
+ { "label": "本溪满族自治县", "index": "B" },
+ { "label": "桓仁满族自治县", "index": "H" },
+ { "label": "明山区", "index": "M" },
+ { "label": "南芬区", "index": "N" },
+ { "label": "平山区", "index": "P" },
+ { "label": "溪湖区", "index": "X" }
+ ]
+ },
+ {
+ "label": "大连市",
+ "index": "D",
+ "children": [
+ { "label": "长海县", "index": "C" },
+ { "label": "甘井子区", "index": "G" },
+ { "label": "金州区", "index": "J" },
+ { "label": "旅顺口区", "index": "L" },
+ { "label": "普兰店区", "index": "P" },
+ { "label": "沙河口区", "index": "S" },
+ { "label": "瓦房店市", "index": "W" },
+ { "label": "西岗区", "index": "X" },
+ { "label": "中山区", "index": "Z" },
+ { "label": "庄河市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "丹东市",
+ "index": "D",
+ "children": [
+ { "label": "东港市", "index": "D" },
+ { "label": "凤城市", "index": "F" },
+ { "label": "宽甸满族自治县", "index": "K" },
+ { "label": "元宝区", "index": "Y" },
+ { "label": "振兴区", "index": "Z" },
+ { "label": "振安区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "抚顺市",
+ "index": "F",
+ "children": [
+ { "label": "东洲区", "index": "D" },
+ { "label": "抚顺县", "index": "F" },
+ { "label": "清原满族自治县", "index": "Q" },
+ { "label": "顺城区", "index": "S" },
+ { "label": "望花区", "index": "W" },
+ { "label": "新抚区", "index": "X" },
+ { "label": "新宾满族自治县", "index": "X" }
+ ]
+ },
+ {
+ "label": "阜新市",
+ "index": "F",
+ "children": [
+ { "label": "阜新蒙古族自治县", "index": "F" },
+ { "label": "海州区", "index": "H" },
+ { "label": "清河门区", "index": "Q" },
+ { "label": "太平区", "index": "T" },
+ { "label": "新邱区", "index": "X" },
+ { "label": "细河区", "index": "X" },
+ { "label": "彰武县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "葫芦岛市",
+ "index": "H",
+ "children": [
+ { "label": "建昌县", "index": "J" },
+ { "label": "连山区", "index": "L" },
+ { "label": "龙港区", "index": "L" },
+ { "label": "南票区", "index": "N" },
+ { "label": "绥中县", "index": "S" },
+ { "label": "兴城市", "index": "X" }
+ ]
+ },
+ {
+ "label": "锦州市",
+ "index": "J",
+ "children": [
+ { "label": "北镇市", "index": "B" },
+ { "label": "古塔区", "index": "G" },
+ { "label": "黑山县", "index": "H" },
+ { "label": "凌河区", "index": "L" },
+ { "label": "凌海市", "index": "L" },
+ { "label": "太和区", "index": "T" },
+ { "label": "义县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "辽阳市",
+ "index": "L",
+ "children": [
+ { "label": "白塔区", "index": "B" },
+ { "label": "灯塔市", "index": "D" },
+ { "label": "弓长岭区", "index": "G" },
+ { "label": "宏伟区", "index": "H" },
+ { "label": "辽阳县", "index": "L" },
+ { "label": "太子河区", "index": "T" },
+ { "label": "文圣区", "index": "W" }
+ ]
+ },
+ {
+ "label": "盘锦市",
+ "index": "P",
+ "children": [
+ { "label": "大洼区", "index": "D" },
+ { "label": "盘山县", "index": "P" },
+ { "label": "双台子区", "index": "S" },
+ { "label": "兴隆台区", "index": "X" }
+ ]
+ },
+ {
+ "label": "沈阳市",
+ "index": "S",
+ "children": [
+ { "label": "大东区", "index": "D" },
+ { "label": "法库县", "index": "F" },
+ { "label": "和平区", "index": "H" },
+ { "label": "皇姑区", "index": "H" },
+ { "label": "浑南区", "index": "H" },
+ { "label": "康平县", "index": "K" },
+ { "label": "辽中区", "index": "L" },
+ { "label": "沈河区", "index": "S" },
+ { "label": "苏家屯区", "index": "S" },
+ { "label": "沈北新区", "index": "S" },
+ { "label": "铁西区", "index": "T" },
+ { "label": "新民市", "index": "X" },
+ { "label": "于洪区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "铁岭市",
+ "index": "T",
+ "children": [
+ { "label": "昌图县", "index": "C" },
+ { "label": "开原市", "index": "K" },
+ { "label": "清河区", "index": "Q" },
+ { "label": "铁岭县", "index": "T" },
+ { "label": "调兵山市", "index": "T" },
+ { "label": "西丰县", "index": "X" },
+ { "label": "银州区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "营口市",
+ "index": "Y",
+ "children": [
+ { "label": "鲅鱼圈区", "index": "B" },
+ { "label": "大石桥市", "index": "D" },
+ { "label": "盖州市", "index": "G" },
+ { "label": "老边区", "index": "L" },
+ { "label": "西市区", "index": "X" },
+ { "label": "站前区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "朝阳市",
+ "index": "Z",
+ "children": [
+ { "label": "北票市", "index": "B" },
+ { "label": "建平县", "index": "J" },
+ { "label": "喀喇沁左翼蒙古族自治县", "index": "K" },
+ { "label": "龙城区", "index": "L" },
+ { "label": "凌源市", "index": "L" },
+ { "label": "双塔区", "index": "S" },
+ { "label": "朝阳县", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "内蒙古自治区",
+ "index": "N",
+ "children": [
+ {
+ "label": "阿拉善盟",
+ "index": "A",
+ "children": [
+ { "label": "阿拉善左旗", "index": "A" },
+ { "label": "阿拉善右旗", "index": "A" },
+ { "label": "额济纳旗", "index": "E" },
+ { "label": "内蒙古阿拉善高新技术产业开发区", "index": "N" }
+ ]
+ },
+ {
+ "label": "包头市",
+ "index": "B",
+ "children": [
+ { "label": "白云鄂博矿区", "index": "B" },
+ { "label": "包头稀土高新技术产业开发区", "index": "B" },
+ { "label": "东河区", "index": "D" },
+ { "label": "达尔罕茂明安联合旗", "index": "D" },
+ { "label": "固阳县", "index": "G" },
+ { "label": "九原区", "index": "J" },
+ { "label": "昆都仑区", "index": "K" },
+ { "label": "青山区", "index": "Q" },
+ { "label": "石拐区", "index": "S" },
+ { "label": "土默特右旗", "index": "T" }
+ ]
+ },
+ {
+ "label": "巴彦淖尔市",
+ "index": "B",
+ "children": [
+ { "label": "磴口县", "index": "D" },
+ { "label": "杭锦后旗", "index": "H" },
+ { "label": "临河区", "index": "L" },
+ { "label": "五原县", "index": "W" },
+ { "label": "乌拉特前旗", "index": "W" },
+ { "label": "乌拉特中旗", "index": "W" },
+ { "label": "乌拉特后旗", "index": "W" }
+ ]
+ },
+ {
+ "label": "赤峰市",
+ "index": "C",
+ "children": [
+ { "label": "阿鲁科尔沁旗", "index": "A" },
+ { "label": "敖汉旗", "index": "A" },
+ { "label": "巴林左旗", "index": "B" },
+ { "label": "巴林右旗", "index": "B" },
+ { "label": "红山区", "index": "H" },
+ { "label": "克什克腾旗", "index": "K" },
+ { "label": "喀喇沁旗", "index": "K" },
+ { "label": "林西县", "index": "L" },
+ { "label": "宁城县", "index": "N" },
+ { "label": "松山区", "index": "S" },
+ { "label": "翁牛特旗", "index": "W" },
+ { "label": "元宝山区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "鄂尔多斯市",
+ "index": "E",
+ "children": [
+ { "label": "东胜区", "index": "D" },
+ { "label": "达拉特旗", "index": "D" },
+ { "label": "鄂托克前旗", "index": "E" },
+ { "label": "鄂托克旗", "index": "E" },
+ { "label": "杭锦旗", "index": "H" },
+ { "label": "康巴什区", "index": "K" },
+ { "label": "乌审旗", "index": "W" },
+ { "label": "伊金霍洛旗", "index": "Y" },
+ { "label": "准格尔旗", "index": "Z" }
+ ]
+ },
+ {
+ "label": "呼和浩特市",
+ "index": "H",
+ "children": [
+ { "label": "回民区", "index": "H" },
+ { "label": "和林格尔县", "index": "H" },
+ { "label": "呼和浩特经济技术开发区", "index": "H" },
+ { "label": "清水河县", "index": "Q" },
+ { "label": "赛罕区", "index": "S" },
+ { "label": "土默特左旗", "index": "T" },
+ { "label": "托克托县", "index": "T" },
+ { "label": "武川县", "index": "W" },
+ { "label": "新城区", "index": "X" },
+ { "label": "玉泉区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "呼伦贝尔市",
+ "index": "H",
+ "children": [
+ { "label": "阿荣旗", "index": "A" },
+ { "label": "陈巴尔虎旗", "index": "C" },
+ { "label": "鄂伦春自治旗", "index": "E" },
+ { "label": "鄂温克族自治旗", "index": "E" },
+ { "label": "额尔古纳市", "index": "E" },
+ { "label": "根河市", "index": "G" },
+ { "label": "海拉尔区", "index": "H" },
+ { "label": "莫力达瓦达斡尔族自治旗", "index": "M" },
+ { "label": "满洲里市", "index": "M" },
+ { "label": "新巴尔虎左旗", "index": "X" },
+ { "label": "新巴尔虎右旗", "index": "X" },
+ { "label": "牙克石市", "index": "Y" },
+ { "label": "扎赉诺尔区", "index": "Z" },
+ { "label": "扎兰屯市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "通辽市",
+ "index": "T",
+ "children": [
+ { "label": "霍林郭勒市", "index": "H" },
+ { "label": "科尔沁区", "index": "K" },
+ { "label": "科尔沁左翼中旗", "index": "K" },
+ { "label": "科尔沁左翼后旗", "index": "K" },
+ { "label": "开鲁县", "index": "K" },
+ { "label": "库伦旗", "index": "K" },
+ { "label": "奈曼旗", "index": "N" },
+ { "label": "通辽经济技术开发区", "index": "T" },
+ { "label": "扎鲁特旗", "index": "Z" }
+ ]
+ },
+ {
+ "label": "乌海市",
+ "index": "W",
+ "children": [
+ { "label": "海勃湾区", "index": "H" },
+ { "label": "海南区", "index": "H" },
+ { "label": "乌达区", "index": "W" }
+ ]
+ },
+ {
+ "label": "乌兰察布市",
+ "index": "W",
+ "children": [
+ { "label": "察哈尔右翼前旗", "index": "C" },
+ { "label": "察哈尔右翼中旗", "index": "C" },
+ { "label": "察哈尔右翼后旗", "index": "C" },
+ { "label": "丰镇市", "index": "F" },
+ { "label": "化德县", "index": "H" },
+ { "label": "集宁区", "index": "J" },
+ { "label": "凉城县", "index": "L" },
+ { "label": "商都县", "index": "S" },
+ { "label": "四子王旗", "index": "S" },
+ { "label": "兴和县", "index": "X" },
+ { "label": "卓资县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "兴安盟",
+ "index": "X",
+ "children": [
+ { "label": "阿尔山市", "index": "A" },
+ { "label": "科尔沁右翼前旗", "index": "K" },
+ { "label": "科尔沁右翼中旗", "index": "K" },
+ { "label": "突泉县", "index": "T" },
+ { "label": "乌兰浩特市", "index": "W" },
+ { "label": "扎赉特旗", "index": "Z" }
+ ]
+ },
+ {
+ "label": "锡林郭勒盟",
+ "index": "X",
+ "children": [
+ { "label": "阿巴嘎旗", "index": "A" },
+ { "label": "东乌珠穆沁旗", "index": "D" },
+ { "label": "多伦县", "index": "D" },
+ { "label": "二连浩特市", "index": "E" },
+ { "label": "苏尼特左旗", "index": "S" },
+ { "label": "苏尼特右旗", "index": "S" },
+ { "label": "太仆寺旗", "index": "T" },
+ { "label": "乌拉盖管理区管委会", "index": "W" },
+ { "label": "锡林浩特市", "index": "X" },
+ { "label": "西乌珠穆沁旗", "index": "X" },
+ { "label": "镶黄旗", "index": "X" },
+ { "label": "正镶白旗", "index": "Z" },
+ { "label": "正蓝旗", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "宁夏回族自治区",
+ "index": "N",
+ "children": [
+ {
+ "label": "固原市",
+ "index": "G",
+ "children": [
+ { "label": "泾源县", "index": "J" },
+ { "label": "隆德县", "index": "L" },
+ { "label": "彭阳县", "index": "P" },
+ { "label": "西吉县", "index": "X" },
+ { "label": "原州区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "石嘴山市",
+ "index": "S",
+ "children": [
+ { "label": "大武口区", "index": "D" },
+ { "label": "惠农区", "index": "H" },
+ { "label": "平罗县", "index": "P" }
+ ]
+ },
+ {
+ "label": "吴忠市",
+ "index": "W",
+ "children": [
+ { "label": "红寺堡区", "index": "H" },
+ { "label": "利通区", "index": "L" },
+ { "label": "青铜峡市", "index": "Q" },
+ { "label": "同心县", "index": "T" },
+ { "label": "盐池县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "银川市",
+ "index": "Y",
+ "children": [
+ { "label": "贺兰县", "index": "H" },
+ { "label": "金凤区", "index": "J" },
+ { "label": "灵武市", "index": "L" },
+ { "label": "兴庆区", "index": "X" },
+ { "label": "西夏区", "index": "X" },
+ { "label": "永宁县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "中卫市",
+ "index": "Z",
+ "children": [
+ { "label": "海原县", "index": "H" },
+ { "label": "沙坡头区", "index": "S" },
+ { "label": "中宁县", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "青海省",
+ "index": "Q",
+ "children": [
+ {
+ "label": "果洛藏族自治州",
+ "index": "G",
+ "children": [
+ { "label": "班玛县", "index": "B" },
+ { "label": "达日县", "index": "D" },
+ { "label": "甘德县", "index": "G" },
+ { "label": "久治县", "index": "J" },
+ { "label": "玛沁县", "index": "M" },
+ { "label": "玛多县", "index": "M" }
+ ]
+ },
+ {
+ "label": "海东市",
+ "index": "H",
+ "children": [
+ { "label": "互助土族自治县", "index": "H" },
+ { "label": "化隆回族自治县", "index": "H" },
+ { "label": "乐都区", "index": "L" },
+ { "label": "民和回族土族自治县", "index": "M" },
+ { "label": "平安区", "index": "P" },
+ { "label": "循化撒拉族自治县", "index": "X" }
+ ]
+ },
+ {
+ "label": "海北藏族自治州",
+ "index": "H",
+ "children": [
+ { "label": "刚察县", "index": "G" },
+ { "label": "海晏县", "index": "H" },
+ { "label": "门源回族自治县", "index": "M" },
+ { "label": "祁连县", "index": "Q" }
+ ]
+ },
+ {
+ "label": "黄南藏族自治州",
+ "index": "H",
+ "children": [
+ { "label": "河南蒙古族自治县", "index": "H" },
+ { "label": "尖扎县", "index": "J" },
+ { "label": "同仁市", "index": "T" },
+ { "label": "泽库县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "海南藏族自治州",
+ "index": "H",
+ "children": [
+ { "label": "共和县", "index": "G" },
+ { "label": "贵德县", "index": "G" },
+ { "label": "贵南县", "index": "G" },
+ { "label": "同德县", "index": "T" },
+ { "label": "兴海县", "index": "X" }
+ ]
+ },
+ {
+ "label": "海西蒙古族藏族自治州",
+ "index": "H",
+ "children": [
+ { "label": "德令哈市", "index": "D" },
+ { "label": "都兰县", "index": "D" },
+ { "label": "大柴旦行政委员会", "index": "D" },
+ { "label": "格尔木市", "index": "G" },
+ { "label": "茫崖市", "index": "M" },
+ { "label": "天峻县", "index": "T" },
+ { "label": "乌兰县", "index": "W" }
+ ]
+ },
+ {
+ "label": "西宁市",
+ "index": "X",
+ "children": [
+ { "label": "城东区", "index": "C" },
+ { "label": "城中区", "index": "C" },
+ { "label": "城西区", "index": "C" },
+ { "label": "城北区", "index": "C" },
+ { "label": "大通回族土族自治县", "index": "D" },
+ { "label": "湟中区", "index": "H" },
+ { "label": "湟源县", "index": "H" }
+ ]
+ },
+ {
+ "label": "玉树藏族自治州",
+ "index": "Y",
+ "children": [
+ { "label": "称多县", "index": "C" },
+ { "label": "囊谦县", "index": "N" },
+ { "label": "曲麻莱县", "index": "Q" },
+ { "label": "玉树市", "index": "Y" },
+ { "label": "杂多县", "index": "Z" },
+ { "label": "治多县", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "山西省",
+ "index": "S",
+ "children": [
+ {
+ "label": "长治市",
+ "index": "C",
+ "children": [
+ { "label": "长子县", "index": "C" },
+ { "label": "壶关县", "index": "H" },
+ { "label": "潞州区", "index": "L" },
+ { "label": "潞城区", "index": "L" },
+ { "label": "黎城县", "index": "L" },
+ { "label": "平顺县", "index": "P" },
+ { "label": "沁县", "index": "Q" },
+ { "label": "沁源县", "index": "Q" },
+ { "label": "上党区", "index": "S" },
+ { "label": "屯留区", "index": "T" },
+ { "label": "武乡县", "index": "W" },
+ { "label": "襄垣县", "index": "X" }
+ ]
+ },
+ {
+ "label": "大同市",
+ "index": "D",
+ "children": [
+ { "label": "广灵县", "index": "G" },
+ { "label": "浑源县", "index": "H" },
+ { "label": "灵丘县", "index": "L" },
+ { "label": "平城区", "index": "P" },
+ { "label": "山西大同经济开发区", "index": "S" },
+ { "label": "天镇县", "index": "T" },
+ { "label": "新荣区", "index": "X" },
+ { "label": "云冈区", "index": "Y" },
+ { "label": "云州区", "index": "Y" },
+ { "label": "阳高县", "index": "Y" },
+ { "label": "左云县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "晋城市",
+ "index": "J",
+ "children": [
+ { "label": "城区", "index": "C" },
+ { "label": "高平市", "index": "G" },
+ { "label": "陵川县", "index": "L" },
+ { "label": "沁水县", "index": "Q" },
+ { "label": "阳城县", "index": "Y" },
+ { "label": "泽州县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "晋中市",
+ "index": "J",
+ "children": [
+ { "label": "和顺县", "index": "H" },
+ { "label": "介休市", "index": "J" },
+ { "label": "灵石县", "index": "L" },
+ { "label": "平遥县", "index": "P" },
+ { "label": "祁县", "index": "Q" },
+ { "label": "寿阳县", "index": "S" },
+ { "label": "太谷区", "index": "T" },
+ { "label": "昔阳县", "index": "X" },
+ { "label": "榆次区", "index": "Y" },
+ { "label": "榆社县", "index": "Y" },
+ { "label": "左权县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "临汾市",
+ "index": "L",
+ "children": [
+ { "label": "安泽县", "index": "A" },
+ { "label": "大宁县", "index": "D" },
+ { "label": "浮山县", "index": "F" },
+ { "label": "汾西县", "index": "F" },
+ { "label": "古县", "index": "G" },
+ { "label": "洪洞县", "index": "H" },
+ { "label": "侯马市", "index": "H" },
+ { "label": "霍州市", "index": "H" },
+ { "label": "吉县", "index": "J" },
+ { "label": "蒲县", "index": "P" },
+ { "label": "曲沃县", "index": "Q" },
+ { "label": "襄汾县", "index": "X" },
+ { "label": "乡宁县", "index": "X" },
+ { "label": "隰县", "index": "X" },
+ { "label": "尧都区", "index": "Y" },
+ { "label": "翼城县", "index": "Y" },
+ { "label": "永和县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "吕梁市",
+ "index": "L",
+ "children": [
+ { "label": "方山县", "index": "F" },
+ { "label": "汾阳市", "index": "F" },
+ { "label": "交城县", "index": "J" },
+ { "label": "交口县", "index": "J" },
+ { "label": "离石区", "index": "L" },
+ { "label": "临县", "index": "L" },
+ { "label": "柳林县", "index": "L" },
+ { "label": "岚县", "index": "L" },
+ { "label": "石楼县", "index": "S" },
+ { "label": "文水县", "index": "W" },
+ { "label": "兴县", "index": "X" },
+ { "label": "孝义市", "index": "X" },
+ { "label": "中阳县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "朔州市",
+ "index": "S",
+ "children": [
+ { "label": "怀仁市", "index": "H" },
+ { "label": "平鲁区", "index": "P" },
+ { "label": "朔城区", "index": "S" },
+ { "label": "山阴县", "index": "S" },
+ { "label": "山西朔州经济开发区", "index": "S" },
+ { "label": "应县", "index": "Y" },
+ { "label": "右玉县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "太原市",
+ "index": "T",
+ "children": [
+ { "label": "古交市", "index": "G" },
+ { "label": "尖草坪区", "index": "J" },
+ { "label": "晋源区", "index": "J" },
+ { "label": "娄烦县", "index": "L" },
+ { "label": "清徐县", "index": "Q" },
+ { "label": "山西转型综合改革示范区", "index": "S" },
+ { "label": "万柏林区", "index": "W" },
+ { "label": "小店区", "index": "X" },
+ { "label": "杏花岭区", "index": "X" },
+ { "label": "迎泽区", "index": "Y" },
+ { "label": "阳曲县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "忻州市",
+ "index": "X",
+ "children": [
+ { "label": "保德县", "index": "B" },
+ { "label": "定襄县", "index": "D" },
+ { "label": "代县", "index": "D" },
+ { "label": "繁峙县", "index": "F" },
+ { "label": "河曲县", "index": "H" },
+ { "label": "静乐县", "index": "J" },
+ { "label": "岢岚县", "index": "K" },
+ { "label": "宁武县", "index": "N" },
+ { "label": "偏关县", "index": "P" },
+ { "label": "神池县", "index": "S" },
+ { "label": "五台县", "index": "W" },
+ { "label": "五寨县", "index": "W" },
+ { "label": "五台山风景名胜区", "index": "W" },
+ { "label": "忻府区", "index": "X" },
+ { "label": "原平市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "阳泉市",
+ "index": "Y",
+ "children": [
+ { "label": "城区", "index": "C" },
+ { "label": "郊区", "index": "J" },
+ { "label": "矿区", "index": "K" },
+ { "label": "平定县", "index": "P" },
+ { "label": "盂县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "运城市",
+ "index": "Y",
+ "children": [
+ { "label": "河津市", "index": "H" },
+ { "label": "稷山县", "index": "J" },
+ { "label": "绛县", "index": "J" },
+ { "label": "临猗县", "index": "L" },
+ { "label": "平陆县", "index": "P" },
+ { "label": "芮城县", "index": "R" },
+ { "label": "万荣县", "index": "W" },
+ { "label": "闻喜县", "index": "W" },
+ { "label": "新绛县", "index": "X" },
+ { "label": "夏县", "index": "X" },
+ { "label": "盐湖区", "index": "Y" },
+ { "label": "垣曲县", "index": "Y" },
+ { "label": "永济市", "index": "Y" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "上海市",
+ "index": "S",
+ "children": [
+ {
+ "label": "市辖区",
+ "index": "S",
+ "children": [
+ { "label": "宝山区", "index": "B" },
+ { "label": "长宁区", "index": "C" },
+ { "label": "崇明区", "index": "C" },
+ { "label": "奉贤区", "index": "F" },
+ { "label": "黄浦区", "index": "H" },
+ { "label": "虹口区", "index": "H" },
+ { "label": "静安区", "index": "J" },
+ { "label": "嘉定区", "index": "J" },
+ { "label": "金山区", "index": "J" },
+ { "label": "闵行区", "index": "M" },
+ { "label": "普陀区", "index": "P" },
+ { "label": "浦东新区", "index": "P" },
+ { "label": "青浦区", "index": "Q" },
+ { "label": "松江区", "index": "S" },
+ { "label": "徐汇区", "index": "X" },
+ { "label": "杨浦区", "index": "Y" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "山东省",
+ "index": "S",
+ "children": [
+ {
+ "label": "滨州市",
+ "index": "B",
+ "children": [
+ { "label": "滨城区", "index": "B" },
+ { "label": "博兴县", "index": "B" },
+ { "label": "惠民县", "index": "H" },
+ { "label": "无棣县", "index": "W" },
+ { "label": "阳信县", "index": "Y" },
+ { "label": "沾化区", "index": "Z" },
+ { "label": "邹平市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "东营市",
+ "index": "D",
+ "children": [
+ { "label": "东营区", "index": "D" },
+ { "label": "东营经济技术开发区", "index": "D" },
+ { "label": "东营港经济开发区", "index": "D" },
+ { "label": "广饶县", "index": "G" },
+ { "label": "河口区", "index": "H" },
+ { "label": "垦利区", "index": "K" },
+ { "label": "利津县", "index": "L" }
+ ]
+ },
+ {
+ "label": "德州市",
+ "index": "D",
+ "children": [
+ { "label": "德城区", "index": "D" },
+ { "label": "德州天衢新区", "index": "D" },
+ { "label": "陵城区", "index": "L" },
+ { "label": "临邑县", "index": "L" },
+ { "label": "乐陵市", "index": "L" },
+ { "label": "宁津县", "index": "N" },
+ { "label": "平原县", "index": "P" },
+ { "label": "庆云县", "index": "Q" },
+ { "label": "齐河县", "index": "Q" },
+ { "label": "武城县", "index": "W" },
+ { "label": "夏津县", "index": "X" },
+ { "label": "禹城市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "菏泽市",
+ "index": "H",
+ "children": [
+ { "label": "曹县", "index": "C" },
+ { "label": "成武县", "index": "C" },
+ { "label": "定陶区", "index": "D" },
+ { "label": "单县", "index": "D" },
+ { "label": "东明县", "index": "D" },
+ { "label": "菏泽经济技术开发区", "index": "H" },
+ { "label": "菏泽高新技术开发区", "index": "H" },
+ { "label": "巨野县", "index": "J" },
+ { "label": "鄄城县", "index": "J" },
+ { "label": "牡丹区", "index": "M" },
+ { "label": "郓城县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "济南市",
+ "index": "J",
+ "children": [
+ { "label": "长清区", "index": "C" },
+ { "label": "钢城区", "index": "G" },
+ { "label": "槐荫区", "index": "H" },
+ { "label": "济阳区", "index": "J" },
+ { "label": "济南高新技术产业开发区", "index": "J" },
+ { "label": "历下区", "index": "L" },
+ { "label": "历城区", "index": "L" },
+ { "label": "莱芜区", "index": "L" },
+ { "label": "平阴县", "index": "P" },
+ { "label": "市中区", "index": "S" },
+ { "label": "商河县", "index": "S" },
+ { "label": "天桥区", "index": "T" },
+ { "label": "章丘区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "济宁市",
+ "index": "J",
+ "children": [
+ { "label": "金乡县", "index": "J" },
+ { "label": "嘉祥县", "index": "J" },
+ { "label": "济宁高新技术产业开发区", "index": "J" },
+ { "label": "梁山县", "index": "L" },
+ { "label": "曲阜市", "index": "Q" },
+ { "label": "任城区", "index": "R" },
+ { "label": "泗水县", "index": "S" },
+ { "label": "微山县", "index": "W" },
+ { "label": "汶上县", "index": "W" },
+ { "label": "兖州区", "index": "Y" },
+ { "label": "鱼台县", "index": "Y" },
+ { "label": "邹城市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "临沂市",
+ "index": "L",
+ "children": [
+ { "label": "费县", "index": "F" },
+ { "label": "河东区", "index": "H" },
+ { "label": "莒南县", "index": "J" },
+ { "label": "兰山区", "index": "L" },
+ { "label": "罗庄区", "index": "L" },
+ { "label": "兰陵县", "index": "L" },
+ { "label": "临沭县", "index": "L" },
+ { "label": "临沂高新技术产业开发区", "index": "L" },
+ { "label": "蒙阴县", "index": "M" },
+ { "label": "平邑县", "index": "P" },
+ { "label": "郯城县", "index": "T" },
+ { "label": "沂南县", "index": "Y" },
+ { "label": "沂水县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "聊城市",
+ "index": "L",
+ "children": [
+ { "label": "茌平区", "index": "C" },
+ { "label": "东昌府区", "index": "D" },
+ { "label": "东阿县", "index": "D" },
+ { "label": "冠县", "index": "G" },
+ { "label": "高唐县", "index": "G" },
+ { "label": "临清市", "index": "L" },
+ { "label": "莘县", "index": "S" },
+ { "label": "阳谷县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "青岛市",
+ "index": "Q",
+ "children": [
+ { "label": "城阳区", "index": "C" },
+ { "label": "黄岛区", "index": "H" },
+ { "label": "即墨区", "index": "J" },
+ { "label": "胶州市", "index": "J" },
+ { "label": "崂山区", "index": "L" },
+ { "label": "李沧区", "index": "L" },
+ { "label": "莱西市", "index": "L" },
+ { "label": "平度市", "index": "P" },
+ { "label": "市南区", "index": "S" },
+ { "label": "市北区", "index": "S" }
+ ]
+ },
+ {
+ "label": "日照市",
+ "index": "R",
+ "children": [
+ { "label": "东港区", "index": "D" },
+ { "label": "莒县", "index": "J" },
+ { "label": "岚山区", "index": "L" },
+ { "label": "日照经济技术开发区", "index": "R" },
+ { "label": "五莲县", "index": "W" }
+ ]
+ },
+ {
+ "label": "泰安市",
+ "index": "T",
+ "children": [
+ { "label": "岱岳区", "index": "D" },
+ { "label": "东平县", "index": "D" },
+ { "label": "肥城市", "index": "F" },
+ { "label": "宁阳县", "index": "N" },
+ { "label": "泰山区", "index": "T" },
+ { "label": "新泰市", "index": "X" }
+ ]
+ },
+ {
+ "label": "潍坊市",
+ "index": "W",
+ "children": [
+ { "label": "安丘市", "index": "A" },
+ { "label": "昌乐县", "index": "C" },
+ { "label": "昌邑市", "index": "C" },
+ { "label": "坊子区", "index": "F" },
+ { "label": "高密市", "index": "G" },
+ { "label": "寒亭区", "index": "H" },
+ { "label": "奎文区", "index": "K" },
+ { "label": "临朐县", "index": "L" },
+ { "label": "青州市", "index": "Q" },
+ { "label": "寿光市", "index": "S" },
+ { "label": "潍城区", "index": "W" },
+ { "label": "潍坊滨海经济技术开发区", "index": "W" },
+ { "label": "诸城市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "威海市",
+ "index": "W",
+ "children": [
+ { "label": "环翠区", "index": "H" },
+ { "label": "荣成市", "index": "R" },
+ { "label": "乳山市", "index": "R" },
+ { "label": "文登区", "index": "W" },
+ { "label": "威海火炬高技术产业开发区", "index": "W" },
+ { "label": "威海经济技术开发区", "index": "W" },
+ { "label": "威海临港经济技术开发区", "index": "W" }
+ ]
+ },
+ {
+ "label": "烟台市",
+ "index": "Y",
+ "children": [
+ { "label": "福山区", "index": "F" },
+ { "label": "海阳市", "index": "H" },
+ { "label": "莱山区", "index": "L" },
+ { "label": "龙口市", "index": "L" },
+ { "label": "莱阳市", "index": "L" },
+ { "label": "莱州市", "index": "L" },
+ { "label": "牟平区", "index": "M" },
+ { "label": "蓬莱区", "index": "P" },
+ { "label": "栖霞市", "index": "Q" },
+ { "label": "烟台高新技术产业开发区", "index": "Y" },
+ { "label": "烟台经济技术开发区", "index": "Y" },
+ { "label": "芝罘区", "index": "Z" },
+ { "label": "招远市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "淄博市",
+ "index": "Z",
+ "children": [
+ { "label": "博山区", "index": "B" },
+ { "label": "高青县", "index": "G" },
+ { "label": "桓台县", "index": "H" },
+ { "label": "临淄区", "index": "L" },
+ { "label": "沂源县", "index": "Y" },
+ { "label": "淄川区", "index": "Z" },
+ { "label": "张店区", "index": "Z" },
+ { "label": "周村区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "枣庄市",
+ "index": "Z",
+ "children": [
+ { "label": "市中区", "index": "S" },
+ { "label": "山亭区", "index": "S" },
+ { "label": "台儿庄区", "index": "T" },
+ { "label": "滕州市", "index": "T" },
+ { "label": "薛城区", "index": "X" },
+ { "label": "峄城区", "index": "Y" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "四川省",
+ "index": "S",
+ "children": [
+ {
+ "label": "阿坝藏族羌族自治州",
+ "index": "A",
+ "children": [
+ { "label": "阿坝县", "index": "A" },
+ { "label": "黑水县", "index": "H" },
+ { "label": "红原县", "index": "H" },
+ { "label": "九寨沟县", "index": "J" },
+ { "label": "金川县", "index": "J" },
+ { "label": "理县", "index": "L" },
+ { "label": "马尔康市", "index": "M" },
+ { "label": "茂县", "index": "M" },
+ { "label": "壤塘县", "index": "R" },
+ { "label": "若尔盖县", "index": "R" },
+ { "label": "松潘县", "index": "S" },
+ { "label": "汶川县", "index": "W" },
+ { "label": "小金县", "index": "X" }
+ ]
+ },
+ {
+ "label": "巴中市",
+ "index": "B",
+ "children": [
+ { "label": "巴州区", "index": "B" },
+ { "label": "恩阳区", "index": "E" },
+ { "label": "南江县", "index": "N" },
+ { "label": "平昌县", "index": "P" },
+ { "label": "通江县", "index": "T" }
+ ]
+ },
+ {
+ "label": "成都市",
+ "index": "C",
+ "children": [
+ { "label": "成华区", "index": "C" },
+ { "label": "崇州市", "index": "C" },
+ { "label": "大邑县", "index": "D" },
+ { "label": "都江堰市", "index": "D" },
+ { "label": "锦江区", "index": "J" },
+ { "label": "金牛区", "index": "J" },
+ { "label": "金堂县", "index": "J" },
+ { "label": "简阳市", "index": "J" },
+ { "label": "龙泉驿区", "index": "L" },
+ { "label": "郫都区", "index": "P" },
+ { "label": "蒲江县", "index": "P" },
+ { "label": "彭州市", "index": "P" },
+ { "label": "青羊区", "index": "Q" },
+ { "label": "青白江区", "index": "Q" },
+ { "label": "邛崃市", "index": "Q" },
+ { "label": "双流区", "index": "S" },
+ { "label": "武侯区", "index": "W" },
+ { "label": "温江区", "index": "W" },
+ { "label": "新都区", "index": "X" },
+ { "label": "新津区", "index": "X" }
+ ]
+ },
+ {
+ "label": "德阳市",
+ "index": "D",
+ "children": [
+ { "label": "广汉市", "index": "G" },
+ { "label": "旌阳区", "index": "J" },
+ { "label": "罗江区", "index": "L" },
+ { "label": "绵竹市", "index": "M" },
+ { "label": "什邡市", "index": "S" },
+ { "label": "中江县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "达州市",
+ "index": "D",
+ "children": [
+ { "label": "达川区", "index": "D" },
+ { "label": "大竹县", "index": "D" },
+ { "label": "开江县", "index": "K" },
+ { "label": "渠县", "index": "Q" },
+ { "label": "通川区", "index": "T" },
+ { "label": "万源市", "index": "W" },
+ { "label": "宣汉县", "index": "X" }
+ ]
+ },
+ {
+ "label": "广元市",
+ "index": "G",
+ "children": [
+ { "label": "苍溪县", "index": "C" },
+ { "label": "剑阁县", "index": "J" },
+ { "label": "利州区", "index": "L" },
+ { "label": "青川县", "index": "Q" },
+ { "label": "旺苍县", "index": "W" },
+ { "label": "昭化区", "index": "Z" },
+ { "label": "朝天区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "广安市",
+ "index": "G",
+ "children": [
+ { "label": "广安区", "index": "G" },
+ { "label": "华蓥市", "index": "H" },
+ { "label": "邻水县", "index": "L" },
+ { "label": "前锋区", "index": "Q" },
+ { "label": "武胜县", "index": "W" },
+ { "label": "岳池县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "甘孜藏族自治州",
+ "index": "G",
+ "children": [
+ { "label": "白玉县", "index": "B" },
+ { "label": "巴塘县", "index": "B" },
+ { "label": "丹巴县", "index": "D" },
+ { "label": "道孚县", "index": "D" },
+ { "label": "德格县", "index": "D" },
+ { "label": "稻城县", "index": "D" },
+ { "label": "得荣县", "index": "D" },
+ { "label": "甘孜县", "index": "G" },
+ { "label": "九龙县", "index": "J" },
+ { "label": "康定市", "index": "K" },
+ { "label": "泸定县", "index": "L" },
+ { "label": "炉霍县", "index": "L" },
+ { "label": "理塘县", "index": "L" },
+ { "label": "石渠县", "index": "S" },
+ { "label": "色达县", "index": "S" },
+ { "label": "新龙县", "index": "X" },
+ { "label": "乡城县", "index": "X" },
+ { "label": "雅江县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "泸州市",
+ "index": "L",
+ "children": [
+ { "label": "古蔺县", "index": "G" },
+ { "label": "合江县", "index": "H" },
+ { "label": "江阳区", "index": "J" },
+ { "label": "龙马潭区", "index": "L" },
+ { "label": "泸县", "index": "L" },
+ { "label": "纳溪区", "index": "N" },
+ { "label": "叙永县", "index": "X" }
+ ]
+ },
+ {
+ "label": "乐山市",
+ "index": "L",
+ "children": [
+ { "label": "峨边彝族自治县", "index": "E" },
+ { "label": "峨眉山市", "index": "E" },
+ { "label": "金口河区", "index": "J" },
+ { "label": "犍为县", "index": "J" },
+ { "label": "井研县", "index": "J" },
+ { "label": "夹江县", "index": "J" },
+ { "label": "沐川县", "index": "M" },
+ { "label": "马边彝族自治县", "index": "M" },
+ { "label": "市中区", "index": "S" },
+ { "label": "沙湾区", "index": "S" },
+ { "label": "五通桥区", "index": "W" }
+ ]
+ },
+ {
+ "label": "凉山彝族自治州",
+ "index": "L",
+ "children": [
+ { "label": "布拖县", "index": "B" },
+ { "label": "德昌县", "index": "D" },
+ { "label": "甘洛县", "index": "G" },
+ { "label": "会理市", "index": "H" },
+ { "label": "会东县", "index": "H" },
+ { "label": "金阳县", "index": "J" },
+ { "label": "雷波县", "index": "L" },
+ { "label": "木里藏族自治县", "index": "M" },
+ { "label": "冕宁县", "index": "M" },
+ { "label": "美姑县", "index": "M" },
+ { "label": "宁南县", "index": "N" },
+ { "label": "普格县", "index": "P" },
+ { "label": "西昌市", "index": "X" },
+ { "label": "喜德县", "index": "X" },
+ { "label": "盐源县", "index": "Y" },
+ { "label": "越西县", "index": "Y" },
+ { "label": "昭觉县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "绵阳市",
+ "index": "M",
+ "children": [
+ { "label": "安州区", "index": "A" },
+ { "label": "北川羌族自治县", "index": "B" },
+ { "label": "涪城区", "index": "F" },
+ { "label": "江油市", "index": "J" },
+ { "label": "平武县", "index": "P" },
+ { "label": "三台县", "index": "S" },
+ { "label": "游仙区", "index": "Y" },
+ { "label": "盐亭县", "index": "Y" },
+ { "label": "梓潼县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "眉山市",
+ "index": "M",
+ "children": [
+ { "label": "东坡区", "index": "D" },
+ { "label": "丹棱县", "index": "D" },
+ { "label": "洪雅县", "index": "H" },
+ { "label": "彭山区", "index": "P" },
+ { "label": "青神县", "index": "Q" },
+ { "label": "仁寿县", "index": "R" }
+ ]
+ },
+ {
+ "label": "内江市",
+ "index": "N",
+ "children": [
+ { "label": "东兴区", "index": "D" },
+ { "label": "隆昌市", "index": "L" },
+ { "label": "市中区", "index": "S" },
+ { "label": "威远县", "index": "W" },
+ { "label": "资中县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "南充市",
+ "index": "N",
+ "children": [
+ { "label": "高坪区", "index": "G" },
+ { "label": "嘉陵区", "index": "J" },
+ { "label": "阆中市", "index": "L" },
+ { "label": "南部县", "index": "N" },
+ { "label": "蓬安县", "index": "P" },
+ { "label": "顺庆区", "index": "S" },
+ { "label": "西充县", "index": "X" },
+ { "label": "营山县", "index": "Y" },
+ { "label": "仪陇县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "攀枝花市",
+ "index": "P",
+ "children": [
+ { "label": "东区", "index": "D" },
+ { "label": "米易县", "index": "M" },
+ { "label": "仁和区", "index": "R" },
+ { "label": "西区", "index": "X" },
+ { "label": "盐边县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "遂宁市",
+ "index": "S",
+ "children": [
+ { "label": "安居区", "index": "A" },
+ { "label": "船山区", "index": "C" },
+ { "label": "大英县", "index": "D" },
+ { "label": "蓬溪县", "index": "P" },
+ { "label": "射洪市", "index": "S" }
+ ]
+ },
+ {
+ "label": "宜宾市",
+ "index": "Y",
+ "children": [
+ { "label": "翠屏区", "index": "C" },
+ { "label": "长宁县", "index": "C" },
+ { "label": "高县", "index": "G" },
+ { "label": "珙县", "index": "G" },
+ { "label": "江安县", "index": "J" },
+ { "label": "南溪区", "index": "N" },
+ { "label": "屏山县", "index": "P" },
+ { "label": "叙州区", "index": "X" },
+ { "label": "兴文县", "index": "X" },
+ { "label": "筠连县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "雅安市",
+ "index": "Y",
+ "children": [
+ { "label": "宝兴县", "index": "B" },
+ { "label": "汉源县", "index": "H" },
+ { "label": "芦山县", "index": "L" },
+ { "label": "名山区", "index": "M" },
+ { "label": "石棉县", "index": "S" },
+ { "label": "天全县", "index": "T" },
+ { "label": "荥经县", "index": "X" },
+ { "label": "雨城区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "自贡市",
+ "index": "Z",
+ "children": [
+ { "label": "大安区", "index": "D" },
+ { "label": "富顺县", "index": "F" },
+ { "label": "贡井区", "index": "G" },
+ { "label": "荣县", "index": "R" },
+ { "label": "沿滩区", "index": "Y" },
+ { "label": "自流井区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "资阳市",
+ "index": "Z",
+ "children": [
+ { "label": "安岳县", "index": "A" },
+ { "label": "乐至县", "index": "L" },
+ { "label": "雁江区", "index": "Y" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "陕西省",
+ "index": "S",
+ "children": [
+ {
+ "label": "安康市",
+ "index": "A",
+ "children": [
+ { "label": "白河县", "index": "B" },
+ { "label": "汉滨区", "index": "H" },
+ { "label": "汉阴县", "index": "H" },
+ { "label": "岚皋县", "index": "L" },
+ { "label": "宁陕县", "index": "N" },
+ { "label": "平利县", "index": "P" },
+ { "label": "石泉县", "index": "S" },
+ { "label": "旬阳市", "index": "X" },
+ { "label": "紫阳县", "index": "Z" },
+ { "label": "镇坪县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "宝鸡市",
+ "index": "B",
+ "children": [
+ { "label": "陈仓区", "index": "C" },
+ { "label": "凤翔区", "index": "F" },
+ { "label": "扶风县", "index": "F" },
+ { "label": "凤县", "index": "F" },
+ { "label": "金台区", "index": "J" },
+ { "label": "陇县", "index": "L" },
+ { "label": "麟游县", "index": "L" },
+ { "label": "眉县", "index": "M" },
+ { "label": "岐山县", "index": "Q" },
+ { "label": "千阳县", "index": "Q" },
+ { "label": "太白县", "index": "T" },
+ { "label": "渭滨区", "index": "W" }
+ ]
+ },
+ {
+ "label": "汉中市",
+ "index": "H",
+ "children": [
+ { "label": "城固县", "index": "C" },
+ { "label": "佛坪县", "index": "F" },
+ { "label": "汉台区", "index": "H" },
+ { "label": "略阳县", "index": "L" },
+ { "label": "留坝县", "index": "L" },
+ { "label": "勉县", "index": "M" },
+ { "label": "南郑区", "index": "N" },
+ { "label": "宁强县", "index": "N" },
+ { "label": "西乡县", "index": "X" },
+ { "label": "洋县", "index": "Y" },
+ { "label": "镇巴县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "商洛市",
+ "index": "S",
+ "children": [
+ { "label": "丹凤县", "index": "D" },
+ { "label": "洛南县", "index": "L" },
+ { "label": "商州区", "index": "S" },
+ { "label": "商南县", "index": "S" },
+ { "label": "山阳县", "index": "S" },
+ { "label": "镇安县", "index": "Z" },
+ { "label": "柞水县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "铜川市",
+ "index": "T",
+ "children": [
+ { "label": "王益区", "index": "W" },
+ { "label": "印台区", "index": "Y" },
+ { "label": "耀州区", "index": "Y" },
+ { "label": "宜君县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "渭南市",
+ "index": "W",
+ "children": [
+ { "label": "白水县", "index": "B" },
+ { "label": "澄城县", "index": "C" },
+ { "label": "大荔县", "index": "D" },
+ { "label": "富平县", "index": "F" },
+ { "label": "华州区", "index": "H" },
+ { "label": "合阳县", "index": "H" },
+ { "label": "韩城市", "index": "H" },
+ { "label": "华阴市", "index": "H" },
+ { "label": "临渭区", "index": "L" },
+ { "label": "蒲城县", "index": "P" },
+ { "label": "潼关县", "index": "T" }
+ ]
+ },
+ {
+ "label": "西安市",
+ "index": "X",
+ "children": [
+ { "label": "碑林区", "index": "B" },
+ { "label": "灞桥区", "index": "B" },
+ { "label": "长安区", "index": "C" },
+ { "label": "高陵区", "index": "G" },
+ { "label": "鄠邑区", "index": "H" },
+ { "label": "莲湖区", "index": "L" },
+ { "label": "临潼区", "index": "L" },
+ { "label": "蓝田县", "index": "L" },
+ { "label": "未央区", "index": "W" },
+ { "label": "新城区", "index": "X" },
+ { "label": "雁塔区", "index": "Y" },
+ { "label": "阎良区", "index": "Y" },
+ { "label": "周至县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "咸阳市",
+ "index": "X",
+ "children": [
+ { "label": "彬州市", "index": "B" },
+ { "label": "长武县", "index": "C" },
+ { "label": "淳化县", "index": "C" },
+ { "label": "泾阳县", "index": "J" },
+ { "label": "礼泉县", "index": "L" },
+ { "label": "秦都区", "index": "Q" },
+ { "label": "乾县", "index": "Q" },
+ { "label": "三原县", "index": "S" },
+ { "label": "渭城区", "index": "W" },
+ { "label": "武功县", "index": "W" },
+ { "label": "旬邑县", "index": "X" },
+ { "label": "兴平市", "index": "X" },
+ { "label": "杨陵区", "index": "Y" },
+ { "label": "永寿县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "延安市",
+ "index": "Y",
+ "children": [
+ { "label": "安塞区", "index": "A" },
+ { "label": "宝塔区", "index": "B" },
+ { "label": "富县", "index": "F" },
+ { "label": "甘泉县", "index": "G" },
+ { "label": "黄龙县", "index": "H" },
+ { "label": "黄陵县", "index": "H" },
+ { "label": "洛川县", "index": "L" },
+ { "label": "吴起县", "index": "W" },
+ { "label": "延长县", "index": "Y" },
+ { "label": "延川县", "index": "Y" },
+ { "label": "宜川县", "index": "Y" },
+ { "label": "志丹县", "index": "Z" },
+ { "label": "子长市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "榆林市",
+ "index": "Y",
+ "children": [
+ { "label": "定边县", "index": "D" },
+ { "label": "府谷县", "index": "F" },
+ { "label": "横山区", "index": "H" },
+ { "label": "靖边县", "index": "J" },
+ { "label": "佳县", "index": "J" },
+ { "label": "米脂县", "index": "M" },
+ { "label": "清涧县", "index": "Q" },
+ { "label": "绥德县", "index": "S" },
+ { "label": "神木市", "index": "S" },
+ { "label": "吴堡县", "index": "W" },
+ { "label": "榆阳区", "index": "Y" },
+ { "label": "子洲县", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "天津市",
+ "index": "T",
+ "children": [
+ {
+ "label": "市辖区",
+ "index": "S",
+ "children": [
+ { "label": "北辰区", "index": "B" },
+ { "label": "宝坻区", "index": "B" },
+ { "label": "滨海新区", "index": "B" },
+ { "label": "东丽区", "index": "D" },
+ { "label": "和平区", "index": "H" },
+ { "label": "河东区", "index": "H" },
+ { "label": "河西区", "index": "H" },
+ { "label": "河北区", "index": "H" },
+ { "label": "红桥区", "index": "H" },
+ { "label": "津南区", "index": "J" },
+ { "label": "静海区", "index": "J" },
+ { "label": "蓟州区", "index": "J" },
+ { "label": "南开区", "index": "N" },
+ { "label": "宁河区", "index": "N" },
+ { "label": "武清区", "index": "W" },
+ { "label": "西青区", "index": "X" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "西藏自治区",
+ "index": "X",
+ "children": [
+ {
+ "label": "阿里地区",
+ "index": "A",
+ "children": [
+ { "label": "措勤县", "index": "C" },
+ { "label": "噶尔县", "index": "G" },
+ { "label": "革吉县", "index": "G" },
+ { "label": "改则县", "index": "G" },
+ { "label": "普兰县", "index": "P" },
+ { "label": "日土县", "index": "R" },
+ { "label": "札达县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "昌都市",
+ "index": "C",
+ "children": [
+ { "label": "八宿县", "index": "B" },
+ { "label": "边坝县", "index": "B" },
+ { "label": "察雅县", "index": "C" },
+ { "label": "丁青县", "index": "D" },
+ { "label": "贡觉县", "index": "G" },
+ { "label": "江达县", "index": "J" },
+ { "label": "卡若区", "index": "K" },
+ { "label": "类乌齐县", "index": "L" },
+ { "label": "洛隆县", "index": "L" },
+ { "label": "芒康县", "index": "M" },
+ { "label": "左贡县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "拉萨市",
+ "index": "L",
+ "children": [
+ { "label": "城关区", "index": "C" },
+ { "label": "堆龙德庆区", "index": "D" },
+ { "label": "达孜区", "index": "D" },
+ { "label": "当雄县", "index": "D" },
+ { "label": "达孜工业园区", "index": "D" },
+ { "label": "格尔木藏青工业园区", "index": "G" },
+ { "label": "林周县", "index": "L" },
+ { "label": "拉萨经济技术开发区", "index": "L" },
+ { "label": "墨竹工卡县", "index": "M" },
+ { "label": "尼木县", "index": "N" },
+ { "label": "曲水县", "index": "Q" },
+ { "label": "西藏文化旅游创意园区", "index": "X" }
+ ]
+ },
+ {
+ "label": "林芝市",
+ "index": "L",
+ "children": [
+ { "label": "巴宜区", "index": "B" },
+ { "label": "波密县", "index": "B" },
+ { "label": "察隅县", "index": "C" },
+ { "label": "工布江达县", "index": "G" },
+ { "label": "朗县", "index": "L" },
+ { "label": "墨脱县", "index": "M" },
+ { "label": "米林市", "index": "M" }
+ ]
+ },
+ {
+ "label": "那曲市",
+ "index": "N",
+ "children": [
+ { "label": "安多县", "index": "A" },
+ { "label": "比如县", "index": "B" },
+ { "label": "班戈县", "index": "B" },
+ { "label": "巴青县", "index": "B" },
+ { "label": "嘉黎县", "index": "J" },
+ { "label": "聂荣县", "index": "N" },
+ { "label": "尼玛县", "index": "N" },
+ { "label": "色尼区", "index": "S" },
+ { "label": "申扎县", "index": "S" },
+ { "label": "索县", "index": "S" },
+ { "label": "双湖县", "index": "S" }
+ ]
+ },
+ {
+ "label": "日喀则市",
+ "index": "R",
+ "children": [
+ { "label": "昂仁县", "index": "A" },
+ { "label": "白朗县", "index": "B" },
+ { "label": "定日县", "index": "D" },
+ { "label": "定结县", "index": "D" },
+ { "label": "岗巴县", "index": "G" },
+ { "label": "江孜县", "index": "J" },
+ { "label": "吉隆县", "index": "J" },
+ { "label": "康马县", "index": "K" },
+ { "label": "拉孜县", "index": "L" },
+ { "label": "南木林县", "index": "N" },
+ { "label": "聂拉木县", "index": "N" },
+ { "label": "仁布县", "index": "R" },
+ { "label": "桑珠孜区", "index": "S" },
+ { "label": "萨迦县", "index": "S" },
+ { "label": "萨嘎县", "index": "S" },
+ { "label": "谢通门县", "index": "X" },
+ { "label": "亚东县", "index": "Y" },
+ { "label": "仲巴县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "山南市",
+ "index": "S",
+ "children": [
+ { "label": "措美县", "index": "C" },
+ { "label": "错那市", "index": "C" },
+ { "label": "贡嘎县", "index": "G" },
+ { "label": "加查县", "index": "J" },
+ { "label": "洛扎县", "index": "L" },
+ { "label": "隆子县", "index": "L" },
+ { "label": "浪卡子县", "index": "L" },
+ { "label": "乃东区", "index": "N" },
+ { "label": "琼结县", "index": "Q" },
+ { "label": "曲松县", "index": "Q" },
+ { "label": "桑日县", "index": "S" },
+ { "label": "扎囊县", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "新疆维吾尔自治区",
+ "index": "X",
+ "children": [
+ {
+ "label": "阿克苏地区",
+ "index": "A",
+ "children": [
+ { "label": "阿克苏市", "index": "A" },
+ { "label": "阿瓦提县", "index": "A" },
+ { "label": "拜城县", "index": "B" },
+ { "label": "库车市", "index": "K" },
+ { "label": "柯坪县", "index": "K" },
+ { "label": "沙雅县", "index": "S" },
+ { "label": "温宿县", "index": "W" },
+ { "label": "乌什县", "index": "W" },
+ { "label": "新和县", "index": "X" }
+ ]
+ },
+ {
+ "label": "阿勒泰地区",
+ "index": "A",
+ "children": [
+ { "label": "阿勒泰市", "index": "A" },
+ { "label": "布尔津县", "index": "B" },
+ { "label": "富蕴县", "index": "F" },
+ { "label": "福海县", "index": "F" },
+ { "label": "哈巴河县", "index": "H" },
+ { "label": "吉木乃县", "index": "J" },
+ { "label": "青河县", "index": "Q" }
+ ]
+ },
+ {
+ "label": "博尔塔拉蒙古自治州",
+ "index": "B",
+ "children": [
+ { "label": "阿拉山口市", "index": "A" },
+ { "label": "博乐市", "index": "B" },
+ { "label": "精河县", "index": "J" },
+ { "label": "温泉县", "index": "W" }
+ ]
+ },
+ {
+ "label": "巴音郭楞蒙古自治州",
+ "index": "B",
+ "children": [
+ { "label": "博湖县", "index": "B" },
+ { "label": "和静县", "index": "H" },
+ { "label": "和硕县", "index": "H" },
+ { "label": "库尔勒市", "index": "K" },
+ { "label": "轮台县", "index": "L" },
+ { "label": "且末县", "index": "Q" },
+ { "label": "若羌县", "index": "R" },
+ { "label": "尉犁县", "index": "W" },
+ { "label": "焉耆回族自治县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "昌吉回族自治州",
+ "index": "C",
+ "children": [
+ { "label": "昌吉市", "index": "C" },
+ { "label": "阜康市", "index": "F" },
+ { "label": "呼图壁县", "index": "H" },
+ { "label": "吉木萨尔县", "index": "J" },
+ { "label": "玛纳斯县", "index": "M" },
+ { "label": "木垒哈萨克自治县", "index": "M" },
+ { "label": "奇台县", "index": "Q" }
+ ]
+ },
+ {
+ "label": "哈密市",
+ "index": "H",
+ "children": [
+ { "label": "巴里坤哈萨克自治县", "index": "B" },
+ { "label": "伊州区", "index": "Y" },
+ { "label": "伊吾县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "和田地区",
+ "index": "H",
+ "children": [
+ { "label": "策勒县", "index": "C" },
+ { "label": "和田市", "index": "H" },
+ { "label": "和田县", "index": "H" },
+ { "label": "洛浦县", "index": "L" },
+ { "label": "墨玉县", "index": "M" },
+ { "label": "民丰县", "index": "M" },
+ { "label": "皮山县", "index": "P" },
+ { "label": "于田县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "克拉玛依市",
+ "index": "K",
+ "children": [
+ { "label": "白碱滩区", "index": "B" },
+ { "label": "独山子区", "index": "D" },
+ { "label": "克拉玛依区", "index": "K" },
+ { "label": "乌尔禾区", "index": "W" }
+ ]
+ },
+ {
+ "label": "克孜勒苏柯尔克孜自治州",
+ "index": "K",
+ "children": [
+ { "label": "阿图什市", "index": "A" },
+ { "label": "阿克陶县", "index": "A" },
+ { "label": "阿合奇县", "index": "A" },
+ { "label": "乌恰县", "index": "W" }
+ ]
+ },
+ {
+ "label": "喀什地区",
+ "index": "K",
+ "children": [
+ { "label": "巴楚县", "index": "B" },
+ { "label": "喀什市", "index": "K" },
+ { "label": "麦盖提县", "index": "M" },
+ { "label": "伽师县", "index": "Q" },
+ { "label": "疏附县", "index": "S" },
+ { "label": "疏勒县", "index": "S" },
+ { "label": "莎车县", "index": "S" },
+ { "label": "塔什库尔干塔吉克自治县", "index": "T" },
+ { "label": "英吉沙县", "index": "Y" },
+ { "label": "叶城县", "index": "Y" },
+ { "label": "岳普湖县", "index": "Y" },
+ { "label": "泽普县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "吐鲁番市",
+ "index": "T",
+ "children": [
+ { "label": "高昌区", "index": "G" },
+ { "label": "鄯善县", "index": "S" },
+ { "label": "托克逊县", "index": "T" }
+ ]
+ },
+ {
+ "label": "塔城地区",
+ "index": "T",
+ "children": [
+ { "label": "额敏县", "index": "E" },
+ { "label": "和布克赛尔蒙古自治县", "index": "H" },
+ { "label": "沙湾市", "index": "S" },
+ { "label": "塔城市", "index": "T" },
+ { "label": "托里县", "index": "T" },
+ { "label": "乌苏市", "index": "W" },
+ { "label": "裕民县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "乌鲁木齐市",
+ "index": "W",
+ "children": [
+ { "label": "达坂城区", "index": "D" },
+ { "label": "米东区", "index": "M" },
+ { "label": "沙依巴克区", "index": "S" },
+ { "label": "水磨沟区", "index": "S" },
+ { "label": "天山区", "index": "T" },
+ { "label": "头屯河区", "index": "T" },
+ { "label": "乌鲁木齐县", "index": "W" },
+ { "label": "新市区", "index": "X" }
+ ]
+ },
+ {
+ "label": "伊犁哈萨克自治州",
+ "index": "Y",
+ "children": [
+ { "label": "察布查尔锡伯自治县", "index": "C" },
+ { "label": "巩留县", "index": "G" },
+ { "label": "霍尔果斯市", "index": "H" },
+ { "label": "霍城县", "index": "H" },
+ { "label": "奎屯市", "index": "K" },
+ { "label": "尼勒克县", "index": "N" },
+ { "label": "特克斯县", "index": "T" },
+ { "label": "新源县", "index": "X" },
+ { "label": "伊宁市", "index": "Y" },
+ { "label": "伊宁县", "index": "Y" },
+ { "label": "昭苏县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "自治区直辖县级行政区划",
+ "index": "Z",
+ "children": [
+ { "label": "阿拉尔市", "index": "A" },
+ { "label": "北屯市", "index": "B" },
+ { "label": "白杨市", "index": "B" },
+ { "label": "胡杨河市", "index": "H" },
+ { "label": "可克达拉市", "index": "K" },
+ { "label": "昆玉市", "index": "K" },
+ { "label": "石河子市", "index": "S" },
+ { "label": "双河市", "index": "S" },
+ { "label": "图木舒克市", "index": "T" },
+ { "label": "铁门关市", "index": "T" },
+ { "label": "五家渠市", "index": "W" },
+ { "label": "新星市", "index": "X" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "云南省",
+ "index": "Y",
+ "children": [
+ {
+ "label": "保山市",
+ "index": "B",
+ "children": [
+ { "label": "昌宁县", "index": "C" },
+ { "label": "隆阳区", "index": "L" },
+ { "label": "龙陵县", "index": "L" },
+ { "label": "施甸县", "index": "S" },
+ { "label": "腾冲市", "index": "T" }
+ ]
+ },
+ {
+ "label": "楚雄彝族自治州",
+ "index": "C",
+ "children": [
+ { "label": "楚雄市", "index": "C" },
+ { "label": "大姚县", "index": "D" },
+ { "label": "禄丰市", "index": "L" },
+ { "label": "牟定县", "index": "M" },
+ { "label": "南华县", "index": "N" },
+ { "label": "双柏县", "index": "S" },
+ { "label": "武定县", "index": "W" },
+ { "label": "姚安县", "index": "Y" },
+ { "label": "永仁县", "index": "Y" },
+ { "label": "元谋县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "大理白族自治州",
+ "index": "D",
+ "children": [
+ { "label": "宾川县", "index": "B" },
+ { "label": "大理市", "index": "D" },
+ { "label": "洱源县", "index": "E" },
+ { "label": "鹤庆县", "index": "H" },
+ { "label": "剑川县", "index": "J" },
+ { "label": "弥渡县", "index": "M" },
+ { "label": "南涧彝族自治县", "index": "N" },
+ { "label": "巍山彝族回族自治县", "index": "W" },
+ { "label": "祥云县", "index": "X" },
+ { "label": "漾濞彝族自治县", "index": "Y" },
+ { "label": "永平县", "index": "Y" },
+ { "label": "云龙县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "德宏傣族景颇族自治州",
+ "index": "D",
+ "children": [
+ { "label": "梁河县", "index": "L" },
+ { "label": "陇川县", "index": "L" },
+ { "label": "芒市", "index": "M" },
+ { "label": "瑞丽市", "index": "R" },
+ { "label": "盈江县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "迪庆藏族自治州",
+ "index": "D",
+ "children": [
+ { "label": "德钦县", "index": "D" },
+ { "label": "维西傈僳族自治县", "index": "W" },
+ { "label": "香格里拉市", "index": "X" }
+ ]
+ },
+ {
+ "label": "红河哈尼族彝族自治州",
+ "index": "H",
+ "children": [
+ { "label": "个旧市", "index": "G" },
+ { "label": "红河县", "index": "H" },
+ { "label": "河口瑶族自治县", "index": "H" },
+ { "label": "建水县", "index": "J" },
+ { "label": "金平苗族瑶族傣族自治县", "index": "J" },
+ { "label": "开远市", "index": "K" },
+ { "label": "泸西县", "index": "L" },
+ { "label": "绿春县", "index": "L" },
+ { "label": "蒙自市", "index": "M" },
+ { "label": "弥勒市", "index": "M" },
+ { "label": "屏边苗族自治县", "index": "P" },
+ { "label": "石屏县", "index": "S" },
+ { "label": "元阳县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "昆明市",
+ "index": "K",
+ "children": [
+ { "label": "安宁市", "index": "A" },
+ { "label": "呈贡区", "index": "C" },
+ { "label": "东川区", "index": "D" },
+ { "label": "富民县", "index": "F" },
+ { "label": "官渡区", "index": "G" },
+ { "label": "晋宁区", "index": "J" },
+ { "label": "禄劝彝族苗族自治县", "index": "L" },
+ { "label": "盘龙区", "index": "P" },
+ { "label": "石林彝族自治县", "index": "S" },
+ { "label": "嵩明县", "index": "S" },
+ { "label": "五华区", "index": "W" },
+ { "label": "西山区", "index": "X" },
+ { "label": "寻甸回族彝族自治县", "index": "X" },
+ { "label": "宜良县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "丽江市",
+ "index": "L",
+ "children": [
+ { "label": "古城区", "index": "G" },
+ { "label": "华坪县", "index": "H" },
+ { "label": "宁蒗彝族自治县", "index": "N" },
+ { "label": "玉龙纳西族自治县", "index": "Y" },
+ { "label": "永胜县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "临沧市",
+ "index": "L",
+ "children": [
+ { "label": "沧源佤族自治县", "index": "C" },
+ { "label": "凤庆县", "index": "F" },
+ { "label": "耿马傣族佤族自治县", "index": "G" },
+ { "label": "临翔区", "index": "L" },
+ { "label": "双江拉祜族佤族布朗族傣族自治县", "index": "S" },
+ { "label": "云县", "index": "Y" },
+ { "label": "永德县", "index": "Y" },
+ { "label": "镇康县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "怒江傈僳族自治州",
+ "index": "N",
+ "children": [
+ { "label": "福贡县", "index": "F" },
+ { "label": "贡山独龙族怒族自治县", "index": "G" },
+ { "label": "泸水市", "index": "L" },
+ { "label": "兰坪白族普米族自治县", "index": "L" }
+ ]
+ },
+ {
+ "label": "普洱市",
+ "index": "P",
+ "children": [
+ { "label": "景东彝族自治县", "index": "J" },
+ { "label": "景谷傣族彝族自治县", "index": "J" },
+ { "label": "江城哈尼族彝族自治县", "index": "J" },
+ { "label": "澜沧拉祜族自治县", "index": "L" },
+ { "label": "墨江哈尼族自治县", "index": "M" },
+ { "label": "孟连傣族拉祜族佤族自治县", "index": "M" },
+ { "label": "宁洱哈尼族彝族自治县", "index": "N" },
+ { "label": "思茅区", "index": "S" },
+ { "label": "西盟佤族自治县", "index": "X" },
+ { "label": "镇沅彝族哈尼族拉祜族自治县", "index": "Z" }
+ ]
+ },
+ {
+ "label": "曲靖市",
+ "index": "Q",
+ "children": [
+ { "label": "富源县", "index": "F" },
+ { "label": "会泽县", "index": "H" },
+ { "label": "陆良县", "index": "L" },
+ { "label": "罗平县", "index": "L" },
+ { "label": "马龙区", "index": "M" },
+ { "label": "麒麟区", "index": "Q" },
+ { "label": "师宗县", "index": "S" },
+ { "label": "宣威市", "index": "X" },
+ { "label": "沾益区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "文山壮族苗族自治州",
+ "index": "W",
+ "children": [
+ { "label": "富宁县", "index": "F" },
+ { "label": "广南县", "index": "G" },
+ { "label": "麻栗坡县", "index": "M" },
+ { "label": "马关县", "index": "M" },
+ { "label": "丘北县", "index": "Q" },
+ { "label": "文山市", "index": "W" },
+ { "label": "西畴县", "index": "X" },
+ { "label": "砚山县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "西双版纳傣族自治州",
+ "index": "X",
+ "children": [
+ { "label": "景洪市", "index": "J" },
+ { "label": "勐海县", "index": "M" },
+ { "label": "勐腊县", "index": "M" }
+ ]
+ },
+ {
+ "label": "玉溪市",
+ "index": "Y",
+ "children": [
+ { "label": "澄江市", "index": "C" },
+ { "label": "峨山彝族自治县", "index": "E" },
+ { "label": "红塔区", "index": "H" },
+ { "label": "华宁县", "index": "H" },
+ { "label": "江川区", "index": "J" },
+ { "label": "通海县", "index": "T" },
+ { "label": "新平彝族傣族自治县", "index": "X" },
+ { "label": "易门县", "index": "Y" },
+ { "label": "元江哈尼族彝族傣族自治县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "昭通市",
+ "index": "Z",
+ "children": [
+ { "label": "大关县", "index": "D" },
+ { "label": "鲁甸县", "index": "L" },
+ { "label": "巧家县", "index": "Q" },
+ { "label": "绥江县", "index": "S" },
+ { "label": "水富市", "index": "S" },
+ { "label": "威信县", "index": "W" },
+ { "label": "盐津县", "index": "Y" },
+ { "label": "永善县", "index": "Y" },
+ { "label": "彝良县", "index": "Y" },
+ { "label": "昭阳区", "index": "Z" },
+ { "label": "镇雄县", "index": "Z" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "浙江省",
+ "index": "Z",
+ "children": [
+ {
+ "label": "杭州市",
+ "index": "H",
+ "children": [
+ { "label": "滨江区", "index": "B" },
+ { "label": "淳安县", "index": "C" },
+ { "label": "富阳区", "index": "F" },
+ { "label": "拱墅区", "index": "G" },
+ { "label": "建德市", "index": "J" },
+ { "label": "临安区", "index": "L" },
+ { "label": "临平区", "index": "L" },
+ { "label": "钱塘区", "index": "Q" },
+ { "label": "上城区", "index": "S" },
+ { "label": "桐庐县", "index": "T" },
+ { "label": "西湖区", "index": "X" },
+ { "label": "萧山区", "index": "X" },
+ { "label": "余杭区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "湖州市",
+ "index": "H",
+ "children": [
+ { "label": "安吉县", "index": "A" },
+ { "label": "长兴县", "index": "C" },
+ { "label": "德清县", "index": "D" },
+ { "label": "南浔区", "index": "N" },
+ { "label": "吴兴区", "index": "W" }
+ ]
+ },
+ {
+ "label": "嘉兴市",
+ "index": "J",
+ "children": [
+ { "label": "海盐县", "index": "H" },
+ { "label": "海宁市", "index": "H" },
+ { "label": "嘉善县", "index": "J" },
+ { "label": "南湖区", "index": "N" },
+ { "label": "平湖市", "index": "P" },
+ { "label": "桐乡市", "index": "T" },
+ { "label": "秀洲区", "index": "X" }
+ ]
+ },
+ {
+ "label": "金华市",
+ "index": "J",
+ "children": [
+ { "label": "东阳市", "index": "D" },
+ { "label": "金东区", "index": "J" },
+ { "label": "兰溪市", "index": "L" },
+ { "label": "浦江县", "index": "P" },
+ { "label": "磐安县", "index": "P" },
+ { "label": "婺城区", "index": "W" },
+ { "label": "武义县", "index": "W" },
+ { "label": "义乌市", "index": "Y" },
+ { "label": "永康市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "丽水市",
+ "index": "L",
+ "children": [
+ { "label": "缙云县", "index": "J" },
+ { "label": "景宁畲族自治县", "index": "J" },
+ { "label": "莲都区", "index": "L" },
+ { "label": "龙泉市", "index": "L" },
+ { "label": "青田县", "index": "Q" },
+ { "label": "庆元县", "index": "Q" },
+ { "label": "遂昌县", "index": "S" },
+ { "label": "松阳县", "index": "S" },
+ { "label": "云和县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "宁波市",
+ "index": "N",
+ "children": [
+ { "label": "北仑区", "index": "B" },
+ { "label": "慈溪市", "index": "C" },
+ { "label": "奉化区", "index": "F" },
+ { "label": "海曙区", "index": "H" },
+ { "label": "江北区", "index": "J" },
+ { "label": "宁海县", "index": "N" },
+ { "label": "象山县", "index": "X" },
+ { "label": "鄞州区", "index": "Y" },
+ { "label": "余姚市", "index": "Y" },
+ { "label": "镇海区", "index": "Z" }
+ ]
+ },
+ {
+ "label": "衢州市",
+ "index": "Q",
+ "children": [
+ { "label": "常山县", "index": "C" },
+ { "label": "江山市", "index": "J" },
+ { "label": "柯城区", "index": "K" },
+ { "label": "开化县", "index": "K" },
+ { "label": "龙游县", "index": "L" },
+ { "label": "衢江区", "index": "Q" }
+ ]
+ },
+ {
+ "label": "绍兴市",
+ "index": "S",
+ "children": [
+ { "label": "柯桥区", "index": "K" },
+ { "label": "上虞区", "index": "S" },
+ { "label": "嵊州市", "index": "S" },
+ { "label": "新昌县", "index": "X" },
+ { "label": "越城区", "index": "Y" },
+ { "label": "诸暨市", "index": "Z" }
+ ]
+ },
+ {
+ "label": "台州市",
+ "index": "T",
+ "children": [
+ { "label": "黄岩区", "index": "H" },
+ { "label": "椒江区", "index": "J" },
+ { "label": "路桥区", "index": "L" },
+ { "label": "临海市", "index": "L" },
+ { "label": "三门县", "index": "S" },
+ { "label": "天台县", "index": "T" },
+ { "label": "温岭市", "index": "W" },
+ { "label": "仙居县", "index": "X" },
+ { "label": "玉环市", "index": "Y" }
+ ]
+ },
+ {
+ "label": "温州市",
+ "index": "W",
+ "children": [
+ { "label": "苍南县", "index": "C" },
+ { "label": "洞头区", "index": "D" },
+ { "label": "鹿城区", "index": "L" },
+ { "label": "龙湾区", "index": "L" },
+ { "label": "乐清市", "index": "L" },
+ { "label": "龙港市", "index": "L" },
+ { "label": "瓯海区", "index": "O" },
+ { "label": "平阳县", "index": "P" },
+ { "label": "瑞安市", "index": "R" },
+ { "label": "泰顺县", "index": "T" },
+ { "label": "文成县", "index": "W" },
+ { "label": "永嘉县", "index": "Y" }
+ ]
+ },
+ {
+ "label": "舟山市",
+ "index": "Z",
+ "children": [
+ { "label": "定海区", "index": "D" },
+ { "label": "岱山县", "index": "D" },
+ { "label": "普陀区", "index": "P" },
+ { "label": "嵊泗县", "index": "S" }
+ ]
+ }
+ ]
+ },
+ {
+ "label": "重庆市",
+ "index": "Z",
+ "children": [
+ {
+ "label": "市辖区",
+ "index": "S",
+ "children": [
+ { "label": "北碚区", "index": "B" },
+ { "label": "巴南区", "index": "B" },
+ { "label": "璧山区", "index": "B" },
+ { "label": "长寿区", "index": "C" },
+ { "label": "大渡口区", "index": "D" },
+ { "label": "大足区", "index": "D" },
+ { "label": "涪陵区", "index": "F" },
+ { "label": "合川区", "index": "H" },
+ { "label": "江北区", "index": "J" },
+ { "label": "九龙坡区", "index": "J" },
+ { "label": "江津区", "index": "J" },
+ { "label": "开州区", "index": "K" },
+ { "label": "梁平区", "index": "L" },
+ { "label": "南岸区", "index": "N" },
+ { "label": "南川区", "index": "N" },
+ { "label": "綦江区", "index": "Q" },
+ { "label": "黔江区", "index": "Q" },
+ { "label": "荣昌区", "index": "R" },
+ { "label": "沙坪坝区", "index": "S" },
+ { "label": "铜梁区", "index": "T" },
+ { "label": "潼南区", "index": "T" },
+ { "label": "万州区", "index": "W" },
+ { "label": "武隆区", "index": "W" },
+ { "label": "渝中区", "index": "Y" },
+ { "label": "渝北区", "index": "Y" },
+ { "label": "永川区", "index": "Y" }
+ ]
+ },
+ {
+ "label": "县",
+ "index": "X",
+ "children": [
+ { "label": "城口县", "index": "C" },
+ { "label": "垫江县", "index": "D" },
+ { "label": "丰都县", "index": "F" },
+ { "label": "奉节县", "index": "F" },
+ { "label": "彭水苗族土家族自治县", "index": "P" },
+ { "label": "石柱土家族自治县", "index": "S" },
+ { "label": "巫山县", "index": "W" },
+ { "label": "巫溪县", "index": "W" },
+ { "label": "秀山土家族苗族自治县", "index": "X" },
+ { "label": "云阳县", "index": "Y" },
+ { "label": "酉阳土家族苗族自治县", "index": "Y" },
+ { "label": "忠县", "index": "Z" }
+ ]
+ }
+ ]
+ }
+]
diff --git a/cool-unix/docs/logo.png b/cool-unix/docs/logo.png
new file mode 100644
index 0000000..05a31d3
Binary files /dev/null and b/cool-unix/docs/logo.png differ
diff --git a/cool-unix/favicon.ico b/cool-unix/favicon.ico
new file mode 100644
index 0000000..b1c8cd1
Binary files /dev/null and b/cool-unix/favicon.ico differ
diff --git a/cool-unix/icons/iconfont/index.scss b/cool-unix/icons/iconfont/index.scss
new file mode 100644
index 0000000..51d9e32
--- /dev/null
+++ b/cool-unix/icons/iconfont/index.scss
@@ -0,0 +1,4 @@
+@font-face {
+ font-family: "iconfont";
+ src: url("data:font/ttf;base64,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IGJ5IHN2ZzJ0dGYgZnJvbSBGb250ZWxsbyBwcm9qZWN0Lmh0dHA6Ly9mb250ZWxsby5jb20AQwByAGUAYQB0AGUAZAAgAGIAeQAgAGkAYwBvAG4AZgBvAG4AdABjAGwALQBpAGMAbwBuAGYAbwBuAHQAUgBlAGcAdQBsAGEAcgBjAGwALQBpAGMAbwBuAGYAbwBuAHQAYwBsAC0AaQBjAG8AbgBmAG8AbgB0AFYAZQByAHMAaQBvAG4AIAAxAC4AMABjAGwALQBpAGMAbwBuAGYAbwBuAHQARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABzAHYAZwAyAHQAdABmACAAZgByAG8AbQAgAEYAbwBuAHQAZQBsAGwAbwAgAHAAcgBvAGoAZQBjAHQALgBoAHQAdABwADoALwAvAGYAbwBuAHQAZQBsAGwAbwAuAGMAbwBtAAACAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIBAgEDAQQBBQEGAQcBCAEJAQoBCwEMAQ0BDgEPARABEQESARMBFAEVARYBFwEYARkBGgEbARwBHQEeAR8BIAEhASIBIwAEYmFjawN5dWUId2FuY2hlbmcGc2hpYmFpBmJvZmFuZwdwaW5nbHVuB2h1YXRvbmcHZGlhbnphbgRmdWxpB2ppdWRpYW4GdHVwaWFuB2Rpbmd3ZWkDdmlwB3l1bmR1YW4IbmFvemhvbmcHamlhb2xpdQZzaG91cnUGemhpY2h1B3NoaWppYW4HcGFpemhhbwVxaWNoZQhzaHVpcGlhbwdkaW5neXVlBmtlZnVfMgx0dWljaHVkZW5nbHUJcGluZ2x1bl8yB3FpYW5iYW8Ic291c3VvXzIKeW91aHVpcXVhbghnb3V3dWRhaQZndWFubGkGcWlhbmJpCWh1YW5nZ3VhbgAAAAA=") format("woff");
+}
diff --git a/cool-unix/icons/iconfont/index.ts b/cool-unix/icons/iconfont/index.ts
new file mode 100644
index 0000000..e4c55d9
--- /dev/null
+++ b/cool-unix/icons/iconfont/index.ts
@@ -0,0 +1,35 @@
+export const iconfont = {
+ "back": "e6db",
+ "yue": "e6bb",
+ "wancheng": "e6bc",
+ "shibai": "e6bd",
+ "bofang": "e6be",
+ "pinglun": "e6bf",
+ "huatong": "e6c0",
+ "dianzan": "e6c1",
+ "fuli": "e6c2",
+ "jiudian": "e6c3",
+ "tupian": "e6c5",
+ "dingwei": "e6c6",
+ "vip": "e6c8",
+ "yunduan": "e6c9",
+ "naozhong": "e6ca",
+ "jiaoliu": "e6cb",
+ "shouru": "e6cc",
+ "zhichu": "e6cd",
+ "shijian": "e6ce",
+ "paizhao": "e6cf",
+ "qiche": "e6d0",
+ "shuipiao": "e6d1",
+ "dingyue": "e6d2",
+ "kefu_2": "e6d3",
+ "tuichudenglu": "e6d4",
+ "pinglun_2": "e6d5",
+ "qianbao": "e6d6",
+ "sousuo_2": "e6d7",
+ "youhuiquan": "e6d8",
+ "gouwudai": "e6ea",
+ "guanli": "e6fd",
+ "qianbi": "e70d",
+ "huangguan": "e712"
+};
diff --git a/cool-unix/icons/index.scss b/cool-unix/icons/index.scss
new file mode 100644
index 0000000..ab11442
--- /dev/null
+++ b/cool-unix/icons/index.scss
@@ -0,0 +1,2 @@
+@import "./iconfont/index.scss";
+@import "./remixicon/index.scss";
diff --git a/cool-unix/icons/index.ts b/cool-unix/icons/index.ts
new file mode 100644
index 0000000..bee5889
--- /dev/null
+++ b/cool-unix/icons/index.ts
@@ -0,0 +1,7 @@
+import { iconfont } from "./iconfont";
+import { remixicon } from "./remixicon";
+
+export const icons = {
+ iconfont,
+ remixicon
+};
diff --git a/cool-unix/icons/remixicon/index.scss b/cool-unix/icons/remixicon/index.scss
new file mode 100644
index 0000000..1a8b970
--- /dev/null
+++ b/cool-unix/icons/remixicon/index.scss
@@ -0,0 +1,4 @@
+@font-face {
+ font-family: "remixicon";
+ src: url("data:font/ttf;base64,AAEAAAALAIAAAwAwR1NVQiCLJXoAAAE4AAAAVE9TLzJCw1nwAAABjAAAAFZjbWFwhDk4UQAADhAAADVyZ2x5ZtskChIAAEmcAAGVFGhlYWQtsn+tAAAA4AAAADZoaGVhCMcHOgAAALwAAAAkaG10eNbUAAAAAAHkAAAMLGxvY2HMoDOgAABDhAAABhhtYXhwBCEAmAAAARgAAAAgbmFtZRwN5TYAAd6wAAADKnBvc3RJRqFaAAHh3AAANLAAAQAAA/z/TAAABOIAAAAABMkAAQAAAAAAAAAAAAAAAAAAAwsAAQAAAAEAAFIXJRFfDzz1AAsEsAAAAADk5R1cAAAAAOTlHVwAAP9lBMkD4wAAAAgAAgAAAAAAAAABAAADCwCMAAwAAAAAAAIAAAAKAAoAAAD/AAAAAAAAAAEAAAAKADAAPgACREZMVAAObGF0bgAaAAQAAAAAAAAAAQAAAAQAAAAAAAAAAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAQAGAAAAAQAAAAEE4AGQAAUAAAL5A0gAAACoAvkDSAAAAkAAOgE1AAACAAUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBmRWQAQOoC9e4D/P9MAGwD/AC0AAAAAQAAAAAAAAAAAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAABOIAAATiAAAE4gAA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AyADJgMoAy4DMAM+A0ADTgNQA1IDVANWA1gDWgNcA2IDZANmA2oDbANuA3QDdgN4A3gDegN8A4IDhAOGA4gDiAOIA4oDjAOOA5ADlgOYA54DoAOiA6YDqAOoA6wDrgOwA7IDtAO+A8ADxAPEA8QDxgPgA+ID5APmA+wD9gP8BA4EEAQQBBIEFAQWBBYEFgQWBCQEJgQoBCgEKAQuBDAENgQ4BDoEQARCBEIEQgRMBFIEVARaBFwEXARkBGYEbARyBHIEeAR6BHoEegR8BH4EgASCBIQEigSMBI4EkASWBJgEmgS4BLoEvAS+BMAEwgTIBMoE0ATSBNQE1gTYBNgE2gTgBOIE6gT0BPQE9gT4BPoE/AT+BQQFBgUIBQgFCAUKBQwFEgUUBRQFFAUWBRgFGgUcBR4FIAUgBSIFLgU2BTgFOAU+BUAFQgVEBUoFXAVmBXQFdgV4BX4FiAWKBYwFkgWYBaIFpAWmBagFqgW8BbwFvgXSBdgF2gXcBd4F8AXyBfIF8gX0BfYF+AX8Bf4GAAYCBgQGBgYIBggGCgYKBhAGEgYSBhYGGAYYBhoGHAYeBiAGIgYoBioGKgYsBiwGLgYwBjIGNAY2BjgAAAE7AgcCBgIIAgkCCgILAbsBugHEAcQAfgB/AqsC3gFGAUcAMQAwACsAKgFPAU4CPQI8AUUBRAGXAZYARwBGAA8ACwAGABYAEwITACICFAAjABAADAAHAAgCDQAaABUAFAABAA4ACgAFAAQAFwASAAMADQAJAg4AGQACABgAEQDvAPAATQBMAiACHwE3ATgASwBKAQ0BDAIjAFQCIQBXAFcCIgBTAFIA3ADbAkwCSwDtAO4CUQJSAPwA+wBaAFsAXABdAQkCJABWAGIAYwItAi4CKgIrAGEAYAIpAigBcgF2AXcBcwF0AXUCNAI1AjYCNwIyAjMApQCkAJsAmgCgAKEAqACpAKwArQCvAK4AvAC9AJ8AngCxALAAvwC+AKYApwCrAKoCaQJpAcIBwgGzAbIBtwG2AbQBtQG5AbgC3ALbAWcBZgD0APMCPwI+Ab8BvgHDAcMAQwBCAEUARAJAAkACgQKAAVgBWQDJAMgBLAErAlcCWACWAJcAgQCAARcBFgCQAJEAkgCTAJUAlACDAIICOQI4AGUAZADVANQCcgJxAdQB1QDOAM8CWQJaAcYBxgBeAFgA/wEAAc0BzAHJAOIA4QIaAhkBWwFaAscCyADGAMcAwwDCAa4BrwEoASkBIgEqASMB3AHdAd8B3gCzALIA6wDsAOoA6QDmAOUCTQJOAOQA4wJQAk8C0ALPAPcA+AFoAWkB8QHwANoA2gIAAgEAZgBnAnkCeQK9ArwCuwGoAakBkwGSAZkBmAE6ATkAawBqAqQCpQF8AX0CWwJcAUEBQAE+AT8CXQJeAfIAJQAkAhwCGwAuAC8CZgJlAmMCZAFhAWAAPwA+AD0APABBAEABMwE0AbwBvQK6ArkA1gDXAmgCZwLKAskC/wL+AvMDBgLLAswDAQMAAvkC+AL9AvwC9AL1AwIDAwL7AvoC9gL3AF8AWQJVAGwAbAEDAQQBbQFsAfQB9QH3AdcB1gHbAdoB2QHYAc8BzgJsAmsAOAA5ADMAMgIeAh0ANQA0ADYANwJgAl8CfwJ+AVEBUAFSAVMC6ALnAMUAxABOAE8BnQGcAJkAmAIxAjAAogCjAX8BfgGBAYABTAFNAS4BLQEwAS8BMgExAfwB/QGlAaQBowGiAs4CzQFqAWsBegF7AXkBeAFeAV8CvgGHAYYB7AHtAYgBiQLaAtECOwI6Au4C7QFcAV0BjQGMAtYC1QDRAkkCSgDQAwgDBwIlAFUBiwGKAsACvwETARIAbgBtAEgASQJ9AnwBVAFVAoUChADeAN0CRQJGAN8A4AC1ALQBsAGxALcAtgHBAcABjwGOATUBNgKvAq4BDwEOAHsAfABwAG8BQgFDAq0CrAJ7AnoBEAERAkgCRwHhAeABCAByAHECQwJEAHkAegGmAacB5QHkAecB5gHjAeIB0gHTAdEB0AJtAm4CqQKoARkBGAEbARoA2QDYAQEBAgBzAHQAzQDMAQYBBwB3AHgBnwGeAOcA6AGQAZEAJwAmACgAKQJqAcUB+gH7APEA8gEnASYCxgLFAtkC2AMEAwUA/QD+AlMB6wHqARUBFAHoAekC7ALrAnACbwD5APoB7wHuAH0AfQJWASQBJQJ4AncAywDKAcsBygLXAcgCpgKnAfkB+AKMAo0CiwKQApECoQKgAooCmwKaApYClwKZApgCngKfApQClQKJAogCnQKcApMCkgFvAW4BHwEeASABIQEdARwBggGDAYUBhAJ2AnUCdAJzAQsBCgFIAUkBSwFKAuAC3wB2AHUDCQMJAwoDCgAbABsAHAAc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AMkAAOvKAADrygAAAMgAAOvbAADr2wAAASwAAOvcAADr3AAAASsAAOvdAADr3QAAAlcAAOveAADr3gAAAlgAAOvfAADr3wAAAJYAAOvgAADr4AAAAJcAAOvhAADr4QAAAIEAAOviAADr4gAAAIAAAOvtAADr7QAAARcAAOvuAADr7gAAARYAAOvxAADr8QAAAJAAAOvyAADr8gAAAJEAAOvzAADr8wAAAJIAAOv0AADr9AAAAJMAAOv1AADr9QAAAJUAAOv2AADr9gAAAJQAAOv3AADr9wAAAIMAAOv4AADr+AAAAIIAAOwBAADsAQAAAjkAAOwCAADsAgAAAjgAAOwNAADsDQAAAGUAAOwOAADsDgAAAGQAAOwVAADsFQAAANUAAOwWAADsFgAAANQAAOwZAADsGQAAAnIAAOwaAADsGgAAAnEAAOwpAADsKQAAAdQAAOwqAADsKgAAAdUAAOwtAADsLQAAAM4AAOwuAADsLgAAAM8AAOw7AADsOwAAAlkAAOw8AADsPAAAAloAAOw/AADsPwAAAcYAAOxAAADsQAAAAcYAAOxBAADsQQAAAF4AAOxCAADsQgAAAFgAAOxRAADsUQAAAP8AAOxSAADsUgAAAQAAAOxVAADsVQAAAc0AAOxWAADsVgAAAcwAAOxaAADsWgAAAckAAOxbAADsWwAAAOIAAOxcAADsXAAAAOEAAOxhAADsYQAAAhoAAOxiAADsYgAAAhkAAOx5AADseQAAAVsAAOx6AADsegAAAVoAAOx/AADsfwAAAscAAOyAAADsgAAAAsgAAOyBAADsgQAAAMYAAOyCAADsggAAAMcAAOyFAADshQAAAMMAAOyGAADshgAAAMIAAOygAADsoAAAAa4AAOyhAADsoQAAAa8AAOynAADspwAAASgAAOypAADsqQAAASkAAOyqAADsqgAAASIAAOysAADsrAAAASoAAOytAADsrQAAASMAAOy0AADstAAAAdwAAOy1AADstQAAAd0AAOy2AADstgAAAd8AAOy3AADstwAAAd4AAOzAAADswAAAALMAAOzBAADswQAAALIAAOzUAADs1AAAAOsAAOzVAADs1QAAAOwAAOzaAADs2gAAAOoAAOzbAADs2wAAAOkAAOzgAADs4AAAAOYAAOzrAADs6wAAAOUAAOzwAADs8AAAAk0AAOzxAADs8QAAAk4AAOz6AADs+gAAAOQAAOz7AADs+wAAAOMAAO0OAADtDgAAAlAAAO0PAADtDwAAAk8AAO0UAADtFAAAAtAAAO0VAADtFQAAAs8AAO0eAADtHgAAAPcAAO0fAADtHwAAAPgAAO0gAADtIAAAAWgAAO0hAADtIQAAAWkAAO0mAADtJgAAAfEAAO0nAADtJwAAAfAAAO0wAADtMAAAANoAAO0xAADtMQAAANoAAO0yAADtMgAAAgAAAO0zAADtMwAAAgEAAO06AADtOgAAAGYAAO07AADtOwAAAGcAAO1CAADtQgAAAnkAAO1DAADtQwAAAnkAAO2LAADtiwAAAr0AAO2MAADtjAAAArwAAO2NAADtjQAAArsAAO2UAADtlAAAAagAAO2VAADtlQAAAakAAO2aAADtmgAAAZMAAO2cAADtnAAAAZIAAO2dAADtnQAAAZkAAO2eAADtngAAAZgAAO26AADtugAAAToAAO27AADtuwAAATkAAO3OAADtzgAAAGsAAO3PAADtzwAAAGoAAO3iAADt4gAAAqQAAO3jAADt4wAAAqUAAO4EAADuBAAAAXwAAO4FAADuBQAAAX0AAO4KAADuCgAAAlsAAO4LAADuCwAAAlwAAO4MAADuDAAAAUEAAO4NAADuDQAAAUAAAO4OAADuDgAAAT4AAO4PAADuDwAAAT8AAO4SAADuEgAAAl0AAO4TAADuEwAAAl4AAO4XAADuFwAAAfIAAO4YAADuGAAAACUAAO4ZAADuGQAAACQAAO4mAADuJgAAAhwAAO4rAADuKwAAAhsAAO42AADuNgAAAC4AAO43AADuNwAAAC8AAO5GAADuRgAAAmYAAO5HAADuRwAAAmUAAO5IAADuSAAAAmMAAO5JAADuSQAAAmQAAO5KAADuSgAAAWEAAO5LAADuSwAAAWAAAO5MAADuTAAAAD8AAO5NAADuTQAAAD4AAO5OAADuTgAAAD0AAO5PAADuTwAAADwAAO5QAADuUAAAAEEAAO5RAADuUQAAAEAAAO5SAADuUgAAATMAAO5TAADuUwAAATQAAO5WAADuVgAAAbwAAO5XAADuVwAAAb0AAO5fAADuXwAAAroAAO5gAADuYAAAArkAAO5yAADucgAAANYAAO5zAADucwAAANcAAO58AADufAAAAmgAAO59AADufQAAAmcAAO5+AADufgAAAsoAAO5/AADufwAAAskAAO6IAADuiAAAAv8AAO6JAADuiQAAAv4AAO6KAADuigAAAvMAAO6LAADuiwAAAwYAAO6MAADujAAAAssAAO6NAADujQAAAswAAO6RAADukQAAAwEAAO6SAADukgAAAwAAAO6TAADukwAAAvkAAO6UAADulAAAAvgAAO6YAADumAAAAv0AAO6ZAADumQAAAvwAAO6aAADumgAAAvQAAO6bAADumwAAAvUAAO6cAADunAAAAwIAAO6dAADunQAAAwMAAO6eAADungAAAvsAAO6fAADunwAAAvoAAO6gAADuoAAAAvYAAO6hAADuoQAAAvcAAO6qAADuqgAAAF8AAO6rAADuqwAAAFkAAO6yAADusgAAAlUAAO63AADutwAAAGwAAO64AADuuAAAAGwAAO66AADuugAAAQMAAO67AADuuwAAAQQAAO6/AADuvwAAAW0AAO7AAADuwAAAAWwAAO7CAADuwgAAAfQAAO7GAADuxgAAAfUAAO7JAADuyQAAAfcAAO7NAADuzQAAAdcAAO7OAADuzgAAAdYAAO7PAADuzwAAAdsAAO7QAADu0AAAAdoAAO7RAADu0QAAAdkAAO7SAADu0gAAAdgAAO7TAADu0wAAAc8AAO7UAADu1AAAAc4AAO7bAADu2wAAAmwAAO7cAADu3AAAAmsAAO7rAADu6wAAADgAAO7sAADu7AAAADkAAO7zAADu8wAAADMAAO72AADu9gAAADIAAO75AADu+QAAAh4AAO76AADu+gAAAh0AAO77AADu+wAAADUAAO78AADu/AAAADQAAO8BAADvAQAAADYAAO8CAADvAgAAADcAAO8HAADvBwAAAmAAAO8IAADvCAAAAl8AAO8JAADvCQAAAn8AAO8KAADvCgAAAn4AAO8TAADvEwAAAVEAAO8UAADvFAAAAVAAAO8XAADvFwAAAVIAAO8YAADvGAAAAVMAAO8dAADvHQAAAugAAO8eAADvHgAAAucAAO8fAADvHwAAAMUAAO8gAADvIAAAAMQAAO8nAADvJwAAAE4AAO8oAADvKAAAAE8AAO86AADvOgAAAZ0AAO8+AADvPgAAAZwAAO9DAADvQwAAAJkAAO9EAADvRAAAAJgAAO9FAADvRQAAAjEAAO9GAADvRgAAAjAAAO9HAADvRwAAAKIAAO9IAADvSAAA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AZ4AAPGaAADxmgAAAOcAAPGbAADxmwAAAOgAAPGeAADxngAAAZAAAPGfAADxnwAAAZEAAPGkAADxpAAAACcAAPGlAADxpQAAACYAAPGmAADxpgAAACgAAPGnAADxpwAAACkAAPGuAADxrgAAAmoAAPGvAADxrwAAAcUAAPG8AADxvAAAAfoAAPG/AADxvwAAAfsAAPHGAADxxgAAAPEAAPHHAADxxwAAAPIAAPHKAADxygAAAScAAPHLAADxywAAASYAAPHSAADx0gAAAsYAAPHTAADx0wAAAsUAAPHYAADx2AAAAtkAAPHZAADx2QAAAtgAAPHdAADx3QAAAwQAAPHeAADx3gAAAwUAAPHnAADx5wAAAP0AAPHoAADx6AAAAP4AAPIBAADyAQAAAlMAAPIGAADyBgAAAesAAPIHAADyBwAAAeoAAPIMAADyDAAAARUAAPINAADyDQAAARQAAPIOAADyDgAAAegAAPIPAADyDwAAAekAAPIQAADyEAAAAuwAAPIRAADyEQAAAusAAPISAADyEgAAAnAAAPIVAADyFQAAAm8AAPIWAADyFgAAAPkAAPIXAADyFwAAAPoAAPIYAADyGAAAAe8AAPIZAADyGQAAAe4AAPIeAADyHgAAAH0AAPIfAADyHwAAAH0AAPInAADyJwAAAlYAAPIuAADyLgAAASQAAPIvAADyLwAAASUAAPIwAADyMAAAAngAAPIxAADyMQAAAncAAPI2AADyNgAAAMsAAPI3AADyNwAAAMoAAPJLAADySwAAAcsAAPJMAADyTAAAAcoAAPJPAADyTwAAAtcAAPJQAADyUAAAAcgAAPJTAADyUwAAAqYAAPJUAADyVAAAAqcAAPJVAADyVQAAAfkAAPJWAADyVgAAAfgAAPJdAADyXQAAAowAAPJeAADyXgAAAo0AAPJfAADyXwAAAosAAPJgAADyYAAAApAAAPJhAADyYQAAApEAAPJiAADyYgAAAqEAAPJjAADyYwAAAqAAAPJkAADyZAAAAooAAPJlAADyZQAAApsAAPJmAADyZgAAApoAAPJpAADyaQAAApYAAPJqAADyagAAApcAAPJrAADyawAAApkAAPJsAADybAAAApgAAPJtAADybQAAAp4AAPJuAADybgAAAp8AAPJxAADycQAAApQAAPJyAADycgAAApUAAPJzAADycwAAAokAAPJ0AADydAAAAogAAPJ1AADydQAAAp0AAPJ2AADydgAAApwAAPJ3AADydwAAApMAAPJ4AADyeAAAApIAAPKHAADyhwAAAW8AAPKIAADyiAAAAW4AAPKLAADyiwAAAR8AAPKMAADyjAAAAR4AAPKPAADyjwAAASAAAPKQAADykAAAASEAAPKRAADykQAAAR0AAPKSAADykgAAARwAAPKbAADymwAAAYIAAPKcAADynAAAAYMAAPKdAADynQAAAYUAAPKeAADyngAAAYQAAPKfAADynwAAAnYAAPKgAADyoAAAAnUAAPKjAADyowAAAnQAAPKkAADypAAAAnMAAPKtAADyrQAAAQsAAPKuAADyrgAAAQoAAPK1AADytQAAAUgAAPK2AADytgAAAUkAAPK3AADytwAAAUsAAPK4AADyuAAAAUoAAPLDAADywwAAAuAAAPLEAADyxAAAAt8AAPLFAADyxQAAAHYAAPLGAADyxgAAAHUAAPLgAADy4AAAAwkAAPLhAADy4QAAAwkAAPLiAADy4gAAAwoAAPLjAADy4wAAAwoAAPLkAADy5AAAABsAAPLlAADy5QAAABsAAPLqAADy6gAAABwAAPLrAADy6wAAABwAAPLwAADy8AAAAgUAAPLxAADy8QAAAgQAAPL8AADy/AAAAhgAAPL9AADy/QAAAhUAAPMAAADzAAAAAhcAAPMBAADzAQAAAhYAAPMeAADzHgAAAccAAPMfAADzHwAAAccAAPMgAADzIAAAAg8AAPMhAADzIQAAACAAAPMiAADzIgAAAhIAAPMjAADzIwAAAB8AAPMkAADzJAAAAhAAAPMlAADzJQAAACEAAPMmAADzJgAAAhEAAPMnAADzJwAAAB4AAPM9AADzPQAAAfMAAPNGAADzRgAAAT0AAPNHAADzRwAAATwAAPNdAADzXQAAAf8AAPNeAADzXgAAAf4AAPNfAADzXwAAAqoAAPNgAADzYAAAArMAAPNhAADzYQAAArIAAPNiAADzYgAAArYAAPNjAADzYwAAArcAAPNkAADzZAAAArUAAPNlAADzZQAAArQAAPNmAADzZgAAAgwAAPNnAADzZwAAAB0AAPNsAADzbAAAAgMAAPNtAADzbQAAAgIAAPNuAADzbgAAALgAAPNvAADzbwAAALkAAPNyAADzcgAAAocAAPNzAADzcwAA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AGwAbwBwAGUAcgBzAC4AIABoAHQAdABwADoALwAvAGYAbwBuAHQAZQBsAGwAbwAuAGMAbwBtAAAAAgAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMLAQIBAwEEAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwEQAREBEgETARQBFQEWARcBGAEZARoBGwEcAR0BHgEfASABIQEiASMBJAElASYBJwEoASkBKgErASwBLQEuAS8BMAExATIBMwE0ATUBNgE3ATgBOQE6ATsBPAE9AT4BPwFAAUEBQgFDAUQBRQFGAUcBSAFJAUoBSwFMAU0BTgFPAVABUQFSAVMBVAFVAVYBVwFYAVkBWgFbAVwBXQFeAV8BYAFhAWIBYwFkAWUBZgFnAWgBaQFqAWsBbAFtAW4BbwFwAXEBcgFzAXQBdQF2AXcBeAF5AXoBewF8AX0BfgF/AYABgQGCAYMBhAGFAYYBhwGIAYkBigGLAYwBjQGOAY8BkAGRAZIBkwGUAZUBlgGXAZgBmQGaAZsBnAGdAZ4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9Af4B/wIAAgECAgIDAgQCBQIGAgcCCAIJAgoCCwIMAg0CDgIPAhACEQISAhMCFAIVAhYCFwIYAhkCGgIbAhwCHQIeAh8CIAIhAiICIwIkAiUCJgInAigCKQIqAisCLAItAi4CLwIwAjECMgIzAjQCNQI2AjcCOAI5AjoCOwI8Aj0CPgI/AkACQQJCAkMCRAJFAkYCRwJIAkkCSgJLAkwCTQJOAk8CUAJRAlICUwJUAlUCVgJXAlgCWQJaAlsCXAJdAl4CXwJgAmECYgJjAmQCZQJmAmcCaAJpAmoCawJsAm0CbgJvAnACcQJyAnMCdAJ1AnYCdwJ4AnkCegJ7AnwCfQJ+An8CgAKBAoICgwKEAoUChgKHAogCiQKKAosCjAKNAo4CjwKQApECkgKTApQClQKWApcCmAKZApoCmwKcAp0CngKfAqACoQKiAqMCpAKlAqYCpwKoAqkCqgKrAqwCrQKuAq8CsAKxArICswK0ArUCtgK3ArgCuQK6ArsCvAK9Ar4CvwLAAsECwgLDAsQCxQLGAscCyALJAsoCywLMAs0CzgLPAtAC0QLSAtMC1ALVAtYC1wLYAtkC2gLbAtwC3QLeAt8C4ALhAuIC4wLkAuUC5gLnAugC6QLqAusC7ALtAu4C7wLwAvEC8gLzAvQC9QL2AvcC+AL5AvoC+wL8Av0C/gL/AwADAQMCAwMDBAMFAwYDBwMIAwkDCgMLAwwDDQMOAw8DEAMRAxIDEwMUAxUDFgMXAxgDGQMaAxsDHAMdAx4DHwMgAyEDIgMjAyQDJQMmAycDKAMpAyoDKwMsAy0DLgMvAzADMQMyAzMDNAM1AzYDNwM4AzkDOgM7AzwDPQM+Az8DQANBA0IDQwNEA0UDRgNHA0gDSQNKA0sDTANNA04DTwNQA1EDUgNTA1QDVQNWA1cDWANZA1oDWwNcA10DXgNfA2ADYQNiA2MDZANlA2YDZwNoA2kDagNrA2wDbQNuA28DcANxA3IDcwN0A3UDdgN3A3gDeQN6A3sDfAN9A34DfwOAA4EDggODA4QDhQOGA4cDiAOJA4oDiwOMA40DjgOPA5ADkQOSA5MDlAOVA5YDlwOYA5kDmgObA5wDnQOeA58DoAOhA6IDowOkA6UDpgOnA6gDqQOqA6sDrAOtA64DrwOwA7EDsgOzA7QDtQO2A7cDuAO5A7oDuwO8A70DvgO/A8ADwQPCA8MDxAPFA8YDxwPIA8kDygPLA8wDzQPOA88D0APRA9ID0wPUA9UD1gPXA9gD2QPaA9sD3APdA94D3wPgA+ED4gPjA+QD5QPmA+cD6APpA+oD6wPsA+0D7gPvA/AD8QPyA/MD9AP1A/YD9wP4A/kD+gP7A/wD/QP+A/8EAAQBBAIEAwQEBAUEBgQHBAgECQQKBAsEDAASYXJyb3ctbGVmdC11cC1saW5lDWFycm93LXVwLWxpbmUTYXJyb3ctcmlnaHQtdXAtbGluZRBhcnJvdy1yaWdodC1saW5lFWFycm93LXJpZ2h0LWRvd24tbGluZQ9hcnJvdy1kb3duLWxpbmUUYXJyb3ctbGVmdC1kb3duLWxpbmUPYXJyb3ctbGVmdC1saW5lFGFycm93LXVwLWNpcmNsZS1saW5lF2Fycm93LXJpZ2h0LWNpcmNsZS1saW5lFmFycm93LWRvd24tY2lyY2xlLWxpbmUWYXJyb3ctbGVmdC1jaXJjbGUtbGluZRRhcnJvdy11cC1jaXJjbGUtZmlsbBdhcnJvdy1yaWdodC1jaXJjbGUtZmlsbBZhcnJvdy1kb3duLWNpcmNsZS1maWxsFmFycm93LWxlZnQtY2lyY2xlLWZpbGwPYXJyb3ctdXAtcy1saW5lEmFycm93LXJpZ2h0LXMtbGluZRFhcnJvdy1kb3duLXMtbGluZRFhcnJvdy1sZWZ0LXMtbGluZRFhcnJvdy1sZWZ0LXMtZmlsbBFhcnJvdy1kb3duLXMtZmlsbBJhcnJvdy1yaWdodC1zLWZpbGwPYXJyb3ctdXAtcy1maWxsEmFycm93LXVwLWRvd24tbGluZRVhcnJvdy1sZWZ0LXJpZ2h0LWxpbmUXYXJyb3ctcmlnaHQtZG91YmxlLWxpbmUUYXJyb3ctdXAtZG91YmxlLWxpbmUMc2tpcC11cC1saW5lE2V4cGFuZC11cC1kb3duLWxpbmUWZXhwYW5kLWxlZnQtcmlnaHQtbGluZRBleHBhbmQtbGVmdC1saW5lEWV4cGFuZC1yaWdodC1saW5lEmFycm93LWdvLWJhY2stbGluZRVhcnJvdy1nby1mb3J3YXJkLWxpbmULaG9tZS0yLWxpbmULaG9tZS0yLWZpbGwMc3RvcmUtMi1saW5lDHN0b3JlLTItZmlsbAxzdG9yZS0zLWZpbGwMc3RvcmUtMy1saW5lFWFuY2llbnQtcGF2aWxpb24tbGluZRVhbmNpZW50LXBhdmlsaW9uLWZpbGwJdGVudC1saW5lCXRlbnQtZmlsbA1ob3NwaXRhbC1maWxsDWhvc3BpdGFsLWxpbmURYW5jaWVudC1nYXRlLWxpbmURYW5jaWVudC1nYXRlLWZpbGwJbWFpbC1saW5lCW1haWwtZmlsbA5tYWlsLXNlbmQtbGluZQ5tYWlsLXNlbmQtZmlsbBBtYWlsLXVucmVhZC1maWxsEG1haWwtdW5yZWFkLWxpbmUNbWFpbC1hZGQtZmlsbA1tYWlsLWFkZC1saW5lDG1haWwtYWktbGluZQxtYWlsLWFpLWZpbGwKaW5ib3gtbGluZQppbmJveC1maWxsEmluYm94LWFyY2hpdmUtbGluZRJpbmJveC1hcmNoaXZlLWZpbGwUaW5ib3gtdW5hcmNoaXZlLWxpbmUUaW5ib3gtdW5hcmNoaXZlLWZpbGwKY2xvdWQtbGluZQpjbG91ZC1maWxsDmNsb3VkLW9mZi1saW5lDmNsb3VkLW9mZi1maWxsDGFyY2hpdmUtbGluZQxhcmNoaXZlLWZpbGwMcHJvZmlsZS1maWxsDHByb2ZpbGUtbGluZQphd2FyZC1saW5lCmF3YXJkLWZpbGwHYXQtbGluZQdhdC1maWxsCm1lZGFsLWZpbGwKbWVkYWwtbGluZRN2ZXJpZmllZC1iYWRnZS1saW5lE3ZlcmlmaWVkLWJhZGdlLWZpbGwOYmFyLWNoYXJ0LWxpbmUZYmFyLWNoYXJ0LWhvcml6b250YWwtbGluZRBiYXItY2hhcnQtMi1saW5lDnBpZS1jaGFydC1saW5lEWJ1YmJsZS1jaGFydC1saW5lFmJhci1jaGFydC1ncm91cGVkLWxpbmUQZG9udXQtY2hhcnQtbGluZQ9saW5lLWNoYXJ0LWxpbmUNYm9va21hcmstZmlsbA1ib29rbWFyay1saW5lDmJyaWVmY2FzZS1maWxsDmJyaWVmY2FzZS1saW5lEGRvbnV0LWNoYXJ0LWZpbGwPbGluZS1jaGFydC1maWxsDWNhbGVuZGFyLWxpbmUNY2FsZW5kYXItZmlsbA9jYWxjdWxhdG9yLWZpbGwPY2FsY3VsYXRvci1saW5lFWN1c3RvbWVyLXNlcnZpY2UtbGluZRVjdXN0b21lci1zZXJ2aWNlLWZpbGwJZmxhZy1maWxsCWZsYWctbGluZQ1mbGFnLW9mZi1saW5lDWZsYWctb2ZmLWZpbGwLZ2xvYmFsLWxpbmULZ2xvYmFsLWZpbGwKbGlua3MtZmlsbAxwcmludGVyLWxpbmUMcHJpbnRlci1maWxsCnJlcGx5LWxpbmUKcmVwbHktZmlsbA9zZW5kLXBsYW5lLWxpbmUPc2VuZC1wbGFuZS1maWxsDnNsaWRlc2hvdy1maWxsDnNsaWRlc2hvdy1saW5lC3dpbmRvdy1saW5lC3dpbmRvdy1maWxsCnN0YWNrLWZpbGwKc3RhY2stbGluZQxzZXJ2aWNlLWZpbGwMc2VydmljZS1saW5lD3JlZ2lzdGVyZWQtZmlsbA9yZWdpc3RlcmVkLWxpbmUOdHJhZGVtYXJrLWZpbGwSYWR2ZXJ0aXNlbWVudC1maWxsEmFkdmVydGlzZW1lbnQtbGluZQ5jb3B5cmlnaHQtbGluZQ5jb3B5cmlnaHQtZmlsbBhjcmVhdGl2ZS1jb21tb25zLW5kLWxpbmUYY3JlYXRpdmUtY29tbW9ucy1uZC1maWxsDGlkLWNhcmQtbGluZQxpZC1jYXJkLWZpbGwOaW5mby1jYXJkLWxpbmUOaW5mby1jYXJkLWZpbGwRcGFzcy1wZW5kaW5nLWZpbGwRcGFzcy1wZW5kaW5nLWxpbmURcGFzcy1leHBpcmVkLWZpbGwRcGFzcy1leHBpcmVkLWxpbmUPcGFzcy12YWxpZC1maWxsD3Bhc3MtdmFsaWQtbGluZQ5tZWdhcGhvbmUtZmlsbA5tZWdhcGhvbmUtbGluZRhjcmVhdGl2ZS1jb21tb25zLWJ5LWZpbGwYY3JlYXRpdmUtY29tbW9ucy1ieS1saW5lFWNyZWF0aXZlLWNvbW1vbnMtZmlsbBVjcmVhdGl2ZS1jb21tb25zLWxpbmUYY3JlYXRpdmUtY29tbW9ucy1uYy1saW5lGGNyZWF0aXZlLWNvbW1vbnMtbmMtZmlsbA1jb3B5bGVmdC1maWxsDWNvcHlsZWZ0LWxpbmUObWVzc2FnZS0yLWxpbmUObWVzc2FnZS0yLWZpbGwPY2hhdC1jaGVjay1saW5lD2NoYXQtY2hlY2stZmlsbBBjaGF0LXVucmVhZC1maWxsEGNoYXQtdW5yZWFkLWxpbmUNY2hhdC1uZXctbGluZQ1jaGF0LW5ldy1maWxsEGNoYXQtZGVsZXRlLWZpbGwQY2hhdC1kZWxldGUtbGluZQxtZXNzYWdlLWZpbGwMbWVzc2FnZS1saW5lC2NoYXQtNC1saW5lC2NoYXQtNC1maWxsEmNoYXQtc2V0dGluZ3MtZmlsbBJjaGF0LXNldHRpbmdzLWxpbmUSY2hhdC1kb3dubG9hZC1maWxsEmNoYXQtZG93bmxvYWQtbGluZRBjaGF0LXVwbG9hZC1saW5lEGNoYXQtdXBsb2FkLWZpbGwRY2hhdC1mb3J3YXJkLWZpbGwRY2hhdC1mb3J3YXJkLWxpbmUPY2hhdC1oZWFydC1saW5lD2NoYXQtaGVhcnQtZmlsbA1jaGF0LW9mZi1saW5lDWNoYXQtb2ZmLWZpbGwNZmVlZGJhY2stbGluZQ1mZWVkYmFjay1maWxsFHF1ZXN0aW9uLWFuc3dlci1saW5lFHF1ZXN0aW9uLWFuc3dlci1maWxsEnF1ZXN0aW9ubmFpcmUtbGluZRJxdWVzdGlvbm5haXJlLWZpbGwKc3BlYWstZmlsbApzcGVhay1saW5lEGNoYXQtdGhyZWFkLWxpbmUQY2hhdC10aHJlYWQtZmlsbBFjaGF0LWhpc3RvcnktZmlsbBFjaGF0LWhpc3RvcnktbGluZRFjaGF0LXByaXZhdGUtbGluZRFjaGF0LXByaXZhdGUtZmlsbBJlbW9qaS1zdGlja2VyLWxpbmUSZW1vamktc3RpY2tlci1maWxsCWVkaXQtbGluZQllZGl0LWZpbGwLbWFya3VwLWxpbmULbWFya3VwLWZpbGwNZWRpdC1ib3gtZmlsbA1lZGl0LWJveC1saW5lDWNvbXB1dGVyLWxpbmUNY29tcHV0ZXItZmlsbAd0di1saW5lB3R2LWZpbGwPc21hcnRwaG9uZS1saW5lD3NtYXJ0cGhvbmUtZmlsbAtkZXZpY2UtZmlsbAtkZXZpY2UtbGluZQpwaG9uZS1saW5lCnBob25lLWZpbGwNaW5zdGFuY2UtZmlsbA1pbnN0YW5jZS1saW5lD2RhdGFiYXNlLTItbGluZQ9kYXRhYmFzZS0yLWZpbGwRa2V5Ym9hcmQtYm94LWZpbGwRa2V5Ym9hcmQtYm94LWxpbmUOc2h1dC1kb3duLWxpbmUOc2h1dC1kb3duLWZpbGwQZmluZ2VycHJpbnQtbGluZRBiYXJjb2RlLWJveC1saW5lEGJhcmNvZGUtYm94LWZpbGwMcXItY29kZS1saW5lDHFyLWNvZGUtZmlsbAxxci1zY2FuLWZpbGwMcXItc2Nhbi1saW5lCmRyYWZ0LWxpbmUKZHJhZnQtZmlsbA9maWxlLXBhcGVyLWxpbmUPZmlsZS1wYXBlci1maWxsCWZpbGUtbGluZQlmaWxlLWZpbGwQc3RpY2t5LW5vdGUtZmlsbBBzdGlja3ktbm90ZS1saW5lDmZpbGUtZWRpdC1saW5lDmZpbGUtZWRpdC1maWxsDmZpbGUtY29weS1maWxsDmZpbGUtY29weS1saW5lCWJpbGwtZmlsbAliaWxsLWxpbmUMYXJ0aWNsZS1maWxsDGFydGljbGUtbGluZQtzdXJ2ZXktZmlsbAtzdXJ2ZXktbGluZQ5jbGlwYm9hcmQtbGluZQ5jbGlwYm9hcmQtZmlsbAluZXdzLWZpbGwJbmV3cy1saW5lDWZpbGUtemlwLWZpbGwNZmlsZS16aXAtbGluZQl0b2RvLWZpbGwJdG9kby1saW5lEGJvb2stbWFya2VkLWxpbmUQYm9vay1tYXJrZWQtZmlsbAl0YXNrLWZpbGwJdGFzay1saW5lD2RvdWJsZS1xdW90ZXMtbA9kb3VibGUtcXVvdGVzLXIPc2luZ2xlLXF1b3Rlcy1sD3NpbmdsZS1xdW90ZXMtcgpsaXN0LWNoZWNrDGxpc3Qtb3JkZXJlZApsaXN0LXJhZGlvCHNvcnQtYXNjCXNvcnQtZGVzYw1zZW5kLWJhY2t3YXJkDWJyaW5nLWZvcndhcmQLd2FsbGV0LWxpbmULd2FsbGV0LWZpbGwOYmFuay1jYXJkLWxpbmUOYmFuay1jYXJkLWZpbGwLcmVmdW5kLWxpbmULcmVmdW5kLWZpbGwJc2FmZS1maWxsCXNhZmUtbGluZQ5wcmljZS10YWctbGluZQ5wcmljZS10YWctZmlsbAt0aWNrZXQtbGluZQt0aWNrZXQtZmlsbAtjb3Vwb24tbGluZQtjb3Vwb24tZmlsbBFzaG9wcGluZy1iYWctbGluZRFzaG9wcGluZy1iYWctZmlsbBJzaG9wcGluZy1jYXJ0LWxpbmUSc2hvcHBpbmctY2FydC1maWxsCHZpcC1saW5lCHZpcC1maWxsEHZpcC1jcm93bi0yLWxpbmUQdmlwLWNyb3duLTItZmlsbBB2aXAtZGlhbW9uZC1maWxsEHZpcC1kaWFtb25kLWxpbmUNZXhjaGFuZ2UtZmlsbA1leGNoYW5nZS1saW5lC3Ryb3BoeS1maWxsC3Ryb3BoeS1saW5lCXN3YXAtbGluZQlzd2FwLWZpbGwRZXhjaGFuZ2UtY255LWxpbmUUZXhjaGFuZ2UtZG9sbGFyLWxpbmUTZXhjaGFuZ2UtZnVuZHMtbGluZRBjb3BwZXItY29pbi1saW5lEGNvcHBlci1jb2luLWZpbGwSbW9uZXktY255LWJveC1saW5lEm1vbmV5LWNueS1ib3gtZmlsbBVtb25leS1jbnktY2lyY2xlLWxpbmUVbW9uZXktY255LWNpcmNsZS1maWxsGG1vbmV5LWRvbGxhci1jaXJjbGUtbGluZRhtb25leS1kb2xsYXItY2lyY2xlLWZpbGwWaW5jcmVhc2UtZGVjcmVhc2UtZmlsbBZpbmNyZWFzZS1kZWNyZWFzZS1saW5lD3JlZC1wYWNrZXQtZmlsbA9yZWQtcGFja2V0LWxpbmUMYXVjdGlvbi1maWxsDGF1Y3Rpb24tbGluZQlnaWZ0LWxpbmUJZ2lmdC1maWxsDTI0LWhvdXJzLWxpbmUIbmZ0LWxpbmUIbmZ0LWZpbGwKaGVhcnQtZmlsbApoZWFydC1saW5lDmhlYXJ0LWFkZC1saW5lDmhlYXJ0LWFkZC1maWxsDnJlc3QtdGltZS1maWxsDnJlc3QtdGltZS1saW5lCmFwcGxlLWxpbmUKYXBwbGUtZmlsbAthbGlwYXktZmlsbAthbGlwYXktbGluZQt3ZWNoYXQtZmlsbAt3ZWNoYXQtbGluZQ93ZWNoYXQtcGF5LWxpbmUPd2VjaGF0LXBheS1maWxsEW1pbmktcHJvZ3JhbS1maWxsEW1pbmktcHJvZ3JhbS1saW5lDGFuZHJvaWQtbGluZQxhbmRyb2lkLWZpbGwMbWFwLXBpbi1saW5lDG1hcC1waW4tZmlsbBFtYXAtcGluLXRpbWUtZmlsbBFtYXAtcGluLXRpbWUtbGluZQxwdXNocGluLWZpbGwMcHVzaHBpbi1saW5lCnVucGluLWxpbmUKdW5waW4tZmlsbAxjb21wYXNzLWZpbGwMY29tcGFzcy1saW5lCmVhcnRoLWxpbmUKZWFydGgtZmlsbBBwYXJraW5nLWJveC1maWxsEHBhcmtpbmctYm94LWxpbmUPbmF2aWdhdGlvbi1maWxsD25hdmlnYXRpb24tbGluZQppbWFnZS1saW5lCmltYWdlLWZpbGwQbXVsdGktaW1hZ2UtbGluZRBtdWx0aS1pbWFnZS1maWxsDXZpZGVvLW9uLWxpbmUNdmlkZW8tb24tZmlsbBFjbGFwcGVyYm9hcmQtbGluZRFjbGFwcGVyYm9hcmQtZmlsbAlmaWxtLWZpbGwJZmlsbS1saW5lCm1vdmllLWZpbGwKbW92aWUtbGluZQlsaXZlLWxpbmUJbGl2ZS1maWxsDHZpZGljb24tbGluZQx2aWRpY29uLWZpbGwOdmlkZW8tb2ZmLWxpbmUOdmlkZW8tb2ZmLWZpbGwLY2FtZXJhLWZpbGwLY2FtZXJhLWxpbmUPY2FtZXJhLW9mZi1maWxsD2NhbWVyYS1vZmYtbGluZRBjYW1lcmEtbGVucy1maWxsEGNhbWVyYS1sZW5zLWxpbmUHbXYtbGluZQdtdi1maWxsDG11c2ljLTItZmlsbAxtdXNpYy0yLWxpbmUOaGVhZHBob25lLWZpbGwOaGVhZHBob25lLWxpbmUIbWljLWxpbmUIbWljLWZpbGwMbWljLW9mZi1saW5lDG1pYy1vZmYtZmlsbBB2b2x1bWUtZG93bi1maWxsEHZvbHVtZS1kb3duLWxpbmUQdm9sdW1lLW11dGUtbGluZRB2b2x1bWUtbXV0ZS1maWxsE25vdGlmaWNhdGlvbi00LWxpbmUTbm90aWZpY2F0aW9uLTQtZmlsbBVub3RpZmljYXRpb24tb2ZmLWZpbGwVbm90aWZpY2F0aW9uLW9mZi1saW5lEHBsYXktY2lyY2xlLWxpbmUQcGxheS1jaXJjbGUtZmlsbBFwYXVzZS1jaXJjbGUtbGluZRFwYXVzZS1jaXJjbGUtZmlsbBJyZWNvcmQtY2lyY2xlLWxpbmUScmVjb3JkLWNpcmNsZS1maWxsEHN0b3AtY2lyY2xlLWZpbGwQc3RvcC1jaXJjbGUtbGluZQ9mdWxsc2NyZWVuLWxpbmUUZnVsbHNjcmVlbi1leGl0LWxpbmUQZXF1YWxpemVyLTItbGluZRBlcXVhbGl6ZXItMi1maWxsCWFwcHMtbGluZQlhcHBzLWZpbGwNZnVuY3Rpb24tbGluZQ1mdW5jdGlvbi1maWxsGWRhc2hib2FyZC1ob3Jpem9udGFsLWxpbmUZZGFzaGJvYXJkLWhvcml6b250YWwtZmlsbAltZW51LWxpbmUNbWVudS1hZGQtbGluZQlzdGFyLWxpbmUJc3Rhci1maWxsDXN0YXItb2ZmLWxpbmUNc3Rhci1vZmYtZmlsbAltb3JlLWxpbmUJbW9yZS1maWxsC21vcmUtMi1saW5lC21vcmUtMi1maWxsDXNldHRpbmdzLWZpbGwNc2V0dGluZ3MtbGluZQtmb3JiaWQtZmlsbAtmb3JiaWQtbGluZQ9wcm9oaWJpdGVkLWxpbmUPcHJvaGliaXRlZC1maWxsEmluZm9ybWF0aW9uLTItbGluZRJpbmZvcm1hdGlvbi0yLWZpbGwSZXJyb3Itd2FybmluZy1maWxsEmVycm9yLXdhcm5pbmctbGluZQ1xdWVzdGlvbi1maWxsDXF1ZXN0aW9uLWxpbmUaY2hlY2tib3gtYmxhbmstY2lyY2xlLWxpbmUaY2hlY2tib3gtYmxhbmstY2lyY2xlLWZpbGwUY2hlY2tib3gtY2lyY2xlLWZpbGwUY2hlY2tib3gtY2lyY2xlLWxpbmUTY2hlY2tib3gtYmxhbmstbGluZRNjaGVja2JveC1ibGFuay1maWxsDWNoZWNrYm94LWxpbmUNY2hlY2tib3gtZmlsbA9hZGQtY2lyY2xlLWxpbmUPYWRkLWNpcmNsZS1maWxsGWluZGV0ZXJtaW5hdGUtY2lyY2xlLWZpbGwZaW5kZXRlcm1pbmF0ZS1jaXJjbGUtbGluZRFjbG9zZS1jaXJjbGUtbGluZRFjbG9zZS1jaXJjbGUtZmlsbBFyYWRpby1idXR0b24tbGluZRFyYWRpby1idXR0b24tZmlsbApjaGVjay1saW5lCmNsb3NlLWxpbmUIYWRkLWxpbmUNc3VidHJhY3QtbGluZQtkaXZpZGUtbGluZQplcXVhbC1saW5lC3VwbG9hZC1saW5lDWRvd25sb2FkLWxpbmUTdXBsb2FkLWNsb3VkLTItbGluZRN1cGxvYWQtY2xvdWQtMi1maWxsFWRvd25sb2FkLWNsb3VkLTItbGluZRVkb3dubG9hZC1jbG91ZC0yLWZpbGwObG9naW4tYm94LWxpbmUObG9naW4tYm94LWZpbGwRc2hpZWxkLWNyb3NzLWxpbmURc2hpZWxkLWNyb3NzLWZpbGwRc2hpZWxkLWNoZWNrLWZpbGwRc2hpZWxkLWNoZWNrLWxpbmUPZGVsZXRlLWJpbi1maWxsD2RlbGV0ZS1iaW4tbGluZQlsb2NrLWxpbmUJbG9jay1maWxsEGxvY2stdW5sb2NrLWxpbmUQbG9jay11bmxvY2stZmlsbBJsb2NrLXBhc3N3b3JkLWxpbmUSbG9jay1wYXNzd29yZC1maWxsCGV5ZS1maWxsCGV5ZS1saW5lDGV5ZS1vZmYtbGluZQxleWUtb2ZmLWZpbGwLc2VhcmNoLWxpbmULc2VhcmNoLWZpbGwKc2hhcmUtbGluZQpzaGFyZS1maWxsDnNoYXJlLWJveC1saW5lDnNoYXJlLWJveC1maWxsEXNoYXJlLWNpcmNsZS1saW5lEXNoYXJlLWNpcmNsZS1maWxsCXRpbWUtZmlsbAl0aW1lLWxpbmUNdGh1bWItdXAtbGluZQ10aHVtYi11cC1maWxsF25vdGlmaWNhdGlvbi1iYWRnZS1maWxsF25vdGlmaWNhdGlvbi1iYWRnZS1saW5lC3RvZ2dsZS1saW5lC3RvZ2dsZS1maWxsC2ZpbHRlci1saW5lC2ZpbHRlci1maWxsDGhpc3RvcnktbGluZQ5sb29wLWxlZnQtbGluZQ1sb2FkZXItMi1saW5lDWxvYWRlci00LWxpbmUQcmVzZXQtcmlnaHQtbGluZQtsb2FkZXItZmlsbAt1c2VyLTMtbGluZQt1c2VyLTMtZmlsbAhzdW4tZmlsbAhzdW4tbGluZQltb29uLWZpbGwJbW9vbi1saW5lDHNoaW5pbmctbGluZQxzaGluaW5nLWZpbGwJZmlyZS1maWxsCWZpcmUtbGluZQ5zcGFya2xpbmctbGluZQ5zcGFya2xpbmctZmlsbApib3gtMS1saW5lCmJveC0xLWZpbGwQYWNjb3VudC1ib3gtbGluZRBhY2NvdW50LWJveC1maWxsE2FjY291bnQtY2lyY2xlLWZpbGwTYWNjb3VudC1jaXJjbGUtbGluZRRhY2NvdW50LXBpbi1ib3gtZmlsbBRhY2NvdW50LXBpbi1ib3gtbGluZQxza2lwLXVwLWZpbGwVYXJyb3ctbGVmdC1yaWdodC1maWxsEmFycm93LXVwLWRvd24tZmlsbBBleHBhbmQtbGVmdC1maWxsEWV4cGFuZC1yaWdodC1maWxsE2V4cGFuZC11cC1kb3duLWZpbGwWZXhwYW5kLWxlZnQtcmlnaHQtZmlsbBJhcnJvdy1nby1iYWNrLWZpbGwVYXJyb3ctZ28tZm9yd2FyZC1maWxsEmNvbnRyYWN0LWxlZnQtbGluZRNjb250cmFjdC1yaWdodC1saW5lE2NvbnRyYWN0LXJpZ2h0LWZpbGwSY29udHJhY3QtbGVmdC1maWxsDmRyYWctbW92ZS1saW5lDmRyYWctbW92ZS1maWxsCWhvbWUtbGluZQlob21lLWZpbGwObWFpbC1vcGVuLWxpbmUObWFpbC1vcGVuLWZpbGwPYXR0YWNobWVudC1saW5lD2F0dGFjaG1lbnQtZmlsbA5iYXItY2hhcnQtZmlsbBliYXItY2hhcnQtaG9yaXpvbnRhbC1maWxsEGJhci1jaGFydC0yLWZpbGwRYnViYmxlLWNoYXJ0LWZpbGwOcGllLWNoYXJ0LWZpbGwWY2FsZW5kYXItc2NoZWR1bGUtbGluZRZjYWxlbmRhci1zY2hlZHVsZS1maWxsEmNhbGVuZGFyLXRvZG8tbGluZRJjYWxlbmRhci10b2RvLWZpbGwTY2FsZW5kYXItZXZlbnQtZmlsbBNjYWxlbmRhci1ldmVudC1saW5lE2NhbGVuZGFyLWNsb3NlLWZpbGwTY2FsZW5kYXItY2hlY2stZmlsbBNjYWxlbmRhci1jaGVjay1saW5lE2NhbGVuZGFyLWNsb3NlLWxpbmUObWVzc2FnZS0zLWxpbmUObWVzc2FnZS0zLWZpbGwLY2hhdC0zLWZpbGwLY2hhdC0zLWxpbmULY2hhdC0xLWZpbGwLY2hhdC0xLWxpbmULY2hhdC0yLWZpbGwLY2hhdC0yLWxpbmUJY3JvcC1saW5lCWNyb3AtZmlsbAxwYWxldHRlLWxpbmUMcGFsZXR0ZS1maWxsEmFudGljbG9ja3dpc2UtbGluZRJhbnRpY2xvY2t3aXNlLWZpbGwOY2xvY2t3aXNlLWxpbmUOY2xvY2t3aXNlLWZpbGwRY29kZS1zLXNsYXNoLWZpbGwLcHV6emxlLWZpbGwLcHV6emxlLWxpbmULc2VydmVyLWZpbGwLc2VydmVyLWxpbmUOcXItc2Nhbi0yLWZpbGwOcXItc2Nhbi0yLWxpbmUJc2Nhbi1saW5lCXNjYW4tZmlsbA9waG9uZS1maW5kLWZpbGwPcGhvbmUtZmluZC1saW5lDGJhcmNvZGUtbGluZQxiYXJjb2RlLWZpbGwOZmlsZS1saXN0LWZpbGwOZmlsZS1saXN0LWxpbmUOZmlsZS10ZXh0LWxpbmUOZmlsZS10ZXh0LWZpbGwJYm9vay1maWxsCWJvb2stbGluZQR0ZXh0C2ZvbnQtZmFtaWx5BGxpbmsJdHJhbnNsYXRlE2NvcHBlci1kaWFtb25kLWZpbGwTY29wcGVyLWRpYW1vbmQtbGluZQxkaXNsaWtlLWZpbGwMZGlzbGlrZS1saW5lDGhlYXJ0LTMtZmlsbAxoZWFydC0zLWxpbmULaGVhcnRzLWZpbGwLaGVhcnRzLWxpbmUIbWFwLWxpbmUIbWFwLWZpbGwRaW1hZ2UtY2lyY2xlLWZpbGwRaW1hZ2UtY2lyY2xlLWxpbmUPaW1hZ2UtZWRpdC1maWxsD2ltYWdlLWVkaXQtbGluZQ5pbWFnZS1hZGQtbGluZQ5pbWFnZS1hZGQtZmlsbA5sYW5kc2NhcGUtbGluZQ5sYW5kc2NhcGUtZmlsbBFjaGVjay1kb3VibGUtbGluZQ1zdWJ0cmFjdC1maWxsEmxvZ291dC1jaXJjbGUtbGluZRJsb2dvdXQtY2lyY2xlLWZpbGwLc2hpZWxkLWZpbGwLc2hpZWxkLWxpbmUKdGltZXItbGluZQp0aW1lci1maWxsEmRlbGV0ZS1iYWNrLTItbGluZRJkZWxldGUtYmFjay0yLWZpbGwTdm9sdW1lLXZpYnJhdGUtbGluZRN2b2x1bWUtdmlicmF0ZS1maWxsF3ZvbHVtZS1vZmYtdmlicmF0ZS1saW5lF3ZvbHVtZS1vZmYtdmlicmF0ZS1maWxsCnRydWNrLWxpbmUKdHJ1Y2stZmlsbBNmbGlnaHQtdGFrZW9mZi1saW5lDXJvYWQtbWFwLWxpbmUNcm9hZC1tYXAtZmlsbA5wdXNocGluLTItbGluZQ5wdXNocGluLTItZmlsbA5tYXAtcGluLTItbGluZQ5tYXAtcGluLTItZmlsbBVjb21wYXNzLWRpc2NvdmVyLWxpbmUVY29tcGFzcy1kaXNjb3Zlci1maWxsDXNpZ25wb3N0LWZpbGwNc2lnbnBvc3QtbGluZQdxcS1saW5lB3FxLWZpbGwLdGlrdG9rLWxpbmULdGlrdG9rLWZpbGwPdXNlci1zbWlsZS1saW5lD3VzZXItc21pbGUtZmlsbAl1c2VyLWxpbmUJdXNlci1maWxsDXVzZXItYWRkLWZpbGwNdXNlci1hZGQtbGluZQ91c2VyLW1pbnVzLWxpbmUPdXNlci1taW51cy1maWxsEHVzZXItZm9sbG93LWZpbGwQdXNlci1mb2xsb3ctbGluZRJ1c2VyLXVuZm9sbG93LWxpbmUSdXNlci11bmZvbGxvdy1maWxsEHVzZXItc2hhcmVkLWZpbGwQdXNlci1zaGFyZWQtbGluZRJ1c2VyLXJlY2VpdmVkLWZpbGwSdXNlci1yZWNlaXZlZC1saW5lEHVzZXItc2VhcmNoLWxpbmUQdXNlci1zZWFyY2gtZmlsbBJ1c2VyLWxvY2F0aW9uLWxpbmUSdXNlci1sb2NhdGlvbi1maWxsDnVzZXItc3Rhci1saW5lDnVzZXItc3Rhci1maWxsEnVzZXItc2V0dGluZ3MtZmlsbBJ1c2VyLXNldHRpbmdzLWxpbmUPdXNlci1oZWFydC1saW5lD3VzZXItaGVhcnQtZmlsbBB1c2VyLWZvcmJpZC1saW5lEHVzZXItZm9yYmlkLWZpbGwKZ3JvdXAtZmlsbApncm91cC1saW5lC3VzZXItMi1maWxsC3VzZXItMi1saW5lEHNoaWVsZC11c2VyLWxpbmUQc2hpZWxkLXVzZXItZmlsbAlza2V0Y2hpbmcMYWxpZ24tYm90dG9tDHJlc3RhcnQtbGluZQxyZXN0YXJ0LWZpbGwMcmVmcmVzaC1saW5lDHJlZnJlc2gtZmlsbA9yZXNldC1sZWZ0LWxpbmUPcmVzZXQtbGVmdC1maWxsDnNraXAtZG93bi1saW5lDnNraXAtZG93bi1maWxsD3NraXAtcmlnaHQtbGluZQ9za2lwLXJpZ2h0LWZpbGwOc2tpcC1sZWZ0LWZpbGwOc2tpcC1sZWZ0LWxpbmUMdGV4dC1zbmlwcGV0EWlucHV0LW1ldGhvZC1saW5lEWlucHV0LW1ldGhvZC1maWxsCWZvbnQtc2l6ZQtmb250LXNpemUtMgpmb250LWNvbG9yCW5vZGUtdHJlZRBwcmljZS10YWctMy1saW5lEHByaWNlLXRhZy0zLWZpbGwLaW5wdXQtZmllbGQNdGltZWxpbmUtdmlldw9wcm9ncmVzcy0yLWxpbmUPcHJvZ3Jlc3MtMi1maWxsCnQtYm94LWxpbmUKdC1ib3gtZmlsbAtlZGl0LTItZmlsbAtlZGl0LTItbGluZQ1sYXlvdXQtMi1saW5lDWxheW91dC0yLWZpbGwSbGF5b3V0LWNvbHVtbi1maWxsEmxheW91dC1jb2x1bW4tbGluZQptb3VzZS1saW5lCm1vdXNlLWZpbGwQZmlsZS11cGxvYWQtbGluZRBmaWxlLXVwbG9hZC1maWxsDnBhZ2Utc2VwYXJhdG9yDWNhcm91c2VsLXZpZXcJbGlzdC12aWV3CnRleHQtYmxvY2sMcGVyY2VudC1saW5lDHBlcmNlbnQtZmlsbAt1cGxvYWQtZmlsbAx0LXNoaXJ0LWxpbmUMdC1zaGlydC1maWxsCG51bWJlci0xFmNoZWNrYm94LW11bHRpcGxlLWxpbmUWY2hlY2tib3gtbXVsdGlwbGUtZmlsbBZjb2xsYXBzZS12ZXJ0aWNhbC1saW5lCWFsaWduLXRvcA13aW5kb3ctMi1saW5lDXdpbmRvdy0yLWZpbGwIc2VvLWxpbmUIc2VvLWZpbGwLc2hhZG93LWxpbmULc2hhZG93LWZpbGwNcHV6emxlLTItbGluZQ1wdXp6bGUtMi1maWxsDW1hcmtkb3duLWxpbmUNbWFya2Rvd24tZmlsbAxzdGFja2VkLXZpZXcNZHJvcGRvd24tbGlzdAx0aW1lci0yLWxpbmUMdGltZXItMi1maWxsC3BhcmVudC1saW5lC3BhcmVudC1maWxsEWZ1bmN0aW9uLWFkZC1saW5lEWZ1bmN0aW9uLWFkZC1maWxsEWFycm93LXVwLWJveC1saW5lEWFycm93LXVwLWJveC1maWxsEmxheW91dC1ib3R0b20tZmlsbBFsYXlvdXQtcmlnaHQtZmlsbBFsYXlvdXQtcmlnaHQtbGluZQ9sYXlvdXQtdG9wLWZpbGwPbGF5b3V0LXRvcC1saW5lEGxheW91dC1sZWZ0LWxpbmUQbGF5b3V0LWxlZnQtZmlsbBFsYXlvdXQtdG9wLTItbGluZRFsYXlvdXQtdG9wLTItZmlsbBNsYXlvdXQtcmlnaHQtMi1saW5lE2xheW91dC1yaWdodC0yLWZpbGwUbGF5b3V0LWJvdHRvbS0yLWxpbmUUbGF5b3V0LWJvdHRvbS0yLWZpbGwSbGF5b3V0LWxlZnQtMi1saW5lEmxheW91dC1sZWZ0LTItZmlsbA9sYXlvdXQtcm93LWZpbGwPbGF5b3V0LXJvdy1saW5lCnRhYmxlLWZpbGwKdGFibGUtbGluZRJsYXlvdXQtYm90dG9tLWxpbmUXcGljdHVyZS1pbi1waWN0dXJlLWxpbmUXcGljdHVyZS1pbi1waWN0dXJlLWZpbGwWYXJyb3ctZG93bi1kb3VibGUtbGluZRZhcnJvdy1sZWZ0LWRvdWJsZS1maWxsAAA=") format("woff");
+}
diff --git a/cool-unix/icons/remixicon/index.ts b/cool-unix/icons/remixicon/index.ts
new file mode 100644
index 0000000..d893a10
--- /dev/null
+++ b/cool-unix/icons/remixicon/index.ts
@@ -0,0 +1,798 @@
+export const remixicon = {
+ "arrow-left-up-line": "ea66",
+ "arrow-up-line": "ea76",
+ "arrow-right-up-line": "ea70",
+ "arrow-right-line": "ea6c",
+ "arrow-right-down-line": "ea6a",
+ "arrow-down-line": "ea4c",
+ "arrow-left-down-line": "ea5e",
+ "arrow-left-line": "ea60",
+ "arrow-up-circle-line": "ea72",
+ "arrow-right-circle-line": "ea68",
+ "arrow-down-circle-line": "ea4a",
+ "arrow-left-circle-line": "ea5c",
+ "arrow-up-circle-fill": "ea71",
+ "arrow-right-circle-fill": "ea67",
+ "arrow-down-circle-fill": "ea49",
+ "arrow-left-circle-fill": "ea5b",
+ "arrow-up-s-line": "ea78",
+ "arrow-right-s-line": "ea6e",
+ "arrow-down-s-line": "ea4e",
+ "arrow-left-s-line": "ea64",
+ "arrow-left-s-fill": "ea63",
+ "arrow-down-s-fill": "ea4d",
+ "arrow-right-s-fill": "ea6d",
+ "arrow-up-s-fill": "ea77",
+ "arrow-up-down-line": "ea74",
+ "arrow-left-right-line": "ea62",
+ "arrow-right-double-line": "f2e5",
+ "arrow-up-double-line": "f2eb",
+ "skip-up-line": "f367",
+ "expand-up-down-line": "f327",
+ "expand-left-right-line": "f323",
+ "expand-left-line": "f321",
+ "expand-right-line": "f325",
+ "arrow-go-back-line": "ea58",
+ "arrow-go-forward-line": "ea5a",
+ "home-2-line": "ee19",
+ "home-2-fill": "ee18",
+ "store-2-line": "f1a5",
+ "store-2-fill": "f1a4",
+ "store-3-fill": "f1a6",
+ "store-3-line": "f1a7",
+ "ancient-pavilion-line": "ea34",
+ "ancient-pavilion-fill": "ea33",
+ "tent-line": "f3df",
+ "tent-fill": "f3de",
+ "hospital-fill": "ee36",
+ "hospital-line": "ee37",
+ "ancient-gate-line": "ea32",
+ "ancient-gate-fill": "ea31",
+ "mail-line": "eef6",
+ "mail-fill": "eef3",
+ "mail-send-line": "eefc",
+ "mail-send-fill": "eefb",
+ "mail-unread-fill": "ef01",
+ "mail-unread-line": "ef02",
+ "mail-add-fill": "eeeb",
+ "mail-add-line": "eeec",
+ "mail-ai-line": "f585",
+ "mail-ai-fill": "f584",
+ "inbox-line": "ee4f",
+ "inbox-fill": "ee4e",
+ "inbox-archive-line": "ee4d",
+ "inbox-archive-fill": "ee4c",
+ "inbox-unarchive-line": "ee51",
+ "inbox-unarchive-fill": "ee50",
+ "cloud-line": "eb9d",
+ "cloud-fill": "eb9c",
+ "cloud-off-line": "eb9f",
+ "cloud-off-fill": "eb9e",
+ "archive-line": "ea48",
+ "archive-fill": "ea47",
+ "profile-fill": "f02c",
+ "profile-line": "f02d",
+ "award-line": "ea8a",
+ "award-fill": "ea89",
+ "at-line": "ea83",
+ "at-fill": "ea82",
+ "medal-fill": "ef27",
+ "medal-line": "ef28",
+ "verified-badge-line": "f3e9",
+ "verified-badge-fill": "f3e8",
+ "bar-chart-line": "ea9e",
+ "bar-chart-horizontal-line": "ea9d",
+ "bar-chart-2-line": "ea96",
+ "pie-chart-line": "effa",
+ "bubble-chart-line": "eb03",
+ "bar-chart-grouped-line": "ea9b",
+ "donut-chart-line": "ec42",
+ "line-chart-line": "eeab",
+ "bookmark-fill": "eae4",
+ "bookmark-line": "eae5",
+ "briefcase-fill": "eaf4",
+ "briefcase-line": "eaf5",
+ "donut-chart-fill": "ec41",
+ "line-chart-fill": "eeaa",
+ "calendar-line": "eb27",
+ "calendar-fill": "eb26",
+ "calculator-fill": "eb1e",
+ "calculator-line": "eb1f",
+ "customer-service-line": "ec0e",
+ "customer-service-fill": "ec0d",
+ "flag-fill": "ed3a",
+ "flag-line": "ed3b",
+ "flag-off-line": "f577",
+ "flag-off-fill": "f576",
+ "global-line": "edcf",
+ "global-fill": "edce",
+ "links-fill": "eeb7",
+ "links-line": "eeb8",
+ "printer-line": "f029",
+ "printer-fill": "f028",
+ "reply-line": "f07a",
+ "reply-fill": "f079",
+ "send-plane-line": "f0da",
+ "send-plane-fill": "f0d9",
+ "slideshow-fill": "f157",
+ "slideshow-line": "f158",
+ "window-line": "f2c6",
+ "window-fill": "f2c5",
+ "stack-fill": "f180",
+ "stack-line": "f181",
+ "service-fill": "f0e1",
+ "service-line": "f0e2",
+ "registered-fill": "f069",
+ "registered-line": "f06a",
+ "trademark-fill": "f21e",
+ "trademark-line": "f21f",
+ "advertisement-fill": "ea16",
+ "advertisement-line": "ea17",
+ "copyright-line": "ebe2",
+ "copyright-fill": "ebe1",
+ "creative-commons-nd-line": "ebf8",
+ "creative-commons-nd-fill": "ebf7",
+ "id-card-line": "f4e9",
+ "id-card-fill": "f4e8",
+ "info-card-line": "f57f",
+ "info-card-fill": "f57e",
+ "pass-pending-fill": "f388",
+ "pass-pending-line": "f389",
+ "pass-expired-fill": "f386",
+ "pass-expired-line": "f387",
+ "pass-valid-fill": "f38a",
+ "pass-valid-line": "f38b",
+ "megaphone-fill": "f384",
+ "megaphone-line": "f385",
+ "creative-commons-by-fill": "ebf1",
+ "creative-commons-by-line": "ebf2",
+ "creative-commons-fill": "ebf3",
+ "creative-commons-line": "ebf4",
+ "creative-commons-nc-line": "ebf6",
+ "creative-commons-nc-fill": "ebf5",
+ "copyleft-fill": "ebdf",
+ "copyleft-line": "ebe0",
+ "message-2-line": "ef44",
+ "message-2-fill": "ef43",
+ "chat-check-line": "eb55",
+ "chat-check-fill": "eb54",
+ "chat-unread-fill": "f529",
+ "chat-unread-line": "f52a",
+ "chat-new-line": "eb63",
+ "chat-new-fill": "eb62",
+ "chat-delete-fill": "eb56",
+ "chat-delete-line": "eb57",
+ "message-fill": "ef47",
+ "message-line": "ef48",
+ "chat-4-line": "eb53",
+ "chat-4-fill": "eb52",
+ "chat-settings-fill": "eb6c",
+ "chat-settings-line": "eb6d",
+ "chat-download-fill": "eb58",
+ "chat-download-line": "eb59",
+ "chat-upload-line": "eb75",
+ "chat-upload-fill": "eb74",
+ "chat-forward-fill": "eb5c",
+ "chat-forward-line": "eb5d",
+ "chat-heart-line": "eb5f",
+ "chat-heart-fill": "eb5e",
+ "chat-off-line": "eb65",
+ "chat-off-fill": "eb64",
+ "feedback-line": "ecc1",
+ "feedback-fill": "ecc0",
+ "question-answer-line": "f043",
+ "question-answer-fill": "f042",
+ "questionnaire-line": "f048",
+ "questionnaire-fill": "f047",
+ "speak-fill": "f36e",
+ "speak-line": "f36f",
+ "chat-thread-line": "f473",
+ "chat-thread-fill": "f472",
+ "chat-history-fill": "eb60",
+ "chat-history-line": "eb61",
+ "chat-private-line": "eb69",
+ "chat-private-fill": "eb68",
+ "emoji-sticker-line": "f37f",
+ "emoji-sticker-fill": "f37e",
+ "edit-line": "ec86",
+ "edit-fill": "ec85",
+ "markup-line": "ef20",
+ "markup-fill": "ef1f",
+ "edit-box-fill": "ec81",
+ "edit-box-line": "ec82",
+ "computer-line": "ebca",
+ "computer-fill": "ebc9",
+ "tv-line": "f237",
+ "tv-fill": "f236",
+ "smartphone-line": "f15a",
+ "smartphone-fill": "f159",
+ "device-fill": "ec2d",
+ "device-line": "ec2e",
+ "phone-line": "efec",
+ "phone-fill": "efe9",
+ "instance-fill": "f382",
+ "instance-line": "f383",
+ "database-2-line": "ec16",
+ "database-2-fill": "ec15",
+ "keyboard-box-fill": "ee72",
+ "keyboard-box-line": "ee73",
+ "shut-down-line": "f126",
+ "shut-down-fill": "f125",
+ "fingerprint-line": "ed31",
+ "fingerprint-fill": "ed30",
+ "barcode-box-line": "eaa0",
+ "barcode-box-fill": "ea9f",
+ "qr-code-line": "f03d",
+ "qr-code-fill": "f03c",
+ "qr-scan-fill": "f040",
+ "qr-scan-line": "f041",
+ "draft-line": "ec5c",
+ "draft-fill": "ec5b",
+ "file-paper-line": "ecfb",
+ "file-paper-fill": "ecfa",
+ "file-line": "eceb",
+ "file-fill": "ece0",
+ "sticky-note-fill": "f19a",
+ "sticky-note-line": "f19b",
+ "file-edit-line": "ecdb",
+ "file-edit-fill": "ecda",
+ "file-copy-fill": "ecd4",
+ "file-copy-line": "ecd5",
+ "bill-fill": "eac1",
+ "bill-line": "eac2",
+ "article-fill": "ea7d",
+ "article-line": "ea7e",
+ "survey-fill": "f1c6",
+ "survey-line": "f1c7",
+ "clipboard-line": "eb91",
+ "clipboard-fill": "eb90",
+ "news-fill": "f417",
+ "news-line": "f418",
+ "file-zip-fill": "ed1e",
+ "file-zip-line": "ed1f",
+ "todo-fill": "f216",
+ "todo-line": "f217",
+ "book-marked-line": "ead9",
+ "book-marked-fill": "ead8",
+ "task-fill": "f1e7",
+ "task-line": "f1e8",
+ "double-quotes-l": "ec51",
+ "double-quotes-r": "ec52",
+ "single-quotes-l": "f13b",
+ "single-quotes-r": "f13c",
+ "list-check": "eeba",
+ "list-ordered": "eebb",
+ "list-radio": "f39b",
+ "sort-asc": "f15f",
+ "sort-desc": "f160",
+ "send-backward": "f0d6",
+ "bring-forward": "eaf6",
+ "wallet-line": "f2ae",
+ "wallet-fill": "f2ad",
+ "bank-card-line": "ea92",
+ "bank-card-fill": "ea91",
+ "refund-line": "f068",
+ "refund-fill": "f067",
+ "safe-fill": "f0aa",
+ "safe-line": "f0ab",
+ "price-tag-line": "f025",
+ "price-tag-fill": "f024",
+ "ticket-line": "f20d",
+ "ticket-fill": "f20c",
+ "coupon-line": "ebee",
+ "coupon-fill": "ebed",
+ "shopping-bag-line": "f118",
+ "shopping-bag-fill": "f117",
+ "shopping-cart-line": "f120",
+ "shopping-cart-fill": "f11f",
+ "vip-line": "f292",
+ "vip-fill": "f291",
+ "vip-crown-2-line": "f28c",
+ "vip-crown-2-fill": "f28b",
+ "vip-diamond-fill": "f28f",
+ "vip-diamond-line": "f290",
+ "exchange-fill": "ecaa",
+ "exchange-line": "ecad",
+ "trophy-fill": "f22e",
+ "trophy-line": "f22f",
+ "swap-line": "f1cb",
+ "swap-fill": "f1ca",
+ "exchange-cny-line": "eca7",
+ "exchange-dollar-line": "eca9",
+ "exchange-funds-line": "ecac",
+ "copper-coin-line": "ebdc",
+ "copper-coin-fill": "ebdb",
+ "money-cny-box-line": "ef5f",
+ "money-cny-box-fill": "ef5e",
+ "money-cny-circle-line": "ef61",
+ "money-cny-circle-fill": "ef60",
+ "money-dollar-circle-line": "ef65",
+ "money-dollar-circle-fill": "ef64",
+ "increase-decrease-fill": "ee52",
+ "increase-decrease-line": "ee53",
+ "red-packet-fill": "f05f",
+ "red-packet-line": "f060",
+ "auction-fill": "ea87",
+ "auction-line": "ea88",
+ "gift-line": "edbb",
+ "gift-fill": "edba",
+ "24-hours-line": "ea02",
+ "nft-line": "f347",
+ "nft-fill": "f346",
+ "heart-fill": "ee0e",
+ "heart-line": "ee0f",
+ "heart-add-line": "ee0d",
+ "heart-add-fill": "ee0c",
+ "rest-time-fill": "f07d",
+ "rest-time-line": "f07e",
+ "apple-line": "ea40",
+ "apple-fill": "ea3f",
+ "alipay-fill": "ea2b",
+ "alipay-line": "ea2c",
+ "wechat-fill": "f2b5",
+ "wechat-line": "f2b6",
+ "wechat-pay-line": "f2b8",
+ "wechat-pay-fill": "f2b7",
+ "mini-program-fill": "ef5a",
+ "mini-program-line": "ef5b",
+ "android-line": "ea36",
+ "android-fill": "ea35",
+ "map-pin-line": "ef14",
+ "map-pin-fill": "ef13",
+ "map-pin-time-fill": "ef17",
+ "map-pin-time-line": "ef18",
+ "pushpin-fill": "f038",
+ "pushpin-line": "f039",
+ "unpin-line": "f377",
+ "unpin-fill": "f376",
+ "compass-fill": "ebc3",
+ "compass-line": "ebc4",
+ "earth-line": "ec7a",
+ "earth-fill": "ec79",
+ "parking-box-fill": "efcd",
+ "parking-box-line": "efce",
+ "navigation-fill": "ef88",
+ "navigation-line": "ef89",
+ "image-line": "ee4b",
+ "image-fill": "ee4a",
+ "multi-image-line": "f5ee",
+ "multi-image-fill": "f5ed",
+ "video-on-line": "f51e",
+ "video-on-fill": "f51d",
+ "clapperboard-line": "eb8f",
+ "clapperboard-fill": "eb8e",
+ "film-fill": "ed20",
+ "film-line": "ed21",
+ "movie-fill": "ef80",
+ "movie-line": "ef81",
+ "live-line": "eec0",
+ "live-fill": "eebf",
+ "vidicon-line": "f288",
+ "vidicon-fill": "f287",
+ "video-off-line": "f51c",
+ "video-off-fill": "f51b",
+ "camera-fill": "eb2e",
+ "camera-line": "eb31",
+ "camera-off-fill": "eb32",
+ "camera-off-line": "eb33",
+ "camera-lens-fill": "eb2f",
+ "camera-lens-line": "eb30",
+ "mv-line": "ef87",
+ "mv-fill": "ef86",
+ "music-2-fill": "ef82",
+ "music-2-line": "ef83",
+ "headphone-fill": "ee04",
+ "headphone-line": "ee05",
+ "mic-line": "ef50",
+ "mic-fill": "ef4f",
+ "mic-off-line": "ef52",
+ "mic-off-fill": "ef51",
+ "volume-down-fill": "f29b",
+ "volume-down-line": "f29c",
+ "volume-mute-line": "f29e",
+ "volume-mute-fill": "f29d",
+ "notification-4-line": "ef96",
+ "notification-4-fill": "ef95",
+ "notification-off-fill": "ef9b",
+ "notification-off-line": "ef9c",
+ "play-circle-line": "f009",
+ "play-circle-fill": "f008",
+ "pause-circle-line": "efd6",
+ "pause-circle-fill": "efd5",
+ "record-circle-line": "f05a",
+ "record-circle-fill": "f059",
+ "stop-circle-fill": "f19e",
+ "stop-circle-line": "f19f",
+ "fullscreen-line": "ed9c",
+ "fullscreen-exit-line": "ed9a",
+ "equalizer-2-line": "f405",
+ "equalizer-2-fill": "f404",
+ "apps-line": "ea44",
+ "apps-fill": "ea43",
+ "function-line": "ed9e",
+ "function-fill": "ed9d",
+ "dashboard-horizontal-line": "f4ce",
+ "dashboard-horizontal-fill": "f4cd",
+ "menu-line": "ef3e",
+ "menu-add-line": "ef3a",
+ "star-line": "f18b",
+ "star-fill": "f186",
+ "star-off-line": "f59b",
+ "star-off-fill": "f59a",
+ "more-line": "ef79",
+ "more-fill": "ef78",
+ "more-2-line": "ef77",
+ "more-2-fill": "ef76",
+ "settings-fill": "f0ed",
+ "settings-line": "f0ee",
+ "forbid-fill": "ed94",
+ "forbid-line": "ed95",
+ "prohibited-line": "f3a1",
+ "prohibited-fill": "f3a0",
+ "information-2-line": "f449",
+ "information-2-fill": "f448",
+ "error-warning-fill": "eca0",
+ "error-warning-line": "eca1",
+ "question-fill": "f044",
+ "question-line": "f045",
+ "checkbox-blank-circle-line": "eb7d",
+ "checkbox-blank-circle-fill": "eb7c",
+ "checkbox-circle-fill": "eb80",
+ "checkbox-circle-line": "eb81",
+ "checkbox-blank-line": "eb7f",
+ "checkbox-blank-fill": "eb7e",
+ "checkbox-line": "eb85",
+ "checkbox-fill": "eb82",
+ "add-circle-line": "ea11",
+ "add-circle-fill": "ea10",
+ "indeterminate-circle-fill": "ee56",
+ "indeterminate-circle-line": "ee57",
+ "close-circle-line": "eb97",
+ "close-circle-fill": "eb96",
+ "radio-button-line": "f050",
+ "radio-button-fill": "f04f",
+ "check-line": "eb7b",
+ "close-line": "eb99",
+ "add-line": "ea13",
+ "subtract-line": "f1af",
+ "divide-line": "ec40",
+ "equal-line": "f31f",
+ "upload-line": "f250",
+ "download-line": "ec5a",
+ "upload-cloud-2-line": "f24c",
+ "upload-cloud-2-fill": "f24b",
+ "download-cloud-2-line": "ec56",
+ "download-cloud-2-fill": "ec55",
+ "login-box-line": "eed4",
+ "login-box-fill": "eed3",
+ "shield-cross-line": "f102",
+ "shield-cross-fill": "f101",
+ "shield-check-fill": "f0ff",
+ "shield-check-line": "f100",
+ "delete-bin-fill": "ec29",
+ "delete-bin-line": "ec2a",
+ "lock-line": "eece",
+ "lock-fill": "eecd",
+ "lock-unlock-line": "eed2",
+ "lock-unlock-fill": "eed1",
+ "lock-password-line": "eed0",
+ "lock-password-fill": "eecf",
+ "eye-fill": "ecb4",
+ "eye-line": "ecb5",
+ "eye-off-line": "ecb7",
+ "eye-off-fill": "ecb6",
+ "search-line": "f0d1",
+ "search-fill": "f0d0",
+ "share-line": "f0fe",
+ "share-fill": "f0f7",
+ "share-box-line": "f0f4",
+ "share-box-fill": "f0f3",
+ "share-circle-line": "f0f6",
+ "share-circle-fill": "f0f5",
+ "time-fill": "f20e",
+ "time-line": "f20f",
+ "thumb-up-line": "f207",
+ "thumb-up-fill": "f206",
+ "notification-badge-fill": "ef97",
+ "notification-badge-line": "ef98",
+ "toggle-line": "f219",
+ "toggle-fill": "f218",
+ "filter-line": "ed27",
+ "filter-fill": "ed26",
+ "history-line": "ee17",
+ "loop-left-line": "f33d",
+ "loader-2-line": "eec2",
+ "loader-4-line": "eec6",
+ "reset-right-line": "f544",
+ "loader-fill": "eec9",
+ "user-3-line": "f256",
+ "user-3-fill": "f255",
+ "sun-fill": "f1bc",
+ "sun-line": "f1bf",
+ "moon-fill": "ef72",
+ "moon-line": "ef75",
+ "shining-line": "f35e",
+ "shining-fill": "f35d",
+ "fire-fill": "ed32",
+ "fire-line": "ed33",
+ "sparkling-line": "f36d",
+ "sparkling-fill": "f36c",
+ "box-1-line": "f2f1",
+ "box-1-fill": "f2f0",
+ "account-box-line": "ea07",
+ "account-box-fill": "ea06",
+ "account-circle-fill": "ea08",
+ "account-circle-line": "ea09",
+ "account-pin-box-fill": "ea0a",
+ "account-pin-box-line": "ea0b",
+ "skip-up-fill": "f366",
+ "arrow-left-right-fill": "ea61",
+ "arrow-up-down-fill": "ea73",
+ "arrow-up-double-fill": "f2ea",
+ "arrow-right-double-fill": "f2e4",
+ "expand-left-fill": "f320",
+ "expand-right-fill": "f324",
+ "expand-up-down-fill": "f326",
+ "expand-left-right-fill": "f322",
+ "arrow-go-back-fill": "ea57",
+ "arrow-go-forward-fill": "ea59",
+ "contract-left-line": "f2fd",
+ "contract-right-line": "f301",
+ "contract-right-fill": "f300",
+ "contract-left-fill": "f2fc",
+ "drag-move-line": "ec62",
+ "drag-move-fill": "ec61",
+ "home-line": "ee2b",
+ "home-fill": "ee26",
+ "mail-open-line": "eefa",
+ "mail-open-fill": "eef9",
+ "attachment-line": "ea86",
+ "attachment-fill": "ea85",
+ "bar-chart-fill": "ea99",
+ "bar-chart-horizontal-fill": "ea9c",
+ "bar-chart-2-fill": "ea95",
+ "bar-chart-grouped-fill": "ea9a",
+ "bubble-chart-fill": "eb02",
+ "pie-chart-fill": "eff9",
+ "calendar-schedule-line": "f3f3",
+ "calendar-schedule-fill": "f3f2",
+ "calendar-todo-line": "eb29",
+ "calendar-todo-fill": "eb28",
+ "calendar-event-fill": "eb24",
+ "calendar-event-line": "eb25",
+ "calendar-close-fill": "f38d",
+ "calendar-check-fill": "eb22",
+ "calendar-check-line": "eb23",
+ "calendar-close-line": "f38e",
+ "message-3-line": "ef46",
+ "message-3-fill": "ef45",
+ "chat-3-fill": "eb50",
+ "chat-3-line": "eb51",
+ "chat-1-fill": "eb4c",
+ "chat-1-line": "eb4d",
+ "chat-2-fill": "eb4e",
+ "chat-2-line": "eb4f",
+ "crop-line": "ec02",
+ "crop-fill": "ec01",
+ "palette-line": "efc5",
+ "palette-fill": "efc4",
+ "anticlockwise-line": "ea3c",
+ "anticlockwise-fill": "ea3b",
+ "clockwise-line": "eb95",
+ "clockwise-fill": "eb94",
+ "code-s-slash-fill": "ebac",
+ "code-s-slash-line": "ebad",
+ "puzzle-fill": "f451",
+ "puzzle-line": "f452",
+ "server-fill": "f0df",
+ "server-line": "f0e0",
+ "qr-scan-2-fill": "f03e",
+ "qr-scan-2-line": "f03f",
+ "scan-line": "f0bd",
+ "scan-fill": "f0bc",
+ "phone-find-fill": "efea",
+ "phone-find-line": "efeb",
+ "barcode-line": "eaa2",
+ "barcode-fill": "eaa1",
+ "file-list-fill": "ecf0",
+ "file-list-line": "ecf1",
+ "file-text-line": "ed0f",
+ "file-text-fill": "ed0e",
+ "book-fill": "ead6",
+ "book-line": "ead7",
+ "text": "f201",
+ "font-family": "f390",
+ "link": "eeb2",
+ "translate": "f227",
+ "copper-diamond-fill": "ebdd",
+ "copper-diamond-line": "ebde",
+ "dislike-fill": "ec3b",
+ "dislike-line": "ec3c",
+ "heart-3-fill": "ee0a",
+ "heart-3-line": "ee0b",
+ "hearts-fill": "ee12",
+ "hearts-line": "ee13",
+ "map-line": "ef08",
+ "map-fill": "ef07",
+ "image-circle-fill": "f412",
+ "image-circle-line": "f413",
+ "image-edit-fill": "ee48",
+ "image-edit-line": "ee49",
+ "image-add-line": "ee47",
+ "image-add-fill": "ee46",
+ "landscape-line": "ee7d",
+ "landscape-fill": "ee7c",
+ "check-double-line": "eb79",
+ "check-double-fill": "eb78",
+ "close-fill": "eb98",
+ "add-fill": "ea12",
+ "subtract-fill": "f1ae",
+ "divide-fill": "ec3f",
+ "equal-fill": "f31e",
+ "logout-circle-line": "eedc",
+ "logout-circle-fill": "eedb",
+ "shield-fill": "f103",
+ "shield-line": "f108",
+ "timer-line": "f215",
+ "timer-fill": "f212",
+ "delete-back-2-line": "ec1a",
+ "delete-back-2-fill": "ec19",
+ "volume-vibrate-line": "f2a4",
+ "volume-vibrate-fill": "f2a3",
+ "volume-off-vibrate-line": "f2a0",
+ "volume-off-vibrate-fill": "f29f",
+ "truck-line": "f231",
+ "truck-fill": "f230",
+ "flight-takeoff-line": "ed43",
+ "flight-takeoff-fill": "ed42",
+ "road-map-line": "f08e",
+ "road-map-fill": "f08d",
+ "pushpin-2-line": "f037",
+ "pushpin-2-fill": "f036",
+ "map-pin-2-line": "ef0a",
+ "map-pin-2-fill": "ef09",
+ "compass-discover-line": "ebc2",
+ "compass-discover-fill": "ebc1",
+ "signpost-fill": "f48d",
+ "signpost-line": "f48e",
+ "qq-line": "f03b",
+ "qq-fill": "f03a",
+ "tiktok-line": "f373",
+ "tiktok-fill": "f372",
+ "user-smile-line": "f274",
+ "user-smile-fill": "f273",
+ "user-line": "f264",
+ "user-fill": "f25f",
+ "user-add-fill": "f25d",
+ "user-add-line": "f25e",
+ "user-minus-line": "f54c",
+ "user-minus-fill": "f54b",
+ "user-follow-fill": "f260",
+ "user-follow-line": "f261",
+ "user-unfollow-line": "f278",
+ "user-unfollow-fill": "f277",
+ "user-shared-fill": "f271",
+ "user-shared-line": "f272",
+ "user-received-fill": "f269",
+ "user-received-line": "f26a",
+ "user-search-line": "f26c",
+ "user-search-fill": "f26b",
+ "user-location-line": "f266",
+ "user-location-fill": "f265",
+ "user-star-line": "f276",
+ "user-star-fill": "f275",
+ "user-settings-fill": "f26d",
+ "user-settings-line": "f26e",
+ "user-heart-line": "f263",
+ "user-heart-fill": "f262",
+ "user-forbid-line": "f3be",
+ "user-forbid-fill": "f3bd",
+ "group-fill": "ede2",
+ "group-line": "ede3",
+ "user-2-fill": "f253",
+ "user-2-line": "f254",
+ "shield-user-line": "f10c",
+ "shield-user-fill": "f10b",
+ "circle-line": "f3c2",
+ "circle-fill": "f3c1",
+ "sketching": "f35f",
+ "align-bottom": "ea24",
+ "restart-line": "f080",
+ "restart-fill": "f07f",
+ "refresh-line": "f064",
+ "refresh-fill": "f063",
+ "reset-left-line": "f542",
+ "reset-left-fill": "f541",
+ "skip-down-line": "f361",
+ "skip-down-fill": "f360",
+ "skip-right-line": "f365",
+ "skip-right-fill": "f364",
+ "skip-left-fill": "f362",
+ "skip-left-line": "f363",
+ "text-snippet": "f46e",
+ "input-method-line": "ee60",
+ "input-method-fill": "ee5f",
+ "font-size": "ed8d",
+ "font-size-2": "ed8c",
+ "font-color": "ed8b",
+ "node-tree": "ef90",
+ "price-tag-3-line": "f023",
+ "price-tag-3-fill": "f022",
+ "input-field": "f47a",
+ "timeline-view": "f46f",
+ "progress-2-line": "f47e",
+ "progress-2-fill": "f47d",
+ "t-box-line": "f1d3",
+ "t-box-fill": "f1d2",
+ "edit-2-fill": "ec7f",
+ "edit-2-line": "ec80",
+ "layout-2-line": "ee7f",
+ "layout-2-fill": "ee7e",
+ "layout-column-fill": "ee8c",
+ "layout-column-line": "ee8d",
+ "mouse-line": "ef7d",
+ "mouse-fill": "ef7c",
+ "file-upload-line": "ed15",
+ "file-upload-fill": "ed14",
+ "page-separator": "efbd",
+ "carousel-view": "f42c",
+ "list-view": "f44c",
+ "text-block": "f46d",
+ "percent-line": "efe6",
+ "percent-fill": "efe5",
+ "upload-fill": "f24f",
+ "t-shirt-line": "f1d9",
+ "t-shirt-fill": "f1d8",
+ "number-1": "efa0",
+ "check-fill": "eb7a",
+ "checkbox-multiple-line": "eb89",
+ "checkbox-multiple-fill": "eb88",
+ "collapse-vertical-line": "f52e",
+ "align-top": "ea29",
+ "window-2-line": "f2c4",
+ "window-2-fill": "f2c3",
+ "seo-line": "f3a4",
+ "seo-fill": "f3a3",
+ "shadow-line": "f45a",
+ "shadow-fill": "f459",
+ "puzzle-2-line": "f450",
+ "puzzle-2-fill": "f44f",
+ "markdown-line": "ef1e",
+ "markdown-fill": "ef1d",
+ "stacked-view": "f464",
+ "dropdown-list": "f3c3",
+ "timer-2-line": "f211",
+ "timer-2-fill": "f210",
+ "parent-line": "efca",
+ "parent-fill": "efc9",
+ "function-add-line": "f4df",
+ "function-add-fill": "f4de",
+ "arrow-up-box-line": "f562",
+ "arrow-up-box-fill": "f561",
+ "layout-bottom-fill": "ee8a",
+ "layout-right-fill": "ee9a",
+ "layout-right-line": "ee9b",
+ "layout-top-fill": "eea0",
+ "layout-top-line": "eea1",
+ "layout-left-line": "ee94",
+ "layout-left-fill": "ee93",
+ "layout-top-2-line": "ee9f",
+ "layout-top-2-fill": "ee9e",
+ "layout-right-2-line": "ee99",
+ "layout-right-2-fill": "ee98",
+ "layout-bottom-2-line": "ee89",
+ "layout-bottom-2-fill": "ee88",
+ "layout-left-2-line": "ee92",
+ "layout-left-2-fill": "ee91",
+ "layout-row-fill": "ee9c",
+ "layout-row-line": "ee9d",
+ "table-fill": "f1dd",
+ "table-line": "f1de",
+ "layout-bottom-line": "ee8b",
+ "picture-in-picture-line": "eff4",
+ "picture-in-picture-fill": "eff3",
+ "arrow-down-double-line": "f2e1",
+ "arrow-down-double-fill": "f2e0",
+ "arrow-left-double-fill": "f2e2",
+ "arrow-left-double-line": "f2e3"
+};
diff --git a/cool-unix/index.html b/cool-unix/index.html
new file mode 100644
index 0000000..5e9a043
--- /dev/null
+++ b/cool-unix/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/locale/en.json b/cool-unix/locale/en.json
new file mode 100644
index 0000000..632a94d
--- /dev/null
+++ b/cool-unix/locale/en.json
@@ -0,0 +1,2582 @@
+[
+ [
+ "其他",
+ "Other"
+ ],
+ [
+ "文件管理",
+ "File Management"
+ ],
+ [
+ "该模板正在开发中",
+ "This template is under development"
+ ],
+ [
+ "未登录",
+ "Not logged in"
+ ],
+ [
+ "总点击",
+ "Total clicks"
+ ],
+ [
+ "赞",
+ "Like"
+ ],
+ [
+ "收藏",
+ "Favorite"
+ ],
+ [
+ "粉丝",
+ "Fans"
+ ],
+ [
+ "接单模式",
+ "Order receiving mode"
+ ],
+ [
+ "已关闭",
+ "Closed"
+ ],
+ [
+ "消息通知",
+ "Message notification"
+ ],
+ [
+ "待支付",
+ "Pending payment"
+ ],
+ [
+ "未发货",
+ "Not shipped"
+ ],
+ [
+ "已发货",
+ "Shipped"
+ ],
+ [
+ "售后 / 退款",
+ "After-sales / Refund"
+ ],
+ [
+ "我的钱包",
+ "My wallet"
+ ],
+ [
+ "数据看板",
+ "Data dashboard"
+ ],
+ [
+ "历史记录",
+ "History"
+ ],
+ [
+ "邀请好友",
+ "Invite friends"
+ ],
+ [
+ "设置",
+ "Settings"
+ ],
+ [
+ "转动图片",
+ "Rotate Picture"
+ ],
+ [
+ "验证通过",
+ "Verification Passed"
+ ],
+ [
+ "验证失败",
+ "Verification Failed"
+ ],
+ [
+ "操作",
+ "Operation"
+ ],
+ [
+ "清空",
+ "Clear"
+ ],
+ [
+ "预览",
+ "Preview"
+ ],
+ [
+ "设置高度",
+ "Set Height"
+ ],
+ [
+ "毛笔效果",
+ "Brush Effect"
+ ],
+ [
+ "添加LOGO",
+ "Add LOGO"
+ ],
+ [
+ "圆角定位点",
+ "Rounded Corner Anchor Point"
+ ],
+ [
+ "内间距",
+ "Inner Spacing"
+ ],
+ [
+ "导出图片",
+ "Export Picture"
+ ],
+ [
+ "矩形",
+ "Rectangle"
+ ],
+ [
+ "点",
+ "Point"
+ ],
+ [
+ "线性",
+ "Linear"
+ ],
+ [
+ "小方格",
+ "Small Square"
+ ],
+ [
+ "格式化",
+ "Format"
+ ],
+ [
+ "添加",
+ "Add"
+ ],
+ [
+ "减去",
+ "Subtract"
+ ],
+ [
+ "获取某个单位的开始时间",
+ "Get the Start Time of a Certain Unit"
+ ],
+ [
+ "密码输入",
+ "Password input"
+ ],
+ [
+ "可清除",
+ "Clearable"
+ ],
+ [
+ "左右插槽",
+ "Left and right slots"
+ ],
+ [
+ "左图标",
+ "Left icon"
+ ],
+ [
+ "右图标",
+ "Right icon"
+ ],
+ [
+ "自动聚焦",
+ "Auto focus"
+ ],
+ [
+ "长度为6",
+ "Length is 6"
+ ],
+ [
+ "步进为10",
+ "Step is 10"
+ ],
+ [
+ "最小为10",
+ "Minimum is 10"
+ ],
+ [
+ "最大为50",
+ "Maximum is 50"
+ ],
+ [
+ "可以小数",
+ "Can be decimal"
+ ],
+ [
+ "可以输入",
+ "Can be input"
+ ],
+ [
+ "用户名",
+ "Username"
+ ],
+ [
+ "请输入用户名",
+ "Please enter username"
+ ],
+ [
+ "邮箱",
+ "Email"
+ ],
+ [
+ "请输入邮箱地址",
+ "Please enter email address"
+ ],
+ [
+ "动态验证",
+ "Dynamic verification"
+ ],
+ [
+ "联系人",
+ "Contact"
+ ],
+ [
+ "添加联系人",
+ "Add contact"
+ ],
+ [
+ "身高",
+ "Height"
+ ],
+ [
+ "跑马灯",
+ "Marquee"
+ ],
+ [
+ "分页",
+ "Pagination"
+ ],
+ [
+ "时间轴",
+ "Timeline"
+ ],
+ [
+ "拖拽",
+ "Drag"
+ ],
+ [
+ "筛选栏",
+ "Filter Bar"
+ ],
+ [
+ "树形结构",
+ "Tree Structure"
+ ],
+ [
+ "状态组件",
+ "Status Component"
+ ],
+ [
+ "角标",
+ "Badge"
+ ],
+ [
+ "通知栏",
+ "Notification Bar"
+ ],
+ [
+ "倒计时",
+ "Countdown"
+ ],
+ [
+ "数字滚动",
+ "Digital Scrolling"
+ ],
+ [
+ "进度条",
+ "Progress Bar"
+ ],
+ [
+ "圆形进度条",
+ "Circular Progress Bar"
+ ],
+ [
+ "骨架图",
+ "Skeleton Screen"
+ ],
+ [
+ "加载更多",
+ "Load More"
+ ],
+ [
+ "反馈组件",
+ "Feedback Component"
+ ],
+ [
+ "操作菜单",
+ "Operation Menu"
+ ],
+ [
+ "弹窗",
+ "Pop-up Window"
+ ],
+ [
+ "确认框",
+ "Confirmation Box"
+ ],
+ [
+ "提示框",
+ "Prompt Box"
+ ],
+ [
+ "签名",
+ "Signature"
+ ],
+ [
+ "水印",
+ "Watermark"
+ ],
+ [
+ "图片裁剪",
+ "Image Cropping"
+ ],
+ [
+ "Canvas",
+ "Canvas"
+ ],
+ [
+ "富文本",
+ "Rich Text"
+ ],
+ [
+ "该功能正在开发中",
+ "This function is under development"
+ ],
+ [
+ "圆形",
+ "Circle"
+ ],
+ [
+ "组合",
+ "Combination"
+ ],
+ [
+ "基础用法",
+ "Basic Usage"
+ ],
+ [
+ "自定义",
+ "Customization"
+ ],
+ [
+ "加快滚动速度",
+ "Speed up scrolling"
+ ],
+ [
+ "显示小数位数",
+ "Display decimal places"
+ ],
+ [
+ "自定义样式",
+ "Custom style"
+ ],
+ [
+ "自定义颜色",
+ "Custom color"
+ ],
+ [
+ "自定义宽度",
+ "Custom width"
+ ],
+ [
+ "不显示文本",
+ "Do not display text"
+ ],
+ [
+ "改个颜色",
+ "Change the color"
+ ],
+ [
+ "显示文本",
+ "Display text"
+ ],
+ [
+ "快一些",
+ "Faster"
+ ],
+ [
+ "带图标",
+ "With icon"
+ ],
+ [
+ "设置速度",
+ "Set speed"
+ ],
+ [
+ "左间隔",
+ "Left interval"
+ ],
+ [
+ "右移动",
+ "Right move"
+ ],
+ [
+ "左移动",
+ "Left move"
+ ],
+ [
+ "多个数据",
+ "Multiple data"
+ ],
+ [
+ "点击收起",
+ "Click to collapse"
+ ],
+ [
+ "点击展开",
+ "Click to expand"
+ ],
+ [
+ "ref 方式调用",
+ "Call by ref method"
+ ],
+ [
+ "自定义图标、文字、大小",
+ "Customize icon, text, size"
+ ],
+ [
+ "上传证件照",
+ "Upload ID photo"
+ ],
+ [
+ "多选",
+ "Multiple selection"
+ ],
+ [
+ "限制 3 个",
+ "Limit 3"
+ ],
+ [
+ "边框",
+ "Border"
+ ],
+ [
+ "显示字数",
+ "Displayed characters"
+ ],
+ [
+ "自动增高",
+ "Auto increase"
+ ],
+ [
+ "其他颜色",
+ "Other colors"
+ ],
+ [
+ "大一点",
+ "Bigger"
+ ],
+ [
+ "正方形",
+ "Square"
+ ],
+ [
+ "范围选择",
+ "Range selection"
+ ],
+ [
+ "显示值",
+ "Display value"
+ ],
+ [
+ "步长10",
+ "Step 10"
+ ],
+ [
+ "开发中,敬请期待",
+ "Under development, please look forward to it"
+ ],
+ [
+ "基础组件",
+ "Basic components"
+ ],
+ [
+ "文本",
+ "Text"
+ ],
+ [
+ "按钮",
+ "Button"
+ ],
+ [
+ "图片",
+ "Image"
+ ],
+ [
+ "图标",
+ "Icon"
+ ],
+ [
+ "标签",
+ "Label"
+ ],
+ [
+ "表单组件",
+ "Form components"
+ ],
+ [
+ "表单验证",
+ "Form validation"
+ ],
+ [
+ "输入框",
+ "Input box"
+ ],
+ [
+ "文本域",
+ "Text area"
+ ],
+ [
+ "计数器",
+ "Counter"
+ ],
+ [
+ "口令输入",
+ "Password input"
+ ],
+ [
+ "键盘",
+ "Keyboard"
+ ],
+ [
+ "单选框",
+ "Radio box"
+ ],
+ [
+ "多选框",
+ "Checkbox"
+ ],
+ [
+ "开关",
+ "Switch"
+ ],
+ [
+ "评分",
+ "Rating"
+ ],
+ [
+ "滑块",
+ "Slider"
+ ],
+ [
+ "选择器",
+ "Selector"
+ ],
+ [
+ "可滑动",
+ "Swipeable"
+ ],
+ [
+ "左滑编辑",
+ "Swipe left to edit"
+ ],
+ [
+ "编辑",
+ "Edit"
+ ],
+ [
+ "右滑删除",
+ "Swipe right to delete"
+ ],
+ [
+ "账号",
+ "Account"
+ ],
+ [
+ "我的订单",
+ "My Orders"
+ ],
+ [
+ "我的收藏",
+ "My Favorites"
+ ],
+ [
+ "筛选",
+ "Filter"
+ ],
+ [
+ "长按项即可拖动排序",
+ "Long press on an item to drag and sort"
+ ],
+ [
+ "单列排序",
+ "Single-column sorting"
+ ],
+ [
+ "不需要长按",
+ "No long press required"
+ ],
+ [
+ "结合列表使用",
+ "Use in combination with a list"
+ ],
+ [
+ "多列排序",
+ "Multi-column sorting"
+ ],
+ [
+ "结合图片使用",
+ "Use in combination with images"
+ ],
+ [
+ "禁用手势",
+ "Disable gestures"
+ ],
+ [
+ "自定义样式2",
+ "Custom style 2"
+ ],
+ [
+ "无图片",
+ "No image"
+ ],
+ [
+ "圆角",
+ "Rounded corners"
+ ],
+ [
+ "自定义大小",
+ "Custom size"
+ ],
+ [
+ "省略号",
+ "Ellipsis"
+ ],
+ [
+ "多行省略号",
+ "Multi-line ellipsis"
+ ],
+ [
+ "金额",
+ "Amount"
+ ],
+ [
+ "手机号脱敏",
+ "Mobile number desensitization"
+ ],
+ [
+ "姓名脱敏",
+ "Name desensitization"
+ ],
+ [
+ "邮箱脱敏",
+ "Email desensitization"
+ ],
+ [
+ "银行卡脱敏",
+ "Bank card desensitization"
+ ],
+ [
+ "自定义脱敏字符",
+ "Custom desensitization character"
+ ],
+ [
+ "主要",
+ "Main"
+ ],
+ [
+ "危险",
+ "Dangerous"
+ ],
+ [
+ "信息",
+ "Information"
+ ],
+ [
+ "邮件",
+ "Mail"
+ ],
+ [
+ "文件",
+ "File"
+ ],
+ [
+ "可关闭",
+ "Closable"
+ ],
+ [
+ "镂空",
+ "Hollowed out"
+ ],
+ [
+ "自定义无圆角",
+ "Custom without rounded corners"
+ ],
+ [
+ "不同裁剪",
+ "Different cropping"
+ ],
+ [
+ "点击可预览",
+ "Click to preview"
+ ],
+ [
+ "失败时显示",
+ "Display when failed"
+ ],
+ [
+ "自定义圆角",
+ "Custom rounded corners"
+ ],
+ [
+ "设置颜色",
+ "Set color"
+ ],
+ [
+ "垂直方向",
+ "Vertical direction"
+ ],
+ [
+ "3秒后加载完成",
+ "Load completed after 3 seconds"
+ ],
+ [
+ "隐藏为 00 的值",
+ "Hide the value of 00"
+ ],
+ [
+ "指定天数",
+ "Specify the number of days"
+ ],
+ [
+ "自定义模板",
+ "Custom template"
+ ],
+ [
+ "指定小时",
+ "Specify the hour"
+ ],
+ [
+ "指定分钟",
+ "Specify the minute"
+ ],
+ [
+ "指定秒",
+ "Specify the second"
+ ],
+ [
+ "完成后提示",
+ "Prompt after completion"
+ ],
+ [
+ "3秒后开始倒计时",
+ "Start the countdown after 3 seconds"
+ ],
+ [
+ "结合按钮",
+ "Combine with button"
+ ],
+ [
+ "购买",
+ "Purchase"
+ ],
+ [
+ "消息",
+ "Message"
+ ],
+ [
+ "结合图片",
+ "Combine with picture"
+ ],
+ [
+ "结合图标",
+ "Combine with icon"
+ ],
+ [
+ "点击触发",
+ "Click to trigger"
+ ],
+ [
+ "不同大小",
+ "Different sizes"
+ ],
+ [
+ "不同颜色",
+ "Different colors"
+ ],
+ [
+ "使用base64",
+ "Use base64"
+ ],
+ [
+ "没有错误提示",
+ "No error prompt"
+ ],
+ [
+ "体重",
+ "Weight"
+ ],
+ [
+ "所在地区",
+ "Location"
+ ],
+ [
+ "出生年月",
+ "Date of Birth"
+ ],
+ [
+ "个人简介",
+ "Personal Introduction"
+ ],
+ [
+ "请输入个人简介",
+ "Please enter your personal introduction"
+ ],
+ [
+ "公开状态",
+ "Public Status"
+ ],
+ [
+ "重置",
+ "Reset"
+ ],
+ [
+ "提交",
+ "Submit"
+ ],
+ [
+ "未知",
+ "Unknown"
+ ],
+ [
+ "篮球",
+ "Basketball"
+ ],
+ [
+ "足球",
+ "Football"
+ ],
+ [
+ "羽毛球",
+ "Badminton"
+ ],
+ [
+ "乒乓球",
+ "Table Tennis"
+ ],
+ [
+ "游泳",
+ "Swimming"
+ ],
+ [
+ "用户名不能为空",
+ "Username cannot be empty"
+ ],
+ [
+ "用户名长度在3-20个字符之间",
+ "Username length should be between 3 and 20 characters"
+ ],
+ [
+ "邮箱不能为空",
+ "Email cannot be empty"
+ ],
+ [
+ "邮箱格式不正确",
+ "Invalid email format"
+ ],
+ [
+ "身高不能为空",
+ "Height cannot be empty"
+ ],
+ [
+ "身高在160-190cm之间",
+ "Height should be between 160 and 190 cm"
+ ],
+ [
+ "显示星期",
+ "Show week"
+ ],
+ [
+ "显示其他月份",
+ "Show other months"
+ ],
+ [
+ "不同位置",
+ "Different positions"
+ ],
+ [
+ "顶部",
+ "Top"
+ ],
+ [
+ "中间",
+ "Middle"
+ ],
+ [
+ "底部",
+ "Bottom"
+ ],
+ [
+ "不同类型",
+ "Different types"
+ ],
+ [
+ "成功",
+ "Success"
+ ],
+ [
+ "失败",
+ "Failure"
+ ],
+ [
+ "警告",
+ "Warning"
+ ],
+ [
+ "问题",
+ "Problem"
+ ],
+ [
+ "停止",
+ "Stop"
+ ],
+ [
+ "自定义图标",
+ "Custom icon"
+ ],
+ [
+ "只存在一个",
+ "Only one exists"
+ ],
+ [
+ "不同位置提示",
+ "Different position tips"
+ ],
+ [
+ "不同类型提示",
+ "Different type tips"
+ ],
+ [
+ "带图标提示",
+ "Tips with icon"
+ ],
+ [
+ "移除其他已存在的提示",
+ "Remove other existing tips"
+ ],
+ [
+ "打开弹窗",
+ "Open pop-up window"
+ ],
+ [
+ "设置宽度 80%",
+ "Set width 80%"
+ ],
+ [
+ "充值1000元",
+ "Recharge 1000 yuan"
+ ],
+ [
+ "完成首笔交易",
+ "Complete the first transaction"
+ ],
+ [
+ "优选灵活配置混合A",
+ "Preferred Flexible Allocation Hybrid A"
+ ],
+ [
+ "1000元起",
+ "Starting from 1000 yuan"
+ ],
+ [
+ "禁用切换按钮",
+ "Disable the switch button"
+ ],
+ [
+ "自定义高度",
+ "Customize height"
+ ],
+ [
+ "多页数",
+ "Multiple pages"
+ ],
+ [
+ "上一页",
+ "Previous page"
+ ],
+ [
+ "下一页",
+ "Next page"
+ ],
+ [
+ "横向滚动",
+ "Horizontal scroll"
+ ],
+ [
+ "纵向滚动",
+ "Vertical scroll"
+ ],
+ [
+ "快一点",
+ "Faster"
+ ],
+ [
+ "暂停",
+ "Pause"
+ ],
+ [
+ "内容靠左",
+ "Content aligned to the left"
+ ],
+ [
+ "QQ",
+ "QQ"
+ ],
+ [
+ "带箭头",
+ "With arrow"
+ ],
+ [
+ "余额",
+ "Balance"
+ ],
+ [
+ "带图片",
+ "With picture"
+ ],
+ [
+ "神仙都没用",
+ "Even the gods are useless"
+ ],
+ [
+ "折叠",
+ "Fold"
+ ],
+ [
+ "插槽",
+ "Slot"
+ ],
+ [
+ "使用 PT 自定义颜色",
+ "Use PT to customize color"
+ ],
+ [
+ "自定义返回图标",
+ "Customize back icon"
+ ],
+ [
+ "自定义返回路径",
+ "Customize back path"
+ ],
+ [
+ "自定义标题内容",
+ "Customize title content"
+ ],
+ [
+ "显示滑块",
+ "Show slider"
+ ],
+ [
+ "添加间距",
+ "Add spacing"
+ ],
+ [
+ "横向填充",
+ "Horizontal fill"
+ ],
+ [
+ "适用于标签数量不多的情况",
+ "Suitable for cases with few labels"
+ ],
+ [
+ "居中",
+ "Center"
+ ],
+ [
+ "单个禁用",
+ "Single disable"
+ ],
+ [
+ "显示下划线",
+ "Show underline"
+ ],
+ [
+ "禁用",
+ "Disable"
+ ],
+ [
+ "取消订单",
+ "Cancel order"
+ ],
+ [
+ "立即购买",
+ "Buy now"
+ ],
+ [
+ "确认收货",
+ "Confirm receipt of goods"
+ ],
+ [
+ "评价",
+ "Evaluate"
+ ],
+ [
+ "禁用状态,无法拖拽",
+ "Disabled state, cannot be dragged"
+ ],
+ [
+ "不吸附边缘,任意位置可拖拽",
+ "Does not adhere to the edge, can be dragged anywhere"
+ ],
+ [
+ "这是一个提示",
+ "This is a tip"
+ ],
+ [
+ "标签格式化",
+ "Label formatting"
+ ],
+ [
+ "固定开始、结束日期",
+ "Fixed start and end dates"
+ ],
+ [
+ "自定义快捷选项",
+ "Custom quick options"
+ ],
+ [
+ "只读",
+ "Read-only"
+ ],
+ [
+ "显示分数",
+ "Show scores"
+ ],
+ [
+ "允许半星",
+ "Allow half stars"
+ ],
+ [
+ "换个图标",
+ "Change the icon"
+ ],
+ [
+ "纵向排列",
+ "Vertical arrangement"
+ ],
+ [
+ "换个样式",
+ "Change the style"
+ ],
+ [
+ "不显示图标",
+ "Do not show the icon"
+ ],
+ [
+ "其他样式",
+ "Other styles"
+ ],
+ [
+ "数字键盘",
+ "Numeric keypad"
+ ],
+ [
+ "打开键盘",
+ "Open the keyboard"
+ ],
+ [
+ "是否显示输入值",
+ "Whether to display the input value"
+ ],
+ [
+ "输入即绑定",
+ "Bind on input"
+ ],
+ [
+ "身份证键盘",
+ "ID card keypad"
+ ],
+ [
+ "密码键盘",
+ "Password keypad"
+ ],
+ [
+ "是否加密",
+ "Whether to encrypt"
+ ],
+ [
+ "车牌号键盘",
+ "License plate number keypad"
+ ],
+ [
+ "数字输入",
+ "Numeric input"
+ ],
+ [
+ "请输入验证码",
+ "Please enter the verification code"
+ ],
+ [
+ "登录",
+ "Login"
+ ],
+ [
+ "购物车 ({num})",
+ "Shopping Cart ({num})"
+ ],
+ [
+ "完成",
+ "Complete"
+ ],
+ [
+ "管理",
+ "Manage"
+ ],
+ [
+ "删除",
+ "Delete"
+ ],
+ [
+ "全选",
+ "Select All"
+ ],
+ [
+ "合计",
+ "Total"
+ ],
+ [
+ "去结算",
+ "Go to Checkout"
+ ],
+ [
+ "温馨提示",
+ "Warm Prompt"
+ ],
+ [
+ "确定删除该商品吗?",
+ "Are you sure to delete this product?"
+ ],
+ [
+ "删除成功",
+ "Delete successfully"
+ ],
+ [
+ "请先选择商品",
+ "Please select a product first"
+ ],
+ [
+ "确定删除选中的商品吗?",
+ "Are you sure to delete the selected products?"
+ ],
+ [
+ "您需支付 {price} 元,请确认支付",
+ "You need to pay {price} yuan. Please confirm the payment"
+ ],
+ [
+ "支付成功",
+ "Payment successful"
+ ],
+ [
+ "已设为默认",
+ "Set as default"
+ ],
+ [
+ "设为默认",
+ "Set as default"
+ ],
+ [
+ "修改",
+ "Modify"
+ ],
+ [
+ "添加地址",
+ "Add address"
+ ],
+ [
+ "Flex 弹性布局",
+ "Flex Elastic Layout"
+ ],
+ [
+ "Tabs 标签页",
+ "Tabs"
+ ],
+ [
+ "Collapse 折叠面板",
+ "Collapse Panel"
+ ],
+ [
+ "Sticky 吸顶",
+ "Sticky"
+ ],
+ [
+ "TopBar 导航栏",
+ "TopBar Navigation Bar"
+ ],
+ [
+ "FloatView 悬浮视图",
+ "FloatView Floating View"
+ ],
+ [
+ "Footer 底部视图",
+ "Footer Bottom View"
+ ],
+ [
+ "List 列表",
+ "List"
+ ],
+ [
+ "ListView 列表视图",
+ "ListView List View"
+ ],
+ [
+ "ListViewRefresh 列表刷新",
+ "ListViewRefresh List Refresh"
+ ],
+ [
+ "Waterfall 瀑布流",
+ "Waterfall Flow"
+ ],
+ [
+ "Banner 轮播图",
+ "Banner Carousel"
+ ],
+ [
+ "Marquee 跑马灯",
+ "Marquee Moving Light"
+ ],
+ [
+ "Pagination 分页",
+ "Pagination"
+ ],
+ [
+ "Timeline 时间轴",
+ "Timeline Time Axis"
+ ],
+ [
+ "Avatar 头像",
+ "Avatar"
+ ],
+ [
+ "ReadMore 查看更多",
+ "ReadMore View More"
+ ],
+ [
+ "Draggable 拖拽",
+ "Draggable Drag"
+ ],
+ [
+ "FilterBar 筛选栏",
+ "FilterBar Filter Bar"
+ ],
+ [
+ "Tree 树形结构",
+ "Tree Tree Structure"
+ ],
+ [
+ "获取某个单位的结束时间",
+ "Get the end time of a certain unit"
+ ],
+ [
+ "是否同一天",
+ "Is it the same day"
+ ],
+ [
+ "是否早于",
+ "Is it earlier than"
+ ],
+ [
+ "是否晚于",
+ "Is it later than"
+ ],
+ [
+ "差值",
+ "Difference"
+ ],
+ [
+ "差值(单位)",
+ "Difference (unit)"
+ ],
+ [
+ "选择图片",
+ "Select a picture"
+ ],
+ [
+ "可调节裁剪框大小",
+ "Adjust the size of the cropping frame"
+ ],
+ [
+ "预览图片",
+ "Preview the picture"
+ ],
+ [
+ "保存图片",
+ "Save the picture"
+ ],
+ [
+ "本页面内容由 canvas 渲染生成,是否立即预览图片效果?",
+ "The content of this page is rendered by canvas. Do you want to preview the picture effect immediately?"
+ ],
+ [
+ "基础动画",
+ "Basic animation"
+ ],
+ [
+ "淡入淡出",
+ "Fade in and out"
+ ],
+ [
+ "播放动画",
+ "Play animation"
+ ],
+ [
+ "滑入",
+ "Slide in"
+ ],
+ [
+ "旋转翻转",
+ "Rotate and flip"
+ ],
+ [
+ "摇摆抖动",
+ "Sway and shake"
+ ],
+ [
+ "特殊效果",
+ "Special effects"
+ ],
+ [
+ "组合动画",
+ "Combined animation"
+ ],
+ [
+ "标题",
+ "Title"
+ ],
+ [
+ "已阅读并同意",
+ "Read and agreed"
+ ],
+ [
+ "用户协议",
+ "User Agreement"
+ ],
+ [
+ "隐私政策",
+ "Privacy Policy"
+ ],
+ [
+ "请先阅读并同意《用户协议》和《隐私政策》",
+ "Please read and agree to the User Agreement and Privacy Policy first"
+ ],
+ [
+ "我的昵称",
+ "My Nickname"
+ ],
+ [
+ "简介",
+ "Profile"
+ ],
+ [
+ "介绍一下自己",
+ "Introduce yourself"
+ ],
+ [
+ "性别",
+ "Gender"
+ ],
+ [
+ "编辑性别",
+ "Edit Gender"
+ ],
+ [
+ "生日",
+ "Birthday"
+ ],
+ [
+ "选择生日",
+ "Select Birthday"
+ ],
+ [
+ "地区",
+ "Region"
+ ],
+ [
+ "选择所在的地区",
+ "Select your region"
+ ],
+ [
+ "选择性别",
+ "Select Gender"
+ ],
+ [
+ "保密",
+ "Confidential"
+ ],
+ [
+ "男",
+ "Male"
+ ],
+ [
+ "女",
+ "Female"
+ ],
+ [
+ "性别设置成功",
+ "Gender settings successful"
+ ],
+ [
+ "生日设置成功",
+ "Birthday settings successful"
+ ],
+ [
+ "地区设置成功",
+ "Region settings successful"
+ ],
+ [
+ "关于{name}",
+ "About {name}"
+ ],
+ [
+ "联系客服",
+ "Contact customer service"
+ ],
+ [
+ "退出登录",
+ "Log out"
+ ],
+ [
+ "确定退出登录吗?",
+ "Are you sure you want to log out?"
+ ],
+ [
+ "深色模式",
+ "Dark mode"
+ ],
+ [
+ "多语言",
+ "Multi-language"
+ ],
+ [
+ "字体大小",
+ "Font size"
+ ],
+ [
+ "访问官网",
+ "Visit official website"
+ ],
+ [
+ "商城",
+ "Mall"
+ ],
+ [
+ "商品分类",
+ "Product category"
+ ],
+ [
+ "商品详情",
+ "Product details"
+ ],
+ [
+ "商品列表、筛选",
+ "Product list, filtering"
+ ],
+ [
+ "购物车",
+ "Shopping cart"
+ ],
+ [
+ "订单列表、详情",
+ "Order list, details"
+ ],
+ [
+ "收货地址",
+ "Delivery address"
+ ],
+ [
+ "聊天",
+ "Chat"
+ ],
+ [
+ "对话列表、历史记录",
+ "Conversation list, history"
+ ],
+ [
+ "流式回复",
+ "Streaming reply"
+ ],
+ [
+ "语言合成",
+ "Text-to-Speech"
+ ],
+ [
+ "语音识别",
+ "Speech recognition"
+ ],
+ [
+ "Animation 动画",
+ "Animation Animation"
+ ],
+ [
+ "编辑地址",
+ "Edit Address"
+ ],
+ [
+ "cool-unix",
+ "cool-unix"
+ ],
+ [
+ "首页",
+ "Home Page"
+ ],
+ [
+ "我的",
+ "Mine"
+ ],
+ [
+ "删除地址后无法恢复,确认要删除该地址吗?",
+ "The address cannot be restored after deletion. Are you sure you want to delete this address?"
+ ],
+ [
+ "加载中",
+ "Loading"
+ ],
+ [
+ "收货人",
+ "Consignee"
+ ],
+ [
+ "请输入收货人姓名",
+ "Please enter the consignee's name"
+ ],
+ [
+ "手机号",
+ "Mobile phone number"
+ ],
+ [
+ "选择省市区",
+ "Select province, city and district"
+ ],
+ [
+ "详细地址",
+ "Detailed address"
+ ],
+ [
+ "小区楼栋、门牌号、村等",
+ "Residential building number, house number, village, etc."
+ ],
+ [
+ "默认地址",
+ "Default address"
+ ],
+ [
+ "保存",
+ "Save"
+ ],
+ [
+ "收货人不能为空",
+ "The consignee cannot be empty"
+ ],
+ [
+ "手机号不能为空",
+ "The mobile phone number cannot be empty"
+ ],
+ [
+ "手机号格式不正确",
+ "The mobile phone number format is incorrect"
+ ],
+ [
+ "详细地址不能为空",
+ "The detailed address cannot be empty"
+ ],
+ [
+ "所在地区不能为空",
+ "The location cannot be empty"
+ ],
+ [
+ "保存中",
+ "Saving"
+ ],
+ [
+ "开启通知",
+ "Enable notifications"
+ ],
+ [
+ "通用设置",
+ "General settings"
+ ],
+ [
+ "通知设置",
+ "Notification settings"
+ ],
+ [
+ "隐私设置",
+ "Privacy settings"
+ ],
+ [
+ "支付失败",
+ "Payment failed"
+ ],
+ [
+ "授权信息仅用于用户登录",
+ "Authorization information is only used for user login"
+ ],
+ [
+ "登录授权失败",
+ "Login authorization failed"
+ ],
+ [
+ "获取短信验证码",
+ "Get SMS verification code"
+ ],
+ [
+ "验证码",
+ "Verification code"
+ ],
+ [
+ "发送短信",
+ "Send SMS"
+ ],
+ [
+ "{n}s后重新获取",
+ "Re-get after {n}s"
+ ],
+ [
+ "获取验证码",
+ "Get verification code"
+ ],
+ [
+ "短信已发送,请查收",
+ "SMS has been sent, please check"
+ ],
+ [
+ "请填写验证码",
+ "Please fill in the verification code"
+ ],
+ [
+ "请填写正确的手机号格式",
+ "Please fill in the correct mobile phone number format"
+ ],
+ [
+ "全局字号",
+ "Global font size"
+ ],
+ [
+ "这是一段示例文字,用于预览不同字号的效果。",
+ "This is a sample text for previewing the effects of different font sizes."
+ ],
+ [
+ "默认 1.0",
+ "Default 1.0"
+ ],
+ [
+ "切换语言",
+ "Switch language"
+ ],
+ [
+ "切换中",
+ "Switching"
+ ],
+ [
+ "模板",
+ "Template"
+ ],
+ [
+ "编辑资料",
+ "Edit profile"
+ ],
+ [
+ "Text 文本",
+ "Text"
+ ],
+ [
+ "Button 按钮",
+ "Button"
+ ],
+ [
+ "滑块大点",
+ "Slider larger"
+ ],
+ [
+ "换个颜色",
+ "Change color"
+ ],
+ [
+ "最大50",
+ "Maximum 50"
+ ],
+ [
+ "自定义触发器",
+ "Custom trigger"
+ ],
+ [
+ "打开选择器",
+ "Open selector"
+ ],
+ [
+ "多列",
+ "Multiple columns"
+ ],
+ [
+ "通过 children 配置多级数据,并使用 column-count 参数指定显示的列数",
+ "Configure multi-level data through children and use the column-count parameter to specify the number of columns to display"
+ ],
+ [
+ "弹窗中使用",
+ "Use in pop-up window"
+ ],
+ [
+ "打开",
+ "Open"
+ ],
+ [
+ "选择地区",
+ "Select region"
+ ],
+ [
+ "绑定值",
+ "Bind value"
+ ],
+ [
+ "下一步",
+ "Next"
+ ],
+ [
+ "确定",
+ "OK"
+ ],
+ [
+ "关闭",
+ "Close"
+ ],
+ [
+ "显示取消按钮",
+ "Show cancel button"
+ ],
+ [
+ "修改按钮文案",
+ "Modify button text"
+ ],
+ [
+ "显示绑定值",
+ "Show bound value"
+ ],
+ [
+ "时",
+ "When"
+ ],
+ [
+ "时:分",
+ "HH:MM"
+ ],
+ [
+ "时:分:秒",
+ "HH:MM:SS"
+ ],
+ [
+ "设置大小",
+ "Set Size"
+ ],
+ [
+ "集成 iconfont 与 remixicon 图标库,展示部分示例",
+ "Integrate iconfont and remixicon icon libraries and display some examples"
+ ],
+ [
+ "iconfont",
+ "iconfont"
+ ],
+ [
+ "remixicon",
+ "remixicon"
+ ],
+ [
+ "复制成功",
+ "Copy Success"
+ ],
+ [
+ "普通",
+ "Normal"
+ ],
+ [
+ "浅色",
+ "Light Color"
+ ],
+ [
+ "深色",
+ "Dark Color"
+ ],
+ [
+ "只显示图标",
+ "Only Show Icons"
+ ],
+ [
+ "文本模式",
+ "Text Mode"
+ ],
+ [
+ "带边框",
+ "With Border"
+ ],
+ [
+ "圆角按钮",
+ "Rounded Button"
+ ],
+ [
+ "带左侧图标",
+ "With Left Icon"
+ ],
+ [
+ "小",
+ "Small"
+ ],
+ [
+ "默认",
+ "Default"
+ ],
+ [
+ "大",
+ "Large"
+ ],
+ [
+ "无权限",
+ "No Permission"
+ ],
+ [
+ "服务异常",
+ "Service Exception"
+ ],
+ [
+ "请在微信浏览器中打开",
+ "Please Open in WeChat Browser"
+ ],
+ [
+ "已取消支付",
+ "Payment Cancelled"
+ ],
+ [
+ "微信",
+ "WeChat"
+ ],
+ [
+ "父子关联",
+ "Father-son association"
+ ],
+ [
+ "选中值",
+ "Selected value"
+ ],
+ [
+ "选中操作",
+ "Selection operation"
+ ],
+ [
+ "选中部分节点",
+ "Select some nodes"
+ ],
+ [
+ "获取选中节点",
+ "Get selected nodes"
+ ],
+ [
+ "获取半选节点",
+ "Get half-selected nodes"
+ ],
+ [
+ "清空选中",
+ "Clear selection"
+ ],
+ [
+ "展开操作",
+ "Expand operation"
+ ],
+ [
+ "展开部分节点",
+ "Expand some nodes"
+ ],
+ [
+ "获取展开节点",
+ "Get expanded nodes"
+ ],
+ [
+ "展开所有",
+ "Expand all"
+ ],
+ [
+ "收起所有",
+ "Collapse all"
+ ],
+ [
+ "开通账号",
+ "Open an account"
+ ],
+ [
+ "赠送500元",
+ "Give 500 yuan"
+ ],
+ [
+ "完成实名认证",
+ "Complete real-name authentication"
+ ],
+ [
+ "通过身份证认证",
+ "Pass ID card authentication"
+ ],
+ [
+ "绑定银行卡",
+ "Bind a bank card"
+ ],
+ [
+ "绑定招商银行储蓄卡",
+ "Bind China Merchants Bank savings card"
+ ],
+ [
+ "首次充值",
+ "First recharge"
+ ],
+ [
+ "日期选择器",
+ "Date Picker"
+ ],
+ [
+ "时间选择器",
+ "Time Picker"
+ ],
+ [
+ "级联选择器",
+ "Cascading Selector"
+ ],
+ [
+ "文件上传",
+ "File Upload"
+ ],
+ [
+ "日历",
+ "Calendar"
+ ],
+ [
+ "布局组件",
+ "Layout Component"
+ ],
+ [
+ "弹性布局",
+ "Flexible Layout"
+ ],
+ [
+ "标签页",
+ "Tab"
+ ],
+ [
+ "折叠面板",
+ "Collapsible Panel"
+ ],
+ [
+ "吸顶",
+ "Sticky"
+ ],
+ [
+ "导航栏",
+ "Navigation Bar"
+ ],
+ [
+ "底部视图",
+ "Bottom View"
+ ],
+ [
+ "悬浮视图",
+ "Floating View"
+ ],
+ [
+ "数据展示",
+ "Data Display"
+ ],
+ [
+ "查看更多",
+ "View More"
+ ],
+ [
+ "列表",
+ "List"
+ ],
+ [
+ "列表视图",
+ "ListView"
+ ],
+ [
+ "列表刷新",
+ "List Refresh"
+ ],
+ [
+ "瀑布流",
+ "Waterfall Flow"
+ ],
+ [
+ "轮播图",
+ "Carousel"
+ ],
+ [
+ "无头",
+ "Headless"
+ ],
+ [
+ "左侧",
+ "Left"
+ ],
+ [
+ "右侧",
+ "Right"
+ ],
+ [
+ "隐藏取消按钮",
+ "Hide Cancel Button"
+ ],
+ [
+ "自定义文本",
+ "Custom Text"
+ ],
+ [
+ "关闭前钩子",
+ "Pre-Close Hook"
+ ],
+ [
+ "显示时长",
+ "Display Duration"
+ ],
+ [
+ "确定要删除吗?",
+ "Are you sure you want to delete?"
+ ],
+ [
+ "确定要删除吗?3秒后自动关闭",
+ "Automatically close in 3 seconds after asking if you are sure you want to delete"
+ ],
+ [
+ "带标题、描述",
+ "With title and description"
+ ],
+ [
+ "无法点击遮罩关闭",
+ "Cannot close by clicking on the mask"
+ ],
+ [
+ "不需要取消按钮",
+ "Do not need Cancel Button"
+ ],
+ [
+ "插槽用法",
+ "Slot Usage"
+ ],
+ [
+ "反馈",
+ "Feedback"
+ ],
+ [
+ "删除好友会同时删除所有聊天记录",
+ "Deleting a friend will also delete all chat records"
+ ],
+ [
+ "删除好友",
+ "Delete Friend"
+ ],
+ [
+ "确定要删除好友吗?",
+ "Are you sure you want to delete the friend?"
+ ],
+ [
+ "点我关闭",
+ "Click me to close"
+ ],
+ [
+ "确定要关闭吗?",
+ "Are you sure you want to close?"
+ ],
+ [
+ "支付宝",
+ "Alipay"
+ ],
+ [
+ "Badge 角标",
+ "Badge Corner Mark"
+ ],
+ [
+ "NoticeBar 通知栏",
+ "NoticeBar Notification Bar"
+ ],
+ [
+ "Countdown 倒计时",
+ "Countdown Countdown Timer"
+ ],
+ [
+ "Progress 进度条",
+ "Progress Progress Bar"
+ ],
+ [
+ "ProgressCircle 圆形进度条",
+ "ProgressCircle Circular Progress Bar"
+ ],
+ [
+ "Skeleton 骨架图",
+ "Skeleton Skeleton Diagram"
+ ],
+ [
+ "LoadMore 加载更多",
+ "LoadMore Load More"
+ ],
+ [
+ "RollingNumber 数字滚动",
+ "RollingNumber Digital Scroll"
+ ],
+ [
+ "ActionSheet 操作菜单",
+ "ActionSheet Operation Menu"
+ ],
+ [
+ "Popup 弹窗",
+ "Popup Pop-up Window"
+ ],
+ [
+ "Confirm 确认框",
+ "Confirm Confirmation Box"
+ ],
+ [
+ "Toast 提示框",
+ "Toast Toast Message"
+ ],
+ [
+ "QRCode 二维码",
+ "QRCode QR Code"
+ ],
+ [
+ "Sign 签名",
+ "Sign Signature"
+ ],
+ [
+ "DayUts 日期",
+ "DayUts Date"
+ ],
+ [
+ "Vibrate 震动",
+ "Vibrate Vibration"
+ ],
+ [
+ "Cropper 图片裁剪",
+ "Cropper Image Cropper"
+ ],
+ [
+ "Canvas 画布",
+ "Canvas Canvas"
+ ],
+ [
+ "SVG 图标",
+ "SVG SVG Icon"
+ ],
+ [
+ "SlideVerify 滑动验证",
+ "SlideVerify Slide Verification"
+ ],
+ [
+ "体重不能为空",
+ "Weight cannot be empty"
+ ],
+ [
+ "体重在40-100kg之间",
+ "Weight should be between 40 - 100 kg"
+ ],
+ [
+ "标签不能为空",
+ "Label cannot be empty"
+ ],
+ [
+ "标签最多选择2个",
+ "At most 2 labels can be selected"
+ ],
+ [
+ "性别不能为空",
+ "Gender cannot be empty"
+ ],
+ [
+ "出生年月不能为空",
+ "Date of birth cannot be empty"
+ ],
+ [
+ "出生年月不大于2010-01-01",
+ "Date of birth should not be later than 2010-01-01"
+ ],
+ [
+ "联系人不能为空",
+ "Contact person cannot be empty"
+ ],
+ [
+ "提交成功",
+ "Submission successful"
+ ],
+ [
+ "单个 true / false",
+ "Single true / false"
+ ],
+ [
+ "带索引、地区选择",
+ "With index, area selection"
+ ],
+ [
+ "换个分隔符",
+ "Change the delimiter"
+ ],
+ [
+ "列表高度小一点",
+ "Make the list height smaller"
+ ],
+ [
+ "范围选",
+ "Range selection"
+ ],
+ [
+ "禁用部分日期",
+ "Disable some dates"
+ ],
+ [
+ "日历长列表",
+ "Calendar long list"
+ ],
+ [
+ "打开日历长列表",
+ "Open the calendar long list"
+ ],
+ [
+ "日历面板",
+ "Calendar panel"
+ ],
+ [
+ "自定义文案和颜色",
+ "Customize text and color"
+ ],
+ [
+ "显示头",
+ "Show the header"
+ ],
+ [
+ "头像上传成功",
+ "Profile picture uploaded successfully"
+ ],
+ [
+ "编辑昵称",
+ "Edit nickname"
+ ],
+ [
+ "请输入昵称",
+ "Please enter a nickname"
+ ],
+ [
+ "请设置2-20个字符,不包括@<>/等无效字符",
+ "Please set 2-20 characters, excluding invalid characters such as @<>/"
+ ],
+ [
+ "确认",
+ "Confirm"
+ ],
+ [
+ "昵称长度需在2-20个字符之间",
+ "Nickname length should be between 2-20 characters"
+ ],
+ [
+ "昵称不能包含@<>/等特殊字符",
+ "Nickname cannot contain special characters such as @<>/"
+ ],
+ [
+ "编辑简介",
+ "Edit profile"
+ ],
+ [
+ "简介不能为空",
+ "Profile cannot be empty"
+ ],
+ [
+ "提示",
+ "Tip"
+ ],
+ [
+ "为提供更好的服务,我们邀请您填写昵称、头像等公开信息",
+ "To provide better service, we invite you to fill in public information such as nickname and profile picture"
+ ],
+ [
+ "头像",
+ "Profile picture"
+ ],
+ [
+ "昵称",
+ "Nickname"
+ ],
+ [
+ "点击输入昵称",
+ "Click to enter nickname"
+ ],
+ [
+ "取消",
+ "Cancel"
+ ],
+ [
+ "请上传头像",
+ "Please upload a profile picture"
+ ],
+ [
+ "登录中",
+ "Logging in"
+ ],
+ [
+ "手机登录",
+ "Mobile login"
+ ],
+ [
+ "未注册的手机号登录成功后将自动注册",
+ "Unregistered mobile numbers will be automatically registered after successful login"
+ ],
+ [
+ "请输入手机号",
+ "Please enter a mobile number"
+ ],
+ [
+ "Image 图片",
+ "Image Picture"
+ ],
+ [
+ "Icon 图标",
+ "Icon Icon"
+ ],
+ [
+ "Tag 标签",
+ "Tag Tag"
+ ],
+ [
+ "Form 表单验证",
+ "Form Form Validation"
+ ],
+ [
+ "Input 输入框",
+ "Input Input Box"
+ ],
+ [
+ "Textarea 文本域",
+ "Textarea Text Area"
+ ],
+ [
+ "InputNumber 计数器",
+ "InputNumber Counter"
+ ],
+ [
+ "InputOtp 口令输入",
+ "InputOtp Password Input"
+ ],
+ [
+ "Keyboard 键盘",
+ "Keyboard Keyboard"
+ ],
+ [
+ "Radio 单选框",
+ "Radio Radio Button"
+ ],
+ [
+ "Checkbox 多选框",
+ "Checkbox Checkbox"
+ ],
+ [
+ "Switch 开关",
+ "Switch Switch"
+ ],
+ [
+ "Rate 评分",
+ "Rate Rating"
+ ],
+ [
+ "Slider 滑块",
+ "Slider Slider"
+ ],
+ [
+ "Select 选择器",
+ "Select Selector"
+ ],
+ [
+ "SelectDate 日期选择器",
+ "SelectDate Date Selector"
+ ],
+ [
+ "SelectTime 时间选择器",
+ "SelectTime Time Selector"
+ ],
+ [
+ "Cascader 级联选择器",
+ "Cascader Cascading Selector"
+ ],
+ [
+ "Upload 文件上传",
+ "Upload File Upload"
+ ],
+ [
+ "Calendar 日历",
+ "Calendar Calendar"
+ ],
+ [
+ "这是一段需要保护的内容",
+ "This is content that needs to be protected"
+ ],
+ [
+ "水印会覆盖在内容上方,防止内容被盗用",
+ "Watermarks will be overlaid on the content to prevent unauthorized use"
+ ],
+ [
+ "可自定义的水印内容区域",
+ "Customizable watermark content area"
+ ],
+ [
+ "水印文本",
+ "Watermark Text"
+ ],
+ [
+ "字体大小",
+ "Font Size"
+ ],
+ [
+ "透明度",
+ "Opacity"
+ ],
+ [
+ "旋转角度",
+ "Rotation Angle"
+ ],
+ [
+ "水印宽度",
+ "Watermark Width"
+ ],
+ [
+ "水印高度",
+ "Watermark Height"
+ ],
+ [
+ "水平间距",
+ "Horizontal Spacing"
+ ],
+ [
+ "垂直间距",
+ "Vertical Spacing"
+ ],
+ [
+ "字体粗细",
+ "Font Weight"
+ ],
+ [
+ "正常",
+ "Normal"
+ ],
+ [
+ "加粗",
+ "Bold"
+ ],
+ [
+ "多行文本水印",
+ "Multi-line Text Watermark"
+ ],
+ [
+ "重要文档",
+ "Important Document"
+ ],
+ [
+ "这是一份重要的文档内容,需要添加水印保护。",
+ "This is an important document that requires watermark protection."
+ ],
+ [
+ "水印可以防止内容被未授权的复制和传播。",
+ "Watermarks can prevent unauthorized copying and distribution of content."
+ ],
+ [
+ "图片保护",
+ "Image Protection"
+ ]
+]
\ No newline at end of file
diff --git a/cool-unix/locale/es.json b/cool-unix/locale/es.json
new file mode 100644
index 0000000..43e5046
--- /dev/null
+++ b/cool-unix/locale/es.json
@@ -0,0 +1,2502 @@
+[
+ [
+ "Animation 动画",
+ "Animación"
+ ],
+ [
+ "编辑地址",
+ "Dirección de edición"
+ ],
+ [
+ "cool-unix",
+ "cool-unix"
+ ],
+ [
+ "首页",
+ "Página principal"
+ ],
+ [
+ "我的",
+ "Mío"
+ ],
+ [
+ "开发中,敬请期待",
+ "En desarrollo, por favor espere"
+ ],
+ [
+ "基础组件",
+ "Componentes básicos"
+ ],
+ [
+ "文本",
+ "Texto"
+ ],
+ [
+ "按钮",
+ "Botón"
+ ],
+ [
+ "图片",
+ "Imagen"
+ ],
+ [
+ "图标",
+ "Icono"
+ ],
+ [
+ "标签",
+ "Etiqueta"
+ ],
+ [
+ "表单组件",
+ "Componentes de formulario"
+ ],
+ [
+ "表单验证",
+ "Validación de formulario"
+ ],
+ [
+ "输入框",
+ "Cuadro de entrada"
+ ],
+ [
+ "文本域",
+ "Área de texto"
+ ],
+ [
+ "计数器",
+ "Contador"
+ ],
+ [
+ "口令输入",
+ "Ingreso de contraseña"
+ ],
+ [
+ "键盘",
+ "Teclado"
+ ],
+ [
+ "单选框",
+ "Checkbox"
+ ],
+ [
+ "多选框",
+ "Checkbox múltiple"
+ ],
+ [
+ "开关",
+ "Interruptor"
+ ],
+ [
+ "评分",
+ "Evaluación"
+ ],
+ [
+ "滑块",
+ "Deslizador"
+ ],
+ [
+ "选择器",
+ "Selector"
+ ],
+ [
+ "跑马灯",
+ "Marquee"
+ ],
+ [
+ "分页",
+ "Paginación"
+ ],
+ [
+ "时间轴",
+ "Timeline"
+ ],
+ [
+ "拖拽",
+ "Drag and Drop"
+ ],
+ [
+ "筛选栏",
+ "Barra de Filtro"
+ ],
+ [
+ "树形结构",
+ "Estructura de árbol"
+ ],
+ [
+ "状态组件",
+ "Componente de Estado"
+ ],
+ [
+ "角标",
+ "Badge"
+ ],
+ [
+ "通知栏",
+ "Barra de Notificaciones"
+ ],
+ [
+ "倒计时",
+ "Cuenta atrás"
+ ],
+ [
+ "数字滚动",
+ "Scroll de números"
+ ],
+ [
+ "进度条",
+ "Barra de Progreso"
+ ],
+ [
+ "圆形进度条",
+ "Barra de Progreso Circular"
+ ],
+ [
+ "骨架图",
+ "Esqueleto"
+ ],
+ [
+ "加载更多",
+ "Cargar más"
+ ],
+ [
+ "反馈组件",
+ "Componente de Retroalimentación"
+ ],
+ [
+ "操作菜单",
+ "Menú de Operaciones"
+ ],
+ [
+ "弹窗",
+ "Ventana emergente"
+ ],
+ [
+ "确认框",
+ "Cuadro de Confirmación"
+ ],
+ [
+ "提示框",
+ "Cuadro de Alerta"
+ ],
+ [
+ "其他",
+ "Otro"
+ ],
+ [
+ "文件管理",
+ "Administración de archivos"
+ ],
+ [
+ "该模板正在开发中",
+ "Este modelo está en desarrollo"
+ ],
+ [
+ "未登录",
+ "No conectado"
+ ],
+ [
+ "总点击",
+ "Clicks totales"
+ ],
+ [
+ "赞",
+ "Me gusta"
+ ],
+ [
+ "收藏",
+ "Favoritos"
+ ],
+ [
+ "粉丝",
+ "Fans"
+ ],
+ [
+ "接单模式",
+ "Modo de aceptar pedidos"
+ ],
+ [
+ "已关闭",
+ "Cerrado"
+ ],
+ [
+ "消息通知",
+ "Notificaciones de mensajes"
+ ],
+ [
+ "待支付",
+ "Pendiente de pago"
+ ],
+ [
+ "未发货",
+ "No enviado"
+ ],
+ [
+ "已发货",
+ "Enviado"
+ ],
+ [
+ "售后 / 退款",
+ "Servicio después de la venta / Reembolso"
+ ],
+ [
+ "我的钱包",
+ "Mi billetera"
+ ],
+ [
+ "数据看板",
+ "Tablero de datos"
+ ],
+ [
+ "历史记录",
+ "Historial"
+ ],
+ [
+ "邀请好友",
+ "Invitar amigos"
+ ],
+ [
+ "设置",
+ "Configuración"
+ ],
+ [
+ "日期选择器",
+ "Selector de fecha"
+ ],
+ [
+ "时间选择器",
+ "Selector de hora"
+ ],
+ [
+ "级联选择器",
+ "Selector en cascada"
+ ],
+ [
+ "文件上传",
+ "Carga de archivo"
+ ],
+ [
+ "日历",
+ "Calendario"
+ ],
+ [
+ "布局组件",
+ "Componente de diseño"
+ ],
+ [
+ "弹性布局",
+ "Diseño flexible"
+ ],
+ [
+ "标签页",
+ "Pestañas"
+ ],
+ [
+ "折叠面板",
+ "Panel desplegable"
+ ],
+ [
+ "吸顶",
+ "Fijación en la parte superior"
+ ],
+ [
+ "导航栏",
+ "Barra de navegación"
+ ],
+ [
+ "底部视图",
+ "Vista inferior"
+ ],
+ [
+ "悬浮视图",
+ "Vista flotante"
+ ],
+ [
+ "数据展示",
+ "Visualización de datos"
+ ],
+ [
+ "查看更多",
+ "Ver más"
+ ],
+ [
+ "列表",
+ "Lista"
+ ],
+ [
+ "列表视图",
+ "Vista de lista"
+ ],
+ [
+ "列表刷新",
+ "Actualización de lista"
+ ],
+ [
+ "瀑布流",
+ "Mosaico"
+ ],
+ [
+ "轮播图",
+ "Carrusel"
+ ],
+ [
+ "显示星期",
+ "Mostrar día de la semana"
+ ],
+ [
+ "显示其他月份",
+ "Mostrar otros meses"
+ ],
+ [
+ "不同位置",
+ "Diferentes ubicaciones"
+ ],
+ [
+ "顶部",
+ "Superior"
+ ],
+ [
+ "中间",
+ "Medio"
+ ],
+ [
+ "底部",
+ "Inferior"
+ ],
+ [
+ "不同类型",
+ "Diferentes tipos"
+ ],
+ [
+ "成功",
+ "Éxito"
+ ],
+ [
+ "失败",
+ "Error"
+ ],
+ [
+ "警告",
+ "Advertencia"
+ ],
+ [
+ "问题",
+ "Problema"
+ ],
+ [
+ "停止",
+ "Detener"
+ ],
+ [
+ "自定义图标",
+ "Ícono personalizado"
+ ],
+ [
+ "只存在一个",
+ "Solo existe uno"
+ ],
+ [
+ "不同位置提示",
+ "Indicación de ubicación diferente"
+ ],
+ [
+ "不同类型提示",
+ "Indicación de tipo diferente"
+ ],
+ [
+ "带图标提示",
+ "Indicación con icono"
+ ],
+ [
+ "移除其他已存在的提示",
+ "Eliminar otras indicaciones existentes"
+ ],
+ [
+ "打开弹窗",
+ "Abrir ventana emergente"
+ ],
+ [
+ "设置宽度 80%",
+ "Establecer el ancho al 80%"
+ ],
+ [
+ "设置大小",
+ "Configurar tamaño"
+ ],
+ [
+ "集成 iconfont 与 remixicon 图标库,展示部分示例",
+ "Integrar iconfont y la librería de iconos remixicon, mostrar algunos ejemplos"
+ ],
+ [
+ "iconfont",
+ "iconfont"
+ ],
+ [
+ "remixicon",
+ "remixicon"
+ ],
+ [
+ "复制成功",
+ "Copia exitosa"
+ ],
+ [
+ "普通",
+ "Normal"
+ ],
+ [
+ "浅色",
+ "Claro"
+ ],
+ [
+ "深色",
+ "Oscuro"
+ ],
+ [
+ "只显示图标",
+ "Mostrar solo iconos"
+ ],
+ [
+ "文本模式",
+ "Modo de texto"
+ ],
+ [
+ "带边框",
+ "Con borde"
+ ],
+ [
+ "圆角按钮",
+ "Botón redondeado"
+ ],
+ [
+ "带左侧图标",
+ "Con icono a la izquierda"
+ ],
+ [
+ "小",
+ "Pequeño"
+ ],
+ [
+ "默认",
+ "Predeterminado"
+ ],
+ [
+ "大",
+ "Grande"
+ ],
+ [
+ "无权限",
+ "Sin permiso"
+ ],
+ [
+ "服务异常",
+ "Error de servicio"
+ ],
+ [
+ "请在微信浏览器中打开",
+ "Abra en el navegador de WeChat"
+ ],
+ [
+ "已取消支付",
+ "Pago cancelado"
+ ],
+ [
+ "密码输入",
+ "Ingreso de contraseña"
+ ],
+ [
+ "可清除",
+ "Borrado posible"
+ ],
+ [
+ "左右插槽",
+ "Ranuras izquierda y derecha"
+ ],
+ [
+ "左图标",
+ "Ícono izquierdo"
+ ],
+ [
+ "右图标",
+ "Ícono derecho"
+ ],
+ [
+ "自动聚焦",
+ "Enfoque automático"
+ ],
+ [
+ "长度为6",
+ "Longitud de 6"
+ ],
+ [
+ "步进为10",
+ "Incremento de 10"
+ ],
+ [
+ "最小为10",
+ "Mínimo de 10"
+ ],
+ [
+ "最大为50",
+ "Máximo de 50"
+ ],
+ [
+ "可以小数",
+ "Con decimales"
+ ],
+ [
+ "可以输入",
+ "Puede ingresar"
+ ],
+ [
+ "用户名",
+ "Nombre de usuario"
+ ],
+ [
+ "请输入用户名",
+ "Ingrese su nombre de usuario"
+ ],
+ [
+ "邮箱",
+ "Correo electrónico"
+ ],
+ [
+ "请输入邮箱地址",
+ "Ingrese su dirección de correo electrónico"
+ ],
+ [
+ "动态验证",
+ "Validación dinámica"
+ ],
+ [
+ "联系人",
+ "Contacto"
+ ],
+ [
+ "添加联系人",
+ "Agregar contacto"
+ ],
+ [
+ "身高",
+ "Altura"
+ ],
+ [
+ "转动图片",
+ "Girar la imagen"
+ ],
+ [
+ "验证通过",
+ "Validación exitosa"
+ ],
+ [
+ "验证失败",
+ "Validación fallida"
+ ],
+ [
+ "操作",
+ "Operación"
+ ],
+ [
+ "清空",
+ "Vaciar"
+ ],
+ [
+ "预览",
+ "Vista previa"
+ ],
+ [
+ "设置高度",
+ "Establecer la altura"
+ ],
+ [
+ "毛笔效果",
+ "Efecto de pincel"
+ ],
+ [
+ "添加LOGO",
+ "Agregar LOGO"
+ ],
+ [
+ "圆角定位点",
+ "Punto de ubicación redondeado"
+ ],
+ [
+ "内间距",
+ "Espaciado interno"
+ ],
+ [
+ "导出图片",
+ "Exportar imagen"
+ ],
+ [
+ "矩形",
+ "Rectángulo"
+ ],
+ [
+ "点",
+ "Punto"
+ ],
+ [
+ "线性",
+ "Lineal"
+ ],
+ [
+ "小方格",
+ "Cuadricula"
+ ],
+ [
+ "格式化",
+ "Formatear"
+ ],
+ [
+ "添加",
+ "Agregar"
+ ],
+ [
+ "减去",
+ "Restar"
+ ],
+ [
+ "获取某个单位的开始时间",
+ "Obtener la hora de inicio de una unidad"
+ ],
+ [
+ "签名",
+ "Autógrafo"
+ ],
+ [
+ "图片裁剪",
+ "Redimensionamiento de imágenes"
+ ],
+ [
+ "Canvas",
+ "Canvas"
+ ],
+ [
+ "富文本",
+ "Texto enriquecido"
+ ],
+ [
+ "该功能正在开发中",
+ "Esta función está en desarrollo"
+ ],
+ [
+ "圆形",
+ "Circular"
+ ],
+ [
+ "组合",
+ "Combinación"
+ ],
+ [
+ "基础用法",
+ "Uso básico"
+ ],
+ [
+ "自定义",
+ "Personalización"
+ ],
+ [
+ "加快滚动速度",
+ "Acelerar la velocidad de desplazamiento"
+ ],
+ [
+ "显示小数位数",
+ "Mostrar número de decimales"
+ ],
+ [
+ "自定义样式",
+ "Estilo personalizado"
+ ],
+ [
+ "自定义颜色",
+ "Color personalizado"
+ ],
+ [
+ "自定义宽度",
+ "Ancho personalizado"
+ ],
+ [
+ "不显示文本",
+ "No mostrar texto"
+ ],
+ [
+ "改个颜色",
+ "Cambiar el color"
+ ],
+ [
+ "显示文本",
+ "Mostrar texto"
+ ],
+ [
+ "快一些",
+ "Más rápido"
+ ],
+ [
+ "带图标",
+ "Con icono"
+ ],
+ [
+ "设置速度",
+ "Configurar velocidad"
+ ],
+ [
+ "体重",
+ "Peso"
+ ],
+ [
+ "所在地区",
+ "Región"
+ ],
+ [
+ "出生年月",
+ "Fecha de nacimiento"
+ ],
+ [
+ "个人简介",
+ "Perfil personal"
+ ],
+ [
+ "请输入个人简介",
+ "Ingrese su perfil personal"
+ ],
+ [
+ "公开状态",
+ "Estado público"
+ ],
+ [
+ "重置",
+ "Restablecer"
+ ],
+ [
+ "提交",
+ "Enviar"
+ ],
+ [
+ "未知",
+ "Desconocido"
+ ],
+ [
+ "篮球",
+ "Baloncesto"
+ ],
+ [
+ "足球",
+ "Fútbol"
+ ],
+ [
+ "羽毛球",
+ "Tenis de mesa"
+ ],
+ [
+ "乒乓球",
+ "Natación"
+ ],
+ [
+ "游泳",
+ "El nombre de usuario no puede estar vacío"
+ ],
+ [
+ "用户名不能为空",
+ "La longitud del nombre de usuario debe estar entre 3 y 20 caracteres"
+ ],
+ [
+ "用户名长度在3-20个字符之间",
+ "El correo electrónico no puede estar vacío"
+ ],
+ [
+ "邮箱不能为空",
+ "El formato del correo electrónico es incorrecto"
+ ],
+ [
+ "邮箱格式不正确",
+ "La estatura no puede estar vacía"
+ ],
+ [
+ "身高不能为空",
+ "La estatura debe estar entre 160 y 190 cm"
+ ],
+ [
+ "身高在160-190cm之间",
+ ""
+ ],
+ [
+ "微信",
+ "WeChat"
+ ],
+ [
+ "父子关联",
+ "Relación padre-hijo"
+ ],
+ [
+ "选中值",
+ "Valor seleccionado"
+ ],
+ [
+ "选中操作",
+ "Operación de selección"
+ ],
+ [
+ "选中部分节点",
+ "Selección de algunos nodos"
+ ],
+ [
+ "获取选中节点",
+ "Obtención de nodos seleccionados"
+ ],
+ [
+ "获取半选节点",
+ "Obtención de nodos semi-seleccionados"
+ ],
+ [
+ "清空选中",
+ "Limpiar selección"
+ ],
+ [
+ "展开操作",
+ "Operación de expansión"
+ ],
+ [
+ "展开部分节点",
+ "Expansión de algunos nodos"
+ ],
+ [
+ "获取展开节点",
+ "Obtención de nodos expandidos"
+ ],
+ [
+ "展开所有",
+ "Expandir todo"
+ ],
+ [
+ "收起所有",
+ "Contraer todo"
+ ],
+ [
+ "开通账号",
+ "Abrir una cuenta"
+ ],
+ [
+ "赠送500元",
+ "Regalo de 500 yuan"
+ ],
+ [
+ "完成实名认证",
+ "Completar la autenticación de identidad"
+ ],
+ [
+ "通过身份证认证",
+ "Autenticación por DNI"
+ ],
+ [
+ "绑定银行卡",
+ "Vincular tarjeta de banco"
+ ],
+ [
+ "绑定招商银行储蓄卡",
+ "Vincular tarjeta de débito de China Merchants Bank"
+ ],
+ [
+ "首次充值",
+ "Primer recarga"
+ ],
+ [
+ "可滑动",
+ "Deslizable"
+ ],
+ [
+ "左滑编辑",
+ "Deslizar hacia la izquierda para editar"
+ ],
+ [
+ "编辑",
+ "Editar"
+ ],
+ [
+ "右滑删除",
+ "Deslizar hacia la derecha para eliminar"
+ ],
+ [
+ "账号",
+ "Cuenta"
+ ],
+ [
+ "我的订单",
+ "Mis pedidos"
+ ],
+ [
+ "我的收藏",
+ "Mis favoritos"
+ ],
+ [
+ "筛选",
+ "Filtrar"
+ ],
+ [
+ "长按项即可拖动排序",
+ "Arrastrar y ordenar presionando y manteniendo el elemento"
+ ],
+ [
+ "单列排序",
+ "Ordenar en una sola columna"
+ ],
+ [
+ "不需要长按",
+ "No es necesario presionar y mantener"
+ ],
+ [
+ "结合列表使用",
+ "Usar en combinación con la lista"
+ ],
+ [
+ "多列排序",
+ "Ordenar en múltiples columnas"
+ ],
+ [
+ "结合图片使用",
+ "Usar en combinación con la imagen"
+ ],
+ [
+ "禁用手势",
+ "Deshabilitar gestos"
+ ],
+ [
+ "自定义样式2",
+ "Estilo personalizado 2"
+ ],
+ [
+ "无图片",
+ "Sin imagen"
+ ],
+ [
+ "圆角",
+ "Esquinas redondeadas"
+ ],
+ [
+ "自定义大小",
+ "Tamaño personalizado"
+ ],
+ [
+ "省略号",
+ "Signos de puntuación"
+ ],
+ [
+ "充值1000元",
+ "Recargar 1000 yuan"
+ ],
+ [
+ "完成首笔交易",
+ "Completar la primera transacción"
+ ],
+ [
+ "优选灵活配置混合A",
+ "Mejora de configuración flexible mixta A"
+ ],
+ [
+ "1000元起",
+ "A partir de 1000 yuan"
+ ],
+ [
+ "禁用切换按钮",
+ "Deshabilitar el botón de cambio"
+ ],
+ [
+ "自定义高度",
+ "Altura personalizada"
+ ],
+ [
+ "多页数",
+ "Múltiples páginas"
+ ],
+ [
+ "上一页",
+ "Página anterior"
+ ],
+ [
+ "下一页",
+ "Página siguiente"
+ ],
+ [
+ "横向滚动",
+ "Desplazamiento horizontal"
+ ],
+ [
+ "纵向滚动",
+ "Desplazamiento vertical"
+ ],
+ [
+ "快一点",
+ "Un poco más rápido"
+ ],
+ [
+ "暂停",
+ "Pausa"
+ ],
+ [
+ "内容靠左",
+ "Contenido a la izquierda"
+ ],
+ [
+ "QQ",
+ "QQ"
+ ],
+ [
+ "带箭头",
+ "Con flecha"
+ ],
+ [
+ "余额",
+ "Saldo"
+ ],
+ [
+ "带图片",
+ "Con imagen"
+ ],
+ [
+ "神仙都没用",
+ "Ni los dioses pueden ayudar"
+ ],
+ [
+ "折叠",
+ "Desplegable"
+ ],
+ [
+ "左间隔",
+ "Intervalo izquierdo"
+ ],
+ [
+ "右移动",
+ "Movimiento hacia la derecha"
+ ],
+ [
+ "左移动",
+ "Movimiento hacia la izquierda"
+ ],
+ [
+ "多个数据",
+ "Varios datos"
+ ],
+ [
+ "点击收起",
+ "Clic para contraer"
+ ],
+ [
+ "点击展开",
+ "Clic para expandir"
+ ],
+ [
+ "ref 方式调用",
+ "Llamada mediante el método ref"
+ ],
+ [
+ "自定义图标、文字、大小",
+ "Ícono, texto y tamaño personalizados"
+ ],
+ [
+ "上传证件照",
+ "Subir foto de identificación"
+ ],
+ [
+ "多选",
+ "Selección múltiple"
+ ],
+ [
+ "限制 3 个",
+ "Límite de 3"
+ ],
+ [
+ "边框",
+ "Borde"
+ ],
+ [
+ "显示字数",
+ "Número de caracteres mostrados"
+ ],
+ [
+ "自动增高",
+ "Alto automático"
+ ],
+ [
+ "其他颜色",
+ "Otros colores"
+ ],
+ [
+ "大一点",
+ "Un poco más grande"
+ ],
+ [
+ "正方形",
+ "Cuadrado"
+ ],
+ [
+ "范围选择",
+ "Selección de rango"
+ ],
+ [
+ "显示值",
+ "Valor mostrado"
+ ],
+ [
+ "步长10",
+ "Paso de 10"
+ ],
+ [
+ "标签格式化",
+ "Formato de etiquetas"
+ ],
+ [
+ "固定开始、结束日期",
+ "Fecha de inicio y fin fijas"
+ ],
+ [
+ "自定义快捷选项",
+ "Opciones rápidas personalizadas"
+ ],
+ [
+ "只读",
+ "Solo lectura"
+ ],
+ [
+ "显示分数",
+ "Mostrar puntos"
+ ],
+ [
+ "允许半星",
+ "Permitir media estrella"
+ ],
+ [
+ "换个图标",
+ "Cambiar el icono"
+ ],
+ [
+ "纵向排列",
+ "Arreglo vertical"
+ ],
+ [
+ "换个样式",
+ "Cambiar el estilo"
+ ],
+ [
+ "不显示图标",
+ "No mostrar icono"
+ ],
+ [
+ "其他样式",
+ "Otros estilos"
+ ],
+ [
+ "数字键盘",
+ "Teclado numérico"
+ ],
+ [
+ "打开键盘",
+ "Abrir el teclado"
+ ],
+ [
+ "是否显示输入值",
+ "Mostrar el valor de entrada"
+ ],
+ [
+ "输入即绑定",
+ "Asociar al ingresar"
+ ],
+ [
+ "身份证键盘",
+ "Teclado de DNI"
+ ],
+ [
+ "密码键盘",
+ "Teclado de contraseña"
+ ],
+ [
+ "是否加密",
+ "Cifrar"
+ ],
+ [
+ "车牌号键盘",
+ "Teclado de matrícula"
+ ],
+ [
+ "数字输入",
+ "Ingreso numérico"
+ ],
+ [
+ "已阅读并同意",
+ "He leído y aceptado"
+ ],
+ [
+ "用户协议",
+ "Términos de usuario"
+ ],
+ [
+ "隐私政策",
+ "Política de privacidad"
+ ],
+ [
+ "请先阅读并同意《用户协议》和《隐私政策》",
+ "Por favor, lea y acepte los Términos de usuario y la Política de privacidad primero"
+ ],
+ [
+ "我的昵称",
+ "Mi nombre de usuario"
+ ],
+ [
+ "简介",
+ "Perfil"
+ ],
+ [
+ "介绍一下自己",
+ "Déjanos un poco de información sobre ti"
+ ],
+ [
+ "性别",
+ "Género"
+ ],
+ [
+ "编辑性别",
+ "Editar género"
+ ],
+ [
+ "生日",
+ "Fecha de nacimiento"
+ ],
+ [
+ "选择生日",
+ "Elegir fecha de nacimiento"
+ ],
+ [
+ "地区",
+ "Región"
+ ],
+ [
+ "选择所在的地区",
+ "Elegir la región donde te encuentras"
+ ],
+ [
+ "选择性别",
+ "Elegir género"
+ ],
+ [
+ "保密",
+ "Confidencial"
+ ],
+ [
+ "男",
+ "Masculino"
+ ],
+ [
+ "女",
+ "Femenino"
+ ],
+ [
+ "性别设置成功",
+ "Configuración de género exitosa"
+ ],
+ [
+ "生日设置成功",
+ "Configuración de fecha de nacimiento exitosa"
+ ],
+ [
+ "地区设置成功",
+ "Configuración de región exitosa"
+ ],
+ [
+ "垂直方向",
+ "Dirección vertical"
+ ],
+ [
+ "3秒后加载完成",
+ "Se cargará completamente después de 3 segundos"
+ ],
+ [
+ "隐藏为 00 的值",
+ "Ocultar el valor de 00"
+ ],
+ [
+ "指定天数",
+ "Días especificados"
+ ],
+ [
+ "自定义模板",
+ "Plantilla personalizada"
+ ],
+ [
+ "指定小时",
+ "Horas especificadas"
+ ],
+ [
+ "指定分钟",
+ "Minutos especificados"
+ ],
+ [
+ "指定秒",
+ "Segundos especificados"
+ ],
+ [
+ "完成后提示",
+ "Mostrar una notificación después de completar"
+ ],
+ [
+ "3秒后开始倒计时",
+ "Comenzar a contar regresivo después de 3 segundos"
+ ],
+ [
+ "结合按钮",
+ "Combinar con un botón"
+ ],
+ [
+ "购买",
+ "Comprar"
+ ],
+ [
+ "消息",
+ "Mensaje"
+ ],
+ [
+ "结合图片",
+ "Combinar con una imagen"
+ ],
+ [
+ "结合图标",
+ "Combinar con un icono"
+ ],
+ [
+ "点击触发",
+ "Activar al hacer clic"
+ ],
+ [
+ "不同大小",
+ "Tamaños diferentes"
+ ],
+ [
+ "不同颜色",
+ "Colores diferentes"
+ ],
+ [
+ "使用base64",
+ "Usar base64"
+ ],
+ [
+ "没有错误提示",
+ "No hay mensaje de error"
+ ],
+ [
+ "请输入验证码",
+ "Ingrese el código de verificación"
+ ],
+ [
+ "登录",
+ "Iniciar sesión"
+ ],
+ [
+ "购物车 ({num})",
+ "Carrito de compras ({num})"
+ ],
+ [
+ "完成",
+ "Completar"
+ ],
+ [
+ "管理",
+ "Administración"
+ ],
+ [
+ "删除",
+ "Eliminar"
+ ],
+ [
+ "全选",
+ "Seleccionar todo"
+ ],
+ [
+ "合计",
+ "Total"
+ ],
+ [
+ "去结算",
+ "Ir a pagar"
+ ],
+ [
+ "温馨提示",
+ "Advertencia amigable"
+ ],
+ [
+ "确定删除该商品吗?",
+ "¿Está seguro de eliminar este producto?"
+ ],
+ [
+ "删除成功",
+ "Eliminado con éxito"
+ ],
+ [
+ "请先选择商品",
+ "Por favor, seleccione un producto primero"
+ ],
+ [
+ "确定删除选中的商品吗?",
+ "¿Está seguro de eliminar los productos seleccionados?"
+ ],
+ [
+ "您需支付 {price} 元,请确认支付",
+ "Debe pagar {price} yuan. Confirme el pago"
+ ],
+ [
+ "支付成功",
+ "Pago exitoso"
+ ],
+ [
+ "已设为默认",
+ "Ha sido establecido como predeterminado"
+ ],
+ [
+ "设为默认",
+ "Establecer como predeterminado"
+ ],
+ [
+ "修改",
+ "Modificar"
+ ],
+ [
+ "添加地址",
+ "Agregar dirección"
+ ],
+ [
+ "Badge 角标",
+ "Badge Badge angular"
+ ],
+ [
+ "NoticeBar 通知栏",
+ "NoticeBar Barra de notificación"
+ ],
+ [
+ "Countdown 倒计时",
+ "Countdown Cuenta atrás"
+ ],
+ [
+ "Progress 进度条",
+ "Progress Barra de progreso"
+ ],
+ [
+ "ProgressCircle 圆形进度条",
+ "ProgressCircle Barra de progreso circular"
+ ],
+ [
+ "Skeleton 骨架图",
+ "Skeleton Esqueleto"
+ ],
+ [
+ "LoadMore 加载更多",
+ "LoadMore Cargar más"
+ ],
+ [
+ "RollingNumber 数字滚动",
+ "RollingNumber Número en movimiento"
+ ],
+ [
+ "ActionSheet 操作菜单",
+ "ActionSheet Menú de acciones"
+ ],
+ [
+ "Popup 弹窗",
+ "Popup Ventana emergente"
+ ],
+ [
+ "Confirm 确认框",
+ "Confirm Cuadro de confirmación"
+ ],
+ [
+ "Toast 提示框",
+ "Toast Alerta"
+ ],
+ [
+ "QRCode 二维码",
+ "QRCode Código QR"
+ ],
+ [
+ "Sign 签名",
+ "Sign Firma"
+ ],
+ [
+ "DayUts 日期",
+ "DayUts Fecha"
+ ],
+ [
+ "Vibrate 震动",
+ "Vibrate Vibración"
+ ],
+ [
+ "Cropper 图片裁剪",
+ "Cropper Corte de imágenes"
+ ],
+ [
+ "Canvas 画布",
+ "Canvas lienzo"
+ ],
+ [
+ "SVG 图标",
+ "SVG Ícono SVG"
+ ],
+ [
+ "SlideVerify 滑动验证",
+ "SlideVerify Verificación por deslizamiento"
+ ],
+ [
+ "Flex 弹性布局",
+ "Flex disposición elástica"
+ ],
+ [
+ "Tabs 标签页",
+ "Tabs pestañas"
+ ],
+ [
+ "Collapse 折叠面板",
+ "Collapse panel desplegable"
+ ],
+ [
+ "Sticky 吸顶",
+ "Sticky fijo en la parte superior"
+ ],
+ [
+ "TopBar 导航栏",
+ "TopBar barra de navegación"
+ ],
+ [
+ "FloatView 悬浮视图",
+ "FloatView vista flotante"
+ ],
+ [
+ "Footer 底部视图",
+ "Footer vista inferior"
+ ],
+ [
+ "List 列表",
+ "List lista"
+ ],
+ [
+ "ListView 列表视图",
+ "ListView vista de lista"
+ ],
+ [
+ "ListViewRefresh 列表刷新",
+ "ListViewRefresh actualización de lista"
+ ],
+ [
+ "Waterfall 瀑布流",
+ "Waterfall flujo de cascada"
+ ],
+ [
+ "Banner 轮播图",
+ "Banner diapositiva"
+ ],
+ [
+ "Marquee 跑马灯",
+ "Marquee corredor de luces"
+ ],
+ [
+ "Pagination 分页",
+ "Pagination paginación"
+ ],
+ [
+ "Timeline 时间轴",
+ "Timeline eje de tiempo"
+ ],
+ [
+ "Avatar 头像",
+ "Avatar avatar"
+ ],
+ [
+ "ReadMore 查看更多",
+ "ReadMore ver más"
+ ],
+ [
+ "Draggable 拖拽",
+ "Draggable arrastrable"
+ ],
+ [
+ "FilterBar 筛选栏",
+ "FilterBar barra de filtro"
+ ],
+ [
+ "Tree 树形结构",
+ "Tree estructura jerárquica"
+ ],
+ [
+ "多行省略号",
+ "Signos de puntos omitidos múltiples"
+ ],
+ [
+ "金额",
+ "Monto"
+ ],
+ [
+ "手机号脱敏",
+ "Desensibilización de número de teléfono móvil"
+ ],
+ [
+ "姓名脱敏",
+ "Desensibilización de nombre"
+ ],
+ [
+ "邮箱脱敏",
+ "Desensibilización de correo electrónico"
+ ],
+ [
+ "银行卡脱敏",
+ "Desensibilización de tarjeta de banco"
+ ],
+ [
+ "自定义脱敏字符",
+ "Caracteres de desensibilización personalizados"
+ ],
+ [
+ "主要",
+ "Principal"
+ ],
+ [
+ "危险",
+ "Peligro"
+ ],
+ [
+ "信息",
+ "Información"
+ ],
+ [
+ "邮件",
+ "Correo electrónico"
+ ],
+ [
+ "文件",
+ "Documento"
+ ],
+ [
+ "可关闭",
+ "Puede cerrarse"
+ ],
+ [
+ "镂空",
+ "Perforado"
+ ],
+ [
+ "自定义无圆角",
+ "Esquinas redondeadas personalizadas sin"
+ ],
+ [
+ "不同裁剪",
+ "Diferentes recortes"
+ ],
+ [
+ "点击可预览",
+ "Puede previsualizar al hacer clic"
+ ],
+ [
+ "失败时显示",
+ "Se muestra en caso de error"
+ ],
+ [
+ "自定义圆角",
+ "Esquinas redondeadas personalizadas"
+ ],
+ [
+ "设置颜色",
+ "Configurar color"
+ ],
+ [
+ "滑块大点",
+ "Botón deslizante más grande"
+ ],
+ [
+ "换个颜色",
+ "Cambiar el color"
+ ],
+ [
+ "最大50",
+ "Máximo 50"
+ ],
+ [
+ "自定义触发器",
+ "Disparador personalizado"
+ ],
+ [
+ "打开选择器",
+ "Abrir selector"
+ ],
+ [
+ "多列",
+ "Columnas múltiples"
+ ],
+ [
+ "通过 children 配置多级数据,并使用 column-count 参数指定显示的列数",
+ "Configurar datos jerárquicos a través de children y especificar el número de columnas mostradas con el parámetro column-count"
+ ],
+ [
+ "弹窗中使用",
+ "Usar en el pop-up"
+ ],
+ [
+ "打开",
+ "Abrir"
+ ],
+ [
+ "选择地区",
+ "Seleccionar región"
+ ],
+ [
+ "绑定值",
+ "Asociar valor"
+ ],
+ [
+ "下一步",
+ "Siguiente paso"
+ ],
+ [
+ "确定",
+ "Confirmar"
+ ],
+ [
+ "关闭",
+ "Cerrar"
+ ],
+ [
+ "显示取消按钮",
+ "Mostrar botón Cancelar"
+ ],
+ [
+ "修改按钮文案",
+ "Modificar el texto del botón"
+ ],
+ [
+ "显示绑定值",
+ "Mostrar el valor asociado"
+ ],
+ [
+ "时",
+ "cuando"
+ ],
+ [
+ "时:分",
+ "HH:mm"
+ ],
+ [
+ "时:分:秒",
+ "HH:mm:ss"
+ ],
+ [
+ "关于{name}",
+ "Sobre {name}"
+ ],
+ [
+ "联系客服",
+ "Contactar con el servicio al cliente"
+ ],
+ [
+ "退出登录",
+ "Cerrar sesión"
+ ],
+ [
+ "确定退出登录吗?",
+ "¿Está seguro de cerrar la sesión?"
+ ],
+ [
+ "深色模式",
+ "Modo oscuro"
+ ],
+ [
+ "多语言",
+ "Multiidioma"
+ ],
+ [
+ "字体大小",
+ "Tamaño de fuente"
+ ],
+ [
+ "访问官网",
+ "Acceder a la página web oficial"
+ ],
+ [
+ "商城",
+ "Tienda"
+ ],
+ [
+ "商品分类",
+ "Clasificación de productos"
+ ],
+ [
+ "商品详情",
+ "Detalle del producto"
+ ],
+ [
+ "商品列表、筛选",
+ "Lista de productos, filtrado"
+ ],
+ [
+ "购物车",
+ "Carrito de compras"
+ ],
+ [
+ "订单列表、详情",
+ "Lista de pedidos, detalles"
+ ],
+ [
+ "收货地址",
+ "Dirección de entrega"
+ ],
+ [
+ "聊天",
+ "Chat"
+ ],
+ [
+ "对话列表、历史记录",
+ "Lista de conversaciones, historial"
+ ],
+ [
+ "流式回复",
+ "Respuesta fluida"
+ ],
+ [
+ "语言合成",
+ "Síntesis de voz"
+ ],
+ [
+ "语音识别",
+ "Reconocimiento de voz"
+ ],
+ [
+ "支付失败",
+ "Pago fallido"
+ ],
+ [
+ "授权信息仅用于用户登录",
+ "La información de autorización solo se utiliza para la autenticación de usuario"
+ ],
+ [
+ "登录授权失败",
+ "Fallo en la autorización de inicio de sesión"
+ ],
+ [
+ "获取短信验证码",
+ "Obtener código de verificación de SMS"
+ ],
+ [
+ "验证码",
+ "Código de verificación"
+ ],
+ [
+ "发送短信",
+ "Enviar SMS"
+ ],
+ [
+ "{n}s后重新获取",
+ "Reintentar en {n} s"
+ ],
+ [
+ "获取验证码",
+ "Obtener código de verificación"
+ ],
+ [
+ "短信已发送,请查收",
+ "El SMS ha sido enviado, por favor revise"
+ ],
+ [
+ "请填写验证码",
+ "Por favor ingrese el código de verificación"
+ ],
+ [
+ "请填写正确的手机号格式",
+ "Por favor ingrese un número de teléfono válido"
+ ],
+ [
+ "全局字号",
+ "Tamaño de fuente global"
+ ],
+ [
+ "这是一段示例文字,用于预览不同字号的效果。",
+ "Este es un texto de muestra para previsualizar los efectos de diferentes tamaños de fuente."
+ ],
+ [
+ "默认 1.0",
+ "Predeterminado 1.0"
+ ],
+ [
+ "切换语言",
+ "Cambiar idioma"
+ ],
+ [
+ "切换中",
+ "Cambiando"
+ ],
+ [
+ "模板",
+ "Plantilla"
+ ],
+ [
+ "编辑资料",
+ "Editar información"
+ ],
+ [
+ "Text 文本",
+ "Texto"
+ ],
+ [
+ "Button 按钮",
+ "Botón"
+ ],
+ [
+ "无头",
+ "Sin cabeza"
+ ],
+ [
+ "左侧",
+ "Izquierda"
+ ],
+ [
+ "右侧",
+ "Derecha"
+ ],
+ [
+ "隐藏取消按钮",
+ "Ocultar botón de cancelación"
+ ],
+ [
+ "自定义文本",
+ "Texto personalizado"
+ ],
+ [
+ "关闭前钩子",
+ "Hook antes de cerrar"
+ ],
+ [
+ "显示时长",
+ "Duración de visualización"
+ ],
+ [
+ "确定要删除吗?",
+ "¿Está seguro de eliminar?"
+ ],
+ [
+ "确定要删除吗?3秒后自动关闭",
+ "Se cerrará automáticamente después de 3 segundos si desea eliminar"
+ ],
+ [
+ "带标题、描述",
+ "Con título y descripción"
+ ],
+ [
+ "无法点击遮罩关闭",
+ "No se puede cerrar haciendo clic en el recuadro de cobertura"
+ ],
+ [
+ "不需要取消按钮",
+ "No se necesita botón de cancelación"
+ ],
+ [
+ "插槽用法",
+ "Uso de ranura"
+ ],
+ [
+ "反馈",
+ "Retroalimentación"
+ ],
+ [
+ "删除好友会同时删除所有聊天记录",
+ "Al eliminar un amigo, se eliminarán todos los registros de chat"
+ ],
+ [
+ "删除好友",
+ "Eliminar amigo"
+ ],
+ [
+ "确定要删除好友吗?",
+ "¿Está seguro de eliminar el amigo?"
+ ],
+ [
+ "点我关闭",
+ "Haga clic aquí para cerrar"
+ ],
+ [
+ "确定要关闭吗?",
+ "¿Está seguro de cerrar?"
+ ],
+ [
+ "支付宝",
+ "Alipay"
+ ],
+ [
+ "获取某个单位的结束时间",
+ "Obtener la hora de finalización de una unidad"
+ ],
+ [
+ "是否同一天",
+ "¿Es el mismo día?"
+ ],
+ [
+ "是否早于",
+ "¿Es anterior a?"
+ ],
+ [
+ "是否晚于",
+ "¿Es posterior a?"
+ ],
+ [
+ "差值",
+ "Diferencia"
+ ],
+ [
+ "差值(单位)",
+ "Diferencia (unidad)"
+ ],
+ [
+ "选择图片",
+ "Seleccionar imagen"
+ ],
+ [
+ "可调节裁剪框大小",
+ "Tamaño del recuadro de recorte ajustable"
+ ],
+ [
+ "预览图片",
+ "Vista previa de la imagen"
+ ],
+ [
+ "保存图片",
+ "Guardar imagen"
+ ],
+ [
+ "本页面内容由 canvas 渲染生成,是否立即预览图片效果?",
+ "El contenido de esta página se renderiza con canvas. ¿Desea previsualizar inmediatamente los efectos de la imagen?"
+ ],
+ [
+ "基础动画",
+ "Animación básica"
+ ],
+ [
+ "淡入淡出",
+ "Fade in/out"
+ ],
+ [
+ "播放动画",
+ "Reproducir animación"
+ ],
+ [
+ "滑入",
+ "Deslizar hacia dentro"
+ ],
+ [
+ "旋转翻转",
+ "Rotar y voltear"
+ ],
+ [
+ "摇摆抖动",
+ "Oscilar y temblar"
+ ],
+ [
+ "特殊效果",
+ "Efectos especiales"
+ ],
+ [
+ "组合动画",
+ "Animación combinada"
+ ],
+ [
+ "标题",
+ "Título"
+ ],
+ [
+ "Image 图片",
+ "Imagen Imagen"
+ ],
+ [
+ "Icon 图标",
+ "Icono Icono"
+ ],
+ [
+ "Tag 标签",
+ "Etiqueta Etiqueta"
+ ],
+ [
+ "Form 表单验证",
+ "Validación de formulario Validación de formulario"
+ ],
+ [
+ "Input 输入框",
+ "Campo de entrada Campo de entrada"
+ ],
+ [
+ "Textarea 文本域",
+ "Área de texto Área de texto"
+ ],
+ [
+ "InputNumber 计数器",
+ "Contador Contador"
+ ],
+ [
+ "InputOtp 口令输入",
+ "Entrada de código de autenticación Entrada de código de autenticación"
+ ],
+ [
+ "Keyboard 键盘",
+ "Teclado Teclado"
+ ],
+ [
+ "Radio 单选框",
+ "Botón de opción única Botón de opción única"
+ ],
+ [
+ "Checkbox 多选框",
+ "Casilla de verificación múltiple Casilla de verificación múltiple"
+ ],
+ [
+ "Switch 开关",
+ "Interruptor Interruptor"
+ ],
+ [
+ "Rate 评分",
+ "Evaluación Evaluación"
+ ],
+ [
+ "Slider 滑块",
+ "Deslizador Deslizador"
+ ],
+ [
+ "Select 选择器",
+ "Selector Selector"
+ ],
+ [
+ "SelectDate 日期选择器",
+ "Selector de fecha Selector de fecha"
+ ],
+ [
+ "SelectTime 时间选择器",
+ "Selector de hora Selector de hora"
+ ],
+ [
+ "Cascader 级联选择器",
+ "Selector en cascada Selector en cascada"
+ ],
+ [
+ "Upload 文件上传",
+ "Carga de archivos Carga de archivos"
+ ],
+ [
+ "Calendar 日历",
+ "Calendario Calendario"
+ ],
+ [
+ "删除地址后无法恢复,确认要删除该地址吗?",
+ "No se puede recuperar la dirección después de eliminarla. ¿Está seguro de querer eliminar esta dirección?"
+ ],
+ [
+ "加载中",
+ "Cargando..."
+ ],
+ [
+ "收货人",
+ "Receptor"
+ ],
+ [
+ "请输入收货人姓名",
+ "Por favor, ingrese el nombre del receptor"
+ ],
+ [
+ "手机号",
+ "Número de teléfono móvil"
+ ],
+ [
+ "选择省市区",
+ "Seleccione provincia, ciudad y distrito"
+ ],
+ [
+ "详细地址",
+ "Dirección detallada"
+ ],
+ [
+ "小区楼栋、门牌号、村等",
+ "Edificio, número de puerta, pueblo, etc."
+ ],
+ [
+ "默认地址",
+ "Dirección predeterminada"
+ ],
+ [
+ "保存",
+ "Guardar"
+ ],
+ [
+ "收货人不能为空",
+ "El receptor no puede estar vacío"
+ ],
+ [
+ "手机号不能为空",
+ "El número de teléfono móvil no puede estar vacío"
+ ],
+ [
+ "手机号格式不正确",
+ "El formato del número de teléfono móvil es incorrecto"
+ ],
+ [
+ "详细地址不能为空",
+ "La dirección detallada no puede estar vacía"
+ ],
+ [
+ "所在地区不能为空",
+ "La región donde se encuentra no puede estar vacía"
+ ],
+ [
+ "保存中",
+ "Guardando..."
+ ],
+ [
+ "开启通知",
+ "Activar notificaciones"
+ ],
+ [
+ "通用设置",
+ "Configuración general"
+ ],
+ [
+ "通知设置",
+ "Configuración de notificaciones"
+ ],
+ [
+ "隐私设置",
+ "Configuración de privacidad"
+ ],
+ [
+ "插槽",
+ "Ranura"
+ ],
+ [
+ "使用 PT 自定义颜色",
+ "Personalizar color con PT"
+ ],
+ [
+ "自定义返回图标",
+ "Personalizar icono de retorno"
+ ],
+ [
+ "自定义返回路径",
+ "Personalizar ruta de retorno"
+ ],
+ [
+ "自定义标题内容",
+ "Personalizar contenido del título"
+ ],
+ [
+ "显示滑块",
+ "Mostrar deslizador"
+ ],
+ [
+ "添加间距",
+ "Agregar espacio"
+ ],
+ [
+ "横向填充",
+ "Relleno horizontal"
+ ],
+ [
+ "适用于标签数量不多的情况",
+ "Aplicable para casos con pocos etiquetas"
+ ],
+ [
+ "居中",
+ "Centrado"
+ ],
+ [
+ "单个禁用",
+ "Deshabilitado individualmente"
+ ],
+ [
+ "显示下划线",
+ "Mostrar subrayado"
+ ],
+ [
+ "禁用",
+ "Deshabilitado"
+ ],
+ [
+ "取消订单",
+ "Cancelar pedido"
+ ],
+ [
+ "立即购买",
+ "Comprar ahora"
+ ],
+ [
+ "确认收货",
+ "Confirmar recepción"
+ ],
+ [
+ "评价",
+ "Evaluar"
+ ],
+ [
+ "禁用状态,无法拖拽",
+ "Estado deshabilitado, no se puede arrastrar"
+ ],
+ [
+ "不吸附边缘,任意位置可拖拽",
+ "No se adhiere a los bordes, se puede arrastrar a cualquier posición"
+ ],
+ [
+ "这是一个提示",
+ "Este es un mensaje"
+ ],
+ [
+ "体重不能为空",
+ "El peso no puede estar vacío"
+ ],
+ [
+ "体重在40-100kg之间",
+ "El peso debe estar entre 40 y 100 kg"
+ ],
+ [
+ "标签不能为空",
+ "La etiqueta no puede estar vacía"
+ ],
+ [
+ "标签最多选择2个",
+ "Máximo 2 etiquetas seleccionadas"
+ ],
+ [
+ "性别不能为空",
+ "El género no puede estar vacío"
+ ],
+ [
+ "出生年月不能为空",
+ "La fecha de nacimiento no puede estar vacía"
+ ],
+ [
+ "出生年月不大于2010-01-01",
+ "La fecha de nacimiento no puede ser posterior a 2010-01-01"
+ ],
+ [
+ "联系人不能为空",
+ "El contacto no puede estar vacío"
+ ],
+ [
+ "提交成功",
+ "Envío exitoso"
+ ],
+ [
+ "单个 true / false",
+ "Individual true / false"
+ ],
+ [
+ "带索引、地区选择",
+ "Con índice, selección de región"
+ ],
+ [
+ "换个分隔符",
+ "Cambia el separador"
+ ],
+ [
+ "列表高度小一点",
+ "Menor altura de la lista"
+ ],
+ [
+ "范围选",
+ "Selección de rango"
+ ],
+ [
+ "禁用部分日期",
+ "Parcialmente deshabilitado"
+ ],
+ [
+ "日历长列表",
+ "Lista larga del calendario"
+ ],
+ [
+ "打开日历长列表",
+ "Abre la lista larga del calendario"
+ ],
+ [
+ "日历面板",
+ "Panel del calendario"
+ ],
+ [
+ "自定义文案和颜色",
+ "Personaliza el texto y el color"
+ ],
+ [
+ "显示头",
+ "Muestra la cabecera"
+ ],
+ [
+ "头像上传成功",
+ "La carga de avatar se realizó con éxito"
+ ],
+ [
+ "编辑昵称",
+ "Editar nombre de usuario"
+ ],
+ [
+ "请输入昵称",
+ "Ingrese su nombre de usuario"
+ ],
+ [
+ "请设置2-20个字符,不包括@<>/等无效字符",
+ "Por favor, configure 2-20 caracteres, excluyendo caracteres no válidos como @<>/"
+ ],
+ [
+ "确认",
+ "Confirmar"
+ ],
+ [
+ "昵称长度需在2-20个字符之间",
+ "La longitud del nombre de usuario debe estar entre 2 y 20 caracteres"
+ ],
+ [
+ "昵称不能包含@<>/等特殊字符",
+ "El nombre de usuario no puede contener caracteres especiales como @<>/"
+ ],
+ [
+ "编辑简介",
+ "Editar biografía"
+ ],
+ [
+ "简介不能为空",
+ "La biografía no puede estar vacía"
+ ],
+ [
+ "提示",
+ "Sugerencia"
+ ],
+ [
+ "为提供更好的服务,我们邀请您填写昵称、头像等公开信息",
+ "Para brindar un mejor servicio, le invitamos a llenar información pública como nombre de usuario y avatar"
+ ],
+ [
+ "头像",
+ "Avatar"
+ ],
+ [
+ "昵称",
+ "Nombre de usuario"
+ ],
+ [
+ "点击输入昵称",
+ "Haga clic para ingresar su nombre de usuario"
+ ],
+ [
+ "取消",
+ "Cancelar"
+ ],
+ [
+ "请上传头像",
+ "Por favor, cargue un avatar"
+ ],
+ [
+ "登录中",
+ "Iniciando sesión"
+ ],
+ [
+ "手机登录",
+ "Inicio de sesión con teléfono móvil"
+ ],
+ [
+ "未注册的手机号登录成功后将自动注册",
+ "Un número de teléfono no registrado se registrará automáticamente después de iniciar sesión con éxito"
+ ],
+ [
+ "请输入手机号",
+ "Ingrese su número de teléfono"
+ ]
+]
\ No newline at end of file
diff --git a/cool-unix/locale/fr.json b/cool-unix/locale/fr.json
new file mode 100644
index 0000000..3d6e0f7
--- /dev/null
+++ b/cool-unix/locale/fr.json
@@ -0,0 +1,2502 @@
+[
+ [
+ "Animation 动画",
+ "Animation"
+ ],
+ [
+ "编辑地址",
+ "Adresse d'édition"
+ ],
+ [
+ "cool-unix",
+ "cool-unix"
+ ],
+ [
+ "首页",
+ "Page d'accueil"
+ ],
+ [
+ "我的",
+ "Moi"
+ ],
+ [
+ "开发中,敬请期待",
+ "En développement, veuillez patienter"
+ ],
+ [
+ "基础组件",
+ "Composants de base"
+ ],
+ [
+ "文本",
+ "Texte"
+ ],
+ [
+ "按钮",
+ "Bouton"
+ ],
+ [
+ "图片",
+ "Image"
+ ],
+ [
+ "图标",
+ "Icône"
+ ],
+ [
+ "标签",
+ "Étiquette"
+ ],
+ [
+ "表单组件",
+ "Composants de formulaire"
+ ],
+ [
+ "表单验证",
+ "Validation de formulaire"
+ ],
+ [
+ "输入框",
+ "Zone de texte"
+ ],
+ [
+ "文本域",
+ "Champ de texte"
+ ],
+ [
+ "计数器",
+ "Compteur"
+ ],
+ [
+ "口令输入",
+ "Entrée de mot de passe"
+ ],
+ [
+ "键盘",
+ "Clavier"
+ ],
+ [
+ "单选框",
+ "Case à cocher"
+ ],
+ [
+ "多选框",
+ "Cases à cocher multiples"
+ ],
+ [
+ "开关",
+ "Commutateur"
+ ],
+ [
+ "评分",
+ "Évaluation"
+ ],
+ [
+ "滑块",
+ "Curseur"
+ ],
+ [
+ "选择器",
+ "Sélecteur"
+ ],
+ [
+ "其他",
+ "Autre"
+ ],
+ [
+ "文件管理",
+ "Gestion de fichiers"
+ ],
+ [
+ "该模板正在开发中",
+ "Ce modèle est en cours de développement"
+ ],
+ [
+ "未登录",
+ "Non connecté"
+ ],
+ [
+ "总点击",
+ "Total de clics"
+ ],
+ [
+ "赞",
+ "J'aime"
+ ],
+ [
+ "收藏",
+ "Favoris"
+ ],
+ [
+ "粉丝",
+ "Abonnés"
+ ],
+ [
+ "接单模式",
+ "Mode de prise de commandes"
+ ],
+ [
+ "已关闭",
+ "Fermé"
+ ],
+ [
+ "消息通知",
+ "Notifications de messages"
+ ],
+ [
+ "待支付",
+ "En attente de paiement"
+ ],
+ [
+ "未发货",
+ "Non expédié"
+ ],
+ [
+ "已发货",
+ "Expédié"
+ ],
+ [
+ "售后 / 退款",
+ "Après-vente / Remboursement"
+ ],
+ [
+ "我的钱包",
+ "Mon porte-monnaie"
+ ],
+ [
+ "数据看板",
+ "Tableau de bord de données"
+ ],
+ [
+ "历史记录",
+ "Historique"
+ ],
+ [
+ "邀请好友",
+ "Inviter des amis"
+ ],
+ [
+ "设置",
+ "Paramètres"
+ ],
+ [
+ "转动图片",
+ "Tourner l'image"
+ ],
+ [
+ "验证通过",
+ "Validation réussie"
+ ],
+ [
+ "验证失败",
+ "Validation échouée"
+ ],
+ [
+ "操作",
+ "Opération"
+ ],
+ [
+ "清空",
+ "Vider"
+ ],
+ [
+ "预览",
+ "Aperçu"
+ ],
+ [
+ "设置高度",
+ "Définir la hauteur"
+ ],
+ [
+ "毛笔效果",
+ "Effet de pinceau"
+ ],
+ [
+ "添加LOGO",
+ "Ajouter un logo"
+ ],
+ [
+ "圆角定位点",
+ "Point d'ancrage arrondi"
+ ],
+ [
+ "内间距",
+ "Espacement intérieur"
+ ],
+ [
+ "导出图片",
+ "Exporter l'image"
+ ],
+ [
+ "矩形",
+ "Rectangle"
+ ],
+ [
+ "点",
+ "Point"
+ ],
+ [
+ "线性",
+ "Linéaire"
+ ],
+ [
+ "小方格",
+ "Petits carrés"
+ ],
+ [
+ "格式化",
+ "Formatage"
+ ],
+ [
+ "添加",
+ "Ajouter"
+ ],
+ [
+ "减去",
+ "Soustraire"
+ ],
+ [
+ "获取某个单位的开始时间",
+ "Obtenir l'heure de début d'une unité"
+ ],
+ [
+ "跑马灯",
+ "Feux de circulation"
+ ],
+ [
+ "分页",
+ "Pagination"
+ ],
+ [
+ "时间轴",
+ "Axe temporel"
+ ],
+ [
+ "拖拽",
+ "Drag and drop"
+ ],
+ [
+ "筛选栏",
+ "Barre de filtrage"
+ ],
+ [
+ "树形结构",
+ "Structure arborescente"
+ ],
+ [
+ "状态组件",
+ "Composant d'état"
+ ],
+ [
+ "角标",
+ "Badge"
+ ],
+ [
+ "通知栏",
+ "Barre de notification"
+ ],
+ [
+ "倒计时",
+ "Compte à rebours"
+ ],
+ [
+ "数字滚动",
+ "Rotation numérique"
+ ],
+ [
+ "进度条",
+ "Barre de progression"
+ ],
+ [
+ "圆形进度条",
+ "Barre de progression circulaire"
+ ],
+ [
+ "骨架图",
+ "Schéma d'ossature"
+ ],
+ [
+ "加载更多",
+ "Charger plus"
+ ],
+ [
+ "反馈组件",
+ "Composant de retour"
+ ],
+ [
+ "操作菜单",
+ "Menu d'opérations"
+ ],
+ [
+ "弹窗",
+ "Pop-up"
+ ],
+ [
+ "确认框",
+ "Boîte de confirmation"
+ ],
+ [
+ "提示框",
+ "Boîte de message"
+ ],
+ [
+ "签名",
+ "Signature"
+ ],
+ [
+ "图片裁剪",
+ "Redimensionnement d'image"
+ ],
+ [
+ "Canvas",
+ "Canvas"
+ ],
+ [
+ "富文本",
+ "Texte riche"
+ ],
+ [
+ "该功能正在开发中",
+ "Cette fonction est en cours de développement"
+ ],
+ [
+ "圆形",
+ "Cercle"
+ ],
+ [
+ "组合",
+ "Groupe"
+ ],
+ [
+ "基础用法",
+ "Utilisation de base"
+ ],
+ [
+ "自定义",
+ "Personnalisé"
+ ],
+ [
+ "加快滚动速度",
+ "Accélérer la vitesse de défilement"
+ ],
+ [
+ "显示小数位数",
+ "Nombre de décimales affichées"
+ ],
+ [
+ "自定义样式",
+ "Style personnalisé"
+ ],
+ [
+ "自定义颜色",
+ "Couleur personnalisée"
+ ],
+ [
+ "自定义宽度",
+ "Largeur personnalisée"
+ ],
+ [
+ "不显示文本",
+ "Ne pas afficher le texte"
+ ],
+ [
+ "改个颜色",
+ "Changer de couleur"
+ ],
+ [
+ "显示文本",
+ "Afficher le texte"
+ ],
+ [
+ "快一些",
+ "Plus rapide"
+ ],
+ [
+ "带图标",
+ "Avec icône"
+ ],
+ [
+ "设置速度",
+ "Réglage de la vitesse"
+ ],
+ [
+ "充值1000元",
+ "Recharger 1000 yuans"
+ ],
+ [
+ "完成首笔交易",
+ "Compléter la première transaction"
+ ],
+ [
+ "优选灵活配置混合A",
+ "Mixte A de configuration flexible privilégiée"
+ ],
+ [
+ "1000元起",
+ "À partir de 1000 yuans"
+ ],
+ [
+ "禁用切换按钮",
+ "Désactiver le bouton de basculement"
+ ],
+ [
+ "自定义高度",
+ "Hauteur personnalisée"
+ ],
+ [
+ "多页数",
+ "Plusieurs pages"
+ ],
+ [
+ "上一页",
+ "Page précédente"
+ ],
+ [
+ "下一页",
+ "Page suivante"
+ ],
+ [
+ "横向滚动",
+ "Défilement horizontal"
+ ],
+ [
+ "纵向滚动",
+ "Défilement vertical"
+ ],
+ [
+ "快一点",
+ "Plus vite"
+ ],
+ [
+ "暂停",
+ "Pause"
+ ],
+ [
+ "内容靠左",
+ "Contenu à gauche"
+ ],
+ [
+ "QQ",
+ "QQ"
+ ],
+ [
+ "带箭头",
+ "Avec flèche"
+ ],
+ [
+ "余额",
+ "Solde"
+ ],
+ [
+ "带图片",
+ "Avec image"
+ ],
+ [
+ "神仙都没用",
+ "Même les dieux ne peuvent rien faire"
+ ],
+ [
+ "折叠",
+ "Détacher"
+ ],
+ [
+ "关于{name}",
+ "À propos de {name}"
+ ],
+ [
+ "联系客服",
+ "Contacter le service client"
+ ],
+ [
+ "退出登录",
+ "Se déconnecter"
+ ],
+ [
+ "确定退出登录吗?",
+ "Êtes-vous sûr de vouloir vous déconnecter?"
+ ],
+ [
+ "深色模式",
+ "Mode foncé"
+ ],
+ [
+ "多语言",
+ "Plusieurs langues"
+ ],
+ [
+ "字体大小",
+ "Taille de police"
+ ],
+ [
+ "访问官网",
+ "Accéder au site web officiel"
+ ],
+ [
+ "商城",
+ "Magasin"
+ ],
+ [
+ "商品分类",
+ "Catégies de produits"
+ ],
+ [
+ "商品详情",
+ "Détails des produits"
+ ],
+ [
+ "商品列表、筛选",
+ "Liste et filtrage des produits"
+ ],
+ [
+ "购物车",
+ "Panier"
+ ],
+ [
+ "订单列表、详情",
+ "Liste et détails des commandes"
+ ],
+ [
+ "收货地址",
+ "Adresse de livraison"
+ ],
+ [
+ "聊天",
+ "Chat"
+ ],
+ [
+ "对话列表、历史记录",
+ "Liste et historique des conversations"
+ ],
+ [
+ "流式回复",
+ "Réponse en flux"
+ ],
+ [
+ "语言合成",
+ "Synthese vocale"
+ ],
+ [
+ "语音识别",
+ "Reconnaissance vocale"
+ ],
+ [
+ "密码输入",
+ "Entrée de mot de passe"
+ ],
+ [
+ "可清除",
+ "可清除"
+ ],
+ [
+ "左右插槽",
+ "Emplacements gauche et droit"
+ ],
+ [
+ "左图标",
+ "Icône gauche"
+ ],
+ [
+ "右图标",
+ "Icône droite"
+ ],
+ [
+ "自动聚焦",
+ "Focus automatique"
+ ],
+ [
+ "长度为6",
+ "Longueur de 6"
+ ],
+ [
+ "步进为10",
+ "Pas de 10"
+ ],
+ [
+ "最小为10",
+ "Minimum de 10"
+ ],
+ [
+ "最大为50",
+ "Maximum de 50"
+ ],
+ [
+ "可以小数",
+ "Avec décimales"
+ ],
+ [
+ "可以输入",
+ "Peut être entré"
+ ],
+ [
+ "用户名",
+ "Nom d'utilisateur"
+ ],
+ [
+ "请输入用户名",
+ "Veuillez entrer votre nom d'utilisateur"
+ ],
+ [
+ "邮箱",
+ "Courriel"
+ ],
+ [
+ "请输入邮箱地址",
+ "Veuillez entrer votre adresse de courriel"
+ ],
+ [
+ "动态验证",
+ "Validation dynamique"
+ ],
+ [
+ "联系人",
+ "Contact"
+ ],
+ [
+ "添加联系人",
+ "Ajouter un contact"
+ ],
+ [
+ "身高",
+ "Taille"
+ ],
+ [
+ "已阅读并同意",
+ "Lu et accepté"
+ ],
+ [
+ "用户协议",
+ "Conditions d'utilisation"
+ ],
+ [
+ "隐私政策",
+ "Politique de confidentialité"
+ ],
+ [
+ "请先阅读并同意《用户协议》和《隐私政策》",
+ "Veuillez lire et accepter les Conditions d'utilisation et la Politique de confidentialité avant de continuer"
+ ],
+ [
+ "我的昵称",
+ "Mon pseudo"
+ ],
+ [
+ "简介",
+ "Présentation"
+ ],
+ [
+ "介绍一下自己",
+ "Décris-toi"
+ ],
+ [
+ "性别",
+ "Genre"
+ ],
+ [
+ "编辑性别",
+ "Modifier le genre"
+ ],
+ [
+ "生日",
+ "Date de naissance"
+ ],
+ [
+ "选择生日",
+ "Choisir la date de naissance"
+ ],
+ [
+ "地区",
+ "Région"
+ ],
+ [
+ "选择所在的地区",
+ "Choisir la région"
+ ],
+ [
+ "选择性别",
+ "Choisir le genre"
+ ],
+ [
+ "保密",
+ "Confidentiel"
+ ],
+ [
+ "男",
+ "Homme"
+ ],
+ [
+ "女",
+ "Femme"
+ ],
+ [
+ "性别设置成功",
+ "Configuration du genre réussie"
+ ],
+ [
+ "生日设置成功",
+ "Configuration de la date de naissance réussie"
+ ],
+ [
+ "地区设置成功",
+ "Configuration de la région réussie"
+ ],
+ [
+ "Flex 弹性布局",
+ "Flex disposition élastique"
+ ],
+ [
+ "Tabs 标签页",
+ "Onglets"
+ ],
+ [
+ "Collapse 折叠面板",
+ "Panneau rabattable"
+ ],
+ [
+ "Sticky 吸顶",
+ "Collant"
+ ],
+ [
+ "TopBar 导航栏",
+ "Barre de navigation"
+ ],
+ [
+ "FloatView 悬浮视图",
+ "Vue flottante"
+ ],
+ [
+ "Footer 底部视图",
+ "Pied de page"
+ ],
+ [
+ "List 列表",
+ "Liste"
+ ],
+ [
+ "ListView 列表视图",
+ "Vue de liste"
+ ],
+ [
+ "ListViewRefresh 列表刷新",
+ "Actualisation de la vue de liste"
+ ],
+ [
+ "Waterfall 瀑布流",
+ "Moulin à eau"
+ ],
+ [
+ "Banner 轮播图",
+ "Bannière"
+ ],
+ [
+ "Marquee 跑马灯",
+ "Lumière de course"
+ ],
+ [
+ "Pagination 分页",
+ "Pagination"
+ ],
+ [
+ "Timeline 时间轴",
+ "Axe temporel"
+ ],
+ [
+ "Avatar 头像",
+ "Avatar"
+ ],
+ [
+ "ReadMore 查看更多",
+ "Voir plus"
+ ],
+ [
+ "Draggable 拖拽",
+ "Draguable"
+ ],
+ [
+ "FilterBar 筛选栏",
+ "Barre de filtrage"
+ ],
+ [
+ "Tree 树形结构",
+ "Structure arborescente"
+ ],
+ [
+ "左间隔",
+ "Intervalle gauche"
+ ],
+ [
+ "右移动",
+ "Décalage droit"
+ ],
+ [
+ "左移动",
+ "Décalage gauche"
+ ],
+ [
+ "多个数据",
+ "Plusieurs données"
+ ],
+ [
+ "点击收起",
+ "Cliquez pour réduire"
+ ],
+ [
+ "点击展开",
+ "Cliquez pour déplier"
+ ],
+ [
+ "ref 方式调用",
+ "Appel par la méthode ref"
+ ],
+ [
+ "自定义图标、文字、大小",
+ "Icône personnalisée, texte, taille"
+ ],
+ [
+ "上传证件照",
+ "Téléchargez une photo d'identité"
+ ],
+ [
+ "多选",
+ "Sélection multiple"
+ ],
+ [
+ "限制 3 个",
+ "Limité à 3"
+ ],
+ [
+ "边框",
+ "Cadre"
+ ],
+ [
+ "显示字数",
+ "Nombre de caractères affichés"
+ ],
+ [
+ "自动增高",
+ "Augmentation automatique"
+ ],
+ [
+ "其他颜色",
+ "Couleur autre"
+ ],
+ [
+ "大一点",
+ "Plus grand"
+ ],
+ [
+ "正方形",
+ "Carré"
+ ],
+ [
+ "范围选择",
+ "Sélection de plage"
+ ],
+ [
+ "显示值",
+ "Valeur affichée"
+ ],
+ [
+ "步长10",
+ "Pas de 10"
+ ],
+ [
+ "显示星期",
+ "Afficher la semaine"
+ ],
+ [
+ "显示其他月份",
+ "Afficher les autres mois"
+ ],
+ [
+ "不同位置",
+ "Différentes positions"
+ ],
+ [
+ "顶部",
+ "Haut"
+ ],
+ [
+ "中间",
+ "Milieu"
+ ],
+ [
+ "底部",
+ "Bas"
+ ],
+ [
+ "不同类型",
+ "Différents types"
+ ],
+ [
+ "成功",
+ "Succès"
+ ],
+ [
+ "失败",
+ "Erreur"
+ ],
+ [
+ "警告",
+ "Avertissement"
+ ],
+ [
+ "问题",
+ "Problème"
+ ],
+ [
+ "停止",
+ "Arrêter"
+ ],
+ [
+ "自定义图标",
+ "Icône personnalisée"
+ ],
+ [
+ "只存在一个",
+ "Il n'y a qu'un seul"
+ ],
+ [
+ "不同位置提示",
+ "Avertissement de position différente"
+ ],
+ [
+ "不同类型提示",
+ "Avertissement de type différent"
+ ],
+ [
+ "带图标提示",
+ "Avertissement avec icône"
+ ],
+ [
+ "移除其他已存在的提示",
+ "Supprimer les autres avertissements existants"
+ ],
+ [
+ "打开弹窗",
+ "Ouvrir une fenêtre modale"
+ ],
+ [
+ "设置宽度 80%",
+ "Définir la largeur à 80%"
+ ],
+ [
+ "日期选择器",
+ "Sélecteur de date"
+ ],
+ [
+ "时间选择器",
+ "Sélecteur d'heure"
+ ],
+ [
+ "级联选择器",
+ "Sélecteur en cascade"
+ ],
+ [
+ "文件上传",
+ "Téléchargement de fichiers"
+ ],
+ [
+ "日历",
+ "Calendrier"
+ ],
+ [
+ "布局组件",
+ "Composant de mise en page"
+ ],
+ [
+ "弹性布局",
+ "Mise en page flexible"
+ ],
+ [
+ "标签页",
+ "Onglets"
+ ],
+ [
+ "折叠面板",
+ "Panneau pliable"
+ ],
+ [
+ "吸顶",
+ "Fixation au sommet"
+ ],
+ [
+ "导航栏",
+ "Barre de navigation"
+ ],
+ [
+ "底部视图",
+ "Vue de bas"
+ ],
+ [
+ "悬浮视图",
+ "Vue flottante"
+ ],
+ [
+ "数据展示",
+ "Affichage de données"
+ ],
+ [
+ "查看更多",
+ "Voir plus"
+ ],
+ [
+ "列表",
+ "Liste"
+ ],
+ [
+ "列表视图",
+ "Vue de liste"
+ ],
+ [
+ "列表刷新",
+ "Rafraîchissement de liste"
+ ],
+ [
+ "瀑布流",
+ "Mouvement de défilement"
+ ],
+ [
+ "轮播图",
+ "Diaporama"
+ ],
+ [
+ "设置大小",
+ "Réglage de la taille"
+ ],
+ [
+ "集成 iconfont 与 remixicon 图标库,展示部分示例",
+ "Intégration des bibliothèques d'icônes iconfont et remixicon, présentation de quelques exemples"
+ ],
+ [
+ "iconfont",
+ "iconfont"
+ ],
+ [
+ "remixicon",
+ "remixicon"
+ ],
+ [
+ "复制成功",
+ "Copie réussie"
+ ],
+ [
+ "普通",
+ "Ordinaire"
+ ],
+ [
+ "浅色",
+ "Clair"
+ ],
+ [
+ "深色",
+ "Foncé"
+ ],
+ [
+ "只显示图标",
+ "Afficher seulement les icônes"
+ ],
+ [
+ "文本模式",
+ "Mode texte"
+ ],
+ [
+ "带边框",
+ "Avec bordure"
+ ],
+ [
+ "圆角按钮",
+ "Bouton arrondi"
+ ],
+ [
+ "带左侧图标",
+ "Avec icône à gauche"
+ ],
+ [
+ "小",
+ "Petit"
+ ],
+ [
+ "默认",
+ "Par défaut"
+ ],
+ [
+ "大",
+ "Grand"
+ ],
+ [
+ "无权限",
+ "Pas autorisé"
+ ],
+ [
+ "服务异常",
+ "Exception de service"
+ ],
+ [
+ "请在微信浏览器中打开",
+ "Veuillez ouvrir dans le navigateur WeChat"
+ ],
+ [
+ "已取消支付",
+ "Paiement annulé"
+ ],
+ [
+ "垂直方向",
+ "Verticalement"
+ ],
+ [
+ "3秒后加载完成",
+ "Chargement terminé après 3 secondes"
+ ],
+ [
+ "隐藏为 00 的值",
+ "Masquer la valeur de 00"
+ ],
+ [
+ "指定天数",
+ "Nombre de jours spécifié"
+ ],
+ [
+ "自定义模板",
+ "Modèle personnalisé"
+ ],
+ [
+ "指定小时",
+ "Heure spécifiée"
+ ],
+ [
+ "指定分钟",
+ "Minute spécifiée"
+ ],
+ [
+ "指定秒",
+ "Seconde spécifiée"
+ ],
+ [
+ "完成后提示",
+ "Message de notification après l'achèvement"
+ ],
+ [
+ "3秒后开始倒计时",
+ "Compte à rebours démarré après 3 secondes"
+ ],
+ [
+ "结合按钮",
+ "Combinaison avec un bouton"
+ ],
+ [
+ "购买",
+ "Achat"
+ ],
+ [
+ "消息",
+ "Message"
+ ],
+ [
+ "结合图片",
+ "Combinaison avec une image"
+ ],
+ [
+ "结合图标",
+ "Combinaison avec une icône"
+ ],
+ [
+ "点击触发",
+ "Démarrage déclenché par un clic"
+ ],
+ [
+ "不同大小",
+ "Tailles différentes"
+ ],
+ [
+ "不同颜色",
+ "Couleurs différentes"
+ ],
+ [
+ "使用base64",
+ "Utilisation de base64"
+ ],
+ [
+ "没有错误提示",
+ "Aucune indication d'erreur"
+ ],
+ [
+ "多行省略号",
+ "Points de suspension multi-lignes"
+ ],
+ [
+ "金额",
+ "Montant"
+ ],
+ [
+ "手机号脱敏",
+ "Masquage du numéro de téléphone mobile"
+ ],
+ [
+ "姓名脱敏",
+ "Masquage du nom"
+ ],
+ [
+ "邮箱脱敏",
+ "Masquage de l'adresse e-mail"
+ ],
+ [
+ "银行卡脱敏",
+ "Masquage de la carte bancaire"
+ ],
+ [
+ "自定义脱敏字符",
+ "Caractères de masquage personnalisés"
+ ],
+ [
+ "主要",
+ "Principal"
+ ],
+ [
+ "危险",
+ "Dangereux"
+ ],
+ [
+ "信息",
+ "Informations"
+ ],
+ [
+ "邮件",
+ "Courrier électronique"
+ ],
+ [
+ "文件",
+ "Fichier"
+ ],
+ [
+ "可关闭",
+ "Peut être fermé"
+ ],
+ [
+ "镂空",
+ "Perforé"
+ ],
+ [
+ "自定义无圆角",
+ "Angles arrondis personnalisés non"
+ ],
+ [
+ "不同裁剪",
+ "Différentes découpes"
+ ],
+ [
+ "点击可预览",
+ "Cliquez pour prévisualiser"
+ ],
+ [
+ "失败时显示",
+ "Afficher en cas d'erreur"
+ ],
+ [
+ "自定义圆角",
+ "Angles arrondis personnalisés"
+ ],
+ [
+ "设置颜色",
+ "Définir la couleur"
+ ],
+ [
+ "可滑动",
+ "Déplaçable"
+ ],
+ [
+ "左滑编辑",
+ "Swipe gauche pour éditer"
+ ],
+ [
+ "编辑",
+ "Éditer"
+ ],
+ [
+ "右滑删除",
+ "Swipe droit pour supprimer"
+ ],
+ [
+ "账号",
+ "Compte"
+ ],
+ [
+ "我的订单",
+ "Mes commandes"
+ ],
+ [
+ "我的收藏",
+ "Mes favoris"
+ ],
+ [
+ "筛选",
+ "Filtrer"
+ ],
+ [
+ "长按项即可拖动排序",
+ "Appuyez longuement sur l'élément pour le trier par drag and drop"
+ ],
+ [
+ "单列排序",
+ "Tri par colonne unique"
+ ],
+ [
+ "不需要长按",
+ "Pas besoin d'appuyer longuement"
+ ],
+ [
+ "结合列表使用",
+ "Utiliser avec une liste"
+ ],
+ [
+ "多列排序",
+ "Tri par plusieurs colonnes"
+ ],
+ [
+ "结合图片使用",
+ "Utiliser avec une image"
+ ],
+ [
+ "禁用手势",
+ "Désactiver les gestes"
+ ],
+ [
+ "自定义样式2",
+ "Style personnalisé 2"
+ ],
+ [
+ "无图片",
+ "Sans image"
+ ],
+ [
+ "圆角",
+ "Bords arrondis"
+ ],
+ [
+ "自定义大小",
+ "Taille personnalisée"
+ ],
+ [
+ "省略号",
+ "Ellipsis"
+ ],
+ [
+ "Badge 角标",
+ "Badge Angle"
+ ],
+ [
+ "NoticeBar 通知栏",
+ "NoticeBar Avis"
+ ],
+ [
+ "Countdown 倒计时",
+ "Countdown Compte à rebours"
+ ],
+ [
+ "Progress 进度条",
+ "Progress Barre de progression"
+ ],
+ [
+ "ProgressCircle 圆形进度条",
+ "ProgressCircle Barre de progression circulaire"
+ ],
+ [
+ "Skeleton 骨架图",
+ "Skeleton Schéma d'ossature"
+ ],
+ [
+ "LoadMore 加载更多",
+ "LoadMore Charger plus"
+ ],
+ [
+ "RollingNumber 数字滚动",
+ "RollingNumber Nombre roulant"
+ ],
+ [
+ "ActionSheet 操作菜单",
+ "ActionSheet Menu d'actions"
+ ],
+ [
+ "Popup 弹窗",
+ "Popup Fenêtre pop-up"
+ ],
+ [
+ "Confirm 确认框",
+ "Confirm Boîte de confirmation"
+ ],
+ [
+ "Toast 提示框",
+ "Toast Boîte de notification"
+ ],
+ [
+ "QRCode 二维码",
+ "QRCode Code QR"
+ ],
+ [
+ "Sign 签名",
+ "Sign Signature"
+ ],
+ [
+ "DayUts 日期",
+ "DayUts Date"
+ ],
+ [
+ "Vibrate 震动",
+ "Vibrate Vibration"
+ ],
+ [
+ "Cropper 图片裁剪",
+ "Cropper Découpe d'image"
+ ],
+ [
+ "Canvas 画布",
+ "Canvas Toile"
+ ],
+ [
+ "SVG 图标",
+ "SVG Icône"
+ ],
+ [
+ "SlideVerify 滑动验证",
+ "SlideVerify Vérification par glissement"
+ ],
+ [
+ "获取某个单位的结束时间",
+ "Obtenir l'heure de fin d'une unité"
+ ],
+ [
+ "是否同一天",
+ "Est-ce le même jour"
+ ],
+ [
+ "是否早于",
+ "Est-ce avant"
+ ],
+ [
+ "是否晚于",
+ "Est-ce après"
+ ],
+ [
+ "差值",
+ "Différence"
+ ],
+ [
+ "差值(单位)",
+ "Unité de la différence"
+ ],
+ [
+ "选择图片",
+ "Sélectionner une image"
+ ],
+ [
+ "可调节裁剪框大小",
+ "Redimensionner la zone de découpe"
+ ],
+ [
+ "预览图片",
+ "Prévisualiser l'image"
+ ],
+ [
+ "保存图片",
+ "Enregistrer l'image"
+ ],
+ [
+ "本页面内容由 canvas 渲染生成,是否立即预览图片效果?",
+ "Le contenu de cette page est généré par le rendu canvas. Voulez-vous prévisualiser immédiatement l'effet de l'image?"
+ ],
+ [
+ "基础动画",
+ "Animation de base"
+ ],
+ [
+ "淡入淡出",
+ "Fade-in et fade-out"
+ ],
+ [
+ "播放动画",
+ "Lancer l'animation"
+ ],
+ [
+ "滑入",
+ "Glisser"
+ ],
+ [
+ "旋转翻转",
+ "Rotation et retournement"
+ ],
+ [
+ "摇摆抖动",
+ "Oscillation"
+ ],
+ [
+ "特殊效果",
+ "Effets spéciaux"
+ ],
+ [
+ "组合动画",
+ "Animation combinée"
+ ],
+ [
+ "标题",
+ "Titre"
+ ],
+ [
+ "体重",
+ "Poids"
+ ],
+ [
+ "所在地区",
+ "Region"
+ ],
+ [
+ "出生年月",
+ "Date de naissance"
+ ],
+ [
+ "个人简介",
+ "Présentation"
+ ],
+ [
+ "请输入个人简介",
+ "Veuillez entrer votre présentation"
+ ],
+ [
+ "公开状态",
+ "Statut public"
+ ],
+ [
+ "重置",
+ "Réinitialiser"
+ ],
+ [
+ "提交",
+ "Soumettre"
+ ],
+ [
+ "未知",
+ "Inconnu"
+ ],
+ [
+ "篮球",
+ "Basketball"
+ ],
+ [
+ "足球",
+ "Football"
+ ],
+ [
+ "羽毛球",
+ "Badminton"
+ ],
+ [
+ "乒乓球",
+ "Ping-pong"
+ ],
+ [
+ "游泳",
+ "Natation"
+ ],
+ [
+ "用户名不能为空",
+ "Le nom d'utilisateur ne peut pas être vide"
+ ],
+ [
+ "用户名长度在3-20个字符之间",
+ "La longueur du nom d'utilisateur est comprise entre 3 et 20 caractères"
+ ],
+ [
+ "邮箱不能为空",
+ "L'adresse e-mail ne peut pas être vide"
+ ],
+ [
+ "邮箱格式不正确",
+ "Le format de l'adresse e-mail est incorrect"
+ ],
+ [
+ "身高不能为空",
+ "La taille ne peut pas être vide"
+ ],
+ [
+ "身高在160-190cm之间",
+ "La taille est comprise entre 160 et 190 cm"
+ ],
+ [
+ "请输入验证码",
+ "Veuillez entrer le code de vérification"
+ ],
+ [
+ "登录",
+ "Connexion"
+ ],
+ [
+ "购物车 ({num})",
+ "Panier ({num})"
+ ],
+ [
+ "完成",
+ "Terminé"
+ ],
+ [
+ "管理",
+ "Gestion"
+ ],
+ [
+ "删除",
+ "Supprimer"
+ ],
+ [
+ "全选",
+ "Tout cocher"
+ ],
+ [
+ "合计",
+ "Total"
+ ],
+ [
+ "去结算",
+ "Passer à la caisse"
+ ],
+ [
+ "温馨提示",
+ "Remarque"
+ ],
+ [
+ "确定删除该商品吗?",
+ "Êtes-vous sûr de supprimer cet article?"
+ ],
+ [
+ "删除成功",
+ "Suppression réussie"
+ ],
+ [
+ "请先选择商品",
+ "Veuillez sélectionner un article d'abord"
+ ],
+ [
+ "确定删除选中的商品吗?",
+ "Êtes-vous sûr de supprimer les articles sélectionnés?"
+ ],
+ [
+ "您需支付 {price} 元,请确认支付",
+ "Vous devez payer {price} yuan, veuillez confirmer le paiement"
+ ],
+ [
+ "支付成功",
+ "Paiement réussi"
+ ],
+ [
+ "已设为默认",
+ "Défini comme préférence"
+ ],
+ [
+ "设为默认",
+ "Définir comme préférence"
+ ],
+ [
+ "修改",
+ "Modifier"
+ ],
+ [
+ "添加地址",
+ "Ajouter une adresse"
+ ],
+ [
+ "微信",
+ "WeChat"
+ ],
+ [
+ "父子关联",
+ "Association père-fils"
+ ],
+ [
+ "选中值",
+ "Valeur sélectionnée"
+ ],
+ [
+ "选中操作",
+ "Opération de sélection"
+ ],
+ [
+ "选中部分节点",
+ "Sélection de quelques nœuds"
+ ],
+ [
+ "获取选中节点",
+ "Obtention des nœuds sélectionnés"
+ ],
+ [
+ "获取半选节点",
+ "Obtention des nœuds semi-sélectionnés"
+ ],
+ [
+ "清空选中",
+ "Effacement de la sélection"
+ ],
+ [
+ "展开操作",
+ "Opération d'expansion"
+ ],
+ [
+ "展开部分节点",
+ "Expansion de quelques nœuds"
+ ],
+ [
+ "获取展开节点",
+ "Obtention des nœuds déployés"
+ ],
+ [
+ "展开所有",
+ "Expansion de tous"
+ ],
+ [
+ "收起所有",
+ "Réduction de tous"
+ ],
+ [
+ "开通账号",
+ "Ouverture de compte"
+ ],
+ [
+ "赠送500元",
+ "Don de 500 yuans"
+ ],
+ [
+ "完成实名认证",
+ "Complétion de l'authentification en ligne"
+ ],
+ [
+ "通过身份证认证",
+ "Authentification par carte d'identité"
+ ],
+ [
+ "绑定银行卡",
+ "Liaison de la carte bancaire"
+ ],
+ [
+ "绑定招商银行储蓄卡",
+ "Liaison de la carte de débit de la Banque commerciale de Chine"
+ ],
+ [
+ "首次充值",
+ "Premier recharge"
+ ],
+ [
+ "滑块大点",
+ "Bouton de curseur plus grand"
+ ],
+ [
+ "换个颜色",
+ "Changer de couleur"
+ ],
+ [
+ "最大50",
+ "Maximum 50"
+ ],
+ [
+ "自定义触发器",
+ "Déclencheur personnalisé"
+ ],
+ [
+ "打开选择器",
+ "Ouvrir le sélecteur"
+ ],
+ [
+ "多列",
+ "Plusieurs colonnes"
+ ],
+ [
+ "通过 children 配置多级数据,并使用 column-count 参数指定显示的列数",
+ "Configurer des données multi-niveaux via children et utiliser le paramètre column-count pour spécifier le nombre de colonnes affichées"
+ ],
+ [
+ "弹窗中使用",
+ "Utiliser dans la fenêtre pop-up"
+ ],
+ [
+ "打开",
+ "Ouvrir"
+ ],
+ [
+ "选择地区",
+ "Sélectionner la région"
+ ],
+ [
+ "绑定值",
+ "Lier la valeur"
+ ],
+ [
+ "下一步",
+ "Etape suivante"
+ ],
+ [
+ "确定",
+ "Confirmer"
+ ],
+ [
+ "关闭",
+ "Fermer"
+ ],
+ [
+ "显示取消按钮",
+ "Afficher le bouton Annuler"
+ ],
+ [
+ "修改按钮文案",
+ "Modifier le texte du bouton"
+ ],
+ [
+ "显示绑定值",
+ "Afficher la valeur liée"
+ ],
+ [
+ "时",
+ "Quand"
+ ],
+ [
+ "时:分",
+ "Heure:Minute"
+ ],
+ [
+ "时:分:秒",
+ "Heure:Minute:Seconde"
+ ],
+ [
+ "标签格式化",
+ "Formatage d'étiquette"
+ ],
+ [
+ "固定开始、结束日期",
+ "Date de début et de fin fixes"
+ ],
+ [
+ "自定义快捷选项",
+ "Options rapides personnalisées"
+ ],
+ [
+ "只读",
+ "Lecture seule"
+ ],
+ [
+ "显示分数",
+ "Afficher les points"
+ ],
+ [
+ "允许半星",
+ "Autoriser la demi-étoile"
+ ],
+ [
+ "换个图标",
+ "Changer d'icône"
+ ],
+ [
+ "纵向排列",
+ "Alignement vertical"
+ ],
+ [
+ "换个样式",
+ "Changer de style"
+ ],
+ [
+ "不显示图标",
+ "Ne pas afficher d'icône"
+ ],
+ [
+ "其他样式",
+ "Autres styles"
+ ],
+ [
+ "数字键盘",
+ "Clavier numérique"
+ ],
+ [
+ "打开键盘",
+ "Ouvrir le clavier"
+ ],
+ [
+ "是否显示输入值",
+ "Afficher ou non la valeur d'entrée"
+ ],
+ [
+ "输入即绑定",
+ "Lier à l'entrée"
+ ],
+ [
+ "身份证键盘",
+ "Clavier de carte d'identité"
+ ],
+ [
+ "密码键盘",
+ "Clavier de mot de passe"
+ ],
+ [
+ "是否加密",
+ "Crypter ou non"
+ ],
+ [
+ "车牌号键盘",
+ "Clavier d'immatriculation"
+ ],
+ [
+ "数字输入",
+ "Entrée numérique"
+ ],
+ [
+ "无头",
+ "Sans tête"
+ ],
+ [
+ "左侧",
+ "Gauche"
+ ],
+ [
+ "右侧",
+ "Droite"
+ ],
+ [
+ "隐藏取消按钮",
+ "Masquer le bouton Annuler"
+ ],
+ [
+ "自定义文本",
+ "Texte personnalisé"
+ ],
+ [
+ "关闭前钩子",
+ "Hook avant la fermeture"
+ ],
+ [
+ "显示时长",
+ "Durée d'affichage"
+ ],
+ [
+ "确定要删除吗?",
+ "Êtes-vous sûr de vouloir supprimer?"
+ ],
+ [
+ "确定要删除吗?3秒后自动关闭",
+ "Êtes-vous sûr de vouloir supprimer? La fenêtre se fermera automatiquement dans 3 secondes"
+ ],
+ [
+ "带标题、描述",
+ "Avec titre et description"
+ ],
+ [
+ "无法点击遮罩关闭",
+ "Impossible de fermer en cliquant sur le masque"
+ ],
+ [
+ "不需要取消按钮",
+ "Pas besoin de bouton Annuler"
+ ],
+ [
+ "插槽用法",
+ "Utilisation de la fente"
+ ],
+ [
+ "反馈",
+ "Retour"
+ ],
+ [
+ "删除好友会同时删除所有聊天记录",
+ "Supprimer un ami supprimera également tous les enregistrements de conversation"
+ ],
+ [
+ "删除好友",
+ "Supprimer un ami"
+ ],
+ [
+ "确定要删除好友吗?",
+ "Êtes-vous sûr de vouloir supprimer l'ami?"
+ ],
+ [
+ "点我关闭",
+ "Cliquez sur moi pour fermer"
+ ],
+ [
+ "确定要关闭吗?",
+ "Êtes-vous sûr de vouloir fermer?"
+ ],
+ [
+ "支付宝",
+ "Alipay"
+ ],
+ [
+ "Image 图片",
+ "Image Image"
+ ],
+ [
+ "Icon 图标",
+ "Icône Icône"
+ ],
+ [
+ "Tag 标签",
+ "Balise Balise"
+ ],
+ [
+ "Form 表单验证",
+ "Validation de formulaire Validation de formulaire"
+ ],
+ [
+ "Input 输入框",
+ "Zone de saisie Zone de saisie"
+ ],
+ [
+ "Textarea 文本域",
+ "Zone de texte Zone de texte"
+ ],
+ [
+ "InputNumber 计数器",
+ "Compteur Compteur"
+ ],
+ [
+ "InputOtp 口令输入",
+ "Entrée de code d'authentification Entrée de code d'authentification"
+ ],
+ [
+ "Keyboard 键盘",
+ "Clavier Clavier"
+ ],
+ [
+ "Radio 单选框",
+ "Case à cocher unique Case à cocher unique"
+ ],
+ [
+ "Checkbox 多选框",
+ "Cases à cocher multiples Cases à cocher multiples"
+ ],
+ [
+ "Switch 开关",
+ "Commutateur Commutateur"
+ ],
+ [
+ "Rate 评分",
+ "Évaluation Évaluation"
+ ],
+ [
+ "Slider 滑块",
+ "Curseur Curseur"
+ ],
+ [
+ "Select 选择器",
+ "Sélecteur Sélecteur"
+ ],
+ [
+ "SelectDate 日期选择器",
+ "Sélecteur de date Sélecteur de date"
+ ],
+ [
+ "SelectTime 时间选择器",
+ "Sélecteur d'heure Sélecteur d'heure"
+ ],
+ [
+ "Cascader 级联选择器",
+ "Sélecteur en cascade Sélecteur en cascade"
+ ],
+ [
+ "Upload 文件上传",
+ "Téléchargement de fichiers Téléchargement de fichiers"
+ ],
+ [
+ "Calendar 日历",
+ "Calendrier Calendrier"
+ ],
+ [
+ "支付失败",
+ "Paiement échoué"
+ ],
+ [
+ "授权信息仅用于用户登录",
+ "Les informations d'autorisation sont uniquement utilisées pour la connexion de l'utilisateur"
+ ],
+ [
+ "登录授权失败",
+ "Autorisation de connexion échouée"
+ ],
+ [
+ "获取短信验证码",
+ "Obtenir un code de vérification par SMS"
+ ],
+ [
+ "验证码",
+ "Code de vérification"
+ ],
+ [
+ "发送短信",
+ "Envoyer un SMS"
+ ],
+ [
+ "{n}s后重新获取",
+ "{n} s pour obtenir à nouveau"
+ ],
+ [
+ "获取验证码",
+ "Obtenir le code de vérification"
+ ],
+ [
+ "短信已发送,请查收",
+ "Le SMS a été envoyé, veuillez vérifier"
+ ],
+ [
+ "请填写验证码",
+ "Veuillez entrer le code de vérification"
+ ],
+ [
+ "请填写正确的手机号格式",
+ "Veuillez entrer le format de numéro de téléphone correct"
+ ],
+ [
+ "全局字号",
+ "Taille de police globale"
+ ],
+ [
+ "这是一段示例文字,用于预览不同字号的效果。",
+ "Ceci est un texte d'exemple pour prévisualiser les effets de différentes tailles de police."
+ ],
+ [
+ "默认 1.0",
+ "Par défaut 1,0"
+ ],
+ [
+ "切换语言",
+ "Changer de langue"
+ ],
+ [
+ "切换中",
+ "En cours de changement"
+ ],
+ [
+ "模板",
+ "Modèle"
+ ],
+ [
+ "编辑资料",
+ "Modifier les informations"
+ ],
+ [
+ "Text 文本",
+ "Texte"
+ ],
+ [
+ "Button 按钮",
+ "Bouton"
+ ],
+ [
+ "体重不能为空",
+ "Le poids ne peut pas être vide."
+ ],
+ [
+ "体重在40-100kg之间",
+ "Le poids doit être compris entre 40 et 100 kg."
+ ],
+ [
+ "标签不能为空",
+ "Le libellé ne peut pas être vide."
+ ],
+ [
+ "标签最多选择2个",
+ "Au plus 2 libellés peuvent être sélectionnés."
+ ],
+ [
+ "性别不能为空",
+ "Le sexe ne peut pas être vide."
+ ],
+ [
+ "出生年月不能为空",
+ "La date de naissance ne peut pas être vide."
+ ],
+ [
+ "出生年月不大于2010-01-01",
+ "La date de naissance ne doit pas être supérieure à 2010-01-01."
+ ],
+ [
+ "联系人不能为空",
+ "Le contact ne peut pas être vide."
+ ],
+ [
+ "提交成功",
+ "Soumission réussie."
+ ],
+ [
+ "单个 true / false",
+ "Un seul true / false"
+ ],
+ [
+ "带索引、地区选择",
+ "Avec index, sélection de région"
+ ],
+ [
+ "换个分隔符",
+ "Changer le séparateur"
+ ],
+ [
+ "列表高度小一点",
+ "La hauteur de la liste est un peu plus petite."
+ ],
+ [
+ "范围选",
+ "Sélectionner une plage"
+ ],
+ [
+ "禁用部分日期",
+ "Désactiver certaines dates"
+ ],
+ [
+ "日历长列表",
+ "Liste longue du calendrier"
+ ],
+ [
+ "打开日历长列表",
+ "Ouvrir la liste longue du calendrier"
+ ],
+ [
+ "日历面板",
+ "Panneau du calendrier"
+ ],
+ [
+ "自定义文案和颜色",
+ "Personnaliser le texte et les couleurs"
+ ],
+ [
+ "显示头",
+ "Afficher la tête"
+ ],
+ [
+ "头像上传成功",
+ "L'avatar a été téléchargé avec succès"
+ ],
+ [
+ "编辑昵称",
+ "Modifier le pseudo"
+ ],
+ [
+ "请输入昵称",
+ "Veuillez entrer un pseudo"
+ ],
+ [
+ "请设置2-20个字符,不包括@<>/等无效字符",
+ "Veuillez définir 2 - 20 caractères, sans compter les caractères invalides tels que @<>/"
+ ],
+ [
+ "确认",
+ "Confirmer"
+ ],
+ [
+ "昵称长度需在2-20个字符之间",
+ "La longueur du pseudo doit être comprise entre 2 et 20 caractères"
+ ],
+ [
+ "昵称不能包含@<>/等特殊字符",
+ "Le pseudo ne peut pas contenir de caractères spéciaux tels que @<>/"
+ ],
+ [
+ "编辑简介",
+ "Modifier la biographie"
+ ],
+ [
+ "简介不能为空",
+ "La biographie ne peut pas être vide"
+ ],
+ [
+ "提示",
+ "Avertissement"
+ ],
+ [
+ "为提供更好的服务,我们邀请您填写昵称、头像等公开信息",
+ "Pour offrir un meilleur service, nous vous invitons à compléter vos informations publiques telles que le pseudo, l'avatar, etc."
+ ],
+ [
+ "头像",
+ "Avatar"
+ ],
+ [
+ "昵称",
+ "Pseudo"
+ ],
+ [
+ "点击输入昵称",
+ "Cliquez pour entrer un pseudo"
+ ],
+ [
+ "取消",
+ "Annuler"
+ ],
+ [
+ "请上传头像",
+ "Veuillez télécharger un avatar"
+ ],
+ [
+ "登录中",
+ "Connexion en cours"
+ ],
+ [
+ "手机登录",
+ "Connexion mobile"
+ ],
+ [
+ "未注册的手机号登录成功后将自动注册",
+ "Un numéro de téléphone non enregistré sera automatiquement enregistré après une connexion réussie"
+ ],
+ [
+ "请输入手机号",
+ "Veuillez entrer un numéro de téléphone"
+ ],
+ [
+ "插槽",
+ "Emplacement"
+ ],
+ [
+ "使用 PT 自定义颜色",
+ "Utiliser les couleurs personnalisées PT"
+ ],
+ [
+ "自定义返回图标",
+ "Icône de retour personnalisée"
+ ],
+ [
+ "自定义返回路径",
+ "Chemin de retour personnalisé"
+ ],
+ [
+ "自定义标题内容",
+ "Contenu de titre personnalisé"
+ ],
+ [
+ "显示滑块",
+ "Afficher le curseur"
+ ],
+ [
+ "添加间距",
+ "Ajouter un espacement"
+ ],
+ [
+ "横向填充",
+ "Remplissage horizontal"
+ ],
+ [
+ "适用于标签数量不多的情况",
+ "S'applique aux cas où le nombre d'étiquettes est faible"
+ ],
+ [
+ "居中",
+ "Centrer"
+ ],
+ [
+ "单个禁用",
+ "Désactivation individuelle"
+ ],
+ [
+ "显示下划线",
+ "Afficher le soulignement"
+ ],
+ [
+ "禁用",
+ "Désactiver"
+ ],
+ [
+ "取消订单",
+ "Annuler la commande"
+ ],
+ [
+ "立即购买",
+ "Acheter immédiatement"
+ ],
+ [
+ "确认收货",
+ "Confirmer la réception des marchandises"
+ ],
+ [
+ "评价",
+ "Évaluer"
+ ],
+ [
+ "禁用状态,无法拖拽",
+ "Statut de désactivation, impossible à draguer"
+ ],
+ [
+ "不吸附边缘,任意位置可拖拽",
+ "Ne s'accroche pas au bord, peut être dragué à n'importe quel endroit"
+ ],
+ [
+ "这是一个提示",
+ "Voici une indication"
+ ],
+ [
+ "删除地址后无法恢复,确认要删除该地址吗?",
+ "La suppression de l'adresse est irréversible. Êtes-vous sûr de vouloir la supprimer?"
+ ],
+ [
+ "加载中",
+ "Chargement en cours"
+ ],
+ [
+ "收货人",
+ "Destinataire"
+ ],
+ [
+ "请输入收货人姓名",
+ "Veuillez entrer le nom du destinataire"
+ ],
+ [
+ "手机号",
+ "Numéro de téléphone"
+ ],
+ [
+ "选择省市区",
+ "Choisir la province, la ville et le district"
+ ],
+ [
+ "详细地址",
+ "Adresse détaillée"
+ ],
+ [
+ "小区楼栋、门牌号、村等",
+ "Immeuble, numéro de porte, village, etc."
+ ],
+ [
+ "默认地址",
+ "Adresse par défaut"
+ ],
+ [
+ "保存",
+ "Enregistrer"
+ ],
+ [
+ "收货人不能为空",
+ "Le destinataire ne peut pas être vide"
+ ],
+ [
+ "手机号不能为空",
+ "Le numéro de téléphone ne peut pas être vide"
+ ],
+ [
+ "手机号格式不正确",
+ "Le format du numéro de téléphone est incorrect"
+ ],
+ [
+ "详细地址不能为空",
+ "L'adresse détaillée ne peut pas être vide"
+ ],
+ [
+ "所在地区不能为空",
+ "La région ne peut pas être vide"
+ ],
+ [
+ "保存中",
+ "Enregistrement en cours"
+ ],
+ [
+ "开启通知",
+ "Activer les notifications"
+ ],
+ [
+ "通用设置",
+ "Paramètres généraux"
+ ],
+ [
+ "通知设置",
+ "Paramètres de notification"
+ ],
+ [
+ "隐私设置",
+ "Paramètres de confidentialité"
+ ]
+]
\ No newline at end of file
diff --git a/cool-unix/locale/index.ts b/cool-unix/locale/index.ts
new file mode 100644
index 0000000..c5c259d
--- /dev/null
+++ b/cool-unix/locale/index.ts
@@ -0,0 +1,149 @@
+import { isNull, forInObject, isEmpty, storage, router } from "@/cool";
+import { ref } from "vue";
+import zhcn from "./zh-cn.json";
+import zhtw from "./zh-tw.json";
+import en from "./en.json";
+import es from "./es.json";
+import ja from "./ja.json";
+import ko from "./ko.json";
+import fr from "./fr.json";
+import { config } from "@/config";
+
+// 解析语言包
+function parse(val: string[][]) {
+ const isCustom = val.length == 1 && val[0].length == 1;
+
+ if (!isCustom) {
+ return val;
+ }
+
+ return val[0][0].split("<__&__>").map((e) => e.split("<__=__>"));
+}
+
+/**
+ * 语言包映射对象,包含所有已支持的语言。
+ * 如需新增语言,只需新建对应的 xx.json 文件并在此处引入即可。
+ */
+const messages = {
+ "zh-cn": parse(zhcn),
+ "zh-tw": parse(zhtw),
+ en: parse(en),
+ es: parse(es),
+ ja: parse(ja),
+ ko: parse(ko),
+ fr: parse(fr)
+};
+
+// 当前语言,默认中文
+export const locale = ref("");
+
+// 设置当前语言
+export const setLocale = (value: string) => {
+ locale.value = value;
+
+ // #ifdef APP
+ // APP 环境下,存储语言到本地
+ storage.set("locale", value, 0);
+ // #endif
+
+ // #ifndef APP
+ // 其他环境下,直接设置全局语言
+ uni.setLocale(value);
+ // #endif
+};
+
+// 获取当前语言
+export const getLocale = (): string => {
+ let value: string;
+
+ // #ifdef APP
+ // APP 环境下,优先从本地存储获取
+ const _locale = storage.get("locale") as string | null;
+
+ if (_locale != null && !isEmpty(_locale)) {
+ value = _locale;
+ } else {
+ // @ts-ignore
+ value = uni.getDeviceInfo().osLanguage as string;
+ }
+
+ // #endif
+
+ // #ifndef APP
+ // 其他环境下,直接获取全局语言
+ value = uni.getLocale();
+ // #endif
+
+ if (isNull(value) || isEmpty(value)) {
+ value = config.locale;
+ }
+
+ return value;
+};
+
+// 追加数据
+export const appendLocale = (name: string, data: string[][]) => {
+ if (messages[name] != null) {
+ (messages[name] as string[][]).unshift(...parse(data));
+ }
+};
+
+// 不带参数的翻译方法
+export const t = (name: string) => {
+ let data = messages[locale.value] as string[][] | null;
+
+ if (data == null) {
+ return name;
+ }
+
+ let text = data.find((e) => e[0] == name)?.[1];
+
+ if (text == null || text == "") {
+ text = name;
+ }
+
+ return text;
+};
+
+// 带参数的翻译方法
+export const $t = (name: string, data: any) => {
+ let text = t(name);
+
+ // 替换参数
+ if (!isNull(data)) {
+ forInObject(data, (value, key) => {
+ if (typeof value === "number") {
+ value = value.toString();
+ }
+
+ text = text.replaceAll(`{${key}}`, value as string);
+ });
+ }
+
+ return text;
+};
+
+// 初始化语言设置
+export const initLocale = () => {
+ locale.value = getLocale();
+
+ // #ifndef APP
+ // 监听语言切换事件,自动更新 locale
+ uni.onLocaleChange((res) => {
+ setLocale(res.locale!);
+ });
+ // #endif
+};
+
+// 更新标题
+export function updateTitle() {
+ const style = router.route()?.style;
+
+ if (style != null) {
+ if (style.navigationBarTitleText != null) {
+ uni.setNavigationBarTitle({
+ title: t(style.navigationBarTitleText as string)
+ });
+ }
+ }
+}
diff --git a/cool-unix/locale/ja.json b/cool-unix/locale/ja.json
new file mode 100644
index 0000000..3786e2d
--- /dev/null
+++ b/cool-unix/locale/ja.json
@@ -0,0 +1,2502 @@
+[
+ [
+ "Animation 动画",
+ "アニメーション"
+ ],
+ [
+ "编辑地址",
+ "編集アドレス"
+ ],
+ [
+ "cool-unix",
+ "クールユニックス"
+ ],
+ [
+ "首页",
+ "ホームページ"
+ ],
+ [
+ "我的",
+ "私の"
+ ],
+ [
+ "显示星期",
+ "曜日を表示する"
+ ],
+ [
+ "显示其他月份",
+ "他の月を表示する"
+ ],
+ [
+ "不同位置",
+ "異なる位置"
+ ],
+ [
+ "顶部",
+ "上部"
+ ],
+ [
+ "中间",
+ "中央"
+ ],
+ [
+ "底部",
+ "下部"
+ ],
+ [
+ "不同类型",
+ "異なる種類"
+ ],
+ [
+ "成功",
+ "成功"
+ ],
+ [
+ "失败",
+ "失敗"
+ ],
+ [
+ "警告",
+ "警告"
+ ],
+ [
+ "问题",
+ "問題"
+ ],
+ [
+ "停止",
+ "停止"
+ ],
+ [
+ "自定义图标",
+ "カスタム アイコン"
+ ],
+ [
+ "只存在一个",
+ "1つだけ存在する"
+ ],
+ [
+ "不同位置提示",
+ "異なる位置のヒント"
+ ],
+ [
+ "不同类型提示",
+ "異なる種類のヒント"
+ ],
+ [
+ "带图标提示",
+ "アイコン付きのヒント"
+ ],
+ [
+ "移除其他已存在的提示",
+ "既存の他のヒントを削除する"
+ ],
+ [
+ "打开弹窗",
+ "ポップアップを開く"
+ ],
+ [
+ "设置宽度 80%",
+ "幅を80%に設定する"
+ ],
+ [
+ "多行省略号",
+ "複数行の省略記号"
+ ],
+ [
+ "金额",
+ "金額"
+ ],
+ [
+ "手机号脱敏",
+ "携帯番号の脱感作"
+ ],
+ [
+ "姓名脱敏",
+ "氏名の脱感作"
+ ],
+ [
+ "邮箱脱敏",
+ "メールアドレスの脱感作"
+ ],
+ [
+ "银行卡脱敏",
+ "銀行カードの脱感作"
+ ],
+ [
+ "自定义脱敏字符",
+ "カスタム脱感作文字"
+ ],
+ [
+ "主要",
+ "主要"
+ ],
+ [
+ "危险",
+ "危険"
+ ],
+ [
+ "信息",
+ "情報"
+ ],
+ [
+ "邮件",
+ "メール"
+ ],
+ [
+ "文件",
+ "ファイル"
+ ],
+ [
+ "可关闭",
+ "クローズ可能"
+ ],
+ [
+ "镂空",
+ "抜け穴"
+ ],
+ [
+ "自定义无圆角",
+ "カスタム角丸なし"
+ ],
+ [
+ "不同裁剪",
+ "異なる裁断"
+ ],
+ [
+ "点击可预览",
+ "クリックでプレビュー可能"
+ ],
+ [
+ "失败时显示",
+ "失敗時に表示"
+ ],
+ [
+ "自定义圆角",
+ "カスタム角丸"
+ ],
+ [
+ "设置颜色",
+ "色を設定"
+ ],
+ [
+ "密码输入",
+ "パスワード入力"
+ ],
+ [
+ "可清除",
+ "クリア可能"
+ ],
+ [
+ "左右插槽",
+ "左右のスロット"
+ ],
+ [
+ "左图标",
+ "左のアイコン"
+ ],
+ [
+ "右图标",
+ "右のアイコン"
+ ],
+ [
+ "自动聚焦",
+ "自動フォーカス"
+ ],
+ [
+ "长度为6",
+ "長さ6"
+ ],
+ [
+ "步进为10",
+ "ステップ10"
+ ],
+ [
+ "最小为10",
+ "最小10"
+ ],
+ [
+ "最大为50",
+ "最大50"
+ ],
+ [
+ "可以小数",
+ "小数可"
+ ],
+ [
+ "可以输入",
+ "入力可"
+ ],
+ [
+ "用户名",
+ "ユーザー名"
+ ],
+ [
+ "请输入用户名",
+ "ユーザー名を入力してください"
+ ],
+ [
+ "邮箱",
+ "メールアドレス"
+ ],
+ [
+ "请输入邮箱地址",
+ "メールアドレスを入力してください"
+ ],
+ [
+ "动态验证",
+ "動的検証"
+ ],
+ [
+ "联系人",
+ "連絡先"
+ ],
+ [
+ "添加联系人",
+ "連絡先を追加"
+ ],
+ [
+ "身高",
+ "身長"
+ ],
+ [
+ "其他",
+ "その他"
+ ],
+ [
+ "文件管理",
+ "ファイル管理"
+ ],
+ [
+ "该模板正在开发中",
+ "このテンプレートは開発中です"
+ ],
+ [
+ "未登录",
+ "未ログイン"
+ ],
+ [
+ "总点击",
+ "総クリック数"
+ ],
+ [
+ "赞",
+ "いいね"
+ ],
+ [
+ "收藏",
+ "お気に入り"
+ ],
+ [
+ "粉丝",
+ "ファン"
+ ],
+ [
+ "接单模式",
+ "受注モード"
+ ],
+ [
+ "已关闭",
+ "クローズド"
+ ],
+ [
+ "消息通知",
+ "メッセージ通知"
+ ],
+ [
+ "待支付",
+ "支払い待ち"
+ ],
+ [
+ "未发货",
+ "未発送"
+ ],
+ [
+ "已发货",
+ "発送済み"
+ ],
+ [
+ "售后 / 退款",
+ "サポート/返金"
+ ],
+ [
+ "我的钱包",
+ "私のウォレット"
+ ],
+ [
+ "数据看板",
+ "データダッシュボード"
+ ],
+ [
+ "历史记录",
+ "履歴"
+ ],
+ [
+ "邀请好友",
+ "友達を招待"
+ ],
+ [
+ "设置",
+ "設定"
+ ],
+ [
+ "开发中,敬请期待",
+ "開発中、お待ちください"
+ ],
+ [
+ "基础组件",
+ "基本コンポーネント"
+ ],
+ [
+ "文本",
+ "テキスト"
+ ],
+ [
+ "按钮",
+ "ボタン"
+ ],
+ [
+ "图片",
+ "画像"
+ ],
+ [
+ "图标",
+ "アイコン"
+ ],
+ [
+ "标签",
+ "ラベル"
+ ],
+ [
+ "表单组件",
+ "フォームコンポーネント"
+ ],
+ [
+ "表单验证",
+ "フォーム検証"
+ ],
+ [
+ "输入框",
+ "入力欄"
+ ],
+ [
+ "文本域",
+ "テキストエリア"
+ ],
+ [
+ "计数器",
+ "カウンター"
+ ],
+ [
+ "口令输入",
+ "パスワード入力"
+ ],
+ [
+ "键盘",
+ "キーボード"
+ ],
+ [
+ "单选框",
+ "ラジオボタン"
+ ],
+ [
+ "多选框",
+ "チェックボックス"
+ ],
+ [
+ "开关",
+ "スイッチ"
+ ],
+ [
+ "评分",
+ "評価"
+ ],
+ [
+ "滑块",
+ "スライダー"
+ ],
+ [
+ "选择器",
+ "セレクター"
+ ],
+ [
+ "签名",
+ "署名"
+ ],
+ [
+ "图片裁剪",
+ "画像裁剪"
+ ],
+ [
+ "Canvas",
+ "キャンバス"
+ ],
+ [
+ "富文本",
+ "リッチテキスト"
+ ],
+ [
+ "该功能正在开发中",
+ "この機能は開発中です"
+ ],
+ [
+ "圆形",
+ "円形"
+ ],
+ [
+ "组合",
+ "コンビネーション"
+ ],
+ [
+ "基础用法",
+ "基本的な使い方"
+ ],
+ [
+ "自定义",
+ "カスタマイズ"
+ ],
+ [
+ "加快滚动速度",
+ "スクロール速度を上げる"
+ ],
+ [
+ "显示小数位数",
+ "小数桁数を表示する"
+ ],
+ [
+ "自定义样式",
+ "カスタムスタイル"
+ ],
+ [
+ "自定义颜色",
+ "カスタムカラー"
+ ],
+ [
+ "自定义宽度",
+ "カスタム幅"
+ ],
+ [
+ "不显示文本",
+ "テキストを表示しない"
+ ],
+ [
+ "改个颜色",
+ "色を変える"
+ ],
+ [
+ "显示文本",
+ "テキストを表示する"
+ ],
+ [
+ "快一些",
+ "もっと速く"
+ ],
+ [
+ "带图标",
+ "アイコン付き"
+ ],
+ [
+ "设置速度",
+ "速度を設定する"
+ ],
+ [
+ "垂直方向",
+ "垂直方向"
+ ],
+ [
+ "3秒后加载完成",
+ "3秒後に読み込み完了"
+ ],
+ [
+ "隐藏为 00 的值",
+ "00の値を非表示にする"
+ ],
+ [
+ "指定天数",
+ "指定日数"
+ ],
+ [
+ "自定义模板",
+ "カスタムテンプレート"
+ ],
+ [
+ "指定小时",
+ "指定時間"
+ ],
+ [
+ "指定分钟",
+ "指定分"
+ ],
+ [
+ "指定秒",
+ "指定秒"
+ ],
+ [
+ "完成后提示",
+ "完了後に表示"
+ ],
+ [
+ "3秒后开始倒计时",
+ "3秒後にカウントダウン開始"
+ ],
+ [
+ "结合按钮",
+ "ボタンと結合"
+ ],
+ [
+ "购买",
+ "購入"
+ ],
+ [
+ "消息",
+ "メッセージ"
+ ],
+ [
+ "结合图片",
+ "画像と結合"
+ ],
+ [
+ "结合图标",
+ "アイコンと結合"
+ ],
+ [
+ "点击触发",
+ "クリックでトリガ"
+ ],
+ [
+ "不同大小",
+ "異なるサイズ"
+ ],
+ [
+ "不同颜色",
+ "異なる色"
+ ],
+ [
+ "使用base64",
+ "base64を使用"
+ ],
+ [
+ "没有错误提示",
+ "エラーメッセージなし"
+ ],
+ [
+ "左间隔",
+ "左間隔"
+ ],
+ [
+ "右移动",
+ "右移動"
+ ],
+ [
+ "左移动",
+ "左移動"
+ ],
+ [
+ "多个数据",
+ "複数のデータ"
+ ],
+ [
+ "点击收起",
+ "クリックで閉じる"
+ ],
+ [
+ "点击展开",
+ "クリックで展開する"
+ ],
+ [
+ "ref 方式调用",
+ "ref 方式で呼び出す"
+ ],
+ [
+ "自定义图标、文字、大小",
+ "カスタム アイコン、文字、サイズ"
+ ],
+ [
+ "上传证件照",
+ "証明写真をアップロードする"
+ ],
+ [
+ "多选",
+ "複数選択"
+ ],
+ [
+ "限制 3 个",
+ "3 つまで制限"
+ ],
+ [
+ "边框",
+ "枠線"
+ ],
+ [
+ "显示字数",
+ "表示文字数"
+ ],
+ [
+ "自动增高",
+ "自動的に高さを増やす"
+ ],
+ [
+ "其他颜色",
+ "その他の色"
+ ],
+ [
+ "大一点",
+ "もう少し大きい"
+ ],
+ [
+ "正方形",
+ "正方形"
+ ],
+ [
+ "范围选择",
+ "範囲選択"
+ ],
+ [
+ "显示值",
+ "表示値"
+ ],
+ [
+ "步长10",
+ "ステップ幅 10"
+ ],
+ [
+ "微信",
+ "微信"
+ ],
+ [
+ "父子关联",
+ "父子関連"
+ ],
+ [
+ "选中值",
+ "選択値"
+ ],
+ [
+ "选中操作",
+ "選択操作"
+ ],
+ [
+ "选中部分节点",
+ "一部のノードを選択"
+ ],
+ [
+ "获取选中节点",
+ "選択されたノードを取得"
+ ],
+ [
+ "获取半选节点",
+ "半選択ノードを取得"
+ ],
+ [
+ "清空选中",
+ "選択をクリア"
+ ],
+ [
+ "展开操作",
+ "展開操作"
+ ],
+ [
+ "展开部分节点",
+ "一部のノードを展開"
+ ],
+ [
+ "获取展开节点",
+ "展開されたノードを取得"
+ ],
+ [
+ "展开所有",
+ "すべて展開"
+ ],
+ [
+ "收起所有",
+ "すべて折りたたむ"
+ ],
+ [
+ "开通账号",
+ "アカウントを開設する"
+ ],
+ [
+ "赠送500元",
+ "500元贈る"
+ ],
+ [
+ "完成实名认证",
+ "実名認証を完了する"
+ ],
+ [
+ "通过身份证认证",
+ "身分証認証を通過する"
+ ],
+ [
+ "绑定银行卡",
+ "銀行カードを登録する"
+ ],
+ [
+ "绑定招商银行储蓄卡",
+ "招商銀行の普通預金を登録する"
+ ],
+ [
+ "首次充值",
+ "初回充値"
+ ],
+ [
+ "已阅读并同意",
+ "既読して同意しました"
+ ],
+ [
+ "用户协议",
+ "利用規約"
+ ],
+ [
+ "隐私政策",
+ "プライバシーポリシー"
+ ],
+ [
+ "请先阅读并同意《用户协议》和《隐私政策》",
+ "まず利用規約とプライバシーポリシーを読んで同意してください"
+ ],
+ [
+ "我的昵称",
+ "私のニックネーム"
+ ],
+ [
+ "简介",
+ "自己紹介"
+ ],
+ [
+ "介绍一下自己",
+ "自己紹介をしてください"
+ ],
+ [
+ "性别",
+ "性別"
+ ],
+ [
+ "编辑性别",
+ "性別を編集する"
+ ],
+ [
+ "生日",
+ "誕生日"
+ ],
+ [
+ "选择生日",
+ "誕生日を選択する"
+ ],
+ [
+ "地区",
+ "地域"
+ ],
+ [
+ "选择所在的地区",
+ "所在する地域を選択する"
+ ],
+ [
+ "选择性别",
+ "性別を選択する"
+ ],
+ [
+ "保密",
+ "非公開"
+ ],
+ [
+ "男",
+ "男性"
+ ],
+ [
+ "女",
+ "女性"
+ ],
+ [
+ "性别设置成功",
+ "性別設定が完了しました"
+ ],
+ [
+ "生日设置成功",
+ "誕生日設定が完了しました"
+ ],
+ [
+ "地区设置成功",
+ "地域設定が完了しました"
+ ],
+ [
+ "Badge 角标",
+ "バッジ"
+ ],
+ [
+ "NoticeBar 通知栏",
+ "通知バー"
+ ],
+ [
+ "Countdown 倒计时",
+ "カウントダウン"
+ ],
+ [
+ "Progress 进度条",
+ "プログレスバー"
+ ],
+ [
+ "ProgressCircle 圆形进度条",
+ "円形プログレスバー"
+ ],
+ [
+ "Skeleton 骨架图",
+ "スケルトン"
+ ],
+ [
+ "LoadMore 加载更多",
+ "ロードモア"
+ ],
+ [
+ "RollingNumber 数字滚动",
+ "数字スクロール"
+ ],
+ [
+ "ActionSheet 操作菜单",
+ "アクションシート"
+ ],
+ [
+ "Popup 弹窗",
+ "ポップアップ"
+ ],
+ [
+ "Confirm 确认框",
+ "確認メッセージ"
+ ],
+ [
+ "Toast 提示框",
+ "トースト"
+ ],
+ [
+ "QRCode 二维码",
+ "QRコード"
+ ],
+ [
+ "Sign 签名",
+ "署名"
+ ],
+ [
+ "DayUts 日期",
+ "日付"
+ ],
+ [
+ "Vibrate 震动",
+ "バイブレーション"
+ ],
+ [
+ "Cropper 图片裁剪",
+ "画像クロッピング"
+ ],
+ [
+ "Canvas 画布",
+ "キャンバス"
+ ],
+ [
+ "SVG 图标",
+ "SVGアイコン"
+ ],
+ [
+ "SlideVerify 滑动验证",
+ "スライド検証"
+ ],
+ [
+ "转动图片",
+ "画像を回転させる"
+ ],
+ [
+ "验证通过",
+ "検証合格"
+ ],
+ [
+ "验证失败",
+ "検証失敗"
+ ],
+ [
+ "操作",
+ "操作"
+ ],
+ [
+ "清空",
+ "クリア"
+ ],
+ [
+ "预览",
+ "プレビュー"
+ ],
+ [
+ "设置高度",
+ "高さを設定する"
+ ],
+ [
+ "毛笔效果",
+ "筆の効果"
+ ],
+ [
+ "添加LOGO",
+ "ロゴを追加する"
+ ],
+ [
+ "圆角定位点",
+ "丸み付きの位置指定ポイント"
+ ],
+ [
+ "内间距",
+ "内側の余白"
+ ],
+ [
+ "导出图片",
+ "画像をエクスポートする"
+ ],
+ [
+ "矩形",
+ "矩形"
+ ],
+ [
+ "点",
+ "ポイント"
+ ],
+ [
+ "线性",
+ "線形"
+ ],
+ [
+ "小方格",
+ "小さなマス目"
+ ],
+ [
+ "格式化",
+ "フォーマット"
+ ],
+ [
+ "添加",
+ "追加する"
+ ],
+ [
+ "减去",
+ "減らす"
+ ],
+ [
+ "获取某个单位的开始时间",
+ "ある単位の開始時間を取得する"
+ ],
+ [
+ "设置大小",
+ "サイズ設定"
+ ],
+ [
+ "集成 iconfont 与 remixicon 图标库,展示部分示例",
+ "iconfontとremixiconアイコンライブラリを統合し、一部のサンプルを表示"
+ ],
+ [
+ "iconfont",
+ "iconfont"
+ ],
+ [
+ "remixicon",
+ "remixicon"
+ ],
+ [
+ "复制成功",
+ "コピー成功"
+ ],
+ [
+ "普通",
+ "通常"
+ ],
+ [
+ "浅色",
+ "明色"
+ ],
+ [
+ "深色",
+ "暗色"
+ ],
+ [
+ "只显示图标",
+ "アイコンのみ表示"
+ ],
+ [
+ "文本模式",
+ "テキストモード"
+ ],
+ [
+ "带边框",
+ "枠付き"
+ ],
+ [
+ "圆角按钮",
+ "丸角ボタン"
+ ],
+ [
+ "带左侧图标",
+ "左側にアイコン付き"
+ ],
+ [
+ "小",
+ "小"
+ ],
+ [
+ "默认",
+ "デフォルト"
+ ],
+ [
+ "大",
+ "大"
+ ],
+ [
+ "无权限",
+ "無権限"
+ ],
+ [
+ "服务异常",
+ "サービスエラー"
+ ],
+ [
+ "请在微信浏览器中打开",
+ "微信ブラウザで開く"
+ ],
+ [
+ "已取消支付",
+ "支払いをキャンセルしました"
+ ],
+ [
+ "可滑动",
+ "スライド可能"
+ ],
+ [
+ "左滑编辑",
+ "左スワイプで編集"
+ ],
+ [
+ "编辑",
+ "編集"
+ ],
+ [
+ "右滑删除",
+ "右スワイプで削除"
+ ],
+ [
+ "账号",
+ "アカウント"
+ ],
+ [
+ "我的订单",
+ "私の注文"
+ ],
+ [
+ "我的收藏",
+ "私のお気に入り"
+ ],
+ [
+ "筛选",
+ "フィルター"
+ ],
+ [
+ "长按项即可拖动排序",
+ "項目を長押しするとソートできます"
+ ],
+ [
+ "单列排序",
+ "単列ソート"
+ ],
+ [
+ "不需要长按",
+ "長押し不要"
+ ],
+ [
+ "结合列表使用",
+ "リストと併用"
+ ],
+ [
+ "多列排序",
+ "多列ソート"
+ ],
+ [
+ "结合图片使用",
+ "画像と併用"
+ ],
+ [
+ "禁用手势",
+ "ジェスチャーを無効にする"
+ ],
+ [
+ "自定义样式2",
+ "カスタムスタイル2"
+ ],
+ [
+ "无图片",
+ "画像なし"
+ ],
+ [
+ "圆角",
+ "丸角"
+ ],
+ [
+ "自定义大小",
+ "カスタムサイズ"
+ ],
+ [
+ "省略号",
+ "省略記号"
+ ],
+ [
+ "体重",
+ "体重"
+ ],
+ [
+ "所在地区",
+ "所在地区"
+ ],
+ [
+ "出生年月",
+ "出生年月"
+ ],
+ [
+ "个人简介",
+ "個人紹介"
+ ],
+ [
+ "请输入个人简介",
+ "個人紹介を入力してください"
+ ],
+ [
+ "公开状态",
+ "公開状態"
+ ],
+ [
+ "重置",
+ "リセット"
+ ],
+ [
+ "提交",
+ "送信"
+ ],
+ [
+ "未知",
+ "未知"
+ ],
+ [
+ "篮球",
+ "バスケットボール"
+ ],
+ [
+ "足球",
+ "サッカー"
+ ],
+ [
+ "羽毛球",
+ "バドミントン"
+ ],
+ [
+ "乒乓球",
+ "卓球"
+ ],
+ [
+ "游泳",
+ "水泳"
+ ],
+ [
+ "用户名不能为空",
+ "ユーザー名を入力してください"
+ ],
+ [
+ "用户名长度在3-20个字符之间",
+ "ユーザー名は3文字以上20文字以内です"
+ ],
+ [
+ "邮箱不能为空",
+ "メールアドレスを入力してください"
+ ],
+ [
+ "邮箱格式不正确",
+ "メールアドレスの形式が正しくありません"
+ ],
+ [
+ "身高不能为空",
+ "身長を入力してください"
+ ],
+ [
+ "身高在160-190cm之间",
+ "身長は160cm以上190cm以下です"
+ ],
+ [
+ "滑块大点",
+ "スライダーを大きくする"
+ ],
+ [
+ "换个颜色",
+ "色を変える"
+ ],
+ [
+ "最大50",
+ "最大50"
+ ],
+ [
+ "自定义触发器",
+ "カスタムトリガー"
+ ],
+ [
+ "打开选择器",
+ "セレクタを開く"
+ ],
+ [
+ "多列",
+ "複数列"
+ ],
+ [
+ "通过 children 配置多级数据,并使用 column-count 参数指定显示的列数",
+ "childrenを使って多階層データを構成し、column-countパラメータで表示する列数を指定する"
+ ],
+ [
+ "弹窗中使用",
+ "ポップアップで使用する"
+ ],
+ [
+ "打开",
+ "開く"
+ ],
+ [
+ "选择地区",
+ "地域を選択する"
+ ],
+ [
+ "绑定值",
+ "バインド値"
+ ],
+ [
+ "下一步",
+ "次へ"
+ ],
+ [
+ "确定",
+ "確定"
+ ],
+ [
+ "关闭",
+ "閉じる"
+ ],
+ [
+ "显示取消按钮",
+ "キャンセルボタンを表示する"
+ ],
+ [
+ "修改按钮文案",
+ "ボタンの文案を変更する"
+ ],
+ [
+ "显示绑定值",
+ "バインド値を表示する"
+ ],
+ [
+ "时",
+ "時"
+ ],
+ [
+ "时:分",
+ "時:分"
+ ],
+ [
+ "时:分:秒",
+ "時:分:秒"
+ ],
+ [
+ "请输入验证码",
+ "認証コードを入力してください"
+ ],
+ [
+ "登录",
+ "ログイン"
+ ],
+ [
+ "购物车 ({num})",
+ "ショッピングカート ({num})"
+ ],
+ [
+ "完成",
+ "完了"
+ ],
+ [
+ "管理",
+ "管理"
+ ],
+ [
+ "删除",
+ "削除"
+ ],
+ [
+ "全选",
+ "全選択"
+ ],
+ [
+ "合计",
+ "合計"
+ ],
+ [
+ "去结算",
+ "決済へ"
+ ],
+ [
+ "温馨提示",
+ "ご注意"
+ ],
+ [
+ "确定删除该商品吗?",
+ "この商品を削除しますか?"
+ ],
+ [
+ "删除成功",
+ "削除に成功しました"
+ ],
+ [
+ "请先选择商品",
+ "まず商品を選択してください"
+ ],
+ [
+ "确定删除选中的商品吗?",
+ "選択した商品を削除しますか?"
+ ],
+ [
+ "您需支付 {price} 元,请确认支付",
+ "{price}元を支払う必要があります。支払いを確認してください"
+ ],
+ [
+ "支付成功",
+ "支払いに成功しました"
+ ],
+ [
+ "已设为默认",
+ "デフォルトに設定されています"
+ ],
+ [
+ "设为默认",
+ "デフォルトに設定する"
+ ],
+ [
+ "修改",
+ "変更"
+ ],
+ [
+ "添加地址",
+ "住所を追加する"
+ ],
+ [
+ "关于{name}",
+ "{name}に関して"
+ ],
+ [
+ "联系客服",
+ "お客様サポートに連絡"
+ ],
+ [
+ "退出登录",
+ "ログアウト"
+ ],
+ [
+ "确定退出登录吗?",
+ "ログアウトを確定しますか?"
+ ],
+ [
+ "深色模式",
+ "ダークモード"
+ ],
+ [
+ "多语言",
+ "多言語"
+ ],
+ [
+ "字体大小",
+ "フォントサイズ"
+ ],
+ [
+ "访问官网",
+ "公式サイトにアクセス"
+ ],
+ [
+ "商城",
+ "マーケット"
+ ],
+ [
+ "商品分类",
+ "商品分類"
+ ],
+ [
+ "商品详情",
+ "商品詳細"
+ ],
+ [
+ "商品列表、筛选",
+ "商品一覧、絞り込み"
+ ],
+ [
+ "购物车",
+ "ショッピングカート"
+ ],
+ [
+ "订单列表、详情",
+ "注文一覧、詳細"
+ ],
+ [
+ "收货地址",
+ "配送先住所"
+ ],
+ [
+ "聊天",
+ "チャット"
+ ],
+ [
+ "对话列表、历史记录",
+ "対話一覧、履歴"
+ ],
+ [
+ "流式回复",
+ "ストリーミング応答"
+ ],
+ [
+ "语言合成",
+ "音声合成"
+ ],
+ [
+ "语音识别",
+ "音声認識"
+ ],
+ [
+ "日期选择器",
+ "日付選択器"
+ ],
+ [
+ "时间选择器",
+ "時間選択器"
+ ],
+ [
+ "级联选择器",
+ "階層選択器"
+ ],
+ [
+ "文件上传",
+ "ファイルアップロード"
+ ],
+ [
+ "日历",
+ "カレンダー"
+ ],
+ [
+ "布局组件",
+ "レイアウトコンポーネント"
+ ],
+ [
+ "弹性布局",
+ "フレキシブルレイアウト"
+ ],
+ [
+ "标签页",
+ "タブページ"
+ ],
+ [
+ "折叠面板",
+ "コラプスパネル"
+ ],
+ [
+ "吸顶",
+ "固定表示"
+ ],
+ [
+ "导航栏",
+ "ナビゲーションバー"
+ ],
+ [
+ "底部视图",
+ "ボトムビュー"
+ ],
+ [
+ "悬浮视图",
+ "フローティングビュー"
+ ],
+ [
+ "数据展示",
+ "データ表示"
+ ],
+ [
+ "查看更多",
+ "もっと見る"
+ ],
+ [
+ "列表",
+ "リスト"
+ ],
+ [
+ "列表视图",
+ "リストビュー"
+ ],
+ [
+ "列表刷新",
+ "リスト更新"
+ ],
+ [
+ "瀑布流",
+ "ウォーターフォール"
+ ],
+ [
+ "轮播图",
+ "スライドショー"
+ ],
+ [
+ "充值1000元",
+ "1000元を充てんする"
+ ],
+ [
+ "完成首笔交易",
+ "初回取引を完了する"
+ ],
+ [
+ "优选灵活配置混合A",
+ "オプティマルフレックスコンフィギュレーションミックスA"
+ ],
+ [
+ "1000元起",
+ "1000元から"
+ ],
+ [
+ "禁用切换按钮",
+ "切り替えボタンを無効にする"
+ ],
+ [
+ "自定义高度",
+ "カスタム高さ"
+ ],
+ [
+ "多页数",
+ "複数のページ"
+ ],
+ [
+ "上一页",
+ "前のページ"
+ ],
+ [
+ "下一页",
+ "次のページ"
+ ],
+ [
+ "横向滚动",
+ "横スクロール"
+ ],
+ [
+ "纵向滚动",
+ "縦スクロール"
+ ],
+ [
+ "快一点",
+ "もう少し速く"
+ ],
+ [
+ "暂停",
+ "一時停止"
+ ],
+ [
+ "内容靠左",
+ "内容を左寄せにする"
+ ],
+ [
+ "QQ",
+ "QQ"
+ ],
+ [
+ "带箭头",
+ "矢印付き"
+ ],
+ [
+ "余额",
+ "残高"
+ ],
+ [
+ "带图片",
+ "画像付き"
+ ],
+ [
+ "神仙都没用",
+ "神様でも無駄"
+ ],
+ [
+ "折叠",
+ "折りたたむ"
+ ],
+ [
+ "删除地址后无法恢复,确认要删除该地址吗?",
+ "アドレスを削除すると復元できません。このアドレスを削除してもよろしいですか?"
+ ],
+ [
+ "加载中",
+ "読み込み中"
+ ],
+ [
+ "收货人",
+ "受取人"
+ ],
+ [
+ "请输入收货人姓名",
+ "受取人の氏名を入力してください"
+ ],
+ [
+ "手机号",
+ "携帯番号"
+ ],
+ [
+ "选择省市区",
+ "省・市・区を選択してください"
+ ],
+ [
+ "详细地址",
+ "詳細アドレス"
+ ],
+ [
+ "小区楼栋、门牌号、村等",
+ "住宅地のビル、門番、村など"
+ ],
+ [
+ "默认地址",
+ "デフォルトアドレス"
+ ],
+ [
+ "保存",
+ "保存"
+ ],
+ [
+ "收货人不能为空",
+ "受取人は空欄にできません"
+ ],
+ [
+ "手机号不能为空",
+ "携帯番号は空欄にできません"
+ ],
+ [
+ "手机号格式不正确",
+ "携帯番号の形式が正しくありません"
+ ],
+ [
+ "详细地址不能为空",
+ "詳細アドレスは空欄にできません"
+ ],
+ [
+ "所在地区不能为空",
+ "所在地は空欄にできません"
+ ],
+ [
+ "保存中",
+ "保存中"
+ ],
+ [
+ "开启通知",
+ "通知を有効にする"
+ ],
+ [
+ "通用设置",
+ "一般設定"
+ ],
+ [
+ "通知设置",
+ "通知設定"
+ ],
+ [
+ "隐私设置",
+ "プライバシー設定"
+ ],
+ [
+ "跑马灯",
+ "回転ランプ"
+ ],
+ [
+ "分页",
+ "ページング"
+ ],
+ [
+ "时间轴",
+ "タイムライン"
+ ],
+ [
+ "拖拽",
+ "ドラッグ"
+ ],
+ [
+ "筛选栏",
+ "フィルターバー"
+ ],
+ [
+ "树形结构",
+ "ツリー構造"
+ ],
+ [
+ "状态组件",
+ "ステータスコンポーネント"
+ ],
+ [
+ "角标",
+ "バッジ"
+ ],
+ [
+ "通知栏",
+ "通知バー"
+ ],
+ [
+ "倒计时",
+ "カウントダウン"
+ ],
+ [
+ "数字滚动",
+ "数字スクロール"
+ ],
+ [
+ "进度条",
+ "プログレスバー"
+ ],
+ [
+ "圆形进度条",
+ "円形プログレスバー"
+ ],
+ [
+ "骨架图",
+ "スケルトン図"
+ ],
+ [
+ "加载更多",
+ "ロードモア"
+ ],
+ [
+ "反馈组件",
+ "フィードバックコンポーネント"
+ ],
+ [
+ "操作菜单",
+ "操作メニュー"
+ ],
+ [
+ "弹窗",
+ "ポップアップ"
+ ],
+ [
+ "确认框",
+ "確認メッセージ"
+ ],
+ [
+ "提示框",
+ "ヒントメッセージ"
+ ],
+ [
+ "标签格式化",
+ "ラベルフォーマット"
+ ],
+ [
+ "固定开始、结束日期",
+ "固定開始、終了日付"
+ ],
+ [
+ "自定义快捷选项",
+ "カスタムショートカットオプション"
+ ],
+ [
+ "只读",
+ "読み取り専用"
+ ],
+ [
+ "显示分数",
+ "スコアを表示"
+ ],
+ [
+ "允许半星",
+ "半星を許可"
+ ],
+ [
+ "换个图标",
+ "アイコンを変更"
+ ],
+ [
+ "纵向排列",
+ "縦並びにする"
+ ],
+ [
+ "换个样式",
+ "スタイルを変更"
+ ],
+ [
+ "不显示图标",
+ "アイコンを表示しない"
+ ],
+ [
+ "其他样式",
+ "その他のスタイル"
+ ],
+ [
+ "数字键盘",
+ "数字キーボード"
+ ],
+ [
+ "打开键盘",
+ "キーボードを開く"
+ ],
+ [
+ "是否显示输入值",
+ "入力値を表示するかどうか"
+ ],
+ [
+ "输入即绑定",
+ "入力するとバインドする"
+ ],
+ [
+ "身份证键盘",
+ "身分証番号キーボード"
+ ],
+ [
+ "密码键盘",
+ "パスワードキーボード"
+ ],
+ [
+ "是否加密",
+ "暗号化するかどうか"
+ ],
+ [
+ "车牌号键盘",
+ "車両登録番号キーボード"
+ ],
+ [
+ "数字输入",
+ "数字入力"
+ ],
+ [
+ "Flex 弹性布局",
+ "Flex 弾性レイアウト"
+ ],
+ [
+ "Tabs 标签页",
+ "Tabs タブ"
+ ],
+ [
+ "Collapse 折叠面板",
+ "Collapse コラプス"
+ ],
+ [
+ "Sticky 吸顶",
+ "Sticky 固定表示"
+ ],
+ [
+ "TopBar 导航栏",
+ "TopBar ナビゲーションバー"
+ ],
+ [
+ "FloatView 悬浮视图",
+ "FloatView フロートビュー"
+ ],
+ [
+ "Footer 底部视图",
+ "Footer フッタービュー"
+ ],
+ [
+ "List 列表",
+ "List リスト"
+ ],
+ [
+ "ListView 列表视图",
+ "ListView リストビュー"
+ ],
+ [
+ "ListViewRefresh 列表刷新",
+ "ListViewRefresh リスト更新"
+ ],
+ [
+ "Waterfall 瀑布流",
+ "Waterfall ウォーターフォール"
+ ],
+ [
+ "Banner 轮播图",
+ "Banner バナー"
+ ],
+ [
+ "Marquee 跑马灯",
+ "Marquee マーキー"
+ ],
+ [
+ "Pagination 分页",
+ "Pagination ページネーション"
+ ],
+ [
+ "Timeline 时间轴",
+ "Timeline タイムライン"
+ ],
+ [
+ "Avatar 头像",
+ "Avatar アバター"
+ ],
+ [
+ "ReadMore 查看更多",
+ "ReadMore もっと見る"
+ ],
+ [
+ "Draggable 拖拽",
+ "Draggable ドラッグ"
+ ],
+ [
+ "FilterBar 筛选栏",
+ "FilterBar フィルターバー"
+ ],
+ [
+ "Tree 树形结构",
+ "Tree ツリー構造"
+ ],
+ [
+ "无头",
+ "無頭"
+ ],
+ [
+ "左侧",
+ "左側"
+ ],
+ [
+ "右侧",
+ "右側"
+ ],
+ [
+ "隐藏取消按钮",
+ "キャンセルボタンを非表示"
+ ],
+ [
+ "自定义文本",
+ "カスタムテキスト"
+ ],
+ [
+ "关闭前钩子",
+ "クローズ前フック"
+ ],
+ [
+ "显示时长",
+ "表示時間"
+ ],
+ [
+ "确定要删除吗?",
+ "削除しますか?"
+ ],
+ [
+ "确定要删除吗?3秒后自动关闭",
+ "3秒後に自動的にクローズします"
+ ],
+ [
+ "带标题、描述",
+ "タイトルと説明付き"
+ ],
+ [
+ "无法点击遮罩关闭",
+ "マスククリックでクローズ不可"
+ ],
+ [
+ "不需要取消按钮",
+ "キャンセルボタン不要"
+ ],
+ [
+ "插槽用法",
+ "スロットの使い方"
+ ],
+ [
+ "反馈",
+ "フィードバック"
+ ],
+ [
+ "删除好友会同时删除所有聊天记录",
+ "友達を削除すると、全てのチャット履歴も削除されます"
+ ],
+ [
+ "删除好友",
+ "友達を削除する"
+ ],
+ [
+ "确定要删除好友吗?",
+ "友達を削除しますか?"
+ ],
+ [
+ "点我关闭",
+ "ここをクリックしてクローズ"
+ ],
+ [
+ "确定要关闭吗?",
+ "クローズしますか?"
+ ],
+ [
+ "支付宝",
+ "アリペイ"
+ ],
+ [
+ "体重不能为空",
+ "体重を空にできません"
+ ],
+ [
+ "体重在40-100kg之间",
+ "体重は40 - 100kgの間です"
+ ],
+ [
+ "标签不能为空",
+ "ラベルを空にできません"
+ ],
+ [
+ "标签最多选择2个",
+ "ラベルは最大2つまで選択できます"
+ ],
+ [
+ "性别不能为空",
+ "性別を空にできません"
+ ],
+ [
+ "出生年月不能为空",
+ "生年月日を空にできません"
+ ],
+ [
+ "出生年月不大于2010-01-01",
+ "生年月日は2010-01-01より大きくありません"
+ ],
+ [
+ "联系人不能为空",
+ "連絡先を空にできません"
+ ],
+ [
+ "提交成功",
+ "送信成功"
+ ],
+ [
+ "单个 true / false",
+ "単一のtrue/false"
+ ],
+ [
+ "带索引、地区选择",
+ "インデックス付き、地域選択"
+ ],
+ [
+ "换个分隔符",
+ "区切り文字を変更する"
+ ],
+ [
+ "列表高度小一点",
+ "リストの高さを少し小さくする"
+ ],
+ [
+ "范围选",
+ "範囲選択"
+ ],
+ [
+ "禁用部分日期",
+ "一部の日付を無効にする"
+ ],
+ [
+ "日历长列表",
+ "カレンダーの長いリスト"
+ ],
+ [
+ "打开日历长列表",
+ "カレンダーの長いリストを開く"
+ ],
+ [
+ "日历面板",
+ "カレンダーパネル"
+ ],
+ [
+ "自定义文案和颜色",
+ "カスタム文案と色"
+ ],
+ [
+ "显示头",
+ "ヘッドを表示する"
+ ],
+ [
+ "支付失败",
+ "支払い失敗"
+ ],
+ [
+ "授权信息仅用于用户登录",
+ "認証情報はユーザーログインにのみ使用されます"
+ ],
+ [
+ "登录授权失败",
+ "ログイン認証失敗"
+ ],
+ [
+ "获取短信验证码",
+ "SMS認証コードを取得する"
+ ],
+ [
+ "验证码",
+ "認証コード"
+ ],
+ [
+ "发送短信",
+ "SMSを送信する"
+ ],
+ [
+ "{n}s后重新获取",
+ "{n}秒後に再取得"
+ ],
+ [
+ "获取验证码",
+ "認証コードを取得する"
+ ],
+ [
+ "短信已发送,请查收",
+ "SMSが送信されました。ご確認ください。"
+ ],
+ [
+ "请填写验证码",
+ "認証コードを入力してください。"
+ ],
+ [
+ "请填写正确的手机号格式",
+ "正しい携帯番号形式を入力してください。"
+ ],
+ [
+ "全局字号",
+ "グローバル文字サイズ"
+ ],
+ [
+ "这是一段示例文字,用于预览不同字号的效果。",
+ "これは、異なる文字サイズの表示を確認するためのサンプルテキストです。"
+ ],
+ [
+ "默认 1.0",
+ "デフォルト1.0"
+ ],
+ [
+ "切换语言",
+ "言語を切り替える"
+ ],
+ [
+ "切换中",
+ "切り替え中"
+ ],
+ [
+ "模板",
+ "テンプレート"
+ ],
+ [
+ "编辑资料",
+ "プロフィールを編集する"
+ ],
+ [
+ "Text 文本",
+ "Text テキスト"
+ ],
+ [
+ "Button 按钮",
+ "Button ボタン"
+ ],
+ [
+ "插槽",
+ "スロット"
+ ],
+ [
+ "使用 PT 自定义颜色",
+ "PT を使用してカスタム カラーを設定する"
+ ],
+ [
+ "自定义返回图标",
+ "カスタム戻るアイコン"
+ ],
+ [
+ "自定义返回路径",
+ "カスタム戻るパス"
+ ],
+ [
+ "自定义标题内容",
+ "カスタム タイトル コンテンツ"
+ ],
+ [
+ "显示滑块",
+ "スライダーを表示する"
+ ],
+ [
+ "添加间距",
+ "余白を追加する"
+ ],
+ [
+ "横向填充",
+ "横方向に埋める"
+ ],
+ [
+ "适用于标签数量不多的情况",
+ "タグの数が少ない場合に適用する"
+ ],
+ [
+ "居中",
+ "中央に配置する"
+ ],
+ [
+ "单个禁用",
+ "単一で無効にする"
+ ],
+ [
+ "显示下划线",
+ "下線を表示する"
+ ],
+ [
+ "禁用",
+ "無効にする"
+ ],
+ [
+ "取消订单",
+ "注文をキャンセルする"
+ ],
+ [
+ "立即购买",
+ "すぐに購入する"
+ ],
+ [
+ "确认收货",
+ "商品受け取りを確認する"
+ ],
+ [
+ "评价",
+ "評価する"
+ ],
+ [
+ "禁用状态,无法拖拽",
+ "無効状態で、ドラッグできない"
+ ],
+ [
+ "不吸附边缘,任意位置可拖拽",
+ "端に吸着せず、任意の位置でドラッグ可能"
+ ],
+ [
+ "这是一个提示",
+ "これはヒントです"
+ ],
+ [
+ "获取某个单位的结束时间",
+ "ある単位の終了時間を取得する"
+ ],
+ [
+ "是否同一天",
+ "同日かどうか"
+ ],
+ [
+ "是否早于",
+ "早いかどうか"
+ ],
+ [
+ "是否晚于",
+ "遅いかどうか"
+ ],
+ [
+ "差值",
+ "差分"
+ ],
+ [
+ "差值(单位)",
+ "差分(単位)"
+ ],
+ [
+ "选择图片",
+ "画像を選択する"
+ ],
+ [
+ "可调节裁剪框大小",
+ "裁断枠のサイズを調整可能"
+ ],
+ [
+ "预览图片",
+ "画像をプレビューする"
+ ],
+ [
+ "保存图片",
+ "画像を保存する"
+ ],
+ [
+ "本页面内容由 canvas 渲染生成,是否立即预览图片效果?",
+ "このページの内容はキャンバスでレンダリングされています。画像の効果をすぐにプレビューしますか?"
+ ],
+ [
+ "基础动画",
+ "基本アニメーション"
+ ],
+ [
+ "淡入淡出",
+ "フェードインとフェードアウト"
+ ],
+ [
+ "播放动画",
+ "アニメーションを再生する"
+ ],
+ [
+ "滑入",
+ "スライドイン"
+ ],
+ [
+ "旋转翻转",
+ "回転と反転"
+ ],
+ [
+ "摇摆抖动",
+ "揺れと震え"
+ ],
+ [
+ "特殊效果",
+ "特殊効果"
+ ],
+ [
+ "组合动画",
+ "コンビネーションアニメーション"
+ ],
+ [
+ "标题",
+ "タイトル"
+ ],
+ [
+ "头像上传成功",
+ "アイコンアップロード成功"
+ ],
+ [
+ "编辑昵称",
+ "ニックネーム編集"
+ ],
+ [
+ "请输入昵称",
+ "ニックネームを入力してください"
+ ],
+ [
+ "请设置2-20个字符,不包括@<>/等无效字符",
+ "2-20文字を設定してください。@<>/などの無効文字は含まないでください"
+ ],
+ [
+ "确认",
+ "確認"
+ ],
+ [
+ "昵称长度需在2-20个字符之间",
+ "ニックネームの長さは2-20文字の間です"
+ ],
+ [
+ "昵称不能包含@<>/等特殊字符",
+ "ニックネームには@<>/などの特殊文字を含めることができません"
+ ],
+ [
+ "编辑简介",
+ "プロフィール編集"
+ ],
+ [
+ "简介不能为空",
+ "プロフィールは空にできません"
+ ],
+ [
+ "提示",
+ "ヒント"
+ ],
+ [
+ "为提供更好的服务,我们邀请您填写昵称、头像等公开信息",
+ "より良いサービスを提供するため、ニックネーム、アイコンなどの公開情報を記入していただきますようお願いいたします"
+ ],
+ [
+ "头像",
+ "アイコン"
+ ],
+ [
+ "昵称",
+ "ニックネーム"
+ ],
+ [
+ "点击输入昵称",
+ "ニックネームを入力してください"
+ ],
+ [
+ "取消",
+ "キャンセル"
+ ],
+ [
+ "请上传头像",
+ "アイコンをアップロードしてください"
+ ],
+ [
+ "登录中",
+ "ログイン中"
+ ],
+ [
+ "手机登录",
+ "モバイルログイン"
+ ],
+ [
+ "未注册的手机号登录成功后将自动注册",
+ "未登録の携帯番号でログインすると自動的に登録されます"
+ ],
+ [
+ "请输入手机号",
+ "携帯番号を入力してください"
+ ],
+ [
+ "Image 图片",
+ "画像 イメージ"
+ ],
+ [
+ "Icon 图标",
+ "アイコン アイコン"
+ ],
+ [
+ "Tag 标签",
+ "タグ タグ"
+ ],
+ [
+ "Form 表单验证",
+ "フォーム フォーム検証"
+ ],
+ [
+ "Input 输入框",
+ "入力 入力欄"
+ ],
+ [
+ "Textarea 文本域",
+ "テキストエリア テキストエリア"
+ ],
+ [
+ "InputNumber 计数器",
+ "入力番号 カウンター"
+ ],
+ [
+ "InputOtp 口令输入",
+ "OTP入力 パスワード入力"
+ ],
+ [
+ "Keyboard 键盘",
+ "キーボード キーボード"
+ ],
+ [
+ "Radio 单选框",
+ "ラジオ ラジオボタン"
+ ],
+ [
+ "Checkbox 多选框",
+ "チェックボックス チェックボックス"
+ ],
+ [
+ "Switch 开关",
+ "スイッチ スイッチ"
+ ],
+ [
+ "Rate 评分",
+ "評価 評価"
+ ],
+ [
+ "Slider 滑块",
+ "スライダー スライダー"
+ ],
+ [
+ "Select 选择器",
+ "セレクト セレクター"
+ ],
+ [
+ "SelectDate 日期选择器",
+ "日付選択 日付選択器"
+ ],
+ [
+ "SelectTime 时间选择器",
+ "時間選択 時間選択器"
+ ],
+ [
+ "Cascader 级联选择器",
+ "階層選択 階層選択器"
+ ],
+ [
+ "Upload 文件上传",
+ "アップロード ファイルアップロード"
+ ],
+ [
+ "Calendar 日历",
+ "カレンダー カレンダー"
+ ]
+]
\ No newline at end of file
diff --git a/cool-unix/locale/ko.json b/cool-unix/locale/ko.json
new file mode 100644
index 0000000..2afd28c
--- /dev/null
+++ b/cool-unix/locale/ko.json
@@ -0,0 +1,2502 @@
+[
+ [
+ "Animation 动画",
+ "애니메이션"
+ ],
+ [
+ "编辑地址",
+ "편집 주소"
+ ],
+ [
+ "cool-unix",
+ "cool-unix"
+ ],
+ [
+ "首页",
+ "홈"
+ ],
+ [
+ "我的",
+ "제가"
+ ],
+ [
+ "转动图片",
+ "사진 회전"
+ ],
+ [
+ "验证通过",
+ "검증 통과"
+ ],
+ [
+ "验证失败",
+ "검증 실패"
+ ],
+ [
+ "操作",
+ "작업"
+ ],
+ [
+ "清空",
+ "지우기"
+ ],
+ [
+ "预览",
+ "미리보기"
+ ],
+ [
+ "设置高度",
+ "높이 설정"
+ ],
+ [
+ "毛笔效果",
+ "붓 효과"
+ ],
+ [
+ "添加LOGO",
+ "로고 추가"
+ ],
+ [
+ "圆角定位点",
+ "둥근 모서리 위치 지점"
+ ],
+ [
+ "内间距",
+ "내부 여백"
+ ],
+ [
+ "导出图片",
+ "사진 내보내기"
+ ],
+ [
+ "矩形",
+ "직사각형"
+ ],
+ [
+ "点",
+ "점"
+ ],
+ [
+ "线性",
+ "선형"
+ ],
+ [
+ "小方格",
+ "작은 사각형"
+ ],
+ [
+ "格式化",
+ "식식화"
+ ],
+ [
+ "添加",
+ "추가"
+ ],
+ [
+ "减去",
+ "뺄셈"
+ ],
+ [
+ "获取某个单位的开始时间",
+ "어떤 단위의 시작 시간 가져오기"
+ ],
+ [
+ "显示星期",
+ "星期 표시"
+ ],
+ [
+ "显示其他月份",
+ "다른 월 표시"
+ ],
+ [
+ "不同位置",
+ "다른 위치"
+ ],
+ [
+ "顶部",
+ "상단"
+ ],
+ [
+ "中间",
+ "중간"
+ ],
+ [
+ "底部",
+ "하단"
+ ],
+ [
+ "不同类型",
+ "다른 유형"
+ ],
+ [
+ "成功",
+ "성공"
+ ],
+ [
+ "失败",
+ "실패"
+ ],
+ [
+ "警告",
+ "경고"
+ ],
+ [
+ "问题",
+ "문제"
+ ],
+ [
+ "停止",
+ "중지"
+ ],
+ [
+ "自定义图标",
+ "사용자 지정 아이콘"
+ ],
+ [
+ "只存在一个",
+ "하나만 존재"
+ ],
+ [
+ "不同位置提示",
+ "다른 위치 팁"
+ ],
+ [
+ "不同类型提示",
+ "다른 유형 팁"
+ ],
+ [
+ "带图标提示",
+ "아이콘 있는 팁"
+ ],
+ [
+ "移除其他已存在的提示",
+ "다른 존재하는 팁 제거"
+ ],
+ [
+ "打开弹窗",
+ "팝업 열기"
+ ],
+ [
+ "设置宽度 80%",
+ "너비 80% 설정"
+ ],
+ [
+ "开发中,敬请期待",
+ "개발 중입니다. 잠시만 기다려주세요."
+ ],
+ [
+ "基础组件",
+ "기본 컴포넌트"
+ ],
+ [
+ "文本",
+ "텍스트"
+ ],
+ [
+ "按钮",
+ "버튼"
+ ],
+ [
+ "图片",
+ "이미지"
+ ],
+ [
+ "图标",
+ "아이콘"
+ ],
+ [
+ "标签",
+ "레이블"
+ ],
+ [
+ "表单组件",
+ "폼 컴포넌트"
+ ],
+ [
+ "表单验证",
+ "폼 검증"
+ ],
+ [
+ "输入框",
+ "입력 상자"
+ ],
+ [
+ "文本域",
+ "텍스트 영역"
+ ],
+ [
+ "计数器",
+ "카운터"
+ ],
+ [
+ "口令输入",
+ "비밀번호 입력"
+ ],
+ [
+ "键盘",
+ "키보드"
+ ],
+ [
+ "单选框",
+ "라디오 버튼"
+ ],
+ [
+ "多选框",
+ "체크 박스"
+ ],
+ [
+ "开关",
+ "스위치"
+ ],
+ [
+ "评分",
+ "평가"
+ ],
+ [
+ "滑块",
+ "슬라이더"
+ ],
+ [
+ "选择器",
+ "선택기"
+ ],
+ [
+ "其他",
+ "기타"
+ ],
+ [
+ "文件管理",
+ "파일 관리"
+ ],
+ [
+ "该模板正在开发中",
+ "이 템플릿은 개발 중입니다."
+ ],
+ [
+ "未登录",
+ "로그인하지 않음"
+ ],
+ [
+ "总点击",
+ "총 클릭 수"
+ ],
+ [
+ "赞",
+ "좋아요"
+ ],
+ [
+ "收藏",
+ "찜"
+ ],
+ [
+ "粉丝",
+ "팬"
+ ],
+ [
+ "接单模式",
+ "주문 모드"
+ ],
+ [
+ "已关闭",
+ "닫힘"
+ ],
+ [
+ "消息通知",
+ "메시지 알림"
+ ],
+ [
+ "待支付",
+ "결제 대기"
+ ],
+ [
+ "未发货",
+ "배송 전"
+ ],
+ [
+ "已发货",
+ "배송 완료"
+ ],
+ [
+ "售后 / 退款",
+ "AS / 환불"
+ ],
+ [
+ "我的钱包",
+ "내 지갑"
+ ],
+ [
+ "数据看板",
+ "데이터 보드"
+ ],
+ [
+ "历史记录",
+ "히스토리"
+ ],
+ [
+ "邀请好友",
+ "친구 초대"
+ ],
+ [
+ "设置",
+ "설정"
+ ],
+ [
+ "密码输入",
+ "비밀번호 입력"
+ ],
+ [
+ "可清除",
+ "삭제 가능"
+ ],
+ [
+ "左右插槽",
+ "좌우 슬롯"
+ ],
+ [
+ "左图标",
+ "왼쪽 아이콘"
+ ],
+ [
+ "右图标",
+ "오른쪽 아이콘"
+ ],
+ [
+ "自动聚焦",
+ "자동 집중"
+ ],
+ [
+ "长度为6",
+ "길이 6"
+ ],
+ [
+ "步进为10",
+ "스텝 10"
+ ],
+ [
+ "最小为10",
+ "최소 10"
+ ],
+ [
+ "最大为50",
+ "최대 50"
+ ],
+ [
+ "可以小数",
+ "소수 가능"
+ ],
+ [
+ "可以输入",
+ "입력 가능"
+ ],
+ [
+ "用户名",
+ "사용자 이름"
+ ],
+ [
+ "请输入用户名",
+ "사용자 이름을 입력하세요"
+ ],
+ [
+ "邮箱",
+ "이메일"
+ ],
+ [
+ "请输入邮箱地址",
+ "이메일 주소를 입력하세요"
+ ],
+ [
+ "动态验证",
+ "동적 검증"
+ ],
+ [
+ "联系人",
+ "연락처"
+ ],
+ [
+ "添加联系人",
+ "연락처 추가"
+ ],
+ [
+ "身高",
+ "키"
+ ],
+ [
+ "体重",
+ "체중"
+ ],
+ [
+ "所在地区",
+ "소재지역"
+ ],
+ [
+ "出生年月",
+ "출생년월일"
+ ],
+ [
+ "个人简介",
+ "개인소개"
+ ],
+ [
+ "请输入个人简介",
+ "개인소개를 입력하세요"
+ ],
+ [
+ "公开状态",
+ "공개상태"
+ ],
+ [
+ "重置",
+ "리셋"
+ ],
+ [
+ "提交",
+ "제출"
+ ],
+ [
+ "未知",
+ "미상"
+ ],
+ [
+ "篮球",
+ "농구"
+ ],
+ [
+ "足球",
+ "축구"
+ ],
+ [
+ "羽毛球",
+ "배드민턴"
+ ],
+ [
+ "乒乓球",
+ "탁구"
+ ],
+ [
+ "游泳",
+ "수영"
+ ],
+ [
+ "用户名不能为空",
+ "사용자 이름은 비어있을 수 없습니다"
+ ],
+ [
+ "用户名长度在3-20个字符之间",
+ "사용자 이름은 3-20자 사이입니다"
+ ],
+ [
+ "邮箱不能为空",
+ "이메일은 비어있을 수 없습니다"
+ ],
+ [
+ "邮箱格式不正确",
+ "이메일 형식이 올바르지 않습니다"
+ ],
+ [
+ "身高不能为空",
+ "키는 비어있을 수 없습니다"
+ ],
+ [
+ "身高在160-190cm之间",
+ "키는 160-190cm 사이입니다"
+ ],
+ [
+ "跑马灯",
+ "走马灯"
+ ],
+ [
+ "分页",
+ "페이징"
+ ],
+ [
+ "时间轴",
+ "타임라인"
+ ],
+ [
+ "拖拽",
+ "드래그 앤 드롭"
+ ],
+ [
+ "筛选栏",
+ "필터 바"
+ ],
+ [
+ "树形结构",
+ "트리 구조"
+ ],
+ [
+ "状态组件",
+ "상태 구성 요소"
+ ],
+ [
+ "角标",
+ "뱃지"
+ ],
+ [
+ "通知栏",
+ "通知 막대"
+ ],
+ [
+ "倒计时",
+ "카운트 다운"
+ ],
+ [
+ "数字滚动",
+ "숫자 스크롤"
+ ],
+ [
+ "进度条",
+ "진도 막대"
+ ],
+ [
+ "圆形进度条",
+ "원형 진도 막대"
+ ],
+ [
+ "骨架图",
+ "스켈레톤 그림"
+ ],
+ [
+ "加载更多",
+ "더 로드"
+ ],
+ [
+ "反馈组件",
+ "피드백 구성 요소"
+ ],
+ [
+ "操作菜单",
+ "작업 메뉴"
+ ],
+ [
+ "弹窗",
+ "팝업 창"
+ ],
+ [
+ "确认框",
+ "확인 창"
+ ],
+ [
+ "提示框",
+ "힌트 창"
+ ],
+ [
+ "左间隔",
+ "왼쪽 여백"
+ ],
+ [
+ "右移动",
+ "오른쪽 이동"
+ ],
+ [
+ "左移动",
+ "왼쪽 이동"
+ ],
+ [
+ "多个数据",
+ "여러 데이터"
+ ],
+ [
+ "点击收起",
+ "클릭하여 접기"
+ ],
+ [
+ "点击展开",
+ "클릭하여 확장"
+ ],
+ [
+ "ref 方式调用",
+ "ref 방식 호출"
+ ],
+ [
+ "自定义图标、文字、大小",
+ "사용자 정의 아이콘, 텍스트, 크기"
+ ],
+ [
+ "上传证件照",
+ "증명 사진 업로드"
+ ],
+ [
+ "多选",
+ "다중 선택"
+ ],
+ [
+ "限制 3 个",
+ "3개 제한"
+ ],
+ [
+ "边框",
+ "테두리"
+ ],
+ [
+ "显示字数",
+ "표시 글자 수"
+ ],
+ [
+ "自动增高",
+ "자동 높이 증가"
+ ],
+ [
+ "其他颜色",
+ "다른 색상"
+ ],
+ [
+ "大一点",
+ "좀 더 크게"
+ ],
+ [
+ "正方形",
+ "정사각형"
+ ],
+ [
+ "范围选择",
+ "범위 선택"
+ ],
+ [
+ "显示值",
+ "표시 값"
+ ],
+ [
+ "步长10",
+ "스텝 10"
+ ],
+ [
+ "Badge 角标",
+ "배지"
+ ],
+ [
+ "NoticeBar 通知栏",
+ "공지사항바"
+ ],
+ [
+ "Countdown 倒计时",
+ "카운트다운"
+ ],
+ [
+ "Progress 进度条",
+ "진도표"
+ ],
+ [
+ "ProgressCircle 圆形进度条",
+ "원형진도표"
+ ],
+ [
+ "Skeleton 骨架图",
+ "스켈레톤"
+ ],
+ [
+ "LoadMore 加载更多",
+ "더 로드"
+ ],
+ [
+ "RollingNumber 数字滚动",
+ "숫자롤링"
+ ],
+ [
+ "ActionSheet 操作菜单",
+ "액션시트"
+ ],
+ [
+ "Popup 弹窗",
+ "팝업"
+ ],
+ [
+ "Confirm 确认框",
+ "확인창"
+ ],
+ [
+ "Toast 提示框",
+ "토스트"
+ ],
+ [
+ "QRCode 二维码",
+ "QR코드"
+ ],
+ [
+ "Sign 签名",
+ "서명"
+ ],
+ [
+ "DayUts 日期",
+ "날짜"
+ ],
+ [
+ "Vibrate 震动",
+ "진동"
+ ],
+ [
+ "Cropper 图片裁剪",
+ "이미지자르기"
+ ],
+ [
+ "Canvas 画布",
+ "캔버스"
+ ],
+ [
+ "SVG 图标",
+ "SVG아이콘"
+ ],
+ [
+ "SlideVerify 滑动验证",
+ "슬라이드검증"
+ ],
+ [
+ "设置大小",
+ "크기 설정"
+ ],
+ [
+ "集成 iconfont 与 remixicon 图标库,展示部分示例",
+ "iconfont와 remixicon 아이콘 라이브러리를 통합하여 일부 예시를 보여줍니다."
+ ],
+ [
+ "iconfont",
+ "iconfont"
+ ],
+ [
+ "remixicon",
+ "remixicon"
+ ],
+ [
+ "复制成功",
+ "복사 성공"
+ ],
+ [
+ "普通",
+ "보통"
+ ],
+ [
+ "浅色",
+ "얼음색"
+ ],
+ [
+ "深色",
+ "진한색"
+ ],
+ [
+ "只显示图标",
+ "아이콘만 표시"
+ ],
+ [
+ "文本模式",
+ "텍스트 모드"
+ ],
+ [
+ "带边框",
+ "테두리가 있는"
+ ],
+ [
+ "圆角按钮",
+ "둥근 모서리 버튼"
+ ],
+ [
+ "带左侧图标",
+ "왼쪽 아이콘"
+ ],
+ [
+ "小",
+ "작음"
+ ],
+ [
+ "默认",
+ "기본"
+ ],
+ [
+ "大",
+ "큰"
+ ],
+ [
+ "无权限",
+ "권한 없음"
+ ],
+ [
+ "服务异常",
+ "서비스 예외"
+ ],
+ [
+ "请在微信浏览器中打开",
+ "위챗 브라우저에서 열어주세요."
+ ],
+ [
+ "已取消支付",
+ "결제 취소됨"
+ ],
+ [
+ "滑块大点",
+ "슬라이더 크게"
+ ],
+ [
+ "换个颜色",
+ "색 변경"
+ ],
+ [
+ "最大50",
+ "최대 50"
+ ],
+ [
+ "自定义触发器",
+ "사용자 지정 트리거"
+ ],
+ [
+ "打开选择器",
+ "선택기 열기"
+ ],
+ [
+ "多列",
+ "다중 열"
+ ],
+ [
+ "通过 children 配置多级数据,并使用 column-count 参数指定显示的列数",
+ "children을 통해 다단계 데이터 구성, column-count 매개변수를 사용하여 표시 열 수 지정"
+ ],
+ [
+ "弹窗中使用",
+ "팝업에서 사용"
+ ],
+ [
+ "打开",
+ "열기"
+ ],
+ [
+ "选择地区",
+ "지역 선택"
+ ],
+ [
+ "绑定值",
+ "바인딩 값"
+ ],
+ [
+ "下一步",
+ "다음"
+ ],
+ [
+ "确定",
+ "확인"
+ ],
+ [
+ "关闭",
+ "닫기"
+ ],
+ [
+ "显示取消按钮",
+ "취소 버튼 표시"
+ ],
+ [
+ "修改按钮文案",
+ "버튼 텍스트 수정"
+ ],
+ [
+ "显示绑定值",
+ "바인딩 값 표시"
+ ],
+ [
+ "时",
+ "시"
+ ],
+ [
+ "时:分",
+ "시:분"
+ ],
+ [
+ "时:分:秒",
+ "시:분:초"
+ ],
+ [
+ "已阅读并同意",
+ "읽고 동의함"
+ ],
+ [
+ "用户协议",
+ "사용자 약관"
+ ],
+ [
+ "隐私政策",
+ "개인 정보 보호 정책"
+ ],
+ [
+ "请先阅读并同意《用户协议》和《隐私政策》",
+ "먼저 《사용자 약관》과 《개인 정보 보호 정책》을 읽고 동의해 주세요."
+ ],
+ [
+ "我的昵称",
+ "제 닉네임"
+ ],
+ [
+ "简介",
+ "소개"
+ ],
+ [
+ "介绍一下自己",
+ "자기 자신을 소개해 주세요."
+ ],
+ [
+ "性别",
+ "성별"
+ ],
+ [
+ "编辑性别",
+ "성별 편집"
+ ],
+ [
+ "生日",
+ "생일"
+ ],
+ [
+ "选择生日",
+ "생일 선택"
+ ],
+ [
+ "地区",
+ "지역"
+ ],
+ [
+ "选择所在的地区",
+ "자신이 있는 지역 선택"
+ ],
+ [
+ "选择性别",
+ "성별 선택"
+ ],
+ [
+ "保密",
+ "비공개"
+ ],
+ [
+ "男",
+ "남"
+ ],
+ [
+ "女",
+ "여"
+ ],
+ [
+ "性别设置成功",
+ "성별 설정 성공"
+ ],
+ [
+ "生日设置成功",
+ "생일 설정 성공"
+ ],
+ [
+ "地区设置成功",
+ "지역 설정 성공"
+ ],
+ [
+ "Image 图片",
+ "Image 이미지"
+ ],
+ [
+ "Icon 图标",
+ "Icon 아이콘"
+ ],
+ [
+ "Tag 标签",
+ "Tag 태그"
+ ],
+ [
+ "Form 表单验证",
+ "Form 폼 검증"
+ ],
+ [
+ "Input 输入框",
+ "Input 입력框"
+ ],
+ [
+ "Textarea 文本域",
+ "Textarea 텍스트 영역"
+ ],
+ [
+ "InputNumber 计数器",
+ "InputNumber 카운터"
+ ],
+ [
+ "InputOtp 口令输入",
+ "InputOtp 비밀번호 입력"
+ ],
+ [
+ "Keyboard 键盘",
+ "Keyboard 키보드"
+ ],
+ [
+ "Radio 单选框",
+ "Radio 단일 선택"
+ ],
+ [
+ "Checkbox 多选框",
+ "Checkbox 다중 선택"
+ ],
+ [
+ "Switch 开关",
+ "Switch 스위치"
+ ],
+ [
+ "Rate 评分",
+ "Rate 평가"
+ ],
+ [
+ "Slider 滑块",
+ "Slider 슬라이더"
+ ],
+ [
+ "Select 选择器",
+ "Select 선택기"
+ ],
+ [
+ "SelectDate 日期选择器",
+ "SelectDate 날짜 선택기"
+ ],
+ [
+ "SelectTime 时间选择器",
+ "SelectTime 시간 선택기"
+ ],
+ [
+ "Cascader 级联选择器",
+ "Cascader 계층 선택기"
+ ],
+ [
+ "Upload 文件上传",
+ "Upload 파일 업로드"
+ ],
+ [
+ "Calendar 日历",
+ "Calendar 달력"
+ ],
+ [
+ "关于{name}",
+ "{name}에 관한"
+ ],
+ [
+ "联系客服",
+ "고객 서비스에 연결"
+ ],
+ [
+ "退出登录",
+ "로그아웃"
+ ],
+ [
+ "确定退出登录吗?",
+ "로그아웃을 확정하시겠습니까?"
+ ],
+ [
+ "深色模式",
+ "다크 모드"
+ ],
+ [
+ "多语言",
+ "다국어"
+ ],
+ [
+ "字体大小",
+ "폰트 크기"
+ ],
+ [
+ "访问官网",
+ "사이트에 방문"
+ ],
+ [
+ "商城",
+ "몰"
+ ],
+ [
+ "商品分类",
+ "상품 분류"
+ ],
+ [
+ "商品详情",
+ "상품 상세 정보"
+ ],
+ [
+ "商品列表、筛选",
+ "상품 목록, 필터링"
+ ],
+ [
+ "购物车",
+ "장바구니"
+ ],
+ [
+ "订单列表、详情",
+ "주문 목록, 상세 정보"
+ ],
+ [
+ "收货地址",
+ "배송 주소"
+ ],
+ [
+ "聊天",
+ "채팅"
+ ],
+ [
+ "对话列表、历史记录",
+ "대화 목록, 이력 기록"
+ ],
+ [
+ "流式回复",
+ "스트리밍 응답"
+ ],
+ [
+ "语言合成",
+ "음성 합성"
+ ],
+ [
+ "语音识别",
+ "음성 인식"
+ ],
+ [
+ "多行省略号",
+ "다중 줄 생략 기호"
+ ],
+ [
+ "金额",
+ "금액"
+ ],
+ [
+ "手机号脱敏",
+ "휴대폰 번호 마스킹"
+ ],
+ [
+ "姓名脱敏",
+ "이름 마스킹"
+ ],
+ [
+ "邮箱脱敏",
+ "이메일 마스킹"
+ ],
+ [
+ "银行卡脱敏",
+ "은행 카드 마스킹"
+ ],
+ [
+ "自定义脱敏字符",
+ "사용자 정의 마스킹 문자"
+ ],
+ [
+ "主要",
+ "주요"
+ ],
+ [
+ "危险",
+ "위험"
+ ],
+ [
+ "信息",
+ "정보"
+ ],
+ [
+ "邮件",
+ "메일"
+ ],
+ [
+ "文件",
+ "파일"
+ ],
+ [
+ "可关闭",
+ "닫을 수 있음"
+ ],
+ [
+ "镂空",
+ "공백"
+ ],
+ [
+ "自定义无圆角",
+ "사용자 정의 둥근 모서리 없음"
+ ],
+ [
+ "不同裁剪",
+ "다른 자르기"
+ ],
+ [
+ "点击可预览",
+ "클릭하여 미리보기 가능"
+ ],
+ [
+ "失败时显示",
+ "실패 시 표시"
+ ],
+ [
+ "自定义圆角",
+ "사용자 정의 둥근 모서리"
+ ],
+ [
+ "设置颜色",
+ "색 설정"
+ ],
+ [
+ "日期选择器",
+ "날짜 선택기"
+ ],
+ [
+ "时间选择器",
+ "시간 선택기"
+ ],
+ [
+ "级联选择器",
+ "계층 선택기"
+ ],
+ [
+ "文件上传",
+ "파일 업로드"
+ ],
+ [
+ "日历",
+ "달력"
+ ],
+ [
+ "布局组件",
+ "레이아웃 구성 요소"
+ ],
+ [
+ "弹性布局",
+ "탄력적 레이아웃"
+ ],
+ [
+ "标签页",
+ "탭 페이지"
+ ],
+ [
+ "折叠面板",
+ "접혀 있는 패널"
+ ],
+ [
+ "吸顶",
+ "상단 고정"
+ ],
+ [
+ "导航栏",
+ "네비게이션 막대"
+ ],
+ [
+ "底部视图",
+ "하단 뷰"
+ ],
+ [
+ "悬浮视图",
+ "부유 뷰"
+ ],
+ [
+ "数据展示",
+ "데이터 표시"
+ ],
+ [
+ "查看更多",
+ "더 보기"
+ ],
+ [
+ "列表",
+ "목록"
+ ],
+ [
+ "列表视图",
+ "목록 뷰"
+ ],
+ [
+ "列表刷新",
+ "목록 새로 고침"
+ ],
+ [
+ "瀑布流",
+ "물결 흐름"
+ ],
+ [
+ "轮播图",
+ "슬라이드 쇼"
+ ],
+ [
+ "垂直方向",
+ "수직 방향"
+ ],
+ [
+ "3秒后加载完成",
+ "3초 후 로드 완료"
+ ],
+ [
+ "隐藏为 00 的值",
+ "00 값을 숨김"
+ ],
+ [
+ "指定天数",
+ "지정된 일 수"
+ ],
+ [
+ "自定义模板",
+ "사용자 정의 템플릿"
+ ],
+ [
+ "指定小时",
+ "지정된 시간"
+ ],
+ [
+ "指定分钟",
+ "지정된 분"
+ ],
+ [
+ "指定秒",
+ "지정된 초"
+ ],
+ [
+ "完成后提示",
+ "완료 후 팁"
+ ],
+ [
+ "3秒后开始倒计时",
+ "3초 후 카운트 다운 시작"
+ ],
+ [
+ "结合按钮",
+ "버튼 결합"
+ ],
+ [
+ "购买",
+ "구매"
+ ],
+ [
+ "消息",
+ "메시지"
+ ],
+ [
+ "结合图片",
+ "이미지 결합"
+ ],
+ [
+ "结合图标",
+ "아이콘 결합"
+ ],
+ [
+ "点击触发",
+ "클릭으로 트리거"
+ ],
+ [
+ "不同大小",
+ "다양한 크기"
+ ],
+ [
+ "不同颜色",
+ "다양한 색상"
+ ],
+ [
+ "使用base64",
+ "base64 사용"
+ ],
+ [
+ "没有错误提示",
+ "에러 메시지 없음"
+ ],
+ [
+ "签名",
+ "서명"
+ ],
+ [
+ "图片裁剪",
+ "이미지 자르기"
+ ],
+ [
+ "Canvas",
+ "캔버스"
+ ],
+ [
+ "富文本",
+ "부채꼴 텍스트"
+ ],
+ [
+ "该功能正在开发中",
+ "이 기능은 개발 중입니다."
+ ],
+ [
+ "圆形",
+ "원형"
+ ],
+ [
+ "组合",
+ "조합"
+ ],
+ [
+ "基础用法",
+ "기본 사용법"
+ ],
+ [
+ "自定义",
+ "사용자 정의"
+ ],
+ [
+ "加快滚动速度",
+ "롤링 속도加快"
+ ],
+ [
+ "显示小数位数",
+ "소수점 자릿수 표시"
+ ],
+ [
+ "自定义样式",
+ "사용자 정의 스타일"
+ ],
+ [
+ "自定义颜色",
+ "사용자 정의 색상"
+ ],
+ [
+ "自定义宽度",
+ "사용자 정의 너비"
+ ],
+ [
+ "不显示文本",
+ "텍스트 표시 안함"
+ ],
+ [
+ "改个颜色",
+ "색상 변경"
+ ],
+ [
+ "显示文本",
+ "텍스트 표시"
+ ],
+ [
+ "快一些",
+ "더 빠르게"
+ ],
+ [
+ "带图标",
+ "아이콘 포함"
+ ],
+ [
+ "设置速度",
+ "속도 설정"
+ ],
+ [
+ "请输入验证码",
+ "인증 코드를 입력하세요"
+ ],
+ [
+ "登录",
+ "로그인"
+ ],
+ [
+ "购物车 ({num})",
+ "장바구니 ({num})"
+ ],
+ [
+ "完成",
+ "완료"
+ ],
+ [
+ "管理",
+ "관리"
+ ],
+ [
+ "删除",
+ "삭제"
+ ],
+ [
+ "全选",
+ "전체 선택"
+ ],
+ [
+ "合计",
+ "합계"
+ ],
+ [
+ "去结算",
+ "결제하기"
+ ],
+ [
+ "温馨提示",
+ "温馨提示"
+ ],
+ [
+ "确定删除该商品吗?",
+ "정말로 이 상품을 삭제하시겠습니까?"
+ ],
+ [
+ "删除成功",
+ "삭제 성공"
+ ],
+ [
+ "请先选择商品",
+ "먼저 상품을 선택하세요"
+ ],
+ [
+ "确定删除选中的商品吗?",
+ "선택한 상품을 정말로 삭제하시겠습니까?"
+ ],
+ [
+ "您需支付 {price} 元,请确认支付",
+ "{price} 원을 지불해야 합니다. 지불을 확인하세요"
+ ],
+ [
+ "支付成功",
+ "지불 성공"
+ ],
+ [
+ "已设为默认",
+ "기본으로 설정됨"
+ ],
+ [
+ "设为默认",
+ "기본으로 설정"
+ ],
+ [
+ "修改",
+ "수정"
+ ],
+ [
+ "添加地址",
+ "주소 추가"
+ ],
+ [
+ "充值1000元",
+ "1000원 충전"
+ ],
+ [
+ "完成首笔交易",
+ "첫 거래 완료"
+ ],
+ [
+ "优选灵活配置混合A",
+ "우수한 유연한 구성 혼합 A"
+ ],
+ [
+ "1000元起",
+ "1000원 이상"
+ ],
+ [
+ "禁用切换按钮",
+ "전환 버튼 비활성화"
+ ],
+ [
+ "自定义高度",
+ "사용자 지정 높이"
+ ],
+ [
+ "多页数",
+ "다중 페이지 수"
+ ],
+ [
+ "上一页",
+ "이전 페이지"
+ ],
+ [
+ "下一页",
+ "다음 페이지"
+ ],
+ [
+ "横向滚动",
+ "가로 스크롤"
+ ],
+ [
+ "纵向滚动",
+ "세로 스크롤"
+ ],
+ [
+ "快一点",
+ "더 빠르게"
+ ],
+ [
+ "暂停",
+ "일시 중지"
+ ],
+ [
+ "内容靠左",
+ "내용 왼쪽"
+ ],
+ [
+ "QQ",
+ "QQ"
+ ],
+ [
+ "带箭头",
+ "화살표가 있는"
+ ],
+ [
+ "余额",
+ "잔액"
+ ],
+ [
+ "带图片",
+ "사진이 있는"
+ ],
+ [
+ "神仙都没用",
+ "신이 없어도 소용 없다"
+ ],
+ [
+ "折叠",
+ "접기"
+ ],
+ [
+ "微信",
+ "위챗"
+ ],
+ [
+ "父子关联",
+ "부자 연관"
+ ],
+ [
+ "选中值",
+ "선택 값"
+ ],
+ [
+ "选中操作",
+ "선택 작업"
+ ],
+ [
+ "选中部分节点",
+ "선택된 부분 노드"
+ ],
+ [
+ "获取选中节点",
+ "선택된 노드 가져오기"
+ ],
+ [
+ "获取半选节点",
+ "하나만 선택된 노드 가져오기"
+ ],
+ [
+ "清空选中",
+ "선택 취소"
+ ],
+ [
+ "展开操作",
+ "열기 작업"
+ ],
+ [
+ "展开部分节点",
+ "부분 노드 열기"
+ ],
+ [
+ "获取展开节点",
+ "열린 노드 가져오기"
+ ],
+ [
+ "展开所有",
+ "모두 열기"
+ ],
+ [
+ "收起所有",
+ "모두 닫기"
+ ],
+ [
+ "开通账号",
+ "계정 개설"
+ ],
+ [
+ "赠送500元",
+ "500원 지급"
+ ],
+ [
+ "完成实名认证",
+ "실명 인증 완료"
+ ],
+ [
+ "通过身份证认证",
+ "주민등록번호 인증 통과"
+ ],
+ [
+ "绑定银行卡",
+ "은행 카드绑定"
+ ],
+ [
+ "绑定招商银行储蓄卡",
+ "招商銀行储蓄卡绑定"
+ ],
+ [
+ "首次充值",
+ "첫차 충전"
+ ],
+ [
+ "可滑动",
+ "드래그 가능"
+ ],
+ [
+ "左滑编辑",
+ "왼쪽으로 드래그하여 편집"
+ ],
+ [
+ "编辑",
+ "편집"
+ ],
+ [
+ "右滑删除",
+ "오른쪽으로 드래그하여 삭제"
+ ],
+ [
+ "账号",
+ "계정"
+ ],
+ [
+ "我的订单",
+ "나의 주문"
+ ],
+ [
+ "我的收藏",
+ "나의 즐겨찾기"
+ ],
+ [
+ "筛选",
+ "필터"
+ ],
+ [
+ "长按项即可拖动排序",
+ "항목을长按하면 드래그하여 정렬 가능"
+ ],
+ [
+ "单列排序",
+ "단일 열 정렬"
+ ],
+ [
+ "不需要长按",
+ "长按 필요 없음"
+ ],
+ [
+ "结合列表使用",
+ "리스트와 함께 사용"
+ ],
+ [
+ "多列排序",
+ "다중 열 정렬"
+ ],
+ [
+ "结合图片使用",
+ "사진과 함께 사용"
+ ],
+ [
+ "禁用手势",
+ "제스처 비활성화"
+ ],
+ [
+ "自定义样式2",
+ "사용자 지정 스타일 2"
+ ],
+ [
+ "无图片",
+ "사진 없음"
+ ],
+ [
+ "圆角",
+ "둥근 모서리"
+ ],
+ [
+ "自定义大小",
+ "사용자 지정 크기"
+ ],
+ [
+ "省略号",
+ "생략 부호"
+ ],
+ [
+ "标签格式化",
+ "태그 형식 지정"
+ ],
+ [
+ "固定开始、结束日期",
+ "고정된 시작 및 종료 날짜"
+ ],
+ [
+ "自定义快捷选项",
+ "사용자 지정 단축 옵션"
+ ],
+ [
+ "只读",
+ "읽기 전용"
+ ],
+ [
+ "显示分数",
+ "점수 표시"
+ ],
+ [
+ "允许半星",
+ "0.5점 허용"
+ ],
+ [
+ "换个图标",
+ "아이콘 변경"
+ ],
+ [
+ "纵向排列",
+ "수직 배치"
+ ],
+ [
+ "换个样式",
+ "스타일 변경"
+ ],
+ [
+ "不显示图标",
+ "아이콘 표시 안 함"
+ ],
+ [
+ "其他样式",
+ "다른 스타일"
+ ],
+ [
+ "数字键盘",
+ "숫자 키보드"
+ ],
+ [
+ "打开键盘",
+ "키보드 열기"
+ ],
+ [
+ "是否显示输入值",
+ "입력 값 표시 여부"
+ ],
+ [
+ "输入即绑定",
+ "입력 시 바인딩"
+ ],
+ [
+ "身份证键盘",
+ "주민등록번호 키보드"
+ ],
+ [
+ "密码键盘",
+ "비밀번호 키보드"
+ ],
+ [
+ "是否加密",
+ "암호화 여부"
+ ],
+ [
+ "车牌号键盘",
+ "자동차 번호판 키보드"
+ ],
+ [
+ "数字输入",
+ "숫자 입력"
+ ],
+ [
+ "插槽",
+ "슬롯"
+ ],
+ [
+ "使用 PT 自定义颜色",
+ "PT를 사용하여 사용자 지정 색상"
+ ],
+ [
+ "自定义返回图标",
+ "사용자 지정 뒤로 가기 아이콘"
+ ],
+ [
+ "自定义返回路径",
+ "사용자 지정 뒤로 가기 경로"
+ ],
+ [
+ "自定义标题内容",
+ "사용자 지정 제목 내용"
+ ],
+ [
+ "显示滑块",
+ "슬라이더 표시"
+ ],
+ [
+ "添加间距",
+ "여백 추가"
+ ],
+ [
+ "横向填充",
+ "가로 채우기"
+ ],
+ [
+ "适用于标签数量不多的情况",
+ "태그 수가 적은 경우에 적용"
+ ],
+ [
+ "居中",
+ "가운데 정렬"
+ ],
+ [
+ "单个禁用",
+ "개별 비활성화"
+ ],
+ [
+ "显示下划线",
+ "밑줄 표시"
+ ],
+ [
+ "禁用",
+ "비활성화"
+ ],
+ [
+ "取消订单",
+ "주문 취소"
+ ],
+ [
+ "立即购买",
+ "즉시 구매"
+ ],
+ [
+ "确认收货",
+ "수취 확인"
+ ],
+ [
+ "评价",
+ "평가"
+ ],
+ [
+ "禁用状态,无法拖拽",
+ "비활성 상태, 드래그할 수 없음"
+ ],
+ [
+ "不吸附边缘,任意位置可拖拽",
+ "모서리에吸附하지 않고,任意位置에서 드래그 가능"
+ ],
+ [
+ "这是一个提示",
+ "이것은 팁입니다"
+ ],
+ [
+ "Flex 弹性布局",
+ "Flex 탄성 레이아웃"
+ ],
+ [
+ "Tabs 标签页",
+ "Tabs 탭 페이지"
+ ],
+ [
+ "Collapse 折叠面板",
+ "Collapse 접혀질 패널"
+ ],
+ [
+ "Sticky 吸顶",
+ "Sticky 스티키"
+ ],
+ [
+ "TopBar 导航栏",
+ "TopBar 네비게이션 바"
+ ],
+ [
+ "FloatView 悬浮视图",
+ "FloatView 부유 뷰"
+ ],
+ [
+ "Footer 底部视图",
+ "Footer 하단 뷰"
+ ],
+ [
+ "List 列表",
+ "List 목록"
+ ],
+ [
+ "ListView 列表视图",
+ "ListView 목록 뷰"
+ ],
+ [
+ "ListViewRefresh 列表刷新",
+ "ListViewRefresh 목록 새로고침"
+ ],
+ [
+ "Waterfall 瀑布流",
+ "Waterfall 워터폴"
+ ],
+ [
+ "Banner 轮播图",
+ "Banner 슬라이드 쇼"
+ ],
+ [
+ "Marquee 跑马灯",
+ "Marquee 마치 뛰는 등불"
+ ],
+ [
+ "Pagination 分页",
+ "Pagination 페이지 분할"
+ ],
+ [
+ "Timeline 时间轴",
+ "Timeline 시간 줄"
+ ],
+ [
+ "Avatar 头像",
+ "Avatar 아바타"
+ ],
+ [
+ "ReadMore 查看更多",
+ "ReadMore 더 보기"
+ ],
+ [
+ "Draggable 拖拽",
+ "Draggable 드래그"
+ ],
+ [
+ "FilterBar 筛选栏",
+ "FilterBar 필터 바"
+ ],
+ [
+ "Tree 树形结构",
+ "Tree 트리 구조"
+ ],
+ [
+ "获取某个单位的结束时间",
+ "어떤 단위의 종료 시간 가져오기"
+ ],
+ [
+ "是否同一天",
+ "동일한 날인지"
+ ],
+ [
+ "是否早于",
+ "이전인지"
+ ],
+ [
+ "是否晚于",
+ "이후인지"
+ ],
+ [
+ "差值",
+ "차이"
+ ],
+ [
+ "差值(单位)",
+ "차이(단위)"
+ ],
+ [
+ "选择图片",
+ "사진 선택"
+ ],
+ [
+ "可调节裁剪框大小",
+ "裁剪 상자를 조절 가능"
+ ],
+ [
+ "预览图片",
+ "미리보기 사진"
+ ],
+ [
+ "保存图片",
+ "사진 저장"
+ ],
+ [
+ "本页面内容由 canvas 渲染生成,是否立即预览图片效果?",
+ "이 페이지 내용은 canvas로 렌더링되어 생성되었습니다. 즉시 사진 효과를 미리보기하시겠습니까?"
+ ],
+ [
+ "基础动画",
+ "기본 애니메이션"
+ ],
+ [
+ "淡入淡出",
+ "페이드 인/아웃"
+ ],
+ [
+ "播放动画",
+ "애니메이션 재생"
+ ],
+ [
+ "滑入",
+ "슬라이드 인"
+ ],
+ [
+ "旋转翻转",
+ "회전/반전"
+ ],
+ [
+ "摇摆抖动",
+ "흔들림"
+ ],
+ [
+ "特殊效果",
+ "특수 효과"
+ ],
+ [
+ "组合动画",
+ "조합 애니메이션"
+ ],
+ [
+ "标题",
+ "제목"
+ ],
+ [
+ "无头",
+ "무두"
+ ],
+ [
+ "左侧",
+ "왼쪽"
+ ],
+ [
+ "右侧",
+ "오른쪽"
+ ],
+ [
+ "隐藏取消按钮",
+ "취소 버튼 숨기기"
+ ],
+ [
+ "自定义文本",
+ "사용자 지정 텍스트"
+ ],
+ [
+ "关闭前钩子",
+ "닫기 전 후크"
+ ],
+ [
+ "显示时长",
+ "표시 시간"
+ ],
+ [
+ "确定要删除吗?",
+ "삭제하시겠습니까?"
+ ],
+ [
+ "确定要删除吗?3秒后自动关闭",
+ "삭제하시겠습니까? 3초 후 자동으로 닫힘"
+ ],
+ [
+ "带标题、描述",
+ "제목, 설명 표시"
+ ],
+ [
+ "无法点击遮罩关闭",
+ "마스크를 클릭하여 닫을 수 없음"
+ ],
+ [
+ "不需要取消按钮",
+ "취소 버튼 필요 없음"
+ ],
+ [
+ "插槽用法",
+ "슬롯 사용법"
+ ],
+ [
+ "反馈",
+ "피드백"
+ ],
+ [
+ "删除好友会同时删除所有聊天记录",
+ "친구를 삭제하면 모든 대화 기록이 함께 삭제됩니다."
+ ],
+ [
+ "删除好友",
+ "친구 삭제"
+ ],
+ [
+ "确定要删除好友吗?",
+ "정말 친구를 삭제하시겠습니까?"
+ ],
+ [
+ "点我关闭",
+ "여기를 클릭하여 닫기"
+ ],
+ [
+ "确定要关闭吗?",
+ "정말 닫으시겠습니까?"
+ ],
+ [
+ "支付宝",
+ "支付宝"
+ ],
+ [
+ "体重不能为空",
+ "체중은 비어있을 수 없습니다."
+ ],
+ [
+ "体重在40-100kg之间",
+ "체중은 40-100kg 사이입니다."
+ ],
+ [
+ "标签不能为空",
+ "태그는 비어있을 수 없습니다."
+ ],
+ [
+ "标签最多选择2个",
+ "태그는 최대 2개까지만 선택할 수 있습니다."
+ ],
+ [
+ "性别不能为空",
+ "성별은 비어있을 수 없습니다."
+ ],
+ [
+ "出生年月不能为空",
+ "생년월일은 비어있을 수 없습니다."
+ ],
+ [
+ "出生年月不大于2010-01-01",
+ "생년월일은 2010-01-01보다 크지 않습니다."
+ ],
+ [
+ "联系人不能为空",
+ "연락처는 비어있을 수 없습니다."
+ ],
+ [
+ "提交成功",
+ "제출 성공"
+ ],
+ [
+ "单个 true / false",
+ "개별 true / false"
+ ],
+ [
+ "带索引、地区选择",
+ "색인, 지역 선택"
+ ],
+ [
+ "换个分隔符",
+ "구분자를 변경하세요"
+ ],
+ [
+ "列表高度小一点",
+ "리스트 높이를 약간 줄입니다."
+ ],
+ [
+ "范围选",
+ "범위 선택"
+ ],
+ [
+ "禁用部分日期",
+ "일부 날짜 비활성화"
+ ],
+ [
+ "日历长列表",
+ "달력 긴 목록"
+ ],
+ [
+ "打开日历长列表",
+ "달력 긴 목록 열기"
+ ],
+ [
+ "日历面板",
+ "달력 패널"
+ ],
+ [
+ "自定义文案和颜色",
+ "사용자 정의 텍스트 및 색상"
+ ],
+ [
+ "显示头",
+ "헤더 표시"
+ ],
+ [
+ "删除地址后无法恢复,确认要删除该地址吗?",
+ "주소를 삭제하면 복구할 수 없습니다. 이 주소를 삭제하시겠습니까?"
+ ],
+ [
+ "加载中",
+ "로딩 중"
+ ],
+ [
+ "收货人",
+ "받는 사람"
+ ],
+ [
+ "请输入收货人姓名",
+ "받는 사람 이름을 입력하세요"
+ ],
+ [
+ "手机号",
+ "휴대폰 번호"
+ ],
+ [
+ "选择省市区",
+ "시/도, 구/군, 동/읍/면을 선택하세요"
+ ],
+ [
+ "详细地址",
+ "상세 주소"
+ ],
+ [
+ "小区楼栋、门牌号、村等",
+ "아파트 빌딩, 호수, 마을 등"
+ ],
+ [
+ "默认地址",
+ "기본 주소"
+ ],
+ [
+ "保存",
+ "저장"
+ ],
+ [
+ "收货人不能为空",
+ "받는 사람은 비어있을 수 없습니다."
+ ],
+ [
+ "手机号不能为空",
+ "휴대폰 번호는 비어있을 수 없습니다."
+ ],
+ [
+ "手机号格式不正确",
+ "휴대폰 번호 형식이 올바르지 않습니다."
+ ],
+ [
+ "详细地址不能为空",
+ "상세 주소는 비어있을 수 없습니다."
+ ],
+ [
+ "所在地区不能为空",
+ "지역이 비어있을 수 없습니다."
+ ],
+ [
+ "保存中",
+ "저장 중"
+ ],
+ [
+ "开启通知",
+ "알림 활성화"
+ ],
+ [
+ "通用设置",
+ "일반 설정"
+ ],
+ [
+ "通知设置",
+ "알림 설정"
+ ],
+ [
+ "隐私设置",
+ "개인 정보 설정"
+ ],
+ [
+ "支付失败",
+ "결제 실패"
+ ],
+ [
+ "授权信息仅用于用户登录",
+ "인증 정보는 사용자 로그인에만 사용됩니다."
+ ],
+ [
+ "登录授权失败",
+ "로그인 인증 실패"
+ ],
+ [
+ "获取短信验证码",
+ "문자 인증 코드 받기"
+ ],
+ [
+ "验证码",
+ "인증 코드"
+ ],
+ [
+ "发送短信",
+ "문자 발송"
+ ],
+ [
+ "{n}s后重新获取",
+ "{n}초 후 재발송"
+ ],
+ [
+ "获取验证码",
+ "인증 코드 받기"
+ ],
+ [
+ "短信已发送,请查收",
+ "문자가 발송되었습니다. 확인해 주세요."
+ ],
+ [
+ "请填写验证码",
+ "인증 코드를 입력해 주세요."
+ ],
+ [
+ "请填写正确的手机号格式",
+ "올바른 핸드폰 번호 형식을 입력해 주세요."
+ ],
+ [
+ "全局字号",
+ "전역 글꼴 크기"
+ ],
+ [
+ "这是一段示例文字,用于预览不同字号的效果。",
+ "다양한 글꼴 크기의 미리보기용 샘플 텍스트입니다."
+ ],
+ [
+ "默认 1.0",
+ "기본 1.0"
+ ],
+ [
+ "切换语言",
+ "언어 변경"
+ ],
+ [
+ "切换中",
+ "변경 중"
+ ],
+ [
+ "模板",
+ "템플릿"
+ ],
+ [
+ "编辑资料",
+ "프로필 편집"
+ ],
+ [
+ "Text 文本",
+ "텍스트"
+ ],
+ [
+ "Button 按钮",
+ "버튼"
+ ],
+ [
+ "头像上传成功",
+ "프로필 사진 업로드 성공"
+ ],
+ [
+ "编辑昵称",
+ "닉네임 편집"
+ ],
+ [
+ "请输入昵称",
+ "닉네임을 입력해주세요"
+ ],
+ [
+ "请设置2-20个字符,不包括@<>/等无效字符",
+ "2-20자로 설정해주세요. @<>/ 등의 유효하지 않은 문자를 포함하지 마세요."
+ ],
+ [
+ "确认",
+ "확인"
+ ],
+ [
+ "昵称长度需在2-20个字符之间",
+ "닉네임 길이는 2-20자 사이여야 합니다."
+ ],
+ [
+ "昵称不能包含@<>/等特殊字符",
+ "닉네임에 @<>/ 등의 특수 문자를 포함할 수 없습니다."
+ ],
+ [
+ "编辑简介",
+ "소개 편집"
+ ],
+ [
+ "简介不能为空",
+ "소개는 비워둘 수 없습니다."
+ ],
+ [
+ "提示",
+ "힌트"
+ ],
+ [
+ "为提供更好的服务,我们邀请您填写昵称、头像等公开信息",
+ "더 나은 서비스를 제공하기 위해, 닉네임, 프로필 사진 등의 공개 정보를 입력해주세요."
+ ],
+ [
+ "头像",
+ "프로필 사진"
+ ],
+ [
+ "昵称",
+ "닉네임"
+ ],
+ [
+ "点击输入昵称",
+ "닉네임 입력을 클릭하세요"
+ ],
+ [
+ "取消",
+ "취소"
+ ],
+ [
+ "请上传头像",
+ "프로필 사진을 업로드해주세요"
+ ],
+ [
+ "登录中",
+ "로그인 중"
+ ],
+ [
+ "手机登录",
+ "모바일 로그인"
+ ],
+ [
+ "未注册的手机号登录成功后将自动注册",
+ "미등록 번호로 로그인 성공 시 자동으로 등록됩니다."
+ ],
+ [
+ "请输入手机号",
+ "휴대폰 번호를 입력해주세요"
+ ]
+]
\ No newline at end of file
diff --git a/cool-unix/locale/zh-cn.json b/cool-unix/locale/zh-cn.json
new file mode 100644
index 0000000..e8d7392
--- /dev/null
+++ b/cool-unix/locale/zh-cn.json
@@ -0,0 +1,2582 @@
+[
+ [
+ "已阅读并同意",
+ ""
+ ],
+ [
+ "用户协议",
+ ""
+ ],
+ [
+ "隐私政策",
+ ""
+ ],
+ [
+ "请先阅读并同意《用户协议》和《隐私政策》",
+ ""
+ ],
+ [
+ "我的昵称",
+ ""
+ ],
+ [
+ "简介",
+ ""
+ ],
+ [
+ "介绍一下自己",
+ ""
+ ],
+ [
+ "性别",
+ ""
+ ],
+ [
+ "编辑性别",
+ ""
+ ],
+ [
+ "生日",
+ ""
+ ],
+ [
+ "选择生日",
+ ""
+ ],
+ [
+ "地区",
+ ""
+ ],
+ [
+ "选择所在的地区",
+ ""
+ ],
+ [
+ "选择性别",
+ ""
+ ],
+ [
+ "保密",
+ ""
+ ],
+ [
+ "男",
+ ""
+ ],
+ [
+ "女",
+ ""
+ ],
+ [
+ "性别设置成功",
+ ""
+ ],
+ [
+ "生日设置成功",
+ ""
+ ],
+ [
+ "地区设置成功",
+ ""
+ ],
+ [
+ "头像上传成功",
+ ""
+ ],
+ [
+ "编辑昵称",
+ ""
+ ],
+ [
+ "请输入昵称",
+ ""
+ ],
+ [
+ "请设置2-20个字符,不包括@<>/等无效字符",
+ ""
+ ],
+ [
+ "确认",
+ ""
+ ],
+ [
+ "昵称长度需在2-20个字符之间",
+ ""
+ ],
+ [
+ "昵称不能包含@<>/等特殊字符",
+ ""
+ ],
+ [
+ "编辑简介",
+ ""
+ ],
+ [
+ "简介不能为空",
+ ""
+ ],
+ [
+ "提示",
+ ""
+ ],
+ [
+ "为提供更好的服务,我们邀请您填写昵称、头像等公开信息",
+ ""
+ ],
+ [
+ "头像",
+ ""
+ ],
+ [
+ "昵称",
+ ""
+ ],
+ [
+ "点击输入昵称",
+ ""
+ ],
+ [
+ "取消",
+ ""
+ ],
+ [
+ "请上传头像",
+ ""
+ ],
+ [
+ "登录中",
+ ""
+ ],
+ [
+ "手机登录",
+ ""
+ ],
+ [
+ "未注册的手机号登录成功后将自动注册",
+ ""
+ ],
+ [
+ "请输入手机号",
+ ""
+ ],
+ [
+ "请输入验证码",
+ ""
+ ],
+ [
+ "登录",
+ ""
+ ],
+ [
+ "购物车 ({num})",
+ ""
+ ],
+ [
+ "完成",
+ ""
+ ],
+ [
+ "管理",
+ ""
+ ],
+ [
+ "删除",
+ ""
+ ],
+ [
+ "全选",
+ ""
+ ],
+ [
+ "合计",
+ ""
+ ],
+ [
+ "去结算",
+ ""
+ ],
+ [
+ "温馨提示",
+ ""
+ ],
+ [
+ "确定删除该商品吗?",
+ ""
+ ],
+ [
+ "删除成功",
+ ""
+ ],
+ [
+ "请先选择商品",
+ ""
+ ],
+ [
+ "确定删除选中的商品吗?",
+ ""
+ ],
+ [
+ "您需支付 {price} 元,请确认支付",
+ ""
+ ],
+ [
+ "支付成功",
+ ""
+ ],
+ [
+ "已设为默认",
+ ""
+ ],
+ [
+ "设为默认",
+ ""
+ ],
+ [
+ "修改",
+ ""
+ ],
+ [
+ "添加地址",
+ ""
+ ],
+ [
+ "删除地址后无法恢复,确认要删除该地址吗?",
+ ""
+ ],
+ [
+ "加载中",
+ ""
+ ],
+ [
+ "收货人",
+ ""
+ ],
+ [
+ "请输入收货人姓名",
+ ""
+ ],
+ [
+ "手机号",
+ ""
+ ],
+ [
+ "选择省市区",
+ ""
+ ],
+ [
+ "详细地址",
+ ""
+ ],
+ [
+ "小区楼栋、门牌号、村等",
+ ""
+ ],
+ [
+ "默认地址",
+ ""
+ ],
+ [
+ "保存",
+ ""
+ ],
+ [
+ "收货人不能为空",
+ ""
+ ],
+ [
+ "手机号不能为空",
+ ""
+ ],
+ [
+ "手机号格式不正确",
+ ""
+ ],
+ [
+ "详细地址不能为空",
+ ""
+ ],
+ [
+ "所在地区不能为空",
+ ""
+ ],
+ [
+ "保存中",
+ ""
+ ],
+ [
+ "开启通知",
+ ""
+ ],
+ [
+ "通用设置",
+ ""
+ ],
+ [
+ "通知设置",
+ ""
+ ],
+ [
+ "隐私设置",
+ ""
+ ],
+ [
+ "关于{name}",
+ ""
+ ],
+ [
+ "联系客服",
+ ""
+ ],
+ [
+ "退出登录",
+ ""
+ ],
+ [
+ "确定退出登录吗?",
+ ""
+ ],
+ [
+ "深色模式",
+ ""
+ ],
+ [
+ "多语言",
+ ""
+ ],
+ [
+ "字体大小",
+ ""
+ ],
+ [
+ "访问官网",
+ ""
+ ],
+ [
+ "商城",
+ ""
+ ],
+ [
+ "商品分类",
+ ""
+ ],
+ [
+ "商品详情",
+ ""
+ ],
+ [
+ "商品列表、筛选",
+ ""
+ ],
+ [
+ "购物车",
+ ""
+ ],
+ [
+ "订单列表、详情",
+ ""
+ ],
+ [
+ "收货地址",
+ ""
+ ],
+ [
+ "聊天",
+ ""
+ ],
+ [
+ "对话列表、历史记录",
+ ""
+ ],
+ [
+ "流式回复",
+ ""
+ ],
+ [
+ "语言合成",
+ ""
+ ],
+ [
+ "语音识别",
+ ""
+ ],
+ [
+ "其他",
+ ""
+ ],
+ [
+ "文件管理",
+ ""
+ ],
+ [
+ "该模板正在开发中",
+ ""
+ ],
+ [
+ "未登录",
+ ""
+ ],
+ [
+ "总点击",
+ ""
+ ],
+ [
+ "赞",
+ ""
+ ],
+ [
+ "收藏",
+ ""
+ ],
+ [
+ "粉丝",
+ ""
+ ],
+ [
+ "接单模式",
+ ""
+ ],
+ [
+ "已关闭",
+ ""
+ ],
+ [
+ "消息通知",
+ ""
+ ],
+ [
+ "待支付",
+ ""
+ ],
+ [
+ "未发货",
+ ""
+ ],
+ [
+ "已发货",
+ ""
+ ],
+ [
+ "售后 / 退款",
+ ""
+ ],
+ [
+ "我的钱包",
+ ""
+ ],
+ [
+ "数据看板",
+ ""
+ ],
+ [
+ "历史记录",
+ ""
+ ],
+ [
+ "邀请好友",
+ ""
+ ],
+ [
+ "设置",
+ ""
+ ],
+ [
+ "开发中,敬请期待",
+ ""
+ ],
+ [
+ "基础组件",
+ ""
+ ],
+ [
+ "文本",
+ ""
+ ],
+ [
+ "按钮",
+ ""
+ ],
+ [
+ "图片",
+ ""
+ ],
+ [
+ "图标",
+ ""
+ ],
+ [
+ "标签",
+ ""
+ ],
+ [
+ "表单组件",
+ ""
+ ],
+ [
+ "表单验证",
+ ""
+ ],
+ [
+ "输入框",
+ ""
+ ],
+ [
+ "文本域",
+ ""
+ ],
+ [
+ "计数器",
+ ""
+ ],
+ [
+ "口令输入",
+ ""
+ ],
+ [
+ "键盘",
+ ""
+ ],
+ [
+ "单选框",
+ ""
+ ],
+ [
+ "多选框",
+ ""
+ ],
+ [
+ "开关",
+ ""
+ ],
+ [
+ "评分",
+ ""
+ ],
+ [
+ "滑块",
+ ""
+ ],
+ [
+ "选择器",
+ ""
+ ],
+ [
+ "日期选择器",
+ ""
+ ],
+ [
+ "时间选择器",
+ ""
+ ],
+ [
+ "级联选择器",
+ ""
+ ],
+ [
+ "文件上传",
+ ""
+ ],
+ [
+ "日历",
+ ""
+ ],
+ [
+ "布局组件",
+ ""
+ ],
+ [
+ "弹性布局",
+ ""
+ ],
+ [
+ "标签页",
+ ""
+ ],
+ [
+ "折叠面板",
+ ""
+ ],
+ [
+ "吸顶",
+ ""
+ ],
+ [
+ "导航栏",
+ ""
+ ],
+ [
+ "底部视图",
+ ""
+ ],
+ [
+ "悬浮视图",
+ ""
+ ],
+ [
+ "数据展示",
+ ""
+ ],
+ [
+ "查看更多",
+ ""
+ ],
+ [
+ "列表",
+ ""
+ ],
+ [
+ "列表视图",
+ ""
+ ],
+ [
+ "列表刷新",
+ ""
+ ],
+ [
+ "瀑布流",
+ ""
+ ],
+ [
+ "轮播图",
+ ""
+ ],
+ [
+ "跑马灯",
+ ""
+ ],
+ [
+ "分页",
+ ""
+ ],
+ [
+ "时间轴",
+ ""
+ ],
+ [
+ "拖拽",
+ ""
+ ],
+ [
+ "筛选栏",
+ ""
+ ],
+ [
+ "树形结构",
+ ""
+ ],
+ [
+ "状态组件",
+ ""
+ ],
+ [
+ "角标",
+ ""
+ ],
+ [
+ "通知栏",
+ ""
+ ],
+ [
+ "倒计时",
+ ""
+ ],
+ [
+ "数字滚动",
+ ""
+ ],
+ [
+ "进度条",
+ ""
+ ],
+ [
+ "圆形进度条",
+ ""
+ ],
+ [
+ "骨架图",
+ ""
+ ],
+ [
+ "加载更多",
+ ""
+ ],
+ [
+ "反馈组件",
+ ""
+ ],
+ [
+ "操作菜单",
+ ""
+ ],
+ [
+ "弹窗",
+ ""
+ ],
+ [
+ "确认框",
+ ""
+ ],
+ [
+ "提示框",
+ ""
+ ],
+ [
+ "签名",
+ ""
+ ],
+ [
+ "水印",
+ ""
+ ],
+ [
+ "图片裁剪",
+ ""
+ ],
+ [
+ "Canvas",
+ ""
+ ],
+ [
+ "富文本",
+ ""
+ ],
+ [
+ "该功能正在开发中",
+ ""
+ ],
+ [
+ "圆形",
+ ""
+ ],
+ [
+ "组合",
+ ""
+ ],
+ [
+ "基础用法",
+ ""
+ ],
+ [
+ "自定义",
+ ""
+ ],
+ [
+ "加快滚动速度",
+ ""
+ ],
+ [
+ "显示小数位数",
+ ""
+ ],
+ [
+ "自定义样式",
+ ""
+ ],
+ [
+ "自定义颜色",
+ ""
+ ],
+ [
+ "自定义宽度",
+ ""
+ ],
+ [
+ "不显示文本",
+ ""
+ ],
+ [
+ "改个颜色",
+ ""
+ ],
+ [
+ "显示文本",
+ ""
+ ],
+ [
+ "快一些",
+ ""
+ ],
+ [
+ "带图标",
+ ""
+ ],
+ [
+ "设置速度",
+ ""
+ ],
+ [
+ "垂直方向",
+ ""
+ ],
+ [
+ "3秒后加载完成",
+ ""
+ ],
+ [
+ "隐藏为 00 的值",
+ ""
+ ],
+ [
+ "指定天数",
+ ""
+ ],
+ [
+ "自定义模板",
+ ""
+ ],
+ [
+ "指定小时",
+ ""
+ ],
+ [
+ "指定分钟",
+ ""
+ ],
+ [
+ "指定秒",
+ ""
+ ],
+ [
+ "完成后提示",
+ ""
+ ],
+ [
+ "3秒后开始倒计时",
+ ""
+ ],
+ [
+ "结合按钮",
+ ""
+ ],
+ [
+ "购买",
+ ""
+ ],
+ [
+ "消息",
+ ""
+ ],
+ [
+ "结合图片",
+ ""
+ ],
+ [
+ "结合图标",
+ ""
+ ],
+ [
+ "点击触发",
+ ""
+ ],
+ [
+ "不同大小",
+ ""
+ ],
+ [
+ "不同颜色",
+ ""
+ ],
+ [
+ "使用base64",
+ ""
+ ],
+ [
+ "没有错误提示",
+ ""
+ ],
+ [
+ "转动图片",
+ ""
+ ],
+ [
+ "验证通过",
+ ""
+ ],
+ [
+ "验证失败",
+ ""
+ ],
+ [
+ "操作",
+ ""
+ ],
+ [
+ "清空",
+ ""
+ ],
+ [
+ "预览",
+ ""
+ ],
+ [
+ "设置高度",
+ ""
+ ],
+ [
+ "毛笔效果",
+ ""
+ ],
+ [
+ "添加LOGO",
+ ""
+ ],
+ [
+ "圆角定位点",
+ ""
+ ],
+ [
+ "内间距",
+ ""
+ ],
+ [
+ "导出图片",
+ ""
+ ],
+ [
+ "矩形",
+ ""
+ ],
+ [
+ "点",
+ ""
+ ],
+ [
+ "线性",
+ ""
+ ],
+ [
+ "小方格",
+ ""
+ ],
+ [
+ "格式化",
+ ""
+ ],
+ [
+ "添加",
+ ""
+ ],
+ [
+ "减去",
+ ""
+ ],
+ [
+ "获取某个单位的开始时间",
+ ""
+ ],
+ [
+ "获取某个单位的结束时间",
+ ""
+ ],
+ [
+ "是否同一天",
+ ""
+ ],
+ [
+ "是否早于",
+ ""
+ ],
+ [
+ "是否晚于",
+ ""
+ ],
+ [
+ "差值",
+ ""
+ ],
+ [
+ "差值(单位)",
+ ""
+ ],
+ [
+ "选择图片",
+ ""
+ ],
+ [
+ "可调节裁剪框大小",
+ ""
+ ],
+ [
+ "预览图片",
+ ""
+ ],
+ [
+ "保存图片",
+ ""
+ ],
+ [
+ "本页面内容由 canvas 渲染生成,是否立即预览图片效果?",
+ ""
+ ],
+ [
+ "基础动画",
+ ""
+ ],
+ [
+ "淡入淡出",
+ ""
+ ],
+ [
+ "播放动画",
+ ""
+ ],
+ [
+ "滑入",
+ ""
+ ],
+ [
+ "旋转翻转",
+ ""
+ ],
+ [
+ "摇摆抖动",
+ ""
+ ],
+ [
+ "特殊效果",
+ ""
+ ],
+ [
+ "组合动画",
+ ""
+ ],
+ [
+ "标题",
+ ""
+ ],
+ [
+ "插槽",
+ ""
+ ],
+ [
+ "使用 PT 自定义颜色",
+ ""
+ ],
+ [
+ "自定义返回图标",
+ ""
+ ],
+ [
+ "自定义返回路径",
+ ""
+ ],
+ [
+ "自定义标题内容",
+ ""
+ ],
+ [
+ "显示滑块",
+ ""
+ ],
+ [
+ "添加间距",
+ ""
+ ],
+ [
+ "横向填充",
+ ""
+ ],
+ [
+ "适用于标签数量不多的情况",
+ ""
+ ],
+ [
+ "居中",
+ ""
+ ],
+ [
+ "单个禁用",
+ ""
+ ],
+ [
+ "显示下划线",
+ ""
+ ],
+ [
+ "禁用",
+ ""
+ ],
+ [
+ "取消订单",
+ ""
+ ],
+ [
+ "立即购买",
+ ""
+ ],
+ [
+ "确认收货",
+ ""
+ ],
+ [
+ "评价",
+ ""
+ ],
+ [
+ "禁用状态,无法拖拽",
+ ""
+ ],
+ [
+ "不吸附边缘,任意位置可拖拽",
+ ""
+ ],
+ [
+ "这是一个提示",
+ ""
+ ],
+ [
+ "左间隔",
+ ""
+ ],
+ [
+ "右移动",
+ ""
+ ],
+ [
+ "左移动",
+ ""
+ ],
+ [
+ "多个数据",
+ ""
+ ],
+ [
+ "点击收起",
+ ""
+ ],
+ [
+ "点击展开",
+ ""
+ ],
+ [
+ "ref 方式调用",
+ ""
+ ],
+ [
+ "自定义图标、文字、大小",
+ ""
+ ],
+ [
+ "上传证件照",
+ ""
+ ],
+ [
+ "多选",
+ ""
+ ],
+ [
+ "限制 3 个",
+ ""
+ ],
+ [
+ "边框",
+ ""
+ ],
+ [
+ "显示字数",
+ ""
+ ],
+ [
+ "自动增高",
+ ""
+ ],
+ [
+ "其他颜色",
+ ""
+ ],
+ [
+ "大一点",
+ ""
+ ],
+ [
+ "正方形",
+ ""
+ ],
+ [
+ "范围选择",
+ ""
+ ],
+ [
+ "显示值",
+ ""
+ ],
+ [
+ "步长10",
+ ""
+ ],
+ [
+ "滑块大点",
+ ""
+ ],
+ [
+ "换个颜色",
+ ""
+ ],
+ [
+ "最大50",
+ ""
+ ],
+ [
+ "自定义触发器",
+ ""
+ ],
+ [
+ "打开选择器",
+ ""
+ ],
+ [
+ "多列",
+ ""
+ ],
+ [
+ "通过 children 配置多级数据,并使用 column-count 参数指定显示的列数",
+ ""
+ ],
+ [
+ "弹窗中使用",
+ ""
+ ],
+ [
+ "打开",
+ ""
+ ],
+ [
+ "选择地区",
+ ""
+ ],
+ [
+ "绑定值",
+ ""
+ ],
+ [
+ "下一步",
+ ""
+ ],
+ [
+ "确定",
+ ""
+ ],
+ [
+ "关闭",
+ ""
+ ],
+ [
+ "显示取消按钮",
+ ""
+ ],
+ [
+ "修改按钮文案",
+ ""
+ ],
+ [
+ "显示绑定值",
+ ""
+ ],
+ [
+ "时",
+ ""
+ ],
+ [
+ "时:分",
+ ""
+ ],
+ [
+ "时:分:秒",
+ ""
+ ],
+ [
+ "标签格式化",
+ ""
+ ],
+ [
+ "固定开始、结束日期",
+ ""
+ ],
+ [
+ "自定义快捷选项",
+ ""
+ ],
+ [
+ "只读",
+ ""
+ ],
+ [
+ "显示分数",
+ ""
+ ],
+ [
+ "允许半星",
+ ""
+ ],
+ [
+ "换个图标",
+ ""
+ ],
+ [
+ "纵向排列",
+ ""
+ ],
+ [
+ "换个样式",
+ ""
+ ],
+ [
+ "不显示图标",
+ ""
+ ],
+ [
+ "其他样式",
+ ""
+ ],
+ [
+ "数字键盘",
+ ""
+ ],
+ [
+ "打开键盘",
+ ""
+ ],
+ [
+ "是否显示输入值",
+ ""
+ ],
+ [
+ "输入即绑定",
+ ""
+ ],
+ [
+ "身份证键盘",
+ ""
+ ],
+ [
+ "密码键盘",
+ ""
+ ],
+ [
+ "是否加密",
+ ""
+ ],
+ [
+ "车牌号键盘",
+ ""
+ ],
+ [
+ "数字输入",
+ ""
+ ],
+ [
+ "密码输入",
+ ""
+ ],
+ [
+ "可清除",
+ ""
+ ],
+ [
+ "左右插槽",
+ ""
+ ],
+ [
+ "左图标",
+ ""
+ ],
+ [
+ "右图标",
+ ""
+ ],
+ [
+ "自动聚焦",
+ ""
+ ],
+ [
+ "长度为6",
+ ""
+ ],
+ [
+ "步进为10",
+ ""
+ ],
+ [
+ "最小为10",
+ ""
+ ],
+ [
+ "最大为50",
+ ""
+ ],
+ [
+ "可以小数",
+ ""
+ ],
+ [
+ "可以输入",
+ ""
+ ],
+ [
+ "用户名",
+ ""
+ ],
+ [
+ "请输入用户名",
+ ""
+ ],
+ [
+ "邮箱",
+ ""
+ ],
+ [
+ "请输入邮箱地址",
+ ""
+ ],
+ [
+ "动态验证",
+ ""
+ ],
+ [
+ "联系人",
+ ""
+ ],
+ [
+ "添加联系人",
+ ""
+ ],
+ [
+ "身高",
+ ""
+ ],
+ [
+ "体重",
+ ""
+ ],
+ [
+ "所在地区",
+ ""
+ ],
+ [
+ "出生年月",
+ ""
+ ],
+ [
+ "个人简介",
+ ""
+ ],
+ [
+ "请输入个人简介",
+ ""
+ ],
+ [
+ "公开状态",
+ ""
+ ],
+ [
+ "重置",
+ ""
+ ],
+ [
+ "提交",
+ ""
+ ],
+ [
+ "未知",
+ ""
+ ],
+ [
+ "篮球",
+ ""
+ ],
+ [
+ "足球",
+ ""
+ ],
+ [
+ "羽毛球",
+ ""
+ ],
+ [
+ "乒乓球",
+ ""
+ ],
+ [
+ "游泳",
+ ""
+ ],
+ [
+ "用户名不能为空",
+ ""
+ ],
+ [
+ "用户名长度在3-20个字符之间",
+ ""
+ ],
+ [
+ "邮箱不能为空",
+ ""
+ ],
+ [
+ "邮箱格式不正确",
+ ""
+ ],
+ [
+ "身高不能为空",
+ ""
+ ],
+ [
+ "身高在160-190cm之间",
+ ""
+ ],
+ [
+ "体重不能为空",
+ ""
+ ],
+ [
+ "体重在40-100kg之间",
+ ""
+ ],
+ [
+ "标签不能为空",
+ ""
+ ],
+ [
+ "标签最多选择2个",
+ ""
+ ],
+ [
+ "性别不能为空",
+ ""
+ ],
+ [
+ "出生年月不能为空",
+ ""
+ ],
+ [
+ "出生年月不大于2010-01-01",
+ ""
+ ],
+ [
+ "联系人不能为空",
+ ""
+ ],
+ [
+ "提交成功",
+ ""
+ ],
+ [
+ "单个 true / false",
+ ""
+ ],
+ [
+ "带索引、地区选择",
+ ""
+ ],
+ [
+ "换个分隔符",
+ ""
+ ],
+ [
+ "列表高度小一点",
+ ""
+ ],
+ [
+ "范围选",
+ ""
+ ],
+ [
+ "禁用部分日期",
+ ""
+ ],
+ [
+ "日历长列表",
+ ""
+ ],
+ [
+ "打开日历长列表",
+ ""
+ ],
+ [
+ "日历面板",
+ ""
+ ],
+ [
+ "自定义文案和颜色",
+ ""
+ ],
+ [
+ "显示头",
+ ""
+ ],
+ [
+ "显示星期",
+ ""
+ ],
+ [
+ "显示其他月份",
+ ""
+ ],
+ [
+ "不同位置",
+ ""
+ ],
+ [
+ "顶部",
+ ""
+ ],
+ [
+ "中间",
+ ""
+ ],
+ [
+ "底部",
+ ""
+ ],
+ [
+ "不同类型",
+ ""
+ ],
+ [
+ "成功",
+ ""
+ ],
+ [
+ "失败",
+ ""
+ ],
+ [
+ "警告",
+ ""
+ ],
+ [
+ "问题",
+ ""
+ ],
+ [
+ "停止",
+ ""
+ ],
+ [
+ "自定义图标",
+ ""
+ ],
+ [
+ "只存在一个",
+ ""
+ ],
+ [
+ "不同位置提示",
+ ""
+ ],
+ [
+ "不同类型提示",
+ ""
+ ],
+ [
+ "带图标提示",
+ ""
+ ],
+ [
+ "移除其他已存在的提示",
+ ""
+ ],
+ [
+ "打开弹窗",
+ ""
+ ],
+ [
+ "设置宽度 80%",
+ ""
+ ],
+ [
+ "无头",
+ ""
+ ],
+ [
+ "左侧",
+ ""
+ ],
+ [
+ "右侧",
+ ""
+ ],
+ [
+ "隐藏取消按钮",
+ ""
+ ],
+ [
+ "自定义文本",
+ ""
+ ],
+ [
+ "关闭前钩子",
+ ""
+ ],
+ [
+ "显示时长",
+ ""
+ ],
+ [
+ "确定要删除吗?",
+ ""
+ ],
+ [
+ "确定要删除吗?3秒后自动关闭",
+ ""
+ ],
+ [
+ "带标题、描述",
+ ""
+ ],
+ [
+ "无法点击遮罩关闭",
+ ""
+ ],
+ [
+ "不需要取消按钮",
+ ""
+ ],
+ [
+ "插槽用法",
+ ""
+ ],
+ [
+ "反馈",
+ ""
+ ],
+ [
+ "删除好友会同时删除所有聊天记录",
+ ""
+ ],
+ [
+ "删除好友",
+ ""
+ ],
+ [
+ "确定要删除好友吗?",
+ ""
+ ],
+ [
+ "点我关闭",
+ ""
+ ],
+ [
+ "确定要关闭吗?",
+ ""
+ ],
+ [
+ "支付宝",
+ ""
+ ],
+ [
+ "微信",
+ ""
+ ],
+ [
+ "父子关联",
+ ""
+ ],
+ [
+ "选中值",
+ ""
+ ],
+ [
+ "选中操作",
+ ""
+ ],
+ [
+ "选中部分节点",
+ ""
+ ],
+ [
+ "获取选中节点",
+ ""
+ ],
+ [
+ "获取半选节点",
+ ""
+ ],
+ [
+ "清空选中",
+ ""
+ ],
+ [
+ "展开操作",
+ ""
+ ],
+ [
+ "展开部分节点",
+ ""
+ ],
+ [
+ "获取展开节点",
+ ""
+ ],
+ [
+ "展开所有",
+ ""
+ ],
+ [
+ "收起所有",
+ ""
+ ],
+ [
+ "开通账号",
+ ""
+ ],
+ [
+ "赠送500元",
+ ""
+ ],
+ [
+ "完成实名认证",
+ ""
+ ],
+ [
+ "通过身份证认证",
+ ""
+ ],
+ [
+ "绑定银行卡",
+ ""
+ ],
+ [
+ "绑定招商银行储蓄卡",
+ ""
+ ],
+ [
+ "首次充值",
+ ""
+ ],
+ [
+ "充值1000元",
+ ""
+ ],
+ [
+ "完成首笔交易",
+ ""
+ ],
+ [
+ "优选灵活配置混合A",
+ ""
+ ],
+ [
+ "1000元起",
+ ""
+ ],
+ [
+ "禁用切换按钮",
+ ""
+ ],
+ [
+ "自定义高度",
+ ""
+ ],
+ [
+ "多页数",
+ ""
+ ],
+ [
+ "上一页",
+ ""
+ ],
+ [
+ "下一页",
+ ""
+ ],
+ [
+ "横向滚动",
+ ""
+ ],
+ [
+ "纵向滚动",
+ ""
+ ],
+ [
+ "快一点",
+ ""
+ ],
+ [
+ "暂停",
+ ""
+ ],
+ [
+ "内容靠左",
+ ""
+ ],
+ [
+ "QQ",
+ ""
+ ],
+ [
+ "带箭头",
+ ""
+ ],
+ [
+ "余额",
+ ""
+ ],
+ [
+ "带图片",
+ ""
+ ],
+ [
+ "神仙都没用",
+ ""
+ ],
+ [
+ "折叠",
+ ""
+ ],
+ [
+ "可滑动",
+ ""
+ ],
+ [
+ "左滑编辑",
+ ""
+ ],
+ [
+ "编辑",
+ ""
+ ],
+ [
+ "右滑删除",
+ ""
+ ],
+ [
+ "账号",
+ ""
+ ],
+ [
+ "我的订单",
+ ""
+ ],
+ [
+ "我的收藏",
+ ""
+ ],
+ [
+ "筛选",
+ ""
+ ],
+ [
+ "长按项即可拖动排序",
+ ""
+ ],
+ [
+ "单列排序",
+ ""
+ ],
+ [
+ "不需要长按",
+ ""
+ ],
+ [
+ "结合列表使用",
+ ""
+ ],
+ [
+ "多列排序",
+ ""
+ ],
+ [
+ "结合图片使用",
+ ""
+ ],
+ [
+ "禁用手势",
+ ""
+ ],
+ [
+ "自定义样式2",
+ ""
+ ],
+ [
+ "无图片",
+ ""
+ ],
+ [
+ "圆角",
+ ""
+ ],
+ [
+ "自定义大小",
+ ""
+ ],
+ [
+ "省略号",
+ ""
+ ],
+ [
+ "多行省略号",
+ ""
+ ],
+ [
+ "金额",
+ ""
+ ],
+ [
+ "手机号脱敏",
+ ""
+ ],
+ [
+ "姓名脱敏",
+ ""
+ ],
+ [
+ "邮箱脱敏",
+ ""
+ ],
+ [
+ "银行卡脱敏",
+ ""
+ ],
+ [
+ "自定义脱敏字符",
+ ""
+ ],
+ [
+ "主要",
+ ""
+ ],
+ [
+ "危险",
+ ""
+ ],
+ [
+ "信息",
+ ""
+ ],
+ [
+ "邮件",
+ ""
+ ],
+ [
+ "文件",
+ ""
+ ],
+ [
+ "可关闭",
+ ""
+ ],
+ [
+ "镂空",
+ ""
+ ],
+ [
+ "自定义无圆角",
+ ""
+ ],
+ [
+ "不同裁剪",
+ ""
+ ],
+ [
+ "点击可预览",
+ ""
+ ],
+ [
+ "失败时显示",
+ ""
+ ],
+ [
+ "自定义圆角",
+ ""
+ ],
+ [
+ "设置颜色",
+ ""
+ ],
+ [
+ "设置大小",
+ ""
+ ],
+ [
+ "集成 iconfont 与 remixicon 图标库,展示部分示例",
+ ""
+ ],
+ [
+ "iconfont",
+ ""
+ ],
+ [
+ "remixicon",
+ ""
+ ],
+ [
+ "复制成功",
+ ""
+ ],
+ [
+ "普通",
+ ""
+ ],
+ [
+ "浅色",
+ ""
+ ],
+ [
+ "深色",
+ ""
+ ],
+ [
+ "只显示图标",
+ ""
+ ],
+ [
+ "文本模式",
+ ""
+ ],
+ [
+ "带边框",
+ ""
+ ],
+ [
+ "圆角按钮",
+ ""
+ ],
+ [
+ "带左侧图标",
+ ""
+ ],
+ [
+ "小",
+ ""
+ ],
+ [
+ "默认",
+ ""
+ ],
+ [
+ "大",
+ ""
+ ],
+ [
+ "无权限",
+ ""
+ ],
+ [
+ "服务异常",
+ ""
+ ],
+ [
+ "请在微信浏览器中打开",
+ ""
+ ],
+ [
+ "已取消支付",
+ ""
+ ],
+ [
+ "支付失败",
+ ""
+ ],
+ [
+ "授权信息仅用于用户登录",
+ ""
+ ],
+ [
+ "登录授权失败",
+ ""
+ ],
+ [
+ "获取短信验证码",
+ ""
+ ],
+ [
+ "验证码",
+ ""
+ ],
+ [
+ "发送短信",
+ ""
+ ],
+ [
+ "{n}s后重新获取",
+ ""
+ ],
+ [
+ "获取验证码",
+ ""
+ ],
+ [
+ "短信已发送,请查收",
+ ""
+ ],
+ [
+ "请填写验证码",
+ ""
+ ],
+ [
+ "请填写正确的手机号格式",
+ ""
+ ],
+ [
+ "全局字号",
+ ""
+ ],
+ [
+ "这是一段示例文字,用于预览不同字号的效果。",
+ ""
+ ],
+ [
+ "默认 1.0",
+ ""
+ ],
+ [
+ "切换语言",
+ ""
+ ],
+ [
+ "切换中",
+ ""
+ ],
+ [
+ "模板",
+ ""
+ ],
+ [
+ "编辑资料",
+ ""
+ ],
+ [
+ "Text 文本",
+ ""
+ ],
+ [
+ "Button 按钮",
+ ""
+ ],
+ [
+ "Image 图片",
+ ""
+ ],
+ [
+ "Icon 图标",
+ ""
+ ],
+ [
+ "Tag 标签",
+ ""
+ ],
+ [
+ "Form 表单验证",
+ ""
+ ],
+ [
+ "Input 输入框",
+ ""
+ ],
+ [
+ "Textarea 文本域",
+ ""
+ ],
+ [
+ "InputNumber 计数器",
+ ""
+ ],
+ [
+ "InputOtp 口令输入",
+ ""
+ ],
+ [
+ "Keyboard 键盘",
+ ""
+ ],
+ [
+ "Radio 单选框",
+ ""
+ ],
+ [
+ "Checkbox 多选框",
+ ""
+ ],
+ [
+ "Switch 开关",
+ ""
+ ],
+ [
+ "Rate 评分",
+ ""
+ ],
+ [
+ "Slider 滑块",
+ ""
+ ],
+ [
+ "Select 选择器",
+ ""
+ ],
+ [
+ "SelectDate 日期选择器",
+ ""
+ ],
+ [
+ "SelectTime 时间选择器",
+ ""
+ ],
+ [
+ "Cascader 级联选择器",
+ ""
+ ],
+ [
+ "Upload 文件上传",
+ ""
+ ],
+ [
+ "Calendar 日历",
+ ""
+ ],
+ [
+ "Flex 弹性布局",
+ ""
+ ],
+ [
+ "Tabs 标签页",
+ ""
+ ],
+ [
+ "Collapse 折叠面板",
+ ""
+ ],
+ [
+ "Sticky 吸顶",
+ ""
+ ],
+ [
+ "TopBar 导航栏",
+ ""
+ ],
+ [
+ "FloatView 悬浮视图",
+ ""
+ ],
+ [
+ "Footer 底部视图",
+ ""
+ ],
+ [
+ "List 列表",
+ ""
+ ],
+ [
+ "ListView 列表视图",
+ ""
+ ],
+ [
+ "ListViewRefresh 列表刷新",
+ ""
+ ],
+ [
+ "Waterfall 瀑布流",
+ ""
+ ],
+ [
+ "Banner 轮播图",
+ ""
+ ],
+ [
+ "Marquee 跑马灯",
+ ""
+ ],
+ [
+ "Pagination 分页",
+ ""
+ ],
+ [
+ "Timeline 时间轴",
+ ""
+ ],
+ [
+ "Avatar 头像",
+ ""
+ ],
+ [
+ "ReadMore 查看更多",
+ ""
+ ],
+ [
+ "Draggable 拖拽",
+ ""
+ ],
+ [
+ "FilterBar 筛选栏",
+ ""
+ ],
+ [
+ "Tree 树形结构",
+ ""
+ ],
+ [
+ "Badge 角标",
+ ""
+ ],
+ [
+ "NoticeBar 通知栏",
+ ""
+ ],
+ [
+ "Countdown 倒计时",
+ ""
+ ],
+ [
+ "Progress 进度条",
+ ""
+ ],
+ [
+ "ProgressCircle 圆形进度条",
+ ""
+ ],
+ [
+ "Skeleton 骨架图",
+ ""
+ ],
+ [
+ "LoadMore 加载更多",
+ ""
+ ],
+ [
+ "RollingNumber 数字滚动",
+ ""
+ ],
+ [
+ "ActionSheet 操作菜单",
+ ""
+ ],
+ [
+ "Popup 弹窗",
+ ""
+ ],
+ [
+ "Confirm 确认框",
+ ""
+ ],
+ [
+ "Toast 提示框",
+ ""
+ ],
+ [
+ "QRCode 二维码",
+ ""
+ ],
+ [
+ "Sign 签名",
+ ""
+ ],
+ [
+ "DayUts 日期",
+ ""
+ ],
+ [
+ "Vibrate 震动",
+ ""
+ ],
+ [
+ "Cropper 图片裁剪",
+ ""
+ ],
+ [
+ "Canvas 画布",
+ ""
+ ],
+ [
+ "SVG 图标",
+ ""
+ ],
+ [
+ "SlideVerify 滑动验证",
+ ""
+ ],
+ [
+ "Animation 动画",
+ ""
+ ],
+ [
+ "编辑地址",
+ ""
+ ],
+ [
+ "cool-unix",
+ ""
+ ],
+ [
+ "首页",
+ ""
+ ],
+ [
+ "我的",
+ ""
+ ],
+ [
+ "这是一段需要保护的内容",
+ ""
+ ],
+ [
+ "水印会覆盖在内容上方,防止内容被盗用",
+ ""
+ ],
+ [
+ "可自定义的水印内容区域",
+ ""
+ ],
+ [
+ "水印文本",
+ ""
+ ],
+ [
+ "字体大小",
+ ""
+ ],
+ [
+ "透明度",
+ ""
+ ],
+ [
+ "旋转角度",
+ ""
+ ],
+ [
+ "水印宽度",
+ ""
+ ],
+ [
+ "水印高度",
+ ""
+ ],
+ [
+ "水平间距",
+ ""
+ ],
+ [
+ "垂直间距",
+ ""
+ ],
+ [
+ "字体粗细",
+ ""
+ ],
+ [
+ "正常",
+ ""
+ ],
+ [
+ "加粗",
+ ""
+ ],
+ [
+ "多行文本水印",
+ ""
+ ],
+ [
+ "重要文档",
+ ""
+ ],
+ [
+ "这是一份重要的文档内容,需要添加水印保护。",
+ ""
+ ],
+ [
+ "水印可以防止内容被未授权的复制和传播。",
+ ""
+ ],
+ [
+ "图片保护",
+ ""
+ ]
+]
\ No newline at end of file
diff --git a/cool-unix/locale/zh-tw.json b/cool-unix/locale/zh-tw.json
new file mode 100644
index 0000000..3a5deed
--- /dev/null
+++ b/cool-unix/locale/zh-tw.json
@@ -0,0 +1,2502 @@
+[
+ [
+ "Animation 动画",
+ "動畫"
+ ],
+ [
+ "编辑地址",
+ "編輯地址"
+ ],
+ [
+ "cool-unix",
+ "cool-unix"
+ ],
+ [
+ "首页",
+ "首頁"
+ ],
+ [
+ "我的",
+ "我的"
+ ],
+ [
+ "开发中,敬请期待",
+ "開發中,敬請期待"
+ ],
+ [
+ "基础组件",
+ "基礎組件"
+ ],
+ [
+ "文本",
+ "文本"
+ ],
+ [
+ "按钮",
+ "按鈕"
+ ],
+ [
+ "图片",
+ "圖片"
+ ],
+ [
+ "图标",
+ "圖標"
+ ],
+ [
+ "标签",
+ "標籤"
+ ],
+ [
+ "表单组件",
+ "表單組件"
+ ],
+ [
+ "表单验证",
+ "表單驗證"
+ ],
+ [
+ "输入框",
+ "輸入框"
+ ],
+ [
+ "文本域",
+ "文本域"
+ ],
+ [
+ "计数器",
+ "計數器"
+ ],
+ [
+ "口令输入",
+ "口令輸入"
+ ],
+ [
+ "键盘",
+ "鍵盤"
+ ],
+ [
+ "单选框",
+ "單選框"
+ ],
+ [
+ "多选框",
+ "多選框"
+ ],
+ [
+ "开关",
+ "開關"
+ ],
+ [
+ "评分",
+ "評分"
+ ],
+ [
+ "滑块",
+ "滑塊"
+ ],
+ [
+ "选择器",
+ "選擇器"
+ ],
+ [
+ "其他",
+ "其他"
+ ],
+ [
+ "文件管理",
+ "文件管理"
+ ],
+ [
+ "该模板正在开发中",
+ "該模板正在開發中"
+ ],
+ [
+ "未登录",
+ "未登錄"
+ ],
+ [
+ "总点击",
+ "總點擊"
+ ],
+ [
+ "赞",
+ "讚"
+ ],
+ [
+ "收藏",
+ "收藏"
+ ],
+ [
+ "粉丝",
+ "粉絲"
+ ],
+ [
+ "接单模式",
+ "接單模式"
+ ],
+ [
+ "已关闭",
+ "已關閉"
+ ],
+ [
+ "消息通知",
+ "消息通知"
+ ],
+ [
+ "待支付",
+ "待支付"
+ ],
+ [
+ "未发货",
+ "未發貨"
+ ],
+ [
+ "已发货",
+ "已發貨"
+ ],
+ [
+ "售后 / 退款",
+ "售後 / 退款"
+ ],
+ [
+ "我的钱包",
+ "我的錢包"
+ ],
+ [
+ "数据看板",
+ "數據看板"
+ ],
+ [
+ "历史记录",
+ "歷史記錄"
+ ],
+ [
+ "邀请好友",
+ "邀請好友"
+ ],
+ [
+ "设置",
+ "設置"
+ ],
+ [
+ "左间隔",
+ "左間隔"
+ ],
+ [
+ "右移动",
+ "右移動"
+ ],
+ [
+ "左移动",
+ "左移動"
+ ],
+ [
+ "多个数据",
+ "多個數據"
+ ],
+ [
+ "点击收起",
+ "點擊收起"
+ ],
+ [
+ "点击展开",
+ "點擊展開"
+ ],
+ [
+ "ref 方式调用",
+ "ref方式調用"
+ ],
+ [
+ "自定义图标、文字、大小",
+ "自定義圖標、文字、大小"
+ ],
+ [
+ "上传证件照",
+ "上傳證件照"
+ ],
+ [
+ "多选",
+ "多選"
+ ],
+ [
+ "限制 3 个",
+ "限制3個"
+ ],
+ [
+ "边框",
+ "邊框"
+ ],
+ [
+ "显示字数",
+ "顯示字數"
+ ],
+ [
+ "自动增高",
+ "自動增高"
+ ],
+ [
+ "其他颜色",
+ "其他顏色"
+ ],
+ [
+ "大一点",
+ "大一點"
+ ],
+ [
+ "正方形",
+ "正方形"
+ ],
+ [
+ "范围选择",
+ "範圍選擇"
+ ],
+ [
+ "显示值",
+ "顯示值"
+ ],
+ [
+ "步长10",
+ "步長10"
+ ],
+ [
+ "转动图片",
+ "轉動圖片"
+ ],
+ [
+ "验证通过",
+ "驗證通過"
+ ],
+ [
+ "验证失败",
+ "驗證失敗"
+ ],
+ [
+ "操作",
+ "操作"
+ ],
+ [
+ "清空",
+ "清空"
+ ],
+ [
+ "预览",
+ "預覽"
+ ],
+ [
+ "设置高度",
+ "設置高度"
+ ],
+ [
+ "毛笔效果",
+ "毛筆效果"
+ ],
+ [
+ "添加LOGO",
+ "添加LOGO"
+ ],
+ [
+ "圆角定位点",
+ "圓角定位點"
+ ],
+ [
+ "内间距",
+ "內間距"
+ ],
+ [
+ "导出图片",
+ "導出圖片"
+ ],
+ [
+ "矩形",
+ "矩形"
+ ],
+ [
+ "点",
+ "點"
+ ],
+ [
+ "线性",
+ "線性"
+ ],
+ [
+ "小方格",
+ "小方格"
+ ],
+ [
+ "格式化",
+ "格式化"
+ ],
+ [
+ "添加",
+ "添加"
+ ],
+ [
+ "减去",
+ "減去"
+ ],
+ [
+ "获取某个单位的开始时间",
+ "獲取某個單位的開始時間"
+ ],
+ [
+ "签名",
+ "簽名"
+ ],
+ [
+ "图片裁剪",
+ "圖片裁剪"
+ ],
+ [
+ "Canvas",
+ "Canvas"
+ ],
+ [
+ "富文本",
+ "富文本"
+ ],
+ [
+ "该功能正在开发中",
+ "該功能正在開發中"
+ ],
+ [
+ "圆形",
+ "圓形"
+ ],
+ [
+ "组合",
+ "組合"
+ ],
+ [
+ "基础用法",
+ "基礎用法"
+ ],
+ [
+ "自定义",
+ "自定義"
+ ],
+ [
+ "加快滚动速度",
+ "加快滾動速度"
+ ],
+ [
+ "显示小数位数",
+ "顯示小數位數"
+ ],
+ [
+ "自定义样式",
+ "自定義樣式"
+ ],
+ [
+ "自定义颜色",
+ "自定義顏色"
+ ],
+ [
+ "自定义宽度",
+ "自定義寬度"
+ ],
+ [
+ "不显示文本",
+ "不顯示文本"
+ ],
+ [
+ "改个颜色",
+ "改個顏色"
+ ],
+ [
+ "显示文本",
+ "顯示文本"
+ ],
+ [
+ "快一些",
+ "快一些"
+ ],
+ [
+ "带图标",
+ "帶圖標"
+ ],
+ [
+ "设置速度",
+ "設置速度"
+ ],
+ [
+ "垂直方向",
+ "垂直方向"
+ ],
+ [
+ "3秒后加载完成",
+ "3秒後加載完成"
+ ],
+ [
+ "隐藏为 00 的值",
+ "隱藏為00的值"
+ ],
+ [
+ "指定天数",
+ "指定天數"
+ ],
+ [
+ "自定义模板",
+ "自定義模板"
+ ],
+ [
+ "指定小时",
+ "指定小時"
+ ],
+ [
+ "指定分钟",
+ "指定分鐘"
+ ],
+ [
+ "指定秒",
+ "指定秒"
+ ],
+ [
+ "完成后提示",
+ "完成後提示"
+ ],
+ [
+ "3秒后开始倒计时",
+ "3秒後開始倒計時"
+ ],
+ [
+ "结合按钮",
+ "結合按鈕"
+ ],
+ [
+ "购买",
+ "購買"
+ ],
+ [
+ "消息",
+ "消息"
+ ],
+ [
+ "结合图片",
+ "結合圖片"
+ ],
+ [
+ "结合图标",
+ "結合圖標"
+ ],
+ [
+ "点击触发",
+ "點擊觸發"
+ ],
+ [
+ "不同大小",
+ "不同大小"
+ ],
+ [
+ "不同颜色",
+ "不同顏色"
+ ],
+ [
+ "使用base64",
+ "使用base64"
+ ],
+ [
+ "没有错误提示",
+ "沒有錯誤提示"
+ ],
+ [
+ "已阅读并同意",
+ "已閱讀並同意"
+ ],
+ [
+ "用户协议",
+ "用戶協議"
+ ],
+ [
+ "隐私政策",
+ "隱私政策"
+ ],
+ [
+ "请先阅读并同意《用户协议》和《隐私政策》",
+ "請先閱讀並同意《用戶協議》和《隱私政策》"
+ ],
+ [
+ "我的昵称",
+ "我的暱稱"
+ ],
+ [
+ "简介",
+ "簡介"
+ ],
+ [
+ "介绍一下自己",
+ "介紹一下自己"
+ ],
+ [
+ "性别",
+ "性別"
+ ],
+ [
+ "编辑性别",
+ "編輯性別"
+ ],
+ [
+ "生日",
+ "生日"
+ ],
+ [
+ "选择生日",
+ "選擇生日"
+ ],
+ [
+ "地区",
+ "地區"
+ ],
+ [
+ "选择所在的地区",
+ "選擇所在的地區"
+ ],
+ [
+ "选择性别",
+ "選擇性別"
+ ],
+ [
+ "保密",
+ "保密"
+ ],
+ [
+ "男",
+ "男"
+ ],
+ [
+ "女",
+ "女"
+ ],
+ [
+ "性别设置成功",
+ "性別設置成功"
+ ],
+ [
+ "生日设置成功",
+ "生日設置成功"
+ ],
+ [
+ "地区设置成功",
+ "地區設置成功"
+ ],
+ [
+ "关于{name}",
+ "關於{name}"
+ ],
+ [
+ "联系客服",
+ "聯繫客服"
+ ],
+ [
+ "退出登录",
+ "退出登入"
+ ],
+ [
+ "确定退出登录吗?",
+ "確定退出登入嗎?"
+ ],
+ [
+ "深色模式",
+ "深色模式"
+ ],
+ [
+ "多语言",
+ "多語言"
+ ],
+ [
+ "字体大小",
+ "字體大小"
+ ],
+ [
+ "访问官网",
+ "訪問官網"
+ ],
+ [
+ "商城",
+ "商城"
+ ],
+ [
+ "商品分类",
+ "商品分類"
+ ],
+ [
+ "商品详情",
+ "商品詳情"
+ ],
+ [
+ "商品列表、筛选",
+ "商品列表、篩選"
+ ],
+ [
+ "购物车",
+ "購物車"
+ ],
+ [
+ "订单列表、详情",
+ "訂單列表、詳情"
+ ],
+ [
+ "收货地址",
+ "收貨地址"
+ ],
+ [
+ "聊天",
+ "聊天"
+ ],
+ [
+ "对话列表、历史记录",
+ "對話列表、歷史記錄"
+ ],
+ [
+ "流式回复",
+ "流式回覆"
+ ],
+ [
+ "语言合成",
+ "語言合成"
+ ],
+ [
+ "语音识别",
+ "語音識別"
+ ],
+ [
+ "请输入验证码",
+ "請輸入驗證碼"
+ ],
+ [
+ "登录",
+ "登入"
+ ],
+ [
+ "购物车 ({num})",
+ "購物車 ({num})"
+ ],
+ [
+ "完成",
+ "完成"
+ ],
+ [
+ "管理",
+ "管理"
+ ],
+ [
+ "删除",
+ "刪除"
+ ],
+ [
+ "全选",
+ "全選"
+ ],
+ [
+ "合计",
+ "合計"
+ ],
+ [
+ "去结算",
+ "去結算"
+ ],
+ [
+ "温馨提示",
+ "溫馨提示"
+ ],
+ [
+ "确定删除该商品吗?",
+ "確定刪除該商品嗎?"
+ ],
+ [
+ "删除成功",
+ "刪除成功"
+ ],
+ [
+ "请先选择商品",
+ "請先選擇商品"
+ ],
+ [
+ "确定删除选中的商品吗?",
+ "確定刪除選中的商品嗎?"
+ ],
+ [
+ "您需支付 {price} 元,请确认支付",
+ "您需支付 {price} 元,請確認支付"
+ ],
+ [
+ "支付成功",
+ "支付成功"
+ ],
+ [
+ "已设为默认",
+ "已設為預設"
+ ],
+ [
+ "设为默认",
+ "設為預設"
+ ],
+ [
+ "修改",
+ "修改"
+ ],
+ [
+ "添加地址",
+ "新增地址"
+ ],
+ [
+ "密码输入",
+ "密碼輸入"
+ ],
+ [
+ "可清除",
+ "可清除"
+ ],
+ [
+ "左右插槽",
+ "左右插槽"
+ ],
+ [
+ "左图标",
+ "左圖示"
+ ],
+ [
+ "右图标",
+ "右圖示"
+ ],
+ [
+ "自动聚焦",
+ "自動聚焦"
+ ],
+ [
+ "长度为6",
+ "長度為6"
+ ],
+ [
+ "步进为10",
+ "步進為10"
+ ],
+ [
+ "最小为10",
+ "最小為10"
+ ],
+ [
+ "最大为50",
+ "最大為50"
+ ],
+ [
+ "可以小数",
+ "可以小數"
+ ],
+ [
+ "可以输入",
+ "可以輸入"
+ ],
+ [
+ "用户名",
+ "使用者名稱"
+ ],
+ [
+ "请输入用户名",
+ "請輸入使用者名稱"
+ ],
+ [
+ "邮箱",
+ "電子郵件"
+ ],
+ [
+ "请输入邮箱地址",
+ "請輸入電子郵件地址"
+ ],
+ [
+ "动态验证",
+ "動態驗證"
+ ],
+ [
+ "联系人",
+ "聯絡人"
+ ],
+ [
+ "添加联系人",
+ "新增聯絡人"
+ ],
+ [
+ "身高",
+ "身高"
+ ],
+ [
+ "微信",
+ "微信"
+ ],
+ [
+ "父子关联",
+ "父子關聯"
+ ],
+ [
+ "选中值",
+ "選中值"
+ ],
+ [
+ "选中操作",
+ "選中操作"
+ ],
+ [
+ "选中部分节点",
+ "選中部分節點"
+ ],
+ [
+ "获取选中节点",
+ "獲取選中節點"
+ ],
+ [
+ "获取半选节点",
+ "獲取半選節點"
+ ],
+ [
+ "清空选中",
+ "清空選中"
+ ],
+ [
+ "展开操作",
+ "展開操作"
+ ],
+ [
+ "展开部分节点",
+ "展開部分節點"
+ ],
+ [
+ "获取展开节点",
+ "獲取展開節點"
+ ],
+ [
+ "展开所有",
+ "展開所有"
+ ],
+ [
+ "收起所有",
+ "收起所有"
+ ],
+ [
+ "开通账号",
+ "開通帳號"
+ ],
+ [
+ "赠送500元",
+ "贈送500元"
+ ],
+ [
+ "完成实名认证",
+ "完成實名認證"
+ ],
+ [
+ "通过身份证认证",
+ "通過身份證認證"
+ ],
+ [
+ "绑定银行卡",
+ "绑定銀行卡"
+ ],
+ [
+ "绑定招商银行储蓄卡",
+ "绑定招商銀行儲蓄卡"
+ ],
+ [
+ "首次充值",
+ "首次充值"
+ ],
+ [
+ "滑块大点",
+ "滑塊大一點"
+ ],
+ [
+ "换个颜色",
+ "換個顏色"
+ ],
+ [
+ "最大50",
+ "最大50"
+ ],
+ [
+ "自定义触发器",
+ "自定義觸發器"
+ ],
+ [
+ "打开选择器",
+ "打開選擇器"
+ ],
+ [
+ "多列",
+ "多列"
+ ],
+ [
+ "通过 children 配置多级数据,并使用 column-count 参数指定显示的列数",
+ "通過 children 配置多級數據,並使用 column-count 參數指定顯示的列數"
+ ],
+ [
+ "弹窗中使用",
+ "彈窗中使用"
+ ],
+ [
+ "打开",
+ "打開"
+ ],
+ [
+ "选择地区",
+ "選擇地區"
+ ],
+ [
+ "绑定值",
+ "绑定值"
+ ],
+ [
+ "下一步",
+ "下一步"
+ ],
+ [
+ "确定",
+ "確定"
+ ],
+ [
+ "关闭",
+ "關閉"
+ ],
+ [
+ "显示取消按钮",
+ "顯示取消按鈕"
+ ],
+ [
+ "修改按钮文案",
+ "修改按鈕文案"
+ ],
+ [
+ "显示绑定值",
+ "顯示绑定值"
+ ],
+ [
+ "时",
+ "時"
+ ],
+ [
+ "时:分",
+ "時:分"
+ ],
+ [
+ "时:分:秒",
+ "時:分:秒"
+ ],
+ [
+ "显示星期",
+ "顯示星期"
+ ],
+ [
+ "显示其他月份",
+ "顯示其他月份"
+ ],
+ [
+ "不同位置",
+ "不同位置"
+ ],
+ [
+ "顶部",
+ "頂部"
+ ],
+ [
+ "中间",
+ "中間"
+ ],
+ [
+ "底部",
+ "底部"
+ ],
+ [
+ "不同类型",
+ "不同類型"
+ ],
+ [
+ "成功",
+ "成功"
+ ],
+ [
+ "失败",
+ "失敗"
+ ],
+ [
+ "警告",
+ "警告"
+ ],
+ [
+ "问题",
+ "問題"
+ ],
+ [
+ "停止",
+ "停止"
+ ],
+ [
+ "自定义图标",
+ "自定義圖標"
+ ],
+ [
+ "只存在一个",
+ "只存在一個"
+ ],
+ [
+ "不同位置提示",
+ "不同位置提示"
+ ],
+ [
+ "不同类型提示",
+ "不同類型提示"
+ ],
+ [
+ "带图标提示",
+ "帶圖標提示"
+ ],
+ [
+ "移除其他已存在的提示",
+ "移除其他已存在的提示"
+ ],
+ [
+ "打开弹窗",
+ "打開彈窗"
+ ],
+ [
+ "设置宽度 80%",
+ "設置寬度 80%"
+ ],
+ [
+ "Badge 角标",
+ "徽章角標"
+ ],
+ [
+ "NoticeBar 通知栏",
+ "通知欄"
+ ],
+ [
+ "Countdown 倒计时",
+ "倒計時"
+ ],
+ [
+ "Progress 进度条",
+ "進度條"
+ ],
+ [
+ "ProgressCircle 圆形进度条",
+ "圓形進度條"
+ ],
+ [
+ "Skeleton 骨架图",
+ "骨架圖"
+ ],
+ [
+ "LoadMore 加载更多",
+ "加載更多"
+ ],
+ [
+ "RollingNumber 数字滚动",
+ "數字滾動"
+ ],
+ [
+ "ActionSheet 操作菜单",
+ "操作菜單"
+ ],
+ [
+ "Popup 弹窗",
+ "彈窗"
+ ],
+ [
+ "Confirm 确认框",
+ "確認框"
+ ],
+ [
+ "Toast 提示框",
+ "提示框"
+ ],
+ [
+ "QRCode 二维码",
+ "二維碼"
+ ],
+ [
+ "Sign 签名",
+ "簽名"
+ ],
+ [
+ "DayUts 日期",
+ "日期"
+ ],
+ [
+ "Vibrate 震动",
+ "震動"
+ ],
+ [
+ "Cropper 图片裁剪",
+ "圖片裁剪"
+ ],
+ [
+ "Canvas 画布",
+ "畫布"
+ ],
+ [
+ "SVG 图标",
+ "SVG圖標"
+ ],
+ [
+ "SlideVerify 滑动验证",
+ "滑動驗證"
+ ],
+ [
+ "充值1000元",
+ "充值1000元"
+ ],
+ [
+ "完成首笔交易",
+ "完成首筆交易"
+ ],
+ [
+ "优选灵活配置混合A",
+ "優選靈活配置混合A"
+ ],
+ [
+ "1000元起",
+ "1000元起"
+ ],
+ [
+ "禁用切换按钮",
+ "禁用切換按鈕"
+ ],
+ [
+ "自定义高度",
+ "自定義高度"
+ ],
+ [
+ "多页数",
+ "多頁數"
+ ],
+ [
+ "上一页",
+ "上一頁"
+ ],
+ [
+ "下一页",
+ "下一頁"
+ ],
+ [
+ "横向滚动",
+ "橫向滾動"
+ ],
+ [
+ "纵向滚动",
+ "縱向滾動"
+ ],
+ [
+ "快一点",
+ "快一點"
+ ],
+ [
+ "暂停",
+ "暫停"
+ ],
+ [
+ "内容靠左",
+ "內容靠左"
+ ],
+ [
+ "QQ",
+ "QQ"
+ ],
+ [
+ "带箭头",
+ "帶箭頭"
+ ],
+ [
+ "余额",
+ "餘額"
+ ],
+ [
+ "带图片",
+ "帶圖片"
+ ],
+ [
+ "神仙都没用",
+ "神仙都沒用"
+ ],
+ [
+ "折叠",
+ "摺疊"
+ ],
+ [
+ "设置大小",
+ "設置大小"
+ ],
+ [
+ "集成 iconfont 与 remixicon 图标库,展示部分示例",
+ "集成 iconfont 與 remixicon 圖標庫,展示部分示例"
+ ],
+ [
+ "iconfont",
+ "iconfont"
+ ],
+ [
+ "remixicon",
+ "remixicon"
+ ],
+ [
+ "复制成功",
+ "複製成功"
+ ],
+ [
+ "普通",
+ "普通"
+ ],
+ [
+ "浅色",
+ "淺色"
+ ],
+ [
+ "深色",
+ "深色"
+ ],
+ [
+ "只显示图标",
+ "只顯示圖標"
+ ],
+ [
+ "文本模式",
+ "文本模式"
+ ],
+ [
+ "带边框",
+ "帶邊框"
+ ],
+ [
+ "圆角按钮",
+ "圓角按鈕"
+ ],
+ [
+ "带左侧图标",
+ "帶左側圖標"
+ ],
+ [
+ "小",
+ "小"
+ ],
+ [
+ "默认",
+ "默認"
+ ],
+ [
+ "大",
+ "大"
+ ],
+ [
+ "无权限",
+ "無權限"
+ ],
+ [
+ "服务异常",
+ "服務異常"
+ ],
+ [
+ "请在微信浏览器中打开",
+ "請在微信瀏覽器中打開"
+ ],
+ [
+ "已取消支付",
+ "已取消支付"
+ ],
+ [
+ "跑马灯",
+ "跑馬燈"
+ ],
+ [
+ "分页",
+ "分頁"
+ ],
+ [
+ "时间轴",
+ "時間軸"
+ ],
+ [
+ "拖拽",
+ "拖拽"
+ ],
+ [
+ "筛选栏",
+ "篩選欄"
+ ],
+ [
+ "树形结构",
+ "樹形結構"
+ ],
+ [
+ "状态组件",
+ "狀態組件"
+ ],
+ [
+ "角标",
+ "角標"
+ ],
+ [
+ "通知栏",
+ "通知欄"
+ ],
+ [
+ "倒计时",
+ "倒計時"
+ ],
+ [
+ "数字滚动",
+ "數字滾動"
+ ],
+ [
+ "进度条",
+ "進度條"
+ ],
+ [
+ "圆形进度条",
+ "圓形進度條"
+ ],
+ [
+ "骨架图",
+ "骨架圖"
+ ],
+ [
+ "加载更多",
+ "加載更多"
+ ],
+ [
+ "反馈组件",
+ "反饋組件"
+ ],
+ [
+ "操作菜单",
+ "操作菜單"
+ ],
+ [
+ "弹窗",
+ "彈窗"
+ ],
+ [
+ "确认框",
+ "確認框"
+ ],
+ [
+ "提示框",
+ "提示框"
+ ],
+ [
+ "多行省略号",
+ "多行省略號"
+ ],
+ [
+ "金额",
+ "金額"
+ ],
+ [
+ "手机号脱敏",
+ "手機號脫敏"
+ ],
+ [
+ "姓名脱敏",
+ "姓名脫敏"
+ ],
+ [
+ "邮箱脱敏",
+ "郵箱脫敏"
+ ],
+ [
+ "银行卡脱敏",
+ "銀行卡脫敏"
+ ],
+ [
+ "自定义脱敏字符",
+ "自定義脫敏字符"
+ ],
+ [
+ "主要",
+ "主要"
+ ],
+ [
+ "危险",
+ "危險"
+ ],
+ [
+ "信息",
+ "信息"
+ ],
+ [
+ "邮件",
+ "郵件"
+ ],
+ [
+ "文件",
+ "文件"
+ ],
+ [
+ "可关闭",
+ "可關閉"
+ ],
+ [
+ "镂空",
+ "鏤空"
+ ],
+ [
+ "自定义无圆角",
+ "自定義無圓角"
+ ],
+ [
+ "不同裁剪",
+ "不同裁剪"
+ ],
+ [
+ "点击可预览",
+ "點擊可預覽"
+ ],
+ [
+ "失败时显示",
+ "失敗時顯示"
+ ],
+ [
+ "自定义圆角",
+ "自定義圓角"
+ ],
+ [
+ "设置颜色",
+ "設置顏色"
+ ],
+ [
+ "体重不能为空",
+ "體重不能為空"
+ ],
+ [
+ "体重在40-100kg之间",
+ "體重在40-100kg之間"
+ ],
+ [
+ "标签不能为空",
+ "標籤不能為空"
+ ],
+ [
+ "标签最多选择2个",
+ "標籤最多選擇2個"
+ ],
+ [
+ "性别不能为空",
+ "性別不能為空"
+ ],
+ [
+ "出生年月不能为空",
+ "出生年月不能為空"
+ ],
+ [
+ "出生年月不大于2010-01-01",
+ "出生年月不大於2010-01-01"
+ ],
+ [
+ "联系人不能为空",
+ "聯繫人不能為空"
+ ],
+ [
+ "提交成功",
+ "提交成功"
+ ],
+ [
+ "单个 true / false",
+ "單個true / false"
+ ],
+ [
+ "带索引、地区选择",
+ "帶索引、地區選擇"
+ ],
+ [
+ "换个分隔符",
+ "換個分隔符"
+ ],
+ [
+ "列表高度小一点",
+ "列表高度小一點"
+ ],
+ [
+ "范围选",
+ "範圍選"
+ ],
+ [
+ "禁用部分日期",
+ "禁用部分日期"
+ ],
+ [
+ "日历长列表",
+ "日曆長列表"
+ ],
+ [
+ "打开日历长列表",
+ "打開日曆長列表"
+ ],
+ [
+ "日历面板",
+ "日曆面板"
+ ],
+ [
+ "自定义文案和颜色",
+ "自定義文案和顏色"
+ ],
+ [
+ "显示头",
+ "顯示頭"
+ ],
+ [
+ "可滑动",
+ "可滑動"
+ ],
+ [
+ "左滑编辑",
+ "左滑編輯"
+ ],
+ [
+ "编辑",
+ "編輯"
+ ],
+ [
+ "右滑删除",
+ "右滑刪除"
+ ],
+ [
+ "账号",
+ "帳號"
+ ],
+ [
+ "我的订单",
+ "我的訂單"
+ ],
+ [
+ "我的收藏",
+ "我的收藏"
+ ],
+ [
+ "筛选",
+ "篩選"
+ ],
+ [
+ "长按项即可拖动排序",
+ "長按項即可拖動排序"
+ ],
+ [
+ "单列排序",
+ "單列排序"
+ ],
+ [
+ "不需要长按",
+ "不需要長按"
+ ],
+ [
+ "结合列表使用",
+ "結合列表使用"
+ ],
+ [
+ "多列排序",
+ "多列排序"
+ ],
+ [
+ "结合图片使用",
+ "結合圖片使用"
+ ],
+ [
+ "禁用手势",
+ "禁用手勢"
+ ],
+ [
+ "自定义样式2",
+ "自定義樣式2"
+ ],
+ [
+ "无图片",
+ "無圖片"
+ ],
+ [
+ "圆角",
+ "圓角"
+ ],
+ [
+ "自定义大小",
+ "自定義大小"
+ ],
+ [
+ "省略号",
+ "省略號"
+ ],
+ [
+ "删除地址后无法恢复,确认要删除该地址吗?",
+ "刪除地址後無法恢復,確認要刪除該地址嗎?"
+ ],
+ [
+ "加载中",
+ "加載中"
+ ],
+ [
+ "收货人",
+ "收貨人"
+ ],
+ [
+ "请输入收货人姓名",
+ "請輸入收貨人姓名"
+ ],
+ [
+ "手机号",
+ "手機號"
+ ],
+ [
+ "选择省市区",
+ "選擇省市區"
+ ],
+ [
+ "详细地址",
+ "詳細地址"
+ ],
+ [
+ "小区楼栋、门牌号、村等",
+ "小區樓棟、門牌號、村等"
+ ],
+ [
+ "默认地址",
+ "默認地址"
+ ],
+ [
+ "保存",
+ "保存"
+ ],
+ [
+ "收货人不能为空",
+ "收貨人不能為空"
+ ],
+ [
+ "手机号不能为空",
+ "手機號不能為空"
+ ],
+ [
+ "手机号格式不正确",
+ "手機號格式不正確"
+ ],
+ [
+ "详细地址不能为空",
+ "詳細地址不能為空"
+ ],
+ [
+ "所在地区不能为空",
+ "所在地區不能為空"
+ ],
+ [
+ "保存中",
+ "保存中"
+ ],
+ [
+ "开启通知",
+ "開啟通知"
+ ],
+ [
+ "通用设置",
+ "通用設置"
+ ],
+ [
+ "通知设置",
+ "通知設置"
+ ],
+ [
+ "隐私设置",
+ "隱私設置"
+ ],
+ [
+ "支付失败",
+ "支付失敗"
+ ],
+ [
+ "授权信息仅用于用户登录",
+ "授權資訊僅用於用戶登錄"
+ ],
+ [
+ "登录授权失败",
+ "登錄授權失敗"
+ ],
+ [
+ "获取短信验证码",
+ "獲取短信驗證碼"
+ ],
+ [
+ "验证码",
+ "驗證碼"
+ ],
+ [
+ "发送短信",
+ "發送短信"
+ ],
+ [
+ "{n}s后重新获取",
+ "{n}s後重新獲取"
+ ],
+ [
+ "获取验证码",
+ "獲取驗證碼"
+ ],
+ [
+ "短信已发送,请查收",
+ "短信已發送,請查收"
+ ],
+ [
+ "请填写验证码",
+ "請填寫驗證碼"
+ ],
+ [
+ "请填写正确的手机号格式",
+ "請填寫正確的手機號格式"
+ ],
+ [
+ "全局字号",
+ "全局字號"
+ ],
+ [
+ "这是一段示例文字,用于预览不同字号的效果。",
+ "這是一段示例文字,用於預覽不同字號的效果。"
+ ],
+ [
+ "默认 1.0",
+ "默認1.0"
+ ],
+ [
+ "切换语言",
+ "切換語言"
+ ],
+ [
+ "切换中",
+ "切換中"
+ ],
+ [
+ "模板",
+ "模板"
+ ],
+ [
+ "编辑资料",
+ "編輯資料"
+ ],
+ [
+ "Text 文本",
+ "Text文本"
+ ],
+ [
+ "Button 按钮",
+ "Button按鈕"
+ ],
+ [
+ "插槽",
+ "插槽"
+ ],
+ [
+ "使用 PT 自定义颜色",
+ "使用PT自定義顏色"
+ ],
+ [
+ "自定义返回图标",
+ "自定義返回圖示"
+ ],
+ [
+ "自定义返回路径",
+ "自定義返回路徑"
+ ],
+ [
+ "自定义标题内容",
+ "自定義標題內容"
+ ],
+ [
+ "显示滑块",
+ "顯示滑塊"
+ ],
+ [
+ "添加间距",
+ "添加間距"
+ ],
+ [
+ "横向填充",
+ "橫向填充"
+ ],
+ [
+ "适用于标签数量不多的情况",
+ "適用於標籤數量不多的情況"
+ ],
+ [
+ "居中",
+ "居中"
+ ],
+ [
+ "单个禁用",
+ "單個禁用"
+ ],
+ [
+ "显示下划线",
+ "顯示下劃線"
+ ],
+ [
+ "禁用",
+ "禁用"
+ ],
+ [
+ "取消订单",
+ "取消訂單"
+ ],
+ [
+ "立即购买",
+ "立即購買"
+ ],
+ [
+ "确认收货",
+ "確認收貨"
+ ],
+ [
+ "评价",
+ "評價"
+ ],
+ [
+ "禁用状态,无法拖拽",
+ "禁用狀態,無法拖拽"
+ ],
+ [
+ "不吸附边缘,任意位置可拖拽",
+ "不吸附邊緣,任意位置可拖拽"
+ ],
+ [
+ "这是一个提示",
+ "這是一個提示"
+ ],
+ [
+ "标签格式化",
+ "標籤格式化"
+ ],
+ [
+ "固定开始、结束日期",
+ "固定開始、結束日期"
+ ],
+ [
+ "自定义快捷选项",
+ "自定義快捷選項"
+ ],
+ [
+ "只读",
+ "唯讀"
+ ],
+ [
+ "显示分数",
+ "顯示分數"
+ ],
+ [
+ "允许半星",
+ "允許半星"
+ ],
+ [
+ "换个图标",
+ "換個圖標"
+ ],
+ [
+ "纵向排列",
+ "縱向排列"
+ ],
+ [
+ "换个样式",
+ "換個樣式"
+ ],
+ [
+ "不显示图标",
+ "不顯示圖標"
+ ],
+ [
+ "其他样式",
+ "其他樣式"
+ ],
+ [
+ "数字键盘",
+ "數字鍵盤"
+ ],
+ [
+ "打开键盘",
+ "打開鍵盤"
+ ],
+ [
+ "是否显示输入值",
+ "是否顯示輸入值"
+ ],
+ [
+ "输入即绑定",
+ "輸入即绑定"
+ ],
+ [
+ "身份证键盘",
+ "身份證鍵盤"
+ ],
+ [
+ "密码键盘",
+ "密碼鍵盤"
+ ],
+ [
+ "是否加密",
+ "是否加密"
+ ],
+ [
+ "车牌号键盘",
+ "車牌號鍵盤"
+ ],
+ [
+ "数字输入",
+ "數字輸入"
+ ],
+ [
+ "Flex 弹性布局",
+ "Flex 彈性布局"
+ ],
+ [
+ "Tabs 标签页",
+ "Tabs 標籤頁"
+ ],
+ [
+ "Collapse 折叠面板",
+ "Collapse 摺疊面板"
+ ],
+ [
+ "Sticky 吸顶",
+ "Sticky 吸頂"
+ ],
+ [
+ "TopBar 导航栏",
+ "TopBar 導航欄"
+ ],
+ [
+ "FloatView 悬浮视图",
+ "FloatView 懸浮視圖"
+ ],
+ [
+ "Footer 底部视图",
+ "Footer 底部視圖"
+ ],
+ [
+ "List 列表",
+ "List 列表"
+ ],
+ [
+ "ListView 列表视图",
+ "ListView 列表視圖"
+ ],
+ [
+ "ListViewRefresh 列表刷新",
+ "ListViewRefresh 列表刷新"
+ ],
+ [
+ "Waterfall 瀑布流",
+ "Waterfall 瀑布流"
+ ],
+ [
+ "Banner 轮播图",
+ "Banner 輪播圖"
+ ],
+ [
+ "Marquee 跑马灯",
+ "Marquee 跑馬燈"
+ ],
+ [
+ "Pagination 分页",
+ "Pagination 分頁"
+ ],
+ [
+ "Timeline 时间轴",
+ "Timeline 時間軸"
+ ],
+ [
+ "Avatar 头像",
+ "Avatar 頭像"
+ ],
+ [
+ "ReadMore 查看更多",
+ "ReadMore 查看更多"
+ ],
+ [
+ "Draggable 拖拽",
+ "Draggable 拖曳"
+ ],
+ [
+ "FilterBar 筛选栏",
+ "FilterBar 篩選欄"
+ ],
+ [
+ "Tree 树形结构",
+ "Tree 樹形結構"
+ ],
+ [
+ "无头",
+ "無頭"
+ ],
+ [
+ "左侧",
+ "左側"
+ ],
+ [
+ "右侧",
+ "右側"
+ ],
+ [
+ "隐藏取消按钮",
+ "隱藏取消按鈕"
+ ],
+ [
+ "自定义文本",
+ "自定義文本"
+ ],
+ [
+ "关闭前钩子",
+ "關閉前鉤子"
+ ],
+ [
+ "显示时长",
+ "顯示時長"
+ ],
+ [
+ "确定要删除吗?",
+ "確定要刪除嗎?"
+ ],
+ [
+ "确定要删除吗?3秒后自动关闭",
+ "確定要刪除嗎?3秒後自動關閉"
+ ],
+ [
+ "带标题、描述",
+ "帶標題、描述"
+ ],
+ [
+ "无法点击遮罩关闭",
+ "無法點擊遮罩關閉"
+ ],
+ [
+ "不需要取消按钮",
+ "不需要取消按鈕"
+ ],
+ [
+ "插槽用法",
+ "插槽用法"
+ ],
+ [
+ "反馈",
+ "反饋"
+ ],
+ [
+ "删除好友会同时删除所有聊天记录",
+ "刪除好友會同時刪除所有聊天記錄"
+ ],
+ [
+ "删除好友",
+ "刪除好友"
+ ],
+ [
+ "确定要删除好友吗?",
+ "確定要刪除好友嗎?"
+ ],
+ [
+ "点我关闭",
+ "點我關閉"
+ ],
+ [
+ "确定要关闭吗?",
+ "確定要關閉嗎?"
+ ],
+ [
+ "支付宝",
+ "支付寶"
+ ],
+ [
+ "头像上传成功",
+ "頭像上傳成功"
+ ],
+ [
+ "编辑昵称",
+ "編輯暱稱"
+ ],
+ [
+ "请输入昵称",
+ "請輸入暱稱"
+ ],
+ [
+ "请设置2-20个字符,不包括@<>/等无效字符",
+ "請設置2-20個字元,不包括@<>/等無效字元"
+ ],
+ [
+ "确认",
+ "確認"
+ ],
+ [
+ "昵称长度需在2-20个字符之间",
+ "暱稱長度需在2-20個字元之間"
+ ],
+ [
+ "昵称不能包含@<>/等特殊字符",
+ "暱稱不能包含@<>/等特殊字元"
+ ],
+ [
+ "编辑简介",
+ "編輯簡介"
+ ],
+ [
+ "简介不能为空",
+ "簡介不能為空"
+ ],
+ [
+ "提示",
+ "提示"
+ ],
+ [
+ "为提供更好的服务,我们邀请您填写昵称、头像等公开信息",
+ "為提供更好的服務,我們邀請您填寫暱稱、頭像等公開資訊"
+ ],
+ [
+ "头像",
+ "頭像"
+ ],
+ [
+ "昵称",
+ "暱稱"
+ ],
+ [
+ "点击输入昵称",
+ "點擊輸入暱稱"
+ ],
+ [
+ "取消",
+ "取消"
+ ],
+ [
+ "请上传头像",
+ "請上傳頭像"
+ ],
+ [
+ "登录中",
+ "登錄中"
+ ],
+ [
+ "手机登录",
+ "手機登錄"
+ ],
+ [
+ "未注册的手机号登录成功后将自动注册",
+ "未註冊的手機號登錄成功後將自動註冊"
+ ],
+ [
+ "请输入手机号",
+ "請輸入手機號"
+ ],
+ [
+ "Image 图片",
+ "影像 圖片"
+ ],
+ [
+ "Icon 图标",
+ "圖示 圖標"
+ ],
+ [
+ "Tag 标签",
+ "標籤 標籤"
+ ],
+ [
+ "Form 表单验证",
+ "表單驗證 表單驗證"
+ ],
+ [
+ "Input 输入框",
+ "輸入框 輸入框"
+ ],
+ [
+ "Textarea 文本域",
+ "文本域 文本域"
+ ],
+ [
+ "InputNumber 计数器",
+ "計數器 計數器"
+ ],
+ [
+ "InputOtp 口令输入",
+ "口令輸入 口令輸入"
+ ],
+ [
+ "Keyboard 键盘",
+ "鍵盤 鍵盤"
+ ],
+ [
+ "Radio 单选框",
+ "單選框 單選框"
+ ],
+ [
+ "Checkbox 多选框",
+ "多選框 多選框"
+ ],
+ [
+ "Switch 开关",
+ "開關 開關"
+ ],
+ [
+ "Rate 评分",
+ "評分 評分"
+ ],
+ [
+ "Slider 滑块",
+ "滑塊 滑塊"
+ ],
+ [
+ "Select 选择器",
+ "選擇器 選擇器"
+ ],
+ [
+ "SelectDate 日期选择器",
+ "日期選擇器 日期選擇器"
+ ],
+ [
+ "SelectTime 时间选择器",
+ "時間選擇器 時間選擇器"
+ ],
+ [
+ "Cascader 级联选择器",
+ "級聯選擇器 級聯選擇器"
+ ],
+ [
+ "Upload 文件上传",
+ "文件上傳 文件上傳"
+ ],
+ [
+ "Calendar 日历",
+ "日曆 日曆"
+ ],
+ [
+ "体重",
+ "體重"
+ ],
+ [
+ "所在地区",
+ "所在地區"
+ ],
+ [
+ "出生年月",
+ "出生年月"
+ ],
+ [
+ "个人简介",
+ "個人簡介"
+ ],
+ [
+ "请输入个人简介",
+ "請輸入個人簡介"
+ ],
+ [
+ "公开状态",
+ "公開狀態"
+ ],
+ [
+ "重置",
+ "重置"
+ ],
+ [
+ "提交",
+ "提交"
+ ],
+ [
+ "未知",
+ "未知"
+ ],
+ [
+ "篮球",
+ "籃球"
+ ],
+ [
+ "足球",
+ "足球"
+ ],
+ [
+ "羽毛球",
+ "羽毛球"
+ ],
+ [
+ "乒乓球",
+ "乒乓球"
+ ],
+ [
+ "游泳",
+ "游泳"
+ ],
+ [
+ "用户名不能为空",
+ "用戶名不能為空"
+ ],
+ [
+ "用户名长度在3-20个字符之间",
+ "用戶名長度在3-20個字符之間"
+ ],
+ [
+ "邮箱不能为空",
+ "郵箱不能為空"
+ ],
+ [
+ "邮箱格式不正确",
+ "郵箱格式不正確"
+ ],
+ [
+ "身高不能为空",
+ "身高不能為空"
+ ],
+ [
+ "身高在160-190cm之间",
+ "身高在160-190cm之間"
+ ],
+ [
+ "日期选择器",
+ "日期選擇器"
+ ],
+ [
+ "时间选择器",
+ "時間選擇器"
+ ],
+ [
+ "级联选择器",
+ "級聯選擇器"
+ ],
+ [
+ "文件上传",
+ "文件上傳"
+ ],
+ [
+ "日历",
+ "日曆"
+ ],
+ [
+ "布局组件",
+ "布局組件"
+ ],
+ [
+ "弹性布局",
+ "彈性布局"
+ ],
+ [
+ "标签页",
+ "標籤頁"
+ ],
+ [
+ "折叠面板",
+ "折疊面板"
+ ],
+ [
+ "吸顶",
+ "吸頂"
+ ],
+ [
+ "导航栏",
+ "導航欄"
+ ],
+ [
+ "底部视图",
+ "底部視圖"
+ ],
+ [
+ "悬浮视图",
+ "懸浮視圖"
+ ],
+ [
+ "数据展示",
+ "數據展示"
+ ],
+ [
+ "查看更多",
+ "查看更多"
+ ],
+ [
+ "列表",
+ "列表"
+ ],
+ [
+ "列表视图",
+ "列表視圖"
+ ],
+ [
+ "列表刷新",
+ "列表刷新"
+ ],
+ [
+ "瀑布流",
+ "瀑布流"
+ ],
+ [
+ "轮播图",
+ "輪播圖"
+ ],
+ [
+ "获取某个单位的结束时间",
+ "獲取某個單位的結束時間"
+ ],
+ [
+ "是否同一天",
+ "是否同一天"
+ ],
+ [
+ "是否早于",
+ "是否早於"
+ ],
+ [
+ "是否晚于",
+ "是否晚於"
+ ],
+ [
+ "差值",
+ "差值"
+ ],
+ [
+ "差值(单位)",
+ "差值(單位)"
+ ],
+ [
+ "选择图片",
+ "選擇圖片"
+ ],
+ [
+ "可调节裁剪框大小",
+ "可調節裁剪框大小"
+ ],
+ [
+ "预览图片",
+ "預覽圖片"
+ ],
+ [
+ "保存图片",
+ "保存圖片"
+ ],
+ [
+ "本页面内容由 canvas 渲染生成,是否立即预览图片效果?",
+ "本頁面內容由 canvas 渲染生成,是否立即預覽圖片效果?"
+ ],
+ [
+ "基础动画",
+ "基礎動畫"
+ ],
+ [
+ "淡入淡出",
+ "淡入淡出"
+ ],
+ [
+ "播放动画",
+ "播放動畫"
+ ],
+ [
+ "滑入",
+ "滑入"
+ ],
+ [
+ "旋转翻转",
+ "旋轉翻轉"
+ ],
+ [
+ "摇摆抖动",
+ "搖摆抖動"
+ ],
+ [
+ "特殊效果",
+ "特殊效果"
+ ],
+ [
+ "组合动画",
+ "組合動畫"
+ ],
+ [
+ "标题",
+ "標題"
+ ]
+]
\ No newline at end of file
diff --git a/cool-unix/main.ts b/cool-unix/main.ts
new file mode 100644
index 0000000..5a197cd
--- /dev/null
+++ b/cool-unix/main.ts
@@ -0,0 +1,14 @@
+import { createSSRApp } from "vue";
+import { cool } from "./cool";
+import App from "./App.uvue";
+import "./router";
+
+export function createApp() {
+ const app = createSSRApp(App);
+
+ cool(app);
+
+ return {
+ app
+ };
+}
diff --git a/cool-unix/manifest.json b/cool-unix/manifest.json
new file mode 100644
index 0000000..5482c84
--- /dev/null
+++ b/cool-unix/manifest.json
@@ -0,0 +1,94 @@
+{
+ "name": "cool-unix",
+ "appid": "__UNI__651711F",
+ "description": "完全开源、永久免费、上手容易、效率极高的开发脚手架",
+ "versionName": "1.0.0",
+ "versionCode": "100",
+ "uni-app-x": {},
+ "quickapp": {},
+ "mp-weixin": {
+ "darkmode": true,
+ "appid": "wxdebc4de0b5584ca4",
+ "setting": {
+ "urlCheck": false,
+ "es6": true
+ },
+ "usingComponents": true
+ },
+ "mp-alipay": {
+ "usingComponents": true
+ },
+ "mp-baidu": {
+ "usingComponents": true
+ },
+ "mp-toutiao": {
+ "usingComponents": true
+ },
+ "uniStatistics": {
+ "enable": false
+ },
+ "vueVersion": "3",
+ "app": {
+ "distribute": {
+ "icons": {
+ "android": {
+ "hdpi": "",
+ "xhdpi": "",
+ "xxhdpi": "",
+ "xxxhdpi": ""
+ }
+ }
+ }
+ },
+ "web": {
+ "darkmode": true,
+ "router": {
+ "mode": "",
+ "base": "./"
+ },
+ "title": "cool-unix"
+ },
+ "app-harmony": {
+ "distribute": {
+ "bundleName": "com.cool.unix",
+ "signingConfigs": {
+ "default": {
+ "certpath": "/Users/icssoa/Library/Application Support/HBuilder X/extensions/launcher/agc-certs/1749115146522.cer",
+ "keyAlias": "debugKey",
+ "keyPassword": "0000001B0CD2170B509D76F6435F878B7ED2FE2E3EA6E7454E26523487B093238D4F7C8B7033D30DE80163",
+ "profile": "/Users/icssoa/Library/Application Support/HBuilder X/extensions/launcher/agc-certs/1749115146522.p7b",
+ "signAlg": "SHA256withECDSA",
+ "storeFile": "/Users/icssoa/Library/Application Support/HBuilder X/extensions/launcher/agc-certs/1749115146522.p12",
+ "storePassword": "0000001B0CD2170B509D76F6435F878B7ED2FE2E3EA6E7454E26523487B093238D4F7C8B7033D30DE80163"
+ }
+ },
+ "icons": {
+ "foreground": "static/logo2.png",
+ "background": "static/logo2.png"
+ }
+ }
+ },
+ "app-android": {
+ "distribute": {
+ "modules": {},
+ "icons": {
+ "hdpi": "docs/logo.png",
+ "xhdpi": "docs/logo.png",
+ "xxhdpi": "docs/logo.png",
+ "xxxhdpi": "docs/logo.png"
+ },
+ "splashScreens": {
+ "default": {}
+ }
+ }
+ },
+ "app-ios": {
+ "distribute": {
+ "modules": {},
+ "icons": {
+ "appstore": "docs/logo.png"
+ },
+ "splashScreens": {}
+ }
+ }
+}
\ No newline at end of file
diff --git a/cool-unix/package.json b/cool-unix/package.json
new file mode 100644
index 0000000..96f7757
--- /dev/null
+++ b/cool-unix/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "cool-unix",
+ "version": "8.0.30",
+ "license": "MIT",
+ "scripts": {
+ "build-ui": "node ./uni_modules/cool-ui/scripts/generate-types.js",
+ "build-icon": "node ./.cool/scripts/icon.js"
+ },
+ "dependencies": {
+ "hammer-touchemulator": "^0.0.2",
+ "vue": "^3.5.13",
+ "weixin-js-sdk": "^1.6.5"
+ },
+ "devDependencies": {
+ "@babel/parser": "^7.27.5",
+ "@babel/types": "^7.27.6",
+ "@cool-vue/ai": "^1.1.7",
+ "@cool-vue/vite-plugin": "^8.2.18",
+ "@dcloudio/types": "^3.4.16",
+ "@types/node": "^24.0.15",
+ "@vue/compiler-sfc": "^3.5.16",
+ "@vue/tsconfig": "^0.7.0",
+ "adm-zip": "^0.5.16",
+ "autoprefixer": "^10.4.21",
+ "postcss": "^8.5.3",
+ "prettier": "^3.5.3",
+ "tailwindcss": "3.4.17",
+ "vite": "^6.3.5"
+ }
+}
diff --git a/cool-unix/pages.json b/cool-unix/pages.json
new file mode 100644
index 0000000..579de22
--- /dev/null
+++ b/cool-unix/pages.json
@@ -0,0 +1,692 @@
+{
+ "pages": [
+ {
+ "path": "pages/index/home",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/index/my",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/index/template",
+ "style": {
+ "navigationBarTitleText": "模板"
+ }
+ }
+ ],
+ "subPackages": [
+ {
+ "root": "pages/set",
+ "pages": [
+ {
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "设置"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "general",
+ "style": {
+ "navigationBarTitleText": "通用设置"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "notice",
+ "style": {
+ "navigationBarTitleText": "通知设置"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "about",
+ "style": {
+ "navigationBarTitleText": ""
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "cs",
+ "style": {
+ "navigationBarTitleText": "联系客服"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/monthlyreport",
+ "pages": [
+ {
+ "path": "list",
+ "style": { "navigationBarTitleText": "我的月报" },
+ "meta": { "isAuth": true }
+ },
+ {
+ "path": "detail",
+ "style": { "navigationBarTitleText": "月报详情" },
+ "meta": { "isAuth": true }
+ },
+ {
+ "path": "submit",
+ "style": { "navigationBarTitleText": "提交月报" },
+ "meta": { "isAuth": true }
+ }
+ ]
+ },
+ {
+ "root": "pages/advice",
+ "pages": [
+ {
+ "path": "index",
+ "style": { "navigationBarTitleText": "工作建议" },
+ "meta": { "isAuth": true }
+ }
+ ]
+ },
+ {
+ "root": "pages/user",
+ "pages": [
+ {
+ "path": "edit",
+ "style": {
+ "navigationBarTitleText": "编辑资料"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "edit-name",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "edit-description",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "login",
+ "style": {
+ "navigationStyle": "custom",
+ "disableScroll": true
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/demo",
+ "pages": [
+ {
+ "path": "basic/text",
+ "style": {
+ "navigationBarTitleText": "Text 文本"
+ }
+ },
+ {
+ "path": "basic/button",
+ "style": {
+ "navigationBarTitleText": "Button 按钮"
+ }
+ },
+ {
+ "path": "basic/image",
+ "style": {
+ "navigationBarTitleText": "Image 图片"
+ }
+ },
+ {
+ "path": "basic/icon",
+ "style": {
+ "navigationBarTitleText": "Icon 图标"
+ }
+ },
+ {
+ "path": "basic/tag",
+ "style": {
+ "navigationBarTitleText": "Tag 标签"
+ }
+ },
+ {
+ "path": "form/form",
+ "style": {
+ "navigationBarTitleText": "Form 表单验证"
+ }
+ },
+ {
+ "path": "form/input",
+ "style": {
+ "navigationBarTitleText": "Input 输入框"
+ }
+ },
+ {
+ "path": "form/textarea",
+ "style": {
+ "navigationBarTitleText": "Textarea 文本域"
+ }
+ },
+ {
+ "path": "form/input-number",
+ "style": {
+ "navigationBarTitleText": "InputNumber 计数器"
+ }
+ },
+ {
+ "path": "form/input-otp",
+ "style": {
+ "navigationBarTitleText": "InputOtp 口令输入"
+ }
+ },
+ {
+ "path": "form/keyboard",
+ "style": {
+ "navigationBarTitleText": "Keyboard 键盘"
+ }
+ },
+ {
+ "path": "form/radio",
+ "style": {
+ "navigationBarTitleText": "Radio 单选框"
+ }
+ },
+ {
+ "path": "form/checkbox",
+ "style": {
+ "navigationBarTitleText": "Checkbox 多选框"
+ }
+ },
+ {
+ "path": "form/switch",
+ "style": {
+ "navigationBarTitleText": "Switch 开关"
+ }
+ },
+ {
+ "path": "form/rate",
+ "style": {
+ "navigationBarTitleText": "Rate 评分"
+ }
+ },
+ {
+ "path": "form/slider",
+ "style": {
+ "navigationBarTitleText": "Slider 滑块"
+ }
+ },
+ {
+ "path": "form/select",
+ "style": {
+ "navigationBarTitleText": "Select 选择器"
+ }
+ },
+ {
+ "path": "form/select-date",
+ "style": {
+ "navigationBarTitleText": "SelectDate 日期选择器"
+ }
+ },
+ {
+ "path": "form/select-time",
+ "style": {
+ "navigationBarTitleText": "SelectTime 时间选择器"
+ }
+ },
+ {
+ "path": "form/cascader",
+ "style": {
+ "navigationBarTitleText": "Cascader 级联选择器"
+ }
+ },
+ {
+ "path": "form/upload",
+ "style": {
+ "navigationBarTitleText": "Upload 文件上传"
+ }
+ },
+ {
+ "path": "form/calendar",
+ "style": {
+ "navigationBarTitleText": "Calendar 日历"
+ }
+ },
+ {
+ "path": "layout/flex",
+ "style": {
+ "navigationBarTitleText": "Flex 弹性布局"
+ }
+ },
+ {
+ "path": "layout/tabs",
+ "style": {
+ "navigationBarTitleText": "Tabs 标签页"
+ }
+ },
+ {
+ "path": "layout/collapse",
+ "style": {
+ "navigationBarTitleText": "Collapse 折叠面板"
+ }
+ },
+ {
+ "path": "layout/sticky",
+ "style": {
+ "navigationBarTitleText": "Sticky 吸顶"
+ }
+ },
+ {
+ "path": "layout/topbar",
+ "style": {
+ "navigationBarTitleText": "TopBar 导航栏"
+ }
+ },
+ {
+ "path": "layout/float-view",
+ "style": {
+ "navigationBarTitleText": "FloatView 悬浮视图"
+ }
+ },
+ {
+ "path": "layout/footer",
+ "style": {
+ "navigationBarTitleText": "Footer 底部视图"
+ }
+ },
+ {
+ "path": "data/list",
+ "style": {
+ "navigationBarTitleText": "List 列表"
+ }
+ },
+ {
+ "path": "data/list-view",
+ "style": {
+ "navigationBarTitleText": "ListView 列表视图"
+ }
+ },
+ {
+ "path": "data/list-view-refresh",
+ "style": {
+ "navigationBarTitleText": "ListViewRefresh 列表刷新"
+ }
+ },
+ {
+ "path": "data/waterfall",
+ "style": {
+ "navigationBarTitleText": "Waterfall 瀑布流"
+ }
+ },
+ {
+ "path": "data/banner",
+ "style": {
+ "navigationBarTitleText": "Banner 轮播图"
+ }
+ },
+ {
+ "path": "data/marquee",
+ "style": {
+ "navigationBarTitleText": "Marquee 跑马灯"
+ }
+ },
+ {
+ "path": "data/pagination",
+ "style": {
+ "navigationBarTitleText": "Pagination 分页"
+ }
+ },
+ {
+ "path": "data/timeline",
+ "style": {
+ "navigationBarTitleText": "Timeline 时间轴"
+ }
+ },
+ {
+ "path": "data/avatar",
+ "style": {
+ "navigationBarTitleText": "Avatar 头像"
+ }
+ },
+ {
+ "path": "data/read-more",
+ "style": {
+ "navigationBarTitleText": "ReadMore 查看更多"
+ }
+ },
+ {
+ "path": "data/draggable",
+ "style": {
+ "navigationBarTitleText": "Draggable 拖拽"
+ }
+ },
+ {
+ "path": "data/filter-bar",
+ "style": {
+ "navigationBarTitleText": "FilterBar 筛选栏"
+ }
+ },
+ {
+ "path": "data/tree",
+ "style": {
+ "navigationBarTitleText": "Tree 树形结构"
+ }
+ },
+ {
+ "path": "status/badge",
+ "style": {
+ "navigationBarTitleText": "Badge 角标"
+ }
+ },
+ {
+ "path": "status/noticebar",
+ "style": {
+ "navigationBarTitleText": "NoticeBar 通知栏"
+ }
+ },
+ {
+ "path": "status/countdown",
+ "style": {
+ "navigationBarTitleText": "Countdown 倒计时"
+ }
+ },
+ {
+ "path": "status/progress",
+ "style": {
+ "navigationBarTitleText": "Progress 进度条"
+ }
+ },
+ {
+ "path": "status/progress-circle",
+ "style": {
+ "navigationBarTitleText": "ProgressCircle 圆形进度条"
+ }
+ },
+ {
+ "path": "status/skeleton",
+ "style": {
+ "navigationBarTitleText": "Skeleton 骨架图"
+ }
+ },
+ {
+ "path": "status/loadmore",
+ "style": {
+ "navigationBarTitleText": "LoadMore 加载更多"
+ }
+ },
+ {
+ "path": "status/rolling-number",
+ "style": {
+ "navigationBarTitleText": "RollingNumber 数字滚动"
+ }
+ },
+ {
+ "path": "feedback/action-sheet",
+ "style": {
+ "navigationBarTitleText": "ActionSheet 操作菜单"
+ }
+ },
+ {
+ "path": "feedback/popup",
+ "style": {
+ "navigationBarTitleText": "Popup 弹窗"
+ }
+ },
+ {
+ "path": "feedback/confirm",
+ "style": {
+ "navigationBarTitleText": "Confirm 确认框"
+ }
+ },
+ {
+ "path": "feedback/toast",
+ "style": {
+ "navigationBarTitleText": "Toast 提示框"
+ }
+ },
+ {
+ "path": "other/qrcode",
+ "style": {
+ "navigationBarTitleText": "QRCode 二维码"
+ }
+ },
+ {
+ "path": "other/sign",
+ "style": {
+ "navigationBarTitleText": "Sign 签名"
+ }
+ },
+ {
+ "path": "other/watermark",
+ "style": {
+ "navigationBarTitleText": "Watermark 水印"
+ }
+ },
+ {
+ "path": "other/day-uts",
+ "style": {
+ "navigationBarTitleText": "DayUts 日期"
+ }
+ },
+ {
+ "path": "other/vibrate",
+ "style": {
+ "navigationBarTitleText": "Vibrate 震动"
+ }
+ },
+ {
+ "path": "other/cropper",
+ "style": {
+ "navigationBarTitleText": "Cropper 图片裁剪"
+ }
+ },
+ {
+ "path": "other/canvas",
+ "style": {
+ "navigationBarTitleText": "Canvas 画布"
+ }
+ },
+ {
+ "path": "other/svg",
+ "style": {
+ "navigationBarTitleText": "SVG 图标"
+ }
+ },
+ {
+ "path": "other/slide-verify",
+ "style": {
+ "navigationBarTitleText": "SlideVerify 滑动验证"
+ }
+ },
+ {
+ "path": "other/animation",
+ "style": {
+ "navigationBarTitleText": "Animation 动画"
+ }
+ },
+ {
+ "path": "other/router/index",
+ "style": {
+ "navigationBarTitleText": "Router 路由"
+ }
+ },
+ {
+ "path": "other/router/query"
+ },
+ {
+ "path": "other/share",
+ "style": {
+ "navigationBarTitleText": "Share 分享"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/template",
+ "pages": [
+ {
+ "path": "post/detail",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "shop/goods-category",
+ "style": {
+ "navigationBarTitleText": "商品分类"
+ }
+ },
+ {
+ "path": "shop/goods-detail/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "shop/shopping-cart",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "shop/address",
+ "style": {
+ "navigationBarTitleText": "收货地址",
+ "enablePullDownRefresh": true
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "shop/address-edit",
+ "style": {
+ "navigationBarTitleText": "编辑地址"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/dailyreport",
+ "pages": [
+ {
+ "path": "list",
+ "style": {
+ "navigationBarTitleText": "我的日报"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "submit",
+ "style": {
+ "navigationBarTitleText": "提交日报"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "detail",
+ "style": {
+ "navigationBarTitleText": "日报详情"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/weeklyreport",
+ "pages": [
+ {
+ "path": "list",
+ "style": {
+ "navigationBarTitleText": "我的周报"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "submit",
+ "style": {
+ "navigationBarTitleText": "提交周报"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ },
+ {
+ "path": "detail",
+ "style": {
+ "navigationBarTitleText": "周报详情"
+ },
+ "meta": {
+ "isAuth": true
+ }
+ }
+ ]
+ }
+ ],
+ "globalStyle": {
+ "navigationBarTitleText": "cool-unix",
+ "navigationBarTextStyle": "@navTextStyle",
+ "backgroundColorContent": "@bgContentColor",
+ "backgroundColor": "@bgColor",
+ "navigationBarBackgroundColor": "@navBgColor"
+ },
+ "tabBar": {
+ "custom": true,
+ "color": "@tabColor",
+ "selectedColor": "@tabSelectedColor",
+ "backgroundColor": "@tabBgColor",
+ "borderStyle": "@tabBorderStyle",
+ "height": "60px",
+ "list": [
+ {
+ "pagePath": "pages/index/home",
+ "iconPath": "/static/icon/tabbar/home.png",
+ "selectedIconPath": "/static/icon/tabbar/home2.png",
+ "text": "首页"
+ },
+ {
+ "pagePath": "pages/index/template",
+ "iconPath": "/static/icon/tabbar/template.png",
+ "selectedIconPath": "/static/icon/tabbar/template2.png",
+ "text": "模板"
+ },
+ {
+ "pagePath": "pages/index/my",
+ "iconPath": "/static/icon/tabbar/my.png",
+ "selectedIconPath": "/static/icon/tabbar/my2.png",
+ "text": "我的"
+ }
+ ]
+ },
+ "uniIdRouter": {}
+}
diff --git a/cool-unix/pages/advice/index.uvue b/cool-unix/pages/advice/index.uvue
new file mode 100644
index 0000000..b21fdc8
--- /dev/null
+++ b/cool-unix/pages/advice/index.uvue
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ 范围:
+ 周
+ 月
+
+
+
+
+
+
+ 周起始(周一):
+
+
+
+
+
+ 月份(YYYY-MM):
+
+
+
+
+
+ 刷新
+
+
+
+ 加载中...
+
+ {{ adviceText }}
+ {{ emptyText }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/dailyreport/detail.uvue b/cool-unix/pages/dailyreport/detail.uvue
new file mode 100644
index 0000000..15afc8a
--- /dev/null
+++ b/cool-unix/pages/dailyreport/detail.uvue
@@ -0,0 +1,222 @@
+
+
+
+
+
+
+
+
+
+
+ {{ formatDate(report.reportDate) }}
+
+ {{ report.status === 1 ? '已提交' : '草稿' }}
+
+
+
+ {{ report.inputType === 1 ? "🎤 语音输入" : "⌨️ 文字输入" }} ·
+ {{ report.submitTime ? ('提交于 ' + formatDateTime(report.submitTime)) : ('创建于 ' + formatDateTime(report.createTime)) }}
+
+
+
+
+
+ 📝 日报内容
+
+ {{ report.userEditedContent || "暂无内容" }}
+
+
+
+
+
+
+
+
+ {{ report.originalText }}
+
+
+
+
+
+
+ {{ report.aiFormattedContent }}
+
+
+
+
+
+
+
+ 编辑日报
+
+
+ {{ isSubmitting ? "提交中..." : "提交日报" }}
+
+
+
+
+
+ 📝
+ 日报不存在
+
+ 返回列表
+
+
+
+
+
+
diff --git a/cool-unix/pages/dailyreport/list.uvue b/cool-unix/pages/dailyreport/list.uvue
new file mode 100644
index 0000000..0723778
--- /dev/null
+++ b/cool-unix/pages/dailyreport/list.uvue
@@ -0,0 +1,327 @@
+
+
+
+
+
+
+ 全部
+
+
+ 草稿
+
+
+ 已提交
+
+
+
+
+
+
+
+
+ 加载中...
+
+
+
+
+
+
+
+
+ {{ formatDate(item.reportDate) }}
+
+ {{ formatWeekday(item.reportDate) }}
+
+
+
+ {{ item.status === 1 ? "已提交" : "草稿" }}
+
+
+
+
+
+
+ {{ getContentPreview(item.userEditedContent) }}
+
+
+
+
+
+
+ {{ item.inputType === 1 ? "🎤 语音输入" : "⌨️ 文字输入" }}
+
+
+ 提交于 {{ formatTime(item.submitTime) }}
+
+
+ 创建于 {{ formatTime(item.createTime) }}
+
+
+
+
+
+
+ 加载中...
+
+
+ 没有更多了
+
+
+
+
+
+ 📝
+ 暂无日报
+
+ 去提交日报
+
+
+
+
+
+
+
+ ✏️
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/dailyreport/submit.uvue b/cool-unix/pages/dailyreport/submit.uvue
new file mode 100644
index 0000000..39f3cc5
--- /dev/null
+++ b/cool-unix/pages/dailyreport/submit.uvue
@@ -0,0 +1,555 @@
+
+
+
+
+
+ 日报日期
+
+
+
+
+
+ 输入方式
+
+
+ 文字输入
+
+
+ 语音输入
+
+
+
+
+
+
+ 语音录制
+
+
+ 按住按钮开始录音(最长60秒)
+
+ 🎤
+
+
+
+
+ 录音中...
+ {{ recordingTime }}s
+ 取消录音
+
+
+
+ 录音完成
+ 时长: {{ recordingTime }}秒
+
+ 重新录音
+
+ {{ isRecognizing ? '识别中...' : '语音识别' }}
+
+
+
+
+
+
+
+ 识别结果
+
+ {{ recognizedText }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ isFormatting ? 'AI生成中...' : '🤖 AI生成日报' }}
+
+
+
+
+
+ AI生成的日报
+
+
+
+ 您可以在下方编辑最终内容
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ isSavingDraft ? '保存中...' : '保存草稿' }}
+
+
+ {{ isSubmitting ? '提交中...' : '提交日报' }}
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/basic/button.uvue b/cool-unix/pages/demo/basic/button.uvue
new file mode 100644
index 0000000..e1fde5d
--- /dev/null
+++ b/cool-unix/pages/demo/basic/button.uvue
@@ -0,0 +1,133 @@
+
+
+
+
+ {{ t("普通") }}
+
+
+
+
+ {{ t("主要") }}
+ {{ t("成功") }}
+ {{ t("警告") }}
+
+
+
+ {{ t("危险") }}
+ {{ t("信息") }}
+
+
+
+ {{ t("浅色") }}
+ {{ t("深色") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("自定义") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/basic/icon.uvue b/cool-unix/pages/demo/basic/icon.uvue
new file mode 100644
index 0000000..76c0b7d
--- /dev/null
+++ b/cool-unix/pages/demo/basic/icon.uvue
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("集成 iconfont 与 remixicon 图标库,展示部分示例") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/basic/image.uvue b/cool-unix/pages/demo/basic/image.uvue
new file mode 100644
index 0000000..399998d
--- /dev/null
+++ b/cool-unix/pages/demo/basic/image.uvue
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+ aspectFill
+
+
+
+
+ aspectFit
+
+
+
+
+ heightFix
+
+
+
+
+ scaleToFill
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/basic/tag.uvue b/cool-unix/pages/demo/basic/tag.uvue
new file mode 100644
index 0000000..78dd28e
--- /dev/null
+++ b/cool-unix/pages/demo/basic/tag.uvue
@@ -0,0 +1,72 @@
+
+
+
+
+
+ {{ t("标签") }}
+
+
+
+
+
+ {{ t("主要") }}
+ {{ t("成功") }}
+ {{ t("警告") }}
+ {{ t("危险") }}
+ {{ t("信息") }}
+
+
+
+
+
+ {{ t("邮件") }}
+ {{ t("日历") }}
+ {{ t("文件") }}
+
+
+
+
+
+ {{ t("圆角") }}
+
+
+
+
+
+ {{ t("可关闭") }}
+
+
+
+
+
+ {{ t("主要") }}
+ {{ t("成功") }}
+ {{ t("警告") }}
+ {{ t("危险") }}
+ {{ t("信息") }}
+
+
+
+
+
+ {{ t("自定义颜色") }}
+
+ {{ t("自定义无圆角") }}
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/basic/text.uvue b/cool-unix/pages/demo/basic/text.uvue
new file mode 100644
index 0000000..8bafa0a
--- /dev/null
+++ b/cool-unix/pages/demo/basic/text.uvue
@@ -0,0 +1,103 @@
+
+
+
+
+ 云想衣裳花想容,春风拂槛露华浓。
+
+
+
+ 明月松间照,清泉石上流。
+ 举头望明月,低头思故乡。
+ 春眠不觉晓,处处闻啼鸟。
+ 劝君更尽一杯酒,西出阳关无故人。
+ 孤帆远影碧空尽,唯见长江天际流。
+ 大漠孤烟直,长河落日圆。
+
+
+
+ 云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。
+
+
+
+ 云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。天阶夜色凉如水,卧看牵牛织女星。人生若只如初见,何事秋风悲画扇。山有木兮木有枝,心悦君兮君不知。
+
+
+
+ text-xs
+ text-sm
+ text-md
+ text-lg
+ text-xl
+
+
+
+ 20rpx
+ 30rpx
+ 15px
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/components/goods-item.uvue b/cool-unix/pages/demo/components/goods-item.uvue
new file mode 100644
index 0000000..c1fde8f
--- /dev/null
+++ b/cool-unix/pages/demo/components/goods-item.uvue
@@ -0,0 +1,32 @@
+
+
+
+
+ {{ item?.title }}
+
+
+
+
+
diff --git a/cool-unix/pages/demo/components/item.uvue b/cool-unix/pages/demo/components/item.uvue
new file mode 100644
index 0000000..1ceffa2
--- /dev/null
+++ b/cool-unix/pages/demo/components/item.uvue
@@ -0,0 +1,28 @@
+
+
+ {{
+ label
+ }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/components/tips.uvue b/cool-unix/pages/demo/components/tips.uvue
new file mode 100644
index 0000000..a3affe1
--- /dev/null
+++ b/cool-unix/pages/demo/components/tips.uvue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/avatar.uvue b/cool-unix/pages/demo/data/avatar.uvue
new file mode 100644
index 0000000..6fbd7e0
--- /dev/null
+++ b/cool-unix/pages/demo/data/avatar.uvue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/banner.uvue b/cool-unix/pages/demo/data/banner.uvue
new file mode 100644
index 0000000..db10f2f
--- /dev/null
+++ b/cool-unix/pages/demo/data/banner.uvue
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/draggable.uvue b/cool-unix/pages/demo/data/draggable.uvue
new file mode 100644
index 0000000..1dccc18
--- /dev/null
+++ b/cool-unix/pages/demo/data/draggable.uvue
@@ -0,0 +1,217 @@
+
+
+
+
+
+ {{ t("长按项即可拖动排序") }}
+
+
+
+
+
+
+
+ {{ (item as UTSJSONObject).label }}
+
+
+
+
+
+
+
+
+
+ {{ (item as UTSJSONObject).label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ (item as UTSJSONObject).label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/filter-bar.uvue b/cool-unix/pages/demo/data/filter-bar.uvue
new file mode 100644
index 0000000..e7b311c
--- /dev/null
+++ b/cool-unix/pages/demo/data/filter-bar.uvue
@@ -0,0 +1,467 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 筛选
+
+
+
+
+
+
+ {{
+ JSON.stringify(filterForm, null, 4)
+ }}
+
+
+
+ {{
+ JSON.stringify(searchForm, null, 4)
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ~
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("取消") }}
+ {{ t("确定") }}
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/list-view-refresh.uvue b/cool-unix/pages/demo/data/list-view-refresh.uvue
new file mode 100644
index 0000000..d44dfaa
--- /dev/null
+++ b/cool-unix/pages/demo/data/list-view-refresh.uvue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/list-view.uvue b/cool-unix/pages/demo/data/list-view.uvue
new file mode 100644
index 0000000..0f2e0a5
--- /dev/null
+++ b/cool-unix/pages/demo/data/list-view.uvue
@@ -0,0 +1,68 @@
+
+
+
+
+
+ 采用虚拟列表技术实现高性能渲染,支持海量数据无限滚动,当前演示数据规模:{{
+ data.length
+ }}条
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/list.uvue b/cool-unix/pages/demo/data/list.uvue
new file mode 100644
index 0000000..b31c4af
--- /dev/null
+++ b/cool-unix/pages/demo/data/list.uvue
@@ -0,0 +1,120 @@
+
+
+
+
+
+ 神仙都没用
+
+
+
+
+
+ 615206459
+
+
+
+
+
+ 18
+
+
+
+
+
+ 10,9000
+
+
+
+
+
+
+
+
+
+
+
+
+ 云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。
+
+
+
+
+
+
+
+
+
+ {{ t("编辑") }}
+
+
+
+
+
+
+
+ {{ t("删除") }}
+
+
+
+
+
+
+
+ 1234567890
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/marquee.uvue b/cool-unix/pages/demo/data/marquee.uvue
new file mode 100644
index 0000000..6bae830
--- /dev/null
+++ b/cool-unix/pages/demo/data/marquee.uvue
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/pagination.uvue b/cool-unix/pages/demo/data/pagination.uvue
new file mode 100644
index 0000000..c13cde3
--- /dev/null
+++ b/cool-unix/pages/demo/data/pagination.uvue
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("上一页") }}
+
+
+
+ {{ t("下一页") }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/read-more.uvue b/cool-unix/pages/demo/data/read-more.uvue
new file mode 100644
index 0000000..4bdefac
--- /dev/null
+++ b/cool-unix/pages/demo/data/read-more.uvue
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+ 云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。
+ 一枝红艳露凝香,云雨巫山枉断肠。借问汉宫谁得似?可怜飞燕倚新妆。
+ 名花倾国两相欢,常得君王带笑看。解释春风无限恨,沉香亭北倚阑干。
+
+
+
+
+
+
+
+ 云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。
+ 一枝红艳露凝香,云雨巫山枉断肠。借问汉宫谁得似?可怜飞燕倚新妆。
+ 名花倾国两相欢,常得君王带笑看。解释春风无限恨,沉香亭北倚阑干。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。
+ 一枝红艳露凝香,云雨巫山枉断肠。借问汉宫谁得似?可怜飞燕倚新妆。
+
+
+
+
+
+ 名花倾国两相欢,常得君王带笑看。解释春风无限恨,沉香亭北倚阑干。
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/timeline.uvue b/cool-unix/pages/demo/data/timeline.uvue
new file mode 100644
index 0000000..7c7b990
--- /dev/null
+++ b/cool-unix/pages/demo/data/timeline.uvue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("优选灵活配置混合A") }}
+
+ {{ t("1000元起") }}
+
+
+ {{
+ t("立即购买")
+ }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/tree.uvue b/cool-unix/pages/demo/data/tree.uvue
new file mode 100644
index 0000000..3d38537
--- /dev/null
+++ b/cool-unix/pages/demo/data/tree.uvue
@@ -0,0 +1,391 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ checkedKeys.join("、") }}
+
+
+
+
+ {{ t("选中部分节点") }}
+
+
+
+ {{ t("获取选中节点") }}
+
+
+
+ {{ t("获取半选节点") }}
+
+ {{ halfCheckedKeys.join("、") }}
+
+
+
+ {{ t("清空选中") }}
+
+
+
+
+
+ {{ t("展开部分节点") }}
+
+
+
+ {{ t("获取展开节点") }}
+
+ {{ expandedKeys.join("、") }}
+
+
+
+ {{ t("展开所有") }}
+
+
+
+ {{ t("收起所有") }}
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/data/waterfall.uvue b/cool-unix/pages/demo/data/waterfall.uvue
new file mode 100644
index 0000000..70557d5
--- /dev/null
+++ b/cool-unix/pages/demo/data/waterfall.uvue
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+ 广告
+
+
+
+
+ {{ item["title"] }}
+
+
+
+ {{
+ item["likeCount"]
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/feedback/action-sheet.uvue b/cool-unix/pages/demo/feedback/action-sheet.uvue
new file mode 100644
index 0000000..9053127
--- /dev/null
+++ b/cool-unix/pages/demo/feedback/action-sheet.uvue
@@ -0,0 +1,206 @@
+
+
+
+
+ {{ t("打开") }}
+
+
+
+ {{ t("打开") }}
+
+
+
+ {{ t("打开") }}
+
+
+
+ {{ t("打开") }}
+
+
+
+ {{ t("打开") }}
+
+
+
+ {{ t("打开") }}
+
+
+
+
+
+
+
+
+
+
+
+ 开通会员享受更多特权和服务,包括无广告体验、专属客服等
+
+
+
+
+ 请阅读并同意
+ 《会员服务协议》
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/feedback/confirm.uvue b/cool-unix/pages/demo/feedback/confirm.uvue
new file mode 100644
index 0000000..f161fb7
--- /dev/null
+++ b/cool-unix/pages/demo/feedback/confirm.uvue
@@ -0,0 +1,94 @@
+
+
+
+
+ {{ t("打开弹窗") }}
+
+
+
+ {{ t("打开弹窗") }}
+
+
+
+ {{ t("打开弹窗") }}
+
+
+
+ {{ t("打开弹窗") }}
+
+
+
+ {{ t("打开弹窗") }}
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/feedback/popup.uvue b/cool-unix/pages/demo/feedback/popup.uvue
new file mode 100644
index 0000000..fde3238
--- /dev/null
+++ b/cool-unix/pages/demo/feedback/popup.uvue
@@ -0,0 +1,100 @@
+
+
+
+
+ {{ t("打开弹窗") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 春江花月夜, 花草复青青。 江水流不尽, 月光照无情。 夜来风雨急, 愁思满心头。
+ 何时再相见, 共赏月明楼。
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/feedback/toast.uvue b/cool-unix/pages/demo/feedback/toast.uvue
new file mode 100644
index 0000000..b05d922
--- /dev/null
+++ b/cool-unix/pages/demo/feedback/toast.uvue
@@ -0,0 +1,93 @@
+
+
+
+
+ {{ t("打开") }}
+
+
+
+
+ {{ t("顶部") }}
+ {{ t("中间") }}
+ {{ t("底部") }}
+
+
+
+
+
+ {{ t("成功") }}
+ {{ t("失败") }}
+ {{ t("警告") }}
+ {{ t("问题") }}
+ {{ t("禁用") }}
+
+
+
+ {{ t("停止") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("打开") }}
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/calendar.uvue b/cool-unix/pages/demo/form/calendar.uvue
new file mode 100644
index 0000000..3d52908
--- /dev/null
+++ b/cool-unix/pages/demo/form/calendar.uvue
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/cascader.uvue b/cool-unix/pages/demo/form/cascader.uvue
new file mode 100644
index 0000000..e8b861c
--- /dev/null
+++ b/cool-unix/pages/demo/form/cascader.uvue
@@ -0,0 +1,509 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/checkbox.uvue b/cool-unix/pages/demo/form/checkbox.uvue
new file mode 100644
index 0000000..dbc6fc0
--- /dev/null
+++ b/cool-unix/pages/demo/form/checkbox.uvue
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+ 同意并阅读
+ 《用户协议》
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/form.uvue b/cool-unix/pages/demo/form/form.uvue
new file mode 100644
index 0000000..6c29e58
--- /dev/null
+++ b/cool-unix/pages/demo/form/form.uvue
@@ -0,0 +1,381 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ t("添加联系人")
+ }}
+
+
+
+
+
+
+ {{ value }} cm
+
+
+
+
+
+
+
+ {{ value }} kg
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ JSON.stringify(formData, null, 4)
+ }}
+
+
+
+
+
+ {{
+ t("重置")
+ }}
+ {{ t("提交") }}
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/input-number.uvue b/cool-unix/pages/demo/form/input-number.uvue
new file mode 100644
index 0000000..46605d7
--- /dev/null
+++ b/cool-unix/pages/demo/form/input-number.uvue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/input-otp.uvue b/cool-unix/pages/demo/form/input-otp.uvue
new file mode 100644
index 0000000..8e7fdb6
--- /dev/null
+++ b/cool-unix/pages/demo/form/input-otp.uvue
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/input.uvue b/cool-unix/pages/demo/form/input.uvue
new file mode 100644
index 0000000..a82b279
--- /dev/null
+++ b/cool-unix/pages/demo/form/input.uvue
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 设置 hold-keyboard 属性后,清除内容时输入框将保持聚焦状态
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/keyboard.uvue b/cool-unix/pages/demo/form/keyboard.uvue
new file mode 100644
index 0000000..a3a8dbe
--- /dev/null
+++ b/cool-unix/pages/demo/form/keyboard.uvue
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+ {{ t("打开键盘") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("打开键盘") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("打开键盘") }}
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/radio.uvue b/cool-unix/pages/demo/form/radio.uvue
new file mode 100644
index 0000000..daa932f
--- /dev/null
+++ b/cool-unix/pages/demo/form/radio.uvue
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/rate.uvue b/cool-unix/pages/demo/form/rate.uvue
new file mode 100644
index 0000000..0ed7725
--- /dev/null
+++ b/cool-unix/pages/demo/form/rate.uvue
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/select-date.uvue b/cool-unix/pages/demo/form/select-date.uvue
new file mode 100644
index 0000000..0daec28
--- /dev/null
+++ b/cool-unix/pages/demo/form/select-date.uvue
@@ -0,0 +1,286 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("打开选择器") }}
+
+
+
+
+
+
+ {{ form.date5 }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/select-time.uvue b/cool-unix/pages/demo/form/select-time.uvue
new file mode 100644
index 0000000..407295f
--- /dev/null
+++ b/cool-unix/pages/demo/form/select-time.uvue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+ {{ t("打开选择器") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/select.uvue b/cool-unix/pages/demo/form/select.uvue
new file mode 100644
index 0000000..5010c98
--- /dev/null
+++ b/cool-unix/pages/demo/form/select.uvue
@@ -0,0 +1,388 @@
+
+
+
+
+
+
+
+
+
+ {{ t("打开选择器") }}
+
+
+
+
+
+
+
+ {{ t("通过 children 配置多级数据,并使用 column-count 参数指定显示的列数") }}
+
+
+
+
+
+
+ {{ t("打开") }}
+
+
+
+
+ H5 和 APP 端通过 teleport 实现弹窗内的选择器使用,小程序端则通过
+ root-portal 实现。
+
+
+
+
+
+
+
+
+
+ {{ t("绑定值") }}:{{ form.selected4 }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/slider.uvue b/cool-unix/pages/demo/form/slider.uvue
new file mode 100644
index 0000000..e2e08e7
--- /dev/null
+++ b/cool-unix/pages/demo/form/slider.uvue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+ {{ num2[0] }} ~ {{ num2[1] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/switch.uvue b/cool-unix/pages/demo/form/switch.uvue
new file mode 100644
index 0000000..8e51ba5
--- /dev/null
+++ b/cool-unix/pages/demo/form/switch.uvue
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/textarea.uvue b/cool-unix/pages/demo/form/textarea.uvue
new file mode 100644
index 0000000..10ec3ac
--- /dev/null
+++ b/cool-unix/pages/demo/form/textarea.uvue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/form/upload.uvue b/cool-unix/pages/demo/form/upload.uvue
new file mode 100644
index 0000000..9932175
--- /dev/null
+++ b/cool-unix/pages/demo/form/upload.uvue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/layout/collapse.uvue b/cool-unix/pages/demo/layout/collapse.uvue
new file mode 100644
index 0000000..4af3613
--- /dev/null
+++ b/cool-unix/pages/demo/layout/collapse.uvue
@@ -0,0 +1,45 @@
+
+
+
+
+ {{ visible ? t("点击收起") : t("点击展开") }}
+
+
+ 云想衣裳花想容,春风拂槛露华浓,若非群玉山头见,会向瑶台月下逢。
+
+
+
+
+ {{ t("点击展开") }}
+
+
+
+ 云想衣裳花想容,春风拂槛露华浓,若非群玉山头见,会向瑶台月下逢。
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/layout/flex.uvue b/cool-unix/pages/demo/layout/flex.uvue
new file mode 100644
index 0000000..f184acd
--- /dev/null
+++ b/cool-unix/pages/demo/layout/flex.uvue
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/layout/float-view.uvue b/cool-unix/pages/demo/layout/float-view.uvue
new file mode 100644
index 0000000..6b87c44
--- /dev/null
+++ b/cool-unix/pages/demo/layout/float-view.uvue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+ {{ t("禁用状态,无法拖拽") }}
+
+
+
+
+
+
+ {{ t("不吸附边缘,任意位置可拖拽") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/layout/footer.uvue b/cool-unix/pages/demo/layout/footer.uvue
new file mode 100644
index 0000000..61049bc
--- /dev/null
+++ b/cool-unix/pages/demo/layout/footer.uvue
@@ -0,0 +1,63 @@
+
+
+
+
+ 解决底部按钮隐藏时页面底部仍有空白间距
+ 解决固定定位时内容占位缺失
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("取消订单") }}
+
+
+
+ {{ t("立即购买") }}
+
+
+
+
+
+ {{ t("确认收货") }}
+
+
+
+ {{ t("评价") }}
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/layout/sticky.uvue b/cool-unix/pages/demo/layout/sticky.uvue
new file mode 100644
index 0000000..3e729b1
--- /dev/null
+++ b/cool-unix/pages/demo/layout/sticky.uvue
@@ -0,0 +1,44 @@
+
+
+
+
+ Header - 1
+
+
+
+
+
+
+
+
+
+
+
+ Header - 2
+
+
+
+
+
+
+
+
+
+
+
+ Header - 3
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/layout/tabs.uvue b/cool-unix/pages/demo/layout/tabs.uvue
new file mode 100644
index 0000000..bd748d5
--- /dev/null
+++ b/cool-unix/pages/demo/layout/tabs.uvue
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("适用于标签数量不多的情况") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/layout/topbar.uvue b/cool-unix/pages/demo/layout/topbar.uvue
new file mode 100644
index 0000000..0e572aa
--- /dev/null
+++ b/cool-unix/pages/demo/layout/topbar.uvue
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("登录") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/animation.uvue b/cool-unix/pages/demo/other/animation.uvue
new file mode 100644
index 0000000..2704690
--- /dev/null
+++ b/cool-unix/pages/demo/other/animation.uvue
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+ rotate
+
+
+ scale
+
+
+ move
+
+
+ opacity
+
+
+
+
+
+
+
+ fadeIn
+
+
+ fadeOut
+
+
+
+ {{ t("播放动画") }}
+
+
+
+
+
+ slideLeft
+
+
+ slideRight
+
+
+ slideUp
+
+
+ slideDown
+
+
+
+ {{ t("播放动画") }}
+
+
+
+
+
+ zoomIn
+
+
+ zoomOut
+
+
+
+ {{ t("播放动画") }}
+
+
+
+
+
+ rotateIn
+
+
+ flipX
+
+
+ flipY
+
+
+
+ {{ t("播放动画") }}
+
+
+
+
+
+ shake
+
+
+ swing
+
+
+ wobble
+
+
+
+ {{ t("播放动画") }}
+
+
+
+
+
+ rollIn
+
+
+ lightSpeed
+
+
+ ripple
+
+
+
+ {{ t("播放动画") }}
+
+
+
+
+
+ sequence
+
+
+
+ {{ t("播放动画") }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/canvas.uvue b/cool-unix/pages/demo/other/canvas.uvue
new file mode 100644
index 0000000..8e71f26
--- /dev/null
+++ b/cool-unix/pages/demo/other/canvas.uvue
@@ -0,0 +1,233 @@
+
+
+
+
+
+
+ {{ t("预览图片") }}
+
+
+
+ {{ t("保存图片") }}
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/cropper.uvue b/cool-unix/pages/demo/other/cropper.uvue
new file mode 100644
index 0000000..020acdb
--- /dev/null
+++ b/cool-unix/pages/demo/other/cropper.uvue
@@ -0,0 +1,55 @@
+
+
+
+
+ {{ t("选择图片") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/day-uts.uvue b/cool-unix/pages/demo/other/day-uts.uvue
new file mode 100644
index 0000000..2ef7d25
--- /dev/null
+++ b/cool-unix/pages/demo/other/day-uts.uvue
@@ -0,0 +1,50 @@
+
+
+
+
+ format("YYYY-MM-DD HH:mm:ss")
+
+
+
+ add(1, "day")
+
+
+
+ subtract(1, "day")
+
+
+
+ startOf("day")
+
+
+
+ endOf("month")
+
+
+
+ isSame(Date)
+
+
+
+ isBefore(Date)
+
+
+
+ isAfter(Date)
+
+
+
+ diff(Date)
+
+
+
+ diffUnit(Date, "day")
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/qrcode.uvue b/cool-unix/pages/demo/other/qrcode.uvue
new file mode 100644
index 0000000..fa8f53d
--- /dev/null
+++ b/cool-unix/pages/demo/other/qrcode.uvue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("预览") }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/router/index.uvue b/cool-unix/pages/demo/other/router/index.uvue
new file mode 100644
index 0000000..296823e
--- /dev/null
+++ b/cool-unix/pages/demo/other/router/index.uvue
@@ -0,0 +1,41 @@
+
+
+
+
+ {{ t("跳转") }}
+
+
+
+ {{ t("跳转") }}
+
+
+
+ {{ t("跳转") }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/router/query.uvue b/cool-unix/pages/demo/other/router/query.uvue
new file mode 100644
index 0000000..50c79ea
--- /dev/null
+++ b/cool-unix/pages/demo/other/router/query.uvue
@@ -0,0 +1,34 @@
+
+
+
+
+ {{ id ?? "-" }}
+
+
+
+ {{ userInfo?.nickName ?? "-" }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/share.uvue b/cool-unix/pages/demo/other/share.uvue
new file mode 100644
index 0000000..dcfe7d7
--- /dev/null
+++ b/cool-unix/pages/demo/other/share.uvue
@@ -0,0 +1,83 @@
+
+
+
+
+ {{ t("分享文本") }}
+
+
+
+ {{ t("分享图片") }}
+
+
+
+ {{ t("分享文件") }}
+
+
+
+ {{ t("分享链接") }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/sign.uvue b/cool-unix/pages/demo/other/sign.uvue
new file mode 100644
index 0000000..f492e8a
--- /dev/null
+++ b/cool-unix/pages/demo/other/sign.uvue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+ {{ t("清空") }}
+ {{ t("预览") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/slide-verify.uvue b/cool-unix/pages/demo/other/slide-verify.uvue
new file mode 100644
index 0000000..3f8b7d8
--- /dev/null
+++ b/cool-unix/pages/demo/other/slide-verify.uvue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/svg.uvue b/cool-unix/pages/demo/other/svg.uvue
new file mode 100644
index 0000000..b75ee3e
--- /dev/null
+++ b/cool-unix/pages/demo/other/svg.uvue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/vibrate.uvue b/cool-unix/pages/demo/other/vibrate.uvue
new file mode 100644
index 0000000..5eebf7c
--- /dev/null
+++ b/cool-unix/pages/demo/other/vibrate.uvue
@@ -0,0 +1,19 @@
+
+
+
+
+ {{ t("点击触发") }}
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/other/watermark.uvue b/cool-unix/pages/demo/other/watermark.uvue
new file mode 100644
index 0000000..0221ef9
--- /dev/null
+++ b/cool-unix/pages/demo/other/watermark.uvue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+ 明月几时有?把酒问青天。 不知天上宫阙,今夕是何年。
+ 我欲乘风归去,又恐琼楼玉宇,高处不胜寒。 起舞弄清影,何似在人间。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/status/badge.uvue b/cool-unix/pages/demo/status/badge.uvue
new file mode 100644
index 0000000..c96397d
--- /dev/null
+++ b/cool-unix/pages/demo/status/badge.uvue
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("购买") }}
+
+
+
+
+
+
+ {{ t("消息") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/status/countdown.uvue b/cool-unix/pages/demo/status/countdown.uvue
new file mode 100644
index 0000000..8335e25
--- /dev/null
+++ b/cool-unix/pages/demo/status/countdown.uvue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/status/loadmore.uvue b/cool-unix/pages/demo/status/loadmore.uvue
new file mode 100644
index 0000000..40a1b3d
--- /dev/null
+++ b/cool-unix/pages/demo/status/loadmore.uvue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/status/noticebar.uvue b/cool-unix/pages/demo/status/noticebar.uvue
new file mode 100644
index 0000000..e3a2baa
--- /dev/null
+++ b/cool-unix/pages/demo/status/noticebar.uvue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/status/progress-circle.uvue b/cool-unix/pages/demo/status/progress-circle.uvue
new file mode 100644
index 0000000..e2fe920
--- /dev/null
+++ b/cool-unix/pages/demo/status/progress-circle.uvue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/status/progress.uvue b/cool-unix/pages/demo/status/progress.uvue
new file mode 100644
index 0000000..2a846ec
--- /dev/null
+++ b/cool-unix/pages/demo/status/progress.uvue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/status/rolling-number.uvue b/cool-unix/pages/demo/status/rolling-number.uvue
new file mode 100644
index 0000000..1190a0f
--- /dev/null
+++ b/cool-unix/pages/demo/status/rolling-number.uvue
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/demo/status/skeleton.uvue b/cool-unix/pages/demo/status/skeleton.uvue
new file mode 100644
index 0000000..d40d10d
--- /dev/null
+++ b/cool-unix/pages/demo/status/skeleton.uvue
@@ -0,0 +1,61 @@
+
+
+
+
+
+ 云想衣裳花想容,春风拂槛露华浓。
+
+
+
+
+
+
+ 立即购买
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/index/home.uvue b/cool-unix/pages/index/home.uvue
new file mode 100644
index 0000000..c2a493d
--- /dev/null
+++ b/cool-unix/pages/index/home.uvue
@@ -0,0 +1,522 @@
+
+
+
+
+
+
+
+
+
+ {{ config.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}({{ item.children?.length ?? 0 }})
+
+
+
+
+
+
+
+ {{ child.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/index/my.uvue b/cool-unix/pages/index/my.uvue
new file mode 100644
index 0000000..5bff20f
--- /dev/null
+++ b/cool-unix/pages/index/my.uvue
@@ -0,0 +1,324 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ userInfo?.nickName ?? t("未登录")
+ }}
+ {{ userInfo?.phone }}
+
+
+
+
+
+
+
+ {{
+ t("总点击")
+ }}
+
+
+
+
+
+
+ {{
+ t("赞")
+ }}
+
+
+
+
+
+
+ {{
+ t("收藏")
+ }}
+
+
+
+
+
+
+ {{
+ t("粉丝")
+ }}
+
+
+
+
+
+
+
+
+ {{ t("接单模式") }}
+ {{
+ t("已关闭")
+ }}
+
+
+
+
+
+
+
+
+
+ {{ t("消息通知") }}
+ {{
+ t("已关闭")
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("待支付") }}
+
+
+
+
+
+
+ {{ t("未发货") }}
+
+
+
+
+
+
+ {{ t("已发货") }}
+
+
+
+
+
+
+
+
+ {{ t("售后 / 退款") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/index/template.uvue b/cool-unix/pages/index/template.uvue
new file mode 100644
index 0000000..9921231
--- /dev/null
+++ b/cool-unix/pages/index/template.uvue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/monthlyreport/detail.uvue b/cool-unix/pages/monthlyreport/detail.uvue
new file mode 100644
index 0000000..deae08c
--- /dev/null
+++ b/cool-unix/pages/monthlyreport/detail.uvue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+ {{ report.month || '-' }}
+
+ {{ report.submitTime ? ('\u63D0\u4EA4\u4E8E ' + formatDateTime(report.submitTime)) : (report.createTime ? ('\u521B\u5EFA\u4E8E ' + formatDateTime(report.createTime)) : '') }}
+
+
+
+
+ {{ '\u6708\u62A5\u5185\u5BB9' }}
+
+ {{ report.userEditedContent || report.aiFormattedContent || report.originalText || '\u6682\u65E0\u5185\u5BB9' }}
+
+
+
+
+ {{ '\u539F\u59CB\u8F93\u5165\u5185\u5BB9' }}
+
+ {{ report.originalText }}
+
+
+
+
+ {{ 'AI\u751F\u6210\u5185\u5BB9' }}
+
+ {{ report.aiFormattedContent }}
+
+
+
+
+
+ {{ '\uD83D\uDCC5' }}
+ {{ '\u6708\u62A5\u4E0D\u5B58\u5728' }}
+ {{ '\u8FD4\u56DE\u5217\u8868' }}
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/monthlyreport/list.uvue b/cool-unix/pages/monthlyreport/list.uvue
new file mode 100644
index 0000000..2984348
--- /dev/null
+++ b/cool-unix/pages/monthlyreport/list.uvue
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+ 刷新
+
+
+
+
+
+
+
+ {{ item.month }}
+
+ {{ item.status === 1 ? "已提交" : "草稿" }}
+
+
+ {{ brief(item.userEditedContent || item.aiFormattedContent || item.originalText) }}
+
+ 提交于 {{ formatTime(item.submitTime) }}
+ 创建于 {{ formatTime(item.createTime) }}
+
+
+
+ 加载中...
+
+
+ 没有更多了
+
+
+
+ 📅
+ 暂无月报
+
+ 去提交月报
+
+
+
+
+
+
+
+ ✏️
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/monthlyreport/submit.uvue b/cool-unix/pages/monthlyreport/submit.uvue
new file mode 100644
index 0000000..339b0f9
--- /dev/null
+++ b/cool-unix/pages/monthlyreport/submit.uvue
@@ -0,0 +1,173 @@
+
+
+
+
+
+ 月份
+
+
+
+
+
+ 工作内容(可选)
+
+
+
+
+
+
+ {{ isGenerating ? '生成中...' : '🧩 从我的周报生成' }}
+
+
+
+
+
+
+ {{ isFormatting ? 'AI生成中...' : '🤖 AI格式化' }}
+
+
+
+
+
+ AI生成的月报
+
+
+
+
+
+
+ 保存草稿
+ 提交
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/set/about.uvue b/cool-unix/pages/set/about.uvue
new file mode 100644
index 0000000..d8c1b2c
--- /dev/null
+++ b/cool-unix/pages/set/about.uvue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+ {{ config.name }}
+ version {{ config.version }}
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/set/cs.uvue b/cool-unix/pages/set/cs.uvue
new file mode 100644
index 0000000..a3af743
--- /dev/null
+++ b/cool-unix/pages/set/cs.uvue
@@ -0,0 +1,39 @@
+
+
+
+ 我们期待与您携手,共同探索技术的边界,共同推动技术的进步
+
+
+
+
+
+
+ 保存图片
+
+
+
+
+
+
diff --git a/cool-unix/pages/set/general.uvue b/cool-unix/pages/set/general.uvue
new file mode 100644
index 0000000..4235d86
--- /dev/null
+++ b/cool-unix/pages/set/general.uvue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/set/index.uvue b/cool-unix/pages/set/index.uvue
new file mode 100644
index 0000000..b32dbcb
--- /dev/null
+++ b/cool-unix/pages/set/index.uvue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("退出登录") }}
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/set/notice.uvue b/cool-unix/pages/set/notice.uvue
new file mode 100644
index 0000000..d03ee0b
--- /dev/null
+++ b/cool-unix/pages/set/notice.uvue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/template/post/detail.uvue b/cool-unix/pages/template/post/detail.uvue
new file mode 100644
index 0000000..610a94a
--- /dev/null
+++ b/cool-unix/pages/template/post/detail.uvue
@@ -0,0 +1,399 @@
+
+
+
+
+
+
+ 神仙都没用
+
+ 立即关注
+
+
+
+
+
+
+
+
+
+
+ ❄️ 雪地旅行商务团价格表
+
+
+ 对于不想做攻略的小伙伴来说定制团真的是最佳选择。雪地自驾没有经验的真心不建议。费用清晰明了。预算很准确,收费很合理。
+
+
+
+
+ 哈尔滨 · 圣 · 索菲亚教堂
+
+
+
+ 编辑于 2天前
+
+
+
+
+ 共 10 条评论
+
+
+
+
+
+
+ 说点什么...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ item.name
+ }}
+
+ 作者
+
+
+
+ {{ item.content }}
+
+
+
+
+ {{ item.time }}
+
+
+ 回复
+
+
+
+
+
+
+
+
+ {{
+ reply.name
+ }}
+
+ 作者
+
+
+ {{
+ reply.content
+ }}
+
+
+
+ {{ reply.time }}
+
+
+ 回复
+
+
+ 展开 1 条回复
+
+
+
+
+
+
+
+
+
+
+
+
+ 说点什么...
+
+
+
+
+
+ 700
+
+
+
+
+ 59
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 发送
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/template/shop/address-edit.uvue b/cool-unix/pages/template/shop/address-edit.uvue
new file mode 100644
index 0000000..b441d7e
--- /dev/null
+++ b/cool-unix/pages/template/shop/address-edit.uvue
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("保存") }}
+
+
+
+
+
diff --git a/cool-unix/pages/template/shop/address.uvue b/cool-unix/pages/template/shop/address.uvue
new file mode 100644
index 0000000..e5b6452
--- /dev/null
+++ b/cool-unix/pages/template/shop/address.uvue
@@ -0,0 +1,221 @@
+
+
+
+
+
+ {{ item.province }} {{ item.city }} {{ item.district }}
+
+ {{ item.address }}
+
+
+ {{ item.contact }}
+ {{
+ item.phone
+ }}
+
+
+
+
+ {{ item.isDefault ? t("已设为默认") : t("设为默认") }}
+
+
+
+ {{ t("删除") }}
+
+
+
+
+ {{ t("修改") }}
+
+
+
+
+
+
+
+
+ {{ t("添加地址") }}
+
+
+
+
+
diff --git a/cool-unix/pages/template/shop/goods-category.uvue b/cool-unix/pages/template/shop/goods-category.uvue
new file mode 100644
index 0000000..5e0f8cc
--- /dev/null
+++ b/cool-unix/pages/template/shop/goods-category.uvue
@@ -0,0 +1,335 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+ {{ goods.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/template/shop/goods-detail/comment.uvue b/cool-unix/pages/template/shop/goods-detail/comment.uvue
new file mode 100644
index 0000000..7fcb237
--- /dev/null
+++ b/cool-unix/pages/template/shop/goods-detail/comment.uvue
@@ -0,0 +1,81 @@
+
+
+
+ 买家评论 78
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+ {{
+ item.time
+ }}
+
+
+ {{
+ item.content
+ }}
+
+
+
+
+
+
+ +3
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/template/shop/goods-detail/desc.uvue b/cool-unix/pages/template/shop/goods-detail/desc.uvue
new file mode 100644
index 0000000..68cae6c
--- /dev/null
+++ b/cool-unix/pages/template/shop/goods-detail/desc.uvue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/template/shop/goods-detail/index.uvue b/cool-unix/pages/template/shop/goods-detail/index.uvue
new file mode 100644
index 0000000..e672abd
--- /dev/null
+++ b/cool-unix/pages/template/shop/goods-detail/index.uvue
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已选:黑色 128GB + 碎屏险
+
+
+
+
+
+
+
+
+
+ 预计11月1日 周三 送达
+ 深圳益田假日广场
+
+
+
+
+
+
+
+ 7天无理由退货 · 正品保证 · 极速发货 · 无忧售后
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 收藏
+
+
+
+
+ 购物车
+
+
+
+
+
+ 加入购物车
+ 立即购买
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/template/shop/goods-detail/info.uvue b/cool-unix/pages/template/shop/goods-detail/info.uvue
new file mode 100644
index 0000000..122ff10
--- /dev/null
+++ b/cool-unix/pages/template/shop/goods-detail/info.uvue
@@ -0,0 +1,34 @@
+
+
+ Apple/苹果 iPhone 15 (A3092) 128GB 黑色 支持移动联通电信5G 双卡双待手机
+
+
+
+ ¥
+
+
+
+
+ 已售 100 件
+
+
+
+ 满199减50
+ 满299减100
+
+
+
+
+
diff --git a/cool-unix/pages/template/shop/goods-detail/topbar.uvue b/cool-unix/pages/template/shop/goods-detail/topbar.uvue
new file mode 100644
index 0000000..54025fb
--- /dev/null
+++ b/cool-unix/pages/template/shop/goods-detail/topbar.uvue
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/template/shop/shopping-cart.uvue b/cool-unix/pages/template/shop/shopping-cart.uvue
new file mode 100644
index 0000000..f728e20
--- /dev/null
+++ b/cool-unix/pages/template/shop/shopping-cart.uvue
@@ -0,0 +1,416 @@
+
+
+
+
+
+
+
+ {{ isDel ? t("完成") : t("管理") }}
+
+
+
+
+
+
+
+ {{ isDel ? t("完成") : t("管理") }}
+
+
+
+
+
+
+
+
+ 🔥 最新降价商品,限时优惠,抓紧抢购!
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+ {{ item.skuName }}
+
+
+
+
+
+ ¥
+ {{ item.price }}
+
+
+
+
+
+
+
+
+
+
+ 比加入时降¥100
+
+ 满1件可换购0.5元商品
+
+
+
+
+ {{ t("删除") }}
+
+
+
+
+
+
+
+
+ {{ t("全选") }}
+
+
+
+ {{ t("删除") }}
+
+
+
+
+
+ {{ t("合计") }}
+
+
+
+
+ {{ t("去结算") }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/template/types/index.ts b/cool-unix/pages/template/types/index.ts
new file mode 100644
index 0000000..6112d33
--- /dev/null
+++ b/cool-unix/pages/template/types/index.ts
@@ -0,0 +1,10 @@
+export type UserAddress = {
+ id?: number;
+ contact: string;
+ phone: string;
+ province: string;
+ city: string;
+ district: string;
+ address: string;
+ isDefault: boolean;
+};
diff --git a/cool-unix/pages/user/components/login/phone.uvue b/cool-unix/pages/user/components/login/phone.uvue
new file mode 100644
index 0000000..0adced0
--- /dev/null
+++ b/cool-unix/pages/user/components/login/phone.uvue
@@ -0,0 +1,134 @@
+
+
+ {{ t("手机登录") }}
+ {{
+ t("未注册的手机号登录成功后将自动注册")
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("登录") }}
+
+
+
+
+
diff --git a/cool-unix/pages/user/components/login/wx.uvue b/cool-unix/pages/user/components/login/wx.uvue
new file mode 100644
index 0000000..751e3aa
--- /dev/null
+++ b/cool-unix/pages/user/components/login/wx.uvue
@@ -0,0 +1,242 @@
+
+
+
+
+ {{ t("为提供更好的服务,我们邀请您填写昵称、头像等公开信息") }}
+
+
+
+ {{ t("头像") }}
+
+
+
+
+
+
+
+
+
+ {{ t("昵称") }}
+
+
+
+
+
+ {{ t("取消") }}
+ {{ t("确认") }}
+
+
+
+
+
+
diff --git a/cool-unix/pages/user/edit-description.uvue b/cool-unix/pages/user/edit-description.uvue
new file mode 100644
index 0000000..1871547
--- /dev/null
+++ b/cool-unix/pages/user/edit-description.uvue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+ {{
+ t("确认")
+ }}
+
+
+
+
+
diff --git a/cool-unix/pages/user/edit-name.uvue b/cool-unix/pages/user/edit-name.uvue
new file mode 100644
index 0000000..a263164
--- /dev/null
+++ b/cool-unix/pages/user/edit-name.uvue
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+ {{ content.length }}/20
+
+
+
+
+ {{
+ t("请设置2-20个字符,不包括@<>/等无效字符")
+ }}
+
+
+
+
+ {{
+ t("确认")
+ }}
+
+
+
+
+
diff --git a/cool-unix/pages/user/edit.uvue b/cool-unix/pages/user/edit.uvue
new file mode 100644
index 0000000..2d97f32
--- /dev/null
+++ b/cool-unix/pages/user/edit.uvue
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ userInfo?.nickName }}
+
+
+ {{ userInfo?.phone }}
+
+
+
+
+
+ {{
+ t("介绍一下自己")
+ }}
+ {{ userInfo?.description }}
+
+
+
+
+
+ {{ genderText }}
+ {{ t("编辑性别") }}
+
+
+
+ {{ userInfo?.birthday }}
+ {{
+ t("选择生日")
+ }}
+
+
+
+ {{ regionText }}
+ {{
+ t("选择所在的地区")
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/user/login.uvue b/cool-unix/pages/user/login.uvue
new file mode 100644
index 0000000..fd0f4e2
--- /dev/null
+++ b/cool-unix/pages/user/login.uvue
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ config.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ t("已阅读并同意")
+ }}
+
+ 《{{ t("用户协议") }}》
+
+ 、
+
+ 《{{ t("隐私政策") }}》
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/user/types/index.ts b/cool-unix/pages/user/types/index.ts
new file mode 100644
index 0000000..ba6722a
--- /dev/null
+++ b/cool-unix/pages/user/types/index.ts
@@ -0,0 +1,4 @@
+export type LoginForm = {
+ phone: string;
+ smsCode: string;
+};
diff --git a/cool-unix/pages/weeklyreport/detail.uvue b/cool-unix/pages/weeklyreport/detail.uvue
new file mode 100644
index 0000000..7cc9ec8
--- /dev/null
+++ b/cool-unix/pages/weeklyreport/detail.uvue
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+ {{ formatWeekRange(report.weekStartDate, report.weekEndDate) }}
+ {{ report.status === 1 ? '\u5DF2\u63D0\u4EA4' : '\u8349\u7A3F' }}
+
+ {{ report.submitTime ? ('\u63D0\u4EA4\u4E8E ' + formatDateTime(report.submitTime)) : ('\u521B\u5EFA\u4E8E ' + formatDateTime(report.createTime)) }}
+
+
+
+
+ {{ '\u5468\u62A5\u5185\u5BB9' }}
+
+ {{ report.userEditedContent || '\u6682\u65E0\u5185\u5BB9' }}
+
+
+
+
+
+ {{ '\u539F\u59CB\u8F93\u5165\u5185\u5BB9' }}
+
+ {{ report.originalText }}
+
+
+
+
+ {{ 'AI\u751F\u6210\u5185\u5BB9' }}
+
+ {{ report.aiFormattedContent }}
+
+
+
+
+
+ {{ '\u7F16\u8F91\u5468\u62A5' }}
+ {{ isSubmitting ? '\u63D0\u4EA4\u4E2D...' : '\u63D0\u4EA4\u5468\u62A5' }}
+
+
+
+
+ {{ '\u270F\uFE0F' }}
+ {{ '\u5468\u62A5\u4E0D\u5B58\u5728' }}
+ {{ '\u8FD4\u56DE\u5217\u8868' }}
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/weeklyreport/list.uvue b/cool-unix/pages/weeklyreport/list.uvue
new file mode 100644
index 0000000..5af5f66
--- /dev/null
+++ b/cool-unix/pages/weeklyreport/list.uvue
@@ -0,0 +1,323 @@
+
+
+
+
+
+
+ 全部
+
+
+ 草稿
+
+
+ 已提交
+
+
+
+
+
+
+
+
+ 加载中...
+
+
+
+
+
+
+
+
+
+ {{ formatWeekRange(item.weekStartDate, item.weekEndDate) }}
+
+
+
+ {{ item.status === 1 ? "已提交" : "草稿" }}
+
+
+
+
+
+
+ {{ getContentPreview(item.userEditedContent) }}
+
+
+
+
+
+
+ {{ item.inputType === 1 ? "🎤 语音输入" : "⌨️ 文字输入" }}
+
+
+ 提交于 {{ formatTime(item.submitTime) }}
+
+
+ 创建于 {{ formatTime(item.createTime) }}
+
+
+
+
+
+
+ 加载中...
+
+
+ 没有更多了
+
+
+
+
+
+ 📝
+ 暂无周报
+
+ 去提交周报
+
+
+
+
+
+
+
+ ✏️
+
+
+
+
+
+
+
+
diff --git a/cool-unix/pages/weeklyreport/submit.uvue b/cool-unix/pages/weeklyreport/submit.uvue
new file mode 100644
index 0000000..72348a3
--- /dev/null
+++ b/cool-unix/pages/weeklyreport/submit.uvue
@@ -0,0 +1,512 @@
+
+
+
+
+
+ 周报周期
+
+
+ 至
+
+
+
+
+ 设置为本周
+
+
+
+
+
+
+ 输入方式
+
+
+ 文字输入
+
+
+ 语音输入
+
+
+
+
+
+
+ 语音录制
+
+ 语音录制功能暂未在H5环境实现
+ 请切换到文字输入
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ isFormatting ? 'AI生成中...' : '🤖 AI生成周报' }}
+
+
+
+
+
+ AI生成的周报
+
+
+
+ 您可以在下方编辑最终内容
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ isGenerating ? '生成中..' : '📝 从我的日报生成' }}
+
+
+
+
+
+
+ {{ isSavingDraft ? '保存中...' : '保存草稿' }}
+
+
+ {{ isSubmitting ? '提交中...' : '提交周报' }}
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/platformConfig.json b/cool-unix/platformConfig.json
new file mode 100644
index 0000000..a85558f
--- /dev/null
+++ b/cool-unix/platformConfig.json
@@ -0,0 +1,3 @@
+{
+ "targets": ["APP-ANDROID"]
+}
diff --git a/cool-unix/pnpm-lock.yaml b/cool-unix/pnpm-lock.yaml
new file mode 100644
index 0000000..de5b73a
--- /dev/null
+++ b/cool-unix/pnpm-lock.yaml
@@ -0,0 +1,2536 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ hammer-touchemulator:
+ specifier: ^0.0.2
+ version: 0.0.2
+ vue:
+ specifier: ^3.5.13
+ version: 3.5.17
+ weixin-js-sdk:
+ specifier: ^1.6.5
+ version: 1.6.5
+ devDependencies:
+ '@babel/parser':
+ specifier: ^7.27.5
+ version: 7.28.0
+ '@babel/types':
+ specifier: ^7.27.6
+ version: 7.28.1
+ '@cool-vue/ai':
+ specifier: ^1.1.7
+ version: 1.1.7
+ '@cool-vue/vite-plugin':
+ specifier: ^8.2.18
+ version: 8.2.18
+ '@dcloudio/types':
+ specifier: ^3.4.16
+ version: 3.4.16
+ '@types/node':
+ specifier: ^24.0.15
+ version: 24.0.15
+ '@vue/compiler-sfc':
+ specifier: ^3.5.16
+ version: 3.5.17
+ '@vue/tsconfig':
+ specifier: ^0.7.0
+ version: 0.7.0(vue@3.5.17)
+ adm-zip:
+ specifier: ^0.5.16
+ version: 0.5.16
+ autoprefixer:
+ specifier: ^10.4.21
+ version: 10.4.21(postcss@8.5.6)
+ postcss:
+ specifier: ^8.5.3
+ version: 8.5.6
+ prettier:
+ specifier: ^3.5.3
+ version: 3.6.2
+ tailwindcss:
+ specifier: 3.4.17
+ version: 3.4.17
+ vite:
+ specifier: ^6.3.5
+ version: 6.3.5(@types/node@24.0.15)(jiti@1.21.7)(yaml@2.8.0)
+
+packages:
+
+ '@alloc/quick-lru@5.2.0':
+ resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
+ engines: {node: '>=10'}
+
+ '@babel/helper-string-parser@7.27.1':
+ resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.27.1':
+ resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.28.0':
+ resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/types@7.28.1':
+ resolution: {integrity: sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@cool-vue/ai@1.1.7':
+ resolution: {integrity: sha512-zXjuydK6Rzfywr69bR9qnWueS09rqfuv4bbVKSntnHnApqpb6Dow7yOcR+CwzaCkSYJCnbM2DG2Wc0ZDQQe1oQ==}
+ hasBin: true
+
+ '@cool-vue/vite-plugin@8.2.18':
+ resolution: {integrity: sha512-CEeYaPxV/5dPjSxf4pMaS9WAJF0+YhCjqnP9IGCxjaTxRRyWlf+2QpMpgG1JnVBcs6pkZXoyP0Os3ULf1O96Bw==}
+
+ '@dcloudio/types@3.4.16':
+ resolution: {integrity: sha512-gJIr1OWtePTDDdjtp8Kh72S/ZGLunoSfHiUvRtXhBmAFNkDWuAKFO90hv62k3GYN/st04xUBQNtBfvhu/YHjww==}
+
+ '@esbuild/aix-ppc64@0.25.8':
+ resolution: {integrity: sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.25.8':
+ resolution: {integrity: sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.25.8':
+ resolution: {integrity: sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.25.8':
+ resolution: {integrity: sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.25.8':
+ resolution: {integrity: sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.25.8':
+ resolution: {integrity: sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.25.8':
+ resolution: {integrity: sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.25.8':
+ resolution: {integrity: sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.25.8':
+ resolution: {integrity: sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.25.8':
+ resolution: {integrity: sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.25.8':
+ resolution: {integrity: sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.25.8':
+ resolution: {integrity: sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.25.8':
+ resolution: {integrity: sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.25.8':
+ resolution: {integrity: sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.25.8':
+ resolution: {integrity: sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.25.8':
+ resolution: {integrity: sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.25.8':
+ resolution: {integrity: sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.25.8':
+ resolution: {integrity: sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.25.8':
+ resolution: {integrity: sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.25.8':
+ resolution: {integrity: sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.25.8':
+ resolution: {integrity: sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.25.8':
+ resolution: {integrity: sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.25.8':
+ resolution: {integrity: sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.25.8':
+ resolution: {integrity: sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.25.8':
+ resolution: {integrity: sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.25.8':
+ resolution: {integrity: sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
+ '@isaacs/balanced-match@4.0.1':
+ resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
+ engines: {node: 20 || >=22}
+
+ '@isaacs/brace-expansion@5.0.0':
+ resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==}
+ engines: {node: 20 || >=22}
+
+ '@isaacs/cliui@8.0.2':
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+
+ '@jridgewell/gen-mapping@0.3.12':
+ resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/sourcemap-codec@1.5.4':
+ resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==}
+
+ '@jridgewell/trace-mapping@0.3.29':
+ resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@pkgjs/parseargs@0.11.0':
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+
+ '@rollup/rollup-android-arm-eabi@4.45.1':
+ resolution: {integrity: sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.45.1':
+ resolution: {integrity: sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.45.1':
+ resolution: {integrity: sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.45.1':
+ resolution: {integrity: sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.45.1':
+ resolution: {integrity: sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.45.1':
+ resolution: {integrity: sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.45.1':
+ resolution: {integrity: sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.45.1':
+ resolution: {integrity: sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==}
+ cpu: [arm]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-arm64-gnu@4.45.1':
+ resolution: {integrity: sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-arm64-musl@4.45.1':
+ resolution: {integrity: sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-loongarch64-gnu@4.45.1':
+ resolution: {integrity: sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==}
+ cpu: [loong64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.45.1':
+ resolution: {integrity: sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.45.1':
+ resolution: {integrity: sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-riscv64-musl@4.45.1':
+ resolution: {integrity: sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-s390x-gnu@4.45.1':
+ resolution: {integrity: sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-x64-gnu@4.45.1':
+ resolution: {integrity: sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-x64-musl@4.45.1':
+ resolution: {integrity: sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-win32-arm64-msvc@4.45.1':
+ resolution: {integrity: sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.45.1':
+ resolution: {integrity: sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.45.1':
+ resolution: {integrity: sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==}
+ cpu: [x64]
+ os: [win32]
+
+ '@trysound/sax@0.2.0':
+ resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
+ engines: {node: '>=10.13.0'}
+
+ '@types/estree@1.0.8':
+ resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+ '@types/node@24.0.15':
+ resolution: {integrity: sha512-oaeTSbCef7U/z7rDeJA138xpG3NuKc64/rZ2qmUFkFJmnMsAPaluIifqyWd8hSSMxyP9oie3dLAqYPblag9KgA==}
+
+ '@vue/compiler-core@3.5.17':
+ resolution: {integrity: sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==}
+
+ '@vue/compiler-dom@3.5.17':
+ resolution: {integrity: sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==}
+
+ '@vue/compiler-sfc@3.5.17':
+ resolution: {integrity: sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==}
+
+ '@vue/compiler-ssr@3.5.17':
+ resolution: {integrity: sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==}
+
+ '@vue/reactivity@3.5.17':
+ resolution: {integrity: sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==}
+
+ '@vue/runtime-core@3.5.17':
+ resolution: {integrity: sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==}
+
+ '@vue/runtime-dom@3.5.17':
+ resolution: {integrity: sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==}
+
+ '@vue/server-renderer@3.5.17':
+ resolution: {integrity: sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==}
+ peerDependencies:
+ vue: 3.5.17
+
+ '@vue/shared@3.5.17':
+ resolution: {integrity: sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==}
+
+ '@vue/tsconfig@0.7.0':
+ resolution: {integrity: sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==}
+ peerDependencies:
+ typescript: 5.x
+ vue: ^3.4.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ vue:
+ optional: true
+
+ adm-zip@0.5.16:
+ resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==}
+ engines: {node: '>=12.0'}
+
+ ansi-escapes@4.3.2:
+ resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
+ engines: {node: '>=8'}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-regex@6.1.0:
+ resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
+ engines: {node: '>=12'}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
+ ansi-styles@6.2.1:
+ resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+ engines: {node: '>=12'}
+
+ any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
+ anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+
+ arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+
+ asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+ autoprefixer@10.4.21:
+ resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+
+ axios@1.10.0:
+ resolution: {integrity: sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==}
+
+ balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
+ binary-extensions@2.3.0:
+ resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
+ engines: {node: '>=8'}
+
+ bl@4.1.0:
+ resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
+
+ boolbase@1.0.0:
+ resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+
+ brace-expansion@2.0.2:
+ resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
+
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
+ browserslist@4.25.1:
+ resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ buffer@5.7.1:
+ resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+
+ call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+
+ camelcase-css@2.0.1:
+ resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
+ engines: {node: '>= 6'}
+
+ caniuse-lite@1.0.30001727:
+ resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==}
+
+ chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+
+ chalk@5.4.1:
+ resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+
+ chardet@0.7.0:
+ resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
+
+ chokidar@3.6.0:
+ resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
+ engines: {node: '>= 8.10.0'}
+
+ cli-cursor@3.1.0:
+ resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
+ engines: {node: '>=8'}
+
+ cli-cursor@5.0.0:
+ resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
+ engines: {node: '>=18'}
+
+ cli-spinners@2.9.2:
+ resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
+ engines: {node: '>=6'}
+
+ cli-width@3.0.0:
+ resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
+ engines: {node: '>= 10'}
+
+ clone@1.0.4:
+ resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
+ engines: {node: '>=0.8'}
+
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+
+ commander@11.1.0:
+ resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
+ engines: {node: '>=16'}
+
+ commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+
+ commander@7.2.0:
+ resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+ engines: {node: '>= 10'}
+
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+
+ css-select@5.2.2:
+ resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==}
+
+ css-tree@2.2.1:
+ resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
+
+ css-tree@2.3.1:
+ resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
+
+ css-what@6.2.2:
+ resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
+ engines: {node: '>= 6'}
+
+ cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ csso@5.0.5:
+ resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
+
+ csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ defaults@1.0.4:
+ resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
+
+ delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+
+ didyoumean@1.2.2:
+ resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
+
+ dlv@1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+
+ dom-serializer@2.0.0:
+ resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
+
+ domelementtype@2.3.0:
+ resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+
+ domhandler@5.0.3:
+ resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
+ engines: {node: '>= 4'}
+
+ domutils@3.2.2:
+ resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
+
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
+ eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+ electron-to-chromium@1.5.187:
+ resolution: {integrity: sha512-cl5Jc9I0KGUoOoSbxvTywTa40uspGJt/BDBoDLoxJRSBpWh4FFXBsjNRHfQrONsV/OoEjDfHUmZQa2d6Ze4YgA==}
+
+ emoji-regex@10.4.0:
+ resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==}
+
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+ emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
+ entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+
+ es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+ engines: {node: '>= 0.4'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es-object-atoms@1.1.1:
+ resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
+ engines: {node: '>= 0.4'}
+
+ es-set-tostringtag@2.1.0:
+ resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
+ engines: {node: '>= 0.4'}
+
+ esbuild@0.25.8:
+ resolution: {integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ escape-string-regexp@1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+
+ estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
+ external-editor@3.1.0:
+ resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
+ engines: {node: '>=4'}
+
+ fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
+ engines: {node: '>=8.6.0'}
+
+ fastq@1.19.1:
+ resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
+
+ fdir@6.4.6:
+ resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ figures@3.2.0:
+ resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
+ engines: {node: '>=8'}
+
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
+ follow-redirects@1.15.9:
+ resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+
+ foreground-child@3.3.1:
+ resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
+ engines: {node: '>=14'}
+
+ form-data@4.0.4:
+ resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==}
+ engines: {node: '>= 6'}
+
+ fraction.js@4.3.7:
+ resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ get-east-asian-width@1.3.0:
+ resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==}
+ engines: {node: '>=18'}
+
+ get-intrinsic@1.3.0:
+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+ engines: {node: '>= 0.4'}
+
+ get-proto@1.0.1:
+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+ engines: {node: '>= 0.4'}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+
+ glob@10.4.5:
+ resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
+ hasBin: true
+
+ glob@11.0.3:
+ resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==}
+ engines: {node: 20 || >=22}
+ hasBin: true
+
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+
+ hammer-touchemulator@0.0.2:
+ resolution: {integrity: sha512-NnH4nBhI18GeT2PdfJWmTeuTAR8IowNtvxL6QQLNk6lo2uJ29rFSstOJ9ZjdVsqbjosVXFCi3SEChiagCPo0aQ==}
+
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
+ has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+ engines: {node: '>= 0.4'}
+
+ has-tostringtag@1.0.2:
+ resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+ engines: {node: '>= 0.4'}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ iconv-lite@0.4.24:
+ resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
+ engines: {node: '>=0.10.0'}
+
+ ieee754@1.2.1:
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ inquirer@8.2.6:
+ resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==}
+ engines: {node: '>=12.0.0'}
+
+ is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+
+ is-core-module@2.16.1:
+ resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
+ engines: {node: '>= 0.4'}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-interactive@1.0.0:
+ resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
+ engines: {node: '>=8'}
+
+ is-interactive@2.0.0:
+ resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==}
+ engines: {node: '>=12'}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ is-unicode-supported@0.1.0:
+ resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
+ engines: {node: '>=10'}
+
+ is-unicode-supported@1.3.0:
+ resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==}
+ engines: {node: '>=12'}
+
+ is-unicode-supported@2.1.0:
+ resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
+ engines: {node: '>=18'}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ jackspeak@3.4.3:
+ resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+
+ jackspeak@4.1.1:
+ resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==}
+ engines: {node: 20 || >=22}
+
+ jiti@1.21.7:
+ resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
+ hasBin: true
+
+ lilconfig@3.1.3:
+ resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
+ engines: {node: '>=14'}
+
+ lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+ lodash-es@4.17.21:
+ resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+
+ lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
+ log-symbols@4.1.0:
+ resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
+ engines: {node: '>=10'}
+
+ log-symbols@6.0.0:
+ resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
+ engines: {node: '>=18'}
+
+ lru-cache@10.4.3:
+ resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
+ lru-cache@11.1.0:
+ resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==}
+ engines: {node: 20 || >=22}
+
+ magic-string@0.30.17:
+ resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
+
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
+ mdn-data@2.0.28:
+ resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
+
+ mdn-data@2.0.30:
+ resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+
+ mimic-function@5.0.1:
+ resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
+ engines: {node: '>=18'}
+
+ minimatch@10.0.3:
+ resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==}
+ engines: {node: 20 || >=22}
+
+ minimatch@9.0.5:
+ resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minipass@7.1.2:
+ resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ mute-stream@0.0.8:
+ resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==}
+
+ mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+
+ nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ node-releases@2.0.19:
+ resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
+
+ normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ normalize-range@0.1.2:
+ resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
+ engines: {node: '>=0.10.0'}
+
+ nth-check@2.1.1:
+ resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ object-hash@3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+
+ onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+
+ onetime@7.0.0:
+ resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
+ engines: {node: '>=18'}
+
+ ora@5.4.1:
+ resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
+ engines: {node: '>=10'}
+
+ ora@8.2.0:
+ resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==}
+ engines: {node: '>=18'}
+
+ os-tmpdir@1.0.2:
+ resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
+ engines: {node: '>=0.10.0'}
+
+ package-json-from-dist@1.0.1:
+ resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ path-scurry@1.11.1:
+ resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+ engines: {node: '>=16 || 14 >=14.18'}
+
+ path-scurry@2.0.0:
+ resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==}
+ engines: {node: 20 || >=22}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
+ pify@2.3.0:
+ resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
+ engines: {node: '>=0.10.0'}
+
+ pirates@4.0.7:
+ resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
+ engines: {node: '>= 6'}
+
+ postcss-import@15.1.0:
+ resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+
+ postcss-js@4.0.1:
+ resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
+ engines: {node: ^12 || ^14 || >= 16}
+ peerDependencies:
+ postcss: ^8.4.21
+
+ postcss-load-config@4.0.2:
+ resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+
+ postcss-nested@6.2.0:
+ resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.2.14
+
+ postcss-selector-parser@6.1.2:
+ resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
+ engines: {node: '>=4'}
+
+ postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+
+ postcss@8.5.6:
+ resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ prettier@3.6.2:
+ resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
+ engines: {node: '>=14'}
+ hasBin: true
+
+ proxy-from-env@1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ read-cache@1.0.0:
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+
+ readable-stream@3.6.2:
+ resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+ engines: {node: '>= 6'}
+
+ readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+
+ resolve@1.22.10:
+ resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
+
+ restore-cursor@3.1.0:
+ resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
+ engines: {node: '>=8'}
+
+ restore-cursor@5.1.0:
+ resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
+ engines: {node: '>=18'}
+
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rollup@4.45.1:
+ resolution: {integrity: sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ run-async@2.4.1:
+ resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==}
+ engines: {node: '>=0.12.0'}
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ rxjs@7.8.2:
+ resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==}
+
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
+ signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ stdin-discarder@0.2.2:
+ resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
+ engines: {node: '>=18'}
+
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
+ string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+
+ string-width@7.2.0:
+ resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
+ engines: {node: '>=18'}
+
+ string_decoder@1.3.0:
+ resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
+ strip-ansi@7.1.0:
+ resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ engines: {node: '>=12'}
+
+ sucrase@3.35.0:
+ resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+
+ supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
+ svgo@3.3.2:
+ resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+
+ tailwindcss@3.4.17:
+ resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+
+ thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+
+ thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+
+ through@2.3.8:
+ resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
+
+ tinyglobby@0.2.14:
+ resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
+ engines: {node: '>=12.0.0'}
+
+ tmp@0.0.33:
+ resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
+ engines: {node: '>=0.6.0'}
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ type-fest@0.21.3:
+ resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
+ engines: {node: '>=10'}
+
+ undici-types@7.8.0:
+ resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==}
+
+ update-browserslist-db@1.1.3:
+ resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ vite@6.3.5:
+ resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ vue@3.5.17:
+ resolution: {integrity: sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ wcwidth@1.0.1:
+ resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
+
+ weixin-js-sdk@1.6.5:
+ resolution: {integrity: sha512-Gph1WAWB2YN/lMOFB/ymb+hbU/wYazzJgu6PMMktCy9cSCeW5wA6Zwt0dpahJbJ+RJEwtTv2x9iIu0U4enuVSQ==}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ wrap-ansi@6.2.0:
+ resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
+ engines: {node: '>=8'}
+
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+
+ wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+
+ yaml@2.8.0:
+ resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==}
+ engines: {node: '>= 14.6'}
+ hasBin: true
+
+snapshots:
+
+ '@alloc/quick-lru@5.2.0': {}
+
+ '@babel/helper-string-parser@7.27.1': {}
+
+ '@babel/helper-validator-identifier@7.27.1': {}
+
+ '@babel/parser@7.28.0':
+ dependencies:
+ '@babel/types': 7.28.1
+
+ '@babel/types@7.28.1':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
+
+ '@cool-vue/ai@1.1.7':
+ dependencies:
+ axios: 1.10.0
+ chalk: 4.1.2
+ commander: 11.1.0
+ glob: 11.0.3
+ inquirer: 8.2.6
+ lodash-es: 4.17.21
+ ora: 8.2.0
+ transitivePeerDependencies:
+ - debug
+
+ '@cool-vue/vite-plugin@8.2.18':
+ dependencies:
+ '@vue/compiler-sfc': 3.5.17
+ axios: 1.10.0
+ glob: 10.4.5
+ lodash: 4.17.21
+ magic-string: 0.30.17
+ prettier: 3.6.2
+ svgo: 3.3.2
+ transitivePeerDependencies:
+ - debug
+
+ '@dcloudio/types@3.4.16': {}
+
+ '@esbuild/aix-ppc64@0.25.8':
+ optional: true
+
+ '@esbuild/android-arm64@0.25.8':
+ optional: true
+
+ '@esbuild/android-arm@0.25.8':
+ optional: true
+
+ '@esbuild/android-x64@0.25.8':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.25.8':
+ optional: true
+
+ '@esbuild/darwin-x64@0.25.8':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.25.8':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.25.8':
+ optional: true
+
+ '@esbuild/linux-arm64@0.25.8':
+ optional: true
+
+ '@esbuild/linux-arm@0.25.8':
+ optional: true
+
+ '@esbuild/linux-ia32@0.25.8':
+ optional: true
+
+ '@esbuild/linux-loong64@0.25.8':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.25.8':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.25.8':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.25.8':
+ optional: true
+
+ '@esbuild/linux-s390x@0.25.8':
+ optional: true
+
+ '@esbuild/linux-x64@0.25.8':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.25.8':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.25.8':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.25.8':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.25.8':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.25.8':
+ optional: true
+
+ '@esbuild/sunos-x64@0.25.8':
+ optional: true
+
+ '@esbuild/win32-arm64@0.25.8':
+ optional: true
+
+ '@esbuild/win32-ia32@0.25.8':
+ optional: true
+
+ '@esbuild/win32-x64@0.25.8':
+ optional: true
+
+ '@isaacs/balanced-match@4.0.1': {}
+
+ '@isaacs/brace-expansion@5.0.0':
+ dependencies:
+ '@isaacs/balanced-match': 4.0.1
+
+ '@isaacs/cliui@8.0.2':
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: string-width@4.2.3
+ strip-ansi: 7.1.0
+ strip-ansi-cjs: strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: wrap-ansi@7.0.0
+
+ '@jridgewell/gen-mapping@0.3.12':
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.4
+ '@jridgewell/trace-mapping': 0.3.29
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/sourcemap-codec@1.5.4': {}
+
+ '@jridgewell/trace-mapping@0.3.29':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.4
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.19.1
+
+ '@pkgjs/parseargs@0.11.0':
+ optional: true
+
+ '@rollup/rollup-android-arm-eabi@4.45.1':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.45.1':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.45.1':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.45.1':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.45.1':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-loongarch64-gnu@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.45.1':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.45.1':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.45.1':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.45.1':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.45.1':
+ optional: true
+
+ '@trysound/sax@0.2.0': {}
+
+ '@types/estree@1.0.8': {}
+
+ '@types/node@24.0.15':
+ dependencies:
+ undici-types: 7.8.0
+
+ '@vue/compiler-core@3.5.17':
+ dependencies:
+ '@babel/parser': 7.28.0
+ '@vue/shared': 3.5.17
+ entities: 4.5.0
+ estree-walker: 2.0.2
+ source-map-js: 1.2.1
+
+ '@vue/compiler-dom@3.5.17':
+ dependencies:
+ '@vue/compiler-core': 3.5.17
+ '@vue/shared': 3.5.17
+
+ '@vue/compiler-sfc@3.5.17':
+ dependencies:
+ '@babel/parser': 7.28.0
+ '@vue/compiler-core': 3.5.17
+ '@vue/compiler-dom': 3.5.17
+ '@vue/compiler-ssr': 3.5.17
+ '@vue/shared': 3.5.17
+ estree-walker: 2.0.2
+ magic-string: 0.30.17
+ postcss: 8.5.6
+ source-map-js: 1.2.1
+
+ '@vue/compiler-ssr@3.5.17':
+ dependencies:
+ '@vue/compiler-dom': 3.5.17
+ '@vue/shared': 3.5.17
+
+ '@vue/reactivity@3.5.17':
+ dependencies:
+ '@vue/shared': 3.5.17
+
+ '@vue/runtime-core@3.5.17':
+ dependencies:
+ '@vue/reactivity': 3.5.17
+ '@vue/shared': 3.5.17
+
+ '@vue/runtime-dom@3.5.17':
+ dependencies:
+ '@vue/reactivity': 3.5.17
+ '@vue/runtime-core': 3.5.17
+ '@vue/shared': 3.5.17
+ csstype: 3.1.3
+
+ '@vue/server-renderer@3.5.17(vue@3.5.17)':
+ dependencies:
+ '@vue/compiler-ssr': 3.5.17
+ '@vue/shared': 3.5.17
+ vue: 3.5.17
+
+ '@vue/shared@3.5.17': {}
+
+ '@vue/tsconfig@0.7.0(vue@3.5.17)':
+ optionalDependencies:
+ vue: 3.5.17
+
+ adm-zip@0.5.16: {}
+
+ ansi-escapes@4.3.2:
+ dependencies:
+ type-fest: 0.21.3
+
+ ansi-regex@5.0.1: {}
+
+ ansi-regex@6.1.0: {}
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ ansi-styles@6.2.1: {}
+
+ any-promise@1.3.0: {}
+
+ anymatch@3.1.3:
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
+ arg@5.0.2: {}
+
+ asynckit@0.4.0: {}
+
+ autoprefixer@10.4.21(postcss@8.5.6):
+ dependencies:
+ browserslist: 4.25.1
+ caniuse-lite: 1.0.30001727
+ fraction.js: 4.3.7
+ normalize-range: 0.1.2
+ picocolors: 1.1.1
+ postcss: 8.5.6
+ postcss-value-parser: 4.2.0
+
+ axios@1.10.0:
+ dependencies:
+ follow-redirects: 1.15.9
+ form-data: 4.0.4
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+
+ balanced-match@1.0.2: {}
+
+ base64-js@1.5.1: {}
+
+ binary-extensions@2.3.0: {}
+
+ bl@4.1.0:
+ dependencies:
+ buffer: 5.7.1
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+
+ boolbase@1.0.0: {}
+
+ brace-expansion@2.0.2:
+ dependencies:
+ balanced-match: 1.0.2
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ browserslist@4.25.1:
+ dependencies:
+ caniuse-lite: 1.0.30001727
+ electron-to-chromium: 1.5.187
+ node-releases: 2.0.19
+ update-browserslist-db: 1.1.3(browserslist@4.25.1)
+
+ buffer@5.7.1:
+ dependencies:
+ base64-js: 1.5.1
+ ieee754: 1.2.1
+
+ call-bind-apply-helpers@1.0.2:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+
+ camelcase-css@2.0.1: {}
+
+ caniuse-lite@1.0.30001727: {}
+
+ chalk@4.1.2:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
+ chalk@5.4.1: {}
+
+ chardet@0.7.0: {}
+
+ chokidar@3.6.0:
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.3
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ cli-cursor@3.1.0:
+ dependencies:
+ restore-cursor: 3.1.0
+
+ cli-cursor@5.0.0:
+ dependencies:
+ restore-cursor: 5.1.0
+
+ cli-spinners@2.9.2: {}
+
+ cli-width@3.0.0: {}
+
+ clone@1.0.4: {}
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.4: {}
+
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
+ commander@11.1.0: {}
+
+ commander@4.1.1: {}
+
+ commander@7.2.0: {}
+
+ cross-spawn@7.0.6:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ css-select@5.2.2:
+ dependencies:
+ boolbase: 1.0.0
+ css-what: 6.2.2
+ domhandler: 5.0.3
+ domutils: 3.2.2
+ nth-check: 2.1.1
+
+ css-tree@2.2.1:
+ dependencies:
+ mdn-data: 2.0.28
+ source-map-js: 1.2.1
+
+ css-tree@2.3.1:
+ dependencies:
+ mdn-data: 2.0.30
+ source-map-js: 1.2.1
+
+ css-what@6.2.2: {}
+
+ cssesc@3.0.0: {}
+
+ csso@5.0.5:
+ dependencies:
+ css-tree: 2.2.1
+
+ csstype@3.1.3: {}
+
+ defaults@1.0.4:
+ dependencies:
+ clone: 1.0.4
+
+ delayed-stream@1.0.0: {}
+
+ didyoumean@1.2.2: {}
+
+ dlv@1.1.3: {}
+
+ dom-serializer@2.0.0:
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ entities: 4.5.0
+
+ domelementtype@2.3.0: {}
+
+ domhandler@5.0.3:
+ dependencies:
+ domelementtype: 2.3.0
+
+ domutils@3.2.2:
+ dependencies:
+ dom-serializer: 2.0.0
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ eastasianwidth@0.2.0: {}
+
+ electron-to-chromium@1.5.187: {}
+
+ emoji-regex@10.4.0: {}
+
+ emoji-regex@8.0.0: {}
+
+ emoji-regex@9.2.2: {}
+
+ entities@4.5.0: {}
+
+ es-define-property@1.0.1: {}
+
+ es-errors@1.3.0: {}
+
+ es-object-atoms@1.1.1:
+ dependencies:
+ es-errors: 1.3.0
+
+ es-set-tostringtag@2.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+
+ esbuild@0.25.8:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.25.8
+ '@esbuild/android-arm': 0.25.8
+ '@esbuild/android-arm64': 0.25.8
+ '@esbuild/android-x64': 0.25.8
+ '@esbuild/darwin-arm64': 0.25.8
+ '@esbuild/darwin-x64': 0.25.8
+ '@esbuild/freebsd-arm64': 0.25.8
+ '@esbuild/freebsd-x64': 0.25.8
+ '@esbuild/linux-arm': 0.25.8
+ '@esbuild/linux-arm64': 0.25.8
+ '@esbuild/linux-ia32': 0.25.8
+ '@esbuild/linux-loong64': 0.25.8
+ '@esbuild/linux-mips64el': 0.25.8
+ '@esbuild/linux-ppc64': 0.25.8
+ '@esbuild/linux-riscv64': 0.25.8
+ '@esbuild/linux-s390x': 0.25.8
+ '@esbuild/linux-x64': 0.25.8
+ '@esbuild/netbsd-arm64': 0.25.8
+ '@esbuild/netbsd-x64': 0.25.8
+ '@esbuild/openbsd-arm64': 0.25.8
+ '@esbuild/openbsd-x64': 0.25.8
+ '@esbuild/openharmony-arm64': 0.25.8
+ '@esbuild/sunos-x64': 0.25.8
+ '@esbuild/win32-arm64': 0.25.8
+ '@esbuild/win32-ia32': 0.25.8
+ '@esbuild/win32-x64': 0.25.8
+
+ escalade@3.2.0: {}
+
+ escape-string-regexp@1.0.5: {}
+
+ estree-walker@2.0.2: {}
+
+ external-editor@3.1.0:
+ dependencies:
+ chardet: 0.7.0
+ iconv-lite: 0.4.24
+ tmp: 0.0.33
+
+ fast-glob@3.3.3:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
+ fastq@1.19.1:
+ dependencies:
+ reusify: 1.1.0
+
+ fdir@6.4.6(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ figures@3.2.0:
+ dependencies:
+ escape-string-regexp: 1.0.5
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ follow-redirects@1.15.9: {}
+
+ foreground-child@3.3.1:
+ dependencies:
+ cross-spawn: 7.0.6
+ signal-exit: 4.1.0
+
+ form-data@4.0.4:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ es-set-tostringtag: 2.1.0
+ hasown: 2.0.2
+ mime-types: 2.1.35
+
+ fraction.js@4.3.7: {}
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ get-east-asian-width@1.3.0: {}
+
+ get-intrinsic@1.3.0:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ function-bind: 1.1.2
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ math-intrinsics: 1.1.0
+
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.1
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob-parent@6.0.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob@10.4.5:
+ dependencies:
+ foreground-child: 3.3.1
+ jackspeak: 3.4.3
+ minimatch: 9.0.5
+ minipass: 7.1.2
+ package-json-from-dist: 1.0.1
+ path-scurry: 1.11.1
+
+ glob@11.0.3:
+ dependencies:
+ foreground-child: 3.3.1
+ jackspeak: 4.1.1
+ minimatch: 10.0.3
+ minipass: 7.1.2
+ package-json-from-dist: 1.0.1
+ path-scurry: 2.0.0
+
+ gopd@1.2.0: {}
+
+ hammer-touchemulator@0.0.2: {}
+
+ has-flag@4.0.0: {}
+
+ has-symbols@1.1.0: {}
+
+ has-tostringtag@1.0.2:
+ dependencies:
+ has-symbols: 1.1.0
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ iconv-lite@0.4.24:
+ dependencies:
+ safer-buffer: 2.1.2
+
+ ieee754@1.2.1: {}
+
+ inherits@2.0.4: {}
+
+ inquirer@8.2.6:
+ dependencies:
+ ansi-escapes: 4.3.2
+ chalk: 4.1.2
+ cli-cursor: 3.1.0
+ cli-width: 3.0.0
+ external-editor: 3.1.0
+ figures: 3.2.0
+ lodash: 4.17.21
+ mute-stream: 0.0.8
+ ora: 5.4.1
+ run-async: 2.4.1
+ rxjs: 7.8.2
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ through: 2.3.8
+ wrap-ansi: 6.2.0
+
+ is-binary-path@2.1.0:
+ dependencies:
+ binary-extensions: 2.3.0
+
+ is-core-module@2.16.1:
+ dependencies:
+ hasown: 2.0.2
+
+ is-extglob@2.1.1: {}
+
+ is-fullwidth-code-point@3.0.0: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-interactive@1.0.0: {}
+
+ is-interactive@2.0.0: {}
+
+ is-number@7.0.0: {}
+
+ is-unicode-supported@0.1.0: {}
+
+ is-unicode-supported@1.3.0: {}
+
+ is-unicode-supported@2.1.0: {}
+
+ isexe@2.0.0: {}
+
+ jackspeak@3.4.3:
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+
+ jackspeak@4.1.1:
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+
+ jiti@1.21.7: {}
+
+ lilconfig@3.1.3: {}
+
+ lines-and-columns@1.2.4: {}
+
+ lodash-es@4.17.21: {}
+
+ lodash@4.17.21: {}
+
+ log-symbols@4.1.0:
+ dependencies:
+ chalk: 4.1.2
+ is-unicode-supported: 0.1.0
+
+ log-symbols@6.0.0:
+ dependencies:
+ chalk: 5.4.1
+ is-unicode-supported: 1.3.0
+
+ lru-cache@10.4.3: {}
+
+ lru-cache@11.1.0: {}
+
+ magic-string@0.30.17:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.4
+
+ math-intrinsics@1.1.0: {}
+
+ mdn-data@2.0.28: {}
+
+ mdn-data@2.0.30: {}
+
+ merge2@1.4.1: {}
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ mimic-fn@2.1.0: {}
+
+ mimic-function@5.0.1: {}
+
+ minimatch@10.0.3:
+ dependencies:
+ '@isaacs/brace-expansion': 5.0.0
+
+ minimatch@9.0.5:
+ dependencies:
+ brace-expansion: 2.0.2
+
+ minipass@7.1.2: {}
+
+ mute-stream@0.0.8: {}
+
+ mz@2.7.0:
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+
+ nanoid@3.3.11: {}
+
+ node-releases@2.0.19: {}
+
+ normalize-path@3.0.0: {}
+
+ normalize-range@0.1.2: {}
+
+ nth-check@2.1.1:
+ dependencies:
+ boolbase: 1.0.0
+
+ object-assign@4.1.1: {}
+
+ object-hash@3.0.0: {}
+
+ onetime@5.1.2:
+ dependencies:
+ mimic-fn: 2.1.0
+
+ onetime@7.0.0:
+ dependencies:
+ mimic-function: 5.0.1
+
+ ora@5.4.1:
+ dependencies:
+ bl: 4.1.0
+ chalk: 4.1.2
+ cli-cursor: 3.1.0
+ cli-spinners: 2.9.2
+ is-interactive: 1.0.0
+ is-unicode-supported: 0.1.0
+ log-symbols: 4.1.0
+ strip-ansi: 6.0.1
+ wcwidth: 1.0.1
+
+ ora@8.2.0:
+ dependencies:
+ chalk: 5.4.1
+ cli-cursor: 5.0.0
+ cli-spinners: 2.9.2
+ is-interactive: 2.0.0
+ is-unicode-supported: 2.1.0
+ log-symbols: 6.0.0
+ stdin-discarder: 0.2.2
+ string-width: 7.2.0
+ strip-ansi: 7.1.0
+
+ os-tmpdir@1.0.2: {}
+
+ package-json-from-dist@1.0.1: {}
+
+ path-key@3.1.1: {}
+
+ path-parse@1.0.7: {}
+
+ path-scurry@1.11.1:
+ dependencies:
+ lru-cache: 10.4.3
+ minipass: 7.1.2
+
+ path-scurry@2.0.0:
+ dependencies:
+ lru-cache: 11.1.0
+ minipass: 7.1.2
+
+ picocolors@1.1.1: {}
+
+ picomatch@2.3.1: {}
+
+ picomatch@4.0.3: {}
+
+ pify@2.3.0: {}
+
+ pirates@4.0.7: {}
+
+ postcss-import@15.1.0(postcss@8.5.6):
+ dependencies:
+ postcss: 8.5.6
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.10
+
+ postcss-js@4.0.1(postcss@8.5.6):
+ dependencies:
+ camelcase-css: 2.0.1
+ postcss: 8.5.6
+
+ postcss-load-config@4.0.2(postcss@8.5.6):
+ dependencies:
+ lilconfig: 3.1.3
+ yaml: 2.8.0
+ optionalDependencies:
+ postcss: 8.5.6
+
+ postcss-nested@6.2.0(postcss@8.5.6):
+ dependencies:
+ postcss: 8.5.6
+ postcss-selector-parser: 6.1.2
+
+ postcss-selector-parser@6.1.2:
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
+ postcss-value-parser@4.2.0: {}
+
+ postcss@8.5.6:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ prettier@3.6.2: {}
+
+ proxy-from-env@1.1.0: {}
+
+ queue-microtask@1.2.3: {}
+
+ read-cache@1.0.0:
+ dependencies:
+ pify: 2.3.0
+
+ readable-stream@3.6.2:
+ dependencies:
+ inherits: 2.0.4
+ string_decoder: 1.3.0
+ util-deprecate: 1.0.2
+
+ readdirp@3.6.0:
+ dependencies:
+ picomatch: 2.3.1
+
+ resolve@1.22.10:
+ dependencies:
+ is-core-module: 2.16.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ restore-cursor@3.1.0:
+ dependencies:
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+
+ restore-cursor@5.1.0:
+ dependencies:
+ onetime: 7.0.0
+ signal-exit: 4.1.0
+
+ reusify@1.1.0: {}
+
+ rollup@4.45.1:
+ dependencies:
+ '@types/estree': 1.0.8
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.45.1
+ '@rollup/rollup-android-arm64': 4.45.1
+ '@rollup/rollup-darwin-arm64': 4.45.1
+ '@rollup/rollup-darwin-x64': 4.45.1
+ '@rollup/rollup-freebsd-arm64': 4.45.1
+ '@rollup/rollup-freebsd-x64': 4.45.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.45.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.45.1
+ '@rollup/rollup-linux-arm64-gnu': 4.45.1
+ '@rollup/rollup-linux-arm64-musl': 4.45.1
+ '@rollup/rollup-linux-loongarch64-gnu': 4.45.1
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.45.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.45.1
+ '@rollup/rollup-linux-riscv64-musl': 4.45.1
+ '@rollup/rollup-linux-s390x-gnu': 4.45.1
+ '@rollup/rollup-linux-x64-gnu': 4.45.1
+ '@rollup/rollup-linux-x64-musl': 4.45.1
+ '@rollup/rollup-win32-arm64-msvc': 4.45.1
+ '@rollup/rollup-win32-ia32-msvc': 4.45.1
+ '@rollup/rollup-win32-x64-msvc': 4.45.1
+ fsevents: 2.3.3
+
+ run-async@2.4.1: {}
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ rxjs@7.8.2:
+ dependencies:
+ tslib: 2.8.1
+
+ safe-buffer@5.2.1: {}
+
+ safer-buffer@2.1.2: {}
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ signal-exit@3.0.7: {}
+
+ signal-exit@4.1.0: {}
+
+ source-map-js@1.2.1: {}
+
+ stdin-discarder@0.2.2: {}
+
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ string-width@5.1.2:
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.1.0
+
+ string-width@7.2.0:
+ dependencies:
+ emoji-regex: 10.4.0
+ get-east-asian-width: 1.3.0
+ strip-ansi: 7.1.0
+
+ string_decoder@1.3.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
+ strip-ansi@7.1.0:
+ dependencies:
+ ansi-regex: 6.1.0
+
+ sucrase@3.35.0:
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.12
+ commander: 4.1.1
+ glob: 10.4.5
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.7
+ ts-interface-checker: 0.1.13
+
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
+ supports-preserve-symlinks-flag@1.0.0: {}
+
+ svgo@3.3.2:
+ dependencies:
+ '@trysound/sax': 0.2.0
+ commander: 7.2.0
+ css-select: 5.2.2
+ css-tree: 2.3.1
+ css-what: 6.2.2
+ csso: 5.0.5
+ picocolors: 1.1.1
+
+ tailwindcss@3.4.17:
+ dependencies:
+ '@alloc/quick-lru': 5.2.0
+ arg: 5.0.2
+ chokidar: 3.6.0
+ didyoumean: 1.2.2
+ dlv: 1.1.3
+ fast-glob: 3.3.3
+ glob-parent: 6.0.2
+ is-glob: 4.0.3
+ jiti: 1.21.7
+ lilconfig: 3.1.3
+ micromatch: 4.0.8
+ normalize-path: 3.0.0
+ object-hash: 3.0.0
+ picocolors: 1.1.1
+ postcss: 8.5.6
+ postcss-import: 15.1.0(postcss@8.5.6)
+ postcss-js: 4.0.1(postcss@8.5.6)
+ postcss-load-config: 4.0.2(postcss@8.5.6)
+ postcss-nested: 6.2.0(postcss@8.5.6)
+ postcss-selector-parser: 6.1.2
+ resolve: 1.22.10
+ sucrase: 3.35.0
+ transitivePeerDependencies:
+ - ts-node
+
+ thenify-all@1.6.0:
+ dependencies:
+ thenify: 3.3.1
+
+ thenify@3.3.1:
+ dependencies:
+ any-promise: 1.3.0
+
+ through@2.3.8: {}
+
+ tinyglobby@0.2.14:
+ dependencies:
+ fdir: 6.4.6(picomatch@4.0.3)
+ picomatch: 4.0.3
+
+ tmp@0.0.33:
+ dependencies:
+ os-tmpdir: 1.0.2
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ ts-interface-checker@0.1.13: {}
+
+ tslib@2.8.1: {}
+
+ type-fest@0.21.3: {}
+
+ undici-types@7.8.0: {}
+
+ update-browserslist-db@1.1.3(browserslist@4.25.1):
+ dependencies:
+ browserslist: 4.25.1
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
+ util-deprecate@1.0.2: {}
+
+ vite@6.3.5(@types/node@24.0.15)(jiti@1.21.7)(yaml@2.8.0):
+ dependencies:
+ esbuild: 0.25.8
+ fdir: 6.4.6(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.45.1
+ tinyglobby: 0.2.14
+ optionalDependencies:
+ '@types/node': 24.0.15
+ fsevents: 2.3.3
+ jiti: 1.21.7
+ yaml: 2.8.0
+
+ vue@3.5.17:
+ dependencies:
+ '@vue/compiler-dom': 3.5.17
+ '@vue/compiler-sfc': 3.5.17
+ '@vue/runtime-dom': 3.5.17
+ '@vue/server-renderer': 3.5.17(vue@3.5.17)
+ '@vue/shared': 3.5.17
+
+ wcwidth@1.0.1:
+ dependencies:
+ defaults: 1.0.4
+
+ weixin-js-sdk@1.6.5: {}
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ wrap-ansi@6.2.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrap-ansi@7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrap-ansi@8.1.0:
+ dependencies:
+ ansi-styles: 6.2.1
+ string-width: 5.1.2
+ strip-ansi: 7.1.0
+
+ yaml@2.8.0: {}
diff --git a/cool-unix/pnpm-workspace.yaml b/cool-unix/pnpm-workspace.yaml
new file mode 100644
index 0000000..efc037a
--- /dev/null
+++ b/cool-unix/pnpm-workspace.yaml
@@ -0,0 +1,2 @@
+onlyBuiltDependencies:
+ - esbuild
diff --git a/cool-unix/router/index.ts b/cool-unix/router/index.ts
new file mode 100644
index 0000000..5fd2f05
--- /dev/null
+++ b/cool-unix/router/index.ts
@@ -0,0 +1,23 @@
+import { isNull, router, useStore } from "@/cool";
+
+/**
+ * 路由跳转前的全局钩子(如修改 pages.json 后需重新编译项目以确保路由信息生效)
+ * @param to 跳转页
+ * @param from 当前页
+ * @param next 跳转函数
+ */
+router.beforeEach((to, from, next) => {
+ const { user } = useStore();
+
+ // 判断是否需要登录
+ if (to.isAuth == true || (isNull(to.meta) ? true : to.meta.isAuth == true)) {
+ // 如果用户信息为空,则跳转到登录页
+ if (!user.isNull()) {
+ next();
+ } else {
+ router.login();
+ }
+ } else {
+ next();
+ }
+});
diff --git a/cool-unix/static/cs.png b/cool-unix/static/cs.png
new file mode 100644
index 0000000..90e8916
Binary files /dev/null and b/cool-unix/static/cs.png differ
diff --git a/cool-unix/static/demo/canvas/bg-content.png b/cool-unix/static/demo/canvas/bg-content.png
new file mode 100644
index 0000000..01b7e69
Binary files /dev/null and b/cool-unix/static/demo/canvas/bg-content.png differ
diff --git a/cool-unix/static/demo/canvas/bg.png b/cool-unix/static/demo/canvas/bg.png
new file mode 100644
index 0000000..fb88690
Binary files /dev/null and b/cool-unix/static/demo/canvas/bg.png differ
diff --git a/cool-unix/static/demo/canvas/coupon.png b/cool-unix/static/demo/canvas/coupon.png
new file mode 100644
index 0000000..82e532b
Binary files /dev/null and b/cool-unix/static/demo/canvas/coupon.png differ
diff --git a/cool-unix/static/demo/canvas/gold-l.png b/cool-unix/static/demo/canvas/gold-l.png
new file mode 100644
index 0000000..d6f078e
Binary files /dev/null and b/cool-unix/static/demo/canvas/gold-l.png differ
diff --git a/cool-unix/static/demo/canvas/gold-r.png b/cool-unix/static/demo/canvas/gold-r.png
new file mode 100644
index 0000000..23b32b9
Binary files /dev/null and b/cool-unix/static/demo/canvas/gold-r.png differ
diff --git a/cool-unix/static/demo/canvas/invite-btn.png b/cool-unix/static/demo/canvas/invite-btn.png
new file mode 100644
index 0000000..e827769
Binary files /dev/null and b/cool-unix/static/demo/canvas/invite-btn.png differ
diff --git a/cool-unix/static/demo/canvas/light.png b/cool-unix/static/demo/canvas/light.png
new file mode 100644
index 0000000..2c91ffe
Binary files /dev/null and b/cool-unix/static/demo/canvas/light.png differ
diff --git a/cool-unix/static/demo/canvas/rp-b.png b/cool-unix/static/demo/canvas/rp-b.png
new file mode 100644
index 0000000..f3000a6
Binary files /dev/null and b/cool-unix/static/demo/canvas/rp-b.png differ
diff --git a/cool-unix/static/demo/canvas/rp-t.png b/cool-unix/static/demo/canvas/rp-t.png
new file mode 100644
index 0000000..ab47c66
Binary files /dev/null and b/cool-unix/static/demo/canvas/rp-t.png differ
diff --git a/cool-unix/static/demo/canvas/text-dezk.png b/cool-unix/static/demo/canvas/text-dezk.png
new file mode 100644
index 0000000..18d2c3f
Binary files /dev/null and b/cool-unix/static/demo/canvas/text-dezk.png differ
diff --git a/cool-unix/static/demo/canvas/text-xrfl.png b/cool-unix/static/demo/canvas/text-xrfl.png
new file mode 100644
index 0000000..5fc1e93
Binary files /dev/null and b/cool-unix/static/demo/canvas/text-xrfl.png differ
diff --git a/cool-unix/static/demo/canvas/text-yqhy.png b/cool-unix/static/demo/canvas/text-yqhy.png
new file mode 100644
index 0000000..ce7d3a9
Binary files /dev/null and b/cool-unix/static/demo/canvas/text-yqhy.png differ
diff --git a/cool-unix/static/demo/svg/category.svg b/cool-unix/static/demo/svg/category.svg
new file mode 100644
index 0000000..8859db5
--- /dev/null
+++ b/cool-unix/static/demo/svg/category.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cool-unix/static/demo/svg/points.svg b/cool-unix/static/demo/svg/points.svg
new file mode 100644
index 0000000..7205ba7
--- /dev/null
+++ b/cool-unix/static/demo/svg/points.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cool-unix/static/demo/svg/shopping-cart.svg b/cool-unix/static/demo/svg/shopping-cart.svg
new file mode 100644
index 0000000..2fba9fe
--- /dev/null
+++ b/cool-unix/static/demo/svg/shopping-cart.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cool-unix/static/empty/comm.png b/cool-unix/static/empty/comm.png
new file mode 100644
index 0000000..04329df
Binary files /dev/null and b/cool-unix/static/empty/comm.png differ
diff --git a/cool-unix/static/icon/tabbar/home.png b/cool-unix/static/icon/tabbar/home.png
new file mode 100644
index 0000000..7977336
Binary files /dev/null and b/cool-unix/static/icon/tabbar/home.png differ
diff --git a/cool-unix/static/icon/tabbar/home2.png b/cool-unix/static/icon/tabbar/home2.png
new file mode 100644
index 0000000..c977ff1
Binary files /dev/null and b/cool-unix/static/icon/tabbar/home2.png differ
diff --git a/cool-unix/static/icon/tabbar/my.png b/cool-unix/static/icon/tabbar/my.png
new file mode 100644
index 0000000..04b13a3
Binary files /dev/null and b/cool-unix/static/icon/tabbar/my.png differ
diff --git a/cool-unix/static/icon/tabbar/my2.png b/cool-unix/static/icon/tabbar/my2.png
new file mode 100644
index 0000000..af63382
Binary files /dev/null and b/cool-unix/static/icon/tabbar/my2.png differ
diff --git a/cool-unix/static/icon/tabbar/template.png b/cool-unix/static/icon/tabbar/template.png
new file mode 100644
index 0000000..2b680ab
Binary files /dev/null and b/cool-unix/static/icon/tabbar/template.png differ
diff --git a/cool-unix/static/icon/tabbar/template2.png b/cool-unix/static/icon/tabbar/template2.png
new file mode 100644
index 0000000..49fcc71
Binary files /dev/null and b/cool-unix/static/icon/tabbar/template2.png differ
diff --git a/cool-unix/static/index.scss b/cool-unix/static/index.scss
new file mode 100644
index 0000000..dc83d5c
--- /dev/null
+++ b/cool-unix/static/index.scss
@@ -0,0 +1,3 @@
+/* @tailwind base; */
+@tailwind components;
+@tailwind utilities;
diff --git a/cool-unix/static/logo.png b/cool-unix/static/logo.png
new file mode 100644
index 0000000..a75c618
Binary files /dev/null and b/cool-unix/static/logo.png differ
diff --git a/cool-unix/static/logo2.png b/cool-unix/static/logo2.png
new file mode 100644
index 0000000..09c9c65
Binary files /dev/null and b/cool-unix/static/logo2.png differ
diff --git a/cool-unix/tailwind.config.ts b/cool-unix/tailwind.config.ts
new file mode 100644
index 0000000..851400e
--- /dev/null
+++ b/cool-unix/tailwind.config.ts
@@ -0,0 +1,464 @@
+import { join } from "node:path";
+import type { Config } from "tailwindcss";
+
+// 自动推导所有主色和表面色的类型
+type primaryColor =
+ | "emerald"
+ | "green"
+ | "lime"
+ | "orange"
+ | "amber"
+ | "yellow"
+ | "teal"
+ | "cyan"
+ | "sky"
+ | "blue"
+ | "indigo"
+ | "violet"
+ | "purple"
+ | "fuchsia"
+ | "pink";
+type surfaceColor = "slate" | "gray" | "zinc" | "neutral" | "stone" | "soho" | "viva" | "ocean";
+
+/**
+ * 主题主色调色板
+ */
+export const PRIMARY_COLOR_PALETTES = [
+ {
+ name: "emerald",
+ palette: {
+ 50: "#ecfdf5",
+ 100: "#d1fae5",
+ 200: "#a7f3d0",
+ 300: "#6ee7b7",
+ 400: "#34d399",
+ 500: "#10b981",
+ 600: "#059669",
+ 700: "#047857",
+ 800: "#065f46",
+ 900: "#064e3b",
+ 950: "#022c22"
+ }
+ },
+ {
+ name: "green",
+ palette: {
+ 50: "#f0fdf4",
+ 100: "#dcfce7",
+ 200: "#bbf7d0",
+ 300: "#86efac",
+ 400: "#4ade80",
+ 500: "#22c55e",
+ 600: "#16a34a",
+ 700: "#15803d",
+ 800: "#166534",
+ 900: "#14532d",
+ 950: "#052e16"
+ }
+ },
+ {
+ name: "lime",
+ palette: {
+ 50: "#f7fee7",
+ 100: "#ecfccb",
+ 200: "#d9f99d",
+ 300: "#bef264",
+ 400: "#a3e635",
+ 500: "#84cc16",
+ 600: "#65a30d",
+ 700: "#4d7c0f",
+ 800: "#3f6212",
+ 900: "#365314",
+ 950: "#1a2e05"
+ }
+ },
+ {
+ name: "orange",
+ palette: {
+ 50: "#fff7ed",
+ 100: "#ffedd5",
+ 200: "#fed7aa",
+ 300: "#fdba74",
+ 400: "#fb923c",
+ 500: "#f97316",
+ 600: "#ea580c",
+ 700: "#c2410c",
+ 800: "#9a3412",
+ 900: "#7c2d12",
+ 950: "#431407"
+ }
+ },
+ {
+ name: "amber",
+ palette: {
+ 50: "#fffbeb",
+ 100: "#fef3c7",
+ 200: "#fde68a",
+ 300: "#fcd34d",
+ 400: "#fbbf24",
+ 500: "#f59e0b",
+ 600: "#d97706",
+ 700: "#b45309",
+ 800: "#92400e",
+ 900: "#78350f",
+ 950: "#451a03"
+ }
+ },
+ {
+ name: "yellow",
+ palette: {
+ 50: "#fefce8",
+ 100: "#fef9c3",
+ 200: "#fef08a",
+ 300: "#fde047",
+ 400: "#facc15",
+ 500: "#eab308",
+ 600: "#ca8a04",
+ 700: "#a16207",
+ 800: "#854d0e",
+ 900: "#713f12",
+ 950: "#422006"
+ }
+ },
+ {
+ name: "teal",
+ palette: {
+ 50: "#f0fdfa",
+ 100: "#ccfbf1",
+ 200: "#99f6e4",
+ 300: "#5eead4",
+ 400: "#2dd4bf",
+ 500: "#14b8a6",
+ 600: "#0d9488",
+ 700: "#0f766e",
+ 800: "#115e59",
+ 900: "#134e4a",
+ 950: "#042f2e"
+ }
+ },
+ {
+ name: "cyan",
+ palette: {
+ 50: "#ecfeff",
+ 100: "#cffafe",
+ 200: "#a5f3fc",
+ 300: "#67e8f9",
+ 400: "#22d3ee",
+ 500: "#06b6d4",
+ 600: "#0891b2",
+ 700: "#0e7490",
+ 800: "#155e75",
+ 900: "#164e63",
+ 950: "#083344"
+ }
+ },
+ {
+ name: "sky",
+ palette: {
+ 50: "#f0f9ff",
+ 100: "#e0f2fe",
+ 200: "#bae6fd",
+ 300: "#7dd3fc",
+ 400: "#38bdf8",
+ 500: "#0ea5e9",
+ 600: "#0284c7",
+ 700: "#0369a1",
+ 800: "#075985",
+ 900: "#0c4a6e",
+ 950: "#082f49"
+ }
+ },
+ {
+ name: "blue",
+ palette: {
+ 50: "#eff6ff",
+ 100: "#dbeafe",
+ 200: "#bfdbfe",
+ 300: "#93c5fd",
+ 400: "#60a5fa",
+ 500: "#3b82f6",
+ 600: "#2563eb",
+ 700: "#1d4ed8",
+ 800: "#1e40af",
+ 900: "#1e3a8a",
+ 950: "#172554"
+ }
+ },
+ {
+ name: "indigo",
+ palette: {
+ 50: "#eef2ff",
+ 100: "#e0e7ff",
+ 200: "#c7d2fe",
+ 300: "#a5b4fc",
+ 400: "#818cf8",
+ 500: "#6366f1",
+ 600: "#4f46e5",
+ 700: "#4338ca",
+ 800: "#3730a3",
+ 900: "#312e81",
+ 950: "#1e1b4b"
+ }
+ },
+ {
+ name: "violet",
+ palette: {
+ 50: "#f5f3ff",
+ 100: "#ede9fe",
+ 200: "#ddd6fe",
+ 300: "#c4b5fd",
+ 400: "#a78bfa",
+ 500: "#8b5cf6",
+ 600: "#7c3aed",
+ 700: "#6d28d9",
+ 800: "#5b21b6",
+ 900: "#4c1d95",
+ 950: "#2e1065"
+ }
+ },
+ {
+ name: "purple",
+ palette: {
+ 50: "#faf5ff",
+ 100: "#f3e8ff",
+ 200: "#e9d5ff",
+ 300: "#d8b4fe",
+ 400: "#c084fc",
+ 500: "#a855f7",
+ 600: "#9333ea",
+ 700: "#7e22ce",
+ 800: "#6b21a8",
+ 900: "#581c87",
+ 950: "#3b0764"
+ }
+ },
+ {
+ name: "fuchsia",
+ palette: {
+ 50: "#fdf4ff",
+ 100: "#fae8ff",
+ 200: "#f5d0fe",
+ 300: "#f0abfc",
+ 400: "#e879f9",
+ 500: "#d946ef",
+ 600: "#c026d3",
+ 700: "#a21caf",
+ 800: "#86198f",
+ 900: "#701a75",
+ 950: "#4a044e"
+ }
+ },
+ {
+ name: "pink",
+ palette: {
+ 50: "#fdf2f8",
+ 100: "#fce7f3",
+ 200: "#fbcfe8",
+ 300: "#f9a8d4",
+ 400: "#f472b6",
+ 500: "#ec4899",
+ 600: "#db2777",
+ 700: "#be185d",
+ 800: "#9d174d",
+ 900: "#831843",
+ 950: "#500724"
+ }
+ }
+];
+
+/**
+ * 表面色调色板
+ */
+export const SURFACE_PALETTES = [
+ {
+ name: "slate",
+ palette: {
+ 0: "#ffffff",
+ 50: "#f8fafc",
+ 100: "#f1f5f9",
+ 200: "#e2e8f0",
+ 300: "#cbd5e1",
+ 400: "#94a3b8",
+ 500: "#64748b",
+ 600: "#475569",
+ 700: "#334155",
+ 800: "#1e293b",
+ 900: "#0f172a",
+ 950: "#020617"
+ }
+ },
+ {
+ name: "gray",
+ palette: {
+ 0: "#ffffff",
+ 50: "#f9fafb",
+ 100: "#f3f4f6",
+ 200: "#e5e7eb",
+ 300: "#d1d5db",
+ 400: "#9ca3af",
+ 500: "#6b7280",
+ 600: "#4b5563",
+ 700: "#374151",
+ 800: "#1f2937",
+ 900: "#111827",
+ 950: "#030712"
+ }
+ },
+ {
+ name: "zinc",
+ palette: {
+ 0: "#ffffff",
+ 50: "#fafafa",
+ 100: "#f4f4f5",
+ 200: "#e4e4e7",
+ 300: "#d4d4d8",
+ 400: "#a1a1aa",
+ 500: "#71717a",
+ 600: "#52525b",
+ 700: "#3f3f46",
+ 800: "#27272a",
+ 900: "#18181b",
+ 950: "#09090b"
+ }
+ },
+ {
+ name: "neutral",
+ palette: {
+ 0: "#ffffff",
+ 50: "#fafafa",
+ 100: "#f5f5f5",
+ 200: "#e5e5e5",
+ 300: "#d4d4d4",
+ 400: "#a3a3a3",
+ 500: "#737373",
+ 600: "#525252",
+ 700: "#404040",
+ 800: "#262626",
+ 900: "#171717",
+ 950: "#0a0a0a"
+ }
+ },
+ {
+ name: "stone",
+ palette: {
+ 0: "#ffffff",
+ 50: "#fafaf9",
+ 100: "#f5f5f4",
+ 200: "#e7e5e4",
+ 300: "#d6d3d1",
+ 400: "#a8a29e",
+ 500: "#78716c",
+ 600: "#57534e",
+ 700: "#44403c",
+ 800: "#292524",
+ 900: "#1c1917",
+ 950: "#0c0a09"
+ }
+ },
+ {
+ name: "soho",
+ palette: {
+ 0: "#ffffff",
+ 50: "#f4f4f4",
+ 100: "#e8e9e9",
+ 200: "#d2d2d4",
+ 300: "#bbbcbe",
+ 400: "#a5a5a9",
+ 500: "#8e8f93",
+ 600: "#77787d",
+ 700: "#616268",
+ 800: "#4a4b52",
+ 900: "#34343d",
+ 950: "#1d1e27"
+ }
+ },
+ {
+ name: "viva",
+ palette: {
+ 0: "#ffffff",
+ 50: "#f3f3f3",
+ 100: "#e7e7e8",
+ 200: "#cfd0d0",
+ 300: "#b7b8b9",
+ 400: "#9fa1a1",
+ 500: "#87898a",
+ 600: "#6e7173",
+ 700: "#565a5b",
+ 800: "#3e4244",
+ 900: "#262b2c",
+ 950: "#0e1315"
+ }
+ },
+ {
+ name: "ocean",
+ palette: {
+ 0: "#ffffff",
+ 50: "#fbfcfc",
+ 100: "#F7F9F8",
+ 200: "#EFF3F2",
+ 300: "#DADEDD",
+ 400: "#B1B7B6",
+ 500: "#828787",
+ 600: "#5F7274",
+ 700: "#415B61",
+ 800: "#29444E",
+ 900: "#183240",
+ 950: "#0c1920"
+ }
+ }
+];
+
+/**
+ * 获取指定主色调色板
+ * @param name 主色名称
+ * @returns 以 primary-开头的色值对象
+ */
+function getPrimary(name: primaryColor): Record {
+ const color = PRIMARY_COLOR_PALETTES.find((c) => c.name == name);
+ if (!color) return {};
+ const result: Record = {};
+ Object.entries(color.palette).forEach(([key, value]) => {
+ result[`primary-${key}`] = value;
+ });
+ return result;
+}
+
+/**
+ * 获取指定表面色调色板
+ * @param name 表面色名称
+ * @returns 以 surface-开头的色值对象,0为 surface
+ */
+function getSurface(name: surfaceColor): Record {
+ const color = SURFACE_PALETTES.find((c) => c.name == name);
+ if (!color) return {};
+ const result: Record = {};
+ Object.entries(color.palette).forEach(([key, value]) => {
+ result[key == "0" ? "surface" : `surface-${key}`] = value;
+ });
+ return result;
+}
+
+// 获取项目根目录
+const resolve = (dir: string) => join(__dirname, dir);
+
+export default {
+ content: [resolve("./**/*.{uvue,vue}"), "!**/node_modules/**", "!**/dist/**"],
+ darkMode: "class",
+ theme: {
+ extend: {
+ colors: {
+ ...getPrimary("teal"),
+ ...getSurface("zinc")
+ },
+ fontSize: {
+ md: ["1rem", "1.5rem"]
+ },
+ scale: {
+ "80": "0.8"
+ }
+ }
+ },
+ corePlugins: {
+ preflight: false
+ }
+} as Config;
diff --git a/cool-unix/theme.json b/cool-unix/theme.json
new file mode 100644
index 0000000..9239a9c
--- /dev/null
+++ b/cool-unix/theme.json
@@ -0,0 +1,22 @@
+{
+ "light": {
+ "bgColor": "#f8f8f8",
+ "bgContentColor": "#f8f8f8",
+ "navBgColor": "#ffffff",
+ "navTextStyle": "black",
+ "tabColor": "#999999",
+ "tabSelectedColor": "#14b8a6",
+ "tabBorderStyle": "white",
+ "tabBgColor": "#ffffff"
+ },
+ "dark": {
+ "bgColor": "#191919",
+ "bgContentColor": "#191919",
+ "navBgColor": "#191919",
+ "navTextStyle": "white",
+ "tabColor": "#cccccc",
+ "tabSelectedColor": "#ffffff",
+ "tabBorderStyle": "black",
+ "tabBgColor": "#191919"
+ }
+}
diff --git a/cool-unix/tsconfig.json b/cool-unix/tsconfig.json
new file mode 100644
index 0000000..340331f
--- /dev/null
+++ b/cool-unix/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "extends": "@vue/tsconfig/tsconfig.json",
+ "compilerOptions": {
+ "ignoreDeprecations": "5.0",
+ "verbatimModuleSyntax": true,
+ "experimentalDecorators": true,
+ "sourceMap": true,
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "noImplicitAny": false,
+ "types": [
+ "@dcloudio/types",
+ "vue",
+ "./uni_modules/cool-ui/index.d.ts",
+ "./uni_modules/cool-svg/index.d.ts"
+ ],
+ "lib": ["esnext", "dom"],
+ "outDir": "esbuild",
+ "paths": {
+ "@/*": ["./*"],
+ "$/*": ["./uni_modules/*"]
+ }
+ },
+ "vueCompilerOptions": {
+ "extensions": [".vue", ".uvue"]
+ },
+ "include": ["**/*.uts", "**/*.ts", "main.ts", "**/*.uvue", "**/*.vue", "App.uvue", "**/*.d.ts"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/cool-unix/types/index.ts b/cool-unix/types/index.ts
new file mode 100644
index 0000000..ee9765c
--- /dev/null
+++ b/cool-unix/types/index.ts
@@ -0,0 +1,17 @@
+export type UserInfo = {
+ unionid: string; // 用户唯一id
+ id: number; // 用户id
+ nickName: string; // 昵称
+ avatarUrl?: string; // 头像
+ phone: string; // 手机号
+ gender: number; // 性别
+ status: number; // 状态
+ description?: string; // 描述
+ loginType: number; // 登录类型
+ province?: string; // 省份
+ city?: string; // 城市
+ district?: string; // 区县
+ birthday?: string; // 生日
+ createTime: string; // 创建时间
+ updateTime: string; // 更新时间
+};
diff --git a/cool-unix/types/uni-app.d.ts b/cool-unix/types/uni-app.d.ts
new file mode 100644
index 0000000..bd1b7c6
--- /dev/null
+++ b/cool-unix/types/uni-app.d.ts
@@ -0,0 +1,506 @@
+declare module "@dcloudio/vite-plugin-uni";
+
+declare module "@/uni_modules/cool-vibrate" {
+ export function vibrate(duration: number): void;
+}
+
+declare module "@/uni_modules/cool-open-web" {
+ export function openWeb(url: string): boolean;
+}
+
+declare type Theme = "light" | "dark";
+
+declare interface Uni {
+ setAppTheme(options: {
+ theme: "auto" | Theme;
+ success?: () => void;
+ fail?: (err: {
+ errCode: number;
+ errSubject: string;
+ data: UTSJSONObject;
+ errMsg: string;
+ }) => void;
+ }): void;
+ onAppThemeChange(callback: (res: { appTheme: Theme }) => void): number;
+ onOsThemeChange(callback: (res: { osTheme: Theme }) => void): number;
+ onHostThemeChange(callback: (res: { hostTheme: Theme }) => void): void;
+ createCanvasContextAsync(options: {
+ id: string;
+ component: ComponentInternalInstance;
+ success?: (context: CanvasContext) => void;
+ fail?: (err: {
+ errCode: number;
+ errSubject: string;
+ data: UTSJSONObject;
+ errMsg: string;
+ }) => void;
+ complete?: () => void;
+ }): Promise;
+ rpx2px(px: number): number;
+}
+
+declare interface NodeInfo {
+ id?: string;
+ bottom?: number;
+ context?: number;
+ dataset?: number;
+ height?: number;
+ left?: number;
+ node?: number;
+ right?: number;
+ scrollHeight?: number;
+ scrollLeft?: number;
+ scrollTop?: number;
+ scrollWidth?: number;
+ top?: number;
+ width?: number;
+}
+
+declare interface UniEvent {
+ bubbles: boolean;
+ cancelable: boolean;
+ type: string;
+ target: any;
+ currentTarget: any;
+ timeStamp: number;
+ [key: string]: any;
+}
+
+declare interface UniInputEvent extends UniEvent {
+ detail: {
+ value: string;
+ cursor: number;
+ };
+}
+
+declare interface UniInputFocusEvent extends UniEvent {
+ detail: {
+ value: string;
+ height: number;
+ };
+}
+
+declare interface UniTextareaFocusEvent extends UniEvent {
+ detail: {
+ value: string;
+ height: number;
+ };
+}
+
+declare interface UniInputBlurEvent extends UniEvent {
+ detail: {
+ value: string;
+ cursor: number;
+ };
+}
+
+declare interface UniTextareaBlurEvent extends UniEvent {
+ detail: {
+ value: string;
+ cursor: number;
+ };
+}
+
+declare interface UniInputConfirmEvent extends UniEvent {
+ type: "confirm";
+ detail: {
+ value: string;
+ };
+}
+
+declare interface UniInputKeyboardHeightChangeEvent extends UniEvent {
+ type: "keyboardheightchange";
+ target: {
+ autofocus: boolean;
+ disabled: boolean;
+ type: string;
+ value: string;
+ };
+ currentTarget: {
+ autofocus: boolean;
+ disabled: boolean;
+ type: string;
+ value: string;
+ };
+ isStopPropagation: boolean;
+ detail: {
+ duration: number;
+ height: number;
+ };
+}
+
+declare interface UniTextareaLineChangeEvent extends UniEvent {
+ detail: {
+ lineCount: number;
+ heightRpx: number;
+ height: number;
+ };
+}
+
+declare interface UniTextareaBlurEvent extends UniEvent {
+ detail: {
+ value: string;
+ cursor: number;
+ };
+}
+
+declare interface UniTouch {
+ clientX: number;
+ clientY: number;
+ force: number;
+ identifier: number;
+ pageX: number;
+ pageY: number;
+ radiusX: number;
+ radiusY: number;
+ rotationAngle: number;
+ screenX: number;
+ screenY: number;
+}
+
+declare interface UniTouchEvent extends UniEvent {
+ changedTouches: {
+ clientX: number;
+ clientY: number;
+ force: number;
+ identifier: number;
+ pageX: number;
+ pageY: number;
+ screenX: number;
+ screenY: number;
+ }[];
+ touches: UniTouch[];
+ stopPropagation: () => void;
+ preventDefault: () => void;
+}
+
+declare interface UniPointerEvent extends UniEvent {
+ clickX: number;
+ clickY: number;
+ pageX: number;
+ pageY: number;
+ screenX: number;
+ screenY: number;
+ x: number;
+ y: number;
+}
+
+declare interface UniSliderChangeEvent extends UniEvent {
+ detail: {
+ value: number;
+ };
+}
+
+declare interface UniPickerViewChangeEvent extends UniEvent {
+ detail: {
+ value: number[];
+ };
+}
+
+declare interface UniScrollEvent extends UniEvent {
+ detail: {
+ scrollTop: number;
+ scrollLeft: number;
+ scrollHeight: number;
+ scrollWidth: number;
+ deltaY: number;
+ deltaX: number;
+ };
+}
+
+declare interface UniScrollToUpperEvent extends UniEvent {
+ detail: {
+ direction: string;
+ };
+}
+
+declare interface UniScrollToLowerEvent extends UniEvent {
+ detail: {
+ direction: string;
+ };
+}
+
+declare interface UniRefresherEvent extends UniEvent {
+ detail: {
+ dy: number;
+ };
+}
+
+declare interface UniSwiperChangeEvent extends UniEvent {
+ detail: {
+ current: number;
+ currentItemId: string;
+ source: string;
+ };
+}
+
+declare interface UniMouseEvent extends UniEvent {
+ clientX: number;
+ clientY: number;
+ pageX: number;
+ pageY: number;
+ screenX: number;
+ screenY: number;
+ x: number;
+ y: number;
+}
+
+declare interface UniImageLoadEvent extends UniEvent {
+ detail: {
+ width: number;
+ height: number;
+ };
+}
+
+declare interface JSON {
+ parseObject(text: string): T | null;
+}
+
+declare type UTSJSONObject = {
+ [key: string]: any;
+ parse?(): T | null;
+ get?(key: string): any | null;
+ set?(key: string, value: any | null): void;
+ getAny?(key: string): any | null;
+ getAny?(key: string, def: any): any;
+ getBoolean?(key: string): boolean | null;
+ getBoolean?(key: string, def: any): boolean;
+ getNumber?(key: string): number | null;
+ getNumber?(key: string, def: any): number;
+ getString?(key: string): string | null;
+ getString?(key: string, def: any): string;
+ getJSON?(key: string): UTSJSONObject | null;
+ getJSON?(key: string, def: any): UTSJSONObject;
+ getArray?(key: string): T[] | null;
+ getArray?(key: string, def: T[]): T[];
+ getArray?(key: string): any[] | null;
+ getArray?(key: string, def: any[]): any[];
+ toMap?(): Map;
+};
+
+declare interface ChooseImageTempFile {
+ path: string;
+ size: number;
+ name: string;
+ type: string;
+}
+
+declare type RequestMethod =
+ | "OPTIONS"
+ | "GET"
+ | "HEAD"
+ | "POST"
+ | "PUT"
+ | "DELETE"
+ | "TRACE"
+ | "CONNECT";
+
+declare const onAddToFavorites: (
+ hook: (options: Page.AddToFavoritesOption) => Page.CustomFavoritesContent,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onBackPress: (
+ hook: (options: Page.BackPressOption) => any,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onError: (
+ hook: (error: string) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onExit: (hook: () => void, target?: ComponentInternalInstance | null) => void;
+
+declare const onHide: (hook: () => any, target?: ComponentInternalInstance | null) => void;
+
+declare const onInit: (
+ hook: (query?: AnyObject | undefined) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onLaunch: (
+ hook: (options?: App.LaunchShowOption | undefined) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onLoad: (
+ hook: (query?: AnyObject | undefined) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onNavigationBarButtonTap: (
+ hook: (options: Page.NavigationBarButtonTapOption) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onNavigationBarSearchInputChanged: (
+ hook: (event: Page.NavigationBarSearchInputEvent) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onNavigationBarSearchInputClicked: (
+ hook: () => any,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onNavigationBarSearchInputConfirmed: (
+ hook: (event: Page.NavigationBarSearchInputEvent) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onNavigationBarSearchInputFocusChanged: (
+ hook: onNavigationBarSearchInputFocusChangedHook,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare type onNavigationBarSearchInputFocusChangedHook = (
+ options: NavigationBarSearchInputFocusChanged
+) => void;
+
+declare const onPageHide: (hook: () => any, target?: ComponentInternalInstance | null) => void;
+
+declare const onPageNotFound: (
+ hook: (options: App.PageNotFoundOption) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onPageScroll: (
+ hook: (options: Page.PageScrollOption) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onPageShow: (
+ hook: ((options?: App.LaunchShowOption | undefined) => void) | (() => void),
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onPullDownRefresh: (
+ hook: () => any,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onReachBottom: (hook: () => any, target?: ComponentInternalInstance | null) => void;
+
+declare const onReady: (hook: () => any, target?: ComponentInternalInstance | null) => void;
+
+declare const onResize: (
+ hook: (options: Page.ResizeOption) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onSaveExitState: (
+ hook: onSaveExitStateHook,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare type onSaveExitStateHook = () => SaveExitState;
+
+declare const onShareAppMessage: (
+ hook: (
+ options: Page.ShareAppMessageOption
+ ) => Page.CustomShareContent | Promise>,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onShareTimeline: (
+ hook: () => Page.ShareTimelineContent,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onShow: (
+ hook: ((options?: App.LaunchShowOption | undefined) => void) | (() => void),
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onTabItemTap: (
+ hook: (options: Page.TabItemTapOption) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onThemeChange: (
+ hook: (options: UniApp.OnThemeChangeCallbackResult) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onUnhandledRejection: (
+ hook: (options: UniApp.OnUnhandledRejectionCallbackResult) => void,
+ target?: ComponentInternalInstance | null
+) => void;
+
+declare const onUnload: (hook: () => any, target?: ComponentInternalInstance | null) => void;
+
+declare interface DOMRect {
+ x: number;
+ y: number;
+ width: number;
+ height: number;
+ left: number;
+ top: number;
+ right: number;
+ bottom: number;
+}
+
+declare interface UniElement {
+ $vm: ComponentPublicInstance;
+ id: string;
+ firstChild: UniElement;
+ lastChild: UniElement;
+ previousSibling: UniElement;
+ parentElement: UniElement;
+ children: UniElement[];
+ attributes: Map;
+ dataset: Map;
+ style: CSSStyleDeclaration;
+ classList: string[];
+ takeSnapshot(options: {
+ success?: (res: { tempFilePath: string }) => void;
+ fail?: (err: { errCode: number; errMsg: string }) => void;
+ }): void;
+ getBoundingClientRectAsync(): Promise;
+ getDrawableContext(): DrawableContext;
+ animate(
+ keyframes: UniAnimationKeyframe | UniAnimationKeyframe[],
+ options?:
+ | {
+ delay?: number;
+ direction?: "normal" | "reverse" | "alternate" | "alternate-reverse";
+ duration?: number;
+ easing?:
+ | "ease"
+ | "ease-in"
+ | "ease-out"
+ | "ease-in-out"
+ | "linear"
+ | "cubic-bezier";
+ fill?: "backwards" | "forwards" | "both" | "none";
+ iterations?: number;
+ }
+ | number
+ ): { id: string; playState: "running" | "paused" | "finished" | "idle" } | null;
+}
+
+declare interface CanvasContext extends HTMLCanvasElement {
+ createImage(): HTMLImageElement;
+ reset(): void;
+}
+
+declare type Image = HTMLImageElement;
+
+declare type VueApp = any;
+
+declare interface UniNativeViewElement extends UniElement {
+ bindAndroidView(view: any): void;
+ bindIOSView(): void;
+ bindHarmonyFrameNode(node: FrameNode): void;
+ bindHarmonyWrappedBuilder(
+ builder: WrappedBuilder<[options: O]>
+ ): BuilderNode<[O]>;
+ getHarmonyFrameNode(): FrameNode | null;
+}
+
+declare type UniNativeViewInitEvent = {
+ detail: {
+ element: UniNativeViewElement;
+ };
+};
diff --git a/cool-unix/uni.scss b/cool-unix/uni.scss
new file mode 100644
index 0000000..b9249e9
--- /dev/null
+++ b/cool-unix/uni.scss
@@ -0,0 +1,76 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color:#333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:12px;
+$uni-font-size-base:14px;
+$uni-font-size-lg:16px;
+
+/* 图片尺寸 */
+$uni-img-size-sm:20px;
+$uni-img-size-base:26px;
+$uni-img-size-lg:40px;
+
+/* Border Radius */
+$uni-border-radius-sm: 2px;
+$uni-border-radius-base: 3px;
+$uni-border-radius-lg: 6px;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 5px;
+$uni-spacing-row-base: 10px;
+$uni-spacing-row-lg: 15px;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 4px;
+$uni-spacing-col-base: 8px;
+$uni-spacing-col-lg: 12px;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:20px;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:26px;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:15px;
diff --git a/cool-unix/uni_modules/cool-canvas/components/cl-canvas/cl-canvas.uvue b/cool-unix/uni_modules/cool-canvas/components/cl-canvas/cl-canvas.uvue
new file mode 100644
index 0000000..fc111e6
--- /dev/null
+++ b/cool-unix/uni_modules/cool-canvas/components/cl-canvas/cl-canvas.uvue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-canvas/hooks/index.ts b/cool-unix/uni_modules/cool-canvas/hooks/index.ts
new file mode 100644
index 0000000..de758d4
--- /dev/null
+++ b/cool-unix/uni_modules/cool-canvas/hooks/index.ts
@@ -0,0 +1,813 @@
+import { getDevicePixelRatio, isEmpty } from "@/cool";
+import { getCurrentInstance } from "vue";
+import type {
+ CropImageResult,
+ DivRenderOptions,
+ ImageRenderOptions,
+ TextRenderOptions,
+ TransformOptions
+} from "../types";
+
+/**
+ * Canvas 绘图类,封装了常用的绘图操作
+ */
+export class Canvas {
+ // uni-app CanvasContext 对象
+ context: CanvasContext | null = null;
+ // 2D 渲染上下文
+ ctx: CanvasRenderingContext2D | null = null;
+ // 组件作用域(用于小程序等环境)
+ scope: ComponentPublicInstance | null = null;
+ // 画布ID
+ canvasId: string | null = null;
+ // 渲染队列,存储所有待渲染的异步操作
+ renderQuene: (() => Promise)[] = [];
+ // 图片渲染队列,存储所有待处理的图片参数
+ imageQueue: ImageRenderOptions[] = [];
+
+ /**
+ * 构造函数
+ * @param canvasId 画布ID
+ */
+ constructor(canvasId: string) {
+ const { proxy } = getCurrentInstance()!;
+
+ // 当前页面作用域
+ this.scope = proxy;
+
+ // 画布ID
+ this.canvasId = canvasId;
+ }
+
+ /**
+ * 创建画布上下文
+ * @returns Promise
+ */
+ async create(): Promise {
+ const dpr = getDevicePixelRatio(); // 获取设备像素比
+
+ return new Promise((resolve) => {
+ uni.createCanvasContextAsync({
+ id: this.canvasId!,
+ component: this.scope,
+ success: (context: CanvasContext) => {
+ this.context = context;
+ this.ctx = context.getContext("2d")!;
+ this.ctx.scale(dpr, dpr); // 按照 dpr 缩放,保证高清
+
+ resolve();
+ }
+ });
+ });
+ }
+
+ /**
+ * 设置画布高度
+ * @param value 高度
+ * @returns Canvas
+ */
+ height(value: number): Canvas {
+ this.ctx!.canvas.height = value;
+ return this;
+ }
+
+ /**
+ * 设置画布宽度
+ * @param value 宽度
+ * @returns Canvas
+ */
+ width(value: number): Canvas {
+ this.ctx!.canvas.width = value;
+ return this;
+ }
+
+ /**
+ * 添加块(矩形/圆角矩形)渲染到队列
+ * @param options DivRenderOptions
+ * @returns Canvas
+ */
+ div(options: DivRenderOptions): Canvas {
+ const render = async () => {
+ this.divRender(options);
+ };
+ this.renderQuene.push(render);
+ return this;
+ }
+
+ /**
+ * 添加文本渲染到队列
+ * @param options TextRenderOptions
+ * @returns Canvas
+ */
+ text(options: TextRenderOptions): Canvas {
+ const render = async () => {
+ this.textRender(options);
+ };
+ this.renderQuene.push(render);
+ return this;
+ }
+
+ /**
+ * 添加图片渲染到队列
+ * @param options ImageRenderOptions
+ * @returns Canvas
+ */
+ image(options: ImageRenderOptions): Canvas {
+ const render = async () => {
+ await this.imageRender(options);
+ };
+ this.imageQueue.push(options);
+ this.renderQuene.push(render);
+ return this;
+ }
+
+ /**
+ * 执行绘制流程(预加载图片后依次渲染队列)
+ */
+ async draw(): Promise {
+ // 如果有图片,先预加载
+ if (!isEmpty(this.imageQueue)) {
+ await this.preloadImage();
+ }
+
+ this.render();
+ }
+
+ /**
+ * 下载图片(获取本地路径,兼容APP等平台)
+ * @param item ImageRenderOptions
+ * @returns Promise
+ */
+ downloadImage(item: ImageRenderOptions): Promise {
+ return new Promise((resolve, reject) => {
+ uni.getImageInfo({
+ src: item.url,
+ success: (res) => {
+ // #ifdef APP
+ item.url = res.path; // APP端需用本地路径
+ // #endif
+ resolve();
+ },
+ fail: (err) => {
+ console.error(err);
+ reject(err);
+ }
+ });
+ });
+ }
+
+ /**
+ * 预加载所有图片,确保图片可用
+ */
+ async preloadImage(): Promise {
+ await Promise.all(
+ this.imageQueue.map((e) => {
+ return this.downloadImage(e);
+ })
+ );
+ }
+
+ /**
+ * 设置背景颜色
+ * @param color 颜色字符串
+ */
+ private setBackground(color: string) {
+ this.ctx!.fillStyle = color;
+ }
+
+ /**
+ * 设置边框(支持圆角)
+ * @param options DivRenderOptions
+ */
+ private setBorder(options: DivRenderOptions) {
+ const { x, y, width: w = 0, height: h = 0, borderWidth, borderColor, radius: r } = options;
+
+ if (borderWidth == null || borderColor == null) return;
+
+ this.ctx!.lineWidth = borderWidth;
+ this.ctx!.strokeStyle = borderColor;
+
+ // 偏移距离,保证边框居中
+ let p = borderWidth / 2;
+
+ // 是否有圆角
+ if (r != null) {
+ this.drawRadius(x - p, y - p, w + 2 * p, h + 2 * p, r + p);
+ this.ctx!.stroke();
+ } else {
+ this.ctx!.strokeRect(x - p, y - p, w + 2 * p, h + 2 * p);
+ }
+ }
+
+ /**
+ * 设置变换(缩放、旋转、平移)
+ * @param options TransformOptions
+ */
+ private setTransform(options: TransformOptions) {
+ const ctx = this.ctx!;
+
+ // 平移
+ if (options.translateX != null || options.translateY != null) {
+ ctx.translate(options.translateX ?? 0, options.translateY ?? 0);
+ }
+
+ // 旋转(角度转弧度)
+ if (options.rotate != null) {
+ ctx.rotate((options.rotate * Math.PI) / 180);
+ }
+
+ // 缩放
+ if (options.scale != null) {
+ // 统一缩放
+ ctx.scale(options.scale, options.scale);
+ } else if (options.scaleX != null || options.scaleY != null) {
+ // 分别缩放
+ ctx.scale(options.scaleX ?? 1, options.scaleY ?? 1);
+ }
+ }
+
+ /**
+ * 绘制带圆角的路径
+ * @param x 左上角x
+ * @param y 左上角y
+ * @param w 宽度
+ * @param h 高度
+ * @param r 圆角半径
+ */
+ private drawRadius(x: number, y: number, w: number, h: number, r: number) {
+ // 圆角半径不能超过宽高一半
+ const maxRadius = Math.min(w / 2, h / 2);
+ const radius = Math.min(r, maxRadius);
+
+ this.ctx!.beginPath();
+ // 从左上角圆弧的结束点开始
+ this.ctx!.moveTo(x + radius, y);
+ // 顶边
+ this.ctx!.lineTo(x + w - radius, y);
+ // 右上角圆弧
+ this.ctx!.arc(x + w - radius, y + radius, radius, -Math.PI / 2, 0);
+ // 右边
+ this.ctx!.lineTo(x + w, y + h - radius);
+ // 右下角圆弧
+ this.ctx!.arc(x + w - radius, y + h - radius, radius, 0, Math.PI / 2);
+ // 底边
+ this.ctx!.lineTo(x + radius, y + h);
+ // 左下角圆弧
+ this.ctx!.arc(x + radius, y + h - radius, radius, Math.PI / 2, Math.PI);
+ // 左边
+ this.ctx!.lineTo(x, y + radius);
+ // 左上角圆弧
+ this.ctx!.arc(x + radius, y + radius, radius, Math.PI, -Math.PI / 2);
+ this.ctx!.closePath();
+ }
+
+ /**
+ * 裁剪图片,支持多种裁剪模式
+ * @param mode 裁剪模式
+ * @param canvasWidth 目标区域宽度
+ * @param canvasHeight 目标区域高度
+ * @param imageWidth 原图宽度
+ * @param imageHeight 原图高度
+ * @param drawX 绘制起点X
+ * @param drawY 绘制起点Y
+ * @returns CropImageResult
+ */
+ private cropImage(
+ mode:
+ | "scaleToFill"
+ | "aspectFit"
+ | "aspectFill"
+ | "center"
+ | "top"
+ | "bottom"
+ | "left"
+ | "right"
+ | "topLeft"
+ | "topRight"
+ | "bottomLeft"
+ | "bottomRight",
+ canvasWidth: number,
+ canvasHeight: number,
+ imageWidth: number,
+ imageHeight: number,
+ drawX: number,
+ drawY: number
+ ): CropImageResult {
+ // sx, sy, sw, sh: 原图裁剪区域
+ // dx, dy, dw, dh: 画布绘制区域
+ let sx = 0,
+ sy = 0,
+ sw = imageWidth,
+ sh = imageHeight;
+ let dx = drawX,
+ dy = drawY,
+ dw = canvasWidth,
+ dh = canvasHeight;
+
+ // 计算宽高比
+ const imageRatio = imageWidth / imageHeight;
+ const canvasRatio = canvasWidth / canvasHeight;
+
+ switch (mode) {
+ case "scaleToFill":
+ // 拉伸填充整个区域,可能变形
+ break;
+
+ case "aspectFit":
+ // 保持比例完整显示,可能有留白
+ if (imageRatio > canvasRatio) {
+ // 图片更宽,以宽度为准
+ dw = canvasWidth;
+ dh = canvasWidth / imageRatio;
+ dx = drawX;
+ dy = drawY + (canvasHeight - dh) / 2;
+ } else {
+ // 图片更高,以高度为准
+ dw = canvasHeight * imageRatio;
+ dh = canvasHeight;
+ dx = drawX + (canvasWidth - dw) / 2;
+ dy = drawY;
+ }
+ break;
+
+ case "aspectFill":
+ // 保持比例填充,可能裁剪
+ if (imageRatio > canvasRatio) {
+ // 图片更宽,裁剪左右
+ const scaledWidth = imageHeight * canvasRatio;
+ sx = (imageWidth - scaledWidth) / 2;
+ sw = scaledWidth;
+ } else {
+ // 图片更高,裁剪上下
+ const scaledHeight = imageWidth / canvasRatio;
+ sy = (imageHeight - scaledHeight) / 2;
+ sh = scaledHeight;
+ }
+ break;
+
+ case "center":
+ // 居中显示,不缩放,超出裁剪
+ sx = Math.max(0, (imageWidth - canvasWidth) / 2);
+ sy = Math.max(0, (imageHeight - canvasHeight) / 2);
+ sw = Math.min(imageWidth, canvasWidth);
+ sh = Math.min(imageHeight, canvasHeight);
+ dx = drawX + Math.max(0, (canvasWidth - imageWidth) / 2);
+ dy = drawY + Math.max(0, (canvasHeight - imageHeight) / 2);
+ dw = sw;
+ dh = sh;
+ break;
+
+ case "top":
+ // 顶部对齐,水平居中
+ sx = Math.max(0, (imageWidth - canvasWidth) / 2);
+ sy = 0;
+ sw = Math.min(imageWidth, canvasWidth);
+ sh = Math.min(imageHeight, canvasHeight);
+ dx = drawX + Math.max(0, (canvasWidth - imageWidth) / 2);
+ dy = drawY;
+ dw = sw;
+ dh = sh;
+ break;
+
+ case "bottom":
+ // 底部对齐,水平居中
+ sx = Math.max(0, (imageWidth - canvasWidth) / 2);
+ sy = Math.max(0, imageHeight - canvasHeight);
+ sw = Math.min(imageWidth, canvasWidth);
+ sh = Math.min(imageHeight, canvasHeight);
+ dx = drawX + Math.max(0, (canvasWidth - imageWidth) / 2);
+ dy = drawY + Math.max(0, canvasHeight - imageHeight);
+ dw = sw;
+ dh = sh;
+ break;
+
+ case "left":
+ // 左对齐,垂直居中
+ sx = 0;
+ sy = Math.max(0, (imageHeight - canvasHeight) / 2);
+ sw = Math.min(imageWidth, canvasWidth);
+ sh = Math.min(imageHeight, canvasHeight);
+ dx = drawX;
+ dy = drawY + Math.max(0, (canvasHeight - imageHeight) / 2);
+ dw = sw;
+ dh = sh;
+ break;
+
+ case "right":
+ // 右对齐,垂直居中
+ sx = Math.max(0, imageWidth - canvasWidth);
+ sy = Math.max(0, (imageHeight - canvasHeight) / 2);
+ sw = Math.min(imageWidth, canvasWidth);
+ sh = Math.min(imageHeight, canvasHeight);
+ dx = drawX + Math.max(0, canvasWidth - imageWidth);
+ dy = drawY + Math.max(0, (canvasHeight - imageHeight) / 2);
+ dw = sw;
+ dh = sh;
+ break;
+
+ case "topLeft":
+ // 左上角对齐
+ sx = 0;
+ sy = 0;
+ sw = Math.min(imageWidth, canvasWidth);
+ sh = Math.min(imageHeight, canvasHeight);
+ dx = drawX;
+ dy = drawY;
+ dw = sw;
+ dh = sh;
+ break;
+
+ case "topRight":
+ // 右上角对齐
+ sx = Math.max(0, imageWidth - canvasWidth);
+ sy = 0;
+ sw = Math.min(imageWidth, canvasWidth);
+ sh = Math.min(imageHeight, canvasHeight);
+ dx = drawX + Math.max(0, canvasWidth - imageWidth);
+ dy = drawY;
+ dw = sw;
+ dh = sh;
+ break;
+
+ case "bottomLeft":
+ // 左下角对齐
+ sx = 0;
+ sy = Math.max(0, imageHeight - canvasHeight);
+ sw = Math.min(imageWidth, canvasWidth);
+ sh = Math.min(imageHeight, canvasHeight);
+ dx = drawX;
+ dy = drawY + Math.max(0, canvasHeight - imageHeight);
+ dw = sw;
+ dh = sh;
+ break;
+
+ case "bottomRight":
+ // 右下角对齐
+ sx = Math.max(0, imageWidth - canvasWidth);
+ sy = Math.max(0, imageHeight - canvasHeight);
+ sw = Math.min(imageWidth, canvasWidth);
+ sh = Math.min(imageHeight, canvasHeight);
+ dx = drawX + Math.max(0, canvasWidth - imageWidth);
+ dy = drawY + Math.max(0, canvasHeight - imageHeight);
+ dw = sw;
+ dh = sh;
+ break;
+ }
+
+ return {
+ // 源图片裁剪区域
+ sx,
+ sy,
+ sw,
+ sh,
+ // 目标绘制区域
+ dx,
+ dy,
+ dw,
+ dh
+ } as CropImageResult;
+ }
+
+ /**
+ * 获取文本每行内容(自动换行、支持省略号)
+ * @param options TextRenderOptions
+ * @returns string[] 每行内容
+ */
+ private getTextRows({
+ content,
+ fontSize = 14,
+ width = 100,
+ lineClamp = 1,
+ overflow,
+ letterSpace = 0,
+ fontFamily = "sans-serif",
+ fontWeight = "normal"
+ }: TextRenderOptions) {
+ // 临时设置字体以便准确测量
+ this.ctx!.save();
+ this.ctx!.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
+
+ let arr: string[] = [""];
+ let currentLineWidth = 0;
+
+ for (let i = 0; i < content.length; i++) {
+ const char = content.charAt(i);
+ const charWidth = this.ctx!.measureText(char).width;
+
+ // 计算当前字符加上字符间距后的总宽度
+ const needSpace = arr[arr.length - 1].length > 0 && letterSpace > 0;
+ const totalWidth = charWidth + (needSpace ? letterSpace : 0);
+
+ if (currentLineWidth + totalWidth > width) {
+ // 换行:新行的第一个字符不需要字符间距
+ currentLineWidth = charWidth;
+ arr.push(char);
+ } else {
+ // 最后一行且设置超出省略号
+ if (overflow == "ellipsis" && arr.length == lineClamp) {
+ const ellipsisWidth = this.ctx!.measureText("...").width;
+ const ellipsisSpaceWidth = needSpace ? letterSpace : 0;
+
+ if (
+ currentLineWidth + totalWidth + ellipsisSpaceWidth + ellipsisWidth >
+ width
+ ) {
+ arr[arr.length - 1] += "...";
+ break;
+ }
+ }
+
+ currentLineWidth += totalWidth;
+ arr[arr.length - 1] += char;
+ }
+ }
+
+ this.ctx!.restore();
+ return arr;
+ }
+
+ /**
+ * 渲染块(矩形/圆角矩形)
+ * @param options DivRenderOptions
+ */
+ private divRender(options: DivRenderOptions) {
+ const {
+ x,
+ y,
+ width = 0,
+ height = 0,
+ radius,
+ backgroundColor = "#fff",
+ opacity = 1,
+ scale,
+ scaleX,
+ scaleY,
+ rotate,
+ translateX,
+ translateY
+ } = options;
+
+ this.ctx!.save();
+
+ // 设置透明度
+ this.ctx!.globalAlpha = opacity;
+
+ // 设置背景色
+ this.setBackground(backgroundColor);
+ // 设置边框
+ this.setBorder(options);
+ // 设置变换
+ this.setTransform({
+ scale,
+ scaleX,
+ scaleY,
+ rotate,
+ translateX,
+ translateY
+ });
+
+ // 判断是否有圆角
+ if (radius != null) {
+ // 绘制圆角路径
+ this.drawRadius(x, y, width, height, radius);
+ // 填充
+ this.ctx!.fill();
+ } else {
+ // 普通矩形
+ this.ctx!.fillRect(x, y, width, height);
+ }
+ this.ctx!.restore();
+ }
+
+ /**
+ * 渲染文本
+ * @param options TextRenderOptions
+ */
+ private textRender(options: TextRenderOptions) {
+ let {
+ fontSize = 14,
+ textAlign,
+ width,
+ color = "#000000",
+ x,
+ y,
+ letterSpace,
+ lineHeight,
+ fontFamily = "sans-serif",
+ fontWeight = "normal",
+ opacity = 1,
+ scale,
+ scaleX,
+ scaleY,
+ rotate,
+ translateX,
+ translateY
+ } = options;
+
+ // 如果行高为空,则设置为字体大小的1.4倍
+ if (lineHeight == null) {
+ lineHeight = fontSize * 1.4;
+ }
+
+ this.ctx!.save();
+
+ // 应用变换
+ this.setTransform({
+ scale,
+ scaleX,
+ scaleY,
+ rotate,
+ translateX,
+ translateY
+ });
+
+ // 设置字体样式
+ this.ctx!.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
+
+ // 设置透明度
+ this.ctx!.globalAlpha = opacity;
+
+ // 设置字体颜色
+ this.ctx!.fillStyle = color;
+
+ // 获取每行文本内容
+ const rows = this.getTextRows(options);
+
+ // 左偏移量
+ let offsetLeft = 0;
+
+ // 字体对齐(无字符间距时使用Canvas的textAlign)
+ if (textAlign != null && width != null && (letterSpace == null || letterSpace <= 0)) {
+ this.ctx!.textAlign = textAlign;
+
+ switch (textAlign) {
+ case "left":
+ break;
+ case "center":
+ offsetLeft = width / 2;
+ break;
+ case "right":
+ offsetLeft = width;
+ break;
+ }
+ } else {
+ // 有字符间距时,使用左对齐,手动控制位置
+ this.ctx!.textAlign = "left";
+ }
+
+ // 计算行间距
+ const lineGap = lineHeight - fontSize;
+
+ // 逐行渲染
+ for (let i = 0; i < rows.length; i++) {
+ const currentRow = rows[i];
+ const yPos = (i + 1) * fontSize + y + lineGap * i;
+
+ if (letterSpace != null && letterSpace > 0) {
+ // 逐字符计算宽度,确保字符间距准确
+ let lineWidth = 0;
+ for (let j = 0; j < currentRow.length; j++) {
+ lineWidth += this.ctx!.measureText(currentRow.charAt(j)).width;
+ if (j < currentRow.length - 1) {
+ lineWidth += letterSpace;
+ }
+ }
+
+ // 计算起始位置(考虑 textAlign)
+ let startX = x;
+ if (textAlign == "center" && width != null) {
+ startX = x + (width - lineWidth) / 2;
+ } else if (textAlign == "right" && width != null) {
+ startX = x + width - lineWidth;
+ }
+
+ // 逐字符渲染
+ let charX = startX;
+ for (let j = 0; j < currentRow.length; j++) {
+ const char = currentRow.charAt(j);
+ this.ctx!.fillText(char, charX, yPos);
+
+ // 移动到下一个字符位置
+ charX += this.ctx!.measureText(char).width;
+ if (j < currentRow.length - 1) {
+ charX += letterSpace;
+ }
+ }
+ } else {
+ // 普通渲染(无字符间距)
+ this.ctx!.fillText(currentRow, x + offsetLeft, yPos);
+ }
+ }
+
+ this.ctx!.restore();
+ }
+
+ /**
+ * 渲染图片
+ * @param options ImageRenderOptions
+ */
+ private async imageRender(options: ImageRenderOptions): Promise {
+ return new Promise((resolve) => {
+ this.ctx!.save();
+
+ // 设置透明度
+ this.ctx!.globalAlpha = options.opacity ?? 1;
+
+ // 应用变换
+ this.setTransform({
+ scale: options.scale,
+ scaleX: options.scaleX,
+ scaleY: options.scaleY,
+ rotate: options.rotate,
+ translateX: options.translateX,
+ translateY: options.translateY
+ });
+
+ // 如果有圆角,先绘制路径并裁剪
+ if (options.radius != null) {
+ this.drawRadius(
+ options.x,
+ options.y,
+ options.width,
+ options.height,
+ options.radius
+ );
+ this.ctx!.clip();
+ }
+
+ const temp = this.imageQueue[0];
+
+ let img: Image;
+
+ // 微信小程序/鸿蒙环境创建图片
+ // #ifdef MP-WEIXIN || APP-HARMONY
+ img = this.context!.createImage();
+ // #endif
+
+ // 其他环境创建图片
+ // #ifndef MP-WEIXIN || APP-HARMONY
+ img = new Image();
+ // #endif
+
+ img.src = temp.url;
+
+ img.onload = () => {
+ if (options.mode != null) {
+ let h: number;
+ let w: number;
+
+ // #ifdef H5
+ h = img["height"];
+ w = img["width"];
+ // #endif
+
+ // #ifndef H5
+ h = img.height;
+ w = img.width;
+ // #endif
+
+ // 按模式裁剪并绘制
+ const { sx, sy, sw, sh, dx, dy, dw, dh } = this.cropImage(
+ options.mode,
+ temp.width, // 目标绘制区域宽度
+ temp.height, // 目标绘制区域高度
+ w, // 原图片宽度
+ h, // 原图片高度
+ temp.x, // 绘制X坐标
+ temp.y // 绘制Y坐标
+ );
+
+ // 使用 drawImage 的完整参数形式进行精确裁剪和绘制
+ this.ctx!.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);
+ } else {
+ // 不指定模式时,直接绘制整个图片
+ this.ctx!.drawImage(img, temp.x, temp.y, temp.width, temp.height);
+ }
+
+ this.ctx!.restore();
+ this.imageQueue.shift(); // 移除已渲染图片
+
+ resolve();
+ };
+ });
+ }
+
+ /**
+ * 依次执行渲染队列中的所有操作
+ */
+ async render() {
+ for (let i = 0; i < this.renderQuene.length; i++) {
+ const r = this.renderQuene[i];
+ await r();
+ }
+ }
+}
+
+/**
+ * useCanvas 钩子函数,返回 Canvas 实例
+ * @param canvasId 画布ID
+ * @returns Canvas
+ */
+export const useCanvas = (canvasId: string) => {
+ return new Canvas(canvasId);
+};
diff --git a/cool-unix/uni_modules/cool-canvas/index.ts b/cool-unix/uni_modules/cool-canvas/index.ts
new file mode 100644
index 0000000..007f69d
--- /dev/null
+++ b/cool-unix/uni_modules/cool-canvas/index.ts
@@ -0,0 +1 @@
+export * from "./hooks";
diff --git a/cool-unix/uni_modules/cool-canvas/types/component.d.ts b/cool-unix/uni_modules/cool-canvas/types/component.d.ts
new file mode 100644
index 0000000..cf08e93
--- /dev/null
+++ b/cool-unix/uni_modules/cool-canvas/types/component.d.ts
@@ -0,0 +1,5 @@
+declare type ClCanvasComponentPublicInstance = {
+ saveImage: () => void;
+ previewImage: () => void;
+ createImage: () => Promise;
+};
diff --git a/cool-unix/uni_modules/cool-canvas/types/index.ts b/cool-unix/uni_modules/cool-canvas/types/index.ts
new file mode 100644
index 0000000..4eb5eec
--- /dev/null
+++ b/cool-unix/uni_modules/cool-canvas/types/index.ts
@@ -0,0 +1,95 @@
+// 文本渲染参数
+export type TextRenderOptions = {
+ x: number;
+ y: number;
+ height?: number;
+ width?: number;
+ content: string;
+ color?: string;
+ fontSize?: number;
+ fontFamily?: string;
+ fontWeight?: "normal" | "bold" | "bolder" | "lighter" | number;
+ textAlign?: "left" | "right" | "center";
+ overflow?: "ellipsis";
+ lineClamp?: number;
+ letterSpace?: number;
+ lineHeight?: number;
+ opacity?: number;
+ scale?: number;
+ scaleX?: number;
+ scaleY?: number;
+ rotate?: number;
+ translateX?: number;
+ translateY?: number;
+};
+
+// 图片渲染参数
+export type ImageRenderOptions = {
+ x: number;
+ y: number;
+ height: number;
+ width: number;
+ url: string;
+ mode?:
+ | "scaleToFill"
+ | "aspectFit"
+ | "aspectFill"
+ | "center"
+ | "top"
+ | "bottom"
+ | "left"
+ | "right"
+ | "topLeft"
+ | "topRight"
+ | "bottomLeft"
+ | "bottomRight";
+ radius?: number;
+ opacity?: number;
+ scale?: number;
+ scaleX?: number;
+ scaleY?: number;
+ rotate?: number;
+ translateX?: number;
+ translateY?: number;
+};
+
+// 变换参数
+export type TransformOptions = {
+ scale?: number;
+ scaleX?: number;
+ scaleY?: number;
+ rotate?: number;
+ translateX?: number;
+ translateY?: number;
+};
+
+// 块渲染参数
+export type DivRenderOptions = {
+ x: number;
+ y: number;
+ height?: number;
+ width?: number;
+ radius?: number;
+ backgroundColor?: string;
+ borderWidth?: number;
+ borderColor?: string;
+ opacity?: number;
+ scale?: number;
+ scaleX?: number;
+ scaleY?: number;
+ rotate?: number;
+ translateX?: number;
+ translateY?: number;
+};
+
+// 裁剪图片参数
+export type CropImageResult = {
+ sx: number;
+ sy: number;
+ sw: number;
+ sh: number;
+ dx: number;
+ dy: number;
+ dw: number;
+ dh: number;
+};
diff --git a/cool-unix/uni_modules/cool-open-web/package.json b/cool-unix/uni_modules/cool-open-web/package.json
new file mode 100644
index 0000000..792dc11
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/package.json
@@ -0,0 +1,82 @@
+{
+ "id": "cool-open-web",
+ "displayName": "cool-open-web",
+ "version": "1.0.1",
+ "description": "cool-open-web",
+ "keywords": [
+ "cool-open-web"
+ ],
+ "repository": "",
+ "engines": {
+ "HBuilderX": "^3.9.0"
+ },
+ "dcloudext": {
+ "type": "uts",
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "",
+ "data": "",
+ "permissions": ""
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "u",
+ "aliyun": "u",
+ "alipay": "u"
+ },
+ "client": {
+ "Vue": {
+ "vue2": "u",
+ "vue3": "u"
+ },
+ "App": {
+ "app-android": "u",
+ "app-ios": "u"
+ },
+ "H5-mobile": {
+ "Safari": "u",
+ "Android Browser": "u",
+ "微信浏览器(Android)": "u",
+ "QQ浏览器(Android)": "u"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "u",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u",
+ "钉钉": "u",
+ "快手": "u",
+ "飞书": "u",
+ "京东": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
diff --git a/cool-unix/uni_modules/cool-open-web/readme.md b/cool-unix/uni_modules/cool-open-web/readme.md
new file mode 100644
index 0000000..f801555
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/readme.md
@@ -0,0 +1,17 @@
+# cool-open-web
+
+### 兼容性
+
+| IOS | Andriod | WEB | 小程序 |
+| ---- | ------- | ---- | ------ |
+| 支持 | 支持 | 支持 | 支持 |
+
+### 开发文档
+
+调用:
+
+```ts
+import { openWeb } from "@/uni_modules/cool-open-web";
+
+openWeb("https://cool-js.com/");
+```
diff --git a/cool-unix/uni_modules/cool-open-web/utssdk/app-android/config.json b/cool-unix/uni_modules/cool-open-web/utssdk/app-android/config.json
new file mode 100644
index 0000000..bf95925
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/utssdk/app-android/config.json
@@ -0,0 +1,3 @@
+{
+ "minSdkVersion": "21"
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-open-web/utssdk/app-android/index.uts b/cool-unix/uni_modules/cool-open-web/utssdk/app-android/index.uts
new file mode 100644
index 0000000..95ddd73
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/utssdk/app-android/index.uts
@@ -0,0 +1,93 @@
+// 导入Android相关类
+import Intent from "android.content.Intent"; // Android意图类,用于启动活动
+import Uri from "android.net.Uri"; // Android URI类,用于解析URL
+import Activity from "android.app.Activity"; // Android活动基类
+import Context from "android.content.Context"; // Android上下文类
+
+/**
+ * 打开网页URL函数
+ *
+ * @param url 要打开的网页地址,必须是有效的URL格式
+ * @returns 返回操作结果,true表示成功,false表示失败
+ *
+ * 功能说明:
+ * 1. 验证URL格式的合法性
+ * 2. 创建Intent意图,指定ACTION_VIEW动作
+ * 3. 获取当前Activity实例
+ * 4. 启动系统默认浏览器打开链接
+ * 5. 提供错误处理和异常捕获
+ *
+ * 注意事项:
+ * - URL必须包含协议头(如http://或https://)
+ * - 需要确保设备已安装浏览器应用
+ * - 在某些情况下可能需要网络权限
+ */
+export function openWeb(url: string): boolean {
+ try {
+ // 1. 参数验证:检查URL是否为空或无效
+ if (url.trim() == "") {
+ console.error("[cool-openurl] URL不能为空");
+ return false;
+ }
+
+ // 2. URL格式验证:确保包含协议头
+ let trimmedUrl = url.trim();
+ if (!trimmedUrl.startsWith("http://") && !trimmedUrl.startsWith("https://")) {
+ console.error("[cool-openurl] URL必须包含协议头(http://或https://)");
+ return false;
+ }
+
+ // 3. 解析URL:将字符串转换为Uri对象
+ let uri: Uri | null;
+ try {
+ uri = Uri.parse(trimmedUrl);
+ } catch (e: any) {
+ console.error("[cool-openurl] URL格式无效:" + trimmedUrl, e);
+ return false;
+ }
+
+ // 4. 验证URI是否解析成功
+ if (uri == null) {
+ console.error("[cool-openurl] URI解析失败:" + trimmedUrl);
+ return false;
+ }
+
+ // 5. 创建Intent意图
+ // ACTION_VIEW表示查看指定数据的通用动作,系统会选择合适的应用来处理
+ let intent = new Intent(Intent.ACTION_VIEW, uri);
+
+ // 6. 设置Intent标志
+ // FLAG_ACTIVITY_NEW_TASK:在新的任务栈中启动活动,确保浏览器在独立的任务中运行
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // 7. 获取当前Activity实例
+ let activity = UTSAndroid.getUniActivity();
+ if (activity == null) {
+ console.error("[cool-openurl] 无法获取当前Activity实例");
+ return false;
+ }
+
+ // 8. 类型安全:将获取的对象转换为Activity类型
+ let currentActivity = activity as Activity;
+
+ // 9. 验证系统中是否有能够处理该Intent的应用
+ let packageManager = currentActivity.getPackageManager();
+ let resolveInfos = packageManager.queryIntentActivities(intent, 0);
+
+ if (resolveInfos.size == 0) {
+ console.error("[cool-openurl] 系统中没有可以打开URL的应用");
+ return false;
+ }
+
+ // 10. 启动Intent,打开URL
+ currentActivity.startActivity(intent);
+
+ // 11. 记录成功日志
+ console.log("[cool-openurl] 成功打开URL:" + trimmedUrl);
+ return true;
+ } catch (error: any) {
+ // 12. 异常处理:捕获并记录所有可能的异常
+ console.error("[cool-openurl] 打开URL时发生异常:", error);
+ return false;
+ }
+}
diff --git a/cool-unix/uni_modules/cool-open-web/utssdk/app-harmony/index.uts b/cool-unix/uni_modules/cool-open-web/utssdk/app-harmony/index.uts
new file mode 100644
index 0000000..07213f0
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/utssdk/app-harmony/index.uts
@@ -0,0 +1,36 @@
+import { OpenWebNative } from "./openWeb.ets";
+
+/**
+ * 在鸿蒙系统中打开指定的网页URL
+ * @param url 要打开的网页地址,支持http、https等协议
+ * @returns 返回操作结果,true表示成功,false表示失败
+ */
+export function openWeb(url: string): boolean {
+ // 参数验证:检查URL是否为空或无效
+ if (url == null || url.trim() == "") {
+ console.error("openWeb: URL参数不能为空");
+ return false;
+ }
+
+ try {
+ let trimmedUrl = url.trim();
+
+ // 基本URL格式验证
+ if (!trimmedUrl.includes(".") || trimmedUrl.length < 4) {
+ console.error("openWeb: 无效的URL格式 -", trimmedUrl);
+ return false;
+ }
+
+ // 如果URL不包含协议,默认添加https://
+ if (!trimmedUrl.startsWith("http://") && !trimmedUrl.startsWith("https://") && !trimmedUrl.startsWith("//")) {
+ trimmedUrl = "https://" + trimmedUrl;
+ }
+
+ // 调用鸿蒙原生实现
+ return OpenWebNative.openUrl(trimmedUrl);
+ } catch (e) {
+ // 捕获可能的异常
+ console.error("openWeb: 打开URL时发生错误 -", e);
+ return false;
+ }
+}
diff --git a/cool-unix/uni_modules/cool-open-web/utssdk/app-harmony/openWeb.ets b/cool-unix/uni_modules/cool-open-web/utssdk/app-harmony/openWeb.ets
new file mode 100644
index 0000000..6d29cdf
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/utssdk/app-harmony/openWeb.ets
@@ -0,0 +1,45 @@
+import { Want, common } from '@kit.AbilityKit';
+import { BusinessError } from '@kit.BasicServicesKit';
+
+/**
+ * 原生打开网页控制类
+ * 用于在鸿蒙系统中打开网页URL
+ */
+export class OpenWebNative {
+ /**
+ * 打开指定的网页URL
+ * @param url 要打开的网页地址
+ * @returns 返回操作结果,true表示成功,false表示失败
+ */
+ static openUrl(url: string): boolean {
+ try {
+ // 获取应用上下文
+ const context = getContext() as common.UIAbilityContext;
+
+ // 构建Want对象,用于启动浏览器
+ const want: Want = {
+ action: 'ohos.want.action.viewData', // 查看数据的标准动作
+ entities: ['entity.system.browsable'], // 可浏览实体
+ uri: url // 目标URL
+ };
+
+ // 启动浏览器应用
+ context.startAbility(want)
+ .then(() => {
+ console.info(`成功打开URL: ${url}`);
+ })
+ .catch((error: BusinessError) => {
+ console.error(`打开URL失败: 错误码 ${error.code}, 错误信息 ${error.message}`);
+ });
+
+ return true;
+ } catch (err) {
+ // 捕获意外错误
+ const error: BusinessError = err as BusinessError;
+ console.error(
+ `发生意外错误: 错误码 ${error.code}, 错误信息 ${error.message}`
+ );
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-open-web/utssdk/app-ios/PrivacyInfo.xcprivacy b/cool-unix/uni_modules/cool-open-web/utssdk/app-ios/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000..5397adc
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/utssdk/app-ios/PrivacyInfo.xcprivacy
@@ -0,0 +1,14 @@
+
+
+
+
+ NSPrivacyAccessedAPITypes
+
+ NSPrivacyCollectedDataTypes
+
+ NSPrivacyTracking
+
+ NSPrivacyTrackingDomains
+
+
+
diff --git a/cool-unix/uni_modules/cool-open-web/utssdk/app-ios/config.json b/cool-unix/uni_modules/cool-open-web/utssdk/app-ios/config.json
new file mode 100644
index 0000000..3312828
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/utssdk/app-ios/config.json
@@ -0,0 +1,3 @@
+{
+ "deploymentTarget": "12"
+}
diff --git a/cool-unix/uni_modules/cool-open-web/utssdk/app-ios/index.uts b/cool-unix/uni_modules/cool-open-web/utssdk/app-ios/index.uts
new file mode 100644
index 0000000..7991785
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/utssdk/app-ios/index.uts
@@ -0,0 +1,57 @@
+import { URL } from "Foundation";
+import { UIApplication } from "UIKit";
+
+/**
+ * 在iOS设备上打开指定的网页URL
+ * @param url 要打开的网页地址,支持http、https、tel、mailto等协议
+ * @returns 返回操作结果,true表示成功,false表示失败
+ */
+export function openWeb(url: string): boolean {
+ // 参数验证:检查URL是否为空或无效
+ if (url == null || url.trim() == "") {
+ console.error("openWeb: URL参数不能为空");
+ return false;
+ }
+
+ try {
+ // 创建URL对象,用于验证URL格式的有效性
+ let href = new URL((string = url.trim()));
+
+ // 检查URL对象是否创建成功
+ if (href == null) {
+ console.error("openWeb: 无效的URL格式 -", url);
+ return false;
+ }
+
+ // 检查系统版本,iOS 16.0及以上版本使用新的API
+ if (UTSiOS.available("iOS 16.0, *")) {
+ // iOS 16.0+ 使用 open(_:options:completionHandler:) 方法
+ // 先检查系统是否支持打开该URL
+ if (UIApplication.shared.canOpenURL(href!)) {
+ // 使用新API打开URL,传入空的options和completionHandler
+ UIApplication.shared.open(href!, (options = new Map()), (completionHandler = nil));
+ console.log("openWeb: 成功使用新API打开URL -", url);
+ return true;
+ } else {
+ console.warn("openWeb: 系统不支持打开该URL协议 -", url);
+ return false;
+ }
+ } else {
+ // iOS 16.0以下版本使用已弃用但仍可用的 openURL 方法
+ // 先检查系统是否支持打开该URL
+ if (UIApplication.shared.canOpenURL(href!)) {
+ // 使用传统API打开URL
+ UIApplication.shared.openURL(href!);
+ console.log("openWeb: 成功使用传统API打开URL -", url);
+ return true;
+ } else {
+ console.warn("openWeb: 系统不支持打开该URL协议 -", url);
+ return false;
+ }
+ }
+ } catch (e) {
+ // 捕获可能的异常,如URL格式错误等
+ console.error("openWeb: 打开URL时发生错误 -", e);
+ return false;
+ }
+}
diff --git a/cool-unix/uni_modules/cool-open-web/utssdk/mp-weixin/index.uts b/cool-unix/uni_modules/cool-open-web/utssdk/mp-weixin/index.uts
new file mode 100644
index 0000000..d991ffa
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/utssdk/mp-weixin/index.uts
@@ -0,0 +1,49 @@
+/**
+ * 在微信小程序中打开指定的网页URL
+ * 使用微信小程序的wx.openUrl API
+ * @param url 要打开的网页地址,必须是https协议
+ * @returns 返回操作结果,true表示成功,false表示失败
+ */
+export function openWeb(url: string): boolean {
+ // 参数验证:检查URL是否为空或无效
+ if (url == null || url.trim() == "") {
+ console.error("openWeb: URL参数不能为空");
+ return false;
+ }
+
+ try {
+ let trimmedUrl = url.trim();
+
+ // 微信小程序要求必须是https协议
+ if (!trimmedUrl.startsWith("https://")) {
+ console.error("openWeb: 微信小程序只支持https协议的URL -", trimmedUrl);
+ return false;
+ }
+
+ // 基本URL格式验证
+ if (!trimmedUrl.includes(".") || trimmedUrl.length < 12) { // https:// 最少8个字符 + 域名最少4个字符
+ console.error("openWeb: 无效的URL格式 -", trimmedUrl);
+ return false;
+ }
+
+ // 使用微信小程序的API打开URL
+ wx.openUrl({
+ url: trimmedUrl,
+ success: (res: any) => {
+ console.log("openWeb: 成功打开URL -", trimmedUrl);
+ },
+ fail: (err: any) => {
+ console.error("openWeb: 打开URL失败 -", err);
+ },
+ complete: (res: any) => {
+ console.log("openWeb: 操作完成 -", res);
+ }
+ });
+
+ return true;
+ } catch (e) {
+ // 捕获可能的异常
+ console.error("openWeb: 打开URL时发生错误 -", e);
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-open-web/utssdk/web/index.uts b/cool-unix/uni_modules/cool-open-web/utssdk/web/index.uts
new file mode 100644
index 0000000..413e5db
--- /dev/null
+++ b/cool-unix/uni_modules/cool-open-web/utssdk/web/index.uts
@@ -0,0 +1,37 @@
+/**
+ * 在Web浏览器中打开指定的网页URL
+ * @param url 要打开的网页地址,支持http、https等协议
+ * @returns 返回操作结果,true表示成功,false表示失败
+ */
+export function openWeb(url: string): boolean {
+ // 参数验证:检查URL是否为空或无效
+ if (url == null || url.trim() == "") {
+ console.error("openWeb: URL参数不能为空");
+ return false;
+ }
+
+ try {
+ let trimmedUrl = url.trim();
+
+ // 基本URL格式验证
+ if (!trimmedUrl.includes(".") || trimmedUrl.length < 4) {
+ console.error("openWeb: 无效的URL格式 -", trimmedUrl);
+ return false;
+ }
+
+ // 如果URL不包含协议,默认添加https://
+ if (!trimmedUrl.startsWith("http://") && !trimmedUrl.startsWith("https://") && !trimmedUrl.startsWith("//")) {
+ trimmedUrl = "https://" + trimmedUrl;
+ }
+
+ // 在当前窗口中打开URL
+ location.href = trimmedUrl;
+
+ console.log("openWeb: 成功打开URL -", trimmedUrl);
+ return true;
+ } catch (e) {
+ // 捕获可能的异常
+ console.error("openWeb: 打开URL时发生错误 -", e);
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-share/index.d.ts b/cool-unix/uni_modules/cool-share/index.d.ts
new file mode 100644
index 0000000..4dee4f9
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/index.d.ts
@@ -0,0 +1,10 @@
+declare module "@/uni_modules/cool-share" {
+ export function shareWithSystem(options: {
+ type: "text" | "image" | "file" | "link" | "video" | "audio";
+ title?: string;
+ summary?: string;
+ url?: string;
+ success?: () => void;
+ fail?: (error: string) => void;
+ }): void;
+}
diff --git a/cool-unix/uni_modules/cool-share/package.json b/cool-unix/uni_modules/cool-share/package.json
new file mode 100644
index 0000000..5e917f3
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/package.json
@@ -0,0 +1,84 @@
+{
+ "id": "cool-share",
+ "displayName": "cool-share",
+ "version": "1.0.0",
+ "description": "cool-share",
+ "keywords": [
+ "cool-share",
+ "share",
+ "系统分享"
+ ],
+ "repository": "",
+ "engines": {
+ "HBuilderX": "^4.75"
+ },
+ "dcloudext": {
+ "type": "uts",
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "",
+ "data": "",
+ "permissions": ""
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "u",
+ "aliyun": "u",
+ "alipay": "u"
+ },
+ "client": {
+ "Vue": {
+ "vue2": "u",
+ "vue3": "u"
+ },
+ "App": {
+ "app-android": "u",
+ "app-ios": "u"
+ },
+ "H5-mobile": {
+ "Safari": "u",
+ "Android Browser": "u",
+ "微信浏览器(Android)": "u",
+ "QQ浏览器(Android)": "u"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "u",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u",
+ "钉钉": "u",
+ "快手": "u",
+ "飞书": "u",
+ "京东": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
diff --git a/cool-unix/uni_modules/cool-share/utssdk/app-android/AndroidManifest.xml b/cool-unix/uni_modules/cool-share/utssdk/app-android/AndroidManifest.xml
new file mode 100644
index 0000000..494ebb7
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/utssdk/app-android/AndroidManifest.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-share/utssdk/app-android/config.json b/cool-unix/uni_modules/cool-share/utssdk/app-android/config.json
new file mode 100644
index 0000000..f3189d0
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/utssdk/app-android/config.json
@@ -0,0 +1,3 @@
+{
+ "minSdkVersion": "21"
+}
diff --git a/cool-unix/uni_modules/cool-share/utssdk/app-android/index.uts b/cool-unix/uni_modules/cool-share/utssdk/app-android/index.uts
new file mode 100644
index 0000000..ce49450
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/utssdk/app-android/index.uts
@@ -0,0 +1,459 @@
+import Intent from "android.content.Intent";
+import Uri from "android.net.Uri";
+import Context from "android.content.Context";
+import File from "java.io.File";
+import FileProvider from "androidx.core.content.FileProvider";
+import { ShareWithSystemOptions } from "../interface.uts";
+
+/**
+ * 分享类型枚举
+ */
+const ShareType = {
+ TEXT: "text", // 纯文本分享
+ IMAGE: "image", // 图片分享
+ VIDEO: "video", // 视频分享
+ AUDIO: "audio", // 音频分享
+ FILE: "file", // 文件分享
+ LINK: "link" // 链接分享
+};
+
+/**
+ * MIME 类型映射
+ */
+const MimeTypes = {
+ IMAGE: "image/*",
+ VIDEO: "video/*",
+ AUDIO: "audio/*",
+ TEXT: "text/plain",
+ PDF: "application/pdf",
+ WORD: "application/msword",
+ EXCEL: "application/vnd.ms-excel",
+ PPT: "application/vnd.ms-powerpoint",
+ ZIP: "application/zip",
+ DEFAULT: "*/*"
+};
+
+/**
+ * 判断是否为网络 URL
+ * @param url 地址
+ * @returns 是否为网络 URL
+ */
+function isNetworkUrl(url: string): boolean {
+ return url.startsWith("http://") || url.startsWith("https://");
+}
+
+/**
+ * 根据文件路径获取 File 对象
+ * 按优先级尝试多种路径解析方式
+ * @param filePath 文件路径
+ * @returns File 对象或 null
+ */
+function getFileFromPath(filePath: string): File | null {
+ // 1. 尝试直接路径
+ let file = new File(filePath);
+ if (file.exists()) {
+ return file;
+ }
+
+ // 2. 尝试资源路径
+ file = new File(UTSAndroid.getResourcePath(filePath));
+ if (file.exists()) {
+ return file;
+ }
+
+ // 3. 尝试绝对路径转换
+ file = new File(UTSAndroid.convert2AbsFullPath(filePath));
+ if (file.exists()) {
+ return file;
+ }
+
+ return null;
+}
+
+/**
+ * 根据文件扩展名获取 MIME 类型
+ * @param filePath 文件路径
+ * @param defaultType 默认类型
+ * @returns MIME 类型字符串
+ */
+function getMimeTypeByPath(filePath: string, defaultType: string): string {
+ const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
+
+ if (ext == "") {
+ return defaultType;
+ }
+
+ // 常见文件类型映射
+ const mimeMap = {
+ // 文档类型
+ pdf: MimeTypes["PDF"],
+ doc: MimeTypes["WORD"],
+ docx: MimeTypes["WORD"],
+ xls: MimeTypes["EXCEL"],
+ xlsx: MimeTypes["EXCEL"],
+ ppt: MimeTypes["PPT"],
+ pptx: MimeTypes["PPT"],
+ // 压缩包类型
+ zip: MimeTypes["ZIP"],
+ rar: "application/x-rar-compressed",
+ "7z": "application/x-7z-compressed",
+ tar: "application/x-tar",
+ gz: "application/gzip"
+ };
+
+ return (mimeMap[ext] as string) ?? defaultType;
+}
+
+/**
+ * 下载网络文件到本地缓存
+ * @param url 网络地址
+ * @param success 成功回调,返回本地文件路径
+ * @param fail 失败回调
+ */
+function downloadNetworkFile(
+ url: string,
+ success: (localPath: string) => void,
+ fail: (error: string) => void
+): void {
+ uni.downloadFile({
+ url: url,
+ success: (res) => {
+ if (res.statusCode == 200) {
+ success(res.tempFilePath);
+ } else {
+ fail("下载失败,状态码: " + res.statusCode);
+ }
+ },
+ fail: (err) => {
+ fail("下载失败: " + (err.errMsg ?? "未知错误"));
+ }
+ });
+}
+
+/**
+ * 创建文件 Uri
+ * @param filePath 文件路径(支持本地路径和网络 URL)
+ * @param success 成功回调
+ * @param fail 失败回调
+ */
+function createFileUriAsync(
+ filePath: string,
+ success: (uri: Uri) => void,
+ fail: (error: string) => void
+): void {
+ // 创建文件Uri,支持网络和本地文件。网络文件先下载到本地缓存,再获取Uri。
+ const handleFileToUri = (localPath: string) => {
+ const file = getFileFromPath(localPath);
+ if (file == null) {
+ fail(`文件不存在: ${localPath}`);
+ return;
+ }
+ const context = UTSAndroid.getAppContext();
+ if (context == null) {
+ fail("无法获取App Context");
+ return;
+ }
+ const authority = context.getPackageName() + ".fileprovider";
+ const uri = FileProvider.getUriForFile(context, authority, file);
+ success(uri);
+ };
+
+ if (isNetworkUrl(filePath)) {
+ // 网络路径需先下载,下载完成后处理
+ downloadNetworkFile(filePath, handleFileToUri, fail);
+ } else {
+ // 本地文件直接处理
+ handleFileToUri(filePath);
+ }
+}
+
+/**
+ * 创建图片分享 Intent(异步)
+ * @param url 图片路径(支持本地路径和网络 URL)
+ * @param title 分享标题
+ * @param success 成功回调
+ * @param fail 失败回调
+ */
+function createImageShareIntent(
+ url: string,
+ title: string,
+ success: (intent: Intent) => void,
+ fail: (error: string) => void
+): void {
+ if (url == "") {
+ fail("图片路径不能为空");
+ return;
+ }
+
+ createFileUriAsync(
+ url,
+ (uri: Uri) => {
+ const intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(MimeTypes["IMAGE"] as string);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ intent.putExtra(Intent.EXTRA_TITLE, title);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ success(intent);
+ },
+ (error: string) => {
+ fail(error);
+ }
+ );
+}
+
+/**
+ * 创建视频分享 Intent(异步)
+ * @param url 视频路径(支持本地路径和网络 URL)
+ * @param title 分享标题
+ * @param success 成功回调
+ * @param fail 失败回调
+ */
+function createVideoShareIntent(
+ url: string,
+ title: string,
+ success: (intent: Intent) => void,
+ fail: (error: string) => void
+): void {
+ if (url == "") {
+ fail("视频路径不能为空");
+ return;
+ }
+
+ createFileUriAsync(
+ url,
+ (uri: Uri) => {
+ const intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(MimeTypes["VIDEO"] as string);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ intent.putExtra(Intent.EXTRA_TITLE, title);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ success(intent);
+ },
+ (error: string) => {
+ fail(error);
+ }
+ );
+}
+
+/**
+ * 创建音频分享 Intent(异步)
+ * @param url 音频路径(支持本地路径和网络 URL)
+ * @param title 分享标题
+ * @param success 成功回调
+ * @param fail 失败回调
+ */
+function createAudioShareIntent(
+ url: string,
+ title: string,
+ success: (intent: Intent) => void,
+ fail: (error: string) => void
+): void {
+ if (url == "") {
+ fail("音频路径不能为空");
+ return;
+ }
+
+ createFileUriAsync(
+ url,
+ (uri: Uri) => {
+ const intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(MimeTypes["AUDIO"] as string);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ intent.putExtra(Intent.EXTRA_TITLE, title);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ success(intent);
+ },
+ (error: string) => {
+ fail(error);
+ }
+ );
+}
+
+/**
+ * 创建文件分享 Intent(异步)
+ * @param filePath 文件路径(支持本地路径和网络 URL)
+ * @param title 分享标题
+ * @param success 成功回调
+ * @param fail 失败回调
+ */
+function createFileShareIntent(
+ filePath: string,
+ title: string,
+ success: (intent: Intent) => void,
+ fail: (error: string) => void
+): void {
+ if (filePath == "") {
+ fail("文件路径不能为空");
+ return;
+ }
+
+ createFileUriAsync(
+ filePath,
+ (uri: Uri) => {
+ // 根据文件扩展名确定 MIME 类型
+ const mimeType = getMimeTypeByPath(filePath, MimeTypes["DEFAULT"] as string);
+
+ const intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(mimeType);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ intent.putExtra(Intent.EXTRA_TITLE, title);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ success(intent);
+ },
+ (error: string) => {
+ fail(error);
+ }
+ );
+}
+
+/**
+ * 创建链接分享 Intent
+ * @param url 链接地址
+ * @param title 分享标题
+ * @param summary 分享描述
+ * @param success 成功回调
+ * @param fail 失败回调
+ */
+function createLinkShareIntent(
+ url: string,
+ title: string,
+ summary: string,
+ success: (intent: Intent) => void,
+ fail: (error: string) => void
+): void {
+ if (url == "") {
+ fail("链接地址不能为空");
+ return;
+ }
+
+ // 组合分享内容:标题 + 描述 + 链接
+ let content = "";
+ if (title != "") {
+ content = title;
+ }
+ if (summary != "") {
+ content = content == "" ? summary : content + "\n" + summary;
+ }
+ if (url != "") {
+ content = content == "" ? url : content + "\n" + url;
+ }
+
+ const intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(MimeTypes["TEXT"] as string);
+ intent.putExtra(Intent.EXTRA_TEXT, content);
+
+ success(intent);
+}
+
+/**
+ * 创建文本分享 Intent
+ * @param title 分享标题
+ * @param summary 分享描述
+ * @param url 附加链接(可选)
+ * @param success 成功回调
+ */
+function createTextShareIntent(
+ title: string,
+ summary: string,
+ url: string,
+ success: (intent: Intent) => void
+): void {
+ // 组合分享内容
+ let content = "";
+ if (title != "") {
+ content = title;
+ }
+ if (summary != "") {
+ content = content == "" ? summary : content + "\n" + summary;
+ }
+ if (url != "") {
+ content = content == "" ? url : content + "\n" + url;
+ }
+
+ // 如果内容为空,使用默认文本
+ if (content == "") {
+ content = "分享内容";
+ }
+
+ const intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(MimeTypes["TEXT"] as string);
+ intent.putExtra(Intent.EXTRA_TEXT, content);
+
+ success(intent);
+}
+
+/**
+ * 启动分享 Activity
+ * @param intent 分享 Intent
+ * @param title 选择器标题
+ * @param success 成功回调
+ * @param fail 失败回调
+ */
+function startShareActivity(
+ intent: Intent,
+ title: string,
+ success: () => void,
+ fail: (error: string) => void
+): void {
+ const chooserTitle = title != "" ? title : "选择分享方式";
+ const chooser = Intent.createChooser(intent, chooserTitle);
+
+ try {
+ UTSAndroid.getUniActivity()!.startActivity(chooser);
+ success();
+ } catch (e: Exception) {
+ const errorMsg = e.message ?? "分享失败";
+ fail(errorMsg);
+ }
+}
+
+/**
+ * 系统分享功能
+ * @param options 分享参数
+ * @param options.type 分享类型: text(文本) | image(图片) | video(视频) | audio(音频) | file(文件) | link(链接)
+ * @param options.title 分享标题
+ * @param options.summary 分享描述/内容
+ * @param options.url 资源路径(图片/视频/音频/文件路径或链接地址,支持本地路径和网络 URL)
+ * @param options.success 成功回调
+ * @param options.fail 失败回调
+ */
+export function shareWithSystem(options: ShareWithSystemOptions): void {
+ const type = options.type;
+ const title = options.title ?? "";
+ const summary = options.summary ?? "";
+ const url = options.url ?? "";
+
+ // 成功和失败回调
+ const onSuccess = (intent: Intent) => {
+ startShareActivity(
+ intent,
+ title,
+ () => {
+ options.success?.();
+ },
+ (error: string) => {
+ options.fail?.(error);
+ }
+ );
+ };
+
+ const onFail = (error: string) => {
+ options.fail?.(error);
+ };
+
+ // 根据分享类型创建对应的 Intent
+ if (type == ShareType["IMAGE"]) {
+ createImageShareIntent(url, title, onSuccess, onFail);
+ } else if (type == ShareType["VIDEO"]) {
+ createVideoShareIntent(url, title, onSuccess, onFail);
+ } else if (type == ShareType["AUDIO"]) {
+ createAudioShareIntent(url, title, onSuccess, onFail);
+ } else if (type == ShareType["FILE"]) {
+ createFileShareIntent(url, title, onSuccess, onFail);
+ } else if (type == ShareType["LINK"]) {
+ createLinkShareIntent(url, title, summary, onSuccess, onFail);
+ } else {
+ // 默认为文本分享
+ createTextShareIntent(title, summary, url, onSuccess);
+ }
+}
diff --git a/cool-unix/uni_modules/cool-share/utssdk/app-android/res/xml/file_paths.xml b/cool-unix/uni_modules/cool-share/utssdk/app-android/res/xml/file_paths.xml
new file mode 100644
index 0000000..ff3705f
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/utssdk/app-android/res/xml/file_paths.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-share/utssdk/app-harmony/index.uts b/cool-unix/uni_modules/cool-share/utssdk/app-harmony/index.uts
new file mode 100644
index 0000000..c5dc9fb
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/utssdk/app-harmony/index.uts
@@ -0,0 +1,13 @@
+import { ShareWithSystemOptions } from "../interface.uts";
+import { share } from "./share.ets";
+
+export function shareWithSystem(options: ShareWithSystemOptions) {
+ share(
+ options.type,
+ options.title ?? "",
+ options.summary ?? "",
+ options.url ?? "",
+ options.success ?? (() => {}),
+ options.fail ?? (() => {})
+ );
+}
diff --git a/cool-unix/uni_modules/cool-share/utssdk/app-harmony/share.ets b/cool-unix/uni_modules/cool-share/utssdk/app-harmony/share.ets
new file mode 100644
index 0000000..78c7bbc
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/utssdk/app-harmony/share.ets
@@ -0,0 +1,265 @@
+import { UTSHarmony } from '@dcloudio/uni-app-x-runtime';
+import { systemShare } from '@kit.ShareKit';
+import { uniformTypeDescriptor as utd } from '@kit.ArkData';
+import { common } from '@kit.AbilityKit';
+import { fileUri } from '@kit.CoreFileKit';
+import { BusinessError } from '@kit.BasicServicesKit';
+
+/**
+ * 分享类型枚举
+ */
+enum ShareType {
+ TEXT = "text", // 纯文本分享
+ IMAGE = "image", // 图片分享
+ VIDEO = "video", // 视频分享
+ AUDIO = "audio", // 音频分享
+ FILE = "file", // 文件分享
+ LINK = "link" // 链接分享
+}
+
+/**
+ * 根据文件路径获取统一数据类型标识符
+ * @param filePath 文件路径
+ * @param defaultType 默认数据类型
+ * @returns 统一数据类型标识符
+ */
+function getUtdTypeByPath(filePath: string, defaultType: string): string {
+ const ext = filePath?.split('.')?.pop()?.toLowerCase() ?? '';
+ if (ext === '') {
+ return defaultType;
+ }
+ return utd.getUniformDataTypeByFilenameExtension('.' + ext, defaultType);
+}
+
+/**
+ * 创建图片分享数据
+ * @param url 图片路径(支持本地路径和网络 URL)
+ * @param title 分享标题
+ * @param summary 分享描述
+ * @returns 分享数据对象
+ */
+function createImageShareData(url: string, title: string, summary: string): systemShare.SharedData | null {
+ if (url === '') {
+ return null;
+ }
+
+ const filePath = UTSHarmony.getResourcePath(url);
+ const utdTypeId = getUtdTypeByPath(filePath, utd.UniformDataType.IMAGE);
+
+ return new systemShare.SharedData({
+ utd: utdTypeId,
+ uri: fileUri.getUriFromPath(filePath),
+ title: title,
+ description: summary,
+ });
+}
+
+/**
+ * 创建视频分享数据
+ * @param url 视频路径(支持本地路径和网络 URL)
+ * @param title 分享标题
+ * @param summary 分享描述
+ * @returns 分享数据对象
+ */
+function createVideoShareData(url: string, title: string, summary: string): systemShare.SharedData | null {
+ if (url === '') {
+ return null;
+ }
+
+ const filePath = UTSHarmony.getResourcePath(url);
+ const utdTypeId = getUtdTypeByPath(filePath, utd.UniformDataType.VIDEO);
+
+ return new systemShare.SharedData({
+ utd: utdTypeId,
+ uri: fileUri.getUriFromPath(filePath),
+ title: title,
+ description: summary,
+ });
+}
+
+/**
+ * 创建音频分享数据
+ * @param url 音频路径(支持本地路径和网络 URL)
+ * @param title 分享标题
+ * @param summary 分享描述
+ * @returns 分享数据对象
+ */
+function createAudioShareData(url: string, title: string, summary: string): systemShare.SharedData | null {
+ if (url === '') {
+ return null;
+ }
+
+ const filePath = UTSHarmony.getResourcePath(url);
+ const utdTypeId = getUtdTypeByPath(filePath, utd.UniformDataType.AUDIO);
+
+ return new systemShare.SharedData({
+ utd: utdTypeId,
+ uri: fileUri.getUriFromPath(filePath),
+ title: title,
+ description: summary,
+ });
+}
+
+/**
+ * 创建文件分享数据
+ * @param filePath 文件路径(支持本地路径和网络 URL)
+ * @param title 分享标题
+ * @param summary 分享描述
+ * @returns 分享数据对象
+ */
+function createFileShareData(filePath: string, title: string, summary: string): systemShare.SharedData | null {
+ if (filePath === '') {
+ return null;
+ }
+
+ const resourcePath = UTSHarmony.getResourcePath(filePath);
+ const ext = resourcePath?.split('.')?.pop()?.toLowerCase() ?? '';
+
+ // 根据文件扩展名确定数据类型
+ let utdType = utd.UniformDataType.FILE;
+ let utdTypeId = '';
+
+ // 支持常见的文件类型
+ switch (ext) {
+ case 'zip':
+ case 'rar':
+ case '7z':
+ case 'tar':
+ case 'gz':
+ utdType = utd.UniformDataType.ARCHIVE;
+ break;
+ case 'pdf':
+ utdType = utd.UniformDataType.PDF;
+ break;
+ case 'doc':
+ case 'docx':
+ utdType = utd.UniformDataType.WORD_DOC;
+ break;
+ case 'xls':
+ case 'xlsx':
+ utdType = utd.UniformDataType.EXCEL;
+ break;
+ case 'ppt':
+ case 'pptx':
+ utdType = utd.UniformDataType.PPT;
+ break;
+ default:
+ utdType = utd.UniformDataType.FILE;
+ break;
+ }
+
+ utdTypeId = utd.getUniformDataTypeByFilenameExtension('.' + ext, utdType);
+
+ return new systemShare.SharedData({
+ utd: utdTypeId,
+ uri: fileUri.getUriFromPath(resourcePath),
+ title: title,
+ description: summary,
+ });
+}
+
+/**
+ * 创建链接分享数据
+ * @param url 链接地址
+ * @param title 分享标题
+ * @param summary 分享描述
+ * @returns 分享数据对象
+ */
+function createLinkShareData(url: string, title: string, summary: string): systemShare.SharedData {
+ return new systemShare.SharedData({
+ utd: utd.UniformDataType.HYPERLINK,
+ title: title,
+ content: url,
+ description: summary
+ });
+}
+
+/**
+ * 创建文本分享数据
+ * @param title 分享标题
+ * @param summary 分享内容
+ * @returns 分享数据对象
+ */
+function createTextShareData(title: string, summary: string): systemShare.SharedData {
+ return new systemShare.SharedData({
+ utd: utd.UniformDataType.TEXT,
+ title: title,
+ content: summary
+ });
+}
+
+/**
+ * 系统分享功能
+ * @param options 分享参数
+ * @param options.type 分享类型: text(文本) | image(图片) | video(视频) | audio(音频) | file(文件) | link(链接)
+ * @param options.title 分享标题
+ * @param options.summary 分享描述/内容
+ * @param options.url 资源路径(图片/视频/音频/文件路径或链接地址,支持本地路径和网络 URL)
+ * @param options.success 成功回调
+ * @param options.fail 失败回调
+ */
+export function share(type: string, title: string, summary: string, url: string, success: () => void, fail: (error: string) => void): void {
+ // 获取UI上下文
+ const uiContext: UIContext = UTSHarmony.getCurrentWindow()?.getUIContext();
+ const context: common.UIAbilityContext = uiContext.getHostContext() as common.UIAbilityContext;
+
+ // 根据分享类型创建分享数据
+ let shareData: systemShare.SharedData | null = null;
+ let errorMsg = '';
+
+ switch (type) {
+ case ShareType.IMAGE:
+ shareData = createImageShareData(url, title, summary);
+ errorMsg = '图片路径不能为空';
+ break;
+
+ case ShareType.VIDEO:
+ shareData = createVideoShareData(url, title, summary);
+ errorMsg = '视频路径不能为空';
+ break;
+
+ case ShareType.AUDIO:
+ shareData = createAudioShareData(url, title, summary);
+ errorMsg = '音频路径不能为空';
+ break;
+
+ case ShareType.FILE:
+ shareData = createFileShareData(url, title, summary);
+ errorMsg = '文件路径不能为空';
+ break;
+
+ case ShareType.LINK:
+ shareData = createLinkShareData(url, title, summary);
+ break;
+
+ default:
+ // 默认为文本分享
+ shareData = createTextShareData(title, summary);
+ errorMsg = '分享内容不能为空';
+ break;
+ }
+
+ // 验证分享数据
+ if (shareData === null) {
+ fail(errorMsg);
+ return;
+ }
+
+ // 创建分享控制器
+ const controller: systemShare.ShareController = new systemShare.ShareController(shareData);
+
+ // 显示分享面板,配置分享选项
+ controller.show(context, {
+ selectionMode: systemShare.SelectionMode.SINGLE, // 单选模式
+ previewMode: systemShare.SharePreviewMode.DEFAULT, // 默认预览模式
+ })
+ .then(() => {
+ // 分享成功
+ success();
+ })
+ .catch((error: BusinessError) => {
+ // 分享失败,返回错误信息
+ const errorMessage = error?.message ?? '分享失败';
+ fail(errorMessage);
+ });
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-share/utssdk/app-ios/PrivacyInfo.xcprivacy b/cool-unix/uni_modules/cool-share/utssdk/app-ios/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000..5397adc
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/utssdk/app-ios/PrivacyInfo.xcprivacy
@@ -0,0 +1,14 @@
+
+
+
+
+ NSPrivacyAccessedAPITypes
+
+ NSPrivacyCollectedDataTypes
+
+ NSPrivacyTracking
+
+ NSPrivacyTrackingDomains
+
+
+
diff --git a/cool-unix/uni_modules/cool-share/utssdk/app-ios/config.json b/cool-unix/uni_modules/cool-share/utssdk/app-ios/config.json
new file mode 100644
index 0000000..74ed9c6
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/utssdk/app-ios/config.json
@@ -0,0 +1,3 @@
+{
+ "deploymentTarget": "12"
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-share/utssdk/app-ios/index.uts b/cool-unix/uni_modules/cool-share/utssdk/app-ios/index.uts
new file mode 100644
index 0000000..8a30f58
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/utssdk/app-ios/index.uts
@@ -0,0 +1,287 @@
+import { UIActivityViewController, UIImage } from "UIKit";
+import { URL, Data } from "Foundation";
+import { ShareWithSystemOptions } from "../interface.uts";
+
+/**
+ * 分享类型枚举
+ */
+const ShareType = {
+ TEXT: "text", // 纯文本分享
+ IMAGE: "image", // 图片分享
+ VIDEO: "video", // 视频分享
+ AUDIO: "audio", // 音频分享
+ FILE: "file", // 文件分享
+ LINK: "link" // 链接分享
+};
+
+/**
+ * 判断是否为网络 URL
+ * @param url 地址
+ * @returns 是否为网络 URL
+ */
+function isNetworkUrl(url: string): boolean {
+ return url.startsWith("http://") || url.startsWith("https://");
+}
+
+/**
+ * 下载网络文件到本地缓存
+ * @param url 网络地址
+ * @param success 成功回调,返回本地文件路径
+ * @param fail 失败回调
+ */
+function downloadNetworkFile(
+ url: string,
+ success: (localPath: string) => void,
+ fail: (error: string) => void
+): void {
+ uni.downloadFile({
+ url: url,
+ success: (res) => {
+ if (res.statusCode == 200) {
+ success(res.tempFilePath);
+ } else {
+ fail(`下载失败,状态码: ${res.statusCode}`);
+ }
+ },
+ fail: (err) => {
+ fail(`下载失败: ${err.errMsg ?? "未知错误"}`);
+ }
+ });
+}
+
+/**
+ * 处理文件路径并加载数据
+ * @param filePath 文件路径
+ * @returns Data 对象或 null
+ */
+function loadFileData(filePath: string): Data | null {
+ const absolutePath = UTSiOS.convert2AbsFullPath(filePath);
+ const fileURL = new URL((fileURLWithPath = absolutePath));
+ const data = UTSiOS.try(new Data((contentsOf = fileURL)), "?");
+ return data;
+}
+
+/**
+ * 创建文本分享内容
+ * @param title 标题
+ * @param summary 描述
+ * @param url 链接
+ * @returns 分享内容数组
+ */
+function createTextShareItems(title: string, summary: string, url: string): any[] {
+ // 组合分享内容
+ let content = "";
+ if (title != "") {
+ content = title;
+ }
+ if (summary != "") {
+ content = content == "" ? summary : content + "\n" + summary;
+ }
+ if (url != "") {
+ content = content == "" ? url : content + "\n" + url;
+ }
+
+ // 如果内容为空,使用默认文本
+ if (content == "") {
+ content = "分享内容";
+ }
+
+ return [content];
+}
+
+/**
+ * 创建图片分享内容
+ * @param url 图片路径
+ * @param success 成功回调
+ * @param fail 失败回调
+ */
+function createImageShareItems(
+ url: string,
+ success: (items: any[]) => void,
+ fail: (error: string) => void
+): void {
+ if (url == "") {
+ fail("图片路径不能为空");
+ return;
+ }
+
+ const handleImagePath = (localPath: string) => {
+ const absolutePath = UTSiOS.convert2AbsFullPath(localPath);
+ const image = new UIImage((contentsOfFile = absolutePath));
+
+ if (image == null) {
+ fail("图片加载失败");
+ return;
+ }
+
+ success([image]);
+ };
+
+ if (isNetworkUrl(url)) {
+ // 网络图片先下载
+ downloadNetworkFile(url, handleImagePath, fail);
+ } else {
+ // 本地图片直接处理
+ handleImagePath(url);
+ }
+}
+
+/**
+ * 创建文件分享内容(视频、音频、文件)
+ * @param filePath 文件路径
+ * @param success 成功回调
+ * @param fail 失败回调
+ */
+function createFileShareItems(
+ filePath: string,
+ success: (items: any[]) => void,
+ fail: (error: string) => void
+): void {
+ if (filePath == "") {
+ fail("文件路径不能为空");
+ return;
+ }
+
+ const handleFilePath = (localPath: string) => {
+ const data = loadFileData(localPath);
+
+ if (data == null) {
+ fail("文件加载失败");
+ return;
+ }
+
+ const absolutePath = UTSiOS.convert2AbsFullPath(localPath);
+ const fileURL = new URL.init((fileURLWithPath = absolutePath));
+
+ success([data, fileURL]);
+ };
+
+ if (isNetworkUrl(filePath)) {
+ // 网络文件先下载
+ downloadNetworkFile(filePath, handleFilePath, fail);
+ } else {
+ // 本地文件直接处理
+ handleFilePath(filePath);
+ }
+}
+
+/**
+ * 启动系统分享界面
+ * @param items 分享内容数组
+ * @param success 成功回调
+ * @param fail 失败回调
+ */
+function presentShareController(
+ items: any[],
+ success: () => void,
+ fail: (error: string) => void
+): void {
+ DispatchQueue.main.async(
+ (execute = (): void => {
+ const activityViewController = new UIActivityViewController(
+ (activityItems = items),
+ (applicationActivities = nil)
+ );
+
+ const currentVC = UTSiOS.getCurrentViewController();
+ if (currentVC == null) {
+ fail("无法获取当前视图控制器");
+ return;
+ }
+
+ currentVC.present(
+ activityViewController,
+ (animated = true),
+ (completion = () => {
+ success();
+ })
+ );
+ })
+ );
+}
+
+/**
+ * 系统分享功能
+ * @param options 分享参数
+ * @param options.type 分享类型: text(文本) | image(图片) | video(视频) | audio(音频) | file(文件) | link(链接)
+ * @param options.title 分享标题
+ * @param options.summary 分享描述/内容
+ * @param options.url 资源路径(图片/视频/音频/文件路径或链接地址,支持本地路径和网络 URL)
+ * @param options.success 成功回调
+ * @param options.fail 失败回调
+ */
+export function shareWithSystem(options: ShareWithSystemOptions): void {
+ const type = options.type;
+ const title = options.title ?? "";
+ const summary = options.summary ?? "";
+ const url = options.url ?? "";
+
+ // 根据分享类型创建对应的内容
+ if (type == (ShareType["TEXT"] as string) || type == (ShareType["LINK"] as string)) {
+ // 文本或链接分享
+ const items = createTextShareItems(title, summary, url);
+ presentShareController(
+ items,
+ () => {
+ options.success?.();
+ },
+ (error: string) => {
+ options.fail?.(error);
+ }
+ );
+ } else if (type == (ShareType["IMAGE"] as string)) {
+ // 图片分享
+ createImageShareItems(
+ url,
+ (items: any[]) => {
+ presentShareController(
+ items,
+ () => {
+ options.success?.();
+ },
+ (error: string) => {
+ options.fail?.(error);
+ }
+ );
+ },
+ (error: string) => {
+ options.fail?.(error);
+ }
+ );
+ } else if (
+ type == (ShareType["VIDEO"] as string) ||
+ type == (ShareType["AUDIO"] as string) ||
+ type == (ShareType["FILE"] as string)
+ ) {
+ // 视频、音频、文件分享
+ createFileShareItems(
+ url,
+ (items: any[]) => {
+ presentShareController(
+ items,
+ () => {
+ options.success?.();
+ },
+ (error: string) => {
+ options.fail?.(error);
+ }
+ );
+ },
+ (error: string) => {
+ options.fail?.(error);
+ }
+ );
+ } else {
+ // 未知类型,默认使用文本分享
+ const items = createTextShareItems(title, summary, url);
+ presentShareController(
+ items,
+ () => {
+ options.success?.();
+ },
+ (error: string) => {
+ options.fail?.(error);
+ }
+ );
+ }
+}
diff --git a/cool-unix/uni_modules/cool-share/utssdk/interface.uts b/cool-unix/uni_modules/cool-share/utssdk/interface.uts
new file mode 100644
index 0000000..f46fb21
--- /dev/null
+++ b/cool-unix/uni_modules/cool-share/utssdk/interface.uts
@@ -0,0 +1,29 @@
+export type ShareWithSystemOptions = {
+ /**
+ * 分享类型:
+ * text(文本) | image(图片) | video(视频) | audio(音频) | file(文件) | link(链接)
+ */
+ type: string;
+ /**
+ * 分享标题
+ */
+ title?: string;
+ /**
+ * 分享描述或内容
+ */
+ summary?: string;
+ /**
+ * 分享资源路径:
+ * 如果是图片/视频/音频/文件,填写资源路径或网络URL
+ * 如果是link,填写链接地址
+ */
+ url?: string;
+ /**
+ * 分享成功回调
+ */
+ success?: () => void;
+ /**
+ * 分享失败回调,返回错误信息
+ */
+ fail?: (error: string) => void;
+};
diff --git a/cool-unix/uni_modules/cool-svg/components/cl-svg/cl-svg.uvue b/cool-unix/uni_modules/cool-svg/components/cl-svg/cl-svg.uvue
new file mode 100644
index 0000000..1bfabe4
--- /dev/null
+++ b/cool-unix/uni_modules/cool-svg/components/cl-svg/cl-svg.uvue
@@ -0,0 +1,233 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-svg/index.d.ts b/cool-unix/uni_modules/cool-svg/index.d.ts
new file mode 100644
index 0000000..0e9b0d6
--- /dev/null
+++ b/cool-unix/uni_modules/cool-svg/index.d.ts
@@ -0,0 +1,7 @@
+export {};
+
+declare module "vue" {
+ export interface GlobalComponents {
+ "cl-svg": (typeof import("./components/cl-svg/cl-svg.uvue"))["default"];
+ }
+}
diff --git a/cool-unix/uni_modules/cool-svg/package.json b/cool-unix/uni_modules/cool-svg/package.json
new file mode 100644
index 0000000..efa7f0c
--- /dev/null
+++ b/cool-unix/uni_modules/cool-svg/package.json
@@ -0,0 +1,82 @@
+{
+ "id": "cool-svg",
+ "displayName": "cool-svg",
+ "version": "1.0.0",
+ "description": "cool-svg",
+ "keywords": [
+ "cool-svg"
+ ],
+ "repository": "",
+ "engines": {
+ "HBuilderX": "^4.75"
+ },
+ "dcloudext": {
+ "type": "uts",
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "",
+ "data": "",
+ "permissions": ""
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "u",
+ "aliyun": "u",
+ "alipay": "u"
+ },
+ "client": {
+ "Vue": {
+ "vue2": "u",
+ "vue3": "u"
+ },
+ "App": {
+ "app-android": "u",
+ "app-ios": "u"
+ },
+ "H5-mobile": {
+ "Safari": "u",
+ "Android Browser": "u",
+ "微信浏览器(Android)": "u",
+ "QQ浏览器(Android)": "u"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "u",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u",
+ "钉钉": "u",
+ "快手": "u",
+ "飞书": "u",
+ "京东": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
diff --git a/cool-unix/uni_modules/cool-svg/utssdk/app-android/config.json b/cool-unix/uni_modules/cool-svg/utssdk/app-android/config.json
new file mode 100644
index 0000000..d1ccc13
--- /dev/null
+++ b/cool-unix/uni_modules/cool-svg/utssdk/app-android/config.json
@@ -0,0 +1,4 @@
+{
+ "minSdkVersion": "21",
+ "dependencies": ["com.caverock:androidsvg:1.4"]
+}
diff --git a/cool-unix/uni_modules/cool-svg/utssdk/app-android/index.uts b/cool-unix/uni_modules/cool-svg/utssdk/app-android/index.uts
new file mode 100644
index 0000000..02184c9
--- /dev/null
+++ b/cool-unix/uni_modules/cool-svg/utssdk/app-android/index.uts
@@ -0,0 +1,132 @@
+import PictureDrawable from "android.graphics.drawable.PictureDrawable";
+import ImageView from "android.widget.ImageView";
+import File from "java.io.File";
+import FileInputStream from "java.io.FileInputStream";
+import Color from "android.graphics.Color";
+import RenderOptions from "com.caverock.androidsvg.RenderOptions";
+import Base64 from "android.util.Base64";
+import Charset from "java.nio.charset.Charset";
+import StandardCharsets from "java.nio.charset.StandardCharsets";
+
+/**
+ * CoolSvg Android 平台 SVG 渲染器
+ * 支持多种 SVG 数据格式:
+ * - base64 编码的数据 URL
+ * - URL 编码的数据 URL
+ * - 本地文件路径
+ * - Android 资源文件
+ */
+export class CoolSvg {
+ /** 原生视图元素 */
+ $element: UniNativeViewElement;
+ /** Android ImageView 实例 */
+ imageView: ImageView | null = null;
+
+ /**
+ * 构造函数
+ * @param element uni-app x 原生视图元素
+ */
+ constructor(element: UniNativeViewElement) {
+ this.$element = element;
+ this.imageView = new ImageView(UTSAndroid.getAppContext()!);
+ this.$element.bindAndroidView(this.imageView!);
+ }
+
+ /**
+ * 加载并渲染 SVG
+ * @param src SVG 数据源,支持以下格式:
+ * - data:image/svg+xml;base64,
+ * - data:image/svg+xml,
+ * - 本地文件路径
+ * @param color 填充颜色,用于替换 SVG 中 path 元素的 fill 属性
+ */
+ load(src: string, color: string) {
+ // 空字符串检查
+ if (src == "") {
+ return;
+ }
+
+ try {
+ if (src.startsWith("data:image/svg")) {
+ // 处理数据 URL 格式的 SVG
+ this.loadFromDataUrl(src, color);
+ } else {
+ // 处理本地文件或资源文件
+ this.loadFromFile(src, color);
+ }
+ } catch (e) {
+ // 打印异常信息用于调试
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 从数据 URL 加载 SVG
+ * @param dataUrl 数据 URL 字符串
+ * @param color 填充颜色
+ */
+ private loadFromDataUrl(dataUrl: string, color: string) {
+ let svgString: string;
+
+ if (dataUrl.startsWith("data:image/svg+xml;base64,")) {
+ // 处理 base64 编码的 SVG
+ const base64Prefix = "data:image/svg+xml;base64,";
+ const base64Data = dataUrl.substring(base64Prefix.length);
+ const decodedBytes = Base64.decode(base64Data, Base64.DEFAULT);
+ svgString = String(decodedBytes, StandardCharsets.UTF_8);
+ } else {
+ // 处理 URL 编码的 SVG
+ const urlPrefix = "data:image/svg+xml,";
+ const encodedSvg = dataUrl.substring(urlPrefix.length);
+ svgString = decodeURIComponent(encodedSvg) ?? '';
+ }
+
+ const svg = com.caverock.androidsvg.SVG.getFromString(svgString);
+ this.render(svg, color);
+ }
+
+ /**
+ * 从文件加载 SVG
+ * @param src 文件路径
+ * @param color 填充颜色
+ */
+ private loadFromFile(src: string, color: string) {
+ // uni-app x 正式打包会将资源文件放在 Android asset 中
+ const path = UTSAndroid.getResourcePath(src);
+
+ if (path.startsWith("/android_asset")) {
+ // 从 Android 资源文件中加载
+ const assetPath = path.substring(15); // 移除 "/android_asset" 前缀
+ const svg = com.caverock.androidsvg.SVG.getFromAsset(
+ UTSAndroid.getAppContext()!.getAssets(),
+ assetPath
+ );
+ this.render(svg, color);
+ } else {
+ // 从本地文件系统加载
+ const file = new File(path);
+ if (file.exists()) {
+ const svg = com.caverock.androidsvg.SVG.getFromInputStream(
+ new FileInputStream(file)
+ );
+ this.render(svg, color);
+ }
+ }
+ }
+
+ /**
+ * 渲染 SVG 到 ImageView
+ * @param svg AndroidSVG 对象
+ * @param color 填充颜色,应用到所有 path 元素
+ */
+ private render(svg: com.caverock.androidsvg.SVG, color: string) {
+ // 创建渲染选项,设置 CSS 样式来改变 SVG 的填充颜色
+ const options = RenderOptions.create().css(`path { fill: ${color}; }`);
+
+ // 将 SVG 渲染为 Picture,然后转换为 Drawable
+ const drawable = new PictureDrawable(svg.renderToPicture(options));
+
+ // 设置到 ImageView 中显示
+ this.imageView?.setImageDrawable(drawable);
+ }
+}
diff --git a/cool-unix/uni_modules/cool-svg/utssdk/app-ios/config.json b/cool-unix/uni_modules/cool-svg/utssdk/app-ios/config.json
new file mode 100644
index 0000000..0b40a79
--- /dev/null
+++ b/cool-unix/uni_modules/cool-svg/utssdk/app-ios/config.json
@@ -0,0 +1,9 @@
+{
+ "deploymentTarget": "9",
+ "dependencies-pods": [
+ {
+ "name": "SVGKit",
+ "version": "2.1.0"
+ }
+ ]
+}
diff --git a/cool-unix/uni_modules/cool-svg/utssdk/app-ios/index.uts b/cool-unix/uni_modules/cool-svg/utssdk/app-ios/index.uts
new file mode 100644
index 0000000..76d6816
--- /dev/null
+++ b/cool-unix/uni_modules/cool-svg/utssdk/app-ios/index.uts
@@ -0,0 +1,68 @@
+import { UIView } from "UIKit";
+import { SVGKFastImageView, SVGKImage } from "SVGKit";
+
+/**
+ * CoolSvg iOS 平台 SVG 渲染器
+ * - 本地文件路径
+ */
+export class CoolSvg {
+ /** uni-app x 原生视图元素 */
+ $element: UniNativeViewElement;
+ /** iOS SVGKFastImageView 实例 */
+ imageView: SVGKFastImageView | null = null;
+
+ /**
+ * 构造函数
+ * @param element uni-app x 原生视图元素
+ */
+ constructor(element: UniNativeViewElement) {
+ this.$element = element;
+
+ // 创建占位符 SVG 图像
+ let placeholderImage = SVGKImage((contentsOf = URL((fileURLWithPath = ""))));
+ // 初始化 SVG 图像视图
+ this.imageView = new SVGKFastImageView((svgkImage = placeholderImage));
+ // 将视图绑定到 uni-app x 元素
+ this.$element.bindIOSView(this.imageView!);
+ }
+
+ /**
+ * 加载并渲染 SVG
+ * @param src SVG 数据源
+ * @param color 填充颜色,用于替换 SVG 中 path 元素的 fill 属性
+ */
+ load(src: string, color: string) {
+ // 空字符串检查
+ if (src == "") {
+ return;
+ }
+
+ try {
+ // 从资源路径加载 SVG 图像
+ let svgImage = SVGKImage(
+ (contentsOf = URL((fileURLWithPath = UTSiOS.getResourcePath(src))))
+ );
+
+ // 加载失败检查
+ if (svgImage == null) {
+ return;
+ }
+
+ // 设置 SVG 图像到视图
+ this.imageView!.image = svgImage;
+
+ // 应用颜色覆盖
+ if (color != "") {
+ // 创建颜色覆盖层视图
+ let colorView = new UIView();
+ colorView.frame = this.imageView!.bounds;
+ colorView.backgroundColor = UTSiOS.colorWithString(color);
+ // 设置合成滤镜为 sourceAtop,实现颜色覆盖效果
+ colorView.layer.compositingFilter = "sourceAtop";
+ this.imageView!.addSubview(colorView);
+ }
+ } catch (e) {
+ // 静默处理异常,避免影响应用运行
+ }
+ }
+}
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-action-sheet/cl-action-sheet.uvue b/cool-unix/uni_modules/cool-ui/components/cl-action-sheet/cl-action-sheet.uvue
new file mode 100644
index 0000000..d995465
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-action-sheet/cl-action-sheet.uvue
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+ {{ config.description }}
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-action-sheet/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-action-sheet/props.ts
new file mode 100644
index 0000000..850ffd3
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-action-sheet/props.ts
@@ -0,0 +1,12 @@
+import type { ClActionSheetItem, ClActionSheetOptions, PassThroughProps } from "../../types";
+
+export type ClActionSheetPassThrough = {
+ className?: string;
+ item?: PassThroughProps;
+ list?: PassThroughProps;
+};
+
+export type ClActionSheetProps = {
+ className?: string;
+ pt?: ClActionSheetPassThrough;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-avatar/cl-avatar.uvue b/cool-unix/uni_modules/cool-ui/components/cl-avatar/cl-avatar.uvue
new file mode 100644
index 0000000..ea09b82
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-avatar/cl-avatar.uvue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-avatar/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-avatar/props.ts
new file mode 100644
index 0000000..49d74b1
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-avatar/props.ts
@@ -0,0 +1,14 @@
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClAvatarPassThrough = {
+ className?: string;
+ icon?: ClIconProps;
+};
+
+export type ClAvatarProps = {
+ className?: string;
+ pt?: ClAvatarPassThrough;
+ src?: string;
+ size?: any;
+ rounded?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-back-top/cl-back-top.uvue b/cool-unix/uni_modules/cool-ui/components/cl-back-top/cl-back-top.uvue
new file mode 100644
index 0000000..2626e8f
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-back-top/cl-back-top.uvue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-back-top/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-back-top/props.ts
new file mode 100644
index 0000000..069226c
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-back-top/props.ts
@@ -0,0 +1,4 @@
+export type ClBackTopProps = {
+ className?: string;
+ top?: number | any;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-badge/cl-badge.uvue b/cool-unix/uni_modules/cool-ui/components/cl-badge/cl-badge.uvue
new file mode 100644
index 0000000..7c8b0b2
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-badge/cl-badge.uvue
@@ -0,0 +1,109 @@
+
+
+
+ {{ value }}
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-badge/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-badge/props.ts
new file mode 100644
index 0000000..b2798c2
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-badge/props.ts
@@ -0,0 +1,15 @@
+import type { PassThroughProps, Type } from "../../types";
+
+export type ClBadgePassThrough = {
+ className?: string;
+ text?: PassThroughProps;
+};
+
+export type ClBadgeProps = {
+ className?: string;
+ pt?: ClBadgePassThrough;
+ type?: Type;
+ dot?: boolean;
+ value?: any;
+ position?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-banner/cl-banner.uvue b/cool-unix/uni_modules/cool-ui/components/cl-banner/cl-banner.uvue
new file mode 100644
index 0000000..0e15e02
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-banner/cl-banner.uvue
@@ -0,0 +1,485 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-banner/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-banner/props.ts
new file mode 100644
index 0000000..8888311
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-banner/props.ts
@@ -0,0 +1,25 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClBannerPassThrough = {
+ className?: string;
+ item?: PassThroughProps;
+ itemActive?: PassThroughProps;
+ image?: PassThroughProps;
+ dots?: PassThroughProps;
+ dot?: PassThroughProps;
+ dotActive?: PassThroughProps;
+};
+
+export type ClBannerProps = {
+ className?: string;
+ pt?: ClBannerPassThrough;
+ list?: string[];
+ previousMargin?: number;
+ nextMargin?: number;
+ autoplay?: boolean;
+ interval?: number;
+ showDots?: boolean;
+ disableTouch?: boolean;
+ height?: any;
+ imageMode?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-button/cl-button.uvue b/cool-unix/uni_modules/cool-ui/components/cl-button/cl-button.uvue
new file mode 100644
index 0000000..5bc49de
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-button/cl-button.uvue
@@ -0,0 +1,673 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-button/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-button/props.ts
new file mode 100644
index 0000000..8d69cb1
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-button/props.ts
@@ -0,0 +1,42 @@
+import type { ClIconProps } from "../cl-icon/props";
+import type { ClButtonType, PassThroughProps, Size } from "../../types";
+import type { ClLoadingProps } from "../cl-loading/props";
+
+export type ClButtonPassThrough = {
+ className?: string;
+ label?: PassThroughProps;
+ icon?: ClIconProps;
+ loading?: ClLoadingProps;
+};
+
+export type ClButtonProps = {
+ className?: string;
+ pt?: ClButtonPassThrough;
+ type?: ClButtonType;
+ color?: string;
+ icon?: string;
+ text?: boolean;
+ rounded?: boolean;
+ border?: boolean;
+ loading?: boolean;
+ disabled?: boolean;
+ size?: Size;
+ hoverClass?: string;
+ hoverStopPropagation?: boolean;
+ hoverStartTime?: number;
+ hoverStayTime?: number;
+ formType?: "submit" | "reset";
+ openType?: "agreePrivacyAuthorization" | "feedback" | "share" | "getUserInfo" | "contact" | "getPhoneNumber" | "launchApp" | "openSetting" | "chooseAvatar" | "getAuthorize" | "lifestyle" | "contactShare" | "openGroupProfile" | "openGuildProfile" | "openPublicProfile" | "shareMessageToFriend" | "addFriend" | "addColorSign" | "addGroupApp" | "addToFavorites" | "chooseAddress" | "chooseInvoiceTitle" | "login" | "subscribe" | "favorite" | "watchLater" | "openProfile" | "liveActivity" | "getRealtimePhoneNumber";
+ lang?: "en" | "zh_CN" | "zh_TW";
+ sessionFrom?: string;
+ sendMessageTitle?: string;
+ sendMessagePath?: string;
+ sendMessageImg?: string;
+ showMessageCard?: boolean;
+ appParameter?: string;
+ groupId?: string;
+ guildId?: string;
+ publicId?: string;
+ phoneNumberNoQuotaToast?: boolean;
+ createliveactivity?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-calendar-select/cl-calendar-select.uvue b/cool-unix/uni_modules/cool-ui/components/cl-calendar-select/cl-calendar-select.uvue
new file mode 100644
index 0000000..a14c712
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-calendar-select/cl-calendar-select.uvue
@@ -0,0 +1,310 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-calendar-select/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-calendar-select/props.ts
new file mode 100644
index 0000000..e78ba85
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-calendar-select/props.ts
@@ -0,0 +1,29 @@
+import type { ClCalendarDateConfig, ClCalendarMode } from "../../types";
+import type { ClSelectTriggerPassThrough } from "../cl-select-trigger/props";
+import type { ClPopupPassThrough } from "../cl-popup/props";
+
+export type ClCalendarSelectPassThrough = {
+ trigger?: ClSelectTriggerPassThrough;
+ popup?: ClPopupPassThrough;
+};
+
+export type ClCalendarSelectProps = {
+ className?: string;
+ pt?: ClCalendarSelectPassThrough;
+ modelValue?: string | any;
+ date?: string[];
+ mode?: ClCalendarMode;
+ dateConfig?: ClCalendarDateConfig[];
+ start?: string;
+ end?: string;
+ title?: string;
+ placeholder?: string;
+ showTrigger?: boolean;
+ disabled?: boolean;
+ splitor?: string;
+ rangeSplitor?: string;
+ confirmText?: string;
+ showConfirm?: boolean;
+ cancelText?: string;
+ showCancel?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-calendar/cl-calendar.uvue b/cool-unix/uni_modules/cool-ui/components/cl-calendar/cl-calendar.uvue
new file mode 100644
index 0000000..f69f8e4
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-calendar/cl-calendar.uvue
@@ -0,0 +1,926 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ weekName }}
+
+
+
+
+
+
+
+
+
+ {{ dateCell.topText }}
+
+
+ {{ dateCell.date }}
+
+
+ {{ dateCell.bottomText }}
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-calendar/locale.ts b/cool-unix/uni_modules/cool-ui/components/cl-calendar/locale.ts
new file mode 100644
index 0000000..5e2a15e
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-calendar/locale.ts
@@ -0,0 +1,80 @@
+import { appendLocale } from "@/locale";
+
+setTimeout(() => {
+ appendLocale("zh-cn", [
+ ["周日", "日"],
+ ["周一", "一"],
+ ["周二", "二"],
+ ["周三", "三"],
+ ["周四", "四"],
+ ["周五", "五"],
+ ["周六", "六"],
+ ["{year}年{month}月", "{year}年{month}月"]
+ ]);
+
+ appendLocale("zh-tw", [
+ ["周日", "週日"],
+ ["周一", "週一"],
+ ["周二", "週二"],
+ ["周三", "週三"],
+ ["周四", "週四"],
+ ["周五", "週五"],
+ ["周六", "週六"],
+ ["{year}年{month}月", "{year}年{month}月"]
+ ]);
+
+ appendLocale("en", [
+ ["周日", "Sun"],
+ ["周一", "Mon"],
+ ["周二", "Tue"],
+ ["周三", "Wed"],
+ ["周四", "Thu"],
+ ["周五", "Fri"],
+ ["周六", "Sat"],
+ ["{year}年{month}月", "{month}/{year}"]
+ ]);
+
+ appendLocale("ja", [
+ ["周日", "日曜"],
+ ["周一", "月曜"],
+ ["周二", "火曜"],
+ ["周三", "水曜"],
+ ["周四", "木曜"],
+ ["周五", "金曜"],
+ ["周六", "土曜"],
+ ["{year}年{month}月", "{year}年{month}月"]
+ ]);
+
+ appendLocale("ko", [
+ ["周日", "일"],
+ ["周一", "월"],
+ ["周二", "화"],
+ ["周三", "수"],
+ ["周四", "목"],
+ ["周五", "금"],
+ ["周六", "토"],
+ ["{year}年{month}月", "{year}년 {month}월"]
+ ]);
+
+ appendLocale("fr", [
+ ["周日", "Dim"],
+ ["周一", "Lun"],
+ ["周二", "Mar"],
+ ["周三", "Mer"],
+ ["周四", "Jeu"],
+ ["周五", "Ven"],
+ ["周六", "Sam"],
+ ["{year}年{month}月", "{month}/{year}"]
+ ]);
+
+ appendLocale("es", [
+ ["周日", "Dom"],
+ ["周一", "Lun"],
+ ["周二", "Mar"],
+ ["周三", "Mié"],
+ ["周四", "Jue"],
+ ["周五", "Vie"],
+ ["周六", "Sáb"],
+ ["{year}年{month}月", "{month}/{year}"]
+ ]);
+}, 0);
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-calendar/picker.uvue b/cool-unix/uni_modules/cool-ui/components/cl-calendar/picker.uvue
new file mode 100644
index 0000000..0d6e207
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-calendar/picker.uvue
@@ -0,0 +1,273 @@
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-calendar/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-calendar/props.ts
new file mode 100644
index 0000000..7cb1fc0
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-calendar/props.ts
@@ -0,0 +1,31 @@
+import type { ClCalendarDateConfig, ClCalendarMode } from "../../types";
+
+export type ClCalendarPassThrough = {
+ className?: string;
+};
+
+export type ClCalendarProps = {
+ className?: string;
+ pt?: ClCalendarPassThrough;
+ modelValue?: string | any;
+ date?: string[];
+ mode?: ClCalendarMode;
+ dateConfig?: ClCalendarDateConfig[];
+ start?: string;
+ end?: string;
+ year?: number;
+ month?: number;
+ showOtherMonth?: boolean;
+ showHeader?: boolean;
+ showWeeks?: boolean;
+ cellHeight?: number;
+ cellGap?: number;
+ color?: string;
+ textColor?: string;
+ textOtherMonthColor?: string;
+ textDisabledColor?: string;
+ textTodayColor?: string;
+ textSelectedColor?: string;
+ bgSelectedColor?: string;
+ bgRangeColor?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-cascader/cl-cascader.uvue b/cool-unix/uni_modules/cool-ui/components/cl-cascader/cl-cascader.uvue
new file mode 100644
index 0000000..efff53c
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-cascader/cl-cascader.uvue
@@ -0,0 +1,532 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-cascader/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-cascader/props.ts
new file mode 100644
index 0000000..82dcbec
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-cascader/props.ts
@@ -0,0 +1,23 @@
+import type { ClSelectTriggerPassThrough } from "../cl-select-trigger/props";
+import type { ClPopupPassThrough } from "../cl-popup/props";
+import type { ClListViewItem } from "../../types";
+
+export type ClCascaderPassThrough = {
+ trigger?: ClSelectTriggerPassThrough;
+ popup?: ClPopupPassThrough;
+};
+
+export type ClCascaderProps = {
+ className?: string;
+ pt?: ClCascaderPassThrough;
+ modelValue?: string[];
+ title?: string;
+ placeholder?: string;
+ options?: ClListViewItem[];
+ showTrigger?: boolean;
+ disabled?: boolean;
+ labelKey?: string;
+ valueKey?: string;
+ textSeparator?: string;
+ height?: any;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-checkbox/cl-checkbox.uvue b/cool-unix/uni_modules/cool-ui/components/cl-checkbox/cl-checkbox.uvue
new file mode 100644
index 0000000..3395bbb
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-checkbox/cl-checkbox.uvue
@@ -0,0 +1,177 @@
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-checkbox/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-checkbox/props.ts
new file mode 100644
index 0000000..d752369
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-checkbox/props.ts
@@ -0,0 +1,20 @@
+import type { PassThroughProps } from "../../types";
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClCheckboxPassThrough = {
+ className?: string;
+ icon?: ClIconProps;
+ label?: PassThroughProps;
+};
+
+export type ClCheckboxProps = {
+ className?: string;
+ pt?: ClCheckboxPassThrough;
+ modelValue?: any[] | boolean;
+ label?: string;
+ value?: any;
+ disabled?: boolean;
+ activeIcon?: string;
+ inactiveIcon?: string;
+ showIcon?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-col/cl-col.uvue b/cool-unix/uni_modules/cool-ui/components/cl-col/cl-col.uvue
new file mode 100644
index 0000000..c04ef48
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-col/cl-col.uvue
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-col/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-col/props.ts
new file mode 100644
index 0000000..eaed3e1
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-col/props.ts
@@ -0,0 +1,12 @@
+export type ClColPassThrough = {
+ className?: string;
+};
+
+export type ClColProps = {
+ className?: string;
+ pt?: ClColPassThrough;
+ span?: number;
+ offset?: number;
+ push?: number;
+ pull?: number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-collapse/cl-collapse.uvue b/cool-unix/uni_modules/cool-ui/components/cl-collapse/cl-collapse.uvue
new file mode 100644
index 0000000..3277199
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-collapse/cl-collapse.uvue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-collapse/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-collapse/props.ts
new file mode 100644
index 0000000..5617ed4
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-collapse/props.ts
@@ -0,0 +1,9 @@
+export type ClCollapsePassThrough = {
+ className?: string;
+};
+
+export type ClCollapseProps = {
+ className?: string;
+ pt?: ClCollapsePassThrough;
+ modelValue?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-confirm/cl-confirm.uvue b/cool-unix/uni_modules/cool-ui/components/cl-confirm/cl-confirm.uvue
new file mode 100644
index 0000000..2026984
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-confirm/cl-confirm.uvue
@@ -0,0 +1,194 @@
+
+
+
+ {{ config.title }}
+
+ {{ config.message }}
+
+
+ {{ config.cancelText }}
+ {{ config.confirmText }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-countdown/cl-countdown.uvue b/cool-unix/uni_modules/cool-ui/components/cl-countdown/cl-countdown.uvue
new file mode 100644
index 0000000..2be0d89
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-countdown/cl-countdown.uvue
@@ -0,0 +1,324 @@
+
+
+
+
+ {{ item.value }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-countdown/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-countdown/props.ts
new file mode 100644
index 0000000..32682f2
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-countdown/props.ts
@@ -0,0 +1,20 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClCountdownPassThrough = {
+ className?: string;
+ text?: PassThroughProps;
+ splitor?: PassThroughProps;
+};
+
+export type ClCountdownProps = {
+ className?: string;
+ pt?: ClCountdownPassThrough;
+ format?: string;
+ hideZero?: boolean;
+ day?: number;
+ hour?: number;
+ minute?: number;
+ second?: number;
+ datetime?: Date | string;
+ auto?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-cropper/cl-cropper.uvue b/cool-unix/uni_modules/cool-ui/components/cl-cropper/cl-cropper.uvue
new file mode 100644
index 0000000..56f67eb
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-cropper/cl-cropper.uvue
@@ -0,0 +1,1352 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ cropBox.width }}
+
+
+
+
+
+ {{ cropBox.height }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-cropper/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-cropper/props.ts
new file mode 100644
index 0000000..54c5c38
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-cropper/props.ts
@@ -0,0 +1,19 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClCropperPassThrough = {
+ className?: string;
+ image?: PassThroughProps;
+ op?: PassThroughProps;
+ opItem?: PassThroughProps;
+ mask?: PassThroughProps;
+ cropBox?: PassThroughProps;
+};
+
+export type ClCropperProps = {
+ className?: string;
+ pt?: ClCropperPassThrough;
+ cropWidth?: number;
+ cropHeight?: number;
+ maxScale?: number;
+ resizable?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-draggable/cl-draggable.uvue b/cool-unix/uni_modules/cool-ui/components/cl-draggable/cl-draggable.uvue
new file mode 100644
index 0000000..ae4cb6d
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-draggable/cl-draggable.uvue
@@ -0,0 +1,697 @@
+
+
+
+ {
+ onTouchStart(event, index, 'touch');
+ }
+ "
+ @longpress="
+ (event: UniTouchEvent) => {
+ onTouchStart(event, index, 'longpress');
+ }
+ "
+ @touchmove="onTouchMove"
+ @touchend="onTouchEnd"
+ >
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-draggable/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-draggable/props.ts
new file mode 100644
index 0000000..de0fdf7
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-draggable/props.ts
@@ -0,0 +1,15 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClDraggablePassThrough = {
+ className?: string;
+ ghost?: PassThroughProps;
+};
+
+export type ClDraggableProps = {
+ className?: string;
+ pt?: ClDraggablePassThrough;
+ modelValue?: UTSJSONObject[];
+ disabled?: boolean;
+ columns?: number;
+ longPress?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-empty/cl-empty.uvue b/cool-unix/uni_modules/cool-ui/components/cl-empty/cl-empty.uvue
new file mode 100644
index 0000000..8fce38f
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-empty/cl-empty.uvue
@@ -0,0 +1,102 @@
+
+
+
+
+ {{ text }}
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-filter-bar/cl-filter-bar.uvue b/cool-unix/uni_modules/cool-ui/components/cl-filter-bar/cl-filter-bar.uvue
new file mode 100644
index 0000000..7948dd6
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-filter-bar/cl-filter-bar.uvue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-filter-bar/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-filter-bar/props.ts
new file mode 100644
index 0000000..5f451ea
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-filter-bar/props.ts
@@ -0,0 +1,3 @@
+export type ClFilterBarProps = {
+ className?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-filter-item/cl-filter-item.uvue b/cool-unix/uni_modules/cool-ui/components/cl-filter-item/cl-filter-item.uvue
new file mode 100644
index 0000000..b5f2f41
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-filter-item/cl-filter-item.uvue
@@ -0,0 +1,169 @@
+
+
+
+ {{ text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-filter-item/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-filter-item/props.ts
new file mode 100644
index 0000000..923df1a
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-filter-item/props.ts
@@ -0,0 +1,15 @@
+import type { PassThroughProps, ClFilterItemType, ClSelectOption } from "../../types";
+
+export type ClFilterItemPassThrough = {
+ className?: string;
+ label?: PassThroughProps;
+};
+
+export type ClFilterItemProps = {
+ className?: string;
+ pt?: ClFilterItemPassThrough;
+ label?: string;
+ value: any;
+ type?: ClFilterItemType;
+ options?: ClSelectOption[];
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-float-view/cl-float-view.uvue b/cool-unix/uni_modules/cool-ui/components/cl-float-view/cl-float-view.uvue
new file mode 100644
index 0000000..36bb609
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-float-view/cl-float-view.uvue
@@ -0,0 +1,287 @@
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-float-view/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-float-view/props.ts
new file mode 100644
index 0000000..4a317fc
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-float-view/props.ts
@@ -0,0 +1,10 @@
+export type ClFloatViewProps = {
+ className?: string;
+ zIndex?: number;
+ size?: number;
+ left?: number;
+ bottom?: number;
+ gap?: number;
+ disabled?: boolean;
+ noSnapping?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-footer/cl-footer.uvue b/cool-unix/uni_modules/cool-ui/components/cl-footer/cl-footer.uvue
new file mode 100644
index 0000000..7d25ea9
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-footer/cl-footer.uvue
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-footer/offset.ts b/cool-unix/uni_modules/cool-ui/components/cl-footer/offset.ts
new file mode 100644
index 0000000..7972528
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-footer/offset.ts
@@ -0,0 +1,16 @@
+import { router } from "@/cool";
+import { reactive } from "vue";
+
+export class ClFooterOffset {
+ private data = reactive({});
+
+ set(value: number): void {
+ this.data[router.path()] = value;
+ }
+
+ get(): number {
+ return (this.data[router.path()] as number | null) ?? 0;
+ }
+}
+
+export const clFooterOffset = new ClFooterOffset();
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-footer/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-footer/props.ts
new file mode 100644
index 0000000..d124f8f
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-footer/props.ts
@@ -0,0 +1,14 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClFooterPassThrough = {
+ className?: string;
+ content?: PassThroughProps;
+ wrapper?: PassThroughProps;
+};
+
+export type ClFooterProps = {
+ className?: string;
+ pt?: ClFooterPassThrough;
+ minHeight?: number;
+ vt?: number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-form-item/cl-form-item.uvue b/cool-unix/uni_modules/cool-ui/components/cl-form-item/cl-form-item.uvue
new file mode 100644
index 0000000..fb84444
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-form-item/cl-form-item.uvue
@@ -0,0 +1,269 @@
+
+
+
+
+ {{ label }}
+
+
+ *
+
+
+
+
+
+
+
+
+
+
+
+ {{ errorText }}
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-form-item/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-form-item/props.ts
new file mode 100644
index 0000000..b8c7cab
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-form-item/props.ts
@@ -0,0 +1,22 @@
+import type { ClFormLabelPosition, ClFormRule, PassThroughProps } from "../../types";
+
+export type ClFormItemPassThrough = {
+ className?: string;
+ inner?: PassThroughProps;
+ label?: PassThroughProps;
+ content?: PassThroughProps;
+ error?: PassThroughProps;
+};
+
+export type ClFormItemProps = {
+ className?: string;
+ pt?: ClFormItemPassThrough;
+ label?: string;
+ prop?: string;
+ rules?: ClFormRule[];
+ labelPosition?: ClFormLabelPosition;
+ labelWidth?: string | any;
+ showAsterisk?: boolean | any;
+ showMessage?: boolean | any;
+ required?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-form/cl-form.uvue b/cool-unix/uni_modules/cool-ui/components/cl-form/cl-form.uvue
new file mode 100644
index 0000000..e28c65a
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-form/cl-form.uvue
@@ -0,0 +1,455 @@
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-form/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-form/props.ts
new file mode 100644
index 0000000..b305aef
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-form/props.ts
@@ -0,0 +1,18 @@
+import type { ClFormLabelPosition, ClFormRule, ClFormValidateError } from "../../types";
+
+export type ClFormPassThrough = {
+ className?: string;
+};
+
+export type ClFormProps = {
+ className?: string;
+ pt?: ClFormPassThrough;
+ modelValue?: any;
+ rules?: Map;
+ labelPosition?: ClFormLabelPosition;
+ labelWidth?: string;
+ showAsterisk?: boolean;
+ showMessage?: boolean;
+ disabled?: boolean;
+ scrollToError?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-icon/cl-icon.uvue b/cool-unix/uni_modules/cool-ui/components/cl-icon/cl-icon.uvue
new file mode 100644
index 0000000..d706c11
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-icon/cl-icon.uvue
@@ -0,0 +1,162 @@
+
+
+ {{ icon.text }}
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-icon/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-icon/props.ts
new file mode 100644
index 0000000..7dd4f3f
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-icon/props.ts
@@ -0,0 +1,13 @@
+export type ClIconPassThrough = {
+ className?: string;
+};
+
+export type ClIconProps = {
+ className?: string;
+ pt?: ClIconPassThrough;
+ name?: string;
+ size?: string | number;
+ height?: string | number;
+ width?: string | number;
+ color?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-image/cl-image.uvue b/cool-unix/uni_modules/cool-ui/components/cl-image/cl-image.uvue
new file mode 100644
index 0000000..6d5bbd9
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-image/cl-image.uvue
@@ -0,0 +1,221 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-image/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-image/props.ts
new file mode 100644
index 0000000..eade778
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-image/props.ts
@@ -0,0 +1,26 @@
+import type { PassThroughProps } from "../../types";
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClImagePassThrough = {
+ className?: string;
+ inner?: PassThroughProps;
+ error?: ClIconProps;
+ loading?: PassThroughProps;
+};
+
+export type ClImageProps = {
+ className?: string;
+ pt?: ClImagePassThrough;
+ src?: string;
+ mode?: "scaleToFill" | "aspectFit" | "aspectFill" | "widthFix" | "heightFix" | "top" | "bottom" | "center" | "left" | "right" | "top left" | "top right" | "bottom left" | "bottom right";
+ border?: boolean;
+ preview?: boolean;
+ previewList?: string[];
+ height?: string | number;
+ width?: string | number;
+ showLoading?: boolean;
+ lazyLoad?: boolean;
+ fadeShow?: boolean;
+ webp?: boolean;
+ showMenuByLongpress?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-index-bar/cl-index-bar.uvue b/cool-unix/uni_modules/cool-ui/components/cl-index-bar/cl-index-bar.uvue
new file mode 100644
index 0000000..f01a6f6
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-index-bar/cl-index-bar.uvue
@@ -0,0 +1,317 @@
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+ {{ alertText }}
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-index-bar/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-index-bar/props.ts
new file mode 100644
index 0000000..0f4e9d7
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-index-bar/props.ts
@@ -0,0 +1,10 @@
+export type ClIndexBarPassThrough = {
+ className?: string;
+};
+
+export type ClIndexBarProps = {
+ className?: string;
+ pt?: ClIndexBarPassThrough;
+ modelValue?: number;
+ list?: string[];
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-input-number/cl-input-number.uvue b/cool-unix/uni_modules/cool-ui/components/cl-input-number/cl-input-number.uvue
new file mode 100644
index 0000000..527d874
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-input-number/cl-input-number.uvue
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-input-number/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-input-number/props.ts
new file mode 100644
index 0000000..58c3c66
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-input-number/props.ts
@@ -0,0 +1,34 @@
+import type { PassThroughProps } from "../../types";
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClInputNumberValuePassThrough = {
+ className?: string;
+ input?: PassThroughProps;
+};
+
+export type ClInputNumberOpPassThrough = {
+ className?: string;
+ minus?: PassThroughProps;
+ plus?: PassThroughProps;
+ icon?: ClIconProps;
+};
+
+export type ClInputNumberPassThrough = {
+ className?: string;
+ value?: ClInputNumberValuePassThrough;
+ op?: ClInputNumberOpPassThrough;
+};
+
+export type ClInputNumberProps = {
+ className?: string;
+ modelValue?: number;
+ pt?: ClInputNumberPassThrough;
+ placeholder?: string;
+ step?: number;
+ max?: number;
+ min?: number;
+ inputType?: "digit" | "number";
+ inputable?: boolean;
+ disabled?: boolean;
+ size?: number | string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-input-otp/cl-input-otp.uvue b/cool-unix/uni_modules/cool-ui/components/cl-input-otp/cl-input-otp.uvue
new file mode 100644
index 0000000..89ad20b
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-input-otp/cl-input-otp.uvue
@@ -0,0 +1,280 @@
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-input-otp/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-input-otp/props.ts
new file mode 100644
index 0000000..c427c0f
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-input-otp/props.ts
@@ -0,0 +1,19 @@
+import type { ClInputType, PassThroughProps } from "../../types";
+
+export type ClInputOtpPassThrough = {
+ className?: string;
+ list?: PassThroughProps;
+ item?: PassThroughProps;
+ cursor?: PassThroughProps;
+ value?: PassThroughProps;
+};
+
+export type ClInputOtpProps = {
+ className?: string;
+ pt?: ClInputOtpPassThrough;
+ modelValue?: string;
+ autofocus?: boolean;
+ length?: number;
+ disabled?: boolean;
+ inputType?: ClInputType;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-input/cl-input.uvue b/cool-unix/uni_modules/cool-ui/components/cl-input/cl-input.uvue
new file mode 100644
index 0000000..5f0037b
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-input/cl-input.uvue
@@ -0,0 +1,411 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-input/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-input/props.ts
new file mode 100644
index 0000000..a75909b
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-input/props.ts
@@ -0,0 +1,32 @@
+import type { ClInputType, PassThroughProps } from "../../types";
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClInputPassThrough = {
+ className?: string;
+ inner?: PassThroughProps;
+ prefixIcon?: ClIconProps;
+ suffixIcon?: ClIconProps;
+};
+
+export type ClInputProps = {
+ className?: string;
+ pt?: ClInputPassThrough;
+ modelValue?: string;
+ type?: ClInputType;
+ prefixIcon?: string;
+ suffixIcon?: string;
+ password?: boolean;
+ autofocus?: boolean;
+ disabled?: boolean;
+ readonly?: boolean;
+ placeholder?: string;
+ placeholderClass?: string;
+ border?: boolean;
+ clearable?: boolean;
+ cursorSpacing?: number;
+ confirmHold?: boolean;
+ confirmType?: "done" | "go" | "next" | "search" | "send";
+ adjustPosition?: boolean;
+ maxlength?: number;
+ holdKeyboard?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-keyboard-car/cl-keyboard-car.uvue b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-car/cl-keyboard-car.uvue
new file mode 100644
index 0000000..08c6807
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-car/cl-keyboard-car.uvue
@@ -0,0 +1,354 @@
+
+
+
+
+
+ {{ valueText }}
+
+ {{ placeholder }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-keyboard-car/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-car/props.ts
new file mode 100644
index 0000000..dcfd95f
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-car/props.ts
@@ -0,0 +1,20 @@
+import type { PassThroughProps } from "../../types";
+import type { ClPopupProps } from "../cl-popup/props";
+
+export type ClKeyboardCarPassThrough = {
+ className?: string;
+ item?: PassThroughProps;
+ value?: PassThroughProps;
+ popup?: ClPopupProps;
+};
+
+export type ClKeyboardCarProps = {
+ className?: string;
+ pt?: ClKeyboardCarPassThrough;
+ modelValue?: string;
+ title?: string;
+ placeholder?: string;
+ maxlength?: number;
+ showValue?: boolean;
+ inputImmediate?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-keyboard-number/cl-keyboard-number.uvue b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-number/cl-keyboard-number.uvue
new file mode 100644
index 0000000..9c5d31c
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-number/cl-keyboard-number.uvue
@@ -0,0 +1,431 @@
+
+
+
+
+
+ {{ value }}
+
+ {{ placeholder }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ confirmText }}
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ confirmText }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-keyboard-number/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-number/props.ts
new file mode 100644
index 0000000..e0d55a2
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-number/props.ts
@@ -0,0 +1,22 @@
+import type { PassThroughProps } from "../../types";
+import type { ClPopupProps } from "../cl-popup/props";
+
+export type ClKeyboardNumberPassThrough = {
+ className?: string;
+ item?: PassThroughProps;
+ value?: PassThroughProps;
+ popup?: ClPopupProps;
+};
+
+export type ClKeyboardNumberProps = {
+ className?: string;
+ pt?: ClKeyboardNumberPassThrough;
+ modelValue?: string;
+ type?: "number" | "digit" | "idcard";
+ title?: string;
+ placeholder?: string;
+ maxlength?: number;
+ confirmText?: string;
+ showValue?: boolean;
+ inputImmediate?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-keyboard-password/cl-keyboard-password.uvue b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-password/cl-keyboard-password.uvue
new file mode 100644
index 0000000..76fd7c8
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-password/cl-keyboard-password.uvue
@@ -0,0 +1,450 @@
+
+
+
+
+
+ {{ valueText }}
+
+ {{ placeholder }}
+
+
+
+
+
+
+
+
+
+ {{ confirmText }}
+
+ ABC
+
+ 123
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-keyboard-password/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-password/props.ts
new file mode 100644
index 0000000..4d6d0aa
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-keyboard-password/props.ts
@@ -0,0 +1,23 @@
+import type { PassThroughProps } from "../../types";
+import type { ClPopupProps } from "../cl-popup/props";
+
+export type ClKeyboardPasswordPassThrough = {
+ className?: string;
+ item?: PassThroughProps;
+ value?: PassThroughProps;
+ popup?: ClPopupProps;
+};
+
+export type ClKeyboardPasswordProps = {
+ className?: string;
+ pt?: ClKeyboardPasswordPassThrough;
+ modelValue?: string;
+ title?: string;
+ placeholder?: string;
+ minlength?: number;
+ maxlength?: number;
+ confirmText?: string;
+ showValue?: boolean;
+ inputImmediate?: boolean;
+ encrypt?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-list-item/cl-list-item.uvue b/cool-unix/uni_modules/cool-ui/components/cl-list-item/cl-list-item.uvue
new file mode 100644
index 0000000..162d896
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-list-item/cl-list-item.uvue
@@ -0,0 +1,436 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-list-item/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-list-item/props.ts
new file mode 100644
index 0000000..c01c053
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-list-item/props.ts
@@ -0,0 +1,28 @@
+import type { Justify, PassThroughProps } from "../../types";
+import type { ClIconProps } from "../cl-icon/props";
+import type { ClImageProps } from "../cl-image/props";
+
+export type ClListItemPassThrough = {
+ className?: string;
+ wrapper?: PassThroughProps;
+ inner?: PassThroughProps;
+ label?: PassThroughProps;
+ content?: PassThroughProps;
+ icon?: ClIconProps;
+ image?: ClImageProps;
+ collapse?: PassThroughProps;
+};
+
+export type ClListItemProps = {
+ className?: string;
+ pt?: ClListItemPassThrough;
+ icon?: string;
+ image?: string;
+ label?: string;
+ justify?: Justify;
+ arrow?: boolean;
+ swipeable?: boolean;
+ hoverable?: boolean;
+ disabled?: boolean;
+ collapse?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-list-view/cl-list-view.uvue b/cool-unix/uni_modules/cool-ui/components/cl-list-view/cl-list-view.uvue
new file mode 100644
index 0000000..377830b
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-list-view/cl-list-view.uvue
@@ -0,0 +1,759 @@
+
+
+
+
+
+
+
+
+
+ {{ refresherText }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.data.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ indexList[activeIndex] }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-list-view/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-list-view/props.ts
new file mode 100644
index 0000000..db0b568
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-list-view/props.ts
@@ -0,0 +1,33 @@
+import type { ClListViewItem, ClListViewGroup, ClListViewVirtualItem, PassThroughProps, ClListViewRefresherStatus } from "../../types";
+
+export type ClListViewPassThrough = {
+ className?: string;
+ item?: PassThroughProps;
+ itemHover?: PassThroughProps;
+ list?: PassThroughProps;
+ indexBar?: PassThroughProps;
+ scroller?: PassThroughProps;
+ refresher?: PassThroughProps;
+};
+
+export type ClListViewProps = {
+ className?: string;
+ pt?: ClListViewPassThrough;
+ data?: ClListViewItem[];
+ itemHeight?: number;
+ headerHeight?: number;
+ topHeight?: number;
+ bottomHeight?: number;
+ bufferSize?: number;
+ virtual?: boolean;
+ scrollIntoView?: string;
+ scrollWithAnimation?: boolean;
+ showScrollbar?: boolean;
+ refresherEnabled?: boolean;
+ refresherThreshold?: number;
+ refresherBackground?: string;
+ refresherDefaultText?: string;
+ refresherPullingText?: string;
+ refresherRefreshingText?: string;
+ showBackTop?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-list/cl-list.uvue b/cool-unix/uni_modules/cool-ui/components/cl-list/cl-list.uvue
new file mode 100644
index 0000000..4e5692e
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-list/cl-list.uvue
@@ -0,0 +1,115 @@
+
+
+
+ {{ title }}
+
+
+
+
+
+
+ {{ item.content }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-list/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-list/props.ts
new file mode 100644
index 0000000..8a6b221
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-list/props.ts
@@ -0,0 +1,16 @@
+import type { ClListItem, PassThroughProps } from "../../types";
+import type { ClListItemPassThrough } from "../cl-list-item/props";
+
+export type ClListPassThrough = {
+ className?: string;
+ list?: PassThroughProps;
+ item?: ClListItemPassThrough;
+};
+
+export type ClListProps = {
+ className?: string;
+ pt?: ClListPassThrough;
+ list?: ClListItem[];
+ title?: string;
+ border?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-loading/cl-loading.uvue b/cool-unix/uni_modules/cool-ui/components/cl-loading/cl-loading.uvue
new file mode 100644
index 0000000..e42aac1
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-loading/cl-loading.uvue
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-loading/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-loading/props.ts
new file mode 100644
index 0000000..cb2e520
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-loading/props.ts
@@ -0,0 +1,14 @@
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClLoadingPassThrough = {
+ className?: string;
+ icon?: ClIconProps;
+};
+
+export type ClLoadingProps = {
+ className?: string;
+ pt?: ClLoadingPassThrough;
+ loading?: boolean;
+ size?: any;
+ color?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-loadmore/cl-loadmore.uvue b/cool-unix/uni_modules/cool-ui/components/cl-loadmore/cl-loadmore.uvue
new file mode 100644
index 0000000..6c85ac0
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-loadmore/cl-loadmore.uvue
@@ -0,0 +1,96 @@
+
+
+
+
+
+ {{ message }}
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-loadmore/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-loadmore/props.ts
new file mode 100644
index 0000000..a02caee
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-loadmore/props.ts
@@ -0,0 +1,17 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClLoadmorePassThrough = {
+ className?: string;
+ icon?: PassThroughProps;
+ text?: PassThroughProps;
+};
+
+export type ClLoadmoreProps = {
+ className?: string;
+ pt?: ClLoadmorePassThrough;
+ loading?: boolean;
+ loadingText?: string;
+ finish?: boolean;
+ finishText?: string;
+ safeAreaBottom?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-marquee/cl-marquee.uvue b/cool-unix/uni_modules/cool-ui/components/cl-marquee/cl-marquee.uvue
new file mode 100644
index 0000000..0a84f3e
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-marquee/cl-marquee.uvue
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-marquee/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-marquee/props.ts
new file mode 100644
index 0000000..cd90859
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-marquee/props.ts
@@ -0,0 +1,19 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClMarqueePassThrough = {
+ className?: string;
+ list?: PassThroughProps;
+ item?: PassThroughProps;
+ image?: PassThroughProps;
+};
+
+export type ClMarqueeProps = {
+ className?: string;
+ pt?: ClMarqueePassThrough;
+ list?: string[];
+ direction?: "horizontal" | "vertical";
+ duration?: number;
+ itemHeight?: any;
+ itemWidth?: any;
+ gap?: any;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-noticebar/cl-noticebar.uvue b/cool-unix/uni_modules/cool-ui/components/cl-noticebar/cl-noticebar.uvue
new file mode 100644
index 0000000..386048b
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-noticebar/cl-noticebar.uvue
@@ -0,0 +1,255 @@
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-noticebar/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-noticebar/props.ts
new file mode 100644
index 0000000..b3aa589
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-noticebar/props.ts
@@ -0,0 +1,16 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClNoticebarPassThrough = {
+ className?: string;
+ text?: PassThroughProps;
+};
+
+export type ClNoticebarProps = {
+ className?: string;
+ pt?: ClNoticebarPassThrough;
+ text?: string | string[];
+ direction?: "horizontal" | "vertical";
+ duration?: number;
+ speed?: number;
+ height?: string | number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-page/cl-page.uvue b/cool-unix/uni_modules/cool-ui/components/cl-page/cl-page.uvue
new file mode 100644
index 0000000..4440cdb
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-page/cl-page.uvue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-page/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-page/props.ts
new file mode 100644
index 0000000..12c99df
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-page/props.ts
@@ -0,0 +1,4 @@
+export type ClPageProps = {
+ className?: string;
+ backTop?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-page/theme.uvue b/cool-unix/uni_modules/cool-ui/components/cl-page/theme.uvue
new file mode 100644
index 0000000..d26dc4d
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-page/theme.uvue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-page/ui.uvue b/cool-unix/uni_modules/cool-ui/components/cl-page/ui.uvue
new file mode 100644
index 0000000..41d3707
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-page/ui.uvue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-pagination/cl-pagination.uvue b/cool-unix/uni_modules/cool-ui/components/cl-pagination/cl-pagination.uvue
new file mode 100644
index 0000000..c82d725
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-pagination/cl-pagination.uvue
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-pagination/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-pagination/props.ts
new file mode 100644
index 0000000..a257e97
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-pagination/props.ts
@@ -0,0 +1,20 @@
+import type { PassThroughProps } from "../../types";
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClPaginationPassThrough = {
+ className?: string;
+ item?: PassThroughProps;
+ itemText?: PassThroughProps;
+ prev?: PassThroughProps;
+ prevIcon?: ClIconProps;
+ next?: PassThroughProps;
+ nextIcon?: ClIconProps;
+};
+
+export type ClPaginationProps = {
+ className?: string;
+ pt?: ClPaginationPassThrough;
+ modelValue?: number;
+ total?: number;
+ size?: number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-picker-view/cl-picker-view.uvue b/cool-unix/uni_modules/cool-ui/components/cl-picker-view/cl-picker-view.uvue
new file mode 100644
index 0000000..3efa2f9
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-picker-view/cl-picker-view.uvue
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-picker-view/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-picker-view/props.ts
new file mode 100644
index 0000000..756d22b
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-picker-view/props.ts
@@ -0,0 +1,10 @@
+import type { ClSelectOption } from "../../types";
+
+export type ClSelectPickerViewProps = {
+ className?: string;
+ headers?: string[];
+ value?: number[];
+ columns?: ClSelectOption[][];
+ itemHeight?: number;
+ height?: number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-popup/cl-popup.uvue b/cool-unix/uni_modules/cool-ui/components/cl-popup/cl-popup.uvue
new file mode 100644
index 0000000..743cbcf
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-popup/cl-popup.uvue
@@ -0,0 +1,647 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-popup/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-popup/props.ts
new file mode 100644
index 0000000..3df6265
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-popup/props.ts
@@ -0,0 +1,33 @@
+import type { ClPopupDirection, PassThroughProps } from "../../types";
+
+export type ClPopupHeaderPassThrough = {
+ className?: string;
+ text?: PassThroughProps;
+};
+
+export type ClPopupPassThrough = {
+ className?: string;
+ inner?: PassThroughProps;
+ header?: ClPopupHeaderPassThrough;
+ container?: PassThroughProps;
+ mask?: PassThroughProps;
+ draw?: PassThroughProps;
+};
+
+export type ClPopupProps = {
+ className?: string;
+ pt?: ClPopupPassThrough;
+ modelValue?: boolean;
+ title?: string;
+ direction?: ClPopupDirection;
+ size?: any;
+ showHeader?: boolean;
+ showClose?: boolean;
+ showMask?: boolean;
+ maskClosable?: boolean;
+ swipeClose?: boolean;
+ swipeCloseThreshold?: number;
+ pointerEvents?: "auto" | "none";
+ keepAlive?: boolean;
+ enablePortal?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-progress-circle/cl-progress-circle.uvue b/cool-unix/uni_modules/cool-ui/components/cl-progress-circle/cl-progress-circle.uvue
new file mode 100644
index 0000000..3559332
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-progress-circle/cl-progress-circle.uvue
@@ -0,0 +1,270 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-progress-circle/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-progress-circle/props.ts
new file mode 100644
index 0000000..a347983
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-progress-circle/props.ts
@@ -0,0 +1,21 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClProgressCirclePassThrough = {
+ className?: string;
+ text?: PassThroughProps;
+};
+
+export type ClProgressCircleProps = {
+ className?: string;
+ pt?: ClProgressCirclePassThrough;
+ value?: number;
+ size?: number;
+ strokeWidth?: number;
+ color?: string | any;
+ unColor?: string | any;
+ showText?: boolean;
+ unit?: string;
+ startAngle?: number;
+ clockwise?: boolean;
+ duration?: number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-progress/cl-progress.uvue b/cool-unix/uni_modules/cool-ui/components/cl-progress/cl-progress.uvue
new file mode 100644
index 0000000..486a1b5
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-progress/cl-progress.uvue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-progress/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-progress/props.ts
new file mode 100644
index 0000000..a1f82c6
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-progress/props.ts
@@ -0,0 +1,18 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClProgressPassThrough = {
+ className?: string;
+ outer?: PassThroughProps;
+ inner?: PassThroughProps;
+ text?: PassThroughProps;
+};
+
+export type ClProgressProps = {
+ className?: string;
+ pt?: ClProgressPassThrough;
+ value?: number;
+ strokeWidth?: number;
+ showText?: boolean;
+ color?: string;
+ unColor?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-qrcode/cl-qrcode.uvue b/cool-unix/uni_modules/cool-ui/components/cl-qrcode/cl-qrcode.uvue
new file mode 100644
index 0000000..051e35c
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-qrcode/cl-qrcode.uvue
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-qrcode/draw.ts b/cool-unix/uni_modules/cool-ui/components/cl-qrcode/draw.ts
new file mode 100644
index 0000000..47c2000
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-qrcode/draw.ts
@@ -0,0 +1,403 @@
+/**
+ * 导入所需的工具函数和依赖
+ */
+import { isNull } from "@/cool";
+import { generateFrame } from "./qrcode";
+import type { ClQrcodeMode } from "../../types";
+
+/**
+ * 二维码生成配置选项接口
+ * 定义了生成二维码所需的所有参数
+ */
+export type QrcodeOptions = {
+ ecc: string; // 纠错级别,可选 L/M/Q/H,纠错能力依次增强
+ text: string; // 二维码内容,要编码的文本
+ size: number; // 二维码尺寸,单位px
+ foreground: string; // 前景色,二维码数据点的颜色
+ background: string; // 背景色,二维码背景的颜色
+ padding: number; // 内边距,二维码四周留白的距离
+ logo: string; // logo图片地址,可以在二维码中心显示logo
+ logoSize: number; // logo尺寸,logo图片的显示大小
+ mode: ClQrcodeMode; // 二维码样式模式,支持矩形、圆形、线条、小方块
+ pdColor: string | null; // 定位点颜色,三个角上定位图案的颜色,为null时使用前景色
+ pdRadius: number; // 定位图案圆角半径,为0时绘制直角矩形
+};
+
+/**
+ * 获取当前设备的像素比
+ * 用于处理高分屏显示
+ * @returns 设备像素比
+ */
+function getRatio() {
+ // #ifdef APP || MP-WEIXIN
+ return uni.getWindowInfo().pixelRatio; // App和小程序环境
+ // #endif
+
+ // #ifdef H5
+ return window.devicePixelRatio; // H5环境
+ // #endif
+}
+
+/**
+ * 绘制圆角矩形
+ * 兼容不同平台的圆角矩形绘制方法
+ * @param ctx Canvas上下文
+ * @param x 矩形左上角x坐标
+ * @param y 矩形左上角y坐标
+ * @param width 矩形宽度
+ * @param height 矩形高度
+ * @param radius 圆角半径
+ */
+function drawRoundedRect(
+ ctx: CanvasRenderingContext2D,
+ x: number,
+ y: number,
+ width: number,
+ height: number,
+ radius: number
+) {
+ if (radius <= 0) {
+ // 圆角半径为0时直接绘制矩形
+ ctx.fillRect(x, y, width, height);
+ return;
+ }
+
+ // 限制圆角半径不超过矩形的一半
+ const maxRadius = Math.min(width, height) / 2;
+ const r = Math.min(radius, maxRadius);
+
+ ctx.beginPath();
+ ctx.moveTo(x + r, y);
+ ctx.lineTo(x + width - r, y);
+ ctx.arcTo(x + width, y, x + width, y + r, r);
+ ctx.lineTo(x + width, y + height - r);
+ ctx.arcTo(x + width, y + height, x + width - r, y + height, r);
+ ctx.lineTo(x + r, y + height);
+ ctx.arcTo(x, y + height, x, y + height - r, r);
+ ctx.lineTo(x, y + r);
+ ctx.arcTo(x, y, x + r, y, r);
+ ctx.closePath();
+ ctx.fill();
+}
+
+/**
+ * 绘制定位图案
+ * 绘制7x7的定位图案,包含外框、内框和中心点
+ * @param ctx Canvas上下文
+ * @param startX 定位图案起始X坐标
+ * @param startY 定位图案起始Y坐标
+ * @param px 单个像素点大小
+ * @param pdColor 定位图案颜色
+ * @param background 背景颜色
+ * @param radius 圆角半径
+ */
+function drawPositionPattern(
+ ctx: CanvasRenderingContext2D,
+ startX: number,
+ startY: number,
+ px: number,
+ pdColor: string,
+ background: string,
+ radius: number
+) {
+ const patternSize = px * 7; // 定位图案总尺寸 7x7
+
+ // 绘制外层边框 (7x7)
+ ctx.fillStyle = pdColor;
+ drawRoundedRect(ctx, startX, startY, patternSize, patternSize, radius);
+
+ // 绘制内层空心区域 (5x5)
+ ctx.fillStyle = background;
+ const innerStartX = startX + px;
+ const innerStartY = startY + px;
+ const innerSize = px * 5;
+ const innerRadius = Math.max(0, radius - px); // 内层圆角适当减小
+ drawRoundedRect(ctx, innerStartX, innerStartY, innerSize, innerSize, innerRadius);
+
+ // 绘制中心实心区域 (3x3)
+ ctx.fillStyle = pdColor;
+ const centerStartX = startX + px * 2;
+ const centerStartY = startY + px * 2;
+ const centerSize = px * 3;
+ const centerRadius = Math.max(0, radius - px * 2); // 中心圆角适当减小
+ drawRoundedRect(ctx, centerStartX, centerStartY, centerSize, centerSize, centerRadius);
+}
+
+/**
+ * 绘制二维码到Canvas上下文
+ * 主要的二维码绘制函数,处理不同平台的兼容性
+ * @param context Canvas上下文对象
+ * @param options 二维码配置选项
+ */
+export function drawQrcode(context: CanvasContext, options: QrcodeOptions) {
+ // 获取2D绘图上下文
+ const ctx = context.getContext("2d")!;
+ if (isNull(ctx)) return;
+
+ // 获取设备像素比,用于高清适配
+ const ratio = getRatio();
+
+ // App和小程序平台的画布初始化
+ // #ifdef APP || MP-WEIXIN
+ const c1 = ctx.canvas;
+ // 清空画布并设置尺寸
+ ctx.clearRect(0, 0, c1.offsetWidth, c1.offsetHeight);
+ c1.width = c1.offsetWidth * ratio;
+ c1.height = c1.offsetHeight * ratio;
+ // #endif
+
+ // #ifdef APP
+ ctx.reset();
+ // #endif
+
+ // H5平台的画布初始化
+ // #ifdef H5
+ const c2 = context as HTMLCanvasElement;
+ c2.width = c2.offsetWidth * ratio;
+ c2.height = c2.offsetHeight * ratio;
+ // #endif
+
+ // 缩放画布以适配高分屏
+ ctx.scale(ratio, ratio);
+
+ // 生成二维码数据矩阵
+ const frame = generateFrame(options.text, options.ecc);
+ const points = frame.frameBuffer; // 点阵数据
+ const width = frame.width; // 矩阵宽度
+
+ // 计算二维码内容区域大小(减去四周的padding)
+ const contentSize = options.size - options.padding * 2;
+ // 计算每个数据点的实际像素大小
+ const px = contentSize / width;
+ // 二维码内容的起始位置(考虑padding)
+ const offsetX = options.padding;
+ const offsetY = options.padding;
+
+ // 绘制整个画布背景
+ ctx.fillStyle = options.background;
+ ctx.fillRect(0, 0, options.size, options.size);
+
+ /**
+ * 判断坐标点是否在定位图案区域内
+ * 二维码三个角上的定位图案是7x7的方块
+ * @param i 横坐标
+ * @param j 纵坐标
+ * @param width 二维码宽度
+ * @returns 是否是定位点
+ */
+ function isPositionDetectionPattern(i: number, j: number, width: number): boolean {
+ // 判断三个角的定位图案(7x7)
+ if (i < 7 && j < 7) return true; // 左上角
+ if (i > width - 8 && j < 7) return true; // 右上角
+ if (i < 7 && j > width - 8) return true; // 左下角
+ return false;
+ }
+
+ /**
+ * 判断坐标点是否在Logo区域内(包含缓冲区)
+ * @param i 横坐标
+ * @param j 纵坐标
+ * @param width 二维码宽度
+ * @param logoSize logo尺寸(像素)
+ * @param px 单个数据点像素大小
+ * @returns 是否在logo区域内
+ */
+ function isInLogoArea(
+ i: number,
+ j: number,
+ width: number,
+ logoSize: number,
+ px: number
+ ): boolean {
+ if (logoSize <= 0) return false;
+
+ // 计算logo在矩阵中占用的点数,限制最大不超过二维码总宽度的25%
+ // 根据二维码标准,中心区域最多可以遮挡约30%的数据,但为了确保识别率,我们限制在20%
+ const maxLogoRatio = 0.2; // 20%的区域用于logo
+ const maxLogoPoints = Math.floor(width * maxLogoRatio);
+ const logoPoints = Math.min(Math.ceil(logoSize / px), maxLogoPoints);
+
+ // 减少缓冲区,只保留必要的边距,避免过度遮挡数据
+ // 当logo较小时不需要缓冲区,当logo较大时才添加最小缓冲区
+ const buffer = logoPoints > width * 0.1 ? 1 : 0;
+ const totalLogoPoints = logoPoints + buffer * 2;
+
+ // 计算logo区域在矩阵中的中心位置
+ const centerI = Math.floor(width / 2);
+ const centerJ = Math.floor(width / 2);
+
+ // 计算logo区域的边界
+ const halfSize = Math.floor(totalLogoPoints / 2);
+ const minI = centerI - halfSize;
+ const maxI = centerI + halfSize;
+ const minJ = centerJ - halfSize;
+ const maxJ = centerJ + halfSize;
+
+ // 判断当前点是否在logo区域内
+ return i >= minI && i <= maxI && j >= minJ && j <= maxJ;
+ }
+
+ // 先绘制定位图案
+ const pdColor = options.pdColor ?? options.foreground;
+ const radius = options.pdRadius;
+
+ // 绘制三个定位图案
+ // 左上角 (0, 0)
+ drawPositionPattern(ctx, offsetX, offsetY, px, pdColor, options.background, radius);
+ // 右上角 (width-7, 0)
+ drawPositionPattern(
+ ctx,
+ offsetX + (width - 7) * px,
+ offsetY,
+ px,
+ pdColor,
+ options.background,
+ radius
+ );
+ // 左下角 (0, width-7)
+ drawPositionPattern(
+ ctx,
+ offsetX,
+ offsetY + (width - 7) * px,
+ px,
+ pdColor,
+ options.background,
+ radius
+ );
+
+ // 点的间距,用于圆形和小方块模式
+ const dot = px * 0.1;
+
+ // 遍历绘制数据点(跳过定位图案区域和logo区域)
+ for (let i = 0; i < width; i++) {
+ for (let j = 0; j < width; j++) {
+ if (points[j * width + i] > 0) {
+ // 跳过定位图案区域
+ if (isPositionDetectionPattern(i, j, width)) {
+ continue;
+ }
+
+ // 跳过logo区域(包含缓冲区)
+ if (options.logo != "" && isInLogoArea(i, j, width, options.logoSize, px)) {
+ continue;
+ }
+
+ // 绘制数据点
+ ctx.fillStyle = options.foreground;
+ const x = offsetX + px * i;
+ const y = offsetY + px * j;
+
+ // 根据不同模式绘制数据点
+ switch (options.mode) {
+ case "line": // 线条模式 - 绘制水平线条
+ ctx.fillRect(x, y, px, px / 2);
+ break;
+
+ case "circular": // 圆形模式 - 绘制圆点
+ ctx.beginPath();
+ const rx = x + px / 2 - dot;
+ const ry = y + px / 2 - dot;
+ ctx.arc(rx, ry, px / 2 - dot, 0, 2 * Math.PI);
+ ctx.fill();
+ ctx.closePath();
+ break;
+
+ case "rectSmall": // 小方块模式 - 绘制小一号的方块
+ ctx.fillRect(x + dot, y + dot, px - dot * 2, px - dot * 2);
+ break;
+
+ default: // 默认实心方块模式
+ ctx.fillRect(x, y, px, px);
+ }
+ }
+ }
+ }
+
+ // 绘制 Logo
+ if (options.logo != "") {
+ let img: Image;
+
+ // 微信小程序环境创建图片
+ // #ifdef MP-WEIXIN || APP-HARMONY
+ img = context.createImage();
+ // #endif
+
+ // 其他环境创建图片
+ // #ifndef MP-WEIXIN || APP-HARMONY
+ img = new Image(options.logoSize, options.logoSize);
+ // #endif
+
+ // 设置图片加载完成后的回调,然后设置图片源
+ img.onload = () => {
+ drawLogo(ctx, options, img);
+ };
+ img.src = options.logo;
+ }
+}
+
+/**
+ * 在二维码中心绘制Logo
+ * 在二维码中心位置绘制Logo图片,优化背景处理以减少对二维码数据的影响
+ * @param ctx Canvas上下文
+ * @param options 二维码配置
+ * @param img Logo图片对象
+ */
+function drawLogo(ctx: CanvasRenderingContext2D, options: QrcodeOptions, img: Image) {
+ ctx.save(); // 保存当前绘图状态
+
+ // 计算二维码内容区域的中心位置(考虑padding)
+ const contentSize = options.size - options.padding * 2;
+ const contentCenterX = options.padding + contentSize / 2;
+ const contentCenterY = options.padding + contentSize / 2;
+
+ // 优化背景处理:减少背景边距,最小化对二维码数据的影响
+ // 背景边距从6px减少到3px,降低对数据点的遮挡
+ const backgroundPadding = 3; // 背景比logo大3px
+ const backgroundSize = options.logoSize + backgroundPadding * 2;
+
+ // 绘制白色背景作为Logo的底色(适当大于logo以确保可读性)
+ ctx.fillStyle = options.background; // 使用二维码背景色而不是固定白色,保持一致性
+ const backgroundX = contentCenterX - backgroundSize / 2;
+ const backgroundY = contentCenterY - backgroundSize / 2;
+
+ // 绘制圆角背景,让logo与二维码更好融合
+ const cornerRadius = Math.min(backgroundSize * 0.1, 6); // 背景圆角半径
+ drawRoundedRect(ctx, backgroundX, backgroundY, backgroundSize, backgroundSize, cornerRadius);
+
+ // 获取图片信息后绘制Logo
+ uni.getImageInfo({
+ src: options.logo,
+ success: (imgInfo) => {
+ // 计算logo的精确位置
+ const logoX = contentCenterX - options.logoSize / 2;
+ const logoY = contentCenterY - options.logoSize / 2;
+
+ // 绘制Logo图片,减少边距从3px到1.5px,让logo更大一些
+ const logoPadding = 1.5;
+ const actualLogoSize = options.logoSize - logoPadding * 2;
+
+ // #ifdef APP-HARMONY
+ ctx.drawImage(
+ img,
+ logoX + logoPadding,
+ logoY + logoPadding,
+ actualLogoSize,
+ actualLogoSize,
+ 0,
+ 0,
+ imgInfo.width,
+ imgInfo.height
+ );
+ // #endif
+
+ // #ifndef APP-HARMONY
+ ctx.drawImage(img, logoX + logoPadding, logoY + logoPadding, actualLogoSize, actualLogoSize);
+ // #endif
+
+ ctx.restore(); // 恢复之前的绘图状态
+ },
+ fail(err) {
+ console.error(err);
+ }
+ });
+}
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-qrcode/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-qrcode/props.ts
new file mode 100644
index 0000000..1dc526e
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-qrcode/props.ts
@@ -0,0 +1,17 @@
+import type { QrcodeOptions } from "./draw";
+import type { ClQrcodeMode } from "../../types";
+
+export type ClQrcodeProps = {
+ className?: string;
+ width?: string;
+ height?: string;
+ foreground?: string;
+ background?: string;
+ pdColor?: string | any;
+ pdRadius?: number;
+ text?: string;
+ logo?: string;
+ logoSize?: string;
+ padding?: number;
+ mode?: ClQrcodeMode;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-qrcode/qrcode.ts b/cool-unix/uni_modules/cool-ui/components/cl-qrcode/qrcode.ts
new file mode 100644
index 0000000..0b5a1d5
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-qrcode/qrcode.ts
@@ -0,0 +1,972 @@
+export type GenerateFrameResult = {
+ frameBuffer: Uint8Array;
+ width: number;
+};
+
+/**
+ * 二维码生成器
+ * @description 纯 UTS 实现的二维码生成算法,支持多平台,兼容 uni-app x。核心算法参考 QR Code 标准,支持自定义纠错级别、自动适配内容长度。
+ * @version 1.0.0
+ * @平台兼容性 App、H5、微信小程序、UTS
+ * @注意事项
+ * - 仅支持 8bit 字符串内容,不支持数字/字母/汉字等模式优化
+ * - 生成结果为二维码点阵数据和宽度,需配合 canvas 绘制
+ * - 纠错级别支持 'L'/'M'/'Q'/'H',默认 'L'
+ */
+
+// 对齐块间距表 - 不同版本二维码的对齐块分布位置
+const ALIGNMENT_DELTA = [
+ 0, 11, 15, 19, 23, 27, 31, 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
+ 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
+] as number[];
+
+// 纠错块参数表 - 每个版本包含4个参数:块数、数据宽度、纠错宽度
+const ECC_BLOCKS = [
+ 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17, 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22,
+ 1, 0, 16, 28, 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22, 1, 0, 80, 20, 2, 0, 32,
+ 18, 2, 0, 24, 26, 4, 0, 9, 16, 1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22, 2, 0,
+ 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28, 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4,
+ 1, 13, 26, 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26, 2, 0, 116, 30, 3, 2, 36, 22,
+ 4, 4, 16, 20, 4, 4, 12, 24, 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28, 4, 0, 81,
+ 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24, 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4,
+ 14, 28, 4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22, 3, 1, 115, 30, 4, 5, 40, 24,
+ 11, 5, 16, 20, 11, 5, 12, 24, 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24, 5, 1, 98,
+ 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30, 1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2,
+ 17, 14, 28, 5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28, 3, 4, 113, 28, 3, 11, 44,
+ 26, 17, 4, 21, 26, 9, 16, 13, 26, 3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28,
+ 4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30, 2, 7, 111, 28, 17, 0, 46, 28, 7, 16,
+ 24, 30, 34, 0, 13, 24, 4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30, 6, 4, 117,
+ 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30, 8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30,
+ 22, 13, 15, 30, 10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30, 8, 4, 122, 30, 22,
+ 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30, 3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31,
+ 15, 30, 7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30, 5, 10, 115, 30, 19, 10, 47,
+ 28, 15, 25, 24, 30, 23, 25, 15, 30, 13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15,
+ 30, 17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30, 17, 1, 115, 30, 14, 21, 46,
+ 28, 29, 19, 24, 30, 11, 46, 15, 30, 13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16,
+ 30, 12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30, 6, 14, 121, 30, 6, 34, 47,
+ 28, 46, 10, 24, 30, 2, 64, 15, 30, 17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15,
+ 30, 4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30, 20, 4, 117, 30, 40, 7, 47,
+ 28, 43, 22, 24, 30, 10, 67, 15, 30, 19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15,
+ 30
+] as number[];
+
+// 纠错级别映射表 - 将人类可读的纠错级别映射为内部数值
+const ECC_LEVELS = new Map([
+ ["L", 1],
+ ["M", 0],
+ ["Q", 3],
+ ["H", 2]
+]);
+
+// 最终格式信息掩码表 - 用于格式信息区域的掩码计算(level << 3 | mask)
+const FINAL_FORMAT = [
+ 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976 /* L */, 0x5412, 0x5125, 0x5e7c,
+ 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0 /* M */, 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183,
+ 0x2eda, 0x2bed /* Q */, 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b /* H */
+];
+
+// Galois域指数表 - 用于纠错码计算的查找表
+const GALOIS_EXPONENT = [
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
+ 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
+ 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
+ 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
+ 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
+ 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
+ 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
+ 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
+ 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
+ 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
+ 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
+ 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
+ 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
+ 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
+ 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
+ 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
+];
+
+// Galois域对数表 - 用于纠错码计算的反向查找表
+const GALOIS_LOG = [
+ 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
+ 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
+ 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
+ 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
+ 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
+ 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
+ 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
+ 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
+ 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
+ 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
+ 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
+ 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
+ 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
+ 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
+ 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
+ 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
+];
+
+// 二维码质量评估系数 - 用于计算最佳掩码模式
+// N1: 连续5个及以上同色模块的惩罚分数
+const N1 = 3;
+// N2: 2x2同色模块区域的惩罚分数
+const N2 = 3;
+// N3: 类似定位图形的图案(1:1:3:1:1)的惩罚分数
+const N3 = 40;
+// N4: 黑白模块比例不均衡的惩罚分数
+const N4 = 10;
+
+// 版本信息掩码表 - 用于在二维码中嵌入版本信息
+const VERSION_BLOCK = [
+ 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, 0x928, 0xb78, 0x45d, 0xa17, 0x532,
+ 0x9a6, 0x683, 0x8c9, 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 0x250, 0x9d5,
+ 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 0x541, 0xc69
+];
+
+/**
+ * 生成二维码点阵
+ * @param _str 输入字符串,支持任意文本内容,默认 null 表示空字符串
+ * @param ecc 纠错级别,可选 'L' | 'M' | 'Q' | 'H',默认 'L'
+ * @returns {GenerateFrameResult} 返回二维码点阵数据和宽度
+ */
+export function generateFrame(
+ _str: string | null = null,
+ ecc: string | null = null
+): GenerateFrameResult {
+ // 变量声明区,所有临时变量、缓冲区
+ let i: number;
+ let t: number;
+ let j: number;
+ let k: number;
+ let m: number;
+ let v: number;
+ let x: number;
+ let y: number;
+ let version: number;
+ let str = _str == null ? "" : _str;
+ let width = 0;
+ // 获取纠错级别数值
+ let eccLevel = ECC_LEVELS.get(ecc == null ? "L" : ecc)!;
+
+ // Data block
+ // 数据块、纠错块、块数
+ let dataBlock: number;
+ let eccBlock: number;
+ let neccBlock1: number;
+ let neccBlock2: number;
+
+ // ECC buffer.
+ // 纠错码缓冲区 - 先初始化为空数组,后面会重新赋值
+ let eccBuffer: Uint8Array;
+
+ // Image buffer.
+ // 二维码点阵缓冲区 - 先初始化为空数组,后面会重新赋值
+ let frameBuffer = new Uint8Array(0);
+
+ // Fixed part of the image.
+ // 点阵掩码缓冲区(标记不可变区域) - 先初始化为空数组,后面会重新赋值
+ let frameMask = new Uint8Array(0);
+
+ // Generator polynomial.
+ // 生成多项式缓冲区(纠错码计算用) - 先初始化为空数组,后面会重新赋值
+ let polynomial = new Uint8Array(0);
+
+ // Data input buffer.
+ // 数据输入缓冲区 - 先初始化为空数组,后面会重新赋值
+ let stringBuffer = new Uint8Array(0);
+
+ /**
+ * 设置掩码位,表示该点为不可变区域(对称处理)
+ * @param _x 横坐标
+ * @param _y 纵坐标
+ */
+ function setMask(_x: number, _y: number) {
+ let bit: number;
+ let x = _x;
+ let y = _y;
+
+ if (x > y) {
+ bit = x;
+ x = y;
+ y = bit;
+ }
+
+ bit = y;
+ bit *= y;
+ bit += y;
+ bit >>= 1;
+ bit += x;
+
+ frameMask[bit] = 1;
+ }
+
+ /**
+ * 添加对齐块,设置对应点阵和掩码
+ * @param _x 横坐标
+ * @param _y 纵坐标
+ */
+ function addAlignment(_x: number, _y: number) {
+ let i: number;
+ let x = _x;
+ let y = _y;
+
+ frameBuffer[x + width * y] = 1;
+
+ for (i = -2; i < 2; i++) {
+ frameBuffer[x + i + width * (y - 2)] = 1;
+ frameBuffer[x - 2 + width * (y + i + 1)] = 1;
+ frameBuffer[x + 2 + width * (y + i)] = 1;
+ frameBuffer[x + i + 1 + width * (y + 2)] = 1;
+ }
+
+ for (i = 0; i < 2; i++) {
+ setMask(x - 1, y + i);
+ setMask(x + 1, y - i);
+ setMask(x - i, y - 1);
+ setMask(x + i, y + 1);
+ }
+
+ for (i = 2; i < 4; i++) {
+ frameBuffer[x + i + width * (y - 2)] = 1;
+ frameBuffer[x - 2 + width * (y + i - 1)] = 1;
+ frameBuffer[x + 2 + width * (y + i - 2)] = 1;
+ frameBuffer[x - 1 + width * (y + i - 2)] = 1;
+ }
+ }
+
+ /**
+ * Galois 域取模运算
+ * @param _x 输入数值
+ * @returns {number} 取模结果
+ */
+ function modN(_x: number): number {
+ var x = _x;
+ while (x >= 255) {
+ x -= 255;
+ x = (x >> 8) + (x & 255);
+ }
+
+ return x;
+ }
+
+ /**
+ * 计算并追加纠错码到数据块
+ * @param _data 数据起始索引
+ * @param _dataLength 数据长度
+ * @param _ecc 纠错码起始索引
+ * @param _eccLength 纠错码长度
+ */
+ function appendData(_data: number, _dataLength: number, _ecc: number, _eccLength: number) {
+ let bit: number;
+ let i: number;
+ let j: number;
+ let data = _data;
+ let dataLength = _dataLength;
+ let ecc = _ecc;
+ let eccLength = _eccLength;
+
+ for (i = 0; i < eccLength; i++) {
+ stringBuffer[ecc + i] = 0;
+ }
+
+ for (i = 0; i < dataLength; i++) {
+ bit = GALOIS_LOG[stringBuffer[data + i] ^ stringBuffer[ecc]];
+
+ if (bit != 255) {
+ for (j = 1; j < eccLength; j++) {
+ stringBuffer[ecc + j - 1] =
+ stringBuffer[ecc + j] ^
+ GALOIS_EXPONENT[modN(bit + polynomial[eccLength - j])];
+ }
+ } else {
+ for (j = ecc; j < ecc + eccLength; j++) {
+ stringBuffer[j] = stringBuffer[j + 1];
+ }
+ }
+
+ stringBuffer[ecc + eccLength - 1] =
+ bit == 255 ? 0 : GALOIS_EXPONENT[modN(bit + polynomial[0])];
+ }
+ }
+
+ /**
+ * 判断某点是否为掩码区域
+ * @param _x 横坐标
+ * @param _y 纵坐标
+ * @returns {boolean} 是否为掩码
+ */
+ function isMasked(_x: number, _y: number): boolean {
+ let bit: number;
+ let x = _x;
+ let y = _y;
+
+ if (x > y) {
+ bit = x;
+ x = y;
+ y = bit;
+ }
+
+ bit = y;
+ bit += y * y;
+ bit >>= 1;
+ bit += x;
+ return frameMask[bit] == 1;
+ }
+
+ /**
+ * 根据 QR Code 标准,应用指定的掩码 pattern
+ * @param mask 掩码编号 (0-7)
+ */
+ function applyMask(mask: number) {
+ for (let y = 0; y < width; y++) {
+ for (let x = 0; x < width; x++) {
+ if (!isMasked(x, y)) {
+ let shouldInvert = false;
+ switch (mask) {
+ case 0:
+ shouldInvert = (x + y) % 2 == 0;
+ break;
+ case 1:
+ shouldInvert = y % 2 == 0;
+ break;
+ case 2:
+ shouldInvert = x % 3 == 0;
+ break;
+ case 3:
+ shouldInvert = (x + y) % 3 == 0;
+ break;
+ case 4:
+ shouldInvert = (Math.floor(y / 2) + Math.floor(x / 3)) % 2 == 0;
+ break;
+ case 5:
+ shouldInvert = ((x * y) % 2) + ((x * y) % 3) == 0;
+ break;
+ case 6:
+ shouldInvert = (((x * y) % 2) + ((x * y) % 3)) % 2 == 0;
+ break;
+ case 7:
+ shouldInvert = (((x + y) % 2) + ((x * y) % 3)) % 2 == 0;
+ break;
+ }
+
+ if (shouldInvert) {
+ frameBuffer[x + y * width] ^= 1;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 计算连续同色块的"坏度"分数
+ * @param runLengths
+ * @param length 块长度
+ * @returns {number} 坏度分数
+ */
+ function getBadRuns(runLengths: number[], length: number): number {
+ let badRuns = 0;
+ let i: number;
+
+ for (i = 0; i <= length; i++) {
+ if (i < runLengths.length && runLengths[i] >= 5) {
+ badRuns += N1 + runLengths[i] - 5;
+ }
+ }
+
+ // FBFFFBF as in finder.
+ for (i = 3; i < length - 1; i += 2) {
+ // 检查数组索引是否越界
+ if (i + 2 >= runLengths.length || i - 3 < 0) {
+ continue;
+ }
+
+ if (
+ runLengths[i - 2] == runLengths[i + 2] &&
+ runLengths[i + 2] == runLengths[i - 1] &&
+ runLengths[i - 1] == runLengths[i + 1] &&
+ runLengths[i - 1] * 3 == runLengths[i] &&
+ // Background around the foreground pattern? Not part of the specs.
+ (runLengths[i - 3] == 0 ||
+ i + 3 > length ||
+ runLengths[i - 3] * 3 >= runLengths[i] * 4 ||
+ runLengths[i + 3] * 3 >= runLengths[i] * 4)
+ ) {
+ badRuns += N3;
+ }
+ }
+
+ return badRuns;
+ }
+
+ /**
+ * 评估当前二维码点阵的整体"坏度"
+ * @returns {number} 坏度分数
+ */
+ function checkBadness(): number {
+ let b: number;
+ let b1: number;
+ let bad = 0;
+ let big: number;
+ let bw = 0;
+ let count = 0;
+ let h: number;
+ let x: number;
+ let y: number;
+ // 优化:在函数内创建badBuffer,避免外部变量的内存泄漏风险
+ let badBuffer = new Array(width);
+
+ // Blocks of same colour.
+ for (y = 0; y < width - 1; y++) {
+ for (x = 0; x < width - 1; x++) {
+ // All foreground colour.
+ if (
+ (frameBuffer[x + width * y] == 1 &&
+ frameBuffer[x + 1 + width * y] == 1 &&
+ frameBuffer[x + width * (y + 1)] == 1 &&
+ frameBuffer[x + 1 + width * (y + 1)] == 1) ||
+ // All background colour.
+ (frameBuffer[x + width * y] == 0 &&
+ frameBuffer[x + 1 + width * y] == 0 &&
+ frameBuffer[x + width * (y + 1)] == 0 &&
+ frameBuffer[x + 1 + width * (y + 1)] == 0)
+ ) {
+ bad += N2;
+ }
+ }
+ }
+
+ // X runs
+ for (y = 0; y < width; y++) {
+ h = 0;
+ badBuffer[h] = 0;
+ b = 0;
+ for (x = 0; x < width; x++) {
+ b1 = frameBuffer[x + width * y];
+ if (b1 == b) {
+ if (h < badBuffer.length) {
+ badBuffer[h]++;
+ }
+ } else {
+ h++;
+
+ if (h < badBuffer.length) {
+ badBuffer[h] = 1;
+ }
+ }
+
+ b = b1;
+ bw += b > 0 ? 1 : -1;
+ }
+
+ bad += getBadRuns(badBuffer, h);
+ }
+
+ if (bw < 0) bw = -bw;
+
+ big = bw;
+ big += big << 2;
+ big <<= 1;
+
+ while (big > width * width) {
+ big -= width * width;
+ count++;
+ }
+
+ bad += count * N4;
+
+ // Y runs.
+ for (x = 0; x < width; x++) {
+ h = 0;
+ badBuffer[h] = 0;
+ b = 0;
+ for (y = 0; y < width; y++) {
+ b1 = frameBuffer[x + width * y];
+ if (b1 == b) {
+ if (h < badBuffer.length) {
+ badBuffer[h]++;
+ }
+ } else {
+ h++;
+ if (h < badBuffer.length) {
+ badBuffer[h] = 1;
+ }
+ }
+
+ b = b1;
+ }
+
+ bad += getBadRuns(badBuffer, h);
+ }
+
+ return bad;
+ }
+
+ /**
+ * 将字符串转为 UTF-8 编码,兼容多平台
+ * @param str 输入字符串
+ * @returns {string} UTF-8 编码字符串
+ */
+ function toUtf8(str: string): string {
+ let out = "";
+ let i: number;
+ let len: number;
+ let c: number;
+ len = str.length;
+ for (i = 0; i < len; i++) {
+ c = str.charCodeAt(i)!;
+ if (c >= 0x0001 && c <= 0x007f) {
+ out += str.charAt(i);
+ } else if (c > 0x07ff) {
+ out += String.fromCharCode(0xe0 | ((c >> 12) & 0x0f));
+ out += String.fromCharCode(0x80 | ((c >> 6) & 0x3f));
+ out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f));
+ } else {
+ out += String.fromCharCode(0xc0 | ((c >> 6) & 0x1f));
+ out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f));
+ }
+ }
+ return out;
+ }
+ //end functions
+
+ // Find the smallest version that fits the string.
+ // 1. 字符串转 UTF-8,计算长度
+ str = toUtf8(str);
+ t = str.length;
+
+ // 2. 自动选择最小可用版本
+ version = 0;
+ do {
+ version++;
+ k = (eccLevel - 1) * 4 + (version - 1) * 16;
+ neccBlock1 = ECC_BLOCKS[k++];
+ neccBlock2 = ECC_BLOCKS[k++];
+ dataBlock = ECC_BLOCKS[k++];
+ eccBlock = ECC_BLOCKS[k];
+
+ k = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2 - 3 + (version <= 9 ? 1 : 0);
+
+ if (t <= k) break;
+ } while (version < 40);
+
+ // FIXME: Ensure that it fits insted of being truncated.
+ // 3. 计算二维码宽度
+ width = 17 + 4 * version;
+
+ // Allocate, clear and setup data structures.
+ // 4. 分配缓冲区, 使用定长的 Uint8Array 优化内存
+ v = dataBlock + (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2;
+ eccBuffer = new Uint8Array(v);
+ stringBuffer = new Uint8Array(v);
+
+ // 5. 预分配点阵、掩码缓冲区
+ frameBuffer = new Uint8Array(width * width);
+ frameMask = new Uint8Array(Math.floor((width * (width + 1) + 1) / 2));
+
+ // Insert finders: Foreground colour to frame and background to mask.
+ // 插入定位点: 前景色为二维码,背景色为掩码
+ for (t = 0; t < 3; t++) {
+ k = 0;
+ y = 0;
+ if (t == 1) k = width - 7;
+ if (t == 2) y = width - 7;
+
+ frameBuffer[y + 3 + width * (k + 3)] = 1;
+
+ for (x = 0; x < 6; x++) {
+ frameBuffer[y + x + width * k] = 1;
+ frameBuffer[y + width * (k + x + 1)] = 1;
+ frameBuffer[y + 6 + width * (k + x)] = 1;
+ frameBuffer[y + x + 1 + width * (k + 6)] = 1;
+ }
+
+ for (x = 1; x < 5; x++) {
+ setMask(y + x, k + 1);
+ setMask(y + 1, k + x + 1);
+ setMask(y + 5, k + x);
+ setMask(y + x + 1, k + 5);
+ }
+
+ for (x = 2; x < 4; x++) {
+ frameBuffer[y + x + width * (k + 2)] = 1;
+ frameBuffer[y + 2 + width * (k + x + 1)] = 1;
+ frameBuffer[y + 4 + width * (k + x)] = 1;
+ frameBuffer[y + x + 1 + width * (k + 4)] = 1;
+ }
+ }
+
+ // Alignment blocks.
+ // 插入对齐点: 前景色为二维码,背景色为掩码
+ if (version > 1) {
+ t = ALIGNMENT_DELTA[version];
+ y = width - 7;
+
+ for (;;) {
+ x = width - 7;
+
+ while (x > t - 3) {
+ addAlignment(x, y);
+
+ if (x < t) break;
+
+ x -= t;
+ }
+
+ if (y <= t + 9) break;
+
+ y -= t;
+
+ addAlignment(6, y);
+ addAlignment(y, 6);
+ }
+ }
+
+ // Single foreground cell.
+ // 插入单个前景色单元格: 前景色为二维码,背景色为掩码
+ frameBuffer[8 + width * (width - 8)] = 1;
+
+ // Timing gap (mask only).
+ // 插入时间间隔: 掩码
+ for (y = 0; y < 7; y++) {
+ setMask(7, y);
+ setMask(width - 8, y);
+ setMask(7, y + width - 7);
+ }
+
+ for (x = 0; x < 8; x++) {
+ setMask(x, 7);
+ setMask(x + width - 8, 7);
+ setMask(x, width - 8);
+ }
+
+ // Reserve mask, format area.
+ // 保留掩码,格式化区域
+ for (x = 0; x < 9; x++) {
+ setMask(x, 8);
+ }
+
+ for (x = 0; x < 8; x++) {
+ setMask(x + width - 8, 8);
+ setMask(8, x);
+ }
+
+ for (y = 0; y < 7; y++) {
+ setMask(8, y + width - 7);
+ }
+
+ // Timing row/column.
+ // 插入时间间隔行/列: 掩码
+ for (x = 0; x < width - 14; x++) {
+ if ((x & 1) > 0) {
+ setMask(8 + x, 6);
+ setMask(6, 8 + x);
+ } else {
+ frameBuffer[8 + x + width * 6] = 1;
+ frameBuffer[6 + width * (8 + x)] = 1;
+ }
+ }
+
+ // Version block.
+ if (version > 6) {
+ t = VERSION_BLOCK[version - 7];
+ k = 17;
+
+ for (x = 0; x < 6; x++) {
+ for (y = 0; y < 3; y++) {
+ if ((1 & (k > 11 ? version >> (k - 12) : t >> k)) > 0) {
+ frameBuffer[5 - x + width * (2 - y + width - 11)] = 1;
+ frameBuffer[2 - y + width - 11 + width * (5 - x)] = 1;
+ } else {
+ setMask(5 - x, 2 - y + width - 11);
+ setMask(2 - y + width - 11, 5 - x);
+ }
+ k--;
+ }
+ }
+ }
+
+ // Sync mask bits. Only set above for background cells, so now add the foreground.
+ // 同步掩码位。只有上方的背景单元格需要设置,现在添加前景色。
+ for (y = 0; y < width; y++) {
+ for (x = 0; x <= y; x++) {
+ if (frameBuffer[x + width * y] > 0) {
+ setMask(x, y);
+ }
+ }
+ }
+
+ // Convert string to bit stream. 8-bit data to QR-coded 8-bit data (numeric, alphanum, or kanji
+ // not supported).
+ // 将字符串转换为位流。8位数据转换为QR编码的8位数据(不支持数字、字母或汉字)。
+ v = str.length;
+
+ // String to array.
+ for (i = 0; i < v; i++) {
+ // #ifdef APP-ANDROID
+ // @ts-ignore
+ eccBuffer[i.toInt()] = str.charCodeAt(i)!;
+ // #endif
+ // #ifndef APP-ANDROID
+ eccBuffer[i] = str.charCodeAt(i)!;
+ // #endif
+ }
+
+ //++++++++++++++++++++==============
+ stringBuffer.set(eccBuffer.subarray(0, v));
+
+ // Calculate max string length.
+ x = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2;
+
+ if (v >= x - 2) {
+ v = x - 2;
+
+ if (version > 9) v--;
+ }
+
+ // Shift and re-pack to insert length prefix.
+ // 移位并重新打包以插入长度前缀。
+ i = v;
+
+ if (version > 9) {
+ stringBuffer[i + 2] = 0;
+ stringBuffer[i + 3] = 0;
+
+ while (i-- > 0) {
+ t = stringBuffer[i];
+
+ stringBuffer[i + 3] |= 255 & (t << 4);
+ stringBuffer[i + 2] = t >> 4;
+ }
+
+ stringBuffer[2] |= 255 & (v << 4);
+ stringBuffer[1] = v >> 4;
+ stringBuffer[0] = 0x40 | (v >> 12);
+ } else {
+ stringBuffer[i + 1] = 0;
+ stringBuffer[i + 2] = 0;
+
+ while (i-- > 0) {
+ t = stringBuffer[i];
+
+ stringBuffer[i + 2] |= 255 & (t << 4);
+ stringBuffer[i + 1] = t >> 4;
+ }
+
+ stringBuffer[1] |= 255 & (v << 4);
+ stringBuffer[0] = 0x40 | (v >> 4);
+ }
+
+ // Fill to end with pad pattern.
+ // 用填充模式填充到结束。
+ i = v + 3 - (version < 10 ? 1 : 0);
+
+ while (i < x) {
+ stringBuffer[i++] = 0xec;
+ stringBuffer[i++] = 0x11;
+ }
+
+ // Calculate generator polynomial.
+ // 计算生成多项式。
+ polynomial = new Uint8Array(eccBlock + 1);
+ polynomial[0] = 1;
+
+ for (i = 0; i < eccBlock; i++) {
+ polynomial[i + 1] = 1;
+
+ for (j = i; j > 0; j--) {
+ polynomial[j] =
+ polynomial[j] > 0
+ ? polynomial[j - 1] ^ GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[j]] + i)]
+ : polynomial[j - 1];
+ }
+
+ polynomial[0] = GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[0]] + i)];
+ }
+
+ // Use logs for generator polynomial to save calculation step.
+ // 使用对数计算生成多项式以节省计算步骤。
+ for (i = 0; i < eccBlock; i++) {
+ polynomial[i] = GALOIS_LOG[polynomial[i]];
+ }
+
+ // Append ECC to data buffer.
+ // 将ECC附加到数据缓冲区。
+ k = x;
+ y = 0;
+
+ for (i = 0; i < neccBlock1; i++) {
+ appendData(y, dataBlock, k, eccBlock);
+
+ y += dataBlock;
+ k += eccBlock;
+ }
+
+ for (i = 0; i < neccBlock2; i++) {
+ appendData(y, dataBlock + 1, k, eccBlock);
+
+ y += dataBlock + 1;
+ k += eccBlock;
+ }
+
+ // Interleave blocks.
+ y = 0;
+
+ for (i = 0; i < dataBlock; i++) {
+ for (j = 0; j < neccBlock1; j++) {
+ eccBuffer[y++] = stringBuffer[i + j * dataBlock];
+ }
+
+ for (j = 0; j < neccBlock2; j++) {
+ eccBuffer[y++] = stringBuffer[neccBlock1 * dataBlock + i + j * (dataBlock + 1)];
+ }
+ }
+
+ for (j = 0; j < neccBlock2; j++) {
+ eccBuffer[y++] = stringBuffer[neccBlock1 * dataBlock + i + j * (dataBlock + 1)];
+ }
+
+ for (i = 0; i < eccBlock; i++) {
+ for (j = 0; j < neccBlock1 + neccBlock2; j++) {
+ eccBuffer[y++] = stringBuffer[x + i + j * eccBlock];
+ }
+ }
+
+ stringBuffer.set(eccBuffer);
+
+ // Pack bits into frame avoiding masked area.
+ // 将位流打包到帧中,避免掩码区域。
+ x = width - 1;
+ y = width - 1;
+ k = 1;
+ v = 1;
+
+ // inteleaved data and ECC codes.
+ // 交错数据和ECC代码。
+ m = (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2;
+
+ for (i = 0; i < m; i++) {
+ t = stringBuffer[i];
+
+ for (j = 0; j < 8; j++) {
+ if ((0x80 & t) > 0) {
+ frameBuffer[x + width * y] = 1;
+ }
+
+ // Find next fill position.
+ // 找到下一个填充位置。
+ do {
+ if (v > 0) {
+ x--;
+ } else {
+ x++;
+
+ if (k > 0) {
+ if (y != 0) {
+ y--;
+ } else {
+ x -= 2;
+ k = k == 0 ? 1 : 0;
+
+ if (x == 6) {
+ x--;
+ y = 9;
+ }
+ }
+ } else {
+ if (y != width - 1) {
+ y++;
+ } else {
+ x -= 2;
+ k = k == 0 ? 1 : 0;
+
+ if (x == 6) {
+ x--;
+ y -= 8;
+ }
+ }
+ }
+ }
+
+ v = v == 0 ? 1 : 0;
+ } while (isMasked(x, y));
+ t <<= 1;
+ }
+ }
+
+ // Save pre-mask copy of frame.
+ const frameBufferCopy = frameBuffer.slice(0);
+
+ t = 0;
+ y = 30000;
+
+ // Using `for` instead of `while` since in original Arduino code if an early mask was *good
+ // enough* it wouldn't try for a better one since they get more complex and take longer.
+ // 使用`for`而不是`while`,因为在原始Arduino代码中,如果早期掩码足够好,它不会尝试更好的掩码,因为它们变得更复杂并需要更长的时间。
+ for (k = 0; k < 8; k++) {
+ // Returns foreground-background imbalance.
+ // 返回前景色和背景色的不平衡。
+ applyMask(k);
+
+ x = checkBadness();
+
+ // Is current mask better than previous best?
+ // 当前掩码是否比之前的最佳掩码更好?
+ if (x < y) {
+ y = x;
+ t = k;
+ }
+
+ // Don't increment `i` to a void redoing mask.
+ // 不要增加`i`以避免重新做掩码。
+ if (t == 7) break;
+
+ // Reset for next pass.
+ // 重置下一个循环。
+ frameBuffer.set(frameBufferCopy);
+ }
+
+ // Redo best mask as none were *good enough* (i.e. last wasn't `t`).
+ // 重做最佳掩码,因为没有一个掩码足够好(即最后一个不是`t`)。
+ if (t != k) {
+ // Reset buffer to pre-mask state before applying the best one
+ frameBuffer.set(frameBufferCopy);
+ applyMask(t);
+ }
+
+ // Add in final mask/ECC level bytes.
+ // 添加最终的掩码/ECC级别字节。
+ y = FINAL_FORMAT[t + ((eccLevel - 1) << 3)];
+
+ // Low byte.
+ for (k = 0; k < 8; k++) {
+ if ((y & 1) > 0) {
+ frameBuffer[width - 1 - k + width * 8] = 1;
+
+ if (k < 6) {
+ frameBuffer[8 + width * k] = 1;
+ } else {
+ frameBuffer[8 + width * (k + 1)] = 1;
+ }
+ }
+ y >>= 1;
+ }
+
+ // High byte.
+ for (k = 0; k < 7; k++) {
+ if ((y & 1) > 0) {
+ frameBuffer[8 + width * (width - 7 + k)] = 1;
+
+ if (k > 0) {
+ frameBuffer[6 - k + width * 8] = 1;
+ } else {
+ frameBuffer[7 + width * 8] = 1;
+ }
+ }
+ y >>= 1;
+ }
+
+ // Finally, return the image data.
+ return {
+ frameBuffer: frameBuffer,
+ width: width
+ } as GenerateFrameResult;
+}
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-radio/cl-radio.uvue b/cool-unix/uni_modules/cool-ui/components/cl-radio/cl-radio.uvue
new file mode 100644
index 0000000..c3dc027
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-radio/cl-radio.uvue
@@ -0,0 +1,155 @@
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-radio/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-radio/props.ts
new file mode 100644
index 0000000..0a267b0
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-radio/props.ts
@@ -0,0 +1,20 @@
+import type { PassThroughProps } from "../../types";
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClRadioPassThrough = {
+ className?: string;
+ icon?: ClIconProps;
+ label?: PassThroughProps;
+};
+
+export type ClRadioProps = {
+ className?: string;
+ pt?: ClRadioPassThrough;
+ modelValue?: any;
+ activeIcon?: string;
+ inactiveIcon?: string;
+ showIcon?: boolean;
+ label?: string;
+ value?: any;
+ disabled?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-rate/cl-rate.uvue b/cool-unix/uni_modules/cool-ui/components/cl-rate/cl-rate.uvue
new file mode 100644
index 0000000..2aa7993
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-rate/cl-rate.uvue
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+ {{ modelValue }}
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-rate/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-rate/props.ts
new file mode 100644
index 0000000..1e42589
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-rate/props.ts
@@ -0,0 +1,24 @@
+import type { PassThroughProps } from "../../types";
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClRatePassThrough = {
+ className?: string;
+ item?: PassThroughProps;
+ icon?: ClIconProps;
+ score?: PassThroughProps;
+};
+
+export type ClRateProps = {
+ className?: string;
+ pt?: ClRatePassThrough;
+ modelValue?: number;
+ max?: number;
+ disabled?: boolean;
+ allowHalf?: boolean;
+ showScore?: boolean;
+ size?: number;
+ icon?: string;
+ voidIcon?: string;
+ color?: string;
+ voidColor?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-read-more/cl-read-more.uvue b/cool-unix/uni_modules/cool-ui/components/cl-read-more/cl-read-more.uvue
new file mode 100644
index 0000000..4ca8711
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-read-more/cl-read-more.uvue
@@ -0,0 +1,264 @@
+
+
+
+
+
+
+ {{ content }}
+
+
+
+
+
+
+
+
+
+
+ {{ isExpanded ? collapseText : expandText }}
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-read-more/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-read-more/props.ts
new file mode 100644
index 0000000..7b6a9ef
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-read-more/props.ts
@@ -0,0 +1,25 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClReadMorePassThrough = {
+ className?: string;
+ wrapper?: PassThroughProps;
+ content?: PassThroughProps;
+ contentText?: PassThroughProps;
+ mask?: PassThroughProps;
+ toggle?: PassThroughProps;
+};
+
+export type ClReadMoreProps = {
+ className?: string;
+ pt?: ClReadMorePassThrough;
+ modelValue?: boolean;
+ content?: string;
+ height?: any;
+ expandText?: string;
+ collapseText?: string;
+ expandIcon?: string;
+ collapseIcon?: string;
+ disabled?: boolean;
+ showToggle?: boolean;
+ showMask?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-rolling-number/cl-rolling-number.uvue b/cool-unix/uni_modules/cool-ui/components/cl-rolling-number/cl-rolling-number.uvue
new file mode 100644
index 0000000..df9a80e
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-rolling-number/cl-rolling-number.uvue
@@ -0,0 +1,213 @@
+
+ {{ displayNumber }}
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-rolling-number/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-rolling-number/props.ts
new file mode 100644
index 0000000..bd884ab
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-rolling-number/props.ts
@@ -0,0 +1,21 @@
+export type ClRollingNumberProps = {
+ /**
+ * 绑定值
+ */
+ modelValue: number
+ /**
+ * 动画持续时间,单位毫秒
+ * @default 1000
+ */
+ duration?: number
+ /**
+ * 保留小数位数
+ * @default 0
+ */
+ decimals?: number
+ /**
+ * 是否自动开始动画
+ * @default true
+ */
+ autoStart?: boolean
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-row/cl-row.uvue b/cool-unix/uni_modules/cool-ui/components/cl-row/cl-row.uvue
new file mode 100644
index 0000000..c20efb9
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-row/cl-row.uvue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-row/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-row/props.ts
new file mode 100644
index 0000000..370edc1
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-row/props.ts
@@ -0,0 +1,9 @@
+export type ClRowPassThrough = {
+ className?: string;
+};
+
+export type ClRowProps = {
+ className?: string;
+ pt?: ClRowPassThrough;
+ gutter?: number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-safe-area/cl-safe-area.uvue b/cool-unix/uni_modules/cool-ui/components/cl-safe-area/cl-safe-area.uvue
new file mode 100644
index 0000000..3667460
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-safe-area/cl-safe-area.uvue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-safe-area/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-safe-area/props.ts
new file mode 100644
index 0000000..c651f7f
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-safe-area/props.ts
@@ -0,0 +1,10 @@
+export type ClSafeAreaPassThrough = {
+ className?: string;
+};
+
+export type ClSafeAreaProps = {
+ className?: string;
+ pt?: ClSafeAreaPassThrough;
+ type?: "top" | "bottom";
+ transparent?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-select-date/cl-select-date.uvue b/cool-unix/uni_modules/cool-ui/components/cl-select-date/cl-select-date.uvue
new file mode 100644
index 0000000..b9d1368
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-select-date/cl-select-date.uvue
@@ -0,0 +1,873 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-select-date/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-select-date/props.ts
new file mode 100644
index 0000000..d690cb6
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-select-date/props.ts
@@ -0,0 +1,35 @@
+import type { ClSelectDateShortcut, ClSelectOption } from "../../types";
+import type { ClSelectTriggerPassThrough } from "../cl-select-trigger/props";
+import type { ClPopupPassThrough } from "../cl-popup/props";
+
+export type ClSelectDatePassThrough = {
+ trigger?: ClSelectTriggerPassThrough;
+ popup?: ClPopupPassThrough;
+};
+
+export type ClSelectDateProps = {
+ className?: string;
+ pt?: ClSelectDatePassThrough;
+ modelValue?: string;
+ values?: string[];
+ headers?: string[];
+ title?: string;
+ placeholder?: string;
+ showTrigger?: boolean;
+ disabled?: boolean;
+ confirmText?: string;
+ showConfirm?: boolean;
+ cancelText?: string;
+ showCancel?: boolean;
+ labelFormat?: string;
+ valueFormat?: string;
+ start?: string;
+ end?: string;
+ type?: "year" | "month" | "date" | "hour" | "minute" | "second";
+ rangeable?: boolean;
+ startPlaceholder?: string;
+ endPlaceholder?: string;
+ rangeSeparator?: string;
+ showShortcuts?: boolean;
+ shortcuts?: ClSelectDateShortcut[];
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-select-time/cl-select-time.uvue b/cool-unix/uni_modules/cool-ui/components/cl-select-time/cl-select-time.uvue
new file mode 100644
index 0000000..2eb2080
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-select-time/cl-select-time.uvue
@@ -0,0 +1,387 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-select-time/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-select-time/props.ts
new file mode 100644
index 0000000..2971d9f
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-select-time/props.ts
@@ -0,0 +1,25 @@
+import type { ClSelectOption } from "../../types";
+import type { ClSelectTriggerPassThrough } from "../cl-select-trigger/props";
+import type { ClPopupPassThrough } from "../cl-popup/props";
+
+export type ClSelectTimePassThrough = {
+ trigger?: ClSelectTriggerPassThrough;
+ popup?: ClPopupPassThrough;
+};
+
+export type ClSelectTimeProps = {
+ className?: string;
+ pt?: ClSelectTimePassThrough;
+ modelValue?: string;
+ headers?: string[];
+ type?: "hour" | "minute" | "second";
+ title?: string;
+ placeholder?: string;
+ showTrigger?: boolean;
+ disabled?: boolean;
+ confirmText?: string;
+ showConfirm?: boolean;
+ cancelText?: string;
+ showCancel?: boolean;
+ labelFormat?: string | any;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-select-trigger/cl-select-trigger.uvue b/cool-unix/uni_modules/cool-ui/components/cl-select-trigger/cl-select-trigger.uvue
new file mode 100644
index 0000000..c5c030b
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-select-trigger/cl-select-trigger.uvue
@@ -0,0 +1,189 @@
+
+
+
+
+ {{ text }}
+
+
+
+ {{ placeholder }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-select-trigger/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-select-trigger/props.ts
new file mode 100644
index 0000000..82f59ea
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-select-trigger/props.ts
@@ -0,0 +1,19 @@
+import type { ClIconProps } from "../cl-icon/props";
+import type { PassThroughProps } from "../../types";
+
+export type ClSelectTriggerPassThrough = {
+ className?: string;
+ icon?: ClIconProps;
+ placeholder?: PassThroughProps;
+ text?: PassThroughProps;
+};
+
+export type ClSelectTriggerProps = {
+ className?: string;
+ pt?: ClSelectTriggerPassThrough;
+ text?: string;
+ placeholder?: string;
+ arrowIcon?: string;
+ disabled?: boolean;
+ focus?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-select/cl-select.uvue b/cool-unix/uni_modules/cool-ui/components/cl-select/cl-select.uvue
new file mode 100644
index 0000000..239820c
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-select/cl-select.uvue
@@ -0,0 +1,429 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-select/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-select/props.ts
new file mode 100644
index 0000000..3a1fd8f
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-select/props.ts
@@ -0,0 +1,25 @@
+import type { ClSelectOption, ClSelectValue } from "../../types";
+import type { ClSelectTriggerPassThrough } from "../cl-select-trigger/props";
+import type { ClPopupPassThrough } from "../cl-popup/props";
+
+export type ClSelectPassThrough = {
+ trigger?: ClSelectTriggerPassThrough;
+ popup?: ClPopupPassThrough;
+};
+
+export type ClSelectProps = {
+ className?: string;
+ pt?: ClSelectPassThrough;
+ modelValue?: ClSelectValue;
+ title?: string;
+ placeholder?: string;
+ options?: ClSelectOption[];
+ showTrigger?: boolean;
+ disabled?: boolean;
+ columnCount?: number;
+ splitor?: string;
+ confirmText?: string;
+ showConfirm?: boolean;
+ cancelText?: string;
+ showCancel?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-sign/cl-sign.uvue b/cool-unix/uni_modules/cool-ui/components/cl-sign/cl-sign.uvue
new file mode 100644
index 0000000..70de1ee
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-sign/cl-sign.uvue
@@ -0,0 +1,337 @@
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-sign/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-sign/props.ts
new file mode 100644
index 0000000..34b8490
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-sign/props.ts
@@ -0,0 +1,17 @@
+export type ClSignPassThrough = {
+ className?: string;
+};
+
+export type ClSignProps = {
+ className?: string;
+ pt?: ClSignPassThrough;
+ width?: number;
+ height?: number;
+ strokeColor?: string;
+ strokeWidth?: number;
+ backgroundColor?: string;
+ enableBrush?: boolean;
+ minStrokeWidth?: number;
+ maxStrokeWidth?: number;
+ velocitySensitivity?: number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-skeleton/cl-skeleton.uvue b/cool-unix/uni_modules/cool-ui/components/cl-skeleton/cl-skeleton.uvue
new file mode 100644
index 0000000..6a47813
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-skeleton/cl-skeleton.uvue
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-skeleton/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-skeleton/props.ts
new file mode 100644
index 0000000..9a05155
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-skeleton/props.ts
@@ -0,0 +1,13 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClSkeletonPassThrough = {
+ className?: string;
+ loading?: PassThroughProps;
+};
+
+export type ClSkeletonProps = {
+ className?: string;
+ pt?: ClSkeletonPassThrough;
+ loading?: boolean;
+ type?: "text" | "image" | "circle" | "button";
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-slide-verify/cl-slide-verify.uvue b/cool-unix/uni_modules/cool-ui/components/cl-slide-verify/cl-slide-verify.uvue
new file mode 100644
index 0000000..f79e00b
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-slide-verify/cl-slide-verify.uvue
@@ -0,0 +1,500 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentText }}
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-slide-verify/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-slide-verify/props.ts
new file mode 100644
index 0000000..e09ff60
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-slide-verify/props.ts
@@ -0,0 +1,28 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClSlideVerifyPassThrough = {
+ className?: string;
+ track?: PassThroughProps;
+ image?: PassThroughProps;
+ progress?: PassThroughProps;
+ slider?: PassThroughProps;
+ icon?: PassThroughProps;
+ text?: PassThroughProps;
+ label?: PassThroughProps;
+};
+
+export type ClSlideVerifyProps = {
+ className?: string;
+ pt?: ClSlideVerifyPassThrough;
+ modelValue?: boolean;
+ mode?: "slide" | "image";
+ size?: number;
+ disabled?: boolean;
+ imageUrl?: string;
+ imageSize?: any;
+ angleThreshold?: number;
+ text?: string;
+ successText?: string;
+ showFail?: boolean;
+ failText?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-slider/cl-slider.uvue b/cool-unix/uni_modules/cool-ui/components/cl-slider/cl-slider.uvue
new file mode 100644
index 0000000..6cc7e8b
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-slider/cl-slider.uvue
@@ -0,0 +1,550 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ displayValue }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-slider/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-slider/props.ts
new file mode 100644
index 0000000..b4c05cc
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-slider/props.ts
@@ -0,0 +1,24 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClSliderPassThrough = {
+ className?: string;
+ track?: PassThroughProps;
+ progress?: PassThroughProps;
+ thumb?: PassThroughProps;
+ value?: PassThroughProps;
+};
+
+export type ClSliderProps = {
+ className?: string;
+ pt?: ClSliderPassThrough;
+ modelValue?: number;
+ values?: number[];
+ min?: number;
+ max?: number;
+ step?: number;
+ disabled?: boolean;
+ blockSize?: number;
+ trackHeight?: number;
+ showValue?: boolean;
+ range?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-sticky/cl-sticky.uvue b/cool-unix/uni_modules/cool-ui/components/cl-sticky/cl-sticky.uvue
new file mode 100644
index 0000000..45fc483
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-sticky/cl-sticky.uvue
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-sticky/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-sticky/props.ts
new file mode 100644
index 0000000..e723910
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-sticky/props.ts
@@ -0,0 +1,6 @@
+export type ClStickyProps = {
+ className?: string;
+ offsetTop?: number;
+ zIndex?: number;
+ scrollTop?: number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-switch/cl-switch.uvue b/cool-unix/uni_modules/cool-ui/components/cl-switch/cl-switch.uvue
new file mode 100644
index 0000000..a8d6da1
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-switch/cl-switch.uvue
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-switch/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-switch/props.ts
new file mode 100644
index 0000000..85eddd9
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-switch/props.ts
@@ -0,0 +1,19 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClSwitchPassThrough = {
+ className?: string;
+ track?: PassThroughProps;
+ thumb?: PassThroughProps;
+ label?: PassThroughProps;
+ loading?: PassThroughProps;
+};
+
+export type ClSwitchProps = {
+ className?: string;
+ pt?: ClSwitchPassThrough;
+ modelValue?: boolean;
+ disabled?: boolean;
+ loading?: boolean;
+ height?: number;
+ width?: number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-tabs/cl-tabs.uvue b/cool-unix/uni_modules/cool-ui/components/cl-tabs/cl-tabs.uvue
new file mode 100644
index 0000000..d3923a5
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-tabs/cl-tabs.uvue
@@ -0,0 +1,464 @@
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-tabs/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-tabs/props.ts
new file mode 100644
index 0000000..5de00fa
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-tabs/props.ts
@@ -0,0 +1,24 @@
+import type { ClTabsItem, PassThroughProps } from "../../types";
+
+export type ClTabsPassThrough = {
+ className?: string;
+ text?: PassThroughProps;
+ item?: PassThroughProps;
+ line?: PassThroughProps;
+ slider?: PassThroughProps;
+};
+
+export type ClTabsProps = {
+ className?: string;
+ pt?: ClTabsPassThrough;
+ modelValue?: string | number;
+ height?: string | number;
+ list?: ClTabsItem[];
+ fill?: boolean;
+ gutter?: number;
+ color?: string;
+ unColor?: string;
+ showLine?: boolean;
+ showSlider?: boolean;
+ disabled?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-tag/cl-tag.uvue b/cool-unix/uni_modules/cool-ui/components/cl-tag/cl-tag.uvue
new file mode 100644
index 0000000..1228060
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-tag/cl-tag.uvue
@@ -0,0 +1,188 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-tag/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-tag/props.ts
new file mode 100644
index 0000000..1c41177
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-tag/props.ts
@@ -0,0 +1,17 @@
+import type { Type } from "../../types";
+import type { ClTextPassThrough } from "../cl-text/props";
+
+export type ClTagPassThrough = {
+ className?: string;
+ text?: ClTextPassThrough;
+};
+
+export type ClTagProps = {
+ className?: string;
+ pt?: ClTagPassThrough;
+ type?: Type;
+ icon?: string;
+ rounded?: boolean;
+ closable?: boolean;
+ plain?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-text/cl-text.uvue b/cool-unix/uni_modules/cool-ui/components/cl-text/cl-text.uvue
new file mode 100644
index 0000000..f0804cf
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-text/cl-text.uvue
@@ -0,0 +1,349 @@
+
+
+
+ {{ content }}
+
+
+
+
+
+ {{ content }}
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-text/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-text/props.ts
new file mode 100644
index 0000000..7b40957
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-text/props.ts
@@ -0,0 +1,26 @@
+import type { ClTextType } from "../../types";
+
+export type ClTextPassThrough = {
+ className?: string;
+};
+
+export type ClTextProps = {
+ className?: string;
+ pt?: ClTextPassThrough;
+ value?: string | number | any;
+ color?: string;
+ size?: number | string | any;
+ type?: ClTextType;
+ mask?: boolean;
+ currency?: string;
+ precision?: number;
+ maskStart?: number;
+ maskEnd?: number;
+ maskChar?: string;
+ ellipsis?: boolean;
+ lines?: number;
+ selectable?: boolean;
+ space?: "ensp" | "emsp" | "nbsp";
+ decode?: boolean;
+ preWrap?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-textarea/cl-textarea.uvue b/cool-unix/uni_modules/cool-ui/components/cl-textarea/cl-textarea.uvue
new file mode 100644
index 0000000..8b2d66c
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-textarea/cl-textarea.uvue
@@ -0,0 +1,407 @@
+
+
+
+
+ {{ value.length }} / {{ maxlength }}
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-textarea/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-textarea/props.ts
new file mode 100644
index 0000000..68fe1b4
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-textarea/props.ts
@@ -0,0 +1,37 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClTextareaPassThrough = {
+ className?: string;
+ inner?: PassThroughProps;
+};
+
+export type ClTextareaProps = {
+ className?: string;
+ pt?: ClTextareaPassThrough;
+ modelValue?: string;
+ border?: boolean;
+ disabled?: boolean;
+ readonly?: boolean;
+ showWordLimit?: boolean;
+ name?: string;
+ placeholder?: string;
+ placeholderClass?: string;
+ maxlength?: number;
+ autofocus?: boolean;
+ confirmType?: "done" | "go" | "next" | "search" | "send";
+ cursor?: number;
+ confirmHold?: boolean;
+ height?: any;
+ autoHeight?: boolean;
+ fixed?: boolean;
+ cursorSpacing?: number;
+ cursorColor?: string;
+ showConfirmBar?: boolean;
+ selectionStart?: number;
+ selectionEnd?: number;
+ adjustPosition?: boolean;
+ inputmode?: "none" | "text" | "decimal" | "numeric" | "tel" | "search" | "email" | "url";
+ holdKeyboard?: boolean;
+ disableDefaultPadding?: boolean;
+ adjustKeyboardTo?: "cursor" | "bottom";
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-timeline-item/cl-timeline-item.uvue b/cool-unix/uni_modules/cool-ui/components/cl-timeline-item/cl-timeline-item.uvue
new file mode 100644
index 0000000..49edbc2
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-timeline-item/cl-timeline-item.uvue
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+ {{ content }}
+
+
+
+ {{ date }}
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-timeline-item/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-timeline-item/props.ts
new file mode 100644
index 0000000..178903e
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-timeline-item/props.ts
@@ -0,0 +1,19 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClTimelineItemPassThrough = {
+ className?: string;
+ icon?: PassThroughProps;
+ title?: PassThroughProps;
+ content?: PassThroughProps;
+ date?: PassThroughProps;
+};
+
+export type ClTimelineItemProps = {
+ className?: string;
+ pt?: ClTimelineItemPassThrough;
+ title?: string;
+ icon?: string;
+ content?: string;
+ date?: string;
+ hideLine?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-timeline/cl-timeline.uvue b/cool-unix/uni_modules/cool-ui/components/cl-timeline/cl-timeline.uvue
new file mode 100644
index 0000000..ab27b06
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-timeline/cl-timeline.uvue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-timeline/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-timeline/props.ts
new file mode 100644
index 0000000..fe8df7e
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-timeline/props.ts
@@ -0,0 +1,8 @@
+export type ClTimelinePassThrough = {
+ className?: string;
+};
+
+export type ClTimelineProps = {
+ className?: string;
+ pt?: ClTimelinePassThrough;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-toast/cl-toast.uvue b/cool-unix/uni_modules/cool-ui/components/cl-toast/cl-toast.uvue
new file mode 100644
index 0000000..e6b0b08
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-toast/cl-toast.uvue
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
+
+ {{ item.message }}
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-toast/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-toast/props.ts
new file mode 100644
index 0000000..2bfaf09
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-toast/props.ts
@@ -0,0 +1,5 @@
+import type { ClToastOptions } from "../../types";
+
+export type ClToastProps = {
+ className?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-topbar/cl-topbar.uvue b/cool-unix/uni_modules/cool-ui/components/cl-topbar/cl-topbar.uvue
new file mode 100644
index 0000000..07d2df6
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-topbar/cl-topbar.uvue
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-topbar/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-topbar/props.ts
new file mode 100644
index 0000000..c7896e2
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-topbar/props.ts
@@ -0,0 +1,23 @@
+import type { PassThroughProps } from "../../types";
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClTopbarPassThrough = {
+ className?: string;
+ title?: PassThroughProps;
+ back?: ClIconProps;
+};
+
+export type ClTopbarProps = {
+ className?: string;
+ pt?: ClTopbarPassThrough;
+ title?: string;
+ color?: string;
+ backgroundColor?: string;
+ showBack?: boolean;
+ backable?: boolean;
+ backPath?: string;
+ backIcon?: string;
+ safeAreaTop?: boolean;
+ fixed?: boolean;
+ height?: number | string | any;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-tree-item/cl-tree-item.uvue b/cool-unix/uni_modules/cool-ui/components/cl-tree-item/cl-tree-item.uvue
new file mode 100644
index 0000000..eeb23a8
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-tree-item/cl-tree-item.uvue
@@ -0,0 +1,219 @@
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-tree-item/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-tree-item/props.ts
new file mode 100644
index 0000000..cb1f70c
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-tree-item/props.ts
@@ -0,0 +1,22 @@
+import type { ClTreeItem, PassThroughProps } from "../../types";
+import type { ClIconProps } from "../cl-icon/props";
+
+export type ClTreeItemPassThrough = {
+ item?: PassThroughProps;
+ itemChecked?: PassThroughProps;
+ itemWrapper?: PassThroughProps;
+ expand?: PassThroughProps;
+ expandIcon?: ClIconProps;
+ checkbox?: PassThroughProps;
+ checkedIcon?: ClIconProps;
+ halfCheckedIcon?: ClIconProps;
+ uncheckedIcon?: ClIconProps;
+ label?: PassThroughProps;
+};
+
+export type ClTreeItemProps = {
+ className?: string;
+ pt?: ClTreeItemPassThrough;
+ item?: ClTreeItem;
+ level?: number;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-tree/cl-tree.uvue b/cool-unix/uni_modules/cool-ui/components/cl-tree/cl-tree.uvue
new file mode 100644
index 0000000..e77ef9c
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-tree/cl-tree.uvue
@@ -0,0 +1,583 @@
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-tree/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-tree/props.ts
new file mode 100644
index 0000000..5a54acf
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-tree/props.ts
@@ -0,0 +1,17 @@
+import type { ClTreeItem, ClTreeNodeInfo } from "../../types";
+
+export type ClTreePassThrough = {
+ className?: string;
+};
+
+export type ClTreeProps = {
+ className?: string;
+ pt?: ClTreePassThrough;
+ modelValue?: any | any;
+ list?: ClTreeItem[];
+ icon?: string;
+ expandIcon?: string;
+ checkStrictly?: boolean;
+ checkable?: boolean;
+ multiple?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-upload/cl-upload.uvue b/cool-unix/uni_modules/cool-ui/components/cl-upload/cl-upload.uvue
new file mode 100644
index 0000000..9ce3357
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-upload/cl-upload.uvue
@@ -0,0 +1,447 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ text }}
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-upload/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-upload/props.ts
new file mode 100644
index 0000000..0279fa8
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-upload/props.ts
@@ -0,0 +1,26 @@
+import type { ClUploadItem, PassThroughProps } from "../../types";
+
+export type ClUploadPassThrough = {
+ className?: string;
+ item?: PassThroughProps;
+ add?: PassThroughProps;
+ image?: PassThroughProps;
+ icon?: PassThroughProps;
+ text?: PassThroughProps;
+};
+
+export type ClUploadProps = {
+ className?: string;
+ pt?: ClUploadPassThrough;
+ modelValue?: string[] | string;
+ icon?: string;
+ text?: string;
+ sizeType?: string[] | string;
+ sourceType?: string[];
+ height?: any;
+ width?: any;
+ multiple?: boolean;
+ limit?: number;
+ disabled?: boolean;
+ test?: boolean;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-waterfall/cl-waterfall.uvue b/cool-unix/uni_modules/cool-ui/components/cl-waterfall/cl-waterfall.uvue
new file mode 100644
index 0000000..9c8b84c
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-waterfall/cl-waterfall.uvue
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-waterfall/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-waterfall/props.ts
new file mode 100644
index 0000000..efd1f53
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-waterfall/props.ts
@@ -0,0 +1,11 @@
+export type ClWaterfallPassThrough = {
+ className?: string;
+};
+
+export type ClWaterfallProps = {
+ className?: string;
+ pt?: ClWaterfallPassThrough;
+ column?: number;
+ gutter?: number;
+ nodeKey?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-watermark/cl-watermark.uvue b/cool-unix/uni_modules/cool-ui/components/cl-watermark/cl-watermark.uvue
new file mode 100644
index 0000000..6d25a58
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-watermark/cl-watermark.uvue
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cool-unix/uni_modules/cool-ui/components/cl-watermark/props.ts b/cool-unix/uni_modules/cool-ui/components/cl-watermark/props.ts
new file mode 100644
index 0000000..7c374c1
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/components/cl-watermark/props.ts
@@ -0,0 +1,24 @@
+import type { PassThroughProps } from "../../types";
+
+export type ClWatermarkPassThrough = {
+ className?: string;
+ container?: PassThroughProps;
+};
+
+export type ClWatermarkProps = {
+ className?: string;
+ pt?: ClWatermarkPassThrough;
+ text?: string;
+ fontSize?: number;
+ color?: string;
+ darkColor?: string;
+ opacity?: number;
+ rotate?: number;
+ width?: number;
+ height?: number;
+ gapX?: number;
+ gapY?: number;
+ zIndex?: number;
+ fontWeight?: string;
+ fontFamily?: string;
+};
diff --git a/cool-unix/uni_modules/cool-ui/config.ts b/cool-unix/uni_modules/cool-ui/config.ts
new file mode 100644
index 0000000..d98435a
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/config.ts
@@ -0,0 +1,15 @@
+import { reactive } from "vue";
+
+type Config = {
+ fontSize: number | null;
+ zIndex: number;
+ startDate: string;
+ endDate: string;
+};
+
+export const config = reactive({
+ fontSize: null,
+ zIndex: 600,
+ startDate: "2000-01-01 00:00:00",
+ endDate: "2050-12-31 23:59:59"
+});
diff --git a/cool-unix/uni_modules/cool-ui/hooks/component.ts b/cool-unix/uni_modules/cool-ui/hooks/component.ts
new file mode 100644
index 0000000..e235989
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/hooks/component.ts
@@ -0,0 +1,24 @@
+import { parse } from "@/cool";
+import type { ClCascaderOption, ClListViewItem, ClTreeItem } from "../types";
+
+export function useListView(data: UTSJSONObject[]) {
+ return data.map((e) => {
+ return parse({
+ ...e,
+ value: e
+ })!;
+ });
+}
+
+export function useCascader(data: UTSJSONObject[]) {
+ return data.map((e) => parse(e)!);
+}
+
+export function useTree(data: UTSJSONObject[]) {
+ return data.map((e) => {
+ return parse({
+ ...e,
+ value: e
+ })!;
+ });
+}
diff --git a/cool-unix/uni_modules/cool-ui/hooks/form.ts b/cool-unix/uni_modules/cool-ui/hooks/form.ts
new file mode 100644
index 0000000..e023bdb
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/hooks/form.ts
@@ -0,0 +1,142 @@
+import { computed, ref, type ComputedRef } from "vue";
+import type { ClFormRule, ClFormValidateError } from "../types";
+import { useParent } from "@/cool";
+
+export class Form {
+ public formRef = ref(null);
+ public disabled: ComputedRef;
+
+ constructor() {
+ // 获取 cl-form 实例
+ if (this.formRef.value == null) {
+ const ClForm = useParent("cl-form");
+
+ if (ClForm != null) {
+ this.formRef.value = ClForm;
+ }
+ }
+
+ // 监听表单是否禁用
+ this.disabled = computed(() => {
+ if (this.formRef.value == null) {
+ return false;
+ }
+
+ return this.formRef.value.disabled;
+ });
+ }
+
+ // 注册表单字段
+ addField = (prop: string, rules: ClFormRule[]): void => {
+ this.formRef.value!.addField(prop, rules);
+ };
+
+ // 注销表单字段
+ removeField = (prop: string): void => {
+ this.formRef.value!.removeField(prop);
+ };
+
+ // 获取字段值
+ getValue = (prop: string): any | null => {
+ return this.formRef.value!.getValue(prop);
+ };
+
+ // 设置字段错误信息
+ setError = (prop: string, error: string): void => {
+ this.formRef.value!.setError(prop, error);
+ };
+
+ // 获取字段错误信息
+ getError = (prop: string): string => {
+ return this.formRef.value!.getError(prop);
+ };
+
+ // 获取所有错误信息
+ getErrors = async (): Promise => {
+ return this.formRef.value!.getErrors();
+ };
+
+ // 移除字段错误信息
+ removeError = (prop: string): void => {
+ this.formRef.value!.removeError(prop);
+ };
+
+ // 清除所有错误信息
+ clearErrors = (): void => {
+ this.formRef.value!.clearErrors();
+ };
+
+ // 获取字段规则
+ getRule = (prop: string): ClFormRule[] => {
+ return this.formRef.value!.getRule(prop);
+ };
+
+ // 设置字段规则
+ setRule = (prop: string, rules: ClFormRule[]): void => {
+ this.formRef.value!.setRule(prop, rules);
+ };
+
+ // 移除字段规则
+ removeRule = (prop: string): void => {
+ this.formRef.value!.removeRule(prop);
+ };
+
+ // 验证单个规则
+ validateRule = (value: any | null, rule: ClFormRule): string | null => {
+ return this.formRef.value!.validateRule(value, rule);
+ };
+
+ // 清除所有验证
+ clearValidate = (): void => {
+ this.formRef.value!.clearValidate();
+ };
+
+ // 验证单个字段
+ validateField = (prop: string): string | null => {
+ return this.formRef.value!.validateField(prop);
+ };
+
+ // 验证整个表单
+ validate = (callback: (valid: boolean, errors: ClFormValidateError[]) => void): void => {
+ this.formRef.value!.validate(callback);
+ };
+
+ // 检查字段是否存在错误
+ isError = (prop: string): boolean => {
+ return this.formRef.value!.getError(prop) != "";
+ };
+}
+
+class FormItem {
+ public formItemRef = ref(null);
+ public isError: ComputedRef;
+
+ constructor() {
+ const { isError } = new Form();
+
+ if (this.formItemRef.value == null) {
+ const ClFormItem = useParent("cl-form-item");
+
+ if (ClFormItem != null) {
+ this.formItemRef.value = ClFormItem;
+ }
+ }
+
+ // 监听表单字段是否验证错误
+ this.isError = computed(() => {
+ if (this.formItemRef.value == null) {
+ return false;
+ }
+
+ return isError(this.formItemRef.value.prop);
+ });
+ }
+}
+
+export const useForm = (): Form => {
+ return new Form();
+};
+
+export const useFormItem = (): FormItem => {
+ return new FormItem();
+};
diff --git a/cool-unix/uni_modules/cool-ui/hooks/index.ts b/cool-unix/uni_modules/cool-ui/hooks/index.ts
new file mode 100644
index 0000000..17b1a58
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/hooks/index.ts
@@ -0,0 +1,5 @@
+export * from "./component";
+export * from "./form";
+export * from "./page";
+export * from "./size";
+export * from "./ui";
diff --git a/cool-unix/uni_modules/cool-ui/hooks/page.ts b/cool-unix/uni_modules/cool-ui/hooks/page.ts
new file mode 100644
index 0000000..6378b70
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/hooks/page.ts
@@ -0,0 +1,60 @@
+import { router, scroller, useParent } from "@/cool";
+
+class Page {
+ pageRef: ClPageComponentPublicInstance | null = null;
+
+ constructor() {
+ this.pageRef = useParent("cl-page");
+ }
+
+ /**
+ * 获取页面路径
+ * @returns 页面路径
+ */
+ path = () => {
+ return router.path();
+ };
+
+ /**
+ * 获取滚动位置
+ * @returns 滚动位置
+ */
+ getScrollTop = (): number => {
+ return this.pageRef!.scrollTop as number;
+ };
+
+ /**
+ * 滚动到指定位置
+ * @param top 滚动位置
+ */
+ scrollTo = (top: number) => {
+ this.pageRef!.scrollTo(top);
+ };
+
+ /**
+ * 回到顶部
+ */
+ scrollToTop = () => {
+ this.pageRef!.scrollToTop();
+ };
+
+ /**
+ * 监听页面滚动
+ * @param callback 回调函数
+ */
+ onScroll = (callback: (top: number) => void) => {
+ scroller.on(callback);
+ };
+
+ /**
+ * 取消监听页面滚动
+ * @param callback 回调函数
+ */
+ offScroll = (callback: (top: number) => void) => {
+ scroller.off(callback);
+ };
+}
+
+export function usePage(): Page {
+ return new Page();
+}
diff --git a/cool-unix/uni_modules/cool-ui/hooks/size.ts b/cool-unix/uni_modules/cool-ui/hooks/size.ts
new file mode 100644
index 0000000..00c45e9
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/hooks/size.ts
@@ -0,0 +1,159 @@
+import { computed, type ComputedRef } from "vue";
+import { config } from "../config";
+import { rpx2px } from "@/cool";
+
+/**
+ * 字号管理类
+ * 用于处理文本大小的缩放和样式
+ */
+class Size {
+ // 预设的字号类名
+ public names = [
+ "text-xs",
+ "text-sm",
+ "text-md",
+ "text-lg",
+ "text-xl",
+ "text-2xl",
+ "text-3xl",
+ "text-4xl",
+ "text-5xl",
+ "text-6xl",
+ "text-7xl",
+ "text-8xl",
+ "text-9xl"
+ ];
+
+ // 对应的字号大小
+ public sizes = [20, 24, 28, 32, 36, 44, 52, 60, 72, 84, 96, 120, 152];
+
+ // 对应的行高
+ public lineHeights = [28, 36, 44, 52, 52, 1, 1, 1, 1, 1, 1, 1, 1];
+
+ // 原始类名
+ public className: ComputedRef = computed(() => "");
+
+ // 计算后的类名
+ public ptClassName: ComputedRef;
+
+ constructor(cb: (() => string) | null) {
+ this.className = computed(cb ?? (() => ""));
+
+ // 根据全局字号配置动态计算类名
+ this.ptClassName = computed(() => {
+ if (config.fontSize == null) {
+ return this.className.value;
+ }
+
+ const name = this.names[this.getIndex()];
+ return this.className.value.replace(`-important-${name}`, "").replace(name, "");
+ });
+ }
+
+ /**
+ * 获取全局字号缩放比例
+ */
+ getScale = () => {
+ return config.fontSize ?? 1;
+ };
+
+ /**
+ * 根据缩放比例计算rpx值
+ * @param val - 需要转换的值
+ */
+ getRpx = (val: number | string) => {
+ const scale = this.getScale();
+
+ if (typeof val == "number") {
+ return val * scale + "rpx";
+ } else {
+ const num = parseFloat(val);
+ const unit = val.replace(`${num}`, "");
+
+ return num * scale + unit;
+ }
+ };
+
+ /**
+ * 获取px值
+ * @param val - 需要转换的值 10、10rpx、10px
+ * @returns 转换后的px值
+ */
+ getPxValue = (val: number | string) => {
+ const scale = this.getScale();
+
+ if (typeof val == "string") {
+ const num = parseFloat(val);
+ const unit = val.replace(`${num}`, "");
+
+ if (unit == "px") {
+ return num * scale;
+ } else {
+ return rpx2px(num * scale);
+ }
+ } else {
+ return rpx2px(val * scale);
+ }
+ };
+
+ /**
+ * 获取px值
+ */
+ getPx = (val: number | string) => {
+ return this.getPxValue(val) + "px";
+ };
+
+ /**
+ * 获取当前字号在预设中的索引
+ */
+ getIndex = () => {
+ let index = this.names.findIndex((name) => {
+ if (this.className.value.includes(name)) {
+ return true;
+ }
+
+ return false;
+ });
+
+ // 默认使用 text-md (14px)
+ if (index < 0) {
+ index = 2;
+ }
+
+ return index;
+ };
+
+ /**
+ * 获取最终的字号大小
+ * @param size - 指定字号大小,为空则使用预设值
+ */
+ getSize = (size: number | string | null): null | string => {
+ // 如果未设置全局字号,且未指定size,直接返回null;否则返回对应rpx值
+ if (config.fontSize == null && size == null) {
+ return null;
+ }
+
+ return this.getRpx(size ?? this.sizes[this.getIndex()]);
+ };
+
+ /**
+ * 获取当前行高
+ */
+ getLineHeight = (): null | string => {
+ // 未设置全局字号时返回null
+ if (config.fontSize == null) {
+ return null;
+ }
+
+ const lineHeight = this.lineHeights[this.getIndex()];
+ return lineHeight == 1 ? `1` : this.getRpx(lineHeight);
+ };
+}
+
+/**
+ * 字号管理Hook
+ * @param className - 类名
+ */
+export function useSize(cb: (() => string) | null = null): Size {
+ return new Size(cb);
+}
diff --git a/cool-unix/uni_modules/cool-ui/hooks/ui.ts b/cool-unix/uni_modules/cool-ui/hooks/ui.ts
new file mode 100644
index 0000000..2330d49
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/hooks/ui.ts
@@ -0,0 +1,120 @@
+import { router } from "@/cool";
+import type { ClConfirmAction, ClConfirmOptions, ClToastOptions } from "../types";
+import { t } from "@/locale";
+
+/**
+ * UiInstance 类型定义
+ * - showConfirm: 显示确认弹窗的方法
+ * - showTips: 显示提示弹窗的方法
+ */
+export type UiInstance = {
+ /**
+ * 显示确认弹窗
+ * @param options ClConfirmOptions 弹窗配置项
+ */
+ showConfirm: (options: ClConfirmOptions) => void;
+
+ /**
+ * 显示提示弹窗
+ * @param message 提示消息
+ * @param callback 回调函数,参数为用户操作类型
+ */
+ showTips: (message: string, callback: (action: ClConfirmAction) => void) => void;
+
+ /**
+ * 显示提示弹窗
+ * @param options ClToastOptions 弹窗配置项
+ */
+ showToast: (options: ClToastOptions) => void;
+};
+
+/**
+ * 存储每个页面对应的 UiInstance 实例
+ * key: 当前页面路由
+ * value: UiInstance 实例
+ */
+const list = new Map();
+
+/**
+ * Ui 类,提供全局弹窗调用能力
+ */
+class Ui {
+ /**
+ * 获取当前页面的 UiInstance 实例
+ * @returns UiInstance | undefined
+ */
+ getInstance() {
+ return list.get(router.path());
+ }
+
+ /**
+ * 显示确认弹窗
+ * @param options ClConfirmOptions 弹窗配置项
+ */
+ showConfirm(options: ClConfirmOptions): void {
+ const instance = this.getInstance();
+ if (instance != null) {
+ instance.showConfirm(options);
+ }
+ }
+
+ /**
+ * 显示提示弹窗
+ * @param message 提示消息
+ * @param callback 回调函数
+ */
+ showTips(message: string, callback: (action: ClConfirmAction) => void): void {
+ const instance = this.getInstance();
+ if (instance != null) {
+ instance.showTips(message, callback);
+ }
+ }
+
+ /**
+ * 显示提示弹窗
+ * @param options ClToastOptions 弹窗配置项
+ */
+ showToast(options: ClToastOptions): void {
+ const instance = this.getInstance();
+ if (instance != null) {
+ instance.showToast(options);
+ }
+ }
+
+ /**
+ * 显示加载中弹窗
+ * @param title 提示内容
+ * @param mask 是否显示蒙层
+ */
+ showLoading(title: string | null = null, mask: boolean | null = null): void {
+ uni.showLoading({
+ title: title ?? t("加载中"),
+ mask: mask ?? true
+ });
+ }
+
+ /**
+ * 隐藏加载中弹窗
+ */
+ hideLoading(): void {
+ uni.hideLoading();
+ }
+}
+
+/**
+ * 获取 Ui 实例(始终返回同一个 Ui 实例)
+ * @returns Ui
+ */
+const ui = new Ui();
+
+export function useUi() {
+ return ui;
+}
+
+/**
+ * 注册当前页面的 UiInstance 实例
+ * @param instance UiInstance
+ */
+export function createUi(instance: UiInstance): void {
+ list.set(router.path(), instance);
+}
diff --git a/cool-unix/uni_modules/cool-ui/index.d.ts b/cool-unix/uni_modules/cool-ui/index.d.ts
new file mode 100644
index 0000000..99d6fce
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/index.d.ts
@@ -0,0 +1,155 @@
+import type { ClActionSheetItem, ClActionSheetOptions, PassThroughProps, Type, ClButtonType, Size, ClCalendarDateConfig, ClCalendarMode, ClListViewItem, ClFilterItemType, ClSelectOption, ClFormLabelPosition, ClFormRule, ClFormValidateError, ClInputType, ClListItem, Justify, ClListViewGroup, ClListViewVirtualItem, ClListViewRefresherStatus, ClPopupDirection, ClQrcodeMode, ClSelectValue, ClSelectDateShortcut, ClTabsItem, ClTextType, ClToastOptions, ClTreeItem, ClTreeNodeInfo, ClUploadItem } from "./types";
+import { type QrcodeOptions } from "./draw";
+
+import type { ClActionSheetProps, ClActionSheetPassThrough } from "./components/cl-action-sheet/props";
+import type { ClAvatarProps, ClAvatarPassThrough } from "./components/cl-avatar/props";
+import type { ClBackTopProps } from "./components/cl-back-top/props";
+import type { ClBadgeProps, ClBadgePassThrough } from "./components/cl-badge/props";
+import type { ClBannerProps, ClBannerPassThrough } from "./components/cl-banner/props";
+import type { ClButtonProps, ClButtonPassThrough } from "./components/cl-button/props";
+import type { ClCalendarProps, ClCalendarPassThrough } from "./components/cl-calendar/props";
+import type { ClCalendarSelectProps, ClCalendarSelectPassThrough } from "./components/cl-calendar-select/props";
+import type { ClCascaderProps, ClCascaderPassThrough } from "./components/cl-cascader/props";
+import type { ClCheckboxProps, ClCheckboxPassThrough } from "./components/cl-checkbox/props";
+import type { ClColProps, ClColPassThrough } from "./components/cl-col/props";
+import type { ClCollapseProps, ClCollapsePassThrough } from "./components/cl-collapse/props";
+import type { ClCountdownProps, ClCountdownPassThrough } from "./components/cl-countdown/props";
+import type { ClCropperProps, ClCropperPassThrough } from "./components/cl-cropper/props";
+import type { ClDraggableProps, ClDraggablePassThrough } from "./components/cl-draggable/props";
+import type { ClFilterBarProps } from "./components/cl-filter-bar/props";
+import type { ClFilterItemProps, ClFilterItemPassThrough } from "./components/cl-filter-item/props";
+import type { ClFloatViewProps } from "./components/cl-float-view/props";
+import type { ClFooterProps, ClFooterPassThrough } from "./components/cl-footer/props";
+import type { ClFormProps, ClFormPassThrough } from "./components/cl-form/props";
+import type { ClFormItemProps, ClFormItemPassThrough } from "./components/cl-form-item/props";
+import type { ClIconProps, ClIconPassThrough } from "./components/cl-icon/props";
+import type { ClImageProps, ClImagePassThrough } from "./components/cl-image/props";
+import type { ClIndexBarProps, ClIndexBarPassThrough } from "./components/cl-index-bar/props";
+import type { ClInputProps, ClInputPassThrough } from "./components/cl-input/props";
+import type { ClInputNumberProps, ClInputNumberPassThrough, ClInputNumberValuePassThrough, ClInputNumberOpPassThrough } from "./components/cl-input-number/props";
+import type { ClInputOtpProps, ClInputOtpPassThrough } from "./components/cl-input-otp/props";
+import type { ClKeyboardCarProps, ClKeyboardCarPassThrough } from "./components/cl-keyboard-car/props";
+import type { ClKeyboardNumberProps, ClKeyboardNumberPassThrough } from "./components/cl-keyboard-number/props";
+import type { ClKeyboardPasswordProps, ClKeyboardPasswordPassThrough } from "./components/cl-keyboard-password/props";
+import type { ClListProps, ClListPassThrough } from "./components/cl-list/props";
+import type { ClListItemProps, ClListItemPassThrough } from "./components/cl-list-item/props";
+import type { ClListViewProps, ClListViewPassThrough } from "./components/cl-list-view/props";
+import type { ClLoadingProps, ClLoadingPassThrough } from "./components/cl-loading/props";
+import type { ClLoadmoreProps, ClLoadmorePassThrough } from "./components/cl-loadmore/props";
+import type { ClMarqueeProps, ClMarqueePassThrough } from "./components/cl-marquee/props";
+import type { ClNoticebarProps, ClNoticebarPassThrough } from "./components/cl-noticebar/props";
+import type { ClPageProps } from "./components/cl-page/props";
+import type { ClPaginationProps, ClPaginationPassThrough } from "./components/cl-pagination/props";
+import type { ClSelectPickerViewProps } from "./components/cl-select-picker-view/props";
+import type { ClPopupProps, ClPopupPassThrough, ClPopupHeaderPassThrough } from "./components/cl-popup/props";
+import type { ClProgressProps, ClProgressPassThrough } from "./components/cl-progress/props";
+import type { ClProgressCircleProps, ClProgressCirclePassThrough } from "./components/cl-progress-circle/props";
+import type { ClQrcodeProps } from "./components/cl-qrcode/props";
+import type { ClRadioProps, ClRadioPassThrough } from "./components/cl-radio/props";
+import type { ClRateProps, ClRatePassThrough } from "./components/cl-rate/props";
+import type { ClReadMoreProps, ClReadMorePassThrough } from "./components/cl-read-more/props";
+import type { ClRowProps, ClRowPassThrough } from "./components/cl-row/props";
+import type { ClSafeAreaProps, ClSafeAreaPassThrough } from "./components/cl-safe-area/props";
+import type { ClSelectProps, ClSelectPassThrough } from "./components/cl-select/props";
+import type { ClSelectDateProps, ClSelectDatePassThrough } from "./components/cl-select-date/props";
+import type { ClSelectTimeProps, ClSelectTimePassThrough } from "./components/cl-select-time/props";
+import type { ClSelectTriggerProps, ClSelectTriggerPassThrough } from "./components/cl-select-trigger/props";
+import type { ClSignProps, ClSignPassThrough } from "./components/cl-sign/props";
+import type { ClSkeletonProps, ClSkeletonPassThrough } from "./components/cl-skeleton/props";
+import type { ClSlideVerifyProps, ClSlideVerifyPassThrough } from "./components/cl-slide-verify/props";
+import type { ClSliderProps, ClSliderPassThrough } from "./components/cl-slider/props";
+import type { ClStickyProps } from "./components/cl-sticky/props";
+import type { ClSwitchProps, ClSwitchPassThrough } from "./components/cl-switch/props";
+import type { ClTabsProps, ClTabsPassThrough } from "./components/cl-tabs/props";
+import type { ClTagProps, ClTagPassThrough } from "./components/cl-tag/props";
+import type { ClTextProps, ClTextPassThrough } from "./components/cl-text/props";
+import type { ClTextareaProps, ClTextareaPassThrough } from "./components/cl-textarea/props";
+import type { ClTimelineProps, ClTimelinePassThrough } from "./components/cl-timeline/props";
+import type { ClTimelineItemProps, ClTimelineItemPassThrough } from "./components/cl-timeline-item/props";
+import type { ClToastProps } from "./components/cl-toast/props";
+import type { ClTopbarProps, ClTopbarPassThrough } from "./components/cl-topbar/props";
+import type { ClTreeProps, ClTreePassThrough } from "./components/cl-tree/props";
+import type { ClTreeItemProps, ClTreeItemPassThrough } from "./components/cl-tree-item/props";
+import type { ClUploadProps, ClUploadPassThrough } from "./components/cl-upload/props";
+import type { ClWaterfallProps, ClWaterfallPassThrough } from "./components/cl-waterfall/props";
+import type { ClWatermarkProps, ClWatermarkPassThrough } from "./components/cl-watermark/props";
+
+export {};
+
+// 自动生成的组件全局类型声明
+declare module "vue" {
+ export interface GlobalComponents {
+ "cl-action-sheet": (typeof import('./components/cl-action-sheet/cl-action-sheet.uvue')['default']) & import('vue').DefineComponent;
+ "cl-avatar": (typeof import('./components/cl-avatar/cl-avatar.uvue')['default']) & import('vue').DefineComponent;
+ "cl-back-top": (typeof import('./components/cl-back-top/cl-back-top.uvue')['default']) & import('vue').DefineComponent;
+ "cl-badge": (typeof import('./components/cl-badge/cl-badge.uvue')['default']) & import('vue').DefineComponent;
+ "cl-banner": (typeof import('./components/cl-banner/cl-banner.uvue')['default']) & import('vue').DefineComponent;
+ "cl-button": (typeof import('./components/cl-button/cl-button.uvue')['default']) & import('vue').DefineComponent;
+ "cl-calendar": (typeof import('./components/cl-calendar/cl-calendar.uvue')['default']) & import('vue').DefineComponent;
+ "cl-calendar-select": (typeof import('./components/cl-calendar-select/cl-calendar-select.uvue')['default']) & import('vue').DefineComponent;
+ "cl-cascader": (typeof import('./components/cl-cascader/cl-cascader.uvue')['default']) & import('vue').DefineComponent;
+ "cl-checkbox": (typeof import('./components/cl-checkbox/cl-checkbox.uvue')['default']) & import('vue').DefineComponent;
+ "cl-col": (typeof import('./components/cl-col/cl-col.uvue')['default']) & import('vue').DefineComponent;
+ "cl-collapse": (typeof import('./components/cl-collapse/cl-collapse.uvue')['default']) & import('vue').DefineComponent;
+ "cl-countdown": (typeof import('./components/cl-countdown/cl-countdown.uvue')['default']) & import('vue').DefineComponent;
+ "cl-cropper": (typeof import('./components/cl-cropper/cl-cropper.uvue')['default']) & import('vue').DefineComponent;
+ "cl-draggable": (typeof import('./components/cl-draggable/cl-draggable.uvue')['default']) & import('vue').DefineComponent;
+ "cl-filter-bar": (typeof import('./components/cl-filter-bar/cl-filter-bar.uvue')['default']) & import('vue').DefineComponent;
+ "cl-filter-item": (typeof import('./components/cl-filter-item/cl-filter-item.uvue')['default']) & import('vue').DefineComponent;
+ "cl-float-view": (typeof import('./components/cl-float-view/cl-float-view.uvue')['default']) & import('vue').DefineComponent;
+ "cl-footer": (typeof import('./components/cl-footer/cl-footer.uvue')['default']) & import('vue').DefineComponent;
+ "cl-form": (typeof import('./components/cl-form/cl-form.uvue')['default']) & import('vue').DefineComponent;
+ "cl-form-item": (typeof import('./components/cl-form-item/cl-form-item.uvue')['default']) & import('vue').DefineComponent;
+ "cl-icon": (typeof import('./components/cl-icon/cl-icon.uvue')['default']) & import('vue').DefineComponent;
+ "cl-image": (typeof import('./components/cl-image/cl-image.uvue')['default']) & import('vue').DefineComponent;
+ "cl-index-bar": (typeof import('./components/cl-index-bar/cl-index-bar.uvue')['default']) & import('vue').DefineComponent;
+ "cl-input": (typeof import('./components/cl-input/cl-input.uvue')['default']) & import('vue').DefineComponent;
+ "cl-input-number": (typeof import('./components/cl-input-number/cl-input-number.uvue')['default']) & import('vue').DefineComponent;
+ "cl-input-otp": (typeof import('./components/cl-input-otp/cl-input-otp.uvue')['default']) & import('vue').DefineComponent;
+ "cl-keyboard-car": (typeof import('./components/cl-keyboard-car/cl-keyboard-car.uvue')['default']) & import('vue').DefineComponent;
+ "cl-keyboard-number": (typeof import('./components/cl-keyboard-number/cl-keyboard-number.uvue')['default']) & import('vue').DefineComponent;
+ "cl-keyboard-password": (typeof import('./components/cl-keyboard-password/cl-keyboard-password.uvue')['default']) & import('vue').DefineComponent;
+ "cl-list": (typeof import('./components/cl-list/cl-list.uvue')['default']) & import('vue').DefineComponent;
+ "cl-list-item": (typeof import('./components/cl-list-item/cl-list-item.uvue')['default']) & import('vue').DefineComponent;
+ "cl-list-view": (typeof import('./components/cl-list-view/cl-list-view.uvue')['default']) & import('vue').DefineComponent;
+ "cl-loading": (typeof import('./components/cl-loading/cl-loading.uvue')['default']) & import('vue').DefineComponent;
+ "cl-loadmore": (typeof import('./components/cl-loadmore/cl-loadmore.uvue')['default']) & import('vue').DefineComponent;
+ "cl-marquee": (typeof import('./components/cl-marquee/cl-marquee.uvue')['default']) & import('vue').DefineComponent;
+ "cl-noticebar": (typeof import('./components/cl-noticebar/cl-noticebar.uvue')['default']) & import('vue').DefineComponent;
+ "cl-page": (typeof import('./components/cl-page/cl-page.uvue')['default']) & import('vue').DefineComponent;
+ "cl-pagination": (typeof import('./components/cl-pagination/cl-pagination.uvue')['default']) & import('vue').DefineComponent;
+ "cl-select-picker-view": (typeof import('./components/cl-select-picker-view/cl-select-picker-view.uvue')['default']) & import('vue').DefineComponent;
+ "cl-popup": (typeof import('./components/cl-popup/cl-popup.uvue')['default']) & import('vue').DefineComponent;
+ "cl-progress": (typeof import('./components/cl-progress/cl-progress.uvue')['default']) & import('vue').DefineComponent;
+ "cl-progress-circle": (typeof import('./components/cl-progress-circle/cl-progress-circle.uvue')['default']) & import('vue').DefineComponent;
+ "cl-qrcode": (typeof import('./components/cl-qrcode/cl-qrcode.uvue')['default']) & import('vue').DefineComponent;
+ "cl-radio": (typeof import('./components/cl-radio/cl-radio.uvue')['default']) & import('vue').DefineComponent;
+ "cl-rate": (typeof import('./components/cl-rate/cl-rate.uvue')['default']) & import('vue').DefineComponent;
+ "cl-read-more": (typeof import('./components/cl-read-more/cl-read-more.uvue')['default']) & import('vue').DefineComponent;
+ "cl-row": (typeof import('./components/cl-row/cl-row.uvue')['default']) & import('vue').DefineComponent;
+ "cl-safe-area": (typeof import('./components/cl-safe-area/cl-safe-area.uvue')['default']) & import('vue').DefineComponent;
+ "cl-select": (typeof import('./components/cl-select/cl-select.uvue')['default']) & import('vue').DefineComponent;
+ "cl-select-date": (typeof import('./components/cl-select-date/cl-select-date.uvue')['default']) & import('vue').DefineComponent;
+ "cl-select-time": (typeof import('./components/cl-select-time/cl-select-time.uvue')['default']) & import('vue').DefineComponent;
+ "cl-select-trigger": (typeof import('./components/cl-select-trigger/cl-select-trigger.uvue')['default']) & import('vue').DefineComponent;
+ "cl-sign": (typeof import('./components/cl-sign/cl-sign.uvue')['default']) & import('vue').DefineComponent;
+ "cl-skeleton": (typeof import('./components/cl-skeleton/cl-skeleton.uvue')['default']) & import('vue').DefineComponent;
+ "cl-slide-verify": (typeof import('./components/cl-slide-verify/cl-slide-verify.uvue')['default']) & import('vue').DefineComponent;
+ "cl-slider": (typeof import('./components/cl-slider/cl-slider.uvue')['default']) & import('vue').DefineComponent;
+ "cl-sticky": (typeof import('./components/cl-sticky/cl-sticky.uvue')['default']) & import('vue').DefineComponent;
+ "cl-switch": (typeof import('./components/cl-switch/cl-switch.uvue')['default']) & import('vue').DefineComponent;
+ "cl-tabs": (typeof import('./components/cl-tabs/cl-tabs.uvue')['default']) & import('vue').DefineComponent;
+ "cl-tag": (typeof import('./components/cl-tag/cl-tag.uvue')['default']) & import('vue').DefineComponent;
+ "cl-text": (typeof import('./components/cl-text/cl-text.uvue')['default']) & import('vue').DefineComponent;
+ "cl-textarea": (typeof import('./components/cl-textarea/cl-textarea.uvue')['default']) & import('vue').DefineComponent;
+ "cl-timeline": (typeof import('./components/cl-timeline/cl-timeline.uvue')['default']) & import('vue').DefineComponent;
+ "cl-timeline-item": (typeof import('./components/cl-timeline-item/cl-timeline-item.uvue')['default']) & import('vue').DefineComponent;
+ "cl-toast": (typeof import('./components/cl-toast/cl-toast.uvue')['default']) & import('vue').DefineComponent;
+ "cl-topbar": (typeof import('./components/cl-topbar/cl-topbar.uvue')['default']) & import('vue').DefineComponent;
+ "cl-tree": (typeof import('./components/cl-tree/cl-tree.uvue')['default']) & import('vue').DefineComponent;
+ "cl-tree-item": (typeof import('./components/cl-tree-item/cl-tree-item.uvue')['default']) & import('vue').DefineComponent;
+ "cl-upload": (typeof import('./components/cl-upload/cl-upload.uvue')['default']) & import('vue').DefineComponent;
+ "cl-waterfall": (typeof import('./components/cl-waterfall/cl-waterfall.uvue')['default']) & import('vue').DefineComponent;
+ "cl-watermark": (typeof import('./components/cl-watermark/cl-watermark.uvue')['default']) & import('vue').DefineComponent;
+ }
+}
diff --git a/cool-unix/uni_modules/cool-ui/index.ts b/cool-unix/uni_modules/cool-ui/index.ts
new file mode 100644
index 0000000..79b1c33
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/index.ts
@@ -0,0 +1,5 @@
+import "./locale";
+import "./components/cl-calendar/locale";
+
+export * from "./types";
+export * from "./hooks";
diff --git a/cool-unix/uni_modules/cool-ui/locale/en.json b/cool-unix/uni_modules/cool-ui/locale/en.json
new file mode 100644
index 0000000..ba6428e
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/locale/en.json
@@ -0,0 +1 @@
+[["10月","October"],["11月","November"],["12月","December"],["{year}年{month}月","{year} {month}"],["一","one"],["二","two"],["三","three"],["四","four"],["五","five"],["六","six"],["结束日期","End Date"],[" 至 "," to "],["今天","Today"],["近7天","Last 7 Days"],["近30天","Last 30 Days"],["近90天","Last 90 Days"],["近一年","Last Year"],["请选择完整时间范围","Please select a full time range"],["开始日期不能大于结束日期","Start date cannot be greater than end date"],["展开","Expand"],["收起","Collapse"],["提示","Tip"],["没有更多了","No more"],["下拉刷新","Pull down to refresh"],["释放立即刷新","Release to refresh immediately"],["密码键盘","Password Keyboard"],["安全键盘,请放心输入","Secure Keyboard, input with confidence"],["请输入内容","Please enter content"],["请输入{minlength}到{maxlength}位密码","Please enter a password of {minlength} to {maxlength} digits"],["最多输入{maxlength}位","Maximum input of {maxlength} digits"],["数字键盘","Numeric Keyboard"],["身份证号码格式不正确","Invalid ID number format"],["车牌键盘","License Plate Keyboard"],["车牌号格式不正确","Invalid license plate number format"],["此字段为必填项","This field is required"],["最小值为{min}","Minimum value is {min}"],["最少需要{min}个字符","At least {min} characters required"],["最大值为{max}","Maximum value is {max}"],["最多允许{max}个字符","Maximum {max} characters allowed"],["格式不正确","Incorrect format"],["暂无数据","No data available"],["1月","Jan"],["2月","Feb"],["3月","Mar"],["4月","Apr"],["5月","May"],["6月","Jun"],["7月","Jul"],["8月","Aug"],["9月","Sep"],["加载中","Loading"],["上传 / 拍摄","Upload / Shoot"],["请输入","Please enter"],["验证成功","Verification successful"],["验证失败","Verification failed"],["向右滑动转动图片","Swipe right to rotate the picture"],["向右滑动验证","Swipe right to verify"],["请选择","Please select"],["小时","Hour"],["分钟","Minute"],["秒数","Seconds"],["确定","OK"],["取消","Cancel"],["年","Year"],["月","Month"],["日","Day"],["时","Hour"],["分","Minute"],["秒","Second"],["开始日期","Start date"]]
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-ui/locale/es.json b/cool-unix/uni_modules/cool-ui/locale/es.json
new file mode 100644
index 0000000..e84b5e4
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/locale/es.json
@@ -0,0 +1 @@
+[["10月","oct."],["11月","nov."],["12月","dic."],["{year}年{month}月","{year} {month}"],["一","uno"],["二","dos"],["三","tres"],["四","cuatro"],["五","cinco"],["六","seis"],["加载中","Cargando"],["上传 / 拍摄","Subir / Tomar foto"],["请输入","Ingrese aquí"],["验证成功","Validación exitosa"],["验证失败","Validación fallida"],["向右滑动转动图片","Deslice hacia la derecha para girar la imagen"],["向右滑动验证","Deslice hacia la derecha para validar"],["请选择","Seleccione"],["小时","Horas"],["分钟","Minutos"],["秒数","Segundos"],["确定","Aceptar"],["取消","Cancelar"],["年","Año"],["月","Mes"],["日","Día"],["时","Hora"],["分","Minuto"],["秒","Segundo"],["开始日期","Fecha de inicio"],["数字键盘","Teclado numérico"],["身份证号码格式不正确","El formato del número de identificación es incorrecto"],["车牌键盘","Teclado de matrícula"],["车牌号格式不正确","El formato de la matrícula es incorrecto"],["此字段为必填项","Este campo es obligatorio"],["最小值为{min}","El valor mínimo es {min}"],["最少需要{min}个字符","Se necesitan como mínimo {min} caracteres"],["最大值为{max}","El valor máximo es {max}"],["最多允许{max}个字符","Se permiten como máximo {max} caracteres"],["格式不正确","Formato incorrecto"],["暂无数据","No hay datos disponibles"],["1月","Enero"],["2月","Febrero"],["3月","Marzo"],["4月","Abril"],["5月","Mayo"],["6月","Junio"],["7月","Julio"],["8月","Agosto"],["9月","Septiembre"],["结束日期","Fecha de finalización"],[" 至 "," a "],["今天","Hoy"],["近7天","Últimos 7 días"],["近30天","Últimos 30 días"],["近90天","Últimos 90 días"],["近一年","Último año"],["请选择完整时间范围","Seleccione un rango de tiempo completo"],["开始日期不能大于结束日期","La fecha de inicio no puede ser mayor que la fecha de finalización"],["展开","Expandir"],["收起","Contraer"],["提示","Sugerencia"],["没有更多了","No hay más"],["下拉刷新","Refrescar hacia abajo"],["释放立即刷新","Suelta para refrescar inmediatamente"],["密码键盘","Teclado de contraseña"],["安全键盘,请放心输入","Teclado seguro, ingrese con confianza"],["请输入内容","Ingrese el contenido"],["请输入{minlength}到{maxlength}位密码","Ingrese una contraseña de {minlength} a {maxlength} dígitos"],["最多输入{maxlength}位","Máximo {maxlength} dígitos"]]
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-ui/locale/fr.json b/cool-unix/uni_modules/cool-ui/locale/fr.json
new file mode 100644
index 0000000..e96b93a
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/locale/fr.json
@@ -0,0 +1 @@
+[["10月","oct."],["11月","nov."],["12月","déc."],["{year}年{month}月","{year} {month}"],["一","un"],["二","deux"],["三","trois"],["四","quatre"],["五","cinq"],["六","six"],["加载中","Chargement..."],["上传 / 拍摄","Télécharger / Prendre une photo"],["请输入","Veuillez entrer"],["验证成功","Vérification réussie"],["验证失败","Vérification échouée"],["向右滑动转动图片","Glisser vers la droite pour tourner l'image"],["向右滑动验证","Glisser vers la droite pour vérifier"],["请选择","Veuillez sélectionner"],["小时","Heures"],["分钟","Minutes"],["秒数","Secondes"],["确定","OK"],["取消","Annuler"],["年","Ans"],["月","Mois"],["日","Jours"],["时","Heures"],["分","Minutes"],["秒","Secondes"],["开始日期","Date de début"],["数字键盘","Pavé numérique"],["身份证号码格式不正确","Format de numéro de carte d'identité incorrect"],["车牌键盘","Pavé plaque d'immatriculation"],["车牌号格式不正确","Format de numéro de plaque d'immatriculation incorrect"],["此字段为必填项","Ce champ est obligatoire"],["最小值为{min}","La valeur minimale est {min}"],["最少需要{min}个字符","Au moins {min} caractères sont nécessaires"],["最大值为{max}","La valeur maximale est {max}"],["最多允许{max}个字符","Au plus {max} caractères sont autorisés"],["格式不正确","Format incorrect"],["暂无数据","Aucune donnée disponible"],["1月","janvier"],["2月","février"],["3月","mars"],["4月","avril"],["5月","mai"],["6月","juin"],["7月","juillet"],["8月","août"],["9月","septembre"],["结束日期","Date de fin"],[" 至 ","au"],["今天","Aujourd'hui"],["近7天","Derniers 7 jours"],["近30天","Derniers 30 jours"],["近90天","Derniers 90 jours"],["近一年","Dernière année"],["请选择完整时间范围","Veuillez sélectionner une plage de temps complète"],["开始日期不能大于结束日期","La date de début ne peut pas être supérieure à la date de fin"],["展开","Développer"],["收起","Réduire"],["提示","Avertissement"],["没有更多了","Plus rien"],["下拉刷新","Actualiser en basculant"],["释放立即刷新","Décrocher pour actualiser immédiatement"],["密码键盘","Clavier de mot de passe"],["安全键盘,请放心输入","Clavier sécurisé, saisissez sans crainte"],["请输入内容","Veuillez saisir le contenu"],["请输入{minlength}到{maxlength}位密码","Veuillez saisir un mot de passe de {minlength} à {maxlength} caractères"],["最多输入{maxlength}位","Maximum {maxlength} caractères"]]
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-ui/locale/index.ts b/cool-unix/uni_modules/cool-ui/locale/index.ts
new file mode 100644
index 0000000..8b2481d
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/locale/index.ts
@@ -0,0 +1,19 @@
+import { appendLocale } from "@/locale";
+
+import zhcn from "./zh-cn.json";
+import zhtw from "./zh-tw.json";
+import en from "./en.json";
+import es from "./es.json";
+import ja from "./ja.json";
+import fr from "./fr.json";
+import ko from "./ko.json";
+
+setTimeout(() => {
+ appendLocale("zh-cn", zhcn);
+ appendLocale("zh-tw", zhtw);
+ appendLocale("en", en);
+ appendLocale("es", es);
+ appendLocale("ja", ja);
+ appendLocale("fr", fr);
+ appendLocale("ko", ko);
+}, 0);
diff --git a/cool-unix/uni_modules/cool-ui/locale/ja.json b/cool-unix/uni_modules/cool-ui/locale/ja.json
new file mode 100644
index 0000000..7145dfb
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/locale/ja.json
@@ -0,0 +1 @@
+[["10月","10月"],["11月","11月"],["12月","12月"],["{year}年{month}月","{year}年{month}月"],["一","一"],["二","二"],["三","三"],["四","四"],["五","五"],["六","六"],["数字键盘","数字キーボード"],["身份证号码格式不正确","身分証番号の形式が正しくありません"],["车牌键盘","自動車番号キーボード"],["车牌号格式不正确","自動車番号の形式が正しくありません"],["此字段为必填项","この項目は必須です"],["最小值为{min}","最小値は{min}です"],["最少需要{min}个字符","{min}文字以上必要です"],["最大值为{max}","最大値は{max}です"],["最多允许{max}个字符","{max}文字以下です"],["格式不正确","形式が正しくありません"],["暂无数据","データはありません"],["1月","1月"],["2月","2月"],["3月","3月"],["4月","4月"],["5月","5月"],["6月","6月"],["7月","7月"],["8月","8月"],["9月","9月"],["加载中","読み込み中"],["上传 / 拍摄","アップロード/撮影"],["请输入","入力してください"],["验证成功","認証成功"],["验证失败","認証失敗"],["向右滑动转动图片","右にスワイプして画像を回転させる"],["向右滑动验证","右にスワイプして認証する"],["请选择","選択してください"],["小时","時間"],["分钟","分"],["秒数","秒数"],["确定","確定"],["取消","キャンセル"],["年","年"],["月","月"],["日","日"],["时","時"],["分","分"],["秒","秒"],["开始日期","開始日付"],["结束日期","終了日"],[" 至 ","から"],["今天","今日"],["近7天","直近7日間"],["近30天","直近30日間"],["近90天","直近90日間"],["近一年","直近1年間"],["请选择完整时间范围","完全な期間を選択してください"],["开始日期不能大于结束日期","開始日は終了日より大きくてはいけません"],["展开","展開"],["收起","閉じる"],["提示","ヒント"],["没有更多了","もうありません"],["下拉刷新","ドロップダウンで更新"],["释放立即刷新","すぐに更新するには解放してください"],["密码键盘","パスワードキーボード"],["安全键盘,请放心输入","セキュリティキーボード、安心して入力してください"],["请输入内容","内容を入力してください"],["请输入{minlength}到{maxlength}位密码","{minlength}桁から{maxlength}桁のパスワードを入力してください"],["最多输入{maxlength}位","{maxlength}桁まで入力可能"]]
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-ui/locale/ko.json b/cool-unix/uni_modules/cool-ui/locale/ko.json
new file mode 100644
index 0000000..798fff9
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/locale/ko.json
@@ -0,0 +1 @@
+[["10月","10월"],["11月","11월"],["12月","12월"],["{year}年{month}月","{year}년 {month}월"],["一","일"],["二","이"],["三","삼"],["四","사"],["五","오"],["六","육"],["加载中","로딩 중"],["上传 / 拍摄","업로드 / 촬영"],["请输入","입력해 주세요"],["验证成功","인증 성공"],["验证失败","인증 실패"],["向右滑动转动图片","화면을 오른쪽으로 드래그하여 사진을 회전시켜 주세요"],["向右滑动验证","오른쪽으로 슬라이드하여 인증해 주세요"],["请选择","선택해 주세요"],["小时","시간"],["分钟","분"],["秒数","초"],["确定","확인"],["取消","취소"],["年","년"],["月","월"],["日","일"],["时","시"],["分","분"],["秒","초"],["开始日期","시작 일자"],["数字键盘","숫자 키보드"],["身份证号码格式不正确","주민등록번호 형식이 올바르지 않습니다."],["车牌键盘","자동차 번호판 키보드"],["车牌号格式不正确","자동차 번호판 형식이 올바르지 않습니다."],["此字段为必填项","이 필드는 필수입니다."],["最小值为{min}","최소값은 {min}입니다."],["最少需要{min}个字符","최소 {min}개의 문자가 필요합니다."],["最大值为{max}","최대값은 {max}입니다."],["最多允许{max}个字符","최대 {max}개의 문자를 허용합니다."],["格式不正确","형식이 올바르지 않습니다."],["暂无数据","데이터가 없습니다."],["1月","1월"],["2月","2월"],["3月","3월"],["4月","4월"],["5月","5월"],["6月","6월"],["7月","7월"],["8月","8월"],["9月","9월"],["结束日期","종료일"],[" 至 ","~"],["今天","오늘"],["近7天","지난 7일"],["近30天","지난 30일"],["近90天","지난 90일"],["近一年","지난 1년"],["请选择完整时间范围","전체 시간 범위를 선택하세요."],["开始日期不能大于结束日期","시작일은 종료일보다 클 수 없습니다."],["展开","열기"],["收起","접기"],["提示","힌트"],["没有更多了","더 이상 없습니다."],["下拉刷新","드롭다운 새로고침"],["释放立即刷新","즉시 새로고침하려면 놓아주세요."],["密码键盘","비밀번호 키보드"],["安全键盘,请放心输入","안전한 키보드입니다. 안심하고 입력해주세요."],["请输入内容","내용을 입력하세요."],["请输入{minlength}到{maxlength}位密码","{minlength}에서 {maxlength}자리 비밀번호를 입력하세요."],["最多输入{maxlength}位","최대 {maxlength}자리까지 입력 가능합니다."]]
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-ui/locale/zh-cn.json b/cool-unix/uni_modules/cool-ui/locale/zh-cn.json
new file mode 100644
index 0000000..81fc2d2
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/locale/zh-cn.json
@@ -0,0 +1 @@
+[["加载中",""],["上传 / 拍摄",""],["请输入",""],["验证成功",""],["验证失败",""],["向右滑动转动图片",""],["向右滑动验证",""],["请选择",""],["小时",""],["分钟",""],["秒数",""],["确定",""],["取消",""],["年",""],["月",""],["日",""],["时",""],["分",""],["秒",""],["开始日期",""],["结束日期",""],[" 至 ",""],["今天",""],["近7天",""],["近30天",""],["近90天",""],["近一年",""],["请选择完整时间范围",""],["开始日期不能大于结束日期",""],["展开",""],["收起",""],["提示",""],["没有更多了",""],["下拉刷新",""],["释放立即刷新",""],["密码键盘",""],["安全键盘,请放心输入",""],["请输入内容",""],["请输入{minlength}到{maxlength}位密码",""],["最多输入{maxlength}位",""],["数字键盘",""],["身份证号码格式不正确",""],["车牌键盘",""],["车牌号格式不正确",""],["此字段为必填项",""],["最小值为{min}",""],["最少需要{min}个字符",""],["最大值为{max}",""],["最多允许{max}个字符",""],["格式不正确",""],["暂无数据",""],["1月",""],["2月",""],["3月",""],["4月",""],["5月",""],["6月",""],["7月",""],["8月",""],["9月",""],["10月",""],["11月",""],["12月",""],["{year}年{month}月",""],["一",""],["二",""],["三",""],["四",""],["五",""],["六",""]]
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-ui/locale/zh-tw.json b/cool-unix/uni_modules/cool-ui/locale/zh-tw.json
new file mode 100644
index 0000000..7ef165e
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/locale/zh-tw.json
@@ -0,0 +1 @@
+[["10月","十月"],["11月","十一月"],["12月","十二月"],["{year}年{month}月","{year}年{month}月"],["一","一"],["二","二"],["三","三"],["四","四"],["五","五"],["六","六"],["加载中","加載中"],["上传 / 拍摄","上傳 / 拍攝"],["请输入","請輸入"],["验证成功","驗證成功"],["验证失败","驗證失敗"],["向右滑动转动图片","向右滑動轉動圖片"],["向右滑动验证","向右滑動驗證"],["请选择","請選擇"],["小时","小時"],["分钟","分鐘"],["秒数","秒數"],["确定","確定"],["取消","取消"],["年","年"],["月","月"],["日","日"],["时","時"],["分","分"],["秒","秒"],["开始日期","開始日期"],["数字键盘","數字鍵盤"],["身份证号码格式不正确","身份證號碼格式不正確"],["车牌键盘","車牌鍵盤"],["车牌号格式不正确","車牌號格式不正確"],["此字段为必填项","此欄位為必填項"],["最小值为{min}","最小值為{min}"],["最少需要{min}个字符","最少需要{min}個字元"],["最大值为{max}","最大值為{max}"],["最多允许{max}个字符","最多允許{max}個字元"],["格式不正确","格式不正確"],["暂无数据","暂无資料"],["1月","1月"],["2月","2月"],["3月","3月"],["4月","4月"],["5月","5月"],["6月","6月"],["7月","7月"],["8月","8月"],["9月","9月"],["结束日期","結束日期"],[" 至 "," 至 "],["今天","今天"],["近7天","近7天"],["近30天","近30天"],["近90天","近90天"],["近一年","近一年"],["请选择完整时间范围","請選擇完整時間範圍"],["开始日期不能大于结束日期","開始日期不能大於結束日期"],["展开","展開"],["收起","收起"],["提示","提示"],["没有更多了","沒有更多了"],["下拉刷新","下拉刷新"],["释放立即刷新","釋放立即刷新"],["密码键盘","密碼鍵盤"],["安全键盘,请放心输入","安全鍵盤,請放心輸入"],["请输入内容","請輸入內容"],["请输入{minlength}到{maxlength}位密码","請輸入{minlength}到{maxlength}位密碼"],["最多输入{maxlength}位","最多輸入{maxlength}位"]]
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-ui/scripts/generate-types.js b/cool-unix/uni_modules/cool-ui/scripts/generate-types.js
new file mode 100644
index 0000000..7ecf0cc
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/scripts/generate-types.js
@@ -0,0 +1,1394 @@
+const fs = require("fs");
+const path = require("path");
+const { parse } = require("@vue/compiler-sfc");
+const babelParser = require("@babel/parser");
+const t = require("@babel/types");
+
+/**
+ * UVUE 组件类型定义生成器
+ *
+ * 这个脚本可以自动解析 uvue 文件中的 Vue 3 Composition API 代码,
+ * 提取组件的 Props、Emits、Expose 等类型信息,并生成对应的 TypeScript 类型定义。
+ *
+ * 支持的特性:
+ * - ✅ defineProps:支持所有 Vue 3 props 定义方式,包括 PropType、联合类型、可选/必需属性
+ * - ✅ defineEmits:支持 TypeScript 类型化的 defineEmits<{}>() 和数组形式的 defineEmits([])
+ * - ✅ defineSlots:支持 TypeScript 类型化的 defineSlots<{}>() 插槽定义
+ * - ✅ defineExpose:解析组件暴露的方法和属性
+ * - ✅ defineOptions:提取组件名称
+ * - ✅ 自动生成 Vue 全局组件类型声明
+ *
+ * 生成的文件:
+ * - index.d.ts:包含全局组件类型声明的主文件
+ * - types/components.ts:包含具体组件 Props 接口的类型文件
+ *
+ * 使用方法:
+ * 1. 确保项目已安装必要依赖:@vue/compiler-sfc @babel/parser @babel/types
+ * 2. 运行脚本:npm run generate-types 或 node uni_modules/cool-ui/scripts/generate-types.js
+ * 3. 生成的类型文件将自动更新到对应位置
+ *
+ * @author AI Assistant
+ * @version 1.0.0
+ */
+
+/**
+ * 解析uvue文件并提取类型信息
+ */
+class UvueTypeParser {
+ constructor() {
+ this.componentTypes = new Map();
+ }
+
+ /**
+ * 使用Vue官方编译器解析uvue文件
+ */
+ parseUvueFile(filePath) {
+ const content = fs.readFileSync(filePath, "utf-8");
+
+ try {
+ // 使用Vue官方编译器解析SFC文件
+ const { descriptor } = parse(content, { filename: filePath });
+
+ if (!descriptor.script && !descriptor.scriptSetup) {
+ console.log(` 跳过文件 ${path.basename(filePath)}: 没有script部分`);
+ return null;
+ }
+
+ // 优先使用script setup,否则使用普通script
+ const script = descriptor.scriptSetup || descriptor.script;
+ if (!script || !script.content) {
+ return null;
+ }
+
+ return this.parseScriptContent(script.content, filePath);
+ } catch (error) {
+ console.error(`解析文件 ${filePath} 时出错:`, error.message);
+ return null;
+ }
+ }
+
+ /**
+ * 解析script内容
+ */
+ parseScriptContent(scriptContent, filePath) {
+ try {
+ // 使用Babel解析TypeScript代码
+ const ast = babelParser.parse(scriptContent, {
+ sourceType: "module",
+ plugins: ["typescript", "decorators-legacy"]
+ });
+
+ const result = {
+ name: null,
+ props: {},
+ emits: {},
+ slots: {},
+ expose: {},
+ imports: [],
+ passThroughTypes: {},
+ filePath
+ };
+
+ // 遍历AST节点
+ this.traverseAST(ast, result);
+
+ return result.name ? result : null;
+ } catch (error) {
+ console.error(`解析script内容时出错:`, error.message);
+ return null;
+ }
+ }
+
+ /**
+ * 遍历AST并提取信息
+ */
+ traverseAST(ast, result) {
+ const visit = (node) => {
+ if (!node) return;
+
+ // 处理import语句
+ if (t.isImportDeclaration(node)) {
+ this.extractImports(node, result);
+ }
+
+ // 处理defineOptions调用
+ if (
+ t.isCallExpression(node) &&
+ t.isIdentifier(node.callee) &&
+ node.callee.name === "defineOptions"
+ ) {
+ this.extractDefineOptions(node, result);
+ }
+
+ // 处理defineProps调用
+ if (
+ t.isCallExpression(node) &&
+ t.isIdentifier(node.callee) &&
+ node.callee.name === "defineProps"
+ ) {
+ this.extractDefineProps(node, result);
+ }
+
+ // 处理defineEmits调用
+ if (
+ t.isCallExpression(node) &&
+ t.isIdentifier(node.callee) &&
+ node.callee.name === "defineEmits"
+ ) {
+ this.extractDefineEmits(node, result);
+ }
+
+ // 处理defineSlots调用
+ if (
+ t.isCallExpression(node) &&
+ t.isIdentifier(node.callee) &&
+ node.callee.name === "defineSlots"
+ ) {
+ this.extractDefineSlots(node, result);
+ }
+
+ // 处理defineExpose调用
+ if (
+ t.isCallExpression(node) &&
+ t.isIdentifier(node.callee) &&
+ node.callee.name === "defineExpose"
+ ) {
+ this.extractDefineExpose(node, result);
+ }
+
+ // 处理type声明(如PassThrough类型)
+ if (t.isTSTypeAliasDeclaration(node)) {
+ this.extractTypeAlias(node, result);
+ }
+
+ // 递归遍历所有子节点
+ for (const key in node) {
+ const child = node[key];
+ if (Array.isArray(child)) {
+ child.forEach(visit);
+ } else if (child && typeof child === "object" && child.type) {
+ visit(child);
+ }
+ }
+ };
+
+ visit(ast);
+ }
+
+ /**
+ * 提取import语句中的类型导入
+ */
+ extractImports(node, result) {
+ if (!t.isStringLiteral(node.source)) return;
+
+ const source = node.source.value;
+ const typeImports = [];
+
+ // 只处理类型导入 (import type {...} 或 import { type ... })
+ if (node.importKind === "type") {
+ // import type { Type1, Type2 } from '...'
+ for (const specifier of node.specifiers) {
+ if (t.isImportSpecifier(specifier)) {
+ const importedName = t.isIdentifier(specifier.imported)
+ ? specifier.imported.name
+ : specifier.imported.value;
+ typeImports.push(importedName);
+ }
+ }
+ } else {
+ // import { type Type1, type Type2, normalFunction } from '...'
+ for (const specifier of node.specifiers) {
+ if (t.isImportSpecifier(specifier) && specifier.importKind === "type") {
+ const importedName = t.isIdentifier(specifier.imported)
+ ? specifier.imported.name
+ : specifier.imported.value;
+ typeImports.push(importedName);
+ }
+ }
+ }
+
+ // 只保存类型导入,并且不是vue或其他框架的导入
+ if (typeImports.length > 0 && !source.includes("vue") && !source.includes("@/")) {
+ result.imports.push({
+ source,
+ types: typeImports,
+ isTypeOnly: node.importKind === "type"
+ });
+ }
+ }
+
+ /**
+ * 提取defineOptions中的组件名
+ */
+ extractDefineOptions(node, result) {
+ if (node.arguments.length > 0 && t.isObjectExpression(node.arguments[0])) {
+ const props = node.arguments[0].properties;
+ for (const prop of props) {
+ if (
+ t.isObjectProperty(prop) &&
+ t.isIdentifier(prop.key) &&
+ prop.key.name === "name" &&
+ t.isStringLiteral(prop.value)
+ ) {
+ result.name = prop.value.value;
+ }
+ }
+ }
+ }
+
+ /**
+ * 提取defineProps中的props定义
+ */
+ extractDefineProps(node, result) {
+ if (node.arguments.length > 0 && t.isObjectExpression(node.arguments[0])) {
+ const propsObj = node.arguments[0];
+
+ for (const prop of propsObj.properties) {
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
+ const propName = prop.key.name;
+ const propConfig = this.extractPropConfig(prop.value);
+ if (propConfig) {
+ result.props[propName] = propConfig;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 提取单个prop的配置
+ */
+ extractPropConfig(propValue) {
+ if (!t.isObjectExpression(propValue)) {
+ return null;
+ }
+
+ // 默认所有 props 都是可选的(非必填),符合 Vue 的默认行为
+ const config = {
+ type: "any",
+ required: false
+ };
+
+ for (const prop of propValue.properties) {
+ if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key)) continue;
+
+ const key = prop.key.name;
+
+ if (key === "type") {
+ config.type = this.extractTypeFromValue(prop.value);
+ } else if (key === "required" && t.isBooleanLiteral(prop.value)) {
+ // 只有显式设置 required: true 时才设为必填
+ config.required = prop.value.value;
+ }
+ }
+
+ return config;
+ }
+
+ /**
+ * 从AST值节点提取类型信息
+ */
+ extractTypeFromValue(node) {
+ // 处理基础类型
+ if (t.isIdentifier(node)) {
+ switch (node.name) {
+ case "String":
+ return "string";
+ case "Number":
+ return "number";
+ case "Boolean":
+ return "boolean";
+ case "Object":
+ return "object";
+ case "Array":
+ return "any[]";
+ case "Function":
+ return "Function";
+ default:
+ return node.name;
+ }
+ }
+
+ // 处理 String as PropType 形式
+ if (t.isTSAsExpression(node) && t.isTSTypeReference(node.typeAnnotation)) {
+ const typeRef = node.typeAnnotation;
+ if (t.isIdentifier(typeRef.typeName) && typeRef.typeName.name === "PropType") {
+ if (typeRef.typeParameters && typeRef.typeParameters.params.length > 0) {
+ return this.extractTSType(typeRef.typeParameters.params[0]);
+ }
+ }
+ }
+
+ return "any";
+ }
+
+ /**
+ * 提取TypeScript类型
+ */
+ extractTSType(tsType) {
+ if (t.isTSStringKeyword(tsType)) return "string";
+ if (t.isTSNumberKeyword(tsType)) return "number";
+ if (t.isTSBooleanKeyword(tsType)) return "boolean";
+ if (t.isTSObjectKeyword(tsType)) return "object";
+ if (t.isTSAnyKeyword(tsType)) return "any";
+
+ // 处理联合类型
+ if (t.isTSUnionType(tsType)) {
+ const types = tsType.types.map((type) => {
+ if (t.isTSLiteralType(type) && t.isStringLiteral(type.literal)) {
+ return `"${type.literal.value}"`;
+ }
+ return this.extractTSType(type);
+ });
+ return types.join(" | ");
+ }
+
+ // 处理字面量类型
+ if (t.isTSLiteralType(tsType)) {
+ if (t.isStringLiteral(tsType.literal)) {
+ return `"${tsType.literal.value}"`;
+ }
+ if (t.isNumericLiteral(tsType.literal)) {
+ return tsType.literal.value.toString();
+ }
+ if (t.isBooleanLiteral(tsType.literal)) {
+ return tsType.literal.value.toString();
+ }
+ }
+
+ // 处理类型引用
+ if (t.isTSTypeReference(tsType) && t.isIdentifier(tsType.typeName)) {
+ const typeName = tsType.typeName.name;
+
+ // 处理泛型类型,如 Array
+ if (tsType.typeParameters && tsType.typeParameters.params.length > 0) {
+ const typeArgs = tsType.typeParameters.params.map(param => this.extractTSType(param));
+ if (typeName === "Array") {
+ return `${typeArgs[0]}[]`;
+ }
+ return `${typeName}<${typeArgs.join(", ")}>`;
+ }
+
+ return typeName;
+ }
+
+ // 处理数组类型: T[]
+ if (t.isTSArrayType(tsType)) {
+ const elementType = this.extractTSType(tsType.elementType);
+ return `${elementType}[]`;
+ }
+
+ return "any";
+ }
+
+ /**
+ * 提取defineEmits中的事件定义
+ */
+ extractDefineEmits(node, result) {
+ // 处理类型化的emits: defineEmits<{ eventName: [type] }>()
+ if (node.typeParameters && node.typeParameters.params.length > 0) {
+ const typeParam = node.typeParameters.params[0];
+ if (t.isTSTypeLiteral(typeParam)) {
+ for (const member of typeParam.members) {
+ if (t.isTSPropertySignature(member)) {
+ let eventName = "";
+
+ // 处理字符串键名和标识符键名
+ if (t.isStringLiteral(member.key)) {
+ eventName = member.key.value;
+ } else if (t.isIdentifier(member.key)) {
+ eventName = member.key.name;
+ }
+
+ if (eventName && member.typeAnnotation) {
+ const eventType = this.extractEmitType(
+ member.typeAnnotation.typeAnnotation
+ );
+ result.emits[eventName] = eventType;
+ }
+ }
+ }
+ }
+ }
+
+ // 处理数组形式的emits: defineEmits(['event1', 'event2'])
+ else if (node.arguments.length > 0 && t.isArrayExpression(node.arguments[0])) {
+ const events = node.arguments[0].elements;
+ for (const event of events) {
+ if (t.isStringLiteral(event)) {
+ result.emits[event.value] = "any";
+ }
+ }
+ }
+ }
+
+ /**
+ * 提取emit事件的参数类型
+ */
+ extractEmitType(tsType) {
+ // 处理元组类型: [value: string]
+ if (t.isTSTupleType(tsType)) {
+ const elementTypes = tsType.elementTypes.map((elem) => {
+ if (t.isTSNamedTupleMember(elem)) {
+ // 处理命名元组成员: value: string
+ return `${elem.label.name}: ${this.extractTSType(elem.elementType)}`;
+ }
+ return this.extractTSType(elem);
+ });
+ return elementTypes.join(", ");
+ }
+
+ // 处理其他类型
+ return this.extractTSType(tsType);
+ }
+
+ /**
+ * 提取defineSlots中的插槽定义
+ */
+ extractDefineSlots(node, result) {
+ // 处理类型化的slots: defineSlots<{ slotName: { propName: type } }>()
+ if (node.typeParameters && node.typeParameters.params.length > 0) {
+ const typeParam = node.typeParameters.params[0];
+ if (t.isTSTypeLiteral(typeParam)) {
+ for (const member of typeParam.members) {
+ let slotName = "";
+
+ // 处理方法签名: slotName(props: { ... }): any
+ if (t.isTSMethodSignature(member)) {
+ if (t.isIdentifier(member.key)) {
+ slotName = member.key.name;
+ } else if (t.isStringLiteral(member.key)) {
+ slotName = member.key.value;
+ }
+
+ if (slotName && member.parameters && member.parameters.length > 0) {
+ const firstParam = member.parameters[0];
+ if (firstParam.typeAnnotation) {
+ const slotTypeInfo = this.extractSlotTypeWithDependencies(
+ firstParam.typeAnnotation.typeAnnotation
+ );
+ result.slots[slotName] = slotTypeInfo.type;
+
+ // 收集外部类型依赖
+ if (slotTypeInfo.externalTypes.length > 0) {
+ if (!result.slotExternalTypes) {
+ result.slotExternalTypes = new Set();
+ }
+ slotTypeInfo.externalTypes.forEach(type =>
+ result.slotExternalTypes.add(type)
+ );
+ }
+ }
+ }
+ }
+ // 处理属性签名: slotName: { propName: type }
+ else if (t.isTSPropertySignature(member)) {
+ // 处理字符串键名和标识符键名
+ if (t.isStringLiteral(member.key)) {
+ slotName = member.key.value;
+ } else if (t.isIdentifier(member.key)) {
+ slotName = member.key.name;
+ }
+
+ if (slotName && member.typeAnnotation) {
+ const slotTypeInfo = this.extractSlotTypeWithDependencies(
+ member.typeAnnotation.typeAnnotation
+ );
+ result.slots[slotName] = slotTypeInfo.type;
+
+ // 收集外部类型依赖
+ if (slotTypeInfo.externalTypes.length > 0) {
+ if (!result.slotExternalTypes) {
+ result.slotExternalTypes = new Set();
+ }
+ slotTypeInfo.externalTypes.forEach(type =>
+ result.slotExternalTypes.add(type)
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 提取插槽的参数类型
+ */
+ extractSlotType(tsType) {
+ // 处理对象类型: { item: string, index: number }
+ if (t.isTSTypeLiteral(tsType)) {
+ const props = [];
+ for (const member of tsType.members) {
+ if (t.isTSPropertySignature(member)) {
+ let propName = "";
+ let propType = "any";
+
+ // 获取属性名
+ if (t.isIdentifier(member.key)) {
+ propName = member.key.name;
+ } else if (t.isStringLiteral(member.key)) {
+ propName = member.key.value;
+ }
+
+ // 获取属性类型
+ if (member.typeAnnotation && member.typeAnnotation.typeAnnotation) {
+ propType = this.extractTSType(member.typeAnnotation.typeAnnotation);
+ }
+
+ if (propName) {
+ props.push(`${propName}: ${propType}`);
+ }
+ }
+ }
+ return props.length > 0 ? `{ ${props.join(", ")} }` : "{}";
+ }
+
+ // 处理其他类型
+ return this.extractTSType(tsType);
+ }
+
+ /**
+ * 提取插槽的参数类型,同时收集外部类型依赖
+ */
+ extractSlotTypeWithDependencies(tsType) {
+ const externalTypes = new Set();
+
+ const extractTypeWithDeps = (type) => {
+ // 处理对象类型: { item: string, index: number }
+ if (t.isTSTypeLiteral(type)) {
+ const props = [];
+ for (const member of type.members) {
+ if (t.isTSPropertySignature(member)) {
+ let propName = "";
+ let propType = "any";
+
+ // 获取属性名
+ if (t.isIdentifier(member.key)) {
+ propName = member.key.name;
+ } else if (t.isStringLiteral(member.key)) {
+ propName = member.key.value;
+ }
+
+ // 获取属性类型并收集外部依赖
+ if (member.typeAnnotation && member.typeAnnotation.typeAnnotation) {
+ const typeInfo = this.extractTSTypeWithDependencies(
+ member.typeAnnotation.typeAnnotation
+ );
+ propType = typeInfo.type;
+ // 收集外部类型依赖
+ typeInfo.externalTypes.forEach(t => externalTypes.add(t));
+ }
+
+ if (propName) {
+ props.push(`${propName}: ${propType}`);
+ }
+ }
+ }
+ return props.length > 0 ? `{ ${props.join(", ")} }` : "{}";
+ }
+
+ // 处理其他类型
+ const typeInfo = this.extractTSTypeWithDependencies(type);
+ typeInfo.externalTypes.forEach(t => externalTypes.add(t));
+ return typeInfo.type;
+ };
+
+ const slotType = extractTypeWithDeps(tsType);
+
+ return {
+ type: slotType,
+ externalTypes: Array.from(externalTypes)
+ };
+ }
+
+ /**
+ * 提取defineExpose中的导出定义
+ */
+ extractDefineExpose(node, result) {
+ if (node.arguments.length > 0 && t.isObjectExpression(node.arguments[0])) {
+ const exposeObj = node.arguments[0];
+ for (const prop of exposeObj.properties) {
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
+ result.expose[prop.key.name] = "any"; // 可以进一步分析类型
+ }
+ }
+ }
+ }
+
+ /**
+ * 提取类型别名声明(如PassThrough类型及其相关类型)
+ */
+ extractTypeAlias(node, result) {
+ if (t.isIdentifier(node.id)) {
+ const typeName = node.id.name;
+
+ // 提取PassThrough类型及其相关的嵌套类型
+ if (typeName === "PassThrough" || typeName.endsWith("PassThrough")) {
+ const typeDefinition = this.extractTSTypeDefinition(node.typeAnnotation);
+ result.passThroughTypes[typeName] = typeDefinition;
+ }
+ }
+ }
+
+ /**
+ * 提取TypeScript类型定义,同时收集外部类型依赖
+ */
+ extractTSTypeDefinition(tsType) {
+ if (t.isTSTypeLiteral(tsType)) {
+ const properties = {};
+ const externalTypes = new Set(); // 收集外部类型依赖
+
+ for (const member of tsType.members) {
+ if (t.isTSPropertySignature(member)) {
+ let propName = "";
+ let propType = "any";
+ let isOptional = false;
+
+ // 获取属性名
+ if (t.isIdentifier(member.key)) {
+ propName = member.key.name;
+ } else if (t.isStringLiteral(member.key)) {
+ propName = member.key.value;
+ }
+
+ // 检查是否可选
+ isOptional = !!member.optional;
+
+ // 获取属性类型,同时收集外部类型依赖
+ if (member.typeAnnotation && member.typeAnnotation.typeAnnotation) {
+ const typeInfo = this.extractTSTypeWithDependencies(
+ member.typeAnnotation.typeAnnotation
+ );
+ propType = typeInfo.type;
+ // 收集外部类型依赖
+ typeInfo.externalTypes.forEach((type) => externalTypes.add(type));
+ }
+
+ if (propName) {
+ properties[propName] = {
+ type: propType,
+ optional: isOptional
+ };
+ }
+ }
+ }
+
+ return {
+ properties,
+ externalTypes: Array.from(externalTypes)
+ };
+ }
+
+ return {
+ properties: {},
+ externalTypes: []
+ };
+ }
+
+ /**
+ * 提取TypeScript类型,同时收集外部类型依赖
+ */
+ extractTSTypeWithDependencies(tsType) {
+ const externalTypes = new Set();
+
+ const extractType = (type) => {
+ if (t.isTSStringKeyword(type)) return "string";
+ if (t.isTSNumberKeyword(type)) return "number";
+ if (t.isTSBooleanKeyword(type)) return "boolean";
+ if (t.isTSObjectKeyword(type)) return "object";
+ if (t.isTSAnyKeyword(type)) return "any";
+
+ // 处理联合类型
+ if (t.isTSUnionType(type)) {
+ const types = type.types.map((unionType) => {
+ if (t.isTSLiteralType(unionType) && t.isStringLiteral(unionType.literal)) {
+ return `"${unionType.literal.value}"`;
+ }
+ return extractType(unionType);
+ });
+ return types.join(" | ");
+ }
+
+ // 处理字面量类型
+ if (t.isTSLiteralType(type)) {
+ if (t.isStringLiteral(type.literal)) {
+ return `"${type.literal.value}"`;
+ }
+ if (t.isNumericLiteral(type.literal)) {
+ return type.literal.value.toString();
+ }
+ if (t.isBooleanLiteral(type.literal)) {
+ return type.literal.value.toString();
+ }
+ }
+
+ // 处理类型引用
+ if (t.isTSTypeReference(type) && t.isIdentifier(type.typeName)) {
+ const typeName = type.typeName.name;
+ // 检查是否为外部类型(不是基础类型)
+ if (
+ ![
+ "String",
+ "Number",
+ "Boolean",
+ "Object",
+ "Array",
+ "Function",
+ "Date"
+ ].includes(typeName)
+ ) {
+ externalTypes.add(typeName);
+ }
+ return typeName;
+ }
+
+ // 处理数组类型
+ if (t.isTSArrayType(type)) {
+ const elementType = extractType(type.elementType);
+ return `${elementType}[]`;
+ }
+
+ return "any";
+ };
+
+ const type = extractType(tsType);
+
+ return {
+ type,
+ externalTypes: Array.from(externalTypes)
+ };
+ }
+
+ /**
+ * 扫描指定目录下的所有uvue文件
+ * 只扫描与父目录同名的主组件文件,忽略辅助组件
+ */
+ scanUvueFiles(directory) {
+ const results = [];
+
+ function scanDir(dir) {
+ if (!fs.existsSync(dir)) return;
+
+ const items = fs.readdirSync(dir);
+
+ for (const item of items) {
+ const fullPath = path.join(dir, item);
+ const stat = fs.statSync(fullPath);
+
+ if (stat.isDirectory()) {
+ scanDir(fullPath);
+ } else if (item.endsWith(".uvue")) {
+ // 只包含与父目录同名的 .uvue 文件(主组件)
+ const parentDirName = path.basename(path.dirname(fullPath));
+ const fileNameWithoutExt = path.basename(item, ".uvue");
+
+ if (parentDirName === fileNameWithoutExt) {
+ results.push(fullPath);
+ }
+ }
+ }
+ }
+
+ scanDir(directory);
+ return results;
+ }
+
+ /**
+ * 生成TypeScript类型定义
+ */
+ generateTypeDefinitions(components) {
+ // 收集所有需要的类型导入
+ const allImports = this.collectAllImports(components);
+
+ // 收集所有组件的PassThrough类型导入
+ const passThroughImports = this.collectPassThroughImports(components);
+
+ let typeDefinitions = "";
+
+ // 生成import语句
+ if (allImports.length > 0) {
+ for (const importInfo of allImports) {
+ const importPath = this.resolveImportPath(importInfo.source);
+ if (importInfo.isTypeOnly) {
+ typeDefinitions += `import type { ${importInfo.types.join(
+ ", "
+ )} } from "${importPath}";\n`;
+ } else {
+ typeDefinitions += `import { type ${importInfo.types.join(
+ ", type "
+ )} } from "${importPath}";\n`;
+ }
+ }
+ typeDefinitions += "\n";
+ }
+
+ // 生成组件Props类型导入语句
+ if (passThroughImports.length > 0) {
+ for (const importInfo of passThroughImports) {
+ typeDefinitions += `import type { ${importInfo.types.join(", ")} } from "${importInfo.source}";\n`;
+ }
+ typeDefinitions += "\n";
+ }
+
+ // 不再在这里生成组件Props接口,而是从单独的props.ts文件导入
+
+ // 检查是否有插槽定义,如果有则导入 SlotsType
+ let hasSlotsDefinition = false;
+ for (const component of components) {
+ if (component && Object.keys(component.slots).length > 0) {
+ hasSlotsDefinition = true;
+ break;
+ }
+ }
+
+ // 不再需要导入 DefineProps,改用 import('vue').DefineComponent
+
+ // 生成全局组件声明
+ typeDefinitions += `export {};\n\n`;
+ typeDefinitions += `// 自动生成的组件全局类型声明\n`;
+ typeDefinitions += `declare module "vue" {\n`;
+ typeDefinitions += `\texport interface GlobalComponents {\n`;
+
+ for (const component of components) {
+ if (!component) continue;
+
+ const propsType = this.generatePropsTypeName(component.name);
+
+ // 使用参考 cl-list 的写法格式
+ typeDefinitions += `\t\t"${component.name}": (typeof import('./components/${component.name}/${component.name}.uvue')['default']) & import('vue').DefineComponent<${propsType}>;\n`;
+ }
+
+ typeDefinitions += `\t}\n`;
+ typeDefinitions += `}\n`;
+
+ return typeDefinitions;
+ }
+
+ /**
+ * 收集所有组件的类型导入(不包括组件自身的Props导入)
+ */
+ collectAllImports(components) {
+ const importMap = new Map();
+
+ for (const component of components) {
+ if (!component || !component.imports) continue;
+
+ for (const importInfo of component.imports) {
+ // 跳过组件自身的props文件导入,这些将在collectPassThroughImports中处理
+ if (importInfo.source.includes("props") || importInfo.source.includes("../cl-")) {
+ continue;
+ }
+
+ const key = importInfo.source;
+ if (importMap.has(key)) {
+ // 合并类型导入
+ const existing = importMap.get(key);
+ const allTypes = [...new Set([...existing.types, ...importInfo.types])];
+ importMap.set(key, {
+ source: importInfo.source,
+ types: allTypes,
+ isTypeOnly: existing.isTypeOnly && importInfo.isTypeOnly
+ });
+ } else {
+ importMap.set(key, { ...importInfo });
+ }
+ }
+ }
+
+ return Array.from(importMap.values());
+ }
+
+ /**
+ * 收集所有组件的Props类型导入
+ */
+ collectPassThroughImports(components) {
+ const propsImports = [];
+
+ for (const component of components) {
+ if (!component) continue;
+
+ const propsTypeName = this.generatePropsTypeName(component.name);
+ const componentPath = `./components/${component.name}/props`;
+
+ const typesToImport = [propsTypeName];
+
+ // 如果组件有PassThrough类型,也需要导入
+ if (component.passThroughTypes && Object.keys(component.passThroughTypes).length > 0) {
+ // 添加主要的PassThrough类型
+ if (component.passThroughTypes.PassThrough) {
+ const passThroughTypeName = this.generatePassThroughTypeName(component.name);
+ typesToImport.push(passThroughTypeName);
+ }
+
+ // 添加所有嵌套的PassThrough类型
+ for (const originalTypeName of Object.keys(component.passThroughTypes)) {
+ if (originalTypeName === "PassThrough") continue;
+
+ const nestedTypeName = this.generateNestedPassThroughTypeName(
+ component.name,
+ originalTypeName
+ );
+ typesToImport.push(nestedTypeName);
+ }
+ }
+
+ propsImports.push({
+ source: componentPath,
+ types: typesToImport
+ });
+ }
+
+ return propsImports;
+ }
+
+ /**
+ * 解析导入路径,将相对路径转换为从index.d.ts的相对路径
+ */
+ resolveImportPath(originalPath) {
+ // 原始路径是从组件文件的相对路径,比如 "../../types"
+ // 需要转换为从 index.d.ts 的相对路径,即 "./types"
+
+ if (originalPath.startsWith("../../types")) {
+ return "./types";
+ }
+
+ // 处理其他相对路径
+ if (originalPath.startsWith("../")) {
+ // 计算相对层级
+ const levels = (originalPath.match(/\.\.\//g) || []).length;
+ if (levels >= 2) {
+ // 减少两级,因为index.d.ts在uni_modules/cool-ui/目录下
+ const remaining = originalPath.replace(/\.\.\//g, "");
+ return `./${remaining}`;
+ }
+ }
+
+ return originalPath;
+ }
+
+ /**
+ * 生成Props接口
+ */
+ generatePropsInterface(component) {
+ const propsTypeName = this.generatePropsTypeName(component.name);
+
+ if (Object.keys(component.props).length === 0) {
+ return `export interface ${propsTypeName} {}`;
+ }
+
+ let propsInterface = `export interface ${propsTypeName} {\n`;
+
+ for (const [propName, propInfo] of Object.entries(component.props)) {
+ const optional = propInfo.required ? "" : "?";
+ let propType = propInfo.type;
+
+ // 如果是 pt 或 passThrough 属性,且存在对应的 PassThrough 类型定义,使用组件特定的 PassThrough 类型
+ if (
+ (propName === "pt" || propName === "passThrough") &&
+ component.passThroughTypes &&
+ component.passThroughTypes.PassThrough
+ ) {
+ propType = this.generatePassThroughTypeName(component.name);
+ }
+
+ propsInterface += `\t${propName}${optional}: ${propType};\n`;
+ }
+
+ propsInterface += `}`;
+ return propsInterface;
+ }
+
+ /**
+ * 生成Props类型名称
+ */
+ generatePropsTypeName(componentName) {
+ const pascalName = componentName
+ .split("-")
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
+ .join("");
+ return `${pascalName}Props`;
+ }
+
+ /**
+ * 生成PassThrough类型名称
+ */
+ generatePassThroughTypeName(componentName) {
+ const pascalName = componentName
+ .split("-")
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
+ .join("");
+ return `${pascalName}PassThrough`;
+ }
+
+ /**
+ * 生成嵌套PassThrough类型名称
+ */
+ generateNestedPassThroughTypeName(componentName, originalTypeName) {
+ const pascalName = componentName
+ .split("-")
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
+ .join("");
+
+ // 移除原类型名中的"PassThrough"后缀(如果存在)
+ const baseTypeName = originalTypeName.replace(/PassThrough$/, "");
+ return `${pascalName}${baseTypeName}PassThrough`;
+ }
+
+ /**
+ * 获取类型生成顺序(依赖关系排序)
+ */
+ getTypeGenerationOrder(passThroughTypes, componentName) {
+ const typeNames = Object.keys(passThroughTypes);
+
+ // 简单排序:先生成嵌套类型,再生成主类型
+ return typeNames
+ .filter((name) => name !== "PassThrough")
+ .concat(typeNames.filter((name) => name === "PassThrough"));
+ }
+
+ /**
+ * 替换类型引用中的嵌套类型为组件特定的类型名
+ */
+ replaceNestedTypeReferences(typeString, componentName, passThroughTypes) {
+ let result = typeString;
+
+ // 替换所有已知的嵌套类型引用
+ for (const originalTypeName of Object.keys(passThroughTypes)) {
+ if (originalTypeName === "PassThrough") continue;
+
+ const newTypeName = this.generateNestedPassThroughTypeName(
+ componentName,
+ originalTypeName
+ );
+
+ // 使用词边界来确保精确匹配
+ const regex = new RegExp(`\\b${originalTypeName}\\b`, "g");
+ result = result.replace(regex, newTypeName);
+ }
+
+ return result;
+ }
+
+ /**
+ * 生成Emits类型
+ */
+ generateEmitsType(emits) {
+ const emitEntries = Object.entries(emits).map(([name, type]) => {
+ return `"${name}": (${type}) => void`;
+ });
+ return `{ ${emitEntries.join("; ")} }`;
+ }
+
+ /**
+ * 生成Slots类型
+ */
+ generateSlotsType(slots) {
+ const slotEntries = Object.entries(slots).map(([name, type]) => {
+ // 将插槽参数类型转换为对象属性格式
+ // 从 "{ item: ClListItem }" 转换为 "{ item: ClListItem }"
+ const slotProps = type.replace(/props:\s*/, '');
+ return `${name}: ${slotProps}`;
+ });
+ return `{}, {}, {}, {}, {}, {}, SlotsType<{ ${slotEntries.join(", ")} }>`;
+ }
+
+ /**
+ * 为单个组件生成props.ts文件
+ */
+ generateComponentPropsFile(component) {
+ const componentDir = path.dirname(component.filePath);
+ const propsFilePath = path.join(componentDir, "props.ts");
+
+ let propsContent = "";
+
+ // 收集需要导入的类型
+ const imports = new Map();
+
+ // 添加组件原有的导入
+ if (component.imports && component.imports.length > 0) {
+ for (const importInfo of component.imports) {
+ const importPath = this.resolveImportPathForComponent(
+ importInfo.source,
+ componentDir
+ );
+ if (!imports.has(importPath)) {
+ imports.set(importPath, new Set());
+ }
+ importInfo.types.forEach((type) => imports.get(importPath).add(type));
+ }
+ }
+
+ // 收集PassThrough类型中的外部类型依赖
+ if (component.passThroughTypes && component.passThroughTypes.PassThrough) {
+ const passThroughDef = component.passThroughTypes.PassThrough;
+ if (passThroughDef.externalTypes && passThroughDef.externalTypes.length > 0) {
+ // 为PassThrough类型的外部依赖寻找对应的导入路径
+ const externalTypesToImport = this.mapExternalTypesToImports(
+ passThroughDef.externalTypes,
+ component.imports
+ );
+
+ for (const [importPath, types] of externalTypesToImport) {
+ const resolvedPath = this.resolveImportPathForComponent(
+ importPath,
+ componentDir
+ );
+ if (!imports.has(resolvedPath)) {
+ imports.set(resolvedPath, new Set());
+ }
+ types.forEach((type) => imports.get(resolvedPath).add(type));
+ }
+ }
+ }
+
+ // 收集slots中的外部类型依赖
+ if (component.slotExternalTypes && component.slotExternalTypes.size > 0) {
+ const slotExternalTypes = Array.from(component.slotExternalTypes);
+ const externalTypesToImport = this.mapExternalTypesToImports(
+ slotExternalTypes,
+ component.imports
+ );
+
+ for (const [importPath, types] of externalTypesToImport) {
+ const resolvedPath = this.resolveImportPathForComponent(
+ importPath,
+ componentDir
+ );
+ if (!imports.has(resolvedPath)) {
+ imports.set(resolvedPath, new Set());
+ }
+ types.forEach((type) => imports.get(resolvedPath).add(type));
+ }
+ }
+
+ // 生成import语句
+ if (imports.size > 0) {
+ for (const [importPath, types] of imports) {
+ const typeList = Array.from(types);
+ propsContent += `import type { ${typeList.join(", ")} } from "${importPath}";\n`;
+ }
+ propsContent += "\n";
+ }
+
+ // 生成PassThrough类型定义(如果存在)
+ if (component.passThroughTypes && Object.keys(component.passThroughTypes).length > 0) {
+ // 首先生成所有嵌套的PassThrough类型
+ const typeOrder = this.getTypeGenerationOrder(
+ component.passThroughTypes,
+ component.name
+ );
+
+ for (const originalTypeName of typeOrder) {
+ if (originalTypeName === "PassThrough") continue; // 主要类型最后处理
+
+ const typeDef = component.passThroughTypes[originalTypeName];
+ const newTypeName = this.generateNestedPassThroughTypeName(
+ component.name,
+ originalTypeName
+ );
+
+ propsContent += `export type ${newTypeName} = {\n`;
+
+ for (const [propName, propInfo] of Object.entries(typeDef.properties)) {
+ const optional = propInfo.optional ? "?" : "";
+ let propType = propInfo.type;
+
+ // 替换嵌套类型引用为组件特定的类型名
+ propType = this.replaceNestedTypeReferences(
+ propType,
+ component.name,
+ component.passThroughTypes
+ );
+
+ propsContent += `\t${propName}${optional}: ${propType};\n`;
+ }
+
+ propsContent += `};\n\n`;
+ }
+
+ // 最后生成主要的PassThrough类型
+ if (component.passThroughTypes.PassThrough) {
+ const passThroughTypeName = this.generatePassThroughTypeName(component.name);
+ const passThroughDef = component.passThroughTypes.PassThrough;
+
+ propsContent += `export type ${passThroughTypeName} = {\n`;
+
+ for (const [propName, propInfo] of Object.entries(passThroughDef.properties)) {
+ const optional = propInfo.optional ? "?" : "";
+ let propType = propInfo.type;
+
+ // 替换嵌套类型引用为组件特定的类型名
+ propType = this.replaceNestedTypeReferences(
+ propType,
+ component.name,
+ component.passThroughTypes
+ );
+
+ propsContent += `\t${propName}${optional}: ${propType};\n`;
+ }
+
+ propsContent += `};\n\n`;
+ }
+ }
+
+ // 生成props类型定义
+ const propsTypeName = this.generatePropsTypeName(component.name);
+
+ propsContent += `export type ${propsTypeName} = {\n`;
+
+ // 添加固定的 className 参数
+ propsContent += `\tclassName?: string;\n`;
+
+ // 添加组件定义的其他 props
+ for (const [propName, propInfo] of Object.entries(component.props)) {
+ const optional = propInfo.required ? "" : "?";
+ let propType = propInfo.type;
+
+ // 如果是 pt 或 passThrough 属性,且存在对应的 PassThrough 类型定义,使用组件特定的 PassThrough 类型
+ if (
+ (propName === "pt" || propName === "passThrough") &&
+ component.passThroughTypes &&
+ component.passThroughTypes.PassThrough
+ ) {
+ propType = this.generatePassThroughTypeName(component.name);
+ }
+
+ propsContent += `\t${propName}${optional}: ${propType};\n`;
+ }
+
+ propsContent += `};\n`;
+
+ // 写入文件
+ fs.writeFileSync(propsFilePath, propsContent, "utf-8");
+
+ return propsFilePath;
+ }
+
+ /**
+ * 将外部类型映射到它们的导入路径
+ */
+ mapExternalTypesToImports(externalTypes, componentImports) {
+ const typeToImportMap = new Map();
+
+ // 根据组件的导入信息建立类型到导入路径的映射
+ if (componentImports && componentImports.length > 0) {
+ for (const importInfo of componentImports) {
+ for (const type of importInfo.types) {
+ if (!typeToImportMap.has(importInfo.source)) {
+ typeToImportMap.set(importInfo.source, new Set());
+ }
+ typeToImportMap.get(importInfo.source).add(type);
+ }
+ }
+ }
+
+ const result = new Map();
+
+ // 将外部类型映射到对应的导入路径
+ for (const externalType of externalTypes) {
+ for (const [importPath, types] of typeToImportMap) {
+ if (types.has(externalType)) {
+ if (!result.has(importPath)) {
+ result.set(importPath, []);
+ }
+ result.get(importPath).push(externalType);
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * 解析组件目录的导入路径
+ */
+ resolveImportPathForComponent(originalPath, componentDir) {
+ // 如果是相对路径,保持相对路径
+ if (originalPath.startsWith("./") || originalPath.startsWith("../")) {
+ return originalPath;
+ }
+
+ // 如果是绝对路径(从项目根目录),转换为相对路径
+ if (originalPath.startsWith("@/")) {
+ // 计算从组件目录到项目根目录的相对路径
+ const relativePath = path.relative(componentDir, process.cwd());
+ return originalPath.replace("@/", relativePath + "/");
+ }
+
+ return originalPath;
+ }
+
+ /**
+ * 主要生成函数
+ */
+ async generate() {
+ try {
+ console.log("开始解析uvue文件类型定义...");
+
+ // 扫描组件目录
+ const componentsDir = path.join(__dirname, "../components");
+ const uvueFiles = this.scanUvueFiles(componentsDir);
+
+ console.log(`找到 ${uvueFiles.length} 个uvue文件`);
+
+ // 解析每个文件
+ const components = [];
+ for (const filePath of uvueFiles) {
+ console.log(`解析文件: ${path.relative(process.cwd(), filePath)}`);
+ const componentInfo = this.parseUvueFile(filePath);
+ if (componentInfo) {
+ components.push(componentInfo);
+ console.log(` - 组件名: ${componentInfo.name}`);
+ console.log(` - Props: ${Object.keys(componentInfo.props).length} 个`);
+ console.log(` - Emits: ${Object.keys(componentInfo.emits).length} 个`);
+ console.log(` - Slots: ${Object.keys(componentInfo.slots).length} 个`);
+ console.log(` - Expose: ${Object.keys(componentInfo.expose).length} 个`);
+ }
+ }
+
+ // 生成每个组件的单独props.ts文件
+ console.log("\n开始生成单独的props.ts文件...");
+ const generatedPropsFiles = [];
+ for (const component of components) {
+ if (component) {
+ try {
+ const propsFilePath = this.generateComponentPropsFile(component);
+ generatedPropsFiles.push(propsFilePath);
+ console.log(` - 已生成: ${path.relative(process.cwd(), propsFilePath)}`);
+ } catch (error) {
+ console.error(
+ `生成 ${component.name} 的props.ts文件时出错:`,
+ error.message
+ );
+ }
+ }
+ }
+
+ // 生成类型定义
+ const typeDefinitions = this.generateTypeDefinitions(components);
+
+ // 写入文件
+ const outputPath = path.join(__dirname, "../index.d.ts");
+
+ fs.writeFileSync(outputPath, typeDefinitions, "utf-8");
+
+ console.log(`\n类型定义已生成到:`);
+ console.log(` - ${path.relative(process.cwd(), outputPath)}`);
+ console.log(`总共处理了 ${components.length} 个组件`);
+ console.log(`生成了 ${generatedPropsFiles.length} 个props.ts文件`);
+ } catch (error) {
+ console.error("生成类型定义时出错:", error);
+ process.exit(1);
+ }
+ }
+}
+
+// 执行生成
+if (require.main === module) {
+ const parser = new UvueTypeParser();
+ parser.generate();
+}
+
+module.exports = UvueTypeParser;
diff --git a/cool-unix/uni_modules/cool-ui/types/component.d.ts b/cool-unix/uni_modules/cool-ui/types/component.d.ts
new file mode 100644
index 0000000..14e5ec7
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/types/component.d.ts
@@ -0,0 +1,245 @@
+declare type ComponentPublicInstance = any;
+
+declare type ClInputComponentPublicInstance = {
+ isFocus: boolean;
+ focus: () => void;
+ clear: () => void;
+};
+
+declare type ClTextareaComponentPublicInstance = {
+ isFocus: boolean;
+ focus: () => void;
+};
+
+declare type ClPopupComponentPublicInstance = {
+ isOpened: boolean;
+ isOpen: boolean;
+ open: () => void;
+ close: () => void;
+};
+
+declare type ClSelectComponentPublicInstance = {
+ open: (cb: ((value: any) => void) | null) => void;
+ close: () => void;
+};
+
+declare type ClSelectDateComponentPublicInstance = {
+ open: (cb: ((value: string) => void) | null) => void;
+ close: () => void;
+ setValue: (value: string) => void;
+ setValues: (values: string[]) => void;
+ clear: () => void;
+ setRange: (index: number) => void;
+ confirm: () => void;
+};
+
+declare type ClSelectTimeComponentPublicInstance = {
+ open: (cb: ((value: string) => void) | null) => void;
+ close: () => void;
+};
+
+declare type ClRowComponentPublicInstance = {
+ gutter: number;
+};
+
+declare type ClConfirmComponentPublicInstance = {
+ open: (options: {
+ title: string;
+ message: string;
+ confirmText?: string;
+ showConfirm?: boolean;
+ cancelText?: string;
+ showCancel?: boolean;
+ }) => void;
+ close: () => void;
+};
+
+declare type ClActionSheetComponentPublicInstance = {
+ open: (options: {
+ title?: string;
+ list: {
+ label: string;
+ icon?: string;
+ disabled?: boolean;
+ color?: string;
+ callback?: () => void;
+ }[];
+ cancelText?: string;
+ showCancel?: boolean;
+ }) => void;
+ close: () => void;
+};
+
+declare type ClToastComponentPublicInstance = {
+ open: (options: {
+ message: string;
+ duration?: number;
+ icon?: string;
+ position?: "top" | "center" | "bottom";
+ }) => void;
+ close: () => void;
+};
+
+declare type ClKeyboardNumberComponentPublicInstance = {
+ open: () => void;
+ close: () => void;
+};
+
+declare type ClKeyboardCarComponentPublicInstance = {
+ open: () => void;
+ close: () => void;
+};
+
+declare type ClKeyboardPasswordComponentPublicInstance = {
+ open: () => void;
+ close: () => void;
+};
+
+declare type ClPaginationComponentPublicInstance = {
+ prev: () => void;
+ next: () => void;
+};
+
+declare type ClCollapseComponentPublicInstance = {
+ show: () => void;
+ hide: () => void;
+ toggle: () => void;
+};
+
+declare type ClCountdownComponentPublicInstance = {
+ next: () => void;
+ start: () => void;
+ stop: () => void;
+ done: () => void;
+ isRunning: boolean;
+};
+
+declare type ClStickyComponentPublicInstance = {
+ getRect: () => void;
+};
+
+declare type ClListIndexComponentPublicInstance = {
+ scrollToIndex: (index: string) => void;
+};
+
+declare type ClListItemComponentPublicInstance = {
+ resetSwipe: () => void;
+ initSwipe: () => void;
+};
+
+declare type ClListViewComponentPublicInstance = {
+ data: ClListViewItem[];
+ stopRefresh: () => void;
+};
+
+declare type ClCascaderComponentPublicInstance = {
+ open: () => void;
+ close: () => void;
+ reset: () => void;
+ clear: () => void;
+};
+
+declare type ClWaterfallComponentPublicInstance = {
+ append: (data: UTSJSONObject[]) => Promise;
+ remove: (id: string | number) => void;
+ update: (id: string | number, data: UTSJSONObject) => void;
+ clear: () => void;
+};
+
+declare type ClQrcodeComponentPublicInstance = {
+ toPng: () => Promise;
+};
+
+declare type ClProgressCircleComponentPublicInstance = {
+ animate: (value: number) => void;
+};
+
+declare type ClSignComponentPublicInstance = {
+ clear: () => void;
+ toPng: () => Promise;
+};
+
+declare type ClCropperComponentPublicInstance = {
+ open: (url: string) => void;
+ close: () => void;
+ chooseImage: () => void;
+ toPng: () => Promise;
+};
+
+declare type ClFormComponentPublicInstance = {
+ labelPosition: "left" | "top" | "right";
+ labelWidth: string;
+ showAsterisk: boolean;
+ showMessage: boolean;
+ disabled: boolean;
+ data: UTSJSONObject;
+ errors: Map;
+ fields: Set;
+ addField: (prop: string, rules: ClFormRule[]) => void;
+ removeField: (prop: string) => void;
+ getValue: (prop: string) => any | null;
+ setError: (prop: string, error: string) => void;
+ getError: (prop: string) => string;
+ getErrors: () => Promise;
+ removeError: (prop: string) => void;
+ clearErrors: () => void;
+ getRule: (prop: string) => ClFormRule[];
+ setRule: (prop: string, rules: ClFormRule[]) => void;
+ removeRule: (prop: string) => void;
+ validateRule: (value: any | null, rule: ClFormRule) => string | null;
+ clearValidate: () => void;
+ validateField: (prop: string) => string | null;
+ validate: (callback: (valid: boolean, errors: ClFormValidateError[]) => void) => Promise;
+};
+
+declare type ClFormItemComponentPublicInstance = {
+ prop: string;
+ isError: boolean;
+};
+
+declare type ClPageComponentPublicInstance = {
+ scrollTop: number;
+ scrollTo: (top: number) => void;
+ scrollToTop: () => void;
+};
+
+declare type ClSlideVerifyComponentPublicInstance = {
+ init: () => void;
+ reset: () => void;
+};
+
+declare type ClTreeComponentPublicInstance = {
+ icon: string;
+ expandIcon: string;
+ checkable: boolean;
+ multiple: boolean;
+ checkStrictly: boolean;
+ clearChecked: () => void;
+ setChecked: (key: string | number, flag: boolean) => void;
+ setCheckedKeys: (keys: (string | number)[]) => void;
+ getCheckedKeys: () => (string | number)[];
+ getHalfCheckedKeys: () => (string | number)[];
+ setExpanded: (key: string | number, flag: boolean) => void;
+ setExpandedKeys: (keys: (string | number)[]) => void;
+ getExpandedKeys: () => (string | number)[];
+ expandAll: () => void;
+ collapseAll: () => void;
+};
+
+declare type ClCalendarComponentPublicInstance = {
+ open(cb: ((value: string | string[]) => void) | null = null): void;
+ close(): void;
+};
+
+declare type ClMarqueeComponentPublicInstance = {
+ play(): void;
+ pause(): void;
+ start(): void;
+ stop(): void;
+ reset(): void;
+};
+
+declare type ClReadMoreComponentPublicInstance = {
+ toggle(): void;
+ getContentHeight(): void;
+};
diff --git a/cool-unix/uni_modules/cool-ui/types/index.ts b/cool-unix/uni_modules/cool-ui/types/index.ts
new file mode 100644
index 0000000..3734a97
--- /dev/null
+++ b/cool-unix/uni_modules/cool-ui/types/index.ts
@@ -0,0 +1,239 @@
+export type Size = "small" | "normal" | "large";
+
+export type Type = "primary" | "success" | "warn" | "error" | "info";
+
+export type PassThroughProps = {
+ className?: string;
+};
+
+export type Justify = "start" | "center" | "end";
+
+export type ClInputType =
+ | "text"
+ | "number"
+ | "idcard"
+ | "digit"
+ | "tel"
+ | "safe-password"
+ | "nickname";
+
+export type ClTextType = "default" | "phone" | "name" | "amount" | "card" | "email";
+
+export type ClButtonType = "primary" | "success" | "warn" | "error" | "info" | "light" | "dark";
+
+export type ClRadioOption = {
+ label?: string;
+ value: string | number | boolean;
+ disabled?: boolean;
+};
+
+export type ClCheckboxOption = {
+ label?: string;
+ value: string | number | boolean;
+ disabled?: boolean;
+};
+
+export type ClSelectValue = string[] | number[] | number | string | null;
+
+export type ClSelectOption = {
+ label: string;
+ value: any;
+ children?: ClSelectOption[];
+};
+
+export type ClConfirmAction = "confirm" | "cancel" | "close";
+
+export type ClConfirmBeforeCloseEvent = {
+ close: () => void;
+ showLoading: () => void;
+ hideLoading: () => void;
+};
+
+export type ClConfirmOptions = {
+ title: string;
+ message: string;
+ callback?: (action: ClConfirmAction) => void;
+ beforeClose?: (action: ClConfirmAction, event: ClConfirmBeforeCloseEvent) => void;
+ confirmText?: string;
+ showConfirm?: boolean;
+ cancelText?: string;
+ showCancel?: boolean;
+ duration?: number;
+};
+
+export type ClActionSheetItem = {
+ label: string;
+ icon?: string;
+ disabled?: boolean;
+ color?: string;
+ callback?: () => void;
+};
+
+export type ClActionSheetOptions = {
+ list: ClActionSheetItem[];
+ title?: string;
+ description?: string;
+ cancelText?: string;
+ showCancel?: boolean;
+ maskClosable?: boolean;
+};
+
+export type ClToastPosition = "top" | "center" | "bottom";
+export type ClToastType = "success" | "warn" | "error" | "question" | "disabled" | "stop";
+
+export type ClToastOptions = {
+ type?: ClToastType;
+ icon?: string;
+ image?: string;
+ message: string;
+ position?: ClToastPosition;
+ duration?: number;
+ clear?: boolean;
+};
+
+export type ClTabsItem = {
+ label: string;
+ value: string | number;
+ disabled?: boolean;
+};
+
+export type ClListItem = {
+ label: string;
+ content?: string;
+ icon?: string;
+ arrow?: boolean;
+ hoverable?: boolean;
+ disabled?: boolean;
+};
+
+export type ClListViewItem = {
+ label?: string;
+ value?: any;
+ index?: string;
+ children?: ClListViewItem[];
+};
+
+export type ClListViewGroup = {
+ index: string;
+ children: ClListViewItem[];
+};
+
+export type ClListViewVirtualItem = {
+ key: string;
+ type: "header" | "item";
+ index: number;
+ top: number;
+ height: number;
+ data: ClListViewItem;
+};
+
+export type ClListViewRefresherStatus = "default" | "pulling" | "refreshing";
+
+export type ClCascaderOption = ClListViewItem;
+
+export type ClPopupDirection = "top" | "right" | "bottom" | "center" | "left";
+
+export type ClQrcodeMode = "rect" | "circular" | "line" | "rectSmall";
+
+export type ClUploadItem = {
+ uid: string;
+ preview: string;
+ url: string;
+ progress: number;
+};
+
+export type ClSelectDateShortcut = {
+ label: string;
+ value: string[];
+};
+
+// 表单规则类型
+export type ClFormRule = {
+ // 是否必填
+ required?: boolean;
+ // 错误信息
+ message?: string;
+ // 最小长度
+ min?: number;
+ // 最大长度
+ max?: number;
+ // 正则验证
+ pattern?: RegExp;
+ // 自定义验证函数
+ validator?: (value: any | null) => boolean | string;
+};
+
+export type ClFormValidateError = {
+ field: string;
+ message: string;
+};
+
+export type ClFormValidateResult = {
+ valid: boolean;
+ errors: ClFormValidateError[];
+};
+
+export type ClFormLabelPosition = "left" | "top" | "right";
+
+export type ClFilterItemType = "switch" | "sort" | "select";
+
+export type ClFilterItem = {
+ label: string;
+ value: any;
+ type: ClFilterItemType;
+ options?: ClSelectOption[];
+};
+
+export type ClTreeItem = {
+ id: string | number;
+ label: string;
+ disabled?: boolean;
+ children?: ClTreeItem[];
+ value?: UTSJSONObject;
+ isExpand?: boolean;
+ isChecked?: boolean;
+ isHalfChecked?: boolean;
+};
+
+export type ClTreeNodeInfo = {
+ node: ClTreeItem;
+ parent?: ClTreeItem;
+ index: number;
+};
+
+export type ClCalendarMode = "single" | "multiple" | "range";
+
+export type ClCalendarDateConfig = {
+ date: string;
+ topText?: string;
+ bottomText?: string;
+ disabled?: boolean;
+ color?: string;
+};
+
+export type ClMarqueeDirection = "horizontal" | "vertical";
+
+export type ClMarqueeItem = {
+ url: string;
+ originalIndex: number;
+};
+
+export type ClMarqueePassThrough = {
+ className?: string;
+ container?: PassThroughProps;
+ item?: PassThroughProps;
+ image?: PassThroughProps;
+};
+
+export type ClMarqueeProps = {
+ className?: string;
+ pt?: ClMarqueePassThrough;
+ list?: string[];
+ direction?: ClMarqueeDirection;
+ speed?: number;
+ pause?: boolean;
+ pauseOnHover?: boolean;
+ itemHeight?: number;
+ itemWidth?: number;
+ gap?: number;
+};
diff --git a/cool-unix/uni_modules/cool-vibrate/package.json b/cool-unix/uni_modules/cool-vibrate/package.json
new file mode 100644
index 0000000..d4729d1
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/package.json
@@ -0,0 +1,82 @@
+{
+ "id": "cool-vibrate",
+ "displayName": "cool-vibrate",
+ "version": "1.0.1",
+ "description": "cool-vibrate",
+ "keywords": [
+ "cool-vibrate"
+ ],
+ "repository": "",
+ "engines": {
+ "HBuilderX": "^3.9.0"
+ },
+ "dcloudext": {
+ "type": "uts",
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "",
+ "data": "",
+ "permissions": ""
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "u",
+ "aliyun": "u",
+ "alipay": "u"
+ },
+ "client": {
+ "Vue": {
+ "vue2": "u",
+ "vue3": "u"
+ },
+ "App": {
+ "app-android": "u",
+ "app-ios": "u"
+ },
+ "H5-mobile": {
+ "Safari": "u",
+ "Android Browser": "u",
+ "微信浏览器(Android)": "u",
+ "QQ浏览器(Android)": "u"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "u",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u",
+ "钉钉": "u",
+ "快手": "u",
+ "飞书": "u",
+ "京东": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
diff --git a/cool-unix/uni_modules/cool-vibrate/readme.md b/cool-unix/uni_modules/cool-vibrate/readme.md
new file mode 100644
index 0000000..7921923
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/readme.md
@@ -0,0 +1,17 @@
+# cool-vibrate
+
+### 兼容性
+
+| IOS | Andriod | WEB | 小程序 |
+| ---- | ------- | ---- | ------ |
+| 支持 | 支持 | 支持 | 支持 |
+
+### 开发文档
+
+调用:
+
+```ts
+import { vibrate } from "@/uni_modules/cool-vibrate";
+
+vibrate(1);
+```
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/app-android/AndroidManifest.xml b/cool-unix/uni_modules/cool-vibrate/utssdk/app-android/AndroidManifest.xml
new file mode 100644
index 0000000..a4146c9
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/app-android/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/app-android/config.json b/cool-unix/uni_modules/cool-vibrate/utssdk/app-android/config.json
new file mode 100644
index 0000000..db71d48
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/app-android/config.json
@@ -0,0 +1,4 @@
+{
+ "minSdkVersion": "19",
+ "targetSdkVersion": "34"
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/app-android/index.uts b/cool-unix/uni_modules/cool-vibrate/utssdk/app-android/index.uts
new file mode 100644
index 0000000..366b8d7
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/app-android/index.uts
@@ -0,0 +1,37 @@
+import Vibrator from "android.os.Vibrator";
+import VibratorManager from "android.os.VibratorManager";
+import VibrationEffect from "android.os.VibrationEffect";
+import Context from "android.content.Context";
+import Build from "android.os.Build";
+
+/**
+ * 震动
+ * @param {number} duration 震动时间单位ms
+ */
+export function vibrate(duration: number) {
+ try {
+ const context = UTSAndroid.getAppContext() as Context;
+ let vb: Vibrator | null = null;
+
+ // Android 12 (API 31) 及以上使用 VibratorManager
+ if (Build.VERSION.SDK_INT >= 31) {
+ const vibratorManager = context.getSystemService(
+ Context.VIBRATOR_MANAGER_SERVICE
+ ) as VibratorManager;
+ vb = vibratorManager.getDefaultVibrator();
+ }
+
+ if (vb != null && vb.hasVibrator()) {
+ // Android 8.0 (API 26) 及以上使用 VibrationEffect
+ if (Build.VERSION.SDK_INT >= 26) {
+ const effect = VibrationEffect.createOneShot(
+ duration.toLong(),
+ VibrationEffect.DEFAULT_AMPLITUDE
+ );
+ vb.vibrate(effect);
+ }
+ }
+ } catch (e) {
+ console.error("震动失败:", e);
+ }
+}
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/index.uts b/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/index.uts
new file mode 100644
index 0000000..55dda44
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/index.uts
@@ -0,0 +1,6 @@
+import { Vibrate } from "../interface.uts";
+import { VibrateNative } from "./vibrate.ets";
+
+export function vibrate(duration: number) {
+ VibrateNative.vibrate(duration);
+}
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/module.json5 b/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/module.json5
new file mode 100644
index 0000000..d6e15cf
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/module.json5
@@ -0,0 +1,13 @@
+{
+ "module": {
+ "requestPermissions": [
+ {
+ "name": "ohos.permission.VIBRATE",
+ "usedScene": {
+ "when": "inuse"
+ },
+ "reason": "$string:permission_VIBRATE_reason"
+ }
+ ]
+ }
+}
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/resources/base/element/string.json b/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/resources/base/element/string.json
new file mode 100644
index 0000000..40c3c45
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "permission_VIBRATE_reason",
+ "value": "需要振动权限来提供更好的触觉反馈体验"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/vibrate.ets b/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/vibrate.ets
new file mode 100644
index 0000000..4faa8b2
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/app-harmony/vibrate.ets
@@ -0,0 +1,43 @@
+import { vibrator } from '@kit.SensorServiceKit';
+import { BusinessError } from '@kit.BasicServicesKit';
+
+/**
+ * 原生振动控制类
+ * 用于控制设备振动,提供触觉反馈
+ */
+export class VibrateNative {
+ /**
+ * 使设备振动指定时长
+ * @param duration 振动持续时间(毫秒)
+ */
+ static vibrate(duration: number): void {
+ try {
+ // 调用系统振动API
+ vibrator.startVibration(
+ {
+ type: 'time', // 振动类型为时间模式
+ duration: duration // 振动持续时间
+ },
+ {
+ id: 0, // 振动任务ID
+ usage: 'alarm' // 振动场景类型,用于系统开关管控
+ },
+ (error: BusinessError) => {
+ // 错误处理回调
+ if (error) {
+ console.error(
+ `振动启动失败: 错误码 ${error.code}, 错误信息 ${error.message}`
+ );
+ return;
+ }
+ }
+ );
+ } catch (err) {
+ // 捕获意外错误
+ const error: BusinessError = err as BusinessError;
+ console.error(
+ `发生意外错误: 错误码 ${error.code}, 错误信息 ${error.message}`
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/app-ios/PrivacyInfo.xcprivacy b/cool-unix/uni_modules/cool-vibrate/utssdk/app-ios/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000..5397adc
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/app-ios/PrivacyInfo.xcprivacy
@@ -0,0 +1,14 @@
+
+
+
+
+ NSPrivacyAccessedAPITypes
+
+ NSPrivacyCollectedDataTypes
+
+ NSPrivacyTracking
+
+ NSPrivacyTrackingDomains
+
+
+
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/app-ios/config.json b/cool-unix/uni_modules/cool-vibrate/utssdk/app-ios/config.json
new file mode 100644
index 0000000..721b81e
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/app-ios/config.json
@@ -0,0 +1,3 @@
+{
+ "deploymentTarget": "9"
+}
\ No newline at end of file
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/app-ios/index.uts b/cool-unix/uni_modules/cool-vibrate/utssdk/app-ios/index.uts
new file mode 100644
index 0000000..1d42ef6
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/app-ios/index.uts
@@ -0,0 +1,42 @@
+import * as AudioToolbox from "AudioToolbox";
+import * as UIKit from "UIKit";
+import { Thread } from "Foundation";
+
+/**
+ * 触发设备震动
+ * @param duration 震动持续时间,单位:毫秒(ms),仅在iOS 13.0+有效
+ */
+export function vibrate(duration: number) {
+ // 参数验证:确保duration为正数
+ if (duration < 0) {
+ duration = 0;
+ }
+
+ // 检查iOS版本,决定使用哪种震动方式
+ if (UTSiOS.available("iOS 13.0, *")) {
+ // 创建中等强度的触觉反馈生成器
+ const generator = new UIKit.UIImpactFeedbackGenerator(
+ (style = UIKit.UIImpactFeedbackGenerator.FeedbackStyle.medium)
+ );
+
+ // 准备生成器,提高首次触发的响应速度
+ generator.prepare();
+
+ // 记录开始时间
+ const startTime = new Date().getTime();
+ const endTime = startTime + duration;
+
+ // 循环产生震动效果,直到达到指定时长
+ while (new Date().getTime() < endTime) {
+ // 触发触觉反馈,强度为0.5(中等强度)
+ generator.impactOccurred((intensity = 0.5));
+
+ // 暂停100毫秒,避免过于频繁的震动
+ Thread.sleep((forTimeInterval = 0.1));
+ }
+ } else {
+ // iOS 13.0以下版本:使用AudioToolbox播放系统震动音效
+ // 注意:此方式无法控制震动时长,duration参数将被忽略
+ AudioToolbox.AudioServicesPlayAlertSound(AudioToolbox.kSystemSoundID_Vibrate);
+ }
+}
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/interface.uts b/cool-unix/uni_modules/cool-vibrate/utssdk/interface.uts
new file mode 100644
index 0000000..19b7e85
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/interface.uts
@@ -0,0 +1 @@
+export type Vibrate = (duration: number) => void;
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/mp-weixin/index.uts b/cool-unix/uni_modules/cool-vibrate/utssdk/mp-weixin/index.uts
new file mode 100644
index 0000000..124d5ad
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/mp-weixin/index.uts
@@ -0,0 +1,13 @@
+/**
+ * 震动
+ * @param {number} duration 震动时间单位ms,ios微信失效
+ */
+export function vibrate(duration: number) {
+ wx.vibrateShort({
+ type: "medium",
+ success() {},
+ fail(error) {
+ console.error("微信:震动失败");
+ }
+ });
+}
diff --git a/cool-unix/uni_modules/cool-vibrate/utssdk/web/index.uts b/cool-unix/uni_modules/cool-vibrate/utssdk/web/index.uts
new file mode 100644
index 0000000..b276b52
--- /dev/null
+++ b/cool-unix/uni_modules/cool-vibrate/utssdk/web/index.uts
@@ -0,0 +1,11 @@
+/**
+ * 震动
+ * @param {number} duration 震动时间单位ms,ios微信失效
+ */
+export function vibrate(duration: number) {
+ try {
+ navigator.vibrate(duration);
+ } catch (error) {
+ console.error("WEB震动失败:", error);
+ }
+}
diff --git a/cool-unix/vite.config.ts b/cool-unix/vite.config.ts
new file mode 100644
index 0000000..92bb427
--- /dev/null
+++ b/cool-unix/vite.config.ts
@@ -0,0 +1,36 @@
+import { defineConfig } from "vite";
+import { cool } from "@cool-vue/vite-plugin";
+import { proxy } from "./config/proxy";
+import tailwindcss from "tailwindcss";
+import { join } from "node:path";
+import uni from "@dcloudio/vite-plugin-uni";
+
+const resolve = (dir: string) => join(__dirname, dir);
+
+for (const i in proxy) {
+ proxy[`/${i}/`] = proxy[i];
+}
+
+export default defineConfig({
+ plugins: [
+ uni(),
+ cool({
+ type: "uniapp-x",
+ proxy,
+ tailwind: {
+ enable: true
+ }
+ })
+ ],
+
+ server: {
+ port: 9900,
+ proxy
+ },
+
+ css: {
+ postcss: {
+ plugins: [tailwindcss({ config: resolve("./tailwind.config.ts") })]
+ }
+ }
+});