From 69fcd22ffd1dbd4bd58935cb1527f1b1b1654d4b Mon Sep 17 00:00:00 2001 From: maxmon <541182180@qq.com> Date: Mon, 10 May 2021 00:02:23 +0800 Subject: [PATCH] =?UTF-8?q?v1.2.7=201=E3=80=81+=20=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E9=80=89=E4=B8=AD=E7=AC=AC=E4=B8=80=E4=B8=AA=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=EF=BC=9B=202=E3=80=81+=20=E5=B7=B2=E6=A0=87=E6=B3=A8=E7=9A=84?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E5=B1=95=E7=A4=BA=E9=A6=962=E5=AD=97?= =?UTF-8?q?=EF=BC=8C=E9=98=B2=E6=AD=A2=E8=BF=87=E9=95=BF=EF=BC=9B=203?= =?UTF-8?q?=E3=80=81+=20=E6=A0=87=E6=B3=A8=E8=BF=87=E9=95=BF=E7=9A=84?= =?UTF-8?q?=EF=BC=8C=E6=8C=89...=E5=B1=95=E7=A4=BA=EF=BC=9B=20v1.2.6=201?= =?UTF-8?q?=E3=80=81+=20=E6=8C=89=E6=9C=8D=E5=8A=A1=E5=99=A8=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E6=98=BE=E7=A4=BA=E6=98=AF=E5=90=A6=E6=A0=87=E6=B3=A8?= =?UTF-8?q?=EF=BC=9B=202=E3=80=81+=20=E9=99=90=E5=88=B6=E6=B2=A1=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E5=AE=8C=E4=B8=8D=E8=83=BD=E5=88=87=E6=8D=A2=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=9B=203=E3=80=81^=20=E4=BF=AE=E5=A4=8D=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E5=AE=9E=E4=BD=93=E7=B1=BB=E5=9E=8B=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=80=BC=EF=BC=8C=E7=BD=AE=E7=A9=BA=EF=BC=9B=20v1.2.5=201?= =?UTF-8?q?=E3=80=81+=20=E5=BF=AB=E6=8D=B7=E9=94=AE=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E7=BC=93=E5=AD=98=EF=BC=9B=202=E3=80=81+=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=95=B4=E4=BD=93=E6=A0=87=E6=B3=A8=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E6=9D=A1=EF=BC=9B=203=E3=80=81+=20Eacape=E5=8F=AF?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=8C=89=E9=92=AE=E5=BF=AB=E6=8D=B7=E9=94=AE?= =?UTF-8?q?=EF=BC=9B=204=E3=80=81^=20=E5=B7=B2=E6=A0=87=E6=B3=A8=E7=9A=84?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A2=9E=E5=8A=A0checked=E5=9B=BE=E6=A0=87?= =?UTF-8?q?=EF=BC=9B=205=E3=80=81^=20=E5=AE=9E=E4=BD=93=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E6=96=87=E6=9C=AC=E5=B1=85=E4=B8=AD=EF=BC=9B?= =?UTF-8?q?=206=E3=80=81^=20=E5=AE=9E=E4=BD=93=E7=B1=BB=E5=9E=8B=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=AE=9E=E6=97=B6=E7=94=9F=E6=95=88=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E6=97=B6=E7=94=9F=E6=95=88=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/config/index.js | 2 +- fe/src/components/NER/index.vue | 105 ++++++++++++++++++++++++++----- fe/src/components/home/index.vue | 15 ----- 3 files changed, 89 insertions(+), 33 deletions(-) diff --git a/fe/config/index.js b/fe/config/index.js index 86e3578..c63faf8 100644 --- a/fe/config/index.js +++ b/fe/config/index.js @@ -54,7 +54,7 @@ module.exports = { // Paths assetsRoot: path.resolve(__dirname, '../dist'), assetsSubDirectory: 'static', - assetsPublicPath: '/dw-tool-ner/v1.2.4/', + assetsPublicPath: '/dw-tool-ner/v1.2.7/', /** * Source Maps diff --git a/fe/src/components/NER/index.vue b/fe/src/components/NER/index.vue index a4f252b..e78547b 100644 --- a/fe/src/components/NER/index.vue +++ b/fe/src/components/NER/index.vue @@ -6,10 +6,12 @@
{{ file }} +
+
上页 @@ -30,7 +32,7 @@ @mouseleave="setFocus('')" > - + {{ type }} {{ fastTypeKey[type] ? `【${fastTypeKey[type]}】` : '' }} @@ -90,7 +92,7 @@ backgroundColor: types[ner.type] ? types[ner.type].color : `#fff`, }" > - {{ ner.type }} + {{ ner.type.substr(0,2) }} {{ ner.name }}
@@ -130,9 +132,6 @@ function query (method, url, data = '', cb) { } xhr.send(JSON.stringify(data)) } -get('/v1/index', function (data) { - console.log('data', data) -}) function updateType2Server (projectName, typeList, types) { const entityTypes = typeList.map((type) => { return { @@ -167,11 +166,12 @@ export default { nowText: '', // 当前的文件文本 ners: [], // 当前文件已标注的实体 nowNer: {}, // 当前鼠标正在标注的实体 - nowType: 'person', // 当前选择的实体类型 + nowType: '', // 当前选择的实体类型 typeList: ['person', 'location', 'organiztion'], // 实体类型可选列表 + isAnnoDic: {}, // 服务器是否返回已标注过 nowFocus: '', // 鼠标当前位置的对象,比如标注框/类型按钮/翻页按钮 - fastKeyType: {}, // 快捷键对应的类型 - fastTypeKey: {}, // 类型对应的快捷键 + fastKeyType: localStorage.fastKeyType ? JSON.parse(localStorage.fastKeyType) : {}, // 快捷键对应的类型 + fastTypeKey: localStorage.fastTypeKey ? JSON.parse(localStorage.fastTypeKey) : {}, // 类型对应的快捷键 types: { // 类型对应的属性 'person': { color: '#e61490' @@ -200,6 +200,21 @@ export default { return [...this.ners, this.nowNer] } return this.ners + }, + processRate: function () { + const files = this.files || [] + if (!files.length) return 0 + const nersCache = this.nersCache || {} + const projectName = this.projectName || '' + const isAnnoDic = this.isAnnoDic || {} + let cnt = 0 + for (let i = 0; i < files.length; i += 1) { + const file = files[i] + if (isAnnoDic[`${projectName}_${file}`] || (nersCache[file] && nersCache[file].length)) { + cnt += 1 + } + } + return cnt / files.length } }, methods: { @@ -208,7 +223,11 @@ export default { if (that.pageNumber > 1) { that.pageNumber = that.pageNumber - 1 get(`/v1/files/query?projectName=${that.projectName}&pageNumber=${that.pageNumber}&pageSize=${that.pageSize}`, function (info) { - that.$set(that, 'files', info) + that.$set(that, 'files', info.map((item) => { + if (typeof item === 'string') return item + that.isAnnoDic[`${that.projectName}_${item.fileName}`] = item.isAnno + return item.fileName + })) }) } }, @@ -217,7 +236,11 @@ export default { if (that.files.length === that.pageSize) { that.pageNumber = that.pageNumber + 1 get(`/v1/files/query?projectName=${that.projectName}&pageNumber=${that.pageNumber}&pageSize=${that.pageSize}`, function (info) { - that.$set(that, 'files', info) + that.$set(that, 'files', info.map((item) => { + if (typeof item === 'string') return item + that.isAnnoDic[`${that.projectName}_${item.fileName}`] = item.isAnno + return item.fileName + })) }) } }, @@ -225,6 +248,14 @@ export default { this.$router.push({path: '/'}) }, save: function () { + if (window.isLoadingNowText) { + if (Date.now() - window.isLoadingNowText < 30 * 1000) { + alert('请等待文件内容加载') + return false + } else { + delete window.isLoadingNowText + } + } const that = this // 保存当前标注 post('/v1/anno/create', { @@ -233,6 +264,7 @@ export default { annoDetails: JSON.stringify(that.ners) }) that.$set(that.nersCache, that.nowFile, [...that.ners]) + return true }, /** * 选中目标文件 @@ -240,13 +272,16 @@ export default { */ setNowText: function (newFile) { const that = this - that.save() + const isSaved = that.save() + if (!isSaved) return false + window.isLoadingNowText = Date.now() that.nowFile = newFile that.nowText = that.textDic[newFile] const hasCache = !!that.nersCache[newFile] that.$set(that, 'ners', that.nersCache[newFile] ? [...that.nersCache[newFile]] : []) that.flushWordsType() get(`/v1/anno/query?projectName=${that.projectName}&fileName=${newFile}`, function (info) { + delete window.isLoadingNowText // 如果本地没有缓存,就用线上的标注记录 if (!hasCache && info.annoDetails) { that.$set(that, 'ners', JSON.parse(info.annoDetails)) @@ -271,6 +306,10 @@ export default { */ pointWord: function (idx, config = {}) { if (this.mode === 'select') { + if (!this.nowType) { + alert('请先选择标签') + return false + } this.endIdx = idx const type = this.nowType const start = Math.min(this.startIdx, this.endIdx) @@ -408,6 +447,9 @@ export default { return false }, endSelect: function () { + if (!this.nowType) { + return false + } const isRepeat = this.checkIsRepeat(this.nowNer) if (!isRepeat && this.nowNer.isMove) { delete this.nowNer.isMove @@ -516,7 +558,6 @@ export default { }, mounted () { const that = this - console.log(that.$route) const { projectName, projectType, entityTypes } = that.$route.query if (projectName) { that.projectName = projectName @@ -531,8 +572,14 @@ export default { return entityType.type }) that.types = types + // 进入时默认选择第一个标签,防止弹出请选择标签的提示 + if (that.typeList && that.typeList[0]) that.nowType = that.typeList[0] get(`/v1/files/query?projectName=${projectName}&pageNumber=${that.pageNumber}&pageSize=${that.pageSize}`, function (info) { - that.$set(that, 'files', info) + that.$set(that, 'files', info.map((item) => { + if (typeof item === 'string') return item + that.isAnnoDic[`${that.projectName}_${item.fileName}`] = item.isAnno + return item.fileName + })) }) } function calcColumnWordCount () { @@ -570,8 +617,8 @@ export default { if (oldKey) { that.$set(that.fastKeyType, oldKey, undefined) } - // 保存新的快捷键 - that.$set(that.fastKeyType, key, that.nowFocus) + // 保存新的快捷键,按Eacape可以起到删除快捷键的作用 + if (key !== 'Escape') that.$set(that.fastKeyType, key, that.nowFocus) // 计算新的 类型->键 关系 const typeKey = {} for (const key in that.fastKeyType) { @@ -579,6 +626,8 @@ export default { typeKey[type] = key } that.$set(that, 'fastTypeKey', typeKey) + localStorage.fastKeyType = JSON.stringify(that.fastKeyType) + localStorage.fastTypeKey = JSON.stringify(that.fastTypeKey) } } } @@ -638,8 +687,15 @@ export default { cursor: pointer; } .left .file.checked { + position: relative; color: #ccc; } +.left .file .checked-icon { + position: absolute; + right: 2px; + top: 0; + bottom: 0; +} .left .file.selected { background: #033271; z-index: 5; @@ -648,6 +704,12 @@ export default { overflow: auto; height: calc(100% - 82px); } +.left .file-list .process-bar { + position: absolute; + top: 0; + border-top: 2px solid #35e558; + transition: 0.3s width linear; +} .left .out-btn, .left .page-ctl { position: absolute; @@ -720,9 +782,9 @@ export default { .type { position: relative; box-sizing: content-box; - /* box-shadow: 2px 2px 0px #ccc; */ border: 1px solid #ccc; border-bottom: 3px solid #ccc; + text-align: center; } .type.selected, .result.selected { @@ -781,6 +843,15 @@ export default { height: 22px; text-align: left; } +.result-type { + text-align: center; +} +.result-name { + overflow: hidden; + height: 100%; + text-overflow: ellipsis; + word-break: keep-all; +} .result-type, .result-name { width: 30%; diff --git a/fe/src/components/home/index.vue b/fe/src/components/home/index.vue index 6355f05..95871aa 100644 --- a/fe/src/components/home/index.vue +++ b/fe/src/components/home/index.vue @@ -69,18 +69,6 @@ function getColor () { function get (url, cb) { query('GET', url, '', cb) } -function updateType2Server (projectName, typeList, types) { - const entityTypes = typeList.map((type) => { - return { - type, - color: types[type].color - } - }) - post('/v1/project/update_entity_types', { - projectName: projectName, - entityTypes: JSON.stringify(entityTypes) - }) -} function post (url, data, cb) { query('POST', url, data, cb) } @@ -191,7 +179,6 @@ export default { }) that.typeList.push(newType) console.log(that.typeList) - updateType2Server(that.projectName, that.typeList, that.types) }, delType: function (type, ev) { const that = this @@ -209,7 +196,6 @@ export default { } that.typeList = newTypeList that.types = newTypes - updateType2Server(that.projectName, that.typeList, that.types) }, checkDelType: function (type, ev) { ev && ev.stopPropagation() @@ -232,7 +218,6 @@ export default { const that = this console.log(tarType, ev.target.value) that.$set(that.types[tarType], 'color', ev.target.value) - updateType2Server(that.projectName, that.typeList, that.types) } }, mounted () {