|
@@ -0,0 +1,2269 @@
|
|
|
+import { Button, Checkbox, Col, Drawer, Form, Input, InputNumber, message, Modal, Radio, RadioChangeEvent, Row, Select, Slider, Space, Spin, Switch, Tooltip } from 'antd'
|
|
|
+import React, { useCallback, useEffect, useMemo, useState } from "react"
|
|
|
+import modal from "antd/lib/modal"
|
|
|
+import style from './index.less'
|
|
|
+import './index1.less'
|
|
|
+import { ReactComponent as Topimg } from '@/assets/topimg.svg'
|
|
|
+import { ReactComponent as Topslider } from '@/assets/topslider.svg'
|
|
|
+import { ReactComponent as Topvideo } from '@/assets/topvideo.svg'
|
|
|
+import { ReactComponent as Img } from '@/assets/img.svg'
|
|
|
+import { ReactComponent as MyText } from '@/assets/text.svg'
|
|
|
+import { ReactComponent as TopNullBack } from '@/assets/topNullBack.svg'
|
|
|
+import { ReactComponent as FollowAcc } from '@/assets/followAcc.svg'
|
|
|
+import { ReactComponent as EditSvg } from '@/assets/edit.svg'
|
|
|
+import { ReactComponent as SliderImgSvg } from '@/assets/sliderImgSvg.svg'
|
|
|
+import { ReactComponent as JumpLink } from '@/assets/jumpLink.svg'
|
|
|
+import { ReactComponent as ImgText } from '@/assets/imgText.svg'
|
|
|
+import { ReactComponent as FloatbuttonSvg } from '@/assets/floatbuttonSvg.svg'
|
|
|
+import { ReactComponent as WxAutoSvg } from '@/assets/wxAutoSvg.svg'
|
|
|
+
|
|
|
+import { AlignCenterOutlined, AlignLeftOutlined, AlignRightOutlined, DeleteOutlined, PlusOutlined, QuestionCircleOutlined, RetweetOutlined, SwapLeftOutlined, SwapRightOutlined } from '@ant-design/icons'
|
|
|
+import { useDrop, useDrag } from 'ahooks'
|
|
|
+import arrayMove from "array-move";
|
|
|
+import ColorPicker from '@/components/ColorPicker1'
|
|
|
+import TextArea from 'antd/lib/input/TextArea'
|
|
|
+import moment from 'moment'
|
|
|
+import { TopImg, TopVideo, Text, Img as ImgProps, GhButton, TopSlider, LinkButton, Shelfnew, WxAutoButton, Floatbutton } from '../../req'
|
|
|
+import { imgContent, txtContent, ghContent, topvideoNewContent, linkContent, topsliderContent, topimgContent, topvideoContent, shelfnewContent, shelfnewContent2, btModelJumpGh, btModelJumpLink, btModelJumpLink103, btModelJumpGh103, jumpLink104, jumpGh104, jumpLink103, jumpGh103, wxAutoContent, jumpWxAuto104, jumpWxAuto103, btModelJumpWxAuto, btModelJumpWxAuto103, floatbuttonContent, floatbuttonBtTypeWxAuto, floatbuttonBtTypeGh } from './content'
|
|
|
+import { landingPageReducer, Content, Props } from './landingPageReducer'
|
|
|
+
|
|
|
+import {
|
|
|
+ SortableList,
|
|
|
+ SortableItemText,
|
|
|
+ SortableItemImg,
|
|
|
+ SortableItemFollowAcc,
|
|
|
+ SortableItemImgText,
|
|
|
+ SortableUlList,
|
|
|
+ SortableItemNoLi,
|
|
|
+ SortableItemLi,
|
|
|
+ SortableItemJumpLink,
|
|
|
+ SortableItemWxAuto,
|
|
|
+ SortableItemFloatbutton
|
|
|
+} from './sortable'
|
|
|
+import { useModel } from 'umi'
|
|
|
+import SelectCloud from '../selectCloud'
|
|
|
+import { getTypeKey, txtLength } from '@/utils/utils'
|
|
|
+
|
|
|
+const { Option } = Select;
|
|
|
+
|
|
|
+function AddLandingPage(props: Props) {
|
|
|
+ let { visible, hideModal, ajax, id } = props
|
|
|
+
|
|
|
+ const { state, stateGlobal, dispatch, dispatchGlobal } = landingPageReducer()
|
|
|
+ const { content, pageBackColor } = state
|
|
|
+ const { componentItem } = stateGlobal
|
|
|
+ const { currentUser }: any = useModel('@@initialState', model => ({ currentUser: model.initialState?.currentUser }))
|
|
|
+ const { init, add, get, state: { parentId, belongUser } } = useModel('useLaunchAdq.useBdMediaPup')
|
|
|
+ /** 变量开始 */
|
|
|
+ const [selectImgVisible, setSelectImgVisible] = useState<boolean>(false) // 选择图片弹窗
|
|
|
+ const [lastVisible, setLastVisible] = useState<boolean>(false) // 最后保存设置
|
|
|
+ const [shareTittle, setShareTittle] = useState<string>('') // 分享标题
|
|
|
+ const [shareDesc, setShareDesc] = useState<string>('') // 分享描述
|
|
|
+ const [pageName, setPageName] = useState<string>('') // 落地页名称
|
|
|
+ const [sort, setSort] = useState<number>(0) // 排序
|
|
|
+ const [imgSize, setImgSize] = useState<{
|
|
|
+ aspectRatio?: string, //宽高比
|
|
|
+ minWidth?: string, //最小宽度
|
|
|
+ maxWidth?: string, //最大宽度
|
|
|
+ minHeight?: string, //最小高度
|
|
|
+ maxHeight?: string, //最大高度
|
|
|
+ minMediaSize?: number, // 最小媒体大小
|
|
|
+ maxMediaSize?: number, // 最大媒体大小
|
|
|
+ minVideoLength?: number, // 最小视频时长
|
|
|
+ maxVideoLength?: number, // 最大视频时长
|
|
|
+ minVideoBitRate?: number, // 最小视频比特率
|
|
|
+ maxVideoBitRate?: number, // 最大视频比特率
|
|
|
+ mediaType?: 'IMG' | 'VIDEO' | 'PAGE', // 内容类型 1 图片 2 视频
|
|
|
+ }>({}) // 要选择的素材信息
|
|
|
+ const [isFootlock, setIsFootlock] = useState<boolean>(false) // 是否横板视频
|
|
|
+ const [scType, setCcType] = useState<1 | 2 | 3 | 4 | 5>(1) // 视频 单图片 多图片处理
|
|
|
+ const [sliderImgContent, setSliderImgContent] = useState<{ url: string, width?: number, height?: number }[]>([]) // 保存回填数据
|
|
|
+ const [imgTextButtonShow, setImgTextButtonShow] = useState<boolean>(false)
|
|
|
+ const [goodsCount, setGoodsCount] = useState<number>(0)
|
|
|
+ /** 变量结束 */
|
|
|
+
|
|
|
+ // console.log('content---->', content)
|
|
|
+
|
|
|
+ // 回填
|
|
|
+ useEffect(() => {
|
|
|
+ if (id) {
|
|
|
+ get.run({ sysMediaId: id, mediaType: 'PAGE' }).then(res => {
|
|
|
+ if (res) {
|
|
|
+ const { pageSpecsList, shareContentSpec } = res
|
|
|
+ dispatch({ type: 'setPageBackColor', params: { pageBackColor: pageSpecsList[0]?.bgColor } })
|
|
|
+ let pageElementsSpecList = pageSpecsList[0]?.pageElementsSpecList
|
|
|
+ dispatch({
|
|
|
+ type: 'setCon', params: {
|
|
|
+ content: pageElementsSpecList?.map((item: any) => {
|
|
|
+ let typeKey = getTypeKey(item?.elementType)
|
|
|
+ if (typeKey) {
|
|
|
+ let data = item[typeKey] || {}
|
|
|
+ return {
|
|
|
+ elementType: item?.elementType,
|
|
|
+ ...data
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return item
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ setShareDesc(() => shareContentSpec?.shareTitle || '')
|
|
|
+ setShareTittle(() => shareContentSpec?.shareDescription || '')
|
|
|
+ // global = global?.map((item: any) => ({ ...item, comptActive: false }))
|
|
|
+ // dispatchGlobal({ type: "setConItem", params: { componentItem: global || [] } })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // dispatch({ type: 'init', params: { elementType: 'empty' } })
|
|
|
+ }
|
|
|
+ }, [id])
|
|
|
+
|
|
|
+ const config = {
|
|
|
+ title: '警告!',
|
|
|
+ cancelText: '取消',
|
|
|
+ okText: '确定',
|
|
|
+ onOk: () => { hideModal() },
|
|
|
+ content: (
|
|
|
+ <>
|
|
|
+ <div>不会保存您所做的更改,确定关闭?</div>
|
|
|
+ </>
|
|
|
+ ),
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 获取选中内容对应图片视频尺寸大小 */
|
|
|
+ useEffect(() => {
|
|
|
+ let selectData = content?.find((item: Content) => item.comptActive)
|
|
|
+ if (!selectData) {
|
|
|
+ selectData = componentItem?.find((item: { comptActive: boolean }) => item.comptActive)
|
|
|
+ }
|
|
|
+ if (selectData?.elementType === "TOP_IMAGE") {
|
|
|
+ setIsFootlock(() => false)
|
|
|
+ if (selectData?.adLocation === 'sns') { // 朋友圈信息流
|
|
|
+ if (selectData?.outerStyle === 0) { // 常规广告
|
|
|
+ init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: 800, height: 800 }]] })
|
|
|
+ } else { // 卡片广告
|
|
|
+ init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: 800, height: 450 }]] })
|
|
|
+ }
|
|
|
+ } else { // 公众号及其他
|
|
|
+ init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: 800, height: 800 }], [{ relation: '=', width: 800, height: 450 }], [{ relation: '=', width: 800, height: 640 }], [{ relation: '=', width: 640, height: 800 }]] })
|
|
|
+ }
|
|
|
+ } else if (selectData?.elementType === 'IMAGE') { // 内容图片
|
|
|
+ setIsFootlock(() => false)
|
|
|
+ init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: 750, height: null }, { relation: '<=', width: null, height: 1536 }]] })
|
|
|
+ } else if (selectData?.elementType === 'TOP_SLIDER') { // 轮播图
|
|
|
+ init({ mediaType: 'IMG', num: selectData?.imageUrlList?.length || 3, cloudSize: [[{ relation: '=', width: 800, height: 800 }]] })
|
|
|
+ setIsFootlock(() => false)
|
|
|
+ } else if (selectData?.elementType === 'TOP_VIDEO') { // 视频
|
|
|
+ if (selectData?.adLocation === 'sns') { // 朋友圈信息流
|
|
|
+ if (selectData?.outerStyle === 0) { // 常规广告
|
|
|
+ init({ mediaType: 'VIDEO', cloudSize: [[{ relation: '=', width: 640, height: 480 }], [{ relation: '=', width: 640, height: 360 }], [{ relation: '=', width: 750, height: 1334 }], [{ relation: '=', width: 720, height: 1280 }] ] })
|
|
|
+ } else { // 卡片广告
|
|
|
+ init({ mediaType: 'VIDEO', cloudSize: [[{ relation: '=', width: 750, height: null }, { relation: '<=', width: null, height: 1536 }]] })
|
|
|
+ }
|
|
|
+ } else { // 公众号及其它
|
|
|
+ init({ mediaType: 'VIDEO', cloudSize: [[{ relation: '=', width: 750, height: null }, { relation: '<=', width: null, height: 1536 }]] })
|
|
|
+ setIsFootlock(() => false)
|
|
|
+ }
|
|
|
+ } else if (selectData?.elementType === 'shelfnew') { // 图文复合组件 1个
|
|
|
+ if (selectData?.type === '104') {
|
|
|
+ setIsFootlock(() => false)
|
|
|
+ setImgSize(() => ({ minWidth: '360', maxWidth: '360', minHeight: '360', maxHeight: '360', minMediaSize: 0, maxMediaSize: 307200, mediaType: 'IMG' }))
|
|
|
+ } else if (selectData?.type === '103') {
|
|
|
+ setIsFootlock(() => false)
|
|
|
+ setImgSize(() => ({ minWidth: '480', maxWidth: '480', minHeight: '480', maxHeight: '480', minMediaSize: 0, maxMediaSize: 307200, mediaType: 'IMG' }))
|
|
|
+ }
|
|
|
+ } else if (selectData?.elementType === 'FLOAT_BUTTON') {
|
|
|
+ setIsFootlock(() => false)
|
|
|
+ init({ mediaType: 'VIDEO', cloudSize: { minWidth: '96', maxWidth: '96', minHeight: '96', maxHeight: '96', minMediaSize: 0, maxMediaSize: 307200 } })
|
|
|
+ setImgSize(() => ({ minWidth: '96', maxWidth: '96', minHeight: '96', maxHeight: '96', minMediaSize: 0, maxMediaSize: 307200, mediaType: 'IMG' }))
|
|
|
+ }
|
|
|
+ }, [content])
|
|
|
+
|
|
|
+ const [dragging, setDragging] = useState<string | null>(null);
|
|
|
+ const getDragProps = useDrag({
|
|
|
+ onDragStart: (data) => {
|
|
|
+ setDragging(data);
|
|
|
+ },
|
|
|
+ onDragEnd: () => {
|
|
|
+ setDragging(null);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ // 头部内容拖到接收区
|
|
|
+ const [dropProps] = useDrop({
|
|
|
+ onDom: (con: string, e) => { // 头部
|
|
|
+ let newCon = content?.map((item: TopImg | TopVideo | TopSlider) => {
|
|
|
+ return { ...item, comptActive: false }
|
|
|
+ })
|
|
|
+ let topCon = newCon[0]
|
|
|
+ topCon.type = con
|
|
|
+ topCon.comptActive = true
|
|
|
+ let conContent: TopImg | TopVideo | TopSlider
|
|
|
+ if (con === 'TOP_SLIDER') {
|
|
|
+ conContent = { ...topsliderContent, comptActive: true } as TopSlider
|
|
|
+ } else if (con === 'TOP_IMAGE') {
|
|
|
+ conContent = { ...topimgContent, comptActive: true } as TopImg
|
|
|
+ } else if (con === 'TOP_VIDEO') {
|
|
|
+ conContent = { ...topvideoNewContent, comptActive: true } as TopVideo
|
|
|
+ } else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ topCon = { ...conContent }
|
|
|
+ newCon[0] = topCon
|
|
|
+ dispatch({ type: 'setCon', params: { content: newCon } })
|
|
|
+ },
|
|
|
+ });
|
|
|
+ const [draggingCon, setDraggingCon] = useState<string | null>(null);
|
|
|
+ const getDragPropsCon = useDrag({
|
|
|
+ onDragStart: (data) => {
|
|
|
+ setDraggingCon(data);
|
|
|
+ },
|
|
|
+ onDragEnd: () => {
|
|
|
+ setDraggingCon(null);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ // 内容拖到接收区
|
|
|
+ const [dropConProps, { isHovering: isHoveringCon }] = useDrop({
|
|
|
+ onDom: (con: string, e) => { // 内容
|
|
|
+ let newCon: Content[] = content?.map((item: Text | ImgProps | GhButton) => { // | LinkButton | WxAutoButton
|
|
|
+ return { ...item, comptActive: false }
|
|
|
+ })
|
|
|
+ let newConItem = componentItem?.map((item: Floatbutton) => {
|
|
|
+ return { ...item, comptActive: false }
|
|
|
+ })
|
|
|
+ if (con === 'TEXT') {
|
|
|
+ newCon.push({ ...txtContent, comptActive: true } as any)
|
|
|
+ } else if (con === 'IMAGE') {
|
|
|
+ newCon.push({ ...imgContent, comptActive: true } as any)
|
|
|
+ } else if (con === 'GH') {
|
|
|
+ newCon.push({ ...ghContent, comptActive: true } as any)
|
|
|
+ // } else if (con === 'JumpLink') {
|
|
|
+ // newCon.push({ ...linkContent, comptActive: true } as any)
|
|
|
+ // } else if (con === 'shelfnew') {
|
|
|
+ // newCon.push({ ...shelfnewContent, comptActive: true } as any)
|
|
|
+ } else if (con === 'ENTERPRISE_WX') {
|
|
|
+ newCon.push({ ...wxAutoContent, comptActive: true } as any)
|
|
|
+ } else if (con === 'FLOAT_BUTTON') {
|
|
|
+ newConItem.push({ ...floatbuttonContent, comptActive: true })
|
|
|
+ setDraggingCon(null);
|
|
|
+ } else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ dispatch({ type: 'setCon', params: { content: newCon } })
|
|
|
+ dispatchGlobal({ type: "setConItem", params: { componentItem: newConItem } })
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ /** 选中设置 */
|
|
|
+ const installActive = useCallback((e, index: number) => {
|
|
|
+ e.stopPropagation(); e.preventDefault();
|
|
|
+ let newCon = content?.map((item: any) => {
|
|
|
+ return { ...item, comptActive: false }
|
|
|
+ })
|
|
|
+ let newConItem = componentItem?.map((item: { widgetTypeV2: string }) => {
|
|
|
+ return { ...item, comptActive: false }
|
|
|
+ })
|
|
|
+ setImgTextButtonShow(false)
|
|
|
+ if (index === 99999) {
|
|
|
+ newConItem = newConItem?.map((item: { widgetTypeV2: string }) => {
|
|
|
+ if (item.widgetTypeV2 === 'floatbutton') {
|
|
|
+ return { ...item, comptActive: true }
|
|
|
+ }
|
|
|
+ return item
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ newCon[index].comptActive = true
|
|
|
+ }
|
|
|
+ dispatch({ type: 'setCon', params: { content: newCon } })
|
|
|
+ dispatchGlobal({ type: "setConItem", params: { componentItem: newConItem } })
|
|
|
+ }, [content, imgTextButtonShow, componentItem])
|
|
|
+ /** 清除选中 */
|
|
|
+ const installActiveNull = useCallback((e) => {
|
|
|
+ e.stopPropagation(); e.preventDefault();
|
|
|
+ let newCon = content?.map((item: any) => {
|
|
|
+ return { ...item, comptActive: false }
|
|
|
+ })
|
|
|
+ setImgTextButtonShow(false)
|
|
|
+ dispatch({ type: 'setCon', params: { content: newCon } })
|
|
|
+ let newConItem = componentItem?.map((item: { widgetTypeV2: string }) => {
|
|
|
+ return { ...item, comptActive: false }
|
|
|
+ })
|
|
|
+ dispatchGlobal({ type: "setConItem", params: { componentItem: newConItem } })
|
|
|
+ }, [content])
|
|
|
+ /** 内容功能按钮区 */
|
|
|
+ const handleBtn = useCallback((type: string, index: number) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ switch (type) {
|
|
|
+ case 'lower': // 下移动
|
|
|
+ dispatch({ type: 'setCon', params: { content: arrayMove(content, index, index + 1) } })
|
|
|
+ break;
|
|
|
+ case 'upper': // 上移动
|
|
|
+ dispatch({ type: 'setCon', params: { content: arrayMove(content, index, index - 1) } })
|
|
|
+ break;
|
|
|
+ case 'IMAGE': // 图片
|
|
|
+ newContent.splice(index, 0, { ...imgContent });
|
|
|
+ dispatch({ type: 'setCon', params: { content: newContent } })
|
|
|
+ break;
|
|
|
+ case 'TEXT': // 文本
|
|
|
+ newContent.splice(index, 0, { ...txtContent });
|
|
|
+ dispatch({ type: 'setCon', params: { content: newContent } })
|
|
|
+ break;
|
|
|
+ case 'GH': // 关注公众号按钮
|
|
|
+ newContent.splice(index, 0, { ...ghContent });
|
|
|
+ dispatch({ type: 'setCon', params: { content: newContent } })
|
|
|
+ break;
|
|
|
+ // case 'link': // 跳转链接按钮
|
|
|
+ // newContent.splice(index, 0, { ...linkContent });
|
|
|
+ // dispatch({ type: 'setCon', params: { content: newContent } })
|
|
|
+ // break;
|
|
|
+ // case 'shelfnew': // 图文复合组件
|
|
|
+ // newContent.splice(index, 0, { ...shelfnewContent });
|
|
|
+ // dispatch({ type: 'setCon', params: { content: newContent } })
|
|
|
+ // break;
|
|
|
+ case 'ENTERPRISE_WX': // 图文复合组件
|
|
|
+ newContent.splice(index, 0, { ...wxAutoContent });
|
|
|
+ dispatch({ type: 'setCon', params: { content: newContent } })
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }, [content])
|
|
|
+ /** 头部删除 */
|
|
|
+ const topDelType = useCallback(() => {
|
|
|
+ setDragging(null);
|
|
|
+ content[0] = {
|
|
|
+ elementType: 'empty',
|
|
|
+ comptActive: false
|
|
|
+ }
|
|
|
+ dispatch({ type: 'setCon', params: { content } })
|
|
|
+ }, [content, dragging])
|
|
|
+ /** 内容删除 */
|
|
|
+ const delType = useCallback((e, index: number) => {
|
|
|
+ e.stopPropagation(); e.preventDefault();
|
|
|
+ setImgTextButtonShow(false)
|
|
|
+ if (index === 99999) { // 删除悬浮组件
|
|
|
+ let newContentItem = JSON.parse(JSON.stringify(componentItem))
|
|
|
+ newContentItem = newContentItem?.filter((item: { widgetTypeV2: string }) => item.widgetTypeV2 !== 'floatbutton')
|
|
|
+ dispatchGlobal({ type: 'setConItem', params: { componentItem: JSON.parse(JSON.stringify(newContentItem)) } })
|
|
|
+ } else {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ newContent?.splice(index, 1)
|
|
|
+ dispatch({ type: 'setCon', params: { content: JSON.parse(JSON.stringify(newContent)) } })
|
|
|
+ }
|
|
|
+ }, [content, componentItem, imgTextButtonShow])
|
|
|
+
|
|
|
+ const onSortEnd = ({ oldIndex, newIndex }: { oldIndex: number, newIndex: number }) => {
|
|
|
+ dispatch({ type: 'setCon', params: { content: arrayMove(content, oldIndex, newIndex) } })
|
|
|
+ }
|
|
|
+ // 基础内容
|
|
|
+ const comptCon = () => {
|
|
|
+ if (content?.length === 0) {
|
|
|
+ return null
|
|
|
+ } else {
|
|
|
+ return <SortableList axis='y' onSortEnd={onSortEnd} useDragHandle isFloatButton={componentItem?.some((item: { elementType: string }) => item.elementType === 'FLOAT_BUTTON')}>
|
|
|
+ {content.map((value: Text | ImgProps | GhButton, index: number) => {
|
|
|
+ if (value?.elementType === 'IMAGE') {
|
|
|
+ return <SortableItemImg key={`item-${value.elementType}-${index}`} index={index} data={{ length: content?.length, index }} item={value} click={(e: any) => { installActive(e, index) }} del={(e: any) => { delType(e, index) }} upload={(num: number) => { clickUpdateImg(num) }} handleBtn={handleBtn} />
|
|
|
+ } else if (value?.elementType === 'TEXT') {
|
|
|
+ return <SortableItemText key={`item-${value.elementType}-${index}`} index={index} data={{ length: content?.length, index }} item={value} click={(e: any) => { installActive(e, index) }} del={(e: any) => { delType(e, index) }} pageBackColor={pageBackColor} handleBtn={handleBtn} />
|
|
|
+ } else if (value?.elementType === 'GH') {
|
|
|
+ return <SortableItemFollowAcc key={`item-${value.elementType}-${index}`} index={index} data={{ length: content?.length, index }} item={value} click={(e: any) => { installActive(e, index) }} del={(e: any) => { delType(e, index) }} handleBtn={handleBtn} />
|
|
|
+ } else if (value?.elementType === 'ENTERPRISE_WX') {
|
|
|
+ return <SortableItemWxAuto key={`item-${value.elementType}-${index}`} index={index} data={{ length: content?.length, index }} item={value} click={(e: any) => { installActive(e, index) }} del={(e: any) => { delType(e, index) }} handleBtn={handleBtn} />
|
|
|
+ // } else if (value?.elementType === 'link') {
|
|
|
+ // return <SortableItemJumpLink key={`item-${value.elementType}-${index}`} index={index} data={{ length: content?.length, index }} item={value} click={(e: any) => { installActive(e, index) }} del={(e: any) => { delType(e, index) }} handleBtn={handleBtn} />
|
|
|
+ // } else if (value?.elementType === 'shelfnew') {
|
|
|
+ // return <SortableItemImgText key={`item-${value.elementType}-${index}`} index={index} data={{ length: content?.length, index }} item={value} click={(e: any) => { installActive(e, index) }} del={(e: any) => { delType(e, index) }} handleBtn={handleBtn} />
|
|
|
+ } else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ })}
|
|
|
+ <div className={`comptCon ${isHoveringCon && 'hovering'} ${draggingCon && 'draggingCon'}`} {...dropConProps}>{(isHoveringCon || draggingCon) && '请拖至此处'}</div>
|
|
|
+ {componentItem?.some((item: { elementType: string }) => item.elementType === 'FLOAT_BUTTON') && <SortableItemFloatbutton index={99999} item={componentItem.find((item: { elementType: string }) => item.elementType === 'FLOAT_BUTTON')} click={(e: any) => { installActive(e, 99999) }} del={(e: any) => { delType(e, 99999) }} />}
|
|
|
+ </SortableList>
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /** 设置start */
|
|
|
+ const setCon = useCallback((key: string, value: any, isTopImg?: boolean) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ selectCon[key] = value
|
|
|
+ if (selectCon?.elementType === 'TOP_VIDEO' && (key === 'adLocation' || key === 'outerStyle')) {
|
|
|
+ selectCon['videoUrl'] = ''
|
|
|
+ }
|
|
|
+ let newSelectCon = { ...selectCon }
|
|
|
+ oldContent[selectIndex] = newSelectCon
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }, [content, goodsCount])
|
|
|
+ /** 设置end */
|
|
|
+ // 顶部组件
|
|
|
+ const topCon = useMemo(() => {
|
|
|
+ let { imageUrl, elementType, activeIndex, imageUrlList, videoUrl } = content[0]
|
|
|
+ return <>
|
|
|
+ {
|
|
|
+ elementType === 'TOP_IMAGE' ? <>
|
|
|
+ <div className={`compt componentType41 ${content[0]?.comptActive && 'comptActive'}`} onClick={(e) => { installActive(e, 0) }}>
|
|
|
+ <div className={'componentWrap'}>
|
|
|
+ <div className={'componentContent'}>
|
|
|
+ {
|
|
|
+ imageUrl ? <img src={imageUrl} style={{ display: 'block', width: '100%', margin: 0 }} /> : <div className={'default'} style={{ width: 375, height: 300, margin: 0 }}>
|
|
|
+ <div className={'defaultIcon'} style={{ marginTop: 80 }}>
|
|
|
+ <Topimg />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {
|
|
|
+ !imageUrl && <div className={'comptUpload'} style={{ margin: 0 }}>
|
|
|
+ <button style={{ marginTop: 150 }} className={'comptEditButton'} onClick={() => { clickUpdateImg(1) }}>上传图片</button>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ <section className={'comptEditBtns'}>
|
|
|
+ <div className={'comptEditBtnsInner'}>
|
|
|
+ {imageUrl && <button onClick={() => { editSelectImg(imageUrl) }}><EditSvg /></button>}
|
|
|
+ <button onClick={topDelType}><DeleteOutlined /></button>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+ </div>
|
|
|
+ </> :
|
|
|
+ elementType === 'TOP_SLIDER' ? <>
|
|
|
+ <div className={`compt componentType101 ${content[0]?.comptActive && 'comptActive'}`} onClick={(e) => { installActive(e, 0) }}>
|
|
|
+ <div className={'componentWrap'}>
|
|
|
+ <div className={'componentContent'}>
|
|
|
+ {imageUrlList?.length > 0 ? <div style={{ position: 'relative', width: 375, height: 375 }}>
|
|
|
+ {imageUrlList?.map((imgUrl: any, index: number) => {
|
|
|
+ if (imgUrl) {
|
|
|
+ return <img src={imgUrl} key={index} style={{ maxWidth: '100%', position: 'absolute', display: 'block', zIndex: activeIndex === index ? 1 : 0 }} />
|
|
|
+ } else {
|
|
|
+ return <div className="default" key={index} style={{ width: 375, zIndex: activeIndex === index ? 1 : 0, height: '100%', position: 'absolute', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
|
+ <div className="defaultIcon">
|
|
|
+ <SliderImgSvg />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ })}
|
|
|
+ <div className={'sliderD'}>
|
|
|
+ {imageUrlList.map((item: any, index: number) => <i key={index} style={activeIndex === index ? { backgroundColor: 'rgba(0, 0, 0, .4)' } : {}}></i>)}
|
|
|
+ </div>
|
|
|
+ </div> : <div style={{ position: 'relative', height: 222, width: 375 }} className={'sliderCon'}>
|
|
|
+ <div className={'default'}>
|
|
|
+ <div className={'defaultIcon'}>
|
|
|
+ <Topslider />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className={'sliderD'}>
|
|
|
+ {imageUrlList.fill('').map((item: any, index: number) => <i key={index} style={activeIndex === index ? { backgroundColor: 'rgba(0, 0, 0, .4)' } : {}}></i>)}
|
|
|
+ </div>
|
|
|
+ </div>}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <section className={'comptEditBtns'}>
|
|
|
+ <div className={'comptEditBtnsInner'}>
|
|
|
+ <button onClick={topDelType}><DeleteOutlined /></button>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+ </div>
|
|
|
+ </> :
|
|
|
+ elementType === 'TOP_VIDEO' ? <>
|
|
|
+ <div className={`compt componentType61 ${content[0]?.comptActive && 'comptActive'}`} onClick={(e) => { installActive(e, 0) }}>
|
|
|
+ <div className={'componentWrap'}>
|
|
|
+ <div className={'componentContent'}>
|
|
|
+ {
|
|
|
+ videoUrl ? <div className="videoPlay">
|
|
|
+ <video src={videoUrl} style={{ display: 'block', width: '100%', margin: 0 }} />
|
|
|
+ <span></span>
|
|
|
+ </div>
|
|
|
+ : <div className={'default'} style={{ width: 375, height: 300, margin: 0 }}>
|
|
|
+ <div className={'defaultIcon'} style={{ marginTop: 80 }}>
|
|
|
+ <Topvideo />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {!videoUrl && <div className={'comptUpload'} style={{ margin: 0 }}>
|
|
|
+ <button style={{ marginTop: 150 }} className={'comptEditButton'} onClick={() => { clickUpdateVideo() }}>上传视频</button>
|
|
|
+ </div>}
|
|
|
+
|
|
|
+ <section className={'comptEditBtns'}>
|
|
|
+ <div className={'comptEditBtnsInner'}>
|
|
|
+ {videoUrl && <button onClick={() => { clickUpdateVideo() }}><EditSvg /></button>}
|
|
|
+ <button onClick={topDelType}><DeleteOutlined /></button>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+ </div>
|
|
|
+ </> :
|
|
|
+ <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>
|
|
|
+ }
|
|
|
+ </>
|
|
|
+ }, [content, state, dragging])
|
|
|
+
|
|
|
+ /** 图标开启与关闭 */
|
|
|
+ const iconHandle = (e: boolean) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ selectCon['useIcon'] = e ? 1 : 0
|
|
|
+ oldContent[selectIndex] = selectCon
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /** 视频切换广告位 */
|
|
|
+ const changeAdLocation = (value: 'sns' | 'gh') => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ selectCon['adLocation'] = value
|
|
|
+ if (value === 'gh') {
|
|
|
+ selectCon['styleType'] = 1
|
|
|
+ } else {
|
|
|
+ selectCon['styleType'] = 0
|
|
|
+ }
|
|
|
+ selectCon['videoUrl'] = ''
|
|
|
+ oldContent[selectIndex] = selectCon
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 视频切换外层样式 */
|
|
|
+ const changeOuterLayout = (value: string) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ selectCon['viewType'] = value
|
|
|
+ let newSelectCon: any
|
|
|
+ if (value === '0') {
|
|
|
+ let { outerUseTopMaterial, streamDisplayWidth, streamDisplayHeight, streamVideoThumb, streamVideoUrl, streamDisplayType, streamThumbMd5, streamVideoMd5, displayType, ...clearSelectCon } = selectCon
|
|
|
+ newSelectCon = {
|
|
|
+ ...clearSelectCon
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ newSelectCon = {
|
|
|
+ ...selectCon,
|
|
|
+ outerUseTopMaterial: '0',
|
|
|
+ styleType: '0'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ oldContent[selectIndex] = newSelectCon
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 轮播图选择点击切换图片 多张图片 */
|
|
|
+ const sliderSelect = (index: number, count: number) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = newContent[selectIndex]
|
|
|
+ let imgList: any[] = []
|
|
|
+ selectCon?.imageUrlList?.forEach((item: string) => {
|
|
|
+ if (item) {
|
|
|
+ imgList.push({ url: item })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ setSliderImgContent(imgList)
|
|
|
+ }
|
|
|
+ setCon('activeIndex', index)
|
|
|
+ setCcType(3)
|
|
|
+ setSelectImgVisible(true)
|
|
|
+ }
|
|
|
+ /** 轮播图图片数量设置 */
|
|
|
+ const sliderImgNum = useCallback((num: string) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ let { imageUrlList } = selectCon
|
|
|
+ if (imageUrlList?.length > Number(num)) { // 减少
|
|
|
+ selectCon['imageUrlList'] = [...imageUrlList?.splice(0, Number(num))]
|
|
|
+ } else { // 增加
|
|
|
+ let newGroup = Array(Number(num) - imageUrlList?.length).fill('').map(() => "")
|
|
|
+ imageUrlList = [...imageUrlList, ...newGroup]
|
|
|
+ selectCon['imageUrlList'] = imageUrlList
|
|
|
+ }
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }, [content])
|
|
|
+
|
|
|
+ /** 轮播图位置拖动切换顺序 */
|
|
|
+ const onSortEndSlider = useCallback(({ oldIndex, newIndex }: { oldIndex: number, newIndex: number }) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ let { imageUrlList } = selectCon
|
|
|
+ imageUrlList = arrayMove(imageUrlList, oldIndex, newIndex)
|
|
|
+ selectCon['imageUrlList'] = imageUrlList
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }, [content])
|
|
|
+
|
|
|
+ /** 图文单个设置 */
|
|
|
+ const onShelfnewTxtCon = useCallback((value: string, count: number, parameter: string) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ if (selectCon?.type === '103') {
|
|
|
+ let componentItem = selectCon?.layoutItems.componentItem[goodsCount]
|
|
|
+ let shelfnewItem = componentItem?.layoutItems?.componentItem[0]?.layoutItems?.componentItem
|
|
|
+ shelfnewItem[count + 1][parameter] = value
|
|
|
+ if (count + 1 === 2 && parameter === 'content') {
|
|
|
+ if (shelfnewItem[count + 1]?.name === '价格') {
|
|
|
+ shelfnewItem[count + 1][parameter] = '¥' + value
|
|
|
+ } else {
|
|
|
+ shelfnewItem[count + 1][parameter] = value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (selectCon?.type === '104') {
|
|
|
+ let componentItem = selectCon?.layoutItems?.componentItem[0]?.layoutItems?.componentItem
|
|
|
+ let textData = componentItem[1]?.layoutItems?.componentItem
|
|
|
+ textData[count][parameter] = value
|
|
|
+ if (count === 1 && parameter === 'content') {
|
|
|
+ let name = textData[count]?.name
|
|
|
+ if (name === '价格') {
|
|
|
+ textData[count][parameter] = '¥' + value
|
|
|
+ } else {
|
|
|
+ textData[count][parameter] = value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }, [content, goodsCount])
|
|
|
+ /** 设置描述类型 */
|
|
|
+ const onSetShelfnewDescType = useCallback((e: RadioChangeEvent) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ if (selectCon?.type === '103') {
|
|
|
+ let componentItem = selectCon?.layoutItems.componentItem[goodsCount]
|
|
|
+ let shelfnewItem = componentItem?.layoutItems?.componentItem[0]
|
|
|
+ shelfnewItem.descType = e.target.value
|
|
|
+ let textData = shelfnewItem?.layoutItems?.componentItem
|
|
|
+ if (e.target.value === 'price') {
|
|
|
+ textData[2] = {
|
|
|
+ ...textData[2],
|
|
|
+ name: '价格',
|
|
|
+ content: '',
|
|
|
+ fontColor: '#353535',
|
|
|
+ fontSize: '32',
|
|
|
+ showType: "1",
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let { showType, ...desc } = textData[2]
|
|
|
+ textData[2] = {
|
|
|
+ ...desc,
|
|
|
+ name: '描述',
|
|
|
+ content: '',
|
|
|
+ fontColor: '#4D4D4D',
|
|
|
+ fontSize: '24'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (selectCon?.type === '104') {
|
|
|
+ let componentItem = selectCon?.layoutItems?.componentItem[0]?.layoutItems?.componentItem
|
|
|
+ componentItem[1].descType = e.target.value
|
|
|
+ let textData = componentItem[1]?.layoutItems?.componentItem
|
|
|
+ if (e.target.value === 'price') {
|
|
|
+ textData[1] = {
|
|
|
+ ...textData[1],
|
|
|
+ name: '价格',
|
|
|
+ content: '',
|
|
|
+ fontColor: '#353535',
|
|
|
+ fontSize: '32',
|
|
|
+ showType: "1",
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let { showType, ...desc } = textData[1]
|
|
|
+ textData[1] = {
|
|
|
+ ...desc,
|
|
|
+ name: '描述',
|
|
|
+ content: '',
|
|
|
+ fontColor: '#4D4D4D',
|
|
|
+ fontSize: '24'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }, [content, goodsCount])
|
|
|
+
|
|
|
+ /** 设置跳转方式 */
|
|
|
+ const onSetShelfnewJumpMode = useCallback((e: RadioChangeEvent) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ if (selectCon?.type === '103') {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].jumpMode = e.target.value
|
|
|
+ let jumpData = selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].layoutItems.componentItem[3]
|
|
|
+ let widgetTypeV2 = jumpData?.widgetTypeV2
|
|
|
+ let componentItem = selectCon?.layoutItems?.componentItem[goodsCount]?.layoutItems?.componentItem
|
|
|
+ if (e.target.value === 'btn_jump') {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem = [{ ...componentItem[0] }]
|
|
|
+ } else {
|
|
|
+ switch (widgetTypeV2) {
|
|
|
+ case 'link':
|
|
|
+ componentItem[1] = { ...btModelJumpLink103, origBtnJumpUrl: jumpData?.origBtnJumpUrl }
|
|
|
+ break
|
|
|
+ case 'gh':
|
|
|
+ componentItem[1] = { ...btModelJumpGh103, subType: jumpData?.subType, btnFontType: jumpData?.btnFontType }
|
|
|
+ break
|
|
|
+ case 'enterprise_wx_auto':
|
|
|
+ componentItem[1] = { ...btModelJumpWxAuto103, subType: jumpData?.subType, btnFontType: jumpData?.btnFontType }
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (selectCon?.type === '104') {
|
|
|
+ selectCon.layoutItems.componentItem[0].jumpMode = e.target.value
|
|
|
+ let textData = selectCon?.layoutItems?.componentItem[0]?.layoutItems?.componentItem[1]?.layoutItems?.componentItem
|
|
|
+ let widgetTypeV2 = textData[2].widgetTypeV2
|
|
|
+ let componentItem = selectCon?.layoutItems?.componentItem
|
|
|
+ if (e.target.value === 'btn_jump') {
|
|
|
+ selectCon.layoutItems.componentItem = [{ ...componentItem[0] }]
|
|
|
+ } else {
|
|
|
+ switch (widgetTypeV2) {
|
|
|
+ case 'link':
|
|
|
+ componentItem[1] = { ...btModelJumpLink, origBtnJumpUrl: textData[2]?.origBtnJumpUrl }
|
|
|
+ break
|
|
|
+ case 'gh':
|
|
|
+ componentItem[1] = { ...btModelJumpGh, subType: textData[2]?.subType, btnFontType: textData[2]?.btnFontType }
|
|
|
+ break
|
|
|
+ case 'enterprise_wx_auto':
|
|
|
+ componentItem[1] = { ...btModelJumpWxAuto, subType: textData[2]?.subType, btnFontType: textData[2]?.btnFontType }
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }, [content, goodsCount])
|
|
|
+ // 设置图文跳转链接按钮
|
|
|
+ const onSetShelfnewButton = useCallback((value: string) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ // "btn_jump" "total_jump"
|
|
|
+ if (selectCon?.type === '103') {
|
|
|
+ let jumpMode = selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].jumpMode
|
|
|
+ let btnContent = selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].layoutItems.componentItem[3]
|
|
|
+ if (value === 'link') {
|
|
|
+ if (jumpMode === "total_jump") {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[1] = { ...btModelJumpLink103 }
|
|
|
+ }
|
|
|
+ if (btnContent?.horizontalAlignment) {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].layoutItems.componentItem[3] = { ...jumpLink103, horizontalAlignment: '1' }
|
|
|
+ } else {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].layoutItems.componentItem[3] = { ...jumpLink103 }
|
|
|
+ }
|
|
|
+ } else if (value === 'gh') {
|
|
|
+ if (jumpMode === "total_jump") {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[1] = { ...btModelJumpGh103 }
|
|
|
+ }
|
|
|
+ if (btnContent?.horizontalAlignment) {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].layoutItems.componentItem[3] = { ...jumpGh103, horizontalAlignment: '1' }
|
|
|
+ } else {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].layoutItems.componentItem[3] = { ...jumpGh103 }
|
|
|
+ }
|
|
|
+ } else if (value === 'enterprise_wx_auto') {
|
|
|
+ if (jumpMode === "total_jump") {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[1] = { ...btModelJumpWxAuto103 }
|
|
|
+ }
|
|
|
+ if (btnContent?.horizontalAlignment) {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].layoutItems.componentItem[3] = { ...jumpWxAuto103, horizontalAlignment: '1' }
|
|
|
+ } else {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].layoutItems.componentItem[3] = { ...jumpWxAuto103 }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (selectCon?.type === '104') {
|
|
|
+ let jumpMode = selectCon.layoutItems.componentItem[0].jumpMode
|
|
|
+ if (value === 'link') {
|
|
|
+ if (jumpMode === "total_jump") {
|
|
|
+ selectCon.layoutItems.componentItem[1] = { ...btModelJumpLink }
|
|
|
+ }
|
|
|
+ selectCon.layoutItems.componentItem[0].layoutItems.componentItem[1].layoutItems.componentItem[2] = { ...jumpLink104 }
|
|
|
+ } else if (value === 'gh') {
|
|
|
+ if (jumpMode === "total_jump") {
|
|
|
+ selectCon.layoutItems.componentItem[1] = { ...btModelJumpGh }
|
|
|
+ }
|
|
|
+ selectCon.layoutItems.componentItem[0].layoutItems.componentItem[1].layoutItems.componentItem[2] = { ...jumpGh104 }
|
|
|
+ } else if (value === 'enterprise_wx_auto') {
|
|
|
+ if (jumpMode === "total_jump") {
|
|
|
+ selectCon.layoutItems.componentItem[1] = { ...btModelJumpWxAuto }
|
|
|
+ }
|
|
|
+ selectCon.layoutItems.componentItem[0].layoutItems.componentItem[1].layoutItems.componentItem[2] = { ...jumpWxAuto104 }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }, [content, goodsCount])
|
|
|
+ // 配置图文跳转链接按钮字段
|
|
|
+ const onSetShelfnewButtonField = useCallback((field: string, value: string) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ if (selectCon?.type === '103') {
|
|
|
+ let jumpMode = selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].jumpMode
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].layoutItems.componentItem[3][field] = value
|
|
|
+ if (field === 'btnBorderColorTheme') {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[0].layoutItems.componentItem[3]['borderSize'] = "2"
|
|
|
+ }
|
|
|
+ if (jumpMode === 'total_jump' && (field === 'subType' || field === 'btnFontType')) {
|
|
|
+ selectCon.layoutItems.componentItem[goodsCount].layoutItems.componentItem[1][field] = value
|
|
|
+ }
|
|
|
+ } else if (selectCon?.type === '104') {
|
|
|
+ let jumpMode = selectCon.layoutItems.componentItem[0].jumpMode
|
|
|
+ selectCon.layoutItems.componentItem[0].layoutItems.componentItem[1].layoutItems.componentItem[2][field] = value
|
|
|
+ if (field === 'btnBorderColorTheme') {
|
|
|
+ selectCon.layoutItems.componentItem[0].layoutItems.componentItem[1].layoutItems.componentItem[2]['borderSize'] = "2"
|
|
|
+ }
|
|
|
+ if (jumpMode === 'total_jump' && (field === 'subType' || field === 'btnFontType')) {
|
|
|
+ selectCon.layoutItems.componentItem[1][field] = value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }, [content, goodsCount])
|
|
|
+
|
|
|
+ // 设置图文复合组件类型
|
|
|
+ const setShelfnewType = useCallback((value: string) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ if (value === '103') {
|
|
|
+ newContent[selectIndex] = { ...shelfnewContent2, comptActive: true }
|
|
|
+ } else if (value === '104') {
|
|
|
+ newContent[selectIndex] = { ...shelfnewContent, comptActive: true }
|
|
|
+ }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...newContent] } })
|
|
|
+ }
|
|
|
+ }, [content])
|
|
|
+
|
|
|
+ // 设置对齐方式
|
|
|
+ const setAilgin103 = useCallback((align: number) => {
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = newContent[selectIndex]
|
|
|
+ selectCon.wxad_align = align
|
|
|
+ let componentItem = selectCon?.layoutItems?.componentItem?.map((item: any) => {
|
|
|
+ let shelfnewItem = item?.layoutItems?.componentItem[0]?.layoutItems?.componentItem
|
|
|
+ if (align === 0) {
|
|
|
+ shelfnewItem = shelfnewItem?.map((oldItem: any, index: number) => {
|
|
|
+ if (index === 0) {
|
|
|
+ return oldItem
|
|
|
+ } else if (index === 1 || index === 2) {
|
|
|
+ let { textAlignment, ...newItem } = oldItem
|
|
|
+ return newItem
|
|
|
+ } else {
|
|
|
+ let { horizontalAlignment, ...newItem } = oldItem
|
|
|
+ return newItem
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ shelfnewItem = shelfnewItem?.map((newItem: any, index: number) => {
|
|
|
+ if (index === 0) {
|
|
|
+ return newItem
|
|
|
+ } else if (index === 1 || index === 2) {
|
|
|
+ return { ...newItem, textAlignment: "1" }
|
|
|
+ } else {
|
|
|
+ return { ...newItem, horizontalAlignment: "1" }
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+ }
|
|
|
+ item.layoutItems.componentItem[0].layoutItems.componentItem = shelfnewItem
|
|
|
+ return item
|
|
|
+ })
|
|
|
+ selectCon.layoutItems.componentItem = componentItem
|
|
|
+ newContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...newContent] } })
|
|
|
+ }
|
|
|
+ }, [content])
|
|
|
+
|
|
|
+ // 设置悬浮弹窗
|
|
|
+ const setGlobalComponentItem = (key: string, value: any, isDel = false) => {
|
|
|
+ let newConItem = JSON.parse(JSON.stringify(componentItem))
|
|
|
+ let selectIndex = newConItem?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newConItem
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ // 设置悬浮窗 转化按钮
|
|
|
+ if (key === 'componentItem' && (value === 'gh' || value === 'enterprise_wx_auto')) {
|
|
|
+ if (value === 'gh') {
|
|
|
+ selectCon[key] = floatbuttonBtTypeGh
|
|
|
+ } else if (value === 'enterprise_wx_auto') {
|
|
|
+ selectCon[key] = floatbuttonBtTypeWxAuto
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (!isDel) {
|
|
|
+ selectCon[key] = value
|
|
|
+ if (key === 'wxad_styleType') {
|
|
|
+ if (value === '1') {
|
|
|
+ selectCon['iconUrl'] = ""
|
|
|
+ selectCon['desc'] = selectCon?.desc || ""
|
|
|
+ } else if (value === '2') {
|
|
|
+ delete selectCon['iconUrl']
|
|
|
+ selectCon['desc'] = selectCon?.desc || ""
|
|
|
+ } else if (value === '3') {
|
|
|
+ delete selectCon['iconUrl']
|
|
|
+ delete selectCon['desc']
|
|
|
+ }
|
|
|
+ selectCon[key] = value
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ delete selectCon[key]
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ dispatchGlobal({ type: 'setConItem', params: { componentItem: JSON.parse(JSON.stringify(oldContent)) } })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 选中设置
|
|
|
+ const rightCon = () => {
|
|
|
+ let selectCon = content?.find((item: Content) => item.comptActive)
|
|
|
+ if (!selectCon) {
|
|
|
+ selectCon = componentItem?.find((item: { comptActive: boolean }) => item.comptActive)
|
|
|
+ }
|
|
|
+ if (selectCon) {
|
|
|
+ let { elementType, adLocation, outerStyle, imageUrlList, pureImageUrl, imageUrl, text, fontColor, fontSize, fontStyle, textAlignment,
|
|
|
+ paddingTop, paddingBottom, fastFollow, btnTitle, btnFontType, btnBorderColorTheme, btnBgColorTheme, useIcon,
|
|
|
+ styleType, type, initHeight, outerUseTopMaterial, componentCount, activeIndex, componentGroupList, origBtnJumpUrl,
|
|
|
+ layoutItems, borderColor, bgColor, wxad_align, wxad_styleType, iconUrl, title, desc, titleColor, descColor, componentItem, appearPaddingTop, appearPaddingBottom } = selectCon
|
|
|
+ let descType = "text"
|
|
|
+ let jumpMode = "btn_jump"
|
|
|
+ let shelfnewImgData: { pureImageUrl: string } = { pureImageUrl: '' } // 图片信息
|
|
|
+ let shelfnewTitleData: { content: string, fontColor: string } = { content: "", fontColor: "#353535" } // 标题信息
|
|
|
+ let shelfnewDescData: { name: string, content: string, fontColor: string } = { name: '', content: "", fontColor: "#B2B2B2" } // 描述信息
|
|
|
+ let shelfnewBtData: {
|
|
|
+ widgetTypeV2: string, btnTitle: string, btnBgColorTheme: string,
|
|
|
+ subType: '17' | '1', btnFontType: '0' | '1',
|
|
|
+ btnBorderColorTheme: string, fontColor: string, origBtnJumpUrl: string,
|
|
|
+ custorData: any[]
|
|
|
+ } = { widgetTypeV2: '', btnFontType: '0', subType: '17', btnTitle: "", btnBgColorTheme: "#07C160", btnBorderColorTheme: "#FFFFFF", fontColor: "#FFFFFF", origBtnJumpUrl: "", custorData: [] }
|
|
|
+
|
|
|
+ let custorGroup = []
|
|
|
+ if (elementType === 'enterprise_wx_auto') {
|
|
|
+ custorGroup = selectCon?.custorData || []
|
|
|
+ } else if (elementType === 'shelfnew') {
|
|
|
+ if (type === '104') { // 图文复合组件 单个
|
|
|
+ let shelfnewData = layoutItems?.componentItem[0]?.layoutItems?.componentItem
|
|
|
+ jumpMode = layoutItems?.componentItem[0]?.jumpMode
|
|
|
+ descType = shelfnewData[1]?.descType
|
|
|
+ shelfnewImgData = shelfnewData[0]
|
|
|
+ shelfnewTitleData = shelfnewData[1]?.layoutItems?.componentItem[0]
|
|
|
+ shelfnewDescData = shelfnewData[1]?.layoutItems?.componentItem[1]
|
|
|
+ shelfnewBtData = shelfnewData[1]?.layoutItems?.componentItem[2]
|
|
|
+ } else if (type === '103') {
|
|
|
+ // goodsCount
|
|
|
+ let componentItems = layoutItems.componentItem
|
|
|
+ let componentItem = componentItems[goodsCount]
|
|
|
+ borderColor = componentItem?.borderColor || "#e5e5e5"
|
|
|
+ bgColor = componentItem?.bgColor || "#ffffff"
|
|
|
+ jumpMode = componentItem?.layoutItems?.componentItem[0]?.jumpMode
|
|
|
+ let shelfnewItem = componentItem?.layoutItems?.componentItem[0]?.layoutItems?.componentItem
|
|
|
+ descType = componentItem?.layoutItems?.componentItem[0]?.descType
|
|
|
+ shelfnewImgData = shelfnewItem[0]
|
|
|
+ shelfnewTitleData = shelfnewItem[1]
|
|
|
+ shelfnewDescData = shelfnewItem[2]
|
|
|
+ shelfnewBtData = shelfnewItem[3]
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return <>
|
|
|
+ {
|
|
|
+ elementType === 'TOP_IMAGE' ? <div className="widget">
|
|
|
+ <div className="caption section">
|
|
|
+ <div className="caption-title">顶部组件:图片</div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">广告位与样式</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">广告位</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { setCon('adLocation', e.target.value, true) }} value={adLocation} size='small'>
|
|
|
+ <Radio value='sns'>朋友圈信息流</Radio>
|
|
|
+ <Radio value='gh'>公众号及其他</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {adLocation === 'sns' && <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">外层样式</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Select value={outerStyle} style={{ width: 100 }} onChange={(e) => { setCon('outerStyle', e, true) }}>
|
|
|
+ <Option value={0}>常规广告</Option>
|
|
|
+ <Option value={1}>卡片广告</Option>
|
|
|
+ </Select>
|
|
|
+ </div>
|
|
|
+ </div>}
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">素材设置</div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'flex-start' }}>
|
|
|
+ <div className="adui-form-label">图片素材</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className={`upload-img-item ${imageUrl ? 'upload-img-item_uploaded' : ''}`}>
|
|
|
+ {imageUrl ? <div className="upload-img-item-inner" style={{ backgroundImage: `url(${imageUrl})` }}>
|
|
|
+ <div className='upload-img-item-action' onClick={() => { clickUpdateImg(1) }}>
|
|
|
+ <RetweetOutlined />
|
|
|
+ </div>
|
|
|
+ </div> : <div className="upload-img-item-inner" onClick={() => { clickUpdateImg(1) }}>
|
|
|
+ <PlusOutlined />
|
|
|
+ </div>}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ elementType === 'TOP_SLIDER' ? <div className="widget">
|
|
|
+ <div className="caption section">
|
|
|
+ <div className="caption-title">顶部组件:轮播图</div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">素材设置</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">图片数量</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { sliderImgNum(e.target.value) }} value={imageUrlList?.length || 3} size='small'>
|
|
|
+ <Radio.Button value={3}>3张</Radio.Button>
|
|
|
+ <Radio.Button value={4}>4张</Radio.Button>
|
|
|
+ <Radio.Button value={6}>6张</Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">上传素材</div>
|
|
|
+ <SortableUlList axis='xy' onSortEnd={onSortEndSlider} useDragHandle>
|
|
|
+ {imageUrlList?.map((item: any, index: number) => {
|
|
|
+ if (item) {
|
|
|
+ return <SortableItemLi key={`slider-${index}`} index={index} isActive={activeIndex === index} pureImageUrl={item} click={() => { sliderSelect(index, imageUrlList.length) }} setActiveIndex={() => { setCon('activeIndex', index) }}></SortableItemLi>
|
|
|
+ } else {
|
|
|
+ return <SortableItemNoLi key={`slider-${index}`} index={index} isActive={activeIndex === index} click={() => { sliderSelect(index, imageUrlList.length) }}></SortableItemNoLi>
|
|
|
+ }
|
|
|
+ })}
|
|
|
+ </SortableUlList>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ elementType === 'TOP_VIDEO' ? <div className="widget">
|
|
|
+ <div className="caption section">
|
|
|
+ <div className="caption-title">顶部组件:视频</div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">广告位与样式</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">广告位</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { changeAdLocation(e.target.value) }} value={adLocation} size='small'>
|
|
|
+ <Radio value='sns'>朋友圈信息流</Radio>
|
|
|
+ <Radio value='gh'>公众号及其他</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {adLocation === 'sns' && <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">外层样式</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Select size="small" value={outerStyle} style={{ width: 100 }} onChange={(e) => { changeOuterLayout(e) }}>
|
|
|
+ <Option value={0}>常规广告</Option>
|
|
|
+ <Option value={1} disabled>卡片广告</Option>
|
|
|
+ </Select>
|
|
|
+ </div>
|
|
|
+ </div>}
|
|
|
+ {/* {
|
|
|
+ adLocation === 'sns' && outerStyle === 0 && <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">视频类型</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { viewTypeChange(e.target.value, 1) }} value={styleType} size='small'>
|
|
|
+ <Radio value='0'>横板视频</Radio>
|
|
|
+ <Radio value='1'>竖版视频</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ {
|
|
|
+ adLocation === 'sns' && outerStyle === 1 && <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">外层素材</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Checkbox onChange={(e: CheckboxChangeEvent) => { outerUseTopMaterialHandle(e.target.checked) }} checked={outerUseTopMaterial === '0' ? false : true}>顶部素材不用于广告外层</Checkbox>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ } */}
|
|
|
+ {/* {
|
|
|
+ outerUseTopMaterial === '1' && <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">视频类型</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { viewTypeChange(e.target.value, 2) }} value={type} size='small'>
|
|
|
+ <Radio value='61'>短视频</Radio>
|
|
|
+ <Radio value='62'>长视频</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ } */}
|
|
|
+ {/* {
|
|
|
+ adLocation === 'gh' && <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">视频类型</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { viewTypeChange(e.target.value, 2) }} value={type} size='small'>
|
|
|
+ <Radio value='61'>短视频</Radio>
|
|
|
+ <Radio value='62'>长视频</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ } */}
|
|
|
+ {adLocation === 'sns' && styleType === '1' && <div className="adui-form-item" style={{ alignItems: 'flex-start' }}>
|
|
|
+ <div className="adui-form-label" style={{ marginTop: 2 }}>视频尺寸</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group value={initHeight} onChange={(e) => { setCon('initHeight', e.target.value) }}>
|
|
|
+ <Radio value={1536}>750像素 x 1536像素</Radio>
|
|
|
+ <Radio value={1334}>750像素 x 1334像素</Radio>
|
|
|
+ <Radio value={1280}>720像素 x 1280像素</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ elementType === 'TEXT' ? <div className="widget">
|
|
|
+ <div className="caption section">
|
|
|
+ <div className="caption-title">文本</div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">推广文案</div>
|
|
|
+ <TextArea
|
|
|
+ placeholder="请输入"
|
|
|
+ autoSize={{ minRows: 4, maxRows: 6 }}
|
|
|
+ value={text}
|
|
|
+ onChange={(e) => { setCon('text', e.target.value) }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">字符与段落</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">字符样式</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className="fl-sb">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center' }}>
|
|
|
+ <Space>
|
|
|
+ <Select value={fontSize} style={{ width: 60 }} onChange={(e) => { setCon('fontSize', e) }}>
|
|
|
+ {[14, 15, 16, 18, 20, 24, 36].map((item: number) => (<Option value={item} key={item}>{item}</Option>))}
|
|
|
+ </Select>
|
|
|
+ <ColorPicker onColor={(color: string) => { setCon('fontColor', color) }} color={fontColor}></ColorPicker>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ <Radio.Group onChange={(e) => { setCon('fontStyle', e.target.value) }} value={fontStyle}>
|
|
|
+ <Radio.Button value={0}>常规</Radio.Button>
|
|
|
+ <Radio.Button value={1}>加粗</Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">对齐方式</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { setCon('textAlignment', e.target.value) }} value={textAlignment}>
|
|
|
+ <Radio.Button value={0}><AlignLeftOutlined /></Radio.Button>
|
|
|
+ <Radio.Button value={1}><AlignCenterOutlined /></Radio.Button>
|
|
|
+ <Radio.Button value={2}><AlignRightOutlined /></Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">边距</div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">上边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">下边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ elementType === 'IMAGE' ? <div className="widget">
|
|
|
+ <div className="caption section">
|
|
|
+ <div className="caption-title">图片</div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">素材设置</div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'flex-start' }}>
|
|
|
+ <div className="adui-form-label">图片素材</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className={`upload-img-item ${imageUrl ? 'upload-img-item_uploaded' : ''}`}>
|
|
|
+ {
|
|
|
+ imageUrl ? <div className="upload-img-item-inner" style={{ backgroundImage: `url(${imageUrl ? imageUrl : ""})` }}>
|
|
|
+ <div className='upload-img-item-action' onClick={() => { clickUpdateImg(1) }}>
|
|
|
+ <RetweetOutlined />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ <div className="upload-img-item-inner" onClick={() => { clickUpdateImg(1) }}>
|
|
|
+ <PlusOutlined />
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">边距</div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">上边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">下边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ elementType === 'GH' ? <div className="widget">
|
|
|
+ <div className="caption section">
|
|
|
+ <div className="caption-title">关注公众号</div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <Space>
|
|
|
+ <Switch size="small" checked={fastFollow === 1 ? true : false} onChange={(e) => { setCon('fastFollow', e ? 1 : 0) }} />
|
|
|
+ 一键关注
|
|
|
+ <Tooltip placement="top" title={'唤起公众号简介的半屏面板,点击其中按钮直接关注公众号'}>
|
|
|
+ <QuestionCircleOutlined />
|
|
|
+ </Tooltip>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">按钮外观</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">按钮文案</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className="fl-sb">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center' }}>
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', border: '1px solid #d9d9d9', borderRadius: 2, paddingRight: 8 }}>
|
|
|
+ <Input maxLength={useIcon === 1 ? 8 : 10} style={{ width: 90 }} bordered={false} value={btnTitle} onChange={(e) => { setCon('btnTitle', e.target.value) }} /> <span>{btnTitle?.length}/{useIcon === 1 ? 8 : 10}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Radio.Group onChange={(e) => { setCon('btnFontType', e.target.value) }} value={btnFontType}>
|
|
|
+ <Radio.Button value={0}>常规</Radio.Button>
|
|
|
+ <Radio.Button value={1}>加粗</Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">字体色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('fontColor', color) }} color={fontColor}></ColorPicker><div className="colorShow">{fontColor}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">图标</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Switch size="small" checked={useIcon === 1 ? true : false} onChange={(e) => { iconHandle(e) }} /> <span>{useIcon === 1 ? '已启用' : '未启用'}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">边框色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('btnBorderColorTheme', color) }} color={btnBorderColorTheme}></ColorPicker><div className="colorShow">{btnBorderColorTheme}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">背景色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('btnBgColorTheme', color) }} color={btnBgColorTheme}></ColorPicker><div className="colorShow">{btnBgColorTheme}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">边距</div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">上边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">下边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div> :
|
|
|
+ elementType === 'ENTERPRISE_WX' ? <div className="widget">
|
|
|
+ <div className="caption section">
|
|
|
+ <div className="caption-title">添加商家微信</div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">按钮外观</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">按钮文案</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className="fl-sb">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center' }}>
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', border: '1px solid #d9d9d9', borderRadius: 2, paddingRight: 8 }}>
|
|
|
+ <Input maxLength={useIcon === 1 ? 8 : 10} style={{ width: 90 }} bordered={false} value={btnTitle} onChange={(e) => { setCon('btnTitle', e.target.value) }} /> <span>{btnTitle?.length}/{useIcon === 1 ? 8 : 10}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Radio.Group onChange={(e) => { setCon('btnFontType', e.target.value) }} value={btnFontType}>
|
|
|
+ <Radio.Button value={0}>常规</Radio.Button>
|
|
|
+ <Radio.Button value={1}>加粗</Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">字体色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('fontColor', color) }} color={fontColor}></ColorPicker> <div className="colorShow">{fontColor}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">图标</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Switch size="small" checked={useIcon === 1 ? true : false} onChange={(e) => { iconHandle(e) }} /> <span>{useIcon === 1 ? '已启用' : '未启用'}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">边框色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('btnBorderColorTheme', color) }} color={btnBorderColorTheme}></ColorPicker> <div className="colorShow">{btnBorderColorTheme}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">背景色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('btnBgColorTheme', color) }} color={btnBgColorTheme}></ColorPicker> <div className="colorShow">{btnBgColorTheme}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">边距</div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">上边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">下边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ elementType === 'link' ? <div className="widget">
|
|
|
+ {/* <div className="caption section">
|
|
|
+ <div className="caption-title">跳转链接</div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">链接设置</div>
|
|
|
+ <Input placeholder="以 http:// 或 https:// 开头" value={origBtnJumpUrl} onChange={(e) => { setCon('origBtnJumpUrl', e.target.value) }} />
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">按钮外观</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">按钮文案</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className="fl-sb">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center' }}>
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', border: '1px solid #d9d9d9', borderRadius: 2, paddingRight: 8 }}>
|
|
|
+ <Input maxLength={10} style={{ width: 90 }} bordered={false} value={btnTitle} onChange={(e) => { setCon('btnTitle', e.target.value) }} /> <span>{btnTitle?.length}/10</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Radio.Group onChange={(e) => { setCon('btnFontType', e.target.value) }} value={btnFontType}>
|
|
|
+ <Radio.Button value="0">常规</Radio.Button>
|
|
|
+ <Radio.Button value="1">加粗</Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">字体色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('fontColor', color) }} color={fontColor}></ColorPicker><div className="colorShow">{fontColor}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">图标</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Switch size="small" checked={useIcon === '1' ? true : false} onChange={(e) => { iconHandle(e) }} /> <span>{useIcon === '1' ? '已启用' : '未启用'}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">边框色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('btnBorderColorTheme', color) }} color={btnBorderColorTheme}></ColorPicker><div className="colorShow">{btnBorderColorTheme}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">背景色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('btnBgColorTheme', color) }} color={btnBgColorTheme}></ColorPicker><div className="colorShow">{btnBgColorTheme}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">边距</div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">上边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">下边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div> */}
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ elementType === 'shelfnew' ? <div className="widget">
|
|
|
+ {/* {imgTextButtonShow ? <>
|
|
|
+ <div className="caption section goBack" onClick={() => { setImgTextButtonShow(false) }}>
|
|
|
+ <SwapLeftOutlined />
|
|
|
+ <span>返回</span>
|
|
|
+ </div>
|
|
|
+ {shelfnewBtData.widgetTypeV2 === 'gh' || shelfnewBtData.widgetTypeV2 === 'link' || shelfnewBtData.widgetTypeV2 === 'enterprise_wx_auto' ? <>
|
|
|
+
|
|
|
+ {shelfnewBtData.widgetTypeV2 === 'link' ? <div className="form section">
|
|
|
+ <div className="form-caption">链接设置</div>
|
|
|
+ <Input placeholder="以 http:// 或 https:// 开头" value={shelfnewBtData?.origBtnJumpUrl} onChange={(e) => { onSetShelfnewButtonField('origBtnJumpUrl', e.target.value) }} />
|
|
|
+ </div> : shelfnewBtData.widgetTypeV2 === 'gh' ? <div className="form section">
|
|
|
+ <Space>
|
|
|
+ <Switch size="small" checked={shelfnewBtData?.subType === '17' ? true : false} onChange={(e) => { onSetShelfnewButtonField('subType', e ? '17' : '1') }} />
|
|
|
+ 一键关注
|
|
|
+ <Tooltip placement="top" title={'唤起公众号简介的半屏面板,点击其中按钮直接关注公众号'}>
|
|
|
+ <QuestionCircleOutlined />
|
|
|
+ </Tooltip>
|
|
|
+ </Space>
|
|
|
+ </div> : <div className="form section">
|
|
|
+ <div className="form-caption">客服设置</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">客服分配</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className="fl-sb">
|
|
|
+ <Button size="small" onClick={clickCustorGroup}>{shelfnewBtData?.custorData?.length > 0 ? '修改客服组' : '选择客服组'}</Button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {shelfnewBtData?.custorData?.length > 0 && <div className='adui-form-item custorGroup'>
|
|
|
+ {shelfnewBtData?.custorData?.map((item: { label: string, custorData: any[], id: number }) => <div key={item.id}>
|
|
|
+ <strong>{item.label}:</strong><span>{item.custorData[0]?.name}</span>
|
|
|
+ </div>)}
|
|
|
+ </div>}
|
|
|
+ </div>}
|
|
|
+
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">按钮外观</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">按钮文案</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className="fl-sb">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center' }}>
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', border: '1px solid #d9d9d9', borderRadius: 2, paddingRight: 8 }}>
|
|
|
+ <Input maxLength={5} style={{ width: 90 }} bordered={false} value={shelfnewBtData?.btnTitle} onChange={(e) => { onSetShelfnewButtonField('btnTitle', e.target.value) }} /> <span>{shelfnewBtData?.btnTitle?.length}/5</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Radio.Group onChange={(e) => { onSetShelfnewButtonField('btnFontType', e.target.value) }} value={shelfnewBtData?.btnFontType}>
|
|
|
+ <Radio.Button value="0">常规</Radio.Button>
|
|
|
+ <Radio.Button value="1">加粗</Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">字体色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { onSetShelfnewButtonField('fontColor', color) }} color={shelfnewBtData?.fontColor}></ColorPicker><div className="colorShow">{shelfnewBtData?.fontColor}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">边框色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { onSetShelfnewButtonField('btnBorderColorTheme', color) }} color={shelfnewBtData?.btnBorderColorTheme}></ColorPicker><div className="colorShow">{shelfnewBtData?.btnBorderColorTheme}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">背景色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { onSetShelfnewButtonField('btnBgColorTheme', color) }} color={shelfnewBtData?.btnBgColorTheme}></ColorPicker><div className="colorShow">{shelfnewBtData?.btnBgColorTheme}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </> : <></>}
|
|
|
+ </> : <>
|
|
|
+ <div className="caption section">
|
|
|
+ <div className="caption-title">图文复合组件</div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">类型</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <>
|
|
|
+ <Radio.Group onChange={(e) => { setShelfnewType(e.target.value) }} value={type}>
|
|
|
+ <Radio value='104'>一行1个</Radio>
|
|
|
+ <Radio value='103'>一行2个</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ {type === '103' && <Radio.Group onChange={(e) => { setGoodsCount(e.target.value) }} value={goodsCount} size='small' style={{ marginTop: 10 }}>
|
|
|
+ <Radio.Button value={0}>商品1</Radio.Button>
|
|
|
+ <Radio.Button value={1}>商品2</Radio.Button>
|
|
|
+ </Radio.Group>}
|
|
|
+ </>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="form section">
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">配图</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div>
|
|
|
+ <Button onClick={() => { setCcType(4); setSelectImgVisible(true); setNum(1) }}>上传图片</Button>
|
|
|
+ <div style={{ marginTop: 4, fontSize: 12, color: '#636363' }}>{type === '103' ? '尺寸:480像素*480像素' : '尺寸:360像素*360像素'}</div>
|
|
|
+ <div style={{ marginTop: 4, fontSize: 12, color: '#636363' }}>格式:不超过300k</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'flex-start' }}>
|
|
|
+ <div className="adui-form-label" style={{ marginTop: 6 }}>标题</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Input.TextArea placeholder="请输入标题" onChange={(e) => { onShelfnewTxtCon(e.target.value?.replace(/\r|\n/ig, ""), 0, 'content') }} value={shelfnewTitleData?.content} showCount maxLength={type === '104' ? 12 : 8} autoSize />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">描述</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space direction="vertical" style={{ width: '100%' }}>
|
|
|
+ <Radio.Group onChange={onSetShelfnewDescType} value={descType}>
|
|
|
+ <Radio value="text">文字</Radio>
|
|
|
+ <Radio value="price">价格</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ {descType === 'text' ?
|
|
|
+ <Input.TextArea placeholder="请输入描述" onChange={(e) => { onShelfnewTxtCon(e.target.value?.replace(/\r|\n/ig, ""), 1, 'content') }} value={shelfnewDescData?.content} showCount maxLength={type === '104' ? 15 : 10} autoSize={{ minRows: 2, maxRows: 2 }} /> :
|
|
|
+ <div>
|
|
|
+ <Input placeholder="请输入" suffix="元" onChange={(e) => { onShelfnewTxtCon(e.target.value, 1, 'content') }} style={{ width: 150 }} value={shelfnewDescData?.content?.split('¥')[1]} />
|
|
|
+ <div style={{ fontSize: 12, color: '#636363', marginTop: 5 }}>价格范围0.01~999,999,999.99元</div>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {type === '103' && <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">对齐</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { setAilgin103(e.target.value) }} value={wxad_align}>
|
|
|
+ <Radio value={0}>左对齐</Radio>
|
|
|
+ <Radio value={1}>居中对齐</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>}
|
|
|
+
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'flex-start' }}>
|
|
|
+ <div className="adui-form-label" style={{ marginTop: 14 }}>字体颜色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space style={{ width: '100%' }} size="large" className="shelfnewColor">
|
|
|
+ <div>
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { onShelfnewTxtCon(color, 0, 'fontColor') }} color={shelfnewTitleData?.fontColor}></ColorPicker> <div className="colorShow">{shelfnewTitleData?.fontColor}</div></Space>
|
|
|
+ <div className="colorName">标题</div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { onShelfnewTxtCon(color, 1, 'fontColor') }} color={shelfnewDescData?.fontColor}></ColorPicker> <div className="colorShow">{shelfnewDescData?.fontColor}</div></Space>
|
|
|
+ <div className="colorName">{shelfnewDescData?.name}</div>
|
|
|
+ </div>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'flex-start' }}>
|
|
|
+ <div className="adui-form-label" style={{ marginTop: 14 }}>其它颜色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space style={{ width: '100%' }} size="large" className="shelfnewColor">
|
|
|
+ <div>
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('borderColor', color) }} color={borderColor}></ColorPicker> <div className="colorShow">{borderColor}</div></Space>
|
|
|
+ <div className="colorName">边框</div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setCon('bgColor', color) }} color={bgColor}></ColorPicker> <div className="colorShow">{bgColor}</div></Space>
|
|
|
+ <div className="colorName">背景</div>
|
|
|
+ </div>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">边距</div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">上边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingTop} onChange={(value: number) => { setCon('paddingTop', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">下边距</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
|
+ <div style={{ flexGrow: 1 }}><Slider value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} /></div>
|
|
|
+ <InputNumber min={0} max={100} step={1} value={paddingBottom} onChange={(value: number) => { setCon('paddingBottom', value) }} style={{ width: 80, marginLeft: 20 }} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">按钮</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">跳转方式</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={onSetShelfnewJumpMode} value={jumpMode}>
|
|
|
+ <Radio value="btn_jump">按钮跳转</Radio>
|
|
|
+ <Radio value="total_jump">全局跳转</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">按钮类型</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space>
|
|
|
+ <Select style={{ width: 120 }} value={shelfnewBtData.widgetTypeV2} onChange={(e) => { onSetShelfnewButton(e) }}>
|
|
|
+ <Option value="link">跳转链接</Option>
|
|
|
+ <Option value="gh">关注公众号</Option>
|
|
|
+ <Option value="enterprise_wx_auto">添加商家微信</Option>
|
|
|
+ </Select>
|
|
|
+ <Button type="link" size="small" onClick={() => { setImgTextButtonShow(true) }}>配置</Button>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </>} */}
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ elementType === 'floatbutton' ? <div style={{ height: '100%' }}>
|
|
|
+ <div className={`widget ${imgTextButtonShow ? 'widget_back' : ''}`}>
|
|
|
+ <div className="caption section">
|
|
|
+ <div className="caption-title">悬浮按钮</div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">卡片设置</div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <div className="adui-form-label">转化按钮</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className='form-result-text'><span>{componentItem?.name}</span> <Button type="link" size='small' style={{ color: '#6b6b6b', fontSize: 12 }} onClick={() => { setImgTextButtonShow(true) }}>设置</Button> </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">卡片样式</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { setGlobalComponentItem('wxad_styleType', e.target.value) }} className="floatType" value={wxad_styleType}>
|
|
|
+ <Radio.Button value='1'>
|
|
|
+ <div className='floatTypeInner'>
|
|
|
+ <i className="floatTypeAvatar"></i>
|
|
|
+ <i className="floatTypeText_two"></i>
|
|
|
+ <i className="floatTypeButton"></i>
|
|
|
+ </div>
|
|
|
+ </Radio.Button>
|
|
|
+ <Radio.Button value='2'>
|
|
|
+ <div className='floatTypeInner'>
|
|
|
+ <i style={{ display: 'inline-block', height: 12 }}></i>
|
|
|
+ <i className="floatTypeText_two"></i>
|
|
|
+ <i className="floatTypeButton"></i>
|
|
|
+ </div>
|
|
|
+ </Radio.Button>
|
|
|
+ <Radio.Button value='3'>
|
|
|
+ <div className='floatTypeInner'>
|
|
|
+ <i style={{ display: 'inline-block', height: 12 }}></i>
|
|
|
+ <i className="floatTypeText_one"></i>
|
|
|
+ <i className="floatTypeButton"></i>
|
|
|
+ </div>
|
|
|
+ </Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">内容设置</div>
|
|
|
+ {wxad_styleType === '1' && <div className="adui-form-item" style={{ alignItems: 'flex-start' }}>
|
|
|
+ <div className="adui-form-label">图片</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className={`upload-img-item ${iconUrl ? 'upload-img-item_uploaded' : ''}`}>
|
|
|
+ {
|
|
|
+ iconUrl ? <div className="upload-img-item-inner" style={{ backgroundImage: `url(${iconUrl ? iconUrl : ""})` }}>
|
|
|
+ <div className='upload-img-item-action' onClick={() => { setCcType(5); setSelectImgVisible(true); }}>
|
|
|
+ <RetweetOutlined />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ <div className="upload-img-item-inner" onClick={() => { setCcType(5); setSelectImgVisible(true); }}>
|
|
|
+ <PlusOutlined />
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ <div style={{ marginTop: 4, fontSize: 12, color: '#A3A3A3' }}>尺寸:96像素*96像素</div>
|
|
|
+ <div style={{ marginTop: 4, fontSize: 12, color: '#A3A3A3' }}>格式:不超过300k</div>
|
|
|
+ </div>
|
|
|
+ </div>}
|
|
|
+
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'flex-start', marginBottom: 10 }}>
|
|
|
+ <div className="adui-form-label" style={{ marginTop: 6 }}>标题</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Input.TextArea placeholder="请输入标题" onChange={(e) => { setGlobalComponentItem('title', e.target.value?.replace(/\r|\n/ig, "")) }} value={title} showCount maxLength={10} autoSize />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {(wxad_styleType === '1' || wxad_styleType === '2') && <div className="adui-form-item" style={{ alignItems: 'flex-start', marginBottom: 10 }}>
|
|
|
+ <div className="adui-form-label" style={{ marginTop: 6 }}>描述</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Input.TextArea placeholder="请输入描述" onChange={(e) => { setGlobalComponentItem('desc', e.target.value?.replace(/\r|\n/ig, "")) }} value={desc} showCount maxLength={14} autoSize />
|
|
|
+ </div>
|
|
|
+ </div>}
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center', marginBottom: 10 }}>
|
|
|
+ <div className="adui-form-label" style={{ marginTop: 6 }}>标题字色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setGlobalComponentItem('titleColor', color) }} color={titleColor}></ColorPicker> <div className="colorShow">{titleColor}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {(wxad_styleType === '1' || wxad_styleType === '2') && <div className="adui-form-item" style={{ alignItems: 'center', marginBottom: 10 }}>
|
|
|
+ <div className="adui-form-label" style={{ marginTop: 6 }}>描述字色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setGlobalComponentItem('descColor', color) }} color={descColor}></ColorPicker> <div className="colorShow">{descColor}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>}
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">更多设置</div>
|
|
|
+ <div className='adui-form-tip adui-form-tip_normal'>如果落地页只有一页,悬浮组件的更多设置必须为“进入页面时出现”、且“不消失”</div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">出现方式</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { setGlobalComponentItem('appearPaddingTop', e.target.value) }} value={Number(appearPaddingTop)}>
|
|
|
+ <Radio value={0}>进入页面时出现</Radio>
|
|
|
+ <Radio value={100}>滑动页面时出现</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item">
|
|
|
+ <div className="adui-form-label">消失方式</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Radio.Group onChange={(e) => { setGlobalComponentItem('appearPaddingBottom', e.target.value) }} value={Number(appearPaddingBottom)}>
|
|
|
+ <Radio value={0}>不消失</Radio>
|
|
|
+ <Radio value={80}>滑至页面底部时消失</Radio>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {/* 设置转化按钮 imgTextButtonShow */}
|
|
|
+ <div className='aside' style={{ transform: imgTextButtonShow ? 'translate3d(0px, 0px, 0px)' : 'translate3d(100%, 0px, 0px)', transition: 'all 0.3s cubic-bezier(0, 0, 0.2, 1) 0s' }}>
|
|
|
+ <div className='aside-nav'>
|
|
|
+ <Button type='link' icon={<SwapLeftOutlined />} onClick={() => { setImgTextButtonShow(false) }}>返回</Button>
|
|
|
+ </div>
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">按钮类型</div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center' }}>
|
|
|
+ <Select style={{ width: 180 }} className="aside-select" dropdownClassName="aside-select" onChange={(e) => { setGlobalComponentItem('componentItem', e) }} value={componentItem?.widgetTypeV2} size="small">
|
|
|
+ <Option value="gh"><FollowAcc />关注公众号</Option>
|
|
|
+ <Option value="enterprise_wx_auto"><WxAutoSvg />添加商家微信</Option>
|
|
|
+ </Select>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {componentItem?.widgetTypeV2 === 'gh' ? <>
|
|
|
+ <div className="form section">
|
|
|
+ <Space>
|
|
|
+ <Switch size="small" checked={componentItem?.subType === '17' ? true : false} onChange={(e) => { setGlobalComponentItem('componentItem', { ...componentItem, subType: e ? '17' : '1' }) }} />
|
|
|
+ 一键关注
|
|
|
+ <Tooltip placement="top" title={'唤起公众号简介的半屏面板,点击其中按钮直接关注公众号'}>
|
|
|
+ <QuestionCircleOutlined />
|
|
|
+ </Tooltip>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ </> : null}
|
|
|
+ <div className="form section">
|
|
|
+ <div className="form-caption">按钮外观</div>
|
|
|
+ <div className="adui-form-item" style={{ marginBottom: 10 }}>
|
|
|
+ <div className="adui-form-label">按钮文案</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <div className="fl-sb">
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center' }}>
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', border: '1px solid #d9d9d9', borderRadius: 2, paddingRight: 8 }}>
|
|
|
+ <Input maxLength={5} style={{ width: 90 }} bordered={false} value={componentItem?.btnTitle} onChange={(e) => { setGlobalComponentItem('componentItem', { ...componentItem, btnTitle: e.target.value }) }} /> <span>{componentItem?.btnTitle?.length}/5</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Radio.Group onChange={(e) => { setGlobalComponentItem('componentItem', { ...componentItem, btnFontType: e.target.value }) }} value={componentItem?.btnFontType}>
|
|
|
+ <Radio.Button value={0}>常规</Radio.Button>
|
|
|
+ <Radio.Button value={1}>加粗</Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center', marginBottom: 10 }}>
|
|
|
+ <div className="adui-form-label">字体色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setGlobalComponentItem('componentItem', { ...componentItem, fontColor: color }) }} color={componentItem?.fontColor}></ColorPicker><div className="colorShow">{componentItem?.fontColor}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="adui-form-item" style={{ alignItems: 'center', marginBottom: 10 }}>
|
|
|
+ <div className="adui-form-label">填充色</div>
|
|
|
+ <div className="adui-form-control">
|
|
|
+ <Space><ColorPicker onColor={(color: string) => { setGlobalComponentItem('componentItem', { ...componentItem, btnBgColorTheme: color }) }} color={componentItem?.btnBgColorTheme}></ColorPicker><div className="colorShow">{componentItem?.btnBgColorTheme}</div></Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div> :
|
|
|
+ null
|
|
|
+ }
|
|
|
+
|
|
|
+ </>
|
|
|
+ } else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /** 选择单张图片 */
|
|
|
+ const clickUpdateImg = useCallback((num: number) => {
|
|
|
+ setSliderImgContent([])
|
|
|
+ setCcType(1)
|
|
|
+ setSelectImgVisible(true)
|
|
|
+ }, [imgSize, scType, content, sliderImgContent])
|
|
|
+
|
|
|
+ /** 选择视频 */
|
|
|
+ const clickUpdateVideo = useCallback(() => {
|
|
|
+ setCcType(2)
|
|
|
+ setSelectImgVisible(true)
|
|
|
+ }, [imgSize, scType])
|
|
|
+
|
|
|
+ /** 弹窗返回设置图片 */
|
|
|
+ const setImg = useCallback((value: any[]) => {
|
|
|
+ setSelectImgVisible(false)
|
|
|
+ let newContent = JSON.parse(JSON.stringify(content))
|
|
|
+ let selectIndex = newContent?.findIndex((item: Content) => item.comptActive)
|
|
|
+ let oldContent = newContent
|
|
|
+ if (scType === 1) { // 图片
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ selectCon['imageUrl'] = value[0]?.url
|
|
|
+ selectCon['width'] = Number(value[0]?.width)
|
|
|
+ selectCon['height'] = Number(value[0]?.height)
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ } else if (scType === 2) { // 视频要判断是否是长视频 还是短视频
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ selectCon['width'] = value[0]?.width
|
|
|
+ selectCon['height'] = value[0]?.height
|
|
|
+ selectCon['videoUrl'] = value[0]?.url
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ } else if (scType === 3) { // 轮播
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let urlList = value?.map(item => item?.url)
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ selectCon.imageUrlList = selectCon.imageUrlList?.reduce((prev: any[], cur: any, index: number) => {
|
|
|
+ prev.push(urlList[index] || "")
|
|
|
+ return prev
|
|
|
+ }, [])
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ } else if (scType === 4) { // 设置图文复合组件图片
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ if (selectCon?.type === '104') {
|
|
|
+ let componentItem = selectCon?.layoutItems?.componentItem[0]?.layoutItems?.componentItem
|
|
|
+ componentItem[0] = {
|
|
|
+ ...componentItem[0],
|
|
|
+ pureImageUrl: value[0]?.content
|
|
|
+ }
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ } else if (selectCon?.type === '103') {
|
|
|
+ let componentItem = selectCon?.layoutItems.componentItem[goodsCount]
|
|
|
+ let shelfnewItem = componentItem?.layoutItems?.componentItem[0]?.layoutItems?.componentItem
|
|
|
+ shelfnewItem[0].pureImageUrl = value[0]?.content
|
|
|
+ oldContent[selectIndex] = { ...selectCon }
|
|
|
+ dispatch({ type: 'setCon', params: { content: [...oldContent] } })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (scType === 5) { // 设置悬浮组件
|
|
|
+ if (selectIndex !== -1) {
|
|
|
+ let selectCon = oldContent[selectIndex]
|
|
|
+ selectCon['iconUrl'] = value[0]?.content
|
|
|
+ dispatchGlobal({ type: 'setConItem', params: { componentItem: JSON.parse(JSON.stringify(oldContent)) } })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, [content, scType, goodsCount])
|
|
|
+ /** 回填数据 */
|
|
|
+ const editSelectImg = useCallback((url: any[]) => {
|
|
|
+ setSelectImgVisible(true)
|
|
|
+ }, [selectImgVisible])
|
|
|
+
|
|
|
+ /** 下一步 */
|
|
|
+ const nextHandle = useCallback(() => {
|
|
|
+ if (content.length === 1) {
|
|
|
+ message.error('请完善内容')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (((content[0]?.elementType === "TOP_IMAGE") && !content[0].imageUrl) || content[0]?.elementType === "empty") {
|
|
|
+ message.error('请完善顶部组件内容')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (content[0]?.elementType === "TOP_SLIDER" && !content[0].imageUrlList?.every((item: string) => item)) {
|
|
|
+ message.error('请完善轮播图组件内容~~')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (content[0]?.elementType === "TOP_VIDEO" && !content[0].videoUrl) {
|
|
|
+ message.error('请完善顶部视频组件内容~~')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ let reg = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/;
|
|
|
+ let a = content?.every((item: any) => {
|
|
|
+ if (item?.elementType === "GH") {
|
|
|
+ if (item?.btnTitle) {
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ message.error('关注公众号按钮按钮文案未填写')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ } else if (item?.elementType === "link") {
|
|
|
+ if (!reg.test(item?.origBtnJumpUrl)) {
|
|
|
+ message.error('跳转链接按钮请输入正确链接')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (item?.btnTitle) {
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ message.error('关注公众号按钮按钮文案未填写')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ } else if (item?.elementType === "IMAGE") {
|
|
|
+ if (item.imageUrl) {
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ message.error('请选择图片')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ } else if (item?.elementType === "TEXT") {
|
|
|
+ if (item.text) {
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ message.error('请完善文本内容')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ } else if (item?.elementType === "ENTERPRISE_WX") {
|
|
|
+ if (item?.btnTitle) {
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ message.error('客服组按钮按钮文案未填写')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ } else if (item?.elementType === "shelfnew") {
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ if (componentItem?.length > 0) {
|
|
|
+ let b = componentItem?.every((item: any) => {
|
|
|
+ if (item?.elementType === "floatbutton") {
|
|
|
+ if (item?.wxad_styleType === '1') {
|
|
|
+ if (!item?.iconUrl) {
|
|
|
+ message.error('悬浮组件请上传图片')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (!item?.title) {
|
|
|
+ message.error('悬浮组件请输入标题')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (!item?.desc) {
|
|
|
+ message.error('悬浮组件请输入描述')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ } else if (item?.wxad_styleType === '2') {
|
|
|
+ if (!item?.title) {
|
|
|
+ message.error('悬浮组件请输入标题')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (!item?.desc) {
|
|
|
+ message.error('悬浮组件请输入描述')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ } else if (item?.wxad_styleType === '3') {
|
|
|
+ if (!item?.title) {
|
|
|
+ message.error('悬浮组件请输入标题')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (item?.componentItem?.widgetTypeV2 === 'enterprise_wx_auto') {
|
|
|
+ if (item?.componentItem?.custorData && item?.componentItem?.custorData?.length > 0) {
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ message.error('请完善悬浮组件客服组内容')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ })
|
|
|
+ if (b) {
|
|
|
+
|
|
|
+ } else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (a) {
|
|
|
+ setLastVisible(true)
|
|
|
+ }
|
|
|
+
|
|
|
+ }, [lastVisible, state, componentItem])
|
|
|
+
|
|
|
+ /** 保存 */
|
|
|
+ const saveHandle = useCallback(() => {
|
|
|
+ let { content, pageBackColor } = state
|
|
|
+ if (!shareTittle || !shareDesc) {
|
|
|
+ message.error('请填写分享标题或者描述')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ let layoutName: string = pageName
|
|
|
+ if (!pageName) {
|
|
|
+ layoutName = `${id ? '复制' : ''}原生推广页` + moment().format("YYYYMMDDHHmmss") + '_' + currentUser?.userId
|
|
|
+ }
|
|
|
+
|
|
|
+ let pageContextList: Array<ImgProps | TopImg | TopVideo | TopSlider | Text | GhButton> = content?.map((item: { elementType: string, comptActive: boolean, activeIndex: boolean }) => {
|
|
|
+ let { elementType, comptActive, activeIndex, ...data } = item
|
|
|
+ let typeKey = getTypeKey(elementType)
|
|
|
+ let newItem = { elementType }
|
|
|
+ newItem[typeKey] = data
|
|
|
+ return newItem
|
|
|
+ })
|
|
|
+
|
|
|
+ let pageSpecs = {
|
|
|
+ bgColor: pageBackColor,
|
|
|
+ pageElementsSpecList: pageContextList
|
|
|
+ }
|
|
|
+
|
|
|
+ let params = {
|
|
|
+ mediaType: 'PAGE',
|
|
|
+ folder: false,
|
|
|
+ parentId, title:
|
|
|
+ layoutName,
|
|
|
+ pageName: layoutName,
|
|
|
+ belongUser: belongUser === '0' ? false : true,
|
|
|
+ sort,
|
|
|
+ pageSpecsList: [pageSpecs],
|
|
|
+ globalSpec: null,
|
|
|
+ shareContentSpec: {
|
|
|
+ shareTitle: shareTittle,
|
|
|
+ shareDescription: shareDesc
|
|
|
+ }
|
|
|
+ }
|
|
|
+ add.run(params).then(res => {
|
|
|
+ if (res) {
|
|
|
+ ajax.refresh()
|
|
|
+ hideModal && hideModal()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }, [state, shareTittle, pageName, parentId, sort, shareDesc, belongUser, currentUser, ajax, id, componentItem])
|
|
|
+
|
|
|
+ return <Drawer
|
|
|
+ title={
|
|
|
+ <div className={style.drawerTitle}>
|
|
|
+ <div>
|
|
|
+ <Space>
|
|
|
+ <span>{id ? '复制' : '创建'}推广页</span>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ <Button type='primary' size='small' className={style.next} onClick={() => { nextHandle() }}>下一步 <SwapRightOutlined /></Button>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ placement="right"
|
|
|
+ onClose={() => {
|
|
|
+ modal.confirm(config);
|
|
|
+ }}
|
|
|
+ visible={visible}
|
|
|
+ width='90%'
|
|
|
+ className={`addDraw ${style.drawer}`}
|
|
|
+ >
|
|
|
+ {/* 选择素材 */}
|
|
|
+ {selectImgVisible && <SelectCloud visible={selectImgVisible} sliderImgContent={sliderImgContent} onClose={() => setSelectImgVisible(false)} onChange={setImg} />}
|
|
|
+
|
|
|
+ <Modal
|
|
|
+ title={<>
|
|
|
+ <div style={{ marginBottom: 2, color: '#1f1f1f' }}>分享设置</div>
|
|
|
+ <div style={{ color: '#a3a3a3', fontSize: 12 }}>设置推广页的分享样式</div>
|
|
|
+ </>}
|
|
|
+ visible={lastVisible}
|
|
|
+ confirmLoading={add.loading}
|
|
|
+ onOk={saveHandle}
|
|
|
+ onCancel={() => { setLastVisible(false) }}
|
|
|
+ >
|
|
|
+ <Form labelCol={{ span: 4 }}>
|
|
|
+ <Form.Item label="落地页名称">
|
|
|
+ <Space><Input placeholder='落地页名称(不填写,创建时间+创建者ID)' value={pageName} onChange={(e) => { setPageName(e.target.value) }} style={txtLength(pageName) > 60 ? { width: 300, borderColor: 'red' } : { width: 300 }} /><span style={txtLength(pageName) > 60 ? { color: 'red' } : {}}>{txtLength(pageName)}/60</span></Space>
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item label="分享标题">
|
|
|
+ <Space><Input placeholder='建议与详情页面主题相符' value={shareTittle} onChange={(e) => { setShareTittle(e.target.value) }} style={txtLength(shareTittle) > 20 ? { width: 300, borderColor: 'red' } : { width: 300 }} /><span style={txtLength(shareTittle) > 20 ? { color: 'red' } : {}}>{txtLength(shareTittle)}/20</span></Space>
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item label="分享描述">
|
|
|
+ <Space><Input placeholder='对标题的简要解读' style={txtLength(shareDesc) > 30 ? { width: 300, borderColor: 'red' } : { width: 300 }} value={shareDesc} onChange={(e) => { setShareDesc(e.target.value) }} /><span style={txtLength(shareTittle) > 30 ? { color: 'red' } : {}}>{txtLength(shareDesc)}/30</span></Space>
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item label="排序" tooltip="值越大越靠前">
|
|
|
+ <InputNumber placeholder='输入排序' min={0} value={sort} onChange={(e) => { setSort(e) }} />
|
|
|
+ </Form.Item>
|
|
|
+ </Form>
|
|
|
+ </Modal>
|
|
|
+
|
|
|
+ <Spin spinning={get.loading}>
|
|
|
+ <div className={style.boxCont}>
|
|
|
+ <Row className={style.row}>
|
|
|
+ <Col flex="320px" className={style.right}>
|
|
|
+ <div className={style.title}>顶部组件</div>
|
|
|
+ <div className={style.assembly}>
|
|
|
+ {
|
|
|
+ content[0].elementType === 'empty' ? <>
|
|
|
+ <div {...getDragProps(`TOP_IMAGE`)}> <Topimg /> <span>图片</span> </div>
|
|
|
+ <div {...getDragProps(`TOP_SLIDER`)}> <Topslider /> <span>轮播图</span> </div>
|
|
|
+ <div {...getDragProps(`TOP_VIDEO`)}> <Topvideo /> <span>视频</span></div>
|
|
|
+ </>
|
|
|
+ :
|
|
|
+ <>
|
|
|
+ <div className={style.disabled}> <Topimg /> <span>图片</span> </div>
|
|
|
+ <div className={style.disabled}> <Topslider /> <span>轮播图</span> </div>
|
|
|
+ <div className={style.disabled}> <Topvideo /> <span>视频</span></div>
|
|
|
+ </>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className={style.title}>基础组件</div>
|
|
|
+ <div className={style.assembly}>
|
|
|
+ <div {...getDragPropsCon(`IMAGE`)}> <Img /> <span className="my">图片</span> </div>
|
|
|
+ <div {...getDragPropsCon(`TEXT`)}> <MyText /> <span>文字</span> </div>
|
|
|
+ </div>
|
|
|
+ <div className={style.title}>转化按钮</div>
|
|
|
+ <div className={style.assembly}>
|
|
|
+ <div {...getDragPropsCon(`GH`)}> <FollowAcc /> <span className="my">关注公众号</span> </div>
|
|
|
+ {/* <div {...getDragPropsCon(`JumpLink`)}> <JumpLink /> <span className="my">跳转链接</span> </div> */}
|
|
|
+ <div {...getDragPropsCon(`ENTERPRISE_WX`)}> <WxAutoSvg /> <span className="my">添加商家微信</span> </div>
|
|
|
+ </div>
|
|
|
+ {/* <div className={style.title}>营销组件</div>
|
|
|
+ <div className={style.assembly}>
|
|
|
+ <div {...getDragPropsCon(`shelfnew`)}> <ImgText /> <span className="my">图文复合组件</span> </div>
|
|
|
+ {componentItem?.some((item: { elementType: string }) => item.elementType === 'FLOAT_BUTTON') ?
|
|
|
+ <div className={style.disabled}> <FloatbuttonSvg /> <span>悬浮组件</span></div> : <div {...getDragPropsCon(`FLOAT_BUTTON`)}> <FloatbuttonSvg /> <span className="my">悬浮组件</span> </div>
|
|
|
+ }
|
|
|
+ </div> */}
|
|
|
+ </Col>
|
|
|
+ <Col flex="auto" className={style.center} onClick={installActiveNull}>
|
|
|
+
|
|
|
+ <div className={style.page} style={{ backgroundColor: pageBackColor || '#FFFFFF' }}>
|
|
|
+ {/* 头部 */}
|
|
|
+ <div>{topCon}</div>
|
|
|
+ {/* 内容*/}
|
|
|
+ <div className={`comptPlaceholder lastChild`} id="comptCon">
|
|
|
+ {comptCon()}
|
|
|
+ </div>
|
|
|
+ <div className={style.sidebar}>
|
|
|
+ <div>
|
|
|
+ <ColorPicker onColor={(color: string) => { dispatch({ type: 'setPageBackColor', params: { pageBackColor: color } }) }} color={pageBackColor}></ColorPicker>
|
|
|
+ <div style={{ marginTop: 4 }}>背景</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </Col>
|
|
|
+ <Col flex="380px" className={style.left}>{rightCon()}</Col>
|
|
|
+ </Row>
|
|
|
+ </div>
|
|
|
+ </Spin>
|
|
|
+ </Drawer>
|
|
|
+}
|
|
|
+export default React.memo(AddLandingPage)
|