Skip to content

Commit

Permalink
feat: 文章增加目录跳转功能
Browse files Browse the repository at this point in the history
  • Loading branch information
Liusiyuan-git committed Jan 15, 2023
1 parent 126d40f commit bcce9a9
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 8 deletions.
79 changes: 77 additions & 2 deletions src/pages/article/article.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
<collections-choose v-model:visible="collectionsVisible" :id="articleId"
:uuid="authorUuid" :mode="'article'"
@collected="collected"></collections-choose>
<el-row class="catalog">
<span class="title" v-if="headers">文章目录</span>
<ul id="header-container" class="header-container"></ul>
</el-row>
<el-row class="main" v-show="!loading">
<el-image v-if="data.cover" fit="cover" class="cover" :src="data.cover" :preview-src-list="[data.cover]"></el-image>
<el-row class="header">
Expand Down Expand Up @@ -111,8 +115,8 @@ import {ref, onBeforeUnmount, shallowRef, onBeforeMount, onMounted} from "vue";
import {Editor} from '@wangeditor/editor-for-vue'
import {userMainStore} from "../../store/user";
import {baseMainStore} from "../../store/base";
import router from "../../router";
import CollectionsChoose from "../collect/component/choose.vue";
import {SlateNode} from "@wangeditor/editor";
let e = null
let agreeAnimation = null
Expand All @@ -137,6 +141,7 @@ let iconCollect = ref(null)
let loading = ref(false)
let visible = ref(false)
let collectionsVisible = ref(false)
let headers = ref(false)
let agreeBounce = ref(1);
let collectBounce = ref(1);
let comment = ref(0)
Expand Down Expand Up @@ -210,6 +215,7 @@ function getArticle() {
data.value = reply.data
editorRef.value.setHtml(data.value["html"])
setTitle(reply.data["title"])
setHeaders()
getUserArticleAgree()
getUserArticleCollect()
addClickListenToImg()
Expand All @@ -220,6 +226,22 @@ function getArticle() {
})
}
function setHeaders(){
let headerContainer = document.getElementById('header-container')
headerContainer.addEventListener('mousedown', event => {
if (event.target.tagName !== 'LI') return
event.preventDefault()
const id = event.target.id.slice(8)
scrollTo( id)
})
headerContainer.innerHTML = editorRef.value.getElemsByTypePrefix('header').map(header => {
const text = SlateNode.string(header)
const {id, type} = header
return `<li id="catalog-${id}" class="li ${type}">${text}</li>`
}).join('')
headerContainer.innerHTML && (headers.value = true)
}
function addClickListenToImg(){
const images = document.getElementsByClassName("w-e-image-container")
Array.prototype.forEach.call(images, function (image) {
Expand Down Expand Up @@ -255,7 +277,7 @@ function setView() {
}
function articleNotExist() {
router.push({name: "result", query: {type: "error", title: '获取文章失败', description: "文章不存在或已被删除"}})
// router.push({name: "result", query: {type: "error", title: '获取文章失败', description: "文章不存在或已被删除"}})
}
function background() {
Expand Down Expand Up @@ -421,6 +443,59 @@ onBeforeUnmount(function () {
}
}
.catalog {
position: fixed;
top: 85px;
bottom: 0;
right: calc(52% + 360px);
width: 250px;
overflow-y: auto;
z-index: 100;
display: unset;
.title{
font-size: 25px;
color: var(--el-text-color-regular)
}
.header-container {
list-style-type: none;
padding-left: 0;
width: 100%;
margin-top: 0;
::v-deep(.li) {
color: var(--el-text-color-secondary);
margin: 10px 0;
cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
::v-deep(.li:hover) {
color: var(--el-color-primary);
}
::v-deep(.header1) {
font-size: 20px;
}
::v-deep(.header2) {
font-size: 16px;
padding-left: 15px;
}
::v-deep(.header3) {
font-size: 14px;
padding-left: 30px;
}
::v-deep(.header4) {
font-size: 12px;
padding-left: 45px;
}
::v-deep(.header5) {
font-size: 12px;
padding-left: 60px;
}
}
}
.main {
width: 100%;
flex-direction: column;
Expand Down
101 changes: 95 additions & 6 deletions src/pages/article/write.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@
</el-row>
</el-affix>
</el-row>
<el-row class="main">
<el-row class="catalog">
<span class="title" v-if="headers">文章目录</span>
<ul id="header-container" class="header-container"></ul>
</el-row>
<el-row class="main" id="article-write-main">
<el-row class="area" id="area">
<el-drawer
v-model="draft"
Expand Down Expand Up @@ -77,6 +81,7 @@
import {onBeforeUnmount, ref, shallowRef, onMounted} from 'vue'
import {backToHome, getAssets, setTitle} from "../../utils/globalFunc";
import {Editor, Toolbar} from '@wangeditor/editor-for-vue'
import {SlateNode} from '@wangeditor/editor'
import {success, info, warning, error} from "../../utils/message";
import {customCheckVideoFn, customParseVideoSrc} from "../../utils/video";
import {get, post} from "../../utils/axios"
Expand All @@ -86,6 +91,7 @@ import {userMainStore} from "../../store/user";
import {baseMainStore} from "../../store/base";
import {storeToRefs} from "pinia/dist/pinia.esm-browser";
import {useRoute} from "vue-router";
import {scrollToContainer, throttle} from "../../utils/scroll";
const userStore = userMainStore()
const baseStore = baseMainStore()
Expand Down Expand Up @@ -135,6 +141,8 @@ let drawer = ref(false)
let loading = ref(false)
let uploading = ref(false)
let percentage = ref(0)
let headers = ref(false)
let headerContainer = null
let body = null
let draftMarked = false
let uploadBox = {}
Expand All @@ -143,6 +151,7 @@ let uploadParams = {
Region: article.value.region,
}
let token = null
let delayEdit = null
function handleCreated(editor) {
editorRef.value = editor
Expand Down Expand Up @@ -181,12 +190,21 @@ function editChange(editor) {
uploadBox["title"] = title.value
uploadBox["html"] = editor.getHtml()
uploadBox["update"] = new Date().toLocaleDateString()
editSave(function () {
time.value = "最近保存:" + uploadBox["update"]
})
headerContainer.innerHTML = editor.getElemsByTypePrefix('header').map(header => {
const text = SlateNode.string(header)
const {id, type} = header
return `<li id="catalog-${id}" class="li ${type}">${text}</li>`
}).join('')
headerContainer.innerHTML && (headers.value = true)
mode.value === 'create' && draftMark()
delayEdit ? delayEdit() : delayEdit= throttle(function (){
editSave(function () {
time.value = "最近保存:" + uploadBox["update"]
})
}, 1000)
}
function draftMark() {
if (!draftId.value || draftMarked || !uuid.value) {
return
Expand Down Expand Up @@ -273,6 +291,23 @@ function initData() {
mode.value = userRouteValue.query["mode"]
draftId.value = parseInt(userRouteValue.query["id"])
token = localStorage.getItem(import.meta.env.VITE_MATRIX_TOKEN_KEY)
headerContainer = document.getElementById('header-container')
headerContainer.addEventListener('mousedown', event => {
if (event.target.tagName !== 'LI') return
event.preventDefault()
const id = event.target.id.slice(8)
scrollToContainer("article-write-main", id)
})
}
function heightToTop(container, ele){
let root = container;
let height = 0;
do{
height += ele.offsetTop;
ele = ele.offsetParent;
}while( ele && ele !== root )
return height;
}
function getLastDraft() {
Expand Down Expand Up @@ -359,7 +394,7 @@ function getDataEdit() {
onMounted(() => {
body = document.body
body.style.backgroundColor = "var(--el-color-white)"
setTimeout(function (){
setTimeout(function () {
init()
}, 1000)
})
Expand Down Expand Up @@ -435,6 +470,60 @@ onMounted(() => {
}
}
.catalog {
position: absolute;
top: 127px;
bottom: 0;
right: calc(52% + 360px);
width: 250px;
overflow-y: auto;
z-index: 100;
display: unset;
.title{
font-size: 25px;
color: var(--el-text-color-regular)
}
.header-container {
list-style-type: none;
padding-left: 0;
width: 100%;
margin-top: 0;
::v-deep(.li) {
color: var(--el-text-color-secondary);
margin: 10px 0;
cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
::v-deep(.li:hover) {
color: var(--el-color-primary);
}
::v-deep(.header1) {
font-size: 20px;
}
::v-deep(.header2) {
font-size: 16px;
padding-left: 15px;
}
::v-deep(.header3) {
font-size: 14px;
padding-left: 30px;
}
::v-deep(.header4) {
font-size: 12px;
padding-left: 45px;
}
::v-deep(.header5) {
font-size: 12px;
padding-left: 60px;
}
}
}
.main {
position: absolute;
top: 91px;
Expand All @@ -444,7 +533,7 @@ onMounted(() => {
overflow-y: auto;
.area {
width: 700px;
width: 720px;
margin: 0 auto;
height: fit-content;
Expand Down

0 comments on commit bcce9a9

Please sign in to comment.