xn-fe-tools 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -98,6 +98,63 @@ console.log(VERSION)
98
98
  console.log(getVersion())
99
99
  ```
100
100
 
101
+ ## 🤖 MCP 支持(AI 助手集成)
102
+
103
+ xn-fe-tools 内置了 [MCP(Model Context Protocol)](https://modelcontextprotocol.io/) 服务端,安装后 AI 助手可以自动获取所有 Hook 的 API 信息、使用文档、最佳实践和代码模板,帮助你正确使用最新功能。
104
+
105
+ ### 配置
106
+
107
+ 在项目中创建 MCP 配置文件:
108
+
109
+ **Kiro** — `.kiro/settings/mcp.json`:
110
+
111
+ ```json
112
+ {
113
+ "mcpServers": {
114
+ "xn-fe-tools": {
115
+ "command": "npx",
116
+ "args": ["xn-fe-tools-mcp"]
117
+ }
118
+ }
119
+ }
120
+ ```
121
+
122
+ **Cursor** — `.cursor/mcp.json`:
123
+
124
+ ```json
125
+ {
126
+ "mcpServers": {
127
+ "xn-fe-tools": {
128
+ "command": "npx",
129
+ "args": ["xn-fe-tools-mcp"]
130
+ }
131
+ }
132
+ }
133
+ ```
134
+
135
+ **Claude Code** — `.mcp.json`:
136
+
137
+ ```json
138
+ {
139
+ "mcpServers": {
140
+ "xn-fe-tools": {
141
+ "command": "npx",
142
+ "args": ["xn-fe-tools-mcp"]
143
+ }
144
+ }
145
+ }
146
+ ```
147
+
148
+ 配置完成后,AI 助手即可通过以下工具获取信息:
149
+
150
+ | 工具 | 说明 |
151
+ |------|------|
152
+ | `list_hooks` | 列出所有可用 Hook |
153
+ | `get_hook_detail` | 查询 Hook 的 API 类型定义 |
154
+ | `get_hook_doc` | 获取 Hook 使用文档 |
155
+ | `get_hook_usage_rule` | 获取 Hook 使用规则和最佳实践 |
156
+ | `get_hook_template` | 获取代码模板(支持 Element Plus / Ant Design Vue) |
157
+
101
158
  ## 📄 License
102
159
 
103
160
  MIT
@@ -1 +1 @@
1
- {"version":3,"file":"toAwaitFetch.d.ts","sourceRoot":"","sources":["../../../src/hooks/toAwaitFetch/toAwaitFetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toAwaitFetch.d.ts","sourceRoot":"","sources":["../../../src/hooks/toAwaitFetch/toAwaitFetch.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,12 @@
1
1
  import { type Ref, type MaybeRefOrGetter, type ComputedRef } from 'vue';
2
2
  export interface UseInputNumberOptions {
3
- precision?: number;
4
- autoFixed?: boolean | 'pad' | 'trim';
3
+ precision?: MaybeRefOrGetter<number>;
4
+ decimalLimitMode?: MaybeRefOrGetter<'discard' | 'ceil' | 'round'>;
5
+ autoFixed?: MaybeRefOrGetter<boolean | 'pad' | 'trim'>;
5
6
  max?: number;
6
7
  min?: number;
7
- allowNegative?: boolean;
8
- showThousands?: boolean;
8
+ allowNegative?: MaybeRefOrGetter<boolean>;
9
+ showThousands?: MaybeRefOrGetter<boolean>;
9
10
  }
10
11
  export interface UseInputNumberReturn {
11
12
  value: Ref<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/useInputNumber/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwC,KAAK,GAAG,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,KAAK,CAAC;AAE9G,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACxD,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,MAAM,CAAC;CACrD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,oBAAoB,CAAC;AACtF,wBAAgB,cAAc,CAAC,KAAK,EAAE,gBAAgB,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/useInputNumber/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwC,KAAK,GAAG,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,KAAK,CAAC;AAE9G,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACrC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAClE,SAAS,CAAC,EAAE,gBAAgB,CAAC,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACxD,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,MAAM,CAAC;CACrD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,oBAAoB,CAAC;AACtF,wBAAgB,cAAc,CAAC,KAAK,EAAE,gBAAgB,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,oBAAoB,CAAC"}
@@ -0,0 +1,58 @@
1
+ {
2
+ "version": "1.5.0",
3
+ "generatedAt": "2026-03-02T07:16:55.846Z",
4
+ "hooks": [
5
+ {
6
+ "name": "toAwaitFetch",
7
+ "description": "一个强大的 HTTP 请求工具,支持链式调用和解构两种使用方式,提供了完整的错误处理、重试机制和全局配置功能。",
8
+ "typeDefinitions": "export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';\n\nexport type RequestType = 'json' | 'form' | 'text' | 'blob' | 'arraybuffer';\n\nexport type ResponseType = 'json' | 'text' | 'blob' | 'arraybuffer' | 'formData';\n\nexport type HeadersConfig = \n\nexport type ValidateStatusFn = (status: number) => boolean;\n\nexport type ValidateResponseFn<T = any> = (response: T) => boolean;\n\nexport type TransformResponseFn<TRaw = any, TTransformed = any> = (data: TRaw) => TTransformed;\n\nexport type HttpErrorHandler<T = any> = (\n error: Error,\n status: number,\n response: T,\n suppressError: () => void,\n) => void | Promise<void>;\n\nexport type BusinessErrorHandler<T = any> = (\n error: Error,\n response: T,\n suppressError: () => void\n) => void | Promise<void>;\n\nexport type NetworkErrorHandler = (\n error: Error,\n suppressError: () => void,\n) => void | Promise<void>;\n\nexport type ShouldRetry = (attempt: number, error: FetchError) => boolean | Promise<boolean>;\n\nexport interface RetryConfig {\n /**\n * 是否开启重试\n * @default false\n */\n enabled?: boolean;\n /**\n * 最大重试次数\n * @default 3\n */\n maxRetryCount?: number;\n /**\n * 重试延迟时间(毫秒)\n * @default 1000\n */\n delay?: number;\n /**\n * 自定义重试判断函数,返回 true 表示继续重试,false 表示停止重试\n * 如果未提供,将使用默认的重试逻辑\n */\n shouldRetry?: ShouldRetry;\n}\n\nexport interface RequestConfig<TRequest = any, TResponse = any> {\n /**\n * 请求 URL(必需)\n */\n url: string;\n /**\n * HTTP 方法\n * @default 'GET'\n */\n method?: HttpMethod;\n /**\n * 请求数据\n * - GET 请求时,data 会转换为 URL 查询参数\n * - POST/PUT/PATCH 等请求时,data 作为请求体数据\n * - POST 请求的查询参数应该放在 URL 中(如 '/api/users?page=1')\n */\n data?: TRequest;\n /**\n * 验证请求状态码是否符合要求的函数,返回布尔类型\n */\n validateStatus?: ValidateStatusFn;\n /**\n * 验证请求内容是否符合业务要求,返回布尔类型\n */\n validateResponse?: ValidateResponseFn<TResponse>;\n /**\n * 响应数据转换函数\n * 用于将原始响应数据转换为业务中使用的数据格式\n * 在 validateResponse 验证通过后执行\n * @example\n * transformResponse: (data) => data.result.list\n */\n transformResponse?: TransformResponseFn<TResponse, TResponse>;\n /**\n * 用来捕获 validateStatus 为 false 时进行错误处理的函数\n */\n onHttpError?: HttpErrorHandler<TResponse>;\n /**\n * 用来捕获 validateResponse 为 false 时进行错误处理的函数\n * 主要用来处理业务场景的错误\n */\n onBusinessError?: BusinessErrorHandler<TResponse>;\n /**\n * 用来捕获网络异常的错误处理函数\n * 主要用来处理无网络、跨域等报错问题\n */\n onNetworkError?: NetworkErrorHandler;\n /**\n * 重试配置\n */\n retry?: RetryConfig;\n /**\n * 请求超时时间(毫秒)\n */\n timeout?: number;\n /**\n * 请求头配置\n * 可以是 HeadersInit、Record<string, string> 或返回这些类型的函数\n * 函数接收 { url, method } 作为参数,可用于动态生成请求头\n */\n headers?: HeadersConfig;\n /**\n * 取消请求的信号(可与返回的 cancel 一起使用)\n */\n signal?: AbortSignal;\n /**\n * 是否发送凭证(Cookie/授权头)\n * @default true\n */\n withCredentials?: boolean;\n /**\n * 请求数据类型\n * @default 'json'\n */\n requestType?: RequestType;\n /**\n * 响应数据类型\n * @default 'json'\n */\n responseType?: ResponseType;\n}\n\nexport interface GlobalConfig<TResponse = any> {\n /**\n * 基础 URL,会与请求的 url 拼接\n */\n baseURL?: string;\n /**\n * 验证请求状态码是否符合要求的函数,返回布尔类型\n */\n validateStatus?: ValidateStatusFn;\n /**\n * 验证请求内容是否符合业务要求,返回布尔类型\n */\n validateResponse?: ValidateResponseFn<TResponse>;\n /**\n * 响应数据转换函数\n * 用于将原始响应数据转换为业务中使用的数据格式\n * 在 validateResponse 验证通过后执行\n * @example\n * // 全局配置:提取通用的 data 字段\n * transformResponse: (response) => response.data\n */\n transformResponse?: TransformResponseFn<TResponse, TResponse>;\n /**\n * 用来捕获 validateStatus 为 false 时进行错误处理的函数\n */\n onHttpError?: HttpErrorHandler<TResponse>;\n /**\n * 用来捕获 validateResponse 为 false 时进行错误处理的函数\n * 主要用来处理业务场景的错误\n */\n onBusinessError?: BusinessErrorHandler<TResponse>;\n /**\n * 用来捕获网络异常的错误处理函数\n * 主要用来处理无网络、跨域等报错问题\n */\n onNetworkError?: NetworkErrorHandler;\n /**\n * 重试配置\n */\n retry?: RetryConfig;\n /**\n * 请求超时时间(毫秒)\n */\n timeout?: number;\n /**\n * 请求头配置\n * 可以是 HeadersInit、Record<string, string> 或返回这些类型的函数\n * 函数接收 { url, method } 作为参数,可用于动态生成请求头\n */\n headers?: HeadersConfig;\n /**\n * 是否发送凭证(Cookie/授权头)\n * @default true\n */\n withCredentials?: boolean;\n /**\n * 请求数据类型\n * @default 'json'\n */\n requestType?: RequestType;\n /**\n * 响应数据类型\n * @default 'json'\n */\n responseType?: ResponseType;\n}\n\nexport interface FetchResponse<T = any> {\n /**\n * 响应数据\n */\n data: T;\n /**\n * HTTP 状态码\n */\n status: number;\n /**\n * 状态文本\n */\n statusText: string;\n /**\n * 响应头\n */\n headers: Headers;\n /**\n * 原始 Response 对象\n */\n response: Response;\n}\n\nexport interface FetchError<T = any> {\n /**\n * 错误信息\n */\n message: string;\n /**\n * 错误类型\n */\n type: 'http' | 'business' | 'network' | 'timeout';\n /**\n * HTTP 状态码(如果是 HTTP 错误)\n */\n status?: number;\n /**\n * 响应数据(如果有)\n */\n response?: T;\n /**\n * 原始错误对象\n */\n error?: Error | TypeError | DOMException;\n}\n\nexport type FetchResult<T = any> = [T | undefined, FetchError | undefined, boolean, FetchResponse<T> | undefined];\n\nexport interface FetchResultPromise<T = any> extends Promise<FetchResult<T>> {\n /**\n * 成功回调(重载 Promise 的 then 方法)\n * @param callback 成功时的回调函数,接收数据和可选的完整响应对象\n * @returns 返回自身,支持链式调用\n */\n then(callback: (data: T, response: FetchResponse<T>) => void): this;\n /**\n * 取消当前请求(触发 AbortController)\n */\n cancel(): void;\n \n /**\n * Promise 的 then 方法(保持兼容性)\n */\n then<TResult1 = FetchResult<T>, TResult2 = never>(\n onfulfilled?: ((value: FetchResult<T>) => TResult1 | PromiseLike<TResult1>) | null | undefined,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined\n ): Promise<TResult1 | TResult2>;\n \n /**\n * HTTP 验证错误回调\n * @param callback HTTP 验证错误时的回调函数(validateStatus 返回 false)\n * @returns 返回自身,支持链式调用\n */\n catchHttp(callback: (error: FetchError) => void): this;\n \n /**\n * 业务验证错误回调\n * @param callback 业务验证错误时的回调函数(validateResponse 返回 false)\n * @returns 返回自身,支持链式调用\n */\n catchBusiness(callback: (error: FetchError) => void): this;\n \n /**\n * 网络错误回调(网络错误、超时等)\n * @param callback 网络错误时的回调函数\n * @returns 返回自身,支持链式调用\n */\n catchNetwork(callback: (error: FetchError) => void): this;\n \n /**\n * Promise 的 catch 方法(保持兼容性)\n */\n catch<TResult = never>(\n onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined\n ): Promise<FetchResult<T> | TResult>;\n}\n\nexport interface FetchInstance {\n /**\n * 发送请求\n * @param config 请求配置\n * @returns FetchResultPromise<TResponse> 支持链式调用和解构\n */\n request<TRequest = any, TResponse = any>(\n config: RequestConfig<TRequest, TResponse>\n ): FetchResultPromise<TResponse>;\n\n /**\n * 设置全局配置\n * @param config 全局配置\n */\n setGlobalConfig(config: GlobalConfig): void;\n /**\n * 获取当前全局配置\n */\n getGlobalConfig(): GlobalConfig;\n /**\n * 合并全局配置\n * @param config 部分全局配置\n */\n mergeGlobalConfig(config: Partial<GlobalConfig>): void;\n\n /**\n * GET 请求(支持链式调用)\n * @param url 请求 URL\n * @param params 请求参数(会转换为 URL 查询参数)\n * @param config 请求配置(不包含 url、method 和 data)\n * @returns FetchResultPromise<TResponse> 支持链式调用和解构\n */\n sendGet<TResponse = any, TRequest = any>(\n url: string,\n params?: TRequest,\n config?: Omit<RequestConfig<TRequest, TResponse>, 'url' | 'method' | 'data'>\n ): FetchResultPromise<TResponse>;\n\n /**\n * POST 请求(支持链式调用)\n * 默认使用 JSON 格式发送数据\n * @param url 请求 URL\n * @param data 请求数据\n * @param config 请求配置(不包含 url、method 和 data)\n * @returns FetchResultPromise<TResponse> 支持链式调用和解构\n */\n sendPost<TResponse = any, TRequest = any>(\n url: string,\n data?: TRequest,\n config?: Omit<RequestConfig<TRequest, TResponse>, 'url' | 'method' | 'data'>\n ): FetchResultPromise<TResponse>;\n\n /**\n * POST 请求,使用 FormData 格式发送数据(支持文件上传)\n * @param url 请求 URL\n * @param data 请求数据(对象会自动转换为 FormData)\n * @param config 请求配置(不包含 url、method 和 data)\n * @returns FetchResultPromise<TResponse> 支持链式调用和解构\n */\n sendPostForm<TResponse = any, TRequest = any>(\n url: string,\n data?: TRequest,\n config?: Omit<RequestConfig<TRequest, TResponse>, 'url' | 'method' | 'data'>\n ): FetchResultPromise<TResponse>;\n\n /**\n * POST 请求,发送 Blob 数据\n * @param url 请求 URL\n * @param data 请求体(JSON/可序列化对象)\n * @param config 请求配置(不包含 url、method 和 data)\n * @returns FetchResultPromise<Blob> 支持链式调用和解构\n */\n sendPostBlob<TRequest = any>(\n url: string,\n data?: TRequest,\n config?: Omit<RequestConfig<TRequest, Blob>, 'url' | 'method' | 'data'>\n ): FetchResultPromise<Blob>;\n\n /**\n * GET 请求,响应返回 Blob 数据(用于下载文件)\n * @param url 请求 URL\n * @param params 请求参数(会转换为 URL 查询参数)\n * @param config 请求配置(不包含 url、method 和 data)\n * @returns FetchResultPromise<Blob> 支持链式调用和解构\n */\n sendGetBlob<TRequest = any>(\n url: string,\n params?: TRequest,\n config?: Omit<RequestConfig<TRequest, Blob>, 'url' | 'method' | 'data'>\n ): FetchResultPromise<Blob>;\n}\n\nexport type CreateFetch = (globalConfig?: GlobalConfig) => FetchInstance;\n\nexport type ToAwaitFetch = CreateFetch &",
9
+ "templates": {
10
+ "default": "import { sendGet, sendPost } from 'xn-fe-tools'\n\ninterface User {\n id: number\n name: string\n}\n\ninterface CreateUserRequest {\n name: string\n}\n\n// GET 请求(响应类型明确,请求参数省略)\nconst [data, error, success] = await sendGet<User[]>('/api/users')\n\n// POST 请求\nconst [created] = await sendPost<User, CreateUserRequest>('/api/users', { name: 'John' })"
11
+ },
12
+ "docPath": "docs/hooks/toAwaitFetch.md",
13
+ "rulePath": "docs/rules/toAwaitFetch.mdc",
14
+ "hasDoc": true,
15
+ "hasRule": true
16
+ },
17
+ {
18
+ "name": "useInputNumber",
19
+ "description": "一个用于管理数字输入、精度控制和格式化展示的 Vue Hook。",
20
+ "typeDefinitions": "export interface UseInputNumberOptions {\n precision?: MaybeRefOrGetter<number>; // 小数点位数\n decimalLimitMode?: MaybeRefOrGetter<'discard' | 'ceil' | 'round'>; // 处理小数位超限的方式\n autoFixed?: MaybeRefOrGetter<boolean | 'pad' | 'trim'>; // 是否自动补全/修正小数点后的位数\n max?: number; // 最大值\n min?: number; // 最小值\n allowNegative?: MaybeRefOrGetter<boolean>; // 是否允许负数\n showThousands?: MaybeRefOrGetter<boolean>; // 是否显示千分位\n}\n\nexport interface UseInputNumberReturn {\n value: Ref<string>;\n displayValue: ComputedRef<string>;\n handleInput: (val: string | number | undefined) => void;\n handleBlur: () => void;\n formatter: (val: string) => string;\n parser: (val: string) => string;\n clean: (val: string | number | undefined) => string;\n}\n\nexport function useInputNumber(options?: UseInputNumberOptions): UseInputNumberReturn;\n\nexport function useInputNumber(value: MaybeRefOrGetter<string | number | undefined>, options?: UseInputNumberOptions): UseInputNumberReturn;",
21
+ "templates": {
22
+ "default": "<script setup lang=\"ts\">\nimport { useInputNumber } from 'xn-fe-tools'\n\n// 基础用法:第一个参数传入初始值,第二个参数传入配置选项\nconst { value, displayValue, handleInput, handleBlur } = useInputNumber('100.50', {\n precision: 2,\n showThousands: true,\n})\n</script>\n\n<template>\n <div>\n <input\n :value=\"displayValue\"\n @input=\"e => handleInput((e.target as HTMLInputElement).value)\"\n @blur=\"handleBlur\"\n />\n <p>原始数值: {{ value }}</p>\n </div>\n</template>",
23
+ "element-plus": "<script setup lang=\"ts\">\nimport { watch } from 'vue'\nimport { useInputNumber } from 'xn-fe-tools'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number\n displayValue?: string | number\n precision?: number\n autoFixed?: boolean\n max?: number\n min?: number\n allowNegative?: boolean\n showThousands?: boolean\n }>(),\n {\n modelValue: '',\n precision: 0,\n autoFixed: true,\n showThousands: false,\n allowNegative: false,\n }\n)\n\nconst emits = defineEmits(['update:modelValue', 'update:displayValue', 'change', 'blur', 'input'])\n\n// 使用 Hook:第一个参数传 Getter,第二个参数传 props\nconst {\n value,\n displayValue,\n handleBlur: _handleBlur,\n parser,\n formatter,\n handleInput,\n} = useInputNumber(() => props.modelValue, props)\n\nwatch(value, val => {\n emits('update:modelValue', val)\n emits('change', val)\n})\n\nwatch(displayValue, val => {\n emits('update:displayValue', val)\n})\n\nconst handleBlur = () => {\n _handleBlur()\n emits('blur')\n}\n\n// 注意:在使用 v-model=\"value\" 时,el-input 会自动处理输入\n</script>\n\n<template>\n <el-input\n v-bind=\"$attrs\"\n v-model=\"value\"\n @blur=\"handleBlur\"\n @input=\"handleInput\"\n :formatter=\"formatter\"\n :parser=\"parser\"\n >\n <!-- 透传插槽 -->\n <template v-for=\"(_, name) in $slots\" #[name]=\"scope\">\n <slot :name=\"name\" v-bind=\"scope || {}\" />\n </template>\n </el-input>\n</template>",
24
+ "ant-design-vue": "<script setup lang=\"ts\">\nimport { watch } from 'vue'\nimport { Input } from 'ant-design-vue'\nimport { useInputNumber } from 'xn-fe-tools'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number\n displayValue?: string | number\n precision?: number\n autoFixed?: boolean\n max?: number\n min?: number\n allowNegative?: boolean\n showThousands?: boolean\n }>(),\n {\n modelValue: '',\n displayValue: '',\n precision: 0,\n autoFixed: true,\n showThousands: false,\n allowNegative: false,\n }\n)\n\nconst emits = defineEmits(['update:modelValue', 'update:displayValue', 'change', 'blur'])\n\nconst {\n value,\n displayValue,\n handleBlur: _handleBlur,\n handleInput: _handleInput,\n clean: _clean,\n} = useInputNumber(() => props.modelValue, props)\n\n// 同步状态输出\nwatch(value, val => {\n emits('update:modelValue', val)\n})\n\nwatch(displayValue, val => {\n emits('update:displayValue', val)\n})\n\nconst handleBlur = () => {\n _handleBlur()\n emits('blur')\n}\n\nconst handleChange = (e: any) => {\n const inputEl = e.target\n const oldRawValue = inputEl.value\n const oldCursorPos = inputEl.selectionStart || 0\n\n // 使用 hook 内部的 clean 逻辑来计算光标前真正会保留的字符数量\n // 这样就能自动处理“中间输入负号被过滤”等情况,保持计数的一致性\n const validBeforeCursor = _clean(oldRawValue.slice(0, oldCursorPos)).length\n\n // 执行 hook 清洗逻辑\n _handleInput(oldRawValue)\n\n const newVal = displayValue.value\n\n // 强制同步 DOM\n if (inputEl.value !== newVal) {\n inputEl.value = newVal\n\n // 恢复光标位置:找到第 validBeforeCursor 个有效字符在 newVal 中的位置\n let newPos = 0\n let validCount = 0\n while (validCount < validBeforeCursor && newPos < newVal.length) {\n // 这里的判断逻辑要与 clean 保持一致:只有数字、小数点、负号被视为有效字符\n if (/[\\d.-]/.test(newVal[newPos])) {\n validCount++\n }\n newPos++\n }\n\n inputEl.setSelectionRange(newPos, newPos)\n }\n\n emits('change', e)\n}\n</script>\n\n<template>\n <Input v-bind=\"$attrs\" :value=\"displayValue\" @change=\"handleChange\" @blur=\"handleBlur\">\n <!-- 透传 Ant Design Vue 的插槽 (prefix, suffix, addonBefore, addonAfter 等) -->\n <template v-for=\"(_, name) in $slots\" #[name]=\"scope\">\n <slot :name=\"name\" v-bind=\"scope || {}\" />\n </template>\n </Input>\n</template>"
25
+ },
26
+ "docPath": "docs/hooks/useInputNumber.md",
27
+ "rulePath": "docs/rules/useInputNumber.mdc",
28
+ "hasDoc": true,
29
+ "hasRule": true
30
+ },
31
+ {
32
+ "name": "useRequestCache",
33
+ "description": "用于处理请求缓存的 Hook,支持内存缓存、持久化缓存(LocalStorage/SessionStorage)、请求去重(并发共享)和结果转换。",
34
+ "typeDefinitions": "export type CacheStrategy = 'memory' | 'localStorage' | 'sessionStorage' | 'indexedDB'\n\nexport type CacheKeyGenerator<P> = string | ((params: P) => string)\n\nexport interface UseRequestCacheOptions<T = any, P = any, R = any> {\n /** 请求函数 */\n requestFn: (params: P) => Promise<R>\n \n /** 缓存唯一标记,用于区分不同请求。可以是字符串或生成函数 */\n cacheKey: CacheKeyGenerator<P>\n \n /** 缓存时间(毫秒),默认 5 分钟 (300000ms) */\n cacheTime?: number\n \n /** Storage 策略,默认为 'memory' */\n storage?: MaybeRefOrGetter<CacheStrategy>\n \n /** 请求参数(响应式或普通对象),用于生成动态 key */\n params?: MaybeRefOrGetter<P>\n \n /** 结果转换函数,在返回数据前进行转换 */\n transformResult?: (data: R) => T\n \n /** 是否立即执行,默认 true */\n immediate?: boolean\n\n /** 手动指定的 storage key 前缀,默认 'req_cache_' */\n storageKeyPrefix?: string\n\n /** 首次请求是否强制更新(跳过缓存),默认为 false */\n forceRefreshOnFirst?: MaybeRefOrGetter<boolean>\n\n /** IndexedDB 数据库名称,仅在 storage 为 'indexedDB' 时有效,默认 'RequestCacheDB' */\n dbName?: string\n\n /** IndexedDB 存储对象名称,仅在 storage 为 'indexedDB' 时有效,默认 'request_cache' */\n storeName?: string\n\n /** 请求成功的回调 */\n onSuccess?: (data: T) => void\n\n /** 请求失败的回调 */\n onError?: (error: any) => void\n}\n\nexport interface UseRequestCacheReturn<T> {\n data: Ref<T | undefined>\n loading: Ref<boolean>\n error: Ref<any>\n \n /** 执行请求 (优先使用缓存) */\n run: () => Promise<T | undefined>\n \n /** 刷新(忽略缓存,强制请求) */\n refresh: () => Promise<T | undefined>\n \n /** 清除指定 key 的缓存,如果不传则清除当前自动生成的 key */\n clearCache: (key?: string) => Promise<void>\n}",
35
+ "templates": {
36
+ "default": "<script setup lang=\"ts\">\nimport { useRequestCache } from 'xn-fe-tools'\nimport { ref, computed } from 'vue'\n\n// 模拟请求函数\nconst fetchUserInfo = async (params: { id: number }) => {\n return new Promise(resolve =>\n setTimeout(() => {\n resolve({ id: params.id, name: `User ${params.id}`, role: 'admin' })\n }, 500)\n )\n}\n\nconst userId = ref(1)\n\nconst { data, loading, run, refresh } = useRequestCache({\n // 请求函数\n requestFn: fetchUserInfo,\n // 参数 (响应式)\n params: computed(() => ({ id: userId.value })),\n // 缓存 Key (动态)\n cacheKey: params => `user-info-${params.id}`,\n // 缓存时间 5 分钟\n cacheTime: 5 * 60 * 1000,\n // 自动执行\n immediate: true,\n})\n</script>\n\n<template>\n <div>\n <div v-if=\"loading\">Loading...</div>\n <div v-else>\n <pre>{{ data }}</pre>\n </div>\n\n <button @click=\"userId++\">Next User (New Request)</button>\n <button @click=\"userId--\">Prev User (Cached?)</button>\n <button @click=\"refresh\">Force Refresh</button>\n </div>\n</template>"
37
+ },
38
+ "docPath": "docs/hooks/useRequestCache.md",
39
+ "rulePath": "docs/rules/useRequestCache.mdc",
40
+ "hasDoc": true,
41
+ "hasRule": true
42
+ },
43
+ {
44
+ "name": "useTableRequest",
45
+ "description": "用于表格请求的 Hook,支持分页、防抖、自动/手动请求、参数变化自动刷新等功能。",
46
+ "typeDefinitions": "export type RequestFunction<P, R> = (params: P) => Promise<R>\n\nexport interface PaginationConfig {\n /** 默认页码,默认 1 */\n defaultPage?: number\n /** 默认每页数量,默认 10 */\n defaultPageSize?: number\n /** 页码字段名,默认 'page' */\n pageKey?: string\n /** 每页数量字段名,默认 'pageSize' */\n pageSizeKey?: string\n}\n\nexport interface TransformResultData<T> {\n /** 列表数据 */\n list: T[]\n /** 总数 */\n total: number\n}\n\nexport interface UseTableRequestOptions<T = any, R = any, P = any> {\n /** 请求参数(响应式) */\n params?: MaybeRefOrGetter<P>\n /** 是否立即执行,默认 true */\n immediate?: boolean\n /** 防抖延迟(毫秒),默认 0(不防抖) */\n debounceDelay?: number\n /** 分页配置 */\n pagination?: PaginationConfig\n /** 数据列表字段名,默认空(直接使用 response),支持点号分隔的嵌套路径,如 \"data\" 或 \"data.list\" */\n dataField?: string\n /** 总数字段名,默认空(自动推断),支持点号分隔的嵌套路径,如 \"total\" 或 \"data.total\" */\n totalField?: string\n /** 当前页码字段名,默认空(不修正),支持点号分隔的嵌套路径,如 \"page\" 或 \"data.currentPage\" */\n currentPageField?: string\n /** 请求前转换参数 */\n transformParams?: (params: P, pagination: { page: number; pageSize: number }) => any\n /** 请求后转换结果,返回 { list, total } */\n transformResult?: (response: R) => TransformResultData<T>\n /** 请求成功回调 */\n onSuccess?: (data: T[], response: R) => void\n /** 请求失败回调 */\n onError?: (error: Error) => void\n /** 是否开启增量模式(滚动加载),默认 false */\n incremental?: boolean\n}\n\nexport interface PaginationState {\n /** 当前页码 */\n page: number\n /** 每页数量 */\n pageSize: number\n /** 总数 */\n total: number\n}\n\nexport interface UseTableRequestReturn<T> {\n /** 列表数据 */\n data: Ref<T[]>\n /** 加载状态 */\n loading: Ref<boolean>\n /** 错误信息 */\n error: Ref<Error | null>\n /** 分页信息 */\n pagination: PaginationState\n /** 手动触发请求 */\n run: () => Promise<void>\n /** 翻页 */\n onPageChange: (page: number) => Promise<void>\n /** 改变每页数量 */\n onSizeChange: (size: number) => Promise<void>\n /** 刷新数据(增量模式下清空数据并重置页码,普通模式下等同于 run) */\n refresh: () => Promise<void>\n}\n\nexport interface UseTableRequestGlobalConfig {\n /** 是否立即执行,默认 true */\n immediate?: boolean\n /** 防抖延迟(毫秒),默认 0(不防抖) */\n debounceDelay?: number\n /** 分页配置 */\n pagination?: PaginationConfig\n /** 数据列表字段名,默认空(直接使用 response),支持点号分隔的嵌套路径,如 \"data\" 或 \"data.list\" */\n dataField?: string\n /** 总数字段名,默认空(自动推断),支持点号分隔的嵌套路径,如 \"total\" 或 \"data.total\" */\n totalField?: string\n /** 当前页码字段名,默认空(不修正),支持点号分隔的嵌套路径,如 \"page\" 或 \"data.currentPage\" */\n currentPageField?: string\n /** 是否开启增量模式(滚动加载),默认 false */\n incremental?: boolean\n}",
47
+ "templates": {
48
+ "default": "<script setup lang=\"ts\">\nimport { ref, computed } from 'vue'\nimport { useTableRequest } from 'xn-fe-tools'\n\ninterface User {\n id: number\n name: string\n}\n\ninterface ApiResponse {\n code: number\n data: {\n records: User[]\n total: number\n }\n}\n\ninterface QueryParams {\n keyword: string\n}\n\n// 模拟请求函数\nconst fetchUserList = (params: QueryParams) => {\n // 这里的 fetch 返回 Promise<ApiResponse>\n return fetch(`/api/users?${new URLSearchParams(params as any)}`).then(\n res => res.json() as Promise<ApiResponse>\n )\n}\n\nconst search = ref('')\n\nconst { data, loading, error, pagination, run, onPageChange, onSizeChange } = useTableRequest<\n User,\n ApiResponse,\n QueryParams\n>(fetchUserList, {\n params: computed(() => ({ keyword: search.value })),\n immediate: true,\n debounceDelay: 300,\n transformResult: (res: ApiResponse) => ({\n list: res.data.records,\n total: res.data.total,\n }),\n})\n</script>\n\n<template>\n <div>\n <input v-model=\"search\" placeholder=\"搜索...\" />\n\n <div v-if=\"loading\">加载中...</div>\n <div v-else-if=\"error\">{{ error.message }}</div>\n <table v-else>\n <tr v-for=\"item in data\" :key=\"item.id\">\n <td>{{ item.name }}</td>\n </tr>\n </table>\n\n <div class=\"pagination\">\n <span>共 {{ pagination.total }} 条</span>\n <button @click=\"onPageChange(pagination.page - 1)\" :disabled=\"pagination.page <= 1\">\n 上一页\n </button>\n <span>第 {{ pagination.page }} 页</span>\n <button\n @click=\"onPageChange(pagination.page + 1)\"\n :disabled=\"pagination.page * pagination.pageSize >= pagination.total\"\n >\n 下一页\n </button>\n </div>\n </div>\n</template>",
49
+ "element-plus": "<script setup lang=\"ts\">\nimport { useTableRequest } from 'xn-fe-tools'\n\nconst { data, loading, pagination, onPageChange, onSizeChange } = useTableRequest(fetchData, {\n transformResult: res => ({ list: res.data, total: res.total }),\n})\n</script>\n\n<template>\n <el-table :data=\"data\" v-loading=\"loading\">\n <!-- columns -->\n </el-table>\n\n <el-pagination\n v-model:current-page=\"pagination.page\"\n v-model:page-size=\"pagination.pageSize\"\n :total=\"pagination.total\"\n :page-sizes=\"[10, 20, 50, 100]\"\n layout=\"total, sizes, prev, pager, next\"\n />\n</template>",
50
+ "ant-design-vue": "<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useTableRequest } from 'xn-fe-tools'\n\nconst { data, loading, pagination, run, onPageChange, onSizeChange } = useTableRequest(fetchData, {\n // ... options\n})\n\n// 适配 Ant Design Vue 的分页对象\nconst antdPagination = computed(() => ({\n current: pagination.page,\n pageSize: pagination.pageSize,\n total: pagination.total,\n showSizeChanger: true,\n onChange: onPageChange,\n onShowSizeChange: (_: number, size: number) => onSizeChange(size),\n}))\n\nconst handleTableChange = (pag: any) => {\n onPageChange(pag.current)\n if (pag.pageSize !== pagination.pageSize) {\n onSizeChange(pag.pageSize)\n }\n}\n</script>\n\n<template>\n <a-table\n :dataSource=\"data\"\n :loading=\"loading\"\n :pagination=\"antdPagination\"\n @change=\"handleTableChange\"\n >\n <!-- columns -->\n </a-table>\n</template>"
51
+ },
52
+ "docPath": "docs/hooks/useTableRequest.md",
53
+ "rulePath": "docs/rules/useTableRequest.mdc",
54
+ "hasDoc": true,
55
+ "hasRule": true
56
+ }
57
+ ]
58
+ }