feat: 支持用手机标注ner
This commit is contained in:
parent
ac1d2d41e4
commit
71435a451a
|
@ -1,4 +1,4 @@
|
||||||
# dw-tool-ner
|
# whale-anno
|
||||||
|
|
||||||
> Datawhale's ner tool.
|
> Datawhale's ner tool.
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Various Dev Server settings
|
// Various Dev Server settings
|
||||||
host: 'localhost', // can be overwritten by process.env.HOST
|
host: '0.0.0.0', // can be overwritten by process.env.HOST
|
||||||
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
|
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
|
||||||
autoOpenBrowser: false,
|
autoOpenBrowser: false,
|
||||||
errorOverlay: true,
|
errorOverlay: true,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>dw-tool-ner</title><link href=/static/css/app.cb359e49664391241f41c3263ba7c710.css rel=stylesheet></head><body><div id=app></div><style>html, body {
|
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>whale-anno</title><link href=/static/css/app.cb359e49664391241f41c3263ba7c710.css rel=stylesheet></head><body><div id=app></div><style>html, body {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||||||
<title>dw-tool-ner</title>
|
<title>whale-anno</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
@ -15,6 +15,9 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
button, input, span {
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -43,7 +43,24 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="ner-box" class="ner-box" @mouseup="setMode('')" @mouseleave="setMode('');setFocus('')" @keydown="setTypeByFastKey" @mouseover="setFocus('ner-box')">
|
<div id="ner-box" class="ner-box" @mouseup="setMode('')" @touchend="setMode('')" @mouseleave="setMode('');setFocus('')" @keydown="setTypeByFastKey" @mouseover="setFocus('ner-box')">
|
||||||
|
<!-- <svg style=" position: absolute; z-index: 99999999; overflow: unset; pointer-events: none">
|
||||||
|
<template class="rect" v-for="(word, idx) in nowNers" >
|
||||||
|
<template v-for="(w, i) in word.name">
|
||||||
|
<line
|
||||||
|
v-if="i === 0 || ((word.start%columnWordCount)+i) % columnWordCount === 0"
|
||||||
|
:key="`${word}${w}${i}`"
|
||||||
|
:x1="`${((word.start+i)%columnWordCount)*20 + (word.isSmall && i === 0 ? 2 : 0)}px`"
|
||||||
|
:y1="`${((word.start+i)/columnWordCount|0)*35 + (word.isSmall ? 0 : -2)}px`"
|
||||||
|
:x2="`${((Math.min(word.end-(word.start+i), columnWordCount, columnWordCount - (word.start+i)%columnWordCount))*20 - (word.isSmall && i === 0 ? 4 : 0)) + ((word.start+i)%columnWordCount)*20 + (word.isSmall && i === 0 ? 2 : 0)}px`"
|
||||||
|
:y2="`${word.isSmall?18:22+((word.start+i)/columnWordCount|0)*35 + (word.isSmall ? 0 : -2)}px`"
|
||||||
|
style="stroke:rgb(255,0,0);stroke-width:2"
|
||||||
|
></line>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
<text x="201" y="10" fill="red">关系一</text>
|
||||||
|
</svg> -->
|
||||||
<div class="word-rect-area">
|
<div class="word-rect-area">
|
||||||
<span class="rect" v-for="(word, idx) in nowNers" :key="idx">
|
<span class="rect" v-for="(word, idx) in nowNers" :key="idx">
|
||||||
<span v-for="(w, i) in word.name" :key="`${word}${w}${i}`">
|
<span v-for="(w, i) in word.name" :key="`${word}${w}${i}`">
|
||||||
|
@ -77,7 +94,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="projectType === '命名实体识别'">
|
<div v-if="projectType === '命名实体识别'">
|
||||||
<span class="word" v-for="(word, idx) in nowText" :key="idx" @contextmenu="stopPrev" @mousedown="startSelect(idx, $event)" @mousemove="pointWord(idx)"
|
<span class="word" v-for="(word, idx) in nowText" :key="idx" :id="idx" @contextmenu="stopPrev" @mousedown="startSelect(idx, $event)" @touchstart="startSelect(idx, $event)" @mousemove="pointWord(idx)" @touchmove="pointWordByTouch($event)"
|
||||||
>
|
>
|
||||||
{{ word }}
|
{{ word }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -90,8 +107,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-btn-box">
|
<div class="page-btn-box">
|
||||||
<button class="page-btn" @click="changeIdx(-1)" @mouseover="setFocus('page-up')" @mouseleave="setFocus('')">上一个 {{ fastTypeKey['page-up'] ? `【${fastTypeKey['page-up']}】` : '' }}</button>
|
<button class="page-btn" @click="changeIdx(-1, $event)" @mouseover="setFocus('page-up')" @mouseleave="setFocus('')">上一个 {{ fastTypeKey['page-up'] ? `【${fastTypeKey['page-up']}】` : '' }}</button>
|
||||||
<button class="page-btn" @click="changeIdx(+1)" @mouseover="setFocus('page-down')" @mouseleave="setFocus('')">下一个 {{ fastTypeKey['page-down'] ? `【${fastTypeKey['page-down']}】` : '' }}</button>
|
<button class="page-btn" @click="changeIdx(+1, $event)" @mouseover="setFocus('page-down')" @mouseleave="setFocus('')">下一个 {{ fastTypeKey['page-down'] ? `【${fastTypeKey['page-down']}】` : '' }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="result-box">
|
<div class="result-box">
|
||||||
|
@ -316,7 +333,10 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changeIdx: function (d) {
|
changeIdx: function (d, event) {
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault() // 防止手机双击放大屏幕
|
||||||
|
}
|
||||||
const nowIdx = this.files.indexOf(this.nowFile)
|
const nowIdx = this.files.indexOf(this.nowFile)
|
||||||
let newIdx = nowIdx + d
|
let newIdx = nowIdx + d
|
||||||
if (newIdx < 0) newIdx = 0
|
if (newIdx < 0) newIdx = 0
|
||||||
|
@ -328,6 +348,7 @@ export default {
|
||||||
* @param idx 点击文字的定位
|
* @param idx 点击文字的定位
|
||||||
*/
|
*/
|
||||||
pointWord: function (idx, config = {}) {
|
pointWord: function (idx, config = {}) {
|
||||||
|
console.log(this.mode, idx, config)
|
||||||
if (this.mode === 'select') {
|
if (this.mode === 'select') {
|
||||||
if (!this.nowType) {
|
if (!this.nowType) {
|
||||||
alert('请先选择标签')
|
alert('请先选择标签')
|
||||||
|
@ -342,6 +363,14 @@ export default {
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
pointWordByTouch: function (event) {
|
||||||
|
event.preventDefault() // 防止触发页面下拉
|
||||||
|
let {pageX, pageY} = event.touches[0]
|
||||||
|
let dom = document.elementFromPoint(pageX, pageY)
|
||||||
|
if (dom && dom.id) {
|
||||||
|
this.pointWord(dom.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 配置标注类型
|
* 配置标注类型
|
||||||
* @param 类型
|
* @param 类型
|
||||||
|
@ -457,7 +486,19 @@ export default {
|
||||||
},
|
},
|
||||||
startSelect: function (idx, event) {
|
startSelect: function (idx, event) {
|
||||||
if (this.projectType !== '命名实体识别') return
|
if (this.projectType !== '命名实体识别') return
|
||||||
|
let isNeedDel = false
|
||||||
|
if (event.touches) {
|
||||||
|
// 手机双击删除
|
||||||
|
if (this.startSelectTouchTs && Date.now() - this.startSelectTouchTs < 300) {
|
||||||
|
isNeedDel = true
|
||||||
|
}
|
||||||
|
this.startSelectTouchTs = Date.now()
|
||||||
|
}
|
||||||
if (event.which === 3) {
|
if (event.which === 3) {
|
||||||
|
// 电脑右键删除
|
||||||
|
isNeedDel = true
|
||||||
|
}
|
||||||
|
if (isNeedDel) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
// 右键删除对应的图标
|
// 右键删除对应的图标
|
||||||
const ners = this.ners
|
const ners = this.ners
|
||||||
|
@ -494,6 +535,7 @@ export default {
|
||||||
}
|
}
|
||||||
const isRepeat = this.checkIsRepeat(this.nowNer)
|
const isRepeat = this.checkIsRepeat(this.nowNer)
|
||||||
if (!isRepeat && this.nowNer.isMove) {
|
if (!isRepeat && this.nowNer.isMove) {
|
||||||
|
console.log(this.nowNer)
|
||||||
delete this.nowNer.isMove
|
delete this.nowNer.isMove
|
||||||
this.ners.push(this.nowNer)
|
this.ners.push(this.nowNer)
|
||||||
this.$set(this, 'ners', this.ners.sort((a, b) => {
|
this.$set(this, 'ners', this.ners.sort((a, b) => {
|
||||||
|
@ -963,4 +1005,22 @@ export default {
|
||||||
top: -9px;
|
top: -9px;
|
||||||
right: -9px;
|
right: -9px;
|
||||||
}
|
}
|
||||||
|
@media only screen and (max-width: 800px) {
|
||||||
|
.out-title {
|
||||||
|
text-align: right !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
.out-title {
|
||||||
|
font-size: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media only screen and (max-width: 800px) {
|
||||||
|
.result-box {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.left {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -290,6 +290,7 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1 1;
|
flex: 1 1;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
margin: 0 10px;
|
||||||
/* height: calc(100% - 92px); */
|
/* height: calc(100% - 92px); */
|
||||||
}
|
}
|
||||||
.button {
|
.button {
|
||||||
|
|
Loading…
Reference in New Issue