wjx před 3 týdny
rodič
revize
4e41cbfd86

+ 9 - 0
src/pages/weComTask/API/global.ts

@@ -289,4 +289,13 @@ export async function getBookChapterListListApi(data: { pageNum: number, pageSiz
         method: 'POST',
         data
     });
+}
+
+// 小程序链接
+export async function getGenerateUrllinkApi(data: {path: string, query: string}) {
+    return request({
+        url: api + '/bookAppWechatMiniapp/api/miniappBase/generateUrllink/wxed3542b04192b2ee',
+        method: 'POST',
+        data
+    });
 }

+ 3 - 0
src/pages/weComTask/components/newsModal/global.less

@@ -0,0 +1,3 @@
+.imgNews .ant-image {
+    display: block;
+}

+ 42 - 0
src/pages/weComTask/components/newsModal/index.less

@@ -0,0 +1,42 @@
+.imgNews {
+    display: inline-block;
+    overflow: hidden;
+    position: relative;
+    border-radius: 6px;
+
+    &>div {
+        .img {
+            width: 130px;
+            height: 100px;
+            cursor: pointer;
+            object-fit: contain;
+        }
+    }
+
+    .mask {
+        position: absolute;
+        width: 100%;
+        height: 100%;
+        top: 0;
+        left: 0;
+        background-color: rgba(0, 0, 0, .1);
+        display: flex;
+        justify-content: center;
+        align-items: center;
+
+        &>img {
+            width: 20px;
+            height: 20px;
+            display: inline-block;
+            cursor: pointer;
+        }
+    }
+}
+
+.video {
+    width: 100%;
+    max-width: 320px;
+    max-height: 600px;
+    display: block;
+    margin: auto;
+}

+ 40 - 0
src/pages/weComTask/components/newsModal/videoNews.tsx

@@ -0,0 +1,40 @@
+import React, { useState } from "react"
+import style from './index.less'
+import { Image, ImageProps, Modal } from 'antd'
+import { getVideoImgUrl } from "@/utils/utils"
+import play from "../../../../public/image/play.png"
+import { CloseOutlined } from '@ant-design/icons';
+import './global.less'
+
+interface Props extends ImageProps {
+    keyFrameImageUrl?: string
+    maskBodyStyle?: React.CSSProperties
+    maskImgStyle?: React.CSSProperties
+}
+
+const VideoNews: React.FC<Props> = ({ preview = false, src, maskBodyStyle, maskImgStyle, keyFrameImageUrl, ...data }) => {
+
+    /*****************************/
+    const [toPlay, setToPlay] = useState<boolean>(false)
+    /*****************************/
+
+    return <>
+        <div className={`${style.imgNews} imgNews`}>
+            <Image src={keyFrameImageUrl || (src ? getVideoImgUrl(src) : 'error')} preview={false} {...data} className={style.img}/>
+            <div className={style.mask} style={maskBodyStyle}>
+                <img src={play} style={maskImgStyle} onClick={(e) => { e.stopPropagation(); e.preventDefault(); setToPlay(true) }} />
+            </div>
+        </div>
+        {toPlay && <Modal
+            open={toPlay}
+            styles={{body: { backgroundColor: 'rgba(0,0,0,0.8)', overflow: 'hidden', borderRadius: 6 }}}
+            footer={null}
+            closeIcon={<CloseOutlined style={{ color: '#FFF' }}/>}
+            onCancel={(e) => {e.stopPropagation(); setToPlay(false)}}
+        >
+            <video className={style.video} style={{ borderRadius: 6 }} src={src} autoPlay controls>您的浏览器不支持 video 标签。</video>
+        </Modal>}
+    </>
+}
+
+export default React.memo(VideoNews)

+ 32 - 0
src/pages/weComTask/page/miniProgramPages/center.tsx

@@ -0,0 +1,32 @@
+import { Col, ColorPicker } from "antd"
+import React, { useContext } from "react"
+import style from './index.less'
+import { DispatchMiniPageCreate } from "./drawerMini";
+import CenterTop from './centerTop'
+
+const Center: React.FC = () => {
+
+    /**************************************/
+    const { pageSpecs, setPageSpecs } = useContext(DispatchMiniPageCreate)!;
+    const { bgColor } = pageSpecs
+    /**************************************/
+
+    return <Col flex="auto" className={style.center}>
+        <div className={style.page} style={{ backgroundColor: bgColor || '#FFFFFF' }}>
+            <div><CenterTop /></div>
+            <div className={style.sidebar}>
+                <div>
+                    <ColorPicker
+                        onChange={(value, css) => {
+                            setPageSpecs({ ...pageSpecs, bgColor: css })
+                        }}
+                        value={bgColor}
+                    />
+                    <div style={{ marginTop: 4 }}>背景</div>
+                </div>
+            </div>
+        </div>
+    </Col>
+}
+
+export default React.memo(Center)

+ 118 - 0
src/pages/weComTask/page/miniProgramPages/centerTop.tsx

@@ -0,0 +1,118 @@
+import React, { useContext } from "react"
+import { DispatchMiniPageCreate } from "./drawerMini";
+import { useDrop } from "ahooks";
+import './global.less'
+import { topImageContent, topVideoContent } from "./const";
+import { DeleteOutlined } from '@ant-design/icons';
+
+import { ReactComponent as TopNullBack } from '../../../../public/svg/topNullBack.svg'
+import { ReactComponent as TopImgSvg } from '../../../../public/svg/topimg.svg'
+import { ReactComponent as EditSvg } from '../../../../public/svg/edit.svg'
+import { ReactComponent as TopVideoSvg } from '../../../../public/svg/topvideo.svg'
+import VideoNews from "../../components/newsModal/videoNews";
+import { Button } from "antd";
+
+const CenterTop: React.FC = () => {
+
+    /**************************************/
+    const { dragging, pageSpecs, setDragging, setPageSpecs, installActive } = useContext(DispatchMiniPageCreate)!;
+    const { pageElementsSpecList } = pageSpecs
+    const topSpec = pageElementsSpecList?.[0]
+    /**************************************/
+
+    // 头部内容拖到接收区
+    const [dropProps] = useDrop({
+        onDom: (key: string) => { // 头部
+            const newPageElementsSpecList = pageElementsSpecList?.map(item => ({ ...item, comptActive: false }))
+            if (key === 'TOP_IMAGE') {
+                newPageElementsSpecList[0] = { ...topImageContent, comptActive: true }
+            } else if (key === 'TOP_VIDEO') {
+                newPageElementsSpecList[0] = { ...topVideoContent, comptActive: true }
+            } else {
+                return
+            }
+            setPageSpecs({ ...pageSpecs, pageElementsSpecList: newPageElementsSpecList })
+        }
+    });
+
+
+    // 内容拖到接收区
+    const [dropConProps, { isHovering: isHoveringCon }] = useDrop({
+        onDom: (con: string, e) => { // 内容
+
+        },
+    });
+
+    const delTopSpec = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
+        e.stopPropagation();
+        setDragging(null);
+        const newPageSpecs = JSON.parse(JSON.stringify(pageSpecs))
+        newPageSpecs.pageElementsSpecList[0] = { elementType: 'empty' }
+        setPageSpecs(newPageSpecs)
+    }
+
+    if (topSpec?.elementType) {
+        switch (topSpec.elementType) {
+            case "TOP_IMAGE":
+                return <div className={`compt componentType41 ${topSpec?.comptActive && 'comptActive'}`} onClick={(e) => { installActive(e, 0) }}>
+                    <div className={'componentWrap'}>
+                        <div className={'componentContent'}>
+                            {topSpec?.url ? <img src={topSpec?.url} style={{ display: 'block', width: '100%', margin: 0 }} /> : <div className={'default'} style={{ width: 375, height: 300, margin: 0 }}>
+                                <div className={'defaultIcon'} style={{ marginTop: 80 }}>
+                                    <TopImgSvg />
+                                </div>
+                            </div>}
+                        </div>
+                    </div>
+
+                    {!topSpec?.url && <div className={'comptUpload'} style={{ margin: 0 }}>
+                        <button style={{ marginTop: 150 }} className={'comptEditButton'} onClick={() => { }}>上传图片</button>
+                    </div>}
+                    <section className={'comptEditBtns'}>
+                        <div className={'comptEditBtnsInner'}>
+                            {topSpec?.url && <Button onClick={() => { }} icon={<EditSvg />}></Button>}
+                            <Button onClick={delTopSpec} icon={<DeleteOutlined />} style={{ fontSize: 14 }}/>
+                        </div>
+                    </section>
+                </div>
+            case "TOP_VIDEO":
+                return <div className={`compt componentType61 ${topSpec?.comptActive && 'comptActive'}`} onClick={(e) => { installActive(e, 0) }}>
+                    <div className={'componentWrap'}>
+                        <div className={'componentContent'} style={{ lineHeight: 'normal' }}>
+                            {topSpec?.url ? <div className="videoPlay">
+                                <VideoNews src={topSpec.url} style={{ display: 'block', width: '100%', margin: 0, height: '100%' }} maskImgStyle={{ position: 'absolute', top: '50%', left: '50%', width: 40, height: 40, transform: 'translate(-50%, -50%)', zIndex: 10 }} />
+                            </div> : <div className={'default'} style={{ width: 375, height: 300, margin: 0 }}>
+                                <div className={'defaultIcon'} style={{ marginTop: 80 }}>
+                                    <TopVideoSvg />
+                                </div>
+                            </div>}
+                        </div>
+                    </div>
+                    {!topSpec?.url && <div className={'comptUpload'} style={{ margin: 0 }}>
+                        <button style={{ marginTop: 150 }} className={'comptEditButton'} onClick={() => { }}>上传视频</button>
+                    </div>}
+
+                    <section className={'comptEditBtns'}>
+                        <div className={'comptEditBtnsInner'}>
+                            {topSpec?.url && <Button onClick={() => { }} icon={<EditSvg />}></Button>}
+                            <Button onClick={delTopSpec} icon={<DeleteOutlined />} style={{ fontSize: 14 }}/>
+                        </div>
+                    </section>
+                </div>
+            default:
+                return <div className={`compt topComptArea ${dragging ? 'dragging' : ''}`} {...dropProps}>
+                    <TopNullBack />
+
+                    {dragging ? <div className="topAreaTitle" style={{ marginTop: 30 }}>
+                        拖至此处
+                    </div> : <>
+                        <p className={'topAreaTitle'}>顶部组件区</p>
+                        <div className={'desc'}>在左上方,选择顶部组件添加到此处</div>
+                    </>}
+                </div>
+        }
+    }
+    return <span>页面BUG,刷新页面后尝试</span>
+}
+
+export default React.memo(CenterTop)

+ 32 - 0
src/pages/weComTask/page/miniProgramPages/const.ts

@@ -0,0 +1,32 @@
+
+// 顶部图片
+export const topImageContent: TASK_MINI_PAGE_CREATE.TopImage = {
+    elementType: 'TOP_IMAGE',
+    url: ''
+}
+
+// 顶部视频
+export const topVideoContent: TASK_MINI_PAGE_CREATE.TopVideo = {
+    elementType: 'TOP_VIDEO',
+    url: ''
+}
+
+// 图片内容
+export const imgContent: TASK_MINI_PAGE_CREATE.Image = {
+    elementType: 'IMAGE',
+    url: '',
+    paddingTop: 0,
+    paddingBottom: 0,
+}
+
+// 内容文本
+export const txtContent: TASK_MINI_PAGE_CREATE.Text = {
+    elementType: 'TEXT',
+    text: '',
+    fontStyle: 0,
+    textAlignment: 0,
+    fontSize: 20,
+    fontColor: '#595959',
+    paddingTop: 22,
+    paddingBottom: 22,
+}

+ 20 - 0
src/pages/weComTask/page/miniProgramPages/dragItem.tsx

@@ -0,0 +1,20 @@
+import React from "react";
+
+interface Props {
+    dragProps: {
+        draggable: "true";
+        key: string;
+        onDragStart: (e: React.DragEvent<Element>) => void;
+        onDragEnd: (e: React.DragEvent) => void;
+    }
+    title: string,
+    icon: JSX.Element
+}
+
+const DragItem: React.FC<Props> = ({ dragProps, title, icon }) => {
+
+    const { key, ...otherProps } = dragProps;
+    return <div key={key} {...otherProps}> {icon} <span>{title}</span></div>
+}
+
+export default React.memo(DragItem)

+ 46 - 3
src/pages/weComTask/page/miniProgramPages/drawerMini.tsx

@@ -1,5 +1,9 @@
-import { Drawer } from "antd"
-import React from "react"
+import { Drawer, Row } from "antd"
+import React, { useState } from "react"
+import style from './index.less'
+import Left from "./left"
+import Center from "./center"
+import Right from "./right"
 
 interface Props {
     groupList: { label: string, value: number }[]
@@ -8,9 +12,31 @@ interface Props {
     onClose?: () => void
     initialValues?: any
 }
+
+export const DispatchMiniPageCreate = React.createContext<TASK_MINI_PAGE_CREATE.DispatchMiniPageCreate | null>(null);
+
 const DrawerMini: React.FC<Props> = ({ visible, onChange, onClose, groupList, initialValues }) => {
 
 
+    /**************************************/
+    const [pageSpecs, setPageSpecs] = useState<TASK_MINI_PAGE_CREATE.PageSpecsProps>({
+        bgColor: '#FFFFFF',
+        pageElementsSpecList: [{ elementType: 'empty' }]
+    })
+    const [dragging, setDragging] = useState<string | null>(null);
+    const [draggingCon, setDraggingCon] = useState<string | null>(null);
+    /**************************************/
+
+    const installActive = (e: React.MouseEvent<HTMLDivElement, MouseEvent>, index: number) => {
+        e.stopPropagation();
+        e.preventDefault();
+        const { pageElementsSpecList } = pageSpecs
+        const newPageElementsSpecList = pageElementsSpecList?.map(item => ({ ...item, comptActive: false }))
+        newPageElementsSpecList[index].comptActive = true
+        setPageSpecs({ ...pageSpecs, pageElementsSpecList: newPageElementsSpecList })
+    }
+
+    console.log('pageElementsSpecList------------->', pageSpecs)
 
     return <Drawer
         title={<strong>{initialValues?.id ? initialValues?.isCopy ? '复制落地页' : '修改' + initialValues.name + '落地页' : '新增落地页'}</strong>}
@@ -18,8 +44,25 @@ const DrawerMini: React.FC<Props> = ({ visible, onChange, onClose, groupList, in
         onClose={onClose}
         open={visible}
         width={'80%'}
+        className={style.drawer}
+        styles={{ body: { padding: '0 2px 0 10px' } }}
     >
-        
+        <DispatchMiniPageCreate.Provider
+            value={{
+                dragging, setDragging,
+                draggingCon, setDraggingCon,
+                pageSpecs, setPageSpecs,
+                installActive,
+            }}
+        >
+            <div className={style.boxCont}>
+                <Row className={style.row}>
+                    <Left />
+                    <Center />
+                    <Right />
+                </Row>
+            </div>
+        </DispatchMiniPageCreate.Provider>
     </Drawer>
 }
 

+ 998 - 0
src/pages/weComTask/page/miniProgramPages/global.less

@@ -0,0 +1,998 @@
+.widget {
+  box-sizing: border-box;
+  // padding: 15px 0;
+  background-color: #fff;
+  box-shadow: -1px 0 0 0 hsl(0deg 0% 87% / 65%);
+  width: 100%;
+  height: 100%;
+  position: relative;
+  overflow-y: scroll;
+  font-size: 12px;
+  transition: all .35s ease;
+}
+
+.aside .form,
+.widget .form {
+  padding-top: 28px;
+  padding-bottom: 28px;
+  height: auto;
+
+  .adui-form-item {
+    margin-bottom: 20px;
+  }
+
+  .adui-form-label,
+  .adui-form-tip {
+    font-size: 12px;
+    line-height: 18px;
+  }
+
+  .adui-form-label {
+    width: 4em;
+  }
+
+  .adui-form-control {
+    flex: 1;
+  }
+
+  .ant-radio-wrapper {
+    font-size: 12px;
+  }
+}
+
+.widget_back {
+  opacity: 0;
+  transform: translateX(-30px);
+}
+
+.caption {
+  padding-top: 20px;
+  padding-bottom: 20px;
+}
+
+.section {
+  padding-left: 28px;
+  padding-right: 28px;
+  box-shadow: 0 1px 0 0 hsl(0deg, 0%, 87%, 65%);
+}
+
+.goBack {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  color: #000;
+  cursor: pointer;
+}
+
+.caption-title {
+  font-size: 14px;
+  line-height: 24px;
+  color: #1f1f1f;
+  font-weight: 600;
+}
+
+.adui-form-label,
+.adui-form-tip {
+  font-size: var(--font-size-small);
+}
+
+.adui-form-tip_normal {
+  color: #a3a3a3;
+}
+
+.adui-form-tip:not(:empty) {
+  margin-top: 8px;
+}
+
+.adui-form-label {
+  flex: none;
+  display: inline-flex;
+  align-items: center;
+  margin-right: 10px;
+  color: var(--gray-900);
+  white-space: nowrap;
+}
+
+.adui-form-item {
+  display: flex;
+  margin-bottom: 24px;
+  align-items: baseline;
+}
+
+.form-caption {
+  margin-bottom: 16px;
+  font-size: 13px;
+  line-height: 20px;
+  color: #1f1f1f;
+  font-weight: 600;
+}
+
+.upload-img-item {
+  width: 70px;
+  height: 70px;
+  cursor: pointer;
+
+}
+
+.upload-img-item-inner {
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background-color: #fdfdfd;
+  border: 1px dashed #e3e3e3;
+  color: #919191;
+  border-radius: 4px;
+  background-size: cover;
+  background-position: 50% 50%;
+
+  &::before {
+    content: "";
+    padding-top: 100%;
+  }
+
+  &::after {
+    content: "";
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, .1);
+    opacity: 0;
+    border-radius: 4px;
+    visibility: hidden;
+    transition: all .1s ease;
+  }
+
+  &:hover {
+    background-color: #fafafa;
+    color: #363636;
+    border: 1px dashed #d6d6d6;
+
+    & .upload-img-item-action {
+      opacity: 1;
+      visibility: visible;
+    }
+
+    & .sliderhandle {
+      opacity: 1;
+      visibility: visible;
+    }
+  }
+}
+
+.upload-img-item_uploaded {
+  .upload-img-item-inner {
+    background-clip: content-box;
+    border: 2px solid transparent;
+    border-radius: 6px;
+  }
+}
+
+.sliderhandle {
+  position: absolute;
+  z-index: 1;
+  top: 4px;
+  left: 4px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 16px;
+  height: 16px;
+  font-size: 12px;
+  line-height: 12px;
+  color: #d6d6d6;
+  font-weight: 600;
+  background-color: rgba(0, 0, 0, .6);
+  border-radius: 100%;
+  // opacity: 0;
+  // visibility: hidden;
+  cursor: pointer;
+  transform: scale(1.2);
+  transform-origin: 80% 0;
+}
+
+.upload-img-item-action {
+  position: absolute;
+  z-index: 1;
+  top: 4px;
+  right: 4px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 16px;
+  height: 16px;
+  font-size: 12px;
+  line-height: 12px;
+  color: #d6d6d6;
+  font-weight: 600;
+  background-color: rgba(0, 0, 0, .6);
+  border-radius: 100%;
+  opacity: 0;
+  visibility: hidden;
+  cursor: pointer;
+  transform: scale(1.2);
+  transform-origin: 80% 0;
+}
+
+.imageUpload {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  padding: 4px;
+  border-radius: 6px;
+  box-shadow: 0 0 0 1px hsl(0deg, 0%, 87%, 45%);
+  list-style-type: none;
+  margin: 0;
+}
+
+.imageUploadItem {
+  display: inline-block;
+  vertical-align: top;
+  padding: 4px;
+  background-color: transparent;
+  border-radius: 4px;
+
+  &.active .upload-img-item-inner {
+    border: 1px dashed #1890ff;
+  }
+}
+
+.imageUploadItemInnerDone {
+  &.active .upload-img-item-inner {
+    border: 1px solid #1890ff;
+  }
+}
+
+.addDraw {
+  .ant-drawer-body {
+    padding-right: 0;
+
+    >.ant-spin-nested-loading {
+      width: 100%;
+      height: 100%;
+
+      >.ant-spin-container {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+
+  .fl-sb {
+    justify-content: space-between;
+  }
+
+  .fl-center,
+  .fl-sb {
+    display: flex;
+    align-items: center;
+  }
+
+  .fl-sb>div .swatch {
+    margin-top: 4px !important;
+  }
+}
+
+
+
+.compt {
+  position: relative;
+  z-index: 1000;
+
+  &:hover {
+    z-index: 1002;
+  }
+
+  &.comptActive {
+    position: relative;
+    z-index: 1002;
+
+    .componentWrap {
+      z-index: 2;
+    }
+  }
+
+  &.comptFixedBottom {
+    position: absolute;
+    z-index: 2;
+    bottom: 0;
+    width: 375px;
+    text-align: left;
+  }
+
+  &:hover .comptEditBtnsInner {
+    opacity: 1;
+    visibility: visible;
+  }
+
+  &:hover .componentWrap {
+    z-index: 2;
+
+    &::after {
+      box-shadow: 0 0 0 1px #1890ff;
+      display: block;
+    }
+  }
+
+  &:hover .comptEditTrBtns {
+    display: block;
+  }
+
+  &.comptActive .componentWrap {
+    z-index: 2;
+    box-shadow: 0 0 0 2px #1890ff;
+    display: block;
+  }
+}
+
+
+.topComptArea {
+  align-items: center;
+  justify-content: center;
+  margin: 8px;
+  height: 240px;
+  z-index: 2;
+  font-size: 16px;
+  color: rgba(0, 0, 0, .58);
+  letter-spacing: 0;
+  line-height: 22px;
+  text-align: center;
+  background: #fafafa;
+  border: 1.5px dashed rgba(0, 0, 0, .06);
+
+  svg {
+    margin-top: 35px;
+  }
+
+  .desc {
+    font-size: 12px;
+    line-height: 20px;
+    color: rgba(0, 0, 0, .36);
+  }
+
+  .topAreaTitle {
+    margin: 0;
+    margin-top: 4px;
+    font-size: 14px;
+    font-weight: 600;
+    line-height: 24px;
+    text-align: center;
+    color: rgba(0, 0, 0, .58);
+  }
+
+  &.dragging {
+    padding: 0;
+    background-color: #e4f2ff;
+    border: 1px dashed #1890ff;
+  }
+}
+
+.uiFlexCenter {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+
+.uiFlexAlignCenter {
+  -ms-flex-pack: center;
+  justify-content: center;
+}
+
+.comptPlaceholder {
+  position: relative;
+  height: 0;
+  list-style-type: none;
+  padding: 0;
+  border-radius: 0;
+  margin: 0;
+  font-weight: 700;
+  font-size: 14px;
+  // color: #1890ff;
+  letter-spacing: 0;
+  text-align: center;
+  display: flex;
+  flex-direction: column;
+
+  &>div.page-0 {
+    min-height: 420px;
+    position: relative;
+    display: flex;
+    flex-direction: column;
+  }
+
+  .comptCon {
+    // min-height: 40px;
+    display: flex;
+    align-items: center;
+    font-size: 14px;
+    justify-content: center;
+    font-weight: 600;
+
+    &.draggingCon {
+      min-height: 100px;
+      border: 1px dashed rgba(0, 0, 0, 0.2);
+      color: rgba(0, 0, 0, 0.2);
+      flex: 1;
+    }
+
+    &.draggingCon1 {
+      min-height: 60px;
+      border: 1px dashed rgba(0, 0, 0, 0.2);
+      color: rgba(0, 0, 0, 0.2);
+    }
+
+    &.hovering {
+      border: 1px dashed #1890ff;
+      color: #1890ff;
+    }
+  }
+}
+
+.comptPlaceholder.lastChild,
+.pageEmpty .comptPlaceholder {
+  flex: 1;
+  height: auto;
+}
+
+.default {
+  width: 100%;
+  height: 100%;
+  background: #fafafa;
+  overflow: hidden;
+}
+
+.defaultIcon {
+  width: 56px;
+  height: 56px;
+  display: block;
+  margin: 0 auto;
+  color: #b0b0b0;
+
+  >svg {
+    width: 100%;
+    height: 100%;
+    fill: currentColor;
+  }
+}
+
+.form-result-text {
+  color: #1f1f1f;
+  line-height: 26px;
+  font-size: 12px;
+
+  &>span {
+    margin-right: 10px;
+    position: relative;
+
+    &::before {
+      content: "";
+      position: absolute;
+      top: 50%;
+      right: -10px;
+      margin-top: -6px;
+      width: 1px;
+      height: 12px;
+      background-color: #ebebeb;
+    }
+  }
+}
+
+.componentWrap {
+  position: relative;
+  z-index: 1;
+
+  &::after {
+    content: "";
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    z-index: 1;
+    box-shadow: 0 0 0 2px #1890ff;
+    display: none;
+  }
+
+  .textAreaDiv {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: #fff;
+  }
+
+  textarea {
+    outline: 0;
+    padding: 0;
+    color: #666;
+    font-family: inherit;
+    font-size: 100%;
+    margin: 0;
+    overflow: auto;
+    vertical-align: top;
+    resize: none;
+  }
+
+  .textarea {
+    position: absolute;
+    z-index: 2;
+    left: 0;
+    border: none;
+    width: 100%;
+    height: 100%;
+    background: transparent;
+    overflow: hidden;
+  }
+}
+
+.componentContent {
+  overflow: hidden;
+
+  .sliderCon {
+    position: relative;
+    width: 375px;
+    height: 222px;
+
+    >.default {
+      width: 375px;
+      height: 100%;
+      position: absolute;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+  }
+
+  .sliderD {
+    position: absolute;
+    bottom: 10px;
+    width: 100%;
+    display: flex;
+    justify-content: center;
+    z-index: 2;
+
+    >i {
+      display: inline-block;
+      vertical-align: middle;
+      width: 6px;
+      height: 6px;
+      border-radius: 3px;
+      background-color: rgba(0, 0, 0, 0.15);
+      margin-left: 0px;
+
+      &:not(:nth-child(1)) {
+        margin-left: 10px;
+      }
+    }
+  }
+}
+
+.comptUpload {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  z-index: 2;
+}
+
+.comptEditButton {
+  padding: 12px 34px;
+  font-size: 13px;
+  color: #6b6b6b;
+  letter-spacing: 0;
+  line-height: 22px;
+  border: 1px dashed #d6d6d6;
+  border-radius: 3px;
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+  cursor: pointer;
+
+  &:hover {
+    color: #292929;
+    background: rgba(0, 0, 0, .03);
+    border: 1px dashed #a3a3a3;
+    border-radius: 3px;
+  }
+}
+
+.shelfItemContent {
+  .title {
+    font-weight: 700;
+    font-size: 14px;
+    color: #353535;
+    letter-spacing: 0;
+  }
+
+  .desc {
+    font-size: 13px;
+    color: #4d4d4d;
+    letter-spacing: 0;
+    font-weight: normal;
+  }
+
+  .btn {
+    display: inline-block;
+    background: #07c160;
+    width: 77px;
+    height: 30px;
+    line-height: 30px;
+    font-size: 13px;
+    color: #fff;
+    text-align: center;
+    box-sizing: content-box;
+  }
+}
+
+.shelf.listType {
+  flex-direction: column;
+
+  p {
+    margin: 0;
+    text-align: left;
+  }
+
+  .shelfItem {
+    height: 114px;
+    border-radius: 4px;
+  }
+
+  .shelfItemImg {
+    width: 90px;
+    height: 90px;
+  }
+
+  .shelfItemContent {
+    // flex: 1;
+    // width: calc(100% - 90px);
+    height: 100%;
+    min-width: 0;
+    text-align: left;
+
+    .title {
+      white-space: nowrap;
+      overflow: hidden;
+    }
+
+    .desc {
+      height: 35px;
+      overflow: hidden;
+    }
+  }
+}
+
+.shelfItem-3q {
+  display: flex;
+}
+
+.shelf.gridType {
+  display: flex;
+  flex-wrap: wrap;
+
+  .shelfItem-3q {
+    flex-direction: column;
+    width: 160px;
+    border-radius: 4px;
+    box-sizing: content-box;
+  }
+
+  .shelfItemImg {
+    width: 150px;
+    height: 150px;
+    margin-bottom: 8px;
+  }
+}
+
+.shelfItem {
+  display: flex;
+}
+
+.comptEditBtns {
+  position: absolute;
+  top: 0;
+  right: -35px;
+  width: 34px;
+  z-index: 1;
+  box-sizing: inherit;
+}
+
+.comptEditBtnsInner {
+  opacity: 0;
+  visibility: hidden;
+  background-color: #fff;
+  transition: all .1s ease;
+  border-radius: 0 6px 6px 0;
+  box-shadow: 0 0 0 1px hsl(0deg, 0%, 87%, 20%), 0 3px 6px 0 rgb(0, 0, 0, 4%);
+  overflow: hidden;
+
+  button {
+    position: relative;
+    display: inline-block;
+    font-weight: 500;
+    color: var(--gray-800);
+    background-color: transparent;
+    padding: 0 4px;
+    margin: 4px;
+    border-radius: 4px;
+    text-decoration: none;
+    outline: none;
+    appearance: none;
+    cursor: pointer;
+    user-select: none;
+    border: none;
+    transition: color var(--motion-duration-fast) var(--ease-in-out), background-color var(--motion-duration-fast) var(--ease-in-out), background-image var(--motion-duration-fast) var(--ease-in-out), box-shadow var(--motion-duration-fast) var(--ease-in-out);
+  }
+}
+
+.text {
+  word-wrap: break-word;
+}
+
+.shelfnewColor {
+  &>div {
+    .colorName {
+      text-align: center;
+      color: rgb(99, 99, 99);
+      font-size: 12px;
+    }
+  }
+}
+
+.colorShow {
+  box-shadow: 0 0 0 1px #e0e0e0;
+  padding: 4px 8px;
+  font-size: 12px;
+  border-radius: 4px;
+  width: 70px;
+}
+
+.comptEditTrBtns {
+  position: absolute;
+  top: 0;
+  right: 0;
+  z-index: 2;
+  display: none;
+  background-color: rgba(0, 0, 0, 0.3);
+
+  .comptEditTrBtnsInner {
+    display: flex;
+    justify-content: flex-end;
+
+    &>a {
+      font-size: 12px;
+      padding: 0 5px;
+
+      &:hover {
+        box-shadow: 0 0 0 1px #1890ff;
+      }
+    }
+
+    .ant-popover-inner-content {
+      padding: 3px !important;
+    }
+  }
+}
+
+.assBts {
+  display: flex;
+
+  >div {
+    width: 24px;
+    height: 24px;
+    cursor: pointer;
+    border-radius: 4px;
+
+    &:hover {
+      box-shadow: 0 0 0 1px #1890ff;
+    }
+
+    >svg {
+      width: 24px;
+      height: 24px;
+    }
+  }
+}
+
+.text {
+  word-wrap: break-word;
+}
+
+.videoPlay {
+  position: relative;
+
+  >span {
+    z-index: 10;
+    background-image: url('../../../../public/image/MpaVideoIcon.png');
+    margin-top: -23px;
+    margin-left: -23px;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    width: 46px;
+    height: 46px;
+    background-size: 46px;
+  }
+
+  >div {
+    display: block !important;
+    border-radius: 0 !important;
+    
+    .ant-image{
+      display: block;
+    }
+  }
+  
+}
+
+.floatButtonWrapper {
+  padding: 8px;
+  background-color: #fff;
+}
+
+.floatButton {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-align: center;
+  align-items: center;
+  padding-left: 16px;
+  padding-right: 20px;
+  height: 72px;
+  background-color: hsla(0, 0%, 94%, .96);
+  border-radius: 8px;
+}
+
+.floatButtonAvatarPlaceholder {
+  background-color: #c7c7c7;
+}
+
+.floatButtonAvatar,
+.floatButtonAvatarPlaceholder {
+  flex: none;
+  margin-right: 12px;
+  width: 48px;
+  height: 48px;
+  border-radius: 4px;
+}
+
+.floatButtonTexts {
+  flex: 1;
+  min-width: 0;
+}
+
+.floatButtonTitle {
+  font-size: 16px;
+  line-height: 22px;
+  color: #1f1f1f;
+  font-weight: 600;
+}
+
+.floatButtonDesc {
+  margin-top: 1px;
+  font-size: 12px;
+  line-height: 17px;
+  color: #a3a3a3;
+}
+
+.floatButtonDesc,
+.floatButtonTitle {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.floatButtonLink {
+  margin-left: 12px;
+  padding-left: 4px;
+  padding-right: 4px;
+  font-size: 14px;
+  line-height: 32px;
+  color: #fff;
+  font-weight: 500;
+  background-color: #07c160;
+  border-radius: 4px;
+}
+
+.floatType {
+  >.ant-radio-button-wrapper {
+    border-radius: 0;
+    padding: 4.5px 6px;
+    margin-right: 5px;
+  }
+}
+
+.floatTypeInner {
+  width: 59px;
+  display: flex;
+  align-items: center;
+  padding-left: 4px;
+  padding-right: 4px;
+  height: 20px;
+  background-color: hsla(0, 0%, 42%, .25);
+}
+
+.floatTypeAvatar {
+  flex: none;
+  margin-right: 2px;
+  width: 12px;
+  height: 12px;
+  background-color: #6b6b6b;
+}
+
+.floatTypeText_one,
+.floatTypeText_two {
+  flex: 1;
+
+  &::before {
+    display: block;
+    opacity: .23;
+    height: 2px;
+    background-color: #6b6b6b;
+  }
+
+  &::after {
+    display: block;
+    opacity: .23;
+    height: 2px;
+    background-color: #6b6b6b;
+  }
+}
+
+.floatTypeText_one::before,
+.floatTypeText_two::before {
+  content: "";
+}
+
+.floatTypeText_two::after {
+  content: "";
+  margin-top: 2px;
+  width: 70.58824%;
+}
+
+.floatTypeButton {
+  margin-left: 2px;
+  width: 12px;
+  height: 4px;
+  background-color: #6b6b6b;
+}
+
+.aside {
+  position: absolute;
+  top: 0;
+  background-color: #fff;
+  z-index: 10;
+  width: 100%;
+  height: 100%;
+  overflow-y: auto;
+}
+
+.aside-nav {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 16px 16px 16px 12px;
+  box-shadow: 0 1px 0 0 rgba(222, 222, 222, 0.65);
+
+  >button {
+    color: #6b6b6b;
+    font-size: 12px;
+  }
+}
+
+.aside-select {
+  span.ant-select-selection-item {
+    display: flex;
+    align-items: center;
+  }
+
+  .ant-select-item-option-content {
+    display: flex;
+    align-items: center;
+  }
+}
+
+.custorGroup {
+  flex-direction: column;
+}

+ 113 - 0
src/pages/weComTask/page/miniProgramPages/index.less

@@ -0,0 +1,113 @@
+.drawer {
+    .boxCont {
+        width: 100%;
+        height: 100%;
+        background-color: #f3f3f3;
+
+        .row {
+            height: 100%;
+
+            >div {
+                overflow-y: scroll;
+
+                >.title {
+                    font-size: 14px;
+                    line-height: 20px;
+                    color: #1f1f1f;
+                    font-weight: 700;
+                    margin-bottom: 10px;
+                }
+
+                >.assembly {
+                    width: 100%;
+                    display: flex;
+                    flex-wrap: wrap;
+                    margin-bottom: 15px;
+
+                    >div {
+                        width: 33.33%;
+                        border: 1px solid #f3f3f3;
+                        cursor: pointer;
+                        font-size: 12px;
+                        color: #525252;
+                        min-width: 78px;
+                        display: flex;
+                        flex-direction: column;
+                        justify-content: center;
+                        align-items: center;
+                        padding: 20px 0;
+
+                        &:not(:nth-child(1)) {
+                            border-left: none;
+                        }
+                    }
+
+                    >.disabled {
+                        cursor: default;
+
+                        >svg,
+                        span {
+                            opacity: .3;
+                        }
+                    }
+                }
+            }
+
+            .right {
+                background-color: #fff;
+                padding: 10px;
+                box-sizing: border-box;
+            }
+
+            .center {
+                max-height: 100%;
+                padding: 15px 0 200px;
+                box-sizing: border-box;
+
+                >.page {
+                    margin: 0 auto;
+                    width: 375px;
+                    min-height: 667px;
+                    background-color: rgb(255, 255, 255);
+                    position: relative;
+                    padding-top: 1px;
+                    box-shadow: 0 3px 5px 0 rgba(0, 0, 0, 3%), 0 6px 15px 0 rgba(0, 0, 0, 4%), 0 0 0 1px hsl(0deg, 0%, 87%, 60%);
+                }
+
+            }
+
+            .left {
+                max-height: 100%;
+                width: 100%;
+                overflow: hidden;
+            }
+        }
+    }
+
+    .ant-drawer-body {
+        padding: 0 !important;
+    }
+
+    .drawerTitle {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        button.next {
+            margin-right: 50px;
+        }
+    }
+}
+
+.sidebar{
+    position: absolute;
+    top: 0;
+    left: -64px;
+    width: 32px;
+    z-index: 4;
+    transform-origin: top right;
+    text-align: center;
+    font-size: 12px;
+    color: #6b6b6b;
+    z-index: 1008;
+}

+ 33 - 1
src/pages/weComTask/page/miniProgramPages/index.tsx

@@ -11,6 +11,9 @@ import { delLandingPageApi, getLandingPageListApi, GetLandingPageListProps } fro
 import { useSize } from "ahooks";
 import { TableConfig } from "./tableConfig";
 import { randomString } from "@/utils/utils";
+import DrawerMini from "./drawerMini";
+import { getGenerateUrllinkApi } from "../../API/global";
+import ShowQrCode from "./showQrCode";
 
 
 /**
@@ -29,10 +32,12 @@ const MiniProgramPages: React.FC = () => {
     const [groupList, setGroupList] = useState<{ label: string, value: number }[]>([])
     const [selectedRows, setselectedRows] = useState<any[]>([])
     const [initialValues, setInitialValues] = useState<any>()
+    const [qrCode, setQrCode] = useState<{ url: string, visible: boolean }>()
 
     const getProjectGroupsAllList = useAjax(() => getProjectGroupsAllListApi())
     const getLandingPageList = useAjax((params) => getLandingPageListApi(params))
     const delLandingPage = useAjax((params) => delLandingPageApi(params))
+    const getGenerateUrllink = useAjax((params) => getGenerateUrllinkApi(params))
     /******************************************/
 
     useEffect(() => {
@@ -95,6 +100,14 @@ const MiniProgramPages: React.FC = () => {
         }).catch(() => hide())
     }
 
+    const handleCode = (id: number) => {
+        getGenerateUrllink.run({ path: '/pages/Ldpage/index', query: `pageId=${id}` }).then(res => {
+            if (res?.data) {
+                setQrCode({ visible: true, url: res.data })
+            }
+        })
+    }
+
     return <Card
         styles={{ body: { padding: 0, display: 'flex', flexDirection: 'column', height: 'calc(100vh - 88px)' } }}
     >
@@ -167,7 +180,7 @@ const MiniProgramPages: React.FC = () => {
         <div className={style.bookLinkTable} ref={ref}>
             <Table
                 dataSource={getLandingPageList?.data?.data?.records}
-                columns={TableConfig(handleEdit, handleDel)}
+                columns={TableConfig(handleEdit, handleDel, handleCode)}
                 bordered
                 pagination={false}
                 rowKey={'id'}
@@ -244,6 +257,25 @@ const MiniProgramPages: React.FC = () => {
                 setVisible(false)
             }}
         />}
+        {/* {visible && <DrawerMini
+            initialValues={initialValues}
+            groupList={groupList}
+            visible={visible}
+            onChange={() => {
+                setInitialValues(undefined)
+                setVisible(false)
+                getLandingPageList?.refresh()
+            }}
+            onClose={() => {
+                setInitialValues(undefined)
+                setVisible(false)
+            }}
+        />} */}
+
+        {qrCode?.visible && <ShowQrCode 
+            {...qrCode}
+            onClose={() => setQrCode(undefined)}
+        />}
     </Card>
 }
 

+ 64 - 0
src/pages/weComTask/page/miniProgramPages/left.tsx

@@ -0,0 +1,64 @@
+import { Col } from "antd"
+import React, { useContext } from "react"
+import style from './index.less'
+import { useDrag } from "ahooks";
+import { ReactComponent as TopImgSvg } from '../../../../public/svg/topimg.svg'
+import { ReactComponent as TopVideoSvg } from '../../../../public/svg/topvideo.svg'
+import { ReactComponent as ImgSvg } from '../../../../public/svg/img.svg'
+import { ReactComponent as TextSvg } from '../../../../public/svg/text.svg'
+import { ReactComponent as FloatbuttonSvg } from '../../../../public/svg/floatbuttonSvg.svg'
+import { DispatchMiniPageCreate } from "./drawerMini";
+import DragItem from "./dragItem";
+
+const Left: React.FC = () => {
+
+    /**************************************/
+    const { setDragging, setDraggingCon, pageSpecs: { pageElementsSpecList } } = useContext(DispatchMiniPageCreate)!;
+    /**************************************/
+
+    const getDragProps = useDrag({
+        onDragStart: (data) => {
+            setDragging(data);
+        },
+        onDragEnd: () => {
+            setDragging(null);
+        },
+    });
+
+
+    const getDragPropsCon = useDrag({
+        onDragStart: (data) => {
+            setDraggingCon(data);
+        },
+        onDragEnd: () => {
+            setDraggingCon(null);
+        },
+    });
+
+
+    return <Col flex="320px" className={style.right}>
+        <div className={style.title}>顶部组件</div>
+        <div className={style.assembly}>
+            {pageElementsSpecList?.[0].elementType === 'empty' ? <>
+                <DragItem icon={<TopImgSvg />} title="图片" dragProps={getDragProps(`TOP_IMAGE`)} />
+                <DragItem icon={<TopVideoSvg />} title="视频" dragProps={getDragProps(`TOP_VIDEO`)} />
+            </> : <>
+                <div className={style.disabled}> <TopImgSvg /> <span>图片</span> </div>
+                <div className={style.disabled}> <TopVideoSvg /> <span>视频</span></div>
+            </>}
+        </div>
+
+        <div className={style.title}>基础组件</div>
+        <div className={style.assembly}>
+            <DragItem icon={<ImgSvg />} title="图片" dragProps={getDragPropsCon(`IMAGE`)} />
+            <DragItem icon={<TextSvg />} title="文字" dragProps={getDragPropsCon(`TEXT`)} />
+        </div>
+
+        <div className={style.title}>营销组件</div>
+        <div className={style.assembly}>
+            <DragItem icon={<FloatbuttonSvg />} title="悬浮组件" dragProps={getDragPropsCon(`FLOAT_BUTTON`)} />
+        </div>
+    </Col>
+}
+
+export default React.memo(Left)

+ 24 - 0
src/pages/weComTask/page/miniProgramPages/right.tsx

@@ -0,0 +1,24 @@
+import { Col } from 'antd';
+import React, { useContext, useEffect, useState } from 'react';
+import style from './index.less'
+import './global.less'
+import { DispatchMiniPageCreate } from './drawerMini';
+
+const Right: React.FC = () => {
+
+    /**************************************/
+    const { pageSpecs, setPageSpecs } = useContext(DispatchMiniPageCreate)!;
+    const { pageElementsSpecList } = pageSpecs
+    const activeSpec = pageElementsSpecList?.find(item => item?.elementType)
+    /**************************************/
+    // if (activeSpec) {
+    //     return <Col flex="380px" className={style.left}>
+
+    //     </Col>
+    // }
+    return <Col flex="380px" className={style.left}>
+
+    </Col>
+};
+
+export default React.memo(Right);

+ 28 - 0
src/pages/weComTask/page/miniProgramPages/showQrCode.tsx

@@ -0,0 +1,28 @@
+import { Modal, QRCode, Space } from "antd"
+import React from "react"
+
+interface Props {
+    url: string,
+    visible?: boolean
+    onClose?: () => void
+}
+
+/**
+ * 
+ * @param param0 
+ * @returns 
+ */
+const ShowQrCode: React.FC<Props> = ({ url, visible, onClose }) => <Modal
+    title="预览二维码"
+    open={visible}
+    onCancel={onClose}
+    footer={null}
+    width={332}
+>
+    <Space align="center" direction='vertical'>
+        <QRCode value={url} size={300} />
+        <span>{url}</span>
+    </Space>
+</Modal>
+
+export default React.memo(ShowQrCode)

+ 8 - 4
src/pages/weComTask/page/miniProgramPages/tableConfig.tsx

@@ -2,7 +2,11 @@ import { ColumnsType } from "antd/es/table"
 import { Flex, Popconfirm, Image } from "antd"
 
 
-export function TableConfig(handleEdit?: (d: Record<string, any>, isCopy?: boolean) => void, handleDel?: (data: number[]) => void): ColumnsType<any> {
+export function TableConfig(
+    handleEdit?: (d: Record<string, any>, isCopy?: boolean) => void, 
+    handleDel?: (data: number[]) => void,
+    handleCode?: (id: number) => void
+): ColumnsType<any> {
 
     const arr: ColumnsType<any> = [
         {
@@ -81,13 +85,13 @@ export function TableConfig(handleEdit?: (d: Record<string, any>, isCopy?: boole
             title: '操作',
             dataIndex: 'cz',
             key: 'cz',
-            align: 'center',
-            width: 100,
+            width: 200,
             fixed: 'right',
             render: (_, records) => {
-                return <Flex gap={4} justify='center'>
+                return <Flex gap={4}>
                     <a onClick={() => handleEdit?.(records, true)}>复制</a>
                     <a onClick={() => handleEdit?.(records)}>修改</a>
+                    <a onClick={() => handleCode?.(records.id)}>小程序预览链接</a>
                     <Popconfirm
                         title="确定删除?"
                         onConfirm={() => { handleDel?.([records.id]) }}

+ 53 - 0
src/pages/weComTask/page/miniProgramPages/typings.d.ts

@@ -0,0 +1,53 @@
+declare namespace TASK_MINI_PAGE_CREATE {
+    interface ActiveType {
+        comptActive?: boolean
+    }
+
+    interface Padding {
+        paddingTop: number,//边距 顶部轮播不存在
+        paddingBottom: number,//边距 顶部轮播不存在
+    }
+
+    interface DispatchMiniPageCreate {
+        dragging: string,
+        setDragging: React.Dispatch<React.SetStateAction<string>>
+        draggingCon: string,
+        setDraggingCon: React.Dispatch<React.SetStateAction<string>>
+        pageSpecs: TASK_MINI_PAGE_CREATE.PageSpecsProps
+        setPageSpecs: React.Dispatch<React.SetStateAction<TASK_MINI_PAGE_CREATE.PageSpecsProps>>
+        installActive: (e: React.MouseEvent<HTMLDivElement, MouseEvent>, index: number) => void
+    }
+
+    interface Text extends ActiveType, Padding {
+        text: string,
+        fontSize: 14 | 15 | 16 | 18 | 20 | 24 | 36,
+        fontColor: string,
+        textAlignment: 0 | 1 | 2,  // 取值 0: left, 1: middle, 2: right. 默认 0
+        fontStyle: 0 | 1,  // 0: 常规, 1: 加粗. 默认 0
+        elementType: 'TEXT'
+    }
+
+    interface TopImage extends ActiveType {
+        url: string,
+        elementType: 'TOP_IMAGE'
+    }
+
+    interface TopVideo extends ActiveType {
+        url: string,
+        elementType: 'TOP_VIDEO'
+    }
+
+    interface Image extends ActiveType, Padding {
+        url: string,
+        elementType: 'IMAGE'
+    }
+
+    type Empty = {
+        elementType: 'empty'
+    }
+
+    interface PageSpecsProps {
+        bgColor: string,
+        pageElementsSpecList: Array<TopImage | TopVideo | Image | Text | Empty>
+    }
+}

binární
src/public/image/MpaVideoIcon.png


+ 1 - 0
src/public/svg/edit.svg

@@ -0,0 +1 @@
+<svg class="adui-button-leftIcon adui-icon-base" width="18" height="18" viewBox="0 0 18 18" fill="var(--gray-700)" data-interactive="false" data-icon="replace"><path d="M3.5 3.5V6.5H6.5V3.5H3.5ZM16 10V16H10V10H16ZM3.5 9V10.5C3.5 11.7426 4.50736 12.75 5.75 12.75H7V11L9.75 13.5L7 16V14.25H5.75C3.67893 14.25 2 12.5711 2 10.5V9H3.5ZM14.5 11.5H11.5V14.5H14.5V11.5ZM11 2V3.75H12.25C14.3211 3.75 16 5.42893 16 7.5V9H14.5V7.5C14.5 6.25736 13.4926 5.25 12.25 5.25H11V7L8.25 4.5L11 2ZM8 2V8H2V2H8Z" fill-rule="evenodd"></path></svg>

+ 1 - 0
src/public/svg/floatbuttonSvg.svg

@@ -0,0 +1 @@
+<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5.5 8.5C3.84315 8.5 2.5 9.84315 2.5 11.5V16.5C2.5 18.1569 3.84315 19.5 5.5 19.5H22.5C24.1569 19.5 25.5 18.1569 25.5 16.5V11.5C25.5 9.84315 24.1569 8.5 22.5 8.5H5.5ZM5.5 12.5H8.5V15.5H5.5V12.5ZM17.5 14.5V13.5H22.5V14.5H17.5Z" fill="url(#paint0_linear)" stroke="white"></path><defs><linearGradient id="paint0_linear" x1="24.3537" y1="18.9707" x2="24.3537" y2="9.55829" gradientUnits="userSpaceOnUse"><stop stop-color="#999999"></stop><stop offset="1" stop-color="#737373"></stop></linearGradient></defs></svg>

+ 1 - 0
src/public/svg/img.svg

@@ -0,0 +1 @@
+<svg width="28" height="28" viewBox="0 0 28 28"><defs><linearGradient x1="50%" y1="99.707%" x2="50%" y2="5.583%" id="a"><stop stop-color="#999" offset="0%"></stop><stop stop-color="#737373" offset="100%"></stop></linearGradient></defs><path d="M19.5 6A2.5 2.5 0 0122 8.5v11a2.5 2.5 0 01-2.5 2.5h-11A2.5 2.5 0 016 19.5v-11A2.5 2.5 0 018.5 6h11zm-2.657 8.156a1 1 0 00-1.347.006l-4.22 3.881a.5.5 0 01-.643.03l-2.731-2.087a.25.25 0 00-.402.199V19.5a1 1 0 001 1h11a1 1 0 001-1v-1.82a.5.5 0 00-.165-.371zM11 9.5a1.5 1.5 0 100 3 1.5 1.5 0 000-3z" fill="url(#a)" fill-rule="nonzero"></path></svg>

+ 1 - 0
src/public/svg/text.svg

@@ -0,0 +1 @@
+<svg width="28" height="28" viewBox="0 0 28 28"><defs><linearGradient x1="50%" y1="99.707%" x2="50%" y2="5.583%" id="canvas_gradient_common"><stop stop-color="#999" offset="0%"></stop><stop stop-color="#737373" offset="100%"></stop></linearGradient></defs><path d="M8.5 6h11A2.5 2.5 0 0122 8.5v11a2.5 2.5 0 01-2.5 2.5h-11A2.5 2.5 0 016 19.5v-11A2.5 2.5 0 018.5 6zm1 3.5V11h9V9.5h-9zM12 17v1.5h4V17h-4zm-2.5-6v1.5h.75l.375-1.5H9.5zm9 0h-1.125l.375 1.5h.75V11zm-5.25 0v6h1.5v-6h-1.5z" fill="url(#a)" fill-rule="nonzero"></path></svg>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
src/public/svg/topNullBack.svg


+ 1 - 0
src/public/svg/topimg.svg

@@ -0,0 +1 @@
+<svg width="28" height="28" viewBox="0 0 28 28"><defs><linearGradient x1="50%" y1="99.707%" x2="50%" y2="5.583%" id="a"><stop stop-color="#999" offset="0%"></stop><stop stop-color="#737373" offset="100%"></stop></linearGradient></defs><g fill="none" fill-rule="evenodd"><path d="M19.5 6A2.5 2.5 0 0122 8.5v11a2.5 2.5 0 01-2.5 2.5h-11A2.5 2.5 0 016 19.5v-11A2.5 2.5 0 018.5 6h11zm-2.657 8.156a1 1 0 00-1.347.006l-4.22 3.881a.5.5 0 01-.643.03l-2.731-2.087a.25.25 0 00-.402.199V19.5a1 1 0 001 1h11a1 1 0 001-1v-1.82a.5.5 0 00-.165-.371zM11 9.5a1.5 1.5 0 100 3 1.5 1.5 0 000-3z" fill="url(#a)" fill-rule="nonzero"></path><path d="M5.25 1a.75.75 0 010 1.5h-2.5a.75.75 0 010-1.5h2.5zm5 0a.75.75 0 110 1.5h-2.5a.75.75 0 010-1.5h2.5zm5 0a.75.75 0 110 1.5h-2.5a.75.75 0 110-1.5h2.5zm5 0a.75.75 0 110 1.5h-2.5a.75.75 0 110-1.5h2.5zm5 0a.75.75 0 110 1.5h-2.5a.75.75 0 110-1.5h2.5z" fill="#C7C7C7"></path></g></svg>

+ 1 - 0
src/public/svg/topvideo.svg

@@ -0,0 +1 @@
+<svg width="28" height="28" viewBox="0 0 28 28"><defs><linearGradient x1="50%" y1="99.707%" x2="50%" y2="5.583%" id="a"><stop stop-color="#999" offset="0%"></stop><stop stop-color="#737373" offset="100%"></stop></linearGradient></defs><g fill="none" fill-rule="evenodd"><path d="M16.5 8A1.5 1.5 0 0118 9.5v2.25l4.2-3.15a.5.5 0 01.8.4v10a.5.5 0 01-.8.4L18 16.25v2.25a1.5 1.5 0 01-1.5 1.5h-10A1.5 1.5 0 015 18.5v-9A1.5 1.5 0 016.5 8h10z" fill="url(#a)" fill-rule="nonzero"></path><path d="M5.25 1a.75.75 0 010 1.5h-2.5a.75.75 0 010-1.5h2.5zm5 0a.75.75 0 110 1.5h-2.5a.75.75 0 010-1.5h2.5zm5 0a.75.75 0 110 1.5h-2.5a.75.75 0 110-1.5h2.5zm5 0a.75.75 0 110 1.5h-2.5a.75.75 0 110-1.5h2.5zm5 0a.75.75 0 110 1.5h-2.5a.75.75 0 110-1.5h2.5z" fill="#C7C7C7"></path></g></svg>

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů