layui/example/src/components/LayCode.vue

207 lines
5.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="lay-code">
<div id="source" class="source">
<slot />
<div v-if="$slots.description" class="description">
<slot name="description" />
</div>
</div>
<div ref="meta" class="meta">
<div class="language-html">
<slot name="code" />
</div>
</div>
<div :class="{ 'is-fixed': isFixContorl }" class="control">
<i class="layui-icon layui-icon-play btn" @click="onPlayground" title="在 Playground 中打开" />
<i class="layui-icon layui-icon-file btn" @click="copy" title="复制代码" />
<i class="layui-icon layui-icon-fonts-code btn" @click="toggle" title="查看代码"/>
</div>
</div>
</template>
<script setup lang="ts">
import { layer } from '@layui/layer-vue'
import { onMounted, onUnmounted, ref, watch } from 'vue'
import { usePlayGround } from '../plugin/usePlayground'
const meta = ref<HTMLElement>({} as HTMLElement)
const isFixContorl = ref(false)
const codeAreaHeight = ref(0)
const show = ref(false)
const toggle = function () {
show.value = !show.value
}
const onPlayground = function(){
const foundCodes = meta.value.getElementsByClassName('language-html')
const foundCode = foundCodes[0];
const SourceCode = foundCode.textContent || "";
const { link } = usePlayGround(SourceCode, true)
window.open(link)
}
const copy = function () {
const foundCodes = meta.value.getElementsByClassName('language-html')
const foundCode = foundCodes[0];
let successful = false;
// 使用原生系统剪贴板只适用被授权安全的站点http下不能使用
if (navigator.clipboard && document.hasFocus()) {
const text = foundCode.textContent || "";
navigator.clipboard.writeText(text);
successful = true;
} else if (window.getSelection()){
// 使用document.execCommand
// 代码div显示状态直接使用隐藏状态则创建一个div
var range = document.createRange();
let copyDiv;
if (show.value) {
range.selectNode(foundCode);
} else {
copyDiv = document.createElement('div');
copyDiv.innerHTML = foundCode.innerHTML;
copyDiv.style.position="fixed";
copyDiv.style.left="-9999px";
document.body.appendChild(copyDiv);
range.selectNode(copyDiv);
}
window.getSelection()?.addRange(range);
try {
successful = document.execCommand('copy');
} catch(err) {
successful = false;
console.error(err);
}
window.getSelection()?.removeAllRanges();
copyDiv?.remove();
}
if (successful) {
layer.msg("复制成功", { icon : 1, time: 1000}, ()=>{})
} else {
layer.msg("复制失败", { icon : 2, time: 1000}, ()=>{})
}
}
onMounted(() => {
const foundDescs = meta.value.getElementsByClassName('description')
const foundCodes = meta.value.getElementsByClassName('language-html')
if (foundDescs.length) {
codeAreaHeight.value =
foundDescs[0].clientHeight + foundCodes[0].clientHeight + 30
} else {
codeAreaHeight.value = foundCodes[0].clientHeight + 20
}
})
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll)
})
watch(show, (value) => {
if (value) {
meta.value.style.height = `${codeAreaHeight.value}px`
window.addEventListener('scroll', handleScroll)
setTimeout(handleScroll, 100)
} else {
meta.value.style.height = '0'
window.removeEventListener('scroll', handleScroll)
}
})
function handleScroll() {
const { top, bottom } = meta.value.getBoundingClientRect()
isFixContorl.value =
bottom > window.innerHeight && top + 44 <= window.innerHeight
}
</script>
<style>
.lay-code {
margin: 1rem 0;
border: 1px solid whitesmoke;
border-radius: 3px;
background: var(--c-bg);
transition: all 0.2s;
}
.lay-code:hover {
box-shadow: var(--shadow-2);
}
.lay-code .source {
padding: 24px;
padding-bottom:15px;
}
.lay-code .meta {
padding: 0 10px;
height: 0;
background-color: var(--c-page-background);
overflow: hidden;
transition: height 0.2s;
}
.lay-code .source .description {
padding: 20px;
margin: 20px 0;
margin-bottom: 0px;
border: 1px solid whitesmoke;
box-sizing: border-box;
background: var(--c-bg);
font-size: 14px;
line-height: 22px;
color: var(--c-text-light-1);
word-break: break-word;
}
.lay-code .source .description p {
margin: 0 !important;
line-height: 26px !important;
}
.lay-code .source .description code {
display: inline-block;
padding: 1px 5px;
margin: 0 4px;
height: 18px;
border-radius: 2px;
background-color: var(--code-inline-bg-color);
font-size: 12px;
line-height: 18px;
color: var(--c-text-light);
}
.lay-code .control {
height: 44px;
box-sizing: border-box;
margin-top: 10px;
border-top: 1px solid whitesmoke;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
background: var(--c-bg);
text-align: center;
color: var(--c-text);
cursor: pointer;
width: 100%;
user-select: none;
}
.lay-code .control.is-fixed {
position: sticky;
z-index: 11;
bottom: 0;
}
.lay-code .control:hover {
background-color: var(--c-page-background);
color: var(--c-brand);
}
.lay-code .control > i {
display: inline-block;
font-size: 16px;
line-height: 44px;
transition: all 0.3s;
padding-left: 10px;
padding-right: 10px;
}
.btn:hover::before {
color: #5FB878;
}
</style>