feima-shortcuts 0.0.8 → 0.1.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/bin/feima.js +35 -1
- package/package.json +1 -1
- package/src/generate.js +7 -1
- package/src/scripts/{new.js → restful-api/new.js} +1 -1
- package/src/scripts/{old.js → restful-api/old.js} +1 -1
- package/src/scripts/template/card.js +142 -0
- package/src/scripts/template/form.js +233 -0
- package/src/scripts/template/index.js +15 -0
- package/src/scripts/template/tabs.js +98 -0
- /package/src/scripts/{restful-api.js → restful-api/index.js} +0 -0
package/bin/feima.js
CHANGED
|
@@ -1,15 +1,49 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const inquirer = require("inquirer");
|
|
3
3
|
const feima = require("../src/generate");
|
|
4
|
+
const { version } = require("../package.json"); // 读取 package.json 中的版本号
|
|
4
5
|
|
|
5
6
|
const run = () => {
|
|
7
|
+
console.log(`🚀 当前版本:v${version}`);
|
|
8
|
+
|
|
6
9
|
inquirer
|
|
7
10
|
.prompt([
|
|
11
|
+
{
|
|
12
|
+
type: "list",
|
|
13
|
+
name: "type",
|
|
14
|
+
message: "请选择模版类型",
|
|
15
|
+
choices: ["api", "template"],
|
|
16
|
+
},
|
|
17
|
+
// 页面模版创建方式
|
|
18
|
+
{
|
|
19
|
+
type: "input",
|
|
20
|
+
message: "输入页面路径:",
|
|
21
|
+
name: "template-path",
|
|
22
|
+
default: "warehouseManagement/inventoryTransfer/internalAllocation/index", // 默认值
|
|
23
|
+
when: function (answers) {
|
|
24
|
+
return ["template"].includes(answers.type);
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: "list",
|
|
29
|
+
name: "template-type",
|
|
30
|
+
message: "请选择页面模版类型",
|
|
31
|
+
choices: ["card", 'tabs', 'form'],
|
|
32
|
+
when: function (answers) {
|
|
33
|
+
return answers['template-path'];
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
// 接口创建方式
|
|
8
39
|
{
|
|
9
40
|
type: "list",
|
|
10
41
|
name: "template",
|
|
11
42
|
message: "请选择接口类型",
|
|
12
|
-
choices: ["new",'old'],
|
|
43
|
+
choices: ["new", 'old'],
|
|
44
|
+
when: function (answers) {
|
|
45
|
+
return ["api"].includes(answers.type);
|
|
46
|
+
},
|
|
13
47
|
},
|
|
14
48
|
{
|
|
15
49
|
type: "input",
|
package/package.json
CHANGED
package/src/generate.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
const restfulApi = require("./scripts/restful-api");
|
|
2
|
+
const template = require("./scripts/template");
|
|
2
3
|
|
|
3
4
|
exports.run = function (answers) {
|
|
4
|
-
|
|
5
|
+
if (answers.type == 'api') {
|
|
6
|
+
restfulApi.run(answers);
|
|
7
|
+
}
|
|
8
|
+
if (answers.type == 'template') {
|
|
9
|
+
template.run(answers)
|
|
10
|
+
}
|
|
5
11
|
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const { makeDir } = require("../../utils/makeDir");
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
function toKebabCase(str) {
|
|
6
|
+
if (/^[A-Z]/.test(str)) {
|
|
7
|
+
throw new Error('首字母不能是大写');
|
|
8
|
+
}
|
|
9
|
+
return str.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const templateStr = ({fileName}) => {
|
|
13
|
+
const className = toKebabCase(fileName);
|
|
14
|
+
|
|
15
|
+
return `<template>
|
|
16
|
+
<el-card class="${className}">
|
|
17
|
+
<f-table
|
|
18
|
+
ref="tableRef"
|
|
19
|
+
:params="params"
|
|
20
|
+
:columns="columns"
|
|
21
|
+
:request="request"
|
|
22
|
+
style="max-width: 1000px"
|
|
23
|
+
>
|
|
24
|
+
<template #option="scopeData">
|
|
25
|
+
<el-table-column v-bind="scopeData">
|
|
26
|
+
<template #default="{ row }">
|
|
27
|
+
<el-button
|
|
28
|
+
link
|
|
29
|
+
type="primary"
|
|
30
|
+
@click="
|
|
31
|
+
$router.push({
|
|
32
|
+
path: '/xxx',
|
|
33
|
+
query: { id: 'xx' },
|
|
34
|
+
})
|
|
35
|
+
"
|
|
36
|
+
>
|
|
37
|
+
编辑
|
|
38
|
+
</el-button>
|
|
39
|
+
</template>
|
|
40
|
+
</el-table-column>
|
|
41
|
+
</template>
|
|
42
|
+
</f-table>
|
|
43
|
+
</el-card>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<script setup lang="ts">
|
|
47
|
+
import { ref } from "vue";
|
|
48
|
+
|
|
49
|
+
defineOptions({
|
|
50
|
+
name: "${fileName}",
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const tableRef = ref<any>(null);
|
|
54
|
+
const params = ref<any>({});
|
|
55
|
+
const columns = ref<any[]>([
|
|
56
|
+
{
|
|
57
|
+
width: 130,
|
|
58
|
+
prop: "clientName",
|
|
59
|
+
label: "供应商名称",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
customizeId: "option",
|
|
63
|
+
search: false,
|
|
64
|
+
fixed: "right",
|
|
65
|
+
label: "操作",
|
|
66
|
+
width: 100,
|
|
67
|
+
},
|
|
68
|
+
]);
|
|
69
|
+
|
|
70
|
+
const request = ({ createTime, ...params }: any) => {
|
|
71
|
+
return new Promise((resolve) => {
|
|
72
|
+
if (createTime) {
|
|
73
|
+
params.startTime = \`\${createTime[0]} 00:00:00\`;
|
|
74
|
+
params.endTime = \`\${createTime[1]} 23:59:59\`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// adminSupplierList({
|
|
78
|
+
// params,
|
|
79
|
+
// })
|
|
80
|
+
// .then((res) => {
|
|
81
|
+
// resolve({
|
|
82
|
+
// data: res.data.list,
|
|
83
|
+
// total: res.data.total,
|
|
84
|
+
// });
|
|
85
|
+
// })
|
|
86
|
+
// .catch(() => {
|
|
87
|
+
// resolve({
|
|
88
|
+
// data: [],
|
|
89
|
+
// });
|
|
90
|
+
// });
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<style lang="scss" scoped>
|
|
96
|
+
.${className} {
|
|
97
|
+
height: 100%;
|
|
98
|
+
|
|
99
|
+
:deep(.el-card__body) {
|
|
100
|
+
--el-card-padding: 0;
|
|
101
|
+
height: 100%;
|
|
102
|
+
display: flex;
|
|
103
|
+
flex-direction: column;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
:deep(.el-form-item__content) {
|
|
107
|
+
--form-item-content: 210px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
&-btns {
|
|
111
|
+
display: flex;
|
|
112
|
+
gap: var(--base-gap);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
</style>`;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
exports.run = function (answers) {
|
|
121
|
+
const filePath = `./src/views/${answers['template-path']}.vue`;
|
|
122
|
+
const parts = filePath.split('/');
|
|
123
|
+
const fileName = parts[parts.length - 2];
|
|
124
|
+
const fileIndex = parts[parts.length - 1];
|
|
125
|
+
const makeDirPath = [...parts].slice(0, -1).join('/');
|
|
126
|
+
|
|
127
|
+
makeDir(makeDirPath);
|
|
128
|
+
process.chdir(makeDirPath);
|
|
129
|
+
|
|
130
|
+
const template = templateStr({ fileName });
|
|
131
|
+
|
|
132
|
+
const targetFilePath = `./${fileIndex}`;
|
|
133
|
+
|
|
134
|
+
// 新增:判断文件是否存在
|
|
135
|
+
if (fs.existsSync(targetFilePath)) {
|
|
136
|
+
console.log(`❌ 文件已存在:${targetFilePath},未进行覆盖操作。`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
fs.writeFileSync(targetFilePath, template);
|
|
141
|
+
console.log(`✅ 文件创建成功`);
|
|
142
|
+
};
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const { makeDir } = require("../../utils/makeDir");
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
function toKebabCase(str) {
|
|
6
|
+
if (/^[A-Z]/.test(str)) {
|
|
7
|
+
throw new Error('首字母不能是大写');
|
|
8
|
+
}
|
|
9
|
+
return str.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const templateStr = ({fileName}) => {
|
|
13
|
+
const className = toKebabCase(fileName);
|
|
14
|
+
|
|
15
|
+
return `<template>
|
|
16
|
+
<el-card class="${className}">
|
|
17
|
+
<el-form
|
|
18
|
+
ref="formRef"
|
|
19
|
+
inline
|
|
20
|
+
:model="formValue"
|
|
21
|
+
label-width="120px"
|
|
22
|
+
label-suffix=":"
|
|
23
|
+
>
|
|
24
|
+
<el-form-item
|
|
25
|
+
class="block"
|
|
26
|
+
label="测试姓名"
|
|
27
|
+
prop="name"
|
|
28
|
+
:rules="[
|
|
29
|
+
{
|
|
30
|
+
required: true,
|
|
31
|
+
message: '请输入测试姓名',
|
|
32
|
+
trigger: 'blur',
|
|
33
|
+
},
|
|
34
|
+
]"
|
|
35
|
+
>
|
|
36
|
+
<el-input v-model="formValue.name" />
|
|
37
|
+
</el-form-item>
|
|
38
|
+
<el-form-item
|
|
39
|
+
label="测试2"
|
|
40
|
+
prop="test2"
|
|
41
|
+
>
|
|
42
|
+
<el-input v-model="formValue.test1" />
|
|
43
|
+
</el-form-item>
|
|
44
|
+
<el-form-item
|
|
45
|
+
label="测试3"
|
|
46
|
+
prop="test3"
|
|
47
|
+
>
|
|
48
|
+
<el-input v-model="formValue.test1" />
|
|
49
|
+
</el-form-item>
|
|
50
|
+
|
|
51
|
+
<el-form-item
|
|
52
|
+
class="block-content"
|
|
53
|
+
label="备注(只是示例)"
|
|
54
|
+
prop="remark"
|
|
55
|
+
>
|
|
56
|
+
<el-input
|
|
57
|
+
v-model="formValue.remark"
|
|
58
|
+
:rows="3"
|
|
59
|
+
type="textarea"
|
|
60
|
+
/>
|
|
61
|
+
</el-form-item>
|
|
62
|
+
<el-form-item
|
|
63
|
+
class="block-content"
|
|
64
|
+
label="富文本(只是示例)"
|
|
65
|
+
prop="remark"
|
|
66
|
+
>
|
|
67
|
+
<ProFormTinymce v-model="formValue.richText" />
|
|
68
|
+
</el-form-item>
|
|
69
|
+
|
|
70
|
+
<el-form-item
|
|
71
|
+
class="block-content"
|
|
72
|
+
label="富文本(只是示例)"
|
|
73
|
+
prop="remark"
|
|
74
|
+
>
|
|
75
|
+
<ProFormImage
|
|
76
|
+
v-model="formValue.images"
|
|
77
|
+
:limit="1"
|
|
78
|
+
:before-upload="handleBeforeUpload"
|
|
79
|
+
>
|
|
80
|
+
<template #footer>
|
|
81
|
+
<div class="pro-form-image-tip">
|
|
82
|
+
<el-icon color="red"><Warning /></el-icon>
|
|
83
|
+
仅支持上传宽度750px且大小不超过1MB图片
|
|
84
|
+
</div>
|
|
85
|
+
</template>
|
|
86
|
+
</ProFormImage>
|
|
87
|
+
</el-form-item>
|
|
88
|
+
</el-form>
|
|
89
|
+
|
|
90
|
+
<PageFooter>
|
|
91
|
+
<el-button
|
|
92
|
+
type="primary"
|
|
93
|
+
v-fLoading="onSubmit"
|
|
94
|
+
>
|
|
95
|
+
提交
|
|
96
|
+
</el-button>
|
|
97
|
+
</PageFooter>
|
|
98
|
+
</el-card>
|
|
99
|
+
</template>
|
|
100
|
+
|
|
101
|
+
<script setup lang="ts">
|
|
102
|
+
import { ref } from "vue";
|
|
103
|
+
import { ElMessage } from "element-plus";
|
|
104
|
+
|
|
105
|
+
import PageFooter from "@/components/PageFooter.vue";
|
|
106
|
+
import ProFormTinymce from "@/components/ProFormTinymce.vue";
|
|
107
|
+
import ProFormImage from "@/components/ProFormImage.vue";
|
|
108
|
+
|
|
109
|
+
defineOptions({
|
|
110
|
+
name: "${fileName}",
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const formRef = ref<any>();
|
|
114
|
+
const formValue = ref<any>({
|
|
115
|
+
name: "",
|
|
116
|
+
test2: "",
|
|
117
|
+
test3: "",
|
|
118
|
+
remark: "",
|
|
119
|
+
richText: "",
|
|
120
|
+
images: [],
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// 上传之前的处理
|
|
124
|
+
const handleBeforeUpload = (file: any) => {
|
|
125
|
+
if (file.size > 1048576) {
|
|
126
|
+
ElMessage.error("超出最大上传大小,图片不能大于1MB");
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
// 示例,不需要自己删除
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
const reader = new FileReader();
|
|
132
|
+
|
|
133
|
+
reader.onload = () => {
|
|
134
|
+
const img: any = new Image();
|
|
135
|
+
img.src = reader.result;
|
|
136
|
+
|
|
137
|
+
img.onload = () => {
|
|
138
|
+
// 检查图片宽度是否超过 750px
|
|
139
|
+
if (img.width != 750) {
|
|
140
|
+
ElMessage.error("图片宽度需为 750 像素");
|
|
141
|
+
reject(); // 取消上传
|
|
142
|
+
} else {
|
|
143
|
+
resolve(""); // 宽度合格,允许上传
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
img.onerror = () => {
|
|
148
|
+
ElMessage.error("图片加载失败");
|
|
149
|
+
reject(); // 图片加载失败,取消上传
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
reader.readAsDataURL(file); // 读取文件
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
const onSubmit = async () => {
|
|
157
|
+
await formRef.value.validate();
|
|
158
|
+
try {
|
|
159
|
+
const { images, ...values } = formValue.value;
|
|
160
|
+
const submitData = {
|
|
161
|
+
...values,
|
|
162
|
+
images: images.map((item: any) => item.path).join(","),
|
|
163
|
+
};
|
|
164
|
+
let formData = new FormData();
|
|
165
|
+
formData.append("json", JSON.stringify(submitData));
|
|
166
|
+
// const res: any = await addTransferOrder({
|
|
167
|
+
// data: formData,
|
|
168
|
+
// });
|
|
169
|
+
// if (res.code != 200) {
|
|
170
|
+
// ElMessage.error(res.message || "系统出错");
|
|
171
|
+
// return;
|
|
172
|
+
// }
|
|
173
|
+
// ElMessage.success(res.message);
|
|
174
|
+
} catch (error) {
|
|
175
|
+
console.error(error);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
</script>
|
|
179
|
+
<style lang="scss" scoped>
|
|
180
|
+
.${className} {
|
|
181
|
+
height: calc(100% - var(--page-footer-height));
|
|
182
|
+
padding-bottom: var(--page-footer-height);
|
|
183
|
+
overflow-y: scroll;
|
|
184
|
+
--form-item-content: 250px;
|
|
185
|
+
|
|
186
|
+
:deep(.el-form-item__content) {
|
|
187
|
+
width: var(--form-item-content);
|
|
188
|
+
flex: 0 auto;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
:deep(.el-card__body) {
|
|
192
|
+
height: 100%;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.block {
|
|
196
|
+
width: 100%;
|
|
197
|
+
}
|
|
198
|
+
.block-content {
|
|
199
|
+
width: 100%;
|
|
200
|
+
|
|
201
|
+
:deep(.el-form-item__content) {
|
|
202
|
+
width: 100%;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
</style>`;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
exports.run = function (answers) {
|
|
212
|
+
const filePath = `./src/views/${answers['template-path']}.vue`;
|
|
213
|
+
const parts = filePath.split('/');
|
|
214
|
+
const fileName = parts[parts.length - 2];
|
|
215
|
+
const fileIndex = parts[parts.length - 1];
|
|
216
|
+
const makeDirPath = [...parts].slice(0, -1).join('/');
|
|
217
|
+
|
|
218
|
+
makeDir(makeDirPath);
|
|
219
|
+
process.chdir(makeDirPath);
|
|
220
|
+
|
|
221
|
+
const template = templateStr({ fileName });
|
|
222
|
+
|
|
223
|
+
const targetFilePath = `./${fileIndex}`;
|
|
224
|
+
|
|
225
|
+
// 新增:判断文件是否存在
|
|
226
|
+
if (fs.existsSync(targetFilePath)) {
|
|
227
|
+
console.log(`❌ 文件已存在:${targetFilePath},未进行覆盖操作。`);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
fs.writeFileSync(targetFilePath, template);
|
|
232
|
+
console.log(`✅ 文件创建成功`);
|
|
233
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const card = require("./card");
|
|
2
|
+
const tabs = require("./tabs");
|
|
3
|
+
const form = require("./form");
|
|
4
|
+
|
|
5
|
+
exports.run = function (answers) {
|
|
6
|
+
if (answers['template-type'] === "card") {
|
|
7
|
+
card.run(answers);
|
|
8
|
+
};
|
|
9
|
+
if (answers['template-type'] === "tabs") {
|
|
10
|
+
tabs.run(answers);
|
|
11
|
+
};
|
|
12
|
+
if (answers['template-type'] === "form") {
|
|
13
|
+
form.run(answers);
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const { makeDir } = require("../../utils/makeDir");
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
function toKebabCase(str) {
|
|
6
|
+
if (/^[A-Z]/.test(str)) {
|
|
7
|
+
throw new Error('首字母不能是大写');
|
|
8
|
+
}
|
|
9
|
+
return str.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const templateStr = ({fileName}) => {
|
|
13
|
+
const className = toKebabCase(fileName);
|
|
14
|
+
|
|
15
|
+
return `<template>
|
|
16
|
+
<el-card class="${className}">
|
|
17
|
+
<el-tabs
|
|
18
|
+
v-model="tabActive"
|
|
19
|
+
type="border-card"
|
|
20
|
+
>
|
|
21
|
+
<el-tab-pane
|
|
22
|
+
label="使用商品列表"
|
|
23
|
+
name="use"
|
|
24
|
+
>
|
|
25
|
+
use
|
|
26
|
+
</el-tab-pane>
|
|
27
|
+
<el-tab-pane
|
|
28
|
+
label="删除商品列表"
|
|
29
|
+
name="delete"
|
|
30
|
+
>
|
|
31
|
+
delete
|
|
32
|
+
</el-tab-pane>
|
|
33
|
+
</el-tabs>
|
|
34
|
+
</el-card>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script setup lang="ts">
|
|
38
|
+
import { ref } from "vue";
|
|
39
|
+
|
|
40
|
+
defineOptions({
|
|
41
|
+
name: "${fileName}",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const tabActive = ref("use");
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<style lang="scss" scoped>
|
|
48
|
+
.${className} {
|
|
49
|
+
height: 100%;
|
|
50
|
+
|
|
51
|
+
:deep(.el-card__body) {
|
|
52
|
+
--el-card-padding: 0;
|
|
53
|
+
height: 100%;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
:deep(.el-tabs) {
|
|
57
|
+
height: 100%;
|
|
58
|
+
|
|
59
|
+
.el-tabs__header {
|
|
60
|
+
margin-bottom: 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.el-tabs__content {
|
|
64
|
+
padding: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.el-tab-pane {
|
|
68
|
+
height: 100%;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
</style>`;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
exports.run = function (answers) {
|
|
77
|
+
const filePath = `./src/views/${answers['template-path']}.vue`;
|
|
78
|
+
const parts = filePath.split('/');
|
|
79
|
+
const fileName = parts[parts.length - 2];
|
|
80
|
+
const fileIndex = parts[parts.length - 1];
|
|
81
|
+
const makeDirPath = [...parts].slice(0, -1).join('/');
|
|
82
|
+
|
|
83
|
+
makeDir(makeDirPath);
|
|
84
|
+
process.chdir(makeDirPath);
|
|
85
|
+
|
|
86
|
+
const template = templateStr({ fileName });
|
|
87
|
+
|
|
88
|
+
const targetFilePath = `./${fileIndex}`;
|
|
89
|
+
|
|
90
|
+
// 新增:判断文件是否存在
|
|
91
|
+
if (fs.existsSync(targetFilePath)) {
|
|
92
|
+
console.log(`❌ 文件已存在:${targetFilePath},未进行覆盖操作。`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fs.writeFileSync(targetFilePath, template);
|
|
97
|
+
console.log(`✅ 文件创建成功`);
|
|
98
|
+
};
|
|
File without changes
|