|
|
|
@ -1,33 +1,92 @@ |
|
|
|
|
<template> |
|
|
|
|
<div> |
|
|
|
|
<v-contextmenu ref="contextmenu" :disabled="disabled"> |
|
|
|
|
<v-contextmenu-item @click="addNote">{{$t('read.contextmenu.add')}}</v-contextmenu-item> |
|
|
|
|
</v-contextmenu> |
|
|
|
|
<el-tabs v-model="activeName" type="card" closable @tab-remove="removeTab"> |
|
|
|
|
<el-tab-pane :label="item.title" :name="item.title" v-for="(item,index) in openList" :key="item.title"> |
|
|
|
|
<el-row> |
|
|
|
|
<el-col :span="18"> |
|
|
|
|
<div class="content" v-contextmenu:contextmenu :ref="'edit'+item.title" @mouseup="show" @contextmenu="selectText" v-html="item.content"/> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="5" class="ml3 note-list"> |
|
|
|
|
<el-row v-for="(item,index) in noteList" :key="index" class="mb2"> |
|
|
|
|
<el-tooltip class="item" effect="dark" :content="$t('read.tip.click_note_list')"> |
|
|
|
|
<el-card> |
|
|
|
|
<div slot="header" class="clearfix"> |
|
|
|
|
<span>{{item.title}}</span> |
|
|
|
|
<el-button style="float: right; padding: 3px 0" type="text">{{$t('button.del')}}</el-button> |
|
|
|
|
</div> |
|
|
|
|
<div class="text item choose-note" @click="jump(item)" @mouseover="highlighting(item)" @mouseout="reset(item)"> |
|
|
|
|
{{item.content}} |
|
|
|
|
</div> |
|
|
|
|
</el-card> |
|
|
|
|
</el-tooltip> |
|
|
|
|
</el-row> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
</el-tab-pane> |
|
|
|
|
</el-tabs> |
|
|
|
|
</div> |
|
|
|
|
<div> |
|
|
|
|
<v-contextmenu ref="contextmenu" :disabled="disabled"> |
|
|
|
|
<v-contextmenu-item> |
|
|
|
|
<el-popover |
|
|
|
|
v-model="visible" |
|
|
|
|
trigger="click" |
|
|
|
|
> |
|
|
|
|
<el-form ref="form" :model="note_form" :rules="rules" label-width="80px"> |
|
|
|
|
<el-form-item :label="$t('read.tip.form.note_title')" prop="note_title"> |
|
|
|
|
<el-input v-model="note_form.note_title" :placeholder="$t('input_please', { keyword: this.$t('read.tip.form.note_title') })"></el-input> |
|
|
|
|
</el-form-item> |
|
|
|
|
<el-form-item :label="$t('read.tip.form.note_content')" prop="note_content"> |
|
|
|
|
<el-input type="textarea" v-model="note_form.note_content" :placeholder="$t('input_please', { keyword: this.$t('read.tip.form.note_content') })"></el-input> |
|
|
|
|
</el-form-item> |
|
|
|
|
<el-form-item> |
|
|
|
|
<el-button @click="addNote">{{$t('button.add')}}</el-button> |
|
|
|
|
<el-button @click="visible=false">{{$t('button.cancel')}}</el-button> |
|
|
|
|
</el-form-item> |
|
|
|
|
</el-form> |
|
|
|
|
<el-button slot="reference">{{$t('read.contextmenu.add')}}</el-button> |
|
|
|
|
</el-popover> |
|
|
|
|
</v-contextmenu-item> |
|
|
|
|
</v-contextmenu> |
|
|
|
|
<el-tabs v-model="activeName" type="card" closable @tab-remove="removeTab"> |
|
|
|
|
<el-tab-pane :label="key" :name="key" v-for="(item,key) in openList" :key="key"> |
|
|
|
|
<el-row> |
|
|
|
|
<el-col :span="18"> |
|
|
|
|
<div class="content" v-contextmenu:contextmenu :ref="'edit'+item.title" @mouseup="show" |
|
|
|
|
@contextmenu="selectText" v-html="item.content"/> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="5" class="ml3 note-list"> |
|
|
|
|
<el-row v-for="(item,index) in noteList" :key="index" class="mb2"> |
|
|
|
|
<el-card> |
|
|
|
|
<div slot="header" class="clearfix"> |
|
|
|
|
<el-row type="flex" justify="space-around"> |
|
|
|
|
<span>{{item.title}}</span> |
|
|
|
|
<el-button-group> |
|
|
|
|
<el-button size="mini" type="primary" @click="edit(item)" icon="el-icon-edit"></el-button> |
|
|
|
|
<el-popconfirm |
|
|
|
|
@onConfirm="del(item,index)" |
|
|
|
|
:title="$t('read.tip.del_confirm')" |
|
|
|
|
> |
|
|
|
|
<el-button size="mini" type="danger" slot="reference" icon="el-icon-delete"></el-button> |
|
|
|
|
</el-popconfirm> |
|
|
|
|
</el-button-group> |
|
|
|
|
</el-row> |
|
|
|
|
</div> |
|
|
|
|
<div class="text item" @click="jump(item)" @mouseover="highlighting(item)" |
|
|
|
|
@mouseout="reset(item)"> |
|
|
|
|
<transition v-if="item.isEdit" @after-leave="save(item)"> |
|
|
|
|
<el-tooltip class="item" effect="dark" :content="$t('read.tip.auto_save')" v-model="item.isEdit"> |
|
|
|
|
<el-input type="textarea" v-model="item.content"></el-input> |
|
|
|
|
</el-tooltip> |
|
|
|
|
</transition> |
|
|
|
|
<template v-else>{{item.content}}</template> |
|
|
|
|
</div> |
|
|
|
|
</el-card> |
|
|
|
|
<el-alert v-if="item.message" |
|
|
|
|
@close="item.message=null;item.type=null" |
|
|
|
|
:title="item.message" |
|
|
|
|
:type="item.type"> |
|
|
|
|
</el-alert> |
|
|
|
|
</el-row> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
</el-tab-pane> |
|
|
|
|
</el-tabs> |
|
|
|
|
<el-col :span="21"> |
|
|
|
|
<el-row class="mt2"> |
|
|
|
|
<el-col :span="7" v-for="(item,index) in stars" :key="index"> |
|
|
|
|
<h3 class="center">{{$t('read.tip.rating_'+(index+1))}}</h3> |
|
|
|
|
<el-rate |
|
|
|
|
class="center star-icon" |
|
|
|
|
v-model="item.value" |
|
|
|
|
show-score |
|
|
|
|
score-template="{value}分" |
|
|
|
|
:disabled="item.value>0"> |
|
|
|
|
</el-rate> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
<el-row class="mt2" type="flex" justify="center"> |
|
|
|
|
<el-col :span="3"> |
|
|
|
|
<el-button class="star-button" v-if="show_star_button" @click="submitRating">{{$t('button.rating')}} |
|
|
|
|
</el-button> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
</el-col> |
|
|
|
|
</div> |
|
|
|
|
</template> |
|
|
|
|
|
|
|
|
|
<script lang="ts"> |
|
|
|
@ -36,86 +95,145 @@ |
|
|
|
|
|
|
|
|
|
export default Vue.extend({ |
|
|
|
|
name: 'read', |
|
|
|
|
data(){ |
|
|
|
|
data() { |
|
|
|
|
return { |
|
|
|
|
//显示笔记表单 |
|
|
|
|
visible: false, |
|
|
|
|
//笔记表单 |
|
|
|
|
note_form:{ |
|
|
|
|
note_title:'', |
|
|
|
|
note_content:'' |
|
|
|
|
}, |
|
|
|
|
rules:{ |
|
|
|
|
note_title:[{ |
|
|
|
|
required: true, |
|
|
|
|
message: this.$t('input_please', { keyword: this.$t('read.tip.form.note_title') }), |
|
|
|
|
trigger: 'blur' |
|
|
|
|
}], |
|
|
|
|
note_content:[{ |
|
|
|
|
required: true, |
|
|
|
|
message: this.$t('input_please', { keyword: this.$t('read.tip.form.note_content') }), |
|
|
|
|
trigger: 'blur' |
|
|
|
|
}] |
|
|
|
|
}, |
|
|
|
|
//活动的论文标签 |
|
|
|
|
activeName:'', |
|
|
|
|
activeName: '', |
|
|
|
|
//笔记列表 |
|
|
|
|
noteList:[], |
|
|
|
|
noteList: [], |
|
|
|
|
//禁用右键菜单标志位 |
|
|
|
|
disabled:true, |
|
|
|
|
disabled: true, |
|
|
|
|
//替换目标 |
|
|
|
|
replace:[] |
|
|
|
|
replace: [], |
|
|
|
|
stars: [{ value: 0 }, { value: 0 }, { value: 0 }], |
|
|
|
|
show_star_button: true |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
computed:{ |
|
|
|
|
computed: { |
|
|
|
|
//打开的论文标签 |
|
|
|
|
openList(){ |
|
|
|
|
openList() { |
|
|
|
|
return this.$store.state.read.read |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
watch:{ |
|
|
|
|
watch: { |
|
|
|
|
//激活的论文标签 |
|
|
|
|
activeName(newVal){ |
|
|
|
|
this.$store.commit('read/choose',newVal) |
|
|
|
|
activeName(newVal) { |
|
|
|
|
this.$store.commit('read/choose', newVal) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
methods: { |
|
|
|
|
//编辑笔记 |
|
|
|
|
edit(item: any) { |
|
|
|
|
if ('isEdit' in item) { |
|
|
|
|
item.isEdit = !item.isEdit |
|
|
|
|
} else { |
|
|
|
|
this.$set(item, 'isEdit', true) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
//保存笔记 |
|
|
|
|
save(item: any) { |
|
|
|
|
this.$set(item, 'type', 'success') |
|
|
|
|
this.$set(item, 'message', '保存成功') |
|
|
|
|
}, |
|
|
|
|
//删除笔记 |
|
|
|
|
del(item: any,index:number) { |
|
|
|
|
this.$set(item, 'type', 'success') |
|
|
|
|
this.$set(item, 'message', '删除成功') |
|
|
|
|
this.noteList.splice(index,1) |
|
|
|
|
}, |
|
|
|
|
//提交评分 |
|
|
|
|
submitRating() { |
|
|
|
|
console.info(this.stars) |
|
|
|
|
}, |
|
|
|
|
//高亮笔记 |
|
|
|
|
highlighting(item:any){ |
|
|
|
|
let ele=document.getElementById(item.id) |
|
|
|
|
if(ele&&this.GLOBAL.visible_in_container(this.$refs['edit'+this.activeName][0],ele)){ |
|
|
|
|
highlighting(item: any) { |
|
|
|
|
let ele = document.getElementById(item.id) |
|
|
|
|
if (ele && this.GLOBAL.visible_in_container(this.$refs['edit' + this.activeName][0], ele)) { |
|
|
|
|
ele.classList.add('heightlight') |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
reset(item:any){ |
|
|
|
|
let ele=document.getElementById(item.id) |
|
|
|
|
if(ele){ |
|
|
|
|
reset(item: any) { |
|
|
|
|
let ele = document.getElementById(item.id) |
|
|
|
|
if (ele) { |
|
|
|
|
ele.classList.remove('heightlight') |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
//跳转到笔记位置 |
|
|
|
|
jump(item:any){ |
|
|
|
|
let ele=document.getElementById(item.id) |
|
|
|
|
if(ele){ |
|
|
|
|
jump(item: any) { |
|
|
|
|
let ele = document.getElementById(item.id) |
|
|
|
|
if (ele) { |
|
|
|
|
ele.scrollIntoView({ |
|
|
|
|
block:'center' |
|
|
|
|
block: 'center' |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
//是否显示右键菜单 |
|
|
|
|
show(){ |
|
|
|
|
let s=getSelection() |
|
|
|
|
if(s){ |
|
|
|
|
this.disabled=s.isCollapsed |
|
|
|
|
}else{ |
|
|
|
|
this.disabled=true |
|
|
|
|
show() { |
|
|
|
|
let s = getSelection() |
|
|
|
|
if (s) { |
|
|
|
|
this.disabled = s.isCollapsed |
|
|
|
|
} else { |
|
|
|
|
this.disabled = true |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
//关闭标签 |
|
|
|
|
removeTab(name:string){ |
|
|
|
|
this.$store.commit('read/close',name) |
|
|
|
|
if(this.openList.length===0){ |
|
|
|
|
this.$router.push(this.localePath('/document')) |
|
|
|
|
this.$store.commit('menus/none') |
|
|
|
|
removeTab(name: string) { |
|
|
|
|
this.$store.commit('read/close', name) |
|
|
|
|
if (Object.keys(this.openList).length === 0) { |
|
|
|
|
this.$router.push(this.localePath('/document')) |
|
|
|
|
this.$store.commit('menus/none') |
|
|
|
|
} |
|
|
|
|
this.activeName=this.$store.state.read.activeName |
|
|
|
|
this.activeName = this.$store.state.read.activeName |
|
|
|
|
}, |
|
|
|
|
//添加笔记 |
|
|
|
|
addNote(){ |
|
|
|
|
for(let index in this.replace){ |
|
|
|
|
if(this.replace[index].val&&this.replace[index].replaceVal){ |
|
|
|
|
this.replace[index].val.replaceWith(this.replace[index].replaceVal) |
|
|
|
|
addNote() { |
|
|
|
|
this.$refs.form.validate((valid: boolean)=>{ |
|
|
|
|
if (valid) { |
|
|
|
|
for (let index in this.replace) { |
|
|
|
|
if (this.replace[index].val && this.replace[index].replaceVal) { |
|
|
|
|
this.replace[index].val.replaceWith(this.replace[index].replaceVal) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
this.noteList.unshift({ |
|
|
|
|
id: `fuck${(Math.random()*10).toFixed()}`, |
|
|
|
|
title: this.note_form.note_title, |
|
|
|
|
content: this.note_form.note_content |
|
|
|
|
}) |
|
|
|
|
this.replace = [] |
|
|
|
|
this.visible=false |
|
|
|
|
this.note_form.note_title='' |
|
|
|
|
this.note_form.note_content='' |
|
|
|
|
} else { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
this.replace=[] |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
}, |
|
|
|
|
//显示选中文本 |
|
|
|
|
selectText(){ |
|
|
|
|
selectText() { |
|
|
|
|
let selection = getSelection() |
|
|
|
|
console.info(selection) |
|
|
|
|
if(selection&&!this.disabled) { |
|
|
|
|
if (selection && !this.disabled) { |
|
|
|
|
let range = selection.getRangeAt(0) |
|
|
|
|
console.info(range) |
|
|
|
|
if (range.startContainer === range.endContainer) { |
|
|
|
@ -127,9 +245,10 @@ |
|
|
|
|
console.info(tip + '全选') |
|
|
|
|
bold.innerText = anchorNode.wholeText |
|
|
|
|
this.replace.push({ |
|
|
|
|
val:anchorNode, |
|
|
|
|
val: anchorNode, |
|
|
|
|
replaceVal: bold |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
console.info(tip + '选中一部分') |
|
|
|
|
let start = document.createTextNode(anchorNode.substringData(0, range.startOffset)) |
|
|
|
@ -138,7 +257,7 @@ |
|
|
|
|
bold.innerText = anchorNode.substringData(range.startOffset, range.endOffset - range.startOffset) |
|
|
|
|
span.append(start, bold, end) |
|
|
|
|
this.replace.push({ |
|
|
|
|
val:anchorNode, |
|
|
|
|
val: anchorNode, |
|
|
|
|
replaceVal: span |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
@ -148,62 +267,47 @@ |
|
|
|
|
let endNode = range.endContainer |
|
|
|
|
console.info() |
|
|
|
|
} |
|
|
|
|
}else{ |
|
|
|
|
} else { |
|
|
|
|
this.$message.error({ |
|
|
|
|
message:this.$t('read.tip.contextmenu_err').toString(), |
|
|
|
|
showClose:true, |
|
|
|
|
duration:1000 |
|
|
|
|
}); |
|
|
|
|
message: this.$t('read.tip.contextmenu_err').toString(), |
|
|
|
|
showClose: true, |
|
|
|
|
duration: 1000 |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
// let selectData=anchorNode.substringData(range.startOffset,range.endOffset-range.startOffset) |
|
|
|
|
// console.info(selectData) |
|
|
|
|
// |
|
|
|
|
// |
|
|
|
|
// let start=document.createTextNode(anchorNode.substringData(0,range.startOffset)) |
|
|
|
|
// console.info(start) |
|
|
|
|
// |
|
|
|
|
// let end=document.createTextNode(anchorNode.substringData(range.endOffset,anchorNode.length)) |
|
|
|
|
// console.info(end) |
|
|
|
|
// let pre=selection.anchorNode.parentElement |
|
|
|
|
// // pre.innerHTML='' |
|
|
|
|
// let bold=document.createElement('span') |
|
|
|
|
// bold.innerText=selectData |
|
|
|
|
// bold.classList.add('bold') |
|
|
|
|
// // pre.append(start,bold,end) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
mounted() { |
|
|
|
|
this.activeName=this.$store.state.read.activeName |
|
|
|
|
for(let n=0;n<10;n++){ |
|
|
|
|
this.noteList.push({ |
|
|
|
|
id:`fuck${n}`, |
|
|
|
|
title:`笔记${n}`, |
|
|
|
|
content:`内容${n}` |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
this.activeName = this.$store.state.read.activeName |
|
|
|
|
for (let n = 0; n < 10; n++) { |
|
|
|
|
this.noteList.push({ |
|
|
|
|
id: `fuck${n}`, |
|
|
|
|
title: `笔记${n}`, |
|
|
|
|
content: `内容${n}` |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
</script> |
|
|
|
|
<style> |
|
|
|
|
.heightlight{ |
|
|
|
|
.heightlight { |
|
|
|
|
color: #74f2ff; |
|
|
|
|
font-size: larger; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.choose-note{ |
|
|
|
|
.choose-note { |
|
|
|
|
cursor: pointer; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pre{ |
|
|
|
|
pre { |
|
|
|
|
overflow-x: hidden; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.content{ |
|
|
|
|
.content { |
|
|
|
|
height: 600px; |
|
|
|
|
overflow-y: auto; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.note-list{ |
|
|
|
|
.note-list { |
|
|
|
|
height: 600px; |
|
|
|
|
overflow-y: auto; |
|
|
|
|
} |
|
|
|
@ -221,7 +325,16 @@ |
|
|
|
|
display: table; |
|
|
|
|
content: ""; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.clearfix::after { |
|
|
|
|
clear: both |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.star-button { |
|
|
|
|
width: 100%; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.star-icon i { |
|
|
|
|
font-size: 30px; |
|
|
|
|
} |
|
|
|
|
</style> |
|
|
|
|