add result panel.
This commit is contained in:
140
src/shared/split-panel/index.vue
Normal file
140
src/shared/split-panel/index.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<div
|
||||
:style="{ cursor, userSelect }"
|
||||
class="vue-splitter-container clearfix"
|
||||
@mouseup="onMouseUp"
|
||||
@mousemove="onMouseMove"
|
||||
>
|
||||
<Pane
|
||||
class="splitter-pane splitter-paneL"
|
||||
:split="split"
|
||||
:style="{ [type]: percent + '%' }"
|
||||
>
|
||||
<slot name="panel"></slot>
|
||||
</Pane>
|
||||
|
||||
<Resizer
|
||||
:className="className"
|
||||
:style="{ [resizeType]: percent + '%' }"
|
||||
:split="split"
|
||||
@mousedown.native="onMouseDown"
|
||||
@click.native="onClick"
|
||||
></Resizer>
|
||||
|
||||
<Pane
|
||||
class="splitter-pane splitter-paneR"
|
||||
:split="split"
|
||||
:style="{ [type]: 100 - percent + '%' }"
|
||||
>
|
||||
<slot name="paner"></slot>
|
||||
</Pane>
|
||||
<div class="vue-splitter-container-mask" v-if="active"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Resizer from "./resizer.vue"
|
||||
import Pane from "./pane.vue"
|
||||
import { computed, ref } from "vue"
|
||||
|
||||
const {
|
||||
minPercent = 10,
|
||||
defaultPercent = 50,
|
||||
split,
|
||||
className,
|
||||
} = defineProps<{
|
||||
minPercent?: number
|
||||
defaultPercent?: number
|
||||
split: "vertical" | "horizontal"
|
||||
className?: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(["resize"])
|
||||
|
||||
const active = ref(false)
|
||||
const hasMoved = ref(false)
|
||||
const percent = ref(defaultPercent)
|
||||
const type = ref(split === "vertical" ? "width" : "height")
|
||||
const resizeType = ref(split === "vertical" ? "left" : "top")
|
||||
|
||||
const userSelect = computed(() => (active.value ? "none" : "auto"))
|
||||
const cursor = computed(() =>
|
||||
active.value ? (split === "vertical" ? "col-resize" : "row-resize") : ""
|
||||
)
|
||||
|
||||
// watch(
|
||||
// () => defaultPercent,
|
||||
// (newValue) => {
|
||||
// percent.value = newValue
|
||||
// }
|
||||
// )
|
||||
|
||||
function onClick() {
|
||||
if (!hasMoved.value) {
|
||||
percent.value = 50
|
||||
emit("resize", percent.value)
|
||||
}
|
||||
}
|
||||
function onMouseDown() {
|
||||
active.value = true
|
||||
hasMoved.value = false
|
||||
}
|
||||
function onMouseUp() {
|
||||
active.value = false
|
||||
}
|
||||
function onMouseMove(e: any) {
|
||||
if (e.buttons === 0) {
|
||||
active.value = false
|
||||
}
|
||||
if (active.value) {
|
||||
let offset = 0
|
||||
let target = e.currentTarget
|
||||
if (split === "vertical") {
|
||||
while (target) {
|
||||
offset += target.offsetLeft
|
||||
target = target.offsetParent
|
||||
}
|
||||
} else {
|
||||
while (target) {
|
||||
offset += target.offsetTop
|
||||
target = target.offsetParent
|
||||
}
|
||||
}
|
||||
const currentPage = split === "vertical" ? e.pageX : e.pageY
|
||||
const targetOffset =
|
||||
split === "vertical"
|
||||
? e.currentTarget.offsetWidth
|
||||
: e.currentTarget.offsetHeight
|
||||
const newPercent =
|
||||
Math.floor(((currentPage - offset) / targetOffset) * 10000) / 100
|
||||
if (newPercent > minPercent && newPercent < 100 - minPercent) {
|
||||
percent.value = newPercent
|
||||
}
|
||||
emit("resize", newPercent)
|
||||
hasMoved.value = true
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.clearfix:after {
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: " ";
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
.vue-splitter-container {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.vue-splitter-container-mask {
|
||||
z-index: 9999;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
</style>
|
||||
40
src/shared/split-panel/pane.vue
Normal file
40
src/shared/split-panel/pane.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div :class="classes">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const { className, split } = defineProps<{
|
||||
split: "horizontal" | "vertical"
|
||||
className?: string
|
||||
}>()
|
||||
|
||||
const classes = $computed(() => [split, className].join(" "))
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.splitter-pane.vertical.splitter-paneL {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
height: 100%;
|
||||
padding-right: 3px;
|
||||
}
|
||||
.splitter-pane.vertical.splitter-paneR {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
height: 100%;
|
||||
padding-left: 3px;
|
||||
}
|
||||
.splitter-pane.horizontal.splitter-paneL {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
.splitter-pane.horizontal.splitter-paneR {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
padding-top: 3px;
|
||||
}
|
||||
</style>
|
||||
43
src/shared/split-panel/resizer.vue
Normal file
43
src/shared/split-panel/resizer.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div :class="classes"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue"
|
||||
|
||||
const { className, split } = defineProps<{
|
||||
split: "horizontal" | "vertical"
|
||||
className?: string
|
||||
}>()
|
||||
|
||||
const classes = computed(() =>
|
||||
["splitter-pane-resizer", split, className].join(" ")
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.splitter-pane-resizer {
|
||||
box-sizing: border-box;
|
||||
background: #000;
|
||||
position: absolute;
|
||||
opacity: 0.2;
|
||||
z-index: 1;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
.splitter-pane-resizer.horizontal {
|
||||
height: 11px;
|
||||
margin: -5px 0;
|
||||
border-top: 5px solid rgba(255, 255, 255, 0);
|
||||
border-bottom: 5px solid rgba(255, 255, 255, 0);
|
||||
cursor: row-resize;
|
||||
width: 100%;
|
||||
}
|
||||
.splitter-pane-resizer.vertical {
|
||||
width: 11px;
|
||||
height: 100%;
|
||||
margin-left: -5px;
|
||||
border-left: 5px solid rgba(255, 255, 255, 0);
|
||||
border-right: 5px solid rgba(255, 255, 255, 0);
|
||||
cursor: col-resize;
|
||||
}
|
||||
</style>
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useToggle } from "@vueuse/core"
|
||||
import { defineStore } from "pinia"
|
||||
import { ref } from "vue"
|
||||
|
||||
export const useLoginStore = defineStore("login", () => {
|
||||
const visible = ref(false)
|
||||
const [visible] = useToggle()
|
||||
|
||||
function show() {
|
||||
visible.value = true
|
||||
|
||||
Reference in New Issue
Block a user