zcw-shared 1.19.0 → 1.21.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 +1291 -65
- package/dist/functions/ag-grid/generateLicense.d.ts +5 -1
- package/dist/functions/ag-grid/generateLicense.js +3 -3
- package/dist/functions/ag-grid/generateLicense.js.map +1 -1
- package/dist/functions/android/buildProject.d.ts +9 -8
- package/dist/functions/android/buildProject.js +19 -20
- package/dist/functions/android/buildProject.js.map +1 -1
- package/dist/functions/android/detectAndroidModules.d.ts +7 -1
- package/dist/functions/android/detectAndroidModules.js +7 -7
- package/dist/functions/android/detectAndroidModules.js.map +1 -1
- package/dist/functions/android/modifyGradle.d.ts +10 -1
- package/dist/functions/android/modifyGradle.js +7 -7
- package/dist/functions/android/modifyGradle.js.map +1 -1
- package/dist/functions/android/modifyManifest.d.ts +11 -2
- package/dist/functions/android/modifyManifest.js +4 -4
- package/dist/functions/android/modifyManifest.js.map +1 -1
- package/dist/functions/android/permission.d.ts +15 -5
- package/dist/functions/android/permission.js +8 -8
- package/dist/functions/android/permission.js.map +1 -1
- package/dist/functions/array-object/deepClone.d.ts +12 -0
- package/dist/functions/array-object/deepClone.js +131 -0
- package/dist/functions/array-object/deepClone.js.map +1 -0
- package/dist/functions/array-object/flatten.d.ts +7 -0
- package/dist/functions/array-object/flatten.js +60 -0
- package/dist/functions/array-object/flatten.js.map +1 -0
- package/dist/functions/array-object/unique.d.ts +10 -0
- package/dist/functions/array-object/unique.js +85 -0
- package/dist/functions/array-object/unique.js.map +1 -0
- package/dist/functions/async/createInterruptibleTask.d.ts +37 -0
- package/dist/functions/async/createInterruptibleTask.js +180 -0
- package/dist/functions/async/createInterruptibleTask.js.map +1 -0
- package/dist/functions/color/convertColor.js +1 -1
- package/dist/functions/color/convertColor.js.map +1 -1
- package/dist/functions/data-structures/Heap.d.ts +11 -0
- package/dist/functions/data-structures/Heap.js +91 -0
- package/dist/functions/data-structures/Heap.js.map +1 -0
- package/dist/functions/data-structures/LinkedList.d.ts +18 -0
- package/dist/functions/data-structures/LinkedList.js +135 -0
- package/dist/functions/data-structures/LinkedList.js.map +1 -0
- package/dist/functions/data-structures/PriorityQueue.d.ts +14 -0
- package/dist/functions/data-structures/PriorityQueue.js +77 -0
- package/dist/functions/data-structures/PriorityQueue.js.map +1 -0
- package/dist/functions/data-structures/Queue.d.ts +10 -0
- package/dist/functions/data-structures/Queue.js +27 -0
- package/dist/functions/data-structures/Queue.js.map +1 -0
- package/dist/functions/data-structures/Stack.d.ts +10 -0
- package/dist/functions/data-structures/Stack.js +27 -0
- package/dist/functions/data-structures/Stack.js.map +1 -0
- package/dist/functions/debug/createDebugger.d.ts +14 -3
- package/dist/functions/debug/createDebugger.js +10 -35
- package/dist/functions/debug/createDebugger.js.map +1 -1
- package/dist/functions/design-tokens/buildTokens.d.ts +76 -0
- package/dist/functions/design-tokens/buildTokens.js +183 -0
- package/dist/functions/design-tokens/buildTokens.js.map +1 -0
- package/dist/functions/design-tokens/generateVariables.d.ts +7 -0
- package/dist/functions/design-tokens/generateVariables.js +135 -0
- package/dist/functions/design-tokens/generateVariables.js.map +1 -0
- package/dist/functions/design-tokens/mixColors.d.ts +1 -0
- package/dist/functions/design-tokens/mixColors.js +38 -0
- package/dist/functions/design-tokens/mixColors.js.map +1 -0
- package/dist/functions/design-tokens/parseDesignTokens.d.ts +10 -0
- package/dist/functions/design-tokens/parseDesignTokens.js +216 -0
- package/dist/functions/design-tokens/parseDesignTokens.js.map +1 -0
- package/dist/functions/dom/demonstrateResourceLoading.d.ts +32 -0
- package/dist/functions/dom/demonstrateResourceLoading.js +169 -0
- package/dist/functions/dom/demonstrateResourceLoading.js.map +1 -0
- package/dist/functions/dom/detectOverflow.d.ts +5 -1
- package/dist/functions/dom/detectOverflow.js +2 -2
- package/dist/functions/dom/detectOverflow.js.map +1 -1
- package/dist/functions/dom/getViewportRect.d.ts +5 -1
- package/dist/functions/dom/getViewportRect.js +3 -3
- package/dist/functions/dom/getViewportRect.js.map +1 -1
- package/dist/functions/functional/compose.d.ts +1 -0
- package/dist/functions/functional/compose.js +10 -0
- package/dist/functions/functional/compose.js.map +1 -0
- package/dist/functions/functional/curry.d.ts +1 -0
- package/dist/functions/functional/curry.js +13 -0
- package/dist/functions/functional/curry.js.map +1 -0
- package/dist/functions/functional/pipe.d.ts +1 -0
- package/dist/functions/functional/pipe.js +10 -0
- package/dist/functions/functional/pipe.js.map +1 -0
- package/dist/functions/image/compressToTargetSize.d.ts +8 -1
- package/dist/functions/image/compressToTargetSize.js +11 -8
- package/dist/functions/image/compressToTargetSize.js.map +1 -1
- package/dist/functions/image/generateMacIcons.d.ts +5 -1
- package/dist/functions/image/generateMacIcons.js +4 -4
- package/dist/functions/image/generateMacIcons.js.map +1 -1
- package/dist/functions/image/generateMacTrayIcon.d.ts +4 -1
- package/dist/functions/image/generateMacTrayIcon.js +2 -2
- package/dist/functions/image/generateMacTrayIcon.js.map +1 -1
- package/dist/functions/image/generatePaddedImage.d.ts +4 -1
- package/dist/functions/image/generatePaddedImage.js +3 -3
- package/dist/functions/image/generatePaddedImage.js.map +1 -1
- package/dist/functions/image/generatePwaIcons.d.ts +5 -1
- package/dist/functions/image/generatePwaIcons.js +4 -4
- package/dist/functions/image/generatePwaIcons.js.map +1 -1
- package/dist/functions/image/generateRoundedImage.d.ts +5 -1
- package/dist/functions/image/generateRoundedImage.js +4 -4
- package/dist/functions/image/generateRoundedImage.js.map +1 -1
- package/dist/functions/image/getImageDimensions.d.ts +5 -1
- package/dist/functions/image/getImageDimensions.js +3 -3
- package/dist/functions/image/getImageDimensions.js.map +1 -1
- package/dist/functions/ipc/dispatchIpcRequest.d.ts +4 -1
- package/dist/functions/ipc/dispatchIpcRequest.js +3 -3
- package/dist/functions/ipc/dispatchIpcRequest.js.map +1 -1
- package/dist/functions/performance/debounce.d.ts +5 -0
- package/dist/functions/performance/debounce.js +12 -0
- package/dist/functions/performance/debounce.js.map +1 -0
- package/dist/functions/performance/memoize.d.ts +1 -0
- package/dist/functions/performance/memoize.js +13 -0
- package/dist/functions/performance/memoize.js.map +1 -0
- package/dist/functions/performance/throttle.d.ts +1 -0
- package/dist/functions/performance/throttle.js +11 -0
- package/dist/functions/performance/throttle.js.map +1 -0
- package/dist/functions/platform/tencent-cloud/deploy.tcb.d.ts +13 -0
- package/dist/functions/platform/tencent-cloud/deploy.tcb.js +46 -0
- package/dist/functions/platform/tencent-cloud/deploy.tcb.js.map +1 -0
- package/dist/functions/platform/tencent-cloud/getSecret.d.ts +4 -0
- package/dist/functions/platform/tencent-cloud/getSecret.js +19 -0
- package/dist/functions/platform/tencent-cloud/getSecret.js.map +1 -0
- package/dist/functions/platform/uniapp/app-plus/buildAndroidApp.d.ts +27 -0
- package/dist/functions/platform/uniapp/app-plus/buildAndroidApp.js +287 -0
- package/dist/functions/platform/uniapp/app-plus/buildAndroidApp.js.map +1 -0
- package/dist/functions/platform/uniapp/build.d.ts +21 -0
- package/dist/functions/platform/uniapp/build.js +83 -0
- package/dist/functions/platform/uniapp/build.js.map +1 -0
- package/dist/functions/platform/uniapp/detectAndroidProjectStructure.d.ts +11 -0
- package/dist/functions/platform/uniapp/detectAndroidProjectStructure.js +30 -0
- package/dist/functions/platform/uniapp/detectAndroidProjectStructure.js.map +1 -0
- package/dist/functions/platform/uniapp/detectProjectType.d.ts +20 -0
- package/dist/functions/platform/uniapp/detectProjectType.js +68 -0
- package/dist/functions/platform/uniapp/detectProjectType.js.map +1 -0
- package/dist/functions/platform/uniapp/parseManifest.d.ts +18 -0
- package/dist/functions/platform/uniapp/parseManifest.js +49 -0
- package/dist/functions/platform/uniapp/parseManifest.js.map +1 -0
- package/dist/functions/platform/uniapp/waitForPages.d.ts +7 -0
- package/dist/functions/platform/uniapp/waitForPages.js +20 -0
- package/dist/functions/platform/uniapp/waitForPages.js.map +1 -0
- package/dist/functions/principles/functionBind.d.ts +4 -0
- package/dist/functions/principles/functionBind.js +33 -0
- package/dist/functions/principles/functionBind.js.map +1 -0
- package/dist/functions/principles/myInstanceof.d.ts +5 -0
- package/dist/functions/principles/myInstanceof.js +56 -0
- package/dist/functions/principles/myInstanceof.js.map +1 -0
- package/dist/functions/principles/myNew.d.ts +3 -0
- package/dist/functions/principles/myNew.js +19 -0
- package/dist/functions/principles/myNew.js.map +1 -0
- package/dist/functions/software/findSoftware.d.ts +2 -2
- package/dist/functions/software/findSoftware.js +1 -1
- package/dist/functions/software/findSoftware.js.map +1 -1
- package/dist/functions/string/base64.d.ts +4 -1
- package/dist/functions/string/base64.js +2 -2
- package/dist/functions/string/base64.js.map +1 -1
- package/dist/functions/tencent-cloud/deploy.tcb.d.ts +12 -2
- package/dist/functions/tencent-cloud/deploy.tcb.js +7 -8
- package/dist/functions/tencent-cloud/deploy.tcb.js.map +1 -1
- package/dist/functions/uniapp/app-plus/buildAndroidApp.d.ts +27 -2
- package/dist/functions/uniapp/app-plus/buildAndroidApp.js +71 -29
- package/dist/functions/uniapp/app-plus/buildAndroidApp.js.map +1 -1
- package/dist/functions/uniapp/build.d.ts +9 -8
- package/dist/functions/uniapp/build.js +8 -9
- package/dist/functions/uniapp/build.js.map +1 -1
- package/dist/functions/uniapp/detectAndroidProjectStructure.d.ts +5 -1
- package/dist/functions/uniapp/detectAndroidProjectStructure.js +5 -5
- package/dist/functions/uniapp/detectAndroidProjectStructure.js.map +1 -1
- package/dist/functions/uniapp/detectProjectType.d.ts +8 -4
- package/dist/functions/uniapp/detectProjectType.js +20 -20
- package/dist/functions/uniapp/detectProjectType.js.map +1 -1
- package/dist/functions/uniapp/parseManifest.d.ts +7 -1
- package/dist/functions/uniapp/parseManifest.js +7 -4
- package/dist/functions/uniapp/parseManifest.js.map +1 -1
- package/dist/functions/uniapp/waitForPages.d.ts +6 -2
- package/dist/functions/uniapp/waitForPages.js +3 -3
- package/dist/functions/uniapp/waitForPages.js.map +1 -1
- package/dist/functions/utils/AVLTree.d.ts +19 -0
- package/dist/functions/utils/AVLTree.js +197 -0
- package/dist/functions/utils/AVLTree.js.map +1 -0
- package/dist/functions/utils/BinarySearchTree.d.ts +19 -0
- package/dist/functions/utils/BinarySearchTree.js +150 -0
- package/dist/functions/utils/BinarySearchTree.js.map +1 -0
- package/dist/functions/utils/EventEmitter.d.ts +32 -0
- package/dist/functions/utils/EventEmitter.js +108 -0
- package/dist/functions/utils/EventEmitter.js.map +1 -0
- package/dist/functions/utils/Graph.d.ts +19 -0
- package/dist/functions/utils/Graph.js +190 -0
- package/dist/functions/utils/Graph.js.map +1 -0
- package/dist/functions/utils/HashMap.d.ts +13 -0
- package/dist/functions/utils/HashMap.js +128 -0
- package/dist/functions/utils/HashMap.js.map +1 -0
- package/dist/functions/utils/Heap.d.ts +11 -0
- package/dist/functions/utils/Heap.js +91 -0
- package/dist/functions/utils/Heap.js.map +1 -0
- package/dist/functions/utils/LRUCache.d.ts +41 -0
- package/dist/functions/utils/LRUCache.js +182 -0
- package/dist/functions/utils/LRUCache.js.map +1 -0
- package/dist/functions/utils/LinkedList.d.ts +18 -0
- package/dist/functions/utils/LinkedList.js +135 -0
- package/dist/functions/utils/LinkedList.js.map +1 -0
- package/dist/functions/utils/MyPromise.d.ts +32 -0
- package/dist/functions/utils/MyPromise.js +254 -0
- package/dist/functions/utils/MyPromise.js.map +1 -0
- package/dist/functions/utils/PriorityQueue.d.ts +14 -0
- package/dist/functions/utils/PriorityQueue.js +77 -0
- package/dist/functions/utils/PriorityQueue.js.map +1 -0
- package/dist/functions/utils/Queue.d.ts +10 -0
- package/dist/functions/utils/Queue.js +27 -0
- package/dist/functions/utils/Queue.js.map +1 -0
- package/dist/functions/utils/Stack.d.ts +10 -0
- package/dist/functions/utils/Stack.js +27 -0
- package/dist/functions/utils/Stack.js.map +1 -0
- package/dist/functions/utils/Trie.d.ts +16 -0
- package/dist/functions/utils/Trie.js +127 -0
- package/dist/functions/utils/Trie.js.map +1 -0
- package/dist/functions/utils/UnionFind.d.ts +8 -0
- package/dist/functions/utils/UnionFind.js +53 -0
- package/dist/functions/utils/UnionFind.js.map +1 -0
- package/dist/functions/utils/createI18n.d.ts +2 -0
- package/dist/functions/utils/createI18n.js +97 -0
- package/dist/functions/utils/createI18n.js.map +1 -0
- package/dist/functions/utils/createReactive.d.ts +10 -0
- package/dist/functions/utils/createReactive.js +50 -0
- package/dist/functions/utils/createReactive.js.map +1 -0
- package/dist/functions/utils/curryAdvanced.d.ts +8 -0
- package/dist/functions/utils/curryAdvanced.js +87 -0
- package/dist/functions/utils/curryAdvanced.js.map +1 -0
- package/dist/functions/utils/debounce.d.ts +5 -1
- package/dist/functions/utils/debounce.js +3 -4
- package/dist/functions/utils/debounce.js.map +1 -1
- package/dist/functions/utils/deepClone.d.ts +12 -0
- package/dist/functions/utils/deepClone.js +131 -0
- package/dist/functions/utils/deepClone.js.map +1 -0
- package/dist/functions/utils/diff.d.ts +25 -0
- package/dist/functions/utils/diff.js +316 -0
- package/dist/functions/utils/diff.js.map +1 -0
- package/dist/functions/utils/flatten.d.ts +7 -0
- package/dist/functions/utils/flatten.js +60 -0
- package/dist/functions/utils/flatten.js.map +1 -0
- package/dist/functions/utils/flattenObject.d.ts +5 -0
- package/dist/functions/utils/flattenObject.js +102 -0
- package/dist/functions/utils/flattenObject.js.map +1 -0
- package/dist/functions/utils/formatString.d.ts +5 -0
- package/dist/functions/utils/formatString.js +9 -0
- package/dist/functions/utils/formatString.js.map +1 -0
- package/dist/functions/utils/functionBind.d.ts +4 -0
- package/dist/functions/utils/functionBind.js +33 -0
- package/dist/functions/utils/functionBind.js.map +1 -0
- package/dist/functions/utils/generateExports.d.ts +16 -6
- package/dist/functions/utils/generateExports.js +11 -11
- package/dist/functions/utils/generateExports.js.map +1 -1
- package/dist/functions/utils/generatorUtils.d.ts +16 -0
- package/dist/functions/utils/generatorUtils.js +139 -0
- package/dist/functions/utils/generatorUtils.js.map +1 -0
- package/dist/functions/utils/i18n.d.ts +27 -0
- package/dist/functions/utils/i18n.js +119 -0
- package/dist/functions/utils/i18n.js.map +1 -0
- package/dist/functions/utils/myInstanceof.d.ts +5 -0
- package/dist/functions/utils/myInstanceof.js +56 -0
- package/dist/functions/utils/myInstanceof.js.map +1 -0
- package/dist/functions/utils/myNew.d.ts +3 -0
- package/dist/functions/utils/myNew.js +19 -0
- package/dist/functions/utils/myNew.js.map +1 -0
- package/dist/functions/utils/permission.d.ts +40 -0
- package/dist/functions/utils/permission.js +189 -0
- package/dist/functions/utils/permission.js.map +1 -0
- package/dist/functions/utils/pinia.d.ts +52 -0
- package/dist/functions/utils/pinia.js +183 -0
- package/dist/functions/utils/pinia.js.map +1 -0
- package/dist/functions/utils/promiseLimit.d.ts +10 -0
- package/dist/functions/utils/promiseLimit.js +125 -0
- package/dist/functions/utils/promiseLimit.js.map +1 -0
- package/dist/functions/utils/retryWithBackoff.d.ts +4 -1
- package/dist/functions/utils/retryWithBackoff.js +2 -3
- package/dist/functions/utils/retryWithBackoff.js.map +1 -1
- package/dist/functions/utils/unique.d.ts +10 -0
- package/dist/functions/utils/unique.js +85 -0
- package/dist/functions/utils/unique.js.map +1 -0
- package/dist/functions/utils/validate.d.ts +4 -1
- package/dist/functions/utils/validate.js +2 -3
- package/dist/functions/utils/validate.js.map +1 -1
- package/dist/functions/utils/walk.d.ts +8 -2
- package/dist/functions/utils/walk.js +9 -10
- package/dist/functions/utils/walk.js.map +1 -1
- package/dist/functions/vue/dynamicMount.d.ts +3 -2
- package/dist/functions/vue/dynamicMount.js +6 -6
- package/dist/functions/vue/dynamicMount.js.map +1 -1
- package/dist/functions/wechat/miniapp/downloadFile.d.ts +5 -1
- package/dist/functions/wechat/miniapp/downloadFile.js +3 -3
- package/dist/functions/wechat/miniapp/downloadFile.js.map +1 -1
- package/dist/functions/xml/modifyXml.d.ts +9 -2
- package/dist/functions/xml/modifyXml.js +4 -4
- package/dist/functions/xml/modifyXml.js.map +1 -1
- package/dist/hooks/createGlobalState.d.ts +2 -0
- package/dist/hooks/createGlobalState.js +11 -0
- package/dist/hooks/createGlobalState.js.map +1 -0
- package/dist/hooks/createInjectionState.d.ts +14 -0
- package/dist/hooks/createInjectionState.js +20 -0
- package/dist/hooks/createInjectionState.js.map +1 -0
- package/dist/hooks/createSharedComposable.d.ts +2 -0
- package/dist/hooks/createSharedComposable.js +13 -0
- package/dist/hooks/createSharedComposable.js.map +1 -0
- package/dist/hooks/injectLocal.d.ts +10 -0
- package/dist/hooks/injectLocal.js +12 -0
- package/dist/hooks/injectLocal.js.map +1 -0
- package/dist/hooks/provideLocal.d.ts +9 -0
- package/dist/hooks/provideLocal.js +7 -0
- package/dist/hooks/provideLocal.js.map +1 -0
- package/dist/hooks/useAltool.d.ts +1 -1
- package/dist/hooks/useAltool.js +13 -13
- package/dist/hooks/useAltool.js.map +1 -1
- package/dist/hooks/useAsyncState.d.ts +30 -0
- package/dist/hooks/useAsyncState.js +46 -0
- package/dist/hooks/useAsyncState.js.map +1 -0
- package/dist/hooks/useDebouncedRefHistory.d.ts +22 -0
- package/dist/hooks/useDebouncedRefHistory.js +46 -0
- package/dist/hooks/useDebouncedRefHistory.js.map +1 -0
- package/dist/hooks/useDraggable.d.ts +14 -11
- package/dist/hooks/useDraggable.js +60 -80
- package/dist/hooks/useDraggable.js.map +1 -1
- package/dist/hooks/useLocalStorage.d.ts +5 -1
- package/dist/hooks/useLocalStorage.js +5 -4
- package/dist/hooks/useLocalStorage.js.map +1 -1
- package/dist/hooks/useManualRefHistory.d.ts +26 -0
- package/dist/hooks/useManualRefHistory.js +80 -0
- package/dist/hooks/useManualRefHistory.js.map +1 -0
- package/dist/hooks/usePermission.d.ts +7 -0
- package/dist/hooks/usePermission.js +123 -0
- package/dist/hooks/usePermission.js.map +1 -0
- package/dist/hooks/useRefHistory.d.ts +21 -0
- package/dist/hooks/useRefHistory.js +41 -0
- package/dist/hooks/useRefHistory.js.map +1 -0
- package/dist/hooks/useResizable.d.ts +14 -8
- package/dist/hooks/useResizable.js +40 -31
- package/dist/hooks/useResizable.js.map +1 -1
- package/dist/hooks/useSessionStorage.d.ts +5 -1
- package/dist/hooks/useSessionStorage.js +5 -4
- package/dist/hooks/useSessionStorage.js.map +1 -1
- package/dist/hooks/useStorage.d.ts +4 -1
- package/dist/hooks/useStorage.js +4 -4
- package/dist/hooks/useStorage.js.map +1 -1
- package/dist/hooks/useStorageWithIndexedDB.d.ts +5 -1
- package/dist/hooks/useStorageWithIndexedDB.js +24 -11
- package/dist/hooks/useStorageWithIndexedDB.js.map +1 -1
- package/dist/hooks/useWebWorker.d.ts +13 -13
- package/dist/hooks/useWebWorker.js +15 -17
- package/dist/hooks/useWebWorker.js.map +1 -1
- package/dist/hooks/useWorkerFunction.d.ts +15 -11
- package/dist/hooks/useWorkerFunction.js +16 -16
- package/dist/hooks/useWorkerFunction.js.map +1 -1
- package/dist/hooks/useWorkerPool.d.ts +15 -12
- package/dist/hooks/useWorkerPool.js +18 -13
- package/dist/hooks/useWorkerPool.js.map +1 -1
- package/package.json +50 -3
- package/references/browser.d.ts +28 -2
- package/references/dom.d.ts +45 -0
- package/references/indexeddb.d.ts +1 -0
- package/references/node.d.ts +42 -7
- package/references/vue.d.ts +161 -5
- package/references/xlsx.d.ts +51 -0
- package/types/android-build.d.ts +0 -22
- package/types/reactive.d.ts +67 -0
- package/types/tencent-cloud.d.ts +1 -9
- 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
|
-
// ❌
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
74
|
-
|
|
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
|
-
|
|
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
|
|
115
|
-
|
|
359
|
+
import fs from 'fs'
|
|
360
|
+
import path from 'path'
|
|
361
|
+
import { buildProject } from 'shared/functions/android/buildProject'
|
|
116
362
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
//
|
|
123
|
-
import {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
|
529
|
+
// 创建模拟的依赖函数
|
|
530
|
+
const mockDeps = {
|
|
264
531
|
existsSync: (path: string) => path.includes('build.gradle'),
|
|
265
532
|
readFileSync: (path: string) => 'mock file content',
|
|
266
|
-
|
|
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(
|
|
277
|
-
|
|
278
|
-
|
|
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.
|
|
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.
|
|
352
|
-
docs/api/category.md
|
|
353
|
-
|
|
612
|
+
# 4. 创建函数文档(必须!)
|
|
613
|
+
docs/api/category/newFunction.md
|
|
614
|
+
|
|
615
|
+
# 5. 创建 Playground 组件(如果是浏览器端函数)
|
|
616
|
+
docs/.vitepress/components/NewFunctionPlayground.vue
|
|
354
617
|
|
|
355
|
-
#
|
|
618
|
+
# 6. 更新侧边栏配置
|
|
619
|
+
docs/.vitepress/config.ts
|
|
620
|
+
|
|
621
|
+
# 7. 验证文档编译
|
|
356
622
|
npm run docs:dev
|
|
357
623
|
|
|
358
|
-
#
|
|
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 {
|
|
367
|
-
import type {
|
|
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:
|
|
378
|
-
deps:
|
|
379
|
-
):
|
|
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
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
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
|
|