195 lines
4.3 KiB
Vue
195 lines
4.3 KiB
Vue
<template>
|
|
<!-- 结果图片 -->
|
|
<div class="result-image">
|
|
<div class="header" v-show="showHeader">
|
|
<span class="icon">
|
|
<svg-icon name="chat-compose" size="24" size-unit="px" />
|
|
</span>
|
|
<span class="icon">
|
|
<svg-icon name="expand-lg" size="24" size-unit="px" />
|
|
</span>
|
|
<span class="icon">
|
|
<svg-icon name="download" size="24" size-unit="px" />
|
|
</span>
|
|
<button class="edit">
|
|
<span class="icon"><svg-icon name="edit" size="11" /></span>
|
|
<span class="text">Edit</span>
|
|
</button>
|
|
</div>
|
|
<img class="image" :src="data.url" />
|
|
<div class="more" @click="showMenu = !showMenu" @mousedown.stop>
|
|
<svg-icon name="more" size="24" size-unit="px" color="#C9C9C9" />
|
|
</div>
|
|
<div class="menu" v-show="showMenu" @mousedown.stop>
|
|
<div
|
|
v-for="(v, i) in menus"
|
|
:key="i"
|
|
:class="[v.isDivide ? 'divide' : 'item']"
|
|
@click="onMenuItem(v)"
|
|
>
|
|
<template v-if="!v.isDivide">
|
|
<span class="label">{{ v.label }}</span>
|
|
<span class="tip">{{ v.tip }}</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { reactive, ref, onBeforeUnmount, useAttrs } from 'vue'
|
|
const props = defineProps({
|
|
data: {
|
|
type: Object,
|
|
default: () => ({})
|
|
}
|
|
})
|
|
const attrs = useAttrs()
|
|
const showHeader = ref(!!attrs.node?.data?.isHeader)
|
|
const showMenu = ref(false)
|
|
const data = reactive({
|
|
url: props.data?.url || ''
|
|
})
|
|
const menus = ref([
|
|
{ label: 'Copy', tip: 'Ctrl+C', on: () => {} },
|
|
{ label: 'Paste', tip: 'Ctrl+V', on: () => {} },
|
|
{ label: 'Duplicate', tip: 'Ctrl+D', on: () => {} },
|
|
{ label: 'Delete', tip: 'Del', on: () => {} },
|
|
{ isDivide: true },
|
|
{ label: 'Bring to font', tip: 'Del', on: () => {} },
|
|
{ label: 'Send to back', tip: 'Del', on: () => {} },
|
|
{ isDivide: true },
|
|
{ label: 'Flip horizontal', tip: '', on: () => {} },
|
|
{ label: 'Flip vertical', tip: '', on: () => {} }
|
|
])
|
|
const onMenuItem = (v) => {
|
|
v.on && v.on()
|
|
hideMenu()
|
|
}
|
|
const hideMenu = () => {
|
|
showMenu.value = false
|
|
}
|
|
document.addEventListener('mousedown', hideMenu)
|
|
onBeforeUnmount(() => {
|
|
document.removeEventListener('mousedown', hideMenu)
|
|
})
|
|
defineExpose({ data })
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.result-image {
|
|
width: 244px;
|
|
border-radius: 16px;
|
|
border: 3px solid #d9d9d9;
|
|
box-shadow: 0px 15px 21px 0px #0000000d;
|
|
padding: 25px 6px;
|
|
user-select: none;
|
|
background-color: #fff;
|
|
> .header {
|
|
position: absolute;
|
|
top: -20px;
|
|
left: 50%;
|
|
transform: translate(-50%, -100%);
|
|
width: auto;
|
|
height: 50px;
|
|
border-radius: 10px;
|
|
border: 2px solid #ebebeb;
|
|
box-shadow: 0px 15px 21px 0px #0000000d;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
user-select: none;
|
|
padding: 0 19px;
|
|
gap: 12px;
|
|
background-color: #fff;
|
|
> .icon {
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 30px;
|
|
height: 30px;
|
|
--svg-icon-color: #000;
|
|
border-radius: 4px;
|
|
&:hover {
|
|
background-color: #dfdfdf;
|
|
}
|
|
}
|
|
> .edit {
|
|
width: 80px;
|
|
height: 30px;
|
|
border-radius: 4px;
|
|
border: none;
|
|
background-color: #ff7a51;
|
|
color: #fff;
|
|
font-size: 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
&:active {
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
}
|
|
|
|
> .image {
|
|
width: 100%;
|
|
height: auto;
|
|
}
|
|
position: relative;
|
|
|
|
> .more {
|
|
position: absolute;
|
|
top: 5px;
|
|
right: 9px;
|
|
width: 24px;
|
|
height: 24px;
|
|
cursor: pointer;
|
|
}
|
|
> .menu {
|
|
position: absolute;
|
|
width: 244px;
|
|
height: auto;
|
|
top: 0;
|
|
right: -10px;
|
|
transform: translate(100%, 0);
|
|
border-radius: 16px;
|
|
padding: 16px 14px;
|
|
box-shadow: 0px 15px 21px 0px rgba(0, 0, 0, 0.05);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 12px;
|
|
background-color: #fff;
|
|
z-index: 50;
|
|
> .item {
|
|
width: 100%;
|
|
height: 27px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 8px;
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
&:hover {
|
|
background: #f3f3f3;
|
|
}
|
|
> .label {
|
|
color: #000;
|
|
}
|
|
> .tip {
|
|
color: rgba(0, 0, 0, 0.3);
|
|
}
|
|
}
|
|
> .divide {
|
|
width: 100%;
|
|
height: 0;
|
|
border-bottom: 1px solid #e5e5e5;
|
|
}
|
|
}
|
|
}
|
|
</style>
|