zcw-shared 1.19.0 → 1.20.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.
Files changed (249) hide show
  1. package/README.md +1291 -65
  2. package/dist/functions/ag-grid/generateLicense.d.ts +5 -1
  3. package/dist/functions/ag-grid/generateLicense.js +3 -3
  4. package/dist/functions/ag-grid/generateLicense.js.map +1 -1
  5. package/dist/functions/android/buildProject.d.ts +9 -8
  6. package/dist/functions/android/buildProject.js +19 -20
  7. package/dist/functions/android/buildProject.js.map +1 -1
  8. package/dist/functions/android/detectAndroidModules.d.ts +7 -1
  9. package/dist/functions/android/detectAndroidModules.js +7 -7
  10. package/dist/functions/android/detectAndroidModules.js.map +1 -1
  11. package/dist/functions/android/modifyGradle.d.ts +10 -1
  12. package/dist/functions/android/modifyGradle.js +7 -7
  13. package/dist/functions/android/modifyGradle.js.map +1 -1
  14. package/dist/functions/android/modifyManifest.d.ts +11 -2
  15. package/dist/functions/android/modifyManifest.js +4 -4
  16. package/dist/functions/android/modifyManifest.js.map +1 -1
  17. package/dist/functions/android/permission.d.ts +15 -5
  18. package/dist/functions/android/permission.js +8 -8
  19. package/dist/functions/android/permission.js.map +1 -1
  20. package/dist/functions/async/createInterruptibleTask.d.ts +37 -0
  21. package/dist/functions/async/createInterruptibleTask.js +180 -0
  22. package/dist/functions/async/createInterruptibleTask.js.map +1 -0
  23. package/dist/functions/color/convertColor.js +1 -1
  24. package/dist/functions/color/convertColor.js.map +1 -1
  25. package/dist/functions/debug/createDebugger.d.ts +14 -3
  26. package/dist/functions/debug/createDebugger.js +10 -35
  27. package/dist/functions/debug/createDebugger.js.map +1 -1
  28. package/dist/functions/dom/demonstrateResourceLoading.d.ts +32 -0
  29. package/dist/functions/dom/demonstrateResourceLoading.js +169 -0
  30. package/dist/functions/dom/demonstrateResourceLoading.js.map +1 -0
  31. package/dist/functions/dom/detectOverflow.d.ts +5 -1
  32. package/dist/functions/dom/detectOverflow.js +2 -2
  33. package/dist/functions/dom/detectOverflow.js.map +1 -1
  34. package/dist/functions/dom/getViewportRect.d.ts +5 -1
  35. package/dist/functions/dom/getViewportRect.js +3 -3
  36. package/dist/functions/dom/getViewportRect.js.map +1 -1
  37. package/dist/functions/image/compressToTargetSize.d.ts +8 -1
  38. package/dist/functions/image/compressToTargetSize.js +11 -8
  39. package/dist/functions/image/compressToTargetSize.js.map +1 -1
  40. package/dist/functions/image/generateMacIcons.d.ts +5 -1
  41. package/dist/functions/image/generateMacIcons.js +4 -4
  42. package/dist/functions/image/generateMacIcons.js.map +1 -1
  43. package/dist/functions/image/generateMacTrayIcon.d.ts +4 -1
  44. package/dist/functions/image/generateMacTrayIcon.js +2 -2
  45. package/dist/functions/image/generateMacTrayIcon.js.map +1 -1
  46. package/dist/functions/image/generatePaddedImage.d.ts +4 -1
  47. package/dist/functions/image/generatePaddedImage.js +3 -3
  48. package/dist/functions/image/generatePaddedImage.js.map +1 -1
  49. package/dist/functions/image/generatePwaIcons.d.ts +5 -1
  50. package/dist/functions/image/generatePwaIcons.js +4 -4
  51. package/dist/functions/image/generatePwaIcons.js.map +1 -1
  52. package/dist/functions/image/generateRoundedImage.d.ts +5 -1
  53. package/dist/functions/image/generateRoundedImage.js +4 -4
  54. package/dist/functions/image/generateRoundedImage.js.map +1 -1
  55. package/dist/functions/image/getImageDimensions.d.ts +5 -1
  56. package/dist/functions/image/getImageDimensions.js +3 -3
  57. package/dist/functions/image/getImageDimensions.js.map +1 -1
  58. package/dist/functions/ipc/dispatchIpcRequest.d.ts +4 -1
  59. package/dist/functions/ipc/dispatchIpcRequest.js +3 -3
  60. package/dist/functions/ipc/dispatchIpcRequest.js.map +1 -1
  61. package/dist/functions/software/findSoftware.d.ts +2 -2
  62. package/dist/functions/software/findSoftware.js +1 -1
  63. package/dist/functions/software/findSoftware.js.map +1 -1
  64. package/dist/functions/string/base64.d.ts +4 -1
  65. package/dist/functions/string/base64.js +2 -2
  66. package/dist/functions/string/base64.js.map +1 -1
  67. package/dist/functions/tencent-cloud/deploy.tcb.d.ts +12 -2
  68. package/dist/functions/tencent-cloud/deploy.tcb.js +7 -8
  69. package/dist/functions/tencent-cloud/deploy.tcb.js.map +1 -1
  70. package/dist/functions/uniapp/app-plus/buildAndroidApp.d.ts +27 -2
  71. package/dist/functions/uniapp/app-plus/buildAndroidApp.js +71 -29
  72. package/dist/functions/uniapp/app-plus/buildAndroidApp.js.map +1 -1
  73. package/dist/functions/uniapp/build.d.ts +9 -8
  74. package/dist/functions/uniapp/build.js +8 -9
  75. package/dist/functions/uniapp/build.js.map +1 -1
  76. package/dist/functions/uniapp/detectAndroidProjectStructure.d.ts +5 -1
  77. package/dist/functions/uniapp/detectAndroidProjectStructure.js +5 -5
  78. package/dist/functions/uniapp/detectAndroidProjectStructure.js.map +1 -1
  79. package/dist/functions/uniapp/detectProjectType.d.ts +8 -4
  80. package/dist/functions/uniapp/detectProjectType.js +20 -20
  81. package/dist/functions/uniapp/detectProjectType.js.map +1 -1
  82. package/dist/functions/uniapp/parseManifest.d.ts +7 -1
  83. package/dist/functions/uniapp/parseManifest.js +7 -4
  84. package/dist/functions/uniapp/parseManifest.js.map +1 -1
  85. package/dist/functions/uniapp/waitForPages.d.ts +6 -2
  86. package/dist/functions/uniapp/waitForPages.js +3 -3
  87. package/dist/functions/uniapp/waitForPages.js.map +1 -1
  88. package/dist/functions/utils/AVLTree.d.ts +19 -0
  89. package/dist/functions/utils/AVLTree.js +197 -0
  90. package/dist/functions/utils/AVLTree.js.map +1 -0
  91. package/dist/functions/utils/BinarySearchTree.d.ts +19 -0
  92. package/dist/functions/utils/BinarySearchTree.js +150 -0
  93. package/dist/functions/utils/BinarySearchTree.js.map +1 -0
  94. package/dist/functions/utils/EventEmitter.d.ts +32 -0
  95. package/dist/functions/utils/EventEmitter.js +108 -0
  96. package/dist/functions/utils/EventEmitter.js.map +1 -0
  97. package/dist/functions/utils/Graph.d.ts +19 -0
  98. package/dist/functions/utils/Graph.js +190 -0
  99. package/dist/functions/utils/Graph.js.map +1 -0
  100. package/dist/functions/utils/HashMap.d.ts +13 -0
  101. package/dist/functions/utils/HashMap.js +128 -0
  102. package/dist/functions/utils/HashMap.js.map +1 -0
  103. package/dist/functions/utils/Heap.d.ts +11 -0
  104. package/dist/functions/utils/Heap.js +91 -0
  105. package/dist/functions/utils/Heap.js.map +1 -0
  106. package/dist/functions/utils/LRUCache.d.ts +41 -0
  107. package/dist/functions/utils/LRUCache.js +182 -0
  108. package/dist/functions/utils/LRUCache.js.map +1 -0
  109. package/dist/functions/utils/LinkedList.d.ts +18 -0
  110. package/dist/functions/utils/LinkedList.js +135 -0
  111. package/dist/functions/utils/LinkedList.js.map +1 -0
  112. package/dist/functions/utils/MyPromise.d.ts +32 -0
  113. package/dist/functions/utils/MyPromise.js +254 -0
  114. package/dist/functions/utils/MyPromise.js.map +1 -0
  115. package/dist/functions/utils/PriorityQueue.d.ts +14 -0
  116. package/dist/functions/utils/PriorityQueue.js +77 -0
  117. package/dist/functions/utils/PriorityQueue.js.map +1 -0
  118. package/dist/functions/utils/Queue.d.ts +10 -0
  119. package/dist/functions/utils/Queue.js +27 -0
  120. package/dist/functions/utils/Queue.js.map +1 -0
  121. package/dist/functions/utils/Stack.d.ts +10 -0
  122. package/dist/functions/utils/Stack.js +27 -0
  123. package/dist/functions/utils/Stack.js.map +1 -0
  124. package/dist/functions/utils/Trie.d.ts +16 -0
  125. package/dist/functions/utils/Trie.js +127 -0
  126. package/dist/functions/utils/Trie.js.map +1 -0
  127. package/dist/functions/utils/UnionFind.d.ts +8 -0
  128. package/dist/functions/utils/UnionFind.js +53 -0
  129. package/dist/functions/utils/UnionFind.js.map +1 -0
  130. package/dist/functions/utils/curryAdvanced.d.ts +8 -0
  131. package/dist/functions/utils/curryAdvanced.js +87 -0
  132. package/dist/functions/utils/curryAdvanced.js.map +1 -0
  133. package/dist/functions/utils/debounce.d.ts +5 -1
  134. package/dist/functions/utils/debounce.js +3 -4
  135. package/dist/functions/utils/debounce.js.map +1 -1
  136. package/dist/functions/utils/deepClone.d.ts +12 -0
  137. package/dist/functions/utils/deepClone.js +131 -0
  138. package/dist/functions/utils/deepClone.js.map +1 -0
  139. package/dist/functions/utils/flatten.d.ts +7 -0
  140. package/dist/functions/utils/flatten.js +60 -0
  141. package/dist/functions/utils/flatten.js.map +1 -0
  142. package/dist/functions/utils/flattenObject.d.ts +5 -0
  143. package/dist/functions/utils/flattenObject.js +102 -0
  144. package/dist/functions/utils/flattenObject.js.map +1 -0
  145. package/dist/functions/utils/functionBind.d.ts +4 -0
  146. package/dist/functions/utils/functionBind.js +33 -0
  147. package/dist/functions/utils/functionBind.js.map +1 -0
  148. package/dist/functions/utils/generateExports.d.ts +16 -6
  149. package/dist/functions/utils/generateExports.js +11 -11
  150. package/dist/functions/utils/generateExports.js.map +1 -1
  151. package/dist/functions/utils/generatorUtils.d.ts +16 -0
  152. package/dist/functions/utils/generatorUtils.js +139 -0
  153. package/dist/functions/utils/generatorUtils.js.map +1 -0
  154. package/dist/functions/utils/myInstanceof.d.ts +5 -0
  155. package/dist/functions/utils/myInstanceof.js +56 -0
  156. package/dist/functions/utils/myInstanceof.js.map +1 -0
  157. package/dist/functions/utils/myNew.d.ts +3 -0
  158. package/dist/functions/utils/myNew.js +19 -0
  159. package/dist/functions/utils/myNew.js.map +1 -0
  160. package/dist/functions/utils/promiseLimit.d.ts +10 -0
  161. package/dist/functions/utils/promiseLimit.js +125 -0
  162. package/dist/functions/utils/promiseLimit.js.map +1 -0
  163. package/dist/functions/utils/retryWithBackoff.d.ts +4 -1
  164. package/dist/functions/utils/retryWithBackoff.js +2 -3
  165. package/dist/functions/utils/retryWithBackoff.js.map +1 -1
  166. package/dist/functions/utils/unique.d.ts +10 -0
  167. package/dist/functions/utils/unique.js +85 -0
  168. package/dist/functions/utils/unique.js.map +1 -0
  169. package/dist/functions/utils/validate.d.ts +4 -1
  170. package/dist/functions/utils/validate.js +2 -3
  171. package/dist/functions/utils/validate.js.map +1 -1
  172. package/dist/functions/utils/walk.d.ts +8 -2
  173. package/dist/functions/utils/walk.js +9 -10
  174. package/dist/functions/utils/walk.js.map +1 -1
  175. package/dist/functions/vue/dynamicMount.d.ts +3 -2
  176. package/dist/functions/vue/dynamicMount.js +6 -6
  177. package/dist/functions/vue/dynamicMount.js.map +1 -1
  178. package/dist/functions/wechat/miniapp/downloadFile.d.ts +5 -1
  179. package/dist/functions/wechat/miniapp/downloadFile.js +3 -3
  180. package/dist/functions/wechat/miniapp/downloadFile.js.map +1 -1
  181. package/dist/functions/xml/modifyXml.d.ts +9 -2
  182. package/dist/functions/xml/modifyXml.js +4 -4
  183. package/dist/functions/xml/modifyXml.js.map +1 -1
  184. package/dist/hooks/createGlobalState.d.ts +2 -0
  185. package/dist/hooks/createGlobalState.js +11 -0
  186. package/dist/hooks/createGlobalState.js.map +1 -0
  187. package/dist/hooks/createInjectionState.d.ts +14 -0
  188. package/dist/hooks/createInjectionState.js +20 -0
  189. package/dist/hooks/createInjectionState.js.map +1 -0
  190. package/dist/hooks/createSharedComposable.d.ts +2 -0
  191. package/dist/hooks/createSharedComposable.js +13 -0
  192. package/dist/hooks/createSharedComposable.js.map +1 -0
  193. package/dist/hooks/injectLocal.d.ts +10 -0
  194. package/dist/hooks/injectLocal.js +12 -0
  195. package/dist/hooks/injectLocal.js.map +1 -0
  196. package/dist/hooks/provideLocal.d.ts +9 -0
  197. package/dist/hooks/provideLocal.js +7 -0
  198. package/dist/hooks/provideLocal.js.map +1 -0
  199. package/dist/hooks/useAltool.d.ts +1 -1
  200. package/dist/hooks/useAltool.js +13 -13
  201. package/dist/hooks/useAltool.js.map +1 -1
  202. package/dist/hooks/useAsyncState.d.ts +30 -0
  203. package/dist/hooks/useAsyncState.js +46 -0
  204. package/dist/hooks/useAsyncState.js.map +1 -0
  205. package/dist/hooks/useDebouncedRefHistory.d.ts +22 -0
  206. package/dist/hooks/useDebouncedRefHistory.js +46 -0
  207. package/dist/hooks/useDebouncedRefHistory.js.map +1 -0
  208. package/dist/hooks/useDraggable.d.ts +14 -11
  209. package/dist/hooks/useDraggable.js +60 -80
  210. package/dist/hooks/useDraggable.js.map +1 -1
  211. package/dist/hooks/useLocalStorage.d.ts +5 -1
  212. package/dist/hooks/useLocalStorage.js +5 -4
  213. package/dist/hooks/useLocalStorage.js.map +1 -1
  214. package/dist/hooks/useManualRefHistory.d.ts +26 -0
  215. package/dist/hooks/useManualRefHistory.js +80 -0
  216. package/dist/hooks/useManualRefHistory.js.map +1 -0
  217. package/dist/hooks/useRefHistory.d.ts +21 -0
  218. package/dist/hooks/useRefHistory.js +41 -0
  219. package/dist/hooks/useRefHistory.js.map +1 -0
  220. package/dist/hooks/useResizable.d.ts +14 -8
  221. package/dist/hooks/useResizable.js +40 -31
  222. package/dist/hooks/useResizable.js.map +1 -1
  223. package/dist/hooks/useSessionStorage.d.ts +5 -1
  224. package/dist/hooks/useSessionStorage.js +5 -4
  225. package/dist/hooks/useSessionStorage.js.map +1 -1
  226. package/dist/hooks/useStorage.d.ts +4 -1
  227. package/dist/hooks/useStorage.js +4 -4
  228. package/dist/hooks/useStorage.js.map +1 -1
  229. package/dist/hooks/useStorageWithIndexedDB.d.ts +5 -1
  230. package/dist/hooks/useStorageWithIndexedDB.js +24 -11
  231. package/dist/hooks/useStorageWithIndexedDB.js.map +1 -1
  232. package/dist/hooks/useWebWorker.d.ts +13 -13
  233. package/dist/hooks/useWebWorker.js +15 -17
  234. package/dist/hooks/useWebWorker.js.map +1 -1
  235. package/dist/hooks/useWorkerFunction.d.ts +15 -11
  236. package/dist/hooks/useWorkerFunction.js +16 -16
  237. package/dist/hooks/useWorkerFunction.js.map +1 -1
  238. package/dist/hooks/useWorkerPool.d.ts +15 -12
  239. package/dist/hooks/useWorkerPool.js +18 -13
  240. package/dist/hooks/useWorkerPool.js.map +1 -1
  241. package/package.json +40 -3
  242. package/references/browser.d.ts +28 -2
  243. package/references/dom.d.ts +45 -0
  244. package/references/indexeddb.d.ts +1 -0
  245. package/references/node.d.ts +42 -7
  246. package/references/vue.d.ts +161 -5
  247. package/types/android-build.d.ts +0 -22
  248. package/types/tencent-cloud.d.ts +1 -9
  249. package/types/uniapp-android-build.d.ts +0 -21
package/README.md CHANGED
@@ -9,6 +9,8 @@
9
9
  **环境无关性(Environment Agnostic)**
10
10
  - 所有函数都通过依赖注入接收环境相关的API
11
11
  - 不直接使用 `window`、`document`、`fs` 等全局对象
12
+ - 不传入整个模块对象(包括 Node.js API、浏览器 API 和第三方 SDK)
13
+ - 只传入实际使用的函数,使用 `Interface['method']` 精确提取类型
12
14
  - 支持 Node.js、浏览器、UniApp、微信小程序等多种运行环境
13
15
 
14
16
  **模块化架构**
@@ -16,6 +18,11 @@
16
18
  - 无统一入口文件,避免不必要的依赖
17
19
  - 清晰的类型定义和环境抽象
18
20
 
21
+ **类型安全优先**
22
+ - 完整的 TypeScript 类型定义
23
+ - 从 `references/` 提取类型,避免重复定义
24
+ - 使用 `import type` 导入类型,零运行时开销
25
+
19
26
  ### 目录结构
20
27
 
21
28
  ```
@@ -59,25 +66,218 @@ playground/ # 测试和验证环境
59
66
 
60
67
  ### 1. 依赖注入模式
61
68
 
62
- 所有环境相关的操作都通过参数传入:
69
+ 所有环境相关的操作都通过参数传入,并遵循以下规则:
70
+
71
+ #### 规则 1:不直接导入第三方库
72
+
73
+ ```typescript
74
+ // ❌ 错误:直接导入 Vue
75
+ import { ref, watch } from 'vue'
76
+
77
+ // ✅ 正确:从 references 导入类型
78
+ import type { Ref } from '../../references/vue.d'
79
+ ```
80
+
81
+ #### 规则 2:只传入实际使用的函数,不传入整个模块
63
82
 
64
83
  ```typescript
65
- // ❌ 错误:直接使用环境API
66
- export function readFile(path: string) {
67
- return fs.readFileSync(path, 'utf8') // 直接依赖Node.js
84
+ // ❌ 错误:传入整个模块
85
+ import type { FileSystem, Path } from '../../references/node.d'
86
+
87
+ export function myFunction(fs: FileSystem, path: Path) {
88
+ fs.existsSync(...)
89
+ path.join(...)
68
90
  }
69
91
 
70
- // ✅ 正确:依赖注入
71
- import type { FileSystem } from '../../references/node.d'
92
+ // ✅ 正确:只传入使用的函数
93
+ import type { FileSystem, Path } from '../../references/node.d'
94
+
95
+ export interface MyFunctionDeps {
96
+ /** 检查文件是否存在 */
97
+ existsSync: FileSystem['existsSync']
98
+ /** 路径拼接 */
99
+ join: Path['join']
100
+ }
101
+
102
+ export function myFunction(deps: MyFunctionDeps) {
103
+ deps.existsSync(...)
104
+ deps.join(...)
105
+ }
106
+ ```
107
+
108
+ #### 规则 3:使用 `deps.` 前缀,不要解构
109
+
110
+ ```typescript
111
+ // ❌ 错误:解构可能导致命名冲突
112
+ export function myFunction(deps: MyFunctionDeps) {
113
+ const { existsSync, join } = deps // 难以追踪来源
114
+ existsSync(...)
115
+ }
116
+
117
+ // ✅ 正确:使用 deps. 前缀
118
+ export function myFunction(deps: MyFunctionDeps) {
119
+ deps.existsSync(...) // 清晰明确
120
+ deps.join(...)
121
+ }
122
+ ```
123
+
124
+ #### 规则 4:类型定义在 references 中,使用 typeof 或索引访问提取
125
+
126
+ ```typescript
127
+ // ❌ 错误:在函数中定义类型
128
+ export interface MyFunctionDeps {
129
+ exec: (command: string, callback: (error: any) => void) => any
130
+ }
131
+
132
+ // ✅ 正确:从 references 提取类型
133
+ import type { ChildProcess } from '../../references/node.d'
134
+ import type { setTimeout } from '../../references/timer.d'
135
+
136
+ export interface MyFunctionDeps {
137
+ exec: ChildProcess['exec']
138
+ setTimeout: typeof setTimeout
139
+ }
140
+ ```
141
+
142
+ #### 规则 5:每个函数维护自己完整的依赖,不要分散
143
+
144
+ ```typescript
145
+ // ❌ 错误:依赖分散到多个参数
146
+ export function myFunction(
147
+ path: string,
148
+ fsDeps: FsDeps,
149
+ pathDeps: PathDeps,
150
+ systemDeps: SystemDeps
151
+ ) { }
152
+
153
+ // ✅ 正确:统一的依赖对象
154
+ export interface MyFunctionDeps {
155
+ existsSync: FileSystem['existsSync']
156
+ readFileSync: FileSystem['readFileSync']
157
+ join: Path['join']
158
+ xmlParser: XMLParserConstructor
159
+ }
160
+
161
+ export function myFunction(path: string, deps: MyFunctionDeps) {
162
+ deps.existsSync(...)
163
+ deps.readFileSync(...)
164
+ deps.join(...)
165
+ }
166
+ ```
167
+
168
+ #### 规则 6:第三方 SDK 对象也要拆分
169
+
170
+ 不仅是 Node.js 和浏览器 API,第三方 SDK 对象(Vue、微信、UniApp 等)也要遵循同样的规则。
72
171
 
73
- export function readFile(path: string, fs: FileSystem) {
74
- return fs.readFileSync(path, 'utf8') // 通过参数注入
172
+ ```typescript
173
+ // 错误:传入整个 Vue 运行时
174
+ import type { VueRuntime } from '../../references/vue.d'
175
+
176
+ export interface DynamicMountOptions {
177
+ vue: VueRuntime // 包含很多未使用的方法
178
+ }
179
+
180
+ export function dynamicMount(options: DynamicMountOptions) {
181
+ options.vue.createVNode(...)
182
+ options.vue.render(...)
183
+ }
184
+
185
+ // ✅ 正确:只传入使用的函数
186
+ import type { VueRuntime } from '../../references/vue.d'
187
+
188
+ export interface DynamicMountDeps {
189
+ createVNode: VueRuntime['createVNode']
190
+ render: VueRuntime['render']
191
+ }
192
+
193
+ export function dynamicMount(deps: DynamicMountDeps) {
194
+ deps.createVNode(...)
195
+ deps.render(...)
196
+ }
197
+ ```
198
+
199
+ **常见第三方 SDK 拆分示例:**
200
+
201
+ ```typescript
202
+ // 微信小程序 API
203
+ import type { Wx } from '../../references/wechat.d'
204
+
205
+ export interface WxDownloadFileDeps {
206
+ USER_DATA_PATH: Wx['env']['USER_DATA_PATH']
207
+ downloadFile: Wx['downloadFile']
208
+ }
209
+
210
+ // UniApp API
211
+ import type { UniApp } from '../../references/uniapp.d'
212
+
213
+ export interface WaitForPagesDeps {
214
+ getCurrentPages: UniApp['getCurrentPages']
215
+ }
216
+
217
+ // CryptoJS
218
+ import type { CryptoJS } from '../../references/crypto-js.d'
219
+
220
+ export interface GenerateLicenseDeps {
221
+ MD5: CryptoJS['MD5']
222
+ }
223
+
224
+ // 腾讯云 SDK
225
+ import type { CloudBaseManager } from '../../references/tencent-cloud.d'
226
+
227
+ export interface DeployTCBDeps {
228
+ init: CloudBaseManager['init']
229
+ }
230
+ ```
231
+
232
+ #### 完整示例
233
+
234
+ ```typescript
235
+ // src/functions/android/buildProject.ts
236
+ import type { FileSystem, Path, ChildProcess } from '../../../references/node.d'
237
+ import type { setTimeout } from '../../../references/timer.d'
238
+
239
+ export interface AndroidBuildDependencies {
240
+ /** 检查文件/目录是否存在 */
241
+ existsSync: FileSystem['existsSync']
242
+ /** 读取目录内容 */
243
+ readdirSync: FileSystem['readdirSync']
244
+ /** 获取文件状态 */
245
+ statSync: FileSystem['statSync']
246
+ /** 路径拼接 */
247
+ join: Path['join']
248
+ /** 获取进程平台信息 */
249
+ platform: string
250
+ /** 执行子进程命令 */
251
+ exec: ChildProcess['exec']
252
+ /** 超时设置函数 */
253
+ setTimeout: typeof setTimeout
254
+ }
255
+
256
+ export async function buildProject(
257
+ options: AndroidBuildOptions,
258
+ deps: AndroidBuildDependencies
259
+ ): Promise<AndroidBuildResult> {
260
+ // 使用 deps. 前缀访问所有依赖
261
+ if (!deps.existsSync(projectPath)) {
262
+ return { success: false, error: '路径不存在' }
263
+ }
264
+
265
+ const buildPath = deps.join(projectPath, 'build.gradle')
266
+ const files = deps.readdirSync(projectPath)
267
+
268
+ deps.exec(command, (error, stdout, stderr) => {
269
+ // ...
270
+ })
271
+
272
+ deps.setTimeout(() => {
273
+ // ...
274
+ }, 1000)
75
275
  }
76
276
  ```
77
277
 
78
278
  ### 2. 类型抽象
79
279
 
80
- **references/** 目录定义环境API的抽象接口:
280
+ **references/** 目录定义环境API的抽象类型(接口、类型别名等),所有基础类型都应在此定义:
81
281
 
82
282
  ```typescript
83
283
  // references/node.d.ts
@@ -85,12 +285,51 @@ export interface FileSystem {
85
285
  readFileSync(path: string, encoding?: string): string
86
286
  writeFileSync(path: string, data: any): void
87
287
  existsSync(path: string): boolean
288
+ readdirSync(path: string): string[]
289
+ statSync(path: string): { isDirectory(): boolean; isFile(): boolean }
290
+ }
291
+
292
+ export interface Path {
293
+ join(...paths: string[]): string
294
+ dirname(path: string): string
295
+ basename(path: string): string
296
+ }
297
+
298
+ export interface ChildProcess {
299
+ exec(command: string, callback?: (error: any, stdout: string, stderr: string) => void): any
88
300
  }
89
301
 
90
302
  // references/browser.d.ts
91
303
  export interface Window {
304
+ innerWidth: number
305
+ innerHeight: number
92
306
  localStorage: Storage
93
- fetch: (url: string) => Promise<Response>
307
+ Image: new () => HTMLImageElement
308
+ File: new (bits: BlobPart[], name: string, options?: FilePropertyBag) => File
309
+ }
310
+
311
+ // references/dom.d.ts
312
+ export interface Document {
313
+ createElement<K extends keyof HTMLElementTagNameMap>(tagName: K): HTMLElementTagNameMap[K]
314
+ head: HTMLElement
315
+ }
316
+
317
+ // references/vue.d.ts
318
+ export interface Ref<T = any> {
319
+ value: T
320
+ }
321
+
322
+ export type InjectionKey<T> = symbol
323
+
324
+ // references/timer.d.ts
325
+ export declare const setTimeout: (callback: (...args: any[]) => void, ms?: number, ...args: any[]) => any
326
+ export declare const clearTimeout: (timeoutId: any) => void
327
+
328
+ // references/console.d.ts
329
+ export interface Console {
330
+ log(message?: any, ...optionalParams: any[]): void
331
+ error(message?: any, ...optionalParams: any[]): void
332
+ warn(message?: any, ...optionalParams: any[]): void
94
333
  }
95
334
  ```
96
335
 
@@ -103,6 +342,12 @@ export interface RgbColor {
103
342
  g: number
104
343
  b: number
105
344
  }
345
+
346
+ // types/android-build.d.ts
347
+ export interface AndroidBuildOptions {
348
+ projectPath: string
349
+ buildVariant?: 'debug' | 'release'
350
+ }
106
351
  ```
107
352
 
108
353
  ### 3. 多环境适配
@@ -111,20 +356,43 @@ export interface RgbColor {
111
356
 
112
357
  ```typescript
113
358
  // Node.js 环境
114
- import { convertColor } from 'shared/functions/color/convertColor'
115
- convertColor('#ff0000', 'rgb') // 纯函数,无环境依赖
359
+ import fs from 'fs'
360
+ import path from 'path'
361
+ import { buildProject } from 'shared/functions/android/buildProject'
116
362
 
117
- // 浏览器环境
118
- import { useStorage } from 'shared/hooks/useStorage'
119
- import { useLocalStorage } from 'shared/hooks/useLocalStorage'
120
- const storage = useStorage(useLocalStorage(window)) // 注入浏览器API
363
+ const result = await buildProject(options, {
364
+ existsSync: fs.existsSync,
365
+ readdirSync: fs.readdirSync,
366
+ statSync: fs.statSync,
367
+ join: path.join,
368
+ platform: process.platform,
369
+ exec: require('child_process').exec,
370
+ setTimeout
371
+ })
121
372
 
122
- // UniApp 环境
123
- import { buildProject } from 'shared/functions/android/buildProject'
124
- buildProject(projectPath, {
125
- fs: uni.getFileSystemManager(), // 注入UniApp API
126
- path: uniPath,
127
- process: uniProcess
373
+ // 浏览器 Vue 环境
374
+ import { ref, shallowRef, watch } from 'vue'
375
+ import { useAsyncState } from 'shared/hooks/useAsyncState'
376
+
377
+ // 传入 Vue 运行时函数和浏览器 API
378
+ const { state, isLoading } = useAsyncState(
379
+ async () => fetch('/api/data').then(r => r.json()),
380
+ {
381
+ immediate: true,
382
+ delay: 1000
383
+ },
384
+ {
385
+ vue: { ref, shallowRef, watch }, // Vue Composition API 函数
386
+ host: { setTimeout } // 浏览器定时器
387
+ }
388
+ )
389
+
390
+ // 浏览器 DOM 操作
391
+ import { getViewportRect } from 'shared/functions/dom/getViewportRect'
392
+
393
+ const viewport = getViewportRect({
394
+ innerWidth: window.innerWidth,
395
+ innerHeight: window.innerHeight
128
396
  })
129
397
  ```
130
398
 
@@ -257,27 +525,24 @@ const edgeCases = [
257
525
 
258
526
  ```typescript
259
527
  import { buildProject } from 'shared/functions/android/buildProject'
260
- import type { FileSystem, Path } from 'shared/references/node'
261
528
 
262
- // 模拟文件系统
263
- const mockFs: FileSystem = {
529
+ // 创建模拟的依赖函数
530
+ const mockDeps = {
264
531
  existsSync: (path: string) => path.includes('build.gradle'),
265
532
  readFileSync: (path: string) => 'mock file content',
266
- writeFileSync: (path: string, data: any) => {},
267
- // ... 其他方法
268
- }
269
-
270
- const mockPath: Path = {
533
+ readdirSync: (path: string) => ['file1.txt', 'file2.txt'],
534
+ statSync: (path: string) => ({ isDirectory: () => false, isFile: () => true }),
271
535
  join: (...paths: string[]) => paths.join('/'),
272
- // ... 其他方法
536
+ platform: 'darwin',
537
+ exec: (cmd: string, callback: any) => callback(null, 'success', ''),
538
+ setTimeout: (fn: () => void, delay: number) => global.setTimeout(fn, delay)
273
539
  }
274
540
 
275
541
  function testBuildProject() {
276
- const result = buildProject('/mock/project', {
277
- fs: mockFs,
278
- path: mockPath,
279
- // ... 其他依赖
280
- })
542
+ const result = buildProject(
543
+ { projectPath: '/mock/project', buildVariant: 'debug' },
544
+ mockDeps
545
+ )
281
546
  console.log('构建结果:', result)
282
547
  }
283
548
  ```
@@ -330,11 +595,7 @@ npx tsx tests/*.test.ts
330
595
 
331
596
  2. **编译依赖**:改动了函数以后,因为playground中引用的是编译后的shared包,所以需要先编译shared包(`npm run build`),test中才能用到最新的代码。
332
597
 
333
- 3. **文档同步更新**:每次新增新功能或修改现有功能后,**必须**同步更新VitePress文档:
334
- - 在 `docs/api/` 目录下更新或创建对应的API文档
335
- - 在 `docs/examples/` 目录下添加使用示例
336
- - 确保文档中的TypeScript泛型语法使用反引号包裹(如 `Promise<\`File\`>`)以避免Vue编译错误
337
- - 运行 `npm run docs:dev` 验证文档编译无误
598
+ 3. **文档同步更新**:每次新增或修改函数后,**必须**同步更新 VitePress 文档。详细规范见下方"文档规范"章节。
338
599
 
339
600
  ### 1. 添加新函数
340
601
 
@@ -348,40 +609,175 @@ types/category.d.ts
348
609
  # 3. 创建测试
349
610
  playground/tests/newFunction.test.ts
350
611
 
351
- # 4. 更新VitePress文档
352
- docs/api/category.md # API文档
353
- docs/examples/category.md # 使用示例
612
+ # 4. 创建函数文档(必须!)
613
+ docs/api/category/newFunction.md
614
+
615
+ # 5. 创建 Playground 组件(如果是浏览器端函数)
616
+ docs/.vitepress/components/NewFunctionPlayground.vue
354
617
 
355
- # 5. 验证文档编译
618
+ # 6. 更新侧边栏配置
619
+ docs/.vitepress/config.ts
620
+
621
+ # 7. 验证文档编译
356
622
  npm run docs:dev
357
623
 
358
- # 6. 构建和导出
624
+ # 8. 构建和导出
359
625
  npm run build
360
626
  ```
361
627
 
362
628
  ### 2. 函数开发模板
363
629
 
630
+ 遵循最新的依赖注入规范:
631
+
364
632
  ```typescript
365
633
  // src/functions/category/newFunction.ts
366
- import type { SomeType } from '../../types/category.d'
367
- import type { EnvironmentAPI } from '../../references/environment.d'
634
+ import type { FileSystem, Path } from '../../references/node.d'
635
+ import type { setTimeout } from '../../references/timer.d'
636
+ import type { Console } from '../../references/console.d'
637
+
638
+ /**
639
+ * 函数依赖接口
640
+ * 注意:
641
+ * 1. 只包含实际使用的函数
642
+ * 2. 使用 Interface['method'] 或 typeof 提取类型
643
+ * 3. 每个依赖都要有清晰的注释
644
+ */
645
+ export interface NewFunctionDeps {
646
+ /** 检查文件是否存在 */
647
+ existsSync: FileSystem['existsSync']
648
+ /** 读取文件内容 */
649
+ readFileSync: FileSystem['readFileSync']
650
+ /** 路径拼接 */
651
+ join: Path['join']
652
+ /** 超时函数 */
653
+ setTimeout: typeof setTimeout
654
+ /** 错误日志函数 */
655
+ error: Console['error']
656
+ /** 日志输出函数 */
657
+ log: Console['log']
658
+ }
368
659
 
369
660
  /**
370
661
  * 函数描述
371
662
  *
372
663
  * @param input - 输入参数
373
- * @param deps - 环境依赖
664
+ * @param deps - 环境依赖(包含所有需要的函数)
374
665
  * @returns 返回值描述
666
+ *
667
+ * @example
668
+ * ```typescript
669
+ * import fs from 'fs'
670
+ * import path from 'path'
671
+ *
672
+ * const result = newFunction(input, {
673
+ * existsSync: fs.existsSync,
674
+ * readFileSync: fs.readFileSync,
675
+ * join: path.join,
676
+ * setTimeout,
677
+ * error: console.error,
678
+ * log: console.log
679
+ * })
680
+ * ```
375
681
  */
376
682
  export function newFunction(
377
- input: SomeType,
378
- deps: EnvironmentAPI
379
- ): ReturnType {
380
- // 实现逻辑
683
+ input: string,
684
+ deps: NewFunctionDeps
685
+ ): string {
686
+ // ✅ 使用 deps. 前缀访问所有依赖
687
+ if (!deps.existsSync(input)) {
688
+ deps.error('文件不存在')
689
+ return ''
690
+ }
691
+
692
+ const content = deps.readFileSync(input, 'utf8')
693
+ const outputPath = deps.join(input, '../output.txt')
694
+
695
+ deps.setTimeout(() => {
696
+ deps.log('处理完成')
697
+ }, 1000)
698
+
699
+ return content
700
+ }
701
+ ```
702
+
703
+ **Vue Hooks 开发模板:**
704
+
705
+ ```typescript
706
+ // src/hooks/useNewHook.ts
707
+ import type { Ref } from '../../references/vue.d'
708
+ import type { setTimeout } from '../../references/timer.d'
709
+
710
+ export interface VueCompositionAPI {
711
+ ref: <T>(value: T) => Ref<T>
712
+ watch: (source: any, callback: () => void, options?: any) => void
713
+ onMounted: (fn: () => void) => void
714
+ onUnmounted: (fn: () => void) => void
715
+ }
716
+
717
+ export interface NewHookEnvironment {
718
+ vue: VueCompositionAPI
719
+ host: {
720
+ setTimeout: typeof setTimeout
721
+ clearTimeout: typeof clearTimeout
722
+ }
723
+ }
724
+
725
+ export function useNewHook<T>(
726
+ source: Ref<T>,
727
+ options: NewHookOptions,
728
+ env: NewHookEnvironment
729
+ ): NewHookReturn<T> {
730
+ const state = env.vue.ref<T>(initialValue)
731
+
732
+ env.vue.watch(source, () => {
733
+ // 监听逻辑
734
+ })
735
+
736
+ env.vue.onMounted(() => {
737
+ // 挂载逻辑
738
+ })
739
+
740
+ env.host.setTimeout(() => {
741
+ // 定时器逻辑
742
+ }, 1000)
743
+
744
+ return { state }
381
745
  }
382
746
  ```
383
747
 
384
- ### 3. 构建和发布
748
+ ### 3. 代码检查清单
749
+
750
+ 在提交代码前,请确保:
751
+
752
+ #### ✅ 依赖注入检查
753
+ - [ ] 没有直接 `import` 第三方库(如 `vue`、`react`)
754
+ - [ ] 没有直接使用全局对象(`window`、`document`、`global`、`process`)
755
+ - [ ] 所有环境依赖都通过 `deps` 或 `env` 参数传入
756
+ - [ ] 使用 `deps.` 前缀访问依赖,没有解构
757
+
758
+ #### ✅ 类型定义检查
759
+ - [ ] 类型从 `references/` 导入,使用 `import type`
760
+ - [ ] 依赖接口命名为 `{FunctionName}Deps` 或 `{HookName}Environment`
761
+ - [ ] 使用 `Interface['method']` 或 `typeof` 提取类型
762
+ - [ ] 每个依赖都有清晰的 JSDoc 注释
763
+ - [ ] 没有在函数中重复定义已存在的类型
764
+
765
+ #### ✅ 函数设计检查
766
+ - [ ] 只传入实际使用的函数,不传入整个模块对象
767
+ - [ ] 第三方 SDK 对象(Vue、Wx、UniApp 等)也要拆分
768
+ - [ ] 函数签名清晰,参数顺序合理
769
+ - [ ] 错误处理完善,不会意外抛出异常
770
+ - [ ] 有完整的 JSDoc 文档注释
771
+
772
+ #### ✅ 测试和文档检查
773
+ - [ ] 创建了对应的测试文件
774
+ - [ ] 创建了 VitePress 文档
775
+ - [ ] 浏览器函数创建了 Playground 组件
776
+ - [ ] 更新了侧边栏配置
777
+ - [ ] 运行 `npm run build` 编译成功
778
+ - [ ] 运行 `npm run docs:dev` 文档正常显示
779
+
780
+ ### 4. 构建和发布
385
781
 
386
782
  ```bash
387
783
  # 类型检查
@@ -404,32 +800,862 @@ npm run publish:major # 主要版本
404
800
  ### 函数设计
405
801
 
406
802
  1. **纯函数优先**:无副作用,相同输入产生相同输出
407
- 2. **依赖注入**:环境相关API通过参数传入
803
+ 2. **依赖注入**:环境相关API通过 `deps` 参数传入
408
804
  3. **类型安全**:完整的TypeScript类型定义
409
805
  4. **错误处理**:优雅处理异常情况,返回null而非抛出异常
806
+ 5. **精确依赖**:只传入实际使用的函数,不传入整个模块
807
+ 6. **使用前缀**:通过 `deps.` 访问依赖,避免命名冲突
410
808
 
411
809
  ### 类型定义
412
810
 
413
811
  1. **分层设计**:业务类型放在 `types/`,环境类型放在 `references/`
414
- 2. **接口抽象**:定义最小化的接口,只包含必要的方法
415
- 3. **泛型支持**:提供灵活的类型参数
812
+ 2. **类型提取**:使用 `Interface['method']` 或 `typeof` 从 references 提取类型
813
+ 3. **避免重复定义**:不在函数中定义已存在于 references 的类型
814
+ 4. **完整注释**:每个依赖函数都要有清晰的注释说明用途
815
+ 5. **统一接口**:每个函数有自己完整的 `Deps` 接口,不依赖通用的 `SystemDependencies`
816
+
817
+ ### 依赖管理
818
+
819
+ 1. **不导入第三方库**:不直接 `import { ref } from 'vue'`,而是通过 `env` 对象传入
820
+ 2. **不依赖全局对象**:不直接使用 `window`、`document`、`global`
821
+ 3. **接口命名规范**:`{FunctionName}Deps`,例如 `BuildProjectDeps`、`ModifyManifestDeps`
822
+ 4. **使用 deps. 前缀**:所有依赖访问都使用 `deps.methodName()`,不解构
416
823
 
417
824
  ### 测试要求
418
825
 
419
826
  1. **全面覆盖**:正常、边界、异常情况
420
827
  2. **环境模拟**:使用mock对象测试环境依赖
421
828
  3. **文档化**:测试即文档,展示函数的使用方法
829
+ 4. **依赖注入测试**:验证函数在不同依赖注入下的行为
830
+
831
+ ### 快速检查清单
832
+
833
+ 在编写新函数或修改现有函数时,快速检查以下要点:
834
+
835
+ **✅ 6大核心规则:**
836
+ 1. ❌ 不直接导入第三方库 → ✅ 从 `references/` 导入类型
837
+ 2. ❌ 不传入整个模块对象 → ✅ 只传入实际使用的函数
838
+ 3. ❌ 不解构 deps 对象 → ✅ 使用 `deps.` 前缀访问
839
+ 4. ❌ 不重复定义类型 → ✅ 使用 `Interface['method']` 提取
840
+ 5. ❌ 不分散依赖到多个参数 → ✅ 统一的 `Deps` 接口
841
+ 6. ❌ 第三方 SDK 也不能整个传入 → ✅ Vue、Wx 等也要拆分
842
+
843
+ **✅ 命名规范:**
844
+ - 函数依赖接口:`{FunctionName}Deps`
845
+ - Hook 环境接口:`{HookName}Environment`
846
+ - Playground 组件:`{FunctionName}Playground.vue`
847
+
848
+ **✅ 文档完整性:**
849
+ - [ ] Markdown 文档(`docs/api/category/functionName.md`)
850
+ - [ ] Playground 组件(浏览器函数必须)
851
+ - [ ] 测试文件(`playground/tests/functionName.test.ts`)
852
+ - [ ] 侧边栏配置已更新
853
+
854
+ ### 常见错误和解决方案
855
+
856
+ #### ❌ 错误 1:直接导入第三方库
857
+ ```typescript
858
+ import { ref, watch } from 'vue' // ❌ 错误
859
+ ```
860
+ **解决方案:**
861
+ ```typescript
862
+ import type { Ref } from '../../references/vue.d' // ✅ 正确
863
+
864
+ export interface VueCompositionAPI {
865
+ ref: <T>(value: T) => Ref<T>
866
+ watch: (source: any, callback: () => void) => void
867
+ }
868
+
869
+ export function useMyHook(env: { vue: VueCompositionAPI }) {
870
+ const state = env.vue.ref(0)
871
+ env.vue.watch(state, () => {})
872
+ }
873
+ ```
874
+
875
+ #### ❌ 错误 2:传入整个模块对象
876
+ ```typescript
877
+ export function myFunction(fs: FileSystem, path: Path) { // ❌ 错误
878
+ fs.existsSync(...)
879
+ }
880
+ ```
881
+ **解决方案:**
882
+ ```typescript
883
+ export interface MyFunctionDeps {
884
+ existsSync: FileSystem['existsSync'] // ✅ 正确
885
+ }
886
+
887
+ export function myFunction(deps: MyFunctionDeps) {
888
+ deps.existsSync(...)
889
+ }
890
+ ```
891
+
892
+ #### ❌ 错误 3:解构依赖对象
893
+ ```typescript
894
+ export function myFunction(deps: MyFunctionDeps) {
895
+ const { existsSync, join } = deps // ❌ 错误,可能命名冲突
896
+ }
897
+ ```
898
+ **解决方案:**
899
+ ```typescript
900
+ export function myFunction(deps: MyFunctionDeps) {
901
+ deps.existsSync(...) // ✅ 正确,清晰明确
902
+ deps.join(...)
903
+ }
904
+ ```
905
+
906
+ #### ❌ 错误 4:在函数中定义类型
907
+ ```typescript
908
+ export interface MyFunctionDeps {
909
+ exec: (cmd: string, cb: (err: any) => void) => any // ❌ 错误
910
+ }
911
+ ```
912
+ **解决方案:**
913
+ ```typescript
914
+ import type { ChildProcess } from '../../references/node.d'
915
+
916
+ export interface MyFunctionDeps {
917
+ exec: ChildProcess['exec'] // ✅ 正确,从 references 提取
918
+ }
919
+ ```
920
+
921
+ #### ❌ 错误 5:依赖全局对象
922
+ ```typescript
923
+ export function myFunction(window: Window) { // ❌ 错误
924
+ const width = window.innerWidth
925
+ window.localStorage.setItem(...)
926
+ }
927
+ ```
928
+ **解决方案:**
929
+ ```typescript
930
+ import type { Window } from '../../references/browser.d'
931
+
932
+ export interface MyFunctionDeps {
933
+ innerWidth: Window['innerWidth'] // ✅ 正确
934
+ setItem: (key: string, value: string) => void
935
+ }
936
+
937
+ export function myFunction(deps: MyFunctionDeps) {
938
+ const width = deps.innerWidth
939
+ deps.setItem('key', 'value')
940
+ }
941
+ ```
942
+
943
+ #### ❌ 错误 6:传入整个第三方 SDK 对象
944
+ ```typescript
945
+ import type { VueRuntime } from '../../references/vue.d'
946
+ import type { Wx } from '../../references/wechat.d'
947
+
948
+ export interface MyFunctionDeps {
949
+ vue: VueRuntime // ❌ 错误,包含很多未使用的方法
950
+ wx: Wx // ❌ 错误,包含很多未使用的方法
951
+ }
952
+
953
+ export function myFunction(deps: MyFunctionDeps) {
954
+ deps.vue.createVNode(...)
955
+ deps.wx.downloadFile(...)
956
+ }
957
+ ```
958
+ **解决方案:**
959
+ ```typescript
960
+ import type { VueRuntime } from '../../references/vue.d'
961
+ import type { Wx } from '../../references/wechat.d'
962
+
963
+ export interface MyFunctionDeps {
964
+ createVNode: VueRuntime['createVNode'] // ✅ 正确
965
+ downloadFile: Wx['downloadFile'] // ✅ 正确
966
+ USER_DATA_PATH: Wx['env']['USER_DATA_PATH'] // ✅ 嵌套属性也要精确提取
967
+ }
968
+
969
+ export function myFunction(deps: MyFunctionDeps) {
970
+ deps.createVNode(...)
971
+ deps.downloadFile(...)
972
+ const path = `${deps.USER_DATA_PATH}/file.txt`
973
+ }
974
+ ```
975
+
976
+ **常见第三方 SDK 对象拆分:**
977
+ - `VueRuntime` → 只传入 `createVNode`, `render` 等实际使用的方法
978
+ - `Wx` (微信) → 只传入 `downloadFile`, `request` 等实际使用的方法
979
+ - `UniApp` → 只传入 `getCurrentPages` 等实际使用的方法
980
+ - `CryptoJS` → 只传入 `MD5`, `SHA256` 等实际使用的方法
981
+ - `CloudBaseManager` → 只传入 `init` 等实际使用的方法
982
+ - `Sharp` (图像处理) → 已经是函数,直接作为依赖
422
983
 
423
984
  ### 文档规范
424
985
 
425
- 1. **JSDoc注释**:详细的函数说明和参数描述
426
- 2. **使用示例**:在测试文件中提供实际使用案例
427
- 3. **类型导出**:确保所有相关类型都可以导入
428
- 4. **VitePress文档**:
429
- - **API文档**:在 `docs/api/` 目录下为每个模块创建详细的API文档
430
- - **示例文档**:在 `docs/examples/` 目录下提供实际使用示例
431
- - **语法规范**:TypeScript泛型语法必须用反引号包裹(如 `Promise<\`File\`>`)
432
- - **编译验证**:确保文档能够正常编译,无Vue语法错误
986
+ **重要:每个函数或 Hook 都必须有完整的文档!**
987
+
988
+ #### 0. 文档网站开发
989
+
990
+ 本项目使用 VitePress 构建文档网站。
991
+
992
+ **开发命令:**
993
+
994
+ ```bash
995
+ # 本地开发文档网站
996
+ npm run docs:dev
997
+
998
+ # 构建生产版本
999
+ npm run docs:build
1000
+
1001
+ # 预览构建后的网站
1002
+ npm run docs:preview
1003
+ ```
1004
+
1005
+ **文档目录结构:**
1006
+
1007
+ ```
1008
+ docs/
1009
+ ├── index.md # 首页
1010
+ ├── guide/ # 指南文档
1011
+ ├── api/ # API文档
1012
+ │ ├── color/ # 按功能分类
1013
+ │ ├── string/
1014
+ │ └── utils/
1015
+ └── .vitepress/ # VitePress配置
1016
+ ├── config.ts # 网站配置和侧边栏
1017
+ ├── theme/ # 主题配置
1018
+ └── components/ # Playground组件
1019
+ ```
1020
+
1021
+ #### 1. 文档文件结构
1022
+
1023
+ 每个函数必须有独立的 Markdown 文档:
1024
+
1025
+ ```
1026
+ docs/api/
1027
+ ├── color/
1028
+ │ ├── convertColor.md # 每个函数一个文档
1029
+ │ ├── colorValidation.md
1030
+ │ └── ...
1031
+ ├── string/
1032
+ │ ├── capitalize.md
1033
+ │ └── ...
1034
+ └── utils/
1035
+ ├── debounce.md
1036
+ └── ...
1037
+ ```
1038
+
1039
+ #### 2. 文档内容模板
1040
+
1041
+ 每个函数文档应按照以下结构编写(按优先级排序):
1042
+
1043
+ ##### 必需部分
1044
+
1045
+ ```markdown
1046
+ # functionName
1047
+
1048
+ <!-- 1. 函数描述(一句话) -->
1049
+ 简短描述函数的功能和用途。
1050
+
1051
+ <!-- 2. Playground 组件(浏览器端函数必须有) -->
1052
+ <script setup>
1053
+ import FunctionNamePlayground from '../../.vitepress/components/FunctionNamePlayground.vue'
1054
+ </script>
1055
+
1056
+ <FunctionNamePlayground />
1057
+
1058
+ <!-- 3. 前置依赖(如果函数有 deps 参数) -->
1059
+ ## 前置依赖
1060
+
1061
+ ### 依赖参数
1062
+
1063
+ | 参数名 | 类型 | 说明 |
1064
+ |--------|------|------|
1065
+ | `deps.xxx` | `Type` | 依赖说明 |
1066
+
1067
+ ### 环境要求
1068
+
1069
+ - **第三方库名**: 用途说明
1070
+
1071
+ \`\`\`bash
1072
+ npm install library-name
1073
+ \`\`\`
1074
+
1075
+ <!-- 4. 函数签名 -->
1076
+ ## 函数签名
1077
+
1078
+ \`\`\`typescript
1079
+ function functionName(
1080
+ param1: Type1,
1081
+ param2: Type2,
1082
+ deps?: DepsType
1083
+ ): ReturnType
1084
+
1085
+ interface FunctionNameDeps {
1086
+ // 依赖接口定义
1087
+ }
1088
+ \`\`\`
1089
+
1090
+ <!-- 5. 参数表格 -->
1091
+ ## 参数
1092
+
1093
+ | 参数名 | 类型 | 必填 | 说明 |
1094
+ |--------|------|------|------|
1095
+ | `param1` | `Type1` | 是 | 参数说明 |
1096
+ | `param2` | `Type2` | 否 | 可选参数说明 |
1097
+
1098
+ <!-- 6. 返回值 -->
1099
+ ## 返回值
1100
+
1101
+ | 类型 | 说明 |
1102
+ |------|------|
1103
+ | `ReturnType` | 返回值说明 |
1104
+
1105
+ <!-- 7. 工作原理 -->
1106
+ ## 工作原理
1107
+
1108
+ 1. 步骤1说明
1109
+ 2. 步骤2说明
1110
+ 3. 步骤3说明
1111
+ 4. 返回结果
1112
+
1113
+ 补充说明...
1114
+ ```
1115
+
1116
+ ##### 可选部分
1117
+
1118
+ ```markdown
1119
+ <!-- 异常(如果函数会抛出错误) -->
1120
+ ## 异常
1121
+
1122
+ | 错误类型 | 触发条件 | 错误信息 |
1123
+ |----------|----------|----------|
1124
+ | `Error` | 条件 | 错误文本 |
1125
+ ```
1126
+
1127
+ ##### 文档编写注意事项
1128
+
1129
+ - ✅ **必须包含**:函数描述、函数签名、参数表格、返回值、工作原理
1130
+ - ✅ **浏览器端函数必须有** Playground 组件
1131
+ - ✅ **有 deps 参数的函数必须有**前置依赖说明
1132
+ - ❌ **不要包含**:`## 导入` 章节(已在首页说明)
1133
+ - ❌ **不要包含**:冗长的使用示例代码
1134
+ - ❌ **不要包含**:`## 注意事项` 章节(信息整合到其他部分)
1135
+ - ✅ **使用表格**:参数、返回值、异常等都用表格展示
1136
+ - ✅ **工作原理简明扼要**:说明核心逻辑即可,不要过于详细
1137
+
1138
+ #### 3. Playground 组件规范
1139
+
1140
+ 浏览器端函数必须创建交互式 Playground 组件:
1141
+
1142
+ **命名规范:**
1143
+ - 文件名:`{FunctionName}Playground.vue`(首字母大小写,驼峰命名)
1144
+ - 位置:`docs/.vitepress/components/`
1145
+
1146
+ **设计规范:**
1147
+
1148
+ 所有 Playground 组件必须遵循统一的设计语言,确保视觉一致性和用户体验:
1149
+
1150
+ ##### 视觉风格
1151
+
1152
+ 1. **容器背景**
1153
+ ```css
1154
+ .playground-container {
1155
+ width: 100%; /* 重要:占满容器宽度 */
1156
+ padding: 24px;
1157
+ background: linear-gradient(135deg, #f5f7fa 0%, #ffffff 100%);
1158
+ border-radius: 16px;
1159
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
1160
+ box-sizing: border-box; /* 重要:确保 padding 不溢出 */
1161
+ }
1162
+ ```
1163
+
1164
+ 2. **卡片样式**
1165
+ ```css
1166
+ .card {
1167
+ background: white;
1168
+ border-radius: 12px;
1169
+ padding: 20px;
1170
+ margin-bottom: 20px;
1171
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06); /* 注意:是 12px 和 0.06,不是 8px 和 0.08 */
1172
+ }
1173
+ ```
1174
+
1175
+ 3. **标题样式**
1176
+ ```css
1177
+ h4 {
1178
+ margin: 0 0 16px 0;
1179
+ font-size: 15px;
1180
+ font-weight: 600;
1181
+ color: #374151; /* 重要:统一使用 #374151,不是 #2c3e50 */
1182
+ text-transform: uppercase; /* 重要:标题全部大写 */
1183
+ letter-spacing: 0.05em; /* 重要:增加字母间距 */
1184
+ }
1185
+ ```
1186
+
1187
+ ##### 配色方案
1188
+
1189
+ 1. **主色调**
1190
+ - 主要按钮:`#3b82f6`(蓝色)
1191
+ - 成功状态:`#10b981`(绿色)
1192
+ - 错误状态:`#ef4444`(红色)
1193
+ - 警告状态:`#f59e0b`(橙色)
1194
+ - 中性按钮:`#6b7280`(灰色)
1195
+
1196
+ 2. **文本颜色**
1197
+ - 主标题:`#374151`(15-16px)
1198
+ - 正文:`#6b7280`(14px)
1199
+ - 次要文本:`#9ca3af`(13px)
1200
+
1201
+ 3. **边框和背景**
1202
+ - 边框:`#e5e7eb`(2px solid)
1203
+ - 卡片背景:`#ffffff`
1204
+ - 输入框背景:`#f9fafb`
1205
+
1206
+ ##### 交互元素
1207
+
1208
+ 1. **输入框**
1209
+ ```css
1210
+ input, textarea, select {
1211
+ padding: 12px 14px;
1212
+ border: 2px solid #e5e7eb; /* 重要:使用 #e5e7eb,不是 #e0e0e0 */
1213
+ border-radius: 8px;
1214
+ font-size: 14px;
1215
+ box-sizing: border-box;
1216
+ transition: all 0.2s;
1217
+ }
1218
+
1219
+ input:focus, textarea:focus, select:focus {
1220
+ outline: none;
1221
+ border-color: #3b82f6;
1222
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); /* 重要:焦点阴影 */
1223
+ }
1224
+ ```
1225
+
1226
+ 2. **按钮基础样式**
1227
+ ```css
1228
+ .btn {
1229
+ padding: 12px 18px; /* 注意:是 18px,不是 20px */
1230
+ border: none; /* 重要:按钮无边框 */
1231
+ border-radius: 8px;
1232
+ font-size: 13px; /* 注意:是 13px,不是 14px */
1233
+ font-weight: 600;
1234
+ cursor: pointer;
1235
+ transition: all 0.2s;
1236
+ }
1237
+
1238
+ .btn:hover:not(:disabled) {
1239
+ transform: translateY(-1px); /* 重要:hover 向上移动 */
1240
+ }
1241
+
1242
+ .btn:disabled {
1243
+ opacity: 0.5;
1244
+ cursor: not-allowed;
1245
+ }
1246
+ ```
1247
+
1248
+ 3. **小按钮样式**
1249
+ ```css
1250
+ .btn-small {
1251
+ padding: 4px 12px; /* 用于工具按钮 */
1252
+ font-size: 12px;
1253
+ }
1254
+ ```
1255
+
1256
+ 4. **按钮颜色变体**
1257
+ ```css
1258
+ /* 主要按钮 - 蓝色 */
1259
+ .btn-primary {
1260
+ background: #3b82f6;
1261
+ color: white;
1262
+ }
1263
+ .btn-primary:hover {
1264
+ background: #2563eb;
1265
+ }
1266
+
1267
+ /* 次要按钮 - 灰色 */
1268
+ .btn-secondary {
1269
+ background: #6b7280;
1270
+ color: white;
1271
+ }
1272
+ .btn-secondary:hover {
1273
+ background: #4b5563;
1274
+ }
1275
+
1276
+ /* 成功按钮 - 绿色 */
1277
+ .btn-success {
1278
+ background: #10b981;
1279
+ color: white;
1280
+ }
1281
+ .btn-success:hover {
1282
+ background: #059669;
1283
+ }
1284
+
1285
+ /* 危险按钮 - 红色 */
1286
+ .btn-danger {
1287
+ background: #ef4444;
1288
+ color: white;
1289
+ }
1290
+ .btn-danger:hover {
1291
+ background: #dc2626;
1292
+ }
1293
+
1294
+ /* 警告按钮 - 橙色 */
1295
+ .btn-warning {
1296
+ background: #f59e0b;
1297
+ color: white;
1298
+ }
1299
+ .btn-warning:hover {
1300
+ background: #d97706;
1301
+ }
1302
+
1303
+ /* 信息按钮 - 青色 */
1304
+ .btn-info {
1305
+ background: #06b6d4;
1306
+ color: white;
1307
+ }
1308
+ .btn-info:hover {
1309
+ background: #0891b2;
1310
+ }
1311
+ ```
1312
+
1313
+ ##### 布局规范
1314
+
1315
+ 1. **间距系统**
1316
+ - 组件间距:`20px`
1317
+ - 内边距:`20-24px`
1318
+ - 小间距:`12px`
1319
+ - 表单元素间距:`16px`
1320
+
1321
+ 2. **圆角统一**
1322
+ - 容器:`16px`
1323
+ - 卡片:`12px`
1324
+ - 输入框/按钮:`8px`
1325
+ - 小元素:`6px`
1326
+
1327
+ 3. **响应式设计**
1328
+ ```css
1329
+ @media (max-width: 768px) {
1330
+ .playground-container {
1331
+ padding: 20px;
1332
+ }
1333
+
1334
+ .grid {
1335
+ grid-template-columns: 1fr;
1336
+ }
1337
+ }
1338
+ ```
1339
+
1340
+ ##### 特殊元素
1341
+
1342
+ 1. **统计卡片**
1343
+ ```css
1344
+ .stat-item {
1345
+ display: flex;
1346
+ flex-direction: column;
1347
+ gap: 8px;
1348
+ padding: 16px;
1349
+ background: #f9fafb;
1350
+ border-radius: 8px;
1351
+ border: 2px solid #e5e7eb;
1352
+ text-align: center;
1353
+ }
1354
+
1355
+ .stat-label {
1356
+ font-size: 11px;
1357
+ color: #6b7280;
1358
+ font-weight: 600;
1359
+ text-transform: uppercase;
1360
+ letter-spacing: 0.05em;
1361
+ }
1362
+
1363
+ .stat-value {
1364
+ font-size: 20px; /* 统计数值使用 20px */
1365
+ font-weight: 700;
1366
+ color: #3b82f6; /* 重要:统计值使用主色调 */
1367
+ font-family: monospace; /* 重要:数字使用等宽字体 */
1368
+ }
1369
+ ```
1370
+
1371
+ 2. **日志区域**(推荐使用整体框方式)
1372
+ ```css
1373
+ .log-content {
1374
+ background: #f9fafb;
1375
+ border: 2px solid #e5e7eb;
1376
+ border-radius: 8px;
1377
+ padding: 18px;
1378
+ max-height: 320px;
1379
+ overflow-y: auto;
1380
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
1381
+ font-size: 13px;
1382
+ line-height: 1.6;
1383
+ }
1384
+
1385
+ .log-item {
1386
+ padding: 4px 0;
1387
+ color: #374151;
1388
+ word-break: break-word;
1389
+ }
1390
+
1391
+ .log-empty {
1392
+ color: #9ca3af;
1393
+ text-align: center;
1394
+ padding: 24px;
1395
+ font-size: 13px;
1396
+ }
1397
+ ```
1398
+
1399
+ 3. **结果展示**
1400
+ ```css
1401
+ .result-card {
1402
+ padding: 18px;
1403
+ background: #f9fafb;
1404
+ border: 2px solid #e5e7eb;
1405
+ border-radius: 8px;
1406
+ font-family: monospace;
1407
+ font-size: 13px;
1408
+ line-height: 1.6;
1409
+ }
1410
+ ```
1411
+
1412
+ 2. **代码块**
1413
+ ```css
1414
+ pre, code {
1415
+ background: #1e293b;
1416
+ color: #e2e8f0;
1417
+ padding: 18px;
1418
+ border-radius: 8px;
1419
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
1420
+ font-size: 13px;
1421
+ line-height: 1.6;
1422
+ }
1423
+ ```
1424
+
1425
+ 3. **状态指示**
1426
+ ```css
1427
+ .status-indicator {
1428
+ display: inline-block;
1429
+ width: 8px;
1430
+ height: 8px;
1431
+ border-radius: 50%;
1432
+ margin-right: 8px;
1433
+ }
1434
+
1435
+ .status-success { background: #10b981; }
1436
+ .status-error { background: #ef4444; }
1437
+ .status-warning { background: #f59e0b; }
1438
+ .status-info { background: #3b82f6; }
1439
+ ```
1440
+
1441
+ ##### 禁止事项
1442
+
1443
+ 1. **❌ 不使用 emoji**
1444
+ - 不在 UI 中使用 emoji 图标
1445
+ - 使用简洁的文字描述代替
1446
+ - 必要时使用 Unicode 符号(如 ✓ ✗)
1447
+
1448
+ 2. **❌ 不使用渐变色背景(按钮除外)**
1449
+ - 避免在卡片上使用渐变
1450
+ - 使用纯色或微妙的线性渐变
1451
+
1452
+ 3. **❌ 不使用过大的字体**
1453
+ - 标题 15-16px
1454
+ - 正文 14px
1455
+ - 代码 13px
1456
+ - label 13px
1457
+
1458
+ 4. **❌ 不使用左侧色块装饰**
1459
+ - 避免 `border-left` 彩色边框
1460
+ - 使用统一的边框样式
1461
+
1462
+ ##### 组件模板
1463
+
1464
+ ```vue
1465
+ <script setup lang="ts">
1466
+ import { ref } from 'vue'
1467
+ import { functionName } from '../../../src/functions/category/functionName'
1468
+
1469
+ // 组件逻辑
1470
+ const input = ref('')
1471
+ const result = ref('')
1472
+
1473
+ function handleAction() {
1474
+ result.value = functionName(input.value)
1475
+ }
1476
+ </script>
1477
+
1478
+ <template>
1479
+ <div class="function-playground">
1480
+ <!-- 配置区域 -->
1481
+ <div class="config-section">
1482
+ <h4>配置选项</h4>
1483
+ <div class="input-group">
1484
+ <label>输入</label>
1485
+ <input v-model="input" type="text" placeholder="请输入..." />
1486
+ </div>
1487
+ <button @click="handleAction" class="btn-primary">执行</button>
1488
+ </div>
1489
+
1490
+ <!-- 结果区域 -->
1491
+ <div class="result-section" v-if="result">
1492
+ <h4>结果</h4>
1493
+ <div class="result-card">{{ result }}</div>
1494
+ </div>
1495
+
1496
+ <!-- 说明区域 -->
1497
+ <div class="description-section">
1498
+ <h4>功能说明</h4>
1499
+ <p>函数功能的简要说明...</p>
1500
+ </div>
1501
+ </div>
1502
+ </template>
1503
+
1504
+ <style scoped>
1505
+ .function-playground {
1506
+ width: 100%;
1507
+ padding: 24px;
1508
+ background: linear-gradient(135deg, #f5f7fa 0%, #ffffff 100%);
1509
+ border-radius: 16px;
1510
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
1511
+ box-sizing: border-box;
1512
+ }
1513
+
1514
+ .config-section,
1515
+ .result-section,
1516
+ .description-section {
1517
+ background: white;
1518
+ border-radius: 12px;
1519
+ padding: 20px;
1520
+ margin-bottom: 20px;
1521
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
1522
+ }
1523
+
1524
+ h4 {
1525
+ margin: 0 0 16px 0;
1526
+ font-size: 15px;
1527
+ font-weight: 600;
1528
+ color: #374151;
1529
+ text-transform: uppercase;
1530
+ letter-spacing: 0.05em;
1531
+ }
1532
+
1533
+ .input-group {
1534
+ margin-bottom: 16px;
1535
+ }
1536
+
1537
+ label {
1538
+ display: block;
1539
+ margin-bottom: 8px;
1540
+ font-size: 13px;
1541
+ font-weight: 600;
1542
+ color: #6b7280;
1543
+ }
1544
+
1545
+ input {
1546
+ width: 100%;
1547
+ padding: 12px 14px;
1548
+ border: 2px solid #e5e7eb;
1549
+ border-radius: 8px;
1550
+ font-size: 14px;
1551
+ box-sizing: border-box;
1552
+ transition: all 0.2s;
1553
+ }
1554
+
1555
+ input:focus {
1556
+ outline: none;
1557
+ border-color: #3b82f6;
1558
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
1559
+ }
1560
+
1561
+ button {
1562
+ padding: 12px 20px;
1563
+ border: none;
1564
+ border-radius: 8px;
1565
+ font-size: 14px;
1566
+ font-weight: 600;
1567
+ cursor: pointer;
1568
+ transition: all 0.2s;
1569
+ }
1570
+
1571
+ .btn-primary {
1572
+ background: #3b82f6;
1573
+ color: white;
1574
+ }
1575
+
1576
+ .btn-primary:hover:not(:disabled) {
1577
+ transform: translateY(-1px);
1578
+ }
1579
+
1580
+ .result-card {
1581
+ padding: 18px;
1582
+ background: #f9fafb;
1583
+ border: 2px solid #e5e7eb;
1584
+ border-radius: 8px;
1585
+ font-family: monospace;
1586
+ font-size: 13px;
1587
+ line-height: 1.6;
1588
+ color: #374151;
1589
+ }
1590
+
1591
+ p {
1592
+ margin: 0;
1593
+ font-size: 14px;
1594
+ line-height: 1.6;
1595
+ color: #6b7280;
1596
+ }
1597
+
1598
+ @media (max-width: 768px) {
1599
+ .function-playground {
1600
+ padding: 20px;
1601
+ }
1602
+ }
1603
+ </style>
1604
+ ```
1605
+
1606
+ **开发注意事项:**
1607
+ - ✅ 使用 `../../../src/` 导入实际函数,不要 mock
1608
+ - ✅ 文件末尾不要有多余空行
1609
+ - ✅ 所有输入框添加 `box-sizing: border-box` 和 `min-width: 0`
1610
+ - ✅ 提供实时交互效果
1611
+ - ✅ 遵循统一的设计规范
1612
+ - ✅ 使用语义化的类名
1613
+ - ✅ 添加响应式设计
1614
+ - ✅ 保持视觉一致性
1615
+
1616
+ #### 4. 侧边栏配置
1617
+
1618
+ 在 `docs/.vitepress/config.ts` 中添加菜单项:
1619
+
1620
+ ```typescript
1621
+ {
1622
+ text: '模块名',
1623
+ collapsed: true,
1624
+ items: [
1625
+ { text: 'functionName', link: '/api/category/functionName' },
1626
+ // ... 其他函数
1627
+ ]
1628
+ }
1629
+ ```
1630
+
1631
+ #### 5. 文档检查清单
1632
+
1633
+ 添加新函数后,必须确认:
1634
+
1635
+ - [ ] 函数文档已创建(`docs/api/category/functionName.md`)
1636
+ - [ ] 文档包含所有必需部分(Playground、导入、类型、说明、示例、注意事项)
1637
+ - [ ] Playground 组件已创建(浏览器端函数)
1638
+ - [ ] 组件正确导入实际函数(不是 mock)
1639
+ - [ ] 侧边栏配置已更新
1640
+ - [ ] 运行 `npm run docs:dev` 验证无 404 错误
1641
+ - [ ] 页面可以正常访问和交互
1642
+ - [ ] 组件末尾无多余空行
1643
+
1644
+ #### 6. 常见问题
1645
+
1646
+ **Q: 页面显示 404?**
1647
+ - 检查文件名大小写是否正确
1648
+ - 检查侧边栏配置路径是否正确
1649
+ - 检查 Playground 组件是否有语法错误
1650
+ - 清除缓存并重启开发服务器
1651
+
1652
+ **Q: Playground 不显示?**
1653
+ - 检查组件文件名是否符合命名规范
1654
+ - 检查组件末尾是否有多余空行
1655
+ - 检查是否正确导入实际函数
1656
+
1657
+ **Q: Node.js 端函数需要 Playground 吗?**
1658
+ - 不需要,只需要详细的代码示例即可
433
1659
 
434
1660
  ---
435
1661