阅读论文页面更新

master
pan 4 years ago
parent 70dfcd75a1
commit b19a2088ab
  1. 30
      nuxt.config.js
  2. 321
      pages/index/read.vue
  3. 3
      static/star.svg
  4. 33
      store/read.js

@ -99,11 +99,13 @@ export default {
"action": "操作",
"app_name": "云笔记",
"button": {
"add": "添加",
"cancel": "取消",
"catalog": "目录",
"del": "删除",
"edit": "编辑",
"ok": "確定",
"ok": "确定",
"rating": "提交评分",
"submit": "提交"
},
"center": {
@ -179,8 +181,18 @@ export default {
"add": "添加笔记"
},
"tip": {
"add_tip": "是否添加该笔记?",
"auto_save": "失去焦点自动保存",
"click_note_list": "选中内容定位笔记",
"contextmenu_err": "请选中文本进行操作"
"contextmenu_err": "请选中文本进行操作",
"del_confirm": "确认删除此笔记?",
"form": {
"note_content": "笔记内容",
"note_title": "笔记标题"
},
"rating_1": "本文对您的科研工作是否有帮助",
"rating_2": "本文的内容是否科学严谨",
"rating_3": "您对本文的推荐程度"
}
},
"reading_online": "在线阅读",
@ -222,11 +234,13 @@ export default {
"action": "",
"app_name": "cloudnote",
"button": {
"add": "",
"cancel": "",
"catalog": "",
"del": "",
"edit": "",
"ok": "",
"rating": "",
"submit": ""
},
"center": {
@ -302,8 +316,18 @@ export default {
"add": ""
},
"tip": {
"add_tip": "",
"auto_save": "",
"click_note_list": "",
"contextmenu_err": ""
"contextmenu_err": "",
"del_confirm": "",
"form": {
"note_content": "",
"note_title": ""
},
"rating_1": "",
"rating_2": "",
"rating_3": ""
}
},
"reading_online": "",

@ -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>

@ -0,0 +1,3 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg t="1595744424150" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5626"
width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 218.9312l63.9488 129.536a124.5184 124.5184 0 0 0 93.696 68.096l142.9504 20.7872-103.4752 100.8128a124.3648 124.3648 0 0 0-35.84 110.1312l24.3712 142.3872-128-67.1744a124.2112 124.2112 0 0 0-115.8656 0l-128 67.1744 24.4224-142.3872a124.6208 124.6208 0 0 0-35.84-110.1824L210.944 437.3504l143.0528-20.8384a124.3136 124.3136 0 0 0 93.5936-68.0448l63.9488-129.536m0-167.7312a13.7216 13.7216 0 0 0-12.3904 7.68L374.1696 312.2176a42.496 42.496 0 0 1-32.0512 23.2448l-279.552 40.6528a13.7728 13.7728 0 0 0-7.6288 23.5008l202.2912 197.1712a42.7008 42.7008 0 0 1 12.2368 37.6832L221.696 912.896a13.824 13.824 0 0 0 13.568 16.1792 14.1824 14.1824 0 0 0 6.4512-1.6384l250.0096-131.4304a42.3936 42.3936 0 0 1 39.6288 0l250.0096 131.4304a14.1824 14.1824 0 0 0 6.4512 1.6384 13.824 13.824 0 0 0 13.568-16.1792l-47.7696-278.4256a42.7008 42.7008 0 0 1 12.2368-37.6832l202.2912-197.1712a13.7728 13.7728 0 0 0-7.6288-23.5008l-279.552-40.6528a42.496 42.496 0 0 1-32.0512-23.2448L523.9296 58.88A13.7216 13.7216 0 0 0 511.5392 51.2z" p-id="5627"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -1,42 +1,33 @@
import Vue from 'vue'
/**
* 阅读论文标签数据
*/
export const state=()=>({
//已打开论文列表
read:[],
read: { },
//激活的论文标签
activeName:''
})
export const mutations = {
//新建论文标签
open(state,item){
let isNew=true
for(let i in state.read) {
if (state.read[i].title === item.title) {
isNew=false
mutations.choose(state,item.title)
}
}
if(isNew) {
state.read.push(item)
mutations.choose(state, state.read[state.read.length - 1].title)
if(item.title in state.read){
mutations.choose(state,item.title)
}else{
Vue.set(state.read,item.title, item)
mutations.choose(state)
}
},
//关闭论文标签
close(state,title){
for(let i in state.read){
if(state.read[i].title===title){
state.read.splice(i,1)
if(state.read.length>0){
if(state.activeName===title) {
mutations.choose(state, state.read[state.read.length - 1].title)
}
}
}
Vue.delete(state.read,title)
if(Object.keys(state.read).length>0&&state.activeName===title){
mutations.choose(state)
}
},
//选择论文标签
choose(state,title){
choose(state,title=Object.keys(state.read)[Object.keys(state.read).length-1]){
state.activeName=title
}
}

Loading…
Cancel
Save