123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- import { IconAdd, IconMove } from "@/assets/icons";
- import { DesignComp } from "@/modules/editor/objects/DesignTemp/DesignComp";
- import { css, cx } from "@linaria/core";
- import { IconDelete } from "@queenjs/icons";
- import "animate.css";
- import {
- defineComponent,
- inject,
- onMounted,
- onUnmounted,
- reactive,
- ref,
- } from "vue";
- import { bool, string } from "vue-types";
- import { useEditor } from "../../..";
- import { useCompEditLayerRef, useCompRef } from "./hooks";
- let intersectionObserver: any;
- export const View = defineComponent({
- props: {
- compId: string().isRequired,
- editlayer: bool().def(true),
- showMask: bool().def(false),
- meta: bool().def(true),
- },
- emits: ["dblclick", "click"],
- setup(props, { slots, emit, attrs }) {
- const { store, actions, helper, controls } = useEditor();
- const compRef = useCompRef(props.compId, props.meta);
- const editorLayerRef = props.editlayer
- ? useCompEditLayerRef(props.compId)
- : ref();
- const isLongPage = controls.screenCtrl.isLongPage;
- const isPreview = inject("isPreview", false);
- const state = reactive({
- showAnimation: false,
- });
- function createBgStyles() {
- let bgS = {
- position: "absolute",
- top: 0,
- left: 0,
- right: 0,
- bottom: 0,
- zIndex: -1,
- };
- return bgS;
- }
- function getAniStyles(comp: any) {
- if (!comp.layout.anim) return "";
- if (
- comp.layout.anim &&
- state.showAnimation &&
- ((!props.showMask && store.isEditMode) || !store.isEditMode)
- ) {
- return `animate__animated animate__${comp.layout.anim} animate__delay-0.1s`;
- } else {
- return "opacity-0";
- }
- }
- onUnmounted(() => {
- intersectionObserver.disconnect();
- });
- onMounted(() => {
- intersectionObserver = new IntersectionObserver((entries) => {
- if (entries[0].intersectionRatio <= 0) {
- if (isLongPage) return;
- state.showAnimation = false;
- } else {
- state.showAnimation = true;
- }
- });
- intersectionObserver.observe(compRef.value);
- });
- const pageCtrl = controls.pageCtrl;
- return () => {
- const comp = helper.findComp(props.compId);
- if (!comp) return store.isEditMode ? <div>无效组件</div> : null;
- const isStreamCard = helper.isStreamCard(props.compId);
- const gizmo = controls.selectCtrl.gizmo;
- const page = controls.pageCtrl;
- const showBgDiv = isPreview && !isLongPage;
- const isContiner = comp.compKey == "Container";
- let isFocus =
- store.isEditMode &&
- gizmo.state.transform.selected.length > 1 &&
- gizmo.state.lastId == props.compId;
- const style = helper.createStyle(comp.layout, comp);
- if (comp.compKey == "Container") {
- delete style.transform;
- style["transform-origin"] = "center center";
- }
- const cardStyles = helper.createViewStyles(comp.layout, comp);
- let bgStyles: any = {};
- if (showBgDiv) {
- bgStyles = createBgStyles();
- bgStyles.background = cardStyles.background;
- delete cardStyles.background;
- }
- if (comp.compKey == "Text") {
- cardStyles["overflow"] = "visible";
- }
- if (isStreamCard) {
- style.overflow = "unset";
- style.position = "relative";
- }
- if (store.isPreview) {
- style.overflow = "hidden";
- }
- const aniStyles = getAniStyles(comp);
- function RenderPre() {
- if (
- page.state.currStreamCardId != props.compId ||
- !isStreamCard ||
- !store.isEditMode
- )
- return;
- let i = pageCtrl.streamCardIds.indexOf(props.compId);
- if (i > 0) {
- const c = helper.findComp(
- pageCtrl.streamCardIds[i - 1]
- ) as DesignComp;
- const PreComp = controls.compUICtrl.state.components.get(
- c.compKey
- ) as any;
- return (
- <div
- class="absolute w-full h-150px pointer-events-none"
- style={{
- bottom: style.height,
- }}
- >
- {/* <div class="absolute w-full h-150px pointer-events-none overflow-hidden">
- <PreComp.Component
- compId={c.id}
- key={c.id}
- style={{ position: "absolute", bottom: "0" }}
- />
- </div> */}
- {/* <div class={maskStyleUp}></div> */}
- <div class={[divideStyle, "bottom"]}>
- {/* <span class="tip">上一页分割线</span> */}
- </div>
- </div>
- );
- }
- }
- function RenderAfter() {
- if (
- page.state.currStreamCardId != props.compId ||
- !isStreamCard ||
- !store.isEditMode
- )
- return;
- let i = pageCtrl.streamCardIds.indexOf(props.compId);
- if (i < pageCtrl.streamCardIds.length - 1) {
- const c = helper.findComp(
- pageCtrl.streamCardIds[i + 1]
- ) as DesignComp;
- const AfterComp = controls.compUICtrl.state.components.get(
- c.compKey
- ) as any;
- return (
- <div class="relative pointer-events-none">
- {/* <div class="h-150px pointer-events-none overflow-hidden">
- <AfterComp.Component compId={c.id} key={c.id} />
- </div> */}
- {/* <div class={maskStyle}></div> */}
- <div class={[divideStyle, "top"]}>
- {/* <span class="tip">下一页分割线</span> */}
- </div>
- </div>
- );
- }
- }
- return (
- <>
- {showBgDiv && isContiner && <div style={bgStyles}></div>}
- <div
- {...attrs}
- ref={compRef}
- class={[
- comp.compKey,
- viewStyle,
- page.state.currStreamCardId == props.compId &&
- store.isEditMode &&
- !isPreview &&
- CurrCompStyle,
- isFocus && AnchorCompStyle,
- isFocus && groupCompCls,
- ]}
- style={style}
- onClick={(e) => {
- if (!store.isEditMode) {
- e.stopPropagation();
- emit("click");
- }
- }}
- onDblclick={() => emit("dblclick")}
- >
- <div
- class={aniStyles}
- style={cardStyles}
- onMousemove={(e) => {
- if (
- !store.isEditMode ||
- !controls.dragAddCtrl.dragingCompKey ||
- !helper.isStreamCard(props.compId)
- )
- return;
- controls.editorCtrl.clickPickComp(props.compId);
- }}
- >
- {showBgDiv && !isContiner && <div style={bgStyles}></div>}
- {slots.default?.()}
- </div>
- {/* {store.isEditMode &&
- isStreamCard &&
- store.currStreamCardId == props.compId && (
- <Hudop compId={props.compId} />
- )} */}
- {store.isEditMode && props.editlayer && (
- <div ref={editorLayerRef} class={editAreaStyle}></div>
- )}
- {props.showMask && isLongPage && (
- <>
- {RenderPre()}
- {RenderAfter()}
- </>
- )}
- {props.showMask &&
- !isLongPage &&
- controls.screenCtrl.state.screen.useFor == "mobile" && (
- <div
- class={cx(
- safeAreaStyles,
- "absolute left-0 top-1/2 w-1/1 translate -translate-y-1/2 transform pointer-events-none"
- )}
- style={{
- height: `${controls.screenCtrl.state.safeFactor * 100}%`,
- }}
- >
- <div class={[divideStyle, "top"]}>
- <span class="tip"> 安全线</span>
- </div>
- <div class={[divideStyle, "bottom"]}>
- <span class="tip"> 安全线</span>
- </div>
- </div>
- )}
- </div>
- </>
- );
- };
- },
- });
- export const Hudop = defineComponent({
- props: {
- compId: string().isRequired,
- },
- setup(props) {
- const { store, actions, helper, controls } = useEditor();
- const opref = ref();
- onMounted(() => {
- opref.value.editable = "hudop";
- });
- const page = controls.pageCtrl;
- return () => (
- <div class="hudop shadow" ref={opref}>
- {page.streamCardIds.length > 1 && (
- <IconMove
- class="draganchor"
- onMousedown={() => controls.editorCtrl.clickPickComp(props.compId)}
- />
- )}
- {page.streamCardIds.length > 1 && (
- <IconDelete
- onClick={(e: any) => {
- e.stopPropagation();
- actions.removeStreamCard(props.compId);
- }}
- />
- )}
- <IconAdd
- onClick={(e: any) => {
- e.stopPropagation();
- const index = page.streamCardIds.indexOf(props.compId) + 1;
- actions.addCompToDesign("Container", index);
- }}
- />
- </div>
- );
- },
- });
- const viewStyle = css`
- position: relative;
- font-size: 0;
- cursor: pointer;
- flex-shrink: 0;
- > :first-child {
- width: 100%;
- height: 100%;
- }
- .hudop {
- position: absolute;
- top: 0px;
- left: -46px;
- background-color: white;
- flex-direction: column;
- color: black;
- display: flex;
- font-size: 12px;
- width: 28px;
- align-items: center;
- border-radius: 4px;
- z-index: 997;
- .inficon {
- padding: 8px;
- }
- }
- `;
- const editCompStyle = css`
- &:hover {
- outline: 2px dashed @inf-primary-color;
- }
- `;
- const CurrCompStyle = css`
- position: relative;
- z-index: 998;
- box-shadow: 0 0 0 3000px rgba(0, 0, 0, 0.5);
- &:before {
- content: "";
- position: absolute;
- left: -1px;
- right: -1px;
- top: -1px;
- bottom: -1px;
- z-index: 999;
- pointer-events: none;
- background-image: repeating-linear-gradient(
- to right,
- @inf-primary-color 0%,
- @inf-primary-color 50%,
- transparent 50%,
- transparent 100%
- ),
- repeating-linear-gradient(
- to right,
- @inf-primary-color 0%,
- @inf-primary-color 50%,
- transparent 50%,
- transparent 100%
- ),
- repeating-linear-gradient(
- to bottom,
- @inf-primary-color 0%,
- @inf-primary-color 50%,
- transparent 50%,
- transparent 100%
- ),
- repeating-linear-gradient(
- to bottom,
- @inf-primary-color 0%,
- @inf-primary-color 50%,
- transparent 50%,
- transparent 100%
- );
- background-position: left top, left bottom, left top, right top;
- background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
- background-size: 8px 1px, 8px 1px, 1px 8px, 1px 8px;
- }
- `;
- const AnchorCompStyle = css`
- &:before {
- background-size: 8px 2px, 8px 2px, 2px 8px, 2px 8px;
- }
- `;
- const groupCompCls = css`
- outline: 2px dashed @inf-primary-color !important;
- `;
- const editAreaStyle = css`
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- pointer-events: none;
- `;
- // const editAreaTestStyle = css`
- // position: absolute;
- // top: 0;
- // left: 0;
- // width: 100px;
- // height: 100px;
- // background-color: red;
- // `;
- const maskStyle = css`
- background: rgba(0, 0, 0, 0.3);
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- `;
- const maskStyleUp = css`
- background: rgba(0, 0, 0, 0.3);
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- `;
- const divideStyle = css`
- position: absolute;
- left: -5%;
- width: 110%;
- height: 1px;
- background-image: linear-gradient(
- to right,
- #eb684e 0%,
- #eb684e 50%,
- transparent 50%
- );
- background-size: 8px 1px;
- background-repeat: repeat-x;
- &.top {
- top: 0;
- }
- &.bottom {
- bottom: 0;
- }
- .tip {
- margin-left: 15px;
- font-size: 12px;
- position: absolute;
- left: 100%;
- width: 80px;
- top: -10px;
- color: #eb684e;
- }
- `;
- const safeAreaStyles = css`
- box-shadow: 0 0 0 3000px rgba(0, 0, 0, 0.3);
- `;
|