vue锚点跳转至指定位置并且给当前文本增加高亮效果

<template>
	<div class="privacy">
		<div class="privacy-upInfo">
			<div class="privacy-upreturn">
				<h3 class="privacy-upreturn-h3">
					<button class="privacy-upreturn-return" @click="privacyReturn">
						返回
					</button>
				</h3>
				<div class="privacy-info">
					<h4>
						文件名称: <span>{{ fileName }}</span>
					</h4>
					<h4>
						审核日期: <span>{{ audioDate }}</span>
					</h4>
				</div>
				<h3 class="privacy-upreturn-infoTitle">
					{{ summary }}
				</h3>
			</div>
		</div>
		<div class="privacy-main clearfix">
			<div class="privacy-main-left">
				<h3 class="left_h3">隐私政策文本</h3>
				<div v-html="textContent" class="privacy-text"></div>
			</div>
			<div class="privacy-main-right">
				<h3>不通过评估项</h3>
				<el-menu
					default-active="2"
					class="pass-demo"
					@open="handleOpen"
					@close="handleClose"
					text-color="#333333"
					:unique-opened="true"
					active-text-color="#EC7555">
					<el-submenu
						class="textShow"
						v-for="(item, index) in unPassAssess"
						:key="item.id"
						:index="item.id.toString()">
						<template slot="title">
							<div :title="item.text"><i class="el-icon-caret-right"></i>{{ item.text }}</div>
						</template>
						<el-menu-item-group>
							<el-menu-item
								v-for="(itemChild, indChild) in item.sub_title"
								:key="indChild"
								:index="index + 1 + '-' + (indChild + 1)"
								:title="itemChild.text"
								@click="gotoParagraph(item, itemChild, 'noPass')">{{ itemChild.text }}</el-menu-item>
						</el-menu-item-group>
					</el-submenu>
				</el-menu>
				<h3>通过评估项</h3>
				<el-menu
					default-active="2"
					class="pass-demo-menu"
					@open="handleOpen"
					@close="handleClose"
					text-color="#333333"
					:unique-opened="true"
					active-text-color="#5D7EDD">
					<el-submenu
						class="textShow"
						v-for="(item, index) in passAssess"
						:key="item.id"
						:index="item.id.toString()">
						<template slot="title">
							<div :title="item.text"><i class="el-icon-caret-right"></i>{{ item.text }}</div>
						</template>
						<el-menu-item-group>
							<el-menu-item
								v-for="(itemChild, indChild) in item.sub_title"
								:key="indChild"
								:title="itemChild.text"
								:index="index + 1 + '-' + (indChild + 1)"
								@click="gotoParagraph(item, itemChild, 'pass')">{{ itemChild.text }}</el-menu-item>
						</el-menu-item-group>
					</el-submenu>
				</el-menu>
			</div>
		</div>
	</div>
</template>
<script>
import axios from "axios";
export default {
	data() {
		return {
			currentPage: 1,
			privacyDetailId: "",
			fileName: "",
			audioDate: "",
			summary: "",
			unPassAssess: [],
			passAssess: [],
			textContent: "",
			myParagraph: [],
			splitIdArr: [],
		};
	},
	created() {
		this.privacyDetailId = this.$route.query.jumpId;
		this.currentPage = this.$route.query.currentPage || 1;
	},
	mounted() {
		console.log();
		this.initDataDetail();
	},
	methods: {
		async initDataDetail() {
			let params = {
				id: this.privacyDetailId,
			};
			const { resultCode, result } = await this.$api.getPrivacyPolicyDetail(
				params
			);
			const { fileName, updateTime, jsonData, summary, htmlFilePath } = result;
			this.summary = summary;
			this.fileName = fileName;
			this.audioDate = updateTime;
			this.unPassAssess = jsonData.unqualified;
			this.passAssess = jsonData.qualified;
			// 线上环境打开
			this.htmlFile(
				`${window.location.origin}/policy-audit/resoure/html/` + htmlFilePath
			);
			// 本地环境打开
			// this.htmlFile(
			// 	`http://192.168.1.84/policy-audit/resoure/html/` + htmlFilePath
			// );
		},
		privacyReturn() {
			// this.$router.go(-1);
			this.$router.push({ path: "/privacyPolicyList", query: { currentPage: this.currentPage } });
		},
		async htmlFile(url) {
			let param = {
				accept: "text/html, text/plain",
			};
			await axios.get(url, param).then((res) => {
				this.textContent = res.data;
			});
		},
		handleOpen(key, keyPath) { },
		handleClose(key, keyPath) { },
		gotoParagraph(item, itemChild, passer) {
			//锚点定位
			var paragraph = "";
			var no_pass_class = document.getElementsByClassName("no_pass");
			var pass_class = document.getElementsByClassName("pass");
			var pg_color_class = document.getElementsByClassName("bg_color");
			var pg_colors_class = document.getElementsByClassName("bg_colors");
			if (this.splitIdArr.length > 0) {
				for (var k = 0; k < this.splitIdArr.length; k++) {
					document.querySelector(
						`.span_${this.splitIdArr[k]}`
					).innerHTML = document
						.querySelector(`.span_${this.splitIdArr[k]}`)
						.innerHTML.replace(/(<([^>]+)>)/g, "");
				}
			}
			this.splitIdArr = [];
			if (no_pass_class) {
				for (var i = 0; i < this.myParagraph.length; i++) {
					document
						.querySelector(`.span_${this.myParagraph[i]}`)
						.classList.remove("no_pass");
				}
			}
			if (pass_class) {
				for (var i = 0; i < pass_class.length; i++) {
					document
						.querySelector(`.span_${this.myParagraph[i]}`)
						.classList.remove("pass");
				}
			}
			// 内容截取标记
			if (itemChild.char_in_split && itemChild.char_in_split.length > 0) {
				paragraph = document.querySelector(
					`.span_${
					itemChild.char_in_split[0].split_id > itemChild.split_ids[0]
						? itemChild.split_ids[0]
						: itemChild.char_in_split[0].split_id
					}`
				);

				for (var j = 0; j < itemChild.char_in_split.length; j++) {
					let { split_id, elements } = itemChild.char_in_split[j];
					this.splitIdArr.push(split_id);
					if (split_id) {
						var strList = "";
						let str = document
							.querySelector(`.span_${split_id}`)
							.innerHTML.replace(/(<([^>]+)>)/g, "");
						strList = str.split("");
						if (elements.length > 0) {
							for (var i = 0; i < elements.length; i++) {
								var { start, end } = elements[i];
								if (start == end - 1) {
									strList[start] = `<em class="${
										passer == "pass" ? "bg_colors" : "bg_color"
										}">${str[start]}</em>`;
								} else {
									strList[start] = `<em class="${
										passer == "pass" ? "bg_colors" : "bg_color"
										}">${str[start]}`;
									strList[end - 1] = `${str[end - 1]}</em>`;
								}
							}
							document.querySelector(
								`.span_${split_id}`
							).innerHTML = strList.join("");
						}
					}
				}
			}
			// 段落标记
			if (itemChild.split_ids && itemChild.split_ids.length > 0) {
				if (itemChild.char_in_split && itemChild.char_in_split.length > 0) {
					paragraph = document.querySelector(
						`.span_${
						itemChild.char_in_split[0].split_id > itemChild.split_ids[0]
							? itemChild.split_ids[0]
							: itemChild.char_in_split[0].split_id
						} `
					);
				} else {
					paragraph = document.querySelector(
						`.span_${itemChild.split_ids[0]} `
					);
				}
				this.myParagraph = itemChild.split_ids;
				for (var k = 0; k < itemChild.split_ids.length; k++) {
					if (passer == "noPass") {
						document
							.getElementsByClassName(`span_${itemChild.split_ids[k]}`)[0]
							.classList.add("no_pass");
					} else if (passer == "pass") {
						document
							.getElementsByClassName(`span_${itemChild.split_ids[k]}`)[0]
							.classList.add("pass");
					}
				}
			}
			//  锚点
			if (paragraph) {
				paragraph.scrollIntoView({
					behavior: "smooth",
					block: "start",
					inline: "start",
				});
			}
		},
	},
};
</script>
<style lang="scss" scope>
.privacy {
	&-upInfo {
		box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.1);
		border-radius: 4px;
	}
	&-upreturn {
		overflow: hidden;
		background: rgba(255, 255, 255, 1);
		border: 1px solid rgba(235, 237, 242, 1);
		&-h3 {
			width: 120px;
			height: 36px;
			margin-top: 30px;
			float: left;
			border-right: 1px solid #dddddd;
		}
		&-return {
			width: 78px;
			height: 36px;
			background: rgba(47, 127, 227, 1);
			box-shadow: 0px 2px 7px 0px rgba(47, 127, 227, 0.5);
			border-radius: 2px;
			border: rgba(47, 127, 227, 1);
			outline: none;
			cursor: pointer;
			color: #fff;
			float: left;
			margin-left: 22px;
			padding-left: 22px;
			position: relative;
			&::after {
				content: "";
				position: absolute;
				display: block;
				height: 20px;
				width: 12px;
				top: 8px;
				left: 14px;
				background: url("../../assets/images/privacy/return.png") no-repeat left
					center;
			}
		}
		&-infoTitle {
			float: right;
			font-size: 16px;
			color: #454545;
			height: 30px;
			margin: 40px 192px 0 0;
			line-height: 30px;
			text-indent: 23px;
			margin-left: 20px;
		}
	}
	&-info {
		float: left;
		background: rgba(255, 255, 255, 1);
		padding: 24px 0 20px 0;
		h4 {
			margin: 0 0 0 31px;
			font-size: 16px;
			height: 16px;
			line-height: 16px;
			color: #333333;
			&:first-child {
				margin-bottom: 20px;
			}
			span {
				font-weight: normal;
				margin-left: 17px;
			}
		}
	}
	&-main {
		border-radius: 4px;
		height: calc(100vh - 232px);
		width: 100%;
		margin-top: 20px;
		&-left {
			float: left;
			width: calc(100% - 460px);
			height: 100%;
			background: rgba(255, 255, 255, 1);
			box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.1);
			box-sizing: border-box;
			padding: 0 20px 0 30px;
			font-family: "微软雅黑", PingFang-SC-Regular, Helvetica, sans-serif;
			overflow: auto;
			h3 {
				font-size: 16px;
				border-left: 5px solid #5d7edd;
				text-indent: 9px;
				margin-bottom: 18px;
				margin-top: 30px;
				color: #333333;
			}
			.privacy-text {
				& > div {
					width: 100% !important;
					margin: 0 !important;
				}
				.no_pass {
					border: 1px solid #ec7555 !important;
					color: #ec7555 !important;
				}
				.pass {
					border: 1px solid #5d7edd;
					color: #5d7edd;
				}
				p {
					line-height: 1.5em;
					margin-top: 1.5em;
				}
				em {
					font-style: normal;
				}
				.bg_colors {
					background: #89d5fd;
					color: #454545;
					font-style: normal;
				}
				.bg_color {
					background: #ec7555;
					color: #454545;
					font-style: normal;
				}
			}
		}
		&-right {
			float: right;
			width: 440px;
			height: 100%;
			background: #fff;
			overflow: auto;
			box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.1);
			box-sizing: border-box;
			padding: 25px 35px 11px 27px;
			.el-menu {
				border-right: none !important;
				background: rgba(237, 241, 245, 1);
				.is-opened {
					.el-icon-caret-right:before {
						content: ":";
					}
					.el-icon-caret-right:before {
						content: "\e790";
					}
				}
				.el-submenu {
					.el-menu-item {
						padding: 0 20px 0 50px !important;
						text-overflow: ellipsis;
						overflow: hidden;
					}
					.el-menu-item-group__title {
						padding: 0 !important;
					}
					.el-submenu__title {
						padding: 0 20px 0 20px !important;
						font-size: 14px !important;
						& > div {
							white-space: nowrap;
							text-overflow: ellipsis;
							overflow: hidden;
							vertical-align: middle;
						}
						.el-icon-caret-left {
							font-size: 14px;
						}
						.el-submenu__icon-arrow {
							display: none;
						}
					}
					.el-menu--inline {
						background: #f9fdff;
					}
				}
			}
			h3 {
				margin: 0;
				font-size: 16px;
				border-left: 5px solid #5d7edd;
				text-indent: 9px;
				margin-bottom: 18px;
				&:nth-of-type(2) {
					margin-top: 31px;
				}
			}
		}
	}
}
</style>

点击右边锚点定位左边内容并且增加高亮效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值