diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fee7f41 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +assets diff --git a/cool-admin-java/cool-admin.iml b/cool-admin-java/cool-admin.iml new file mode 100644 index 0000000..d001a39 --- /dev/null +++ b/cool-admin-java/cool-admin.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/cache/CoolCache.java b/cool-admin-java/src/main/java/com/cool/core/cache/CoolCache.java index aa6d381..b16ce48 100644 --- a/cool-admin-java/src/main/java/com/cool/core/cache/CoolCache.java +++ b/cool-admin-java/src/main/java/com/cool/core/cache/CoolCache.java @@ -5,8 +5,6 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import com.cool.core.util.ConvertUtil; import jakarta.annotation.PostConstruct; -import java.time.Duration; -import java.util.Arrays; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.cache.CacheType; @@ -17,6 +15,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.stereotype.Component; +import java.time.Duration; +import java.util.Arrays; + /** * 缓存工具类 */ @@ -174,7 +175,7 @@ public class CoolCache { cache.put(key, value); } else if (type.equalsIgnoreCase(CacheType.REDIS.name())) { redisCache.put(cacheName, key.getBytes(), ObjectUtil.serialize(value), - java.time.Duration.ofSeconds(ttl)); + Duration.ofSeconds(ttl)); } } } diff --git a/cool-admin-java/src/main/java/com/cool/core/plugin/event/PluginActionEnum.java b/cool-admin-java/src/main/java/com/cool/core/plugin/event/PluginActionEnum.java new file mode 100644 index 0000000..064b807 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/plugin/event/PluginActionEnum.java @@ -0,0 +1,7 @@ +package com.cool.core.plugin.event; + +public enum PluginActionEnum { + INSTALL, + UNINSTALL, + UPDATE, +} diff --git a/cool-admin-java/src/main/resources/banner.txt b/cool-admin-java/src/main/resources/banner.txt index 0fce0d9..74fdf6d 100644 --- a/cool-admin-java/src/main/resources/banner.txt +++ b/cool-admin-java/src/main/resources/banner.txt @@ -1,8 +1,8 @@ -✨🌈✨[cool-admin-java-plus](https://gitee.com/hlc4417/cool-admin-java-plus)✨🌈✨ +✨🌈✨===================================================================================✨🌈✨ ______ ___ ___ _____ _ ______ ____ ____ _____ ____ _____ .' ___ | .' `. .' `.|_ _| V8.x / \ |_ _ `.|_ \ / _||_ _||_ \|_ _| / .' \_|/ .-. \/ .-. \ | | ______ / _ \ | | `. \ | \/ | | | | \ | | | | | | | || | | | | | _|______|/ ___ \ | | | | | |\ /| | | | | |\ \| | \ `.___.'\\ `-' /\ `-' /_| |__/ | _/ / \ \_ _| |_.' /_| |_\/_| |_ _| |_ _| |_\ |_ `.____ .' `.___.' `.___.'|________| |____| |____||______.'|_____||_____||_____||_____|\____| -:: https://java.cool-admin.com :: \ No newline at end of file +✨🌈✨===================================================================================✨🌈✨ \ No newline at end of file diff --git a/cool-admin-vue/packages/crud/.gitignore b/cool-admin-vue/packages/crud/.gitignore new file mode 100644 index 0000000..403adbc --- /dev/null +++ b/cool-admin-vue/packages/crud/.gitignore @@ -0,0 +1,23 @@ +.DS_Store +node_modules +/dist + + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/cool-admin-vue/packages/crud/.prettierrc b/cool-admin-vue/packages/crud/.prettierrc new file mode 100644 index 0000000..b82b0c6 --- /dev/null +++ b/cool-admin-vue/packages/crud/.prettierrc @@ -0,0 +1,9 @@ +{ + "tabWidth": 4, + "useTabs": true, + "semi": true, + "jsxBracketSameLine": true, + "singleQuote": false, + "printWidth": 100, + "trailingComma": "none" +} diff --git a/cool-admin-vue/packages/crud/README.md b/cool-admin-vue/packages/crud/README.md new file mode 100644 index 0000000..9500cde --- /dev/null +++ b/cool-admin-vue/packages/crud/README.md @@ -0,0 +1,33 @@ +# 介绍 + +**cool-admin for vue**是基于[Vue.js](https://v3.cn.vuejs.org)开发。 + +[cool-admin 官方文档](https://cool-js.com/) + +尝试 `cool-admin` 最简单的方法就是查看文档及运行示例。 + + + +[Ai极速编码 🔥 在线体验](https://show.cool-admin.com/helper/ai-code) + + + +## 代码仓库 + +**cool-admin for vue** 是开源免费的,遵循[MIT](https://baike.baidu.com/item/MIT/10772952)开源协议,意味着您无需支付任何费用,也无需授权,即可将它应用到您的产品中。 + +开源免费,并不意味着您可以将 cool-admin 应用到非法的领域,比如涉及赌博,暴力等方面。如因此产生纠纷等法律问题,`cool-admin`不承担任何责任。 + +[https://github.com/cool-team-official/cool-admin-vue](https://github.com/cool-team-official/cool-admin-vue) + +```shell +git clone https://github.com/cool-team-official/cool-admin-vue.git +``` + +## 技术选型 + +- [Vue.js](https://v3.cn.vuejs.org),基础框架; +- [VueRouter](https://router.vuejs.org),Vue.js 官方路由; +- [Pinia](https://pinia.vuejs.org),轻量级状态管理库; +- [ElementPlus](https://element-plus.gitee.io/zh-CN),桌面端组件库; +- [Vite](https://vitejs.cn),构建工具; diff --git a/cool-admin-vue/packages/crud/index.d.ts b/cool-admin-vue/packages/crud/index.d.ts new file mode 100644 index 0000000..2d403ac --- /dev/null +++ b/cool-admin-vue/packages/crud/index.d.ts @@ -0,0 +1,811 @@ +// vue +declare namespace Vue { + interface Ref { + value: T; + } + + type Emit = (name: any, ...args: any[]) => void; +} + +// element-plus +declare namespace ElementPlus { + type Size = "large" | "default" | "small"; + type Align = "left" | "center" | "right"; + + interface FormProps { + inline?: boolean; + labelPosition?: "left" | "right" | "top"; + labelWidth?: string | number; + labelSuffix?: string; + hideRequiredAsterisk?: boolean; + showMessage?: boolean; + inlineMessage?: boolean; + statusIcon?: boolean; + validateOnRuleChange?: boolean; + size?: Size; + disabled?: boolean; + [key: string]: any; + } +} + +// mitt +declare interface Mitt { + on(name: string, callback: (data: any) => void): void; + off(name: string, callback: (data: any) => void): void; + emit(name: string, data?: any): void; +} + +// emitter +declare interface EmitterItem { + name: string; + callback(data: any, events: { refresh(params: any): void; crudList: ClCrud.Ref[] }): void; +} + +declare interface Emitter { + list: EmitterItem[]; + init(events: any): void; + on(name: string, callback: (data: any) => void): void; + emit(name: string, data?: any): void; +} + +// 方法 +declare type fn = () => void; + +// 对象 +declare type obj = { + [key: string]: any; +}; + +// 全部可选 +declare type DeepPartial = T extends Function + ? T + : T extends object + ? { [P in keyof T]?: DeepPartial } + : T; + +// 合并 +declare type Merge = Omit & B; + +// 移除 [key] +declare type RemoveIndex = { + [P in keyof T as string extends P ? never : number extends P ? never : P]: T[P]; +}; + +// 任用列表 +declare type List = Array | (() => DeepPartial)>; + +// 获取keys +declare type PropKey = keyof RemoveIndex | (string & {}); + +// 任意字符串 +declare type AnyString = string & {}; + +// 类型或者 Ref 泛型 +declare type RefData = T | Vue.Ref; + +// browser +declare type Browser = { + screen: string; + isMini: boolean; +}; + +// 字典选项 +declare type DictOptions = { + label?: string; + value?: any; + color?: string; + type?: string; + [key: string]: any; +}[]; + +// render +declare namespace Render { + type OpButton = + | `slot-${string}` + | { + label: string; + type?: string; + hidden?: boolean; + onClick(options: { scope: obj }): void; + [key: string]: any; + }; + + interface Props { + onChange?(value: any): void; + [key: string]: any; + } + + interface Component { + name?: string; + options?: RefData; + props?: RefData; + style?: obj; + slots?: { + [key: string]: (data?: any) => any; + }; + vm?: any; + [key: string]: any; + } +} + +// crud +declare namespace ClCrud { + declare interface Field { + comment: string; + source: string; + propertyName: string; + type: string; + dict: string | string[]; + nullable: boolean; + } + + interface Label { + op: string; + add: string; + delete: string; + multiDelete: string; + update: string; + refresh: string; + info: string; + search: string; + reset: string; + clear: string; + save: string; + close: string; + confirm: string; + advSearch: string; + searchKey: string; + placeholder: string; + placeholderSelect: string; + tips: string; + saveSuccess: string; + deleteSuccess: string; + deleteConfirm: string; + empty: string; + desc: string; + asc: string; + select: string; + deselect: string; + seeMore: string; + hideContent: string; + nonEmpty: string; + collapse: string; + expand: string; + [key: string]: string; + } + + interface Dict { + primaryId: string; + api: { + list: string; + add: string; + update: string; + delete: string; + info: string; + page: string; + }; + pagination: { + page: string; + size: string; + }; + search: { + keyWord: string; + query: string; + }; + sort: { + order: string; + prop: string; + }; + label: Label; + } + + interface Permission { + page?: boolean; + list?: boolean; + add?: boolean; + delete?: boolean; + update?: boolean; + info?: boolean; + [key: string]: any; + } + + interface Params { + page: { + page?: number; + size?: number; + [key: string]: any; + }; + list: obj; + add: obj; + delete: { + ids?: any[]; + [key: string]: any; + }; + update: { + id?: any; + [key: string]: any; + }; + info: { + id?: any; + [key: string]: any; + }; + } + + interface Response { + page: { + list: any[]; + pagination: { + total: number; + page: number; + size: number; + [key: string]: any; + }; + [key: string]: any; + }; + list: any[]; + add: any; + update: any; + info: any; + delete: any; + } + + interface Service { + api: { + page(params?: Params["page"]): Promise; + list(params?: Params["list"]): Promise; + add(params?: Params["add"]): Promise; + update(params?: Params["update"]): Promise; + info(params?: Params["info"]): Promise; + delete(params?: Params["delete"]): Promise; + permission: Permission; + search: { + fieldEq: Field[]; + fieldLike: Field[]; + keyWordLikeFields: Field[]; + }; + [key: string]: any; + }; + } + + interface Config { + name: string; + service: Service["api"]; + permission: Permission; + dict: Dict; + onRefresh( + params: obj, + event: { + done: fn; + next: Service["api"]["page"]; + render: (data: any | any[], pagination?: Response["page"]["pagination"]) => void; + } + ): void; + onDelete( + selection: obj[], + event: { + next: Service["api"]["delete"]; + } + ): void; + } + + interface Ref { + "cl-table": ClTable.Ref; + "cl-upsert": ClUpsert.Ref; + id: number; + mitt: Mitt; + name: string; + routePath: string; + permission: Permission; + dict: Dict; + service: Service["api"]; + loading: boolean; + params: obj; + selection: obj[]; + set(key: "dict" | "style" | "service" | "permission", value: any): void; + done(): void; + getParams(): obj; + setParams(data: obj): void; + getPermission(key?: string): boolean; + rowInfo(data: obj): void; + rowAdd(): void; + rowEdit(data: obj): void; + rowAppend(data?: obj): void; + rowClose(): void; + rowDelete(...selection: obj[]): void; + proxy(name: string, data?: any[]): any; + paramsReplace(params: obj): obj; + refresh: Service["api"]["page"]; + [key: string]: any; + } + + interface Options extends DeepPartial { + service?: any; + } +} + +declare namespace ClTable { + type OpButton = Array<"info" | "edit" | "delete" | AnyString | Render.OpButton>; + + type ColumnType = "index" | "selection" | "expand" | "op" | AnyString; + + interface Column { + type: ColumnType; + hidden: RefData; + component: Render.Component; + search: { + isInput: boolean; + value: any; + icon: () => any; + refreshOnChange: boolean; + component: Render.Component; + }; + dict: RefData; + dictFormatter: (values: DictOptions) => string; + dictColor: boolean; + dictSeparator: string; + dictAllLevels: boolean; + buttons: OpButton | ((options: { scope: T }) => OpButton); + align: ElementPlus.Align; + label: any; + renderLabel: (options: { column: any; $index: number }) => any; + className: string; + prop: PropKey; + orderNum: number; + width: RefData; + minWidth: RefData; + renderHeader: (options: { column: any; $index: number }) => any; + sortable: boolean | "desc" | "descending" | "ascending" | "asc" | "custom"; + sortMethod: fn; + sortBy: string | ((row: T, index: number) => any) | any[]; + resizable: boolean; + columnKey: string; + headerAlign: ElementPlus.Align; + showOverflowTooltip: boolean; + fixed: boolean | string; + render: (row: T, column: any, value: any, index: number) => any; + formatter: (row: T, column: any, value: any, index: number) => any; + selectable: (row: T, index: number) => boolean; + reserveSelection: boolean; + filterMethod: fn; + filteredValue: unknown[]; + filters: unknown[]; + filterPlacement: string; + filterMultiple: boolean; + index: ((index: number) => number) | number; + sortOrders: unknown[]; + children: Column[]; + [key: string]: any; + } + + type ContextMenu = Array< + | ClContextMenu.Item + | ((row: obj, column: obj, event: PointerEvent) => ClContextMenu.Item) + | "refresh" + | "check" + | "update" + | "edit" + | "delete" + | "info" + | "order-desc" + | "order-asc" + >; + + type Plugin = (options: { exposed: Ref }) => void; + + interface Config { + columns: Column[]; + autoHeight: boolean; + height: any; + contextMenu: ContextMenu; + defaultSort: { + prop: string; + order: "descending" | "ascending"; + }; + sortRefresh: boolean; + emptyText: string; + rowKey: string; + on?: { + [key: string]: (...args: any[]) => void; + }; + props?: { + [key: string]: any; + }; + plugins?: Plugin[]; + onRowContextmenu?(row: T, column: any, event: any): void; + } + + interface Ref { + Table: any; + config: obj; + selection: T[]; + data: T[]; + columns: Column[]; + reBuild(cb?: fn): void; + calcMaxHeight(): void; + setData(data: T[]): void; + setColumns(columns: Column[]): void; + showColumn(props: PropKey | PropKey[], status?: boolean): void; + hideColumn(props: PropKey | PropKey[]): void; + changeSort(prop: PropKey, order: string): void; + clearSelection(): void; + getSelectionRows(): any[]; + toggleRowSelection(row: T, selected?: boolean): void; + toggleAllSelection(): void; + toggleRowExpansion(row: T, expanded?: boolean): void; + setCurrentRow(row: T): void; + clearSort(): void; + clearFilter(columnKeys: PropKey[]): void; + doLayout(): void; + sort(prop: PropKey, order: string): void; + scrollTo(position: { top?: number; left?: number }): void; + setScrollTop(top: number): void; + setScrollLeft(left: number): void; + updateKeyChildren(key: string, children: any[]): void; + } + + interface Options extends DeepPartial> { + columns?: List>; + } +} + +declare namespace ClFormTabs { + type labels = { + label: string; + value: string; + name?: string; + icon?: any; + lazy?: boolean; + [key: string]: any; + }[]; +} + +declare namespace ClForm { + type CloseAction = "close" | "save" | AnyString; + + interface Rule { + type?: + | "string" + | "number" + | "boolean" + | "method" + | "regexp" + | "integer" + | "float" + | "array" + | "object" + | "enum" + | "date" + | "url" + | "hex" + | "email" + | "any"; + required?: boolean; + message?: string; + min?: number; + max?: number; + trigger?: any; + validator?(rule: any, value: any, callback: (error?: Error) => void): void; + [key: string]: any; + } + + interface Hook { + Fn: (value: any, options: { form: obj; prop: string; method: "submit" | "bind" }) => any; + Key: + | "number" + | "string" + | "split" + | "join" + | "boolean" + | "booleanNumber" + | "datetimeRange" + | "splitJoin" + | "json" + | "empty" + | AnyString; + Pipe: Hook["Key"] | Hook["Fn"]; + Event: { + bind?: Hook["Pipe"] | Hook["Pipe"][]; + submit?: Hook["Pipe"] | Hook["Pipe"][]; + reset?: (prop: string) => string[]; + }; + } + + interface Item { + type?: "tabs"; + prop?: PropKey; + props?: { + labels?: ClFormTabs.labels; + justify?: "left" | "center" | "right"; + color?: string; + mergeProp?: boolean; + labelWidth?: string; + error?: string; + showMessage?: boolean; + inlineMessage?: boolean; + size?: "medium" | "default" | "small"; + [key: string]: any; + }; + span?: number; + col?: { + span: number; + offset: number; + push: number; + pull: number; + xs: any; + sm: any; + md: any; + lg: any; + xl: any; + tag: string; + }; + group?: string; + collapse?: boolean; + value?: any; + label?: string; + renderLabel?: any; + flex?: boolean; + hook?: Hook["Event"] | Hook["Key"]; + hidden?: boolean | ((options: { scope: obj }) => boolean); + prepend?: Render.Component; + component?: Render.Component; + append?: Render.Component; + rules?: Rule | Rule[]; + required?: boolean; + children?: Item[]; + [key: string]: any; + } + + interface Config { + title?: any; + height?: any; + width?: any; + props: ElementPlus.FormProps; + items: Item[]; + form: obj; + isReset?: boolean; + on?: { + open?(data: T): void; + close?(action: CloseAction, done: fn): void; + submit?(data: T, event: { close: fn; done: fn }): void; + change?(data: T, prop: string): void; + }; + op: { + hidden?: boolean; + saveButtonText?: string; + closeButtonText?: string; + justify?: "flex-start" | "center" | "flex-end"; + buttons?: Array; + }; + dialog: { + title?: any; + height?: string; + width?: string; + hideHeader?: boolean; + controls?: Array<"fullscreen" | "close" | AnyString>; + [key: string]: any; + }; + [key: string]: any; + } + + type Plugin = (options: { + exposed: Ref; + onOpen(cb: () => void): void; + onClose(cb: () => void): void; + onSubmit(cb: (data: obj) => obj): void; + }) => void; + + type Items = List>; + + interface Ref { + Form: any; + form: T; + config: { + items: Item[]; + [key: string]: any; + }; + open(options: Options, plugins?: Plugin[]): void; + close(action?: CloseAction): void; + done(): void; + clear(): void; + reset(): void; + showLoading(): void; + hideLoading(): void; + setDisabled(flag?: boolean): void; + invokeData(data: any): void; + setData(prop: string, value: any): void; + bindForm(data: obj): void; + getForm(prop?: string): any; + setForm(prop: string, value: any): void; + setOptions(prop: string, list: DictOptions): void; + setProps(prop: string, value: any): void; + setConfig(path: string, value: any): void; + showItem(props: string[] | string): void; + hideItem(props: string[] | string): void; + toggleItem(prop: string, flag?: boolean): void; + resetFields(): void; + clearValidate(props?: string[] | string): void; + validateField( + props?: string[] | string, + callback?: (isValid: boolean, invalidFields: any[]) => void + ): Promise; + validate(callback: (isValid: boolean, invalidFields: any[]) => void): Promise; + changeTab(value: any, valid?: boolean): Promise; + setTitle(value: string): void; + submit(cb?: (data: obj) => void): void; + Tabs: { + active: RefData; + list: ClFormTabs.labels; + change(value: any, valid?: boolean): Promise; + [key: string]: any; + }; + [key: string]: any; + } + + interface Options extends DeepPartial { + items?: Items; + } +} + +declare namespace ClUpsert { + interface Config { + sync: boolean; + items: ClForm.Item[]; + props: ClForm.Config["props"]; + op: ClForm.Config["op"]; + dialog: ClForm.Config["dialog"]; + onOpen?(): void; + onOpened?(data: T): void; + onClose?(action: ClForm.CloseAction, done: fn): void; + onClosed?(): void; + onInfo?( + data: T, + event: { close: fn; done(data: T): void; next: ClCrud.Service["api"]["info"] } + ): void; + onSubmit?( + data: T, + event: { close: fn; done: fn; next: ClCrud.Service["api"]["update"] } + ): void; + plugins?: ClForm.Plugin[]; + } + + interface Ref extends ClForm.Ref { + mode: "add" | "update" | "info" | AnyString; + } + + interface Options extends DeepPartial> { + items?: ClForm.Items; + } +} + +declare namespace ClAdvSearch { + interface Config { + items?: ClForm.Item[]; + title?: string; + size?: string | number; + op?: ("clear" | "reset" | "close" | "search" | `slot-${string}`)[]; + onSearch?(data: T, options: { next: ClCrud.Service["api"]["page"]; close(): void }): void; + } + + interface Ref extends ClForm.Ref {} + + interface Options extends DeepPartial> { + items?: ClForm.Items; + } +} + +declare namespace ClSearch { + type Plugin = (options: { exposed: Ref }) => void; + + interface Config { + inline?: boolean; + items?: ClForm.Item[]; + data?: T; + props?: ElementPlus.FormProps; + resetBtn?: boolean; + collapse?: boolean; + Form?: ClForm.Ref; + onChange?(data: T, prop: string): void; + onLoad?(data: T): void; + onSearch?(data: T, options: { next: ClCrud.Service["api"]["page"] }): void; + plugins?: Plugin[]; + } + + interface Ref extends ClForm.Ref { + search(params?: obj): void; + reset(): void; + } + + interface Options extends DeepPartial> { + items?: ClForm.Items; + } +} + +declare namespace ClContextMenu { + interface Item { + label: string; + prefixIcon?: any; + suffixIcon?: any; + ellipsis?: boolean; + disabled?: boolean; + hidden?: boolean; + children?: Item[]; + showChildren?: boolean; + callback?(done: fn): void; + [key: string]: any; + } + + interface Event { + pageX: number; + pageY: number; + [key: string]: any; + } + + interface Options { + class?: string; + hover?: + | boolean + | { + target?: string; + className?: string; + }; + list?: Item[]; + } + + interface Ref { + open(event: Event, options: Options): Exposed; + close(): void; + } + + interface Exposed { + close(): void; + } +} + +declare namespace ClDialog { + interface Provide { + visible: Vue.Ref; + fullscreen: Vue.Ref; + } +} + +declare interface Config { + dict: ClCrud.Dict; + permission: ClCrud.Permission; + events: { + [key: string]: (...args: any[]) => any; + }; + style: { + size: ElementPlus.Size; + colors: string[]; + form: { + labelPosition: ElementPlus.FormProps["labelPosition"]; + labelWidth: ElementPlus.FormProps["labelWidth"]; + span: number; + plugins: ClForm.Plugin[]; + }; + table: { + stripe: boolean; + border: boolean; + highlightCurrentRow: boolean; + resizable: boolean; + autoHeight: boolean; + contextMenu: ClTable.ContextMenu; + column: { + minWidth: number | string; + align: ElementPlus.Align; + headerAlign: ElementPlus.Align; + opWidth: number | string; + }; + plugins: ClTable.Plugin[]; + }; + search: { + plugins: ClSearch.Plugin[]; + }; + }; +} + +declare type Options = DeepPartial; + +declare interface CrudOptions { + options: Options; +} diff --git a/cool-admin-vue/packages/crud/index.html b/cool-admin-vue/packages/crud/index.html new file mode 100644 index 0000000..79f5bc6 --- /dev/null +++ b/cool-admin-vue/packages/crud/index.html @@ -0,0 +1,29 @@ + + + + + + + + + + + + + +
+
+

+
+

+

+
+
+ +
+ + + diff --git a/cool-admin-vue/packages/crud/package.json b/cool-admin-vue/packages/crud/package.json new file mode 100644 index 0000000..9ababe6 --- /dev/null +++ b/cool-admin-vue/packages/crud/package.json @@ -0,0 +1,38 @@ +{ + "name": "@cool-vue/crud", + "version": "8.0.6", + "private": false, + "main": "./dist/index.umd.js", + "module": "./dist/index.es.js", + "types": "types/entry.d.ts", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@vue/runtime-core": "^3.5.13", + "element-plus": "^2.10.4", + "lodash-es": "^4.17.21", + "vue": "^3.5.13" + }, + "devDependencies": { + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.2.1", + "@vitejs/plugin-vue-jsx": "^4.1.1", + "prettier": "^3.5.1", + "sass": "^1.85.0", + "sass-loader": "^16.0.5", + "typescript": "^5.3.3", + "vite": "^6.1.0", + "vite-plugin-dts": "^4.5.0", + "vue-tsc": "^2.2.2" + }, + "files": [ + "types", + "dist", + "index.d.ts", + "index.ts" + ] +} diff --git a/cool-admin-vue/packages/crud/pnpm-lock.yaml b/cool-admin-vue/packages/crud/pnpm-lock.yaml new file mode 100644 index 0000000..471c806 --- /dev/null +++ b/cool-admin-vue/packages/crud/pnpm-lock.yaml @@ -0,0 +1,2350 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@vue/runtime-core': + specifier: ^3.5.13 + version: 3.5.13 + element-plus: + specifier: ^2.9.4 + version: 2.9.4(vue@3.5.13(typescript@5.7.3)) + lodash-es: + specifier: ^4.17.21 + version: 4.17.21 + vue: + specifier: ^3.5.13 + version: 3.5.13(typescript@5.7.3) + devDependencies: + '@types/node': + specifier: ^20.11.16 + version: 20.17.19 + '@vitejs/plugin-vue': + specifier: ^5.2.1 + version: 5.2.1(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3)) + '@vitejs/plugin-vue-jsx': + specifier: ^4.1.1 + version: 4.1.1(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3)) + prettier: + specifier: ^3.5.1 + version: 3.5.1 + sass: + specifier: ^1.85.0 + version: 1.85.0 + sass-loader: + specifier: ^16.0.5 + version: 16.0.5(sass@1.85.0) + typescript: + specifier: ^5.3.3 + version: 5.7.3 + vite: + specifier: ^6.1.0 + version: 6.1.0(@types/node@20.17.19)(sass@1.85.0) + vite-plugin-dts: + specifier: ^4.5.0 + version: 4.5.0(@types/node@20.17.19)(rollup@4.34.8)(typescript@5.7.3)(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0)) + vue-tsc: + specifier: ^2.2.2 + version: 2.2.2(typescript@5.7.3) + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.9': + resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.26.9': + resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.26.5': + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.26.9': + resolution: {integrity: sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-member-expression-to-functions@7.25.9': + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.25.9': + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-replace-supers@7.26.5': + resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.26.9': + resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.26.9': + resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.25.9': + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.26.8': + resolution: {integrity: sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.26.9': + resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.26.9': + resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.26.9': + resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} + engines: {node: '>=6.9.0'} + + '@ctrl/tinycolor@3.6.1': + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + + '@element-plus/icons-vue@2.3.1': + resolution: {integrity: sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==} + peerDependencies: + vue: ^3.2.0 + + '@esbuild/aix-ppc64@0.24.2': + resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.24.2': + resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.24.2': + resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.24.2': + resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.24.2': + resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.24.2': + resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.24.2': + resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.24.2': + resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.24.2': + resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.24.2': + resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.24.2': + resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.24.2': + resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.24.2': + resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.24.2': + resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.24.2': + resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.24.2': + resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.24.2': + resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.24.2': + resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.24.2': + resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.24.2': + resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.24.2': + resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.24.2': + resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.24.2': + resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.24.2': + resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.24.2': + resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@floating-ui/core@1.6.9': + resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==} + + '@floating-ui/dom@1.6.13': + resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==} + + '@floating-ui/utils@0.2.9': + resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@microsoft/api-extractor-model@7.30.3': + resolution: {integrity: sha512-yEAvq0F78MmStXdqz9TTT4PZ05Xu5R8nqgwI5xmUmQjWBQ9E6R2n8HB/iZMRciG4rf9iwI2mtuQwIzDXBvHn1w==} + + '@microsoft/api-extractor@7.50.0': + resolution: {integrity: sha512-Ds/PHTiVzuENQsmXrJKkSdfgNkr/SDG/2rDef0AWl3BchAnXdO7gXaYsAkNx4gWiC4OngNA3fQfd3+BcQxP1DQ==} + hasBin: true + + '@microsoft/tsdoc-config@0.17.1': + resolution: {integrity: sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==} + + '@microsoft/tsdoc@0.15.1': + resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} + + '@parcel/watcher-android-arm64@2.5.1': + resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.1': + resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.1': + resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.1': + resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.1': + resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm-musl@2.5.1': + resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm64-musl@2.5.1': + resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-x64-glibc@2.5.1': + resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-x64-musl@2.5.1': + resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@parcel/watcher-win32-arm64@2.5.1': + resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.1': + resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.1': + resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.1': + resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} + engines: {node: '>= 10.0.0'} + + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.34.8': + resolution: {integrity: sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.34.8': + resolution: {integrity: sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.34.8': + resolution: {integrity: sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.34.8': + resolution: {integrity: sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.34.8': + resolution: {integrity: sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.34.8': + resolution: {integrity: sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + resolution: {integrity: sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.34.8': + resolution: {integrity: sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.34.8': + resolution: {integrity: sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.34.8': + resolution: {integrity: sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + resolution: {integrity: sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + resolution: {integrity: sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-gnu@4.34.8': + resolution: {integrity: sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-s390x-gnu@4.34.8': + resolution: {integrity: sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.34.8': + resolution: {integrity: sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.34.8': + resolution: {integrity: sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-win32-arm64-msvc@4.34.8': + resolution: {integrity: sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.34.8': + resolution: {integrity: sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.34.8': + resolution: {integrity: sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==} + cpu: [x64] + os: [win32] + + '@rushstack/node-core-library@5.11.0': + resolution: {integrity: sha512-I8+VzG9A0F3nH2rLpPd7hF8F7l5Xb7D+ldrWVZYegXM6CsKkvWc670RlgK3WX8/AseZfXA/vVrh0bpXe2Y2UDQ==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/rig-package@0.5.3': + resolution: {integrity: sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==} + + '@rushstack/terminal@0.15.0': + resolution: {integrity: sha512-vXQPRQ+vJJn4GVqxkwRe+UGgzNxdV8xuJZY2zem46Y0p3tlahucH9/hPmLGj2i9dQnUBFiRnoM9/KW7PYw8F4Q==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/ts-command-line@4.23.5': + resolution: {integrity: sha512-jg70HfoK44KfSP3MTiL5rxsZH7X1ktX3cZs9Sl8eDu1/LxJSbPsh0MOFRC710lIuYYSgxWjI5AjbCBAl7u3RxA==} + + '@sxzz/popperjs-es@2.11.7': + resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==} + + '@types/argparse@1.0.38': + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.15': + resolution: {integrity: sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==} + + '@types/node@20.17.19': + resolution: {integrity: sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==} + + '@types/web-bluetooth@0.0.16': + resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} + + '@vitejs/plugin-vue-jsx@4.1.1': + resolution: {integrity: sha512-uMJqv/7u1zz/9NbWAD3XdjaY20tKTf17XVfQ9zq4wY1BjsB/PjpJPMe2xiG39QpP4ZdhYNhm4Hvo66uJrykNLA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.0.0 + + '@vitejs/plugin-vue@5.2.1': + resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.2.25 + + '@volar/language-core@2.4.11': + resolution: {integrity: sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==} + + '@volar/source-map@2.4.11': + resolution: {integrity: sha512-ZQpmafIGvaZMn/8iuvCFGrW3smeqkq/IIh9F1SdSx9aUl0J4Iurzd6/FhmjNO5g2ejF3rT45dKskgXWiofqlZQ==} + + '@volar/typescript@2.4.11': + resolution: {integrity: sha512-2DT+Tdh88Spp5PyPbqhyoYavYCPDsqbHLFwcUI9K1NlY1YgUJvujGdrqUp0zWxnW7KWNTr3xSpMuv2WnaTKDAw==} + + '@vue/babel-helper-vue-transform-on@1.2.5': + resolution: {integrity: sha512-lOz4t39ZdmU4DJAa2hwPYmKc8EsuGa2U0L9KaZaOJUt0UwQNjNA3AZTq6uEivhOKhhG1Wvy96SvYBoFmCg3uuw==} + + '@vue/babel-plugin-jsx@1.2.5': + resolution: {integrity: sha512-zTrNmOd4939H9KsRIGmmzn3q2zvv1mjxkYZHgqHZgDrXz5B1Q3WyGEjO2f+JrmKghvl1JIRcvo63LgM1kH5zFg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + + '@vue/babel-plugin-resolve-type@1.2.5': + resolution: {integrity: sha512-U/ibkQrf5sx0XXRnUZD1mo5F7PkpKyTbfXM3a3rC4YnUz6crHEz9Jg09jzzL6QYlXNto/9CePdOg/c87O4Nlfg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@vue/compiler-core@3.5.13': + resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} + + '@vue/compiler-dom@3.5.13': + resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} + + '@vue/compiler-sfc@3.5.13': + resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} + + '@vue/compiler-ssr@3.5.13': + resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} + + '@vue/compiler-vue2@2.7.16': + resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + + '@vue/language-core@2.2.0': + resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/language-core@2.2.2': + resolution: {integrity: sha512-QotO41kurE5PLf3vrNgGTk3QswO2PdUFjBwNiOi7zMmGhwb25PSTh9hD1MCgKC06AVv+8sZQvlL3Do4TTVHSiQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/reactivity@3.5.13': + resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} + + '@vue/runtime-core@3.5.13': + resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} + + '@vue/runtime-dom@3.5.13': + resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} + + '@vue/server-renderer@3.5.13': + resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} + peerDependencies: + vue: 3.5.13 + + '@vue/shared@3.5.13': + resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} + + '@vueuse/core@9.13.0': + resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==} + + '@vueuse/metadata@9.13.0': + resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==} + + '@vueuse/shared@9.13.0': + resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + + ajv@8.13.0: + resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + + alien-signals@0.4.14: + resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} + + alien-signals@1.0.3: + resolution: {integrity: sha512-zQOh3wAYK5ujENxvBBR3CFGF/b6afaSzZ/c9yNhJ1ENrGHETvpUuKQsa93Qrclp0+PzTF93MaZ7scVp1uUozhA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + caniuse-lite@1.0.30001700: + resolution: {integrity: sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + + electron-to-chromium@1.5.102: + resolution: {integrity: sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q==} + + element-plus@2.9.4: + resolution: {integrity: sha512-sGnW0wd9zf6lEGixXV2gfwx3X6VTMkP52qTkX7zbURJ2oariyslrKTBh2txt1sdn1pUvj2l0KY3OfSXoZGmDOw==} + peerDependencies: + vue: ^3.2.0 + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + esbuild@0.24.2: + resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} + + 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==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + + immutable@5.0.3: + resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==} + + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + 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-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + + local-pkg@0.5.1: + resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} + engines: {node: '>=14'} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash-unified@1.0.3: + resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==} + peerDependencies: + '@types/lodash-es': '*' + lodash: '*' + lodash-es: '*' + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + memoize-one@6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + minimatch@3.0.8: + resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + normalize-wheel-es@1.2.0: + resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + 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.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + postcss@8.5.2: + resolution: {integrity: sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==} + engines: {node: ^10 || ^12 || >=14} + + prettier@3.5.1: + resolution: {integrity: sha512-hPpFQvHwL3Qv5AdRvBFMhnKo4tYxp0ReXiPn2bxkiohEX6mBeBwEpBSQTkD458RaaDKQMYSp4hX4UtfUTA5wDw==} + engines: {node: '>=14'} + hasBin: true + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + + rollup@4.34.8: + resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + sass-loader@16.0.5: + resolution: {integrity: sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + sass: ^1.3.0 + sass-embedded: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + node-sass: + optional: true + sass: + optional: true + sass-embedded: + optional: true + webpack: + optional: true + + sass@1.85.0: + resolution: {integrity: sha512-3ToiC1xZ1Y8aU7+CkgCI/tqyuPXEmYGJXO7H4uqp0xkLXUqp88rQQ4j1HmP37xSJLbCJPaIiv+cT1y+grssrww==} + engines: {node: '>=14.0.0'} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svg-tags@1.0.0: + resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + typescript@5.7.2: + resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} + engines: {node: '>=14.17'} + hasBin: true + + typescript@5.7.3: + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + update-browserslist-db@1.1.2: + resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + vite-plugin-dts@4.5.0: + resolution: {integrity: sha512-M1lrPTdi7gilLYRZoLmGYnl4fbPryVYsehPN9JgaxjJKTs8/f7tuAlvCCvOLB5gRDQTTKnptBcB0ACsaw2wNLw==} + peerDependencies: + typescript: '*' + vite: '*' + peerDependenciesMeta: + vite: + optional: true + + vite@6.1.0: + resolution: {integrity: sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==} + 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 + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-tsc@2.2.2: + resolution: {integrity: sha512-1icPKkxAA5KTAaSwg0wVWdE48EdsH8fgvcbAiqojP4jXKl6LEM3soiW1aG/zrWrFt8Mw1ncG2vG1PvpZpVfehA==} + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue@3.5.13: + resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.26.8': {} + + '@babel/core@7.26.9': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helpers': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + convert-source-map: 2.0.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.26.9': + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.25.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/helper-compilation-targets@7.26.5': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.26.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/traverse': 7.26.9 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-member-expression-to-functions@7.25.9': + dependencies: + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.25.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/helper-plugin-utils@7.26.5': {} + + '@babel/helper-replace-supers@7.26.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + dependencies: + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helpers@7.26.9': + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + + '@babel/parser@7.26.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-typescript@7.26.8(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/template@7.26.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + + '@babel/traverse@7.26.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.26.9': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@ctrl/tinycolor@3.6.1': {} + + '@element-plus/icons-vue@2.3.1(vue@3.5.13(typescript@5.7.3))': + dependencies: + vue: 3.5.13(typescript@5.7.3) + + '@esbuild/aix-ppc64@0.24.2': + optional: true + + '@esbuild/android-arm64@0.24.2': + optional: true + + '@esbuild/android-arm@0.24.2': + optional: true + + '@esbuild/android-x64@0.24.2': + optional: true + + '@esbuild/darwin-arm64@0.24.2': + optional: true + + '@esbuild/darwin-x64@0.24.2': + optional: true + + '@esbuild/freebsd-arm64@0.24.2': + optional: true + + '@esbuild/freebsd-x64@0.24.2': + optional: true + + '@esbuild/linux-arm64@0.24.2': + optional: true + + '@esbuild/linux-arm@0.24.2': + optional: true + + '@esbuild/linux-ia32@0.24.2': + optional: true + + '@esbuild/linux-loong64@0.24.2': + optional: true + + '@esbuild/linux-mips64el@0.24.2': + optional: true + + '@esbuild/linux-ppc64@0.24.2': + optional: true + + '@esbuild/linux-riscv64@0.24.2': + optional: true + + '@esbuild/linux-s390x@0.24.2': + optional: true + + '@esbuild/linux-x64@0.24.2': + optional: true + + '@esbuild/netbsd-arm64@0.24.2': + optional: true + + '@esbuild/netbsd-x64@0.24.2': + optional: true + + '@esbuild/openbsd-arm64@0.24.2': + optional: true + + '@esbuild/openbsd-x64@0.24.2': + optional: true + + '@esbuild/sunos-x64@0.24.2': + optional: true + + '@esbuild/win32-arm64@0.24.2': + optional: true + + '@esbuild/win32-ia32@0.24.2': + optional: true + + '@esbuild/win32-x64@0.24.2': + optional: true + + '@floating-ui/core@1.6.9': + dependencies: + '@floating-ui/utils': 0.2.9 + + '@floating-ui/dom@1.6.13': + dependencies: + '@floating-ui/core': 1.6.9 + '@floating-ui/utils': 0.2.9 + + '@floating-ui/utils@0.2.9': {} + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@microsoft/api-extractor-model@7.30.3(@types/node@20.17.19)': + dependencies: + '@microsoft/tsdoc': 0.15.1 + '@microsoft/tsdoc-config': 0.17.1 + '@rushstack/node-core-library': 5.11.0(@types/node@20.17.19) + transitivePeerDependencies: + - '@types/node' + + '@microsoft/api-extractor@7.50.0(@types/node@20.17.19)': + dependencies: + '@microsoft/api-extractor-model': 7.30.3(@types/node@20.17.19) + '@microsoft/tsdoc': 0.15.1 + '@microsoft/tsdoc-config': 0.17.1 + '@rushstack/node-core-library': 5.11.0(@types/node@20.17.19) + '@rushstack/rig-package': 0.5.3 + '@rushstack/terminal': 0.15.0(@types/node@20.17.19) + '@rushstack/ts-command-line': 4.23.5(@types/node@20.17.19) + lodash: 4.17.21 + minimatch: 3.0.8 + resolve: 1.22.10 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.7.2 + transitivePeerDependencies: + - '@types/node' + + '@microsoft/tsdoc-config@0.17.1': + dependencies: + '@microsoft/tsdoc': 0.15.1 + ajv: 8.12.0 + jju: 1.4.0 + resolve: 1.22.10 + + '@microsoft/tsdoc@0.15.1': {} + + '@parcel/watcher-android-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-x64@2.5.1': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.1': + optional: true + + '@parcel/watcher-win32-arm64@2.5.1': + optional: true + + '@parcel/watcher-win32-ia32@2.5.1': + optional: true + + '@parcel/watcher-win32-x64@2.5.1': + optional: true + + '@parcel/watcher@2.5.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.1 + '@parcel/watcher-darwin-arm64': 2.5.1 + '@parcel/watcher-darwin-x64': 2.5.1 + '@parcel/watcher-freebsd-x64': 2.5.1 + '@parcel/watcher-linux-arm-glibc': 2.5.1 + '@parcel/watcher-linux-arm-musl': 2.5.1 + '@parcel/watcher-linux-arm64-glibc': 2.5.1 + '@parcel/watcher-linux-arm64-musl': 2.5.1 + '@parcel/watcher-linux-x64-glibc': 2.5.1 + '@parcel/watcher-linux-x64-musl': 2.5.1 + '@parcel/watcher-win32-arm64': 2.5.1 + '@parcel/watcher-win32-ia32': 2.5.1 + '@parcel/watcher-win32-x64': 2.5.1 + optional: true + + '@rollup/pluginutils@5.1.4(rollup@4.34.8)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.34.8 + + '@rollup/rollup-android-arm-eabi@4.34.8': + optional: true + + '@rollup/rollup-android-arm64@4.34.8': + optional: true + + '@rollup/rollup-darwin-arm64@4.34.8': + optional: true + + '@rollup/rollup-darwin-x64@4.34.8': + optional: true + + '@rollup/rollup-freebsd-arm64@4.34.8': + optional: true + + '@rollup/rollup-freebsd-x64@4.34.8': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.34.8': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.34.8': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-x64-musl@4.34.8': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.34.8': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.34.8': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.34.8': + optional: true + + '@rushstack/node-core-library@5.11.0(@types/node@20.17.19)': + dependencies: + ajv: 8.13.0 + ajv-draft-04: 1.0.0(ajv@8.13.0) + ajv-formats: 3.0.1(ajv@8.13.0) + fs-extra: 11.3.0 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.10 + semver: 7.5.4 + optionalDependencies: + '@types/node': 20.17.19 + + '@rushstack/rig-package@0.5.3': + dependencies: + resolve: 1.22.10 + strip-json-comments: 3.1.1 + + '@rushstack/terminal@0.15.0(@types/node@20.17.19)': + dependencies: + '@rushstack/node-core-library': 5.11.0(@types/node@20.17.19) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 20.17.19 + + '@rushstack/ts-command-line@4.23.5(@types/node@20.17.19)': + dependencies: + '@rushstack/terminal': 0.15.0(@types/node@20.17.19) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + + '@sxzz/popperjs-es@2.11.7': {} + + '@types/argparse@1.0.38': {} + + '@types/estree@1.0.6': {} + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.15 + + '@types/lodash@4.17.15': {} + + '@types/node@20.17.19': + dependencies: + undici-types: 6.19.8 + + '@types/web-bluetooth@0.0.16': {} + + '@vitejs/plugin-vue-jsx@4.1.1(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@babel/core': 7.26.9 + '@babel/plugin-transform-typescript': 7.26.8(@babel/core@7.26.9) + '@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.9) + vite: 6.1.0(@types/node@20.17.19)(sass@1.85.0) + vue: 3.5.13(typescript@5.7.3) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-vue@5.2.1(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3))': + dependencies: + vite: 6.1.0(@types/node@20.17.19)(sass@1.85.0) + vue: 3.5.13(typescript@5.7.3) + + '@volar/language-core@2.4.11': + dependencies: + '@volar/source-map': 2.4.11 + + '@volar/source-map@2.4.11': {} + + '@volar/typescript@2.4.11': + dependencies: + '@volar/language-core': 2.4.11 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue/babel-helper-vue-transform-on@1.2.5': {} + + '@vue/babel-plugin-jsx@1.2.5(@babel/core@7.26.9)': + dependencies: + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.9) + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + '@vue/babel-helper-vue-transform-on': 1.2.5 + '@vue/babel-plugin-resolve-type': 1.2.5(@babel/core@7.26.9) + html-tags: 3.3.1 + svg-tags: 1.0.0 + optionalDependencies: + '@babel/core': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@vue/babel-plugin-resolve-type@1.2.5(@babel/core@7.26.9)': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/parser': 7.26.9 + '@vue/compiler-sfc': 3.5.13 + transitivePeerDependencies: + - supports-color + + '@vue/compiler-core@3.5.13': + dependencies: + '@babel/parser': 7.26.9 + '@vue/shared': 3.5.13 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.13': + dependencies: + '@vue/compiler-core': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/compiler-sfc@3.5.13': + dependencies: + '@babel/parser': 7.26.9 + '@vue/compiler-core': 3.5.13 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + estree-walker: 2.0.2 + magic-string: 0.30.17 + postcss: 8.5.2 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.13': + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/compiler-vue2@2.7.16': + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + '@vue/language-core@2.2.0(typescript@5.7.3)': + dependencies: + '@volar/language-core': 2.4.11 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.13 + alien-signals: 0.4.14 + minimatch: 9.0.5 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.7.3 + + '@vue/language-core@2.2.2(typescript@5.7.3)': + dependencies: + '@volar/language-core': 2.4.11 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.13 + alien-signals: 1.0.3 + minimatch: 9.0.5 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.7.3 + + '@vue/reactivity@3.5.13': + dependencies: + '@vue/shared': 3.5.13 + + '@vue/runtime-core@3.5.13': + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/runtime-dom@3.5.13': + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/runtime-core': 3.5.13 + '@vue/shared': 3.5.13 + csstype: 3.1.3 + + '@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + vue: 3.5.13(typescript@5.7.3) + + '@vue/shared@3.5.13': {} + + '@vueuse/core@9.13.0(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@types/web-bluetooth': 0.0.16 + '@vueuse/metadata': 9.13.0 + '@vueuse/shared': 9.13.0(vue@3.5.13(typescript@5.7.3)) + vue-demi: 0.14.10(vue@3.5.13(typescript@5.7.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/metadata@9.13.0': {} + + '@vueuse/shared@9.13.0(vue@3.5.13(typescript@5.7.3))': + dependencies: + vue-demi: 0.14.10(vue@3.5.13(typescript@5.7.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + acorn@8.14.0: {} + + ajv-draft-04@1.0.0(ajv@8.13.0): + optionalDependencies: + ajv: 8.13.0 + + ajv-formats@3.0.1(ajv@8.13.0): + optionalDependencies: + ajv: 8.13.0 + + ajv@8.12.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + ajv@8.13.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + alien-signals@0.4.14: {} + + alien-signals@1.0.3: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + async-validator@4.2.5: {} + + balanced-match@1.0.2: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + optional: true + + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001700 + electron-to-chromium: 1.5.102 + node-releases: 2.0.19 + update-browserslist-db: 1.1.2(browserslist@4.24.4) + + caniuse-lite@1.0.30001700: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + compare-versions@6.1.1: {} + + concat-map@0.0.1: {} + + confbox@0.1.8: {} + + convert-source-map@2.0.0: {} + + csstype@3.1.3: {} + + dayjs@1.11.13: {} + + de-indent@1.0.2: {} + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + detect-libc@1.0.3: + optional: true + + electron-to-chromium@1.5.102: {} + + element-plus@2.9.4(vue@3.5.13(typescript@5.7.3)): + dependencies: + '@ctrl/tinycolor': 3.6.1 + '@element-plus/icons-vue': 2.3.1(vue@3.5.13(typescript@5.7.3)) + '@floating-ui/dom': 1.6.13 + '@popperjs/core': '@sxzz/popperjs-es@2.11.7' + '@types/lodash': 4.17.15 + '@types/lodash-es': 4.17.12 + '@vueuse/core': 9.13.0(vue@3.5.13(typescript@5.7.3)) + async-validator: 4.2.5 + dayjs: 1.11.13 + escape-html: 1.0.3 + lodash: 4.17.21 + lodash-es: 4.17.21 + lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21) + memoize-one: 6.0.0 + normalize-wheel-es: 1.2.0 + vue: 3.5.13(typescript@5.7.3) + transitivePeerDependencies: + - '@vue/composition-api' + + entities@4.5.0: {} + + esbuild@0.24.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.2 + '@esbuild/android-arm': 0.24.2 + '@esbuild/android-arm64': 0.24.2 + '@esbuild/android-x64': 0.24.2 + '@esbuild/darwin-arm64': 0.24.2 + '@esbuild/darwin-x64': 0.24.2 + '@esbuild/freebsd-arm64': 0.24.2 + '@esbuild/freebsd-x64': 0.24.2 + '@esbuild/linux-arm': 0.24.2 + '@esbuild/linux-arm64': 0.24.2 + '@esbuild/linux-ia32': 0.24.2 + '@esbuild/linux-loong64': 0.24.2 + '@esbuild/linux-mips64el': 0.24.2 + '@esbuild/linux-ppc64': 0.24.2 + '@esbuild/linux-riscv64': 0.24.2 + '@esbuild/linux-s390x': 0.24.2 + '@esbuild/linux-x64': 0.24.2 + '@esbuild/netbsd-arm64': 0.24.2 + '@esbuild/netbsd-x64': 0.24.2 + '@esbuild/openbsd-arm64': 0.24.2 + '@esbuild/openbsd-x64': 0.24.2 + '@esbuild/sunos-x64': 0.24.2 + '@esbuild/win32-arm64': 0.24.2 + '@esbuild/win32-ia32': 0.24.2 + '@esbuild/win32-x64': 0.24.2 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + estree-walker@2.0.2: {} + + fast-deep-equal@3.1.3: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + optional: true + + fs-extra@11.3.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + globals@11.12.0: {} + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + html-tags@3.3.1: {} + + immutable@5.0.3: {} + + import-lazy@4.0.0: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: + optional: true + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + optional: true + + is-number@7.0.0: + optional: true + + jju@1.4.0: {} + + js-tokens@4.0.0: {} + + jsesc@3.1.0: {} + + json-schema-traverse@1.0.0: {} + + json5@2.2.3: {} + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + kolorist@1.8.0: {} + + local-pkg@0.5.1: + dependencies: + mlly: 1.7.4 + pkg-types: 1.3.1 + + lodash-es@4.17.21: {} + + lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21): + dependencies: + '@types/lodash-es': 4.17.12 + lodash: 4.17.21 + lodash-es: 4.17.21 + + lodash@4.17.21: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + memoize-one@6.0.0: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + optional: true + + minimatch@3.0.8: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + mlly@1.7.4: + dependencies: + acorn: 8.14.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.5.4 + + ms@2.1.3: {} + + muggle-string@0.4.1: {} + + nanoid@3.3.8: {} + + neo-async@2.6.2: {} + + node-addon-api@7.1.1: + optional: true + + node-releases@2.0.19: {} + + normalize-wheel-es@1.2.0: {} + + path-browserify@1.0.1: {} + + path-parse@1.0.7: {} + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: + optional: true + + picomatch@4.0.2: {} + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 2.0.3 + + postcss@8.5.2: + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prettier@3.5.1: {} + + punycode@2.3.1: {} + + readdirp@4.1.2: {} + + require-from-string@2.0.2: {} + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + rollup@4.34.8: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.34.8 + '@rollup/rollup-android-arm64': 4.34.8 + '@rollup/rollup-darwin-arm64': 4.34.8 + '@rollup/rollup-darwin-x64': 4.34.8 + '@rollup/rollup-freebsd-arm64': 4.34.8 + '@rollup/rollup-freebsd-x64': 4.34.8 + '@rollup/rollup-linux-arm-gnueabihf': 4.34.8 + '@rollup/rollup-linux-arm-musleabihf': 4.34.8 + '@rollup/rollup-linux-arm64-gnu': 4.34.8 + '@rollup/rollup-linux-arm64-musl': 4.34.8 + '@rollup/rollup-linux-loongarch64-gnu': 4.34.8 + '@rollup/rollup-linux-powerpc64le-gnu': 4.34.8 + '@rollup/rollup-linux-riscv64-gnu': 4.34.8 + '@rollup/rollup-linux-s390x-gnu': 4.34.8 + '@rollup/rollup-linux-x64-gnu': 4.34.8 + '@rollup/rollup-linux-x64-musl': 4.34.8 + '@rollup/rollup-win32-arm64-msvc': 4.34.8 + '@rollup/rollup-win32-ia32-msvc': 4.34.8 + '@rollup/rollup-win32-x64-msvc': 4.34.8 + fsevents: 2.3.3 + + sass-loader@16.0.5(sass@1.85.0): + dependencies: + neo-async: 2.6.2 + optionalDependencies: + sass: 1.85.0 + + sass@1.85.0: + dependencies: + chokidar: 4.0.3 + immutable: 5.0.3 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.1 + + semver@6.3.1: {} + + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + + source-map-js@1.2.1: {} + + source-map@0.6.1: {} + + sprintf-js@1.0.3: {} + + string-argv@0.3.2: {} + + strip-json-comments@3.1.1: {} + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svg-tags@1.0.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + optional: true + + typescript@5.7.2: {} + + typescript@5.7.3: {} + + ufo@1.5.4: {} + + undici-types@6.19.8: {} + + universalify@2.0.1: {} + + update-browserslist-db@1.1.2(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + vite-plugin-dts@4.5.0(@types/node@20.17.19)(rollup@4.34.8)(typescript@5.7.3)(vite@6.1.0(@types/node@20.17.19)(sass@1.85.0)): + dependencies: + '@microsoft/api-extractor': 7.50.0(@types/node@20.17.19) + '@rollup/pluginutils': 5.1.4(rollup@4.34.8) + '@volar/typescript': 2.4.11 + '@vue/language-core': 2.2.0(typescript@5.7.3) + compare-versions: 6.1.1 + debug: 4.4.0 + kolorist: 1.8.0 + local-pkg: 0.5.1 + magic-string: 0.30.17 + typescript: 5.7.3 + optionalDependencies: + vite: 6.1.0(@types/node@20.17.19)(sass@1.85.0) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + + vite@6.1.0(@types/node@20.17.19)(sass@1.85.0): + dependencies: + esbuild: 0.24.2 + postcss: 8.5.2 + rollup: 4.34.8 + optionalDependencies: + '@types/node': 20.17.19 + fsevents: 2.3.3 + sass: 1.85.0 + + vscode-uri@3.1.0: {} + + vue-demi@0.14.10(vue@3.5.13(typescript@5.7.3)): + dependencies: + vue: 3.5.13(typescript@5.7.3) + + vue-tsc@2.2.2(typescript@5.7.3): + dependencies: + '@volar/typescript': 2.4.11 + '@vue/language-core': 2.2.2(typescript@5.7.3) + typescript: 5.7.3 + + vue@3.5.13(typescript@5.7.3): + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-sfc': 3.5.13 + '@vue/runtime-dom': 3.5.13 + '@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@5.7.3)) + '@vue/shared': 3.5.13 + optionalDependencies: + typescript: 5.7.3 + + yallist@3.1.1: {} + + yallist@4.0.0: {} diff --git a/cool-admin-vue/packages/crud/src/App.vue b/cool-admin-vue/packages/crud/src/App.vue new file mode 100644 index 0000000..cc45c80 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/App.vue @@ -0,0 +1,208 @@ + + + + + diff --git a/cool-admin-vue/packages/crud/src/components/add-btn/index.tsx b/cool-admin-vue/packages/crud/src/components/add-btn/index.tsx new file mode 100644 index 0000000..1f42fac --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/add-btn/index.tsx @@ -0,0 +1,21 @@ +import { defineComponent } from "vue"; +import { useConfig, useCore } from "../../hooks"; + +export default defineComponent({ + name: "cl-add-btn", + + setup(_, { slots }) { + const { crud } = useCore(); + const { style } = useConfig(); + + return () => { + return ( + crud.getPermission("add") && ( + + {slots.default?.() || crud.dict.label.add} + + ) + ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/adv/btn.tsx b/cool-admin-vue/packages/crud/src/components/adv/btn.tsx new file mode 100644 index 0000000..34b4da5 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/adv/btn.tsx @@ -0,0 +1,31 @@ +import { useConfig, useCore } from "../../hooks"; +import { defineComponent } from "vue"; +import { Search } from "@element-plus/icons-vue"; + +export default defineComponent({ + name: "cl-adv-btn", + + components: { + Search + }, + + setup(_, { slots }) { + const { crud, mitt } = useCore(); + const { style } = useConfig(); + + function open() { + mitt.emit("crud.openAdvSearch"); + } + + return () => { + return ( + + + + + {slots.default?.() || crud.dict.label.advSearch} + + ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/adv/search.tsx b/cool-admin-vue/packages/crud/src/components/adv/search.tsx new file mode 100644 index 0000000..e06e214 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/adv/search.tsx @@ -0,0 +1,212 @@ +import { + defineComponent, + h, + inject, + mergeProps, + nextTick, + type PropType, + reactive, + ref +} from "vue"; +import { Close } from "@element-plus/icons-vue"; +import { useBrowser, useConfig, useCore } from "../../hooks"; +import { renderNode } from "../../utils/vnode"; +import { useApi } from "../form/helper"; +import { isArray } from "lodash-es"; + +export default defineComponent({ + name: "cl-adv-search", + + components: { + Close + }, + + props: { + // 表单项 + items: { + type: Array as PropType, + default: () => [] + }, + // 标题 + title: String, + // 窗体大小 + size: { + type: [Number, String], + default: "30%" + }, + // 操作按钮 + op: { + type: Array, + default: () => ["clear", "reset", "close", "search"] + }, + // 搜索钩子 + onSearch: Function + }, + + emits: ["reset", "clear"], + + setup(props, { emit, slots, expose }) { + const { crud, mitt } = useCore(); + const { style } = useConfig(); + const browser = useBrowser(); + + // 配置 + const config = reactive( + mergeProps(props, inject("useAdvSearch__options") || {}) + ); + + // cl-form + const Form = ref(); + + // el-drawer + const Drawer = ref(); + + // 是否可见 + const visible = ref(false); + + // 打开 + function open() { + visible.value = true; + + nextTick(() => { + Form.value?.open({ + items: config.items || [], + op: { + hidden: true + }, + isReset: false + }); + }); + } + + // 关闭 + function close() { + Drawer.value.handleClose(); + } + + // 重置数据 + function reset() { + const d: any = {}; + + config.items?.map((e) => { + if (typeof e.hook != "string" && e.hook?.reset) { + const props = e.hook.reset(e.prop!); + + if (isArray(props)) { + props.forEach((prop) => { + d[prop] = undefined; + }); + } + } + + d[e.prop!] = undefined; + }); + + // 重置表单 + Form.value?.reset(); + + // 列表刷新 + search(); + + // 重置事件 + emit("reset", d); + } + + // 清空数据 + function clear() { + Form.value?.clear(); + emit("clear"); + } + + // 搜素请求 + function search(params?: any) { + const form = Form.value?.getForm(); + + function next(data: any) { + Form.value?.done(); + close(); + + return crud.refresh({ + ...data, + ...params, + page: 1 + }); + } + + if (config.onSearch) { + config.onSearch(form, { next, close }); + } else { + next(form); + } + } + + // 消息事件 + mitt.on("crud.openAdvSearch", open); + + // 渲染表单 + function renderForm() { + return h(, {}, slots); + } + + // 渲染底部 + function renderFooter() { + const fns = { search, reset, clear, close }; + + return config.op?.map((e: string) => { + switch (e) { + case "search": + case "reset": + case "clear": + case "close": + return h( + , + { + type: e == "search" ? "primary" : null, + size: style.size, + onClick: () => { + fns[e](); + } + }, + { default: () => crud.dict.label[e] } + ); + + default: + return renderNode(e, { + scope: Form.value?.getForm(), + slots + }); + } + }); + } + + expose({ + open, + close, + clear, + ...useApi({ Form }), + reset, + Form + }); + + return () => { + return ( + +
+ {config.title || crud.dict.label.advSearch} + + + +
+
{renderForm()}
+ +
+ ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/context-menu/index.tsx b/cool-admin-vue/packages/crud/src/components/context-menu/index.tsx new file mode 100644 index 0000000..4da9501 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/context-menu/index.tsx @@ -0,0 +1,279 @@ +import { + defineComponent, + h, + nextTick, + onMounted, + type PropType, + reactive, + ref, + render, + toRaw +} from "vue"; +import { isString } from "lodash-es"; +import { addClass, contains, removeClass } from "../../utils"; +import { useRefs } from "../../hooks"; +import { ElIcon } from "element-plus"; +import { ArrowRight } from "@element-plus/icons-vue"; + +const ClContextMenu = defineComponent({ + name: "cl-context-menu", + + props: { + show: Boolean, + options: { + type: Object as PropType, + default: () => ({}) + }, + event: { + type: Object, + default: () => ({}) + } + }, + + setup(props, { expose, slots }) { + const { refs, setRefs } = useRefs(); + + // 是否可见 + const visible = ref(props.show || false); + + // 按钮列表 + const list = ref([]); + + // 样式 + const style = reactive({ + left: "0px", + top: "0px" + }); + + // 选中值 + const ids = ref(""); + + // 阻止默认事件 + function stopDefault(e: any) { + if (e.preventDefault) { + e.preventDefault(); + } + + if (e.stopPropagation) { + e.stopPropagation(); + } + } + + // 解析列表 + function parseList(list: ClContextMenu.Item[]) { + function deep(list: ClContextMenu.Item[]) { + list.forEach((e) => { + e.showChildren = false; + + if (e.children) { + deep(e.children); + } + }); + } + + deep(list); + + return list; + } + + // 目标元素 + let targetEl: any; + + // 关闭 + function close() { + visible.value = false; + ids.value = ""; + + if (targetEl) { + removeClass(targetEl, "cl-context-menu__target"); + } + } + + // 打开 + function open(event: any, options: ClContextMenu.Options = {}) { + // 阻止默认事件 + stopDefault(event); + + // 显示 + visible.value = true; + + // 元素 + const el = refs["context-menu"].querySelector(".cl-context-menu__box") as HTMLElement; + + // 点击样式 + if (options?.hover) { + const d = options.hover === true ? {} : options.hover; + targetEl = event.target; + + if (targetEl && isString(targetEl.className)) { + if (d.target) { + while (!targetEl.className.includes(d.target)) { + targetEl = targetEl.parentNode; + } + } + + addClass(targetEl, d.className || "cl-context-menu__target"); + } + } + + // 自定义样式 + if (options?.class) { + addClass(el, options.class); + } + + // 菜单列表 + if (options?.list) { + list.value = parseList(options.list); + } + + nextTick(() => { + // 计算位置 + let left = event.pageX; + let top = event.pageY; + + // 组件方式用 offset 计算 + if (!props.show) { + left = event.offsetX; + top = event.offsetY; + } + + const { clientHeight: h1, clientWidth: w1 } = event.target?.ownerDocument.body; + const { clientHeight: h2, clientWidth: w2 } = el; + + if (top + h2 > h1) { + top = h1 - h2 - 5; + } + + if (left + w2 > w1) { + left = w1 - w2 - 5; + } + + style.left = left + "px"; + style.top = top + "px"; + }); + + return { + close + }; + } + + // 行点击 + function rowClick(item: ClContextMenu.Item, id: string) { + ids.value = id; + + if (item.disabled) { + return false; + } + + if (item.callback) { + return item.callback(close); + } + + if (item.children) { + item.showChildren = !item.showChildren; + } else { + close(); + } + } + + expose({ + open, + close + }); + + onMounted(function () { + if (visible.value) { + const { body, documentElement } = props.event.target.ownerDocument; + + // 添加到 body 下 + body.appendChild(refs["context-menu"]); + // 关闭事件 + (documentElement || body).addEventListener("mousedown", (e: any) => { + const el = refs["context-menu"]; + if (!contains(el, e.target) && el != e.target) { + close(); + } + }); + + // 默认打开 + open(props.event, props?.options); + } + }); + + return () => { + function deep(list: ClContextMenu.Item[], pId: string, level: number) { + return ( +
1 && "is-append"]}> + {list + .filter((e) => !e.hidden) + .map((e, i) => { + const id = `${pId}-${i}`; + + if (!e.suffixIcon) { + // 默认图标 + if (e.children) { + e.suffixIcon = ArrowRight; + } + } + + return ( +
{ + rowClick(e, id); + ev.stopPropagation(); + }}> + {/* 前缀图标 */} + {e.prefixIcon && {h(toRaw(e.prefixIcon))}} + + {/* 标题 */} + {e.label} + + {/* 后缀图标 */} + {e.suffixIcon && {h(toRaw(e.suffixIcon))}} + + {/* 子集 */} + {e.children && + e.showChildren && + deep(e.children, id, level + 1)} +
+ ); + })} +
+ ); + } + + return ( + visible.value && ( +
+ {slots.default ? slots.default() : deep(list.value, "0", 1)} +
+ ) + ); + }; + } +}); + +export const ContextMenu = { + open(event: any, options: ClContextMenu.Options) { + const vm = h(ClContextMenu, { + show: true, + event, + options + }); + + render(vm, event.target.ownerDocument.createElement("div")); + + return vm.component?.exposed as ClContextMenu.Exposed; + } +}; + +export default ClContextMenu; diff --git a/cool-admin-vue/packages/crud/src/components/crud/helper.ts b/cool-admin-vue/packages/crud/src/components/crud/helper.ts new file mode 100644 index 0000000..4275990 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/crud/helper.ts @@ -0,0 +1,287 @@ +import { ElMessage, ElMessageBox } from "element-plus"; +import { Mitt } from "../../utils/mitt"; +import { ref } from "vue"; +import { assign, isArray, isFunction } from "lodash-es"; +import { merge } from "../../utils"; + +interface Options { + mitt: Mitt; + config: ClCrud.Config; + crud: ClCrud.Ref; +} + +export function useHelper({ config, crud, mitt }: Options) { + // 刷新随机值,避免脏数据 + const refreshRd = ref(0); + + // 获取权限 + function getPermission(key: "page" | "list" | "info" | "update" | "add" | "delete"): boolean { + return Boolean(crud.permission[key]); + } + + // 根据字典替换请求参数 + function paramsReplace(params: obj) { + const { pagination, search, sort } = crud.dict; + + // 请求参数 + const a: any = { ...params }; + + // 字典 + const b: any = { ...pagination, ...search, ...sort }; + + for (const i in b) { + if (a[i]) { + if (i != b[i]) { + a[`_${b[i]}`] = a[i]; + + delete a[i]; + } + } + } + + for (const i in a) { + if (i[0] === "_") { + a[i.substr(1)] = a[i]; + + delete a[i]; + } + } + + return a; + } + + // 刷新请求 + function refresh(params?: obj) { + const { service, dict } = crud; + + return new Promise((success, error) => { + // 合并请求参数 + const reqParams = paramsReplace(assign(crud.params, params)); + + // Loading + crud.loading = true; + + // 预防脏数据 + const rd = (refreshRd.value = Math.random()); + + // 完成事件 + function done() { + crud.loading = false; + } + + // 渲染 + function render(data: any | any[], pagination?: any) { + const res = isArray(data) ? { list: data, pagination } : data; + done(); + success(res); + mitt.emit("crud.refresh", res); + } + + // 下一步 + function next(params: obj): Promise { + return new Promise(async (resolve, reject) => { + await service[dict.api.page](params) + .then((res) => { + if (rd != refreshRd.value) { + return false; + } + + if (isArray(res)) { + res = { + list: res, + pagination: { + total: res.length + } + }; + } + + render(res); + resolve(res); + }) + .catch((err) => { + ElMessage.error(err.message); + error(err); + reject(err); + }); + + done(); + }); + } + + // 刷新钩子 + if (config.onRefresh) { + config.onRefresh(reqParams, { next, done, render }); + } else { + next(reqParams); + } + }); + } + + // 打开详情 + function rowInfo(data: any) { + mitt.emit("crud.proxy", { + name: "info", + data: [data] + }); + } + + // 打开新增 + function rowAdd() { + mitt.emit("crud.proxy", { + name: "add" + }); + } + + // 打开编辑 + function rowEdit(data: any) { + mitt.emit("crud.proxy", { + name: "edit", + data: [data] + }); + } + + // 打开追加 + function rowAppend(data: any) { + mitt.emit("crud.proxy", { + name: "append", + data: [data] + }); + } + + // 关闭新增、编辑弹窗 + function rowClose() { + mitt.emit("crud.proxy", { + name: "close" + }); + } + + // 删除请求 + function rowDelete(...selection: any[]) { + const { service, dict } = crud; + + // 参数 + const params = { + ids: selection.map((e) => e[dict.primaryId]) + }; + + // 下一步 + async function next(data: obj) { + return new Promise((resolve, reject) => { + ElMessageBox({ + type: "warning", + title: dict.label.tips, + message: dict.label.deleteConfirm, + confirmButtonText: dict.label.confirm, + cancelButtonText: dict.label.close, + showCancelButton: true, + async beforeClose(action, instance, done) { + if (action === "confirm") { + instance.confirmButtonLoading = true; + + await service[dict.api.delete]({ ...params, ...data }) + .then((res) => { + ElMessage.success(dict.label.deleteSuccess); + + refresh(); + resolve(res); + }) + .catch((err) => { + ElMessage.error(err.message); + reject(err); + }); + + instance.confirmButtonLoading = false; + } + + done(); + } + }).catch(() => null); + }); + } + + // 删除钩子 + if (config.onDelete) { + config.onDelete(selection, { next }); + } else { + next(params); + } + } + + // 代理 + function proxy(name: string, data?: any[]) { + mitt.emit("crud.proxy", { + name, + data + }); + } + + // 获取请求参数 + function getParams() { + return crud.params; + } + + // 替换请求参数 + function setParams(data: obj) { + merge(crud.params, data); + } + + // 设置 + function set(key: string, value: any) { + if (!value) { + return false; + } + + switch (key) { + // 服务 + case "service": + Object.assign(crud.service, value); + crud.service.__proto__ = value.__proto__; + if (value._permission) { + for (const i in value._permission) { + crud.permission[i] = value._permission[i]; + } + } + break; + + // 权限 + case "permission": + if (isFunction(value)) { + merge(crud.permission, value(crud)); + } else { + merge(crud.permission, value); + } + break; + + default: + merge(crud[key], value); + break; + } + } + + // 监听事件 + function on(name: string, callback: fn) { + mitt.on(`${name}-${crud.id}`, callback); + } + + // 默认值 + set("dict", config.dict); + set("service", config.service); + set("permission", config.permission); + + return { + proxy, + set, + on, + rowInfo, + rowAdd, + rowEdit, + rowAppend, + rowDelete, + rowClose, + refresh, + getPermission, + paramsReplace, + getParams, + setParams + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/crud/index.tsx b/cool-admin-vue/packages/crud/src/components/crud/index.tsx new file mode 100644 index 0000000..197dfff --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/crud/index.tsx @@ -0,0 +1,91 @@ +import { defineComponent, getCurrentInstance, inject, provide, reactive } from "vue"; +import { cloneDeep } from "lodash-es"; +import { useHelper } from "./helper"; +import { Mitt } from "../../utils/mitt"; +import { merge, mergeConfig } from "../../utils"; +import { crudList } from "../../emitter"; +import { useConfig } from "../../hooks"; + +export default defineComponent({ + name: "cl-crud", + + props: { + // 组件名 + name: String, + // 是否有边框 + border: Boolean, + // 内间距 + padding: { + type: String, + default: "10px" + } + }, + + setup(props, { slots, expose }) { + // 当前实例 + const inst = getCurrentInstance(); + + // 配置 + const config = reactive(mergeConfig(inject("useCrud__options") || {})); + + // 事件 + const mitt = new Mitt(inst?.uid); + + // 全局配置 + const { dict, permission } = useConfig(); + + // 参数 + const crud = reactive( + merge( + { + id: props.name || inst?.uid, + // 绑定的路由地址 + routePath: location.pathname || "/", + // 表格加载状态 + loading: false, + // 表格已选列 + selection: [], + // 请求参数 + params: { + page: 1, + size: 20 + }, + // 请求服务 + service: {}, + // 字典 + dict: {}, + // 权限 + permission: {}, + // 事件 + mitt, + // 配置 + config + }, + cloneDeep({ dict, permission }) + ) + ); + + // 追加参数 + merge(crud, useHelper({ config, crud, mitt })); + + // 集合 + crudList.push(crud); + + // 值穿透 + provide("crud", crud); + provide("mitt", mitt); + + // 导出 + expose(crud); + + return () => { + return ( +
+ {slots.default?.()} +
+ ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/dialog/index.tsx b/cool-admin-vue/packages/crud/src/components/dialog/index.tsx new file mode 100644 index 0000000..7eaa763 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/dialog/index.tsx @@ -0,0 +1,288 @@ +import { computed, defineComponent, h, provide, ref, watch } from "vue"; +import { Close, FullScreen, Minus } from "@element-plus/icons-vue"; +import { renderNode } from "../../utils/vnode"; +import { isArray, isBoolean } from "lodash-es"; +import { useBrowser } from "../../hooks"; + +export default defineComponent({ + name: "cl-dialog", + + components: { + Close, + FullScreen, + Minus + }, + + props: { + // 是否可见 + modelValue: { + type: Boolean, + default: false + }, + // Extraneous non-props attributes + props: Object, + // 标题 + title: { + type: String, + default: "-" + }, + // 高度 + height: String, + // 宽度 + width: { + type: String, + default: "50%" + }, + // 內间距 + padding: { + type: String, + default: "20px" + }, + // 是否缓存 + keepAlive: Boolean, + // 是否全屏 + fullscreen: Boolean, + // 控制按钮 + controls: { + type: Array, + default: () => ["fullscreen", "close"] + }, + // 隐藏头部元素 + hideHeader: Boolean, + // 关闭前 + beforeClose: Function, + // 是否需要滚动条 + scrollbar: { + type: Boolean, + default: true + }, + // 背景透明 + transparent: Boolean + }, + + emits: ["update:modelValue", "fullscreen-change"], + + setup(props, { emit, expose, slots }) { + const browser = useBrowser(); + + // el-dialog + const Dialog = ref(); + + // 是否全屏 + const fullscreen = ref(false); + + // 是否可见 + const visible = ref(false); + + // 缓存数 + const cacheKey = ref(0); + + // 是否全屏 + const isFullscreen = computed(() => { + return browser && browser.isMini ? true : fullscreen.value; + }); + + // 监听绑定值 + watch( + () => props.modelValue, + (val) => { + visible.value = val; + if (val && !props.keepAlive) { + cacheKey.value += 1; + } + }, + { + immediate: true + } + ); + + // 监听 fullscreen 变化 + watch( + () => props.fullscreen, + (val) => { + fullscreen.value = val; + }, + { + immediate: true + } + ); + + // fullscreen-change 回调 + watch(fullscreen, (val: boolean) => { + emit("fullscreen-change", val); + }); + + // 提供 + provide("dialog", { + visible, + fullscreen: isFullscreen + }); + + // 打开 + function open() { + fullscreen.value = true; + } + + // 关闭 + function close() { + function done() { + onClose(); + } + + if (props.beforeClose) { + props.beforeClose(done); + } else { + done(); + } + } + + // 关闭后 + function onClose() { + emit("update:modelValue", false); + } + + // 切换全屏 + function changeFullscreen(val?: boolean) { + fullscreen.value = isBoolean(val) ? Boolean(val) : !fullscreen.value; + } + + // 双击全屏 + function dblClickFullscreen() { + if (isArray(props.controls) && props.controls.includes("fullscreen")) { + changeFullscreen(); + } + } + + // 渲染头部 + function renderHeader() { + return ( + props.hideHeader || ( +
+ {props.title} + +
+ {props.controls.map((e: any) => { + switch (e) { + //全屏按钮 + case "fullscreen": + if (browser.screen === "xs") { + return null; + } + + // 是否显示全屏按钮 + if (isFullscreen.value) { + return ( + + ); + } else { + return ( + + ); + } + + // 关闭按钮 + case "close": + return ( + + ); + + // 自定义按钮 + default: + return renderNode(e, { + slots + }); + } + })} +
+
+ ) + ); + } + + expose({ + Dialog, + visible, + isFullscreen, + open, + close, + changeFullscreen + }); + + return () => { + return h( + , + {}, + { + header() { + return renderHeader(); + }, + default() { + const height = isFullscreen.value ? "100%" : props.height; + + const style = { + padding: props.padding, + height + }; + + function content() { + return ( +
+ {slots.default?.()} +
+ ); + } + + if (props.scrollbar) { + style.height = "auto"; + + return {content()}; + } else { + return content(); + } + }, + footer() { + const d = slots.footer?.(); + + if (d && d[0]?.shapeFlag) { + return ; + } + + return null; + } + } + ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/error-message/index.tsx b/cool-admin-vue/packages/crud/src/components/error-message/index.tsx new file mode 100644 index 0000000..f150249 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/error-message/index.tsx @@ -0,0 +1,15 @@ +import { defineComponent } from "vue"; + +export default defineComponent({ + name: "cl-error-message", + + props: { + title: String + }, + + setup(props) { + return () => { + return
{props.title}
; + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/filter/index.tsx b/cool-admin-vue/packages/crud/src/components/filter/index.tsx new file mode 100644 index 0000000..851c270 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/filter/index.tsx @@ -0,0 +1,23 @@ +import { defineComponent } from "vue"; + +export default defineComponent({ + name: "cl-filter", + + props: { + label: String + }, + + setup(props, { slots }) { + return () => { + return ( +
+ + {props.label} + + + {slots.default?.()} +
+ ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/flex1/index.tsx b/cool-admin-vue/packages/crud/src/components/flex1/index.tsx new file mode 100644 index 0000000..b22955f --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/flex1/index.tsx @@ -0,0 +1,11 @@ +import { defineComponent } from "vue"; + +export default defineComponent({ + name: "cl-flex1", + + setup() { + return () => { + return
; + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/form-card/index.tsx b/cool-admin-vue/packages/crud/src/components/form-card/index.tsx new file mode 100644 index 0000000..b3fdde4 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/form-card/index.tsx @@ -0,0 +1,51 @@ +import { defineComponent, ref } from "vue"; +import { ArrowDown, ArrowUp } from "@element-plus/icons-vue"; + +export default defineComponent({ + name: "cl-form-card", + + components: { + ArrowDown, + ArrowUp + }, + + props: { + label: String, + // 展开状态 + expand: { + type: Boolean, + default: true + }, + // 是否能展开、收起 + isExpand: { + type: Boolean, + default: true + } + }, + + setup(props, { slots }) { + const visible = ref(props.expand); + + function toExpand() { + if (props.isExpand) { + visible.value = !visible.value; + } + } + + return () => { + return ( +
+
+ {props.label} + + + + + +
+
{slots.default?.()}
+
+ ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/form-tabs/index.tsx b/cool-admin-vue/packages/crud/src/components/form-tabs/index.tsx new file mode 100644 index 0000000..55a8ae3 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/form-tabs/index.tsx @@ -0,0 +1,145 @@ +import { + defineComponent, + h, + nextTick, + onMounted, + PropType, + reactive, + ref, + toRaw, + watch +} from "vue"; +import { isEmpty } from "lodash-es"; +import { useDialog, useRefs } from "../../hooks"; + +export default defineComponent({ + name: "cl-form-tabs", + + props: { + modelValue: [String, Number], + labels: { + type: Array, + default: () => [] + }, + justify: { + type: String as PropType< + "start" | "end" | "left" | "right" | "center" | "justify" | "match-parent" + >, + default: "center" + }, + type: { + type: String as PropType<"card" | "default">, + default: "default" + } + }, + + emits: ["update:modelValue", "change"], + + setup(props, { emit, expose }) { + const { refs, setRefs } = useRefs(); + + // 标识 + const active = ref(""); + + // 切换列表 + const list = ref([]); + + // 下划线 + const line = reactive({ + width: "", + offsetLeft: "", + transform: "", + backgroundColor: "" + }); + + function update(val: any) { + if (!val) { + return false; + } + + nextTick(() => { + const index = list.value.findIndex((e) => e.value === val); + const item = refs[`tab-${index}`]; + + if (item) { + // 下划线位置 + line.width = item.offsetWidth + "px"; + line.transform = `translateX(${item.offsetLeft}px)`; + + // 靠左位置 + let left = item.offsetLeft + item.clientWidth / 2 - 414 / 2 + 15; + + if (left < 0) { + left = 0; + } + + // 设置滚动距离 + refs.tabs.scrollLeft = left; + } + }); + + active.value = val; + emit("update:modelValue", val); + } + + // 监听绑定值变化 + watch(() => props.modelValue, update); + + // 监听值修改 + watch( + () => active.value, + (val) => { + emit("change", val); + } + ); + + useDialog({ + onFullscreen() { + update(active.value); + } + }); + + onMounted(function () { + if (!isEmpty(props.labels)) { + list.value = props.labels; + update(isEmpty(props.modelValue) ? list.value[0].value : props.modelValue); + } + }); + + expose({ + active, + list, + line, + update + }); + + return () => { + return ( +
+
+
    + {list.value.map((e, i) => { + return ( +
  • { + update(e.value); + }}> + {e.icon && {h(toRaw(e.icon))}} + {e.label} +
  • + ); + })} + + {line.width &&
    } +
+
+
+ ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/form/helper/action.ts b/cool-admin-vue/packages/crud/src/components/form/helper/action.ts new file mode 100644 index 0000000..eaf9674 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/form/helper/action.ts @@ -0,0 +1,146 @@ +import { assign } from "lodash-es"; +import { dataset } from "../../../utils"; + +export function useAction({ + config, + form, + Form +}: { + config: ClForm.Config; + form: obj; + Form: Vue.Ref; +}) { + // 设置数据 + function set( + { + prop, + key, + path + }: { prop?: string; key?: "options" | "props" | "hidden" | "hidden-toggle"; path?: string }, + data?: any + ) { + const p: string = path || ""; + + if (path) { + dataset(config, p, data); + } else { + let d: any; + + if (prop) { + function deep(arr: ClForm.Item[]) { + arr.forEach((e) => { + if (e.prop == prop) { + d = e; + } else { + if (e.children) { + deep(e.children); + } + } + }); + } + + deep(config.items); + } + + if (d) { + switch (key) { + case "options": + d.component.options = data; + break; + + case "props": + assign(d.component.props, data); + break; + + case "hidden": + d.hidden = data; + break; + + case "hidden-toggle": + d.hidden = data === undefined ? !d.hidden : !data; + break; + + default: + assign(d, data); + break; + } + } else { + console.error(`[set] ${prop} is not found`); + } + } + } + + // 获取表单值 + function getForm(prop: string) { + return prop ? form[prop] : form; + } + + // 设置表单值 + function setForm(prop: string, value: any) { + form[prop] = value; + } + + // 设置配置 + function setConfig(path: string, value: any) { + set({ path }, value); + } + + // 设置数据 + function setData(prop: string, value: any) { + set({ prop }, value); + } + + // 设置表单项的下拉数据列表 + function setOptions(prop: string, value: any[]) { + set({ prop, key: "options" }, value); + } + + // 设置表单项的组件参数 + function setProps(prop: string, value: any) { + set({ prop, key: "props" }, value); + } + + // 切换表单项的显示、隐藏 + function toggleItem(prop: string, value?: boolean) { + set({ prop, key: "hidden-toggle" }, value); + } + + // 对部分表单项隐藏 + function hideItem(...props: string[]) { + props.forEach((prop) => { + set({ prop, key: "hidden" }, true); + }); + } + + // 对部分表单项显示 + function showItem(...props: string[]) { + props.forEach((prop) => { + set({ prop, key: "hidden" }, false); + }); + } + + // 设置标题 + function setTitle(value: string) { + config.title = value; + } + + // 是否展开表单项 + function collapseItem(e: any) { + Form.value?.clearValidate(e.prop); + e.collapse = !e.collapse; + } + + return { + getForm, + setForm, + setData, + setConfig, + setOptions, + setProps, + toggleItem, + hideItem, + showItem, + setTitle, + collapseItem + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/form/helper/api.ts b/cool-admin-vue/packages/crud/src/components/form/helper/api.ts new file mode 100644 index 0000000..a37190c --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/form/helper/api.ts @@ -0,0 +1,36 @@ +import { useElApi } from "../../../hooks"; + +export function useApi({ Form }: { Form: Vue.Ref }) { + return useElApi( + [ + "open", + "close", + "clear", + "reset", + "submit", + "bindForm", + "changeTab", + "setTitle", + "showLoading", + "hideLoading", + "collapseItem", + "getForm", + "setForm", + "invokeData", + "setData", + "setConfig", + "setOptions", + "setProps", + "toggleItem", + "hideItem", + "showItem", + "validate", + "validateField", + "resetFields", + "scrollToField", + "clearValidate", + "fields" + ], + Form + ); +} diff --git a/cool-admin-vue/packages/crud/src/components/form/helper/index.ts b/cool-admin-vue/packages/crud/src/components/form/helper/index.ts new file mode 100644 index 0000000..f89d7ad --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/form/helper/index.ts @@ -0,0 +1,85 @@ +import { reactive, ref, watch } from "vue"; +import { useConfig } from "../../../hooks"; +import { cloneDeep } from "lodash-es"; + +export function useForm() { + const { dict } = useConfig(); + + // 表单配置 + const config = reactive({ + title: "-", + height: undefined, + width: "50%", + props: { + labelWidth: 100 + }, + on: {}, + op: { + hidden: false, + saveButtonText: dict.label.save, + closeButtonText: dict.label.close, + buttons: ["close", "save"] + }, + dialog: { + closeOnClickModal: false, + appendToBody: true + }, + items: [], + form: {}, + _data: {} + }); + + const Form = ref(); + + // 表单数据 + const form = reactive({}); + + // 表单数据备份 + const oldForm = ref({}); + + // 表单是否可见 + const visible = ref(false); + + // 表单提交保存状态 + const saving = ref(false); + + // 表单加载状态 + const loading = ref(false); + + // 表单禁用状态 + const disabled = ref(false); + + // 监听表单变化 + watch( + () => form, + (val) => { + if (config.on?.change) { + for (const i in val) { + if (form[i] !== oldForm.value[i]) { + config.on?.change(val, i); + } + } + } + + oldForm.value = cloneDeep(val); + }, + { + deep: true + } + ); + + return { + Form, + config, + form, + visible, + saving, + loading, + disabled + }; +} + +export * from "./action"; +export * from "./api"; +export * from "./plugins"; +export * from "./tabs"; diff --git a/cool-admin-vue/packages/crud/src/components/form/helper/plugins.ts b/cool-admin-vue/packages/crud/src/components/form/helper/plugins.ts new file mode 100644 index 0000000..67caf3f --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/form/helper/plugins.ts @@ -0,0 +1,92 @@ +import { getCurrentInstance, type Ref, watch, type WatchStopHandle } from "vue"; +import { useConfig } from "../../../hooks"; +import { uniqueFns } from "../../../utils"; + +export function usePlugins(enable: boolean, { visible }: { visible: Ref }) { + const that: any = getCurrentInstance(); + const { style } = useConfig(); + + interface Event { + onOpen: (() => void)[]; + onClose: (() => void)[]; + onSubmit: ((data: obj) => Promise | obj)[]; + [key: string]: any; + } + + // 事件 + const ev: Event = { + onOpen: [], + onClose: [], + onSubmit: [] + }; + + // 监听器 + let timer: WatchStopHandle | null = null; + + // 插件创建 + function create(plugins: ClForm.Plugin[] = []) { + if (!enable) { + return false; + } + + for (const i in ev) { + ev[i] = []; + } + + // 停止监听 + if (timer) { + timer(); + } + + // 执行 + uniqueFns([...(style.form.plugins || []), ...plugins]).forEach((p) => { + const d: any = { + exposed: that.exposed + }; + + for (const i in ev) { + d[i] = (cb: any) => { + ev[i].push(cb); + }; + } + + p(d); + }); + + timer = watch( + visible, + (val) => { + if (val) { + setTimeout(() => { + ev.onOpen.forEach((e) => e()); + }, 10); + } else { + ev.onClose.forEach((e) => e()); + } + }, + { + immediate: true + } + ); + } + + // 表单提交 + async function submit(data: any) { + let d = data; + + for (let i = 0; i < ev.onSubmit.length; i++) { + const d2 = await ev.onSubmit[i](d); + + if (d2) { + d = d2; + } + } + + return d; + } + + return { + create, + submit + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/form/helper/tabs.ts b/cool-admin-vue/packages/crud/src/components/form/helper/tabs.ts new file mode 100644 index 0000000..e067616 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/form/helper/tabs.ts @@ -0,0 +1,151 @@ +import { computed, ref } from "vue"; + +export function useTabs({ config, Form }: { config: ClForm.Config; Form: Vue.Ref }) { + // 选中 + const active = ref(); + + // 列表 + const list = computed(() => { + return get()?.props?.labels || []; + }); + + // 获取选项 + function getItem(value: any) { + return list.value.find((e) => e.value == value); + } + + // 是否已加载 + function isLoaded(value: any) { + const d = getItem(value); + return d?.lazy ? d.loaded : true; + } + + // 加载后 + function onLoad(value: any) { + const d = getItem(value); + d!.loaded = true; + } + + // 查找分组 + function toGroup(opts: { config: ClForm.Config; prop: string; refs: any }) { + if (active.value) { + let name; + + // 查找标签上绑定的数据 + const el = opts.refs.form.querySelector(`[data-prop="${opts.prop}"]`); + + // 各自判断 + if (el) { + name = el?.getAttribute("data-group"); + } else { + function deep(d: ClForm.Item) { + if (d.prop == opts.prop) { + name = d.group; + } else { + if (d.children) { + d.children.forEach(deep); + } + } + } + + config.items.forEach(deep); + } + + if (name) { + set(name); + } + } + } + + // 获取参数 + function get() { + return config.items.find((e) => e.type === "tabs"); + } + + // 设置参数 + function set(data: any) { + active.value = data; + } + + // 清空 + function clear() { + // 清空选中 + active.value = undefined; + + // 清空加载状态 + list.value.forEach((e) => { + if (e.lazy && e.loaded) { + e.loaded = undefined; + } + }); + } + + // 切换 + function change(value: any, isValid = true) { + return new Promise((resolve: Function, reject: Function) => { + function next() { + active.value = value; + resolve(); + } + + if (isValid) { + let isError = false; + + const arr = config.items + .filter((e) => e.group == active.value && !e._hidden && e.prop) + .map((e) => { + return new Promise((r: Function) => { + // 验证表单 + Form.value.validateField(e.prop, (valid: string) => { + if (valid) { + isError = true; + } + + r(valid); + }); + }); + }); + + Promise.all(arr).then((msg) => { + if (isError) { + reject(msg.filter(Boolean)); + } else { + next(); + } + }); + } else { + next(); + } + }); + } + + // 合并 + function mergeProp(item: ClForm.Item) { + const d = get(); + + if (d && d.props) { + const { mergeProp, labels = [] } = d.props; + + if (mergeProp) { + const t = labels.find((e) => e.value == item.group); + + if (t && t.name) { + item.prop = `${t.name}-${item.prop}`; + } + } + } + } + + return { + active, + list, + isLoaded, + onLoad, + get, + set, + change, + clear, + mergeProp, + toGroup + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/form/index.tsx b/cool-admin-vue/packages/crud/src/components/form/index.tsx new file mode 100644 index 0000000..c27b4d4 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/form/index.tsx @@ -0,0 +1,683 @@ +import { defineComponent, h, nextTick } from "vue"; +import { assign, cloneDeep, isBoolean, isFunction, keys } from "lodash-es"; +import { useAction, useForm, usePlugins, useTabs } from "./helper"; +import { useBrowser, useConfig, useElApi, useRefs } from "../../hooks"; +import { getValue, merge } from "../../utils"; +import formHook from "../../utils/form-hook"; +import { renderNode } from "../../utils/vnode"; + +export default defineComponent({ + name: "cl-form", + + props: { + name: String, + inner: Boolean, + inline: Boolean, + enablePlugin: { + type: Boolean, + default: true + } + }, + + setup(props, { expose, slots }) { + const { refs, setRefs } = useRefs(); + const { style, dict } = useConfig(); + const browser = useBrowser(); + const { Form, config, form, visible, saving, loading, disabled } = useForm(); + + // 关闭的操作类型 + let closeAction: ClForm.CloseAction = "close"; + + // 旧表单数据 + let defForm: obj | undefined; + + // 选项卡 + const Tabs = useTabs({ config, Form }); + + // 操作 + const Action = useAction({ config, form, Form }); + + // 方法 + const ElFormApi = useElApi( + [ + "validate", + "validateField", + "resetFields", + "scrollToField", + "clearValidate", + "fields" + ], + Form + ); + + // 插件 + const plugin = usePlugins(props.enablePlugin, { visible }); + + // 显示加载中 + function showLoading() { + loading.value = true; + } + + // 隐藏加载 + function hideLoading() { + loading.value = false; + } + + // 设置是否禁用 + function setDisabled(val: boolean = true) { + disabled.value = val; + } + + // 请求表单保存状态 + function done() { + saving.value = false; + } + + // 关闭表单 + function close(action?: ClForm.CloseAction) { + if (action) { + closeAction = action; + } + + beforeClose(() => { + visible.value = false; + done(); + }); + } + + // 关闭前 + function beforeClose(done: fn) { + if (config.on?.close) { + config.on.close(closeAction, done); + } else { + done(); + } + } + + // 关闭后 + function onClosed() { + Tabs.clear(); + Form.value?.clearValidate(); + } + + // 清空表单验证 + function clear() { + for (const i in form) { + delete form[i]; + } + + setTimeout(() => { + Form.value?.clearValidate(); + }, 0); + } + + // 重置 + function reset() { + if (defForm) { + for (const i in defForm) { + form[i] = cloneDeep(defForm[i]); + } + } + } + + // 转换表单值,处理多层级等数据 + function invokeData(d: any) { + for (const i in d) { + if (i.includes("-")) { + // 结构参数 + const [a, ...arr] = i.split("-"); + + // 关键值的key + const k: string = arr.pop() || ""; + + if (!d[a]) { + d[a] = {}; + } + + let f: any = d[a]; + + // 设置默认值 + arr.forEach((e) => { + if (!f[e]) { + f[e] = {}; + } + + f = f[e]; + }); + + // 设置关键值 + f[k] = d[i]; + + delete d[i]; + } + } + } + + // 表单提交 + function submit(callback?: fn) { + // 验证表单 + Form.value.validate(async (valid: boolean, error: any) => { + if (valid) { + saving.value = true; + + // 拷贝表单值 + const d = cloneDeep(form); + + config.items.forEach((e) => { + function deep(e: ClForm.Item) { + if (e.prop) { + // 过滤隐藏的表单项 + if (e._hidden) { + if (e.prop) { + delete d[e.prop]; + } + } + + // hook 提交处理 + if (e.hook) { + formHook.submit({ + ...e, + value: e.prop ? d[e.prop] : undefined, + form: d + }); + } + } + + if (e.children) { + e.children.forEach(deep); + } + } + + deep(e); + }); + + // 处理数据 + invokeData(d); + + const submit = callback || config.on?.submit; + + // 提交事件 + if (submit) { + submit(await plugin.submit(d), { + close() { + close("save"); + }, + done + }); + } else { + done(); + } + } else { + // 切换到对应的选项卡 + Tabs.toGroup({ + refs, + config, + prop: keys(error)[0] + }); + } + }); + } + + // 打开表单 + function open(options?: ClForm.Options, plugins?: ClForm.Plugin[]) { + if (!options) { + return console.error("Options is not null"); + } + + // 清空 + if (options.isReset !== false) { + clear(); + } + + // 显示对话框 + visible.value = true; + + // 默认关闭方式 + closeAction = "close"; + + // 合并配置 + for (const i in config) { + switch (i) { + // 表单项 + case "items": + function deep(arr: any[]): any[] { + return arr.map((e) => { + const d = getValue(e); + + return { + ...d, + children: d?.children ? deep(d.children) : undefined + }; + }); + } + + config.items = deep(options.items || []); + break; + // 事件、参数、操作 + case "on": + case "op": + case "props": + case "dialog": + case "_data": + merge(config[i], options[i] || {}); + break; + // 其他 + default: + config[i] = options[i]; + break; + } + } + + // 预设表单值 + if (options?.form) { + for (const i in options.form) { + form[i] = options.form[i]; + } + } + + // 设置表单数据 + config.items.forEach((e) => { + function deep(e: ClForm.Item) { + if (e.prop) { + // 解析 prop + if (e.prop.includes(".")) { + e.prop = e.prop.replace(/\./g, "-"); + } + + // prop 合并 + Tabs.mergeProp(e); + + // hook 绑定值 + formHook.bind({ + ...e, + value: form[e.prop] !== undefined ? form[e.prop] : cloneDeep(e.value), + form + }); + + // 表单验证 + if (e.required) { + e.rules = { + required: true, + message: dict.label.nonEmpty.replace("{label}", e.label || "") + }; + } + } + + // 设置 tabs 默认值 + if (e.type == "tabs") { + Tabs.set(e.value); + } + + // 子集 + if (e.children) { + e.children.forEach(deep); + } + } + + deep(e); + }); + + // 设置默认值 + if (!defForm) { + defForm = cloneDeep(form); + } + + // 创建插件 + plugin.create(plugins); + + // 打开回调 + nextTick(() => { + setTimeout(() => { + // 打开事件 + if (config.on?.open) { + config.on.open(form); + } + }, 10); + }); + } + + // 绑定表单数据 + function bindForm(data: any) { + config.items.forEach((e) => { + function deep(e: ClForm.Item) { + formHook.bind({ + ...e, + value: e.prop ? data[e.prop] : undefined, + form: data + }); + + if (e.children) { + e.children.forEach(deep); + } + } + + deep(e); + }); + + assign(form, data); + } + + // 渲染表单项 + function renderFormItem(e: ClForm.Item) { + const { isDisabled } = config._data; + + if (e.type == "tabs") { + return ( + + ); + } + + // 是否隐藏 + e._hidden = parseHidden(e.hidden, { + scope: form + }); + + // 分组显示 + const inGroup = e.group ? e.group === Tabs.active.value : true; + + // 是否已加载完成 + const isLoaded = e.component && Tabs.isLoaded(e.group); + + // 表单项 + const FormItem = h( + , + e.props, + { + label() { + if (e.renderLabel) { + return renderNode(e.renderLabel, { + scope: form, + render: "slot", + slots + }); + } else { + return e.label; + } + }, + default() { + return ( +
+
+ {["prepend", "component", "append"] + .filter((k) => e[k]) + .map((name) => { + const children = e.children && ( +
+ + {e.children.map(renderFormItem)} + +
+ ); + + const Item = renderNode(e[name], { + item: e, + prop: e.prop, + scope: form, + slots, + children, + _data: { + isDisabled + } + }); + + return ( +
+ {Item} +
+ ); + })} +
+ + {isBoolean(e.collapse) && ( +
{ + Action.collapseItem(e); + }}> + + {e.collapse + ? dict.label.seeMore + : dict.label.hideContent} + +
+ )} +
+ ); + } + } + ); + + let span = e.span || style.form.span; + + if (browser.isMini) { + span = 24; + } + + // 是否行内 + const Item = props.inline ? ( + FormItem + ) : ( + + {FormItem} + + ); + + return isLoaded ? Item : null; + } + + // 渲染表单 + function renderContainer() { + // 表单项列表 + const children = config.items.map(renderFormItem); + + // 表单标签位置 + const labelPosition = + browser.isMini && !props.inline + ? "top" + : config.props.labelPosition || style.form.labelPosition; + + return ( +
+ {h( + { + submit(); + e.preventDefault(); + }} + />, + { + ...config.props, + labelPosition + }, + { + default: () => { + const items = [ + slots.prepend && slots.prepend({ scope: form }), + children, + slots.append && slots.append({ scope: form }) + ]; + + return ( +
+ {props.inline ? ( + items + ) : ( + {items} + )} +
+ ); + } + } + )} +
+ ); + } + + // 渲染表单底部按钮 + function renderFooter() { + const { hidden, buttons, saveButtonText, closeButtonText, justify } = config.op; + + if (hidden) { + return null; + } + + const Btns = buttons?.map((e: any) => { + switch (e) { + case "save": + return ( + { + submit(); + }}> + {saveButtonText} + + ); + case "close": + return ( + { + close("close"); + }}> + {closeButtonText} + + ); + default: + return renderNode(e, { + scope: form, + slots, + custom() { + return ( + { + e.onClick({ scope: form }); + }}> + {e.label} + + ); + } + }); + } + }); + + return ( + + ); + } + + // Tools + function parseHidden(value: any, { scope }: any) { + if (isBoolean(value)) { + return value; + } else if (isFunction(value)) { + return value({ scope }); + } + + return false; + } + + const ctx = { + name: props.name, + refs, + Form, + visible, + saving, + form, + config, + loading, + disabled, + open, + close, + done, + clear, + reset, + submit, + invokeData, + bindForm, + showLoading, + hideLoading, + setDisabled, + Tabs, + ...Action, + ...ElFormApi + }; + + expose(ctx); + + return () => { + if (props.inner) { + return ( + visible.value && ( +
+ {renderContainer()} + {renderFooter()} +
+ ) + ); + } else { + return h( + , + { + title: config.title, + height: config.height, + width: config.width, + ...config.dialog, + beforeClose, + onClosed, + keepAlive: false + }, + { + default() { + return renderContainer(); + }, + footer() { + return renderFooter(); + } + } + ); + } + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/index.tsx b/cool-admin-vue/packages/crud/src/components/index.tsx new file mode 100644 index 0000000..b23c344 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/index.tsx @@ -0,0 +1,50 @@ +import { App } from "vue"; +import Crud from "./crud"; +import AddBtn from "./add-btn"; +import AdvBtn from "./adv/btn"; +import AdvSearch from "./adv/search"; +import Flex from "./flex1"; +import Form from "./form"; +import FormTabs from "./form-tabs"; +import FormCard from "./form-card"; +import MultiDeleteBtn from "./multi-delete-btn"; +import Pagination from "./pagination"; +import RefreshBtn from "./refresh-btn"; +import SearchKey from "./search-key"; +import Table from "./table"; +import Upsert from "./upsert"; +import Dialog from "./dialog"; +import Filter from "./filter"; +import Search from "./search"; +import ErrorMessage from "./error-message"; +import Row from "./row"; +import ContextMenu from "./context-menu"; + +export const components: { [key: string]: any } = { + Crud, + AddBtn, + AdvBtn, + AdvSearch, + Flex, + Form, + FormTabs, + FormCard, + MultiDeleteBtn, + Pagination, + RefreshBtn, + SearchKey, + Table, + Upsert, + Dialog, + Filter, + Search, + ErrorMessage, + Row, + ContextMenu +}; + +export function useComponent(app: App) { + for (const i in components) { + app.component(components[i].name, components[i]); + } +} diff --git a/cool-admin-vue/packages/crud/src/components/multi-delete-btn/index.tsx b/cool-admin-vue/packages/crud/src/components/multi-delete-btn/index.tsx new file mode 100644 index 0000000..a1d9433 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/multi-delete-btn/index.tsx @@ -0,0 +1,27 @@ +import { defineComponent } from "vue"; +import { useConfig, useCore } from "../../hooks"; + +export default defineComponent({ + name: "cl-multi-delete-btn", + + setup(_, { slots }) { + const { crud } = useCore(); + const { style } = useConfig(); + + return () => { + return ( + crud.getPermission("delete") && ( + { + crud.rowDelete(...crud.selection); + }}> + {slots.default?.() || crud.dict.label.multiDelete} + + ) + ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/pagination/index.tsx b/cool-admin-vue/packages/crud/src/components/pagination/index.tsx new file mode 100644 index 0000000..c1ff3dd --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/pagination/index.tsx @@ -0,0 +1,90 @@ +import { defineComponent, h, onMounted, onUnmounted, ref } from "vue"; +import { useBrowser, useConfig, useCore } from "../../hooks"; + +export default defineComponent({ + name: "cl-pagination", + + setup(_, { expose }) { + const { crud, mitt } = useCore(); + const { style } = useConfig(); + const browser = useBrowser(); + + // 总数 + const total = ref(0); + + // 当前页数 + const currentPage = ref(1); + + // 每页大小 + const pageSize = ref(20); + + // 页数发生变化 + function onCurrentChange(index: number) { + crud.refresh({ + page: index + }); + } + + // 条目发生变化 + function onSizeChange(size: number) { + crud.refresh({ + page: 1, + size + }); + } + + // 设置分页信息 + function setPagination(res: obj) { + if (res) { + currentPage.value = res.currentPage || res.page || 1; + pageSize.value = res.pageSize || res.size || 20; + total.value = res.total || 0; + crud.params.size = pageSize.value; + } + } + + // 数据刷新 + function onRefresh(res: ClCrud.Response["page"]) { + setPagination(res.pagination); + } + + // 监听刷新事件 + onMounted(() => { + mitt.on("crud.refresh", onRefresh); + }); + + // 移除监听事件 + onUnmounted(() => { + mitt.off("crud.refresh", onRefresh); + }); + + expose({ + total, + currentPage, + pageSize, + setPagination + }); + + return () => { + return h( + , + { + onSizeChange, + onCurrentChange, + total: total.value, + currentPage: currentPage.value, + pageSize: pageSize.value + } + ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/refresh-btn/index.tsx b/cool-admin-vue/packages/crud/src/components/refresh-btn/index.tsx new file mode 100644 index 0000000..df8b8cd --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/refresh-btn/index.tsx @@ -0,0 +1,23 @@ +import { defineComponent } from "vue"; +import { useConfig, useCore } from "../../hooks"; + +export default defineComponent({ + name: "cl-refresh-btn", + + setup(_, { slots }) { + const { crud } = useCore(); + const { style } = useConfig(); + + return () => { + return ( + { + crud.refresh(); + }}> + {slots.default?.() || crud.dict.label.refresh} + + ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/row/index.tsx b/cool-admin-vue/packages/crud/src/components/row/index.tsx new file mode 100644 index 0000000..4ea69c6 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/row/index.tsx @@ -0,0 +1,11 @@ +import { defineComponent } from "vue"; + +export default defineComponent({ + name: "cl-row", + + setup(_, { slots }) { + return () => { + return {slots.default && slots.default()}; + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/search-key/index.tsx b/cool-admin-vue/packages/crud/src/components/search-key/index.tsx new file mode 100644 index 0000000..4b805e2 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/search-key/index.tsx @@ -0,0 +1,179 @@ +import { computed, defineComponent, type PropType, ref, useModel } from "vue"; +import { useConfig, useCore } from "../../hooks"; +import { parsePx } from "../../utils"; +import { debounce } from "lodash-es"; + +export default defineComponent({ + name: "cl-search-key", + + props: { + // 绑定值 + modelValue: String, + // 选中字段 + field: { + type: String, + default: "keyWord" + }, + // 字段列表 + fieldList: { + type: Array as PropType>, + default: () => [] + }, + // 搜索时的钩子 + onSearch: Function, + // 输入框占位内容 + placeholder: String, + // 宽度 + width: { + type: [String, Number], + default: 280 + }, + // 是否实时刷新 + refreshOnInput: Boolean + }, + + emits: ["update:modelValue", "change", "field-change"], + + setup(props, { emit, expose }) { + const { crud } = useCore(); + const { style } = useConfig(); + + // 选中字段 + const selectField = ref(props.field); + + // 加载状态 + const loading = ref(false); + + // 文字提示 + const placeholder = computed(() => { + if (props.placeholder) { + return props.placeholder; + } else { + const item = props.fieldList.find((e) => e.value == selectField.value); + + if (item) { + return crud.dict.label.placeholder + item.label; + } else { + return crud.dict.label.searchKey; + } + } + }); + + // 搜索内容 + const value = useModel(props, "modelValue"); + + // 锁 + let lock = false; + + // 搜索 + function search() { + if (!lock) { + const params: obj = {}; + + props.fieldList.forEach((e) => { + params[e.value] = undefined; + }); + + async function next(newParams?: obj) { + loading.value = true; + + await crud + .refresh({ + page: 1, + ...params, + [selectField.value]: value.value || undefined, + ...newParams + }) + .catch((err) => { + console.error(err); + }); + + loading.value = false; + } + + if (props.onSearch) { + props.onSearch(params, { next }); + } else { + next(); + } + } + } + + // 回车搜索 + function onKeydown({ key }: KeyboardEvent) { + if (key === "Enter") { + search(); + } + } + + // 监听变化 + function onChange(val: string) { + if (!props.refreshOnInput) { + search(); + lock = true; + + setTimeout(() => { + lock = false; + }, 300); + + emit("change", val); + } + } + + // 监听输入 + const onInput = debounce((val: string) => { + emit("change", val); + + if (props.refreshOnInput) { + search(); + } + }, 300); + + // 监听字段选择 + function onFieldChange() { + emit("field-change", selectField.value); + value.value = undefined; + } + + expose({ + search + }); + + return () => { + return ( +
+ 0} + onChange={onFieldChange}> + {props.fieldList.map((e, i) => ( + + ))} + + +
+ + + + {crud.dict.label.search} + +
+
+ ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/search/helper/plugins.ts b/cool-admin-vue/packages/crud/src/components/search/helper/plugins.ts new file mode 100644 index 0000000..05628e6 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/search/helper/plugins.ts @@ -0,0 +1,21 @@ +import { getCurrentInstance } from "vue"; +import { useConfig } from "../../../hooks"; +import { uniqueFns } from "../../../utils"; + +export function usePlugins() { + const that: any = getCurrentInstance(); + const { style } = useConfig(); + + // 插件创建 + function create(plugins: ClSearch.Plugin[] = []) { + uniqueFns([...(style.search?.plugins || []), ...plugins]).forEach((p) => { + p({ + exposed: that.exposed + }); + }); + } + + return { + create + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/search/index.tsx b/cool-admin-vue/packages/crud/src/components/search/index.tsx new file mode 100644 index 0000000..b4b89d2 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/search/index.tsx @@ -0,0 +1,307 @@ +import { useConfig, useCore, useForm, useProxy, useRefs } from "../../hooks"; +import { + defineComponent, + h, + inject, + mergeProps, + nextTick, + onMounted, + onUnmounted, + PropType, + reactive, + ref +} from "vue"; +import { useApi } from "../form/helper"; +import { Bottom, Refresh, Search, Top } from "@element-plus/icons-vue"; +import { mitt } from "../../utils/mitt"; +import { isArray, isEmpty } from "lodash-es"; +import { usePlugins } from "./helper/plugins"; + +export default defineComponent({ + name: "cl-search", + + props: { + // 是否行内 + inline: { + type: Boolean, + default: true + }, + + // cl-form 表单配置 + props: { + type: Object, + default: () => ({}) + }, + + // 表单值 + data: { + type: Object, + default: () => ({}) + }, + + // 列 + items: { + type: Array as PropType, + default: () => [] + }, + + // 是否需要重置按钮 + resetBtn: { + type: Boolean, + default: false + }, + + // 是否需要折叠 + collapse: { + type: Boolean, + default: false + }, + + // 初始化 + onLoad: Function, + + // 搜索时钩子 + onSearch: Function + }, + + emits: ["reset"], + + setup(props, { slots, expose, emit }) { + const { crud } = useCore(); + const { refs, setRefs } = useRefs(); + const { style } = useConfig(); + const plugin = usePlugins(); + + // 配置 + const config = reactive( + mergeProps(props, inject("useSearch__options") || {}) + ); + + // cl-form + const Form = useForm(); + + // 加载中 + const loading = ref(false); + + // 展开 + const isExpand = ref(!config.collapse); + + // 显示展开、收起按钮 + const showExpandBtn = ref(false); + + // 搜索 + function search(params?: any) { + const form = Form.value?.getForm(); + + async function next(data?: any) { + loading.value = true; + + const d = { + page: 1, + ...form, + ...data, + ...params + }; + + for (const i in d) { + if (d[i] === "") { + d[i] = undefined; + } + } + + const res = await crud.refresh(d); + + loading.value = false; + + return res; + } + + if (config.onSearch) { + config.onSearch(form, { next }); + } else { + next(); + } + } + + // 重置 + function reset() { + const d: any = {}; + + config.items?.map((e) => { + if (typeof e.hook != "string" && e.hook?.reset) { + const props = e.hook.reset(e.prop!); + + if (isArray(props)) { + props.forEach((prop) => { + d[prop] = undefined; + }); + } + } + + d[e.prop!] = undefined; + }); + + // 重置表单 + Form.value?.reset(); + + // 列表刷新 + search(d); + + // 重置事件 + emit("reset", d); + } + + // 收起、展开 + function expand() { + isExpand.value = !isExpand.value; + + nextTick(() => { + crud?.["cl-table"].calcMaxHeight(); + }); + } + + // 判断展开状态 + function onExpand() { + if (config.collapse) { + const el = refs.form?.querySelector(".cl-form__items"); + + if (el) { + showExpandBtn.value = el.clientHeight > 84; + } + } + } + + function onResize() { + onExpand(); + } + + const ctx = { + search, + reset, + Form, + config, + ...useApi({ Form }) + }; + + useProxy(ctx); + expose(ctx); + plugin.create(config.plugins); + + onMounted(() => { + Form.value?.open({ + op: { + hidden: true + }, + props: { + labelPosition: "right", + ...config.props + }, + items: config.items?.map((e) => { + return { + col: { + sm: 12, + md: 8, + xs: 24, + lg: 6 + }, + ...e + }; + }), + form: config.data, + on: { + open(data) { + config.onLoad?.(data); + onExpand(); + }, + change(data, prop) { + config.onChange?.(data, prop); + } + } + }); + + mitt.on("resize", onResize); + }); + + onUnmounted(() => { + mitt.off("resize", onResize); + }); + + return () => { + const btnEl = ( + + {/* 重置按钮 */} + {config.resetBtn && ( + + {crud.dict.label.reset} + + )} + + {/* 搜索按钮 */} + { + search(); + }}> + {crud.dict.label.search} + + + {/* 自定义按钮 */} + {slots?.buttons?.(Form.value?.form)} + + ); + + return ( +
+
+ {h( + , + {}, + { + append() { + return config.collapse ? null : isEmpty(config.items) || btnEl; + }, + ...slots + } + )} +
+ + {config.collapse && ( +
+ {showExpandBtn.value && ( + + + {isExpand.value + ? crud.dict.label.collapse + : crud.dict.label.expand} + + {isExpand.value ? : } + + )} + + + + {btnEl} +
+ )} +
+ ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/table/helper/data.ts b/cool-admin-vue/packages/crud/src/components/table/helper/data.ts new file mode 100644 index 0000000..53ac4a8 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/helper/data.ts @@ -0,0 +1,35 @@ +import { nextTick, ref } from "vue"; +import { useCore } from "../../../hooks"; + +export function useData({ config, Table }: { config: ClTable.Config; Table: Vue.Ref }) { + const { mitt, crud } = useCore(); + + // 列表数据 + const data = ref([]); + + // 设置数据 + function setData(list: obj[]) { + data.value = list; + } + + // 监听刷新 + mitt.on("crud.refresh", ({ list }: ClCrud.Response["page"]) => { + data.value = list; + + // 显示选中行 + nextTick(() => { + crud.selection.forEach((e) => { + const d = list.find((a) => a[config.rowKey] == e[config.rowKey]); + + if (d) { + Table.value.toggleRowSelection(d, true); + } + }); + }); + }); + + return { + data, + setData + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/table/helper/header.tsx b/cool-admin-vue/packages/crud/src/components/table/helper/header.tsx new file mode 100644 index 0000000..3f20a14 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/helper/header.tsx @@ -0,0 +1,91 @@ +import { CloseBold, Search } from "@element-plus/icons-vue"; +import { h } from "vue"; +import { useCrud } from "../../../hooks"; +import { renderNode } from "../../../utils/vnode"; + +export function renderHeader(item: ClTable.Column, { scope, slots }: any) { + const crud = useCrud(); + + const slot = slots[`header-${item.prop}`]; + + if (slot) { + return slot({ + scope + }); + } + + if (!item.search || !item.search.component) { + return item.label; + } + + // 显示输入框 + function show(e: MouseEvent) { + item.search.isInput = true; + e.stopPropagation(); + } + + // 隐藏输入框 + function hide() { + if (item.search.value !== undefined) { + item.search.value = undefined; + refresh(); + } + + item.search.isInput = false; + } + + // 刷新 + function refresh(params?: any) { + const { value } = item.search; + + crud.value?.refresh({ + page: 1, + [item.prop]: value === "" ? undefined : value, + ...params + }); + } + + // 文字 + const text = ( +
+ {item.search.icon?.() ?? } + + {item.renderLabel ? item.renderLabel(scope) : item.label} +
+ ); + + // 输入框 + const input = h(renderNode(item.search.component, { prop: item.prop }), { + clearable: true, + modelValue: item.search.value, + onVnodeMounted(vn) { + // 默认聚焦 + vn.component?.exposed?.focus?.(); + }, + onInput(val: any) { + item.search.value = val; + }, + onChange(val: any) { + item.search.value = val; + + // 更改时刷新列表 + if (item.search.refreshOnChange) { + refresh(); + } + } + }); + + return ( +
+
{item.search.isInput ? input : text}
+ + {item.search.isInput && ( +
+ + + +
+ )} +
+ ); +} diff --git a/cool-admin-vue/packages/crud/src/components/table/helper/height.ts b/cool-admin-vue/packages/crud/src/components/table/helper/height.ts new file mode 100644 index 0000000..76f0586 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/helper/height.ts @@ -0,0 +1,99 @@ +import { debounce, last } from "lodash-es"; +import { nextTick, onActivated, onMounted, ref } from "vue"; +import { addClass, removeClass } from "../../../utils"; +import { mitt } from "../../../utils/mitt"; + +// 表格高度 +export function useHeight({ config, Table }: { Table: Vue.Ref; config: ClTable.Config }) { + // 最大高度 + const maxHeight = ref(0); + + // 计算表格最大高度 + const update = debounce(async () => { + await nextTick(); + + let vm = Table.value; + + if (vm) { + while (!vm.$parent?.$el.className?.includes("cl-crud")) { + vm = vm.$parent; + } + + if (vm) { + const p = vm.$parent.$el; + + await nextTick(); + + // 高度 + let h = 0; + + // 表格下间距 + if (vm.$el.className.includes("cl-row")) { + h += 10; + } + + // 上高度 + h += vm.$el.offsetTop; + + // 获取下高度 + let n = vm.$el.nextSibling; + + // 集合 + const arr = [vm.$el]; + + while (n) { + if (n.offsetHeight > 0) { + h += n.offsetHeight || 0; + arr.push(n); + + if (n.className.includes("cl-row--last")) { + h += 10; + } + } + + n = n.nextSibling; + } + + // 移除 cl-row--last + arr.forEach((e) => { + removeClass(e, "cl-row--last"); + }); + + // 最后一个可视元素 + const z = last(arr); + + // 去掉 cl-row 下间距高度 + if (z?.className.includes("cl-row")) { + addClass(z, "cl-row--last"); + h -= 10; + } + + // 上间距 + h += parseInt(window.getComputedStyle(p).paddingTop, 10); + + // 设置最大高度 + if (config.autoHeight) { + maxHeight.value = p.clientHeight - h; + } + } + } + }, 100); + + // 窗口大小改变事件 + mitt.on("resize", () => { + update(); + }); + + onMounted(function () { + update(); + }); + + onActivated(function () { + update(); + }); + + return { + maxHeight, + calcMaxHeight: update + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/table/helper/index.ts b/cool-admin-vue/packages/crud/src/components/table/helper/index.ts new file mode 100644 index 0000000..27f6f7d --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/helper/index.ts @@ -0,0 +1,43 @@ +import { inject, reactive, ref } from "vue"; +import { useConfig } from "../../../hooks"; +import { getValue, mergeConfig } from "../../../utils"; +import type { TableInstance } from "element-plus"; + +export function useTable(props: any) { + const { style } = useConfig(); + + const Table = ref(); + + // 配置 + const config = reactive(mergeConfig(props, inject("useTable__options") || {})); + + // 列表项动态处理 + config.columns = (config.columns || []).map((e) => getValue(e)); + + // 自动高度 + config.autoHeight = config.autoHeight ?? style.table.autoHeight; + + // 右键菜单 + config.contextMenu = config.contextMenu ?? style.table.contextMenu; + + // 事件 + if (!config.on) { + config.on = {}; + } + + // 参数 + if (!config.props) { + config.props = {}; + } + + return { Table, config }; +} + +export * from "./data"; +export * from "./height"; +export * from "./op"; +export * from "./render"; +export * from "./row"; +export * from "./selection"; +export * from "./sort"; +export * from "./header"; diff --git a/cool-admin-vue/packages/crud/src/components/table/helper/op.ts b/cool-admin-vue/packages/crud/src/components/table/helper/op.ts new file mode 100644 index 0000000..556be31 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/helper/op.ts @@ -0,0 +1,69 @@ +import { nextTick, ref } from "vue"; +import { useCore } from "../../../hooks"; +import { isArray, isBoolean } from "lodash-es"; + +export function useOp({ config }: { config: ClTable.Config }) { + const { mitt } = useCore(); + + // 是否可见,用于解决一些显示隐藏的副作用 + const visible = ref(true); + + // 重新构建 + async function reBuild(cb?: fn) { + visible.value = false; + + await nextTick(); + + if (cb) { + cb(); + } + + visible.value = true; + + await nextTick(); + + mitt.emit("resize"); + } + + // 显示列 + function showColumn(prop: string | string[], status?: boolean) { + const keys = isArray(prop) ? prop : [prop]; + + // 多级表头 + function deep(list: ClTable.Column[]) { + list.forEach((e) => { + if (e.prop && keys.includes(e.prop)) { + e.hidden = isBoolean(status) ? !status : false; + } + + if (e.children) { + deep(e.children); + } + }); + } + + deep(config.columns); + } + + // 隐藏列 + function hideColumn(prop: string | string[]) { + showColumn(prop, false); + } + + // 设置列 + function setColumns(list: ClTable.Column[]) { + if (list) { + reBuild(() => { + config.columns.splice(0, config.columns.length, ...list); + }); + } + } + + return { + visible, + reBuild, + showColumn, + hideColumn, + setColumns + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/table/helper/plugins.ts b/cool-admin-vue/packages/crud/src/components/table/helper/plugins.ts new file mode 100644 index 0000000..4d47605 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/helper/plugins.ts @@ -0,0 +1,22 @@ +import { getCurrentInstance } from "vue"; +import { useConfig } from "../../../hooks"; +import { uniqueFns } from "../../../utils"; + +export function usePlugins() { + const that: any = getCurrentInstance(); + const { style } = useConfig(); + + // 插件创建 + function create(plugins: ClTable.Plugin[] = []) { + // 执行 + uniqueFns([...(style.table.plugins || []), ...plugins]).forEach((p) => { + p({ + exposed: that.exposed + }); + }); + } + + return { + create + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/table/helper/render.tsx b/cool-admin-vue/packages/crud/src/components/table/helper/render.tsx new file mode 100644 index 0000000..21c5bbc --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/helper/render.tsx @@ -0,0 +1,327 @@ +import { h, useSlots } from "vue"; +import { useBrowser, useConfig, useCore } from "../../../hooks"; +import { assign, cloneDeep, isArray, isEmpty, isObject, isString, orderBy } from "lodash-es"; +import { deepFind, getValue } from "../../../utils"; +import { renderNode } from "../../../utils/vnode"; +import { renderHeader } from "./header"; + +// 渲染 +export function useRender() { + const browser = useBrowser(); + const slots = useSlots(); + const { crud } = useCore(); + const { style } = useConfig(); + + // 渲染列 + function renderColumn(columns: ClTable.Column[]) { + const arr = columns.map((e) => { + const d = getValue(e); + + if (!d.orderNum) { + d.orderNum = 0; + } + + return d; + }); + + return orderBy(arr, "orderNum", "asc") + .map((item, index) => { + if (item.hidden) { + return null; + } + + const ElTableColumn = ( + + ); + + // 操作按钮 + if (item.type === "op") { + const props = assign( + { + label: crud.dict.label.op, + width: style.table.column.opWidth, + fixed: browser.isMini ? null : "right" + }, + item + ); + + return h(ElTableColumn, props, { + default: (scope: any) => { + return ( +
+ {renderOpButtons(item.buttons, { scope })} +
+ ); + } + }); + } + // 多选,序号 + else if (["selection", "index"].includes(item.type)) { + return h(ElTableColumn, item); + } + // 默认 + else { + function deep(item: ClTable.Column) { + if (item.hidden) { + return null; + } + + const props: obj = cloneDeep(item); + + // Cannot set property children of # + delete props.children; + + return h(ElTableColumn, props, { + header(scope: any) { + return renderHeader(item, { scope, slots }); + }, + default(scope: any) { + if (item.children) { + return item.children.map(deep); + } + + // 使用插槽 + const slot = slots[`column-${item.prop}`]; + + if (slot) { + return slot({ + scope, + item + }); + } else { + // 绑定值 + let value = scope.row[item.prop]; + + // 格式化 + if (item.formatter) { + value = item.formatter( + scope.row, + scope.column, + value, + scope.$index + ); + + if (isObject(value)) { + return value; + } + } + + // 自定义渲染 + if (item.render) { + return item.render( + scope.row, + scope.column, + value, + scope.$index + ); + } + // 自定义渲染2 + else if (item.component) { + return renderNode(item.component, { + prop: item.prop, + scope: scope.row, + _data: { + column: scope.column, + index: scope.$index, + row: scope.row + } + }); + } + // 字典状态 + else if (item.dict) { + return renderDict(value, item); + } + // 空数据 + else if (isEmpty(value)) { + return scope.emptyText; + } else { + return value; + } + } + } + }); + } + + return deep(item); + } + }) + .filter(Boolean); + } + + // 渲染操作按钮 + function renderOpButtons(buttons: any, { scope }: any) { + const list = getValue(buttons || ["edit", "delete"], { scope }) as ClTable.OpButton; + + return list.map((vnode) => { + if (vnode === "info") { + return ( + { + crud.rowInfo(scope.row); + e.stopPropagation(); + }}> + {crud.dict.label?.info} + + ); + } else if (vnode === "edit") { + return ( + { + crud.rowEdit(scope.row); + e.stopPropagation(); + }}> + {crud.dict.label?.update} + + ); + } else if (vnode === "delete") { + return ( + { + crud.rowDelete(scope.row); + e.stopPropagation(); + }}> + {crud.dict.label?.delete} + + ); + } else { + if (typeof vnode === "object") { + if (vnode.hidden) { + return null; + } + } + + return renderNode(vnode, { + scope, + slots, + custom(vnode) { + return ( + { + vnode.onClick({ scope }); + e.stopPropagation(); + }}> + {vnode.label} + + ); + } + }); + } + }); + } + + // 渲染字典 + function renderDict(value: any, item: ClTable.Column) { + // 选项列表 + const list = cloneDeep(item.dict || []) as DictOptions; + + // 字符串分隔符 + const separator = item.dictSeparator === undefined ? "," : item.dictSeparator; + + // 设置颜色 + if (item.dictColor) { + list.forEach((e, i) => { + if (!e.color) { + e.color = style.colors[i]; + } + }); + } + + // 绑定值 + let values: any[] = []; + + // 格式化值 + if (isArray(value)) { + values = value; + } else if (isString(value)) { + if (separator) { + values = value.split(separator); + } else { + values = [value]; + } + } else { + values = [value]; + } + + // 返回值 + const result = values + .filter((e) => e !== undefined && e !== null && e !== "") + .map((v) => { + const d = deepFind(v, list, { allLevels: item.dictAllLevels }) || { + label: v, + value: v + }; + + return { + ...d, + children: [] + }; + }); + + // 格式化返回 + if (item.dictFormatter) { + return item.dictFormatter(result); + } else { + // tag 返回 + return result.map((e) => { + return h( + , + { + type: e.type, + closable: e.closable, + hit: e.hit, + color: e.color, + size: e.size, + effect: e.effect || "dark", + round: e.round + }, + { + default: () => {e.label} + } + ); + }); + } + } + + // 插槽 empty + function renderEmpty(emptyText: string) { + return ( +
+ {slots.empty ? ( + slots.empty() + ) : ( + + )} +
+ ); + } + + // 插槽 append + function renderAppend() { + return
{slots.append && slots.append()}
; + } + + return { + renderColumn, + renderEmpty, + renderAppend + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/table/helper/row.ts b/cool-admin-vue/packages/crud/src/components/table/helper/row.ts new file mode 100644 index 0000000..80b7620 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/helper/row.ts @@ -0,0 +1,130 @@ +import { isEmpty, isFunction } from "lodash-es"; +import { useCore } from "../../../hooks"; +import { ContextMenu } from "../../context-menu"; + +// 单元行事件 +export function useRow({ + Table, + config, + Sort +}: { + Table: Vue.Ref; + config: ClTable.Config; + Sort: { + defaultSort: { + prop?: string; + order?: string; + }; + changeSort(prop: string, order: string): void; + }; +}) { + const { crud } = useCore(); + + // 右键菜单 + function onRowContextMenu(row: obj, column: obj, event: PointerEvent) { + // 菜单按钮 + const buttons = config.contextMenu; + // 是否开启 + const enable = !isEmpty(buttons); + + if (enable) { + // 高亮 + Table.value.setCurrentRow(row); + + // 解析按钮 + const list = buttons + .map((e) => { + switch (e) { + case "refresh": + return { + label: crud.dict.label.refresh, + callback(done: fn) { + crud.refresh(); + done(); + } + }; + case "edit": + case "update": + return { + label: crud.dict.label.update, + hidden: !crud.getPermission("update"), + callback(done: fn) { + crud.rowEdit(row); + done(); + } + }; + case "delete": + return { + label: crud.dict.label.delete, + hidden: !crud.getPermission("delete"), + callback(done: fn) { + crud.rowDelete(row); + done(); + } + }; + case "info": + return { + label: crud.dict.label.info, + hidden: !crud.getPermission("info"), + callback(done: fn) { + crud.rowInfo(row); + done(); + } + }; + case "check": + return { + label: crud.selection.find((e) => e.id == row.id) + ? crud.dict.label.deselect + : crud.dict.label.select, + hidden: !config.columns.find((e) => e.type === "selection"), + callback(done: fn) { + Table.value.toggleRowSelection(row); + done(); + } + }; + case "order-desc": + return { + label: `${column.label} - ${crud.dict.label.desc}`, + hidden: !column.sortable, + callback(done: fn) { + Sort.changeSort(column.property, "desc"); + done(); + } + }; + case "order-asc": + return { + label: `${column.label} - ${crud.dict.label.asc}`, + hidden: !column.sortable, + callback(done: fn) { + Sort.changeSort(column.property, "asc"); + done(); + } + }; + default: + if (isFunction(e)) { + return e(row, column, event); + } else { + return e; + } + } + }) + .filter((e) => Boolean(e) && !e.hidden); + + // 打开菜单 + if (!isEmpty(list)) { + ContextMenu.open(event, { + list + }); + } + } + + // 回调 + if (config.onRowContextmenu) { + config.onRowContextmenu(row, column, event); + } + } + + return { + onRowContextMenu + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/table/helper/selection.ts b/cool-admin-vue/packages/crud/src/components/table/helper/selection.ts new file mode 100644 index 0000000..67a2dd2 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/helper/selection.ts @@ -0,0 +1,16 @@ +import { useCore } from "../../../hooks"; + +export function useSelection({ emit }: { emit: Vue.Emit }) { + const { crud } = useCore(); + + // 选择项发生变化 + function onSelectionChange(selection: any[]) { + crud.selection.splice(0, crud.selection.length, ...selection); + emit("selection-change", crud.selection); + } + + return { + selection: crud.selection, + onSelectionChange + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/table/helper/sort.ts b/cool-admin-vue/packages/crud/src/components/table/helper/sort.ts new file mode 100644 index 0000000..2b95fe8 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/helper/sort.ts @@ -0,0 +1,86 @@ +import { useCore } from "../../../hooks"; + +// 排序 +export function useSort({ + config, + Table, + emit +}: { + config: ClTable.Config; + Table: Vue.Ref; + emit: Vue.Emit; +}) { + const { crud } = useCore(); + + // 设置默认排序Ï + const defaultSort = (function () { + let { prop, order } = config.defaultSort || {}; + + const item = config.columns.find((e) => + ["desc", "asc", "descending", "ascending"].find((a) => a == e.sortable) + ); + + if (item) { + prop = item.prop; + order = ["descending", "desc"].find((a) => a == item.sortable) + ? "descending" + : "ascending"; + } + + if (order && prop) { + crud.params.order = ["descending", "desc"].includes(order) ? "desc" : "asc"; + crud.params.prop = prop; + + return { + prop, + order + }; + } + + return {}; + })(); + + // 排序监听 + function onSortChange({ prop, order }: { prop: string | undefined; order: string }) { + if (config.sortRefresh) { + if (order === "descending") { + order = "desc"; + } + + if (order === "ascending") { + order = "asc"; + } + + if (!order) { + prop = undefined; + } + + crud.refresh({ + prop, + order, + page: 1 + }); + } + + emit("sort-change", { prop, order }); + } + + // 改变排序 + function changeSort(prop: string, order: string) { + if (order === "desc") { + order = "descending"; + } + + if (order === "asc") { + order = "ascending"; + } + + Table.value?.sort(prop, order); + } + + return { + defaultSort, + onSortChange, + changeSort + }; +} diff --git a/cool-admin-vue/packages/crud/src/components/table/index.tsx b/cool-admin-vue/packages/crud/src/components/table/index.tsx new file mode 100644 index 0000000..6f35bd8 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/table/index.tsx @@ -0,0 +1,165 @@ +import { defineComponent, h } from "vue"; +import { + useData, + useHeight, + useOp, + useRender, + useRow, + useSelection, + useSort, + useTable +} from "./helper"; +import { useConfig, useCore, useElApi, useProxy } from "../../hooks"; +import { usePlugins } from "./helper/plugins"; + +export default defineComponent({ + name: "cl-table", + + props: { + // 列配置 + columns: { + type: Array, + default: () => [] + }, + // 是否自动计算高度 + autoHeight: { + type: Boolean, + default: null + }, + // 固定高度 + height: null, + // 右键菜单 + contextMenu: { + type: [Array, Boolean], + default: null + }, + // 默认排序 + defaultSort: Object, + // 排序后是否刷新 + sortRefresh: { + type: Boolean, + default: true + }, + // 空数据显示文案 + emptyText: String, + // 当前行的 key + rowKey: { + type: String, + default: "id" + } + }, + + emits: ["selection-change", "sort-change"], + + setup(props, { emit, expose }) { + const { crud } = useCore(); + const { style } = useConfig(); + const { Table, config } = useTable(props); + const plugin = usePlugins(); + + // 排序 + const Sort = useSort({ config, emit, Table }); + + // 行 + const Row = useRow({ + config, + Table, + Sort + }); + + // 高度 + const Height = useHeight({ config, Table }); + + // 数据 + const Data = useData({ config, Table }); + + // 多选 + const Selection = useSelection({ emit }); + + // 操作 + const Op = useOp({ config }); + + // 方法 + const ElTableApi = useElApi( + [ + "clearSelection", + "getSelectionRows", + "toggleRowSelection", + "toggleAllSelection", + "toggleRowExpansion", + "setCurrentRow", + "clearSort", + "clearFilter", + "doLayout", + "sort", + "scrollTo", + "setScrollTop", + "setScrollLeft", + "updateKeyChildren" + ], + Table + ); + + const ctx = { + Table, + config, + columns: config.columns, + ...Selection, + ...Data, + ...Sort, + ...Row, + ...Height, + ...Op, + ...ElTableApi + }; + + useProxy(ctx); + expose(ctx); + plugin.create(config.plugins); + + return () => { + const { renderColumn, renderAppend, renderEmpty } = useRender(); + + return ( + ctx.visible.value && + h( + , + { + ...config.on, + ...config.props, + + // config + maxHeight: config.autoHeight ? ctx.maxHeight.value : null, + height: config.autoHeight ? config.height : null, + rowKey: config.rowKey, + + // ctx + defaultSort: ctx.defaultSort, + data: ctx.data.value, + onRowContextmenu: ctx.onRowContextMenu, + onSelectionChange: ctx.onSelectionChange, + onSortChange: ctx.onSortChange, + + // style + size: style.size, + border: style.table.border, + highlightCurrentRow: style.table.highlightCurrentRow, + resizable: style.table.resizable, + stripe: style.table.stripe + }, + { + default() { + return renderColumn(ctx.columns); + }, + empty() { + return renderEmpty(config.emptyText || crud.dict.label.empty); + }, + append() { + return renderAppend(); + } + } + ) + ); + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/components/upsert/index.tsx b/cool-admin-vue/packages/crud/src/components/upsert/index.tsx new file mode 100644 index 0000000..37c7f87 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/components/upsert/index.tsx @@ -0,0 +1,306 @@ +import { defineComponent, h, inject, reactive, ref, toRefs } from "vue"; +import { ElMessage } from "element-plus"; +import { useCore, useProxy } from "../../hooks"; +import { useApi } from "../form/helper"; +import { mergeConfig } from "../../utils"; + +export default defineComponent({ + name: "cl-upsert", + + props: { + // 表单项 + items: { + type: Array, + default: () => [] + }, + // 参数 + props: Object, + // 编辑时是否同步打开 + sync: Boolean, + // 操作按钮参数 + op: Object, + // 参数 + dialog: Object, + // 打开表单钩子 + onOpen: Function, + // 打开表单后钩子 + onOpened: Function, + // 关闭表单钩子 + onClose: Function, + // 关闭表单后钩子 + onClosed: Function, + // 获取表单数据钩子 + onInfo: Function, + // 表单提交钩子 + onSubmit: Function + }, + + emits: ["opened", "closed"], + + setup(props, { slots, expose }) { + const { crud } = useCore(); + + const config = reactive( + mergeConfig(props, inject("useUpsert__options") || {}) + ); + + // el-form + const Form = ref(); + + // 模式 + const mode = ref("info"); + + // 关闭表单 + function close(action?: ClForm.CloseAction) { + Form.value?.close(action); + } + + // 关闭后 + function onClosed() { + Form.value?.hideLoading(); + + if (config.onClosed) { + config.onClosed(); + } + } + + // 关闭前 + function beforeClose(action: ClForm.CloseAction, done: fn) { + function next() { + done(); + onClosed(); + } + + if (config.onClose) { + config.onClose(action, next); + } else { + next(); + } + } + + // 提交 + function submit(data: obj) { + const { service, dict, refresh } = crud; + + function done() { + Form.value?.done(); + } + + function next(data: obj) { + return new Promise((resolve, reject) => { + // 发送请求 + service[dict.api[mode.value]](data) + .then((res) => { + ElMessage.success(dict.label.saveSuccess); + done(); + close("save"); + refresh(); + resolve(res); + }) + .catch((err) => { + ElMessage.error(err.message); + done(); + reject(err); + }); + }); + } + + // 提交钩子 + if (config.onSubmit) { + config.onSubmit(data, { + done, + next, + close() { + close("save"); + } + }); + } else { + next(data); + } + } + + // 打开表单 + function open() { + // 是否禁用 + const isDisabled = mode.value == "info"; + + return new Promise((resolve) => { + if (!Form.value) { + return console.error(" is not found"); + } + + Form.value?.open( + { + title: crud.dict.label[mode.value], + props: { + ...config.props, + disabled: isDisabled + }, + op: { + ...config.op, + hidden: isDisabled + }, + dialog: config.dialog, + items: config.items || [], + on: { + open() { + if (config.onOpen) { + config.onOpen(); + } + + resolve(true); + }, + submit, + close: beforeClose + }, + form: {}, + _data: { + isDisabled + } + }, + config.plugins + ); + }); + } + + // 打开后事件 + function onOpened() { + const data = Form.value?.getForm(); + + if (config.onOpened) { + config.onOpened(data); + } + } + + // 新增 + async function add() { + mode.value = "add"; + + // 打开中 + await open(); + + // 打开后 + onOpened(); + } + + // 追加 + async function append(data: any) { + mode.value = "add"; + + // 打开中 + await open(); + + // 绑定值 + if (data) { + Form.value?.bindForm(data); + } + + // 打开后 + onOpened(); + } + + // 编辑 + function edit(data?: any) { + mode.value = "update"; + getInfo(data); + } + + // 详情 + function info(data?: any) { + mode.value = "info"; + getInfo(data); + } + + // 信息 + function getInfo(data: any) { + // 显示加载中 + Form.value?.showLoading(); + + // 是否同步打开 + if (!config.sync) { + open(); + } + + // 完成 + async function done(data?: any) { + // 加载完成 + Form.value?.hideLoading(); + + // 合并数据 + if (data) { + Form.value?.bindForm(data); + } + + // 同步打开表单 + if (config.sync) { + await open(); + } + + onOpened(); + } + + // 获取详情 + function next(data: any): Promise { + return new Promise(async (resolve, reject) => { + // 发送请求 + await crud.service[crud.dict.api.info]({ + [crud.dict.primaryId]: data[crud.dict.primaryId] + }) + .then((res) => { + done(res); + resolve(res); + }) + .catch((err) => { + ElMessage.error(err.message); + reject(err); + }); + + // 隐藏加载框 + Form.value?.hideLoading(); + }); + } + + // 详情钩子 + if (config.onInfo) { + config.onInfo(data, { + close, + next, + done + }); + } else { + next(data); + } + } + + // 完成 + function done() { + Form.value?.hideLoading(); + } + + const ctx = { + config, + ...toRefs(config), + ...useApi({ Form }), + Form, + get form() { + return Form.value?.form || {}; + }, + mode, + add, + append, + edit, + info, + open, + close, + done, + submit + }; + + useProxy(ctx); + expose(ctx); + + return () => { + return
{h(, {}, slots)}
; + }; + } +}); diff --git a/cool-admin-vue/packages/crud/src/emitter.ts b/cool-admin-vue/packages/crud/src/emitter.ts new file mode 100644 index 0000000..3099ff4 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/emitter.ts @@ -0,0 +1,27 @@ +export const crudList: ClCrud.Ref[] = []; + +export const emitter: Emitter = { + list: [], + init(events) { + for (const i in events) { + this.on(i, events[i]); + } + }, + emit(name, data) { + this.list.forEach((e: EmitterItem) => { + const [_name] = e.name.split("-"); + + if (name == _name) { + e.callback(data, { + crudList, + refresh(params) { + crudList.forEach((c) => c.refresh(params)); + } + }); + } + }); + }, + on(name, callback) { + this.list.push({ name, callback }); + } +}; diff --git a/cool-admin-vue/packages/crud/src/entry.ts b/cool-admin-vue/packages/crud/src/entry.ts new file mode 100644 index 0000000..07562c1 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/entry.ts @@ -0,0 +1,30 @@ +import { type App } from "vue"; +import { useComponent } from "./components"; +import { useProvide } from "./provide"; +import global from "./utils/global"; +import "./static/index.scss"; + +const Crud = { + install(app: App, options?: any) { + global.set("__CrudApp__", app); + + // 穿透值 + useProvide(app, options); + + // 设置组件 + useComponent(app); + + return { + name: "cl-crud" + }; + } +}; + +export { Crud }; + +export * from "./emitter"; +export * from "./hooks"; +export * from "./locale"; +export { registerFormHook } from "./utils/form-hook"; +export { renderNode } from "./utils/vnode"; +export { ContextMenu } from "./components/context-menu"; diff --git a/cool-admin-vue/packages/crud/src/hooks/crud.ts b/cool-admin-vue/packages/crud/src/hooks/crud.ts new file mode 100644 index 0000000..e894329 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/hooks/crud.ts @@ -0,0 +1,191 @@ +import { assign } from "lodash-es"; +import { TestService } from "../test/service"; +import { getCurrentInstance, inject, nextTick, provide, ref, type Ref, watch } from "vue"; + +// 获取上级 +function useParent(name: string, r: Ref) { + const d = getCurrentInstance(); + + if (d) { + let parent = d.proxy?.$.parent; + + if (parent) { + while (parent && parent.type?.name != name && parent.type?.name != "cl-crud") { + parent = parent?.parent; + } + + if (parent) { + if (parent.type.name == name) { + r.value = parent.exposed; + } + } + } + } +} + +// 多事件 +function useEvent( + names: string[], + { r, options, clear, isChild }: { r: any; options: any; clear?: string; isChild?: boolean } +) { + if (!r.__ev) r.__ev = {}; + + const d: { [key: string]: (args: any[]) => void } = {}; + const ev = r.__ev as { [key: string]: { fn: any; isChild?: boolean }[] }; + + names.forEach((k) => { + if (!ev[k]) ev[k] = []; + + if (options[k]) { + ev[k].push({ + fn: options[k], + isChild + }); + } + + d[k] = (...args: any[]) => { + ev[k].forEach((e) => { + if (e.fn) { + e.fn(...args); + } + }); + + if (clear == k) { + for (const i in ev) { + ev[i] = ev[i].filter((e) => !e.isChild); + } + } + }; + }); + + return d; +} + +// crud +export function useCrud(options?: ClCrud.Options, cb?: (app: ClCrud.Ref) => void) { + const Crud = ref(); + useParent("cl-crud", Crud); + + if (options) { + // 测试模式 + if (options.service == "test") { + options.service = new TestService(); + } + + provide("useCrud__options", options); + } + + watch(Crud, (val) => { + if (val) { + if (cb) { + cb(val); + } + } + }); + + return Crud; +} + +// 新增、编辑 +export function useUpsert(options?: ClUpsert.Options) { + const Upsert = ref(); + useParent("cl-upsert", Upsert); + const isChild = !!Upsert.value; + + if (options) { + provide("useUpsert__options", options); + } + + watch( + Upsert, + (val) => { + if (val) { + if (options) { + const event = useEvent(["onOpen", "onOpened", "onClosed"], { + r: val, + options, + clear: "onClosed", + isChild + }); + + assign(val.config, event); + } + } + }, + { + immediate: true + } + ); + + return Upsert; +} + +// 表格 +export function useTable(options?: ClTable.Options, cb?: (table: ClTable.Ref) => void) { + const Table = ref>(); + useParent("cl-table", Table); + + if (options) { + provide("useTable__options", options); + } + + watch(Table, (val) => { + if (val) { + if (cb) { + cb(val); + } + } + }); + + return Table; +} + +// 表单 +export function useForm(cb?: (app: ClForm.Ref) => void) { + const Form = ref>(); + useParent("cl-form", Form); + + nextTick(() => { + if (cb && Form.value) { + cb(Form.value); + } + }); + + return Form; +} + +// 高级搜索 +export function useAdvSearch(options?: ClAdvSearch.Options) { + const AdvSearch = ref>(); + useParent("cl-adv-search", AdvSearch); + + if (options) { + provide("useAdvSearch__options", options); + } + + return AdvSearch; +} + +// 搜索 +export function useSearch(options?: ClSearch.Options) { + const Search = ref>(); + useParent("cl-search", Search); + + provide("useSearch__options", options); + + return Search; +} + +// 对话框 +export function useDialog(options?: { onFullscreen(visible: boolean): void }) { + const Dialog = inject("dialog") as ClDialog.Provide; + + watch( + () => Dialog?.fullscreen.value, + (val) => { + options?.onFullscreen(val); + } + ); + + return Dialog; +} diff --git a/cool-admin-vue/packages/crud/src/hooks/index.ts b/cool-admin-vue/packages/crud/src/hooks/index.ts new file mode 100644 index 0000000..14fd596 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/hooks/index.ts @@ -0,0 +1,74 @@ +import { Mitt } from "../utils/mitt"; +import { isFunction } from "lodash-es"; +import { getCurrentInstance, inject, reactive } from "vue"; + +export function useCore() { + const crud = inject("crud") as ClCrud.Ref; + const mitt = inject("mitt") as Mitt; + + return { + crud, + mitt + }; +} + +export function useConfig() { + return inject("__config__") as Config; +} + +export function useBrowser() { + return inject("__browser__") as Browser; +} + +export function useRefs() { + const refs = reactive<{ [key: string]: obj }>({}); + + function setRefs(name: string) { + return (el: any) => { + refs[name] = el; + }; + } + + return { refs, setRefs }; +} + +export function useProxy(ctx: any) { + const { type }: any = getCurrentInstance(); + const { mitt, crud } = useCore(); + + // 挂载 + crud[type.name] = ctx; + + // 事件 + mitt.on("crud.proxy", ({ name, data = [], callback }: any) => { + if (ctx[name]) { + let d = null; + + if (isFunction(ctx[name])) { + d = ctx[name](...data); + } else { + d = ctx[name]; + } + + if (callback) { + callback(d); + } + } + }); + + return ctx; +} + +export function useElApi(keys: string[], el: any) { + const apis: obj = {}; + + keys.forEach((e) => { + apis[e] = (...args: any[]) => { + return el.value[e](...args); + }; + }); + + return apis; +} + +export * from "./crud"; diff --git a/cool-admin-vue/packages/crud/src/index.ts b/cool-admin-vue/packages/crud/src/index.ts new file mode 100644 index 0000000..363490f --- /dev/null +++ b/cool-admin-vue/packages/crud/src/index.ts @@ -0,0 +1 @@ +export * from "./entry"; diff --git a/cool-admin-vue/packages/crud/src/locale/en.ts b/cool-admin-vue/packages/crud/src/locale/en.ts new file mode 100644 index 0000000..0de015e --- /dev/null +++ b/cool-admin-vue/packages/crud/src/locale/en.ts @@ -0,0 +1,33 @@ +export default { + op: "Operation", + add: "Add", + delete: "Delete", + multiDelete: "Delete", + update: "Edit", + refresh: "Refresh", + info: "Details", + search: "Search", + reset: "Reset", + clear: "Clear", + save: "Save", + close: "Cancel", + confirm: "Confirm", + advSearch: "Advanced Search", + searchKey: "Search Keyword", + placeholder: "Please enter", + tips: "Tips", + saveSuccess: "Save successful", + deleteSuccess: "Delete successful", + deleteConfirm: + "This operation will permanently delete the selected data. Do you want to continue?", + empty: "No data available", + desc: "Descending", + asc: "Ascending", + select: "Select", + deselect: "Deselect", + seeMore: "See more", + hideContent: "Hide content", + nonEmpty: "{label} cannot be empty", + collapse: "Collapse", + expand: "Expand" +}; diff --git a/cool-admin-vue/packages/crud/src/locale/index.ts b/cool-admin-vue/packages/crud/src/locale/index.ts new file mode 100644 index 0000000..087df5e --- /dev/null +++ b/cool-admin-vue/packages/crud/src/locale/index.ts @@ -0,0 +1,11 @@ +import en from "./en"; +import ja from "./ja"; +import zhCn from "./zh-cn"; +import zhTw from "./zh-tw"; + +export const locale = { + en, + ja, + "zh-cn": zhCn, + "zh-tw": zhTw +}; diff --git a/cool-admin-vue/packages/crud/src/locale/ja.ts b/cool-admin-vue/packages/crud/src/locale/ja.ts new file mode 100644 index 0000000..9d67240 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/locale/ja.ts @@ -0,0 +1,32 @@ +export default { + op: "操作", + add: "追加", + delete: "削除", + multiDelete: "削除", + update: "編集", + refresh: "リフレッシュ", + info: "詳細", + search: "検索", + reset: "リセット", + clear: "クリア", + save: "保存", + close: "キャンセル", + confirm: "確認", + advSearch: "高度な検索", + searchKey: "検索キーワード", + placeholder: "入力してください", + tips: "ヒント", + saveSuccess: "保存が成功しました", + deleteSuccess: "削除が成功しました", + deleteConfirm: "この操作は選択したデータを永久に削除します。続行しますか?", + empty: "データがありません", + desc: "降順", + asc: "昇順", + select: "選択", + deselect: "選択解除", + seeMore: "詳細を表示", + hideContent: "コンテンツを非表示", + nonEmpty: "{label}は空にできません", + collapse: "折り畳む", + expand: "展開" +}; diff --git a/cool-admin-vue/packages/crud/src/locale/zh-cn.ts b/cool-admin-vue/packages/crud/src/locale/zh-cn.ts new file mode 100644 index 0000000..69d9e7d --- /dev/null +++ b/cool-admin-vue/packages/crud/src/locale/zh-cn.ts @@ -0,0 +1,32 @@ +export default { + op: "操作", + add: "新增", + delete: "删除", + multiDelete: "删除", + update: "编辑", + refresh: "刷新", + info: "详情", + search: "搜索", + reset: "重置", + clear: "清空", + save: "保存", + close: "取消", + confirm: "确定", + advSearch: "高级搜索", + searchKey: "搜索关键字", + placeholder: "请输入", + tips: "提示", + saveSuccess: "保存成功", + deleteSuccess: "删除成功", + deleteConfirm: "此操作将永久删除选中数据,是否继续?", + empty: "暂无数据", + desc: "降序", + asc: "升序", + select: "选择", + deselect: "取消选择", + seeMore: "查看更多", + hideContent: "隐藏内容", + nonEmpty: "{label}不能为空", + collapse: "收起", + expand: "展开更多" +}; diff --git a/cool-admin-vue/packages/crud/src/locale/zh-tw.ts b/cool-admin-vue/packages/crud/src/locale/zh-tw.ts new file mode 100644 index 0000000..dbd83e8 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/locale/zh-tw.ts @@ -0,0 +1,32 @@ +export default { + op: "操作", + add: "新增", + delete: "刪除", + multiDelete: "刪除", + update: "編輯", + refresh: "刷新", + info: "詳情", + search: "搜尋", + reset: "重置", + clear: "清空", + save: "保存", + close: "取消", + confirm: "確定", + advSearch: "高級搜索", + searchKey: "搜索關鍵字", + placeholder: "請輸入", + tips: "提示", + saveSuccess: "保存成功", + deleteSuccess: "刪除成功", + deleteConfirm: "此操作將永久刪除選中數據,是否繼續?", + empty: "暫無數據", + desc: "降序", + asc: "升序", + select: "選擇", + deselect: "取消選擇", + seeMore: "查看更多", + hideContent: "隱藏內容", + nonEmpty: "{label}不能為空", + collapse: "收起", + expand: "展開" +}; diff --git a/cool-admin-vue/packages/crud/src/main.ts b/cool-admin-vue/packages/crud/src/main.ts new file mode 100644 index 0000000..c82311a --- /dev/null +++ b/cool-admin-vue/packages/crud/src/main.ts @@ -0,0 +1,27 @@ +import { createApp } from "vue"; +import App from "./App.vue"; +import { Crud, locale } from "./entry"; +// import Crud, { locale } from "../dist/index.umd"; +// import "../dist/index.css"; +import ElementPlus from "element-plus"; +import "element-plus/dist/index.css"; + +const app = createApp(App); + +app.use(ElementPlus) + .use(Crud, { + dict: { + sort: { + prop: "order", + order: "sort" + }, + label: locale["zh-cn"] + }, + style: { + // size: "default" + }, + render: { + autoHeight: true + } + }) + .mount("#app"); diff --git a/cool-admin-vue/packages/crud/src/provide.ts b/cool-admin-vue/packages/crud/src/provide.ts new file mode 100644 index 0000000..0248bff --- /dev/null +++ b/cool-admin-vue/packages/crud/src/provide.ts @@ -0,0 +1,129 @@ +import { type App, reactive } from "vue"; +import { mitt } from "./utils/mitt"; +import { emitter } from "./emitter"; +import { locale } from "./locale"; +import { merge } from "./utils"; + +// 设置配置 +function setConfig(app: App, options: Options = {}) { + const config = merge( + { + permission: { + update: true, + page: true, + info: true, + list: true, + add: true, + delete: true + }, + dict: { + primaryId: "id", + api: { + list: "list", + add: "add", + update: "update", + delete: "delete", + info: "info", + page: "page" + }, + pagination: { + page: "page", + size: "size" + }, + search: { + keyWord: "keyWord", + query: "query" + }, + sort: { + order: "order", + prop: "prop" + }, + label: locale["zh-cn"] + }, + style: { + colors: [ + "#d42ca8", + "#1c109d", + "#6d17c3", + "#6dc9f1", + "#04c273", + "#06b31c", + "#f9f494", + "#aa7a24", + "#d57121", + "#e93f4d" + ], + form: { + labelPostion: "right", + labelWidth: "100px", + span: 24 + }, + table: { + border: true, + highlightCurrentRow: true, + autoHeight: true, + contextMenu: ["refresh", "check", "edit", "delete", "order-asc", "order-desc"], + column: { + align: "center", + opWidth: 180 + } + } + }, + events: {} + } as Options, + options + ); + + // 初始化事件 + if (config.events) { + emitter.init(config.events); + } + + app.provide("__config__", config); + + return config; +} + +// 设置浏览器 +function setBrowser(app: App) { + // 浏览器信息 + const browser = reactive({ + isMini: false, + screen: "full" + }); + + // 更新信息 + function update() { + const w = document.body.clientWidth; + + if (w < 768) { + browser.screen = "xs"; + } else if (w < 992) { + browser.screen = "sm"; + } else if (w < 1200) { + browser.screen = "md"; + } else if (w < 1920) { + browser.screen = "xl"; + } else { + browser.screen = "full"; + } + + browser.isMini = browser.screen === "xs"; + } + + // 监听浏览器窗口变化 + window.addEventListener("resize", () => { + update(); + + // 事件 + mitt.emit("resize"); + }); + + update(); + app.provide("__browser__", browser); +} + +export function useProvide(app: App, options: Options = {}) { + setBrowser(app); + setConfig(app, options); +} diff --git a/cool-admin-vue/packages/crud/src/static/index.scss b/cool-admin-vue/packages/crud/src/static/index.scss new file mode 100644 index 0000000..1b7ee65 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/static/index.scss @@ -0,0 +1,862 @@ +.cl-crud { + height: 100%; + overflow: hidden auto; + position: relative; + box-sizing: border-box; + background-color: #fff; + + &.is-border { + border: 1px solid var(--el-border-color); + border-radius: var(--el-border-radius-base); + } + + & > .cl-row { + width: 100%; + + &:not(.cl-row--last) > * { + margin: 0 10px 10px 0; + + &:last-child { + margin-right: 0; + } + } + + .cl-flex1 { + margin-right: 0; + } + } +} + +.cl-flex1 { + flex: 1; + font-size: 12px; +} + +.cl-search-key { + display: inline-flex; + + &__select { + margin-right: 10px; + + &.el-select { + width: 100px; + } + } + + &__wrap { + display: inline-flex; + + .el-input { + flex: 1; + } + + .el-button { + margin-left: 10px; + } + } +} + +.cl-table { + width: 100%; + + .el-table { + &.el-loading-parent--relative { + box-sizing: border-box; + } + + &__header { + .el-table__cell { + background-color: var(--el-fill-color-lighter) !important; + color: var(--el-text-color-primary); + + .cell { + line-height: normal; + } + + &.is-sortable { + .cl-table-header__search { + width: auto; + + &.is-input { + width: calc(100% - 24px) !important; + } + } + } + } + } + + &__empty-block { + height: auto !important; + } + } + + .el-loading-mask { + .el-loading-spinner { + .el-icon-loading { + font-size: 25px; + color: #000; + } + + .el-loading-text { + color: var(--el-text-color-secondary); + margin-top: 5px; + } + } + } + + &__op { + margin-bottom: -5px; + + .el-button { + margin-bottom: 5px; + outline-offset: -2px !important; + + &.is-text { + border: 1px solid var(--el-button-border-color) !important; + + &:hover { + background-color: var(--el-button-bg-color) !important; + } + } + } + } + + .cl-table-header__search { + display: inline-flex; + align-items: center; + gap: 5px; + width: 100%; + cursor: pointer; + + &-label { + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + } + + &:hover { + color: var(--el-color-primary); + } + + &-inner { + flex: 1; + + & > div { + width: 100%; + + .el-date-editor { + margin-right: 0; + } + } + } + + &-close { + font-size: 14px; + height: 30px; + width: 30px; + border: 1px solid var(--el-border-color); + border-radius: 6px; + background-color: var(--el-fill-color-blank); + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s; + color: var(--el-text-color-secondary); + + &:hover { + border-color: var(--el-border-color-hover); + color: var(--el-text-color-primary); + } + } + } + + .is-left { + .cl-table-header__search-label { + justify-content: flex-start; + } + } + + .is-right { + .cl-table-header__search-label { + justify-content: flex-end; + } + } +} + +.cl-pagination { + &.el-pagination { + --el-pagination-border-radius: var(--el-border-radius-base); + } + + .btn-prev, + .btn-next, + .el-pager li { + border-radius: var(--el-border-radius-base); + } +} + +.cl-filter { + display: flex; + align-items: center; + margin: 0 10px; + + &__label { + font-size: 12px; + margin-right: 10px; + white-space: nowrap; + } + + .el-select { + min-width: 120px; + } +} + +.cl-search { + &__btns { + margin-left: 5px; + } + + &__more { + display: flex; + align-items: center; + justify-content: space-between; + + .el-form-item { + margin-bottom: 0; + } + } + + .el-form:not(.el-form--label-top) { + .el-form-item__label { + &:empty { + display: none; + } + } + + .cl-search__btns { + .el-form-item__label { + display: none; + } + } + } + + .cl-search__btns { + .el-button + .el-button { + margin-left: 10px; + } + } + + &.is-inline { + margin-bottom: 0 !important; + } + + &.is-collapse { + background-color: var(--el-fill-color-lighter); + padding: 10px; + margin-bottom: 10px !important; + border-radius: 6px; + border: 1px solid var(--el-border-color-extra-light); + + &.is-fold { + .cl-search__form { + max-height: 42px; + overflow: hidden; + + &:has(.el-form--label-top) { + max-height: 68px; + } + } + } + } +} + +.cl-adv-btn { + margin-left: 10px; + + .el-icon { + margin-right: 5px; + } +} + +.cl-adv-search { + &.el-drawer { + background-color: #fff; + } + + .el-drawer__body { + padding: 0; + } + + &__header { + display: flex; + align-items: center; + justify-content: space-between; + height: 50px; + padding: 0 15px 0 20px; + user-select: none; + + .text { + font-size: 16px; + } + + .el-icon { + cursor: pointer; + + &:hover { + color: red; + } + } + } + + &__container { + height: calc(100% - 110px); + overflow-y: auto; + padding: 10px 20px; + box-sizing: border-box; + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-thumb { + border-radius: 6px; + background-color: rgba(144, 147, 153, 0.3); + } + + .el-form-item__content { + & > div { + width: 100%; + } + } + } + + &__footer { + display: flex; + align-items: center; + justify-content: flex-end; + height: 60px; + border-top: 1px solid var(--el-border-color-extra-light); + padding: 0 10px; + box-sizing: border-box; + } +} + +.cl-form { + [class*="el-col-"].is-guttered { + min-height: 0; + } + + &-item { + display: flex; + + &__component { + display: flex; + + &.flex1 { + flex: 1; + width: 100%; + + & > div { + width: 100%; + } + } + } + + &__prepend { + margin-right: 10px; + } + + &__append { + margin-left: 10px; + } + + &__collapse { + width: 100%; + font-size: 12px; + cursor: pointer; + + .el-divider { + margin: 16px 0; + + &__text { + font-size: 12px; + } + } + + i { + margin-left: 6px; + } + } + + .el-table__header tr { + line-height: normal; + } + } + + &__footer { + display: flex; + justify-content: flex-end; + } + + .cl-crud { + line-height: normal; + } + + .el-form { + .el-form-item { + .el-form-item { + margin-bottom: 18px; + } + + .el-input-number { + &__decrease, + &__increase { + border: 0; + background-color: transparent; + } + } + + &__label { + .el-tooltip { + i { + margin-left: 5px; + } + } + } + + &__content { + min-width: 0px; + + & > div { + width: 100%; + } + } + } + + &:not(.el-form--label-top) { + .el-form-item { + &.no-label { + & > .el-form-item__label { + padding: 0; + display: none; + } + } + } + } + + &.el-form--label-top { + .el-form-item { + margin-bottom: 22px; + } + + .el-form-item__label { + margin: 0 0 4px 0; + min-height: 22px; + } + + .el-form-item__error { + padding-top: 4px; + } + } + + &.el-form--inline { + .cl-form__items { + display: flex; + flex-wrap: wrap; + } + + .el-form-item { + margin: 0 10px 10px 0; + + .el-date-editor { + box-sizing: border-box; + + .el-range-input { + &:nth-child(2) { + margin-left: 5px; + } + } + } + + .el-select { + width: 173px; + } + + &:last-child { + margin-right: 0; + } + } + } + } +} + +.cl-form-tabs { + border-bottom: 1px solid var(--el-border-color); + overflow: hidden; + width: calc(100% - 10px); + margin: 0 5px 20px 5px; + + &__wrap { + height: 35px; + width: 100%; + overflow-x: auto; + overflow-y: hidden; + scrollbar-width: none; + -ms-overflow-style: none; + position: relative; + + &::-webkit-scrollbar { + display: none; + } + } + + ul { + display: inline-flex; + white-space: nowrap; + margin: 0; + padding: 0; + + li { + display: inline-flex; + align-items: center; + list-style: none; + padding: 0 20px; + height: 35px; + cursor: pointer; + + .el-icon { + margin-right: 5px; + font-size: 16px; + } + + &.is-active { + color: var(--el-color-primary); + } + } + } + + &__line { + height: 3px; + width: 100%; + position: absolute; + bottom: -1px; + left: 0; + transition: + transform 0.3s ease-in-out, + width 0.2s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1); + background-color: var(--el-color-primary); + } + + &--card { + .cl-form-tabs__line { + display: none; + } + + ul { + border: 1px solid var(--el-border-color); + border-top-left-radius: 5px; + border-top-right-radius: 5px; + + li { + border-left: 1px solid var(--el-border-color); + + &:first-child { + border-left-width: 0; + } + } + } + } +} + +.cl-form-card { + margin-top: 0; + + &__header { + display: flex; + align-items: center; + justify-content: space-between; + font-size: 14px; + height: 32px; + line-height: normal; + font-weight: bold; + padding: 0 10px; + background-color: var(--el-fill-color-lighter); + border-radius: var(--el-border-radius-base); + cursor: pointer; + user-select: none; + + &:hover { + background-color: var(--el-fill-color-light); + } + } + + &__container { + transition: all 0.3s; + display: grid; + grid-template-rows: 0fr; + + > .cl-form-item__children { + min-height: 0; + overflow: hidden; + + .el-row { + margin-top: 10px; + } + } + } + + &.is-expand { + > .cl-form-card__container { + grid-template-rows: 1fr; + margin-bottom: -18px; + } + } + + .cl-form-card { + margin-left: 10px; + } +} + +.cl-dialog { + display: flex; + flex-direction: column; + + &.el-dialog { + padding: 0; + border-radius: 8px; + } + + .el-dialog { + &__header { + padding: 0; + margin-right: 0; + + &-slot { + &.is-drag { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + -khtml-user-select: none; + user-select: none; + cursor: move; + } + } + } + + &__body { + padding: 0; + box-sizing: border-box; + flex: 1; + overflow: hidden; + } + + &__footer { + padding: 0; + } + } + + &__header { + position: relative; + padding: 10px; + border-bottom: 1px solid var(--el-border-color-extra-light); + text-align: center; + user-select: none; + } + + &__default { + box-sizing: border-box; + } + + &__footer { + border-top: 1px solid var(--el-border-color-extra-light); + padding: 20px; + } + + &__title { + display: block; + font-size: 15px; + letter-spacing: 0.5px; + } + + &__controls { + display: flex; + justify-content: flex-end; + position: absolute; + right: 8px; + top: 8px; + z-index: 9; + width: 100%; + + &-icon, + .minimize, + .maximize, + .close { + display: flex; + align-items: center; + justify-content: center; + height: 28px; + width: 28px; + border: 0; + background-color: transparent; + cursor: pointer; + outline: none; + border-radius: 6px; + margin-left: 5px; + + i { + font-size: 18px; + } + + &:hover { + background-color: var(--el-fill-color-darker); + } + } + } + + &.hidden-header { + .el-dialog__header { + display: none; + } + } + + &.is-fullscreen { + height: 100vh !important; + border-radius: 0; + overflow: hidden; + + .cl-dialog__container { + height: 100% !important; + } + } + + &.is-transparent { + background-color: transparent !important; + } +} + +.cl-context-menu { + position: absolute; + z-index: 9999; + + &__box { + width: 160px; + background-color: var(--el-bg-color); + border: 1px solid var(--el-border-color-extra-light); + box-shadow: + 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -2px rgba(0, 0, 0, 0.1); + border-radius: 6px; + position: absolute; + top: 0; + padding: 5px; + + &.is-append { + right: calc(-100% - 5px); + top: -5px; + } + + & > div { + display: flex; + align-items: center; + font-size: 12px; + cursor: pointer; + padding: 5px 15px; + color: var(--el-text-color-primary); + position: relative; + border-radius: 4px; + + span { + flex: 1; + user-select: none; + } + + &:hover { + background-color: var(--el-fill-color-lighter); + } + + i { + &:first-child { + margin-right: 5px; + } + + &:last-child { + margin-left: 5px; + } + } + + &.is-active { + background-color: #f7f7f7; + color: #000; + } + + &.is-ellipsis { + span { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + + &.is-disabled { + span { + color: #ccc; + + &:hover { + color: #ccc; + } + } + } + } + } + + &__target { + position: relative; + + &::after { + content: ""; + display: block; + position: absolute; + left: 0; + top: 0; + height: 100%; + width: 100%; + background-color: rgba(0, 0, 0, 0.05); + } + } +} + +@media only screen and (max-width: 768px) { + .el-table { + &__body { + &-wrapper { + &::-webkit-scrollbar { + height: 6px; + width: 6px; + } + } + } + } + + .cl-search-key { + width: 100%; + margin-right: 0 !important; + + &__wrap { + width: 100% !important; + } + } +} + +.cl-error-message { + display: flex; + align-items: center; + height: 32px; + padding: 0 10px; + font-size: 14px; + color: var(--el-color-danger); + border: 1px solid var(--el-color-danger); + border-radius: 4px; + box-sizing: border-box; + user-select: none; +} diff --git a/cool-admin-vue/packages/crud/src/test/service.ts b/cool-admin-vue/packages/crud/src/test/service.ts new file mode 100644 index 0000000..90e8f8a --- /dev/null +++ b/cool-admin-vue/packages/crud/src/test/service.ts @@ -0,0 +1,231 @@ +import { assign, orderBy } from "lodash-es"; +import { uuid } from "../utils"; + +const userList = [ + { + id: 1, + name: "楚行云", + createTime: "1996-09-14", + wages: 73026, + status: 1, + account: "chuxingyun", + occupation: 4, + phone: 13797353874 + }, + { + id: 2, + name: "秦尘", + createTime: "1977-11-09", + wages: 74520, + status: 0, + account: "qincheng", + occupation: 3, + phone: 18593911044 + }, + { + id: 3, + name: "叶凡", + createTime: "1982-11-28", + wages: 81420, + status: 0, + account: "yefan", + occupation: 1, + phone: 16234136338 + }, + { + id: 4, + name: "白小纯", + createTime: "2012-12-17", + wages: 65197, + status: 1, + account: "baixiaochun", + occupation: 2, + phone: 16325661110 + }, + { + id: 5, + name: "韩立", + createTime: "1982-07-10", + wages: 99107, + status: 1, + account: "hanli", + occupation: 2, + phone: 18486594866 + }, + { + id: 6, + name: "唐三", + createTime: "2019-07-31", + wages: 80658, + status: 1, + account: "tangsan", + occupation: 5, + phone: 15565014642 + }, + { + id: 7, + name: "王林", + createTime: "2009-07-26", + wages: 57408, + status: 1, + account: "wanglin", + occupation: 1, + phone: 13852767084 + }, + { + id: 8, + name: "李强", + createTime: "2016-04-26", + wages: 71782, + status: 1, + account: "liqiang", + occupation: 3, + phone: 18365332834 + }, + { + id: 9, + name: "秦羽", + createTime: "1984-01-18", + wages: 87860, + status: 1, + account: "qinyu", + occupation: 0, + phone: 18149247129 + } +]; + +class TestService { + // 分页列表 + async page(params: any) { + const { keyWord, page, size, sort, order } = params || {}; + + // 关键字查询 + const keyWordLikeFields = ["phone", "name"]; + + // 等值查询 + const fieldEq = ["createTime", "occupation", "status"]; + + // 模糊查询 + const likeFields = ["phone", "name"]; + + // 过滤后的列表 + const list = orderBy(userList, order, sort).filter((e: any) => { + let f = true; + + if (keyWord !== undefined) { + f = !!keyWordLikeFields.find((k) => String(e[k]).includes(String(params.keyWord))); + } + + fieldEq.forEach((k) => { + if (f) { + if (params[k] !== undefined) { + f = e[k] == params[k]; + } + } + }); + + likeFields.forEach((k) => { + if (f) { + if (params[k] !== undefined) { + f = String(e[k]).includes(String(params[k])); + } + } + }); + + return f; + }); + + return new Promise((resolve) => { + // 模拟延迟 + setTimeout(() => { + resolve({ + list: list.slice((page - 1) * size, page * size), + pagination: { + total: list.length, + page, + size + }, + subData: { + wages: list.reduce((a, b) => { + return a + b.wages; + }, 0) + } + }); + }, 500); + }); + } + + // 更新 + async update(params: { id: any; [key: string]: any }) { + const item = userList.find((e) => e.id == params.id); + + if (item) { + assign(item, params); + } + } + + // 新增 + async add(params: any) { + const id = uuid(); + + userList.push({ + id, + ...params + }); + + return id; + } + + // 详情 + async info(params: { id: any }) { + const { id } = params || {}; + return userList.find((e) => e.id == id); + } + + // 删除 + async delete(params: { ids: any[] }) { + const { ids = [] } = params || {}; + + ids.forEach((id) => { + const index = userList.findIndex((e) => e.id == id); + userList.splice(index, 1); + }); + } + + // 全部列表 + async list() { + return userList; + } + + search = { + fieldEq: [ + { + propertyName: "occupation", + comment: "工作", + source: "a.occupation" + } + ], + fieldLike: [ + { + propertyName: "status", + comment: "状态", + dict: ["关闭", "开启"], + source: "a.status" + } + ], + keyWordLikeFields: [ + { + propertyName: "name", + comment: "姓名", + source: "a.name" + }, + { + propertyName: "phone", + comment: "手机号", + source: "a.phone" + } + ] + }; +} + +export { TestService }; diff --git a/cool-admin-vue/packages/crud/src/utils/form-hook.ts b/cool-admin-vue/packages/crud/src/utils/form-hook.ts new file mode 100644 index 0000000..df30051 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/utils/form-hook.ts @@ -0,0 +1,149 @@ +import { isArray, isEmpty, isFunction, isObject, isString } from "lodash-es"; + +export const format: { [key: string]: ClForm.Hook["Fn"] } = { + number(value) { + return value ? (isArray(value) ? value.map(Number) : Number(value)) : value; + }, + string(value) { + return value ? (isArray(value) ? value.map(String) : String(value)) : value; + }, + split(value) { + if (isString(value)) { + return value.split(",").filter(Boolean); + } else if (isArray(value)) { + return value; + } else { + return []; + } + }, + join(value) { + return isArray(value) ? value.join(",") : value; + }, + boolean(value) { + return Boolean(value); + }, + booleanNumber(value) { + return value ? 1 : 0; + }, + datetimeRange(value, { form, method, prop }) { + const key = prop.charAt(0).toUpperCase() + prop.slice(1); + + const start = `start${key}`; + const end = `end${key}`; + + if (method == "bind") { + return [form[start], form[end]]; + } else { + const [startTime, endTime] = value || []; + form[start] = startTime; + form[end] = endTime; + return undefined; + } + }, + splitJoin(value, { method }) { + if (method == "bind") { + return isString(value) ? value.split(",").filter(Boolean) : value; + } else { + return isArray(value) ? value.join(",") : value; + } + }, + json(value, { method }) { + if (method == "bind") { + try { + return JSON.parse(value); + } catch (e) { + return {}; + } + } else { + return JSON.stringify(value); + } + }, + empty(value) { + if (isString(value)) { + return value === "" ? undefined : value; + } + + if (isArray(value)) { + return isEmpty(value) ? undefined : value; + } + + return value; + } +}; + +function init({ value, form, prop }: any) { + if (prop) { + const [a, b] = prop.split("-"); + if (b) { + form[prop] = form[a] ? form[a][b] : form[a]; + } else { + form[prop] = value; + } + } +} + +function parse(method: "submit" | "bind", { value, hook: pipe, form, prop }: any) { + init({ value, method, form, prop }); + + if (!pipe) { + return false; + } + + let pipes: any[] = []; + + if (isString(pipe)) { + if (format[pipe]) { + pipes = [pipe]; + } else { + console.error(`[hook] ${pipe} is not found`); + } + } else if (isArray(pipe)) { + pipes = pipe; + } else if (isObject(pipe)) { + pipes = isArray(pipe[method]) ? pipe[method] : [pipe[method]]; + } else if (isFunction(pipe)) { + pipes = [pipe]; + } else { + console.error(`[hook] ${pipe} format error`); + } + + let v = value; + + pipes.forEach((e) => { + let f: any = null; + + if (isString(e)) { + f = format[e]; + } else if (isFunction(e)) { + f = e; + } + + if (f) { + v = f(v, { + method, + form, + prop + }); + } + }); + + if (prop) { + form[prop] = v; + } +} + +const formHook = { + bind(data: any) { + parse("bind", data); + }, + + submit(data: any) { + parse("submit", data); + } +}; + +export function registerFormHook(name: string, fn: ClForm.Hook["Fn"]) { + format[name] = fn; +} + +export default formHook; diff --git a/cool-admin-vue/packages/crud/src/utils/global.ts b/cool-admin-vue/packages/crud/src/utils/global.ts new file mode 100644 index 0000000..83b7b0b --- /dev/null +++ b/cool-admin-vue/packages/crud/src/utils/global.ts @@ -0,0 +1,16 @@ +// @ts-nocheck +import { type App } from "vue"; + +export default { + get vue(): App { + return window.__CrudApp__; + }, + + get(key: string) { + return window[key]; + }, + + set(key: string, value: any) { + window[key] = value; + } +}; diff --git a/cool-admin-vue/packages/crud/src/utils/index.ts b/cool-admin-vue/packages/crud/src/utils/index.ts new file mode 100644 index 0000000..05ae097 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/utils/index.ts @@ -0,0 +1,164 @@ +import { isRef, mergeProps, toValue } from "vue"; +import { assign, flatMap, isArray, isFunction, isNumber, mergeWith } from "lodash-es"; + +// 是否对象 +export function isObject(val: any) { + return val !== null && typeof val === "object"; +} + +// 解析px +export function parsePx(val: string | number) { + return isNumber(val) ? `${val}px` : val; +} + +// 数据设置 +export function dataset(obj: any, key: string, value: any): any { + const isGet = value === undefined; + let d = obj; + + const arr = flatMap( + key.split(".").map((e) => { + if (e.includes("[")) { + return e.split("[").map((e) => e.replace(/"/g, "")); + } else { + return e; + } + }) + ); + + try { + for (let i = 0; i < arr.length; i++) { + const e: any = arr[i]; + let n: any = null; + + if (e.includes("]")) { + const [k, v] = e.replace("]", "").split(":"); + + if (v) { + n = d.findIndex((x: any) => x[k] == v); + } else { + n = Number(k); + } + } else { + n = e; + } + + if (i != arr.length - 1) { + d = d[n]; + } else { + if (isGet) { + return d[n]; + } else { + if (isObject(value)) { + assign(d[n], value); + } else { + d[n] = value; + } + } + } + } + + return obj; + } catch (e) { + console.error("[dataset] format error", `${key}`); + return {}; + } +} + +// 元素是否包含 +export function contains(parent: any, node: any) { + return parent !== node && parent && parent.contains(node); +} + +// 合并配置 +export function mergeConfig(a: any, b?: any): any { + return b ? mergeProps(a, b) : a; +} + +// 合并数据 +export function merge(d1: any, d2: any) { + return mergeWith(d1, d2, (_, b) => { + if (isArray(b)) { + return b; + } + }); +} + +// 添加元素 +export function addClass(el: Element, name: string) { + if (el?.classList) { + el.classList.add(name); + } +} + +// 移除元素 +export function removeClass(el: Element, name: string) { + if (el?.classList) { + el.classList.remove(name); + } +} + +// 获取值 +export function getValue(value: T | Vue.Ref | ((d: any) => T), data?: any): T { + if (isRef(value)) { + return toValue(value) as T; + } else { + if (isFunction(value)) { + return value(data); + } else { + return value as T; + } + } +} + +// 深度查找 +export function deepFind(value: any, list: any[], options?: { allLevels: boolean }) { + const { allLevels = true } = options || {}; + + function deep(arr: DictOptions, name: string[]): any | undefined { + for (const e of arr) { + if (e.value === value) { + if (allLevels) { + return { + ...e, + label: [...name, e.label].join(" / ") + }; + } else { + return e; + } + } else if (e.children) { + const d = deep(e.children, [...name!, e.label!]); + + if (d !== undefined) { + return d; + } + } + } + return undefined; + } + + return deep(list, []); +} + +// uuid +export function uuid(separator = "-"): string { + const s: any[] = []; + const hexDigits = "0123456789abcdef"; + for (let i = 0; i < 36; i++) { + s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); + } + s[14] = "4"; + s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); + s[8] = s[13] = s[18] = s[23] = separator; + + return s.join(""); +} + +// 移除相同的方法 +export function uniqueFns(fns: any[]) { + const arr = new Map(); + fns.forEach((fn) => { + arr.set(fn.name, fn); + }); + return Array.from(arr.values()); +} diff --git a/cool-admin-vue/packages/crud/src/utils/mitt.ts b/cool-admin-vue/packages/crud/src/utils/mitt.ts new file mode 100644 index 0000000..b79cedb --- /dev/null +++ b/cool-admin-vue/packages/crud/src/utils/mitt.ts @@ -0,0 +1,30 @@ +import _mitt from "mitt"; + +const mitt = _mitt(); + +class Mitt { + id: number; + + constructor(id?: number) { + this.id = id || 0; + } + + send(type: "emit" | "off" | "on", name: string, ...args: any[]) { + // @ts-expect-error + mitt[type](`${this.id}__${name}`, ...args); + } + + emit(name: string, ...args: any[]) { + this.send("emit", name, ...args); + } + + off(name: string, handler: (...args: any[]) => void) { + this.send("off", name, handler); + } + + on(name: string, handler: (...args: any[]) => void) { + this.send("on", name, handler); + } +} + +export { Mitt, mitt }; diff --git a/cool-admin-vue/packages/crud/src/utils/parse.tsx b/cool-admin-vue/packages/crud/src/utils/parse.tsx new file mode 100644 index 0000000..404ccbb --- /dev/null +++ b/cool-admin-vue/packages/crud/src/utils/parse.tsx @@ -0,0 +1,52 @@ +import { isString } from "lodash-es"; +import { getValue, isObject } from "."; + +// 解析扩展组件 +export function parseExtensionComponent(vnode: Render.Component) { + if (["el-select", "el-radio-group", "el-checkbox-group"].includes(vnode.name!)) { + const list = getValue(vnode.options || []); + + const children = ( +
+ {list.map((e, i) => { + let label: any; + let value: any; + + if (isString(e)) { + label = value = e; + } else if (isObject(e)) { + label = e.label; + value = e.value; + } else { + return ; + } + + switch (vnode.name) { + case "el-select": + return ; + case "el-radio-group": + return ( + + {label} + + ); + case "el-checkbox-group": + return ( + + {label} + + ); + default: + return null; + } + })} +
+ ); + + return { + children + }; + } else { + return {}; + } +} diff --git a/cool-admin-vue/packages/crud/src/utils/vnode.tsx b/cool-admin-vue/packages/crud/src/utils/vnode.tsx new file mode 100644 index 0000000..e213eb1 --- /dev/null +++ b/cool-admin-vue/packages/crud/src/utils/vnode.tsx @@ -0,0 +1,182 @@ +import { h, resolveComponent, toRaw, type VNode } from "vue"; +import { isObject } from "./index"; +import { parseExtensionComponent } from "./parse"; +import global from "./global"; +import { useConfig } from "../hooks"; +import { isFunction, isString } from "lodash-es"; + +// 配置 +interface Options { + // 标识 + prop?: string; + // 数据值 + scope?: any; + // 当前行 + item?: any; + // 插槽 + slots?: any; + // 子集 + children?: any[] & any; + // 自定义 + custom?: (vnode: any) => any; + // 渲染方式 + render?: "slot" | null; + // 其他 + [key: string]: any; +} + +// 临时注册组件列表 +const regs: Map = new Map(); + +// 解析节点 +export function parseNode(vnode: any, options: Options): VNode { + const { scope, prop, slots, children, _data } = options || {}; + + // 渲染后组件 + let comp: VNode | null = null; + + // 插槽模式渲染 + if (vnode.name?.includes("slot-")) { + const rn = slots[vnode.name]; + + if (rn) { + return rn({ scope, prop, ..._data }); + } else { + return ; + } + } + + // 实例模式下,先注册到全局,再分解组件渲染 + if (vnode.vm && !regs.get(vnode.name)) { + global.vue.component(vnode.name, { ...vnode.vm }); + regs.set(vnode.name, { ...vnode.vm }); + } + + // 处理 props + if (isFunction(vnode.props)) { + vnode.props = vnode.props({ scope, prop, ..._data }); + } + + // 组件参数 + const props = { + ...vnode.props, + ..._data, + prop, + scope + }; + + // 是否禁用 + props.disabled = _data?.isDisabled || props.disabled; + + // 添加双向绑定 + if (props && scope) { + if (prop) { + props.modelValue = scope[prop]; + props["onUpdate:modelValue"] = function (val: any) { + scope[prop] = val; + }; + } + } + + // 组件实例渲染 + if (vnode.vm) { + comp = h(regs.get(vnode.name), props); + } else { + const slots = { + ...vnode.slots + }; + + if (children) { + slots.default = () => children; + } + + // 渲染组件 + comp = h(toRaw(resolveComponent(vnode.name)), props, slots); + } + + // 挂载到 refs 中 + const refBind = vnode.ref || options.ref; + if (isFunction(refBind)) { + setTimeout(() => { + refBind(comp?.component?.exposed); + }, 0); + } + + return comp; +} + +// 渲染节点 +export function renderNode(vnode: any, options: Options) { + const config = useConfig(); + const { item, scope, children, _data, render } = options || {}; + + if (!vnode) { + return null; + } + + if (vnode.__v_isVNode) { + return vnode; + } + + // 默认参数配置 + if (item) { + if (item.component) { + if (!item.component.props) { + item.component.props = {}; + } + + // 占位符 + let placeholder = ""; + + switch (item.component?.name) { + case "el-input": + placeholder = config.dict.label.placeholder; + break; + } + + if (placeholder) { + if (!item.component.props.placeholder) { + item.component.props.placeholder = placeholder; + } + } + } + } + + // 组件实例 + if (vnode.vm) { + if (!vnode.name) { + vnode.name = vnode.vm?.name || vnode.vm?.__hmrId; + } + + return parseNode(vnode, options); + } + + // 组件名渲染 + if (isString(vnode)) { + if (render == "slot") { + if (!vnode.includes("slot-")) { + return vnode; + } + } + + return parseNode({ name: vnode }, options); + } + + // 方法回调 + if (isFunction(vnode)) { + return vnode({ scope, h, ..._data }); + } + + // jsx 模式 + if (isObject(vnode)) { + if (vnode.name) { + return parseNode(vnode, { ...options, children, ...parseExtensionComponent(vnode) }); + } else { + if (options.custom) { + return options.custom(vnode); + } + + return ; + } + } +} diff --git a/cool-admin-vue/packages/crud/tsconfig.json b/cool-admin-vue/packages/crud/tsconfig.json new file mode 100644 index 0000000..75d48c2 --- /dev/null +++ b/cool-admin-vue/packages/crud/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "strict": false, + "noImplicitAny": false, + + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + "types": ["./index.d.ts"], + + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + }, + "declaration": true, + "declarationDir": "types", + "emitDeclarationOnly": true + }, + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], + "exclude": ["src/App.vue", "node_modules", "dist"] +} diff --git a/cool-admin-vue/packages/crud/types/components/add-btn/index.d.ts b/cool-admin-vue/packages/crud/types/components/add-btn/index.d.ts new file mode 100644 index 0000000..29d4988 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/add-btn/index.d.ts @@ -0,0 +1,2 @@ +declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/adv/btn.d.ts b/cool-admin-vue/packages/crud/types/components/adv/btn.d.ts new file mode 100644 index 0000000..5091404 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/adv/btn.d.ts @@ -0,0 +1,4 @@ +declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, { + Search: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/adv/search.d.ts b/cool-admin-vue/packages/crud/types/components/adv/search.d.ts new file mode 100644 index 0000000..569b3b2 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/adv/search.d.ts @@ -0,0 +1,90 @@ +import { PropType } from "vue"; + +declare const _default: import("vue").DefineComponent< + import("vue").ExtractPropTypes<{ + items: { + type: PropType; + default: () => any[]; + }; + title: StringConstructor; + size: { + type: (NumberConstructor | StringConstructor)[]; + default: string; + }; + op: { + type: ArrayConstructor; + default: () => string[]; + }; + onSearch: FunctionConstructor; + }>, + () => any, + {}, + {}, + {}, + import("vue").ComponentOptionsMixin, + import("vue").ComponentOptionsMixin, + ("clear" | "reset")[], + "clear" | "reset", + import("vue").PublicProps, + Readonly< + import("vue").ExtractPropTypes<{ + items: { + type: PropType; + default: () => any[]; + }; + title: StringConstructor; + size: { + type: (NumberConstructor | StringConstructor)[]; + default: string; + }; + op: { + type: ArrayConstructor; + default: () => string[]; + }; + onSearch: FunctionConstructor; + }> + > & + Readonly<{ + onReset?: (...args: any[]) => any; + onClear?: (...args: any[]) => any; + }>, + { + size: string | number; + items: ClForm.Item[]; + op: unknown[]; + }, + {}, + { + Close: import("vue").DefineComponent< + {}, + {}, + {}, + {}, + {}, + import("vue").ComponentOptionsMixin, + import("vue").ComponentOptionsMixin, + {}, + string, + import("vue").VNodeProps & + import("vue").AllowedComponentProps & + import("vue").ComponentCustomProps, + Readonly>, + {}, + {}, + {}, + {}, + string, + import("vue").ComponentProvideOptions, + true, + {}, + any + >; + }, + {}, + string, + import("vue").ComponentProvideOptions, + true, + {}, + any +>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/context-menu/index.d.ts b/cool-admin-vue/packages/crud/types/components/context-menu/index.d.ts new file mode 100644 index 0000000..8562fd9 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/context-menu/index.d.ts @@ -0,0 +1,55 @@ +import { PropType } from "vue"; + +declare const ClContextMenu: import("vue").DefineComponent< + import("vue").ExtractPropTypes<{ + show: BooleanConstructor; + options: { + type: PropType; + default: () => {}; + }; + event: { + type: ObjectConstructor; + default: () => {}; + }; + }>, + () => any, + {}, + {}, + {}, + import("vue").ComponentOptionsMixin, + import("vue").ComponentOptionsMixin, + {}, + string, + import("vue").PublicProps, + Readonly< + import("vue").ExtractPropTypes<{ + show: BooleanConstructor; + options: { + type: PropType; + default: () => {}; + }; + event: { + type: ObjectConstructor; + default: () => {}; + }; + }> + > & + Readonly<{}>, + { + options: ClContextMenu.Options; + show: boolean; + event: Record; + }, + {}, + {}, + {}, + string, + import("vue").ComponentProvideOptions, + true, + {}, + any +>; +export declare const ContextMenu: { + open(event: any, options: ClContextMenu.Options): ClContextMenu.Exposed; +}; +export default ClContextMenu; diff --git a/cool-admin-vue/packages/crud/types/components/crud/helper.d.ts b/cool-admin-vue/packages/crud/types/components/crud/helper.d.ts new file mode 100644 index 0000000..8744a15 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/crud/helper.d.ts @@ -0,0 +1,24 @@ +import { Mitt } from "../../utils/mitt"; + +interface Options { + mitt: Mitt; + config: ClCrud.Config; + crud: ClCrud.Ref; +} +export declare function useHelper({ config, crud, mitt }: Options): { + proxy: (name: string, data?: any[]) => void; + set: (key: string, value: any) => boolean; + on: (name: string, callback: fn) => void; + rowInfo: (data: any) => void; + rowAdd: () => void; + rowEdit: (data: any) => void; + rowAppend: (data: any) => void; + rowDelete: (...selection: any[]) => void; + rowClose: () => void; + refresh: (params?: obj) => Promise; + getPermission: (key: "page" | "list" | "info" | "update" | "add" | "delete") => boolean; + paramsReplace: (params: obj) => any; + getParams: () => obj; + setParams: (data: obj) => void; +}; +export {}; diff --git a/cool-admin-vue/packages/crud/types/components/crud/index.d.ts b/cool-admin-vue/packages/crud/types/components/crud/index.d.ts new file mode 100644 index 0000000..93e8de9 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/crud/index.d.ts @@ -0,0 +1,19 @@ +declare const _default: import('vue').DefineComponent, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly> & Readonly<{}>, { + border: boolean; + padding: string; +}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/dialog/index.d.ts b/cool-admin-vue/packages/crud/types/components/dialog/index.d.ts new file mode 100644 index 0000000..6482060 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/dialog/index.d.ts @@ -0,0 +1,86 @@ +declare const _default: import('vue').DefineComponent string[]; + }; + hideHeader: BooleanConstructor; + beforeClose: FunctionConstructor; + scrollbar: { + type: BooleanConstructor; + default: boolean; + }; + transparent: BooleanConstructor; +}>, () => import('vue').VNode, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("update:modelValue" | "fullscreen-change")[], "update:modelValue" | "fullscreen-change", import('vue').PublicProps, Readonly string[]; + }; + hideHeader: BooleanConstructor; + beforeClose: FunctionConstructor; + scrollbar: { + type: BooleanConstructor; + default: boolean; + }; + transparent: BooleanConstructor; +}>> & Readonly<{ + "onUpdate:modelValue"?: (...args: any[]) => any; + "onFullscreen-change"?: (...args: any[]) => any; +}>, { + title: string; + padding: string; + width: string; + hideHeader: boolean; + controls: unknown[]; + fullscreen: boolean; + keepAlive: boolean; + modelValue: boolean; + transparent: boolean; + scrollbar: boolean; +}, {}, { + Close: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; + FullScreen: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; + Minus: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/error-message/index.d.ts b/cool-admin-vue/packages/crud/types/components/error-message/index.d.ts new file mode 100644 index 0000000..bcc538c --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/error-message/index.d.ts @@ -0,0 +1,6 @@ +declare const _default: import('vue').DefineComponent, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/filter/index.d.ts b/cool-admin-vue/packages/crud/types/components/filter/index.d.ts new file mode 100644 index 0000000..bb8f8c6 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/filter/index.d.ts @@ -0,0 +1,6 @@ +declare const _default: import('vue').DefineComponent, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/flex1/index.d.ts b/cool-admin-vue/packages/crud/types/components/flex1/index.d.ts new file mode 100644 index 0000000..29d4988 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/flex1/index.d.ts @@ -0,0 +1,2 @@ +declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/form-card/index.d.ts b/cool-admin-vue/packages/crud/types/components/form-card/index.d.ts new file mode 100644 index 0000000..8c93df5 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/form-card/index.d.ts @@ -0,0 +1,28 @@ +declare const _default: import('vue').DefineComponent, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly> & Readonly<{}>, { + expand: boolean; + isExpand: boolean; +}, {}, { + ArrowDown: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; + ArrowUp: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/form-tabs/index.d.ts b/cool-admin-vue/packages/crud/types/components/form-tabs/index.d.ts new file mode 100644 index 0000000..fd55ecd --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/form-tabs/index.d.ts @@ -0,0 +1,67 @@ +import { PropType } from "vue"; + +declare const _default: import("vue").DefineComponent< + import("vue").ExtractPropTypes<{ + modelValue: (NumberConstructor | StringConstructor)[]; + labels: { + type: ArrayConstructor; + default: () => any[]; + }; + justify: { + type: PropType< + "start" | "end" | "left" | "right" | "center" | "justify" | "match-parent" + >; + default: string; + }; + type: { + type: PropType<"card" | "default">; + default: string; + }; + }>, + () => any, + {}, + {}, + {}, + import("vue").ComponentOptionsMixin, + import("vue").ComponentOptionsMixin, + ("change" | "update:modelValue")[], + "change" | "update:modelValue", + import("vue").PublicProps, + Readonly< + import("vue").ExtractPropTypes<{ + modelValue: (NumberConstructor | StringConstructor)[]; + labels: { + type: ArrayConstructor; + default: () => any[]; + }; + justify: { + type: PropType< + "start" | "end" | "left" | "right" | "center" | "justify" | "match-parent" + >; + default: string; + }; + type: { + type: PropType<"card" | "default">; + default: string; + }; + }> + > & + Readonly<{ + onChange?: (...args: any[]) => any; + "onUpdate:modelValue"?: (...args: any[]) => any; + }>, + { + type: "default" | "card"; + labels: unknown[]; + justify: "left" | "center" | "right" | "justify" | "start" | "end" | "match-parent"; + }, + {}, + {}, + {}, + string, + import("vue").ComponentProvideOptions, + true, + {}, + any +>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/form/helper/action.d.ts b/cool-admin-vue/packages/crud/types/components/form/helper/action.d.ts new file mode 100644 index 0000000..fef6a4d --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/form/helper/action.d.ts @@ -0,0 +1,17 @@ +export declare function useAction({ config, form, Form }: { + config: ClForm.Config; + form: obj; + Form: Vue.Ref; +}): { + getForm: (prop: string) => any; + setForm: (prop: string, value: any) => void; + setData: (prop: string, value: any) => void; + setConfig: (path: string, value: any) => void; + setOptions: (prop: string, value: any[]) => void; + setProps: (prop: string, value: any) => void; + toggleItem: (prop: string, value?: boolean) => void; + hideItem: (...props: string[]) => void; + showItem: (...props: string[]) => void; + setTitle: (value: string) => void; + collapseItem: (e: any) => void; +}; diff --git a/cool-admin-vue/packages/crud/types/components/form/helper/api.d.ts b/cool-admin-vue/packages/crud/types/components/form/helper/api.d.ts new file mode 100644 index 0000000..ea4f483 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/form/helper/api.d.ts @@ -0,0 +1,3 @@ +export declare function useApi({ Form }: { + Form: Vue.Ref; +}): obj; diff --git a/cool-admin-vue/packages/crud/types/components/form/helper/index.d.ts b/cool-admin-vue/packages/crud/types/components/form/helper/index.d.ts new file mode 100644 index 0000000..a6ae9b9 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/form/helper/index.d.ts @@ -0,0 +1,237 @@ +export declare function useForm(): { + Form: import('vue').Ref; + config: { + [x: string]: any; + title?: any; + height?: any; + width?: any; + props: { + [x: string]: any; + inline?: boolean; + labelPosition?: "left" | "right" | "top"; + labelWidth?: string | number; + labelSuffix?: string; + hideRequiredAsterisk?: boolean; + showMessage?: boolean; + inlineMessage?: boolean; + statusIcon?: boolean; + validateOnRuleChange?: boolean; + size?: ElementPlus.Size; + disabled?: boolean; + }; + items: { + [x: string]: any; + type?: "tabs"; + prop?: string & {}; + props?: { + [x: string]: any; + labels?: { + [x: string]: any; + label: string; + value: string; + name?: string; + icon?: any; + lazy?: boolean; + }[]; + justify?: "left" | "center" | "right"; + color?: string; + mergeProp?: boolean; + labelWidth?: string; + error?: string; + showMessage?: boolean; + inlineMessage?: boolean; + size?: "medium" | "default" | "small"; + }; + span?: number; + col?: { + span: number; + offset: number; + push: number; + pull: number; + xs: any; + sm: any; + md: any; + lg: any; + xl: any; + tag: string; + }; + group?: string; + collapse?: boolean; + value?: any; + label?: string; + renderLabel?: any; + flex?: boolean; + hook?: "string" | "number" | "boolean" | "join" | "split" | AnyString | "empty" | "booleanNumber" | "datetimeRange" | "splitJoin" | "json" | { + bind?: ClForm.Hook["Pipe"] | ClForm.Hook["Pipe"][]; + submit?: ClForm.Hook["Pipe"] | ClForm.Hook["Pipe"][]; + reset?: (prop: string) => string[]; + }; + hidden?: boolean | ((options: { + scope: obj; + }) => boolean); + prepend?: { + [x: string]: any; + name?: string; + options?: { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[] | { + value: { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[]; + }; + props?: { + [x: string]: any; + onChange?: (value: any) => void; + } | { + value: { + [x: string]: any; + onChange?: (value: any) => void; + }; + }; + style?: obj; + slots?: { + [key: string]: (data?: any) => any; + }; + vm?: any; + }; + component?: { + [x: string]: any; + name?: string; + options?: { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[] | { + value: { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[]; + }; + props?: { + [x: string]: any; + onChange?: (value: any) => void; + } | { + value: { + [x: string]: any; + onChange?: (value: any) => void; + }; + }; + style?: obj; + slots?: { + [key: string]: (data?: any) => any; + }; + vm?: any; + }; + append?: { + [x: string]: any; + name?: string; + options?: { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[] | { + value: { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[]; + }; + props?: { + [x: string]: any; + onChange?: (value: any) => void; + } | { + value: { + [x: string]: any; + onChange?: (value: any) => void; + }; + }; + style?: obj; + slots?: { + [key: string]: (data?: any) => any; + }; + vm?: any; + }; + rules?: { + [x: string]: any; + type?: "string" | "number" | "boolean" | "method" | "regexp" | "integer" | "float" | "array" | "object" | "enum" | "date" | "url" | "hex" | "email" | "any"; + required?: boolean; + message?: string; + min?: number; + max?: number; + trigger?: any; + validator?: (rule: any, value: any, callback: (error?: Error) => void) => void; + } | { + [x: string]: any; + type?: "string" | "number" | "boolean" | "method" | "regexp" | "integer" | "float" | "array" | "object" | "enum" | "date" | "url" | "hex" | "email" | "any"; + required?: boolean; + message?: string; + min?: number; + max?: number; + trigger?: any; + validator?: (rule: any, value: any, callback: (error?: Error) => void) => void; + }[]; + required?: boolean; + children?: /*elided*/ any[]; + }[]; + form: obj; + isReset?: boolean; + on?: { + open?: (data: any) => void; + close?: (action: ClForm.CloseAction, done: fn) => void; + submit?: (data: any, event: { + close: fn; + done: fn; + }) => void; + change?: (data: any, prop: string) => void; + }; + op: { + hidden?: boolean; + saveButtonText?: string; + closeButtonText?: string; + justify?: "flex-start" | "center" | "flex-end"; + buttons?: (`slot-${string}` | ClForm.CloseAction | { + [x: string]: any; + label: string; + type?: string; + hidden?: boolean; + onClick: (options: { + scope: obj; + }) => void; + })[]; + }; + dialog: { + [x: string]: any; + title?: any; + height?: string; + width?: string; + hideHeader?: boolean; + controls?: Array<"fullscreen" | "close" | AnyString>; + }; + }; + form: obj; + visible: import('vue').Ref; + saving: import('vue').Ref; + loading: import('vue').Ref; + disabled: import('vue').Ref; +}; +export * from './action'; +export * from './api'; +export * from './plugins'; +export * from './tabs'; diff --git a/cool-admin-vue/packages/crud/types/components/form/helper/plugins.d.ts b/cool-admin-vue/packages/crud/types/components/form/helper/plugins.d.ts new file mode 100644 index 0000000..20db6a0 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/form/helper/plugins.d.ts @@ -0,0 +1,13 @@ +import { Ref } from "vue"; + +export declare function usePlugins( + enable: boolean, + { + visible + }: { + visible: Ref; + } +): { + create: (plugins?: ClForm.Plugin[]) => boolean; + submit: (data: any) => Promise; +}; diff --git a/cool-admin-vue/packages/crud/types/components/form/helper/tabs.d.ts b/cool-admin-vue/packages/crud/types/components/form/helper/tabs.d.ts new file mode 100644 index 0000000..f1c24a6 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/form/helper/tabs.d.ts @@ -0,0 +1,19 @@ +export declare function useTabs({ config, Form }: { + config: ClForm.Config; + Form: Vue.Ref; +}): { + active: import('vue').Ref; + list: import('vue').ComputedRef; + isLoaded: (value: any) => any; + onLoad: (value: any) => void; + get: () => ClForm.Item; + set: (data: any) => void; + change: (value: any, isValid?: boolean) => Promise; + clear: () => void; + mergeProp: (item: ClForm.Item) => void; + toGroup: (opts: { + config: ClForm.Config; + prop: string; + refs: any; + }) => void; +}; diff --git a/cool-admin-vue/packages/crud/types/components/form/index.d.ts b/cool-admin-vue/packages/crud/types/components/form/index.d.ts new file mode 100644 index 0000000..a006771 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/form/index.d.ts @@ -0,0 +1,22 @@ +declare const _default: import('vue').DefineComponent, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly> & Readonly<{}>, { + inline: boolean; + inner: boolean; + enablePlugin: boolean; +}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/index.d.ts b/cool-admin-vue/packages/crud/types/components/index.d.ts new file mode 100644 index 0000000..c0278b1 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/index.d.ts @@ -0,0 +1,6 @@ +import { App } from "vue"; + +export declare const components: { + [key: string]: any; +}; +export declare function useComponent(app: App): void; diff --git a/cool-admin-vue/packages/crud/types/components/multi-delete-btn/index.d.ts b/cool-admin-vue/packages/crud/types/components/multi-delete-btn/index.d.ts new file mode 100644 index 0000000..29d4988 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/multi-delete-btn/index.d.ts @@ -0,0 +1,2 @@ +declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/pagination/index.d.ts b/cool-admin-vue/packages/crud/types/components/pagination/index.d.ts new file mode 100644 index 0000000..b82693a --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/pagination/index.d.ts @@ -0,0 +1,4 @@ +declare const _default: import('vue').DefineComponent<{}, () => import('vue').VNode, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/refresh-btn/index.d.ts b/cool-admin-vue/packages/crud/types/components/refresh-btn/index.d.ts new file mode 100644 index 0000000..29d4988 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/refresh-btn/index.d.ts @@ -0,0 +1,2 @@ +declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/row/index.d.ts b/cool-admin-vue/packages/crud/types/components/row/index.d.ts new file mode 100644 index 0000000..29d4988 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/row/index.d.ts @@ -0,0 +1,2 @@ +declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/search-key/index.d.ts b/cool-admin-vue/packages/crud/types/components/search-key/index.d.ts new file mode 100644 index 0000000..ca46dd1 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/search-key/index.d.ts @@ -0,0 +1,84 @@ +import { PropType } from "vue"; + +declare const _default: import("vue").DefineComponent< + import("vue").ExtractPropTypes<{ + modelValue: StringConstructor; + field: { + type: StringConstructor; + default: string; + }; + fieldList: { + type: PropType< + Array<{ + label: string; + value: string; + }> + >; + default: () => any[]; + }; + onSearch: FunctionConstructor; + placeholder: StringConstructor; + width: { + type: (NumberConstructor | StringConstructor)[]; + default: number; + }; + refreshOnInput: BooleanConstructor; + }>, + () => any, + {}, + {}, + {}, + import("vue").ComponentOptionsMixin, + import("vue").ComponentOptionsMixin, + ("change" | "update:modelValue" | "field-change")[], + "change" | "update:modelValue" | "field-change", + import("vue").PublicProps, + Readonly< + import("vue").ExtractPropTypes<{ + modelValue: StringConstructor; + field: { + type: StringConstructor; + default: string; + }; + fieldList: { + type: PropType< + Array<{ + label: string; + value: string; + }> + >; + default: () => any[]; + }; + onSearch: FunctionConstructor; + placeholder: StringConstructor; + width: { + type: (NumberConstructor | StringConstructor)[]; + default: number; + }; + refreshOnInput: BooleanConstructor; + }> + > & + Readonly<{ + onChange?: (...args: any[]) => any; + "onUpdate:modelValue"?: (...args: any[]) => any; + "onField-change"?: (...args: any[]) => any; + }>, + { + width: string | number; + refreshOnInput: boolean; + field: string; + fieldList: { + label: string; + value: string; + }[]; + }, + {}, + {}, + {}, + string, + import("vue").ComponentProvideOptions, + true, + {}, + any +>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/search/helper/plugins.d.ts b/cool-admin-vue/packages/crud/types/components/search/helper/plugins.d.ts new file mode 100644 index 0000000..7d1138c --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/search/helper/plugins.d.ts @@ -0,0 +1,3 @@ +export declare function usePlugins(): { + create: (plugins?: ClSearch.Plugin[]) => void; +}; diff --git a/cool-admin-vue/packages/crud/types/components/search/index.d.ts b/cool-admin-vue/packages/crud/types/components/search/index.d.ts new file mode 100644 index 0000000..6031d13 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/search/index.d.ts @@ -0,0 +1,91 @@ +import { PropType } from "vue"; + +declare const _default: import("vue").DefineComponent< + import("vue").ExtractPropTypes<{ + inline: { + type: BooleanConstructor; + default: boolean; + }; + props: { + type: ObjectConstructor; + default: () => {}; + }; + data: { + type: ObjectConstructor; + default: () => {}; + }; + items: { + type: PropType; + default: () => any[]; + }; + resetBtn: { + type: BooleanConstructor; + default: boolean; + }; + collapse: { + type: BooleanConstructor; + default: boolean; + }; + onLoad: FunctionConstructor; + onSearch: FunctionConstructor; + }>, + () => any, + {}, + {}, + {}, + import("vue").ComponentOptionsMixin, + import("vue").ComponentOptionsMixin, + "reset"[], + "reset", + import("vue").PublicProps, + Readonly< + import("vue").ExtractPropTypes<{ + inline: { + type: BooleanConstructor; + default: boolean; + }; + props: { + type: ObjectConstructor; + default: () => {}; + }; + data: { + type: ObjectConstructor; + default: () => {}; + }; + items: { + type: PropType; + default: () => any[]; + }; + resetBtn: { + type: BooleanConstructor; + default: boolean; + }; + collapse: { + type: BooleanConstructor; + default: boolean; + }; + onLoad: FunctionConstructor; + onSearch: FunctionConstructor; + }> + > & + Readonly<{ + onReset?: (...args: any[]) => any; + }>, + { + data: Record; + props: Record; + items: ClForm.Item[]; + inline: boolean; + resetBtn: boolean; + collapse: boolean; + }, + {}, + {}, + {}, + string, + import("vue").ComponentProvideOptions, + true, + {}, + any +>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/table/helper/data.d.ts b/cool-admin-vue/packages/crud/types/components/table/helper/data.d.ts new file mode 100644 index 0000000..932629f --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/helper/data.d.ts @@ -0,0 +1,7 @@ +export declare function useData({ config, Table }: { + config: ClTable.Config; + Table: Vue.Ref; +}): { + data: import('vue').Ref; + setData: (list: obj[]) => void; +}; diff --git a/cool-admin-vue/packages/crud/types/components/table/helper/header.d.ts b/cool-admin-vue/packages/crud/types/components/table/helper/header.d.ts new file mode 100644 index 0000000..0b4bd8b --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/helper/header.d.ts @@ -0,0 +1 @@ +export declare function renderHeader(item: ClTable.Column, { scope, slots }: any): any; diff --git a/cool-admin-vue/packages/crud/types/components/table/helper/height.d.ts b/cool-admin-vue/packages/crud/types/components/table/helper/height.d.ts new file mode 100644 index 0000000..12d050a --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/helper/height.d.ts @@ -0,0 +1,7 @@ +export declare function useHeight({ config, Table }: { + Table: Vue.Ref; + config: ClTable.Config; +}): { + maxHeight: import('vue').Ref; + calcMaxHeight: import('lodash').DebouncedFunc<() => Promise>; +}; diff --git a/cool-admin-vue/packages/crud/types/components/table/helper/index.d.ts b/cool-admin-vue/packages/crud/types/components/table/helper/index.d.ts new file mode 100644 index 0000000..e316b01 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/helper/index.d.ts @@ -0,0 +1,220 @@ +import { TableInstance } from "element-plus"; + +export declare function useTable(props: any): { + Table: import("vue").Ref; + config: { + columns: { + [x: string]: any; + type: ClTable.ColumnType; + hidden: + | boolean + | { + value: boolean; + }; + component: { + [x: string]: any; + name?: string; + options?: + | { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[] + | { + value: { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[]; + }; + props?: + | { + [x: string]: any; + onChange?: (value: any) => void; + } + | { + value: { + [x: string]: any; + onChange?: (value: any) => void; + }; + }; + style?: obj; + slots?: { + [key: string]: (data?: any) => any; + }; + vm?: any; + }; + search: { + isInput: boolean; + value: any; + icon: () => any; + refreshOnChange: boolean; + component: { + [x: string]: any; + name?: string; + options?: + | { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[] + | { + value: { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[]; + }; + props?: + | { + [x: string]: any; + onChange?: (value: any) => void; + } + | { + value: { + [x: string]: any; + onChange?: (value: any) => void; + }; + }; + style?: obj; + slots?: { + [key: string]: (data?: any) => any; + }; + vm?: any; + }; + }; + dict: + | { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[] + | { + value: { + [x: string]: any; + label?: string; + value?: any; + color?: string; + type?: string; + }[]; + }; + dictFormatter: (values: DictOptions) => string; + dictColor: boolean; + dictSeparator: string; + dictAllLevels: boolean; + buttons: + | ((options: { scope: any }) => ClTable.OpButton) + | ( + | "info" + | "delete" + | "edit" + | AnyString + | `slot-${string}` + | { + [x: string]: any; + label: string; + type?: string; + hidden?: boolean; + onClick: (options: { scope: obj }) => void; + } + )[]; + align: ElementPlus.Align; + label: any; + renderLabel: (options: { column: any; $index: number }) => any; + className: string; + prop: string & {}; + orderNum: number; + width: + | string + | number + | { + value: string | number; + }; + minWidth: + | string + | number + | { + value: string | number; + }; + renderHeader: (options: { column: any; $index: number }) => any; + sortable: boolean | "desc" | "descending" | "ascending" | "asc" | "custom"; + sortMethod: fn; + sortBy: string | any[] | ((row: any, index: number) => any); + resizable: boolean; + columnKey: string; + headerAlign: ElementPlus.Align; + showOverflowTooltip: boolean; + fixed: boolean | string; + render: (row: any, column: any, value: any, index: number) => any; + formatter: (row: any, column: any, value: any, index: number) => any; + selectable: (row: any, index: number) => boolean; + reserveSelection: boolean; + filterMethod: fn; + filteredValue: unknown[]; + filters: unknown[]; + filterPlacement: string; + filterMultiple: boolean; + index: ((index: number) => number) | number; + sortOrders: unknown[]; + children: /*elided*/ any[]; + }[]; + autoHeight: boolean; + height: any; + contextMenu: ( + | "info" + | "update" + | "delete" + | "edit" + | "refresh" + | { + [x: string]: any; + label: string; + prefixIcon?: any; + suffixIcon?: any; + ellipsis?: boolean; + disabled?: boolean; + hidden?: boolean; + children?: /*elided*/ any[]; + showChildren?: boolean; + callback?: (done: fn) => void; + } + | ((row: obj, column: obj, event: PointerEvent) => ClContextMenu.Item) + | "check" + | "order-desc" + | "order-asc" + )[]; + defaultSort: { + prop: string; + order: "descending" | "ascending"; + }; + sortRefresh: boolean; + emptyText: string; + rowKey: string; + on?: { + [key: string]: (...args: any[]) => void; + }; + props?: { + [key: string]: any; + }; + plugins?: ClTable.Plugin[]; + onRowContextmenu?: (row: any, column: any, event: any) => void; + }; +}; +export * from "./data"; +export * from "./height"; +export * from "./op"; +export * from "./render"; +export * from "./row"; +export * from "./selection"; +export * from "./sort"; +export * from "./header"; diff --git a/cool-admin-vue/packages/crud/types/components/table/helper/op.d.ts b/cool-admin-vue/packages/crud/types/components/table/helper/op.d.ts new file mode 100644 index 0000000..6e8a7a7 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/helper/op.d.ts @@ -0,0 +1,9 @@ +export declare function useOp({ config }: { + config: ClTable.Config; +}): { + visible: import('vue').Ref; + reBuild: (cb?: fn) => Promise; + showColumn: (prop: string | string[], status?: boolean) => void; + hideColumn: (prop: string | string[]) => void; + setColumns: (list: ClTable.Column[]) => void; +}; diff --git a/cool-admin-vue/packages/crud/types/components/table/helper/plugins.d.ts b/cool-admin-vue/packages/crud/types/components/table/helper/plugins.d.ts new file mode 100644 index 0000000..5e94af8 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/helper/plugins.d.ts @@ -0,0 +1,3 @@ +export declare function usePlugins(): { + create: (plugins?: ClTable.Plugin[]) => void; +}; diff --git a/cool-admin-vue/packages/crud/types/components/table/helper/render.d.ts b/cool-admin-vue/packages/crud/types/components/table/helper/render.d.ts new file mode 100644 index 0000000..226bd5e --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/helper/render.d.ts @@ -0,0 +1,7 @@ +export declare function useRender(): { + renderColumn: (columns: ClTable.Column[]) => import('vue').VNode[]; + renderEmpty: (emptyText: string) => any; + renderAppend: () => any; +}; diff --git a/cool-admin-vue/packages/crud/types/components/table/helper/row.d.ts b/cool-admin-vue/packages/crud/types/components/table/helper/row.d.ts new file mode 100644 index 0000000..1b70cad --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/helper/row.d.ts @@ -0,0 +1,13 @@ +export declare function useRow({ Table, config, Sort }: { + Table: Vue.Ref; + config: ClTable.Config; + Sort: { + defaultSort: { + prop?: string; + order?: string; + }; + changeSort(prop: string, order: string): void; + }; +}): { + onRowContextMenu: (row: obj, column: obj, event: PointerEvent) => void; +}; diff --git a/cool-admin-vue/packages/crud/types/components/table/helper/selection.d.ts b/cool-admin-vue/packages/crud/types/components/table/helper/selection.d.ts new file mode 100644 index 0000000..568a302 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/helper/selection.d.ts @@ -0,0 +1,6 @@ +export declare function useSelection({ emit }: { + emit: Vue.Emit; +}): { + selection: obj[]; + onSelectionChange: (selection: any[]) => void; +}; diff --git a/cool-admin-vue/packages/crud/types/components/table/helper/sort.d.ts b/cool-admin-vue/packages/crud/types/components/table/helper/sort.d.ts new file mode 100644 index 0000000..f996d62 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/helper/sort.d.ts @@ -0,0 +1,18 @@ +export declare function useSort({ config, Table, emit }: { + config: ClTable.Config; + Table: Vue.Ref; + emit: Vue.Emit; +}): { + defaultSort: { + prop: string; + order: "descending" | "ascending"; + } | { + prop?: undefined; + order?: undefined; + }; + onSortChange: ({ prop, order }: { + prop: string | undefined; + order: string; + }) => void; + changeSort: (prop: string, order: string) => void; +}; diff --git a/cool-admin-vue/packages/crud/types/components/table/index.d.ts b/cool-admin-vue/packages/crud/types/components/table/index.d.ts new file mode 100644 index 0000000..9ae9df3 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/table/index.d.ts @@ -0,0 +1,62 @@ +declare const _default: import('vue').DefineComponent any[]; + }; + autoHeight: { + type: BooleanConstructor; + default: any; + }; + height: any; + contextMenu: { + type: (ArrayConstructor | BooleanConstructor)[]; + default: any; + }; + defaultSort: ObjectConstructor; + sortRefresh: { + type: BooleanConstructor; + default: boolean; + }; + emptyText: StringConstructor; + rowKey: { + type: StringConstructor; + default: string; + }; +}>, () => import('vue').VNode, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("selection-change" | "sort-change")[], "selection-change" | "sort-change", import('vue').PublicProps, Readonly any[]; + }; + autoHeight: { + type: BooleanConstructor; + default: any; + }; + height: any; + contextMenu: { + type: (ArrayConstructor | BooleanConstructor)[]; + default: any; + }; + defaultSort: ObjectConstructor; + sortRefresh: { + type: BooleanConstructor; + default: boolean; + }; + emptyText: StringConstructor; + rowKey: { + type: StringConstructor; + default: string; + }; +}>> & Readonly<{ + "onSelection-change"?: (...args: any[]) => any; + "onSort-change"?: (...args: any[]) => any; +}>, { + columns: unknown[]; + autoHeight: boolean; + height: any; + contextMenu: boolean | unknown[]; + sortRefresh: boolean; + rowKey: string; +}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/components/upsert/index.d.ts b/cool-admin-vue/packages/crud/types/components/upsert/index.d.ts new file mode 100644 index 0000000..7b9fb0b --- /dev/null +++ b/cool-admin-vue/packages/crud/types/components/upsert/index.d.ts @@ -0,0 +1,38 @@ +declare const _default: import('vue').DefineComponent any[]; + }; + props: ObjectConstructor; + sync: BooleanConstructor; + op: ObjectConstructor; + dialog: ObjectConstructor; + onOpen: FunctionConstructor; + onOpened: FunctionConstructor; + onClose: FunctionConstructor; + onClosed: FunctionConstructor; + onInfo: FunctionConstructor; + onSubmit: FunctionConstructor; +}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("opened" | "closed")[], "opened" | "closed", import('vue').PublicProps, Readonly any[]; + }; + props: ObjectConstructor; + sync: BooleanConstructor; + op: ObjectConstructor; + dialog: ObjectConstructor; + onOpen: FunctionConstructor; + onOpened: FunctionConstructor; + onClose: FunctionConstructor; + onClosed: FunctionConstructor; + onInfo: FunctionConstructor; + onSubmit: FunctionConstructor; +}>> & Readonly<{ + onOpened?: (...args: any[]) => any; + onClosed?: (...args: any[]) => any; +}>, { + sync: boolean; + items: unknown[]; +}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/emitter.d.ts b/cool-admin-vue/packages/crud/types/emitter.d.ts new file mode 100644 index 0000000..b4d8fef --- /dev/null +++ b/cool-admin-vue/packages/crud/types/emitter.d.ts @@ -0,0 +1,2 @@ +export declare const crudList: ClCrud.Ref[]; +export declare const emitter: Emitter; diff --git a/cool-admin-vue/packages/crud/types/entry.d.ts b/cool-admin-vue/packages/crud/types/entry.d.ts new file mode 100644 index 0000000..654f597 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/entry.d.ts @@ -0,0 +1,17 @@ +import { App } from "vue"; + +declare const Crud: { + install( + app: App, + options?: any + ): { + name: string; + }; +}; +export { Crud }; +export * from "./emitter"; +export * from "./hooks"; +export * from "./locale"; +export { registerFormHook } from "./utils/form-hook"; +export { renderNode } from "./utils/vnode"; +export { ContextMenu } from "./components/context-menu"; diff --git a/cool-admin-vue/packages/crud/types/hooks/crud.d.ts b/cool-admin-vue/packages/crud/types/hooks/crud.d.ts new file mode 100644 index 0000000..a077eeb --- /dev/null +++ b/cool-admin-vue/packages/crud/types/hooks/crud.d.ts @@ -0,0 +1,25 @@ +import { Ref } from "vue"; + +export declare function useCrud( + options?: ClCrud.Options, + cb?: (app: ClCrud.Ref) => void +): Ref; +export declare function useUpsert( + options?: ClUpsert.Options +): Ref, ClUpsert.Ref>; +export declare function useTable( + options?: ClTable.Options, + cb?: (table: ClTable.Ref) => void +): Ref, ClTable.Ref>; +export declare function useForm( + cb?: (app: ClForm.Ref) => void +): Ref, ClForm.Ref>; +export declare function useAdvSearch( + options?: ClAdvSearch.Options +): Ref, ClAdvSearch.Ref>; +export declare function useSearch( + options?: ClSearch.Options +): Ref, ClSearch.Ref>; +export declare function useDialog(options?: { + onFullscreen(visible: boolean): void; +}): ClDialog.Provide; diff --git a/cool-admin-vue/packages/crud/types/hooks/index.d.ts b/cool-admin-vue/packages/crud/types/hooks/index.d.ts new file mode 100644 index 0000000..22812a9 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/hooks/index.d.ts @@ -0,0 +1,17 @@ +import { Mitt } from "../utils/mitt"; + +export declare function useCore(): { + crud: ClCrud.Ref; + mitt: Mitt; +}; +export declare function useConfig(): Config; +export declare function useBrowser(): Browser; +export declare function useRefs(): { + refs: { + [key: string]: obj; + }; + setRefs: (name: string) => (el: any) => void; +}; +export declare function useProxy(ctx: any): any; +export declare function useElApi(keys: string[], el: any): obj; +export * from "./crud"; diff --git a/cool-admin-vue/packages/crud/types/locale/en.d.ts b/cool-admin-vue/packages/crud/types/locale/en.d.ts new file mode 100644 index 0000000..d0c88bd --- /dev/null +++ b/cool-admin-vue/packages/crud/types/locale/en.d.ts @@ -0,0 +1,33 @@ +declare const _default: { + op: string; + add: string; + delete: string; + multiDelete: string; + update: string; + refresh: string; + info: string; + search: string; + reset: string; + clear: string; + save: string; + close: string; + confirm: string; + advSearch: string; + searchKey: string; + placeholder: string; + tips: string; + saveSuccess: string; + deleteSuccess: string; + deleteConfirm: string; + empty: string; + desc: string; + asc: string; + select: string; + deselect: string; + seeMore: string; + hideContent: string; + nonEmpty: string; + collapse: string; + expand: string; +}; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/locale/index.d.ts b/cool-admin-vue/packages/crud/types/locale/index.d.ts new file mode 100644 index 0000000..a9e8362 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/locale/index.d.ts @@ -0,0 +1,130 @@ +export declare const locale: { + en: { + op: string; + add: string; + delete: string; + multiDelete: string; + update: string; + refresh: string; + info: string; + search: string; + reset: string; + clear: string; + save: string; + close: string; + confirm: string; + advSearch: string; + searchKey: string; + placeholder: string; + tips: string; + saveSuccess: string; + deleteSuccess: string; + deleteConfirm: string; + empty: string; + desc: string; + asc: string; + select: string; + deselect: string; + seeMore: string; + hideContent: string; + nonEmpty: string; + collapse: string; + expand: string; + }; + ja: { + op: string; + add: string; + delete: string; + multiDelete: string; + update: string; + refresh: string; + info: string; + search: string; + reset: string; + clear: string; + save: string; + close: string; + confirm: string; + advSearch: string; + searchKey: string; + placeholder: string; + tips: string; + saveSuccess: string; + deleteSuccess: string; + deleteConfirm: string; + empty: string; + desc: string; + asc: string; + select: string; + deselect: string; + seeMore: string; + hideContent: string; + nonEmpty: string; + collapse: string; + expand: string; + }; + "zh-cn": { + op: string; + add: string; + delete: string; + multiDelete: string; + update: string; + refresh: string; + info: string; + search: string; + reset: string; + clear: string; + save: string; + close: string; + confirm: string; + advSearch: string; + searchKey: string; + placeholder: string; + tips: string; + saveSuccess: string; + deleteSuccess: string; + deleteConfirm: string; + empty: string; + desc: string; + asc: string; + select: string; + deselect: string; + seeMore: string; + hideContent: string; + nonEmpty: string; + collapse: string; + expand: string; + }; + "zh-tw": { + op: string; + add: string; + delete: string; + multiDelete: string; + update: string; + refresh: string; + info: string; + search: string; + reset: string; + clear: string; + save: string; + close: string; + confirm: string; + advSearch: string; + searchKey: string; + placeholder: string; + tips: string; + saveSuccess: string; + deleteSuccess: string; + deleteConfirm: string; + empty: string; + desc: string; + asc: string; + select: string; + deselect: string; + seeMore: string; + hideContent: string; + nonEmpty: string; + collapse: string; + expand: string; + }; +}; diff --git a/cool-admin-vue/packages/crud/types/locale/ja.d.ts b/cool-admin-vue/packages/crud/types/locale/ja.d.ts new file mode 100644 index 0000000..d0c88bd --- /dev/null +++ b/cool-admin-vue/packages/crud/types/locale/ja.d.ts @@ -0,0 +1,33 @@ +declare const _default: { + op: string; + add: string; + delete: string; + multiDelete: string; + update: string; + refresh: string; + info: string; + search: string; + reset: string; + clear: string; + save: string; + close: string; + confirm: string; + advSearch: string; + searchKey: string; + placeholder: string; + tips: string; + saveSuccess: string; + deleteSuccess: string; + deleteConfirm: string; + empty: string; + desc: string; + asc: string; + select: string; + deselect: string; + seeMore: string; + hideContent: string; + nonEmpty: string; + collapse: string; + expand: string; +}; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/locale/zh-cn.d.ts b/cool-admin-vue/packages/crud/types/locale/zh-cn.d.ts new file mode 100644 index 0000000..d0c88bd --- /dev/null +++ b/cool-admin-vue/packages/crud/types/locale/zh-cn.d.ts @@ -0,0 +1,33 @@ +declare const _default: { + op: string; + add: string; + delete: string; + multiDelete: string; + update: string; + refresh: string; + info: string; + search: string; + reset: string; + clear: string; + save: string; + close: string; + confirm: string; + advSearch: string; + searchKey: string; + placeholder: string; + tips: string; + saveSuccess: string; + deleteSuccess: string; + deleteConfirm: string; + empty: string; + desc: string; + asc: string; + select: string; + deselect: string; + seeMore: string; + hideContent: string; + nonEmpty: string; + collapse: string; + expand: string; +}; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/locale/zh-tw.d.ts b/cool-admin-vue/packages/crud/types/locale/zh-tw.d.ts new file mode 100644 index 0000000..d0c88bd --- /dev/null +++ b/cool-admin-vue/packages/crud/types/locale/zh-tw.d.ts @@ -0,0 +1,33 @@ +declare const _default: { + op: string; + add: string; + delete: string; + multiDelete: string; + update: string; + refresh: string; + info: string; + search: string; + reset: string; + clear: string; + save: string; + close: string; + confirm: string; + advSearch: string; + searchKey: string; + placeholder: string; + tips: string; + saveSuccess: string; + deleteSuccess: string; + deleteConfirm: string; + empty: string; + desc: string; + asc: string; + select: string; + deselect: string; + seeMore: string; + hideContent: string; + nonEmpty: string; + collapse: string; + expand: string; +}; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/main.d.ts b/cool-admin-vue/packages/crud/types/main.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/cool-admin-vue/packages/crud/types/provide.d.ts b/cool-admin-vue/packages/crud/types/provide.d.ts new file mode 100644 index 0000000..3995aec --- /dev/null +++ b/cool-admin-vue/packages/crud/types/provide.d.ts @@ -0,0 +1,3 @@ +import { App } from "vue"; + +export declare function useProvide(app: App, options?: Options): void; diff --git a/cool-admin-vue/packages/crud/types/test/service.d.ts b/cool-admin-vue/packages/crud/types/test/service.d.ts new file mode 100644 index 0000000..84d6dd2 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/test/service.d.ts @@ -0,0 +1,52 @@ +declare class TestService { + page(params: any): Promise; + update(params: { + id: any; + [key: string]: any; + }): Promise; + add(params: any): Promise; + info(params: { + id: any; + }): Promise<{ + id: number; + name: string; + createTime: string; + wages: number; + status: number; + account: string; + occupation: number; + phone: number; + }>; + delete(params: { + ids: any[]; + }): Promise; + list(): Promise<{ + id: number; + name: string; + createTime: string; + wages: number; + status: number; + account: string; + occupation: number; + phone: number; + }[]>; + search: { + fieldEq: { + propertyName: string; + comment: string; + source: string; + }[]; + fieldLike: { + propertyName: string; + comment: string; + dict: string[]; + source: string; + }[]; + keyWordLikeFields: { + propertyName: string; + comment: string; + source: string; + }[]; + }; +} +export { TestService }; diff --git a/cool-admin-vue/packages/crud/types/utils/form-hook.d.ts b/cool-admin-vue/packages/crud/types/utils/form-hook.d.ts new file mode 100644 index 0000000..7e5b2cf --- /dev/null +++ b/cool-admin-vue/packages/crud/types/utils/form-hook.d.ts @@ -0,0 +1,9 @@ +export declare const format: { + [key: string]: ClForm.Hook["Fn"]; +}; +declare const formHook: { + bind(data: any): void; + submit(data: any): void; +}; +export declare function registerFormHook(name: string, fn: ClForm.Hook["Fn"]): void; +export default formHook; diff --git a/cool-admin-vue/packages/crud/types/utils/global.d.ts b/cool-admin-vue/packages/crud/types/utils/global.d.ts new file mode 100644 index 0000000..fac3730 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/utils/global.d.ts @@ -0,0 +1,8 @@ +import { App } from "vue"; + +declare const _default: { + readonly vue: App; + get(key: string): any; + set(key: string, value: any): void; +}; +export default _default; diff --git a/cool-admin-vue/packages/crud/types/utils/index.d.ts b/cool-admin-vue/packages/crud/types/utils/index.d.ts new file mode 100644 index 0000000..2351cd0 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/utils/index.d.ts @@ -0,0 +1,14 @@ +export declare function isObject(val: any): boolean; +export declare function parsePx(val: string | number): string; +export declare function dataset(obj: any, key: string, value: any): any; +export declare function contains(parent: any, node: any): any; +export declare function mergeConfig(a: any, b?: any): any; +export declare function merge(d1: any, d2: any): any; +export declare function addClass(el: Element, name: string): void; +export declare function removeClass(el: Element, name: string): void; +export declare function getValue(value: T | Vue.Ref | ((d: any) => T), data?: any): T; +export declare function deepFind(value: any, list: any[], options?: { + allLevels: boolean; +}): any; +export declare function uuid(separator?: string): string; +export declare function uniqueFns(fns: any[]): any[]; diff --git a/cool-admin-vue/packages/crud/types/utils/mitt.d.ts b/cool-admin-vue/packages/crud/types/utils/mitt.d.ts new file mode 100644 index 0000000..be94bfc --- /dev/null +++ b/cool-admin-vue/packages/crud/types/utils/mitt.d.ts @@ -0,0 +1,10 @@ +declare const mitt: import('mitt').Emitter>; +declare class Mitt { + id: number; + constructor(id?: number); + send(type: "emit" | "off" | "on", name: string, ...args: any[]): void; + emit(name: string, ...args: any[]): void; + off(name: string, handler: (...args: any[]) => void): void; + on(name: string, handler: (...args: any[]) => void): void; +} +export { Mitt, mitt }; diff --git a/cool-admin-vue/packages/crud/types/utils/parse.d.ts b/cool-admin-vue/packages/crud/types/utils/parse.d.ts new file mode 100644 index 0000000..d4639fd --- /dev/null +++ b/cool-admin-vue/packages/crud/types/utils/parse.d.ts @@ -0,0 +1,5 @@ +export declare function parseExtensionComponent(vnode: Render.Component): { + children: any; +} | { + children?: undefined; +}; diff --git a/cool-admin-vue/packages/crud/types/utils/vnode.d.ts b/cool-admin-vue/packages/crud/types/utils/vnode.d.ts new file mode 100644 index 0000000..d3fa417 --- /dev/null +++ b/cool-admin-vue/packages/crud/types/utils/vnode.d.ts @@ -0,0 +1,15 @@ +import { VNode } from "vue"; + +interface Options { + prop?: string; + scope?: any; + item?: any; + slots?: any; + children?: any[] & any; + custom?: (vnode: any) => any; + render?: "slot" | null; + [key: string]: any; +} +export declare function parseNode(vnode: any, options: Options): VNode; +export declare function renderNode(vnode: any, options: Options): any; +export {}; diff --git a/cool-admin-vue/packages/crud/vite.config.ts b/cool-admin-vue/packages/crud/vite.config.ts new file mode 100644 index 0000000..b8e622c --- /dev/null +++ b/cool-admin-vue/packages/crud/vite.config.ts @@ -0,0 +1,49 @@ +import { defineConfig } from "vite"; +import vue from "@vitejs/plugin-vue"; +import vueJsx from "@vitejs/plugin-vue-jsx"; +import dts from "vite-plugin-dts"; +import { resolve } from "path"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + dts({ + include: ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"], + outDir: "types" + }) + ], + + css: { + preprocessorOptions: { + scss: { + charset: false, + api: "modern-compiler" + } + } + }, + + build: { + lib: { + entry: resolve(__dirname, "src/entry.ts"), + name: "index", + fileName: (format) => `index.${format}.js`, + cssFileName: "index" + }, + rollupOptions: { + external: ["element-plus", "@element-plus/icons-vue", "vue"], + output: { + exports: "named", + globals: { + "element-plus": "ElementPlus", + "@element-plus/icons-vue": "ElementPlusIconsVue", + vue: "Vue" + } + } + }, + sourcemap: true, + minify: "terser", + cssCodeSplit: false + } +}); diff --git a/cool-admin-vue/packages/crud/yarn.lock b/cool-admin-vue/packages/crud/yarn.lock new file mode 100644 index 0000000..4271e79 --- /dev/null +++ b/cool-admin-vue/packages/crud/yarn.lock @@ -0,0 +1,1790 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@babel/code-frame@^7.26.2", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/compat-data@^7.27.2": + version "7.28.0" + resolved "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.28.0.tgz#9fc6fd58c2a6a15243cd13983224968392070790" + integrity sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw== + +"@babel/core@^7.27.1": + version "7.28.0" + resolved "https://registry.npmmirror.com/@babel/core/-/core-7.28.0.tgz#55dad808d5bf3445a108eefc88ea3fdf034749a4" + integrity sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.0" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-module-transforms" "^7.27.3" + "@babel/helpers" "^7.27.6" + "@babel/parser" "^7.28.0" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.0" + "@babel/types" "^7.28.0" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.28.0": + version "7.28.0" + resolved "https://registry.npmmirror.com/@babel/generator/-/generator-7.28.0.tgz#9cc2f7bd6eb054d77dc66c2664148a0c5118acd2" + integrity sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg== + dependencies: + "@babel/parser" "^7.28.0" + "@babel/types" "^7.28.0" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/helper-annotate-as-pure@^7.27.1", "@babel/helper-annotate-as-pure@^7.27.3": + version "7.27.3" + resolved "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz#f31fd86b915fc4daf1f3ac6976c59be7084ed9c5" + integrity sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg== + dependencies: + "@babel/types" "^7.27.3" + +"@babel/helper-compilation-targets@^7.27.2": + version "7.27.2" + resolved "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== + dependencies: + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz#5bee4262a6ea5ddc852d0806199eb17ca3de9281" + integrity sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/traverse" "^7.27.1" + semver "^6.3.1" + +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-member-expression-to-functions@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz#ea1211276be93e798ce19037da6f06fbb994fa44" + integrity sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-module-imports@^7.25.9", "@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-module-transforms@^7.27.3": + version "7.27.3" + resolved "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz#db0bbcfba5802f9ef7870705a7ef8788508ede02" + integrity sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg== + dependencies: + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.27.3" + +"@babel/helper-optimise-call-expression@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200" + integrity sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw== + dependencies: + "@babel/types" "^7.27.1" + +"@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== + +"@babel/helper-replace-supers@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz#b1ed2d634ce3bdb730e4b52de30f8cccfd692bc0" + integrity sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/traverse" "^7.27.1" + +"@babel/helper-skip-transparent-expression-wrappers@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz#62bb91b3abba8c7f1fec0252d9dbea11b3ee7a56" + integrity sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helpers@^7.27.6": + version "7.27.6" + resolved "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.27.6.tgz#6456fed15b2cb669d2d1fabe84b66b34991d812c" + integrity sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug== + dependencies: + "@babel/template" "^7.27.2" + "@babel/types" "^7.27.6" + +"@babel/parser@^7.26.9", "@babel/parser@^7.27.2", "@babel/parser@^7.27.5", "@babel/parser@^7.28.0": + version "7.28.0" + resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.0.tgz#979829fbab51a29e13901e5a80713dbcb840825e" + integrity sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g== + dependencies: + "@babel/types" "^7.28.0" + +"@babel/plugin-syntax-jsx@^7.25.9": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz#2f9beb5eff30fa507c5532d107daac7b888fa34c" + integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-typescript@^7.27.1": + version "7.27.1" + resolved "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz#5147d29066a793450f220c63fa3a9431b7e6dd18" + integrity sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-typescript@^7.27.1": + version "7.28.0" + resolved "https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz#796cbd249ab56c18168b49e3e1d341b72af04a6b" + integrity sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.3" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/plugin-syntax-typescript" "^7.27.1" + +"@babel/template@^7.26.9", "@babel/template@^7.27.2": + version "7.27.2" + resolved "https://registry.npmmirror.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + +"@babel/traverse@^7.26.9", "@babel/traverse@^7.27.1", "@babel/traverse@^7.27.3", "@babel/traverse@^7.28.0": + version "7.28.0" + resolved "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.28.0.tgz#518aa113359b062042379e333db18380b537e34b" + integrity sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.0" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.0" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.0" + debug "^4.3.1" + +"@babel/types@^7.26.9", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.27.6", "@babel/types@^7.28.0": + version "7.28.1" + resolved "https://registry.npmmirror.com/@babel/types/-/types-7.28.1.tgz#2aaf3c10b31ba03a77ac84f52b3912a0edef4cf9" + integrity sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + +"@ctrl/tinycolor@^3.4.1": + version "3.6.1" + resolved "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz#b6c75a56a1947cc916ea058772d666a2c8932f31" + integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== + +"@element-plus/icons-vue@^2.3.1": + version "2.3.1" + resolved "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz#1f635ad5fdd5c85ed936481525570e82b5a8307a" + integrity sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg== + +"@esbuild/aix-ppc64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz#a1414903bb38027382f85f03dda6065056757727" + integrity sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA== + +"@esbuild/android-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz#c859994089e9767224269884061f89dae6fb51c6" + integrity sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w== + +"@esbuild/android-arm@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.8.tgz#96a8f2ca91c6cd29ea90b1af79d83761c8ba0059" + integrity sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw== + +"@esbuild/android-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.8.tgz#a3a626c4fec4a024a9fa8c7679c39996e92916f0" + integrity sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA== + +"@esbuild/darwin-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz#a5e1252ca2983d566af1c0ea39aded65736fc66d" + integrity sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw== + +"@esbuild/darwin-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz#5271b0df2bb12ce8df886704bfdd1c7cc01385d2" + integrity sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg== + +"@esbuild/freebsd-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz#d0a0e7fdf19733b8bb1566b81df1aa0bb7e46ada" + integrity sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA== + +"@esbuild/freebsd-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz#2de8b2e0899d08f1cb1ef3128e159616e7e85343" + integrity sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw== + +"@esbuild/linux-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz#a4209efadc0c2975716458484a4e90c237c48ae9" + integrity sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w== + +"@esbuild/linux-arm@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz#ccd9e291c24cd8d9142d819d463e2e7200d25b19" + integrity sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg== + +"@esbuild/linux-ia32@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz#006ad1536d0c2b28fb3a1cf0b53bcb85aaf92c4d" + integrity sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg== + +"@esbuild/linux-loong64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz#127b3fbfb2c2e08b1397e985932f718f09a8f5c4" + integrity sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ== + +"@esbuild/linux-mips64el@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz#837d1449517791e3fa7d82675a2d06d9f56cb340" + integrity sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw== + +"@esbuild/linux-ppc64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz#aa2e3bd93ab8df084212f1895ca4b03c42d9e0fe" + integrity sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ== + +"@esbuild/linux-riscv64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz#a340620e31093fef72767dd28ab04214b3442083" + integrity sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg== + +"@esbuild/linux-s390x@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz#ddfed266c8c13f5efb3105a0cd47f6dcd0e79e71" + integrity sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg== + +"@esbuild/linux-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz#9a4f78c75c051e8c060183ebb39a269ba936a2ac" + integrity sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ== + +"@esbuild/netbsd-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz#902c80e1d678047926387230bc037e63e00697d0" + integrity sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw== + +"@esbuild/netbsd-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz#2d9eb4692add2681ff05a14ce99de54fbed7079c" + integrity sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg== + +"@esbuild/openbsd-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz#89c3b998c6de739db38ab7fb71a8a76b3fa84a45" + integrity sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ== + +"@esbuild/openbsd-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz#2f01615cf472b0e48c077045cfd96b5c149365cc" + integrity sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ== + +"@esbuild/openharmony-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz#a201f720cd2c3ebf9a6033fcc3feb069a54b509a" + integrity sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg== + +"@esbuild/sunos-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz#07046c977985a3334667f19e6ab3a01a80862afb" + integrity sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w== + +"@esbuild/win32-arm64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz#4a5470caf0d16127c05d4833d4934213c69392d1" + integrity sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ== + +"@esbuild/win32-ia32@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz#3de3e8470b7b328d99dbc3e9ec1eace207e5bbc4" + integrity sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg== + +"@esbuild/win32-x64@0.25.8": + version "0.25.8" + resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz#610d7ea539d2fcdbe39237b5cc175eb2c4451f9c" + integrity sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw== + +"@floating-ui/core@^1.7.2": + version "1.7.2" + resolved "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.2.tgz#3d1c35263950b314b6d5a72c8bfb9e3c1551aefd" + integrity sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw== + dependencies: + "@floating-ui/utils" "^0.2.10" + +"@floating-ui/dom@^1.0.1": + version "1.7.2" + resolved "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.2.tgz#3540b051cf5ce0d4f4db5fb2507a76e8ea5b4a45" + integrity sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA== + dependencies: + "@floating-ui/core" "^1.7.2" + "@floating-ui/utils" "^0.2.10" + +"@floating-ui/utils@^0.2.10": + version "0.2.10" + resolved "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.10.tgz#a2a1e3812d14525f725d011a73eceb41fef5bc1c" + integrity sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ== + +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.12" + resolved "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz#2234ce26c62889f03db3d7fea43c1932ab3e927b" + integrity sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.4" + resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz#7358043433b2e5da569aa02cbc4c121da3af27d7" + integrity sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw== + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.29" + resolved "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz#a58d31eaadaf92c6695680b2e1d464a9b8fbf7fc" + integrity sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@microsoft/api-extractor-model@7.30.6": + version "7.30.6" + resolved "https://registry.npmmirror.com/@microsoft/api-extractor-model/-/api-extractor-model-7.30.6.tgz#cd9c434521dda3b226cc0f6aefb9c20afaf99c92" + integrity sha512-znmFn69wf/AIrwHya3fxX6uB5etSIn6vg4Q4RB/tb5VDDs1rqREc+AvMC/p19MUN13CZ7+V/8pkYPTj7q8tftg== + dependencies: + "@microsoft/tsdoc" "~0.15.1" + "@microsoft/tsdoc-config" "~0.17.1" + "@rushstack/node-core-library" "5.13.1" + +"@microsoft/api-extractor@^7.50.1": + version "7.52.8" + resolved "https://registry.npmmirror.com/@microsoft/api-extractor/-/api-extractor-7.52.8.tgz#7cc944f44ca1b1ad9d7272ab5d98e81987c1f8ca" + integrity sha512-cszYIcjiNscDoMB1CIKZ3My61+JOhpERGlGr54i6bocvGLrcL/wo9o+RNXMBrb7XgLtKaizZWUpqRduQuHQLdg== + dependencies: + "@microsoft/api-extractor-model" "7.30.6" + "@microsoft/tsdoc" "~0.15.1" + "@microsoft/tsdoc-config" "~0.17.1" + "@rushstack/node-core-library" "5.13.1" + "@rushstack/rig-package" "0.5.3" + "@rushstack/terminal" "0.15.3" + "@rushstack/ts-command-line" "5.0.1" + lodash "~4.17.15" + minimatch "~3.0.3" + resolve "~1.22.1" + semver "~7.5.4" + source-map "~0.6.1" + typescript "5.8.2" + +"@microsoft/tsdoc-config@~0.17.1": + version "0.17.1" + resolved "https://registry.npmmirror.com/@microsoft/tsdoc-config/-/tsdoc-config-0.17.1.tgz#e0f0b50628f4ad7fe121ca616beacfe6a25b9335" + integrity sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw== + dependencies: + "@microsoft/tsdoc" "0.15.1" + ajv "~8.12.0" + jju "~1.4.0" + resolve "~1.22.2" + +"@microsoft/tsdoc@0.15.1", "@microsoft/tsdoc@~0.15.1": + version "0.15.1" + resolved "https://registry.npmmirror.com/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz#d4f6937353bc4568292654efb0a0e0532adbcba2" + integrity sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw== + +"@parcel/watcher-android-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1" + integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA== + +"@parcel/watcher-darwin-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz#3d26dce38de6590ef79c47ec2c55793c06ad4f67" + integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw== + +"@parcel/watcher-darwin-x64@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz#99f3af3869069ccf774e4ddfccf7e64fd2311ef8" + integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg== + +"@parcel/watcher-freebsd-x64@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz#14d6857741a9f51dfe51d5b08b7c8afdbc73ad9b" + integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ== + +"@parcel/watcher-linux-arm-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz#43c3246d6892381db473bb4f663229ad20b609a1" + integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA== + +"@parcel/watcher-linux-arm-musl@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz#663750f7090bb6278d2210de643eb8a3f780d08e" + integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q== + +"@parcel/watcher-linux-arm64-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz#ba60e1f56977f7e47cd7e31ad65d15fdcbd07e30" + integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w== + +"@parcel/watcher-linux-arm64-musl@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz#f7fbcdff2f04c526f96eac01f97419a6a99855d2" + integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg== + +"@parcel/watcher-linux-x64-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz#4d2ea0f633eb1917d83d483392ce6181b6a92e4e" + integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A== + +"@parcel/watcher-linux-x64-musl@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz#277b346b05db54f55657301dd77bdf99d63606ee" + integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg== + +"@parcel/watcher-win32-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz#7e9e02a26784d47503de1d10e8eab6cceb524243" + integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw== + +"@parcel/watcher-win32-ia32@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz#2d0f94fa59a873cdc584bf7f6b1dc628ddf976e6" + integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ== + +"@parcel/watcher-win32-x64@2.5.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz#ae52693259664ba6f2228fa61d7ee44b64ea0947" + integrity sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA== + +"@parcel/watcher@^2.4.1": + version "2.5.1" + resolved "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.1.tgz#342507a9cfaaf172479a882309def1e991fb1200" + integrity sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg== + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.5.1" + "@parcel/watcher-darwin-arm64" "2.5.1" + "@parcel/watcher-darwin-x64" "2.5.1" + "@parcel/watcher-freebsd-x64" "2.5.1" + "@parcel/watcher-linux-arm-glibc" "2.5.1" + "@parcel/watcher-linux-arm-musl" "2.5.1" + "@parcel/watcher-linux-arm64-glibc" "2.5.1" + "@parcel/watcher-linux-arm64-musl" "2.5.1" + "@parcel/watcher-linux-x64-glibc" "2.5.1" + "@parcel/watcher-linux-x64-musl" "2.5.1" + "@parcel/watcher-win32-arm64" "2.5.1" + "@parcel/watcher-win32-ia32" "2.5.1" + "@parcel/watcher-win32-x64" "2.5.1" + +"@popperjs/core@npm:@sxzz/popperjs-es@^2.11.7": + version "2.11.7" + resolved "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz#a7f69e3665d3da9b115f9e71671dae1b97e13671" + integrity sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ== + +"@rolldown/pluginutils@^1.0.0-beta.9": + version "1.0.0-beta.28" + resolved "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.28.tgz#3a5887a3cd4b556afedf1f4a282fd061e2bb2524" + integrity sha512-fe3/1HZ3qJmXvkGv1kacKq2b+x9gbcyF1hnmLBVrRFEQWoOcRapQjXf8+hgyxI0EJAbnKEtrp5yhohQCFCjycw== + +"@rollup/pluginutils@^5.1.4": + version "5.2.0" + resolved "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.2.0.tgz#eac25ca5b0bdda4ba735ddaca5fbf26bd435f602" + integrity sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^4.0.2" + +"@rollup/rollup-android-arm-eabi@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.1.tgz#8560592f0dcf43b8cb0949af9f1d916205148d12" + integrity sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA== + +"@rollup/rollup-android-arm64@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.1.tgz#6bfb777bbce998691b6fd3e916b05cd46392d020" + integrity sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ== + +"@rollup/rollup-darwin-arm64@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.1.tgz#7efce10220293a22e7b7b595d05d8b8400a7bcf3" + integrity sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA== + +"@rollup/rollup-darwin-x64@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.1.tgz#c617a8ece21050bfbea299c126767d2e70cfa79a" + integrity sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og== + +"@rollup/rollup-freebsd-arm64@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.1.tgz#5a6af0a9acf82162d2910933649ae24fc0ea3ecb" + integrity sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g== + +"@rollup/rollup-freebsd-x64@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.1.tgz#ae9709463560196fc275bd0da598668a2e341023" + integrity sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A== + +"@rollup/rollup-linux-arm-gnueabihf@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.1.tgz#6ec52661764dbd54c19d6520a403aa385a5c0fbf" + integrity sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q== + +"@rollup/rollup-linux-arm-musleabihf@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.1.tgz#fd33ba4a43ef8419e96811236493d19436271923" + integrity sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q== + +"@rollup/rollup-linux-arm64-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.1.tgz#933b3d99b73c9d7bf4506cab0d5d313c7e74fd2d" + integrity sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw== + +"@rollup/rollup-linux-arm64-musl@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.1.tgz#dbe9ae24ee9e97b75662fddcb69eb7f23c89280a" + integrity sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog== + +"@rollup/rollup-linux-loongarch64-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.1.tgz#818c5a071eec744436dbcdd76fe9c3c869dc9a8d" + integrity sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg== + +"@rollup/rollup-linux-powerpc64le-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.1.tgz#6b8591def27d886fa147fb0340126c7d6682a7e4" + integrity sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg== + +"@rollup/rollup-linux-riscv64-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.1.tgz#f1861ac4ee8da64e0b0d23853ff26fe2baa876cf" + integrity sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw== + +"@rollup/rollup-linux-riscv64-musl@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.1.tgz#320c961401a923b374e358664527b188e374e1ae" + integrity sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA== + +"@rollup/rollup-linux-s390x-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.1.tgz#1763eed3362b50b6164d3f0947486c03cc7e616d" + integrity sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw== + +"@rollup/rollup-linux-x64-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.1.tgz#0d4c8d0b8f801902f0844a40a9d981a0179f4971" + integrity sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw== + +"@rollup/rollup-linux-x64-musl@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.1.tgz#ec30bb48b5fe22a3aaba98072f2d5b7139e1a8eb" + integrity sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw== + +"@rollup/rollup-win32-arm64-msvc@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.1.tgz#27a6e48d1502e8e4bed96bedfb533738655874f2" + integrity sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg== + +"@rollup/rollup-win32-ia32-msvc@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.1.tgz#a2fbad3bec20ff879f3fd51720adf33692ca8f3d" + integrity sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw== + +"@rollup/rollup-win32-x64-msvc@4.45.1": + version "4.45.1" + resolved "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.1.tgz#e5085c6d13da15b4c5133cd2a6bb11f25b6bb77a" + integrity sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA== + +"@rushstack/node-core-library@5.13.1": + version "5.13.1" + resolved "https://registry.npmmirror.com/@rushstack/node-core-library/-/node-core-library-5.13.1.tgz#e56b915ecb08b5a92711acac6b233417353a32dc" + integrity sha512-5yXhzPFGEkVc9Fu92wsNJ9jlvdwz4RNb2bMso+/+TH0nMm1jDDDsOIf4l8GAkPxGuwPw5DH24RliWVfSPhlW/Q== + dependencies: + ajv "~8.13.0" + ajv-draft-04 "~1.0.0" + ajv-formats "~3.0.1" + fs-extra "~11.3.0" + import-lazy "~4.0.0" + jju "~1.4.0" + resolve "~1.22.1" + semver "~7.5.4" + +"@rushstack/rig-package@0.5.3": + version "0.5.3" + resolved "https://registry.npmmirror.com/@rushstack/rig-package/-/rig-package-0.5.3.tgz#ea4d8a3458540b1295500149c04e645f23134e5d" + integrity sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow== + dependencies: + resolve "~1.22.1" + strip-json-comments "~3.1.1" + +"@rushstack/terminal@0.15.3": + version "0.15.3" + resolved "https://registry.npmmirror.com/@rushstack/terminal/-/terminal-0.15.3.tgz#365e0ae5ac73bb4883b096ae36c5011f52911861" + integrity sha512-DGJ0B2Vm69468kZCJkPj3AH5nN+nR9SPmC0rFHtzsS4lBQ7/dgOwtwVxYP7W9JPDMuRBkJ4KHmWKr036eJsj9g== + dependencies: + "@rushstack/node-core-library" "5.13.1" + supports-color "~8.1.1" + +"@rushstack/ts-command-line@5.0.1": + version "5.0.1" + resolved "https://registry.npmmirror.com/@rushstack/ts-command-line/-/ts-command-line-5.0.1.tgz#e147394b5ce87ef79db95b5b4f155461d6f2c50e" + integrity sha512-bsbUucn41UXrQK7wgM8CNM/jagBytEyJqXw/umtI8d68vFm1Jwxh1OtLrlW7uGZgjCWiiPH6ooUNa1aVsuVr3Q== + dependencies: + "@rushstack/terminal" "0.15.3" + "@types/argparse" "1.0.38" + argparse "~1.0.9" + string-argv "~0.3.1" + +"@types/argparse@1.0.38": + version "1.0.38" + resolved "https://registry.npmmirror.com/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9" + integrity sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA== + +"@types/estree@1.0.8", "@types/estree@^1.0.0": + version "1.0.8" + resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/lodash-es@^4.17.6": + version "4.17.12" + resolved "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz#65f6d1e5f80539aa7cfbfc962de5def0cf4f341b" + integrity sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*", "@types/lodash@^4.14.182": + version "4.17.20" + resolved "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.20.tgz#1ca77361d7363432d29f5e55950d9ec1e1c6ea93" + integrity sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA== + +"@types/node@^20.11.16": + version "20.19.9" + resolved "https://registry.npmmirror.com/@types/node/-/node-20.19.9.tgz#ca9a58193fec361cc6e859d88b52261853f1f0d3" + integrity sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw== + dependencies: + undici-types "~6.21.0" + +"@types/web-bluetooth@^0.0.16": + version "0.0.16" + resolved "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz#1d12873a8e49567371f2a75fe3e7f7edca6662d8" + integrity sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ== + +"@vitejs/plugin-vue-jsx@^4.1.1": + version "4.2.0" + resolved "https://registry.npmmirror.com/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-4.2.0.tgz#2738ec05d4705ed553a107342017192e37351640" + integrity sha512-DSTrmrdLp+0LDNF77fqrKfx7X0ErRbOcUAgJL/HbSesqQwoUvUQ4uYQqaex+rovqgGcoPqVk+AwUh3v9CuiYIw== + dependencies: + "@babel/core" "^7.27.1" + "@babel/plugin-transform-typescript" "^7.27.1" + "@rolldown/pluginutils" "^1.0.0-beta.9" + "@vue/babel-plugin-jsx" "^1.4.0" + +"@vitejs/plugin-vue@^5.2.1": + version "5.2.4" + resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz#9e8a512eb174bfc2a333ba959bbf9de428d89ad8" + integrity sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA== + +"@volar/language-core@2.4.15": + version "2.4.15" + resolved "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz#759d04cb4eab9920560b8bcfa4515d5b08a1b7ce" + integrity sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA== + dependencies: + "@volar/source-map" "2.4.15" + +"@volar/language-core@2.4.20", "@volar/language-core@~2.4.11": + version "2.4.20" + resolved "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.20.tgz#be6d4efc6bb2f77d6c01bbbb3ef53661a869e0d0" + integrity sha512-dRDF1G33xaAIDqR6+mXUIjXYdu9vzSxlMGfMEwBxQsfY/JMUEXSpLTR057oTKlUQ2nIvCmP9k94A8h8z2VrNSA== + dependencies: + "@volar/source-map" "2.4.20" + +"@volar/source-map@2.4.15": + version "2.4.15" + resolved "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.15.tgz#18aba09994c0268e59a418f9d738e4a85302781d" + integrity sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg== + +"@volar/source-map@2.4.20": + version "2.4.20" + resolved "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.20.tgz#55ff844410d8d670ef2c3722e2717223edbf8717" + integrity sha512-mVjmFQH8mC+nUaVwmbxoYUy8cww+abaO8dWzqPUjilsavjxH0jCJ3Mp8HFuHsdewZs2c+SP+EO7hCd8Z92whJg== + +"@volar/typescript@2.4.15": + version "2.4.15" + resolved "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.15.tgz#1445d23f8e4f9ad821b6bfa58cf4a2b980dc5f97" + integrity sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg== + dependencies: + "@volar/language-core" "2.4.15" + path-browserify "^1.0.1" + vscode-uri "^3.0.8" + +"@volar/typescript@^2.4.11": + version "2.4.20" + resolved "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.20.tgz#c388d6fe5ee31ddeb5338d01dbbfc71054065a7c" + integrity sha512-Oc4DczPwQyXcVbd+5RsNEqX6ia0+w3p+klwdZQ6ZKhFjWoBP9PCPQYlKYRi/tDemWphW93P/Vv13vcE9I9D2GQ== + dependencies: + "@volar/language-core" "2.4.20" + path-browserify "^1.0.1" + vscode-uri "^3.0.8" + +"@vue/babel-helper-vue-transform-on@1.4.0": + version "1.4.0" + resolved "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.4.0.tgz#616020488692a9c42a613280d62ed1b727045d95" + integrity sha512-mCokbouEQ/ocRce/FpKCRItGo+013tHg7tixg3DUNS+6bmIchPt66012kBMm476vyEIJPafrvOf4E5OYj3shSw== + +"@vue/babel-plugin-jsx@^1.4.0": + version "1.4.0" + resolved "https://registry.npmmirror.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.4.0.tgz#c155c795ce980edf46aa6feceed93945a95ca658" + integrity sha512-9zAHmwgMWlaN6qRKdrg1uKsBKHvnUU+Py+MOCTuYZBoZsopa90Di10QRjB+YPnVss0BZbG/H5XFwJY1fTxJWhA== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.26.5" + "@babel/plugin-syntax-jsx" "^7.25.9" + "@babel/template" "^7.26.9" + "@babel/traverse" "^7.26.9" + "@babel/types" "^7.26.9" + "@vue/babel-helper-vue-transform-on" "1.4.0" + "@vue/babel-plugin-resolve-type" "1.4.0" + "@vue/shared" "^3.5.13" + +"@vue/babel-plugin-resolve-type@1.4.0": + version "1.4.0" + resolved "https://registry.npmmirror.com/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.4.0.tgz#4d357a81fb0cc9cad0e8c81b118115bda2c51543" + integrity sha512-4xqDRRbQQEWHQyjlYSgZsWj44KfiF6D+ktCuXyZ8EnVDYV3pztmXJDf1HveAjUAXxAnR8daCQT51RneWWxtTyQ== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.26.5" + "@babel/parser" "^7.26.9" + "@vue/compiler-sfc" "^3.5.13" + +"@vue/compiler-core@3.5.17": + version "3.5.17" + resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.17.tgz#23d291bd01b863da3ef2e26e7db84d8e01a9b4c5" + integrity sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA== + dependencies: + "@babel/parser" "^7.27.5" + "@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", "@vue/compiler-dom@^3.5.0": + version "3.5.17" + resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz#7bc19a20e23b670243a64b47ce3a890239b870be" + integrity sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ== + dependencies: + "@vue/compiler-core" "3.5.17" + "@vue/shared" "3.5.17" + +"@vue/compiler-sfc@3.5.17", "@vue/compiler-sfc@^3.5.13": + version "3.5.17" + resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz#c518871276e26593612bdab36f3f5bcd053b13bf" + integrity sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww== + dependencies: + "@babel/parser" "^7.27.5" + "@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": + version "3.5.17" + resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz#14ba3b7bba6e0e1fd02002316263165a5d1046c7" + integrity sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ== + dependencies: + "@vue/compiler-dom" "3.5.17" + "@vue/shared" "3.5.17" + +"@vue/compiler-vue2@^2.7.16": + version "2.7.16" + resolved "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz#2ba837cbd3f1b33c2bc865fbe1a3b53fb611e249" + integrity sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A== + dependencies: + de-indent "^1.0.2" + he "^1.2.0" + +"@vue/language-core@2.2.0": + version "2.2.0" + resolved "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.0.tgz#e48c54584f889f78b120ce10a050dfb316c7fcdf" + integrity sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw== + dependencies: + "@volar/language-core" "~2.4.11" + "@vue/compiler-dom" "^3.5.0" + "@vue/compiler-vue2" "^2.7.16" + "@vue/shared" "^3.5.0" + alien-signals "^0.4.9" + minimatch "^9.0.3" + muggle-string "^0.4.1" + path-browserify "^1.0.1" + +"@vue/language-core@2.2.12": + version "2.2.12" + resolved "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.12.tgz#d01f7e865f593f968cb65c12a13d8337e65641f0" + integrity sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA== + dependencies: + "@volar/language-core" "2.4.15" + "@vue/compiler-dom" "^3.5.0" + "@vue/compiler-vue2" "^2.7.16" + "@vue/shared" "^3.5.0" + alien-signals "^1.0.3" + minimatch "^9.0.3" + muggle-string "^0.4.1" + path-browserify "^1.0.1" + +"@vue/reactivity@3.5.17": + version "3.5.17" + resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.17.tgz#169b5dcf96c7f23788e5ed9745ec8a7227f2125e" + integrity sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw== + dependencies: + "@vue/shared" "3.5.17" + +"@vue/runtime-core@3.5.17", "@vue/runtime-core@^3.5.13": + version "3.5.17" + resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.17.tgz#b17bd41e13011e85e9b1025545292d43f5512730" + integrity sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q== + dependencies: + "@vue/reactivity" "3.5.17" + "@vue/shared" "3.5.17" + +"@vue/runtime-dom@3.5.17": + version "3.5.17" + resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.17.tgz#8e325e29cd03097fe179032fc8df384a426fc83a" + integrity sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g== + 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": + version "3.5.17" + resolved "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.17.tgz#9b8fd6a40a3d55322509fafe78ac841ede649fbe" + integrity sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA== + dependencies: + "@vue/compiler-ssr" "3.5.17" + "@vue/shared" "3.5.17" + +"@vue/shared@3.5.17", "@vue/shared@^3.5.0", "@vue/shared@^3.5.13": + version "3.5.17" + resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.17.tgz#e8b3a41f0be76499882a89e8ed40d86a70fa4b70" + integrity sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg== + +"@vueuse/core@^9.1.0": + version "9.13.0" + resolved "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz#2f69e66d1905c1e4eebc249a01759cf88ea00cf4" + integrity sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw== + dependencies: + "@types/web-bluetooth" "^0.0.16" + "@vueuse/metadata" "9.13.0" + "@vueuse/shared" "9.13.0" + vue-demi "*" + +"@vueuse/metadata@9.13.0": + version "9.13.0" + resolved "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz#bc25a6cdad1b1a93c36ce30191124da6520539ff" + integrity sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ== + +"@vueuse/shared@9.13.0": + version "9.13.0" + resolved "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz#089ff4cc4e2e7a4015e57a8f32e4b39d096353b9" + integrity sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw== + dependencies: + vue-demi "*" + +acorn@^8.14.0: + version "8.15.0" + resolved "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +ajv-draft-04@~1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" + integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== + +ajv-formats@~3.0.1: + version "3.0.1" + resolved "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + +ajv@^8.0.0: + version "8.17.1" + resolved "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ajv@~8.12.0: + version "8.12.0" + resolved "https://registry.npmmirror.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ajv@~8.13.0: + version "8.13.0" + resolved "https://registry.npmmirror.com/ajv/-/ajv-8.13.0.tgz#a3939eaec9fb80d217ddf0c3376948c023f28c91" + integrity sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA== + dependencies: + fast-deep-equal "^3.1.3" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.4.1" + +alien-signals@^0.4.9: + version "0.4.14" + resolved "https://registry.npmmirror.com/alien-signals/-/alien-signals-0.4.14.tgz#9ff8f72a272300a51692f54bd9bbbada78fbf539" + integrity sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q== + +alien-signals@^1.0.3: + version "1.0.13" + resolved "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz#8d6db73462f742ee6b89671fbd8c37d0b1727a7e" + integrity sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg== + +argparse@~1.0.9: + version "1.0.10" + resolved "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +async-validator@^4.2.5: + version "4.2.5" + resolved "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339" + integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.12" + resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.24.0: + version "4.25.1" + resolved "https://registry.npmmirror.com/browserslist/-/browserslist-4.25.1.tgz#ba9e8e6f298a1d86f829c9b975e07948967bb111" + integrity sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw== + dependencies: + caniuse-lite "^1.0.30001726" + electron-to-chromium "^1.5.173" + node-releases "^2.0.19" + update-browserslist-db "^1.1.3" + +caniuse-lite@^1.0.30001726: + version "1.0.30001727" + resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz#22e9706422ad37aa50556af8c10e40e2d93a8b85" + integrity sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q== + +chokidar@^4.0.0: + version "4.0.3" + resolved "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +compare-versions@^6.1.1: + version "6.1.1" + resolved "https://registry.npmmirror.com/compare-versions/-/compare-versions-6.1.1.tgz#7af3cc1099ba37d244b3145a9af5201b629148a9" + integrity sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.npmmirror.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +confbox@^0.2.2: + version "0.2.2" + resolved "https://registry.npmmirror.com/confbox/-/confbox-0.2.2.tgz#8652f53961c74d9e081784beed78555974a9c110" + integrity sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +csstype@^3.1.3: + version "3.1.3" + resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +dayjs@^1.11.13: + version "1.11.13" + resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== + +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== + +debug@^4.1.0, debug@^4.3.1, debug@^4.4.0: + version "4.4.1" + resolved "https://registry.npmmirror.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== + dependencies: + ms "^2.1.3" + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + +electron-to-chromium@^1.5.173: + version "1.5.187" + resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.187.tgz#8c58854e065962351dc87e95614dd78d50425966" + integrity sha512-cl5Jc9I0KGUoOoSbxvTywTa40uspGJt/BDBoDLoxJRSBpWh4FFXBsjNRHfQrONsV/OoEjDfHUmZQa2d6Ze4YgA== + +element-plus@^2.10.4: + version "2.10.4" + resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.10.4.tgz#72de60a6074be79f9f1b299f422e7ac96a3b5e9a" + integrity sha512-UD4elWHrCnp1xlPhbXmVcaKFLCRaRAY6WWRwemGfGW3ceIjXm9fSYc9RNH3AiOEA6Ds1p9ZvhCs76CR9J8Vd+A== + dependencies: + "@ctrl/tinycolor" "^3.4.1" + "@element-plus/icons-vue" "^2.3.1" + "@floating-ui/dom" "^1.0.1" + "@popperjs/core" "npm:@sxzz/popperjs-es@^2.11.7" + "@types/lodash" "^4.14.182" + "@types/lodash-es" "^4.17.6" + "@vueuse/core" "^9.1.0" + async-validator "^4.2.5" + dayjs "^1.11.13" + escape-html "^1.0.3" + lodash "^4.17.21" + lodash-es "^4.17.21" + lodash-unified "^1.0.2" + memoize-one "^6.0.0" + normalize-wheel-es "^1.2.0" + +entities@^4.5.0: + version "4.5.0" + resolved "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +esbuild@^0.25.0: + version "0.25.8" + resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.8.tgz#482d42198b427c9c2f3a81b63d7663aecb1dda07" + integrity sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q== + 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: + version "3.2.0" + resolved "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-html@^1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +exsolve@^1.0.7: + version "1.0.7" + resolved "https://registry.npmmirror.com/exsolve/-/exsolve-1.0.7.tgz#3b74e4c7ca5c5f9a19c3626ca857309fa99f9e9e" + integrity sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-uri@^3.0.1: + version "3.0.6" + resolved "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" + integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== + +fdir@^6.4.4: + version "6.4.6" + resolved "https://registry.npmmirror.com/fdir/-/fdir-6.4.6.tgz#2b268c0232697063111bbf3f64810a2a741ba281" + integrity sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w== + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +fs-extra@~11.3.0: + version "11.3.0" + resolved "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d" + integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +immutable@^5.0.2: + version "5.1.3" + resolved "https://registry.npmmirror.com/immutable/-/immutable-5.1.3.tgz#e6486694c8b76c37c063cca92399fa64098634d4" + integrity sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg== + +import-lazy@~4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" + integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== + +is-core-module@^2.16.0: + version "2.16.1" + resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +jju@~1.4.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +kolorist@^1.8.0: + version "1.8.0" + resolved "https://registry.npmmirror.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" + integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + +local-pkg@^1.0.0: + version "1.1.1" + resolved "https://registry.npmmirror.com/local-pkg/-/local-pkg-1.1.1.tgz#f5fe74a97a3bd3c165788ee08ca9fbe998dc58dd" + integrity sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg== + dependencies: + mlly "^1.7.4" + pkg-types "^2.0.1" + quansync "^0.2.8" + +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + +lodash-unified@^1.0.2: + version "1.0.3" + resolved "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz#80b1eac10ed2eb02ed189f08614a29c27d07c894" + integrity sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ== + +lodash@^4.17.21, lodash@~4.17.15: + version "4.17.21" + resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +magic-string@^0.30.17: + version "0.30.17" + resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" + integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + +memoize-one@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" + integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== + +micromatch@^4.0.5: + version "4.0.8" + resolved "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +minimatch@^9.0.3: + version "9.0.5" + resolved "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimatch@~3.0.3: + version "3.0.8" + resolved "https://registry.npmmirror.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" + integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q== + dependencies: + brace-expansion "^1.1.7" + +mlly@^1.7.4: + version "1.7.4" + resolved "https://registry.npmmirror.com/mlly/-/mlly-1.7.4.tgz#3d7295ea2358ec7a271eaa5d000a0f84febe100f" + integrity sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw== + dependencies: + acorn "^8.14.0" + pathe "^2.0.1" + pkg-types "^1.3.0" + ufo "^1.5.4" + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +muggle-string@^0.4.1: + version "0.4.1" + resolved "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz#3b366bd43b32f809dc20659534dd30e7c8a0d328" + integrity sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ== + +nanoid@^3.3.11: + version "3.3.11" + resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-addon-api@^7.0.0: + version "7.1.1" + resolved "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" + integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== + +node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== + +normalize-wheel-es@^1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz#0fa2593d619f7245a541652619105ab076acf09e" + integrity sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw== + +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +pathe@^2.0.1, pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2: + version "4.0.3" + resolved "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + +pkg-types@^1.3.0: + version "1.3.1" + resolved "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.3.1.tgz#bd7cc70881192777eef5326c19deb46e890917df" + integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + dependencies: + confbox "^0.1.8" + mlly "^1.7.4" + pathe "^2.0.1" + +pkg-types@^2.0.1: + version "2.2.0" + resolved "https://registry.npmmirror.com/pkg-types/-/pkg-types-2.2.0.tgz#049bf404f82a66c465200149457acf0c5fb0fb2d" + integrity sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ== + dependencies: + confbox "^0.2.2" + exsolve "^1.0.7" + pathe "^2.0.3" + +postcss@^8.5.3, postcss@^8.5.6: + version "8.5.6" + resolved "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +prettier@^3.5.1: + version "3.6.2" + resolved "https://registry.npmmirror.com/prettier/-/prettier-3.6.2.tgz#ccda02a1003ebbb2bfda6f83a074978f608b9393" + integrity sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +quansync@^0.2.8: + version "0.2.10" + resolved "https://registry.npmmirror.com/quansync/-/quansync-0.2.10.tgz#32053cf166fa36511aae95fc49796116f2dc20e1" + integrity sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A== + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve@~1.22.1, resolve@~1.22.2: + version "1.22.10" + resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" + integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== + dependencies: + is-core-module "^2.16.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +rollup@^4.34.9: + version "4.45.1" + resolved "https://registry.npmmirror.com/rollup/-/rollup-4.45.1.tgz#d0ef72a8d0a9210d832f9c3c5f3b6a2aa4b0ba64" + integrity sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw== + 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.2" + +sass-loader@^16.0.5: + version "16.0.5" + resolved "https://registry.npmmirror.com/sass-loader/-/sass-loader-16.0.5.tgz#257bc90119ade066851cafe7f2c3f3504c7cda98" + integrity sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw== + dependencies: + neo-async "^2.6.2" + +sass@^1.85.0: + version "1.89.2" + resolved "https://registry.npmmirror.com/sass/-/sass-1.89.2.tgz#a771716aeae774e2b529f72c0ff2dfd46c9de10e" + integrity sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA== + dependencies: + chokidar "^4.0.0" + immutable "^5.0.2" + source-map-js ">=0.6.2 <2.0.0" + optionalDependencies: + "@parcel/watcher" "^2.4.1" + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@~7.5.4: + version "7.5.4" + resolved "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +string-argv@~0.3.1: + version "0.3.2" + resolved "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" + integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== + +strip-json-comments@~3.1.1: + version "3.1.1" + resolved "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@~8.1.1: + version "8.1.1" + resolved "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tinyglobby@^0.2.13: + version "0.2.14" + resolved "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d" + integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== + dependencies: + fdir "^6.4.4" + picomatch "^4.0.2" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +typescript@5.8.2: + version "5.8.2" + resolved "https://registry.npmmirror.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4" + integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ== + +typescript@^5.3.3: + version "5.8.3" + resolved "https://registry.npmmirror.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== + +ufo@^1.5.4: + version "1.6.1" + resolved "https://registry.npmmirror.com/ufo/-/ufo-1.6.1.tgz#ac2db1d54614d1b22c1d603e3aef44a85d8f146b" + integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +update-browserslist-db@^1.1.3: + version "1.1.3" + resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" + integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +uri-js@^4.2.2, uri-js@^4.4.1: + version "4.4.1" + resolved "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +vite-plugin-dts@^4.5.0: + version "4.5.4" + resolved "https://registry.npmmirror.com/vite-plugin-dts/-/vite-plugin-dts-4.5.4.tgz#51b60aaaa760d9cf5c2bb3676c69d81910d6b08c" + integrity sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg== + dependencies: + "@microsoft/api-extractor" "^7.50.1" + "@rollup/pluginutils" "^5.1.4" + "@volar/typescript" "^2.4.11" + "@vue/language-core" "2.2.0" + compare-versions "^6.1.1" + debug "^4.4.0" + kolorist "^1.8.0" + local-pkg "^1.0.0" + magic-string "^0.30.17" + +vite@^6.1.0: + version "6.3.5" + resolved "https://registry.npmmirror.com/vite/-/vite-6.3.5.tgz#fec73879013c9c0128c8d284504c6d19410d12a3" + integrity sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ== + dependencies: + esbuild "^0.25.0" + fdir "^6.4.4" + picomatch "^4.0.2" + postcss "^8.5.3" + rollup "^4.34.9" + tinyglobby "^0.2.13" + optionalDependencies: + fsevents "~2.3.3" + +vscode-uri@^3.0.8: + version "3.1.0" + resolved "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c" + integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ== + +vue-demi@*: + version "0.14.10" + resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04" + integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg== + +vue-tsc@^2.2.2: + version "2.2.12" + resolved "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.12.tgz#5f719b08ef7390a763c1a20169ca5c9d09d55688" + integrity sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw== + dependencies: + "@volar/typescript" "2.4.15" + "@vue/language-core" "2.2.12" + +vue@^3.5.13: + version "3.5.17" + resolved "https://registry.npmmirror.com/vue/-/vue-3.5.17.tgz#ea8a6a45abb2b0620e7d479319ce8434b55650cf" + integrity sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g== + 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/shared" "3.5.17" + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/cool-admin-vue/packages/vite-plugin/.eslintrc.js b/cool-admin-vue/packages/vite-plugin/.eslintrc.js new file mode 100644 index 0000000..53106c1 --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/.eslintrc.js @@ -0,0 +1,12 @@ +export default { + parser: "@typescript-eslint/parser", + extends: ["plugin:@typescript-eslint/recommended"], + parserOptions: { + project: "./tsconfig.json", + tsconfigRootDir: __dirname, + ecmaVersion: 2020, + sourceType: "module", + createDefaultProgram: true, + }, + rules: {}, +}; diff --git a/cool-admin-vue/packages/vite-plugin/.prettierrc b/cool-admin-vue/packages/vite-plugin/.prettierrc new file mode 100644 index 0000000..5305129 --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/.prettierrc @@ -0,0 +1,8 @@ +{ + "tabWidth": 4, + "useTabs": true, + "semi": true, + "jsxBracketSameLine": true, + "singleQuote": false, + "printWidth": 100 +} diff --git a/cool-admin-vue/packages/vite-plugin/client.d.ts b/cool-admin-vue/packages/vite-plugin/client.d.ts new file mode 100644 index 0000000..4982a91 --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/client.d.ts @@ -0,0 +1,48 @@ +declare module "virtual:ctx" { + const ctx: { + serviceLang: string; + modules: string[]; + }; + + export { ctx }; +} + +declare module "virtual:eps" { + const eps: { + isUpdate: boolean; + list: { + prefix: string; + api: { + method: string; + path: string; + summary: string; + dts: { + [key: string]: string; + }; + [key: string]: any; + }[]; + namespace: string; + name: string; + module: string; + columns: { + comment: string; + nullable: boolean; + propertyName: string; + type: string; + [key: string]: any; + }[]; + [key: string]: any; + }[]; + service: any; + }; + + export { eps }; +} + +declare module "virtual:demo"; +declare module "virtual:svg-register"; + +declare module "virtual:svg-icons" { + const svgIcons: string[]; + export { svgIcons }; +} diff --git a/cool-admin-vue/packages/vite-plugin/dist/base.d.ts b/cool-admin-vue/packages/vite-plugin/dist/base.d.ts new file mode 100644 index 0000000..8345a78 --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/dist/base.d.ts @@ -0,0 +1,2 @@ +import type { Plugin } from "vite"; +export declare function base(): Plugin; diff --git a/cool-admin-vue/packages/vite-plugin/dist/config.d.ts b/cool-admin-vue/packages/vite-plugin/dist/config.d.ts new file mode 100644 index 0000000..46b14b5 --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/dist/config.d.ts @@ -0,0 +1,34 @@ +import type { Type } from "../types"; +export declare const config: { + type: Type; + reqUrl: string; + demo: boolean; + nameTag: boolean; + eps: { + enable: boolean; + api: string; + dist: string; + mapping: ({ + custom: ({ propertyName, type }: { + propertyName: string; + type: string; + }) => null; + type?: undefined; + test?: undefined; + } | { + type: string; + test: string[]; + custom?: undefined; + })[]; + }; + svg: { + skipNames: string[]; + }; + tailwind: { + enable: boolean; + remUnit: number; + remPrecision: number; + rpxRatio: number; + darkTextClass: string; + }; +}; diff --git a/cool-admin-vue/packages/vite-plugin/dist/ctx/index.d.ts b/cool-admin-vue/packages/vite-plugin/dist/ctx/index.d.ts new file mode 100644 index 0000000..87eafb6 --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/dist/ctx/index.d.ts @@ -0,0 +1,2 @@ +import type { Ctx } from "../../types"; +export declare function createCtx(): Promise; diff --git a/cool-admin-vue/packages/vite-plugin/dist/demo.d.ts b/cool-admin-vue/packages/vite-plugin/dist/demo.d.ts new file mode 100644 index 0000000..5f66c93 --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/dist/demo.d.ts @@ -0,0 +1,2 @@ +import type { Plugin } from "vite"; +export declare function demo(enable?: boolean): Plugin; diff --git a/cool-admin-vue/packages/vite-plugin/dist/eps/flatten.d.ts b/cool-admin-vue/packages/vite-plugin/dist/eps/flatten.d.ts new file mode 100644 index 0000000..8aba397 --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/dist/eps/flatten.d.ts @@ -0,0 +1,7 @@ +/** + * 将模板字符串扁平化处理,转换为 Service 类型定义 + * @param template - 包含 Service 类型定义的模板字符串 + * @returns 处理后的 Service 类型定义字符串 + * @throws {Error} 当模板中找不到 Service 类型定义时抛出错误 + */ +export declare function flatten(template: string): string; diff --git a/cool-admin-vue/packages/vite-plugin/dist/eps/index.d.ts b/cool-admin-vue/packages/vite-plugin/dist/eps/index.d.ts new file mode 100644 index 0000000..a3719cf --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/dist/eps/index.d.ts @@ -0,0 +1,18 @@ +import type { Eps } from "../../types"; +/** + * 主入口:创建 eps 相关文件和 service + */ +export declare function createEps(): Promise<{ + service: {}; + serviceCode: { + content: string; + types: string[]; + }; + list: Eps.Entity[]; + isUpdate: boolean; +} | { + service: {}; + list: never[]; + serviceCode?: undefined; + isUpdate?: undefined; +}>; diff --git a/cool-admin-vue/packages/vite-plugin/dist/file/index.d.ts b/cool-admin-vue/packages/vite-plugin/dist/file/index.d.ts new file mode 100644 index 0000000..c96a4b3 --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/dist/file/index.d.ts @@ -0,0 +1,6 @@ +interface Item { + path: string; + code: string; +} +export declare function createFile(data: Item | Item[]): Promise; +export {}; diff --git a/cool-admin-vue/packages/vite-plugin/dist/index.d.ts b/cool-admin-vue/packages/vite-plugin/dist/index.d.ts new file mode 100644 index 0000000..007de2c --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/dist/index.d.ts @@ -0,0 +1,2 @@ +import type { Config } from "../types"; +export declare function cool(options: Config.Options): (import("vite").Plugin | Promise> | Promise[]>)[]; diff --git a/cool-admin-vue/packages/vite-plugin/dist/index.js b/cool-admin-vue/packages/vite-plugin/dist/index.js new file mode 100644 index 0000000..b5b68c3 --- /dev/null +++ b/cool-admin-vue/packages/vite-plugin/dist/index.js @@ -0,0 +1,2294 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('fs'), require('path'), require('prettier'), require('axios'), require('lodash'), require('@vue/compiler-sfc'), require('magic-string'), require('glob'), require('node:util'), require('svgo'), require('postcss-value-parser')) : + typeof define === 'function' && define.amd ? define(['exports', 'fs', 'path', 'prettier', 'axios', 'lodash', '@vue/compiler-sfc', 'magic-string', 'glob', 'node:util', 'svgo', 'postcss-value-parser'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.index = {}, global.fs, global.path, global.prettier, global.axios, global.lodash, global.compilerSfc, global.magicString, global.glob, global.util, global.svgo, global.valueParser)); +})(this, (function (exports, fs, path, prettier, axios, lodash, compilerSfc, magicString, glob, util, svgo, valueParser) { 'use strict'; + + const config = { + type: "admin", + reqUrl: "", + nameTag: true, + eps: { + enable: true, + api: "", + dist: "./build/cool", + mapping: [ + { + // 自定义匹配 + custom: ({ propertyName, type }) => { + // 如果没有,返回null或者不返回,则继续遍历其他匹配规则 + return null; + }, + }, + { + type: "string", + test: ["varchar", "text", "simple-json"], + }, + { + type: "string[]", + test: ["simple-array"], + }, + { + type: "Date", + test: ["datetime", "date"], + }, + { + type: "number", + test: ["tinyint", "int", "decimal"], + }, + { + type: "BigInt", + test: ["bigint"], + }, + { + type: "any", + test: ["json"], + }, + ], + }, + svg: { + skipNames: ["base"], + }, + tailwind: { + enable: true, + remUnit: 14, + remPrecision: 6, + rpxRatio: 2, + darkTextClass: "dark:text-surface-50", + }, + }; + + // 根目录 + function rootDir(path$1) { + switch (config.type) { + case "app": + case "uniapp-x": + return path.join(process.env.UNI_INPUT_DIR, path$1); + default: + return path.join(process.cwd(), path$1); + } + } + // 首字母大写 + function firstUpperCase(value) { + return value.replace(/\b(\w)(\w*)/g, function ($0, $1, $2) { + return $1.toUpperCase() + $2; + }); + } + // 横杠转驼峰 + function toCamel(str) { + return str.replace(/([^-])(?:-+([^-]))/g, function ($0, $1, $2) { + return $1 + $2.toUpperCase(); + }); + } + // 创建目录 + function createDir(path, recursive) { + try { + if (!fs.existsSync(path)) + fs.mkdirSync(path, { recursive }); + } + catch (err) { } + } + // 读取文件 + function readFile(path, json) { + try { + const content = fs.readFileSync(path, "utf8"); + return json + ? JSON.parse(content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "")) + : content; + } + catch (err) { } + return ""; + } + // 写入文件 + function writeFile(path, data) { + try { + return fs.writeFileSync(path, data); + } + catch (err) { } + return ""; + } + // 解析body + function parseJson(req) { + return new Promise((resolve) => { + let d = ""; + req.on("data", function (chunk) { + d += chunk; + }); + req.on("end", function () { + try { + resolve(JSON.parse(d)); + } + catch { + resolve({}); + } + }); + }); + } + // 格式化内容 + function formatContent(content, options) { + return prettier.format(content, { + parser: "typescript", + useTabs: true, + tabWidth: 4, + endOfLine: "lf", + semi: true, + ...options, + }); + } + function error(message) { + console.log("\x1B[31m%s\x1B[0m", message); + } + + /** + * 将模板字符串扁平化处理,转换为 Service 类型定义 + * @param template - 包含 Service 类型定义的模板字符串 + * @returns 处理后的 Service 类型定义字符串 + * @throws {Error} 当模板中找不到 Service 类型定义时抛出错误 + */ + function flatten(template) { + // 查找 Service 类型定义的起始位置 + const startIndex = template.indexOf("export type Service = {"); + // 保留 Service 类型定义前的内容 + let header = template.substring(0, startIndex); + // 获取 Service 类型定义及其内容,去除换行和制表符 + const serviceContent = template.substring(startIndex).replace(/\n|\t/g, ""); + let interfaces = ""; + let serviceFields = ""; + // 解析内容并生成接口定义 + parse(serviceContent).forEach(({ key, content, level }) => { + interfaces += `\nexport interface ${firstUpperCase(key)}Interface {${content}}\n`; + serviceFields += `${key}: ${firstUpperCase(key)}Interface;`; + }); + return `${header}${interfaces}\nexport type Service = {${serviceFields}}`; + } + /** + * 查找匹配的右花括号位置 + * @param str - 要搜索的字符串 + * @param startIndex - 开始搜索的位置 + * @returns 匹配的右花括号位置 + * @throws {Error} 当找不到匹配的右花括号时抛出错误 + */ + function findClosingBrace(str, startIndex) { + let braceCount = 1; + let currentIndex = startIndex; + while (currentIndex < str.length && braceCount > 0) { + if (str[currentIndex] === "{") + braceCount++; + if (str[currentIndex] === "}") + braceCount--; + currentIndex++; + } + if (braceCount !== 0) { + throw new Error("Unmatched braces in the template"); + } + return currentIndex - 1; + } + /** + * 解析内容中的嵌套结构 + * @param content - 要解析的内容字符串 + * @returns 解析结果数组,包含解析出的键值对 + */ + function parse(content, level = 0) { + // 匹配形如 xxx: { ... } 的结构 + const interfacePattern = /(\w+)\s*:\s*\{/g; + const result = []; + let match; + while ((match = interfacePattern.exec(content)) !== null) { + const startIndex = match.index + match[0].length; + const endIndex = findClosingBrace(content, startIndex); + if (endIndex > startIndex) { + let parsedContent = content.substring(startIndex, endIndex).trim(); + // 处理嵌套结构 + if (parsedContent.includes("{") && parsedContent.includes("}")) { + const nestedInterfaces = parse(parsedContent, level + 1); + // 替换嵌套的内容为接口引用 + if (nestedInterfaces.length > 0) { + nestedInterfaces.forEach((nestedInterface) => { + const pattern = `${nestedInterface.key}: {${nestedInterface.content}};`; + const replacement = `${nestedInterface.key}: ${firstUpperCase(nestedInterface.key)}Interface`; + parsedContent = parsedContent.replace(pattern, replacement); + }); + } + } + // 将解析结果添加到数组开头 + result.unshift({ + key: match[1], + level, + content: parsedContent, + }); + } + } + return result; + } + + /** + * 获取动态类名 + */ + const getDynamicClassNames = (value) => { + const names = new Set(); + // 匹配函数调用中的对象参数(如 parseClass({'!bg-surface-50': hoverable})) + const functionCallRegex = /\w+\s*\(\s*\{([^}]*)\}\s*\)/gs; + let funcMatch; + while ((funcMatch = functionCallRegex.exec(value)) !== null) { + const objContent = funcMatch[1]; + // 提取对象中的键 + const keyRegex = /['"](.*?)['"]\s*:/gs; + let keyMatch; + while ((keyMatch = keyRegex.exec(objContent)) !== null) { + keyMatch[1].trim() && names.add(keyMatch[1]); + } + } + // 匹配对象键(如 { 'text-a': 1 })- 优化版本,避免跨行错误匹配 + const objKeyRegex = /[{,]\s*['"](.*?)['"]\s*:/gs; + let objKeyMatch; + while ((objKeyMatch = objKeyRegex.exec(value)) !== null) { + const className = objKeyMatch[1].trim(); + // 确保是有效的CSS类名,避免匹配到错误内容 + if (className && !className.includes("\n") && !className.includes("\t")) { + names.add(className); + } + } + // 匹配数组中的字符串元素(如 'text-center')- 优化版本 + const arrayStringRegex = /(?:^|[,\[\s])\s*['"](.*?)['"]/gs; + let arrayMatch; + while ((arrayMatch = arrayStringRegex.exec(value)) !== null) { + const className = arrayMatch[1].trim(); + // 确保是有效的CSS类名 + if (className && !className.includes("\n") && !className.includes("\t")) { + names.add(className); + } + } + // 匹配三元表达式中的字符串(如 'dark' 和 'light') + const ternaryRegex = /(\?|:)\s*['"](.*?)['"]/gs; + let ternaryMatch; + while ((ternaryMatch = ternaryRegex.exec(value)) !== null) { + ternaryMatch[2].trim() && names.add(ternaryMatch[2]); + } + // 匹配反引号模板字符串 - 改进版本 + const templateRegex = /`([^`]*)`/gs; + let templateMatch; + while ((templateMatch = templateRegex.exec(value)) !== null) { + const templateContent = templateMatch[1]; + // 提取模板字符串中的普通文本部分(排除 ${} 表达式) + const textParts = templateContent.split(/\$\{[^}]*\}/); + textParts.forEach((part) => { + part.trim() + .split(/\s+/) + .forEach((className) => { + className.trim() && names.add(className.trim()); + }); + }); + // 提取模板字符串中 ${} 表达式内的字符串 + const expressionRegex = /\$\{([^}]*)\}/gs; + let expressionMatch; + while ((expressionMatch = expressionRegex.exec(templateContent)) !== null) { + const expression = expressionMatch[1]; + // 递归处理表达式中的动态类名 + getDynamicClassNames(expression).forEach((name) => names.add(name)); + } + } + // 处理混合字符串(模板字符串 + 普通文本),如 "`text-red-900` text-red-1000" + const mixedStringRegex = /`[^`]*`\s+([a-zA-Z0-9\-_\s]+)/g; + let mixedMatch; + while ((mixedMatch = mixedStringRegex.exec(value)) !== null) { + const additionalClasses = mixedMatch[1].trim().split(/\s+/); + additionalClasses.forEach((className) => { + className.trim() && names.add(className.trim()); + }); + } + // 处理普通字符串,多个类名用空格分割 + const stringRegex = /['"]([\w\s\-!:\/]+?)['"]/gs; + let stringMatch; + while ((stringMatch = stringRegex.exec(value)) !== null) { + const classNames = stringMatch[1].trim().split(/\s+/); + classNames.forEach((className) => { + className.trim() && names.add(className.trim()); + }); + } + return Array.from(names); + }; + /** + * 获取类名 + */ + function getClassNames(code) { + // 修改正则表达式以支持多行匹配,避免内层引号冲突 + const classRegex = /(?:class|:class|:pt|:hover-class)\s*=\s*(['"`])((?:[^'"`\\]|\\.|`[^`]*`|'[^']*'|"[^"]*")*?)\1/gis; + const classNames = new Set(); + let match; + while ((match = classRegex.exec(code)) !== null) { + const attribute = match[0].split("=")[0].trim(); + const isStaticClass = attribute === "class" || attribute === "hover-class"; + const isPtAttribute = attribute.includes("pt"); + const value = match[2].trim(); + if (isStaticClass) { + // 处理静态 class 和 hover-class + value.split(/\s+/).forEach((name) => name && classNames.add(name)); + } + else if (isPtAttribute) { + // 处理 :pt 属性中的 className + parseClasNameFromPt(value, classNames); + } + else { + // 处理动态 :class 和 :hover-class + getDynamicClassNames(value).forEach((name) => classNames.add(name)); + } + } + return Array.from(classNames); + } + /** + * 从 :pt 属性中解析 className + */ + function parseClasNameFromPt(value, classNames) { + // 递归查找所有 className 属性 + const classNameRegex = /className\s*:\s*/g; + let match; + while ((match = classNameRegex.exec(value)) !== null) { + const startPos = match.index + match[0].length; + const classNameValue = extractComplexValue(value, startPos); + if (classNameValue) { + // 如果是字符串字面量 + if (classNameValue.startsWith('"') || + classNameValue.startsWith("'") || + classNameValue.startsWith("`")) { + if (classNameValue.startsWith("`")) { + // 处理模板字符串 + getDynamicClassNames(classNameValue).forEach((name) => classNames.add(name)); + } + else { + // 处理普通字符串 + const strMatch = classNameValue.match(/['"](.*?)['"]/); + if (strMatch) { + strMatch[1].split(/\s+/).forEach((name) => name && classNames.add(name)); + } + } + } + else { + // 处理动态值(如函数调用、对象等) + getDynamicClassNames(classNameValue).forEach((name) => classNames.add(name)); + } + } + } + } + /** + * 提取复杂值(支持嵌套引号和括号) + */ + function extractComplexValue(text, startPos) { + let pos = startPos; + let depth = 0; + let inString = false; + let stringChar = ""; + let result = ""; + // 跳过开头的空白字符 + while (pos < text.length && /\s/.test(text[pos])) { + pos++; + } + while (pos < text.length) { + const char = text[pos]; + if (!inString) { + if (char === '"' || char === "'" || char === "`") { + inString = true; + stringChar = char; + result += char; + } + else if (char === "{" || char === "(" || char === "[") { + depth++; + result += char; + } + else if (char === "}" || char === ")" || char === "]") { + if (depth === 0 && char === "}") { + // 遇到顶层的 } 时结束 + break; + } + depth--; + result += char; + } + else if (char === "," && depth === 0) { + // 遇到顶层的逗号时结束 + break; + } + else if (char === "\n" && depth === 0 && result.trim() !== "") { + // 如果遇到换行且不在嵌套结构中,且已有内容,则结束 + break; + } + else { + result += char; + } + } + else { + result += char; + if (char === stringChar && text[pos - 1] !== "\\") { + inString = false; + stringChar = ""; + // 如果字符串结束且depth为0,检查是否应该结束 + if (depth === 0) { + // 看看下一个非空白字符是什么 + let nextPos = pos + 1; + while (nextPos < text.length && /\s/.test(text[nextPos])) { + nextPos++; + } + if (nextPos < text.length && (text[nextPos] === "," || text[nextPos] === "}")) { + // 如果下一个字符是逗号或右括号,则结束 + break; + } + } + } + } + pos++; + } + return result.trim() || null; + } + /** + * 获取 class 内容 + */ + function getClassContent(code) { + // 修改正则表达式以支持多行匹配,避免内层引号冲突 + const regex = /(?:class|:class|:pt|:hover-class)\s*=\s*(['"`])((?:[^'"`\\]|\\.|`[^`]*`|'[^']*'|"[^"]*")*?)\1/gis; + const texts = []; + let match; + while ((match = regex.exec(code)) !== null) { + const attribute = match[0].split("=")[0].trim(); + const isPtAttribute = attribute.includes("pt"); + const value = match[2]; + if (isPtAttribute) { + // 手动解析 className 值 + const classNameRegex = /className\s*:\s*/g; + let classNameMatchResult; + while ((classNameMatchResult = classNameRegex.exec(value)) !== null) { + const startPos = classNameMatchResult.index + classNameMatchResult[0].length; + const classNameValue = extractComplexValue(value, startPos); + if (classNameValue) { + texts.push(classNameValue); + } + } + } + else { + texts.push(value); + } + } + return texts; + } + /** + * 获取节点 + */ + function getNodes(code) { + const nodes = []; + // 找到所有顶级template标签的完整内容 + function findTemplateContents(content) { + const results = []; + let index = 0; + while (index < content.length) { + const templateStart = content.indexOf("", templateStart); + if (tagEnd === -1) + break; + // 使用栈来匹配配对的template标签 + let stack = 1; + let currentPos = tagEnd + 1; + while (currentPos < content.length && stack > 0) { + const nextTemplateStart = content.indexOf("", currentPos); + if (nextTemplateEnd === -1) + break; + // 如果开始标签更近,说明有嵌套 + if (nextTemplateStart !== -1 && nextTemplateStart < nextTemplateEnd) { + // 找到开始标签的完整结束 + const nestedTagEnd = content.indexOf(">", nextTemplateStart); + if (nestedTagEnd !== -1) { + stack++; + currentPos = nestedTagEnd + 1; + } + else { + break; + } + } + else { + // 找到结束标签 + stack--; + currentPos = nextTemplateEnd + 11; // ''.length + } + } + if (stack === 0) { + // 提取template内容(不包括template标签本身) + const templateContent = content.substring(tagEnd + 1, currentPos - 11); + results.push(templateContent); + index = currentPos; + } + else { + // 如果没有找到匹配的结束标签,跳过这个开始标签 + index = tagEnd + 1; + } + } + return results; + } + // 递归提取所有template内容中的节点 + function extractNodesFromContent(content) { + // 先提取当前内容中的所有标签 + const regex = /<([^>]+)>/g; + let match; + while ((match = regex.exec(content)) !== null) { + if (!match[1].startsWith("/") && !match[1].startsWith("template")) { + nodes.push(match[1]); + } + } + // 递归处理嵌套的template + const nestedTemplates = findTemplateContents(content); + nestedTemplates.forEach((templateContent) => { + extractNodesFromContent(templateContent); + }); + } + // 获取所有顶级template内容 + const templateContents = findTemplateContents(code); + // 处理每个template内容 + templateContents.forEach((templateContent) => { + extractNodesFromContent(templateContent); + }); + return nodes.map((e) => `<${e}>`); + } + /** + * 添加 script 标签内容 + */ + function addScriptContent(code, content) { + const scriptMatch = /]*>([\s\S]*?)<\/script>/g.exec(code); + if (!scriptMatch) { + return code; + } + const scriptContent = scriptMatch[1]; + const scriptStartIndex = scriptMatch.index + scriptMatch[0].indexOf(">") + 1; + const scriptEndIndex = scriptStartIndex + scriptContent.length; + return (code.substring(0, scriptStartIndex) + + "\n" + + content + + "\n" + + scriptContent.trim() + + code.substring(scriptEndIndex)); + } + /** + * 判断是否为 Tailwind 类名 + */ + function isTailwindClass(className) { + const prefixes = [ + // 布局 + "container", + "flex", + "grid", + "block", + "inline", + "hidden", + "visible", + // 间距 + "p-", + "px-", + "py-", + "pt-", + "pr-", + "pb-", + "pl-", + "m-", + "mx-", + "my-", + "mt-", + "mr-", + "mb-", + "ml-", + "space-", + "gap-", + // 尺寸 + "w-", + "h-", + "min-w-", + "max-w-", + "min-h-", + "max-h-", + // 颜色 + "bg-", + "text-", + "border-", + "ring-", + "shadow-", + // 边框 + "border", + "rounded", + "ring", + // 字体 + "font-", + "text-", + "leading-", + "tracking-", + "antialiased", + // 定位 + "absolute", + "relative", + "fixed", + "sticky", + "static", + "top-", + "right-", + "bottom-", + "left-", + "inset-", + "z-", + // 变换 + "transform", + "translate-", + "rotate-", + "scale-", + "skew-", + // 过渡 + "transition", + "duration-", + "ease-", + "delay-", + // 交互 + "cursor-", + "select-", + "pointer-events-", + // 溢出 + "overflow-", + "truncate", + // 滚动 + "scroll-", + // 伪类和响应式 + "hover:", + "focus:", + "active:", + "disabled:", + "group-hover:", + ]; + const statePrefixes = ["dark:", "dark:!", "light:", "sm:", "md:", "lg:", "xl:", "2xl:"]; + if (className.startsWith("!") && !className.includes("!=")) { + return true; + } + for (const prefix of prefixes) { + if (className.startsWith(prefix)) { + return true; + } + for (const statePrefix of statePrefixes) { + if (className.startsWith(statePrefix + prefix)) { + return true; + } + } + } + return false; + } + /** + * 将 interface 转换为 type + */ + function interfaceToType(code) { + // 匹配 interface 定义 + const interfaceRegex = /interface\s+(\w+)(\s*extends\s+\w+)?\s*\{([^}]*)\}/g; + // 将 interface 转换为 type + return code.replace(interfaceRegex, (match, name, extends_, content) => { + // 处理可能存在的 extends + const extendsStr = extends_ ? extends_ : ""; + // 返回转换后的 type 定义 + return `type ${name}${extendsStr} = {${content}}`; + }); + } + + // 全局 service 对象,用于存储服务结构 + const service = {}; + // eps 实体列表 + let list = []; + /** + * 获取 eps 请求地址 + * @returns {string} eps url + */ + function getEpsUrl() { + let url = config.eps.api; + if (!url) { + url = config.type; + } + switch (url) { + case "app": + case "uniapp-x": + url = "/app/base/comm/eps"; + break; + case "admin": + url = "/admin/base/open/eps"; + break; + } + return url; + } + /** + * 获取 eps 路径 + * @param filename 文件名 + * @returns {string} 完整路径 + */ + function getEpsPath(filename) { + return path.join(config.type == "admin" ? config.eps.dist : rootDir(config.eps.dist), filename || ""); + } + /** + * 获取对象方法名(排除 namespace、permission 字段) + * @param v 对象 + * @returns {string[]} 方法名数组 + */ + function getNames(v) { + return Object.keys(v).filter((e) => !["namespace", "permission"].includes(e)); + } + /** + * 获取字段类型 + */ + function getType({ propertyName, type }) { + for (const map of config.eps.mapping) { + if (map.custom) { + const resType = map.custom({ propertyName, type }); + if (resType) + return resType; + } + if (map.test) { + if (map.test.includes(type)) + return map.type; + } + } + return type; + } + /** + * 格式化方法名,去除特殊字符 + */ + function formatName(name) { + return (name || "").replace(/[:,\s,\/,-]/g, ""); + } + /** + * 检查方法名是否合法(不包含特殊字符) + */ + function checkName(name) { + return name && !["{", "}", ":"].some((e) => name.includes(e)); + } + /** + * 不支持 uniapp-x 平台显示 + */ + function noUniappX(text, defaultText = "") { + if (config.type == "uniapp-x") { + return defaultText; + } + else { + return text; + } + } + /** + * 查找字段 + * @param sources 字段 source 数组 + * @param item eps 实体 + * @returns {Eps.Column[]} 字段数组 + */ + function findColumns(sources, item) { + const columns = [item.columns, item.pageColumns].flat().filter(Boolean); + return (sources || []) + .map((e) => columns.find((c) => c.source == e)) + .filter(Boolean); + } + /** + * 使用 prettier 格式化 TypeScript 代码 + * @param text 代码文本 + * @returns {Promise} 格式化后的代码 + */ + async function formatCode(text) { + return prettier + .format(text, { + parser: "typescript", + useTabs: true, + tabWidth: 4, + endOfLine: "lf", + semi: true, + singleQuote: false, + printWidth: 100, + trailingComma: "none", + }) + .catch(() => { + error(`[cool-eps] Failed to format /build/cool/eps.d.ts. Please delete the file and try again`); + return null; + }); + } + /** + * 获取 eps 数据(本地优先,远程兜底) + */ + async function getData() { + // 读取本地 eps.json + list = readFile(getEpsPath("eps.json"), true) || []; + // 拼接请求地址 + const url = config.reqUrl + getEpsUrl(); + // 请求远程 eps 数据 + await axios + .get(url, { + timeout: 5000, + }) + .then((res) => { + const { code, data, message } = res.data; + if (code === 1000) { + if (!lodash.isEmpty(data) && data) { + list = lodash.values(data).flat(); + } + } + else { + error(`[cool-eps] ${message || "Failed to fetch data"}`); + } + }) + .catch(() => { + error(`[cool-eps] API service is not running → ${url}`); + }); + // 初始化处理,补全缺省字段 + list.forEach((e) => { + if (!e.namespace) + e.namespace = ""; + if (!e.api) + e.api = []; + if (!e.columns) + e.columns = []; + if (!e.search) { + e.search = { + fieldEq: findColumns(e.pageQueryOp?.fieldEq, e), + fieldLike: findColumns(e.pageQueryOp?.fieldLike, e), + keyWordLikeFields: findColumns(e.pageQueryOp?.keyWordLikeFields, e), + }; + } + }); + if (config.type == "uniapp-x" || config.type == "app") { + list = list.filter((e) => e.prefix.startsWith("/app")); + } + } + /** + * 创建 eps.json 文件 + * @returns {boolean} 是否有更新 + */ + function createJson() { + if (config.type == "uniapp-x") { + return false; + } + const arr = list.map((e) => { + return { + prefix: e.prefix, + name: e.name || "", + api: e.api.map((apiItem) => ({ + name: apiItem.name, + method: apiItem.method, + path: apiItem.path, + })), + search: e.search, + }; + }); + const content = JSON.stringify(arr); + const local_content = readFile(getEpsPath("eps.json")); + // 判断是否需要更新 + const isUpdate = content != local_content; + if (isUpdate) { + fs.createWriteStream(getEpsPath("eps.json"), { + flags: "w", + }).write(content); + } + return isUpdate; + } + /** + * 创建 eps 类型描述文件(d.ts/ts) + * @param param0 list: eps实体列表, service: service对象 + */ + async function createDescribe({ list, service }) { + /** + * 创建 Entity 接口定义 + */ + function createEntity() { + const ignore = []; + let t0 = ""; + for (const item of list) { + if (!checkName(item.name)) + continue; + let t = `interface ${formatName(item.name)} {`; + // 合并 columns 和 pageColumns,去重 + const columns = lodash.uniqBy(lodash.compact([...(item.columns || []), ...(item.pageColumns || [])]), "source"); + for (const col of columns || []) { + t += ` + /** + * ${col.comment} + */ + ${col.propertyName}?: ${getType({ + propertyName: col.propertyName, + type: col.type, + })}; + `; + } + t += ` + /** + * 任意键值 + */ + [key: string]: any; + } + `; + if (!ignore.includes(item.name)) { + ignore.push(item.name); + t0 += t + "\n\n"; + } + } + return t0; + } + /** + * 创建 Controller 接口定义 + */ + async function createController() { + let controller = ""; + let chain = ""; + let pageResponse = ""; + /** + * 递归处理 service 树,生成接口定义 + * @param d 当前节点 + * @param k 前缀 + */ + function deep(d, k) { + if (!k) + k = ""; + for (const i in d) { + const name = k + toCamel(firstUpperCase(formatName(i))); + // 检查方法名 + if (!checkName(name)) + continue; + if (d[i].namespace) { + // 查找配置 + const item = list.find((e) => (e.prefix || "") === `/${d[i].namespace}`); + if (item) { + // + let t = `interface ${name} {`; + // 插入方法 + if (item.api) { + // 权限列表 + const permission = []; + item.api.forEach((a) => { + // 方法名 + const n = toCamel(formatName(a.name || lodash.last(a.path.split("/")))); + // 检查方法名 + if (!checkName(n)) + return; + if (n) { + // 参数类型 + let q = []; + // 参数列表 + const { parameters = [] } = a.dts || {}; + parameters.forEach((p) => { + if (p.description) { + q.push(`\n/** ${p.description} */\n`); + } + // 检查参数名 + if (!checkName(p.name)) { + return false; + } + const a = `${p.name}${p.required ? "" : "?"}`; + const b = `${p.schema.type || "string"}`; + q.push(`${a}: ${b};`); + }); + if (lodash.isEmpty(q)) { + q = ["any"]; + } + else { + q.unshift("{"); + q.push("}"); + } + // 返回类型 + let res = ""; + // 实体名 + const en = item.name || "any"; + switch (a.path) { + case "/page": + res = `${name}PageResponse`; + pageResponse += ` + interface ${name}PageResponse { + pagination: PagePagination; + list: ${en}[]; + } + `; + break; + case "/list": + res = `${en} []`; + break; + case "/info": + res = en; + break; + default: + res = "any"; + break; + } + // 方法描述 + t += ` + /** + * ${a.summary || n} + */ + ${n}(data${q.length == 1 ? "?" : ""}: ${q.join("")}): Promise<${res}>; + `; + if (!permission.includes(n)) { + permission.push(n); + } + } + }); + // 权限标识 + t += noUniappX(` + /** + * 权限标识 + */ + permission: { ${permission.map((e) => `${e}: string;`).join("\n")} }; + `); + // 权限状态 + t += noUniappX(` + /** + * 权限状态 + */ + _permission: { ${permission.map((e) => `${e}: boolean;`).join("\n")} }; + `); + // 请求 + t += noUniappX(` + request: Request; + `); + } + t += "}\n\n"; + controller += t; + chain += `${formatName(i)}: ${name};`; + } + } + else { + chain += `${formatName(i)}: {`; + deep(d[i], name); + chain += "};"; + } + } + } + // 遍历 service 树 + deep(service); + return ` + type json = any; + + interface PagePagination { + size: number; + page: number; + total: number; + [key: string]: any; + }; + + interface PageResponse { + pagination: PagePagination; + list: T[]; + [key: string]: any; + }; + + ${pageResponse} + + ${controller} + + ${noUniappX(`interface RequestOptions { + url: string; + method?: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT'; + data?: any; + params?: any; + headers?: any; + timeout?: number; + [key: string]: any; + }`)} + + ${noUniappX("type Request = (options: RequestOptions) => Promise;")} + + ${await createDict()} + + type Service = { + ${noUniappX("request: Request;")} + + ${chain} + } + `; + } + // 组装文件内容 + let text = ` + ${createEntity()} + ${await createController()} + `; + // 文件名 + let name = "eps.d.ts"; + if (config.type == "uniapp-x") { + name = "eps.ts"; + text = text + .replaceAll("interface ", "export interface ") + .replaceAll("type ", "export type ") + .replaceAll("[key: string]: any;", ""); + text = flatten(text); + text = interfaceToType(text); + } + else { + text = ` + declare namespace Eps { + ${text} + } + `; + } + // 格式化文本内容 + const content = await formatCode(text); + const local_content = readFile(getEpsPath(name)); + // 是否需要更新 + if (content && content != local_content && list.length > 0) { + // 创建 eps 描述文件 + fs.createWriteStream(getEpsPath(name), { + flags: "w", + }).write(content); + } + } + /** + * 构建 service 对象树 + */ + function createService() { + // 路径第一层作为 id 标识 + const id = getEpsUrl().split("/")[1]; + list.forEach((e) => { + // 请求地址 + const path = e.prefix[0] == "/" ? e.prefix.substring(1, e.prefix.length) : e.prefix; + // 分隔路径,去除 id,转驼峰 + const arr = path.replace(id, "").split("/").filter(Boolean).map(toCamel); + /** + * 递归构建 service 树 + * @param d 当前节点 + * @param i 当前索引 + */ + function deep(d, i) { + const k = arr[i]; + if (k) { + // 是否最后一个 + if (arr[i + 1]) { + if (!d[k]) { + d[k] = {}; + } + deep(d[k], i + 1); + } + else { + // 不存在则创建 + if (!d[k]) { + d[k] = { + permission: {}, + }; + } + if (!d[k].namespace) { + d[k].namespace = path; + } + // 创建权限 + if (d[k].namespace) { + getNames(d[k]).forEach((i) => { + d[k].permission[i] = + `${d[k].namespace.replace(`${id}/`, "")}/${i}`.replace(/\//g, ":"); + }); + } + // 创建搜索 + d[k].search = e.search; + // 创建方法 + e.api.forEach((a) => { + // 方法名 + const n = a.path.replace("/", ""); + if (n && !/[-:]/g.test(n)) { + d[k][n] = a; + } + }); + } + } + } + deep(service, 0); + }); + } + /** + * 创建 service 代码 + * @returns {string} service 代码 + */ + function createServiceCode() { + const types = []; + let chain = ""; + /** + * 递归处理 service 树,生成接口代码 + * @param d 当前节点 + * @param k 前缀 + */ + function deep(d, k) { + if (!k) + k = ""; + for (const i in d) { + if (["swagger"].includes(i)) { + continue; + } + const name = k + toCamel(firstUpperCase(formatName(i))); + // 检查方法名 + if (!checkName(name)) + continue; + if (d[i].namespace) { + // 查找配置 + const item = list.find((e) => (e.prefix || "") === `/${d[i].namespace}`); + if (item) { + // + let t = `{`; + // 插入方法 + if (item.api) { + item.api.forEach((a) => { + // 方法名 + const n = toCamel(formatName(a.name || lodash.last(a.path.split("/")))); + // 检查方法名 + if (!checkName(n)) + return; + if (n) { + // 参数类型 + let q = []; + // 参数列表 + const { parameters = [] } = a.dts || {}; + parameters.forEach((p) => { + if (p.description) { + q.push(`\n/** ${p.description} */\n`); + } + // 检查参数名 + if (!checkName(p.name)) { + return false; + } + const a = `${p.name}${p.required ? "" : "?"}`; + const b = `${p.schema.type || "string"}`; + q.push(`${a}: ${b}, `); + }); + if (lodash.isEmpty(q)) { + q = ["any"]; + } + else { + q.unshift("{"); + q.push("}"); + } + if (item.name) { + types.push(item.name); + } + // 返回类型 + let res = ""; + // 实体名 + const en = item.name || "any"; + switch (a.path) { + case "/page": + res = `${name}PageResponse`; + types.push(res); + break; + case "/list": + res = `${en}[]`; + break; + case "/info": + res = en; + break; + default: + res = "any"; + break; + } + // 方法描述 + t += ` + /** + * ${a.summary || n} + */ + ${n}(data${q.length == 1 ? "?" : ""}: ${q.join("")})${noUniappX(`: Promise<${res}>`)} { + return request<${res}>({ + url: "/${d[i].namespace}${a.path}", + method: "${(a.method || "get").toLocaleUpperCase()}", + data, + }); + }, + `; + } + }); + } + t += `} as ${name}\n`; + types.push(name); + chain += `${formatName(i)}: ${t},\n`; + } + } + else { + chain += `${formatName(i)}: {`; + deep(d[i], name); + chain += `} as ${firstUpperCase(i)}Interface,`; + types.push(`${firstUpperCase(i)}Interface`); + } + } + } + // 遍历 service 树 + deep(service); + return { + content: `{ ${chain} }`, + types, + }; + } + /** + * 获取字典类型定义 + * @returns {Promise} 字典类型 type 定义 + */ + async function createDict() { + let p = ""; + switch (config.type) { + case "app": + case "uniapp-x": + p = "/app"; + break; + case "admin": + p = "/admin"; + break; + } + const url = config.reqUrl + p + "/dict/info/types"; + const text = await axios + .get(url) + .then((res) => { + const { code, data } = res.data; + if (code === 1000) { + let v = "string"; + if (!lodash.isEmpty(data)) { + v = data.map((e) => `"${e.key}"`).join(" | "); + } + return `type DictKey = ${v}`; + } + }) + .catch(() => { + error(`[cool-eps] Error:${url}`); + }); + return text || ""; + } + /** + * 主入口:创建 eps 相关文件和 service + */ + async function createEps() { + if (config.eps.enable) { + // 获取 eps 数据 + await getData(); + // 构建 service 对象 + createService(); + const serviceCode = createServiceCode(); + // 创建 eps 目录 + createDir(getEpsPath(), true); + // 创建 eps.json 文件 + const isUpdate = createJson(); + // 创建类型描述文件 + createDescribe({ service, list }); + return { + service, + serviceCode, + list, + isUpdate, + }; + } + else { + return { + service: {}, + list: [], + }; + } + } + + function getPlugin(name) { + let code = readFile(rootDir(`./src/plugins/${name}/config.ts`)); + // 设置插件配置 + const set = (key, value) => { + const regex = new RegExp(`(return\\s*{[^}]*?\\b${key}\\b\\s*:\\s*)([^,}]+)`); + if (regex.test(code)) { + code = code.replace(regex, `$1${JSON.stringify(value)}`); + } + else { + const insertPos = code.indexOf("return {") + 8; + code = + code.slice(0, insertPos) + + `\n ${key}: ${JSON.stringify(value)},` + + code.slice(insertPos); + } + }; + // 保存插件配置 + const save = async () => { + const content = await formatContent(code); + writeFile(rootDir(`./src/plugins/${name}/config.ts`), content); + }; + return { + set, + save, + }; + } + // 修改插件 + async function updatePlugin(options) { + const plugin = getPlugin(options.name); + if (options.enable !== undefined) { + plugin.set("enable", options.enable); + } + await plugin.save(); + } + + function getPath() { + return rootDir(`.${config.type == "admin" ? "/src" : ""}/config/proxy.ts`); + } + async function updateProxy(data) { + let code = readFile(getPath()); + const regex = /const\s+value\s*=\s*['"]([^'"]+)['"]/; + if (regex.test(code)) { + code = code.replace(regex, `const value = '${data.name}'`); + } + writeFile(getPath(), code); + } + function getProxyTarget(proxy) { + const code = readFile(getPath()); + const regex = /const\s+value\s*=\s*['"]([^'"]+)['"]/; + const match = code.match(regex); + if (match) { + const value = match[1]; + try { + const { target, rewrite } = proxy[`/${value}/`]; + return target + rewrite(`/${value}`); + } + catch (err) { + error(`[cool-proxy] Error:${value} → ` + getPath()); + return ""; + } + } + } + + // 创建文件 + async function createFile(data) { + const list = lodash.isArray(data) ? data : [data]; + for (const item of list) { + const { path: path$1, code } = item; + // 格式化内容 + const content = await formatContent(code, { + parser: "vue", + }); + // 目录路径 + const dir = (path$1 || "").split("/"); + // 文件名 + const fname = dir.pop(); + // 源码路径 + const srcPath = `./src/${dir.join("/")}`; + // 创建目录 + createDir(srcPath, true); + // 创建文件 + fs.createWriteStream(path.join(srcPath, fname), { + flags: "w", + }).write(content); + } + } + + function createTag(code, id) { + if (/\.vue$/.test(id)) { + let s; + const str = () => s || (s = new magicString(code)); + const { descriptor } = compilerSfc.parse(code); + if (!descriptor.script && descriptor.scriptSetup) { + const res = compilerSfc.compileScript(descriptor, { id }); + const { name, lang } = res.attrs; + str().appendLeft(0, `