完成V1版本

main
expressgy 2 years ago
parent 2e27efcaf8
commit 592db5125f
  1. BIN
      dist_20230222_V1.zip
  2. BIN
      dist_20230222_V2.zip
  3. 2
      index.html
  4. 49
      src/components/DirectoryStructureTree/index.jsx
  5. 2
      src/components/DirectoryStructureTree/index.module.scss
  6. 3
      src/components/Editor/index.jsx
  7. 5
      src/components/Editor/index.module.scss
  8. 136
      src/components/Vision/index.jsx
  9. 81
      src/components/Vision/index.module.scss
  10. 2
      src/config/sys22.js
  11. 5
      src/request/api.js
  12. 28
      src/router/index.jsx
  13. 23
      src/store/defaultStore.js
  14. 2
      src/view/EditPageNew/index.jsx
  15. 72
      src/view/Home/index.jsx
  16. 197
      src/view/Home/index.module.scss
  17. 26
      src/view/Show/index.jsx

Binary file not shown.

Binary file not shown.

@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title> <title>西安升帮联创技术服务有限公司</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

@ -7,7 +7,10 @@ import {useEffect, useState} from "react";
import {autorun} from "mobx"; import {autorun} from "mobx";
export default function DirectoryStructureTree(props) { export default function DirectoryStructureTree(props) {
const [chooseId, setChooseId] = useState(null) const [chooseId, setChooseId] = useState(0)
// const [fatherId, setFatherId] = useState(0)
// const [depth, setDepth] = useState(1)
function handleSetting(e, id) { function handleSetting(e, id) {
e.stopPropagation(); e.stopPropagation();
defaultStore.setSettingMenuId(id) defaultStore.setSettingMenuId(id)
@ -18,43 +21,41 @@ export default function DirectoryStructureTree(props) {
defaultStore.setNewMenuChildren(id) defaultStore.setNewMenuChildren(id)
} }
function handleChoose(e, id){ function handleChoose(e, id) {
e.stopPropagation(); e.stopPropagation();
defaultStore.setChooseMenuId(id) defaultStore.setChooseMenuId(id)
} }
useEffect(() => { useEffect(() => {
const a = autorun(() => { const a = autorun(() => {
if(defaultStore.menuId == chooseId) return if (defaultStore.menuId == chooseId) return
console.log(defaultStore.menuId)
setChooseId(defaultStore.menuId) setChooseId(defaultStore.menuId)
}) })
return () => { return () => {
a() a()
} }
}) },[chooseId])
// if (props.fatherId) {
// setFatherId(props.fatherId)
// }
// if(props.depth){
// setDepth(props.depth)
// }
const depth = props.depth || 1;
const fatherId = props.fatherId || 0;
return props.tree.map((item, index) => { return props.tree.map((item, index) => {
if (item.children && Array.isArray(item.children)) { return item.father == fatherId && <div key={index} className={css.directoryStructureTree}>
return <div key={index} className={css.directoryStructureTree}> <div className={chooseId == item.id ? [css.title, css.titleChoose].join(' ') : css.title}
<div className={chooseId == item.id ? [css.title, css.titleChoose].join(' ') : css.title} onClick={e => handleChoose(e, item.id)}> onClick={e => handleChoose(e, item.id)}>
<div className={css.text}>{item.name}</div> <div className={css.text}>{item.name}</div>
<div className={css.cmd}> <div className={css.cmd}>
<img src={svgAdd} alt="" onClick={e => handleCreate(e, item.id)}/><img src={svgSetting} alt="" {depth < 3 && <img src={svgAdd} alt="" onClick={e => handleCreate(e, item.id)}/>}<img className={css.setting} src={svgSetting} alt=""
onClick={e => handleSetting(e, item.id)}/> onClick={e => handleSetting(e, item.id)}/>
</div>
</div> </div>
<div>{DirectoryStructureTree({tree: item.children})}</div>
</div> </div>
} else { <div>{ depth < 3 && <DirectoryStructureTree tree={props.tree} fatherId={item.id} depth={depth + 1}></DirectoryStructureTree>}</div>
return <div key={index} className={css.directoryStructureTree}> </div>
<div className={chooseId == item.id ? [css.title, css.titleChoose].join(' ') : css.title} onClick={e => handleChoose(e, item.id)}>
<div className={css.text}>{item.name}</div>
<div className={css.cmd}><img src={svgAdd} alt="" onClick={e => handleCreate(e, item.id)}/><img
src={svgSetting} alt="" onClick={e => handleSetting(e, item.id)}/></div>
</div>
</div>
}
}) })
} }

@ -35,7 +35,7 @@
width: 25px; width: 25px;
} }
& > img:nth-child(2){ & > img.setting{
width: 22px; width: 22px;
margin-left: 10px; margin-left: 10px;
} }

@ -68,9 +68,6 @@ export default function Editor(props) {
} }
}, [props.element]) }, [props.element])
useEffect(() => {
// console.log(style)
}, [style])
function hrefClick(e) { function hrefClick(e) {
e.stopPropagation(); e.stopPropagation();

@ -3,6 +3,9 @@
position: relative; position: relative;
min-height: 3rem; min-height: 3rem;
} }
@mixin span{
padding: 10px;
}
// 单元素结构 // 单元素结构
.singleFrame { .singleFrame {
@include frame; @include frame;
@ -23,7 +26,7 @@
// 行内文本 // 行内文本
.span{ .span{
@include frame; @include frame;
padding: 10px; @include span;
width: auto; width: auto;
height: auto; height: auto;
} }

@ -0,0 +1,136 @@
import css from "./index.module.scss";
import {useEffect, useState} from "react";
import svgImg from "@/assets/img.svg";
export default function Vision(props){
const [element, setElement] = useState({})
const [style, setStyle] = useState({})
const [href, setHref] = useState({url: '', state: 0,})
const [img, setImg] = useState(svgImg)
const [inputValue, setInputValue] = useState('')
if(!props.element) return null
useEffect(() => {
let nowElement = null
if(!props.element) return
nowElement = typeof props.element.body == 'string' ? JSON.parse(props.element.body) : props.element
setElement(nowElement)
if (nowElement.config && nowElement.config.styleReal) {
const styleReal = nowElement.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({
url: styleReal.href,
state: styleReal['href-mx']
})
}else{
setStyle({})
}
if(nowElement.identify == 'image' && nowElement.inputValue){
setImg('/ossStatic/' + nowElement.inputValue)
}
if (nowElement.inputValue) {
setInputValue(nowElement.inputValue)
}
}, [props.element])
function hrefClick(e) {
console.log('AAA')
console.log(href)
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)
}
}
switch (element.identify) {
//
case 'singleFrame':
return <div className={css.singleFrame} style={style} onClick={hrefClick}>
{
Array.isArray(element.childElement) ? element.childElement.map(item => {
{return <Vision element={item} key={item.id}></Vision>}
}) : <Vision element={element.childElement}></Vision>
}
</div>
break;
//
case 'transverseFrame':
return <div className={css.transverseFrame} style={style} onClick={hrefClick}>
{
Array.isArray(element.childElement) ? element.childElement.map(item => {
{return <Vision element={item} key={item.id}></Vision>}
}) : <Vision element={element.childElement}></Vision>
}
</div>
break;
//
case 'longitudinalFrame':
return <div className={css.longitudinalFrame} style={style} onClick={hrefClick}>
{
Array.isArray(element.childElement) ? element.childElement.map(item => {
{return <Vision element={item} key={item.id}></Vision>}
}) : <Vision element={element.childElement}></Vision>
}
</div>
break;
//
case 'span':
// <div className={css.span} style={style}}>{inputValue}</div>
return <div className={css.span} style={style} onClick={hrefClick}>{inputValue}</div>
break;
//
case 'blockText':
return <div className={css.span} style={style}><div dangerouslySetInnerHTML={
{ __html: inputValue}} onClick={hrefClick}></div></div>
break;
//
case 'image':
return <div className={css.image} style={style}>
<img src={img} alt="" style={style} onClick={hrefClick}/>
</div>
break;
//
case 'video':
break;
default:
return null
break
}
}

@ -0,0 +1,81 @@
// 框架
@mixin frame{
position: relative;
//min-height: 3rem;
}
@mixin span{
//padding: 10px;
}
// 单元素结构
.singleFrame {
@include frame;
}
// 横向多元素结构
.transverseFrame{
display: flex;
flex-wrap: wrap;
@include frame;
}
// 纵向多元素结构
.longitudinalFrame {
display: flex;
flex-direction: column;
@include frame;
}
// 行内文本
.span{
@include frame;
@include span;
width: auto;
height: auto;
}
.spanDiv{
position: relative;
display: flex;
padding: 5px;
box-sizing: border-box;
& > input{
position: relative;
display: block;
flex: 1;
line-height: 1.5em;
background: #ffffff99;
border: 1px solid #333;
font-size: inherit;
color: inherit;
}
}
.editInput{
position: relative;
min-height: 2em;
}
// 块文本
.blockText{
}
// 图像
.image{
position: relative;
@include frame;
padding: 0;
width: 100px;
& > input{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
min-width: 30px;
min-height: 20px;
opacity: 0;
display: block;
}
& > img{
position: relative;
}
}
// 视频
.video{
}

@ -1,4 +1,4 @@
import icon from '../assets/react.svg' import icon from '../assets/logo.png'

@ -6,6 +6,11 @@ export default {
params:data params:data
}) })
}, },
getContainerPage(data){
return instance.get('/container/getPage',{
params:data
})
},
createContainer(data){ createContainer(data){
const formData = new FormData() const formData = new FormData()
Object.keys(data).map(item => { Object.keys(data).map(item => {

@ -1,18 +1,30 @@
import { Navigate } from 'react-router-dom' import { Navigate } from 'react-router-dom'
import EditPageNew from '@/view/EditPageNew' import EditPageNew from '@/view/EditPageNew'
import Home from "@/view/Home/index.jsx";
import Show from "@/view/Show/index.jsx";
export default [ export default [
// //
{ {
path:'/', path:'/',
element: <Navigate to="/home/index" replace />
},
{
path:'/home',
element: <Home />,
children:[
{
path:':route',
element: <Show />
}
]
},
{
path:'/edit',
element: <EditPageNew /> element: <EditPageNew />
}, },
// { // {
// path:'/signIn',
// element: <SignIn />
// },
// {
// path:'/signUp', // path:'/signUp',
// element: <SignUp /> // element: <SignUp />
// }, // },
@ -26,8 +38,8 @@ export default [
// } // }
// ] // ]
// }, // },
// { {
// path: "", path: "*",
// element: <Navigate to="home" replace /> element: <Navigate to="/" replace />
// } }
] ]

@ -9,6 +9,9 @@ class DefaultStore {
// 系统配置 // 系统配置
config = config; config = config;
// 当前页内容
nowPageContent = null
// 目录结构树 // 目录结构树
directoryStructureTree = [ directoryStructureTree = [
{ {
@ -41,7 +44,7 @@ class DefaultStore {
// 菜单列表 // 菜单列表
menuList = []; menuList = [];
// 当前MenuId // 当前MenuId
menuId = 10; menuId = 0;
// 创建子菜单的ID // 创建子菜单的ID
newMenuChidlrenId = null; newMenuChidlrenId = null;
// 设置菜单 // 设置菜单
@ -81,6 +84,7 @@ class DefaultStore {
templateContainer: observable, templateContainer: observable,
newMenuChidlrenId: observable, newMenuChidlrenId: observable,
settingMenuId: observable, settingMenuId: observable,
nowPageContent: observable,
containerList: computed, containerList: computed,
@ -102,7 +106,8 @@ class DefaultStore {
createMneuItem: action, createMneuItem: action,
setNewMenuChildren: action, setNewMenuChildren: action,
setSettingMenuId: action, setSettingMenuId: action,
setChooseMenuId: action setChooseMenuId: action,
getNowPageContent: action
}); });
} }
@ -212,8 +217,11 @@ class DefaultStore {
async getMenuList(){ async getMenuList(){
const response = await api.getMenuList() const response = await api.getMenuList()
runInAction(() => { runInAction(() => {
this.menuList = response.data.data const menuList = response.data.data
console.log(this.menuList) menuList.sort((a, b) => {
return a.rank - b.rank
})
this.menuList = menuList
}) })
} }
// 添加菜单 // 添加菜单
@ -231,6 +239,13 @@ class DefaultStore {
await api.updateMenuItem(data) await api.updateMenuItem(data)
this.getMenuList() this.getMenuList()
} }
async getNowPageContent(data){
const response = await api.getContainerPage(data)
runInAction(() => {
this.nowPageContent = response.data.data
})
}
} }
export default DefaultStore export default DefaultStore

@ -407,6 +407,8 @@ export default function EditPageNew() {
defaultStore.createMneuItem(menuData) defaultStore.createMneuItem(menuData)
} }
setDeleteMenuState(false) setDeleteMenuState(false)
const menu = {name:'', route:'', rank:0, father:0, icon: '', remarks:''}
setMenuData({...menu})
} }
// //
function handleDeleteMenuItem(){ function handleDeleteMenuItem(){

@ -0,0 +1,72 @@
import css from './index.module.scss'
import logo from '@/assets/logo.png'
import {useEffect, useState} from "react";
import {defaultStore} from "@/store/index.js";
import { Outlet, useNavigate } from "react-router-dom";
import {autorun} from "mobx";
export default function Home() {
const [menuList, setMenuList] = useState([])
const navigate = useNavigate()
useEffect(() => {
defaultStore.getMenuList()
}, [0])
useEffect(() => {
const a = autorun(() => {
if (defaultStore.menuList == menuList) return
setMenuList(defaultStore.menuList)
})
return () => {
a()
}
})
useEffect(() => {
// console.log(menuList)
}, [menuList])
// const history = useHistory()
function goto(router){
navigate(router)
}
return <div className={css.home}>
<header>
<nav>
<div className={css.menu1Box}>
<div className={css.logo}>
<img src={logo} alt=""/>
</div>
</div>
{menuList.map(item1 => {
return item1.father == 0 && <div key={item1.id} className={css.menu1Box}>
<div className={css.title1} onClick={() => goto(item1.route)}>{item1.name}</div>
<div className={css.border}></div>
<div className={css.container}>
{menuList.map(item2 => {
return item1.id == item2.father && <div key={item2.id} className={css.menu2Box}>
<div className={css.title2} onClick={() => goto(item2.route)}>
<div className={css.background}></div>
<div className={css.text}>{item2.name}</div>
</div>
{menuList.map(item3 => {
return item2.id == item3.father &&
<div key={item3.id} className={css.menu3Box}>
<div className={css.title3} onClick={() => goto(item3.route)}>{item3.name}</div>
</div>
})
}
</div>
})
}
</div>
</div>
})}
</nav>
</header>
<div className={css.main}>
<Outlet></Outlet>
</div>
</div>
}

@ -0,0 +1,197 @@
@import '@/assets/default.scss';
div.home {
position: relative;
width: 100%;
height: 100%;
overflow: auto;
min-width: 1000px;
& > header {
position: relative;
width: 100%;
background: #fefefe;
border-bottom: 1px solid #99999933;
& > nav {
position: relative;
max-width: 1200px;
margin: 0 auto;
height: 70px;
display: flex;
& > div.menu1Box:first-child {
padding: 0 1rem;
}
& > div.menu1Box:nth-child(n+2) {
padding: 0 3.5rem;
&:hover {
& > div.container {
max-height: 200px;
}
& > div.border {
background-color: #2c5e99;
}
}
}
& > div.menu1Box:nth-child(n+3) {
&:before {
content: "";
position: absolute;
display: inline-block;
width: 2px;
height: 30px;
background: #33333366;
border-radius: 10px;
left: -1px;
}
}
& > div.menu1Box {
position: relative;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
height: 100%;
//font-weight: 600;
& > div.logo {
position: relative;
display: flex;
align-items: center;
justify-content: center;
img {
width: 60px;
}
}
& > div.border {
position: absolute;
width: 100%;
height: 3px;
background-color: transparent;
bottom: 0px;
transition: background-color ease-in-out 300ms;
}
& > div.title1 {
letter-spacing: 0.5rem;
font-size: 1.2rem;
color: #333;
}
& > div.container {
position: absolute;
max-height: 0;
transition: max-height ease-in-out 300ms;
overflow: hidden;
top: 70px;
width: 100%;
margin: 0;
z-index: 100;
background: #99999918;
& > div.menu2Box:first-child {
margin-top: 0.5rem;
}
& > div.menu2Box:last-child {
margin-bottom: 0.5rem;
}
}
& > div.container > div.menu2Box {
position: relative;
//top:80px;
width: 100%;
& > div.title2:last-child {
margin-bottom: 1rem;
}
& > div.title2 {
position: relative;
line-height: 2em;
font-size: 1rem;
font-weight: bold;
padding: 0 0.5rem;
& > div.text {
position: relative;
color: #444;
@include autoHide;
padding-left: 0.5rem;
transition: all ease-in-out 300ms;
}
& > div.background {
position: absolute;
height: 100%;
left: 0;
width: 0;
transition: all ease-in-out 500ms;
}
&:before {
position: absolute;
display: inline-block;
content: "";
height: 1.2rem;
width: 2px;
background: #33333399;
border-radius: 10px;
margin-right: 0.5rem;
top: 5px;
}
&:hover {
& > div.background {
width: 100%;
background: #2c5e99;
}
& > div.text {
color: #fefefe;
}
}
}
& > div.menu3Box {
position: relative;
& > div.title3 {
position: relative;
padding-left: 1.1rem;
font-size: 1rem;
@include autoHide;
line-height: 1.8em;
transition: background-color ease-in-out 300ms;
&:hover {
color: #2c5e99;
}
&:before {
position: relative;
display: inline-block;
content: ">";
height: 0.5rem;
margin-right: 0.5rem;
}
}
}
}
}
}
}
& > div.main {
}
}

@ -0,0 +1,26 @@
import { useParams } from 'react-router-dom'
import {useEffect, useState} from "react";
import {defaultStore} from "@/store/index.js";
import {autorun} from "mobx";
import Vision from '@/components/Vision'
export default function Show(props){
const [pageData, setPageData] = useState([])
const params = useParams()
console.log(params)
useEffect(() => {
defaultStore.getNowPageContent({route:params.route})
},[params])
useEffect(() => {
const a = autorun(() => {
if(!defaultStore.nowPageContent) return;
setPageData(defaultStore.nowPageContent)
})
return () => {
a()
}
},[pageData])
return pageData.map(item => {
return <Vision element={item} key={item.id}></Vision>
})
}
Loading…
Cancel
Save