@moluoxixi/create-app 2.0.436 → 2.0.437
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/index.d.ts +5 -0
- package/dist/constants/index.js +8 -0
- package/dist/core/feature.d.ts +26 -20
- package/dist/core/feature.js +47 -52
- package/dist/core/prompts.js +6 -3
- package/dist/core/template.js +1 -1
- package/dist/generators/project.js +8 -0
- package/dist/types/packageJson.d.ts +2 -0
- package/dist/utils/deepMerge.d.ts +1 -1
- package/dist/utils/file.js +6 -2
- package/dist/utils/framework.d.ts +11 -0
- package/dist/utils/framework.js +13 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +4 -5
- package/templates/common/base/_npmrc +2 -0
- package/templates/common/base/_yarnrc.yml +3 -0
- package/templates/common/base/node_modules/.bin/parser +4 -4
- package/templates/common/base/node_modules/.bin/rollup +4 -4
- package/templates/common/base/node_modules/.bin/sass +2 -2
- package/templates/common/base/node_modules/.bin/terser +4 -4
- package/templates/common/base/node_modules/.bin/vite +2 -2
- package/templates/common/base/package.json +2 -4
- package/templates/common/base/scripts/build.mts +15 -10
- package/templates/common/base/src/apis/request.ts +23 -32
- package/templates/common/base/src/apis/services/example.ts +2 -2
- package/templates/common/base/src/apis/services/user.ts +2 -2
- package/templates/common/base/tsconfig.app.json +25 -0
- package/templates/common/base/tsconfig.base.json +17 -0
- package/templates/common/base/tsconfig.json +11 -0
- package/templates/common/base/tsconfig.node.json +14 -0
- package/templates/common/base/vite.config.ts +5 -2
- package/templates/common/features/eslint/node_modules/.bin/sass +17 -0
- package/templates/common/features/eslint/node_modules/.bin/terser +17 -0
- package/templates/common/features/eslint/node_modules/.bin/tsx +17 -0
- package/templates/common/features/eslint/node_modules/.bin/vitest +17 -0
- package/templates/common/features/eslint/node_modules/.bin/yaml +17 -0
- package/templates/common/features/eslint/tsconfig.base.json +17 -0
- package/templates/common/features/eslint/tsconfig.json +8 -0
- package/templates/common/features/eslint/tsconfig.node.json +13 -0
- package/templates/common/features/husky/.husky/pre-commit +1 -1
- package/templates/common/features/husky/node_modules/.bin/commitizen +2 -2
- package/templates/common/features/husky/node_modules/.bin/commitlint +2 -2
- package/templates/common/features/husky/node_modules/.bin/cz +2 -2
- package/templates/common/features/husky/node_modules/.bin/git-cz +2 -2
- package/templates/common/features/husky/tsconfig.base.json +17 -0
- package/templates/common/features/husky/tsconfig.json +8 -0
- package/templates/common/features/husky/tsconfig.node.json +13 -0
- package/templates/react/base/node_modules/.bin/sass +4 -4
- package/templates/react/base/node_modules/.bin/terser +4 -4
- package/templates/react/base/node_modules/.bin/vite +4 -4
- package/templates/react/base/package.json +2 -1
- package/templates/react/base/src/main.tsx +1 -1
- package/templates/react/base/src/router/index.tsx +26 -0
- package/templates/react/base/src/utils/common.ts +126 -0
- package/templates/react/base/src/utils/index.ts +7 -0
- package/templates/react/base/tsconfig.app.json +13 -5
- package/templates/react/base/tsconfig.node.json +6 -7
- package/templates/react/features/ant-design/tsconfig.app.json +25 -0
- package/templates/react/features/ant-design/tsconfig.base.json +22 -0
- package/templates/react/features/ant-design/tsconfig.json +11 -0
- package/templates/react/features/ant-design/tsconfig.node.json +14 -0
- package/templates/react/features/i18n/tsconfig.app.json +25 -0
- package/templates/react/features/i18n/tsconfig.base.json +22 -0
- package/templates/react/features/i18n/tsconfig.json +11 -0
- package/templates/react/features/i18n/tsconfig.node.json +14 -0
- package/templates/react/features/manualRoutes/tsconfig.app.json +25 -0
- package/templates/react/features/manualRoutes/tsconfig.base.json +26 -0
- package/templates/react/features/manualRoutes/tsconfig.json +11 -0
- package/templates/react/features/manualRoutes/tsconfig.node.json +14 -0
- package/templates/react/features/pageRoutes/tsconfig.app.json +25 -0
- package/templates/react/features/pageRoutes/tsconfig.base.json +26 -0
- package/templates/react/features/pageRoutes/tsconfig.json +11 -0
- package/templates/react/features/pageRoutes/tsconfig.node.json +14 -0
- package/templates/react/features/sentry/tsconfig.app.json +25 -0
- package/templates/react/features/sentry/tsconfig.base.json +22 -0
- package/templates/react/features/sentry/tsconfig.json +11 -0
- package/templates/react/features/sentry/tsconfig.node.json +14 -0
- package/templates/react/features/zustand/tsconfig.app.json +25 -0
- package/templates/react/features/zustand/tsconfig.base.json +26 -0
- package/templates/react/features/zustand/tsconfig.json +11 -0
- package/templates/react/features/zustand/tsconfig.node.json +14 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/sass +4 -4
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/terser +4 -4
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/vite +2 -2
- package/templates/react/micro-frontends/qiankun/base/package.json +1 -1
- package/templates/react/micro-frontends/qiankun/base/src/main.tsx +3 -3
- package/templates/react/micro-frontends/qiankun/base/tsconfig.app.json +25 -0
- package/templates/react/micro-frontends/qiankun/base/tsconfig.base.json +26 -0
- package/templates/react/micro-frontends/qiankun/base/tsconfig.json +11 -0
- package/templates/react/micro-frontends/qiankun/base/tsconfig.node.json +14 -0
- package/templates/vue/base/node_modules/.bin/vue-tsc +2 -2
- package/templates/vue/base/package.json +3 -2
- package/templates/vue/base/src/assets/fonts/index.css +6 -0
- package/templates/vue/base/src/assets/styles/base.scss +33 -0
- package/templates/vue/base/src/assets/styles/custom.scss +20 -0
- package/templates/vue/base/src/assets/styles/main.scss +8 -0
- package/templates/vue/base/src/assets/styles/tailwind.scss +3 -0
- package/templates/vue/base/src/main.ts +3 -3
- package/templates/vue/base/src/router/index.ts +25 -0
- package/templates/vue/base/src/utils/common.ts +126 -0
- package/templates/vue/base/src/utils/index.ts +4 -0
- package/templates/vue/base/tsconfig.app.json +10 -3
- package/templates/vue/base/tsconfig.base.json +2 -6
- package/templates/vue/base/tsconfig.json +1 -0
- package/templates/vue/base/tsconfig.node.json +1 -2
- package/templates/vue/features/ant-design-vue/tsconfig.app.json +33 -0
- package/templates/vue/features/ant-design-vue/tsconfig.base.json +25 -0
- package/templates/vue/features/ant-design-vue/tsconfig.json +12 -0
- package/templates/vue/features/ant-design-vue/tsconfig.node.json +14 -0
- package/templates/vue/features/element-plus/package.json +3 -0
- package/templates/vue/features/element-plus/src/assets/styles/main.scss +0 -1
- package/templates/vue/features/element-plus/src/layouts/element.vue +1 -1
- package/templates/vue/features/element-plus/src/stores/modules/system.ts +1 -1
- package/templates/vue/features/element-plus/tsconfig.app.json +33 -0
- package/templates/vue/features/element-plus/tsconfig.base.json +25 -0
- package/templates/vue/features/element-plus/tsconfig.json +12 -0
- package/templates/vue/features/element-plus/tsconfig.node.json +14 -0
- package/templates/vue/features/i18n/tsconfig.app.json +33 -0
- package/templates/vue/features/i18n/tsconfig.base.json +25 -0
- package/templates/vue/features/i18n/tsconfig.json +12 -0
- package/templates/vue/features/i18n/tsconfig.node.json +14 -0
- package/templates/vue/features/manualRoutes/package.json +2 -1
- package/templates/vue/features/manualRoutes/src/layouts/index.ts +26 -0
- package/templates/vue/features/manualRoutes/src/router/index.ts +1 -1
- package/templates/vue/features/manualRoutes/src/stores/modules/system.ts +1 -1
- package/templates/vue/features/manualRoutes/tsconfig.app.json +33 -0
- package/templates/vue/features/manualRoutes/tsconfig.base.json +25 -0
- package/templates/vue/features/manualRoutes/tsconfig.json +12 -0
- package/templates/vue/features/manualRoutes/tsconfig.node.json +14 -0
- package/templates/vue/features/pageRoutes/package.json +2 -1
- package/templates/vue/features/pageRoutes/src/layouts/index.ts +26 -0
- package/templates/vue/features/pageRoutes/src/stores/modules/system.ts +1 -1
- package/templates/vue/features/pageRoutes/tsconfig.app.json +33 -0
- package/templates/vue/features/pageRoutes/tsconfig.base.json +25 -0
- package/templates/vue/features/pageRoutes/tsconfig.json +12 -0
- package/templates/vue/features/pageRoutes/tsconfig.node.json +14 -0
- package/templates/vue/features/pinia/package.json +3 -0
- package/templates/vue/features/pinia/src/stores/modules/system.ts +1 -1
- package/templates/vue/features/pinia/tsconfig.app.json +33 -0
- package/templates/vue/features/pinia/tsconfig.base.json +25 -0
- package/templates/vue/features/pinia/tsconfig.json +12 -0
- package/templates/vue/features/pinia/tsconfig.node.json +14 -0
- package/templates/vue/features/sentry/tsconfig.app.json +33 -0
- package/templates/vue/features/sentry/tsconfig.base.json +25 -0
- package/templates/vue/features/sentry/tsconfig.json +12 -0
- package/templates/vue/features/sentry/tsconfig.node.json +14 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/jiti +2 -2
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/sass +4 -4
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/terser +4 -4
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/vite +2 -2
- package/templates/vue/micro-frontends/qiankun/base/package.json +5 -1
- package/templates/vue/micro-frontends/qiankun/base/src/App.vue +13 -0
- package/templates/vue/micro-frontends/qiankun/base/src/assets/fonts/index.css +6 -0
- package/templates/vue/micro-frontends/qiankun/base/src/assets/styles/base.scss +33 -0
- package/templates/vue/micro-frontends/qiankun/base/src/assets/styles/custom.scss +20 -0
- package/templates/vue/micro-frontends/qiankun/base/src/assets/styles/main.scss +8 -0
- package/templates/vue/micro-frontends/qiankun/base/src/assets/styles/tailwind.scss +3 -0
- package/templates/vue/micro-frontends/qiankun/base/src/directives/index.ts +36 -0
- package/templates/vue/micro-frontends/qiankun/base/src/main.ts +5 -5
- package/templates/vue/micro-frontends/qiankun/base/src/router/index.ts +27 -0
- package/templates/vue/micro-frontends/qiankun/base/src/stores/index.ts +8 -0
- package/templates/vue/micro-frontends/qiankun/base/tsconfig.app.json +33 -0
- package/templates/vue/micro-frontends/qiankun/base/tsconfig.base.json +25 -0
- package/templates/vue/micro-frontends/qiankun/base/tsconfig.json +12 -0
- package/templates/vue/micro-frontends/qiankun/base/tsconfig.node.json +14 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/sass +4 -4
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/terser +4 -4
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/vite +4 -4
- package/templates/vue/micro-frontends/qiankun/features/element-plus/package.json +3 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/src/assets/styles/main.scss +0 -1
- package/templates/vue/micro-frontends/qiankun/features/element-plus/src/stores/modules/system.ts +1 -1
- package/templates/vue/micro-frontends/qiankun/features/element-plus/tsconfig.app.json +33 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/tsconfig.base.json +25 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/tsconfig.json +12 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/tsconfig.node.json +14 -0
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/sass +4 -4
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/terser +4 -4
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/vite +4 -4
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/package.json +2 -1
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/src/layouts/index.ts +26 -0
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/src/stores/modules/system.ts +1 -1
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/tsconfig.app.json +33 -0
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/tsconfig.base.json +25 -0
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/tsconfig.json +12 -0
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/tsconfig.node.json +14 -0
- package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/sass +4 -4
- package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/terser +4 -4
- package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/vite +4 -4
- package/templates/vue/micro-frontends/qiankun/features/pageRoutes/package.json +2 -1
- package/templates/vue/micro-frontends/qiankun/features/pageRoutes/src/stores/modules/system.ts +1 -1
- package/templates/vue/micro-frontends/qiankun/features/pageRoutes/tsconfig.app.json +33 -0
- package/templates/vue/micro-frontends/qiankun/features/pageRoutes/tsconfig.base.json +25 -0
- package/templates/vue/micro-frontends/qiankun/features/pageRoutes/tsconfig.json +12 -0
- package/templates/vue/micro-frontends/qiankun/features/pageRoutes/tsconfig.node.json +14 -0
- package/dist/test.d.ts +0 -5
- package/dist/test.js +0 -508
- package/templates/common/base/src/utils/index.ts +0 -87
- /package/templates/vue/features/element-plus/src/assets/styles/{element.scss → element/index.scss} +0 -0
package/dist/test.js
DELETED
|
@@ -1,508 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 测试脚本
|
|
3
|
-
* 通过文件系统扫描自动生成所有测试用例组合
|
|
4
|
-
*/
|
|
5
|
-
import path from 'node:path';
|
|
6
|
-
import process from 'node:process';
|
|
7
|
-
import { fileURLToPath } from 'node:url';
|
|
8
|
-
import chalk from 'chalk';
|
|
9
|
-
import fs from 'fs-extra';
|
|
10
|
-
import { FILE_CONSTANTS, FRAMEWORKS, MICRO_FRONTEND_ENGINES, PACKAGE_MANAGERS, ROUTE_MODES, UI_LIBRARIES, } from "./constants/index.js";
|
|
11
|
-
import { featureToConfig, getRouteModeFeatures, scanAllFeatures } from "./core/feature.js";
|
|
12
|
-
import { generateProject } from "./generators/index.js";
|
|
13
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
-
const __dirname = path.dirname(__filename);
|
|
15
|
-
/** 测试输出目录 */
|
|
16
|
-
const TEST_OUTPUT_DIR = path.resolve(__dirname, '../test');
|
|
17
|
-
/**
|
|
18
|
-
* 测试配置
|
|
19
|
-
* 集中管理测试选项,方便随时调整
|
|
20
|
-
*/
|
|
21
|
-
const TEST_CONFIG = {
|
|
22
|
-
/** 是否使用 minimal 模式(只生成全量和最小配置) */
|
|
23
|
-
minimal: false,
|
|
24
|
-
/** 固定默认值(不参与组合测试) */
|
|
25
|
-
defaults: {
|
|
26
|
-
/** 项目名称(会自动生成,此处为描述) */
|
|
27
|
-
projectName: 'auto-generated',
|
|
28
|
-
/** 项目描述 */
|
|
29
|
-
description: 'A Vite project',
|
|
30
|
-
/** 作者 */
|
|
31
|
-
author: 'test',
|
|
32
|
-
/** 是否启用国际化 */
|
|
33
|
-
i18n: true,
|
|
34
|
-
/** 是否启用错误监控 */
|
|
35
|
-
sentry: false,
|
|
36
|
-
/** 是否启用 ESLint */
|
|
37
|
-
eslint: true,
|
|
38
|
-
/** 是否启用 Git Hooks */
|
|
39
|
-
husky: true,
|
|
40
|
-
},
|
|
41
|
-
/** 参与组合测试的选项 */
|
|
42
|
-
combinations: {
|
|
43
|
-
/** 框架列表(使用常量) */
|
|
44
|
-
frameworks: FRAMEWORKS,
|
|
45
|
-
/** UI 库配置(直接使用 UI_LIBRARIES) */
|
|
46
|
-
uiLibraries: {
|
|
47
|
-
vue: UI_LIBRARIES.vue,
|
|
48
|
-
react: UI_LIBRARIES.react,
|
|
49
|
-
},
|
|
50
|
-
/** 路由模式列表(空数组表示不启用) */
|
|
51
|
-
routeModes: ROUTE_MODES,
|
|
52
|
-
/** 微前端引擎列表(直接使用常量) */
|
|
53
|
-
microFrontendEngines: MICRO_FRONTEND_ENGINES,
|
|
54
|
-
/** 包管理器列表(直接使用常量) */
|
|
55
|
-
packageManagers: PACKAGE_MANAGERS,
|
|
56
|
-
/** 是否测试 i18n 的组合 */
|
|
57
|
-
i18n: false,
|
|
58
|
-
/** 是否测试 sentry 的组合 */
|
|
59
|
-
sentry: false,
|
|
60
|
-
/** 是否测试 eslint 的组合 */
|
|
61
|
-
eslint: false,
|
|
62
|
-
/** 是否测试 husky 的组合 */
|
|
63
|
-
husky: false,
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* 生成所有可能的组合(包括全开、全关)
|
|
68
|
-
*/
|
|
69
|
-
function generateAllCombinations(items) {
|
|
70
|
-
const n = items.length;
|
|
71
|
-
const combinations = [];
|
|
72
|
-
// 生成 2^n 种组合
|
|
73
|
-
for (let i = 0; i < 2 ** n; i++) {
|
|
74
|
-
const combination = [];
|
|
75
|
-
for (let j = 0; j < n; j++) {
|
|
76
|
-
combination.push((i & (1 << j)) !== 0);
|
|
77
|
-
}
|
|
78
|
-
combinations.push(combination);
|
|
79
|
-
}
|
|
80
|
-
return combinations;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* 自动生成测试用例配置(基于组合算法)
|
|
84
|
-
*/
|
|
85
|
-
function generateTestConfigs() {
|
|
86
|
-
const configs = [];
|
|
87
|
-
// 框架列表(空数组表示不启用)
|
|
88
|
-
const frameworks = TEST_CONFIG.combinations.frameworks.length > 0
|
|
89
|
-
? TEST_CONFIG.combinations.frameworks
|
|
90
|
-
: [];
|
|
91
|
-
if (frameworks.length === 0) {
|
|
92
|
-
return configs;
|
|
93
|
-
}
|
|
94
|
-
for (const framework of frameworks) {
|
|
95
|
-
const allFeatures = scanAllFeatures(framework);
|
|
96
|
-
// 分离不同类型的 features
|
|
97
|
-
const uiLibraries = [];
|
|
98
|
-
const routeModes = [];
|
|
99
|
-
const booleanFeatures = [];
|
|
100
|
-
for (const feature of allFeatures) {
|
|
101
|
-
const config = featureToConfig(feature, framework);
|
|
102
|
-
if (!config)
|
|
103
|
-
continue;
|
|
104
|
-
if (config.key === 'uiLibrary') {
|
|
105
|
-
uiLibraries.push(feature);
|
|
106
|
-
}
|
|
107
|
-
else if (config.key === 'routeMode') {
|
|
108
|
-
routeModes.push(feature);
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
booleanFeatures.push(feature);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
if (uiLibraries.length === 0)
|
|
115
|
-
continue;
|
|
116
|
-
// 过滤掉不需要测试的布尔特性(根据 combinations 配置决定)
|
|
117
|
-
// 过滤掉根据框架自动选择的特性(pinia/zustand)
|
|
118
|
-
const autoSelectedFeatures = framework === 'vue' ? ['pinia'] : ['zustand'];
|
|
119
|
-
const filteredBooleanFeatures = booleanFeatures.filter((feature) => {
|
|
120
|
-
// 排除自动选择的特性
|
|
121
|
-
if (autoSelectedFeatures.includes(feature)) {
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
// 根据 combinations 配置决定是否参与组合测试
|
|
125
|
-
const featureConfig = featureToConfig(feature, framework);
|
|
126
|
-
if (featureConfig && featureConfig.key in TEST_CONFIG.combinations) {
|
|
127
|
-
const combinationValue = TEST_CONFIG.combinations[featureConfig.key];
|
|
128
|
-
// 如果是数组(frameworks, uiLibraries, routeModes, packageManagers),跳过
|
|
129
|
-
if (Array.isArray(combinationValue)) {
|
|
130
|
-
return true;
|
|
131
|
-
}
|
|
132
|
-
// 其他布尔特性根据配置决定(i18n, sentry, eslint, husky)
|
|
133
|
-
// 使用 Boolean() 转换,避免类型检查问题
|
|
134
|
-
return Boolean(combinationValue);
|
|
135
|
-
}
|
|
136
|
-
// 默认参与组合测试
|
|
137
|
-
return true;
|
|
138
|
-
});
|
|
139
|
-
// 生成所有组合
|
|
140
|
-
// UI 库列表(按框架分组配置,空数组表示不启用)
|
|
141
|
-
const frameworkUiLibraries = TEST_CONFIG.combinations.uiLibraries[framework] || [];
|
|
142
|
-
// 如果配置为空数组,表示不启用该框架的 UI 库测试
|
|
143
|
-
if (frameworkUiLibraries.length === 0) {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
// 只测试配置中指定的 UI 库
|
|
147
|
-
const uiLibrariesToTest = uiLibraries.filter(uiLib => frameworkUiLibraries.includes(uiLib));
|
|
148
|
-
if (uiLibrariesToTest.length === 0) {
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
for (const uiLibrary of uiLibrariesToTest) {
|
|
152
|
-
// 路由模式列表(空数组表示不启用,使用默认值)
|
|
153
|
-
const routeModesToTest = TEST_CONFIG.combinations.routeModes.length > 0
|
|
154
|
-
? routeModes.filter(routeMode => TEST_CONFIG.combinations.routeModes.includes(routeMode))
|
|
155
|
-
: (routeModes.length > 0 ? routeModes : ['manualRoutes']); // 默认路由模式
|
|
156
|
-
if (routeModesToTest.length === 0) {
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
for (const routeModeFeature of routeModesToTest) {
|
|
160
|
-
// 微前端引擎列表(空数组表示不启用)
|
|
161
|
-
const microFrontendEnginesToTest = TEST_CONFIG.combinations.microFrontendEngines;
|
|
162
|
-
// 如果配置了微前端引擎,生成两种组合:不带微前端(null)和带微前端(配置的引擎)
|
|
163
|
-
// 如果没配置,只生成不带微前端的组合
|
|
164
|
-
const microFrontendOptions = microFrontendEnginesToTest.length > 0
|
|
165
|
-
? [null, ...microFrontendEnginesToTest] // 总是包含 null(不带微前端),再加上配置的引擎
|
|
166
|
-
: [null]; // 如果没配置微前端引擎,只生成不带微前端的组合
|
|
167
|
-
for (const microFrontendEngine of microFrontendOptions) {
|
|
168
|
-
// 生成所有布尔特性的组合(2^n 种)
|
|
169
|
-
const combinations = generateAllCombinations(filteredBooleanFeatures);
|
|
170
|
-
// 包管理器列表(空数组表示不启用)
|
|
171
|
-
const packageManagersToTest = TEST_CONFIG.combinations.packageManagers;
|
|
172
|
-
if (packageManagersToTest.length === 0) {
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
for (const packageManager of packageManagersToTest) {
|
|
176
|
-
// 如果启用 minimal 模式,只生成全开和全关两种组合
|
|
177
|
-
const combinationsToTest = TEST_CONFIG.minimal && filteredBooleanFeatures.length > 0
|
|
178
|
-
? [
|
|
179
|
-
// 全关(minimal)
|
|
180
|
-
Array.from({ length: filteredBooleanFeatures.length }).fill(false),
|
|
181
|
-
// 全开(full)
|
|
182
|
-
Array.from({ length: filteredBooleanFeatures.length }).fill(true),
|
|
183
|
-
]
|
|
184
|
-
: combinations;
|
|
185
|
-
for (const combination of combinationsToTest) {
|
|
186
|
-
const config = {
|
|
187
|
-
framework,
|
|
188
|
-
uiLibrary: uiLibrary,
|
|
189
|
-
routeMode: featureToConfig(routeModeFeature, framework).value,
|
|
190
|
-
packageManager,
|
|
191
|
-
microFrontend: microFrontendEngine !== null,
|
|
192
|
-
microFrontendEngine: microFrontendEngine || undefined,
|
|
193
|
-
};
|
|
194
|
-
// 根据路由模式设置对应的布尔特性
|
|
195
|
-
const routeModeFeatures = getRouteModeFeatures(routeModeFeature);
|
|
196
|
-
config.manualRoutes = routeModeFeatures.manualRoutes;
|
|
197
|
-
config.pageRoutes = routeModeFeatures.pageRoutes;
|
|
198
|
-
// 应用布尔特性的组合
|
|
199
|
-
for (let i = 0; i < filteredBooleanFeatures.length; i++) {
|
|
200
|
-
const feature = filteredBooleanFeatures[i];
|
|
201
|
-
const enabled = combination[i];
|
|
202
|
-
const featureConfig = featureToConfig(feature, framework);
|
|
203
|
-
if (featureConfig && featureConfig.key !== 'uiLibrary' && featureConfig.key !== 'routeMode') {
|
|
204
|
-
config[featureConfig.key] = enabled;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
// 生成测试用例名称
|
|
208
|
-
// 如果没有布尔特性组合,使用固定后缀
|
|
209
|
-
const suffix = filteredBooleanFeatures.length === 0
|
|
210
|
-
? 'default'
|
|
211
|
-
: (() => {
|
|
212
|
-
const enabledFeatures = filteredBooleanFeatures.filter((_, i) => combination[i]);
|
|
213
|
-
return enabledFeatures.length === 0
|
|
214
|
-
? 'minimal'
|
|
215
|
-
: enabledFeatures.length === filteredBooleanFeatures.length
|
|
216
|
-
? 'full'
|
|
217
|
-
: enabledFeatures.join('-');
|
|
218
|
-
})();
|
|
219
|
-
// 生成测试用例名称
|
|
220
|
-
const packageManagerSuffix = TEST_CONFIG.combinations.packageManagers.length > 1 ? `${packageManager}-` : '';
|
|
221
|
-
const microFrontendSuffix = microFrontendEngine ? `${microFrontendEngine}-` : '';
|
|
222
|
-
configs.push(createTestConfig(framework, uiLibrary, `${packageManagerSuffix}${microFrontendSuffix}${routeModeFeature}-${suffix}`, config));
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return configs;
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* 创建测试配置的辅助函数
|
|
233
|
-
* @param framework 框架类型
|
|
234
|
-
* @param uiLibrary UI 库名称
|
|
235
|
-
* @param suffix 后缀名称
|
|
236
|
-
* @param overrides 配置覆盖项
|
|
237
|
-
* @returns 测试配置对象
|
|
238
|
-
*/
|
|
239
|
-
function createTestConfig(framework, uiLibrary, suffix, overrides) {
|
|
240
|
-
const name = `${framework}-${uiLibrary}-${suffix}`;
|
|
241
|
-
return {
|
|
242
|
-
name,
|
|
243
|
-
config: {
|
|
244
|
-
// 固定默认值,不参与组合测试
|
|
245
|
-
projectName: name,
|
|
246
|
-
description: TEST_CONFIG.defaults.description,
|
|
247
|
-
author: TEST_CONFIG.defaults.author,
|
|
248
|
-
// 固定默认值,不参与组合测试(避免几何级增长)
|
|
249
|
-
i18n: TEST_CONFIG.defaults.i18n,
|
|
250
|
-
sentry: TEST_CONFIG.defaults.sentry,
|
|
251
|
-
eslint: TEST_CONFIG.defaults.eslint,
|
|
252
|
-
husky: TEST_CONFIG.defaults.husky,
|
|
253
|
-
packageManager: TEST_CONFIG.combinations.packageManagers[0],
|
|
254
|
-
...overrides,
|
|
255
|
-
},
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* 生成测试项目
|
|
260
|
-
* @returns Promise<void>
|
|
261
|
-
*/
|
|
262
|
-
async function generateTestProjects() {
|
|
263
|
-
console.log(chalk.blue.bold('\n🧪 开始生成测试项目...\n'));
|
|
264
|
-
// 扫描并生成测试配置
|
|
265
|
-
const TEST_CONFIGS = generateTestConfigs();
|
|
266
|
-
console.log(chalk.cyan(`📋 扫描到 ${TEST_CONFIGS.length} 个测试用例\n`));
|
|
267
|
-
// 清理并创建测试目录
|
|
268
|
-
if (fs.existsSync(TEST_OUTPUT_DIR)) {
|
|
269
|
-
fs.removeSync(TEST_OUTPUT_DIR);
|
|
270
|
-
}
|
|
271
|
-
fs.ensureDirSync(TEST_OUTPUT_DIR);
|
|
272
|
-
// 创建 Vue 和 React 子目录
|
|
273
|
-
const vueOutputDir = path.join(TEST_OUTPUT_DIR, 'vue');
|
|
274
|
-
const reactOutputDir = path.join(TEST_OUTPUT_DIR, 'react');
|
|
275
|
-
fs.ensureDirSync(vueOutputDir);
|
|
276
|
-
fs.ensureDirSync(reactOutputDir);
|
|
277
|
-
for (const { name, config } of TEST_CONFIGS) {
|
|
278
|
-
console.log(chalk.cyan(`📦 生成 ${name}...`));
|
|
279
|
-
// 根据框架决定输出目录
|
|
280
|
-
const frameworkOutputDir = config.framework === 'vue' ? vueOutputDir : reactOutputDir;
|
|
281
|
-
const fullConfig = {
|
|
282
|
-
// 固定默认值(不参与组合测试)
|
|
283
|
-
projectName: config.projectName || name,
|
|
284
|
-
description: config.description || TEST_CONFIG.defaults.description,
|
|
285
|
-
author: config.author || TEST_CONFIG.defaults.author,
|
|
286
|
-
framework: config.framework,
|
|
287
|
-
uiLibrary: config.uiLibrary,
|
|
288
|
-
routeMode: config.routeMode,
|
|
289
|
-
// 特性名称与目录名称一致
|
|
290
|
-
pinia: config.framework === 'vue',
|
|
291
|
-
zustand: config.framework === 'react',
|
|
292
|
-
...getRouteModeFeatures(config.routeMode),
|
|
293
|
-
// 固定默认值(不参与组合测试,避免几何级增长)
|
|
294
|
-
i18n: config.i18n ?? TEST_CONFIG.defaults.i18n,
|
|
295
|
-
sentry: config.sentry ?? TEST_CONFIG.defaults.sentry,
|
|
296
|
-
eslint: config.eslint ?? TEST_CONFIG.defaults.eslint,
|
|
297
|
-
husky: config.husky ?? TEST_CONFIG.defaults.husky,
|
|
298
|
-
// 参与组合测试的特性
|
|
299
|
-
microFrontend: config.microFrontend ?? false,
|
|
300
|
-
microFrontendEngine: config.microFrontendEngine,
|
|
301
|
-
packageManager: config.packageManager ?? TEST_CONFIG.combinations.packageManagers[0],
|
|
302
|
-
targetDir: path.join(frameworkOutputDir, name),
|
|
303
|
-
};
|
|
304
|
-
try {
|
|
305
|
-
await generateProject(fullConfig);
|
|
306
|
-
console.log(chalk.green(` ✅ ${name} 生成成功`));
|
|
307
|
-
}
|
|
308
|
-
catch (error) {
|
|
309
|
-
console.log(chalk.red(` ❌ ${name} 生成失败:`), error);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
console.log(chalk.green.bold('\n✅ 测试项目生成完成!\n'));
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* 检查 package.json 中是否有 catalog 引用(应该已经全部替换为实际版本号)
|
|
316
|
-
* @param projectDir 项目目录路径
|
|
317
|
-
* @returns 检查是否通过(true 表示通过,false 表示失败)
|
|
318
|
-
*/
|
|
319
|
-
function checkPackageJsonVersions(projectDir) {
|
|
320
|
-
const packageJsonPath = path.join(projectDir, FILE_CONSTANTS.PACKAGE_JSON);
|
|
321
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
322
|
-
console.log(chalk.red(` ❌ package.json 不存在`));
|
|
323
|
-
return false;
|
|
324
|
-
}
|
|
325
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
326
|
-
let hasError = false;
|
|
327
|
-
// 检查 dependencies 中是否还有 catalog 引用
|
|
328
|
-
if (packageJson.dependencies) {
|
|
329
|
-
for (const [dep, version] of Object.entries(packageJson.dependencies)) {
|
|
330
|
-
if (typeof version === 'string' && version.startsWith('catalog:')) {
|
|
331
|
-
console.log(chalk.red(` ❌ dependencies.${dep}: "${version}" 应该使用实际版本号`));
|
|
332
|
-
hasError = true;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
// 检查 devDependencies 中是否还有 catalog 引用
|
|
337
|
-
if (packageJson.devDependencies) {
|
|
338
|
-
for (const [dep, version] of Object.entries(packageJson.devDependencies)) {
|
|
339
|
-
if (typeof version === 'string' && version.startsWith('catalog:')) {
|
|
340
|
-
console.log(chalk.red(` ❌ devDependencies.${dep}: "${version}" 应该使用实际版本号`));
|
|
341
|
-
hasError = true;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
if (!hasError) {
|
|
346
|
-
console.log(chalk.green(` ✅ package.json 版本号检查通过(无 catalog 引用)`));
|
|
347
|
-
}
|
|
348
|
-
return !hasError;
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* 审计 @moluoxixi 依赖
|
|
352
|
-
*/
|
|
353
|
-
async function auditMoluoxixiDeps() {
|
|
354
|
-
console.log(chalk.blue.bold('\n🔍 开始审计 @moluoxixi 依赖...\n'));
|
|
355
|
-
const TEST_CONFIGS = generateTestConfigs();
|
|
356
|
-
const requiredDeps = [
|
|
357
|
-
'@moluoxixi/vite-config',
|
|
358
|
-
'@moluoxixi/ajax-package',
|
|
359
|
-
];
|
|
360
|
-
let hasError = false;
|
|
361
|
-
for (const { name, config } of TEST_CONFIGS) {
|
|
362
|
-
// 根据框架决定输出目录
|
|
363
|
-
const frameworkOutputDir = config.framework === 'vue'
|
|
364
|
-
? path.join(TEST_OUTPUT_DIR, 'vue')
|
|
365
|
-
: path.join(TEST_OUTPUT_DIR, 'react');
|
|
366
|
-
const projectDir = path.join(frameworkOutputDir, name);
|
|
367
|
-
const packageJsonPath = path.join(projectDir, FILE_CONSTANTS.PACKAGE_JSON);
|
|
368
|
-
console.log(chalk.cyan(`📋 检查 ${name}...`));
|
|
369
|
-
// 根据配置决定需要检查的依赖
|
|
370
|
-
const depsToCheck = [...requiredDeps];
|
|
371
|
-
if (config.eslint) {
|
|
372
|
-
depsToCheck.push('@moluoxixi/eslint-config');
|
|
373
|
-
}
|
|
374
|
-
// 检查 package.json
|
|
375
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
376
|
-
const packageJson = fs.readJsonSync(packageJsonPath);
|
|
377
|
-
const allDeps = {
|
|
378
|
-
...packageJson.dependencies,
|
|
379
|
-
...packageJson.devDependencies,
|
|
380
|
-
};
|
|
381
|
-
for (const dep of depsToCheck) {
|
|
382
|
-
if (!allDeps[dep]) {
|
|
383
|
-
console.log(chalk.red(` ❌ package.json 缺少 ${dep}`));
|
|
384
|
-
hasError = true;
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
console.log(chalk.green(` ✅ package.json 包含 ${dep}`));
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
else {
|
|
392
|
-
console.log(chalk.red(` ❌ package.json 不存在`));
|
|
393
|
-
hasError = true;
|
|
394
|
-
}
|
|
395
|
-
// 检查可选特性文件
|
|
396
|
-
if (!config.eslint) {
|
|
397
|
-
const eslintConfig = path.join(projectDir, 'eslint.config.ts');
|
|
398
|
-
if (fs.existsSync(eslintConfig)) {
|
|
399
|
-
console.log(chalk.red(` ❌ 不应存在 eslint.config.ts(ESLint 已禁用)`));
|
|
400
|
-
hasError = true;
|
|
401
|
-
}
|
|
402
|
-
else {
|
|
403
|
-
console.log(chalk.green(` ✅ eslint.config.ts 已正确移除`));
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
if (!config.husky) {
|
|
407
|
-
const huskyDir = path.join(projectDir, '.husky');
|
|
408
|
-
if (fs.existsSync(huskyDir)) {
|
|
409
|
-
console.log(chalk.red(` ❌ 不应存在 .husky/ 目录(Git Hooks 已禁用)`));
|
|
410
|
-
hasError = true;
|
|
411
|
-
}
|
|
412
|
-
else {
|
|
413
|
-
console.log(chalk.green(` ✅ .husky/ 目录已正确移除`));
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
// 检查 package.json 版本号(确保没有 catalog 引用)
|
|
417
|
-
console.log(chalk.cyan(` 🔍 检查 package.json 版本号...`));
|
|
418
|
-
const packageJsonOk = checkPackageJsonVersions(projectDir);
|
|
419
|
-
if (!packageJsonOk) {
|
|
420
|
-
hasError = true;
|
|
421
|
-
}
|
|
422
|
-
console.log('');
|
|
423
|
-
}
|
|
424
|
-
if (hasError) {
|
|
425
|
-
console.log(chalk.red.bold('\n❌ 审计失败: 存在问题\n'));
|
|
426
|
-
process.exit(1);
|
|
427
|
-
}
|
|
428
|
-
else {
|
|
429
|
-
console.log(chalk.green.bold('\n✅ 审计通过: 所有检查项均通过\n'));
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
/**
|
|
433
|
-
* 显示文件树
|
|
434
|
-
*/
|
|
435
|
-
async function showFileTrees() {
|
|
436
|
-
console.log(chalk.blue.bold('\n📂 项目文件树...\n'));
|
|
437
|
-
const vueOutputDir = path.join(TEST_OUTPUT_DIR, 'vue');
|
|
438
|
-
const reactOutputDir = path.join(TEST_OUTPUT_DIR, 'react');
|
|
439
|
-
// 显示 Vue 项目
|
|
440
|
-
if (fs.existsSync(vueOutputDir)) {
|
|
441
|
-
console.log(chalk.cyan.bold('\n📁 Vue 项目:\n'));
|
|
442
|
-
const vueProjects = fs.readdirSync(vueOutputDir).filter((item) => {
|
|
443
|
-
const itemPath = path.join(vueOutputDir, item);
|
|
444
|
-
return fs.statSync(itemPath).isDirectory();
|
|
445
|
-
});
|
|
446
|
-
for (const projectName of vueProjects) {
|
|
447
|
-
const projectDir = path.join(vueOutputDir, projectName);
|
|
448
|
-
console.log(chalk.cyan(`\n${projectName}/`));
|
|
449
|
-
await printFileTree(projectDir, ' ');
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
// 显示 React 项目
|
|
453
|
-
if (fs.existsSync(reactOutputDir)) {
|
|
454
|
-
console.log(chalk.cyan.bold('\n📁 React 项目:\n'));
|
|
455
|
-
const reactProjects = fs.readdirSync(reactOutputDir).filter((item) => {
|
|
456
|
-
const itemPath = path.join(reactOutputDir, item);
|
|
457
|
-
return fs.statSync(itemPath).isDirectory();
|
|
458
|
-
});
|
|
459
|
-
for (const projectName of reactProjects) {
|
|
460
|
-
const projectDir = path.join(reactOutputDir, projectName);
|
|
461
|
-
console.log(chalk.cyan(`\n${projectName}/`));
|
|
462
|
-
await printFileTree(projectDir, ' ');
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
/**
|
|
467
|
-
* 打印文件树
|
|
468
|
-
* @param dir 目录路径
|
|
469
|
-
* @param indent 缩进字符串
|
|
470
|
-
* @returns Promise<void>
|
|
471
|
-
*/
|
|
472
|
-
async function printFileTree(dir, indent) {
|
|
473
|
-
const items = fs.readdirSync(dir).sort();
|
|
474
|
-
for (const item of items) {
|
|
475
|
-
if (item === FILE_CONSTANTS.NODE_MODULES)
|
|
476
|
-
continue;
|
|
477
|
-
const itemPath = path.join(dir, item);
|
|
478
|
-
const stat = fs.statSync(itemPath);
|
|
479
|
-
if (stat.isDirectory()) {
|
|
480
|
-
console.log(chalk.gray(`${indent}📁 ${item}/`));
|
|
481
|
-
await printFileTree(itemPath, `${indent} `);
|
|
482
|
-
}
|
|
483
|
-
else {
|
|
484
|
-
console.log(chalk.gray(`${indent}📄 ${item}`));
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
/**
|
|
489
|
-
* 主函数
|
|
490
|
-
* 执行测试项目生成、依赖审计和文件树显示
|
|
491
|
-
* @returns Promise<void>
|
|
492
|
-
*/
|
|
493
|
-
async function main() {
|
|
494
|
-
console.log(chalk.blue.bold(`\n${'='.repeat(60)}`));
|
|
495
|
-
console.log(chalk.blue.bold(' Vite CLI Next - 产物审计测试'));
|
|
496
|
-
console.log(chalk.blue.bold('='.repeat(60)));
|
|
497
|
-
if (TEST_CONFIG.minimal) {
|
|
498
|
-
console.log(chalk.yellow(' ⚠️ 运行在 minimal 模式(只生成全量和最小配置)\n'));
|
|
499
|
-
}
|
|
500
|
-
// 1. 生成测试项目
|
|
501
|
-
await generateTestProjects();
|
|
502
|
-
// 2. 审计 @moluoxixi 依赖
|
|
503
|
-
await auditMoluoxixiDeps();
|
|
504
|
-
// 3. 显示文件树
|
|
505
|
-
await showFileTrees();
|
|
506
|
-
console.log(chalk.green.bold('\n✅ 全量产物审计完成!\n'));
|
|
507
|
-
}
|
|
508
|
-
main().catch(console.error);
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 工具函数
|
|
3
|
-
* 通用工具方法
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* 延迟执行
|
|
8
|
-
* @param ms 延迟毫秒数
|
|
9
|
-
* @returns Promise,在指定时间后 resolve
|
|
10
|
-
*/
|
|
11
|
-
export function sleep(ms: number): Promise<void> {
|
|
12
|
-
return new Promise(resolve => setTimeout(resolve, ms))
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 深拷贝
|
|
17
|
-
* @param obj 要拷贝的对象
|
|
18
|
-
* @returns 深拷贝后的新对象
|
|
19
|
-
*/
|
|
20
|
-
export function deepClone<T>(obj: T): T {
|
|
21
|
-
return JSON.parse(JSON.stringify(obj))
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* 防抖函数
|
|
26
|
-
* @param fn 要防抖的函数
|
|
27
|
-
* @param delay 延迟时间(毫秒)
|
|
28
|
-
* @returns 防抖后的函数
|
|
29
|
-
*/
|
|
30
|
-
export function debounce<T extends (...args: unknown[]) => unknown>(
|
|
31
|
-
fn: T,
|
|
32
|
-
delay: number,
|
|
33
|
-
): (...args: Parameters<T>) => void {
|
|
34
|
-
let timer: ReturnType<typeof setTimeout> | null = null
|
|
35
|
-
return function (this: unknown, ...args: Parameters<T>) {
|
|
36
|
-
if (timer) {
|
|
37
|
-
clearTimeout(timer)
|
|
38
|
-
}
|
|
39
|
-
timer = setTimeout(() => {
|
|
40
|
-
fn.apply(this, args)
|
|
41
|
-
}, delay)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* 节流函数
|
|
47
|
-
* @param fn 要节流的函数
|
|
48
|
-
* @param delay 间隔时间(毫秒)
|
|
49
|
-
* @returns 节流后的函数
|
|
50
|
-
*/
|
|
51
|
-
export function throttle<T extends (...args: unknown[]) => unknown>(
|
|
52
|
-
fn: T,
|
|
53
|
-
delay: number,
|
|
54
|
-
): (...args: Parameters<T>) => void {
|
|
55
|
-
let lastTime = 0
|
|
56
|
-
return function (this: unknown, ...args: Parameters<T>) {
|
|
57
|
-
const now = Date.now()
|
|
58
|
-
if (now - lastTime >= delay) {
|
|
59
|
-
lastTime = now
|
|
60
|
-
fn.apply(this, args)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* 格式化日期
|
|
67
|
-
* @param date 日期(Date 对象、时间戳或日期字符串)
|
|
68
|
-
* @param format 格式字符串,默认为 'YYYY-MM-DD HH:mm:ss'
|
|
69
|
-
* @returns 格式化后的日期字符串
|
|
70
|
-
*/
|
|
71
|
-
export function formatDate(date: Date | string | number, format = 'YYYY-MM-DD HH:mm:ss'): string {
|
|
72
|
-
const d = new Date(date)
|
|
73
|
-
const year = d.getFullYear()
|
|
74
|
-
const month = String(d.getMonth() + 1).padStart(2, '0')
|
|
75
|
-
const day = String(d.getDate()).padStart(2, '0')
|
|
76
|
-
const hours = String(d.getHours()).padStart(2, '0')
|
|
77
|
-
const minutes = String(d.getMinutes()).padStart(2, '0')
|
|
78
|
-
const seconds = String(d.getSeconds()).padStart(2, '0')
|
|
79
|
-
|
|
80
|
-
return format
|
|
81
|
-
.replace('YYYY', String(year))
|
|
82
|
-
.replace('MM', month)
|
|
83
|
-
.replace('DD', day)
|
|
84
|
-
.replace('HH', hours)
|
|
85
|
-
.replace('mm', minutes)
|
|
86
|
-
.replace('ss', seconds)
|
|
87
|
-
}
|
/package/templates/vue/features/element-plus/src/assets/styles/{element.scss → element/index.scss}
RENAMED
|
File without changes
|