kk-vue-hooks 1.0.3 → 1.0.7

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/dist/index.cjs.js CHANGED
@@ -1,5 +1,107 @@
1
1
  'use strict';
2
2
 
3
+ var vue = require('vue');
4
+
5
+ /*
6
+ * @Author: 你的名字
7
+ * @LastEditors: 你的名字
8
+ * @Description: Blob流导出工具,用于处理后端返回的文件流并触发下载
9
+ */
10
+ // 从响应头获取文件名
11
+ function getFileNameFromHeader(headers, defaultName) {
12
+ if (!headers)
13
+ return defaultName;
14
+ // 处理不同可能的header键名(考虑大小写)
15
+ const contentDisposition = headers['content-disposition']
16
+ || headers['Content-Disposition']
17
+ || '';
18
+ if (!contentDisposition)
19
+ return defaultName;
20
+ // 匹配文件名(处理带引号和不带引号的情况)
21
+ const match = contentDisposition.match(/filename=("([^"]+)"|([^;]+))/i);
22
+ if (match) {
23
+ // 优先取带引号的内容,没有则取普通内容
24
+ const fileName = match[2] || match[3];
25
+ if (fileName) {
26
+ return decodeURIComponent(fileName);
27
+ }
28
+ }
29
+ return defaultName;
30
+ }
31
+ // 验证Blob对象有效性
32
+ function isValidBlob(blob) {
33
+ return blob !== null && blob !== undefined && blob instanceof Blob;
34
+ }
35
+ // 处理Blob流并下载
36
+ function useBlobExport() {
37
+ // 导出状态
38
+ const isExporting = vue.ref(false);
39
+ // 核心导出方法
40
+ const exportFromBlob = (blob, headers, defaultFileName) => {
41
+ try {
42
+ // 验证Blob对象有效性
43
+ if (!isValidBlob(blob)) {
44
+ console.error('无效的Blob对象,无法导出:', blob);
45
+ return false;
46
+ }
47
+ // 验证Blob大小,避免空文件
48
+ if (blob.size <= 0) {
49
+ console.error('Blob内容为空,无法导出');
50
+ return false;
51
+ }
52
+ isExporting.value = true;
53
+ // 生成默认文件名
54
+ const baseName = defaultFileName || `导出文件_${new Date().toLocaleDateString().replace(/\//g, '-')}`;
55
+ // 从响应头获取文件名(如果有)
56
+ const fileName = getFileNameFromHeader(headers || {}, baseName);
57
+ // 创建下载链接
58
+ const url = window.URL.createObjectURL(blob);
59
+ const a = document.createElement('a');
60
+ a.href = url;
61
+ a.download = fileName;
62
+ // 触发下载
63
+ document.body.appendChild(a);
64
+ a.click();
65
+ // 清理资源 - 使用更合理的延迟时间
66
+ setTimeout(() => {
67
+ document.body.removeChild(a);
68
+ window.URL.revokeObjectURL(url);
69
+ isExporting.value = false;
70
+ }, 500); // 延长延迟确保下载完成
71
+ return true;
72
+ }
73
+ catch (error) {
74
+ console.error('文件导出失败:', error);
75
+ isExporting.value = false;
76
+ return false;
77
+ }
78
+ };
79
+ // 处理可能的JSON错误流(后端可能在错误时返回JSON格式的错误信息)
80
+ const handleErrorBlob = async (blob) => {
81
+ // 先验证Blob有效性
82
+ if (!isValidBlob(blob)) {
83
+ return '无效的错误信息格式';
84
+ }
85
+ try {
86
+ // 将Blob转换为文本
87
+ const text = await new Response(blob).text();
88
+ // 尝试解析为JSON
89
+ const jsonData = JSON.parse(text);
90
+ // 返回错误信息
91
+ return jsonData.message || '导出失败,请重试';
92
+ }
93
+ catch (error) {
94
+ // 不是JSON格式,可能是其他错误
95
+ return '导出文件格式错误';
96
+ }
97
+ };
98
+ return {
99
+ isExporting,
100
+ exportFromBlob,
101
+ handleErrorBlob,
102
+ };
103
+ }
104
+
3
105
  // src/hooks/useStorage.ts
4
106
  /**
5
107
  * 本地存储 Hook(localStorage 封装)
@@ -44,5 +146,6 @@ function useStorage(key, defaultValue) {
44
146
  };
45
147
  }
46
148
 
149
+ exports.useBlobExport = useBlobExport;
47
150
  exports.useStorage = useStorage;
48
151
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/hooks/useStorage.ts"],"sourcesContent":["// src/hooks/useStorage.ts\n/**\n * 本地存储 Hook(localStorage 封装)\n * @param key 存储键名\n * @param defaultValue 默认值\n * @returns 获取值、设置值、删除值的方法\n */\nexport function useStorage<T>(key: string, defaultValue: T) {\n // 获取存储值\n const getStorage = (): T => {\n try {\n const value = localStorage.getItem(key)\n return value ? JSON.parse(value) : defaultValue\n }\n catch (error) {\n console.error('获取本地存储失败:', error)\n return defaultValue\n }\n }\n\n // 设置存储值\n const setStorage = (value: T) => {\n try {\n localStorage.setItem(key, JSON.stringify(value))\n }\n catch (error) {\n console.error('设置本地存储失败:', error)\n }\n }\n\n // 删除存储值\n const removeStorage = () => {\n try {\n localStorage.removeItem(key)\n }\n catch (error) {\n console.error('删除本地存储失败:', error)\n }\n }\n\n return {\n value: getStorage(),\n setStorage,\n removeStorage,\n }\n}\n"],"names":[],"mappings":";;AAAA;AACA;;;;;AAKG;AACG,SAAU,UAAU,CAAI,GAAW,EAAE,YAAe,EAAA;;IAExD,MAAM,UAAU,GAAG,MAAQ;AACzB,QAAA,IAAI;YACF,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;AACvC,YAAA,OAAO,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,YAAY;QACjD;QACA,OAAO,KAAK,EAAE;AACZ,YAAA,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC;AACjC,YAAA,OAAO,YAAY;QACrB;AACF,IAAA,CAAC;;AAGD,IAAA,MAAM,UAAU,GAAG,CAAC,KAAQ,KAAI;AAC9B,QAAA,IAAI;AACF,YAAA,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAClD;QACA,OAAO,KAAK,EAAE;AACZ,YAAA,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC;QACnC;AACF,IAAA,CAAC;;IAGD,MAAM,aAAa,GAAG,MAAK;AACzB,QAAA,IAAI;AACF,YAAA,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC;QAC9B;QACA,OAAO,KAAK,EAAE;AACZ,YAAA,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC;QACnC;AACF,IAAA,CAAC;IAED,OAAO;QACL,KAAK,EAAE,UAAU,EAAE;QACnB,UAAU;QACV,aAAa;KACd;AACH;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/hooks/useBlobExport.ts","../src/hooks/useStorage.ts"],"sourcesContent":["/*\n * @Author: 你的名字\n * @LastEditors: 你的名字\n * @Description: Blob流导出工具,用于处理后端返回的文件流并触发下载\n */\nimport { ref } from 'vue'\n\n// 从响应头获取文件名\nfunction getFileNameFromHeader(headers: Record<string, string>, defaultName: string): string {\n if (!headers)\n return defaultName\n\n // 处理不同可能的header键名(考虑大小写)\n const contentDisposition = headers['content-disposition']\n || headers['Content-Disposition']\n || ''\n\n if (!contentDisposition)\n return defaultName\n\n // 匹配文件名(处理带引号和不带引号的情况)\n const match = contentDisposition.match(/filename=(\"([^\"]+)\"|([^;]+))/i)\n if (match) {\n // 优先取带引号的内容,没有则取普通内容\n const fileName = match[2] || match[3]\n if (fileName) {\n return decodeURIComponent(fileName)\n }\n }\n\n return defaultName\n}\n\n// 验证Blob对象有效性\nfunction isValidBlob(blob: unknown): blob is Blob {\n return blob !== null && blob !== undefined && blob instanceof Blob\n}\n\n// 处理Blob流并下载\nexport function useBlobExport() {\n // 导出状态\n const isExporting = ref(false)\n\n // 核心导出方法\n const exportFromBlob = (\n blob: Blob,\n headers?: Record<string, string>,\n defaultFileName?: string,\n ): boolean => {\n try {\n // 验证Blob对象有效性\n if (!isValidBlob(blob)) {\n console.error('无效的Blob对象,无法导出:', blob)\n return false\n }\n\n // 验证Blob大小,避免空文件\n if (blob.size <= 0) {\n console.error('Blob内容为空,无法导出')\n return false\n }\n\n isExporting.value = true\n\n // 生成默认文件名\n const baseName = defaultFileName || `导出文件_${new Date().toLocaleDateString().replace(/\\//g, '-')}`\n\n // 从响应头获取文件名(如果有)\n const fileName = getFileNameFromHeader(headers || {}, baseName)\n\n // 创建下载链接\n const url = window.URL.createObjectURL(blob)\n const a = document.createElement('a')\n\n a.href = url\n a.download = fileName\n\n // 触发下载\n document.body.appendChild(a)\n a.click()\n\n // 清理资源 - 使用更合理的延迟时间\n setTimeout(() => {\n document.body.removeChild(a)\n window.URL.revokeObjectURL(url)\n isExporting.value = false\n }, 500) // 延长延迟确保下载完成\n\n return true\n }\n catch (error) {\n console.error('文件导出失败:', error)\n isExporting.value = false\n return false\n }\n }\n\n // 处理可能的JSON错误流(后端可能在错误时返回JSON格式的错误信息)\n const handleErrorBlob = async (blob: Blob): Promise<string | null> => {\n // 先验证Blob有效性\n if (!isValidBlob(blob)) {\n return '无效的错误信息格式'\n }\n\n try {\n // 将Blob转换为文本\n const text = await new Response(blob).text()\n\n // 尝试解析为JSON\n const jsonData = JSON.parse(text)\n\n // 返回错误信息\n return jsonData.message || '导出失败,请重试'\n }\n catch (error) {\n // 不是JSON格式,可能是其他错误\n return '导出文件格式错误'\n }\n }\n\n return {\n isExporting,\n exportFromBlob,\n handleErrorBlob,\n }\n}\n","// src/hooks/useStorage.ts\n/**\n * 本地存储 Hook(localStorage 封装)\n * @param key 存储键名\n * @param defaultValue 默认值\n * @returns 获取值、设置值、删除值的方法\n */\nexport function useStorage<T>(key: string, defaultValue: T) {\n // 获取存储值\n const getStorage = (): T => {\n try {\n const value = localStorage.getItem(key)\n return value ? JSON.parse(value) : defaultValue\n }\n catch (error) {\n console.error('获取本地存储失败:', error)\n return defaultValue\n }\n }\n\n // 设置存储值\n const setStorage = (value: T) => {\n try {\n localStorage.setItem(key, JSON.stringify(value))\n }\n catch (error) {\n console.error('设置本地存储失败:', error)\n }\n }\n\n // 删除存储值\n const removeStorage = () => {\n try {\n localStorage.removeItem(key)\n }\n catch (error) {\n console.error('删除本地存储失败:', error)\n }\n }\n\n return {\n value: getStorage(),\n setStorage,\n removeStorage,\n }\n}\n"],"names":["ref"],"mappings":"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"}
package/dist/index.esm.js CHANGED
@@ -1,3 +1,105 @@
1
+ import { ref } from 'vue';
2
+
3
+ /*
4
+ * @Author: 你的名字
5
+ * @LastEditors: 你的名字
6
+ * @Description: Blob流导出工具,用于处理后端返回的文件流并触发下载
7
+ */
8
+ // 从响应头获取文件名
9
+ function getFileNameFromHeader(headers, defaultName) {
10
+ if (!headers)
11
+ return defaultName;
12
+ // 处理不同可能的header键名(考虑大小写)
13
+ const contentDisposition = headers['content-disposition']
14
+ || headers['Content-Disposition']
15
+ || '';
16
+ if (!contentDisposition)
17
+ return defaultName;
18
+ // 匹配文件名(处理带引号和不带引号的情况)
19
+ const match = contentDisposition.match(/filename=("([^"]+)"|([^;]+))/i);
20
+ if (match) {
21
+ // 优先取带引号的内容,没有则取普通内容
22
+ const fileName = match[2] || match[3];
23
+ if (fileName) {
24
+ return decodeURIComponent(fileName);
25
+ }
26
+ }
27
+ return defaultName;
28
+ }
29
+ // 验证Blob对象有效性
30
+ function isValidBlob(blob) {
31
+ return blob !== null && blob !== undefined && blob instanceof Blob;
32
+ }
33
+ // 处理Blob流并下载
34
+ function useBlobExport() {
35
+ // 导出状态
36
+ const isExporting = ref(false);
37
+ // 核心导出方法
38
+ const exportFromBlob = (blob, headers, defaultFileName) => {
39
+ try {
40
+ // 验证Blob对象有效性
41
+ if (!isValidBlob(blob)) {
42
+ console.error('无效的Blob对象,无法导出:', blob);
43
+ return false;
44
+ }
45
+ // 验证Blob大小,避免空文件
46
+ if (blob.size <= 0) {
47
+ console.error('Blob内容为空,无法导出');
48
+ return false;
49
+ }
50
+ isExporting.value = true;
51
+ // 生成默认文件名
52
+ const baseName = defaultFileName || `导出文件_${new Date().toLocaleDateString().replace(/\//g, '-')}`;
53
+ // 从响应头获取文件名(如果有)
54
+ const fileName = getFileNameFromHeader(headers || {}, baseName);
55
+ // 创建下载链接
56
+ const url = window.URL.createObjectURL(blob);
57
+ const a = document.createElement('a');
58
+ a.href = url;
59
+ a.download = fileName;
60
+ // 触发下载
61
+ document.body.appendChild(a);
62
+ a.click();
63
+ // 清理资源 - 使用更合理的延迟时间
64
+ setTimeout(() => {
65
+ document.body.removeChild(a);
66
+ window.URL.revokeObjectURL(url);
67
+ isExporting.value = false;
68
+ }, 500); // 延长延迟确保下载完成
69
+ return true;
70
+ }
71
+ catch (error) {
72
+ console.error('文件导出失败:', error);
73
+ isExporting.value = false;
74
+ return false;
75
+ }
76
+ };
77
+ // 处理可能的JSON错误流(后端可能在错误时返回JSON格式的错误信息)
78
+ const handleErrorBlob = async (blob) => {
79
+ // 先验证Blob有效性
80
+ if (!isValidBlob(blob)) {
81
+ return '无效的错误信息格式';
82
+ }
83
+ try {
84
+ // 将Blob转换为文本
85
+ const text = await new Response(blob).text();
86
+ // 尝试解析为JSON
87
+ const jsonData = JSON.parse(text);
88
+ // 返回错误信息
89
+ return jsonData.message || '导出失败,请重试';
90
+ }
91
+ catch (error) {
92
+ // 不是JSON格式,可能是其他错误
93
+ return '导出文件格式错误';
94
+ }
95
+ };
96
+ return {
97
+ isExporting,
98
+ exportFromBlob,
99
+ handleErrorBlob,
100
+ };
101
+ }
102
+
1
103
  // src/hooks/useStorage.ts
2
104
  /**
3
105
  * 本地存储 Hook(localStorage 封装)
@@ -42,5 +144,5 @@ function useStorage(key, defaultValue) {
42
144
  };
43
145
  }
44
146
 
45
- export { useStorage };
147
+ export { useBlobExport, useStorage };
46
148
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/hooks/useStorage.ts"],"sourcesContent":["// src/hooks/useStorage.ts\n/**\n * 本地存储 Hook(localStorage 封装)\n * @param key 存储键名\n * @param defaultValue 默认值\n * @returns 获取值、设置值、删除值的方法\n */\nexport function useStorage<T>(key: string, defaultValue: T) {\n // 获取存储值\n const getStorage = (): T => {\n try {\n const value = localStorage.getItem(key)\n return value ? JSON.parse(value) : defaultValue\n }\n catch (error) {\n console.error('获取本地存储失败:', error)\n return defaultValue\n }\n }\n\n // 设置存储值\n const setStorage = (value: T) => {\n try {\n localStorage.setItem(key, JSON.stringify(value))\n }\n catch (error) {\n console.error('设置本地存储失败:', error)\n }\n }\n\n // 删除存储值\n const removeStorage = () => {\n try {\n localStorage.removeItem(key)\n }\n catch (error) {\n console.error('删除本地存储失败:', error)\n }\n }\n\n return {\n value: getStorage(),\n setStorage,\n removeStorage,\n }\n}\n"],"names":[],"mappings":"AAAA;AACA;;;;;AAKG;AACG,SAAU,UAAU,CAAI,GAAW,EAAE,YAAe,EAAA;;IAExD,MAAM,UAAU,GAAG,MAAQ;AACzB,QAAA,IAAI;YACF,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;AACvC,YAAA,OAAO,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,YAAY;QACjD;QACA,OAAO,KAAK,EAAE;AACZ,YAAA,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC;AACjC,YAAA,OAAO,YAAY;QACrB;AACF,IAAA,CAAC;;AAGD,IAAA,MAAM,UAAU,GAAG,CAAC,KAAQ,KAAI;AAC9B,QAAA,IAAI;AACF,YAAA,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAClD;QACA,OAAO,KAAK,EAAE;AACZ,YAAA,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC;QACnC;AACF,IAAA,CAAC;;IAGD,MAAM,aAAa,GAAG,MAAK;AACzB,QAAA,IAAI;AACF,YAAA,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC;QAC9B;QACA,OAAO,KAAK,EAAE;AACZ,YAAA,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC;QACnC;AACF,IAAA,CAAC;IAED,OAAO;QACL,KAAK,EAAE,UAAU,EAAE;QACnB,UAAU;QACV,aAAa;KACd;AACH;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/hooks/useBlobExport.ts","../src/hooks/useStorage.ts"],"sourcesContent":["/*\n * @Author: 你的名字\n * @LastEditors: 你的名字\n * @Description: Blob流导出工具,用于处理后端返回的文件流并触发下载\n */\nimport { ref } from 'vue'\n\n// 从响应头获取文件名\nfunction getFileNameFromHeader(headers: Record<string, string>, defaultName: string): string {\n if (!headers)\n return defaultName\n\n // 处理不同可能的header键名(考虑大小写)\n const contentDisposition = headers['content-disposition']\n || headers['Content-Disposition']\n || ''\n\n if (!contentDisposition)\n return defaultName\n\n // 匹配文件名(处理带引号和不带引号的情况)\n const match = contentDisposition.match(/filename=(\"([^\"]+)\"|([^;]+))/i)\n if (match) {\n // 优先取带引号的内容,没有则取普通内容\n const fileName = match[2] || match[3]\n if (fileName) {\n return decodeURIComponent(fileName)\n }\n }\n\n return defaultName\n}\n\n// 验证Blob对象有效性\nfunction isValidBlob(blob: unknown): blob is Blob {\n return blob !== null && blob !== undefined && blob instanceof Blob\n}\n\n// 处理Blob流并下载\nexport function useBlobExport() {\n // 导出状态\n const isExporting = ref(false)\n\n // 核心导出方法\n const exportFromBlob = (\n blob: Blob,\n headers?: Record<string, string>,\n defaultFileName?: string,\n ): boolean => {\n try {\n // 验证Blob对象有效性\n if (!isValidBlob(blob)) {\n console.error('无效的Blob对象,无法导出:', blob)\n return false\n }\n\n // 验证Blob大小,避免空文件\n if (blob.size <= 0) {\n console.error('Blob内容为空,无法导出')\n return false\n }\n\n isExporting.value = true\n\n // 生成默认文件名\n const baseName = defaultFileName || `导出文件_${new Date().toLocaleDateString().replace(/\\//g, '-')}`\n\n // 从响应头获取文件名(如果有)\n const fileName = getFileNameFromHeader(headers || {}, baseName)\n\n // 创建下载链接\n const url = window.URL.createObjectURL(blob)\n const a = document.createElement('a')\n\n a.href = url\n a.download = fileName\n\n // 触发下载\n document.body.appendChild(a)\n a.click()\n\n // 清理资源 - 使用更合理的延迟时间\n setTimeout(() => {\n document.body.removeChild(a)\n window.URL.revokeObjectURL(url)\n isExporting.value = false\n }, 500) // 延长延迟确保下载完成\n\n return true\n }\n catch (error) {\n console.error('文件导出失败:', error)\n isExporting.value = false\n return false\n }\n }\n\n // 处理可能的JSON错误流(后端可能在错误时返回JSON格式的错误信息)\n const handleErrorBlob = async (blob: Blob): Promise<string | null> => {\n // 先验证Blob有效性\n if (!isValidBlob(blob)) {\n return '无效的错误信息格式'\n }\n\n try {\n // 将Blob转换为文本\n const text = await new Response(blob).text()\n\n // 尝试解析为JSON\n const jsonData = JSON.parse(text)\n\n // 返回错误信息\n return jsonData.message || '导出失败,请重试'\n }\n catch (error) {\n // 不是JSON格式,可能是其他错误\n return '导出文件格式错误'\n }\n }\n\n return {\n isExporting,\n exportFromBlob,\n handleErrorBlob,\n }\n}\n","// src/hooks/useStorage.ts\n/**\n * 本地存储 Hook(localStorage 封装)\n * @param key 存储键名\n * @param defaultValue 默认值\n * @returns 获取值、设置值、删除值的方法\n */\nexport function useStorage<T>(key: string, defaultValue: T) {\n // 获取存储值\n const getStorage = (): T => {\n try {\n const value = localStorage.getItem(key)\n return value ? JSON.parse(value) : defaultValue\n }\n catch (error) {\n console.error('获取本地存储失败:', error)\n return defaultValue\n }\n }\n\n // 设置存储值\n const setStorage = (value: T) => {\n try {\n localStorage.setItem(key, JSON.stringify(value))\n }\n catch (error) {\n console.error('设置本地存储失败:', error)\n }\n }\n\n // 删除存储值\n const removeStorage = () => {\n try {\n localStorage.removeItem(key)\n }\n catch (error) {\n console.error('删除本地存储失败:', error)\n }\n }\n\n return {\n value: getStorage(),\n setStorage,\n removeStorage,\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1,2 @@
1
+ export * from './useBlobExport';
1
2
  export * from './useStorage';
@@ -0,0 +1,5 @@
1
+ export declare function useBlobExport(): {
2
+ isExporting: import("vue").Ref<boolean, boolean>;
3
+ exportFromBlob: (blob: Blob, headers?: Record<string, string>, defaultFileName?: string) => boolean;
4
+ handleErrorBlob: (blob: Blob) => Promise<string | null>;
5
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 处理时间范围选择的公共Hook
3
+ * @param {object} options - 配置项
4
+ * @param {string} [options.startKey] - 接口所需的开始时间字段名
5
+ * @param {string} [options.endKey] - 接口所需的结束时间字段名
6
+ * @returns {object} { dateRange, formattedParams, reset }
7
+ */
8
+ export declare function useDateRange(options?: {
9
+ startKey?: string;
10
+ endKey?: string;
11
+ }): {
12
+ dateRange: import("vue").Ref<never[], never[]>;
13
+ formattedParams: import("vue").Ref<{
14
+ [x: string]: null;
15
+ }, {
16
+ [x: string]: null;
17
+ }>;
18
+ reset: () => void;
19
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 通用 loading 状态管理 Hook
3
+ * @param {Array<string>} buttonKeys - 按钮唯一标识列表(如 ['submit', 'reset'])
4
+ * @returns {object} { loading, setLoading, toggleLoading }
5
+ * - loading: 响应式对象,存储各按钮的 loading 状态(如 { submit: true, reset: false })
6
+ * - setLoading: 手动设置某个按钮的 loading 状态(key, status)
7
+ * - toggleLoading: 切换某个按钮的 loading 状态(key)
8
+ */
9
+ export declare function useLoading(buttonKeys?: string[]): {
10
+ loading: {
11
+ value: Record<string, boolean>;
12
+ };
13
+ setLoading: (key: string, status: boolean) => void;
14
+ toggleLoading: (key: string) => void;
15
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 路由参数处理 Hook
3
+ * 同时支持 params(动态路由参数)和 query(查询字符串参数)
4
+ */
5
+ export declare function useRouteParams(): {
6
+ routeParams: import("vue").Ref<{
7
+ [x: string]: string | string[];
8
+ }, {
9
+ [x: string]: string | string[];
10
+ }>;
11
+ routeQuery: import("vue").Ref<{
12
+ [x: string]: import("vue-router").LocationQueryValue | import("vue-router").LocationQueryValue[];
13
+ }, {
14
+ [x: string]: import("vue-router").LocationQueryValue | import("vue-router").LocationQueryValue[];
15
+ }>;
16
+ getParam: <T = string>(key: string, defaultValue?: T) => T | string | undefined;
17
+ getQuery: <T = string>(key: string, defaultValue?: T) => T | string | undefined;
18
+ hasParam: (key: string) => boolean;
19
+ hasQuery: (key: string) => boolean;
20
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kk-vue-hooks",
3
- "version": "1.0.3",
3
+ "version": "1.0.7",
4
4
  "type": "module",
5
5
  "description": "自定义 Vue/React Hooks 集合",
6
6
  "main": "dist/index.cjs.js",
@@ -11,6 +11,9 @@
11
11
  "README.md",
12
12
  "LICENSE"
13
13
  ],
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
14
17
  "keywords": [
15
18
  "vue-hooks",
16
19
  "react-hooks",
@@ -24,10 +27,10 @@
24
27
  "lint:fix": "eslint src --ext .ts --fix",
25
28
  "lint:style": "stylelint \"src/**/*.{css,scss}\"",
26
29
  "pack:check": "npm pack",
27
- "publish:pkg": "npm run lint && npm run build && npm run pack:check && npm publish",
28
- "publish:patch": "npm version patch && npm run publish:pkg",
29
- "publish:minor": "npm version minor && npm run publish:pkg",
30
- "publish:major": "npm version major && npm run publish:pkg",
30
+ "publish:pkg": "npm run lint:fix && npm run build && npm run pack:check && npm publish",
31
+ "publish:patch": "npm version patch",
32
+ "publish:minor": "npm version minor",
33
+ "publish:major": "npm version major",
31
34
  "test": "echo \"Error: no test specified\" && exit 1"
32
35
  },
33
36
  "author": "kk",
@@ -49,6 +52,7 @@
49
52
  },
50
53
  "dependencies": {
51
54
  "tslib": "^2.8.1",
52
- "vue": "^3.5.26"
55
+ "vue": "^3.5.26",
56
+ "vue-router": "^4.6.4"
53
57
  }
54
58
  }