242 lines
6.0 KiB
Vue
242 lines
6.0 KiB
Vue
<template>
|
|
<el-dialog
|
|
v-model="visible"
|
|
width="60%"
|
|
:top="'30px'"
|
|
:close-on-click-modal="false"
|
|
:close-on-press-escape="false"
|
|
:show-close="false"
|
|
center
|
|
custom-class="container"
|
|
@closed="handleClosed"
|
|
>
|
|
<template #header>
|
|
<div class="title">
|
|
{{ filename }}
|
|
<!-- {{ filename }} - <span>{{ status }}</span> -->
|
|
</div>
|
|
</template>
|
|
<codemirror
|
|
v-model="code"
|
|
placeholder="Code goes here..."
|
|
:style="{ height: '79vh', minHeight: '500px' }"
|
|
:autofocus="true"
|
|
:indent-with-tab="true"
|
|
:tab-size="4"
|
|
:extensions="extensions"
|
|
@ready="status = '准备中'"
|
|
@change="handleChange"
|
|
@focus="status = '编辑中'"
|
|
@blur="status = '未聚焦'"
|
|
/>
|
|
<template #footer>
|
|
<footer>
|
|
<div class="select_wrap">
|
|
<el-select v-model="curLang" placeholder="Select language">
|
|
<el-option
|
|
v-for="item in languageKey"
|
|
:key="item"
|
|
:label="item"
|
|
:value="item"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
<div class="footer_btns">
|
|
<el-button type="primary" :loading="loading" @click="handleSave">保存</el-button>
|
|
<el-button type="info" @click="handleClose">关闭</el-button>
|
|
</div>
|
|
</footer>
|
|
</template>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script>
|
|
import { Codemirror } from 'vue-codemirror'
|
|
import { oneDark } from '@codemirror/theme-one-dark'
|
|
import languages from './languages'
|
|
import { sortString, getSuffix } from '@/utils'
|
|
|
|
const languageKey = sortString(Object.keys(languages))
|
|
// console.log('languages: ', languageKey)
|
|
|
|
export default {
|
|
name: 'CodeEdit',
|
|
components: {
|
|
Codemirror
|
|
},
|
|
props: {
|
|
show: {
|
|
required: true,
|
|
type: Boolean
|
|
},
|
|
originalCode: {
|
|
required: true,
|
|
type: String
|
|
},
|
|
filename: {
|
|
required: true,
|
|
type: String
|
|
}
|
|
},
|
|
emits: ['update:show', 'save', 'closed',],
|
|
data() {
|
|
return {
|
|
languageKey,
|
|
curLang: null,
|
|
status: '准备中',
|
|
loading: false,
|
|
isTips: false,
|
|
code: 'hello world'
|
|
}
|
|
},
|
|
computed: {
|
|
extensions() {
|
|
let res = []
|
|
if(this.curLang) res.push(languages[this.curLang]())
|
|
res.push(oneDark)
|
|
return res
|
|
},
|
|
visible: {
|
|
get() {
|
|
return this.show
|
|
},
|
|
set(newVal) {
|
|
this.$emit('update:show', newVal)
|
|
}
|
|
}
|
|
},
|
|
watch: {
|
|
originalCode(newVal) {
|
|
this.code = newVal
|
|
},
|
|
filename(newVal) {
|
|
try {
|
|
let name = String(newVal).toLowerCase()
|
|
let suffix = getSuffix(name)
|
|
switch(suffix) {
|
|
case 'js': return this.curLang = 'javascript'
|
|
case 'ts': return this.curLang = 'typescript'
|
|
case 'jsx': return this.curLang = 'jsx'
|
|
case 'tsx': return this.curLang = 'tsx'
|
|
case 'html': return this.curLang = 'html'
|
|
case 'css': return this.curLang = 'css'
|
|
case 'json': return this.curLang = 'json'
|
|
case 'swift': return this.curLang = 'swift'
|
|
case 'yaml': return this.curLang = 'yaml'
|
|
case 'yml': return this.curLang = 'yaml'
|
|
case 'vb': return this.curLang = 'vb'
|
|
case 'dockerfile': return this.curLang = 'dockerFile'
|
|
case 'sh': return this.curLang = 'shell'
|
|
case 'r': return this.curLang = 'r'
|
|
case 'ruby': return this.curLang = 'ruby'
|
|
case 'go': return this.curLang = 'go'
|
|
case 'julia': return this.curLang = 'julia'
|
|
case 'conf': return this.curLang = 'shell'
|
|
case 'cpp': return this.curLang = 'cpp'
|
|
case 'java': return this.curLang = 'java'
|
|
case 'xml': return this.curLang = 'xml'
|
|
case 'php': return this.curLang = 'php'
|
|
case 'sql': return this.curLang = 'sql'
|
|
case 'md': return this.curLang = 'markdown'
|
|
case 'py': return this.curLang = 'python'
|
|
default:
|
|
// console.log('不支持的文件类型: ', newVal)
|
|
// console.log('默认: ', 'shell')
|
|
return this.curLang = 'shell'
|
|
}
|
|
} catch (error) {
|
|
console.log('未知文件类型', newVal, error)
|
|
}
|
|
}
|
|
},
|
|
created() {
|
|
},
|
|
methods: {
|
|
handleSave() {
|
|
if(this.isTips) {
|
|
this.$messageBox.confirm( '文件已变更, 确认保存?', 'Warning', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
})
|
|
.then(async () => {
|
|
this.visible = false
|
|
this.$emit('save', this.code)
|
|
})
|
|
} else {
|
|
this.visible = false
|
|
}
|
|
},
|
|
handleClosed() {
|
|
this.isTips = false
|
|
this.$emit('closed')
|
|
},
|
|
handleClose() {
|
|
if(this.isTips) {
|
|
this.$messageBox.confirm( '文件已变更, 确认丢弃?', 'Warning', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
})
|
|
.then(async () => {
|
|
this.visible = false
|
|
})
|
|
} else {
|
|
this.visible = false
|
|
}
|
|
},
|
|
handleChange() {
|
|
this.isTips = true
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
</style>
|
|
|
|
<style lang="scss">
|
|
.container {
|
|
.el-dialog__header {
|
|
padding: 5px 0;
|
|
.title {
|
|
color: #409eff;
|
|
text-align: left;
|
|
padding-left: 10px;
|
|
font-size: 13px;
|
|
}
|
|
}
|
|
.el-dialog__body {
|
|
padding: 0;
|
|
.cm-scroller {
|
|
// 滚动条整体部分
|
|
&::-webkit-scrollbar {
|
|
height: 4px;
|
|
width: 4px;
|
|
background-color: #282c34;
|
|
}
|
|
// 底层轨道
|
|
&::-webkit-scrollbar-track {
|
|
background-color: #282c34;
|
|
border-radius: 3px;
|
|
}
|
|
}
|
|
}
|
|
.el-dialog__footer {
|
|
padding: 10px 0;
|
|
}
|
|
footer {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 0 15px;
|
|
justify-content: space-between;
|
|
}
|
|
}
|
|
.select_wrap {
|
|
width: 150px;
|
|
margin-right: 15px;
|
|
}
|
|
.footer_btns {
|
|
margin-top: 15px;
|
|
}
|
|
</style> |