|
@@ -1,81 +1,117 @@
|
|
|
<template>
|
|
|
<div id="app">
|
|
|
<el-container style="padding: 20px;">
|
|
|
- <el-header>
|
|
|
+ <!--<el-header>
|
|
|
<h1 style="text-align: center;">文本标注工具</h1>
|
|
|
- </el-header>
|
|
|
+ </el-header>-->
|
|
|
|
|
|
<el-main>
|
|
|
- <!-- 标注文本和操作按钮 -->
|
|
|
+ <!-- 左侧内容 -->
|
|
|
<el-row>
|
|
|
<el-col :span="18">
|
|
|
- <h3 style="display: inline-block; margin-right: 20px;">标注文本</h3>
|
|
|
- <el-button type="primary" @click="highlightText">高亮标注</el-button>
|
|
|
- <el-color-picker v-model="selectedColor" style="margin-left: 10px;"></el-color-picker>
|
|
|
- <input type="file" @change="handleFileUpload" accept=".txt" style="display: none;" ref="fileInput">
|
|
|
- <el-button type="primary" @click="triggerFileUpload" style="margin-left: 10px;">上传文件</el-button>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
+ <!-- 标注文本和操作按钮 -->
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="24">
|
|
|
+ <h3 style="display: inline-block; margin-right: 20px;">标注文本</h3>
|
|
|
+ <el-button type="primary" @click="highlightText">高亮标注</el-button>
|
|
|
+ <el-color-picker v-model="selectedColor" style="margin-left: 10px;"></el-color-picker>
|
|
|
+ <input type="file" @change="handleFileUpload" accept=".txt" style="display: none;" ref="fileInput">
|
|
|
+ <el-button type="primary" @click="triggerFileUpload" style="margin-left: 10px;">上传文件</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
|
|
|
- <!-- 标注文本区域 -->
|
|
|
- <el-row style="margin-top: 20px;">
|
|
|
- <el-col :span="24">
|
|
|
- <div
|
|
|
- id="textInput"
|
|
|
- contenteditable="true"
|
|
|
- @mouseup="handleTextSelection"
|
|
|
- v-html="highlightedText"
|
|
|
- style="border: 1px solid #ddd; padding: 10px; min-height: 100px;"
|
|
|
- ></div>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
+ <!-- 标注文本区域 -->
|
|
|
+ <el-row style="margin-top: 20px;">
|
|
|
+ <el-col :span="24">
|
|
|
+ <div
|
|
|
+ id="textInput"
|
|
|
+ contenteditable="true"
|
|
|
+ @mouseup="handleTextSelection"
|
|
|
+ v-html="highlightedText"
|
|
|
+ style="border: 1px solid #ddd; padding: 10px; min-height: 100px;"
|
|
|
+ ></div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
|
|
|
- <!-- 选定内容、开始位置、结束位置 -->
|
|
|
- <el-row style="margin-top: 20px;">
|
|
|
- <el-col :span="8">
|
|
|
- <h3>选定内容</h3>
|
|
|
- <input type="text" v-model="selectedText" readonly>
|
|
|
- </el-col>
|
|
|
- <el-col :span="8">
|
|
|
- <h3>开始位置</h3>
|
|
|
- <input type="text" v-model="startOffset" readonly>
|
|
|
- </el-col>
|
|
|
- <el-col :span="8">
|
|
|
- <h3>结束位置</h3>
|
|
|
- <input type="text" v-model="endOffset" readonly>
|
|
|
+ <!-- 选定内容、开始位置、结束位置 -->
|
|
|
+ <el-row style="margin-top: 20px;">
|
|
|
+ <el-col :span="8">
|
|
|
+ <h3>选定内容</h3>
|
|
|
+ <input type="text" v-model="selectedText" readonly>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <h3>开始位置</h3>
|
|
|
+ <input type="text" v-model="startOffset" readonly>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <h3>结束位置</h3>
|
|
|
+ <input type="text" v-model="endOffset" readonly>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
</el-col>
|
|
|
- </el-row>
|
|
|
|
|
|
- <!-- 关系标注 -->
|
|
|
- <h3>关系标注</h3>
|
|
|
- <el-row>
|
|
|
- <el-col :span="6">
|
|
|
- <el-select v-model="headEntityId" placeholder="选择头实体" style="width: 100%;">
|
|
|
- <el-option v-for="entity in entities" :key="entity.id" :label="entity.text" :value="entity.id"></el-option>
|
|
|
- </el-select>
|
|
|
- </el-col>
|
|
|
- <el-col :span="6">
|
|
|
- <el-select v-model="tailEntityId" placeholder="选择尾实体" style="width: 100%;">
|
|
|
- <el-option v-for="entity in entities" :key="entity.id" :label="entity.text" :value="entity.id"></el-option>
|
|
|
- </el-select>
|
|
|
- </el-col>
|
|
|
- <el-col :span="6">
|
|
|
- <el-select v-model="currentRelationType" placeholder="选择关系类型" style="width: 100%;">
|
|
|
- <el-option v-for="type in relationTypes" :key="type" :label="type" :value="type"></el-option>
|
|
|
- </el-select>
|
|
|
- </el-col>
|
|
|
- <el-col :span="6">
|
|
|
- <el-button type="primary" @click="saveRelation">保存关系</el-button>
|
|
|
+ <!-- 右侧窗口 -->
|
|
|
+ <el-col :span="6" style="height: 100%;">
|
|
|
+ <!-- 信息与历史记录窗口 -->
|
|
|
+ <el-card style="height: 50%; margin-bottom: 10px;">
|
|
|
+ <div slot="header" class="clearfix">
|
|
|
+ <span>信息与历史记录</span>
|
|
|
+ </div>
|
|
|
+ <el-tabs type="border-card" style="height: calc(100% - 60px);">
|
|
|
+ <el-tab-pane label="信息">
|
|
|
+ <p>当前标注信息:</p>
|
|
|
+ <ul>
|
|
|
+ <li v-for="entity in entities" :key="entity.id">
|
|
|
+ {{ entity.text }}({{ entity.label }},位置:{{ entity.startOffset }}-{{ entity.endOffset }})
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </el-tab-pane>
|
|
|
+ <el-tab-pane label="历史记录">
|
|
|
+ <p>历史记录:</p>
|
|
|
+ <ul>
|
|
|
+ <li v-for="(log, index) in historyLogs" :key="index">
|
|
|
+ {{ log }}
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ <!-- 关系窗口 -->
|
|
|
+ <el-card style="height: 50%;">
|
|
|
+ <div slot="header" class="clearfix">
|
|
|
+ <span>关系</span>
|
|
|
+ </div>
|
|
|
+ <el-tabs type="border-card" style="height: calc(100% - 60px);">
|
|
|
+ <el-tab-pane label="关系列表">
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-select v-model="headEntityId" placeholder="选择头实体" style="width: 100%; margin-bottom: 10px;">
|
|
|
+ <el-option v-for="entity in entities" :key="entity.id" :label="entity.text" :value="entity.id"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-select v-model="tailEntityId" placeholder="选择尾实体" style="width: 100%; margin-bottom: 10px;">
|
|
|
+ <el-option v-for="entity in entities" :key="entity.id" :label="entity.text" :value="entity.id"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-input v-model="currentRelationType" placeholder="输入关系名称" style="width: 100%; margin-bottom: 10px;"></el-input>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-button type="primary" @click="saveRelation" style="width: 100%;">保存关系</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <ul>
|
|
|
+ <li v-for="relation in relations" :key="relation.id">
|
|
|
+ {{ getEntityText(relation.headEntityId) }} -> {{ getEntityText(relation.tailEntityId) }}({{ relation.type }})
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ </el-card>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
-
|
|
|
- <!-- 关系列表 -->
|
|
|
- <h3>关系列表</h3>
|
|
|
- <ul>
|
|
|
- <li v-for="relation in relations" :key="relation.id">
|
|
|
- {{ getEntityText(relation.headEntityId) }} -> {{ getEntityText(relation.tailEntityId) }}({{ relation.type }})
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
</el-main>
|
|
|
</el-container>
|
|
|
</div>
|
|
@@ -88,7 +124,7 @@ export default {
|
|
|
return {
|
|
|
text: "这是一些需要标注的文本。用户可以选择文本并标记。",
|
|
|
highlightedText: "这是一些需要标注的文本。用户可以选择文本并标记。",
|
|
|
- selectedLabel: "重要",
|
|
|
+ selectedLabel: "选中了一个实体",
|
|
|
selectedText: '', // 选定的内容
|
|
|
startOffset: -1, // 开始位置
|
|
|
endOffset: -1, // 结束位置
|
|
@@ -98,7 +134,8 @@ export default {
|
|
|
headEntityId: '', // 关系中的头实体ID
|
|
|
tailEntityId: '', // 关系中的尾实体ID
|
|
|
currentRelationType: '', // 当前选择的关系类型
|
|
|
- selectedColor: '#ffeb3b' // 默认高亮颜色
|
|
|
+ selectedColor: '#ffeb3b', // 默认高亮颜色
|
|
|
+ historyLogs: [] // 历史记录
|
|
|
};
|
|
|
},
|
|
|
methods: {
|
|
@@ -115,6 +152,7 @@ export default {
|
|
|
const content = e.target.result;
|
|
|
this.text = content;
|
|
|
this.highlightedText = content;
|
|
|
+ this.historyLogs.push(`文件上传成功:${file.name}`);
|
|
|
this.$message({
|
|
|
message: '文件上传成功!',
|
|
|
type: 'success'
|
|
@@ -140,6 +178,7 @@ export default {
|
|
|
color: this.selectedColor // 保存标注颜色
|
|
|
};
|
|
|
this.entities.push(entity); // 保存实体
|
|
|
+ this.historyLogs.push(`标注实体:${this.selectedText}`);
|
|
|
|
|
|
// 高亮显示
|
|
|
this.updateHighlightedText();
|
|
@@ -198,6 +237,7 @@ export default {
|
|
|
type: this.currentRelationType
|
|
|
};
|
|
|
this.relations.push(relation); // 保存关系
|
|
|
+ this.historyLogs.push(`保存关系:${this.getEntityText(relation.headEntityId)} -> ${this.getEntityText(relation.tailEntityId)}(${relation.type})`);
|
|
|
this.$message({
|
|
|
message: '关系保存成功!',
|
|
|
type: 'success'
|
|
@@ -245,19 +285,42 @@ input[readonly] {
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
|
|
|
+.el-col-6 {
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
.el-card {
|
|
|
- margin-bottom: 20px;
|
|
|
+ height: 50%;
|
|
|
+ margin-bottom: 10px; /* 保持卡片之间的间距 */
|
|
|
}
|
|
|
|
|
|
-.el-row {
|
|
|
- margin-bottom: 20px;
|
|
|
+.el-tabs {
|
|
|
+ height: calc(100% - 60px); /* 减去标题栏高度 */
|
|
|
}
|
|
|
|
|
|
-.el-color-picker {
|
|
|
- vertical-align: middle;
|
|
|
+.el-tabs {
|
|
|
+ margin-top: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.clearfix:before,
|
|
|
+.clearfix:after {
|
|
|
+ display: table;
|
|
|
+ content: "";
|
|
|
+}
|
|
|
+.clearfix:after {
|
|
|
+ clear: both;
|
|
|
+}
|
|
|
+
|
|
|
+/* 右侧窗口高度调整 */
|
|
|
+.el-col-6 {
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.el-card {
|
|
|
+ height: 50%;
|
|
|
}
|
|
|
|
|
|
-.el-button {
|
|
|
- margin-left: 10px;
|
|
|
+.el-tabs {
|
|
|
+ height: calc(100% - 60px); /* 减去标题栏高度 */
|
|
|
}
|
|
|
</style>
|