diff --git a/src/assets/img.svg b/src/assets/img.svg
new file mode 100644
index 0000000..62a2fa5
--- /dev/null
+++ b/src/assets/img.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/src/components/Editor/index.jsx b/src/components/Editor/index.jsx
new file mode 100644
index 0000000..fbe1f45
--- /dev/null
+++ b/src/components/Editor/index.jsx
@@ -0,0 +1,174 @@
+import css from './index.module.scss'
+import {useEffect, useState} from "react";
+import svgImg from '@/assets/img.svg'
+import {getMD5} from "@/tools/index.js";
+import api from "@/request/api.js";
+import {defaultStore} from "@/store/index.js";
+
+
+export default function Editor(props) {
+ const [element, setElement] = useState({})
+ const [style, setStyle] = useState({})
+ const [href, setHref] = useState({url: '', state: 0,})
+ const [editState, setEditState] = useState(false)
+ const [inputValue, setInputValue] = useState('')
+ const [img, setImg] = useState(svgImg)
+ const [defaultImg, setDefaultImg] = useState('')
+
+ useEffect(() => {
+ // console.log('ELement', props.element)
+ setElement(props.element)
+ if (props.element.config && props.element.config.styleReal) {
+ const styleReal = props.element.config.styleReal
+ const styleTem = {
+ backgroundImage: styleReal.background
+ ?`url('/ossStatic/${styleReal.background
+ }')`:null,
+ backgroundColor: '#'+styleReal['background-color'],
+ position: styleReal.position,
+ width: styleReal.width + styleReal['width-mx'],
+ height: styleReal.height + styleReal['height-mx'],
+ backdropFilter: styleReal['backdrop-filter'],
+ top: styleReal.top + styleReal['top-mx'],
+ right: styleReal.right + styleReal['right-mx'],
+ bottom: styleReal.bottom + styleReal['bottom-mx'],
+ left: styleReal.left + styleReal['left-mx'],
+ margin: styleReal.margin,
+ padding: styleReal.padding,
+ borderRadius: styleReal['border-radius'] + styleReal['border-radius-mx'],
+ border: styleReal.border,
+ overflow: styleReal.overflow,
+ color: '#'+styleReal.color,
+ fontSize: styleReal['font-size'] + styleReal['font-size-mx'],
+ fontWeight: styleReal['font-weight'],
+ lineHeight: styleReal['line-height'] + styleReal['line-height-mx'],
+ textIndent: styleReal['text-indent'] + styleReal['text-indent-mx'],
+ textAlign: styleReal['text-align'],
+ whiteSpace: styleReal['white-space'],
+ }
+ if(styleReal['all-center']){
+ styleTem.display = 'flex';
+ styleTem['alignItems'] = 'center';
+ styleTem['justifyContent'] = 'center';
+ }
+ setStyle(styleTem)
+ setHref({
+ href: styleReal.href,
+ state: styleReal['href-mx']
+ })
+ if (props.element.inputValue) {
+ setInputValue(props.element.inputValue)
+ }
+ }
+
+ if(props.element.identify == 'image' && props.element.inputValue){
+ setImg('/ossStatic/' + props.element.inputValue)
+ }
+ }, [props.element])
+
+ useEffect(() => {
+ // console.log(style)
+ }, [style])
+
+ function hrefClick(e) {
+ e.stopPropagation();
+ if (!href.url) return;
+ if (href.url.length < 3) return
+ if (href.state == '0') {
+ window.location.href = href.url
+ } else {
+ window.open(href.url)
+ }
+ }
+
+ // 编辑完成
+ function handleEditInputValueOk() {
+ setEditState(false)
+ // console.log(inputValue.split('\n').join('
'))
+ setInputValue(inputValue.split('\n').join('
'))
+ defaultStore.setChooseNodeId(element.id)
+ defaultStore.setInputValue(inputValue.split('\n').join('
'))
+ }
+ // 图片上传
+ async function handleImgChange(e){
+ const file = e.target.files[0];
+ const md5 = await getMD5(file)
+ const data = {
+ md5,
+ file
+ }
+ const response = await api.putFile(data)
+ if(!response.data.state){
+ alert(response.data.data.message)
+ return
+ }
+ const url = response.data.data.filename
+ console.log(url)
+ setImg('/ossStatic/' + url)
+ defaultStore.setChooseNodeId(element.id)
+ defaultStore.setInputValue(url)
+ }
+
+ if(!props.element) return null
+
+ switch (element.identify) {
+ // 单元素结构
+ case 'singleFrame':
+ return
+ {
+ Array.isArray(props.element.childElement) ? props.element.childElement.map(item => {
+ {return }
+ }) :
+ }
+
+ break;
+ // 横向多元素结构
+ case 'transverseFrame':
+ return
+ {
+ Array.isArray(props.element.childElement) ? props.element.childElement.map(item => {
+ {return }
+ }) :
+ }
+
+ break;
+ // 纵向多元素结构
+ case 'longitudinalFrame':
+ return
+ {
+ Array.isArray(props.element.childElement) ? props.element.childElement.map(item => {
+ {return }
+ }) :
+ }
+
+ break;
+ // 行内文本
+ case 'span':
+ return
diff --git a/src/store/defaultStore.js b/src/store/defaultStore.js
index 55805e3..df87ea3 100644
--- a/src/store/defaultStore.js
+++ b/src/store/defaultStore.js
@@ -44,6 +44,9 @@ class DefaultStore {
styleRealRand = null;
styleReal = null;
styleTimeout = null;
+ // 输入内容
+ inputValue = null;
+
constructor() {
// mobx6 和以前版本这是最大的区别
@@ -59,6 +62,7 @@ class DefaultStore {
styleRealRand: observable,
styleReal: observable,
styleTimeout: observable,
+ inputValue:observable,
containerList: computed,
@@ -105,6 +109,10 @@ class DefaultStore {
setStyleTimeout(a){
this.styleTimeout = a
}
+ // 设置新内容
+ setInputValue(value) {
+ this.inputValue = value
+ }
// 获取内容列表
async getContainerList(menuId) {
diff --git a/src/tools/index.js b/src/tools/index.js
index e21d5fa..177ead7 100644
--- a/src/tools/index.js
+++ b/src/tools/index.js
@@ -1,80 +1,80 @@
import SparkMD5 from 'spark-md5'
// 从元素模板中获取指定元素
-export function getTargetElement(identify, AtomTemplate){
+export function getTargetElement(identify, AtomTemplate) {
let element = null;
- for(let i in AtomTemplate){
- if(AtomTemplate[i].identify == identify){
+ for (let i in AtomTemplate) {
+ if (AtomTemplate[i].identify == identify) {
element = AtomTemplate[i];
break
- }else if(Array.isArray(AtomTemplate[i].children)){
+ } else if (Array.isArray(AtomTemplate[i].children)) {
const s = getTargetElement(identify, AtomTemplate[i].children);
- if(s) element = s
+ if (s) element = s
}
}
return element
}
+
// 选择元素节点数的节点
-export function getTargetNode(id, node){
+export function getTargetNode(id, node) {
let targetNode = null
- if(Array.isArray(node)){
+ if (Array.isArray(node)) {
node.map((item, index) => {
- if(item.id == id){
+ if (item.id == id) {
targetNode = item
return item
- }else{
- if(item.childElement && item.childElement.length > 0){
+ } else {
+ if (item.childElement && item.childElement.length > 0) {
const s = getTargetNode(id, item.childElement)
- if(s) targetNode = s
+ if (s) targetNode = s
}
}
})
- }else{
- if(node.id == id){
+ } else {
+ if (node.id == id) {
return node
- }else{
- if(node.childElement.length > 0){
+ } else {
+ if (node.childElement.length > 0) {
const s = getTargetNode(id, node.childElement)
- if(s) targetNode = s
+ if (s) targetNode = s
}
}
}
return targetNode
}
+
// 删除元素节点数的节点
export function deleteTargetNode(id, node){
if(Array.isArray(node)){
- const newList = node.filter((item, index) => {
- if(item.id!=id)return true
- if(item.childElement && item.childElement.length > 0){
- const nodeSS = deleteTargetNode(id, item.childElement)
- if(nodeSS != null){
- item.childElement = nodeSS
- }
+ // 子元素
+ let deleteIndex = null;
+ for(let i in node){
+ if(node[i].id == id){
+ deleteIndex = i;
+ break;
}
- })
- if(newList.length != node){
- return newList
+ }
+ if(deleteIndex != null){
+ node = node.splice(deleteIndex, 1)
}else{
- return null
+ for(let i in node){
+ if(node[i].childElement && node[i].childElement.length > 0){
+ deleteTargetNode(id, node[i].childElement)
+ }
+ }
}
}else{
- if(node.id == id){
+ // 根节点
+ if(id == node.id){
alert('根节点无法删除')
return node
}else{
- if(node.childElement.length > 0){
- const nodeSS = deleteTargetNode(id, node.childElement)
- if(nodeSS != null){
- node.childElement = nodeSS
- }
- }
+ const a = deleteTargetNode(id, node.childElement)
}
}
- return node
}
-export function getMD5(file){
+export function getMD5(file) {
return new Promise((resolve, reject) => {
let fileReader = new FileReader()
@@ -105,12 +105,13 @@ const style1 = [
'border-radius',
'href',// 跳转
'overflow',
- 'box-shadow'
+ 'box-shadow',
+ 'all-center'
// '全剧中',
]
// 文字属性
const style2 = [
- 'color', 'font-size', 'font-weight', 'white-space', 'text-indent', 'line-height', 'text-align'
+ 'color', 'font-size', 'font-weight', 'white-space', 'text-indent', 'line-height', 'text-align', 'href'
]
const containerStyle = style1;
@@ -193,7 +194,7 @@ export class NE {
config: {
childrenType: 'text',
middle: '中间件',
- style: {containerStyle, textStyle},
+ style: {textStyle},
styleLimit: {},
event: {}
},
@@ -206,7 +207,7 @@ export class NE {
config: {
childrenType: 'text',
middle: '中间件',
- style: {containerStyle, textStyle},
+ style: {textStyle},
styleLimit: {},
event: {}
},
@@ -219,7 +220,9 @@ export class NE {
config: {
childrenType: 'images',
middle: '中间件',
- style: {containerStyle, textStyle},
+ style: {
+ textStyle: [...textStyle, 'width','height']
+ },
styleLimit: {},
event: {}
},
@@ -232,7 +235,9 @@ export class NE {
config: {
childrenType: 'video',
middle: '中间件',
- style: {containerStyle, textStyle},
+ style: {
+ textStyle: [...textStyle, 'width','height']
+ },
styleLimit: {},
event: {}
},
@@ -256,7 +261,7 @@ export class NE {
config: {
childrenType: 'text',
middle: '中间件',
- style: {containerStyle, textStyle},
+ style: {textStyle},
styleLimit: {},
event: {}
},
@@ -269,7 +274,7 @@ export class NE {
config: {
childrenType: 'text',
middle: '中间件',
- style: {containerStyle, textStyle},
+ style: {textStyle},
styleLimit: {},
event: {}
},
@@ -282,7 +287,7 @@ export class NE {
config: {
childrenType: 'text',
middle: '中间件',
- style: {containerStyle, textStyle},
+ style: {textStyle},
styleLimit: {},
event: {}
},
@@ -295,7 +300,7 @@ export class NE {
config: {
childrenType: 'text',
middle: '中间件',
- style: {containerStyle, textStyle},
+ style: {textStyle},
styleLimit: {},
event: {}
},
diff --git a/src/view/EditPageNew/index.jsx b/src/view/EditPageNew/index.jsx
index d359955..b4880bc 100644
--- a/src/view/EditPageNew/index.jsx
+++ b/src/view/EditPageNew/index.jsx
@@ -7,6 +7,7 @@ import Button from "@/components/Button/index.jsx";
import Atom from "@/components/Atom/index.jsx";
import ElementStructureTree from "@/components/ElementStructureTree/index.jsx";
import StyleControl from "@/components/StyleControl/index.jsx";
+import Editor from "@/components/Editor/index.jsx";
import css from './index.module.scss'
import svgLolipop from '@/assets/lolipop.svg'
@@ -30,13 +31,15 @@ export default function EditPageNew() {
const [nowContent, setNowContent] = useState({});
// 当下的选中元素
const [nowElement, setNowElement] = useState(null);
+ // 当前目录
+ const [nowMenuId, setNowMenuId] = useState(10);
+ const [nowContainerId, setNowContainerId] = useState(0)
// 属性页开关
const [attributeSwitch, setAttributeSwitch] = useState(false);
// 属性页标签位置
const [attrLabelPosition, setAttrLabelPosition] = useState(0);
-
useEffect(() => {
console.log('生命周期开始,发送请求!')
defaultStore.getContainerList(10)
@@ -47,10 +50,19 @@ export default function EditPageNew() {
if(defaultStore.thumbnailList != thumbnailList){
setThumbnailList(defaultStore.thumbnailList)
}
+
if(defaultStore.containerList != nowContentList){
setNowContentList(defaultStore.containerList)
}
})
+ if(defaultStore.thumbnailList == thumbnailList){
+ thumbnailList.forEach((item, index) => {
+ if(item.id == nowContainerId){
+ chooseThumbnail(index)
+ return
+ }
+ })
+ }
return () => {
q()
}
@@ -134,10 +146,9 @@ export default function EditPageNew() {
useEffect(() => {
const a = autorun(() => {
if(!defaultStore.styleRealRand)return
- // console.log(nowElement)
nowElement.config.styleReal = defaultStore.styleReal
- setNowElement({...nowElement})
- setNowContent({...nowContent})
+ setNowElement(JSON.parse(JSON.stringify(nowElement)))
+ setNowContent(JSON.parse(JSON.stringify(nowContent)))
for (let i in nowContentList) {
if (nowContentList[i].id == nowContent.id) {
nowContentList[i] = nowContent;
@@ -150,6 +161,31 @@ export default function EditPageNew() {
a()
}
}, [nowContent, nowContentList, nowElement])
+ // 修改内容
+ useEffect(() => {
+ const a = autorun(() => {
+ if(!(defaultStore.inputValue && nowElement))return
+ const node = getTargetNode(defaultStore.chooseNodeId, nowContent)
+ if (!node) {
+ alert('未找到节点元素。')
+ } else {
+ setNowElement(node)
+ }
+ nowElement.inputValue = defaultStore.inputValue
+ setNowElement(JSON.parse(JSON.stringify(nowElement)))
+ setNowContent(JSON.parse(JSON.stringify(nowContent)))
+ for (let i in nowContentList) {
+ if (nowContentList[i].id == nowContent.id) {
+ nowContentList[i] = nowContent;
+ break
+ }
+ }
+ defaultStore.setInputValue(null)
+ })
+ return () => {
+ a()
+ }
+ }, [nowContent, nowContentList, nowElement])
// 关闭大纲添加的页面
function closeThumbnailModal() {
@@ -190,13 +226,14 @@ export default function EditPageNew() {
// 选择大纲作为编辑项
function chooseThumbnail(index) {
+ if(nowContentList[thumbnailList[index].id].id == nowContent.id)return
thumbnailList.forEach(item => {
item.choose = false;
})
thumbnailList[index].choose = true;
setThumbnailList([...thumbnailList])
setNowContent(nowContentList[thumbnailList[index].id]);
- console.log(nowContentList[thumbnailList[index].id])
+ setNowContainerId(thumbnailList[index].id)
defaultStore.setChooseNodeId(null)
setNowElement(null)
}
@@ -252,7 +289,7 @@ export default function EditPageNew() {
{
thumbnailList.map((item, index) => {
return
chooseThumbnail(index)}>
@@ -275,7 +312,7 @@ export default function EditPageNew() {
}
{
- setAddThumbnailState(true)
+ setAddThumbnailState(true);
}}>
+
@@ -297,7 +334,7 @@ export default function EditPageNew() {
-
+
path.replace(/^\/api/, '') // 路径重写,本项目不需要重写
+ },
+ '/ossStatic':{
+ target: 'http://localhost:3000', // 代理的目标地址
+ changeOrigin: true, // 开发模式,默认的origin是真实的 origin:localhost:3000 代理服务会把origin修改为目标地址
}
}
},