增加图片粘贴

This commit is contained in:
Yang
2018-02-11 21:06:12 +08:00
parent 7c31080856
commit e083379c3a
8 changed files with 114 additions and 23 deletions
+4
View File
@@ -98,6 +98,10 @@ exports.mv = (oldPath, newPath) => {
}
}
exports.upload = (file, path) => {
exports.write(path, fs.readFileSync(file.path))
}
exports.tree = () => {
return [{
name: '/',
+23 -4
View File
@@ -1,13 +1,14 @@
const Koa = require('koa')
const bodyParser = require('koa-body')
const mime = require('mime')
const file = require('./file')
const bodyParser = require('koa-bodyparser')
const result = (status = 'ok', message = '操作成功', data = null) => {
return { status, message, data }
}
const fileContent = ctx => {
const fileContent = (ctx, next) => {
if (ctx.path === '/api/file') {
if (ctx.method === 'GET') {
ctx.body = result('ok', '获取成功', file.read(ctx.query.path).toString())
@@ -23,12 +24,30 @@ const fileContent = ctx => {
}
} else if (ctx.path === '/api/tree') {
ctx.body = result('ok', '获取成功', file.tree())
} else {
next()
}
}
const attachment = (ctx, next) => {
if (ctx.path.startsWith('/api/attachment')) {
if (ctx.method === 'POST') {
const path = ctx.request.body.fields.path
file.upload(ctx.request.body.files.attachment, path)
ctx.body = result('ok', '上传成功', path)
} else if (ctx.method === 'GET') {
ctx.type = mime.getType(ctx.query.path)
ctx.body = file.read(ctx.query.path)
}
} else {
next()
}
}
const app = new Koa()
app.use(bodyParser())
app.use(async ctx => fileContent(ctx))
app.use(bodyParser({multipart: true}))
app.use(async (ctx, next) => fileContent(ctx, next))
app.use(async (ctx, next) => attachment(ctx, next))
app.listen(3000)
+2 -1
View File
@@ -1,6 +1,7 @@
{
"dependencies": {
"koa": "^2.4.1",
"koa-bodyparser": "^4.2.0"
"koa-body": "^2.5.0",
"mime": "^2.2.0"
}
}
+14 -10
View File
@@ -17,7 +17,7 @@ bytes@3.0.0:
version "3.0.0"
resolved "http://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
co-body@^5.1.0:
co-body@^5.1.1:
version "5.1.1"
resolved "http://registry.npm.taobao.org/co-body/download/co-body-5.1.1.tgz#d97781d1e3344ba4a820fd1806bddf8341505236"
dependencies:
@@ -45,10 +45,6 @@ cookies@~0.7.0:
depd "~1.1.1"
keygrip "~1.0.2"
copy-to@^2.0.1:
version "2.0.1"
resolved "http://registry.npm.taobao.org/copy-to/download/copy-to-2.0.1.tgz#2680fbb8068a48d08656b6098092bdafc906f4a5"
debug@*:
version "3.1.0"
resolved "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
@@ -87,6 +83,10 @@ escape-html@~1.0.1:
version "1.0.3"
resolved "http://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
formidable@^1.1.1:
version "1.1.1"
resolved "http://registry.npm.taobao.org/formidable/download/formidable-1.1.1.tgz#96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9"
fresh@^0.5.2:
version "0.5.2"
resolved "http://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@@ -127,12 +127,12 @@ keygrip@~1.0.2:
version "1.0.2"
resolved "http://registry.npm.taobao.org/keygrip/download/keygrip-1.0.2.tgz#ad3297c557069dea8bcfe7a4fa491b75c5ddeb91"
koa-bodyparser@^4.2.0:
version "4.2.0"
resolved "http://registry.npm.taobao.org/koa-bodyparser/download/koa-bodyparser-4.2.0.tgz#bce6e08bc65f8709b6d1faa9411c7f0d8938aa54"
koa-body@^2.5.0:
version "2.5.0"
resolved "http://registry.npm.taobao.org/koa-body/download/koa-body-2.5.0.tgz#84e8fcd8d5229a8cc1cb98a926e939069e716915"
dependencies:
co-body "^5.1.0"
copy-to "^2.0.1"
co-body "^5.1.1"
formidable "^1.1.1"
koa-compose@^3.0.0:
version "3.2.1"
@@ -198,6 +198,10 @@ mime-types@^2.0.7, mime-types@~2.1.15, mime-types@~2.1.16:
dependencies:
mime-db "~1.30.0"
mime@^2.2.0:
version "2.2.0"
resolved "http://registry.npm.taobao.org/mime/download/mime-2.2.0.tgz#161e541965551d3b549fa1114391e3a3d55b923b"
ms@2.0.0:
version "2.0.0"
resolved "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+25
View File
@@ -25,6 +25,9 @@ export default {
this.onGotAmdLoader()
}
},
beforeDestroy () {
window.removeEventListener('paste', this.paste)
},
methods: {
onGotAmdLoader () {
window.require(['vs/editor/editor.main'], () => {
@@ -44,6 +47,7 @@ export default {
})
this.keyBind()
window.addEventListener('paste', this.paste)
},
keyBind () {
const KM = window.monaco.KeyMod
@@ -85,6 +89,27 @@ export default {
// console.log(this.editor.getModel().getLineContent(this.editor.getPosition().lineNumber))
// })
},
paste (e) {
if (this.editor.isFocused()) {
const items = e.clipboardData.items
for (let i = 0; i < items.length; i++) {
let matches = items[i].type.match(/^image\/(png|jpg|jpeg|gif)$/i)
if (matches) {
this.$emit('paste-img', items[i].getAsFile())
}
}
}
},
insert (text) {
const selection = this.editor.getSelection()
this.editor.executeEdits('', [
{
range: new window.monaco.Range(selection.endLineNumber, selection.endColumn, selection.endLineNumber, selection.endColumn),
text,
forceMoveMarkers: true
}
])
},
setValue (val) {
this.editor.getModel().setValue(val)
}
+10 -6
View File
@@ -1,6 +1,6 @@
<template>
<div class="tree-node">
<details open v-if="item.type === 'dir'">
<details :open="item.name !== 'FILES'" v-if="item.type === 'dir'">
<summary
:style="{background: selected ? '#eee' : 'none'}"
@dblclick="createFile()"
@@ -45,13 +45,17 @@ export default {
},
methods: {
select (f) {
this.$nextTick(() => {
setTimeout(() => {
this.selected = true
if (f.name.endsWith('.md')) {
this.$nextTick(() => {
setTimeout(() => {
this.selected = true
})
})
})
this.$emit('select', f)
this.$emit('select', f)
} else {
window.open(`api/attachment/${f.name}?path=${encodeURIComponent(f.path)}`)
}
},
createFile () {
let filename = window.prompt(`[${this.item.path}] 文件名`, 'new.md')
+23
View File
@@ -125,5 +125,28 @@ export default {
}
})
})
},
upload: (belongPath, file, call) => {
const fr = new FileReader()
fr.readAsBinaryString(file)
fr.onloadend = () => {
const filename = CryptoJS.MD5(CryptoJS.enc.Latin1.parse(fr.result)).toString().substr(0, 8) +
file.name.substr(file.name.lastIndexOf('.'))
const formData = new FormData()
formData.append('path', belongPath.replace(/\\/g, '/').replace(/\/([^/]*)$/, '/FILES/$1/' + filename))
formData.append('attachment', file)
fetch('/api/attachment', {
method: 'POST',
body: formData
}).then(response => {
response.json().then(result => {
if (result.status === 'ok') {
call(result.data)
}
})
})
}
}
}
+13 -2
View File
@@ -13,8 +13,13 @@
</div>
</header>
<div style="display: flex; justify-content: space-between;">
<Tree class="tree" v-model="file"></Tree>
<Editor ref="editor" class="editor" v-model="value" @save="saveFile"></Editor>
<Tree ref="tree" class="tree" v-model="file"></Tree>
<Editor
ref="editor"
class="editor"
v-model="value"
@paste-img="pasteImg"
@save="saveFile"></Editor>
<XView class="view" :value="value"></XView>
</div>
</div>
@@ -78,6 +83,12 @@ export default {
this.file = null
alert(e.message)
})
},
pasteImg (file) {
File.upload(this.file.path, file, filePath => {
this.$refs.tree.change()
this.$refs.editor.insert(`![图片](api/attachment?path=${encodeURIComponent(filePath)})\n`)
})
}
},
watch: {