mirror of
https://github.com/purocean/yn.git
synced 2026-09-24 15:46:02 +08:00
增加图片粘贴
This commit is contained in:
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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,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)
|
||||
}
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,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(`})\n`)
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
Reference in New Issue
Block a user