Merge branch 'main' of ssh://18.167.251.121:10002/aidlab/FiDA_Front
This commit is contained in:
@@ -96,3 +96,10 @@ body,
|
|||||||
--el-color-primary-dark-2: #565656;
|
--el-color-primary-dark-2: #565656;
|
||||||
/* 深灰色(加深20%) */
|
/* 深灰色(加深20%) */
|
||||||
}
|
}
|
||||||
|
.mini-scrollbar::-webkit-scrollbar {
|
||||||
|
width: 0.4rem;
|
||||||
|
}
|
||||||
|
.mini-scrollbar::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|||||||
@@ -105,3 +105,15 @@ body,
|
|||||||
--el-color-primary-light-9: #e3e3e3; /* 极浅的灰色(混合60%白) */
|
--el-color-primary-light-9: #e3e3e3; /* 极浅的灰色(混合60%白) */
|
||||||
--el-color-primary-dark-2: #565656; /* 深灰色(加深20%) */
|
--el-color-primary-dark-2: #565656; /* 深灰色(加深20%) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 迷你滚动条
|
||||||
|
.mini-scrollbar {
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 0.4rem;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
3
src/assets/icons/dc/create.svg
Normal file
3
src/assets/icons/dc/create.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5 0C5.41421 0 5.75 0.335786 5.75 0.75V4.25H9.25C9.66421 4.25 10 4.58579 10 5C10 5.41421 9.66421 5.75 9.25 5.75H5.75V9.25C5.75 9.66421 5.41421 10 5 10C4.58579 10 4.25 9.66421 4.25 9.25V5.75H0.75C0.335786 5.75 0 5.41421 0 5C0 4.58579 0.335786 4.25 0.75 4.25H4.25V0.75C4.25 0.335786 4.58579 0 5 0Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 424 B |
3
src/assets/icons/dc/reset.svg
Normal file
3
src/assets/icons/dc/reset.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1.02518 0C1.31675 0 1.55311 0.23564 1.55311 0.526316V1.35367C2.44992 0.514522 3.65683 0 4.98466 0C7.75456 0 10 2.23858 10 5C10 7.76142 7.75456 10 4.98466 10C2.41401 10 0.295731 8.07235 0.00363895 5.58758C-0.0302986 5.29888 0.176946 5.03741 0.466532 5.00358C0.756118 4.96974 1.01839 5.17635 1.05232 5.46505C1.28281 7.42573 2.95587 8.94737 4.98466 8.94737C7.17142 8.94737 8.94414 7.18007 8.94414 5C8.94414 2.81993 7.17142 1.05263 4.98466 1.05263C3.81245 1.05263 2.7587 1.56036 2.03329 2.36842H3.41571C3.70728 2.36842 3.94364 2.60406 3.94364 2.89474C3.94364 3.18541 3.70728 3.42105 3.41571 3.42105H1.02518C0.740438 3.42105 0.508345 3.19631 0.497639 2.91505C0.497164 2.90406 0.497034 2.89304 0.497254 2.882V0.526316C0.497254 0.23564 0.733616 0 1.02518 0Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 880 B |
@@ -1,3 +1,3 @@
|
|||||||
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.66667 3.33275V2.08333C1.66667 1.6231 1.29357 1.25 0.833333 1.25C0.373096 1.25 0 1.6231 0 2.08333V5.83333C0 6.29357 0.373096 6.66667 0.833333 6.66667H4.16667C4.6269 6.66667 5 6.29357 5 5.83333C5 5.3731 4.6269 5 4.16667 5H2.55837C3.712 3.00589 5.86695 1.66667 8.33333 1.66667C12.0152 1.66667 15 4.65143 15 8.33333C15 12.0152 12.0152 15 8.33333 15C5.16166 15 2.5055 12.7843 1.83185 9.81559C1.73001 9.36677 1.2836 9.08548 0.834775 9.18733C0.385947 9.28917 0.104662 9.73558 0.206506 10.1844C1.04863 13.8956 4.36638 16.6667 8.33333 16.6667C12.9357 16.6667 16.6667 12.9357 16.6667 8.33333C16.6667 3.73096 12.9357 0 8.33333 0C5.60633 0 3.18634 1.30996 1.66667 3.33275ZM8.33333 3.33333C8.79357 3.33333 9.16667 3.70643 9.16667 4.16667V8.33333C9.16667 8.55435 9.07887 8.76631 8.92259 8.92259L6.83926 11.0059C6.51382 11.3314 5.98618 11.3314 5.66074 11.0059C5.33531 10.6805 5.33531 10.1528 5.66074 9.82741L7.5 7.98816V4.16667C7.5 3.70643 7.8731 3.33333 8.33333 3.33333Z" fill="black" fill-opacity="0.75"/>
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.66667 3.33275V2.08333C1.66667 1.6231 1.29357 1.25 0.833333 1.25C0.373096 1.25 0 1.6231 0 2.08333V5.83333C0 6.29357 0.373096 6.66667 0.833333 6.66667H4.16667C4.6269 6.66667 5 6.29357 5 5.83333C5 5.3731 4.6269 5 4.16667 5H2.55837C3.712 3.00589 5.86695 1.66667 8.33333 1.66667C12.0152 1.66667 15 4.65143 15 8.33333C15 12.0152 12.0152 15 8.33333 15C5.16166 15 2.5055 12.7843 1.83185 9.81559C1.73001 9.36677 1.2836 9.08548 0.834775 9.18733C0.385947 9.28917 0.104662 9.73558 0.206506 10.1844C1.04863 13.8956 4.36638 16.6667 8.33333 16.6667C12.9357 16.6667 16.6667 12.9357 16.6667 8.33333C16.6667 3.73096 12.9357 0 8.33333 0C5.60633 0 3.18634 1.30996 1.66667 3.33275ZM8.33333 3.33333C8.79357 3.33333 9.16667 3.70643 9.16667 4.16667V8.33333C9.16667 8.55435 9.07887 8.76631 8.92259 8.92259L6.83926 11.0059C6.51382 11.3314 5.98618 11.3314 5.66074 11.0059C5.33531 10.6805 5.33531 10.1528 5.66074 9.82741L7.5 7.98816V4.16667C7.5 3.70643 7.8731 3.33333 8.33333 3.33333Z" fill="#0D0D0D"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -10,7 +10,14 @@
|
|||||||
<span class="icon"><svg-icon :name="item.name" size="16" /></span>
|
<span class="icon"><svg-icon :name="item.name" size="16" /></span>
|
||||||
<span class="label">{{ item.label }}</span>
|
<span class="label">{{ item.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<button @click="onCreate">创建</button>
|
<button @click="onCreate">
|
||||||
|
<span class="icon"><svg-icon name="dc-create" size="12" /></span>
|
||||||
|
<span class="text">{{ $t('DepthCanvas.create') }}</span>
|
||||||
|
</button>
|
||||||
|
<button @click="onReset">
|
||||||
|
<span class="icon"><svg-icon name="dc-reset" size="12" /></span>
|
||||||
|
<span class="text">{{ $t('DepthCanvas.reset') }}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<brush-control-panel v-if="show" :currentTool="currentTool2" style="top: 14rem" />
|
<brush-control-panel v-if="show" :currentTool="currentTool2" style="top: 14rem" />
|
||||||
@@ -21,6 +28,8 @@
|
|||||||
import depthSlider from './tools/depth-slider.vue'
|
import depthSlider from './tools/depth-slider.vue'
|
||||||
import { OperationType } from '../tools/layerHelper'
|
import { OperationType } from '../tools/layerHelper'
|
||||||
import brushControlPanel from './brush-control-panel.vue'
|
import brushControlPanel from './brush-control-panel.vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
currentTool: { required: true, type: [String, null] }
|
currentTool: { required: true, type: [String, null] }
|
||||||
@@ -37,22 +46,22 @@
|
|||||||
{
|
{
|
||||||
type: OperationType.AISELECT_ADD,
|
type: OperationType.AISELECT_ADD,
|
||||||
name: 'dc-add_sb',
|
name: 'dc-add_sb',
|
||||||
label: 'Add'
|
label: t('DepthCanvas.add')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: OperationType.AISELECT_REMOVE,
|
type: OperationType.AISELECT_REMOVE,
|
||||||
name: 'dc-remove_sb',
|
name: 'dc-remove_sb',
|
||||||
label: 'Remove'
|
label: t('DepthCanvas.remove')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: OperationType.AISELECT_DRAW,
|
type: OperationType.AISELECT_DRAW,
|
||||||
name: 'dc-brush_sb',
|
name: 'dc-brush_sb',
|
||||||
label: 'Brush'
|
label: t('DepthCanvas.brush')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: OperationType.AISELECT_ERASER,
|
type: OperationType.AISELECT_ERASER,
|
||||||
name: 'dc-erase_sb',
|
name: 'dc-erase_sb',
|
||||||
label: 'Erase'
|
label: t('DepthCanvas.erase')
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
const onClickItem = (type: string) => {
|
const onClickItem = (type: string) => {
|
||||||
@@ -61,6 +70,9 @@
|
|||||||
const onCreate = () => {
|
const onCreate = () => {
|
||||||
stateManager.aiSelectboxToolManager.createSelectbox()
|
stateManager.aiSelectboxToolManager.createSelectbox()
|
||||||
}
|
}
|
||||||
|
const onReset = () => {
|
||||||
|
stateManager.aiSelectboxToolManager.resetDemoObject()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
// 淡入淡出动画
|
// 淡入淡出动画
|
||||||
@@ -108,5 +120,22 @@
|
|||||||
background: rgba(235, 235, 235, 0.9);
|
background: rgba(235, 235, 235, 0.9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
> button {
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 2.5rem;
|
||||||
|
background-color: rgba(13, 13, 13, 1);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
padding: 0 0.8rem;
|
||||||
|
gap: 0.8rem;
|
||||||
|
&:active {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<button class="export" @click="emit('export')">
|
<button class="export" @click="emit('export')">
|
||||||
<span class="icon"><svg-icon name="export" size="12" /></span>
|
<span class="icon"><svg-icon name="export" size="12" /></span>
|
||||||
<span class="text">Export</span>
|
<span class="text">{{ $t('DepthCanvas.export') }}</span>
|
||||||
</button>
|
</button>
|
||||||
<!-- <button class="export" @click="emit('export-local')">
|
<!-- <button class="export" @click="emit('export-local')">
|
||||||
<span class="text">保存本地</span>
|
<span class="text">保存本地</span>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
</button> -->
|
</button> -->
|
||||||
<button class="workbench" @click="onWorkbench">
|
<button class="workbench" @click="onWorkbench">
|
||||||
<span class="icon"><svg-icon name="dc-workbench" size="20" /></span>
|
<span class="icon"><svg-icon name="dc-workbench" size="20" /></span>
|
||||||
<span class="text">Workbench</span>
|
<span class="text">{{ $t('DepthCanvas.save') }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -49,6 +49,8 @@
|
|||||||
import { ref, inject, computed } from 'vue'
|
import { ref, inject, computed } from 'vue'
|
||||||
import { exportCanvasToImage } from '../tools/exportMethod'
|
import { exportCanvasToImage } from '../tools/exportMethod'
|
||||||
import { OperationType, BlendMode } from '../tools/layerHelper'
|
import { OperationType, BlendMode } from '../tools/layerHelper'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
const { t } = useI18n()
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
zoom: { default: 1, type: Number },
|
zoom: { default: 1, type: Number },
|
||||||
step: { default: 0.1, type: Number }
|
step: { default: 0.1, type: Number }
|
||||||
@@ -86,37 +88,37 @@
|
|||||||
child: [
|
child: [
|
||||||
{
|
{
|
||||||
name: OperationType.RECTANGLE,
|
name: OperationType.RECTANGLE,
|
||||||
label: 'Rectangle',
|
label: t('DepthCanvas.rectangle'),
|
||||||
icon: 'dc-rectangle',
|
icon: 'dc-rectangle',
|
||||||
iconSize: 13
|
iconSize: 13
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: OperationType.LINE,
|
name: OperationType.LINE,
|
||||||
label: 'Line',
|
label: t('DepthCanvas.line'),
|
||||||
icon: 'dc-line',
|
icon: 'dc-line',
|
||||||
iconSize: 10
|
iconSize: 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: OperationType.ARROW,
|
name: OperationType.ARROW,
|
||||||
label: 'Arrow',
|
label: t('DepthCanvas.arrow'),
|
||||||
icon: 'dc-arrow',
|
icon: 'dc-arrow',
|
||||||
iconSize: 11
|
iconSize: 11
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: OperationType.ELLIPSE,
|
name: OperationType.ELLIPSE,
|
||||||
label: 'Ellipse',
|
label: t('DepthCanvas.ellipse'),
|
||||||
icon: 'dc-ellipse',
|
icon: 'dc-ellipse',
|
||||||
iconSize: 15
|
iconSize: 15
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: OperationType.TRIANGLE,
|
name: OperationType.TRIANGLE,
|
||||||
label: 'Polygon',
|
label: t('DepthCanvas.triangle'),
|
||||||
icon: 'dc-triangle',
|
icon: 'dc-triangle',
|
||||||
iconSize: 14
|
iconSize: 14
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: OperationType.STAR,
|
name: OperationType.STAR,
|
||||||
label: 'Star',
|
label: t('DepthCanvas.star'),
|
||||||
icon: 'dc-star',
|
icon: 'dc-star',
|
||||||
iconSize: 15
|
iconSize: 15
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +1,153 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="basic-info">
|
<div class="basic-info h">
|
||||||
<div>
|
<div>
|
||||||
<span class="label">X:</span>
|
<div class="title">{{ $t('DepthCanvas.position') }}</div>
|
||||||
<span class="value">{{ object.left }}</span>
|
<div class="content">
|
||||||
|
<div>
|
||||||
|
<depth-input
|
||||||
|
before="X"
|
||||||
|
type="number"
|
||||||
|
v-model="data.left"
|
||||||
|
@input="onInpot"
|
||||||
|
@change="onChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<depth-input
|
||||||
|
before="Y"
|
||||||
|
type="number"
|
||||||
|
v-model="data.top"
|
||||||
|
@input="onInpot"
|
||||||
|
@change="onChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div>
|
||||||
|
<depth-input
|
||||||
|
before="W"
|
||||||
|
type="number"
|
||||||
|
v-model="data.width"
|
||||||
|
@input="onInpot"
|
||||||
|
@change="onChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<depth-input
|
||||||
|
before="H"
|
||||||
|
type="number"
|
||||||
|
v-model="data.height"
|
||||||
|
@input="onInpot"
|
||||||
|
@change="onChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="label">Y:</span>
|
<div class="title">{{ $t('DepthCanvas.scale') }}</div>
|
||||||
<span class="value">{{ object.top }}</span>
|
<div class="content">
|
||||||
</div>
|
<div>
|
||||||
<div>
|
<depth-input
|
||||||
<span class="label">Width:</span>
|
type="number"
|
||||||
<span class="value">{{ object.width }}</span>
|
before="X"
|
||||||
</div>
|
after="%"
|
||||||
<div>
|
v-model="data.scaleX"
|
||||||
<span class="label">Height:</span>
|
@input="onInpot"
|
||||||
<span class="value">{{ object.height }}</span>
|
@change="onChange"
|
||||||
</div>
|
/>
|
||||||
<div>
|
</div>
|
||||||
<span class="label">缩放X:</span>
|
<div>
|
||||||
<span class="value">{{ object.scaleX }}</span>
|
<depth-input
|
||||||
</div>
|
type="number"
|
||||||
<div>
|
before="Y"
|
||||||
<span class="label">缩放Y:</span>
|
after="%"
|
||||||
<span class="value">{{ object.scaleY }}</span>
|
v-model="data.scaleY"
|
||||||
</div>
|
@input="onInpot"
|
||||||
<div>
|
@change="onChange"
|
||||||
<span class="label">Angle:</span>
|
/>
|
||||||
<span class="value">{{ object.angle }}</span>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, inject, computed, watch, onMounted } from 'vue'
|
import { ref, inject, computed, nextTick, onBeforeUnmount, reactive, watch } from 'vue'
|
||||||
|
import DepthInput from '../tools/depth-input.vue'
|
||||||
|
const objectManager = inject('objectManager') as any
|
||||||
|
const stateManager = inject('stateManager') as any
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
object: {
|
object: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
onMounted(() => {})
|
const id = computed(() => props.object.info.id)
|
||||||
|
|
||||||
|
const data = reactive({
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
scaleX: 1,
|
||||||
|
scaleY: 1
|
||||||
|
})
|
||||||
|
const updateData = async () => {
|
||||||
|
await nextTick()
|
||||||
|
data.top = Math.round(props.object.top)
|
||||||
|
data.left = Math.round(props.object.left)
|
||||||
|
data.width = Math.round(props.object.width)
|
||||||
|
data.height = Math.round(props.object.height)
|
||||||
|
data.scaleX = Math.round(props.object.scaleX * 100)
|
||||||
|
data.scaleY = Math.round(props.object.scaleY * 100)
|
||||||
|
}
|
||||||
|
updateData()
|
||||||
|
watch(() => props.object, updateData)
|
||||||
|
|
||||||
|
const onInpot = () => setPriority(false)
|
||||||
|
const onChange = () => setPriority(true)
|
||||||
|
const setPriority = (isRecord: boolean) => {
|
||||||
|
const options = {
|
||||||
|
...data,
|
||||||
|
scaleX: data.scaleX / 100,
|
||||||
|
scaleY: data.scaleY / 100
|
||||||
|
}
|
||||||
|
objectManager.updateProperty(id.value, options, isRecord)
|
||||||
|
}
|
||||||
|
|
||||||
|
stateManager.event.add('canvas:undo', updateData)
|
||||||
|
stateManager.event.add('canvas:redo', updateData)
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
stateManager.event.remove('canvas:undo', updateData)
|
||||||
|
stateManager.event.remove('canvas:redo', updateData)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.basic-info {
|
.basic-info {
|
||||||
|
--details-item-margin-bottom: 1.6rem;
|
||||||
> div {
|
> div {
|
||||||
padding: 0.8rem 0;
|
> .content {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
> .label {
|
justify-content: center;
|
||||||
font-size: 1.6rem;
|
> div {
|
||||||
color: #000;
|
flex: 1;
|
||||||
font-weight: bold;
|
margin-right: 3rem;
|
||||||
min-width: 7rem;
|
display: flex;
|
||||||
text-align: right;
|
flex-direction: column;
|
||||||
margin-right: 0.8rem;
|
--depth-input-height: 2.4rem;
|
||||||
}
|
--depth-input-bg-color: rgba(249, 249, 250, 1);
|
||||||
> .value {
|
--depth-input-border-color: rgba(230, 230, 231, 1);
|
||||||
font-size: 1.6rem;
|
--depth-input-decorate-color: rgba(69, 71, 84, 0.1);
|
||||||
color: #333;
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
> .label {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fill-repeat h">
|
<div class="fill-repeat h">
|
||||||
<div>
|
<div>
|
||||||
<div class="title">Image</div>
|
<div class="title">{{ $t('DepthCanvas.image') }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<img :src="object.info.fill.source" alt="" />
|
<img :src="object.info.fill.source" alt="" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="title">Sttings</div>
|
<div class="title">{{ $t('DepthCanvas.settings') }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div>
|
<div>
|
||||||
<div class="label">Rotation</div>
|
<div class="label">{{ $t('DepthCanvas.rotation') }}</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<depth-input
|
<depth-input
|
||||||
icon="dc-angle"
|
icon="dc-angle"
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="label">Scale</div>
|
<div class="label">{{ $t('DepthCanvas.scale') }}</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<depth-slider
|
<depth-slider
|
||||||
v-model="scale"
|
v-model="scale"
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="label">Opacity</div>
|
<div class="label">{{ $t('DepthCanvas.opacity') }}</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<depth-slider
|
<depth-slider
|
||||||
v-model="opacity"
|
v-model="opacity"
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="label">Gap X</div>
|
<div class="label">{{ $t('DepthCanvas.gapX') }}</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<depth-slider
|
<depth-slider
|
||||||
v-model="gapX"
|
v-model="gapX"
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="label">Gap Y</div>
|
<div class="label">{{ $t('DepthCanvas.gapY') }}</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<depth-slider
|
<depth-slider
|
||||||
v-model="gapY"
|
v-model="gapY"
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="label">Offset</div>
|
<div class="label">{{ $t('DepthCanvas.offset') }}</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<depth-offset-tool
|
<depth-offset-tool
|
||||||
v-model="offset"
|
v-model="offset"
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, inject, computed, nextTick, onBeforeUnmount } from 'vue'
|
import { ref, inject, computed, nextTick, onBeforeUnmount, watch } from 'vue'
|
||||||
import DepthOffsetTool from '../tools/depth-offset-tool.vue'
|
import DepthOffsetTool from '../tools/depth-offset-tool.vue'
|
||||||
import DepthSlider from '../tools/depth-slider.vue'
|
import DepthSlider from '../tools/depth-slider.vue'
|
||||||
import DepthInput from '../tools/depth-input.vue'
|
import DepthInput from '../tools/depth-input.vue'
|
||||||
@@ -134,6 +134,7 @@
|
|||||||
opacity.value = Math.round(props.object.opacity * 100)
|
opacity.value = Math.round(props.object.opacity * 100)
|
||||||
}
|
}
|
||||||
updateData()
|
updateData()
|
||||||
|
watch(() => props.object, updateData)
|
||||||
|
|
||||||
const inputFillTransform = () => setFillTransform(false)
|
const inputFillTransform = () => setFillTransform(false)
|
||||||
const changeFillTransform = () => setFillTransform(true)
|
const changeFillTransform = () => setFillTransform(true)
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
<div class="details-panel">
|
<div class="details-panel">
|
||||||
<div class="header" @click="show = !show">
|
<div class="header" @click="show = !show">
|
||||||
<span class="icon"><svg-icon name="dc-details_edit" size="17" /></span>
|
<span class="icon"><svg-icon name="dc-details_edit" size="17" /></span>
|
||||||
<span class="title">Edit Details</span>
|
<span class="title">{{ $t('DepthCanvas.editDetails') }}</span>
|
||||||
<span class="arrow" :class="{ show }">
|
<span class="arrow" :class="{ show }">
|
||||||
<svg-icon name="dc-down_arrow2" size="10" />
|
<svg-icon name="dc-down_arrow2" size="10" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="content" v-if="isShow" v-show="show">
|
<div class="content mini-scrollbar" v-if="isShow" v-show="show">
|
||||||
<!-- <basic-info :object="activeObject" /> -->
|
<basic-info :object="activeObject" />
|
||||||
<fill-repeat :object="activeObject" v-if="isRepeat" />
|
<fill-repeat :object="activeObject" v-if="isRepeat" />
|
||||||
<shape-setting :object="activeObject" v-if="isShape && !isRepeat" />
|
<shape-setting :object="activeObject" v-if="isShape && !isRepeat" />
|
||||||
</div>
|
</div>
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, inject, computed, watch, onMounted } from 'vue'
|
import { ref, inject, computed, watch, onMounted } from 'vue'
|
||||||
|
import BasicInfo from './basic-info.vue'
|
||||||
import FillRepeat from './fill-repeat.vue'
|
import FillRepeat from './fill-repeat.vue'
|
||||||
import ShapeSetting from './shape-setting.vue'
|
import ShapeSetting from './shape-setting.vue'
|
||||||
const props = defineProps({})
|
const props = defineProps({})
|
||||||
@@ -27,10 +28,11 @@
|
|||||||
const layers = computed(() => layerManager.layers.value)
|
const layers = computed(() => layerManager.layers.value)
|
||||||
const activeObject = ref(null)
|
const activeObject = ref(null)
|
||||||
|
|
||||||
const shapes = ['rect', 'line', 'path', 'triangle', 'polygon', 'ellipse']
|
const shapes = ['rect', 'path', 'triangle', 'polygon', 'ellipse']
|
||||||
|
const isImage = computed(() => activeObject.value?.type === 'image')
|
||||||
const isShape = computed(() => shapes.includes(activeObject.value?.type))
|
const isShape = computed(() => shapes.includes(activeObject.value?.type))
|
||||||
const isRepeat = computed(() => activeObject.value?.fill?.repeat === 'repeat')
|
const isRepeat = computed(() => activeObject.value?.fill?.repeat === 'repeat')
|
||||||
const isShow = computed(() => isRepeat.value || isShape.value)
|
const isShow = computed(() => isImage.value || isRepeat.value || isShape.value)
|
||||||
|
|
||||||
const updateActiveObject = () => {
|
const updateActiveObject = () => {
|
||||||
const layer = layerManager.getActiveLayer()
|
const layer = layerManager.getActiveLayer()
|
||||||
@@ -49,7 +51,7 @@
|
|||||||
top: 2.2rem;
|
top: 2.2rem;
|
||||||
right: 3rem;
|
right: 3rem;
|
||||||
width: 28.8rem;
|
width: 28.8rem;
|
||||||
max-height: 80%;
|
max-height: 90%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.6rem;
|
gap: 1.6rem;
|
||||||
@@ -87,6 +89,12 @@
|
|||||||
padding: 1.6rem;
|
padding: 1.6rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
> * {
|
||||||
|
margin-bottom: 1.6rem;
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
&:deep(> div) {
|
&:deep(> div) {
|
||||||
> div {
|
> div {
|
||||||
margin-bottom: var(--details-item-margin-bottom, 1.6rem);
|
margin-bottom: var(--details-item-margin-bottom, 1.6rem);
|
||||||
|
|||||||
@@ -1,79 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="shape-setting h">
|
<div class="shape-setting h">
|
||||||
<div>
|
<div>
|
||||||
<div class="title">Position</div>
|
<div class="title">{{ $t('DepthCanvas.appearance') }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div>
|
<div>
|
||||||
<depth-input
|
<span class="label">{{ $t('DepthCanvas.opacity') }}</span>
|
||||||
before="X"
|
|
||||||
type="number"
|
|
||||||
v-model="data.left"
|
|
||||||
@input="onInpot"
|
|
||||||
@change="onChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<depth-input
|
|
||||||
before="Y"
|
|
||||||
type="number"
|
|
||||||
v-model="data.top"
|
|
||||||
@input="onInpot"
|
|
||||||
@change="onChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
<div>
|
|
||||||
<depth-input
|
|
||||||
before="W"
|
|
||||||
type="number"
|
|
||||||
v-model="data.width"
|
|
||||||
@input="onInpot"
|
|
||||||
@change="onChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<depth-input
|
|
||||||
before="H"
|
|
||||||
type="number"
|
|
||||||
v-model="data.height"
|
|
||||||
@input="onInpot"
|
|
||||||
@change="onChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="title">Scale</div>
|
|
||||||
<div class="content">
|
|
||||||
<div>
|
|
||||||
<depth-input
|
|
||||||
type="number"
|
|
||||||
before="X"
|
|
||||||
after="%"
|
|
||||||
v-model="data.scaleX"
|
|
||||||
@input="onInpot"
|
|
||||||
@change="onChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<depth-input
|
|
||||||
type="number"
|
|
||||||
before="Y"
|
|
||||||
after="%"
|
|
||||||
v-model="data.scaleY"
|
|
||||||
@input="onInpot"
|
|
||||||
@change="onChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="title">Appearance</div>
|
|
||||||
<div class="content">
|
|
||||||
<div>
|
|
||||||
<span class="label">Opacity</span>
|
|
||||||
<depth-input
|
<depth-input
|
||||||
type="number"
|
type="number"
|
||||||
after="%"
|
after="%"
|
||||||
@@ -86,7 +17,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="object.type === 'rect'">
|
<div v-if="object.type === 'rect'">
|
||||||
<span class="label">Corner Radius</span>
|
<span class="label">{{ $t('DepthCanvas.cornerRadius') }}</span>
|
||||||
<depth-input
|
<depth-input
|
||||||
type="number"
|
type="number"
|
||||||
v-model="data.radius"
|
v-model="data.radius"
|
||||||
@@ -96,12 +27,32 @@
|
|||||||
@change="onChange"
|
@change="onChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="object.type === 'path'">
|
||||||
|
<span class="label">{{ $t('DepthCanvas.strokeWidth') }}</span>
|
||||||
|
<depth-input
|
||||||
|
type="number"
|
||||||
|
v-model="data.strokeWidth"
|
||||||
|
min="0"
|
||||||
|
step="1"
|
||||||
|
@input="onInpot"
|
||||||
|
@change="onChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div v-else></div>
|
<div v-else></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div>
|
<div>
|
||||||
<span class="label">Color</span>
|
<span class="label">{{ $t('DepthCanvas.color') }}</span>
|
||||||
<depth-input
|
<depth-input
|
||||||
|
v-if="object.type === 'path'"
|
||||||
|
type="color"
|
||||||
|
v-model="data.stroke"
|
||||||
|
after="%"
|
||||||
|
@input="onInpot"
|
||||||
|
@change="onChange"
|
||||||
|
/>
|
||||||
|
<depth-input
|
||||||
|
v-else
|
||||||
type="color"
|
type="color"
|
||||||
v-model="data.fill"
|
v-model="data.fill"
|
||||||
after="%"
|
after="%"
|
||||||
@@ -116,10 +67,6 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, inject, computed, nextTick, onBeforeUnmount, reactive, watch } from 'vue'
|
import { ref, inject, computed, nextTick, onBeforeUnmount, reactive, watch } from 'vue'
|
||||||
import { ElColorPicker } from 'element-plus'
|
|
||||||
import { getTransformScaleAngle } from '../../manager/ObjectManager'
|
|
||||||
import DepthOffsetTool from '../tools/depth-offset-tool.vue'
|
|
||||||
import DepthSlider from '../tools/depth-slider.vue'
|
|
||||||
import DepthInput from '../tools/depth-input.vue'
|
import DepthInput from '../tools/depth-input.vue'
|
||||||
const objectManager = inject('objectManager') as any
|
const objectManager = inject('objectManager') as any
|
||||||
const stateManager = inject('stateManager') as any
|
const stateManager = inject('stateManager') as any
|
||||||
@@ -132,32 +79,20 @@
|
|||||||
const id = computed(() => props.object.info.id)
|
const id = computed(() => props.object.info.id)
|
||||||
|
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
scaleX: 1,
|
|
||||||
scaleY: 1,
|
|
||||||
opacity: 100,
|
opacity: 100,
|
||||||
radius: 0,
|
radius: 0,
|
||||||
|
|
||||||
fill: ''
|
fill: '',
|
||||||
// stroke: '',
|
stroke: '',
|
||||||
// strokeWidth: 0
|
strokeWidth: 0
|
||||||
})
|
})
|
||||||
const updateData = async () => {
|
const updateData = async () => {
|
||||||
await nextTick()
|
await nextTick()
|
||||||
data.top = Math.round(props.object.top)
|
|
||||||
data.left = Math.round(props.object.left)
|
|
||||||
data.width = Math.round(props.object.width)
|
|
||||||
data.height = Math.round(props.object.height)
|
|
||||||
data.scaleX = Math.round(props.object.scaleX * 100)
|
|
||||||
data.scaleY = Math.round(props.object.scaleY * 100)
|
|
||||||
data.opacity = Math.round(props.object.opacity * 100)
|
data.opacity = Math.round(props.object.opacity * 100)
|
||||||
data.radius = Math.round(props.object.rx)
|
data.radius = Math.round(props.object.rx)
|
||||||
data.fill = props.object.fill
|
data.fill = props.object.fill
|
||||||
// data.stroke = props.object.stroke
|
data.stroke = props.object.stroke
|
||||||
// data.strokeWidth = props.object.strokeWidth
|
data.strokeWidth = props.object.strokeWidth
|
||||||
}
|
}
|
||||||
updateData()
|
updateData()
|
||||||
watch(() => props.object, updateData)
|
watch(() => props.object, updateData)
|
||||||
@@ -167,14 +102,16 @@
|
|||||||
const setPriority = (isRecord: boolean) => {
|
const setPriority = (isRecord: boolean) => {
|
||||||
const options = {
|
const options = {
|
||||||
...data,
|
...data,
|
||||||
opacity: data.opacity / 100,
|
opacity: data.opacity / 100
|
||||||
scaleX: data.scaleX / 100,
|
|
||||||
scaleY: data.scaleY / 100
|
|
||||||
}
|
}
|
||||||
if (props.object.type === 'rect') {
|
if (props.object.type === 'rect') {
|
||||||
options['rx'] = data.radius
|
options['rx'] = data.radius
|
||||||
options['ry'] = data.radius
|
options['ry'] = data.radius
|
||||||
}
|
}
|
||||||
|
if (props.object.type !== 'path') {
|
||||||
|
delete options.stroke
|
||||||
|
delete options.strokeWidth
|
||||||
|
}
|
||||||
delete options.radius
|
delete options.radius
|
||||||
objectManager.updateProperty(id.value, options, isRecord)
|
objectManager.updateProperty(id.value, options, isRecord)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
width: 0;
|
width: 0;
|
||||||
top: 2.2rem;
|
top: 2.2rem;
|
||||||
left: 3rem;
|
left: 3rem;
|
||||||
max-height: 80%;
|
max-height: 90%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.6rem;
|
gap: 1.6rem;
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<span class="icon"><svg-icon name="dc-layer" size="16" /></span>
|
<span class="icon"><svg-icon name="dc-layer" size="16" /></span>
|
||||||
<span class="title">Layer</span>
|
<span class="title">{{ $t('DepthCanvas.layer') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<span class="icon" @click="addLayer"><svg-icon name="add" size="14" /></span>
|
<span class="icon" @click="addLayer"><svg-icon name="add" size="14" /></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content mini-scrollbar">
|
||||||
<VueDraggable
|
<VueDraggable
|
||||||
:model-value="list"
|
:model-value="list"
|
||||||
@start="(e) => handleDragStart(e)"
|
@start="(e) => handleDragStart(e)"
|
||||||
@@ -173,13 +173,6 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
min-height: 20rem;
|
min-height: 20rem;
|
||||||
&::-webkit-scrollbar {
|
|
||||||
width: 4px;
|
|
||||||
}
|
|
||||||
&::-webkit-scrollbar-thumb {
|
|
||||||
border-radius: 4px;
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.sortable-layers-child {
|
.sortable-layers-child {
|
||||||
|
|||||||
@@ -2,10 +2,12 @@
|
|||||||
<div class="depth-input" :class="{ color: isColor }">
|
<div class="depth-input" :class="{ color: isColor }">
|
||||||
<span class="decorate"></span>
|
<span class="decorate"></span>
|
||||||
<span v-show="icon" class="icon">
|
<span v-show="icon" class="icon">
|
||||||
<svg-icon :name="icon" :size="iconSize" size-unit="px" />
|
<svg-icon :name="icon" :size="iconSize" />
|
||||||
</span>
|
</span>
|
||||||
<span v-show="before" class="before">{{ before }}</span>
|
<span v-show="before" class="before">{{ before }}</span>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
v-if="!isColor"
|
||||||
v-bind="attrs"
|
v-bind="attrs"
|
||||||
:value="modelValue"
|
:value="modelValue"
|
||||||
@input="onInput"
|
@input="onInput"
|
||||||
@@ -13,15 +15,17 @@
|
|||||||
@copy.stop
|
@copy.stop
|
||||||
@keydown.stop
|
@keydown.stop
|
||||||
/>
|
/>
|
||||||
<input
|
<template v-else>
|
||||||
v-if="isColor"
|
<input
|
||||||
readonly
|
v-bind="attrs"
|
||||||
type="text"
|
type="color"
|
||||||
:value="colorObj.color"
|
:value="colorObj.color"
|
||||||
@copy.stop
|
@input="onInput"
|
||||||
@keydown.stop
|
@change="onChange"
|
||||||
/>
|
@copy.stop
|
||||||
<template v-if="isColor">
|
@keydown.stop
|
||||||
|
/>
|
||||||
|
<input readonly :value="colorObj.color" @copy.stop @keydown.stop />
|
||||||
<span class="decorate marginl"></span>
|
<span class="decorate marginl"></span>
|
||||||
<input
|
<input
|
||||||
class="alpha"
|
class="alpha"
|
||||||
@@ -35,6 +39,7 @@
|
|||||||
@keydown.stop
|
@keydown.stop
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<span v-show="after" class="after">{{ after }}</span>
|
<span v-show="after" class="after">{{ after }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -220,45 +225,45 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid var(--depth-input-border-color, rgba(230, 230, 231, 1));
|
border: 0.1rem solid var(--depth-input-border-color, rgba(230, 230, 231, 1));
|
||||||
border-radius: 2px;
|
border-radius: 0.2rem;
|
||||||
height: var(--depth-input-height, 20px);
|
height: var(--depth-input-height, 2rem);
|
||||||
background-color: var(--depth-input-bg-color, #fff);
|
background-color: var(--depth-input-bg-color, #fff);
|
||||||
padding: 0 4px 0 2px;
|
padding: 0 0.4rem 0 0.2rem;
|
||||||
&.color {
|
&.color {
|
||||||
--depth-input-decorate-margin-right: 10px;
|
--depth-input-decorate-margin-right: 1rem;
|
||||||
--depth-input-input-margin-right: 10px;
|
--depth-input-input-margin-right: 1rem;
|
||||||
--depth-input-input-font-align: left;
|
--depth-input-input-font-align: left;
|
||||||
--depth-input-after-color: rgba(181, 181, 181, 1);
|
--depth-input-after-color: rgba(181, 181, 181, 1);
|
||||||
}
|
}
|
||||||
> .decorate {
|
> .decorate {
|
||||||
width: 2px;
|
width: 0.2rem;
|
||||||
background-color: var(--depth-input-decorate-color, rgba(230, 230, 231, 1));
|
background-color: var(--depth-input-decorate-color, rgba(230, 230, 231, 1));
|
||||||
border-radius: 2px;
|
border-radius: 0.2rem;
|
||||||
height: 75%;
|
height: 75%;
|
||||||
margin-right: var(--depth-input-decorate-margin-right, 4px);
|
margin-right: var(--depth-input-decorate-margin-right, 0.4rem);
|
||||||
}
|
}
|
||||||
> .iconfont {
|
> .iconfont {
|
||||||
font-size: 12px;
|
font-size: 1.2rem;
|
||||||
color: #000;
|
color: #000;
|
||||||
margin-right: 4px;
|
margin-right: 0.4rem;
|
||||||
}
|
}
|
||||||
> .before {
|
> .before {
|
||||||
font-size: 12px;
|
font-size: 1.2rem;
|
||||||
color: #000;
|
color: #000;
|
||||||
margin-right: 4px;
|
margin-right: 0.4rem;
|
||||||
}
|
}
|
||||||
> .after {
|
> .after {
|
||||||
font-size: 12px;
|
font-size: 1.2rem;
|
||||||
color: var(--depth-input-after-color, #000);
|
color: var(--depth-input-after-color, #000);
|
||||||
margin-left: 2px;
|
margin-left: 0.2rem;
|
||||||
}
|
}
|
||||||
> input {
|
> input {
|
||||||
font-size: 12px;
|
font-size: 1.2rem;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin-right: var(--depth-input-input-margin-right, 0);
|
margin-right: var(--depth-input-input-margin-right, 0rem);
|
||||||
text-align: var(--depth-input-input-font-align, right);
|
text-align: var(--depth-input-input-font-align, right);
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -277,9 +282,9 @@
|
|||||||
}
|
}
|
||||||
&[type='color'] {
|
&[type='color'] {
|
||||||
flex: 0.5;
|
flex: 0.5;
|
||||||
border-radius: 2px;
|
border-radius: 0.2rem;
|
||||||
height: 70%;
|
height: 70%;
|
||||||
border: 1px solid rgb(42, 42, 42);
|
border: 0.1rem solid rgb(42, 42, 42);
|
||||||
display: block;
|
display: block;
|
||||||
&::-webkit-color-swatch-wrapper {
|
&::-webkit-color-swatch-wrapper {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|||||||
@@ -152,52 +152,52 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
> * {
|
> * {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin-right: 10px;
|
margin-right: 1rem;
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
> .dish {
|
> .dish {
|
||||||
width: 115px;
|
width: 11.5rem;
|
||||||
height: 115px;
|
height: 11.5rem;
|
||||||
border: 1px solid #eaeaea;
|
border: 0.1rem solid #eaeaea;
|
||||||
border-radius: 3.4px;
|
border-radius: 0.4rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: #f6f6f6;
|
background-color: #f6f6f6;
|
||||||
margin-top: 20px;
|
margin-top: 2rem;
|
||||||
> * {
|
> * {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
> img {
|
> img {
|
||||||
width: 12px;
|
width: 1.2rem;
|
||||||
height: 12px;
|
height: 1.2rem;
|
||||||
bottom: 3.5px;
|
bottom: 0.35rem;
|
||||||
right: 3.5px;
|
right: 0.35rem;
|
||||||
}
|
}
|
||||||
> .ball {
|
> .ball {
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
width: 8.5px;
|
width: 0.85rem;
|
||||||
height: 8.5px;
|
height: 0.85rem;
|
||||||
border: 1px solid #fff;
|
border: 0.1rem solid #fff;
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
box-shadow: 0px 0.68px 0.17px 0px rgba(0, 0, 0, 0.26);
|
box-shadow: 9 0.07rem 0.02rem 0 rgba(0, 0, 0, 0.26);
|
||||||
}
|
}
|
||||||
> .tip {
|
> .tip {
|
||||||
font-size: 8.5px;
|
font-size: 0.85rem;
|
||||||
color: #000;
|
color: #000;
|
||||||
line-height: 24px;
|
line-height: 2.4rem;
|
||||||
&.x {
|
&.x {
|
||||||
top: 50%;
|
top: 50%;
|
||||||
right: 0%;
|
right: 0%;
|
||||||
transform: translate(100%, -50%);
|
transform: translate(100%, -50%);
|
||||||
padding-left: 6px;
|
padding-left: 0.6rem;
|
||||||
}
|
}
|
||||||
&.y {
|
&.y {
|
||||||
top: 0%;
|
top: 0%;
|
||||||
@@ -216,15 +216,15 @@
|
|||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
&.x {
|
&.x {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-top-width: 1px;
|
border-top-width: 0.1rem;
|
||||||
}
|
}
|
||||||
&.y {
|
&.y {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-left-width: 1px;
|
border-left-width: 0.1rem;
|
||||||
}
|
}
|
||||||
&.z {
|
&.z {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
border-top-width: 1px;
|
border-top-width: 0.1rem;
|
||||||
border-color: #454754;
|
border-color: #454754;
|
||||||
transform: translate(0%, -50%) rotateZ(var(--rotateZ));
|
transform: translate(0%, -50%) rotateZ(var(--rotateZ));
|
||||||
transform-origin: left center;
|
transform-origin: left center;
|
||||||
|
|||||||
@@ -22,12 +22,12 @@
|
|||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.depth-select {
|
.depth-select {
|
||||||
&:deep(.el-select) {
|
&:deep(.el-select) {
|
||||||
--el-select-input-font-size: 12px;
|
--el-select-input-font-size: 1.2rem;
|
||||||
.el-select__wrapper {
|
.el-select__wrapper {
|
||||||
font-size: 12px;
|
font-size: 1.2rem;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
height: 28px;
|
height: 2.8rem;
|
||||||
padding: 0 8px;
|
padding: 0 0.8rem;
|
||||||
}
|
}
|
||||||
.el-select__selected-item,
|
.el-select__selected-item,
|
||||||
.el-select__input-wrapper,
|
.el-select__input-wrapper,
|
||||||
@@ -35,17 +35,17 @@
|
|||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
.el-select__input {
|
.el-select__input {
|
||||||
height: 24px;
|
height: 2.4rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.el-popper {
|
.el-popper {
|
||||||
.el-select-dropdown {
|
.el-select-dropdown {
|
||||||
li {
|
li {
|
||||||
padding-left: 8px;
|
padding-left: 0.8rem;
|
||||||
height: 30px;
|
height: 3rem;
|
||||||
line-height: 30px;
|
line-height: 3rem;
|
||||||
font-size: 12px;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
--input-thumb-size: 1.4rem;
|
--input-thumb-size: 1.2rem;
|
||||||
--backcolor1: var(--depth-slider-thumb-color1, #000);
|
--backcolor1: var(--depth-slider-thumb-color1, #000);
|
||||||
--backcolor2: var(--depth-slider-thumb-color2, #d3d3d3);
|
--backcolor2: var(--depth-slider-thumb-color2, #d3d3d3);
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
background: var(--backcolor1); /* 蓝色滑块 */
|
background: var(--backcolor1); /* 蓝色滑块 */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
&::-webkit-slider-thumb:hover {
|
&::-webkit-slider-thumb:hover {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
@@ -153,9 +153,9 @@
|
|||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
border-left: 5px solid transparent;
|
border-left: 0.5rem solid transparent;
|
||||||
border-right: 5px solid transparent;
|
border-right: 0.5rem solid transparent;
|
||||||
border-top: 5px solid rgba(0, 0, 0, 0.8);
|
border-top: 0.5rem solid rgba(0, 0, 0, 0.8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export class AISelectboxToolManager {
|
|||||||
if (!oldIsAAA && newIsAAA) {
|
if (!oldIsAAA && newIsAAA) {
|
||||||
// 普通工具切换到智能框选工具
|
// 普通工具切换到智能框选工具
|
||||||
this.init()
|
this.init()
|
||||||
|
this.canvasManager.discardActiveObject()
|
||||||
} else if (oldIsAAA && !newIsAAA) {
|
} else if (oldIsAAA && !newIsAAA) {
|
||||||
// 智能框选工具切换到普通工具
|
// 智能框选工具切换到普通工具
|
||||||
this.clear()
|
this.clear()
|
||||||
@@ -101,6 +102,10 @@ export class AISelectboxToolManager {
|
|||||||
this.canvasManager.canvas.remove(this.indicatorObject)
|
this.canvasManager.canvas.remove(this.indicatorObject)
|
||||||
this.indicatorObject = null
|
this.indicatorObject = null
|
||||||
}
|
}
|
||||||
|
resetDemoObject() {
|
||||||
|
this.clearDemoObject()
|
||||||
|
this.createDemoObject()
|
||||||
|
}
|
||||||
// 创建临时画布对象
|
// 创建临时画布对象
|
||||||
async createStaticCanvas(object: fabric.Object) {
|
async createStaticCanvas(object: fabric.Object) {
|
||||||
if (!this.demoObject) this.createDemoObject()
|
if (!this.demoObject) this.createDemoObject()
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import { fabric } from 'fabric-with-all'
|
|||||||
import { createId } from '../../tools/tools'
|
import { createId } from '../../tools/tools'
|
||||||
import { exportObjectsToImage, exportObjectToThumbnail } from '../tools/exportMethod'
|
import { exportObjectsToImage, exportObjectToThumbnail } from '../tools/exportMethod'
|
||||||
import { OperationType, BlendMode } from '../tools/layerHelper'
|
import { OperationType, BlendMode } from '../tools/layerHelper'
|
||||||
import { getArrowPath, cloneObjects, getStarArr } from '../tools/canvasMethod'
|
import { getArrowPath, getLinePath, cloneObjects, getStarArr } from '../tools/canvasMethod'
|
||||||
|
import i18n from '@/lang/index'
|
||||||
|
const t = i18n.global.t
|
||||||
|
|
||||||
export class LayerManager {
|
export class LayerManager {
|
||||||
stateManager: any
|
stateManager: any
|
||||||
@@ -134,10 +136,11 @@ export class LayerManager {
|
|||||||
copyLayerById(id) {
|
copyLayerById(id) {
|
||||||
const object = this.canvasManager.getObjectById(id)
|
const object = this.canvasManager.getObjectById(id)
|
||||||
if (!object) return console.warn('复制图层失败,对象不存在ID:', id)
|
if (!object) return console.warn('复制图层失败,对象不存在ID:', id)
|
||||||
|
this.canvasManager.discardActiveObject()
|
||||||
cloneObjects([object]).then(objects => {
|
cloneObjects([object]).then(objects => {
|
||||||
const newObject = objects[0]
|
const newObject = objects[0]
|
||||||
const info = JSON.parse(JSON.stringify(newObject.info))
|
const info = JSON.parse(JSON.stringify(newObject.info))
|
||||||
info.id = createId("image")
|
info.id = createId("copylayer")
|
||||||
// info.name = info.name
|
// info.name = info.name
|
||||||
newObject.set({
|
newObject.set({
|
||||||
top: newObject.top + 15,
|
top: newObject.top + 15,
|
||||||
@@ -206,7 +209,7 @@ export class LayerManager {
|
|||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
info: {
|
info: {
|
||||||
id: createId("image"),
|
id: createId("image"),
|
||||||
name: '空图层',
|
name: t('DepthCanvas.emptyLayer'),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.setLayerPosition(emptyObject)
|
this.setLayerPosition(emptyObject)
|
||||||
@@ -226,7 +229,7 @@ export class LayerManager {
|
|||||||
evented: false,
|
evented: false,
|
||||||
info: {
|
info: {
|
||||||
id: createId("group"),
|
id: createId("group"),
|
||||||
name: '智能选区组',
|
name: t('DepthCanvas.aiGroupLayer'),
|
||||||
showChildren: true,
|
showChildren: true,
|
||||||
...(options?.info || {}),
|
...(options?.info || {}),
|
||||||
}
|
}
|
||||||
@@ -245,7 +248,7 @@ export class LayerManager {
|
|||||||
...(options || {}),
|
...(options || {}),
|
||||||
info: {
|
info: {
|
||||||
id: createId("text"),
|
id: createId("text"),
|
||||||
name: '文本图层',
|
name: t('DepthCanvas.textLayer'),
|
||||||
...(options?.info || {}),
|
...(options?.info || {}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -263,7 +266,7 @@ export class LayerManager {
|
|||||||
...(options || {}),
|
...(options || {}),
|
||||||
info: {
|
info: {
|
||||||
id: createId("rect"),
|
id: createId("rect"),
|
||||||
name: '矩形图层',
|
name: t('DepthCanvas.rectLayer'),
|
||||||
...(options?.info || {}),
|
...(options?.info || {}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -274,25 +277,27 @@ export class LayerManager {
|
|||||||
}
|
}
|
||||||
/** 创建直线图层 */
|
/** 创建直线图层 */
|
||||||
async createLineLayer(options?: any, isRecord = true, isActive = true) {
|
async createLineLayer(options?: any, isRecord = true, isActive = true) {
|
||||||
const line = [options?.x1 || 0, options?.y1 || 0, options?.x2 || 100, options?.y2 || 0]
|
const width = options?.width || 100
|
||||||
delete options.x1
|
const height = options?.height || 2
|
||||||
delete options.y1
|
delete options.width
|
||||||
delete options.x2
|
delete options.height
|
||||||
delete options.y2
|
const arrowObject = new fabric.Path(getLinePath(width, height), {
|
||||||
const lineObject = new fabric.Line(line, {
|
stroke: '#000', // 只设置边框颜色
|
||||||
stroke: 'black', // 线条颜色
|
strokeWidth: 2, // 边框宽度
|
||||||
strokeWidth: 2, // 线条粗细
|
fill: 'transparent', // 不填充
|
||||||
|
strokeLineCap: 'round',
|
||||||
|
strokeLineJoin: 'round',
|
||||||
...(options || {}),
|
...(options || {}),
|
||||||
info: {
|
info: {
|
||||||
id: createId("line"),
|
id: createId("line"),
|
||||||
name: '直线图层',
|
name: t('DepthCanvas.lineLayer'),
|
||||||
...(options?.info || {}),
|
...(options?.info || {}),
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
this.setLayerPosition(lineObject, options)
|
this.setLayerPosition(arrowObject, options)
|
||||||
await this.canvasManager.add(lineObject, isRecord)
|
await this.canvasManager.add(arrowObject, isRecord)
|
||||||
if (isActive) this.setActiveID(lineObject.info.id)
|
if (isActive) this.setActiveID(arrowObject.info.id)
|
||||||
return lineObject
|
return arrowObject
|
||||||
}
|
}
|
||||||
/** 创建椭圆图层 */
|
/** 创建椭圆图层 */
|
||||||
async createEllipseLayer(options?: any, isRecord = true, isActive = true) {
|
async createEllipseLayer(options?: any, isRecord = true, isActive = true) {
|
||||||
@@ -302,7 +307,7 @@ export class LayerManager {
|
|||||||
...(options || {}),
|
...(options || {}),
|
||||||
info: {
|
info: {
|
||||||
id: createId("ellipse"),
|
id: createId("ellipse"),
|
||||||
name: '椭圆图层',
|
name: t('DepthCanvas.ellipseLayer'),
|
||||||
...(options?.info || {}),
|
...(options?.info || {}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -321,7 +326,7 @@ export class LayerManager {
|
|||||||
...(options || {}),
|
...(options || {}),
|
||||||
info: {
|
info: {
|
||||||
id: createId("triangle"),
|
id: createId("triangle"),
|
||||||
name: '三角形图层',
|
name: t('DepthCanvas.triangleLayer'),
|
||||||
...(options?.info || {}),
|
...(options?.info || {}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -341,7 +346,7 @@ export class LayerManager {
|
|||||||
...(options || {}),
|
...(options || {}),
|
||||||
info: {
|
info: {
|
||||||
id: createId("star"),
|
id: createId("star"),
|
||||||
name: '五角星图层',
|
name: t('DepthCanvas.starLayer'),
|
||||||
...(options?.info || {}),
|
...(options?.info || {}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -353,19 +358,19 @@ export class LayerManager {
|
|||||||
/** 创建箭头图层 */
|
/** 创建箭头图层 */
|
||||||
async createArrowLayer(options?: any, isRecord = true, isActive = true) {
|
async createArrowLayer(options?: any, isRecord = true, isActive = true) {
|
||||||
const width = options?.width || 100
|
const width = options?.width || 100
|
||||||
const height = options?.height || 10
|
const strokeWidth = options?.strokeWidth || 4
|
||||||
delete options.width
|
delete options.width
|
||||||
delete options.height
|
delete options.strokeWidth
|
||||||
const arrowObject = new fabric.Path(getArrowPath(width, height), {
|
const arrowObject = new fabric.Path(getArrowPath(width, strokeWidth), {
|
||||||
stroke: '#000', // 只设置边框颜色
|
stroke: '#000', // 只设置边框颜色
|
||||||
strokeWidth: 3, // 边框宽度
|
strokeWidth, // 边框宽度
|
||||||
fill: 'transparent', // 不填充
|
fill: 'transparent', // 不填充
|
||||||
strokeLineCap: 'round',
|
strokeLineCap: 'round',
|
||||||
strokeLineJoin: 'round',
|
strokeLineJoin: 'round',
|
||||||
...(options || {}),
|
...(options || {}),
|
||||||
info: {
|
info: {
|
||||||
id: createId("star"),
|
id: createId("arrow"),
|
||||||
name: '箭头图层',
|
name: t('DepthCanvas.arrowLayer'),
|
||||||
...(options?.info || {}),
|
...(options?.info || {}),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -395,7 +400,7 @@ export class LayerManager {
|
|||||||
...(options || {}),
|
...(options || {}),
|
||||||
info: {
|
info: {
|
||||||
id: createId("image"),
|
id: createId("image"),
|
||||||
name: "图片图层",
|
name: t('DepthCanvas.imageLayer'),
|
||||||
...(options?.info || {}),
|
...(options?.info || {}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -419,7 +424,7 @@ export class LayerManager {
|
|||||||
info: {
|
info: {
|
||||||
...(targetLayer?.info || {}),
|
...(targetLayer?.info || {}),
|
||||||
id: createId("image"),
|
id: createId("image"),
|
||||||
name: targetLayer?.info?.name || "合并图层",
|
name: targetLayer?.info?.name || t('DepthCanvas.mergeLayer'),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
resolve(img)
|
resolve(img)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { OperationType, OperationTypes } from "../tools/layerHelper";
|
import { OperationType, OperationTypes } from "../tools/layerHelper";
|
||||||
import { getStarArr, getArrowPath, distance, angleBetweenPointsDegrees } from "../tools/canvasMethod";
|
import { getStarArr, getArrowPath, getLinePath, distance, angleBetweenPointsDegrees } from "../tools/canvasMethod";
|
||||||
import { fabric } from 'fabric-with-all'
|
import { fabric } from 'fabric-with-all'
|
||||||
/** 形状管理器 */
|
/** 形状管理器 */
|
||||||
export class ShapeToolManager {
|
export class ShapeToolManager {
|
||||||
@@ -136,22 +136,47 @@ export class ShapeToolManager {
|
|||||||
|
|
||||||
/** 绘制直线 */
|
/** 绘制直线 */
|
||||||
downLine() {
|
downLine() {
|
||||||
const line = new fabric.Line([this.startX, this.startY, this.startX, this.startY], {
|
// const line = new fabric.Line([this.startX, this.startY, this.startX, this.startY], {
|
||||||
stroke: 'black', // 线条颜色
|
// stroke: 'black', // 线条颜色
|
||||||
strokeWidth: 2 // 线条粗细
|
// strokeWidth: 2 // 线条粗细
|
||||||
})
|
// })
|
||||||
return line
|
// return line
|
||||||
|
return new fabric.Path();
|
||||||
}
|
}
|
||||||
moveLine({ x, y }) {
|
moveLine({ x, y }) {
|
||||||
this.demoObject.set({
|
// this.demoObject.set({
|
||||||
x1: this.startX,
|
// x1: this.startX,
|
||||||
y1: this.startY,
|
// y1: this.startY,
|
||||||
x2: x,
|
// x2: x,
|
||||||
y2: y,
|
// y2: y,
|
||||||
})
|
// })
|
||||||
|
const width = distance(this.startX, this.startY, x, y)
|
||||||
|
const angle = angleBetweenPointsDegrees(this.startX, this.startY, x, y)
|
||||||
|
this.canvasManager.canvas.remove(this.demoObject)
|
||||||
|
const arrow = new fabric.Path(getLinePath(width, 2), {
|
||||||
|
left: this.startX,
|
||||||
|
top: this.startY,
|
||||||
|
stroke: '#000', // 只设置边框颜色
|
||||||
|
strokeWidth: 2, // 边框宽度
|
||||||
|
fill: 'transparent', // 不填充
|
||||||
|
strokeLineCap: 'round',
|
||||||
|
strokeLineJoin: 'round',
|
||||||
|
originY: 'center',
|
||||||
|
angle: angle,
|
||||||
|
});
|
||||||
|
this.canvasManager.canvas.add(arrow)
|
||||||
|
this.demoObject = arrow
|
||||||
}
|
}
|
||||||
upLine(object) {
|
upLine(object) {
|
||||||
this.layerManager.createLineLayer(object)
|
if (object.originY !== "center") {
|
||||||
|
this.layerManager.createLineLayer({
|
||||||
|
left: this.startX,
|
||||||
|
top: this.startY,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.layerManager.createLineLayer(object)
|
||||||
|
}
|
||||||
|
// this.layerManager.createLineLayer(object)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 绘制椭圆 */
|
/** 绘制椭圆 */
|
||||||
@@ -228,11 +253,11 @@ export class ShapeToolManager {
|
|||||||
const width = distance(this.startX, this.startY, x, y)
|
const width = distance(this.startX, this.startY, x, y)
|
||||||
const angle = angleBetweenPointsDegrees(this.startX, this.startY, x, y)
|
const angle = angleBetweenPointsDegrees(this.startX, this.startY, x, y)
|
||||||
this.canvasManager.canvas.remove(this.demoObject)
|
this.canvasManager.canvas.remove(this.demoObject)
|
||||||
const arrow = new fabric.Path(getArrowPath(width, 10), {
|
const arrow = new fabric.Path(getArrowPath(width, 4), {
|
||||||
left: this.startX,
|
left: this.startX,
|
||||||
top: this.startY,
|
top: this.startY,
|
||||||
stroke: '#000', // 只设置边框颜色
|
stroke: '#000', // 只设置边框颜色
|
||||||
strokeWidth: 3, // 边框宽度
|
strokeWidth: 4, // 边框宽度
|
||||||
fill: 'transparent', // 不填充
|
fill: 'transparent', // 不填充
|
||||||
strokeLineCap: 'round',
|
strokeLineCap: 'round',
|
||||||
strokeLineJoin: 'round',
|
strokeLineJoin: 'round',
|
||||||
@@ -247,7 +272,7 @@ export class ShapeToolManager {
|
|||||||
this.layerManager.createArrowLayer({
|
this.layerManager.createArrowLayer({
|
||||||
left: this.startX,
|
left: this.startX,
|
||||||
top: this.startY,
|
top: this.startY,
|
||||||
}, true)
|
})
|
||||||
} else {
|
} else {
|
||||||
this.layerManager.createArrowLayer(object)
|
this.layerManager.createArrowLayer(object)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ export class StateManager {
|
|||||||
/** 记录状态 */
|
/** 记录状态 */
|
||||||
recordState() {
|
recordState() {
|
||||||
if (this.running.value) return
|
if (this.running.value) return
|
||||||
console.log("recordState")
|
|
||||||
this.running.value = true
|
this.running.value = true
|
||||||
if (this.historyIndex.value < this.historyList.value.length - 1) {
|
if (this.historyIndex.value < this.historyList.value.length - 1) {
|
||||||
this.historyList.value.splice(this.historyIndex.value + 1)
|
this.historyList.value.splice(this.historyIndex.value + 1)
|
||||||
|
|||||||
@@ -61,13 +61,26 @@ export function getStarArr(width = 0, height = 0) {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
/** 获取箭头路径 */
|
/** 获取箭头路径 */
|
||||||
export function getArrowPath(width = 0, height = 0) {
|
export function getArrowPath(width = 0, strokeWidth = 4) {
|
||||||
|
const height = strokeWidth * 4
|
||||||
const arr = [
|
const arr = [
|
||||||
["M", 0, height / 2],
|
["M", 0, height / 2],
|
||||||
["L", width, height / 2],
|
["L", width, height / 2],
|
||||||
["M", width - 8, 0],
|
["M", width - height, 0],
|
||||||
|
["L", width, height / 2],
|
||||||
|
["L", width - height, height],
|
||||||
|
]
|
||||||
|
var path = ""
|
||||||
|
arr.forEach(item => {
|
||||||
|
path += item.join(" ") + " "
|
||||||
|
})
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
/** 获取直线路径 */
|
||||||
|
export function getLinePath(width = 0, height = 0) {
|
||||||
|
const arr = [
|
||||||
|
["M", 0, height / 2],
|
||||||
["L", width, height / 2],
|
["L", width, height / 2],
|
||||||
["L", width - 8, height],
|
|
||||||
]
|
]
|
||||||
var path = ""
|
var path = ""
|
||||||
arr.forEach(item => {
|
arr.forEach(item => {
|
||||||
|
|||||||
@@ -135,7 +135,9 @@ export default {
|
|||||||
confirm: 'Confirm',
|
confirm: 'Confirm',
|
||||||
styleTitle: 'Settings',
|
styleTitle: 'Settings',
|
||||||
createProject: 'Create Project',
|
createProject: 'Create Project',
|
||||||
trendingReport: 'Trending report'
|
trendingReport: 'Trending report',
|
||||||
|
reportPlaceholder:
|
||||||
|
'Generate a furniture trending report for 2026, including popular styles and design directions.'
|
||||||
},
|
},
|
||||||
area: {
|
area: {
|
||||||
unitedStates: 'United States',
|
unitedStates: 'United States',
|
||||||
@@ -201,6 +203,50 @@ export default {
|
|||||||
loading: 'Loading',
|
loading: 'Loading',
|
||||||
download: 'Download'
|
download: 'Download'
|
||||||
},
|
},
|
||||||
|
DepthCanvas: {
|
||||||
|
layer: "Layer",
|
||||||
|
editDetails: "Edit Details",
|
||||||
|
export: "Export",
|
||||||
|
save: "Save",
|
||||||
|
workbench: "Workbench",
|
||||||
|
position: "Position",
|
||||||
|
size: "Size",
|
||||||
|
appearance: "Appearance",
|
||||||
|
opacity: "Opacity",
|
||||||
|
cornerRadius: "Cor Radius",
|
||||||
|
strokeWidth: "Stroke Width",
|
||||||
|
color: "Color",
|
||||||
|
image: "Image",
|
||||||
|
settings: "Settings",
|
||||||
|
rotation: "Rotation",
|
||||||
|
scale: "Scale",
|
||||||
|
gapX: "Gap X",
|
||||||
|
gapY: "Gap Y",
|
||||||
|
offset: "Offset",
|
||||||
|
emptyLayer: "Empty Layer",
|
||||||
|
aiGroupLayer: "AI Group Layer",
|
||||||
|
textLayer: "Text Layer",
|
||||||
|
rectLayer: "Rect Layer",
|
||||||
|
lineLayer: "Line Layer",
|
||||||
|
ellipseLayer: "Ellipse Layer",
|
||||||
|
triangleLayer: "Triangle Layer",
|
||||||
|
starLayer: "Star Layer",
|
||||||
|
arrowLayer: "Arrow Layer",
|
||||||
|
imageLayer: "Image Layer",
|
||||||
|
mergeLayer: "Merge Layer",
|
||||||
|
rectangle: "Rectangle",
|
||||||
|
line: "Line",
|
||||||
|
arrow: "Arrow",
|
||||||
|
ellipse: "Ellipse",
|
||||||
|
triangle: "Triangle",
|
||||||
|
star: "Star",
|
||||||
|
add: "Add",
|
||||||
|
remove: "Remove",
|
||||||
|
brush: "Brush",
|
||||||
|
erase: "Erase",
|
||||||
|
create: "Create",
|
||||||
|
reset: "Reset"
|
||||||
|
},
|
||||||
clipDialog: {
|
clipDialog: {
|
||||||
title: 'Upload your profile photo',
|
title: 'Upload your profile photo',
|
||||||
cancel: 'Cancel',
|
cancel: 'Cancel',
|
||||||
|
|||||||
@@ -128,7 +128,8 @@ export default {
|
|||||||
confirm: '确认',
|
confirm: '确认',
|
||||||
styleTitle: '设置',
|
styleTitle: '设置',
|
||||||
createProject: '创建项目',
|
createProject: '创建项目',
|
||||||
trendingReport: '趋势报告'
|
trendingReport: '趋势报告',
|
||||||
|
reportPlaceholder: '生成一份2026年家具流行趋势报告,内容包括流行风格和设计方向。'
|
||||||
},
|
},
|
||||||
area: {
|
area: {
|
||||||
unitedStates: '美国',
|
unitedStates: '美国',
|
||||||
@@ -153,7 +154,7 @@ export default {
|
|||||||
quote: '引用',
|
quote: '引用',
|
||||||
delete: '删除',
|
delete: '删除',
|
||||||
edit: '编辑',
|
edit: '编辑',
|
||||||
generatingReport:'正在为您生成报告,可能需要几分钟时间,生成期间你可以继续进行其他任务'
|
generatingReport: '正在为您生成报告,可能需要几分钟时间,生成期间你可以继续进行其他任务'
|
||||||
},
|
},
|
||||||
|
|
||||||
// Version Tree
|
// Version Tree
|
||||||
@@ -198,6 +199,50 @@ export default {
|
|||||||
loading: '加载中',
|
loading: '加载中',
|
||||||
download: '下载'
|
download: '下载'
|
||||||
},
|
},
|
||||||
|
DepthCanvas: {
|
||||||
|
layer: "图层",
|
||||||
|
editDetails: "编辑详情",
|
||||||
|
export: "导出",
|
||||||
|
save: "保存",
|
||||||
|
workbench: "工作台",
|
||||||
|
position: "位置",
|
||||||
|
size: "大小",
|
||||||
|
appearance: "外观",
|
||||||
|
opacity: "透明度",
|
||||||
|
cornerRadius: "圆角半径",
|
||||||
|
strokeWidth: "边框宽度",
|
||||||
|
color: "颜色",
|
||||||
|
image: "图片",
|
||||||
|
settings: "设置",
|
||||||
|
rotation: "旋转角度",
|
||||||
|
scale: "缩放",
|
||||||
|
gapX: "水平间距",
|
||||||
|
gapY: "垂直间距",
|
||||||
|
offset: "偏移量",
|
||||||
|
emptyLayer: "空图层",
|
||||||
|
aiGroupLayer: "智能选区组",
|
||||||
|
textLayer: "文本图层",
|
||||||
|
rectLayer: "矩形图层",
|
||||||
|
lineLayer: "直线图层",
|
||||||
|
ellipseLayer: "椭圆图层",
|
||||||
|
triangleLayer: "三角形图层",
|
||||||
|
starLayer: "五角星图层",
|
||||||
|
arrowLayer: "箭头图层",
|
||||||
|
imageLayer: "图片图层",
|
||||||
|
mergeLayer: "合并图层",
|
||||||
|
rectangle: "矩形",
|
||||||
|
line: "直线",
|
||||||
|
arrow: "箭头",
|
||||||
|
ellipse: "椭圆",
|
||||||
|
triangle: "三角形",
|
||||||
|
star: "五角星",
|
||||||
|
add: "添加",
|
||||||
|
remove: "删除",
|
||||||
|
brush: "画笔",
|
||||||
|
erase: "擦除",
|
||||||
|
create: "创建",
|
||||||
|
reset: "重置"
|
||||||
|
},
|
||||||
clipDialog: {
|
clipDialog: {
|
||||||
title: '上传您的个人资料照片',
|
title: '上传您的个人资料照片',
|
||||||
cancel: '取消',
|
cancel: '取消',
|
||||||
|
|||||||
@@ -495,6 +495,7 @@
|
|||||||
let combinedContent = item.content || ''
|
let combinedContent = item.content || ''
|
||||||
let combinedThinkingText = item.reasoning || ''
|
let combinedThinkingText = item.reasoning || ''
|
||||||
let combinedImageUrl = item.image_url || null
|
let combinedImageUrl = item.image_url || null
|
||||||
|
let webAddress = item.webAddress || null
|
||||||
// 继续往后找连续的 assistant 消息
|
// 继续往后找连续的 assistant 消息
|
||||||
let j = i + 1
|
let j = i + 1
|
||||||
while (j < dialogue.length && dialogue[j].role === 'assistant') {
|
while (j < dialogue.length && dialogue[j].role === 'assistant') {
|
||||||
@@ -504,6 +505,12 @@
|
|||||||
if (dialogue[j].image_url) {
|
if (dialogue[j].image_url) {
|
||||||
combinedImageUrl = dialogue[j].image_url
|
combinedImageUrl = dialogue[j].image_url
|
||||||
}
|
}
|
||||||
|
if (dialogue[j].webAddress) {
|
||||||
|
combinedContent += `<slot slot-name="url"></slot>`
|
||||||
|
webAddress = dialogue[j].webAddress
|
||||||
|
// console.log('webAddress22222222222222', dialogue[j].webAddress)
|
||||||
|
// debugger
|
||||||
|
}
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,6 +525,7 @@
|
|||||||
thinkingText: combinedThinkingText,
|
thinkingText: combinedThinkingText,
|
||||||
text: combinedContent,
|
text: combinedContent,
|
||||||
image_url: combinedImageUrl,
|
image_url: combinedImageUrl,
|
||||||
|
webAddress: !!webAddress ? JSON.parse(webAddress) : null,
|
||||||
isUser: false,
|
isUser: false,
|
||||||
id: result.length + 1,
|
id: result.length + 1,
|
||||||
sessionId: sessionId
|
sessionId: sessionId
|
||||||
@@ -601,6 +609,11 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { ancestors, current } = data
|
const { ancestors, current } = data
|
||||||
|
current.dialogue.forEach((item) => {
|
||||||
|
if (item.webAddress) {
|
||||||
|
console.log(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const imgList = []
|
const imgList = []
|
||||||
const ancestorsList = []
|
const ancestorsList = []
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
<span>{{ content.webAddress?.length }} web pages have been retrieved.</span>
|
<span>{{ content.webAddress?.length }} web pages have been retrieved.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Pause v-show="showStop && isLast" />
|
<Pause v-show="showStop" :key="props.content.createTime" />
|
||||||
<div
|
<div
|
||||||
v-show="!content.streaming"
|
v-show="!content.streaming"
|
||||||
class="operate flex"
|
class="operate flex"
|
||||||
@@ -133,6 +133,14 @@
|
|||||||
isLast: Boolean
|
isLast: Boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
// watch(
|
||||||
|
// () => props.content,
|
||||||
|
// (newVal) => {
|
||||||
|
// console.log('props', newVal)
|
||||||
|
// },
|
||||||
|
// { deep: true,immediate: true }
|
||||||
|
// )
|
||||||
|
|
||||||
const emit = defineEmits(['regenerate'])
|
const emit = defineEmits(['regenerate'])
|
||||||
|
|
||||||
const userAvatar = computed(() => {
|
const userAvatar = computed(() => {
|
||||||
@@ -318,12 +326,14 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.message-context {
|
.message-context {
|
||||||
line-height: 2rem;
|
line-height: 2rem;
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
width: 82%;
|
width: 82%;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
&.is-user .message-context {
|
&.is-user .message-context {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
|||||||
@@ -13,11 +13,12 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 3.6rem;
|
height: 3.6rem;
|
||||||
line-height: 3.6rem;
|
line-height: 3.6rem;
|
||||||
column-gap: 0.6rem;
|
column-gap: 0.6rem;
|
||||||
padding: 0 1.2rem;
|
padding: 0 1.2rem;
|
||||||
background-color: #fffcf4;
|
background-color: #fffcf4;
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
|
color: #ff7a51;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
@@ -30,22 +31,18 @@
|
|||||||
rgba(233, 121, 60, 0.3) 1.61%,
|
rgba(233, 121, 60, 0.3) 1.61%,
|
||||||
rgba(255, 207, 144, 0.3) 101.01%
|
rgba(255, 207, 144, 0.3) 101.01%
|
||||||
);
|
);
|
||||||
-webkit-mask:
|
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||||
linear-gradient(#fff 0 0) content-box,
|
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||||
linear-gradient(#fff 0 0);
|
|
||||||
mask:
|
|
||||||
linear-gradient(#fff 0 0) content-box,
|
|
||||||
linear-gradient(#fff 0 0);
|
|
||||||
-webkit-mask-composite: xor;
|
-webkit-mask-composite: xor;
|
||||||
mask-composite: exclude;
|
mask-composite: exclude;
|
||||||
}
|
}
|
||||||
|
|
||||||
.c-svg{
|
.c-svg {
|
||||||
width: initial;
|
width: initial;
|
||||||
.svg-icon{
|
.svg-icon {
|
||||||
width: 1.2rem;
|
width: 1.2rem;
|
||||||
height: 1.2rem;
|
height: 1.2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="report-card" :class="{ 'is-url': isUrl, 'is-sketch': isSketch }">
|
<div class="report-card" :class="{ 'is-url': isUrl, 'is-sketch': isSketch }">
|
||||||
<div class="report-card-header">
|
<div class="report-card-header">
|
||||||
<span v-if="!isUrl && !isSketch">{{ title || '' }}</span>
|
<!-- <span v-if="!isUrl && !isSketch">{{ title || '' }}</span> -->
|
||||||
<div v-else class="web-sources flex align-center">
|
<div class="web-sources flex align-center">
|
||||||
<span>{{ title || '' }}</span>
|
<span>{{ title || '' }}</span>
|
||||||
<img src="@/assets/images/link.png" class="link-icon" />
|
<img src="@/assets/images/link.png" class="link-icon" />
|
||||||
</div>
|
</div>
|
||||||
@@ -35,16 +35,19 @@
|
|||||||
.report-card {
|
.report-card {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 2.4rem 0;
|
height: 11.2rem;
|
||||||
|
margin: 1.2rem 0 0;
|
||||||
min-height: 11.2rem;
|
min-height: 11.2rem;
|
||||||
background: url('@/assets/images/report-card.png') no-repeat;
|
background: url('@/assets/images/report-card.png') no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
padding: 2.9rem;
|
padding: 2.9rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
margin-bottom: 0;
|
||||||
&.is-url {
|
&.is-url {
|
||||||
background: url('@/assets/images/link-card.png') no-repeat;
|
background: url('@/assets/images/link-card.png') no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
|
margin: 2.4rem 0;
|
||||||
}
|
}
|
||||||
&.is-sketch {
|
&.is-sketch {
|
||||||
background: url('@/assets/images/sketch-card.png') no-repeat;
|
background: url('@/assets/images/sketch-card.png') no-repeat;
|
||||||
@@ -61,7 +64,7 @@
|
|||||||
|
|
||||||
&-header {
|
&-header {
|
||||||
font-family: 'Medium';
|
font-family: 'Medium';
|
||||||
font-size: 1.6rem;
|
font-size: 1.2rem;
|
||||||
margin-bottom: 1.3rem;
|
margin-bottom: 1.3rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@@ -80,7 +83,7 @@
|
|||||||
&-content {
|
&-content {
|
||||||
font-family: 'Regular';
|
font-family: 'Regular';
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-size: 1.6rem;
|
font-size: 1.2rem;
|
||||||
color: #7c7c7c;
|
color: #7c7c7c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
class="preview-image"
|
class="preview-image"
|
||||||
@click="previewImage(image.url)"
|
@click="previewImage(image.url)"
|
||||||
/>
|
/>
|
||||||
<div class="image-remove-btn" @click="removeImage(index)">
|
<div class="image-remove-btn" @click="removeImage(index, image)">
|
||||||
<SvgIcon name="delete" size="16" />
|
<SvgIcon name="delete" size="16" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -305,8 +305,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 移除图片
|
// 移除图片
|
||||||
const removeImage = (index: number) => {
|
const removeImage = (index: number, item: any) => {
|
||||||
uploadedImages.value.splice(index, 1)
|
if (quoteList.value.includes(item)) {
|
||||||
|
const quoteIndex = quoteList.value.indexOf(item)
|
||||||
|
if (quoteIndex > -1) {
|
||||||
|
quoteList.value.splice(quoteIndex, 1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
uploadedImages.value.splice(index, 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const styleKeys: string[] = [
|
const styleKeys: string[] = [
|
||||||
@@ -472,8 +480,7 @@
|
|||||||
customPlaceholder.value = placeholderSpan
|
customPlaceholder.value = placeholderSpan
|
||||||
|
|
||||||
// 打字机效果显示placeholder文本
|
// 打字机效果显示placeholder文本
|
||||||
const placeholderText =
|
const placeholderText = t('Input.reportPlaceholder')
|
||||||
'Generate a furniture trending report for 2026, including popular styles and design directions.'
|
|
||||||
typeWriterEffect(placeholderSpan, placeholderText)
|
typeWriterEffect(placeholderSpan, placeholderText)
|
||||||
|
|
||||||
const removePlaceholderOnInput = () => {
|
const removePlaceholderOnInput = () => {
|
||||||
@@ -815,6 +822,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleQuote = (url: string) => {
|
const handleQuote = (url: string) => {
|
||||||
|
const hasQuoted = quoteList.value.includes(url)
|
||||||
|
if (hasQuoted) return
|
||||||
quoteList.value.push(url)
|
quoteList.value.push(url)
|
||||||
}
|
}
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
|||||||
@@ -16,13 +16,13 @@
|
|||||||
<span class="title" v-show="!isCollapse">{{ $t('Home.home') }}</span>
|
<span class="title" v-show="!isCollapse">{{ $t('Home.home') }}</span>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div class="menu-item" @click="onHistory" :class="{ active: showHistory }">
|
<div class="menu-item" @click="onHistory" :class="{ active: showHistory }">
|
||||||
<span class="icon"><svg-icon name="history" size="24" /></span>
|
<span class="icon"><svg-icon name="history" size="16" /></span>
|
||||||
<span class="title" v-show="!isCollapse">{{ $t('Home.history') }}</span>
|
<span class="title" v-show="!isCollapse">{{ $t('Home.history') }}</span>
|
||||||
<span class="icon jiantou" v-show="!isCollapse"
|
<span class="icon jiantou" v-show="!isCollapse"
|
||||||
><svg-icon name="arrow-right" size="14" />
|
><svg-icon name="arrow-right" size="14" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="history-list" v-show="!isCollapse && showHistory">
|
<div class="history-list mini-scrollbar" v-show="!isCollapse && showHistory">
|
||||||
<div v-for="item in list" :key="item.name" class="history-item">
|
<div v-for="item in list" :key="item.name" class="history-item">
|
||||||
<div v-if="item.title" class="title">{{ item.name }}</div>
|
<div v-if="item.title" class="title">{{ item.name }}</div>
|
||||||
<div
|
<div
|
||||||
@@ -307,7 +307,8 @@
|
|||||||
> .history-list {
|
> .history-list {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
width: 23.2rem;
|
width: 26.4rem;
|
||||||
|
padding: 0 1.5rem;
|
||||||
margin: 1rem auto 0;
|
margin: 1rem auto 0;
|
||||||
> .history-item {
|
> .history-item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
Reference in New Issue
Block a user