123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- <template>
- <Teleport :to="`#${DomOutMountId}`" v-if="stage">
- <transition name="mount-fade">
- <div class="mount-layout" v-if="show">
- <div :size="8" class="mount-controller">
- <div v-for="[key, val] in describeItems" :key="key" class="mount-item">
- <span class="label">{{ val.label }}</span>
- <component
- v-bind="describes[key].props"
- :value="
- 'value' in describes[key] ? describes[key].value : data && data[key]
- "
- @update:value="(val: any) => updateValue(key, val)"
- @change="changeHandler"
- :is="propertyComponents[val.type]"
- :key="key"
- />
- </div>
- </div>
- </div>
- </transition>
- </Teleport>
- </template>
- <script lang="ts" setup>
- import { computed, ref, watch } from "vue";
- import { useStage } from "../hook/use-global-vars.ts";
- import { useMode } from "../hook/use-status.ts";
- import { PropertyDescribes, propertyComponents } from "./index.ts";
- import { DC, EntityShape } from "@/deconstruction.js";
- import { useMouseShapeStatus } from "../hook/use-mouse-status.ts";
- import { DomOutMountId } from "@/constant/index.ts";
- import { Mode } from "@/constant/mode.ts";
- import { debounce } from "@/utils/shared.ts";
- const props = defineProps<{
- show?: boolean;
- target: DC<EntityShape> | undefined;
- data?: Record<string, any>;
- describes: PropertyDescribes;
- }>();
- const emit = defineEmits<{ (e: "change"): void }>();
- const describeItems = computed(() => {
- return Object.entries(props.describes).sort(
- ([_a, a], [_b, b]) => (b.sort || -1) - (a.sort || -1)
- );
- });
- const stage = useStage();
- const status = useMouseShapeStatus(computed(() => props.target));
- const mode = useMode();
- const hidden = computed(
- () =>
- !props.show &&
- (!stage.value?.getStage() ||
- !props.target?.getNode() ||
- !status.value.active ||
- mode.value.has(Mode.draw) ||
- mode.value.has(Mode.draging))
- );
- const show = ref(false);
- watch(
- hidden,
- debounce(() => {
- show.value = !hidden.value;
- }, 32)
- );
- let isUpdate = false;
- const updateValue = (key: string, val: any) => {
- if ("value" in props.describes[key]) {
- props.describes[key].value = val;
- } else {
- props.data![key] = val;
- }
- isUpdate = true;
- };
- watch(hidden, (nHidden, oHidden) => {
- if (nHidden && nHidden !== oHidden && isUpdate) {
- isUpdate = false;
- emit("change");
- }
- });
- const changeHandler = () => {
- isUpdate = false;
- emit("change");
- };
- </script>
- <style lang="scss" scoped>
- .mount-layout {
- pointer-events: all;
- right: 0;
- top: 0;
- bottom: 0;
- position: absolute;
- border-left: 1px solid #e4e7ed;
- background-color: rgba(255, 255, 255, 0.7);
- overflow-y: auto;
- padding: 6px 12px;
- color: #303133;
- width: 240px;
- font-size: 12px;
- box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
- overflow: hidden;
- .mount-controller {
- // display: grid;
- // grid-template-columns: auto 1fr;
- // gap: 10px 0;
- // align-items: center;
- .mount-item {
- margin-bottom: 15px;
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- }
- .label {
- display: block;
- margin-right: 10px;
- color: #303133;
- &::after {
- content: ":";
- }
- }
- }
- }
- .mount-fade-enter-active,
- .mount-fade-leave-active {
- transition: transform 0.3s ease, opacity 0.3s ease;
- }
- .mount-fade-enter-from,
- .mount-fade-leave-to {
- transform: translateX(100%);
- opacity: 0;
- }
- </style>
|