Files
FiDA_Front/src/components/Canvas/DepthCanvas/components/depth-header-tools.vue

164 lines
4.3 KiB
Vue
Raw Normal View History

2026-03-06 15:50:05 +08:00
<template>
<div class="header-tools">
<template v-for="(v, i) in tools" :key="i">
<span class="line" v-if="v.type === 'line'"></span>
<span
v-else
class="icon"
@click="onClickTool(v)"
:class="{ active: v.name === tool, disabled: v.disabled }"
>
<svg-icon :name="v.icon" :size="v.iconSize" />
</span>
</template>
<button class="export" @click="emit('export')">
<span class="icon"><svg-icon name="export" size="12" /></span>
<span class="text">Export</span>
</button>
2026-03-12 15:51:18 +08:00
<button class="export" @click="emit('export-local')">
<span class="text">保存本地</span>
2026-03-11 15:34:56 +08:00
</button>
2026-03-12 15:51:18 +08:00
<button class="export" @click="emit('import-local')">
<span class="text">本地导入</span>
</button>
<button class="workbench" @click="emit('export-close')">
2026-03-06 15:50:05 +08:00
<span class="icon"><svg-icon name="dc-workbench" size="20" /></span>
<span class="text">Workbench</span>
</button>
</div>
</template>
<script setup lang="ts">
import { ref, inject, computed } from 'vue'
2026-03-09 13:44:32 +08:00
import { OperationType } from '../tools/layerHelper'
2026-03-06 15:50:05 +08:00
const props = defineProps({
zoom: { default: 1, type: Number },
step: { default: 0.1, type: Number }
})
2026-03-12 15:51:18 +08:00
const emit = defineEmits(['export', 'export-local', 'import-local', 'export-close'])
2026-03-11 15:34:56 +08:00
const importLocalImage = inject('importLocalImage') as () => void
2026-03-06 15:50:05 +08:00
const stateManager = inject('stateManager') as any
const toolManager = inject('toolManager') as any
2026-03-09 13:44:32 +08:00
const tool = computed(() => toolManager.currentTool.value)
2026-03-06 15:50:05 +08:00
const historyIndex = computed(() => stateManager.historyIndex.value)
const historyList = computed(() => stateManager.historyList.value)
const isUndo = computed(() => !historyList.value[historyIndex.value - 1])
const isRedo = computed(() => !historyList.value[historyIndex.value + 1])
const tools = ref([
2026-03-09 13:44:32 +08:00
{ name: OperationType.SELECT, icon: 'dc-select', iconSize: 16, disabled: ref(false) },
{ name: OperationType.PAN, icon: 'dc-move', iconSize: 18, disabled: ref(false) },
{ name: OperationType.DRAW, icon: 'dc-brush', iconSize: 18, disabled: ref(false) },
{ name: OperationType.ERASER, icon: 'dc-eraser', iconSize: 18, disabled: ref(false) },
2026-03-11 15:34:56 +08:00
{
name: OperationType.IMAGE,
icon: 'dc-image',
iconSize: 17,
disabled: ref(false),
on: () => importLocalImage()
},
2026-03-09 13:44:32 +08:00
{ name: OperationType.SELECTBOX, icon: 'dc-selectbox', iconSize: 16, disabled: ref(false) },
{ name: OperationType.RECTANGLE, icon: 'dc-rectangle', iconSize: 16, disabled: ref(false) },
2026-03-06 15:50:05 +08:00
{ type: 'line' },
{
2026-03-09 13:44:32 +08:00
name: OperationType.UNDO,
2026-03-06 15:50:05 +08:00
icon: 'dc-undo',
iconSize: 18,
disabled: isUndo,
on: () => stateManager.undoState()
},
{
2026-03-09 13:44:32 +08:00
name: OperationType.REDO,
2026-03-06 15:50:05 +08:00
icon: 'dc-redo',
iconSize: 18,
disabled: isRedo,
on: () => stateManager.redoState()
}
])
const onClickTool = (tool: any) => {
if (tool.disabled?.value) return
if (tool.on) {
tool.on()
} else {
toolManager.setTool(tool.name)
}
}
</script>
<style lang="less" scoped>
.header-tools {
position: absolute;
top: 2.2rem;
left: 50%;
transform: translateX(-50%);
height: 5rem;
padding: 0.7rem 1.8rem;
border: 0.2rem solid #ebebeb;
background: #ffffff;
border-radius: 0.6rem;
box-shadow: 0 1.66rem 2.33rem 0 rgba(0, 0, 0, 0.05);
display: flex;
align-items: center;
justify-content: center;
user-select: none;
gap: 1rem;
> .line {
width: 0;
height: 100%;
border-left: 0.2rem solid #d9d9d9;
border-radius: 0.2rem;
margin: 0 0.6rem;
}
> .icon {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
--svg-icon-color: #000;
border-radius: 0.4rem;
&:not(.disabled).active,
&:not(.disabled):hover {
background-color: #ebebeb;
}
&.disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
> button {
cursor: pointer;
border: none;
display: flex;
align-items: center;
justify-content: center;
gap: 0.8rem;
&:active {
opacity: 0.8;
}
}
> .export {
width: 10rem;
height: 3rem;
background-color: #0d0d0d;
color: #fff;
font-size: 1.2rem;
border-radius: 0.4rem;
}
> .workbench {
position: absolute;
top: 0;
right: -2.4rem;
transform: translateX(100%);
height: 100%;
padding: 0 2.4rem;
border: 0.2rem solid #ebebeb;
background: #ffffff;
border-radius: 0.6rem;
box-shadow: 0 1.66rem 2.33rem 0 rgba(0, 0, 0, 0.05);
font-size: 1.7rem;
}
}
</style>