npm node-sass安装失败解决方法
node-sass安装失败,提示如下:
gyp verb check python checking for Python executable "python" in the PATH
gyp verb `which` succeeded python D:\Program Files\Python38\python.EXE
gyp ERR! configure error
gyp ERR! stack Error: Command failed: D:\Program Files\Python38\python.EXE -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack File "<string>", line 1
gyp ERR! stack import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack ^
gyp ERR! stack SyntaxError: invalid syntax
gyp ERR! stack
gyp ERR! stack at ChildProcess.exithandler (child_process.js:303:12)
gyp ERR! stack at ChildProcess.emit (events.js:310:20)
gyp ERR! stack at maybeClose (internal/child_process.js:1021:16)
gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:286:5)
gyp ERR! System Windows_NT 10.0.18362
gyp ERR! command "D:\\Program Files\\nodejs\\node.exe" "E:\\JDProject\\renren-fast-vue\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd E:\JDProject\renren-fast-vue\node_modules\node-sass
gyp ERR! node -v v12.16.3
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
Build failed with error code: 1
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! node-sass@4.9.0 postinstall: `node scripts/build.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the node-sass@4.9.0 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\HP\AppData\Roaming\npm-cache\_logs\2020-05-23T06_27_44_952Z-debug.log
原因:
print "%s.%s.%s" % sys.version_info[:3];
为python2.x版本的语法,如果本地安装的是python3.x,就会报此错误
解决方法:
1. 删除项目中的package-lock.json文件,清除缓存,更新版本号
#后续步骤运行npm install 命令时会重新生成package-lock.json文件
1 npm cache clear --force
2 修改 package.json 文件 提高 node-sass 版本
"node-sass": "4.14.1",
"npm": "^6.14.5", #sass-loader版本为可选项,如果项目很旧,sass-loader版本最好不要改动,否则容易引起项目启动异常
"sass-loader": "8.0.2",
3 保存后重新 npm install 即可
之所以报 就是上面那个该死的 "C\Python27\python.exe"找不到。
原因是 node-sass跟node就版本对应的问题的。
打开命令行 查看 node版本: node -v

node版本不对应,升级node或者降级
查看node-sass和sass-loader版本是否对应
以下是部分版本号对应,具体可百度
sass-loader 4.1.1,node-sass 4.3.0
sass-loader 7.0.3,node-sass 4.7.2
sass-loader 7.3.1,node-sass 4.7.2
sass-loader 7.3.1,node-sass 4.14.1
在项目环境中执行
npm uninstall node-sass sass-loader
npm install sass-loader@版本号 node-sass@版本号 --save-dev //安装对应的版本
----------------------------------------------------------
<template>
<el-dialog
v-model="innerVisible"
:title="dialogTitle"
width="800px"
:top="'5vh'"
:align-center="false"
>
<el-form :model="form" label-width="100px" :rules="rules">
<!-- 基本信息 -->
<div class="section-title">
<div class="section-line"></div>
<span class="title-text">基本信息</span>
</div>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="规则代码" prop="ruleCode" required>
<el-input v-model="form.ruleCode" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="规则名称" prop="ruleName" required>
<el-input v-model="form.ruleName" placeholder="请输入" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="是否内置" required>
<el-radio-group v-model="form.isBuiltin">
<el-radio :label="true">是</el-radio>
<el-radio :label="false">否</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.isBuiltin">
<el-form-item label="研发组织" required>
<el-select v-model="form.devOrg" placeholder="请选择">
<el-option label="研发一部" value="dev1" />
<el-option label="研发二部" value="dev2" />
<el-option label="PPMI-SBU1" value="PPMI-SBU1" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="描述">
<el-input v-model="form.desc" type="textarea" rows="3" />
</el-form-item>
<!-- 编码配置 -->
<div class="config-header">
<div class="section-title">
<div class="section-line"></div>
<span class="title-text">编码配置</span>
</div>
<el-button type="primary" class="add-button" @click="addSection">
<el-icon><Plus /></el-icon> 新增
</el-button>
</div>
<el-form-item label="编码示例">
<el-input v-model="form.example" disabled />
<div style="margin-top: 5px; color: #666;">
说明:1. 字段可以配置多个,2. 每个配置都必须填写
</div>
</el-form-item>
<!-- 使用vuedraggable实现拖拽排序 -->
<draggable
v-model="form.sections"
item-key="id"
handle=".drag-handle"
:animation="150"
ghost-class="ghost"
>
<template #item="{element, index}">
<div class="code-section" :class="`section-${index + 1}`">
<div class="section-header">
<div class="section-left">
<el-icon class="drag-handle"><Operation /></el-icon>
<span>编码{{ numberToChinese(index + 1) }}段</span>
</div>
<div class="section-right">
<el-select
v-model="element.type"
placeholder="请选择"
class="type-select"
>
<el-option label="常量" value="constant" />
<el-option label="日期" value="date" />
<el-option label="流水码" value="sequence" />
<el-option label="业务字段" value="business" />
</el-select>
<el-button
type="danger"
:icon="Delete"
circle
size="small"
@click="removeSection(index)"
class="delete-btn"
></el-button>
</div>
</div>
<!-- 不同类型的编码显示不同的表单项 -->
<div class="section-content">
<!-- 常量类型 -->
<template v-if="element.type === 'constant'">
<el-form-item label="设置值" required>
<el-input v-model="element.value" placeholder="请输入" />
</el-form-item>
</template>
<!-- 日期类型 -->
<template v-if="element.type === 'date'">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="日期格式" required>
<el-select v-model="element.dateFormat" placeholder="请选择">
<el-option label="年月日" value="yyyyMMdd" />
<el-option label="年月" value="yyyyMM" />
<el-option label="月日" value="MMdd" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="码制" required>
<el-select v-model="element.codeSystem" placeholder="请选择">
<el-option label="10进制" value="10" />
<el-option label="16进制" value="16" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="段间分隔符">
<el-select v-model="element.separator" placeholder="请选择">
<el-option label="-" value="-" />
<el-option label="_" value="_" />
<el-option label="/" value="/" />
<el-option label="无" value="" />
</el-select>
</el-form-item>
</template>
<!-- 流水码类型 -->
<template v-if="element.type === 'sequence'">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="长度" required>
<el-input v-model.number="element.length" type="number" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="步长" required>
<el-input v-model.number="element.step" type="number" placeholder="请输入" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="码制" required>
<el-select v-model="element.codeSystem" placeholder="请选择">
<el-option label="10进制" value="10" />
<el-option label="16进制" value="16" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="自动升位">
<el-switch
v-model="element.autoIncrement"
class="green-switch"
active-color="#67c23a"
inactive-color="#dcdfe6"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="段间分隔符">
<el-select v-model="element.separator" placeholder="请选择">
<el-option label="-" value="-" />
<el-option label="_" value="_" />
<el-option label="/" value="/" />
<el-option label="无" value="" />
</el-select>
</el-form-item>
</template>
<!-- 业务字段类型 -->
<template v-if="element.type === 'business'">
<el-form-item label="业务字段" required>
<el-select v-model="element.businessField" placeholder="请选择">
<el-option label="产品名称" value="productName" />
<el-option label="客户编号" value="customerCode" />
<el-option label="订单号" value="orderId" />
</el-select>
</el-form-item>
<el-form-item label="截取模式">
<el-select v-model="element.extractMode" placeholder="请选择">
<el-option label="前缀截取" value="prefix" />
<el-option label="后缀截取" value="suffix" />
<el-option label="无截取" value="none" />
</el-select>
</el-form-item>
<el-form-item label="段间分隔符">
<el-select v-model="element.separator" placeholder="请选择">
<el-option label="-" value="-" />
<el-option label="_" value="_" />
<el-option label="/" value="/" />
<el-option label="无" value="" />
</el-select>
</el-form-item>
</template>
</div>
</div>
</template>
</draggable>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="success" @click="submit">提交</el-button>
<el-button @click="innerVisible = false">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, watch, defineProps, defineEmits, computed } from 'vue'
import { Delete, Plus, Operation } from '@element-plus/icons-vue'
import draggable from 'vuedraggable'
const props = defineProps({
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: '新增'
},
isEdit: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:visible'])
const innerVisible = ref(props.visible)
const dialogTitle = computed(() => props.title)
watch(() => props.visible, val => {
innerVisible.value = val
})
watch(innerVisible, val => {
emit('update:visible', val)
})
// 将数字转换为中文数字
function numberToChinese(num) {
if (typeof num !== 'number') {
num = parseInt(num);
}
if (isNaN(num) || num < 1) {
return '一';
}
const digits = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
const positions = ['', '十', '百', '千', '万', '十万', '百万', '千万', '亿'];
// 处理1-10的数字
if (num >= 1 && num <= 10) {
if (num === 10) return '十';
return digits[num];
}
// 处理11-99的数字
if (num > 10 && num < 100) {
const tens = Math.floor(num / 10);
const ones = num % 10;
if (tens === 1) {
return ones > 0 ? '十' + digits[ones] : '十';
} else {
return ones > 0 ? digits[tens] + '十' + digits[ones] : digits[tens] + '十';
}
}
// 处理100以上的数字(保险起见,虽然一般不会有超过100个编码段)
let result = '';
const numStr = num.toString();
const len = numStr.length;
for (let i = 0; i < len; i++) {
const digit = parseInt(numStr[i]);
const pos = len - i - 1;
if (digit === 0) {
// 避免零零这样的重复
if (result.charAt(result.length - 1) !== '零') {
result += '零';
}
} else {
result += digits[digit] + positions[pos];
}
}
// 处理一些零的情况
result = result.replace(/零+$/, '');
result = result.replace(/零+/, '零');
return result || '零';
}
// 表单校验规则
const rules = {
ruleCode: [{ required: true, message: '请输入规则代码', trigger: 'blur' }],
ruleName: [{ required: true, message: '请输入规则名称', trigger: 'blur' }]
}
// 生成唯一ID
const generateId = () => {
return Date.now() + Math.floor(Math.random() * 1000)
}
// 默认的分隔符
const DEFAULT_SEPARATOR = '-'
const form = reactive({
ruleCode: 'LX202504001',
ruleName: '',
isBuiltin: true,
devOrg: 'PPMI-SBU1',
desc: '',
example: 'LX202504001',
sections: [
{
id: generateId(),
type: 'constant',
value: 'LX'
},
{
id: generateId(),
type: 'date',
dateFormat: 'yyyyMMdd',
codeSystem: '10',
separator: DEFAULT_SEPARATOR
},
{
id: generateId(),
type: 'sequence',
length: 3,
step: 1,
codeSystem: '10',
autoIncrement: true,
separator: DEFAULT_SEPARATOR
},
{
id: generateId(),
type: 'business',
businessField: 'productName',
extractMode: 'none',
separator: DEFAULT_SEPARATOR
}
]
})
// 添加新编码段
function addSection() {
form.sections.push({
id: generateId(),
type: 'constant',
value: '',
separator: DEFAULT_SEPARATOR
})
}
// 移除编码段
function removeSection(index) {
form.sections.splice(index, 1)
}
// 提交表单
function submit() {
// 表单提交逻辑
console.log('提交的表单数据:', form)
innerVisible.value = false
}
</script>
<style scoped>
.section-title {
display: flex;
align-items: center;
margin: 20px 0;
}
.section-line {
width: 4px;
height: 20px;
background-color: #409EFF;
margin-right: 8px;
border-radius: 2px;
}
.title-text {
font-size: 18px;
font-weight: 600;
}
.config-header {
display: flex;
align-items: center;
justify-content: space-between;
margin: 20px 0;
position: relative;
}
.divider-wrapper {
flex: 1;
}
.add-button {
z-index: 1;
position: absolute;
right: 0;
background-color: #67c23a;
border-color: #67c23a;
}
.code-section {
margin-bottom: 15px;
border: 1px solid #EBEEF5;
border-radius: 4px;
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 15px;
border-bottom: 1px dashed #EBEEF5;
background-color: #f0f9eb;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.section-left {
display: flex;
align-items: center;
}
.section-right {
display: flex;
align-items: center;
gap: 20px;
}
.type-select {
width: 120px;
}
.delete-btn {
background-color: #f56c6c;
border-color: #f56c6c;
}
.drag-handle {
cursor: move;
margin-right: 8px;
color: #909399;
}
.ghost {
opacity: 0.5;
background: #c8ebfb;
}
.section-content {
padding: 15px;
background-color: #ffffff;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
}
.green-switch :deep(.el-switch__core) {
background-color: #dcdfe6 !important;
border-color: #dcdfe6 !important;
}
.green-switch :deep(.el-switch__core):hover {
background-color: #dcdfe6 !important;
border-color: #dcdfe6 !important;
}
.green-switch.is-checked :deep(.el-switch__core) {
background-color: #67c23a !important;
border-color: #67c23a !important;
}
</style>
<script setup>
import { ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
import CodeConfigDialog from './components/CodeConfigDialog.vue'
import { Plus, Edit } from '@element-plus/icons-vue'
const showDialog = ref(false)
const dialogTitle = ref('新增')
function openDialog(title = '新增') {
dialogTitle.value = title
showDialog.value = true
}
</script>
<template>
<div class="container">
<div class="logo-container">
<a href="https://vite.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<HelloWorld msg="Vite + Vue" />
<div class="button-container">
<el-button type="primary" size="large" @click="openDialog()">
<el-icon><Plus /></el-icon> 打开编码配置弹窗
</el-button>
<el-button type="warning" size="large" @click="openDialog('编辑')">
<el-icon><Edit /></el-icon> 编辑编码配置
</el-button>
</div>
<CodeConfigDialog v-model:visible="showDialog" :title="dialogTitle" />
</div>
</template>
<style scoped>
.container {
display: flex;
flex-direction: column;
align-items: center;
padding: 2rem;
text-align: center;
}
.logo-container {
display: flex;
margin-bottom: 2rem;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
.button-container {
margin-top: 2rem;
display: flex;
gap: 1rem;
}
</style>
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import './style.css'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
:root {
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

浙公网安备 33010602011771号